From d0d534568c97271e03a0e9f9c16a0966fb50b97a Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 19 Jul 2012 08:49:55 -0400 Subject: SoupSocket: don't emit "readable" on disconnect for blocking sockets "readable" and "writable" are only supposed to be emitted for non-blocking sockets, but we were emitting "readable" on disconnect for all sockets. In libsoup 2.38 and earlier, this could cause a crash if a message in a SoupSessionSync failed at certain points, since the code wasn't expecting to end up in io_read(). The current code no longer has this problem (since soup-message-io no longer uses the SoupSocket signals), but other external users of SoupSocket might. --- libsoup/soup-socket.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 2ac359de..5a88907c 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -1242,8 +1242,10 @@ soup_socket_disconnect (SoupSocket *sock) */ g_object_ref (sock); - /* Give all readers a chance to notice the connection close */ - g_signal_emit (sock, signals[READABLE], 0); + if (priv->non_blocking) { + /* Give all readers a chance to notice the connection close */ + g_signal_emit (sock, signals[READABLE], 0); + } /* FIXME: can't disconnect until all data is read */ -- cgit v1.2.1 From 6c8c418364367e2947bb9bfa9e899d856fa06063 Mon Sep 17 00:00:00 2001 From: Tom Tryfonidis Date: Fri, 20 Jul 2012 13:59:25 +0300 Subject: Updated Greek translation --- po/el.po | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/po/el.po b/po/el.po index f693bc5e..11dae732 100644 --- a/po/el.po +++ b/po/el.po @@ -7,66 +7,71 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-06-14 18:14+0000\n" -"PO-Revision-Date: 2012-06-22 13:16+0200\n" +"POT-Creation-Date: 2012-07-16 22:04+0000\n" +"PO-Revision-Date: 2012-07-20 13:58+0200\n" "Last-Translator: Tom Tryfonidis \n" "Language-Team: Greek \n" +"Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 -#: ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 +#: ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Η σύνδεση τερματίστηκε απρόσμενα" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:189 #, c-format msgid "Output buffer is too small" -msgstr "Το buffer εξόδου είναι πολύ μικρό" +msgstr "Η ενδιάμεση μνήμη εξόδου είναι πολύ μικρή" -#: ../libsoup/soup-message-io.c:836 -#: ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:817 +#: ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "Η λειτουργία ακυρώθηκε" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:864 msgid "Operation would block" msgstr "Η λειτουργία θα μπλοκαριστεί" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "Δεν έχει δοθεί URI" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Μη έγκυρο '%s' URI: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Αδυναμία ανάλυσης URI '%s'" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Μη υποστηριζόμενο URI σχήμα '%s'" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:143 msgid "Hostname is an IP address" msgstr "Το όνομα συστήματος είναι μια διεύθυνση IP" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:164 msgid "Invalid hostname" msgstr "Μη έγκυρο όνομα συστήματος" -#: ../libsoup/soup-tld.c:181 -#: ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:179 +#: ../libsoup/soup-tld.c:221 msgid "Not enough domains" msgstr "Δεν υπάρχουν αρκετοί τομείς" +#: ../libsoup/soup-tld.c:199 +msgid "Hostname has no base domain" +msgstr "Το όνομα συστήματος δεν έχει βασικό τομέα" + -- cgit v1.2.1 From 2a96a353bc1c6f4455ba80708c726442599f9b8e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 24 Jul 2012 15:22:44 -0400 Subject: SoupSessionAsync: fix handling of timed-out SoupRequests When using the SoupRequest API, a message that hit SOUP_SESSION_TIMEOUT would error out, but would not emit "finished" or get fully removed from the queue. Fix that and add SoupRequest tests to timeout-test (along with tests that "finished" gets emitted). --- libsoup/soup-session-async.c | 8 ++ tests/timeout-test.c | 207 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 194 insertions(+), 21 deletions(-) diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 46900552..81afcf8c 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -667,6 +667,14 @@ try_run_until_read (SoupMessageQueueItem *item) } if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + if (item->state != SOUP_MESSAGE_FINISHED) { + gboolean dummy; + + if (soup_message_io_in_progress (item->msg)) + soup_message_io_finished (item->msg); + item->state = SOUP_MESSAGE_FINISHING; + process_queue_item (item, &dummy, FALSE); + } send_request_return_result (item, NULL, error); return; } diff --git a/tests/timeout-test.c b/tests/timeout-test.c index 2bb91d8a..aad2c3d4 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -2,14 +2,35 @@ #include "test-utils.h" +static void +message_finished (SoupMessage *msg, gpointer user_data) +{ + gboolean *finished = user_data; + + *finished = TRUE; +} + +static void +request_started_cb (SoupSession *session, SoupMessage *msg, + SoupSocket *socket, gpointer user_data) +{ + SoupSocket **ret = user_data; + + *ret = socket; +} + static void do_message_to_session (SoupSession *session, const char *uri, const char *comment, guint expected_status) { SoupMessage *msg; + gboolean finished = FALSE; - debug_printf (1, " %s\n", comment); + debug_printf (1, " msg %s\n", comment); msg = soup_message_new ("GET", uri); + + g_signal_connect (msg, "finished", + G_CALLBACK (message_finished), &finished); soup_session_send_message (session, msg); if (msg->status_code != expected_status) { @@ -22,27 +43,26 @@ do_message_to_session (SoupSession *session, const char *uri, if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code) && !soup_message_is_keepalive (msg)) { - debug_printf (1, " ERROR: message is not keepalive!"); + debug_printf (1, " ERROR: message is not keepalive!\n"); errors++; } - g_object_unref (msg); -} - -static void -request_started_cb (SoupSession *session, SoupMessage *msg, - SoupSocket *socket, gpointer user_data) -{ - SoupSocket **ret = user_data; + if (!finished) { + debug_printf (1, " ERROR: 'finished' was not emitted\n"); + errors++; + } - *ret = socket; + g_signal_handlers_disconnect_by_func (msg, + G_CALLBACK (message_finished), + &finished); + g_object_unref (msg); } static void -do_tests_for_session (SoupSession *timeout_session, - SoupSession *idle_session, - SoupSession *plain_session, - char *fast_uri, char *slow_uri) +do_msg_tests_for_session (SoupSession *timeout_session, + SoupSession *idle_session, + SoupSession *plain_session, + char *fast_uri, char *slow_uri) { SoupSocket *ret, *idle_first, *idle_second; SoupSocket *plain_first, *plain_second; @@ -91,6 +111,144 @@ do_tests_for_session (SoupSession *timeout_session, } } +static void +do_request_to_session (SoupRequester *requester, const char *uri, + const char *comment, gboolean expect_timeout) +{ + SoupRequest *req; + SoupMessage *msg; + GInputStream *stream; + GError *error = NULL; + gboolean finished = FALSE; + + debug_printf (1, " req %s\n", comment); + req = soup_requester_request (requester, uri, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); + + g_signal_connect (msg, "finished", + G_CALLBACK (message_finished), &finished); + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + stream = soup_request_send (req, NULL, &error); + else + stream = soup_test_request_send_async_as_sync (req, NULL, &error); + + if (expect_timeout && !error) { + debug_printf (1, " FAILED: request did not time out\n"); + errors++; + } else if (expect_timeout && !g_error_matches (error, G_IO_ERROR, + G_IO_ERROR_TIMED_OUT)) { + debug_printf (1, " FAILED: wrong error: %s\n", + error->message); + errors++; + } else if (!expect_timeout && error) { + debug_printf (1, " FAILED: expected success but got error: %s\n", + error->message); + errors++; + } + g_clear_error (&error); + + if (stream) { + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + g_input_stream_close (stream, NULL, &error); + else + soup_test_stream_close_async_as_sync (stream, NULL, &error); + + if (error) { + debug_printf (1, " ERROR closing string: %s", + error->message); + errors++; + } + } + + if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code) && + !soup_message_is_keepalive (msg)) { + debug_printf (1, " ERROR: message is not keepalive!\n"); + errors++; + } + + if (!finished) { + debug_printf (1, " ERROR: 'finished' was not emitted\n"); + errors++; + } + + g_signal_handlers_disconnect_by_func (msg, + G_CALLBACK (message_finished), + &finished); + g_object_unref (msg); + g_object_unref (req); +} + +static void +do_req_tests_for_session (SoupSession *timeout_session, + SoupSession *idle_session, + SoupSession *plain_session, + char *fast_uri, char *slow_uri) +{ + SoupRequester *timeout_requester, *idle_requester, *plain_requester; + SoupSocket *ret, *idle_first, *idle_second; + SoupSocket *plain_first, *plain_second; + + debug_printf (1, "\n"); + + if (idle_session) { + idle_requester = soup_requester_new (); + soup_session_add_feature (idle_session, + SOUP_SESSION_FEATURE (idle_requester)); + g_object_unref (idle_requester); + + g_signal_connect (idle_session, "request-started", + G_CALLBACK (request_started_cb), &ret); + do_request_to_session (idle_requester, fast_uri, "fast to idle", FALSE); + idle_first = ret; + } + + if (plain_session) { + plain_requester = soup_requester_new (); + soup_session_add_feature (plain_session, + SOUP_SESSION_FEATURE (plain_requester)); + g_object_unref (plain_requester); + + g_signal_connect (plain_session, "request-started", + G_CALLBACK (request_started_cb), &ret); + do_request_to_session (plain_requester, fast_uri, "fast to plain", FALSE); + plain_first = ret; + } + + timeout_requester = soup_requester_new (); + soup_session_add_feature (timeout_session, + SOUP_SESSION_FEATURE (timeout_requester)); + g_object_unref (timeout_requester); + + do_request_to_session (timeout_requester, fast_uri, "fast to timeout", FALSE); + do_request_to_session (timeout_requester, slow_uri, "slow to timeout", TRUE); + + if (idle_session) { + do_request_to_session (idle_requester, fast_uri, "fast to idle", FALSE); + idle_second = ret; + g_signal_handlers_disconnect_by_func (idle_session, + (gpointer)request_started_cb, + &ret); + + if (idle_first == idle_second) { + debug_printf (1, " ERROR: idle_session did not close first connection\n"); + errors++; + } + } + + if (plain_session) { + do_request_to_session (plain_requester, fast_uri, "fast to plain", FALSE); + plain_second = ret; + g_signal_handlers_disconnect_by_func (plain_session, + (gpointer)request_started_cb, + &ret); + + if (plain_first != plain_second) { + debug_printf (1, " ERROR: plain_session closed connection\n"); + errors++; + } + } +} + static void do_timeout_tests (char *fast_uri, char *slow_uri) { @@ -98,10 +256,12 @@ do_timeout_tests (char *fast_uri, char *slow_uri) debug_printf (1, " async\n"); timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_TIMEOUT, 1, - NULL); + SOUP_SESSION_TIMEOUT, 1, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); idle_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_IDLE_TIMEOUT, 1, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); /* The "plain" session also has an idle timeout, but it's longer * than the test takes, so for our purposes it should behave like @@ -109,21 +269,26 @@ do_timeout_tests (char *fast_uri, char *slow_uri) */ plain_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_IDLE_TIMEOUT, 2, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); - do_tests_for_session (timeout_session, idle_session, plain_session, - fast_uri, slow_uri); + + do_msg_tests_for_session (timeout_session, idle_session, plain_session, + fast_uri, slow_uri); + do_req_tests_for_session (timeout_session, idle_session, plain_session, + fast_uri, slow_uri); soup_test_session_abort_unref (timeout_session); soup_test_session_abort_unref (idle_session); soup_test_session_abort_unref (plain_session); - debug_printf (1, " sync\n"); + debug_printf (1, "\n sync\n"); timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, SOUP_SESSION_TIMEOUT, 1, NULL); /* SOUP_SESSION_TIMEOUT doesn't work with sync sessions */ plain_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - do_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri); + do_msg_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri); + do_req_tests_for_session (timeout_session, NULL, plain_session, fast_uri, slow_uri); soup_test_session_abort_unref (timeout_session); soup_test_session_abort_unref (plain_session); } -- cgit v1.2.1 From d491426eb88b7213dd4d688eddb49f71276f6bff Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 24 Jul 2012 16:06:43 -0400 Subject: SoupConverterWrapper: handle truncated responses in general Rather than just the specific case of "server claims non-0 Content-Length but response is empty", allow the response to be truncated at any point. Because, you know, the web. --- libsoup/soup-converter-wrapper.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libsoup/soup-converter-wrapper.c b/libsoup/soup-converter-wrapper.c index 8aa000b9..1953229a 100644 --- a/libsoup/soup-converter-wrapper.c +++ b/libsoup/soup-converter-wrapper.c @@ -15,12 +15,14 @@ #include "soup.h" /* SoupConverterWrapper is a GConverter that wraps another GConverter. - * Mostly it is transparent, but it implements three special fallbacks + * Mostly it is transparent, but it implements four special fallbacks * for Content-Encoding handling: (1) "deflate" can mean either raw - * deflate or zlib-encoded default, (2) the server may mistakenly + * deflate or zlib-encoded deflate, (2) the server may mistakenly * claim that a response is encoded when actually it isn't, (3) the * response may contain trailing junk after the end of the encoded - * portion that we want to ignore. + * portion that we want to ignore, (4) the response may be truncated + * at an arbitrary point rather than containing a complete compressed + * representation. * * If the wrapped conversion succeeds, then the wrapper will set the * %SOUP_MESSAGE_CONTENT_DECODED flag on its message. @@ -271,8 +273,7 @@ soup_converter_wrapper_real_convert (GConverter *converter, } if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT) && - !priv->started && inbuf_size == 0 && - (flags & G_CONVERTER_INPUT_AT_END)) { + inbuf_size == 0 && (flags & G_CONVERTER_INPUT_AT_END)) { /* Server claimed compression but there was no message body. */ g_error_free (my_error); *bytes_written = 0; -- cgit v1.2.1 From 1abd8ecf4211afe67b6bb3ce33061e3ae51bfe97 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Tue, 24 Jul 2012 23:15:09 +0300 Subject: Updated Hebrew translation. --- po/he.po | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/po/he.po b/po/he.po index f201ed5c..db9e6c30 100644 --- a/po/he.po +++ b/po/he.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup gnome\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-12 18:58+0300\n" -"PO-Revision-Date: 2012-07-12 18:58+0200\n" +"POT-Creation-Date: 2012-07-24 23:14+0300\n" +"PO-Revision-Date: 2012-07-24 23:15+0200\n" "Last-Translator: Yaron Shahrabani \n" "Language-Team: Hebrew \n" "Language: \n" @@ -20,57 +20,61 @@ msgstr "" "X-Poedit-Country: ISRAEL\n" "X-Poedit-SourceCharset: utf-8\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 -#: ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 +#: ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "החיבור הופסק באופן בלתי צפוי" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:191 #, c-format msgid "Output buffer is too small" msgstr "אוגר הפלט קטן מדי" -#: ../libsoup/soup-message-io.c:836 -#: ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:817 +#: ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "הפעולה בוטלה" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:864 msgid "Operation would block" msgstr "הפעולה תיחסם" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "לא סופקה כתובת" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "כתובת '%s' שגויה: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "לא ניתן לנתח את הכתובת '%s'" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "תבנית הכתובת אינה נתמכת '%s'" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:148 msgid "Hostname is an IP address" msgstr "שם המארח הוא כתובת IP" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:169 msgid "Invalid hostname" msgstr "שם מארח שגוי" -#: ../libsoup/soup-tld.c:181 -#: ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:184 +#: ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "אין מספיק שמות מתחם" +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "לשם המארח אין שם מתחם בסיסי" + -- cgit v1.2.1 From 6cddb7cdd31fbee94ec424993e99e0b7f7bdb90b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 25 Jul 2012 08:54:11 -0400 Subject: test-utils: simplify the SoupRequest test utils a bit --- tests/coding-test.c | 4 +-- tests/connection-test.c | 22 +++------------- tests/misc-test.c | 4 +-- tests/proxy-test.c | 11 ++------ tests/redirect-test.c | 10 ++------ tests/test-utils.c | 67 +++++++++++++++++++++++++++---------------------- tests/test-utils.h | 13 +++++----- tests/timeout-test.c | 10 ++------ 8 files changed, 58 insertions(+), 83 deletions(-) diff --git a/tests/coding-test.c b/tests/coding-test.c index cda4b89e..02ec23af 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -338,7 +338,7 @@ do_single_coding_req_test (SoupRequest *req, msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - stream = soup_test_request_send_async_as_sync (req, NULL, &error); + stream = soup_test_request_send (req, NULL, &error); if (error) { debug_printf (1, " Error sending request: %s\n", error->message); @@ -359,7 +359,7 @@ do_single_coding_req_test (SoupRequest *req, g_byte_array_append (data, buf, nread); } while (nread > 0); - soup_test_stream_close_async_as_sync (stream, NULL, &error); + soup_test_request_close_stream (req, stream, NULL, &error); if (error) { debug_printf (1, " error closing stream: %s\n", error->message); diff --git a/tests/connection-test.c b/tests/connection-test.c index ddf0c988..6ddc89c5 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -321,21 +321,14 @@ do_timeout_req_test_for_session (SoupSession *session) req = soup_requester_request_uri (requester, timeout_uri, NULL); soup_uri_free (timeout_uri); - if (SOUP_IS_SESSION_SYNC (session)) - stream = soup_request_send (req, NULL, &error); - else - stream = soup_test_request_send_async_as_sync (req, NULL, &error); - + stream = soup_test_request_send (req, NULL, &error); if (!stream) { debug_printf (1, " Unexpected error on send: %s\n", error->message); errors++; g_clear_error (&error); } else { - if (SOUP_IS_SESSION_SYNC (session)) - g_input_stream_close (stream, NULL, &error); - else - soup_test_stream_close_async_as_sync (stream, NULL, &error); + soup_test_request_close_stream (req, stream, NULL, &error); if (error) { debug_printf (1, " Unexpected error on close: %s\n", error->message); @@ -354,21 +347,14 @@ do_timeout_req_test_for_session (SoupSession *session) debug_printf (1, " Second request\n"); req = soup_requester_request_uri (requester, base_uri, NULL); - if (SOUP_IS_SESSION_SYNC (session)) - stream = soup_request_send (req, NULL, &error); - else - stream = soup_test_request_send_async_as_sync (req, NULL, &error); - + stream = soup_test_request_send (req, NULL, &error); if (!stream) { debug_printf (1, " Unexpected error on send: %s\n", error->message); errors++; g_clear_error (&error); } else { - if (SOUP_IS_SESSION_SYNC (session)) - g_input_stream_close (stream, NULL, &error); - else - soup_test_stream_close_async_as_sync (stream, NULL, &error); + soup_test_request_close_stream (req, stream, NULL, &error); if (error) { debug_printf (1, " Unexpected error on close: %s\n", error->message); diff --git a/tests/misc-test.c b/tests/misc-test.c index 605fa216..a71d4aae 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -947,12 +947,12 @@ do_cancel_while_reading_req_test_for_session (SoupRequester *requester) if (SOUP_IS_SESSION_ASYNC (soup_request_get_session (req))) { g_timeout_add (100, cancel_request_timeout, cancellable); - soup_test_request_send_async_as_sync (req, cancellable, &error); + soup_test_request_send (req, cancellable, &error); } else { GThread *thread; thread = g_thread_new ("cancel_request_thread", cancel_request_thread, cancellable); - soup_request_send (req, cancellable, &error); + soup_test_request_send (req, cancellable, &error); g_thread_unref (thread); } diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 85aac9f5..35c9d841 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -166,11 +166,7 @@ test_url_new_api (const char *url, int proxy, guint expected, request = soup_requester_request (requester, url, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); - if (sync) - stream = soup_request_send (request, NULL, &error); - else - stream = soup_test_request_send_async_as_sync (request, NULL, &error); - + stream = soup_test_request_send (request, NULL, &error); if (!stream) { debug_printf (1, " Unexpected error on Request: %s\n", error->message); @@ -179,10 +175,7 @@ test_url_new_api (const char *url, int proxy, guint expected, } if (stream) { - if (sync) - g_input_stream_close (stream, NULL, NULL); - else - soup_test_stream_close_async_as_sync (stream, NULL, NULL); + soup_test_request_close_stream (request, stream, NULL, NULL); if (error) { debug_printf (1, " Unexpected error on close: %s\n", error->message); diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 59a2f077..401eda21 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -255,10 +255,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) g_signal_connect (msg, "restarted", G_CALLBACK (restarted), &treq); - if (SOUP_IS_SESSION_SYNC (session)) - stream = soup_request_send (req, NULL, &error); - else - stream = soup_test_request_send_async_as_sync (req, NULL, &error); + stream = soup_test_request_send (req, NULL, &error); if (SOUP_STATUS_IS_TRANSPORT_ERROR (final_status)) { if (stream) { @@ -289,10 +286,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) return; } - if (SOUP_IS_SESSION_SYNC (session)) - g_input_stream_close (stream, NULL, &error); - else - soup_test_stream_close_async_as_sync (stream, NULL, &error); + soup_test_request_close_stream (req, stream, NULL, &error); if (error) { debug_printf (1, " could not close stream: %s\n", error->message); diff --git a/tests/test-utils.c b/tests/test-utils.c index f040b738..606de327 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -355,8 +355,8 @@ soup_test_server_quit_unref (SoupServer *server) } typedef struct { - GMainLoop *loop; - GAsyncResult *result; + GMainLoop *loop; + GAsyncResult *result; } AsyncAsSyncData; static void @@ -364,51 +364,58 @@ async_as_sync_callback (GObject *object, GAsyncResult *result, gpointer user_data) { - AsyncAsSyncData *data = user_data; + AsyncAsSyncData *data = user_data; - data->result = g_object_ref (result); - g_main_loop_quit (data->loop); + data->result = g_object_ref (result); + g_main_loop_quit (data->loop); } GInputStream * -soup_test_request_send_async_as_sync (SoupRequest *req, - GCancellable *cancellable, - GError **error) +soup_test_request_send (SoupRequest *req, + GCancellable *cancellable, + GError **error) { - AsyncAsSyncData data; - GInputStream *stream; + AsyncAsSyncData data; + GInputStream *stream; - data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + return soup_request_send (req, cancellable, error); - soup_request_send_async (req, cancellable, async_as_sync_callback, &data); - g_main_loop_run (data.loop); + data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); - stream = soup_request_send_finish (req, data.result, error); + soup_request_send_async (req, cancellable, async_as_sync_callback, &data); + g_main_loop_run (data.loop); - g_main_loop_unref (data.loop); - g_object_unref (data.result); + stream = soup_request_send_finish (req, data.result, error); - return stream; + g_main_loop_unref (data.loop); + g_object_unref (data.result); + + return stream; } gboolean -soup_test_stream_close_async_as_sync (GInputStream *stream, - GCancellable *cancellable, - GError **error) +soup_test_request_close_stream (SoupRequest *req, + GInputStream *stream, + GCancellable *cancellable, + GError **error) { - AsyncAsSyncData data; - gboolean ok; + AsyncAsSyncData data; + gboolean ok; - data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + return g_input_stream_close (stream, cancellable, error); - g_input_stream_close_async (stream, G_PRIORITY_DEFAULT, cancellable, - async_as_sync_callback, &data); - g_main_loop_run (data.loop); + data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); - ok = g_input_stream_close_finish (stream, data.result, error); + g_input_stream_close_async (stream, G_PRIORITY_DEFAULT, cancellable, + async_as_sync_callback, &data); + g_main_loop_run (data.loop); - g_main_loop_unref (data.loop); - g_object_unref (data.result); + ok = g_input_stream_close_finish (stream, data.result, error); - return ok; + g_main_loop_unref (data.loop); + g_object_unref (data.result); + + return ok; } diff --git a/tests/test-utils.h b/tests/test-utils.h index 9e969038..5c244f34 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -32,9 +32,10 @@ SoupServer *soup_test_server_new (gboolean in_own_thread); SoupServer *soup_test_server_new_ssl (gboolean in_own_thread); void soup_test_server_quit_unref (SoupServer *server); -GInputStream *soup_test_request_send_async_as_sync (SoupRequest *req, - GCancellable *cancellable, - GError **error); -gboolean soup_test_stream_close_async_as_sync (GInputStream *stream, - GCancellable *cancellable, - GError **error); +GInputStream *soup_test_request_send (SoupRequest *req, + GCancellable *cancellable, + GError **error); +gboolean soup_test_request_close_stream (SoupRequest *req, + GInputStream *stream, + GCancellable *cancellable, + GError **error); diff --git a/tests/timeout-test.c b/tests/timeout-test.c index aad2c3d4..5c9d6a81 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -127,10 +127,7 @@ do_request_to_session (SoupRequester *requester, const char *uri, g_signal_connect (msg, "finished", G_CALLBACK (message_finished), &finished); - if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) - stream = soup_request_send (req, NULL, &error); - else - stream = soup_test_request_send_async_as_sync (req, NULL, &error); + stream = soup_test_request_send (req, NULL, &error); if (expect_timeout && !error) { debug_printf (1, " FAILED: request did not time out\n"); @@ -148,10 +145,7 @@ do_request_to_session (SoupRequester *requester, const char *uri, g_clear_error (&error); if (stream) { - if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) - g_input_stream_close (stream, NULL, &error); - else - soup_test_stream_close_async_as_sync (stream, NULL, &error); + soup_test_request_close_stream (req, stream, NULL, &error); if (error) { debug_printf (1, " ERROR closing string: %s", -- cgit v1.2.1 From 8c6df9feaf38f8ba21c241618048384842dbb302 Mon Sep 17 00:00:00 2001 From: Kjartan Maraas Date: Wed, 25 Jul 2012 16:29:32 +0200 Subject: =?UTF-8?q?Updated=20Norwegian=20bokm=C3=A5l=20translation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- po/nb.po | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/po/nb.po b/po/nb.po index 85295b12..2b6c1073 100644 --- a/po/nb.po +++ b/po/nb.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup 3.5.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-10 07:56+0200\n" -"PO-Revision-Date: 2012-07-10 07:57+0200\n" +"POT-Creation-Date: 2012-07-25 16:29+0200\n" +"PO-Revision-Date: 2012-07-25 16:29+0200\n" "Last-Translator: Kjartan Maraas \n" "Language-Team: Norwegian bokmål \n" "Language: \n" @@ -16,53 +16,57 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Tilkoblingen ble brutt uventet" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:191 #, c-format msgid "Output buffer is too small" msgstr "Buffer for utdata er for liten" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "Operasjonen ble avbrutt" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:864 msgid "Operation would block" msgstr "Operasjonen ville blokkere" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "Ingen URI ble oppgitt" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Ugyldig «%s» URI: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Kunne ikke tolke URI «%s»" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "URI-skjema «%s» er ikke støttet" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:148 msgid "Hostname is an IP address" msgstr "Vertsnavnet er en IP-adresse" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:169 msgid "Invalid hostname" msgstr "Ugyldig vertsnavn" -#: ../libsoup/soup-tld.c:181 ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "Ikke mange nok domener" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Vertsnavnet har ikke noe grunndomene" -- cgit v1.2.1 From 4922c368c0314a6df0ffce24c094302d2a59089e Mon Sep 17 00:00:00 2001 From: Cheng Lu Date: Thu, 26 Jul 2012 13:35:55 +0800 Subject: Update Chinese simplified translation for ui --- po/zh_CN.po | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/po/zh_CN.po b/po/zh_CN.po index 9c94b06a..9ad60d54 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -3,55 +3,74 @@ # This file is distributed under the same license as the libsoup package. # hmasterwang , 2012. # Alpha Cheng , 2012. +# Cheng Lu , 2012. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-05-24 20:15+0000\n" -"PO-Revision-Date: 2012-05-22 17:55+0800\n" -"Last-Translator: Wylmer Wang \n" -"Language-Team: Chinese (China) \n" +"POT-Creation-Date: 2012-07-25 14:24+0000\n" +"PO-Revision-Date: 2012-07-26 13:31+0800\n" +"Last-Translator: Cheng Lu \n" +"Language-Team: Chinese (simplified) \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "连接异常终止" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:191 #, c-format msgid "Output buffer is too small" msgstr "输出缓冲区太小" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "操作被取消" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:864 msgid "Operation would block" msgstr "操作将阻塞" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "未提供 URI" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "无效的“%s”URI:%s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "无法解析 URI:“%s”" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "不支持的 URI 方案:“%s”" + +#: ../libsoup/soup-tld.c:148 +msgid "Hostname is an IP address" +msgstr "主机名是一个 IP 地址" + +#: ../libsoup/soup-tld.c:169 +msgid "Invalid hostname" +msgstr "主机名无效" + +#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "没有足够的域" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "主机名没有基域" -- cgit v1.2.1 From 4b8a040b84d67d5cd9c2ed2063416aa08a676af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Forysiuk?= Date: Thu, 26 Jul 2012 20:44:02 +0200 Subject: Fix building with MinGW compiler --- libsoup/soup-auth-digest.c | 3 +++ libsoup/soup-session-feature.c | 8 ++++---- tests/get.c | 4 ++++ tests/simple-httpd.c | 4 ++++ tests/simple-proxy.c | 4 ++++ 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/libsoup/soup-auth-digest.c b/libsoup/soup-auth-digest.c index 5fe75610..ccdbb2e5 100644 --- a/libsoup/soup-auth-digest.c +++ b/libsoup/soup-auth-digest.c @@ -10,6 +10,9 @@ #endif #include +#ifdef G_OS_WIN32 +#include +#endif #include "soup-auth-digest.h" #include "soup.h" diff --git a/libsoup/soup-session-feature.c b/libsoup/soup-session-feature.c index 9f9b235a..560bb8f7 100644 --- a/libsoup/soup-session-feature.c +++ b/libsoup/soup-session-feature.c @@ -52,7 +52,7 @@ * Since: 2.24 **/ -static void soup_session_feature_default_init (SoupSessionFeatureInterface *interface); +static void soup_session_feature_default_init (SoupSessionFeatureInterface *iface); G_DEFINE_INTERFACE (SoupSessionFeature, soup_session_feature, G_TYPE_OBJECT) @@ -142,10 +142,10 @@ soup_session_feature_detach (SoupSessionFeature *feature, } static void -soup_session_feature_default_init (SoupSessionFeatureInterface *interface) +soup_session_feature_default_init (SoupSessionFeatureInterface *iface) { - interface->attach = soup_session_feature_real_attach; - interface->detach = soup_session_feature_real_detach; + iface->attach = soup_session_feature_real_attach; + iface->detach = soup_session_feature_real_detach; } /** diff --git a/tests/get.c b/tests/get.c index 1d867155..9672ded8 100644 --- a/tests/get.c +++ b/tests/get.c @@ -6,6 +6,10 @@ #include "test-utils.h" #include +#ifdef G_OS_WIN32 +#include +#endif + static SoupSession *session; static GMainLoop *loop; static gboolean debug = FALSE, quiet = FALSE; diff --git a/tests/simple-httpd.c b/tests/simple-httpd.c index 46f0988d..41aa8a35 100644 --- a/tests/simple-httpd.c +++ b/tests/simple-httpd.c @@ -11,6 +11,10 @@ #include #include +#ifdef G_OS_WIN32 +#include +#endif + #ifdef HAVE_MMAP #include #endif diff --git a/tests/simple-proxy.c b/tests/simple-proxy.c index f25f9a04..0600e53d 100644 --- a/tests/simple-proxy.c +++ b/tests/simple-proxy.c @@ -5,6 +5,10 @@ #include "test-utils.h" +#ifdef G_OS_WIN32 +#include +#endif + /* WARNING: this is really really really not especially compliant with * RFC 2616. But it does work for basic stuff. */ -- cgit v1.2.1 From f5902fce98ae0314f0d9ca6e544895548c94a456 Mon Sep 17 00:00:00 2001 From: Sweta Kothari Date: Fri, 27 Jul 2012 14:36:06 +0530 Subject: Updated gujarati file & Added LINGUAS file for gujarati --- po/LINGUAS | 1 + po/gu.po | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 po/gu.po diff --git a/po/LINGUAS b/po/LINGUAS index fc8a7380..b1446e75 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -5,6 +5,7 @@ el es fr gl +gu he id lt diff --git a/po/gu.po b/po/gu.po new file mode 100644 index 00000000..dcca9547 --- /dev/null +++ b/po/gu.po @@ -0,0 +1,76 @@ +# Gujarati translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-07-26 18:48+0000\n" +"PO-Revision-Date: 2012-07-27 14:35+0530\n" +"Last-Translator: \n" +"Language-Team: gu_IN \n" +"Language: gu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.0\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "જોડાણ અનિચ્છનીય રીતે તૂટી ગયુ" + +#: ../libsoup/soup-converter-wrapper.c:191 +#, c-format +msgid "Output buffer is too small" +msgstr "આઉટપુટ બફર ઘણુ નાનું છે" + +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +msgid "Operation was cancelled" +msgstr "ક્રિયા રદ થયેલ હતી" + +#: ../libsoup/soup-message-io.c:864 +msgid "Operation would block" +msgstr "ક્રિયા રોકી રખાશે" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI પૂરુ પાડેલ નથી" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "અમાન્ય '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' ને પદચ્છેદન કરી શક્યા નહિં" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "બિનઆધારભૂત URI યોજના '%s'" + +#: ../libsoup/soup-tld.c:148 +msgid "Hostname is an IP address" +msgstr "યજમાનનામ એ IP સરનામું છે" + +#: ../libsoup/soup-tld.c:169 +msgid "Invalid hostname" +msgstr "અમાન્ય યજમાનનામ" + +#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "પૂરતુ ડોમેઇન નથી" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "યજમાન પાસે મૂળ ડોમેઇન નથી" + -- cgit v1.2.1 From 8e86ea68fd00adb48c52d0b64fa3203858c89f77 Mon Sep 17 00:00:00 2001 From: Alexsey Nadtochey Date: Mon, 30 Jul 2012 15:40:13 +0400 Subject: Updated Russian translation --- po/ru.po | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/po/ru.po b/po/ru.po index abb606b1..aa8e7e70 100644 --- a/po/ru.po +++ b/po/ru.po @@ -6,49 +6,70 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-04-22 08:40+0000\n" -"PO-Revision-Date: 2012-04-23 12:43+0300\n" -"Last-Translator: Yuri Myasoedov \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-07-27 09:06+0000\n" +"PO-Revision-Date: 2012-07-30 13:40+0300\n" +"Last-Translator: Alexsey Nadtochey \n" "Language-Team: Russian \n" +"Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 -#: ../libsoup/soup-message-io.c:232 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Соединение было неожиданно разорвано" -#: ../libsoup/soup-converter-wrapper.c:185 +#: ../libsoup/soup-converter-wrapper.c:191 #, c-format msgid "Output buffer is too small" msgstr "Слишком маленький буфер вывода" -#: ../libsoup/soup-message-io.c:818 +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "Действие отменено" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-message-io.c:864 +msgid "Operation would block" +msgstr "Действие заблокировано" + +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "Не указан URI" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Недопустимый URI «%s»: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Не удалось разобрать URI «%s»" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Неподдерживаемая схема URI «%s»" +#: ../libsoup/soup-tld.c:148 +msgid "Hostname is an IP address" +msgstr "Имя компьютера является IP-адресом" + +#: ../libsoup/soup-tld.c:169 +msgid "Invalid hostname" +msgstr "Неверное имя компьютера" + +#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Недостаточно доменных имён в адресе" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Имя компьютера не содержит доменной части" -- cgit v1.2.1 From 9bf2854f7ff06f0be4eb7305312adacacd2b9151 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 30 Jul 2012 12:13:16 -0400 Subject: autogen.sh: remove two outdated bits --- autogen.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autogen.sh b/autogen.sh index a329db5b..e748f3a1 100755 --- a/autogen.sh +++ b/autogen.sh @@ -15,7 +15,7 @@ PKG_NAME="libsoup" } which gnome-autogen.sh || { - echo "You need to install gnome-common from the GNOME CVS" + echo "You need to install gnome-common" exit 1 } -USE_GNOME2_MACROS=1 . gnome-autogen.sh +. gnome-autogen.sh -- cgit v1.2.1 From 312f65f4f60486e36112c8d1aeb4f5d81b6eac5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Di=C3=A9guez?= Date: Tue, 31 Jul 2012 02:02:52 +0200 Subject: Updated Galician translations --- po/gl.po | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/po/gl.po b/po/gl.po index c493a55c..90e6e749 100644 --- a/po/gl.po +++ b/po/gl.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-06-24 23:26+0200\n" -"PO-Revision-Date: 2012-06-24 23:26+0200\n" +"POT-Creation-Date: 2012-07-31 02:02+0200\n" +"PO-Revision-Date: 2012-07-31 02:02+0200\n" "Last-Translator: Fran Dieguez \n" "Language-Team: Galician \n" "Language: gl\n" @@ -19,53 +19,57 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n!=1);\n" "X-Generator: Gtranslator 2.91.5\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "A conexión rematou de forma non esperada" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:191 #, c-format msgid "Output buffer is too small" msgstr "O búfer de saída é demasiado pequeno" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "A operación foi cancelada" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:864 msgid "Operation would block" msgstr "A operación bloquearase" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "Non se forneceu un URI" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI «%s» non válida: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Non é posíbel analizar o URI «%s»" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Esquema de URI «%s» non admitido" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:148 msgid "Hostname is an IP address" msgstr "O nome do computador é un enderezo IP" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:169 msgid "Invalid hostname" msgstr "O nome do computador non é válido" -#: ../libsoup/soup-tld.c:181 ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "Non hai dominios dabondo" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "O nome do computador non ten un dominio base" -- cgit v1.2.1 From 703c68b72f5fe6c033373946c25f3c6cac92b9ef Mon Sep 17 00:00:00 2001 From: Kristjan SCHMIDT Date: Wed, 1 Aug 2012 20:01:48 +0200 Subject: Add Esperanto translation --- po/LINGUAS | 1 + po/eo.po | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 po/eo.po diff --git a/po/LINGUAS b/po/LINGUAS index b1446e75..f3f53185 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -2,6 +2,7 @@ as bg be el +eo es fr gl diff --git a/po/eo.po b/po/eo.po new file mode 100644 index 00000000..c1550eef --- /dev/null +++ b/po/eo.po @@ -0,0 +1,74 @@ +# Esperanto translation for libsoup. +# Copyright (C) 2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Kristjan SCHMIDT , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-07-31 00:03+0000\n" +"PO-Revision-Date: 2012-08-01 19:57+0200\n" +"Last-Translator: Kristjan SCHMIDT \n" +"Language-Team: Esperanto \n" +"Language: eo\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "La konekto estas neatendite fermita." + +#: ../libsoup/soup-converter-wrapper.c:191 +#, c-format +msgid "Output buffer is too small" +msgstr "La elig-bufro estas tro malgranda" + +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +msgid "Operation was cancelled" +msgstr "La operacio estas ĉesigita" + +#: ../libsoup/soup-message-io.c:864 +msgid "Operation would block" +msgstr "La operacio estus haltigota." + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Neniu URI estas diponigita" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Nevalida '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Ne eblis analizi na URI '%s'" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Nesuptenata URI-skemo '%s'" + +#: ../libsoup/soup-tld.c:148 +msgid "Hostname is an IP address" +msgstr "La komputilnomo estas IP-adreso" + +#: ../libsoup/soup-tld.c:169 +msgid "Invalid hostname" +msgstr "Nevalida komputilnomo" + +#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Ne sufiĉe da retregionoj" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "La komputilnomo ne havas ĉefan retregionon" -- cgit v1.2.1 From 3f48d1b6d64efd30364dab23b03773127548cae9 Mon Sep 17 00:00:00 2001 From: Nilamdyuti Goswami Date: Fri, 3 Aug 2012 15:38:38 +0530 Subject: Assamese translation updated --- po/as.po | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/po/as.po b/po/as.po index 442b9813..011d2c01 100644 --- a/po/as.po +++ b/po/as.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." "cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-12 15:59+0000\n" -"PO-Revision-Date: 2012-07-13 20:11+0530\n" +"POT-Creation-Date: 2012-07-16 22:04+0000\n" +"PO-Revision-Date: 2012-08-03 15:38+0530\n" "Last-Translator: Nilamdyuti Goswami \n" "Language-Team: as_IN \n" "Language: as\n" @@ -19,54 +19,58 @@ msgstr "" "X-Generator: Lokalize 1.0\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "সংযোগ অপ্ৰত্যাশিতভাৱে অন্ত হল" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:189 #, c-format msgid "Output buffer is too small" msgstr "আউটপুট বাফাৰ অতি সৰু" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "কাৰ্য্য বাতিল কৰা হৈছিল" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:864 msgid "Operation would block" msgstr "কাৰ্য্য প্ৰতিৰোধ কৰিব" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "কোনো URl প্ৰদান কৰা হোৱা নাই" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "অবৈধ '%s' URI: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' বিশ্লেষণ কৰিব পৰা নগল" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "অসমৰ্থিত URl আঁচনি '%s'" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:143 msgid "Hostname is an IP address" msgstr "হস্টনাম এটা IP ঠিকনা" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:164 msgid "Invalid hostname" msgstr "অবৈধ হস্টনাম" -#: ../libsoup/soup-tld.c:181 ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:179 ../libsoup/soup-tld.c:221 msgid "Not enough domains" msgstr "পৰ্যাপ্ত ডমেইন নাই" +#: ../libsoup/soup-tld.c:199 +msgid "Hostname has no base domain" +msgstr "হস্টনামৰ কোনো ভিত্তি ডমেইন নাই" + -- cgit v1.2.1 From fbaa0744b98a5e748b99f815b5465ebd8da535ee Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 6 Aug 2012 10:17:28 -0400 Subject: update effective_tld_names.dat --- data/effective_tld_names.dat | 1957 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 1781 insertions(+), 176 deletions(-) diff --git a/data/effective_tld_names.dat b/data/effective_tld_names.dat index 0df8800d..1738ab3e 100644 --- a/data/effective_tld_names.dat +++ b/data/effective_tld_names.dat @@ -1,44 +1,6 @@ -// ***** BEGIN LICENSE BLOCK ***** -// Version: MPL 1.1/GPL 2.0/LGPL 2.1 -// -// The contents of this file are subject to the Mozilla Public License Version -// 1.1 (the "License"); you may not use this file except in compliance with -// the License. You may obtain a copy of the License at -// http://www.mozilla.org/MPL/ -// -// Software distributed under the License is distributed on an "AS IS" basis, -// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -// for the specific language governing rights and limitations under the -// License. -// -// The Original Code is the Public Suffix List. -// -// The Initial Developer of the Original Code is -// Jo Hermans . -// Portions created by the Initial Developer are Copyright (C) 2007 -// the Initial Developer. All Rights Reserved. -// -// Contributor(s): -// Ruben Arakelyan -// Gervase Markham -// Pamela Greene -// David Triendl -// Jothan Frakes -// The kind representatives of many TLD registries -// -// Alternatively, the contents of this file may be used under the terms of -// either the GNU General Public License Version 2 or later (the "GPL"), or -// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -// in which case the provisions of the GPL or the LGPL are applicable instead -// of those above. If you wish to allow use of your version of this file only -// under the terms of either the GPL or the LGPL, and not to allow others to -// use your version of this file under the terms of the MPL, indicate your -// decision by deleting the provisions above and replace them with the notice -// and other provisions required by the GPL or the LGPL. If you do not delete -// the provisions above, a recipient may use your version of this file under -// the terms of any one of the MPL, the GPL or the LGPL. -// -// ***** END LICENSE BLOCK ***** +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. // ===BEGIN ICANN DOMAINS=== @@ -252,18 +214,18 @@ or.at // au : http://en.wikipedia.org/wiki/.au // http://www.auda.org.au/ // 2LDs -com.au -net.au -org.au -edu.au -gov.au -csiro.au -asn.au -id.au -// Historic 2LDs (closed to new registration, but sites still exist) -info.au -conf.au -oz.au +com.au +net.au +org.au +edu.au +gov.au +csiro.au +asn.au +id.au +// Historic 2LDs (closed to new registration, but sites still exist) +info.au +conf.au +oz.au // CGDNs - http://www.cgdn.org.au/ act.au nsw.au @@ -1511,10 +1473,9 @@ jobs // jp : http://en.wikipedia.org/wiki/.jp // http://jprs.co.jp/en/jpdomain.html -// Submitted by registry 2008-06-11 -// Updated by registry 2008-12-04 +// Updated by registry 2012-05-28 jp -// jp organizational type names +// jp organizational type names ac.jp ad.jp co.jp @@ -1524,125 +1485,1750 @@ gr.jp lg.jp ne.jp or.jp +// jp preficture type names +aichi.jp +akita.jp +aomori.jp +chiba.jp +ehime.jp +fukui.jp +fukuoka.jp +fukushima.jp +gifu.jp +gunma.jp +hiroshima.jp +hokkaido.jp +hyogo.jp +ibaraki.jp +ishikawa.jp +iwate.jp +kagawa.jp +kagoshima.jp +kanagawa.jp +kochi.jp +kumamoto.jp +kyoto.jp +mie.jp +miyagi.jp +miyazaki.jp +nagano.jp +nagasaki.jp +nara.jp +niigata.jp +oita.jp +okayama.jp +okinawa.jp +osaka.jp +saga.jp +saitama.jp +shiga.jp +shimane.jp +shizuoka.jp +tochigi.jp +tokushima.jp +tokyo.jp +tottori.jp +toyama.jp +wakayama.jp +yamagata.jp +yamaguchi.jp +yamanashi.jp // jp geographic type names // http://jprs.jp/doc/rule/saisoku-1.html -*.aichi.jp -*.akita.jp -*.aomori.jp -*.chiba.jp -*.ehime.jp -*.fukui.jp -*.fukuoka.jp -*.fukushima.jp -*.gifu.jp -*.gunma.jp -*.hiroshima.jp -*.hokkaido.jp -*.hyogo.jp -*.ibaraki.jp -*.ishikawa.jp -*.iwate.jp -*.kagawa.jp -*.kagoshima.jp -*.kanagawa.jp *.kawasaki.jp *.kitakyushu.jp *.kobe.jp -*.kochi.jp -*.kumamoto.jp -*.kyoto.jp -*.mie.jp -*.miyagi.jp -*.miyazaki.jp -*.nagano.jp -*.nagasaki.jp *.nagoya.jp -*.nara.jp -*.niigata.jp -*.oita.jp -*.okayama.jp -*.okinawa.jp -*.osaka.jp -*.saga.jp -*.saitama.jp *.sapporo.jp *.sendai.jp -*.shiga.jp -*.shimane.jp -*.shizuoka.jp -*.tochigi.jp -*.tokushima.jp -*.tokyo.jp -*.tottori.jp -*.toyama.jp -*.wakayama.jp -*.yamagata.jp -*.yamaguchi.jp -*.yamanashi.jp *.yokohama.jp -!metro.tokyo.jp -!pref.aichi.jp -!pref.akita.jp -!pref.aomori.jp -!pref.chiba.jp -!pref.ehime.jp -!pref.fukui.jp -!pref.fukuoka.jp -!pref.fukushima.jp -!pref.gifu.jp -!pref.gunma.jp -!pref.hiroshima.jp -!pref.hokkaido.jp -!pref.hyogo.jp -!pref.ibaraki.jp -!pref.ishikawa.jp -!pref.iwate.jp -!pref.kagawa.jp -!pref.kagoshima.jp -!pref.kanagawa.jp -!pref.kochi.jp -!pref.kumamoto.jp -!pref.kyoto.jp -!pref.mie.jp -!pref.miyagi.jp -!pref.miyazaki.jp -!pref.nagano.jp -!pref.nagasaki.jp -!pref.nara.jp -!pref.niigata.jp -!pref.oita.jp -!pref.okayama.jp -!pref.okinawa.jp -!pref.osaka.jp -!pref.saga.jp -!pref.saitama.jp -!pref.shiga.jp -!pref.shimane.jp -!pref.shizuoka.jp -!pref.tochigi.jp -!pref.tokushima.jp -!pref.tottori.jp -!pref.toyama.jp -!pref.wakayama.jp -!pref.yamagata.jp -!pref.yamaguchi.jp -!pref.yamanashi.jp -!city.chiba.jp -!city.fukuoka.jp -!city.hiroshima.jp !city.kawasaki.jp !city.kitakyushu.jp !city.kobe.jp -!city.kyoto.jp !city.nagoya.jp -!city.niigata.jp -!city.okayama.jp -!city.osaka.jp -!city.saitama.jp !city.sapporo.jp !city.sendai.jp -!city.shizuoka.jp !city.yokohama.jp +// 4th level registration +aisai.aichi.jp +ama.aichi.jp +anjo.aichi.jp +asuke.aichi.jp +chiryu.aichi.jp +chita.aichi.jp +fuso.aichi.jp +gamagori.aichi.jp +handa.aichi.jp +hazu.aichi.jp +hekinan.aichi.jp +higashiura.aichi.jp +ichinomiya.aichi.jp +inazawa.aichi.jp +inuyama.aichi.jp +isshiki.aichi.jp +iwakura.aichi.jp +kanie.aichi.jp +kariya.aichi.jp +kasugai.aichi.jp +kira.aichi.jp +kiyosu.aichi.jp +komaki.aichi.jp +konan.aichi.jp +kota.aichi.jp +mihama.aichi.jp +miyoshi.aichi.jp +nagakute.aichi.jp +nishio.aichi.jp +nisshin.aichi.jp +obu.aichi.jp +oguchi.aichi.jp +oharu.aichi.jp +okazaki.aichi.jp +owariasahi.aichi.jp +seto.aichi.jp +shikatsu.aichi.jp +shinshiro.aichi.jp +shitara.aichi.jp +tahara.aichi.jp +takahama.aichi.jp +tobishima.aichi.jp +toei.aichi.jp +togo.aichi.jp +tokai.aichi.jp +tokoname.aichi.jp +toyoake.aichi.jp +toyohashi.aichi.jp +toyokawa.aichi.jp +toyone.aichi.jp +toyota.aichi.jp +tsushima.aichi.jp +yatomi.aichi.jp +akita.akita.jp +daisen.akita.jp +fujisato.akita.jp +gojome.akita.jp +hachirogata.akita.jp +happou.akita.jp +higashinaruse.akita.jp +honjo.akita.jp +honjyo.akita.jp +ikawa.akita.jp +kamikoani.akita.jp +kamioka.akita.jp +katagami.akita.jp +kazuno.akita.jp +kitaakita.akita.jp +kosaka.akita.jp +kyowa.akita.jp +misato.akita.jp +mitane.akita.jp +moriyoshi.akita.jp +nikaho.akita.jp +noshiro.akita.jp +odate.akita.jp +oga.akita.jp +ogata.akita.jp +semboku.akita.jp +yokote.akita.jp +yurihonjo.akita.jp +aomori.aomori.jp +gonohe.aomori.jp +hachinohe.aomori.jp +hashikami.aomori.jp +hiranai.aomori.jp +hirosaki.aomori.jp +itayanagi.aomori.jp +kuroishi.aomori.jp +misawa.aomori.jp +mutsu.aomori.jp +nakadomari.aomori.jp +noheji.aomori.jp +oirase.aomori.jp +owani.aomori.jp +rokunohe.aomori.jp +sannohe.aomori.jp +shichinohe.aomori.jp +shingo.aomori.jp +takko.aomori.jp +towada.aomori.jp +tsugaru.aomori.jp +tsuruta.aomori.jp +abiko.chiba.jp +asahi.chiba.jp +chonan.chiba.jp +chosei.chiba.jp +choshi.chiba.jp +chuo.chiba.jp +funabashi.chiba.jp +futtsu.chiba.jp +hanamigawa.chiba.jp +ichihara.chiba.jp +ichikawa.chiba.jp +ichinomiya.chiba.jp +inzai.chiba.jp +isumi.chiba.jp +kamagaya.chiba.jp +kamogawa.chiba.jp +kashiwa.chiba.jp +katori.chiba.jp +katsuura.chiba.jp +kimitsu.chiba.jp +kisarazu.chiba.jp +kozaki.chiba.jp +kujukuri.chiba.jp +kyonan.chiba.jp +matsudo.chiba.jp +midori.chiba.jp +mihama.chiba.jp +minamiboso.chiba.jp +mobara.chiba.jp +mutsuzawa.chiba.jp +nagara.chiba.jp +nagareyama.chiba.jp +narashino.chiba.jp +narita.chiba.jp +noda.chiba.jp +oamishirasato.chiba.jp +omigawa.chiba.jp +onjuku.chiba.jp +otaki.chiba.jp +sakae.chiba.jp +sakura.chiba.jp +shimofusa.chiba.jp +shirako.chiba.jp +shiroi.chiba.jp +shisui.chiba.jp +sodegaura.chiba.jp +sosa.chiba.jp +tako.chiba.jp +tateyama.chiba.jp +togane.chiba.jp +tohnosho.chiba.jp +tomisato.chiba.jp +urayasu.chiba.jp +yachimata.chiba.jp +yachiyo.chiba.jp +yokaichiba.chiba.jp +yokoshibahikari.chiba.jp +yotsukaido.chiba.jp +ainan.ehime.jp +honai.ehime.jp +ikata.ehime.jp +imabari.ehime.jp +iyo.ehime.jp +kamijima.ehime.jp +kihoku.ehime.jp +kumakogen.ehime.jp +masaki.ehime.jp +matsuno.ehime.jp +matsuyama.ehime.jp +namikata.ehime.jp +niihama.ehime.jp +ozu.ehime.jp +saijo.ehime.jp +seiyo.ehime.jp +shikokuchuo.ehime.jp +tobe.ehime.jp +toon.ehime.jp +uchiko.ehime.jp +uwajima.ehime.jp +yawatahama.ehime.jp +echizen.fukui.jp +eiheiji.fukui.jp +fukui.fukui.jp +ikeda.fukui.jp +katsuyama.fukui.jp +mihama.fukui.jp +minamiechizen.fukui.jp +obama.fukui.jp +ohi.fukui.jp +ono.fukui.jp +sabae.fukui.jp +sakai.fukui.jp +takahama.fukui.jp +tsuruga.fukui.jp +wakasa.fukui.jp +ashiya.fukuoka.jp +buzen.fukuoka.jp +chikugo.fukuoka.jp +chikuho.fukuoka.jp +chikujo.fukuoka.jp +chikushino.fukuoka.jp +chikuzen.fukuoka.jp +chuo.fukuoka.jp +dazaifu.fukuoka.jp +fukuchi.fukuoka.jp +hakata.fukuoka.jp +higashi.fukuoka.jp +hirokawa.fukuoka.jp +hisayama.fukuoka.jp +iizuka.fukuoka.jp +inatsuki.fukuoka.jp +kaho.fukuoka.jp +kasuga.fukuoka.jp +kasuya.fukuoka.jp +kawara.fukuoka.jp +keisen.fukuoka.jp +koga.fukuoka.jp +kurate.fukuoka.jp +kurogi.fukuoka.jp +kurume.fukuoka.jp +minami.fukuoka.jp +miyako.fukuoka.jp +miyama.fukuoka.jp +miyawaka.fukuoka.jp +mizumaki.fukuoka.jp +munakata.fukuoka.jp +nakagawa.fukuoka.jp +nakama.fukuoka.jp +nishi.fukuoka.jp +nogata.fukuoka.jp +ogori.fukuoka.jp +okagaki.fukuoka.jp +okawa.fukuoka.jp +oki.fukuoka.jp +omuta.fukuoka.jp +onga.fukuoka.jp +onojo.fukuoka.jp +oto.fukuoka.jp +saigawa.fukuoka.jp +sasaguri.fukuoka.jp +shingu.fukuoka.jp +shinyoshitomi.fukuoka.jp +shonai.fukuoka.jp +soeda.fukuoka.jp +sue.fukuoka.jp +tachiarai.fukuoka.jp +tagawa.fukuoka.jp +takata.fukuoka.jp +toho.fukuoka.jp +toyotsu.fukuoka.jp +tsuiki.fukuoka.jp +ukiha.fukuoka.jp +umi.fukuoka.jp +usui.fukuoka.jp +yamada.fukuoka.jp +yame.fukuoka.jp +yanagawa.fukuoka.jp +yukuhashi.fukuoka.jp +aizubange.fukushima.jp +aizumisato.fukushima.jp +aizuwakamatsu.fukushima.jp +asakawa.fukushima.jp +bandai.fukushima.jp +date.fukushima.jp +fukushima.fukushima.jp +furudono.fukushima.jp +futaba.fukushima.jp +hanawa.fukushima.jp +higashi.fukushima.jp +hirata.fukushima.jp +hirono.fukushima.jp +iitate.fukushima.jp +inawashiro.fukushima.jp +ishikawa.fukushima.jp +iwaki.fukushima.jp +izumizaki.fukushima.jp +kagamiishi.fukushima.jp +kaneyama.fukushima.jp +kawamata.fukushima.jp +kitakata.fukushima.jp +kitashiobara.fukushima.jp +koori.fukushima.jp +koriyama.fukushima.jp +kunimi.fukushima.jp +miharu.fukushima.jp +mishima.fukushima.jp +namie.fukushima.jp +nango.fukushima.jp +nishiaizu.fukushima.jp +nishigo.fukushima.jp +okuma.fukushima.jp +omotego.fukushima.jp +ono.fukushima.jp +otama.fukushima.jp +samegawa.fukushima.jp +shimogo.fukushima.jp +shirakawa.fukushima.jp +showa.fukushima.jp +soma.fukushima.jp +sukagawa.fukushima.jp +taishin.fukushima.jp +tamakawa.fukushima.jp +tanagura.fukushima.jp +tenei.fukushima.jp +yabuki.fukushima.jp +yamato.fukushima.jp +yamatsuri.fukushima.jp +yanaizu.fukushima.jp +yugawa.fukushima.jp +anpachi.gifu.jp +ena.gifu.jp +gifu.gifu.jp +ginan.gifu.jp +godo.gifu.jp +gujo.gifu.jp +hashima.gifu.jp +hichiso.gifu.jp +hida.gifu.jp +higashishirakawa.gifu.jp +ibigawa.gifu.jp +ikeda.gifu.jp +kakamigahara.gifu.jp +kani.gifu.jp +kasahara.gifu.jp +kasamatsu.gifu.jp +kawaue.gifu.jp +kitagata.gifu.jp +mino.gifu.jp +minokamo.gifu.jp +mitake.gifu.jp +mizunami.gifu.jp +motosu.gifu.jp +nakatsugawa.gifu.jp +ogaki.gifu.jp +sakahogi.gifu.jp +seki.gifu.jp +sekigahara.gifu.jp +shirakawa.gifu.jp +tajimi.gifu.jp +takayama.gifu.jp +tarui.gifu.jp +toki.gifu.jp +tomika.gifu.jp +wanouchi.gifu.jp +yamagata.gifu.jp +yaotsu.gifu.jp +yoro.gifu.jp +annaka.gunma.jp +chiyoda.gunma.jp +fujioka.gunma.jp +higashiagatsuma.gunma.jp +isesaki.gunma.jp +itakura.gunma.jp +kanna.gunma.jp +kanra.gunma.jp +katashina.gunma.jp +kawaba.gunma.jp +kiryu.gunma.jp +kusatsu.gunma.jp +maebashi.gunma.jp +meiwa.gunma.jp +midori.gunma.jp +minakami.gunma.jp +naganohara.gunma.jp +nakanojo.gunma.jp +nanmoku.gunma.jp +numata.gunma.jp +oizumi.gunma.jp +ora.gunma.jp +ota.gunma.jp +shibukawa.gunma.jp +shimonita.gunma.jp +shinto.gunma.jp +showa.gunma.jp +takasaki.gunma.jp +takayama.gunma.jp +tamamura.gunma.jp +tatebayashi.gunma.jp +tomioka.gunma.jp +tsukiyono.gunma.jp +tsumagoi.gunma.jp +ueno.gunma.jp +yoshioka.gunma.jp +asaminami.hiroshima.jp +daiwa.hiroshima.jp +etajima.hiroshima.jp +fuchu.hiroshima.jp +fukuyama.hiroshima.jp +hatsukaichi.hiroshima.jp +higashihiroshima.hiroshima.jp +hongo.hiroshima.jp +jinsekikogen.hiroshima.jp +kaita.hiroshima.jp +kui.hiroshima.jp +kumano.hiroshima.jp +kure.hiroshima.jp +mihara.hiroshima.jp +miyoshi.hiroshima.jp +naka.hiroshima.jp +onomichi.hiroshima.jp +osakikamijima.hiroshima.jp +otake.hiroshima.jp +saka.hiroshima.jp +sera.hiroshima.jp +seranishi.hiroshima.jp +shinichi.hiroshima.jp +shobara.hiroshima.jp +takehara.hiroshima.jp +abashiri.hokkaido.jp +abira.hokkaido.jp +aibetsu.hokkaido.jp +akabira.hokkaido.jp +akkeshi.hokkaido.jp +asahikawa.hokkaido.jp +ashibetsu.hokkaido.jp +ashoro.hokkaido.jp +assabu.hokkaido.jp +atsuma.hokkaido.jp +bibai.hokkaido.jp +biei.hokkaido.jp +bifuka.hokkaido.jp +bihoro.hokkaido.jp +biratori.hokkaido.jp +chippubetsu.hokkaido.jp +chitose.hokkaido.jp +date.hokkaido.jp +ebetsu.hokkaido.jp +embetsu.hokkaido.jp +eniwa.hokkaido.jp +erimo.hokkaido.jp +esan.hokkaido.jp +esashi.hokkaido.jp +fukagawa.hokkaido.jp +fukushima.hokkaido.jp +furano.hokkaido.jp +furubira.hokkaido.jp +haboro.hokkaido.jp +hakodate.hokkaido.jp +hamatonbetsu.hokkaido.jp +hidaka.hokkaido.jp +higashikagura.hokkaido.jp +higashikawa.hokkaido.jp +hiroo.hokkaido.jp +hokuryu.hokkaido.jp +hokuto.hokkaido.jp +honbetsu.hokkaido.jp +horokanai.hokkaido.jp +horonobe.hokkaido.jp +ikeda.hokkaido.jp +imakane.hokkaido.jp +ishikari.hokkaido.jp +iwamizawa.hokkaido.jp +iwanai.hokkaido.jp +kamifurano.hokkaido.jp +kamikawa.hokkaido.jp +kamishihoro.hokkaido.jp +kamisunagawa.hokkaido.jp +kamoenai.hokkaido.jp +kayabe.hokkaido.jp +kembuchi.hokkaido.jp +kikonai.hokkaido.jp +kimobetsu.hokkaido.jp +kitahiroshima.hokkaido.jp +kitami.hokkaido.jp +kiyosato.hokkaido.jp +koshimizu.hokkaido.jp +kunneppu.hokkaido.jp +kuriyama.hokkaido.jp +kuromatsunai.hokkaido.jp +kushiro.hokkaido.jp +kutchan.hokkaido.jp +kyowa.hokkaido.jp +mashike.hokkaido.jp +matsumae.hokkaido.jp +mikasa.hokkaido.jp +minamifurano.hokkaido.jp +mombetsu.hokkaido.jp +moseushi.hokkaido.jp +mukawa.hokkaido.jp +muroran.hokkaido.jp +naie.hokkaido.jp +nakagawa.hokkaido.jp +nakasatsunai.hokkaido.jp +nakatombetsu.hokkaido.jp +nanae.hokkaido.jp +nanporo.hokkaido.jp +nayoro.hokkaido.jp +nemuro.hokkaido.jp +niikappu.hokkaido.jp +niki.hokkaido.jp +nishiokoppe.hokkaido.jp +noboribetsu.hokkaido.jp +numata.hokkaido.jp +obihiro.hokkaido.jp +obira.hokkaido.jp +oketo.hokkaido.jp +okoppe.hokkaido.jp +otaru.hokkaido.jp +otobe.hokkaido.jp +otofuke.hokkaido.jp +otoineppu.hokkaido.jp +oumu.hokkaido.jp +ozora.hokkaido.jp +pippu.hokkaido.jp +rankoshi.hokkaido.jp +rebun.hokkaido.jp +rikubetsu.hokkaido.jp +rishiri.hokkaido.jp +rishirifuji.hokkaido.jp +saroma.hokkaido.jp +sarufutsu.hokkaido.jp +shakotan.hokkaido.jp +shari.hokkaido.jp +shibecha.hokkaido.jp +shibetsu.hokkaido.jp +shikabe.hokkaido.jp +shikaoi.hokkaido.jp +shimamaki.hokkaido.jp +shimizu.hokkaido.jp +shimokawa.hokkaido.jp +shinshinotsu.hokkaido.jp +shintoku.hokkaido.jp +shiranuka.hokkaido.jp +shiraoi.hokkaido.jp +shiriuchi.hokkaido.jp +sobetsu.hokkaido.jp +sunagawa.hokkaido.jp +taiki.hokkaido.jp +takasu.hokkaido.jp +takikawa.hokkaido.jp +takinoue.hokkaido.jp +teshikaga.hokkaido.jp +tobetsu.hokkaido.jp +tohma.hokkaido.jp +tomakomai.hokkaido.jp +tomari.hokkaido.jp +toya.hokkaido.jp +toyako.hokkaido.jp +toyotomi.hokkaido.jp +toyoura.hokkaido.jp +tsubetsu.hokkaido.jp +tsukigata.hokkaido.jp +urakawa.hokkaido.jp +urausu.hokkaido.jp +uryu.hokkaido.jp +utashinai.hokkaido.jp +wakkanai.hokkaido.jp +wassamu.hokkaido.jp +yakumo.hokkaido.jp +yoichi.hokkaido.jp +aioi.hyogo.jp +akashi.hyogo.jp +ako.hyogo.jp +amagasaki.hyogo.jp +aogaki.hyogo.jp +asago.hyogo.jp +ashiya.hyogo.jp +awaji.hyogo.jp +fukusaki.hyogo.jp +goshiki.hyogo.jp +harima.hyogo.jp +himeji.hyogo.jp +ichikawa.hyogo.jp +inagawa.hyogo.jp +itami.hyogo.jp +kakogawa.hyogo.jp +kamigori.hyogo.jp +kamikawa.hyogo.jp +kasai.hyogo.jp +kasuga.hyogo.jp +kawanishi.hyogo.jp +miki.hyogo.jp +minamiawaji.hyogo.jp +nishinomiya.hyogo.jp +nishiwaki.hyogo.jp +ono.hyogo.jp +sanda.hyogo.jp +sannan.hyogo.jp +sasayama.hyogo.jp +sayo.hyogo.jp +shingu.hyogo.jp +shinonsen.hyogo.jp +shiso.hyogo.jp +sumoto.hyogo.jp +taishi.hyogo.jp +taka.hyogo.jp +takarazuka.hyogo.jp +takasago.hyogo.jp +takino.hyogo.jp +tamba.hyogo.jp +tatsuno.hyogo.jp +toyooka.hyogo.jp +yabu.hyogo.jp +yashiro.hyogo.jp +yoka.hyogo.jp +yokawa.hyogo.jp +ami.ibaraki.jp +asahi.ibaraki.jp +bando.ibaraki.jp +chikusei.ibaraki.jp +daigo.ibaraki.jp +fujishiro.ibaraki.jp +hitachi.ibaraki.jp +hitachinaka.ibaraki.jp +hitachiomiya.ibaraki.jp +hitachiota.ibaraki.jp +ibaraki.ibaraki.jp +ina.ibaraki.jp +inashiki.ibaraki.jp +itako.ibaraki.jp +iwama.ibaraki.jp +joso.ibaraki.jp +kamisu.ibaraki.jp +kasama.ibaraki.jp +kashima.ibaraki.jp +kasumigaura.ibaraki.jp +koga.ibaraki.jp +miho.ibaraki.jp +mito.ibaraki.jp +moriya.ibaraki.jp +naka.ibaraki.jp +namegata.ibaraki.jp +oarai.ibaraki.jp +ogawa.ibaraki.jp +omitama.ibaraki.jp +ryugasaki.ibaraki.jp +sakai.ibaraki.jp +sakuragawa.ibaraki.jp +shimodate.ibaraki.jp +shimotsuma.ibaraki.jp +shirosato.ibaraki.jp +sowa.ibaraki.jp +suifu.ibaraki.jp +takahagi.ibaraki.jp +tamatsukuri.ibaraki.jp +tokai.ibaraki.jp +tomobe.ibaraki.jp +tone.ibaraki.jp +toride.ibaraki.jp +tsuchiura.ibaraki.jp +tsukuba.ibaraki.jp +uchihara.ibaraki.jp +ushiku.ibaraki.jp +yachiyo.ibaraki.jp +yamagata.ibaraki.jp +yawara.ibaraki.jp +yuki.ibaraki.jp +anamizu.ishikawa.jp +hakui.ishikawa.jp +hakusan.ishikawa.jp +kaga.ishikawa.jp +kahoku.ishikawa.jp +kanazawa.ishikawa.jp +kawakita.ishikawa.jp +komatsu.ishikawa.jp +nakanoto.ishikawa.jp +nanao.ishikawa.jp +nomi.ishikawa.jp +nonoichi.ishikawa.jp +noto.ishikawa.jp +shika.ishikawa.jp +suzu.ishikawa.jp +tsubata.ishikawa.jp +tsurugi.ishikawa.jp +uchinada.ishikawa.jp +wajima.ishikawa.jp +fudai.iwate.jp +fujisawa.iwate.jp +hanamaki.iwate.jp +hiraizumi.iwate.jp +hirono.iwate.jp +ichinohe.iwate.jp +ichinoseki.iwate.jp +iwaizumi.iwate.jp +iwate.iwate.jp +joboji.iwate.jp +kamaishi.iwate.jp +kanegasaki.iwate.jp +karumai.iwate.jp +kawai.iwate.jp +kitakami.iwate.jp +kuji.iwate.jp +kunohe.iwate.jp +kuzumaki.iwate.jp +miyako.iwate.jp +mizusawa.iwate.jp +morioka.iwate.jp +ninohe.iwate.jp +noda.iwate.jp +ofunato.iwate.jp +oshu.iwate.jp +otsuchi.iwate.jp +rikuzentakata.iwate.jp +shiwa.iwate.jp +shizukuishi.iwate.jp +sumita.iwate.jp +takizawa.iwate.jp +tanohata.iwate.jp +tono.iwate.jp +yahaba.iwate.jp +yamada.iwate.jp +ayagawa.kagawa.jp +higashikagawa.kagawa.jp +kanonji.kagawa.jp +kotohira.kagawa.jp +manno.kagawa.jp +marugame.kagawa.jp +mitoyo.kagawa.jp +naoshima.kagawa.jp +sanuki.kagawa.jp +tadotsu.kagawa.jp +takamatsu.kagawa.jp +tonosho.kagawa.jp +uchinomi.kagawa.jp +utazu.kagawa.jp +zentsuji.kagawa.jp +akune.kagoshima.jp +amami.kagoshima.jp +hioki.kagoshima.jp +isa.kagoshima.jp +isen.kagoshima.jp +izumi.kagoshima.jp +kagoshima.kagoshima.jp +kanoya.kagoshima.jp +kawanabe.kagoshima.jp +kinko.kagoshima.jp +kouyama.kagoshima.jp +makurazaki.kagoshima.jp +matsumoto.kagoshima.jp +minamitane.kagoshima.jp +nakatane.kagoshima.jp +nishinoomote.kagoshima.jp +satsumasendai.kagoshima.jp +soo.kagoshima.jp +tarumizu.kagoshima.jp +yusui.kagoshima.jp +aikawa.kanagawa.jp +atsugi.kanagawa.jp +ayase.kanagawa.jp +chigasaki.kanagawa.jp +ebina.kanagawa.jp +fujisawa.kanagawa.jp +hadano.kanagawa.jp +hakone.kanagawa.jp +hiratsuka.kanagawa.jp +isehara.kanagawa.jp +kaisei.kanagawa.jp +kamakura.kanagawa.jp +kiyokawa.kanagawa.jp +matsuda.kanagawa.jp +minamiashigara.kanagawa.jp +miura.kanagawa.jp +nakai.kanagawa.jp +ninomiya.kanagawa.jp +odawara.kanagawa.jp +oi.kanagawa.jp +oiso.kanagawa.jp +sagamihara.kanagawa.jp +samukawa.kanagawa.jp +tsukui.kanagawa.jp +yamakita.kanagawa.jp +yamato.kanagawa.jp +yokosuka.kanagawa.jp +yugawara.kanagawa.jp +zama.kanagawa.jp +zushi.kanagawa.jp +aki.kochi.jp +geisei.kochi.jp +hidaka.kochi.jp +higashitsuno.kochi.jp +ino.kochi.jp +kagami.kochi.jp +kami.kochi.jp +kitagawa.kochi.jp +kochi.kochi.jp +mihara.kochi.jp +motoyama.kochi.jp +muroto.kochi.jp +nahari.kochi.jp +nakamura.kochi.jp +nankoku.kochi.jp +nishitosa.kochi.jp +niyodogawa.kochi.jp +ochi.kochi.jp +okawa.kochi.jp +otoyo.kochi.jp +otsuki.kochi.jp +sakawa.kochi.jp +sukumo.kochi.jp +susaki.kochi.jp +tosa.kochi.jp +tosashimizu.kochi.jp +toyo.kochi.jp +tsuno.kochi.jp +umaji.kochi.jp +yasuda.kochi.jp +yusuhara.kochi.jp +amakusa.kumamoto.jp +arao.kumamoto.jp +aso.kumamoto.jp +choyo.kumamoto.jp +gyokuto.kumamoto.jp +hitoyoshi.kumamoto.jp +kamiamakusa.kumamoto.jp +kashima.kumamoto.jp +kikuchi.kumamoto.jp +kosa.kumamoto.jp +kumamoto.kumamoto.jp +mashiki.kumamoto.jp +mifune.kumamoto.jp +minamata.kumamoto.jp +minamioguni.kumamoto.jp +nagasu.kumamoto.jp +nishihara.kumamoto.jp +oguni.kumamoto.jp +ozu.kumamoto.jp +sumoto.kumamoto.jp +takamori.kumamoto.jp +uki.kumamoto.jp +uto.kumamoto.jp +yamaga.kumamoto.jp +yamato.kumamoto.jp +yatsushiro.kumamoto.jp +ayabe.kyoto.jp +fukuchiyama.kyoto.jp +higashiyama.kyoto.jp +ide.kyoto.jp +ine.kyoto.jp +joyo.kyoto.jp +kameoka.kyoto.jp +kamo.kyoto.jp +kita.kyoto.jp +kizu.kyoto.jp +kumiyama.kyoto.jp +kyotamba.kyoto.jp +kyotanabe.kyoto.jp +kyotango.kyoto.jp +maizuru.kyoto.jp +minami.kyoto.jp +minamiyamashiro.kyoto.jp +miyazu.kyoto.jp +muko.kyoto.jp +nagaokakyo.kyoto.jp +nakagyo.kyoto.jp +nantan.kyoto.jp +oyamazaki.kyoto.jp +sakyo.kyoto.jp +seika.kyoto.jp +tanabe.kyoto.jp +uji.kyoto.jp +ujitawara.kyoto.jp +wazuka.kyoto.jp +yamashina.kyoto.jp +yawata.kyoto.jp +asahi.mie.jp +inabe.mie.jp +ise.mie.jp +kameyama.mie.jp +kawagoe.mie.jp +kiho.mie.jp +kisosaki.mie.jp +kiwa.mie.jp +komono.mie.jp +kumano.mie.jp +kuwana.mie.jp +matsusaka.mie.jp +meiwa.mie.jp +mihama.mie.jp +minamiise.mie.jp +misugi.mie.jp +miyama.mie.jp +nabari.mie.jp +shima.mie.jp +suzuka.mie.jp +tado.mie.jp +taiki.mie.jp +taki.mie.jp +tamaki.mie.jp +toba.mie.jp +tsu.mie.jp +udono.mie.jp +ureshino.mie.jp +watarai.mie.jp +yokkaichi.mie.jp +furukawa.miyagi.jp +higashimatsushima.miyagi.jp +ishinomaki.miyagi.jp +iwanuma.miyagi.jp +kakuda.miyagi.jp +kami.miyagi.jp +kawasaki.miyagi.jp +kesennuma.miyagi.jp +marumori.miyagi.jp +matsushima.miyagi.jp +minamisanriku.miyagi.jp +misato.miyagi.jp +murata.miyagi.jp +natori.miyagi.jp +ogawara.miyagi.jp +ohira.miyagi.jp +onagawa.miyagi.jp +osaki.miyagi.jp +rifu.miyagi.jp +semine.miyagi.jp +shibata.miyagi.jp +shichikashuku.miyagi.jp +shikama.miyagi.jp +shiogama.miyagi.jp +shiroishi.miyagi.jp +tagajo.miyagi.jp +taiwa.miyagi.jp +tome.miyagi.jp +tomiya.miyagi.jp +wakuya.miyagi.jp +watari.miyagi.jp +yamamoto.miyagi.jp +zao.miyagi.jp +aya.miyazaki.jp +ebino.miyazaki.jp +gokase.miyazaki.jp +hyuga.miyazaki.jp +kadogawa.miyazaki.jp +kawaminami.miyazaki.jp +kijo.miyazaki.jp +kitagawa.miyazaki.jp +kitakata.miyazaki.jp +kitaura.miyazaki.jp +kobayashi.miyazaki.jp +kunitomi.miyazaki.jp +kushima.miyazaki.jp +mimata.miyazaki.jp +miyakonojo.miyazaki.jp +miyazaki.miyazaki.jp +morotsuka.miyazaki.jp +nichinan.miyazaki.jp +nishimera.miyazaki.jp +nobeoka.miyazaki.jp +saito.miyazaki.jp +shiiba.miyazaki.jp +shintomi.miyazaki.jp +takaharu.miyazaki.jp +takanabe.miyazaki.jp +takazaki.miyazaki.jp +tsuno.miyazaki.jp +achi.nagano.jp +agematsu.nagano.jp +anan.nagano.jp +aoki.nagano.jp +asahi.nagano.jp +azumino.nagano.jp +chikuhoku.nagano.jp +chikuma.nagano.jp +chino.nagano.jp +fujimi.nagano.jp +hakuba.nagano.jp +hara.nagano.jp +hiraya.nagano.jp +iida.nagano.jp +iijima.nagano.jp +iiyama.nagano.jp +iizuna.nagano.jp +ikeda.nagano.jp +ikusaka.nagano.jp +ina.nagano.jp +karuizawa.nagano.jp +kawakami.nagano.jp +kiso.nagano.jp +kisofukushima.nagano.jp +kitaaiki.nagano.jp +komagane.nagano.jp +komoro.nagano.jp +matsukawa.nagano.jp +matsumoto.nagano.jp +miasa.nagano.jp +minamiaiki.nagano.jp +minamimaki.nagano.jp +minamiminowa.nagano.jp +minowa.nagano.jp +miyada.nagano.jp +miyota.nagano.jp +mochizuki.nagano.jp +nagano.nagano.jp +nagawa.nagano.jp +nagiso.nagano.jp +nakagawa.nagano.jp +nakano.nagano.jp +nozawaonsen.nagano.jp +obuse.nagano.jp +ogawa.nagano.jp +okaya.nagano.jp +omachi.nagano.jp +omi.nagano.jp +ookuwa.nagano.jp +ooshika.nagano.jp +otaki.nagano.jp +otari.nagano.jp +sakae.nagano.jp +sakaki.nagano.jp +saku.nagano.jp +sakuho.nagano.jp +shimosuwa.nagano.jp +shinanomachi.nagano.jp +shiojiri.nagano.jp +suwa.nagano.jp +suzaka.nagano.jp +takagi.nagano.jp +takamori.nagano.jp +takayama.nagano.jp +tateshina.nagano.jp +tatsuno.nagano.jp +togakushi.nagano.jp +togura.nagano.jp +tomi.nagano.jp +ueda.nagano.jp +wada.nagano.jp +yamagata.nagano.jp +yamanouchi.nagano.jp +yasaka.nagano.jp +yasuoka.nagano.jp +chijiwa.nagasaki.jp +futsu.nagasaki.jp +goto.nagasaki.jp +hasami.nagasaki.jp +hirado.nagasaki.jp +iki.nagasaki.jp +isahaya.nagasaki.jp +kawatana.nagasaki.jp +kuchinotsu.nagasaki.jp +matsuura.nagasaki.jp +nagasaki.nagasaki.jp +obama.nagasaki.jp +omura.nagasaki.jp +oseto.nagasaki.jp +saikai.nagasaki.jp +sasebo.nagasaki.jp +seihi.nagasaki.jp +shimabara.nagasaki.jp +shinkamigoto.nagasaki.jp +togitsu.nagasaki.jp +tsushima.nagasaki.jp +unzen.nagasaki.jp +ando.nara.jp +gose.nara.jp +heguri.nara.jp +higashiyoshino.nara.jp +ikaruga.nara.jp +ikoma.nara.jp +kamikitayama.nara.jp +kanmaki.nara.jp +kashiba.nara.jp +kashihara.nara.jp +katsuragi.nara.jp +kawai.nara.jp +kawakami.nara.jp +kawanishi.nara.jp +koryo.nara.jp +kurotaki.nara.jp +mitsue.nara.jp +miyake.nara.jp +nara.nara.jp +nosegawa.nara.jp +oji.nara.jp +ouda.nara.jp +oyodo.nara.jp +sakurai.nara.jp +sango.nara.jp +shimoichi.nara.jp +shimokitayama.nara.jp +shinjo.nara.jp +soni.nara.jp +takatori.nara.jp +tawaramoto.nara.jp +tenkawa.nara.jp +tenri.nara.jp +uda.nara.jp +yamatokoriyama.nara.jp +yamatotakada.nara.jp +yamazoe.nara.jp +yoshino.nara.jp +aga.niigata.jp +agano.niigata.jp +gosen.niigata.jp +itoigawa.niigata.jp +izumozaki.niigata.jp +joetsu.niigata.jp +kamo.niigata.jp +kariwa.niigata.jp +kashiwazaki.niigata.jp +minamiuonuma.niigata.jp +mitsuke.niigata.jp +muika.niigata.jp +murakami.niigata.jp +myoko.niigata.jp +nagaoka.niigata.jp +niigata.niigata.jp +ojiya.niigata.jp +omi.niigata.jp +sado.niigata.jp +sanjo.niigata.jp +seiro.niigata.jp +seirou.niigata.jp +sekikawa.niigata.jp +shibata.niigata.jp +tagami.niigata.jp +tainai.niigata.jp +tochio.niigata.jp +tokamachi.niigata.jp +tsubame.niigata.jp +tsunan.niigata.jp +uonuma.niigata.jp +yahiko.niigata.jp +yoita.niigata.jp +yuzawa.niigata.jp +beppu.oita.jp +bungoono.oita.jp +bungotakada.oita.jp +hasama.oita.jp +hiji.oita.jp +himeshima.oita.jp +hita.oita.jp +kamitsue.oita.jp +kokonoe.oita.jp +kuju.oita.jp +kunisaki.oita.jp +kusu.oita.jp +oita.oita.jp +saiki.oita.jp +taketa.oita.jp +tsukumi.oita.jp +usa.oita.jp +usuki.oita.jp +yufu.oita.jp +akaiwa.okayama.jp +asakuchi.okayama.jp +bizen.okayama.jp +hayashima.okayama.jp +ibara.okayama.jp +kagamino.okayama.jp +kasaoka.okayama.jp +kibichuo.okayama.jp +kumenan.okayama.jp +kurashiki.okayama.jp +maniwa.okayama.jp +misaki.okayama.jp +nagi.okayama.jp +niimi.okayama.jp +nishiawakura.okayama.jp +okayama.okayama.jp +satosho.okayama.jp +setouchi.okayama.jp +shinjo.okayama.jp +shoo.okayama.jp +soja.okayama.jp +takahashi.okayama.jp +tamano.okayama.jp +tsuyama.okayama.jp +wake.okayama.jp +yakage.okayama.jp +aguni.okinawa.jp +ginowan.okinawa.jp +ginoza.okinawa.jp +gushikami.okinawa.jp +haebaru.okinawa.jp +higashi.okinawa.jp +hirara.okinawa.jp +iheya.okinawa.jp +ishigaki.okinawa.jp +ishikawa.okinawa.jp +itoman.okinawa.jp +izena.okinawa.jp +kadena.okinawa.jp +kin.okinawa.jp +kitadaito.okinawa.jp +kitanakagusuku.okinawa.jp +kumejima.okinawa.jp +kunigami.okinawa.jp +minamidaito.okinawa.jp +motobu.okinawa.jp +nago.okinawa.jp +naha.okinawa.jp +nakagusuku.okinawa.jp +nakijin.okinawa.jp +nanjo.okinawa.jp +nishihara.okinawa.jp +ogimi.okinawa.jp +okinawa.okinawa.jp +onna.okinawa.jp +shimoji.okinawa.jp +taketomi.okinawa.jp +tarama.okinawa.jp +tokashiki.okinawa.jp +tomigusuku.okinawa.jp +tonaki.okinawa.jp +urasoe.okinawa.jp +uruma.okinawa.jp +yaese.okinawa.jp +yomitan.okinawa.jp +yonabaru.okinawa.jp +yonaguni.okinawa.jp +zamami.okinawa.jp +abeno.osaka.jp +chihayaakasaka.osaka.jp +chuo.osaka.jp +daito.osaka.jp +fujiidera.osaka.jp +habikino.osaka.jp +hannan.osaka.jp +higashiosaka.osaka.jp +higashisumiyoshi.osaka.jp +higashiyodogawa.osaka.jp +hirakata.osaka.jp +ibaraki.osaka.jp +ikeda.osaka.jp +izumi.osaka.jp +izumiotsu.osaka.jp +izumisano.osaka.jp +kadoma.osaka.jp +kaizuka.osaka.jp +kanan.osaka.jp +kashiwara.osaka.jp +katano.osaka.jp +kawachinagano.osaka.jp +kishiwada.osaka.jp +kita.osaka.jp +kumatori.osaka.jp +matsubara.osaka.jp +minato.osaka.jp +minoh.osaka.jp +misaki.osaka.jp +moriguchi.osaka.jp +neyagawa.osaka.jp +nishi.osaka.jp +nose.osaka.jp +osakasayama.osaka.jp +sakai.osaka.jp +sayama.osaka.jp +sennan.osaka.jp +settsu.osaka.jp +shijonawate.osaka.jp +shimamoto.osaka.jp +suita.osaka.jp +tadaoka.osaka.jp +taishi.osaka.jp +tajiri.osaka.jp +takaishi.osaka.jp +takatsuki.osaka.jp +tondabayashi.osaka.jp +toyonaka.osaka.jp +toyono.osaka.jp +yao.osaka.jp +ariake.saga.jp +arita.saga.jp +fukudomi.saga.jp +genkai.saga.jp +hamatama.saga.jp +hizen.saga.jp +imari.saga.jp +kamimine.saga.jp +kanzaki.saga.jp +karatsu.saga.jp +kashima.saga.jp +kitagata.saga.jp +kitahata.saga.jp +kiyama.saga.jp +kouhoku.saga.jp +kyuragi.saga.jp +nishiarita.saga.jp +ogi.saga.jp +omachi.saga.jp +ouchi.saga.jp +saga.saga.jp +shiroishi.saga.jp +taku.saga.jp +tara.saga.jp +tosu.saga.jp +yoshinogari.saga.jp +arakawa.saitama.jp +asaka.saitama.jp +chichibu.saitama.jp +fujimi.saitama.jp +fujimino.saitama.jp +fukaya.saitama.jp +hanno.saitama.jp +hanyu.saitama.jp +hasuda.saitama.jp +hatogaya.saitama.jp +hatoyama.saitama.jp +hidaka.saitama.jp +higashichichibu.saitama.jp +higashimatsuyama.saitama.jp +honjo.saitama.jp +ina.saitama.jp +iruma.saitama.jp +iwatsuki.saitama.jp +kamiizumi.saitama.jp +kamikawa.saitama.jp +kamisato.saitama.jp +kasukabe.saitama.jp +kawagoe.saitama.jp +kawaguchi.saitama.jp +kawajima.saitama.jp +kazo.saitama.jp +kitamoto.saitama.jp +koshigaya.saitama.jp +kounosu.saitama.jp +kuki.saitama.jp +kumagaya.saitama.jp +matsubushi.saitama.jp +minano.saitama.jp +misato.saitama.jp +miyashiro.saitama.jp +miyoshi.saitama.jp +moroyama.saitama.jp +nagatoro.saitama.jp +namegawa.saitama.jp +niiza.saitama.jp +ogano.saitama.jp +ogawa.saitama.jp +ogose.saitama.jp +okegawa.saitama.jp +omiya.saitama.jp +otaki.saitama.jp +ranzan.saitama.jp +ryokami.saitama.jp +saitama.saitama.jp +sakado.saitama.jp +satte.saitama.jp +sayama.saitama.jp +shiki.saitama.jp +shiraoka.saitama.jp +soka.saitama.jp +sugito.saitama.jp +toda.saitama.jp +tokigawa.saitama.jp +tokorozawa.saitama.jp +tsurugashima.saitama.jp +urawa.saitama.jp +warabi.saitama.jp +yashio.saitama.jp +yokoze.saitama.jp +yono.saitama.jp +yorii.saitama.jp +yoshida.saitama.jp +yoshikawa.saitama.jp +yoshimi.saitama.jp +aisho.shiga.jp +gamo.shiga.jp +higashiomi.shiga.jp +hikone.shiga.jp +koka.shiga.jp +konan.shiga.jp +kosei.shiga.jp +koto.shiga.jp +kusatsu.shiga.jp +maibara.shiga.jp +moriyama.shiga.jp +nagahama.shiga.jp +nishiazai.shiga.jp +notogawa.shiga.jp +omihachiman.shiga.jp +otsu.shiga.jp +ritto.shiga.jp +ryuoh.shiga.jp +takashima.shiga.jp +takatsuki.shiga.jp +torahime.shiga.jp +toyosato.shiga.jp +yasu.shiga.jp +akagi.shimane.jp +ama.shimane.jp +gotsu.shimane.jp +hamada.shimane.jp +higashiizumo.shimane.jp +hikawa.shimane.jp +hikimi.shimane.jp +izumo.shimane.jp +kakinoki.shimane.jp +masuda.shimane.jp +matsue.shimane.jp +misato.shimane.jp +nishinoshima.shimane.jp +ohda.shimane.jp +okinoshima.shimane.jp +okuizumo.shimane.jp +shimane.shimane.jp +tamayu.shimane.jp +tsuwano.shimane.jp +unnan.shimane.jp +yakumo.shimane.jp +yasugi.shimane.jp +yatsuka.shimane.jp +arai.shizuoka.jp +atami.shizuoka.jp +fuji.shizuoka.jp +fujieda.shizuoka.jp +fujikawa.shizuoka.jp +fujinomiya.shizuoka.jp +fukuroi.shizuoka.jp +gotemba.shizuoka.jp +haibara.shizuoka.jp +hamamatsu.shizuoka.jp +higashiizu.shizuoka.jp +ito.shizuoka.jp +iwata.shizuoka.jp +izu.shizuoka.jp +izunokuni.shizuoka.jp +kakegawa.shizuoka.jp +kannami.shizuoka.jp +kawanehon.shizuoka.jp +kawazu.shizuoka.jp +kikugawa.shizuoka.jp +kosai.shizuoka.jp +makinohara.shizuoka.jp +matsuzaki.shizuoka.jp +minamiizu.shizuoka.jp +mishima.shizuoka.jp +morimachi.shizuoka.jp +nishiizu.shizuoka.jp +numazu.shizuoka.jp +omaezaki.shizuoka.jp +shimada.shizuoka.jp +shimizu.shizuoka.jp +shimoda.shizuoka.jp +shizuoka.shizuoka.jp +susono.shizuoka.jp +yaizu.shizuoka.jp +yoshida.shizuoka.jp +ashikaga.tochigi.jp +bato.tochigi.jp +haga.tochigi.jp +ichikai.tochigi.jp +iwafune.tochigi.jp +kaminokawa.tochigi.jp +kanuma.tochigi.jp +karasuyama.tochigi.jp +kuroiso.tochigi.jp +mashiko.tochigi.jp +mibu.tochigi.jp +moka.tochigi.jp +motegi.tochigi.jp +nasu.tochigi.jp +nasushiobara.tochigi.jp +nikko.tochigi.jp +nishikata.tochigi.jp +nogi.tochigi.jp +ohira.tochigi.jp +ohtawara.tochigi.jp +oyama.tochigi.jp +sakura.tochigi.jp +sano.tochigi.jp +shimotsuke.tochigi.jp +shioya.tochigi.jp +takanezawa.tochigi.jp +tochigi.tochigi.jp +tsuga.tochigi.jp +ujiie.tochigi.jp +utsunomiya.tochigi.jp +yaita.tochigi.jp +aizumi.tokushima.jp +anan.tokushima.jp +ichiba.tokushima.jp +itano.tokushima.jp +kainan.tokushima.jp +komatsushima.tokushima.jp +matsushige.tokushima.jp +mima.tokushima.jp +minami.tokushima.jp +miyoshi.tokushima.jp +mugi.tokushima.jp +nakagawa.tokushima.jp +naruto.tokushima.jp +sanagochi.tokushima.jp +shishikui.tokushima.jp +tokushima.tokushima.jp +wajiki.tokushima.jp +adachi.tokyo.jp +akiruno.tokyo.jp +akishima.tokyo.jp +aogashima.tokyo.jp +arakawa.tokyo.jp +bunkyo.tokyo.jp +chiyoda.tokyo.jp +chofu.tokyo.jp +chuo.tokyo.jp +edogawa.tokyo.jp +fuchu.tokyo.jp +fussa.tokyo.jp +hachijo.tokyo.jp +hachioji.tokyo.jp +hamura.tokyo.jp +higashikurume.tokyo.jp +higashimurayama.tokyo.jp +higashiyamato.tokyo.jp +hino.tokyo.jp +hinode.tokyo.jp +hinohara.tokyo.jp +inagi.tokyo.jp +itabashi.tokyo.jp +katsushika.tokyo.jp +kita.tokyo.jp +kiyose.tokyo.jp +kodaira.tokyo.jp +koganei.tokyo.jp +kokubunji.tokyo.jp +komae.tokyo.jp +koto.tokyo.jp +kouzushima.tokyo.jp +kunitachi.tokyo.jp +machida.tokyo.jp +meguro.tokyo.jp +minato.tokyo.jp +mitaka.tokyo.jp +mizuho.tokyo.jp +musashimurayama.tokyo.jp +musashino.tokyo.jp +nakano.tokyo.jp +nerima.tokyo.jp +ogasawara.tokyo.jp +okutama.tokyo.jp +ome.tokyo.jp +oshima.tokyo.jp +ota.tokyo.jp +setagaya.tokyo.jp +shibuya.tokyo.jp +shinagawa.tokyo.jp +shinjuku.tokyo.jp +suginami.tokyo.jp +sumida.tokyo.jp +tachikawa.tokyo.jp +taito.tokyo.jp +tama.tokyo.jp +toshima.tokyo.jp +chizu.tottori.jp +hino.tottori.jp +kawahara.tottori.jp +koge.tottori.jp +kotoura.tottori.jp +misasa.tottori.jp +nanbu.tottori.jp +nichinan.tottori.jp +sakaiminato.tottori.jp +tottori.tottori.jp +wakasa.tottori.jp +yazu.tottori.jp +yonago.tottori.jp +asahi.toyama.jp +fuchu.toyama.jp +fukumitsu.toyama.jp +funahashi.toyama.jp +himi.toyama.jp +imizu.toyama.jp +inami.toyama.jp +johana.toyama.jp +kamiichi.toyama.jp +kurobe.toyama.jp +nakaniikawa.toyama.jp +namerikawa.toyama.jp +nanto.toyama.jp +nyuzen.toyama.jp +oyabe.toyama.jp +taira.toyama.jp +takaoka.toyama.jp +tateyama.toyama.jp +toga.toyama.jp +tonami.toyama.jp +toyama.toyama.jp +unazuki.toyama.jp +uozu.toyama.jp +yamada.toyama.jp +arida.wakayama.jp +aridagawa.wakayama.jp +gobo.wakayama.jp +hashimoto.wakayama.jp +hidaka.wakayama.jp +hirogawa.wakayama.jp +inami.wakayama.jp +iwade.wakayama.jp +kainan.wakayama.jp +kamitonda.wakayama.jp +katsuragi.wakayama.jp +kimino.wakayama.jp +kinokawa.wakayama.jp +kitayama.wakayama.jp +koya.wakayama.jp +koza.wakayama.jp +kozagawa.wakayama.jp +kudoyama.wakayama.jp +kushimoto.wakayama.jp +mihama.wakayama.jp +misato.wakayama.jp +nachikatsuura.wakayama.jp +shingu.wakayama.jp +shirahama.wakayama.jp +taiji.wakayama.jp +tanabe.wakayama.jp +wakayama.wakayama.jp +yuasa.wakayama.jp +yura.wakayama.jp +asahi.yamagata.jp +funagata.yamagata.jp +higashine.yamagata.jp +iide.yamagata.jp +kahoku.yamagata.jp +kaminoyama.yamagata.jp +kaneyama.yamagata.jp +kawanishi.yamagata.jp +mamurogawa.yamagata.jp +mikawa.yamagata.jp +murayama.yamagata.jp +nagai.yamagata.jp +nakayama.yamagata.jp +nanyo.yamagata.jp +nishikawa.yamagata.jp +obanazawa.yamagata.jp +oe.yamagata.jp +oguni.yamagata.jp +ohkura.yamagata.jp +oishida.yamagata.jp +sagae.yamagata.jp +sakata.yamagata.jp +sakegawa.yamagata.jp +shinjo.yamagata.jp +shirataka.yamagata.jp +shonai.yamagata.jp +takahata.yamagata.jp +tendo.yamagata.jp +tozawa.yamagata.jp +tsuruoka.yamagata.jp +yamagata.yamagata.jp +yamanobe.yamagata.jp +yonezawa.yamagata.jp +yuza.yamagata.jp +abu.yamaguchi.jp +hagi.yamaguchi.jp +hikari.yamaguchi.jp +hofu.yamaguchi.jp +iwakuni.yamaguchi.jp +kudamatsu.yamaguchi.jp +mitou.yamaguchi.jp +nagato.yamaguchi.jp +oshima.yamaguchi.jp +shimonoseki.yamaguchi.jp +shunan.yamaguchi.jp +tabuse.yamaguchi.jp +tokuyama.yamaguchi.jp +toyota.yamaguchi.jp +ube.yamaguchi.jp +yuu.yamaguchi.jp +chuo.yamanashi.jp +doshi.yamanashi.jp +fuefuki.yamanashi.jp +fujikawa.yamanashi.jp +fujikawaguchiko.yamanashi.jp +fujiyoshida.yamanashi.jp +hayakawa.yamanashi.jp +hokuto.yamanashi.jp +ichikawamisato.yamanashi.jp +kai.yamanashi.jp +kofu.yamanashi.jp +koshu.yamanashi.jp +kosuge.yamanashi.jp +minami-alps.yamanashi.jp +minobu.yamanashi.jp +nakamichi.yamanashi.jp +nanbu.yamanashi.jp +narusawa.yamanashi.jp +nirasaki.yamanashi.jp +nishikatsura.yamanashi.jp +oshino.yamanashi.jp +otsuki.yamanashi.jp +showa.yamanashi.jp +tabayama.yamanashi.jp +tsuru.yamanashi.jp +uenohara.yamanashi.jp +yamanakako.yamanashi.jp +yamanashi.yamanashi.jp // ke : http://www.kenic.or.ke/index.php?option=com_content&task=view&id=117&Itemid=145 *.ke @@ -4004,6 +5590,7 @@ net.sd org.sd edu.sd med.sd +tv.sd gov.sd info.sd @@ -4051,7 +5638,7 @@ x.se y.se z.se -// sg : http://www.nic.net.sg/sub_policies_agreement/2ld.html +// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines sg com.sg net.sg @@ -4060,9 +5647,13 @@ gov.sg edu.sg per.sg -// sh : http://www.nic.sh/rules.html -// list of 2nd level domains ? +// sh : http://www.nic.sh/registrar.html sh +com.sh +net.sh +gov.sh +org.sh +mil.sh // si : http://en.wikipedia.org/wiki/.si si @@ -4126,6 +5717,11 @@ su // sv : http://www.svnet.org.sv/svpolicy.html *.sv +// sx : http://en.wikipedia.org/wiki/.sx +// Confirmed by registry 2012-05-31 +sx +gov.sx + // sy : http://en.wikipedia.org/wiki/.sy // see also: http://www.gobin.info/domainname/sy.doc sy @@ -4157,8 +5753,7 @@ tel tf // tg : http://en.wikipedia.org/wiki/.tg -// http://www.nic.tg/nictg/index.php implies no reserved 2nd-level domains, -// although this contradicts wikipedia. +// http://www.nic.tg/ tg // th : http://en.wikipedia.org/wiki/.th @@ -4172,7 +5767,7 @@ mi.th net.th or.th -// tj : http://www.nic.tj/policy.htm +// tj : http://www.nic.tj/policy.html tj ac.tj biz.tj @@ -4197,9 +5792,16 @@ tk tl gov.tl -// tm : http://www.nic.tm/rules.html -// list of 2nd level tlds ? +// tm : http://www.nic.tm/local.html tm +com.tm +co.tm +org.tm +net.tm +nom.tm +gov.tm +mil.tm +edu.tm // tn : http://en.wikipedia.org/wiki/.tn // http://whois.ati.tn/ @@ -4357,14 +5959,16 @@ zt.ua co.ua pp.ua -// ug : http://www.registry.co.ug/ +// ug : https://www.registry.co.ug/ ug co.ug +or.ug ac.ug sc.ug go.ug ne.ug -or.ug +com.ug +org.ug // uk : http://en.wikipedia.org/wiki/.uk *.uk @@ -4630,11 +6234,12 @@ paroch.k12.ma.us // uy : http://www.antel.com.uy/ *.uy -// uz : http://www.reg.uz/registerr.html -// are there other 2nd level tlds ? +// uz : http://www.reg.uz/ uz -com.uz co.uz +com.uz +net.uz +org.uz // va : http://en.wikipedia.org/wiki/.va va @@ -4708,7 +6313,7 @@ yt // // xn--mgbaam7a8h ("Emerat" Arabic) : AE -//http://nic.ae/english/arabicdomain/rules.jsp +// http://nic.ae/english/arabicdomain/rules.jsp امارات // xn--54b7fta0cc ("Bangla" Bangla) : BD @@ -4772,9 +6377,9 @@ yt // xn--mgba3a4fra ("Iran" Arabic) : IR ايران -//xn--mgbayh7gpa ("al-Ordon" Arabic) JO -//National Information Technology Center (NITC) -//Royal Scientific Society, Al-Jubeiha +// xn--mgbayh7gpa ("al-Ordon" Arabic) : JO +// National Information Technology Center (NITC) +// Royal Scientific Society, Al-Jubeiha الاردن // xn--3e0b707e ("Republic of Korea" Hangul) : KR -- cgit v1.2.1 From 005e8cd9be521950330bb98c9c207bc6c172c6f6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 6 Aug 2012 10:29:31 -0400 Subject: tld-test: update for changes to TLD data --- tests/tld-test.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/tld-test.c b/tests/tld-test.c index 5f66c686..25d2da28 100644 --- a/tests/tld-test.c +++ b/tests/tld-test.c @@ -59,13 +59,13 @@ static struct { { "test.ac.jp", "test.ac.jp" }, { "www.test.ac.jp", "test.ac.jp" }, { "kyoto.jp", NULL }, - { "c.kyoto.jp", NULL }, - { "b.c.kyoto.jp", "b.c.kyoto.jp" }, - { "a.b.c.kyoto.jp", "b.c.kyoto.jp" }, - { "pref.kyoto.jp", "pref.kyoto.jp" }, /* Exception rule. */ - { "www.pref.kyoto.jp", "pref.kyoto.jp" }, /* Exception rule. */ - { "city.kyoto.jp", "city.kyoto.jp" }, /* Exception rule. */ - { "www.city.kyoto.jp", "city.kyoto.jp" }, /* Exception rule. */ + { "minami.kyoto.jp", NULL }, + { "b.minami.kyoto.jp", "b.minami.kyoto.jp" }, + { "a.b.minami.kyoto.jp", "b.minami.kyoto.jp" }, + { "pref.kyoto.jp", "pref.kyoto.jp" }, + { "www.pref.kyoto.jp", "pref.kyoto.jp" }, + { "city.kyoto.jp", "city.kyoto.jp" }, + { "www.city.kyoto.jp", "city.kyoto.jp" }, /* TLD with a wildcard rule and exceptions. */ { "om", NULL }, { "test.om", NULL }, -- cgit v1.2.1 From f75304e6d16f53b544a08776031921bef9535100 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 29 Mar 2012 19:17:02 +0100 Subject: SoupSocket: local, remote address are undefined if unconnected Warn and return NULL deterministically, rather than warning and returning uninitialized stack garbage, but document it as "undefined"; these methods were never meant to be valid in this situation, apparently. Bug: https://bugzilla.gnome.org/show_bug.cgi?id=673083 --- libsoup/soup-socket.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 5a88907c..4369ff38 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -1280,6 +1280,9 @@ soup_socket_is_connected (SoupSocket *sock) * * Returns the #SoupAddress corresponding to the local end of @sock. * + * Calling this method on an unconnected socket is considered to be + * an error, and produces undefined results. + * * Return value: (transfer none): the #SoupAddress **/ SoupAddress * @@ -1295,13 +1298,25 @@ soup_socket_get_local_address (SoupSocket *sock) GSocketAddress *addr; struct sockaddr_storage sa; gssize sa_len; + GError *error = NULL; + + if (priv->gsock == NULL) { + g_warning ("%s: socket not connected", G_STRLOC); + goto unlock; + } - addr = g_socket_get_local_address (priv->gsock, NULL); + addr = g_socket_get_local_address (priv->gsock, &error); + if (addr == NULL) { + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + goto unlock; + } sa_len = g_socket_address_get_native_size (addr); g_socket_address_to_native (addr, &sa, sa_len, NULL); priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len); g_object_unref (addr); } +unlock: g_mutex_unlock (&priv->addrlock); return priv->local_addr; @@ -1313,6 +1328,9 @@ soup_socket_get_local_address (SoupSocket *sock) * * Returns the #SoupAddress corresponding to the remote end of @sock. * + * Calling this method on an unconnected socket is considered to be + * an error, and produces undefined results. + * * Return value: (transfer none): the #SoupAddress **/ SoupAddress * @@ -1328,13 +1346,25 @@ soup_socket_get_remote_address (SoupSocket *sock) GSocketAddress *addr; struct sockaddr_storage sa; gssize sa_len; + GError *error = NULL; + + if (priv->gsock == NULL) { + g_warning ("%s: socket not connected", G_STRLOC); + goto unlock; + } - addr = g_socket_get_remote_address (priv->gsock, NULL); + addr = g_socket_get_remote_address (priv->gsock, &error); + if (addr == NULL) { + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + goto unlock; + } sa_len = g_socket_address_get_native_size (addr); g_socket_address_to_native (addr, &sa, sa_len, NULL); priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len); g_object_unref (addr); } +unlock: g_mutex_unlock (&priv->addrlock); return priv->remote_addr; -- cgit v1.2.1 From a0ceee0c3c17dde75faeb009bb6376b40780681f Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 29 Mar 2012 19:17:17 +0100 Subject: Add a simple regression test for unbound sockets https://bugzilla.gnome.org/show_bug.cgi?id=673083 --- tests/Makefile.am | 3 ++ tests/socket-test.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 tests/socket-test.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 995196c3..594890b9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -30,6 +30,7 @@ noinst_PROGRAMS = \ simple-httpd \ simple-proxy \ sniffing-test \ + socket-test \ ssl-test \ streaming-test \ timeout-test \ @@ -67,6 +68,7 @@ server_auth_test_SOURCES = server-auth-test.c $(TEST_SRCS) simple_httpd_SOURCES = simple-httpd.c simple_proxy_SOURCES = simple-proxy.c sniffing_test_SOURCES = sniffing-test.c $(TEST_SRCS) +socket_test_SOURCES = socket-test.c $(TEST_SRCS) ssl_test_SOURCES = ssl-test.c $(TEST_SRCS) streaming_test_SOURCES = streaming-test.c $(TEST_SRCS) timeout_test_SOURCES = timeout-test.c $(TEST_SRCS) @@ -99,6 +101,7 @@ TESTS = \ redirect-test \ requester-test \ sniffing-test \ + socket-test \ ssl-test \ streaming-test \ timeout-test \ diff --git a/tests/socket-test.c b/tests/socket-test.c new file mode 100644 index 00000000..60c3e86c --- /dev/null +++ b/tests/socket-test.c @@ -0,0 +1,113 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2007-2012 Red Hat, Inc. + * Copyright 2012 Nokia Corporation + */ + +#include + +#include + +#include "test-utils.h" + +static void +do_unconnected_socket_test (void) +{ + SoupAddress *localhost; + SoupSocket *sock; + SoupSocket *client; + SoupAddress *addr; + guint res; + struct sockaddr_in in_localhost; + + in_localhost.sin_family = AF_INET; + in_localhost.sin_port = 0; + in_localhost.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + + localhost = soup_address_new_from_sockaddr ( + (struct sockaddr *) &in_localhost, sizeof (in_localhost)); + g_assert (localhost != NULL); + res = soup_address_resolve_sync (localhost, NULL); + g_assert_cmpuint (res, ==, SOUP_STATUS_OK); + + sock = soup_socket_new ( + SOUP_SOCKET_LOCAL_ADDRESS, localhost, + NULL); + g_assert (sock != NULL); + + addr = soup_socket_get_local_address (sock); + g_assert (addr != NULL); + g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); + g_assert_cmpuint (soup_address_get_port (addr), ==, 0); + + /* fails with ENOTCONN */ + expect_warning++; + addr = soup_socket_get_remote_address (sock); + g_assert (addr == NULL); + + res = soup_socket_listen (sock); + g_assert_cmpuint (res, ==, TRUE); + + addr = soup_socket_get_local_address (sock); + g_assert (addr != NULL); + g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); + g_assert_cmpuint (soup_address_get_port (addr), >, 0); + + client = soup_socket_new ( + SOUP_SOCKET_REMOTE_ADDRESS, + soup_socket_get_local_address (sock), + NULL); + res = soup_socket_connect_sync (client, NULL); + g_assert_cmpuint (res, ==, SOUP_STATUS_OK); + addr = soup_socket_get_local_address (client); + g_assert (addr != NULL); + addr = soup_socket_get_remote_address (client); + g_assert (addr != NULL); + g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); + g_assert_cmpuint (soup_address_get_port (addr), >, 0); + g_object_unref (client); + + client = soup_socket_new ( + SOUP_SOCKET_REMOTE_ADDRESS, + soup_socket_get_local_address (sock), + NULL); + /* save it for later */ + + /* listening socket fails with ENOTCONN */ + expect_warning++; + addr = soup_socket_get_remote_address (sock); + g_assert (addr == NULL); + + soup_socket_disconnect (sock); + + expect_warning++; + addr = soup_socket_get_remote_address (sock); + g_assert (addr == NULL); + + /* has never been connected */ + expect_warning++; + addr = soup_socket_get_local_address (client); + g_assert (addr == NULL); + + res = soup_socket_connect_sync (client, NULL); + g_assert_cmpuint (res, ==, SOUP_STATUS_CANT_CONNECT); + + expect_warning++; + addr = soup_socket_get_local_address (client); + g_assert (addr == NULL); + + g_object_unref (localhost); + g_object_unref (client); + g_object_unref (sock); +} + +int +main (int argc, char **argv) +{ + test_init (argc, argv, NULL); + + do_unconnected_socket_test (); + + test_cleanup (); + return errors != 0; +} -- cgit v1.2.1 From 1ce7f05e303cda7e53cf7d8e7797f0340e10fd14 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 6 Aug 2012 10:33:38 -0400 Subject: soup-socket.c: fix a use-after-free of a GCancellable --- libsoup/soup-socket.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 4369ff38..c789e648 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -670,10 +670,11 @@ socket_connected (SoupSocket *sock, GSocketConnection *conn, GError *error) if (priv->connect_cancel) { GCancellable *cancellable = priv->connect_cancel; + gboolean cancelled = g_cancellable_is_cancelled (cancellable); g_object_unref (priv->connect_cancel); priv->connect_cancel = NULL; - if (g_cancellable_is_cancelled (cancellable)) + if (cancelled) return SOUP_STATUS_CANCELLED; } -- cgit v1.2.1 From 909850a4945fb9f37c8005a31f501861df9b3942 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 6 Aug 2012 14:28:00 -0400 Subject: soup-xmlrpc: fix parsing of without If a method takes no parameters, you can leave out the section of , but soup_xmlrpc_parse_method_call() was requiring it anyway. Fix that and add some tests of parameter-less methods. https://bugzilla.gnome.org/show_bug.cgi?id=671661 --- libsoup/soup-xmlrpc.c | 33 ++++++++-------- tests/xmlrpc-server-test.c | 12 ++++++ tests/xmlrpc-server.php | 17 +++++++-- tests/xmlrpc-test.c | 94 ++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 122 insertions(+), 34 deletions(-) diff --git a/libsoup/soup-xmlrpc.c b/libsoup/soup-xmlrpc.c index f7908585..8d711d3b 100644 --- a/libsoup/soup-xmlrpc.c +++ b/libsoup/soup-xmlrpc.c @@ -593,29 +593,32 @@ soup_xmlrpc_parse_method_call (const char *method_call, int length, xmlMethodName = xmlNodeGetContent (node); node = find_real_node (node->next); - if (!node || strcmp ((const char *)node->name, "params") != 0) - goto fail; + if (node) { + if (strcmp ((const char *)node->name, "params") != 0) + goto fail; #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS #endif - *params = g_value_array_new (1); - param = find_real_node (node->children); - while (param && !strcmp ((const char *)param->name, "param")) { - xval = find_real_node (param->children); - if (!xval || strcmp ((const char *)xval->name, "value") != 0 || - !parse_value (xval, &value)) { - g_value_array_free (*params); - goto fail; - } - g_value_array_append (*params, &value); - g_value_unset (&value); + *params = soup_value_array_new (); + param = find_real_node (node->children); + while (param && !strcmp ((const char *)param->name, "param")) { + xval = find_real_node (param->children); + if (!xval || strcmp ((const char *)xval->name, "value") != 0 || + !parse_value (xval, &value)) { + g_value_array_free (*params); + goto fail; + } + g_value_array_append (*params, &value); + g_value_unset (&value); - param = find_real_node (param->next); - } + param = find_real_node (param->next); + } #ifdef G_GNUC_END_IGNORE_DEPRECATIONS G_GNUC_END_IGNORE_DEPRECATIONS #endif + } else + *params = soup_value_array_new (); success = TRUE; *method_name = g_strdup ((char *)xmlMethodName); diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c index 8ad2187b..75f6c911 100644 --- a/tests/xmlrpc-server-test.c +++ b/tests/xmlrpc-server-test.c @@ -180,7 +180,17 @@ do_echo (SoupMessage *msg, GValueArray *params) soup_xmlrpc_set_response (msg, G_TYPE_VALUE_ARRAY, out); g_value_array_free (out); +} + +static void +do_ping (SoupMessage *msg, GValueArray *params) +{ + if (params->n_values) { + args_error (msg, params, 0); + return; + } + soup_xmlrpc_set_response (msg, G_TYPE_STRING, "pong"); } static void @@ -216,6 +226,8 @@ server_callback (SoupServer *server, SoupMessage *msg, do_dateChange (msg, params); else if (!strcmp (method_name, "echo")) do_echo (msg, params); + else if (!strcmp (method_name, "ping")) + do_ping (msg, params); else { soup_xmlrpc_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND, "Unknown method %s", method_name); diff --git a/tests/xmlrpc-server.php b/tests/xmlrpc-server.php index 2e3dd381..66cb2be7 100644 --- a/tests/xmlrpc-server.php +++ b/tests/xmlrpc-server.php @@ -2,13 +2,13 @@ function paramfault () { - # xmlrpc-epi-php translates this into a real + # xmlrpc-php translates this into a real $fault["faultCode"] = -32602; $fault["faultString"] = "bad parameter"; return $fault; } -# We only check the params in sum(), because that's the one that +# We only check the params in sum(), because that is the one that # xmlrpc-test tests will fail if given bad args function sum ($method_name, $params, $app_data) @@ -69,8 +69,16 @@ function echo_ ($method_name, $params, $app_data) return $params[0]; } -# Work around xmlrpc-epi-php lossage; otherwise the datetime values -# we return will sometimes get a DST adjustment we don't want. +function ping ($method_name, $params, $app_data) +{ + if (count ($params) == 0) + return "pong"; + else + return paramfault (); +} + +# Work around xmlrpc-php lossage; otherwise the datetime values +# we return will sometimes get a DST adjustment we do not want. putenv ("TZ="); $xmlrpc_server = xmlrpc_server_create (); @@ -79,6 +87,7 @@ xmlrpc_server_register_method($xmlrpc_server, "countBools", "countBools"); xmlrpc_server_register_method($xmlrpc_server, "md5sum", "md5sum"); xmlrpc_server_register_method($xmlrpc_server, "dateChange", "dateChange"); xmlrpc_server_register_method($xmlrpc_server, "echo", "echo_"); +xmlrpc_server_register_method($xmlrpc_server, "ping", "ping"); $response = xmlrpc_server_call_method ($xmlrpc_server, implode("\r\n", file('php://input')), diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c index ec67e4d1..7a29d0e9 100644 --- a/tests/xmlrpc-test.c +++ b/tests/xmlrpc-test.c @@ -27,26 +27,13 @@ static const char *const value_type[] = { }; static gboolean -do_xmlrpc (const char *method, GValue *retval, ...) +send_xmlrpc (const char *body, GValue *retval) { SoupMessage *msg; - va_list args; - GValueArray *params; GError *err = NULL; - char *body; - - va_start (args, retval); - params = soup_value_array_from_args (args); - va_end (args); - - body = soup_xmlrpc_build_method_call (method, params->values, - params->n_values); - g_value_array_free (params); - if (!body) - return FALSE; msg = soup_message_new ("POST", uri); - soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE, + soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY, body, strlen (body)); soup_session_send_message (session, msg); @@ -73,6 +60,30 @@ do_xmlrpc (const char *method, GValue *retval, ...) return TRUE; } +static gboolean +do_xmlrpc (const char *method, GValue *retval, ...) +{ + va_list args; + GValueArray *params; + char *body; + gboolean ret; + + va_start (args, retval); + params = soup_value_array_from_args (args); + va_end (args); + + body = soup_xmlrpc_build_method_call (method, params->values, + params->n_values); + g_value_array_free (params); + if (!body) + return FALSE; + + ret = send_xmlrpc (body, retval); + g_free (body); + + return ret; +} + static gboolean check_xmlrpc (GValue *value, GType type, ...) { @@ -385,6 +396,55 @@ test_echo (void) return TRUE; } +static gboolean +test_ping (gboolean include_params) +{ + GValueArray *params; + GValue retval; + char *request; + char *out; + gboolean ret; + + debug_printf (1, "ping (void (%s) -> string): ", + include_params ? "empty " : "no "); + + params = soup_value_array_new (); + request = soup_xmlrpc_build_method_call ("ping", params->values, + params->n_values); + g_value_array_free (params); + if (!request) + return FALSE; + + if (!include_params) { + char *params, *end; + + params = strstr (request, ""); + if (!params) { + debug_printf (1, "ERROR: XML did not contain !"); + return FALSE; + } + end = params + strlen (""); + memmove (params, end, strlen (end) + 1); + } + + ret = send_xmlrpc (request, &retval); + g_free (request); + + if (!ret || !check_xmlrpc (&retval, G_TYPE_STRING, &out)) + return FALSE; + + if (!strcmp (out, "pong")) { + debug_printf (1, "OK!\n"); + ret = TRUE; + } else { + debug_printf (1, "WRONG! Bad response '%s'", out); + ret = FALSE; + } + + g_free (out); + return ret; +} + static gboolean do_bad_xmlrpc (const char *body) { @@ -476,6 +536,10 @@ main (int argc, char **argv) errors++; if (!test_echo ()) errors++; + if (!test_ping (TRUE)) + errors++; + if (!test_ping (FALSE)) + errors++; if (!test_fault_malformed ()) errors++; if (!test_fault_method ()) -- cgit v1.2.1 From e1ce7249de8d7abc7a81faa706a69830272fe886 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 6 Aug 2012 17:46:39 -0400 Subject: 2.39.5 --- NEWS | 32 ++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 79baf8ee..4fcb242c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,35 @@ +Changes in libsoup from 2.39.4.1 to 2.39.5: + + * Fixed several bugs in the soup-message-io updates that could + cause hangs or I/O errors. [#679527 and other bugs not filed + in bugzilla] + + * Fixed SoupServer:async-context to work properly again + + * Further fixes to soup_uri_normalize() when using the + "unescape_extra" parameter. [#680018] + + * Fixed soup_xmlrpc_parse_method_call() to handle the case + where there is no element (which is legal). + [#671661] + + * Fixed the deprecation warning on soup_message_headers_get() + [#680143] + + * Added warnings to some erroneous SoupSocket usages rather + than returning bogus data. [#673083, Simon McVittie] + + * Fixed build under Windows/MinGW + + * SoupSocket no longer emits the "readable" signal when a + socket is disconnected if that socket is non-blocking. + + * Updated public suffix list to the current version. + + * New/Updated translations: + Assamese, Chinese (simplified), Esperanto, Galician, Greek, Gujarati, + Hebrew, Norwegian bokmål, Russian, Serbian, Slovenian + Changes in libsoup from 2.39.4 to 2.39.4.1: * Fixed indentation problems in tld-parser.py so it will work diff --git a/configure.ac b/configure.ac index 47daa7dd..7046b682 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *** Initialize automake and set version *** dnl ******************************************* AC_PREREQ(2.63) -AC_INIT([libsoup],[2.39.4.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[2.39.5],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -- cgit v1.2.1 From 82084a0c02c958a8d5bff4f847fc1507b10db9ed Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Thu, 2 Aug 2012 16:50:54 +0200 Subject: SoupTLD: fix a regression in soup_tld_is_public_suffix() soup_tld_is_public_suffix() was not returning TRUE for well known TLDs as ".com" after cbae89f4. Also added some extra documentation to soup_tld_get_base_domain() in order to make explicit that it returns NULL for private URLs. Reworked unit tests in order to allow them detect these regressions. https://bugzilla.gnome.org/show_bug.cgi?id=681085 --- libsoup/soup-tld.c | 16 +++++----- tests/tld-test.c | 85 ++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/libsoup/soup-tld.c b/libsoup/soup-tld.c index 0c40b675..fc7c992c 100644 --- a/libsoup/soup-tld.c +++ b/libsoup/soup-tld.c @@ -59,6 +59,10 @@ soup_tld_ensure_rules_hash_table (void) * plus the second level domain, for example for myhost.mydomain.com * it will return mydomain.com. * + * Note that %NULL will be returned for private URLs (those not ending + * with any well known TLD) because choosing a base domain for them + * would be totally arbitrary. + * * This method only works for valid UTF-8 hostnames in their canonical * representation form, so you should use g_hostname_to_unicode() to * get the canonical representation if that is not the case. @@ -106,7 +110,7 @@ soup_tld_domain_is_public_suffix (const char *domain) g_return_val_if_reached (FALSE); base_domain = soup_tld_get_base_domain_internal (domain, 0, &error); - if (base_domain) + if (g_strcmp0 (domain, base_domain)) return FALSE; if (g_error_matches (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_NO_BASE_DOMAIN)) { @@ -178,15 +182,9 @@ soup_tld_get_base_domain_internal (const char *hostname, guint additional_domain /* If we match a *. rule and there were no previous exceptions * nor previous domains then treat it as an exact match. */ - if (!prev_domain) { - g_set_error_literal (error, SOUP_TLD_ERROR, - SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS, - _("Not enough domains")); - return NULL; - } - tld = prev_domain; + tld = prev_domain ? prev_domain : cur_domain; break; - } else if (*flags == SOUP_TLD_RULE_NORMAL || !next_dot) { + } else if (*flags == SOUP_TLD_RULE_NORMAL) { tld = cur_domain; break; } else if (*flags & SOUP_TLD_RULE_EXCEPTION) { diff --git a/tests/tld-test.c b/tests/tld-test.c index 25d2da28..d0c73a8e 100644 --- a/tests/tld-test.c +++ b/tests/tld-test.c @@ -21,16 +21,6 @@ static struct { { ".example", NULL }, { ".example.com", NULL }, { ".example.example", NULL }, - /* Unlisted TLD.*/ - { "example", NULL }, - { "example.example", NULL }, - { "b.example.example", NULL }, - { "a.b.example.example", NULL }, - /* Listed, but non-Internet, TLD. */ - { "local", NULL }, - { "example.local", NULL }, - { "b.example.local", NULL }, - { "a.b.example.local", NULL }, /* TLD with only 1 rule. */ { "biz", NULL }, { "domain.biz", "domain.biz" }, @@ -88,6 +78,20 @@ static struct { /* The original list does not include non-ASCII tests. Let's add a couple. */ { "公司.cn", NULL }, { "a.b.åfjord.no", "b.åfjord.no" } +}, +/* Non Internet TLDs have NULL as expected result + */ +non_inet_tld_tests[] = { + /* Unlisted TLD.*/ + { "example", NULL }, + { "example.example", NULL }, + { "b.example.example", NULL }, + { "a.b.example.example", NULL }, + /* Listed, but non-Internet, TLD. */ + { "local", NULL }, + { "example.local", NULL }, + { "b.example.local", NULL }, + { "a.b.example.local", NULL } }; int @@ -99,29 +103,46 @@ main (int argc, char **argv) errors = 0; for (i = 0; i < G_N_ELEMENTS (tld_tests); ++i) { - gboolean is_public = soup_tld_domain_is_public_suffix (tld_tests[i].hostname); - const char *base_domain = soup_tld_get_base_domain (tld_tests[i].hostname, NULL); + GError *error = NULL; + gboolean is_public = soup_tld_domain_is_public_suffix (tld_tests[i].hostname); + const char *base_domain = soup_tld_get_base_domain (tld_tests[i].hostname, &error); + + debug_printf (1, "Testing %s: ", tld_tests[i].hostname); + + if (is_public && tld_tests[i].result) { + debug_printf (1, "ERROR: domain is public but base_domain is not NULL (%s)\n", + base_domain); + ++errors; + } else if (g_strcmp0 (tld_tests[i].result, base_domain)) { + debug_printf (1, "ERROR: %s expected as base domain but got %s\n", + tld_tests[i].result, base_domain); + ++errors; + + } else if (!tld_tests[i].result && !is_public && + !g_error_matches (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_INVALID_HOSTNAME)) { + debug_printf (1, "ERROR: not public domain with NULL expected result\n"); + ++errors; + } else + debug_printf (1, "OK\n"); + + g_clear_error(&error); + } + + for (i = 0; i < G_N_ELEMENTS (non_inet_tld_tests); ++i) { + gboolean is_public = soup_tld_domain_is_public_suffix (non_inet_tld_tests[i].hostname); + const char *base_domain = soup_tld_get_base_domain (non_inet_tld_tests[i].hostname, NULL); + + debug_printf (1, "Testing %s: ", non_inet_tld_tests[i].hostname); - debug_printf (1, "Testing %s: ", tld_tests[i].hostname); - if (tld_tests[i].result) { - /* Public domains have NULL expected results. */ - if (is_public || g_strcmp0 (tld_tests[i].result, base_domain)) { - debug_printf (1, "ERROR: %s got %s (%s expected)\n", - tld_tests[i].hostname, base_domain, tld_tests[i].result); - ++errors; - } else - debug_printf (1, "OK\n"); - } else { - /* If there is no expected result then either the domain is public or - * the hostname invalid (for example starts with a leading dot). - */ - if (!is_public && base_domain) { - debug_printf (1, "ERROR: public domain %s got %s (none expected)\n", - tld_tests[i].hostname, base_domain); - ++errors; - } else - debug_printf (1, "OK\n"); - } + if (is_public) { + debug_printf (1, "ERROR: domain incorrectly clasified as public\n"); + ++errors; + } else if (base_domain) { + debug_printf (1, "ERROR: non NULL base domain (%s) for local url\n", + base_domain); + ++errors; + } else + debug_printf (1, "OK\n"); } test_cleanup (); -- cgit v1.2.1 From 75c1edb22d63993043b9d233ecd5cb784d905de2 Mon Sep 17 00:00:00 2001 From: Xan Lopez Date: Tue, 7 Aug 2012 15:39:30 +0200 Subject: post-release version bump --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 7046b682..d0d19341 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *** Initialize automake and set version *** dnl ******************************************* AC_PREREQ(2.63) -AC_INIT([libsoup],[2.39.5],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[2.39.6],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -- cgit v1.2.1 From b78be57c5a32fcf8ae1c693bf4af938f8b5278d6 Mon Sep 17 00:00:00 2001 From: Muhammet Kara Date: Wed, 8 Aug 2012 20:06:41 +0300 Subject: [l10n]Added Turkish translation --- po/LINGUAS | 1 + po/tr.po | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 po/tr.po diff --git a/po/LINGUAS b/po/LINGUAS index f3f53185..64192fff 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -19,6 +19,7 @@ sl sr sr@latin te +tr vi zh_CN zh_HK diff --git a/po/tr.po b/po/tr.po new file mode 100644 index 00000000..1c8813a7 --- /dev/null +++ b/po/tr.po @@ -0,0 +1,77 @@ +# Turkish translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Muhammet Kara , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-08-07 13:39+0000\n" +"PO-Revision-Date: 2012-08-08 20:04+0000\n" +"Last-Translator: Muhammet Kara \n" +"Language-Team: Turkish \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Lokalize 1.4\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Bağlantı beklenmedik şekilde sonlandırıldı" + +#: ../libsoup/soup-converter-wrapper.c:191 +#, c-format +msgid "Output buffer is too small" +msgstr "Çıktı arabelleği çok küçük" + +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +msgid "Operation was cancelled" +msgstr "İşlem iptal edildi" + +#: ../libsoup/soup-message-io.c:864 +#, fuzzy +msgid "Operation would block" +msgstr "İşlem bloklanabilir" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI verilmedi" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Geçersiz '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' ayrıştırılamadı" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Desteklenmeyen URI şeması '%s'" + +#: ../libsoup/soup-tld.c:152 +msgid "Hostname is an IP address" +msgstr "Makine adı bir ip adresi" + +#: ../libsoup/soup-tld.c:173 +msgid "Invalid hostname" +msgstr "Geçersiz makine adı" + +#: ../libsoup/soup-tld.c:202 +msgid "Hostname has no base domain" +msgstr "Ana makinenin temel etki alanı yok" + +#: ../libsoup/soup-tld.c:224 +msgid "Not enough domains" +msgstr "Yeterli etki alanı yok" + -- cgit v1.2.1 From b811caef81664713636fb5fca6332dc431ae3780 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Wed, 8 Aug 2012 11:13:19 +0100 Subject: Makefile.glib: allow marshallers signatures containing integer (like INT64) https://bugzilla.gnome.org/show_bug.cgi?id=681438 --- Makefile.glib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.glib b/Makefile.glib index 78eb07d7..8713f9a8 100644 --- a/Makefile.glib +++ b/Makefile.glib @@ -155,7 +155,7 @@ define _glib_make_genmarshal_rules $(if $(_glib_marshal_sources),,$(error Need to define $(_glib_marshal_sources_var) for $(1).[ch])) $(1).list.stamp: $(_glib_marshal_sources) - $$(_GLIB_V_GEN) LC_ALL=C sed -ne 's/.*_$(_glib_marshal_prefix)_\([_A-Z]*\).*/\1/p' $$^ | sort -u | sed -e 's/__/:/' -e 's/_/,/g' > $(1).list.tmp && \ + $$(_GLIB_V_GEN) LC_ALL=C sed -ne 's/.*_$(_glib_marshal_prefix)_\([_A-Z0-9]*\).*/\1/p' $$^ | sort -u | sed -e 's/__/:/' -e 's/_/,/g' > $(1).list.tmp && \ (cmp -s $(1).list.tmp $(1).list || cp $(1).list.tmp $(1).list) && \ rm -f $(1).list.tmp && \ echo timestamp > $$@ -- cgit v1.2.1 From cccf4b45b740c0a601ed6116b79755a6686dfbcc Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 9 Aug 2012 07:24:10 -0400 Subject: soup-misc-private.h: Fix the single-include #define Pointed out by various people on multiple occasions until eventually I remembered to fix it... --- libsoup/soup-misc-private.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index 8276b8a5..0677fc5b 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -4,8 +4,8 @@ * Copyright 2011 Red Hat, Inc. */ -#ifndef SOUP_URI_PRIVATE_H -#define SOUP_URI_PRIVATE_H 1 +#ifndef SOUP_MISC_PRIVATE_H +#define SOUP_MISC_PRIVATE_H 1 #include "soup-socket.h" @@ -41,4 +41,4 @@ SoupURI *soup_socket_get_http_proxy_uri (SoupSocket *sock); method == SOUP_METHOD_PUT || \ method == SOUP_METHOD_DELETE) -#endif /* SOUP_URI_PRIVATE_H */ +#endif /* SOUP_MISC_PRIVATE_H */ -- cgit v1.2.1 From a93481f9c50c50ce419ba0b20e50296bc17da8f6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 10 Aug 2012 16:53:30 -0400 Subject: tests: parallelize proxy-test to make it faster TODO: parallelize auth-test and timeout-test, make it easier to use. --- tests/proxy-test.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++------ tests/test-utils.c | 7 ++++++ tests/test-utils.h | 1 + 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 35c9d841..ee0197a2 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -15,7 +15,7 @@ static SoupProxyTest tests[] = { { "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED }, { "GET -> 403", "http://no-such-hostname.xx/", SOUP_STATUS_FORBIDDEN }, }; -static int ntests = sizeof (tests) / sizeof (tests[0]); +static const int ntests = sizeof (tests) / sizeof (tests[0]); #define HTTP_SERVER "http://127.0.0.1:47524" #define HTTPS_SERVER "https://127.0.0.1:47525" @@ -97,6 +97,7 @@ test_url (const char *url, int proxy, guint expected, proxy_uri = soup_uri_new (proxies[proxy]); session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_PROXY_URI, proxy_uri, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); soup_uri_free (proxy_uri); g_signal_connect (session, "authenticate", @@ -235,6 +236,62 @@ run_test (int i, gboolean sync) debug_printf (1, "\n"); } +static gpointer +async_proxy_test_thread (gpointer num) +{ + GMainContext *context = g_main_context_new (); + + g_main_context_push_thread_default (context); + run_test (GPOINTER_TO_INT (num), FALSE); + g_main_context_pop_thread_default (context); + + return NULL; +} + +static gpointer +sync_proxy_test_thread (gpointer num) +{ + run_test (GPOINTER_TO_INT (num), TRUE); + return NULL; +} + +static void +do_proxy_tests (void) +{ + int i; + + debug_printf (1, "Basic proxy tests\n"); + + if (parallelize) { + GThread *threads[ntests]; + + /* Doing the sync and async tests separately is faster + * than doing them both at the same time (hitting + * apache's connection limit maybe?) + */ + for (i = 0; i < ntests; i++) { + threads[i] = g_thread_new ("async_proxy_test", + async_proxy_test_thread, + GINT_TO_POINTER (i)); + } + for (i = 0; i < ntests; i++) + g_thread_join (threads[i]); + + for (i = 0; i < ntests; i++) { + threads[i] = g_thread_new ("sync_proxy_test", + sync_proxy_test_thread, + GINT_TO_POINTER (i)); + } + for (i = 0; i < ntests; i++) + g_thread_join (threads[i]); + } else { + for (i = 0; i < ntests; i++) { + run_test (i, FALSE); + run_test (i, TRUE); + } + } +} + static void server_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, @@ -319,21 +376,16 @@ main (int argc, char **argv) { SoupServer *server; SoupURI *base_uri; - int i; test_init (argc, argv, NULL); apache_init (); - for (i = 0; i < ntests; i++) { - run_test (i, FALSE); - run_test (i, TRUE); - } - server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); + do_proxy_tests (); do_proxy_fragment_test (base_uri); do_proxy_redirect_test (); diff --git a/tests/test-utils.c b/tests/test-utils.c index 606de327..c34b0b71 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -14,6 +14,7 @@ static gboolean apache_running; static SoupLogger *logger; int debug_level, errors; +gboolean parallelize = TRUE; gboolean expect_warning, tls_available; static int http_debug_level; @@ -37,6 +38,9 @@ static GOptionEntry debug_entry[] = { { "debug", 'd', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, increment_debug_level, "Enable (or increase) test-specific debugging", NULL }, + { "parallel", 'p', G_OPTION_FLAG_REVERSE, + G_OPTION_ARG_NONE, ¶llelize, + "Toggle parallelization (default is on, unless -d or -h)", NULL }, { "http-debug", 'h', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, increment_http_debug_level, "Enable (or increase) HTTP-level debugging", NULL }, @@ -101,6 +105,9 @@ test_init (int argc, char **argv, GOptionEntry *entries) } g_option_context_free (opts); + if (debug_level > 0 || http_debug_level > 0) + parallelize = !parallelize; + /* Exit cleanly on ^C in case we're valgrinding. */ signal (SIGINT, quit); diff --git a/tests/test-utils.h b/tests/test-utils.h index 5c244f34..2783aab3 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -17,6 +17,7 @@ void test_init (int argc, char **argv, GOptionEntry *entries); void test_cleanup (void); extern int debug_level, errors; +extern gboolean parallelize; extern gboolean expect_warning, tls_available; void debug_printf (int level, const char *format, ...) G_GNUC_PRINTF (2, 3); -- cgit v1.2.1 From 61b86e0724150d4b7684acd467ecb333386b8617 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 11 Aug 2012 20:03:44 -0400 Subject: valgrindage --- libsoup/soup-client-input-stream.c | 11 +++++++ libsoup/soup-converter-wrapper.c | 17 ++++++----- libsoup/soup-io-stream.c | 2 ++ libsoup/soup-message-io.c | 8 +++-- libsoup/soup-request-http.c | 9 ++---- libsoup/soup-session-async.c | 21 ++++++------- libsoup/soup-socket.c | 4 ++- libsoup/soup-tld.c | 4 ++- tests/coding-test.c | 12 +++++++- tests/connection-test.c | 4 +++ tests/libsoup.supp | 61 +++++++++++++++++++++++++++++++++++++- tests/proxy-test.c | 2 ++ tests/redirect-test.c | 4 +++ tests/requester-test.c | 10 +++++-- tests/timeout-test.c | 1 + 15 files changed, 138 insertions(+), 32 deletions(-) diff --git a/libsoup/soup-client-input-stream.c b/libsoup/soup-client-input-stream.c index 5c18eaa0..966b9405 100644 --- a/libsoup/soup-client-input-stream.c +++ b/libsoup/soup-client-input-stream.c @@ -46,6 +46,16 @@ soup_client_input_stream_init (SoupClientInputStream *stream) SoupClientInputStreamPrivate); } +static void +soup_client_input_stream_finalize (GObject *object) +{ + SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (object); + + g_clear_object (&cistream->priv->msg); + + G_OBJECT_CLASS (soup_client_input_stream_parent_class)->finalize (object); +} + static void soup_client_input_stream_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) @@ -231,6 +241,7 @@ soup_client_input_stream_class_init (SoupClientInputStreamClass *stream_class) g_type_class_add_private (stream_class, sizeof (SoupClientInputStreamPrivate)); + object_class->finalize = soup_client_input_stream_finalize; object_class->set_property = soup_client_input_stream_set_property; object_class->get_property = soup_client_input_stream_get_property; diff --git a/libsoup/soup-converter-wrapper.c b/libsoup/soup-converter-wrapper.c index 1953229a..6fa19d91 100644 --- a/libsoup/soup-converter-wrapper.c +++ b/libsoup/soup-converter-wrapper.c @@ -49,12 +49,21 @@ struct _SoupConverterWrapperPrivate gboolean discarding; }; +static void +soup_converter_wrapper_init (SoupConverterWrapper *converter) +{ + converter->priv = G_TYPE_INSTANCE_GET_PRIVATE (converter, + SOUP_TYPE_CONVERTER_WRAPPER, + SoupConverterWrapperPrivate); +} + static void soup_converter_wrapper_finalize (GObject *object) { SoupConverterWrapperPrivate *priv = SOUP_CONVERTER_WRAPPER (object)->priv; g_clear_object (&priv->base_converter); + g_clear_object (&priv->msg); G_OBJECT_CLASS (soup_converter_wrapper_parent_class)->finalize (object); } @@ -115,14 +124,6 @@ soup_converter_wrapper_get_property (GObject *object, } } -static void -soup_converter_wrapper_init (SoupConverterWrapper *converter) -{ - converter->priv = G_TYPE_INSTANCE_GET_PRIVATE (converter, - SOUP_TYPE_CONVERTER_WRAPPER, - SoupConverterWrapperPrivate); -} - static void soup_converter_wrapper_class_init (SoupConverterWrapperClass *klass) { diff --git a/libsoup/soup-io-stream.c b/libsoup/soup-io-stream.c index 74c71580..ea5ddef1 100644 --- a/libsoup/soup-io-stream.c +++ b/libsoup/soup-io-stream.c @@ -103,6 +103,8 @@ soup_io_stream_finalize (GObject *object) SoupIOStream *siostream = SOUP_IO_STREAM (object); g_clear_object (&siostream->priv->base_iostream); + g_clear_object (&siostream->priv->istream); + g_clear_object (&siostream->priv->ostream); G_OBJECT_CLASS (soup_io_stream_parent_class)->finalize (object); } diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index eeb67553..6924e20c 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -243,6 +243,7 @@ setup_body_istream (SoupMessage *msg) "converter", wrapper, NULL); g_object_unref (io->body_istream); + g_object_unref (wrapper); io->body_istream = filter; } @@ -908,7 +909,8 @@ io_run (SoupMessage *msg, gpointer user_data) g_error_free (error); soup_message_io_finished (msg); - } + } else if (error) + g_error_free (error); g_object_unref (msg); g_clear_object (&cancellable); @@ -946,8 +948,10 @@ soup_message_io_run_until_finish (SoupMessage *msg, if (!io_run_until (msg, SOUP_MESSAGE_IO_STATE_DONE, SOUP_MESSAGE_IO_STATE_DONE, - cancellable, error)) + cancellable, error)) { + g_object_unref (msg); return FALSE; + } soup_message_io_finished (msg); g_object_unref (msg); diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index 44a1f7d5..4fc82206 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -113,12 +113,9 @@ free_send_async_data (SendAsyncData *sadata) g_object_unref (sadata->http); g_object_unref (sadata->simple); - if (sadata->cancellable) - g_object_unref (sadata->cancellable); - if (sadata->stream) - g_object_unref (sadata->stream); - if (sadata->original) - g_object_unref (sadata->original); + g_clear_object (&sadata->cancellable); + g_clear_object (&sadata->stream); + g_clear_object (&sadata->original); g_slice_free (SendAsyncData, sadata); } diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 81afcf8c..75929edf 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -543,7 +543,7 @@ send_request_finished (SoupSession *session, SoupMessageQueueItem *item) return; } - mostream = g_object_get_data (G_OBJECT (item->msg), "SoupSessionAsync:ostream"); + mostream = g_object_get_data (G_OBJECT (item->result), "SoupSessionAsync:ostream"); if (mostream) { gpointer data; gssize size; @@ -576,9 +576,14 @@ send_async_spliced (GObject *source, GAsyncResult *result, gpointer user_data) { SoupMessageQueueItem *item = user_data; GInputStream *istream = g_object_get_data (source, "istream"); - GError *error = NULL; + /* It should be safe to call the sync close() method here since + * the message body has already been written. + */ + g_input_stream_close (istream, NULL, NULL); + g_object_unref (istream); + /* If the message was cancelled, it will be completed via other means */ if (g_cancellable_is_cancelled (item->cancellable) || !item->result) { @@ -589,14 +594,11 @@ send_async_spliced (GObject *source, GAsyncResult *result, gpointer user_data) if (g_output_stream_splice_finish (G_OUTPUT_STREAM (source), result, &error) == -1) { send_request_return_result (item, NULL, error); + soup_message_queue_item_unref (item); return; } - /* Otherwise either restarted or finished will eventually be called. - * It should be safe to call the sync close() method here since - * the message body has already been written. - */ - g_input_stream_close (istream, NULL, NULL); + /* Otherwise either restarted or finished will eventually be called. */ do_idle_run_queue (item->session); soup_message_queue_item_unref (item); } @@ -612,11 +614,10 @@ send_async_maybe_complete (SoupMessageQueueItem *item, /* Message may be requeued, so gather the current message body... */ ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); - g_object_set_data_full (G_OBJECT (item->msg), "SoupSessionAsync:ostream", + g_object_set_data_full (G_OBJECT (item->result), "SoupSessionAsync:ostream", ostream, g_object_unref); - g_object_set_data_full (G_OBJECT (ostream), "istream", - stream, g_object_unref); + g_object_set_data (G_OBJECT (ostream), "istream", stream); /* Give the splice op its own ref on item */ soup_message_queue_item_ref (item); diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index c789e648..f44cf347 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -674,8 +674,10 @@ socket_connected (SoupSocket *sock, GSocketConnection *conn, GError *error) g_object_unref (priv->connect_cancel); priv->connect_cancel = NULL; - if (cancelled) + if (cancelled) { + g_clear_error (&error); return SOUP_STATUS_CANCELLED; + } } if (error) { diff --git a/libsoup/soup-tld.c b/libsoup/soup-tld.c index fc7c992c..8782a82c 100644 --- a/libsoup/soup-tld.c +++ b/libsoup/soup-tld.c @@ -110,8 +110,10 @@ soup_tld_domain_is_public_suffix (const char *domain) g_return_val_if_reached (FALSE); base_domain = soup_tld_get_base_domain_internal (domain, 0, &error); - if (g_strcmp0 (domain, base_domain)) + if (g_strcmp0 (domain, base_domain)) { + g_clear_error (&error); return FALSE; + } if (g_error_matches (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_NO_BASE_DOMAIN)) { g_error_free (error); diff --git a/tests/coding-test.c b/tests/coding-test.c index 02ec23af..cd7321ed 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -109,7 +109,8 @@ server_callback (SoupServer *server, SoupMessage *msg, if (!soup_header_contains (options, "empty")) { soup_message_body_append (msg->response_body, SOUP_MEMORY_TAKE, contents, length); - } + } else + g_free (contents); if (soup_header_contains (options, "trailing-junk")) { soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY, @@ -366,6 +367,7 @@ do_single_coding_req_test (SoupRequest *req, g_error_free (error); errors++; } + g_object_unref (stream); check_response (msg, expected_encoding, expected_content_type, status); g_object_unref (msg); @@ -434,6 +436,7 @@ do_coding_req_test (void) cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed w/ junk"); g_byte_array_free (cmp, TRUE); + g_object_unref (msg); g_object_unref (req); /* Plain text data, claim gzip with server error */ @@ -450,6 +453,7 @@ do_coding_req_test (void) */ check_req_bodies (plain, cmp, "plain", "mis-encoded"); g_byte_array_free (cmp, TRUE); + g_object_unref (msg); g_object_unref (req); /* Plain text data, claim deflate */ @@ -461,6 +465,7 @@ do_coding_req_test (void) cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed"); g_byte_array_free (cmp, TRUE); + g_object_unref (msg); g_object_unref (req); /* Plain text data, claim deflate w/ junk */ @@ -472,6 +477,7 @@ do_coding_req_test (void) cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed w/ junk"); g_byte_array_free (cmp, TRUE); + g_object_unref (msg); g_object_unref (req); /* Plain text data, claim deflate with server error */ @@ -483,6 +489,7 @@ do_coding_req_test (void) cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED); check_req_bodies (plain, cmp, "plain", "mis-encoded"); g_byte_array_free (cmp, TRUE); + g_object_unref (msg); g_object_unref (req); /* Plain text data, claim deflate (no zlib headers)*/ @@ -494,6 +501,7 @@ do_coding_req_test (void) cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed"); g_byte_array_free (cmp, TRUE); + g_object_unref (msg); g_object_unref (req); /* Plain text data, claim deflate with server error */ @@ -505,6 +513,7 @@ do_coding_req_test (void) cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED); check_req_bodies (plain, cmp, "plain", "mis-encoded"); g_byte_array_free (cmp, TRUE); + g_object_unref (msg); g_object_unref (req); g_byte_array_free (plain, TRUE); @@ -551,6 +560,7 @@ do_coding_empty_test (void) g_byte_array_free (body, TRUE); g_object_unref (req); + soup_uri_free (uri); soup_test_session_abort_unref (session); } diff --git a/tests/connection-test.c b/tests/connection-test.c index 6ddc89c5..f8ff7c1d 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -335,6 +335,7 @@ do_timeout_req_test_for_session (SoupSession *session) errors++; g_clear_error (&error); } + g_object_unref (stream); } if (sockets[1]) { @@ -361,6 +362,7 @@ do_timeout_req_test_for_session (SoupSession *session) errors++; g_clear_error (&error); } + g_object_unref (stream); } msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); @@ -582,6 +584,7 @@ do_non_persistent_test_for_session (SoupSession *session) g_object_ref (msg); soup_session_queue_message (session, msg, NULL, NULL); g_main_loop_run (loop); + g_main_loop_unref (loop); if (msg->status_code != SOUP_STATUS_OK) { debug_printf (1, " Unexpected response: %d %s\n", @@ -589,6 +592,7 @@ do_non_persistent_test_for_session (SoupSession *session) errors++; } g_object_unref (msg); + g_object_unref (socket); } static void diff --git a/tests/libsoup.supp b/tests/libsoup.supp index 24c6516a..ac21e96a 100644 --- a/tests/libsoup.supp +++ b/tests/libsoup.supp @@ -321,7 +321,7 @@ ... fun:_dl_allocate_tls ... - fun:g_thread_create_posix_impl + fun:g_system_thread_new } { glib/filenamecharsets @@ -341,6 +341,40 @@ ... fun:g_tls_backend_gnutls_store_session } +{ + glib/gtlssessioncache_client + Memcheck:Leak + ... + fun:gnutls_session_get_data2 + fun:g_tls_client_connection_gnutls_finish_handshake +} +{ + glib/gtlssessioncache_client2 + Memcheck:Leak + ... + fun:g_bytes_new_with_free_func + fun:g_tls_client_connection_gnutls_finish_handshake +} +{ + glib/gtlssessioncache_client3 + Memcheck:Leak + ... + fun:g_bytes_new_take + fun:g_tls_client_connection_gnutls_constructed +} +{ + glib/gtlssessioncache_client4 + Memcheck:Leak + ... + fun:g_strdup_printf + fun:g_tls_client_connection_gnutls_constructed +} +{ + glib/gtlssessioncache_server + Memcheck:Leak + ... + fun:g_tls_server_connection_gnutls_db_store +} { glib/cached_poll_array Memcheck:Leak @@ -348,6 +382,25 @@ fun:g_malloc_n fun:g_main_context_iterate } +{ + glib/rand + Memcheck:Leak + ... + fun:g_rand_new + fun:g_random_int_range +} +{ + glib/g_cancellable_push_current + Memcheck:Leak + ... + fun:g_cancellable_push_current +} +{ + glib/slice_thread_local + Memcheck:Leak + ... + fun:thread_memory_from_self +} # probably inlines the aggressive memcpy/memcmp { @@ -421,6 +474,12 @@ ... fun:intern_header_name } +{ + libsoup/tlds + Memcheck:Leak + ... + fun:soup_tld_ensure_rules_hash_table +} # fixme? diff --git a/tests/proxy-test.c b/tests/proxy-test.c index ee0197a2..94e548a8 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -183,6 +183,7 @@ test_url_new_api (const char *url, int proxy, guint expected, errors++; g_clear_error (&error); } + g_object_unref (stream); } debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); @@ -244,6 +245,7 @@ async_proxy_test_thread (gpointer num) g_main_context_push_thread_default (context); run_test (GPOINTER_TO_INT (num), FALSE); g_main_context_pop_thread_default (context); + g_main_context_unref (context); return NULL; } diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 401eda21..3708d865 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -273,6 +273,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) } g_error_free (error); + g_object_unref (msg); g_object_unref (req); debug_printf (2, "\n"); return; @@ -280,6 +281,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) debug_printf (1, " could not send request: %s\n", error->message); g_error_free (error); + g_object_unref (msg); g_object_unref (req); errors++; debug_printf (2, "\n"); @@ -293,6 +295,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) g_error_free (error); errors++; } + g_object_unref (stream); if (msg->status_code != final_status) { debug_printf (1, " - Expected final status of %d, got %d !\n", @@ -300,6 +303,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) errors++; } + g_object_unref (msg); g_object_unref (req); debug_printf (2, "\n"); } diff --git a/tests/requester-test.c b/tests/requester-test.c index b4e86ea6..bc45e9f6 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -151,6 +151,7 @@ auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data) stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error); if (!stream) { debug_printf (1, " send_async failed: %s\n", error->message); + g_clear_error (&error); errors++; g_main_loop_quit (loop); return; @@ -196,8 +197,8 @@ test_sent (GObject *source, GAsyncResult *res, gpointer user_data) } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { debug_printf (1, " send_async failed with wrong error: %s\n", error->message); errors++; - g_clear_error (&error); } + g_clear_error (&error); g_main_loop_quit (loop); return; } else { @@ -234,6 +235,7 @@ request_started (SoupSession *session, SoupMessage *msg, { SoupSocket **save_socket = user_data; + g_clear_object (save_socket); *save_socket = g_object_ref (socket); } @@ -280,6 +282,7 @@ do_async_test (SoupSession *session, SoupURI *uri, msg->status_code, msg->reason_phrase, expected_status); g_object_unref (msg); + g_object_unref (socket); errors++; return; } @@ -459,15 +462,17 @@ do_sync_request (SoupSession *session, SoupRequest *request, } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { debug_printf (1, " send failed with wrong error: %s\n", error->message); errors++; - g_clear_error (&error); } + g_clear_error (&error); g_object_unref (msg); + g_object_unref (socket); return; } else if (!in) { debug_printf (1, " soup_request_send failed: %s\n", error->message); g_object_unref (msg); g_clear_error (&error); + g_object_unref (socket); errors++; return; } @@ -477,6 +482,7 @@ do_sync_request (SoupSession *session, SoupRequest *request, msg->reason_phrase); g_object_unref (msg); g_object_unref (in); + g_object_unref (socket); errors++; return; } diff --git a/tests/timeout-test.c b/tests/timeout-test.c index 5c9d6a81..9d9b2d13 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -152,6 +152,7 @@ do_request_to_session (SoupRequester *requester, const char *uri, error->message); errors++; } + g_object_unref (stream); } if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code) && -- cgit v1.2.1 From 045daa9d59fbfa77be0b3526de39b4fd1f47c307 Mon Sep 17 00:00:00 2001 From: Sandeep Sheshrao Shedmake Date: Sun, 12 Aug 2012 19:59:53 +0530 Subject: Added Marathi Translations --- po/LINGUAS | 1 + po/mr.po | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 po/mr.po diff --git a/po/LINGUAS b/po/LINGUAS index 64192fff..f4f8381a 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -10,6 +10,7 @@ gu he id lt +mr nb pa pl diff --git a/po/mr.po b/po/mr.po new file mode 100644 index 00000000..fafc7826 --- /dev/null +++ b/po/mr.po @@ -0,0 +1,76 @@ +# Marathi translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Sandeep Shedmake , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-08-12 00:04+0000\n" +"PO-Revision-Date: 2012-08-12 17:16+0530\n" +"Last-Translator: Sandeep Shedmake \n" +"Language-Team: Marathi \n" +"Language: mr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.4\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "जोडणी अनपेक्षितपणे बंद झाली" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "आउटपुट बफर खूपच लहान आहे" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "कार्य रद्द केले" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "कार्य बंधिस्त करू शकते" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI पुरवले नाही" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "अवैध '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' वाचणे अशक्य" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "असमर्थीत URI सुत्रयोजना '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "यजमाननाव IP पत्ता आहे" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "अवैध यजमाननाव" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "यजमाननावात बेस डोमैन नाही" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "अतिरिक्त डोमैन्स् आढळले नाही" + -- cgit v1.2.1 From 7de731c941954f33c3d0561bd67255ffb394431f Mon Sep 17 00:00:00 2001 From: Christian Kirbach Date: Sun, 12 Aug 2012 21:58:37 +0200 Subject: Added German translation --- po/LINGUAS | 1 + po/de.po | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 po/de.po diff --git a/po/LINGUAS b/po/LINGUAS index f4f8381a..95d1c991 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1,6 +1,7 @@ as bg be +de el eo es diff --git a/po/de.po b/po/de.po new file mode 100644 index 00000000..67e8af75 --- /dev/null +++ b/po/de.po @@ -0,0 +1,75 @@ +# German translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Tobias Endrigkeit , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-08-12 00:04+0000\n" +"PO-Revision-Date: 2012-08-06 20:20+0200\n" +"Last-Translator: Tobias Endrigkeit \n" +"Language-Team: Deutsch \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.5\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Die Verbindung wurde unerwartet beendet" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Der Ausgabe-Zwischenspeicher ist zu klein" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Der Vorgang wurde abgebrochen" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Der Vorgang würde gestoppt werden" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Keine Adresse wurde bereitgestellt" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Ungültige »%s« Adresse: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Die Adresse »%s« konnte nicht verarbeitet werden" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Nicht unterstütztes Adressenschema »%s«" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Der Rechnername ist eine IP-Adresse" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Ungültiger Rechnername" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Der Rechnername hat keine Hauptdomäne" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Nicht genug Domänen" -- cgit v1.2.1 From 9281a4f2088428557b9f1a458eb9446ddc2a97f2 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 12 Aug 2012 10:32:49 -0400 Subject: SoupSessionAsync: fix the idle_run_queue source handling (again) The previous code checked priv->disposed after the session was freed sometimes... --- libsoup/soup-misc-private.h | 4 ++++ libsoup/soup-misc.c | 21 +++++++++++++++++---- libsoup/soup-session-async.c | 18 ++++++++++++++++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index 0677fc5b..79e73bc6 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -41,4 +41,8 @@ SoupURI *soup_socket_get_http_proxy_uri (SoupSocket *sock); method == SOUP_METHOD_PUT || \ method == SOUP_METHOD_DELETE) +GSource *soup_add_completion_reffed (GMainContext *async_context, + GSourceFunc function, + gpointer data); + #endif /* SOUP_MISC_PRIVATE_H */ diff --git a/libsoup/soup-misc.c b/libsoup/soup-misc.c index 83540457..325b5872 100644 --- a/libsoup/soup-misc.c +++ b/libsoup/soup-misc.c @@ -8,6 +8,7 @@ #include #include "soup-misc.h" +#include "soup-misc-private.h" /** * SECTION:soup-misc @@ -112,6 +113,19 @@ soup_add_idle (GMainContext *async_context, return source; } +GSource * +soup_add_completion_reffed (GMainContext *async_context, + GSourceFunc function, + gpointer data) +{ + GSource *source = g_idle_source_new (); + + g_source_set_priority (source, G_PRIORITY_DEFAULT); + g_source_set_callback (source, function, data, NULL); + g_source_attach (source, async_context); + return source; +} + /** * soup_add_completion: (skip) * @async_context: (allow-none): the #GMainContext to dispatch the I/O @@ -132,10 +146,9 @@ GSource * soup_add_completion (GMainContext *async_context, GSourceFunc function, gpointer data) { - GSource *source = g_idle_source_new (); - g_source_set_priority (source, G_PRIORITY_DEFAULT); - g_source_set_callback (source, function, data, NULL); - g_source_attach (source, async_context); + GSource *source; + + source = soup_add_completion_reffed (async_context, function, data); g_source_unref (source); return source; } diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 75929edf..0f365f38 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -16,6 +16,7 @@ #include "soup-session-private.h" #include "soup-message-private.h" #include "soup-message-queue.h" +#include "soup-misc-private.h" /** * SECTION:soup-session-async @@ -37,6 +38,7 @@ G_DEFINE_TYPE (SoupSessionAsync, soup_session_async, SOUP_TYPE_SESSION) typedef struct { SoupSessionAsync *sa; + GSList *sources; gboolean disposed; } SoupSessionAsyncPrivate; @@ -54,8 +56,14 @@ static void soup_session_async_dispose (GObject *object) { SoupSessionAsyncPrivate *priv = SOUP_SESSION_ASYNC_GET_PRIVATE (object); + GSList *iter; priv->disposed = TRUE; + for (iter = priv->sources; iter; iter = iter->next) { + g_source_destroy (iter->data); + g_source_unref (iter->data); + } + g_clear_pointer (&priv->sources, g_slist_free); G_OBJECT_CLASS (soup_session_async_parent_class)->dispose (object); } @@ -359,12 +367,17 @@ static gboolean idle_run_queue (gpointer user_data) { SoupSessionAsyncPrivate *priv = user_data; + GSource *source; if (priv->disposed) return FALSE; + source = g_main_current_source (); + priv->sources = g_slist_remove (priv->sources, source); + /* Ensure that the source is destroyed before running the queue */ - g_source_destroy (g_main_current_source ()); + g_source_destroy (source); + g_source_unref (source); run_queue (priv->sa); return FALSE; @@ -389,7 +402,8 @@ do_idle_run_queue (SoupSession *session) if (source) return; - source = soup_add_completion (async_context, idle_run_queue, priv); + source = soup_add_completion_reffed (async_context, idle_run_queue, priv); + priv->sources = g_slist_prepend (priv->sources, source); } static void -- cgit v1.2.1 From 1be85dff7bd44741595060238f432630d0ed338b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 12 Aug 2012 10:43:01 -0400 Subject: SoupSession: make queue items hold a ref on the session Historically, messages sent via soup_session_queue_message() did not hold a ref on the session, and unreffing the session when messages were in progress would cancel them. This is ugly internally though, and at any rate, depends on being able to know for sure that no one else is secretly holding a ref on the session. So, fix it so that pending messages hold a ref on the session, and you need to use soup_session_abort() before unreffing if you want to cancel everything. If it turns out that this breaks things it can be reverted before 2.40... --- libsoup/soup-message-queue.c | 3 ++- libsoup/soup-session-async.c | 9 ++------- libsoup/soup-session-sync.c | 6 +----- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index 8ef129a9..e4640358 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -101,7 +101,7 @@ soup_message_queue_append (SoupMessageQueue *queue, SoupMessage *msg, SoupMessageQueueItem *item; item = g_slice_new0 (SoupMessageQueueItem); - item->session = queue->session; + item->session = g_object_ref (queue->session); item->async_context = soup_session_get_async_context (item->session); item->queue = queue; item->msg = g_object_ref (msg); @@ -178,6 +178,7 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) /* And free it */ g_signal_handlers_disconnect_by_func (item->msg, queue_message_restarted, item); + g_object_unref (item->session); g_object_unref (item->msg); g_object_unref (item->cancellable); if (item->proxy_addr) diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 0f365f38..6c8e1821 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -140,7 +140,6 @@ tunnel_complete (SoupMessageQueueItem *item) soup_message_queue_item_unref (item->related); soup_session_unqueue_item (session, item); soup_message_queue_item_unref (item); - g_object_unref (session); } static void @@ -210,7 +209,6 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) soup_connection_disconnect (conn); do_idle_run_queue (session); soup_message_queue_item_unref (item); - g_object_unref (session); return; } @@ -229,7 +227,6 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) do_idle_run_queue (session); soup_message_queue_item_unref (item); - g_object_unref (session); return; } @@ -249,7 +246,6 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) G_CALLBACK (connection_closed), session); run_queue ((SoupSessionAsync *)session); soup_message_queue_item_unref (item); - g_object_unref (session); } static void @@ -282,7 +278,6 @@ process_queue_item (SoupMessageQueueItem *item, item->state = SOUP_MESSAGE_CONNECTING; soup_message_queue_item_ref (item); - g_object_ref (session); soup_connection_connect_async (item->conn, item->cancellable, got_connection, item); return; @@ -307,14 +302,14 @@ process_queue_item (SoupMessageQueueItem *item, if (item->state != SOUP_MESSAGE_FINISHED) break; - g_object_ref (session); + soup_message_queue_item_ref (item); soup_session_unqueue_item (session, item); if (item->callback) item->callback (session, item->msg, item->callback_data); else if (item->new_api) send_request_finished (session, item); do_idle_run_queue (session); - g_object_unref (session); + soup_message_queue_item_unref (item); return; default: diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index 96ab9165..81410c57 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -297,7 +297,6 @@ queue_message_callback (gpointer data) SoupMessageQueueItem *item = data; item->callback (item->session, item->msg, item->callback_data); - g_object_unref (item->session); soup_message_queue_item_unref (item); return FALSE; } @@ -311,10 +310,8 @@ queue_message_thread (gpointer data) if (item->callback) { soup_add_completion (soup_session_get_async_context (item->session), queue_message_callback, item); - } else { - g_object_unref (item->session); + } else soup_message_queue_item_unref (item); - } return NULL; } @@ -326,7 +323,6 @@ soup_session_sync_queue_message (SoupSession *session, SoupMessage *msg, SoupMessageQueueItem *item; GThread *thread; - g_object_ref (session); item = soup_session_append_queue_item (session, msg, callback, user_data); thread = g_thread_new ("SoupSessionSync:queue_message", queue_message_thread, item); -- cgit v1.2.1 From be2e90dfc807da9a2b7fefd64d23894378342946 Mon Sep 17 00:00:00 2001 From: Sayak Sarkar Date: Tue, 14 Aug 2012 16:11:39 +0530 Subject: Added Bengali India Translations --- po/bn_IN.po | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 po/bn_IN.po diff --git a/po/bn_IN.po b/po/bn_IN.po new file mode 100644 index 00000000..92326785 --- /dev/null +++ b/po/bn_IN.po @@ -0,0 +1,75 @@ +# Bengali (India) translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Sayak Sarkar , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-08-12 00:04+0000\n" +"PO-Revision-Date: 2012-08-02 19:33+0530\n" +"Last-Translator: Sayak Sarkar \n" +"Language-Team: Bengali (India) \n" +"Language: bn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.4\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "সংযোগ অপ্রত্যাশিতভাবে পর্যবসিত" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "আউটপুট বাফার অত্যন্ত ছোট" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "অপারেশন বাতিল হয়েছে" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "অপারেশন ব্লক করবে" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "কোন URI দেওয়া হয়নি" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "অবৈধ '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' পার্স করা যায়নি" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "অসমর্থিত URI স্কিম '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "হোস্টনেমটি একটি IP অ্যাড্রেস" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "অবৈধ হোস্টনেম" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "হোস্টনেমটির কোনো বেস ডোমেইন নেই" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "ডোমেইনগুলি পর্যাপ্ত নয়" -- cgit v1.2.1 From df14f731c1e1823ed690344a32f5de3896a47225 Mon Sep 17 00:00:00 2001 From: Runa Bhattacharjee Date: Tue, 14 Aug 2012 16:12:38 +0530 Subject: Added Entry for Bengali India and fixed a wrong sequence in the list --- po/LINGUAS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/po/LINGUAS b/po/LINGUAS index 95d1c991..39e493dc 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1,6 +1,7 @@ as -bg be +bg +bn_IN de el eo -- cgit v1.2.1 From 90bc8b050ec2b925947d2ff5ed82748f619ddd0b Mon Sep 17 00:00:00 2001 From: Chao-Hsiung Liao Date: Wed, 15 Aug 2012 15:13:22 +0800 Subject: Updated Traditional Chinese translation(Hong Kong and Taiwan) --- po/zh_HK.po | 22 +++++++++++++--------- po/zh_TW.po | 22 +++++++++++++--------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/po/zh_HK.po b/po/zh_HK.po index 817d6d65..5f7e253d 100644 --- a/po/zh_HK.po +++ b/po/zh_HK.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-16 08:47+0800\n" -"PO-Revision-Date: 2012-07-16 08:48+0800\n" +"POT-Creation-Date: 2012-08-15 15:13+0800\n" +"PO-Revision-Date: 2012-08-15 15:13+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: Chinese (Hong Kong) \n" "Language: zh_TW\n" @@ -18,20 +18,20 @@ msgstr "" #: ../libsoup/soup-body-input-stream.c:136 #: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:193 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "連線無預警的關閉了" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "輸出緩衝區太小" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "操作已被取消" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "操作會阻擋" @@ -55,14 +55,18 @@ msgstr "無法解析 URI「%s」" msgid "Unsupported URI scheme '%s'" msgstr "不支援的 URI scheme「%s」" -#: ../libsoup/soup-tld.c:146 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "主機名稱是 IP 位址" -#: ../libsoup/soup-tld.c:167 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "主機名稱無效" -#: ../libsoup/soup-tld.c:182 ../libsoup/soup-tld.c:220 +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "主機名稱沒有基礎網域" + +#: ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "沒有足夠的網域" diff --git a/po/zh_TW.po b/po/zh_TW.po index f71178d8..20387341 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-16 08:47+0800\n" -"PO-Revision-Date: 2012-07-14 11:47+0800\n" +"POT-Creation-Date: 2012-08-15 15:13+0800\n" +"PO-Revision-Date: 2012-08-15 14:52+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: Chinese (Taiwan) \n" "Language: zh_TW\n" @@ -18,20 +18,20 @@ msgstr "" #: ../libsoup/soup-body-input-stream.c:136 #: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:193 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "連線無預警的關閉了" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "輸出緩衝區太小" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "操作已被取消" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "操作會阻擋" @@ -55,14 +55,18 @@ msgstr "無法解析 URI「%s」" msgid "Unsupported URI scheme '%s'" msgstr "不支援的 URI scheme「%s」" -#: ../libsoup/soup-tld.c:146 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "主機名稱是 IP 位址" -#: ../libsoup/soup-tld.c:167 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "主機名稱無效" -#: ../libsoup/soup-tld.c:182 ../libsoup/soup-tld.c:220 +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "主機名稱沒有基礎網域" + +#: ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "沒有足夠的網域" -- cgit v1.2.1 From 88e6a55529726afec295c47b89100c87f52bc121 Mon Sep 17 00:00:00 2001 From: Daniel Korostil Date: Fri, 17 Aug 2012 08:19:28 +0300 Subject: Added uk translation --- po/LINGUAS | 1 + po/uk.po | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 po/uk.po diff --git a/po/LINGUAS b/po/LINGUAS index 39e493dc..4b85ad26 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -23,6 +23,7 @@ sr sr@latin te tr +uk vi zh_CN zh_HK diff --git a/po/uk.po b/po/uk.po new file mode 100644 index 00000000..9f91f666 --- /dev/null +++ b/po/uk.po @@ -0,0 +1,76 @@ +# Ukrainian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Daniel , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-08-15 07:13+0000\n" +"PO-Revision-Date: 2012-08-16 00:51-0700\n" +"Last-Translator: Daniel \n" +"Language-Team: translation@linux.org.ua\n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" +"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Virtaal 0.7.0\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Несподівано зв'язок розірвано" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Вихідний буфер надто малий" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Операцію скасовано" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Операція заблокує" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Не надано URI" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Неправильний «%s» URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Неможливо розібрати URI «%s»" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Непідтримувана схема URI «%s»" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Назва вузла — адреса IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Неправильна назва вузла" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Назва вузла не містить базового домену" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Не вистачає доменів" -- cgit v1.2.1 From 0d51bcfe06177025e235f860c75275744337739c Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 13 Aug 2012 14:27:02 +0200 Subject: SoupMessage: Add SOUP_MESSAGE_IDEMPOTENT flag In particular, this lets the app indicate that it's OK to use an existing connection when sending a POST. https://bugzilla.gnome.org/show_bug.cgi?id=681493 --- libsoup/soup-message.c | 7 ++++++- libsoup/soup-message.h | 3 ++- libsoup/soup-session.c | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 3e1112e1..2271cd0a 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1453,7 +1453,12 @@ soup_message_cleanup_response (SoupMessage *req) * @SOUP_MESSAGE_NEW_CONNECTION: The message should be sent on a * newly-created connection, not reusing an existing persistent * connection. Note that messages with non-idempotent - * #SoupMessage:methods behave this way by default. + * #SoupMessage:methods behave this way by default, + * unless #SOUP_MESSAGE_IDEMPOTENT is set. + * @SOUP_MESSAGE_IDEMPOTENT: The message is considered idempotent, + * regardless its #SoupMessage:method, and allows reuse of existing + * idle connections, instead of always requiring a new one, unless + * #SOUP_MESSAGE_NEW_CONNECTION is set. * * Various flags that can be set on a #SoupMessage to alter its * behavior. diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index d3c7e3c5..d74ee131 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -119,7 +119,8 @@ typedef enum { #endif SOUP_MESSAGE_CONTENT_DECODED = (1 << 4), SOUP_MESSAGE_CERTIFICATE_TRUSTED = (1 << 5), - SOUP_MESSAGE_NEW_CONNECTION = (1 << 6) + SOUP_MESSAGE_NEW_CONNECTION = (1 << 6), + SOUP_MESSAGE_IDEMPOTENT = (1 << 7) } SoupMessageFlags; void soup_message_set_flags (SoupMessage *msg, diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 7b68d427..90e91893 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1207,7 +1207,8 @@ soup_session_get_connection (SoupSession *session, need_new_connection = (soup_message_get_flags (item->msg) & SOUP_MESSAGE_NEW_CONNECTION) || - !SOUP_METHOD_IS_IDEMPOTENT (item->msg->method); + (!(soup_message_get_flags (item->msg) & SOUP_MESSAGE_IDEMPOTENT) && + !SOUP_METHOD_IS_IDEMPOTENT (item->msg->method)); g_mutex_lock (&priv->conn_lock); -- cgit v1.2.1 From 1b812ae1a0ad1fde1befa887c16954b5ee0e5d1c Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 20 Aug 2012 10:42:18 +0200 Subject: SoupContentSniffer: removed several unused function arguments Removed the SoupMessage argument from various sniffing functions as it isn't really used for sniffing. https://bugzilla.gnome.org/show_bug.cgi?id=682112 --- libsoup/soup-content-sniffer.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index b5fd125e..0986bbe3 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -185,8 +185,8 @@ static char byte_looks_binary[] = { /* HTML5: 2.7.4 Content-Type sniffing: unknown type */ static char* -sniff_unknown (SoupContentSniffer *sniffer, SoupMessage *msg, - SoupBuffer *buffer, gboolean for_text_or_binary) +sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer, + gboolean for_text_or_binary) { const guchar *resource = (const guchar *)buffer->data; int resource_length = MIN (512, buffer->length); @@ -262,8 +262,7 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupMessage *msg, /* HTML5: 2.7.3 Content-Type sniffing: text or binary */ static char* -sniff_text_or_binary (SoupContentSniffer *sniffer, SoupMessage *msg, - SoupBuffer *buffer) +sniff_text_or_binary (SoupContentSniffer *sniffer, SoupBuffer *buffer) { const guchar *resource = (const guchar *)buffer->data; int resource_length = MIN (512, buffer->length); @@ -289,12 +288,12 @@ sniff_text_or_binary (SoupContentSniffer *sniffer, SoupMessage *msg, if (!looks_binary) return g_strdup ("text/plain"); - return sniff_unknown (sniffer, msg, buffer, TRUE); + return sniff_unknown (sniffer, buffer, TRUE); } static char* -sniff_images (SoupContentSniffer *sniffer, SoupMessage *msg, - SoupBuffer *buffer, const char *content_type) +sniff_images (SoupContentSniffer *sniffer, SoupBuffer *buffer, + const char *content_type) { const guchar *resource = (const guchar *)buffer->data; int resource_length = MIN (512, buffer->length); @@ -320,7 +319,7 @@ sniff_images (SoupContentSniffer *sniffer, SoupMessage *msg, } static char* -sniff_feed_or_html (SoupContentSniffer *sniffer, SoupMessage *msg, SoupBuffer *buffer) +sniff_feed_or_html (SoupContentSniffer *sniffer, SoupBuffer *buffer) { const guchar *resource = (const guchar *)buffer->data; int resource_length = MIN (512, buffer->length); @@ -442,7 +441,7 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, !g_ascii_strcasecmp (content_type, "unknown/unknown") || !g_ascii_strcasecmp (content_type, "application/unknown") || !g_ascii_strcasecmp (content_type, "*/*")) - return sniff_unknown (sniffer, msg, buffer, FALSE); + return sniff_unknown (sniffer, buffer, FALSE); if (g_str_has_suffix (content_type, "+xml") || !g_ascii_strcasecmp (content_type, "text/xml") || @@ -460,15 +459,15 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, * this code, keep this in mind. */ if (!g_ascii_strncasecmp (content_type, "image/", 6)) - return sniff_images (sniffer, msg, buffer, content_type); + return sniff_images (sniffer, buffer, content_type); /* If we got text/plain, use text_or_binary */ if (g_str_equal (content_type, "text/plain")) { - return sniff_text_or_binary (sniffer, msg, buffer); + return sniff_text_or_binary (sniffer, buffer); } if (!g_ascii_strcasecmp (content_type, "text/html")) - return sniff_feed_or_html (sniffer, msg, buffer); + return sniff_feed_or_html (sniffer, buffer); return g_strdup (content_type); } -- cgit v1.2.1 From 6d370df18ac14a167a677ea66bfd02883b571b18 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 20 Aug 2012 10:43:56 +0200 Subject: SoupContentSnifferStream: added can_poll() implementation Done in terms of the base_stream can_poll() interface. It was not needed to read resources from network as the underlying streams were all pollable. This will be used later to sniff locally cached resources. The file streams are not pollable so we must implement the can_poll() in order to use "normal" read() calls instead of the read_nonblocking(). https://bugzilla.gnome.org/show_bug.cgi?id=682112 --- libsoup/soup-content-sniffer-stream.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libsoup/soup-content-sniffer-stream.c b/libsoup/soup-content-sniffer-stream.c index 42e92476..173f9021 100644 --- a/libsoup/soup-content-sniffer-stream.c +++ b/libsoup/soup-content-sniffer-stream.c @@ -232,6 +232,16 @@ soup_content_sniffer_stream_skip (GInputStream *stream, return nskipped; } +static gboolean +soup_content_sniffer_stream_can_poll (GPollableInputStream *pollable) +{ + GInputStream *base_stream = G_FILTER_INPUT_STREAM (pollable)->base_stream; + + return G_IS_POLLABLE_INPUT_STREAM (base_stream) && + g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (base_stream)); +} + + static gboolean soup_content_sniffer_stream_is_readable (GPollableInputStream *stream) { @@ -320,6 +330,7 @@ static void soup_content_sniffer_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data) { + pollable_interface->can_poll = soup_content_sniffer_stream_can_poll; pollable_interface->is_readable = soup_content_sniffer_stream_is_readable; pollable_interface->read_nonblocking = soup_content_sniffer_stream_read_nonblocking; pollable_interface->create_source = soup_content_sniffer_stream_create_source; -- cgit v1.2.1 From 93ce2c030c0b2870f63dd2ccd489cc9f317e2962 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 20 Aug 2012 11:57:09 +0200 Subject: SoupCache: simplify the usage of soup_cache_entry_remove()/free() Added a new parameter to soup_cache_entry_remove() that instructs the function to delete the cached resource file if TRUE. It also unconditionally frees the resources allocated by the entry by calling soup_cache_entry_free(). https://bugzilla.gnome.org/show_bug.cgi?id=681509 --- libsoup/soup-cache.c | 65 ++++++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 8b26478d..9b6bfe2e 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -120,7 +120,7 @@ G_DEFINE_TYPE_WITH_CODE (SoupCache, soup_cache, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, soup_cache_session_feature_init)) -static gboolean soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry); +static gboolean soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry, gboolean purge); static void make_room_for_new_entry (SoupCache *cache, guint length_to_add); static gboolean cache_accepts_entries_of_size (SoupCache *cache, guint length_to_add); static gboolean write_next_buffer (SoupCacheEntry *entry, SoupCacheWritingFixture *fixture); @@ -260,13 +260,8 @@ get_cacheability (SoupCache *cache, SoupMessage *msg) * and also unref's the GFile object representing it. */ static void -soup_cache_entry_free (SoupCacheEntry *entry, GFile *file) +soup_cache_entry_free (SoupCacheEntry *entry) { - if (file) { - g_file_delete (file, NULL, NULL); - g_object_unref (file); - } - g_free (entry->uri); g_clear_pointer (&entry->current_writing_buffer, soup_buffer_free); g_clear_pointer (&entry->headers, soup_message_headers_free); @@ -540,8 +535,7 @@ close_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture * too much for the cache */ if (g_cancellable_is_cancelled (entry->cancellable)) { entry->dirty = FALSE; - soup_cache_entry_remove (cache, entry); - soup_cache_entry_free (entry, get_file_from_entry (cache, entry)); + soup_cache_entry_remove (cache, entry, TRUE); entry = NULL; } else if ((soup_message_headers_get_encoding (entry->headers) == SOUP_ENCODING_CHUNKED) || entry->length != (gsize) content_length) { @@ -567,8 +561,7 @@ close_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture * cache->priv->size += length_to_add; } else { entry->dirty = FALSE; - soup_cache_entry_remove (cache, entry); - soup_cache_entry_free (entry, get_file_from_entry (cache, entry)); + soup_cache_entry_remove (cache, entry, TRUE); entry = NULL; } } @@ -720,7 +713,7 @@ msg_got_body_cb (SoupMessage *msg, SoupCacheWritingFixture *fixture) } static gboolean -soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry) +soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry, gboolean purge) { GList *lru_item; @@ -745,6 +738,14 @@ soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry) g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache)); + /* Free resources */ + if (purge) { + GFile *file = get_file_from_entry (cache, entry); + g_file_delete (file, NULL, NULL); + g_object_unref (file); + } + soup_cache_entry_free (entry); + return TRUE; } @@ -803,10 +804,9 @@ make_room_for_new_entry (SoupCache *cache, guint length_to_add) /* Discard entries. Once cancelled resources will be * freed in close_ready_cb */ - if (soup_cache_entry_remove (cache, old_entry)) { - soup_cache_entry_free (old_entry, get_file_from_entry (cache, old_entry)); + if (soup_cache_entry_remove (cache, old_entry, TRUE)) lru_entry = cache->priv->lru_start; - } else + else lru_entry = g_list_next (lru_entry); } } @@ -836,9 +836,7 @@ soup_cache_entry_insert (SoupCache *cache, /* Remove any previous entry */ if ((old_entry = g_hash_table_lookup (cache->priv->cache, GUINT_TO_POINTER (entry->key))) != NULL) { - if (soup_cache_entry_remove (cache, old_entry)) - soup_cache_entry_free (old_entry, get_file_from_entry (cache, old_entry)); - else + if (!soup_cache_entry_remove (cache, old_entry, TRUE)) return FALSE; } @@ -897,8 +895,7 @@ replace_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture *fixt g_object_unref (stream); fixture->cache->priv->n_pending--; entry->dirty = FALSE; - soup_cache_entry_remove (fixture->cache, entry); - soup_cache_entry_free (entry, get_file_from_entry (fixture->cache, entry)); + soup_cache_entry_remove (fixture->cache, entry, TRUE); soup_cache_writing_fixture_free (fixture); return; } @@ -959,17 +956,15 @@ msg_got_headers_cb (SoupMessage *msg, gpointer user_data) return; /* Create a new entry, deleting any old one if present */ - if (entry) { - soup_cache_entry_remove (cache, entry); - soup_cache_entry_free (entry, get_file_from_entry (cache, entry)); - } + if (entry) + soup_cache_entry_remove (cache, entry, TRUE); entry = soup_cache_entry_new (cache, msg, request_time, response_time); entry->hits = 1; /* Do not continue if it can not be stored */ if (!soup_cache_entry_insert (cache, entry, TRUE)) { - soup_cache_entry_free (entry, get_file_from_entry (cache, entry)); + soup_cache_entry_free (entry); return; } @@ -1004,10 +999,8 @@ msg_got_headers_cb (SoupMessage *msg, gpointer user_data) } else if (cacheable & SOUP_CACHE_INVALIDATES) { entry = soup_cache_entry_lookup (cache, msg); - if (entry) { - if (soup_cache_entry_remove (cache, entry)) - soup_cache_entry_free (entry, get_file_from_entry (cache, entry)); - } + if (entry) + soup_cache_entry_remove (cache, entry, TRUE); } else if (cacheable & SOUP_CACHE_VALIDATES) { entry = soup_cache_entry_lookup (cache, msg); @@ -1127,11 +1120,7 @@ static void remove_cache_item (gpointer data, gpointer user_data) { - SoupCache *cache = (SoupCache *) user_data; - SoupCacheEntry *entry = (SoupCacheEntry *) data; - - if (soup_cache_entry_remove (cache, entry)) - soup_cache_entry_free (entry, NULL); + soup_cache_entry_remove ((SoupCache *) user_data, (SoupCacheEntry *) data, FALSE); } static void @@ -1502,11 +1491,7 @@ static void clear_cache_item (gpointer data, gpointer user_data) { - SoupCache *cache = (SoupCache *) user_data; - SoupCacheEntry *entry = (SoupCacheEntry *) data; - - if (soup_cache_entry_remove (cache, entry)) - soup_cache_entry_free (entry, get_file_from_entry (cache, entry)); + soup_cache_entry_remove ((SoupCache *) user_data, (SoupCacheEntry *) data, TRUE); } /** @@ -1741,7 +1726,7 @@ soup_cache_load (SoupCache *cache) entry->status_code = status_code; if (!soup_cache_entry_insert (cache, entry, FALSE)) - soup_cache_entry_free (entry, get_file_from_entry (cache, entry)); + soup_cache_entry_free (entry); } cache->priv->lru_start = g_list_reverse (cache->priv->lru_start); -- cgit v1.2.1 From a90a9a536c8ca0aaa6e1fda50b78f5234dd66afb Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 20 Aug 2012 12:22:17 +0200 Subject: SoupCache: moved data from SoupCacheEntry to the writing fixture The entry fields "current_writing_buffer", "got_body", "stream", and "error" where only used during the writing phase. Therefore we do not need to keep all of them in memory in the SoupCacheEntry structure. https://bugzilla.gnome.org/show_bug.cgi?id=681509 --- libsoup/soup-cache.c | 83 +++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 9b6bfe2e..345d5bb9 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -73,13 +73,9 @@ typedef struct _SoupCacheEntry { gsize length; guint32 corrected_initial_age; guint32 response_time; - SoupBuffer *current_writing_buffer; gboolean dirty; - gboolean got_body; gboolean being_validated; SoupMessageHeaders *headers; - GOutputStream *stream; - GError *error; guint32 hits; GCancellable *cancellable; guint16 status_code; @@ -106,6 +102,10 @@ typedef struct { gulong got_body_handler; gulong restarted_handler; GQueue *buffer_queue; + gboolean got_body; + SoupBuffer *current_writing_buffer; + GError *error; + GOutputStream *ostream; } SoupCacheWritingFixture; enum { @@ -263,9 +263,7 @@ static void soup_cache_entry_free (SoupCacheEntry *entry) { g_free (entry->uri); - g_clear_pointer (&entry->current_writing_buffer, soup_buffer_free); g_clear_pointer (&entry->headers, soup_message_headers_free); - g_clear_error (&entry->error); g_clear_object (&entry->cancellable); g_slice_free (SoupCacheEntry, entry); @@ -437,10 +435,7 @@ soup_cache_entry_new (SoupCache *cache, SoupMessage *msg, time_t request_time, t entry = g_slice_new0 (SoupCacheEntry); entry->dirty = FALSE; - entry->current_writing_buffer = NULL; - entry->got_body = FALSE; entry->being_validated = FALSE; - entry->error = NULL; entry->status_code = msg->status_code; entry->response_time = response_time; entry->uri = soup_uri_to_string (soup_message_get_uri (msg), FALSE); @@ -497,6 +492,9 @@ soup_cache_writing_fixture_free (SoupCacheWritingFixture *fixture) g_signal_handler_disconnect (fixture->msg, fixture->got_body_handler); if (g_signal_handler_is_connected (fixture->msg, fixture->restarted_handler)) g_signal_handler_disconnect (fixture->msg, fixture->restarted_handler); + g_clear_pointer (&fixture->current_writing_buffer, soup_buffer_free); + g_clear_object (&fixture->ostream); + g_clear_error (&fixture->error); g_queue_foreach (fixture->buffer_queue, (GFunc) soup_buffer_free, NULL); g_queue_free (fixture->buffer_queue); g_object_unref (fixture->msg); @@ -518,7 +516,7 @@ close_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture * GOutputStream *stream = G_OUTPUT_STREAM (source); goffset content_length; - g_warn_if_fail (entry->error == NULL); + g_warn_if_fail (fixture->error == NULL); /* FIXME: what do we do on error ? */ @@ -526,7 +524,7 @@ close_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture * g_output_stream_close_finish (stream, result, NULL); g_object_unref (stream); } - entry->stream = NULL; + fixture->ostream = NULL; content_length = soup_message_headers_get_content_length (entry->headers); @@ -568,15 +566,10 @@ close_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture * if (entry) { entry->dirty = FALSE; - entry->got_body = FALSE; - - if (entry->current_writing_buffer) { - soup_buffer_free (entry->current_writing_buffer); - entry->current_writing_buffer = NULL; - } + fixture->got_body = FALSE; - g_object_unref (entry->cancellable); - entry->cancellable = NULL; + g_clear_pointer (&fixture->current_writing_buffer, soup_buffer_free); + g_clear_object (&entry->cancellable); } cache->priv->n_pending--; @@ -589,7 +582,6 @@ static void write_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture *fixture) { GOutputStream *stream = G_OUTPUT_STREAM (source); - GError *error = NULL; gssize write_size; SoupCacheEntry *entry = fixture->entry; @@ -602,10 +594,8 @@ write_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture * return; } - write_size = g_output_stream_write_finish (stream, result, &error); - if (write_size <= 0 || error) { - if (error) - entry->error = error; + write_size = g_output_stream_write_finish (stream, result, &fixture->error); + if (write_size <= 0 || fixture->error) { g_output_stream_close_async (stream, G_PRIORITY_LOW, entry->cancellable, @@ -619,14 +609,13 @@ write_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture * if (fixture->buffer_queue->length > 0) write_next_buffer (entry, fixture); else { - soup_buffer_free (entry->current_writing_buffer); - entry->current_writing_buffer = NULL; + g_clear_pointer (&fixture->current_writing_buffer, soup_buffer_free); - if (entry->got_body) { + if (fixture->got_body) { /* If we already received 'got-body' and we have written all the data, we can close the stream */ - g_output_stream_close_async (entry->stream, + g_output_stream_close_async (fixture->ostream, G_PRIORITY_LOW, entry->cancellable, (GAsyncReadyCallback)close_ready_cb, @@ -645,13 +634,10 @@ write_next_buffer (SoupCacheEntry *entry, SoupCacheWritingFixture *fixture) return FALSE; /* Free the old buffer */ - if (entry->current_writing_buffer) { - soup_buffer_free (entry->current_writing_buffer); - entry->current_writing_buffer = NULL; - } - entry->current_writing_buffer = buffer; + g_clear_pointer (&fixture->current_writing_buffer, soup_buffer_free); + fixture->current_writing_buffer = buffer; - g_output_stream_write_async (entry->stream, buffer->data, buffer->length, + g_output_stream_write_async (fixture->ostream, buffer->data, buffer->length, G_PRIORITY_LOW, entry->cancellable, (GAsyncReadyCallback) write_ready_cb, fixture); @@ -677,7 +663,7 @@ msg_got_chunk_cb (SoupMessage *msg, SoupBuffer *chunk, SoupCacheWritingFixture * /* FIXME: remove the error check when we cancel the caching at the first write error */ /* Only write if the entry stream is ready */ - if (entry->current_writing_buffer == NULL && entry->error == NULL && entry->stream) + if (fixture->current_writing_buffer == NULL && fixture->error == NULL && fixture->ostream) write_next_buffer (entry, fixture); } @@ -687,9 +673,9 @@ msg_got_body_cb (SoupMessage *msg, SoupCacheWritingFixture *fixture) SoupCacheEntry *entry = fixture->entry; g_return_if_fail (entry); - entry->got_body = TRUE; + fixture->got_body = TRUE; - if (!entry->stream && fixture->buffer_queue->length > 0) + if (!fixture->ostream && fixture->buffer_queue->length > 0) /* The stream is not ready to be written but we still have data to write, we'll write it when the stream is opened for writing */ @@ -699,13 +685,13 @@ msg_got_body_cb (SoupMessage *msg, SoupCacheWritingFixture *fixture) if (fixture->buffer_queue->length > 0) { /* If we still have data to write, write it, write_ready_cb will close the stream */ - if (entry->current_writing_buffer == NULL && entry->error == NULL && entry->stream) + if (fixture->current_writing_buffer == NULL && fixture->error == NULL && fixture->ostream) write_next_buffer (entry, fixture); return; } - if (entry->stream && entry->current_writing_buffer == NULL) - g_output_stream_close_async (entry->stream, + if (fixture->ostream && fixture->current_writing_buffer == NULL) + g_output_stream_close_async (fixture->ostream, G_PRIORITY_LOW, entry->cancellable, (GAsyncReadyCallback)close_ready_cb, @@ -887,12 +873,11 @@ static void replace_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture *fixture) { SoupCacheEntry *entry = fixture->entry; - GOutputStream *stream = (GOutputStream *) g_file_replace_finish (G_FILE (source), - result, &entry->error); + GOutputStream *ostream = (GOutputStream *) g_file_replace_finish (G_FILE (source), + result, &fixture->error); - if (g_cancellable_is_cancelled (entry->cancellable) || entry->error) { - if (stream) - g_object_unref (stream); + if (g_cancellable_is_cancelled (entry->cancellable) || fixture->error) { + g_clear_object (&ostream); fixture->cache->priv->n_pending--; entry->dirty = FALSE; soup_cache_entry_remove (fixture->cache, entry, TRUE); @@ -900,13 +885,13 @@ replace_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture *fixt return; } - entry->stream = stream; + fixture->ostream = ostream; /* If we already got all the data we have to initiate the * writing here, since we won't get more 'got-chunk' * signals */ - if (!entry->got_body) + if (!fixture->got_body) return; /* It could happen that reading the data from server @@ -915,7 +900,7 @@ replace_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture *fixt */ if (!write_next_buffer (entry, fixture)) /* Could happen if the resource is empty */ - g_output_stream_close_async (stream, G_PRIORITY_LOW, entry->cancellable, + g_output_stream_close_async (ostream, G_PRIORITY_LOW, entry->cancellable, (GAsyncReadyCallback) close_ready_cb, fixture); } @@ -1582,7 +1567,7 @@ pack_entry (gpointer data, GVariantBuilder *entries_builder = (GVariantBuilder *)user_data; /* Do not store non-consolidated entries */ - if (entry->dirty || entry->current_writing_buffer != NULL || !entry->key) + if (entry->dirty || !entry->key) return; g_variant_builder_open (entries_builder, G_VARIANT_TYPE (SOUP_CACHE_PHEADERS_FORMAT)); -- cgit v1.2.1 From 2376ff2b60705b0f09194a818aed8b26608c652c Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 20 Aug 2012 12:26:19 +0200 Subject: SoupCache: delete untracked files in soup_cache_clear() Delete all the files in the cache directory when clearing the cache even if they aren't coupled with any cache entry. https://bugzilla.gnome.org/show_bug.cgi?id=681509 --- libsoup/soup-cache.c | 79 +++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 345d5bb9..51abbe56 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -65,6 +65,19 @@ static void soup_cache_session_feature_init (SoupSessionFeatureInterface *featur */ #define SOUP_CACHE_CURRENT_VERSION 5 +#define OLD_SOUP_CACHE_FILE "soup.cache" +#define SOUP_CACHE_FILE "soup.cache2" + +#define SOUP_CACHE_HEADERS_FORMAT "{ss}" +#define SOUP_CACHE_PHEADERS_FORMAT "(sbuuuuuqa" SOUP_CACHE_HEADERS_FORMAT ")" +#define SOUP_CACHE_ENTRIES_FORMAT "(qa" SOUP_CACHE_PHEADERS_FORMAT ")" + +/* Basically the same format than above except that some strings are + prepended with &. This way the GVariant returns a pointer to the + data instead of duplicating the string */ +#define SOUP_CACHE_DECODE_HEADERS_FORMAT "{&s&s}" + + typedef struct _SoupCacheEntry { guint32 key; char *uri; @@ -1479,12 +1492,35 @@ clear_cache_item (gpointer data, soup_cache_entry_remove ((SoupCache *) user_data, (SoupCacheEntry *) data, TRUE); } +static void +clear_cache_files (SoupCache *cache) +{ + GFileInfo *file_info; + GFileEnumerator *file_enumerator; + GFile *cache_dir_file = g_file_new_for_path (cache->priv->cache_dir); + + file_enumerator = g_file_enumerate_children (cache_dir_file, G_FILE_ATTRIBUTE_STANDARD_NAME, + G_FILE_QUERY_INFO_NONE, NULL, NULL); + if (file_enumerator) { + while ((file_info = g_file_enumerator_next_file (file_enumerator, NULL, NULL)) != NULL) { + const char *filename = g_file_info_get_name (file_info); + + if (strcmp (filename, SOUP_CACHE_FILE) != 0) { + GFile *cache_file = g_file_get_child (cache_dir_file, filename); + g_file_delete (cache_file, NULL, NULL); + g_object_unref (cache_file); + } + } + g_object_unref (file_enumerator); + } + g_object_unref (cache_dir_file); +} + /** * soup_cache_clear: * @cache: a #SoupCache * - * Will remove all entries in the @cache plus all the cache files - * associated with them. + * Will remove all entries in the @cache plus all the cache files. * * Since: 2.34 */ @@ -1500,6 +1536,9 @@ soup_cache_clear (SoupCache *cache) entries = g_hash_table_get_values (cache->priv->cache); g_list_foreach (entries, clear_cache_item, cache); g_list_free (entries); + + /* Remove also any file not associated with a cache entry. */ + clear_cache_files (cache); } SoupMessage * @@ -1545,18 +1584,6 @@ soup_cache_generate_conditional_request (SoupCache *cache, SoupMessage *original return msg; } -#define OLD_SOUP_CACHE_FILE "soup.cache" -#define SOUP_CACHE_FILE "soup.cache2" - -#define SOUP_CACHE_HEADERS_FORMAT "{ss}" -#define SOUP_CACHE_PHEADERS_FORMAT "(sbuuuuuqa" SOUP_CACHE_HEADERS_FORMAT ")" -#define SOUP_CACHE_ENTRIES_FORMAT "(qa" SOUP_CACHE_PHEADERS_FORMAT ")" - -/* Basically the same format than above except that some strings are - prepended with &. This way the GVariant returns a pointer to the - data instead of duplicating the string */ -#define SOUP_CACHE_DECODE_HEADERS_FORMAT "{&s&s}" - static void pack_entry (gpointer data, gpointer user_data) @@ -1620,30 +1647,6 @@ soup_cache_dump (SoupCache *cache) g_variant_unref (cache_variant); } -static void -clear_cache_files (SoupCache *cache) -{ - GFileInfo *file_info; - GFileEnumerator *file_enumerator; - GFile *cache_dir_file = g_file_new_for_path (cache->priv->cache_dir); - - file_enumerator = g_file_enumerate_children (cache_dir_file, G_FILE_ATTRIBUTE_STANDARD_NAME, - G_FILE_QUERY_INFO_NONE, NULL, NULL); - if (file_enumerator) { - while ((file_info = g_file_enumerator_next_file (file_enumerator, NULL, NULL)) != NULL) { - const char *filename = g_file_info_get_name (file_info); - - if (strcmp (filename, SOUP_CACHE_FILE) != 0) { - GFile *cache_file = g_file_get_child (cache_dir_file, filename); - g_file_delete (cache_file, NULL, NULL); - g_object_unref (cache_file); - } - } - g_object_unref (file_enumerator); - } - g_object_unref (cache_dir_file); -} - void soup_cache_load (SoupCache *cache) { -- cgit v1.2.1 From 207b8aa56d272e20d5d3e052753e15b8fb43214f Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Mon, 20 Aug 2012 10:37:41 -0300 Subject: Make it possibe to request the boundary be discarded by SoupFilterInputStream This makes it easier to implement streams that discard the boundary, like SoupMultipartInputStream. https://bugzilla.gnome.org/show_bug.cgi?id=656684 --- libsoup/soup-filter-input-stream.c | 18 +++++++++++------- libsoup/soup-filter-input-stream.h | 1 + libsoup/soup-socket.c | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/libsoup/soup-filter-input-stream.c b/libsoup/soup-filter-input-stream.c index 79159c38..f8c72515 100644 --- a/libsoup/soup-filter-input-stream.c +++ b/libsoup/soup-filter-input-stream.c @@ -177,7 +177,7 @@ soup_filter_input_stream_read_line (SoupFilterInputStream *fstream, { return soup_filter_input_stream_read_until (fstream, buffer, length, "\n", 1, blocking, - got_line, + TRUE, got_line, cancellable, error); } @@ -188,6 +188,7 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, const void *boundary, gsize boundary_length, gboolean blocking, + gboolean include_boundary, gboolean *got_boundary, GCancellable *cancellable, GError **error) @@ -197,7 +198,7 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, gboolean eof = FALSE; g_return_val_if_fail (SOUP_IS_FILTER_INPUT_STREAM (fstream), -1); - g_return_val_if_fail (boundary_length < length, -1); + g_return_val_if_fail (!include_boundary || (boundary_length < length), -1); *got_boundary = FALSE; @@ -237,8 +238,10 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, if (!eof) end -= boundary_length; for (p = buf; p <= end; p++) { - if (!memcmp (p, boundary, boundary_length)) { - p += boundary_length; + if (*p == *(guint8*)boundary && + !memcmp (p, boundary, boundary_length)) { + if (include_boundary) + p += boundary_length; *got_boundary = TRUE; break; } @@ -247,9 +250,10 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, if (!*got_boundary && fstream->priv->buf->len < length && !eof) goto fill_buffer; - /* Return everything up to 'p' (which is either just after the - * boundary, @boundary_len - 1 bytes before the end of the - * buffer, or end-of-file). + /* Return everything up to 'p' (which is either just after the boundary if + * include_boundary is TRUE, just before the boundary if include_boundary is + * FALSE, @boundary_len - 1 bytes before the end of the buffer, or end-of- + * file). */ return read_from_buf (fstream, buffer, p - buf); } diff --git a/libsoup/soup-filter-input-stream.h b/libsoup/soup-filter-input-stream.h index b86a476f..276b60f7 100644 --- a/libsoup/soup-filter-input-stream.h +++ b/libsoup/soup-filter-input-stream.h @@ -47,6 +47,7 @@ gssize soup_filter_input_stream_read_until (SoupFilterInputStream *fstre const void *boundary, gsize boundary_len, gboolean blocking, + gboolean include_boundary, gboolean *got_boundary, GCancellable *cancellable, GError **error); diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index f44cf347..a9d6bd58 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -1565,7 +1565,7 @@ soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len, SOUP_FILTER_INPUT_STREAM (priv->istream), buffer, len, boundary, boundary_len, !priv->non_blocking, - got_boundary, cancellable, &my_err); + TRUE, got_boundary, cancellable, &my_err); status = translate_read_status (sock, cancellable, my_nread, nread, my_err, error); } -- cgit v1.2.1 From d2a1f47dd173cc6642832c33b554c506dc97b7b9 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Mon, 20 Aug 2012 10:37:17 -0300 Subject: Add SoupMultipartInputStream for handling multipart responses SoupMultipartInputStream can be used by the API user to wrap the input stream, and provides API to obtain the next part and its headers, using a SoupFilterInputStream internally for buffer management. https://bugzilla.gnome.org/show_bug.cgi?id=656684 --- docs/reference/libsoup-2.4-docs.sgml | 1 + docs/reference/libsoup-2.4-sections.txt | 15 + libsoup/Makefile.am | 2 + libsoup/soup-multipart-input-stream.c | 608 ++++++++++++++++++++++++++++++++ libsoup/soup-multipart-input-stream.h | 60 ++++ tests/Makefile.am | 3 + 6 files changed, 689 insertions(+) create mode 100644 libsoup/soup-multipart-input-stream.c create mode 100644 libsoup/soup-multipart-input-stream.h diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index 21e19ea4..76aa87ea 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -74,6 +74,7 @@ + diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 39e8288a..6f819c32 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -926,6 +926,21 @@ SOUP_TYPE_MULTIPART soup_multipart_get_type +
+soup-multipart-input-stream +SoupMultipartInputStream +SoupMultipartInputStream +soup_multipart_input_stream_new + +soup_multipart_input_stream_get_headers +soup_multipart_input_stream_next_part +soup_multipart_input_stream_next_part_async +soup_multipart_input_stream_next_part_finish + +SOUP_TYPE_MULTIPART_INPUT_STREAM +soup_multipart_input_stream_get_type +
+
soup-cookie-jar-text SoupCookieJarText diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index fdba1efa..cc99e75d 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -44,6 +44,7 @@ soup_headers = \ soup-method.h \ soup-misc.h \ soup-multipart.h \ + soup-multipart-input-stream.h \ soup-password-manager.h \ soup-portability.h \ soup-proxy-resolver.h \ @@ -144,6 +145,7 @@ libsoup_2_4_la_SOURCES = \ soup-misc.c \ soup-misc-private.h \ soup-multipart.c \ + soup-multipart-input-stream.c \ soup-password-manager.c \ soup-path-map.h \ soup-path-map.c \ diff --git a/libsoup/soup-multipart-input-stream.c b/libsoup/soup-multipart-input-stream.c new file mode 100644 index 00000000..b1738efe --- /dev/null +++ b/libsoup/soup-multipart-input-stream.c @@ -0,0 +1,608 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-multipart-input-stream.c + * + * Copyright (C) 2012 Collabora Ltd. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "soup-body-input-stream.h" +#include "soup-filter-input-stream.h" +#include "soup-enum-types.h" +#include "soup-message.h" +#include "soup-message-private.h" +#include "soup-multipart-input-stream.h" + +#define RESPONSE_BLOCK_SIZE 8192 + +/** + * SECTION:soup-multipart-input-stream + * @short_description: Multipart input handling stream + * + * This adds support for the multipart responses. For handling the + * multiple parts the user needs to wrap the #GInputStream obtained by + * sending the request with a #SoupMultipartInputStream and use + * soup_multipart_input_stream_next_part() before reading. Responses + * which are not wrapped will be treated like non-multipart responses. + * + * Note that although #SoupMultipartInputStream is a #GInputStream, + * you should not read directly from it, and the results are undefined + * if you do. + * + * Since: 2.40 + **/ + +static void soup_multipart_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupMultipartInputStream, soup_multipart_input_stream, G_TYPE_FILTER_INPUT_STREAM, + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + soup_multipart_input_stream_pollable_init)) + +enum { + PROP_0, + + PROP_MESSAGE, +}; + +struct _SoupMultipartInputStreamPrivate { + SoupMessage *msg; + + gboolean done_with_part; + + GByteArray *meta_buf; + SoupMessageHeaders *current_headers; + + SoupFilterInputStream *base_stream; + + char *boundary; + gsize boundary_size; + + goffset remaining_bytes; +}; + +static void +soup_multipart_input_stream_dispose (GObject *object) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + + g_clear_object (&multipart->priv->msg); + g_clear_object (&multipart->priv->base_stream); + + G_OBJECT_CLASS (soup_multipart_input_stream_parent_class)->dispose (object); +} + +static void +soup_multipart_input_stream_finalize (GObject *object) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + + g_free (multipart->priv->boundary); + + if (multipart->priv->meta_buf) + g_clear_pointer (&multipart->priv->meta_buf, g_byte_array_unref); + + G_OBJECT_CLASS (soup_multipart_input_stream_parent_class)->finalize (object); +} + +static void +soup_multipart_input_stream_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + + switch (prop_id) { + case PROP_MESSAGE: + multipart->priv->msg = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_multipart_input_stream_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + + switch (prop_id) { + case PROP_MESSAGE: + g_value_set_object (value, multipart->priv->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gssize +soup_multipart_input_stream_read_real (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (stream); + SoupMultipartInputStreamPrivate *priv = multipart->priv; + gboolean got_boundary = FALSE; + gssize nread = 0; + guint8 *buf; + + g_return_val_if_fail (priv->boundary != NULL, -1); + + /* If we have received a Content-Length, and are not yet close to the end of + * the part, let's not look for the boundary for now. This optimization is + * necessary for keeping CPU usage civil. + */ + if (priv->remaining_bytes > priv->boundary_size) { + goffset bytes_to_read = MIN (count, priv->remaining_bytes - priv->boundary_size); + + nread = g_pollable_stream_read (G_INPUT_STREAM (priv->base_stream), + buffer, bytes_to_read, blocking, + cancellable, error); + + if (nread > 0) + priv->remaining_bytes -= nread; + + return nread; + } + + if (priv->done_with_part) + return 0; + + nread = soup_filter_input_stream_read_until (priv->base_stream, buffer, count, + priv->boundary, priv->boundary_size, + blocking, FALSE, &got_boundary, + cancellable, error); + + if (nread <= 0) + return nread; + + if (!got_boundary) + return nread; + + priv->done_with_part = TRUE; + + /* Ignore the newline that preceded the boundary. */ + if (nread == 1) { + buf = ((guint8*)buffer); + if (!memcmp (buf, "\n", 1)) + nread -= 1; + } else { + buf = ((guint8*)buffer) + nread - 2; + if (!memcmp (buf, "\r\n", 2)) + nread -= 2; + else if (!memcmp (buf, "\n", 1)) + nread -= 1; + } + + return nread; +} + +static gssize +soup_multipart_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return soup_multipart_input_stream_read_real (stream, buffer, count, + TRUE, cancellable, error); +} + +static void +soup_multipart_input_stream_init (SoupMultipartInputStream *multipart) +{ + SoupMultipartInputStreamPrivate *priv; + priv = multipart->priv = G_TYPE_INSTANCE_GET_PRIVATE (multipart, + SOUP_TYPE_MULTIPART_INPUT_STREAM, + SoupMultipartInputStreamPrivate); + + priv->meta_buf = g_byte_array_sized_new (RESPONSE_BLOCK_SIZE); + priv->done_with_part = FALSE; +} + +static void +soup_multipart_input_stream_constructed (GObject *object) +{ + SoupMultipartInputStream *multipart; + SoupMultipartInputStreamPrivate *priv; + GInputStream *base_stream; + const char* boundary; + GHashTable *params = NULL; + + multipart = SOUP_MULTIPART_INPUT_STREAM (object); + priv = multipart->priv; + + base_stream = G_FILTER_INPUT_STREAM (multipart)->base_stream; + priv->base_stream = SOUP_FILTER_INPUT_STREAM (soup_filter_input_stream_new (base_stream)); + + soup_message_headers_get_content_type (priv->msg->response_headers, + ¶ms); + + boundary = g_hash_table_lookup (params, "boundary"); + if (boundary) { + if (g_str_has_prefix (boundary, "--")) + priv->boundary = g_strdup (boundary); + else + priv->boundary = g_strdup_printf ("--%s", boundary); + + priv->boundary_size = strlen (priv->boundary); + } else { + g_warning ("No boundary found in message tagged as multipart."); + } + + g_hash_table_destroy (params); + + if (G_OBJECT_CLASS (soup_multipart_input_stream_parent_class)->constructed) + G_OBJECT_CLASS (soup_multipart_input_stream_parent_class)->constructed (object); +} + +static gboolean +soup_multipart_input_stream_is_readable (GPollableInputStream *stream) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (stream); + SoupMultipartInputStreamPrivate *priv = multipart->priv; + + return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (priv->base_stream)); +} + +static gssize +soup_multipart_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (stream); + + return soup_multipart_input_stream_read_real (G_INPUT_STREAM (multipart), + buffer, count, + FALSE, NULL, error); +} + +static GSource * +soup_multipart_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (stream); + SoupMultipartInputStreamPrivate *priv = multipart->priv; + GSource *base_source, *pollable_source; + + base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->base_stream), cancellable); + + pollable_source = g_pollable_source_new_full (stream, base_source, cancellable); + g_source_unref (base_source); + + return pollable_source; +} + +static void +soup_multipart_input_stream_class_init (SoupMultipartInputStreamClass *multipart_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (multipart_class); + GInputStreamClass *input_stream_class = + G_INPUT_STREAM_CLASS (multipart_class); + + g_type_class_add_private (multipart_class, sizeof (SoupMultipartInputStreamPrivate)); + + object_class->dispose = soup_multipart_input_stream_dispose; + object_class->finalize = soup_multipart_input_stream_finalize; + object_class->constructed = soup_multipart_input_stream_constructed; + object_class->set_property = soup_multipart_input_stream_set_property; + object_class->get_property = soup_multipart_input_stream_get_property; + + input_stream_class->read_fn = soup_multipart_input_stream_read; + + g_object_class_install_property ( + object_class, PROP_MESSAGE, + g_param_spec_object ("message", + "Message", + "The SoupMessage", + SOUP_TYPE_MESSAGE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + +} + +static void +soup_multipart_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_readable = soup_multipart_input_stream_is_readable; + pollable_interface->read_nonblocking = soup_multipart_input_stream_read_nonblocking; + pollable_interface->create_source = soup_multipart_input_stream_create_source; +} + +static void +soup_multipart_input_stream_parse_headers (SoupMultipartInputStream *multipart) +{ + SoupMultipartInputStreamPrivate *priv = multipart->priv; + gboolean success; + + priv->current_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); + + /* The part lacks headers, but is there. */ + if (!priv->meta_buf->len) + return; + + success = soup_headers_parse ((const char*) priv->meta_buf->data, + (int) priv->meta_buf->len, + priv->current_headers); + + if (success) + priv->remaining_bytes = soup_message_headers_get_content_length (priv->current_headers); + else + g_clear_pointer (&priv->current_headers, soup_message_headers_free); + + g_byte_array_remove_range (priv->meta_buf, 0, priv->meta_buf->len); +} + +static gboolean +soup_multipart_input_stream_read_headers (SoupMultipartInputStream *multipart, + GCancellable *cancellable, + GError **error) +{ + SoupMultipartInputStreamPrivate *priv = multipart->priv; + guchar read_buf[RESPONSE_BLOCK_SIZE]; + guchar *buf; + gboolean got_boundary = FALSE; + gboolean got_lf = FALSE; + gssize nread = 0; + + g_return_val_if_fail (priv->boundary != NULL, TRUE); + + g_clear_pointer (&priv->current_headers, soup_message_headers_free); + + while (1) { + nread = soup_filter_input_stream_read_line (priv->base_stream, read_buf, sizeof (read_buf), + /* blocking */ TRUE, &got_lf, cancellable, error); + + if (nread <= 0) + break; + + g_byte_array_append (priv->meta_buf, read_buf, nread); + + /* Need to do this boundary check before checking for the line feed, since we + * may get the multipart end indicator without getting a new line. + */ + if (!got_boundary && + !strncmp ((char *)priv->meta_buf->data, + priv->boundary, + priv->boundary_size)) { + got_boundary = TRUE; + + /* Now check for possible multipart termination. */ + buf = &read_buf[nread - 2]; + if (nread >= 2 && !memcmp (buf, "--", 2)) { + g_byte_array_set_size (priv->meta_buf, 0); + return FALSE; + } + } + + g_return_val_if_fail (got_lf, FALSE); + + /* Discard pre-boundary lines. */ + if (!got_boundary) { + g_byte_array_set_size (priv->meta_buf, 0); + continue; + } + + if (nread == 1 && + priv->meta_buf->len >= 2 && + !strncmp ((char *)priv->meta_buf->data + + priv->meta_buf->len - 2, + "\n\n", 2)) + break; + else if (nread == 2 && + priv->meta_buf->len >= 3 && + !strncmp ((char *)priv->meta_buf->data + + priv->meta_buf->len - 3, + "\n\r\n", 3)) + break; + } + + return TRUE; +} + +/* Public APIs */ + +/** + * soup_multipart_input_stream_new: + * @msg: the #SoupMessage the response is related to. + * @base_stream: the #GInputStream returned by sending the request. + * + * Creates a new #SoupMultipartInputStream that wraps the + * #GInputStream obtained by sending the #SoupRequest. Reads should + * not be done directly through this object, use the input streams + * returned by soup_multipart_input_stream_next_part() or its async + * counterpart instead. + * + * Returns: a new #SoupMultipartInputStream + * + * Since: 2.40 + **/ +SoupMultipartInputStream * +soup_multipart_input_stream_new (SoupMessage *msg, + GInputStream *base_stream) +{ + return g_object_new (SOUP_TYPE_MULTIPART_INPUT_STREAM, + "message", msg, + "base-stream", base_stream, + NULL); +} + +/** + * soup_multipart_input_stream_next_part: + * @multipart: the #SoupMultipartInputStream + * @cancellable: a #GCancellable + * @error: a #GError + * + * Obtains an input stream for the next part. When dealing with a + * multipart response the input stream needs to be wrapped in a + * #SoupMultipartInputStream and this function or its async + * counterpart need to be called to obtain the first part for + * reading. + * + * After calling this function, + * soup_multipart_input_stream_get_headers() can be used to obtain the + * headers for the first part. A read of 0 bytes indicates the end of + * the part; a new call to this function should be done at that point, + * to obtain the next part. + * + * Return value: (transfer full): a new #GInputStream, or %NULL if + * there are no more parts + * + * Since: 2.40 + */ +GInputStream * +soup_multipart_input_stream_next_part (SoupMultipartInputStream *multipart, + GCancellable *cancellable, + GError **error) +{ + if (!soup_multipart_input_stream_read_headers (multipart, cancellable, error)) + return NULL; + + soup_multipart_input_stream_parse_headers (multipart); + + multipart->priv->done_with_part = FALSE; + + return G_INPUT_STREAM (g_object_new (SOUP_TYPE_BODY_INPUT_STREAM, + "base-stream", G_INPUT_STREAM (multipart), + "close-base-stream", FALSE, + "encoding", SOUP_ENCODING_EOF, + NULL)); + +} + +static void +soup_multipart_input_stream_next_part_thread (GSimpleAsyncResult *simple, + GObject *object, + GCancellable *cancellable) +{ + SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); + GError *error = NULL; + GInputStream *new_stream; + + new_stream = soup_multipart_input_stream_next_part (multipart, cancellable, &error); + + g_input_stream_clear_pending (G_INPUT_STREAM (multipart)); + + if (g_simple_async_result_propagate_error (simple, &error)) + return; + + if (new_stream) + g_simple_async_result_set_op_res_gpointer (simple, new_stream, g_object_unref); +} + +/** + * soup_multipart_input_stream_next_part_async: + * @multipart: the #SoupMultipartInputStream. + * @io_priority: the I/O priority for the request. + * @cancellable: a #GCancellable. + * @callback: callback to call when request is satisfied. + * + * Obtains a #GInputStream for the next request. See + * soup_multipart_input_stream_next_part() for details on the + * workflow. + * + * Return value: a new #GInputStream, or %NULL if there are no more + * parts + * + * Since: 2.40 + */ +void +soup_multipart_input_stream_next_part_async (SoupMultipartInputStream *multipart, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data) +{ + GInputStream *stream = G_INPUT_STREAM (multipart); + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (SOUP_IS_MULTIPART_INPUT_STREAM (multipart)); + + simple = g_simple_async_result_new (G_OBJECT (multipart), + callback, data, + soup_multipart_input_stream_next_part_async); + + if (!g_input_stream_set_pending (stream, &error)) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + + g_simple_async_result_run_in_thread (simple, soup_multipart_input_stream_next_part_thread, + io_priority, cancellable); + g_object_unref (simple); +} + +/** + * soup_multipart_input_stream_next_part_finish: + * @multipart: a #SoupMultipartInputStream. + * @result: a #GAsyncResult. + * @error: a #GError location to store any error, or NULL to ignore. + * + * Finishes an asynchronous request for the next part. + * + * Return value: (transfer full): a newly created #GInputStream for + * reading the next part or %NULL if there are no more parts. + * + * Since: 2.40 + */ +GInputStream * +soup_multipart_input_stream_next_part_finish (SoupMultipartInputStream *multipart, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + GInputStream *new_stream; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (multipart), + soup_multipart_input_stream_next_part_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + new_stream = g_simple_async_result_get_op_res_gpointer (simple); + if (new_stream) + return g_object_ref (new_stream); + + return NULL; +} + +/** + * soup_multipart_input_stream_get_headers: + * @multipart: a #SoupMultipartInputStream. + * + * Obtains the headers for the part currently being processed. Note + * that the #SoupMessageHeaders that are returned are owned by the + * #SoupMultipartInputStream and will be replaced when a call is made + * to soup_multipart_input_stream_next_part() or its async + * counterpart, so if keeping the headers is required, a copy must be + * made. + * + * Note that if a part had no headers at all an empty #SoupMessageHeaders + * will be returned. + * + * Return value: (transfer none): a #SoupMessageHeaders containing the headers + * for the part currently being processed or %NULL if the headers failed to + * parse. + * + * Since: 2.40 + */ +SoupMessageHeaders * +soup_multipart_input_stream_get_headers (SoupMultipartInputStream *multipart) +{ + return multipart->priv->current_headers; +} diff --git a/libsoup/soup-multipart-input-stream.h b/libsoup/soup-multipart-input-stream.h new file mode 100644 index 00000000..77f0f817 --- /dev/null +++ b/libsoup/soup-multipart-input-stream.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Collabora Ltd. + */ + +#ifndef SOUP_MULTIPART_INPUT_STREAM_H +#define SOUP_MULTIPART_INPUT_STREAM_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_MULTIPART_INPUT_STREAM (soup_multipart_input_stream_get_type ()) +#define SOUP_MULTIPART_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SOUP_TYPE_MULTIPART_INPUT_STREAM, SoupMultipartInputStream)) +#define SOUP_MULTIPART_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SOUP_TYPE_MULTIPART_INPUT_STREAM, SoupMultipartInputStreamClass)) +#define SOUP_IS_MULTIPART_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SOUP_TYPE_MULTIPART_INPUT_STREAM)) +#define SOUP_IS_MULTIPART_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SOUP_TYPE_MULTIPART_INPUT_STREAM)) +#define SOUP_MULTIPART_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), SOUP_TYPE_MULTIPART_INPUT_STREAM, SoupMultipartInputStreamClass)) + +typedef struct _SoupMultipartInputStream SoupMultipartInputStream; +typedef struct _SoupMultipartInputStreamPrivate SoupMultipartInputStreamPrivate; +typedef struct _SoupMultipartInputStreamClass SoupMultipartInputStreamClass; + +struct _SoupMultipartInputStream { + GFilterInputStream parent_instance; + + /*< private >*/ + SoupMultipartInputStreamPrivate *priv; +}; + +struct _SoupMultipartInputStreamClass { + GFilterInputStreamClass parent_class; +}; + +GType soup_multipart_input_stream_get_type (void) G_GNUC_CONST; + +SoupMultipartInputStream *soup_multipart_input_stream_new (SoupMessage *msg, + GInputStream *base_stream); + +GInputStream *soup_multipart_input_stream_next_part (SoupMultipartInputStream *multipart, + GCancellable *cancellable, + GError **error); + +void soup_multipart_input_stream_next_part_async (SoupMultipartInputStream *multipart, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer data); + +GInputStream *soup_multipart_input_stream_next_part_finish (SoupMultipartInputStream *multipart, + GAsyncResult *res, + GError **error); + +SoupMessageHeaders *soup_multipart_input_stream_get_headers (SoupMultipartInputStream *multipart); + + +G_END_DECLS + +#endif /* SOUP_MULTIPART_INPUT_STREAM_H */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 594890b9..d2a1cd64 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,6 +24,7 @@ noinst_PROGRAMS = \ get \ header-parsing \ misc-test \ + multipart-test \ ntlm-test \ redirect-test \ requester-test \ @@ -57,6 +58,7 @@ if BUILD_LIBSOUP_GNOME get_LDADD = $(top_builddir)/libsoup/libsoup-gnome-2.4.la endif header_parsing_SOURCES = header-parsing.c $(TEST_SRCS) +multipart_test_SOURCES = multipart-test.c $(TEST_SRCS) misc_test_SOURCES = misc-test.c $(TEST_SRCS) ntlm_test_SOURCES = ntlm-test.c $(TEST_SRCS) proxy_test_SOURCES = proxy-test.c $(TEST_SRCS) @@ -97,6 +99,7 @@ TESTS = \ date \ header-parsing \ misc-test \ + multipart-test \ ntlm-test \ redirect-test \ requester-test \ -- cgit v1.2.1 From 1fcf9757746de2d4d19b6c07bc59c8b5f1bf14b2 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Mon, 20 Aug 2012 15:20:22 -0300 Subject: Add missing file for last commit --- tests/multipart-test.c | 617 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 617 insertions(+) create mode 100644 tests/multipart-test.c diff --git a/tests/multipart-test.c b/tests/multipart-test.c new file mode 100644 index 00000000..136ee0db --- /dev/null +++ b/tests/multipart-test.c @@ -0,0 +1,617 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2011 Collabora Ltd. + */ + +#include +#include +#include +#include + +#define LIBSOUP_USE_UNSTABLE_REQUEST_API +#include +#include +#include +#include + +#include "test-utils.h" + +#define READ_BUFFER_SIZE 8192 + +typedef enum { + NO_MULTIPART, + SYNC_MULTIPART, + ASYNC_MULTIPART, + ASYNC_MULTIPART_SMALL_READS +} MultipartMode; + +char *buffer; +SoupRequester *requester; +char *base_uri_string; +SoupURI *base_uri; +SoupMultipartInputStream *multipart; +unsigned passes; + + +/* This payload contains 4 different responses. + * + * First, a text/html response with a Content-Length (31); + * Second, a response lacking Content-Type with Content-Length (11); + * Third, a text/css response with no Content-Length; + * Fourth, same as the third, but with different content; + */ +const char *payload = \ + "--cut-here\r\n" \ + "Content-Type: text/html\n" + "Content-Length: 30\r\n" \ + "\r\n" \ + "Hey!" \ + "\r\n--cut-here\r\n" \ + "Content-Length: 10\r\n" \ + "\r\n" \ + "soup rocks" \ + "\r\n--cut-here\r\n" \ + "Content-Type: text/css\r\n" \ + "\r\n" \ + ".soup { before: rocks; }" \ + "\r\n--cut-here\n" /* Tests boundary ending in a single \n. */ \ + "Content-Type: text/css\r\n" \ + "\r\n" \ + "#soup { background-color: black; }" \ + "\r\n--cut-here--"; + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + if (msg->method != SOUP_METHOD_GET) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + + soup_message_headers_append (msg->response_headers, + "Content-Type", "multipart/x-mixed-replace; boundary=cut-here"); + + soup_message_body_append (msg->response_body, + SOUP_MEMORY_STATIC, + payload, + strlen (payload)); + + soup_message_body_complete (msg->response_body); +} + +static void +content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, int *sniffed_count) +{ + *sniffed_count = *sniffed_count + 1; + debug_printf (2, " content-sniffed -> %s\n", content_type); +} + +static void +check_is_next (gboolean is_next) +{ + if (!is_next) { + debug_printf (1, " expected a header, but there are no more headers\n"); + errors++; + } +} + +static void +got_headers (SoupMessage *msg, int *headers_count) +{ + SoupMessageHeadersIter iter; + gboolean is_next; + const char* name, *value; + + *headers_count = *headers_count + 1; + + soup_message_headers_iter_init (&iter, msg->response_headers); + + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + if (g_str_equal (name, "Date")) { + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + } + + if (!g_str_equal (name, "Content-Type")) { + debug_printf (1, " expected `Content-Type' got %s\n", name); + errors++; + } + + if (!g_str_equal (value, "multipart/x-mixed-replace; boundary=cut-here")) { + debug_printf (1, " expected `multipart/x-mixed-replace; boundary=cut-here' got %s\n", value); + errors++; + } +} + +static void +read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + GInputStream *stream = G_INPUT_STREAM (source); + GError *error = NULL; + gssize bytes_read = g_input_stream_read_finish (stream, asyncResult, &error); + if (error) { + debug_printf (1, " failed read: %s\n", error->message); + errors++; + + g_main_loop_quit (loop); + return; + } + + if (!bytes_read) { + g_input_stream_close (stream, NULL, &error); + + if (error) { + debug_printf (1, " failed close: %s\n", error->message); + errors++; + } + + g_main_loop_quit (loop); + return; + } + + g_input_stream_read_async (stream, buffer, READ_BUFFER_SIZE, + G_PRIORITY_DEFAULT, NULL, + read_cb, data); +} + +static void +no_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + SoupRequest *request = SOUP_REQUEST (source); + GError *error = NULL; + GInputStream* in; + + in = soup_request_send_finish (request, res, &error); + + if (error) { + debug_printf (1, " failed send: %s\n", error->message); + errors++; + + g_main_loop_quit (loop); + return; + } + + g_input_stream_read_async (in, buffer, READ_BUFFER_SIZE, + G_PRIORITY_DEFAULT, NULL, + read_cb, data); +} + +static void +multipart_close_part_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GInputStream *in = G_INPUT_STREAM (source); + GError *error = NULL; + + g_input_stream_close_finish (in, res, &error); + if (error) { + debug_printf (1, " error closing stream: %s\n", error->message); + errors++; + } +} + +static void multipart_next_part_cb (GObject *source, + GAsyncResult *res, + gpointer data); + +static void +check_read (gsize nread, unsigned passes) +{ + switch (passes) { + case 0: + if (nread != 30) { + debug_printf (1, " expected to read 30 bytes, got: %d\n", (int)nread); + errors++; + } + break; + case 1: + if (nread != 10) { + debug_printf (1, " expected to read 10 bytes, got: %d\n", (int)nread); + errors++; + } + break; + case 2: + if (nread != 24) { + debug_printf (1, " expected to read 24 bytes, got: %d\n", (int)nread); + errors++; + } + break; + case 3: + if (nread != 34) { + debug_printf (1, " expected to read 34 bytes, got: %d\n", (int)nread); + errors++; + } + break; + default: + debug_printf (1, " unexpected read of size: %d\n", (int)nread); + errors++; + } +} + +static void +multipart_read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + GInputStream *in = G_INPUT_STREAM (source); + GError *error = NULL; + static gssize bytes_read_for_part = 0; + gssize bytes_read; + + bytes_read = g_input_stream_read_finish (in, asyncResult, &error); + + if (error) { + debug_printf (1, " failed read: %s\n", error->message); + errors++; + + g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, + multipart_close_part_cb, NULL); + + g_main_loop_quit (loop); + return; + } + + /* Read 0 bytes - try to start reading another part. */ + if (!bytes_read) { + check_read (bytes_read_for_part, passes); + bytes_read_for_part = 0; + passes++; + + g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, + multipart_close_part_cb, NULL); + + soup_multipart_input_stream_next_part_async (multipart, G_PRIORITY_DEFAULT, NULL, + multipart_next_part_cb, data); + return; + } + + bytes_read_for_part += bytes_read; + g_input_stream_read_async (in, buffer, READ_BUFFER_SIZE, + G_PRIORITY_DEFAULT, NULL, + multipart_read_cb, data); +} + +static void +check_headers (SoupMultipartInputStream* multipart, unsigned passes) +{ + SoupMessageHeaders *headers; + SoupMessageHeadersIter iter; + gboolean is_next; + const char *name, *value; + + headers = soup_multipart_input_stream_get_headers (multipart); + soup_message_headers_iter_init (&iter, headers); + + switch (passes) { + case 0: + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + if (!g_str_equal (name, "Content-Type")) { + debug_printf (1, " [0] expected `Content-Type' got %s\n", name); + errors++; + } + + if (!g_str_equal (value, "text/html")) { + debug_printf (1, " [0] expected `text/html' got %s\n", value); + errors++; + } + + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + if (!g_str_equal (name, "Content-Length")) { + debug_printf (1, " [0] expected `Content-Length' got %s\n", name); + errors++; + } + + if (!g_str_equal (value, "30")) { + debug_printf (1, " [0] expected `30' got %s\n", value); + errors++; + } + + break; + case 1: + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + if (!g_str_equal (name, "Content-Length")) { + debug_printf (1, " [1] expected `Content-Length' got %s\n", name); + errors++; + } + + if (!g_str_equal (value, "10")) { + debug_printf (1, " [1] expected `10' got %s\n", value); + errors++; + } + + break; + case 2: + case 3: + is_next = soup_message_headers_iter_next (&iter, &name, &value); + check_is_next (is_next); + + if (!g_str_equal (name, "Content-Type")) { + debug_printf (1, " [%d] expected `Content-Type' got %s\n", passes, name); + errors++; + } + + if (!g_str_equal (value, "text/css")) { + debug_printf (1, " [%d] expected `text/html' got %s\n", passes, value); + errors++; + } + + break; + default: + debug_printf (1, " unexpected part received\n"); + break; + } +} + +static void +multipart_next_part_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + GError *error = NULL; + GInputStream *in; + gsize read_size = READ_BUFFER_SIZE; + + g_assert (SOUP_MULTIPART_INPUT_STREAM (source) == multipart); + + in = soup_multipart_input_stream_next_part_finish (multipart, res, &error); + + if (error) { + debug_printf (1, " failed next part: %s\n", error->message); + errors++; + + g_main_loop_quit (loop); + return; + } + + if (!in) { + if (passes != 4) { + debug_printf (1, " expected 4 parts, got %u\n", passes); + errors++; + } + + g_main_loop_quit (loop); + return; + } + + check_headers (multipart, passes); + + if (g_object_get_data (G_OBJECT (multipart), "multipart-small-reads")) + read_size = 4; + + g_input_stream_read_async (in, buffer, read_size, + G_PRIORITY_DEFAULT, NULL, + multipart_read_cb, data); +} + +static void +multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + SoupRequest *request = SOUP_REQUEST (source); + GError *error = NULL; + GInputStream *in; + SoupMessage *message; + + in = soup_request_send_finish (request, res, &error); + message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + multipart = soup_multipart_input_stream_new (message, in); + + if (error) { + debug_printf (1, " failed send: %s\n", error->message); + errors++; + + g_main_loop_quit (loop); + return; + } + + if (g_object_get_data (source, "multipart-small-reads")) + g_object_set_data (G_OBJECT (multipart), "multipart-small-reads", GINT_TO_POINTER(1)); + + soup_multipart_input_stream_next_part_async (multipart, G_PRIORITY_DEFAULT, NULL, + multipart_next_part_cb, data); +} + +static void +sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) +{ + GMainLoop *loop = (GMainLoop*)data; + SoupRequest *request = SOUP_REQUEST (source); + GError *error = NULL; + GInputStream *in; + SoupMessage *message; + char buffer[READ_BUFFER_SIZE]; + gsize bytes_read; + + in = soup_request_send_finish (request, res, &error); + message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + multipart = soup_multipart_input_stream_new (message, in); + + if (error) { + debug_printf (1, " failed send: %s\n", error->message); + errors++; + + g_main_loop_quit (loop); + return; + } + + while (TRUE) { + in = soup_multipart_input_stream_next_part (multipart, NULL, &error); + + if (error) { + debug_printf (1, " failed sync next part: %s\n", error->message); + errors++; + g_clear_error (&error); + break; + } + + if (!in) + break; + + check_headers (multipart, passes); + + g_input_stream_read_all (in, (void*)buffer, sizeof (buffer), &bytes_read, NULL, &error); + + if (error) { + debug_printf (1, " failed sync read: %s\n", error->message); + errors++; + g_clear_error (&error); + break; + } + + check_read (bytes_read, passes); + + passes++; + } + + if (passes != 4) { + debug_printf (1, " expected 4 parts, got %u\n", passes); + errors++; + } + + g_main_loop_quit (loop); + +} + +static const char* +multipart_mode_to_string (MultipartMode mode) +{ + if (mode == NO_MULTIPART) + return "NO_MULTIPART"; + else if (mode == SYNC_MULTIPART) + return "SYNC_MULTIPART"; + else if (mode == ASYNC_MULTIPART_SMALL_READS) + return "SYNC_MULTIPART_SMALL_READS"; + + return "ASYNC_MULTIPART"; +} + +static void +test_multipart (int headers_expected, int sniffed_expected, MultipartMode multipart_mode) +{ + GError* error = NULL; + SoupRequest* request = soup_requester_request (requester, base_uri_string, &error); + + SoupMessage *msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + GMainLoop *loop = g_main_loop_new (NULL, TRUE); + int headers_count = 0; + int sniffed_count = 0; + GHashTable *params; + const char *content_type; + gboolean message_is_multipart = FALSE; + + debug_printf (1, "test_multipart(%s)\n", multipart_mode_to_string (multipart_mode)); + + /* This is used to track the number of parts. */ + passes = 0; + + /* Force the server to close the connection. */ + soup_message_headers_append (msg->request_headers, + "Connection", "close"); + + g_signal_connect (msg, "got_headers", + G_CALLBACK (got_headers), &headers_count); + + g_signal_connect (msg, "content-sniffed", + G_CALLBACK (content_sniffed), &sniffed_count); + + g_object_ref (msg); + + if (multipart_mode == ASYNC_MULTIPART) + soup_request_send_async (request, NULL, multipart_handling_cb, loop); + else if (multipart_mode == ASYNC_MULTIPART_SMALL_READS) { + g_object_set_data (G_OBJECT (request), "multipart-small-reads", GINT_TO_POINTER(1)); + soup_request_send_async (request, NULL, multipart_handling_cb, loop); + } else if (multipart_mode == SYNC_MULTIPART) + soup_request_send_async (request, NULL, sync_multipart_handling_cb, loop); + else + soup_request_send_async (request, NULL, no_multipart_handling_cb, loop); + + g_main_loop_run (loop); + + content_type = soup_message_headers_get_content_type (msg->response_headers, ¶ms); + + if (content_type && + g_str_has_prefix (content_type, "multipart/") && + g_hash_table_lookup (params, "boundary")) { + message_is_multipart = TRUE; + } + g_clear_pointer (¶ms, g_hash_table_unref); + + if (!message_is_multipart) { + debug_printf (1, + " Header does not indicate a multipart message!\n"); + errors++; + } + + if (headers_count != headers_expected) { + debug_printf (1, + " expected got_header %d times, got %d!\n", + headers_expected, headers_count); + errors++; + } + + if (sniffed_count != sniffed_expected) { + debug_printf (1, + " expected content_sniffed %d times, got %d!\n", + sniffed_expected, sniffed_count); + errors++; + } + + g_object_unref (msg); + g_object_unref (request); + g_main_loop_unref (loop); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupSession *session; + + test_init (argc, argv, NULL); + + buffer = g_malloc (READ_BUFFER_SIZE); + + server = soup_test_server_new (FALSE); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + base_uri = soup_uri_new ("http://127.0.0.1"); + soup_uri_set_port (base_uri, soup_server_get_port (server)); + base_uri_string = soup_uri_to_string (base_uri, FALSE); + + /* FIXME: I had to raise the number of connections allowed here, otherwise I + * was hitting the limit, which indicates some connections are not dying. + */ + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + "use-thread-context", TRUE, + "max-conns", 20, + "max-conns-per-host", 20, + NULL); + soup_session_add_feature_by_type (session, SOUP_TYPE_REQUESTER); + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); + + requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER)); + + test_multipart (1, 1, NO_MULTIPART); + test_multipart (1, 1, SYNC_MULTIPART); + test_multipart (1, 1, ASYNC_MULTIPART); + test_multipart (1, 1, ASYNC_MULTIPART_SMALL_READS); + + soup_uri_free (base_uri); + g_free (base_uri_string); + + soup_test_session_abort_unref (session); + soup_test_server_quit_unref (server); + test_cleanup (); + return errors != 0; +} -- cgit v1.2.1 From e1600cd686e32a52e126998413445f038be81e01 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 20 Aug 2012 12:05:22 -0400 Subject: SoupSession: clarify timeout and idle-timeout docs They only affect connections opened after you set the property. https://bugzilla.gnome.org/show_bug.cgi?id=681781 --- libsoup/soup-session.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 90e91893..c8261575 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -2224,7 +2224,14 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SoupSession:idle-timeout: * - * Connection lifetime when idle + * Connection lifetime (in seconds) when idle. Any connection + * left idle longer than this will be closed. + * + * Although you can change this property at any time, it will + * only affect newly-created connections, not currently-open + * ones. You can call soup_session_abort() after setting this + * if you want to ensure that all future connections will have + * this timeout value. * * Since: 2.4.1 **/ @@ -2427,11 +2434,24 @@ soup_session_class_init (SoupSessionClass *session_class) "Whether to use thread-default main contexts", FALSE, G_PARAM_READWRITE)); + /** + * SoupSession:timeout: + * + * The timeout (in seconds) for socket I/O operations + * (including connecting to a server, and waiting for a reply + * to an HTTP request). + * + * Although you can change this property at any time, it will + * only affect newly-created connections, not currently-open + * ones. You can call soup_session_abort() after setting this + * if you want to ensure that all future connections will have + * this timeout value. + */ /** * SOUP_SESSION_TIMEOUT: * * Alias for the #SoupSession:timeout property. (The timeout - * in seconds for blocking socket I/O operations.) + * in seconds for socket I/O operations.) **/ g_object_class_install_property ( object_class, PROP_TIMEOUT, -- cgit v1.2.1 From b1c493360586a6da9f12480a16c2257f565ba135 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 20 Aug 2012 17:34:28 -0400 Subject: 2.39.90 --- NEWS | 32 ++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 4fcb242c..514a94da 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,35 @@ +Changes in libsoup from 2.39.5 to 2.39.90: + + * Added SoupMultipartInputStream, for handling multipart + responses (particularly multipart/x-mixed-replace). + [#656684, Gustavo] + + * Fixed a potential crash in SoupSessionAsync after the + session is finalized. + + * Fixed a regression in soup_tls_is_public_suffix() [#681085, + Sergio] + + * Added a SOUP_MESSAGE_IDEMPOTENT flag, so that apps can + bypass the "POSTs must be sent on new connections" check, + which was causing evolution-ews to have to create a new + connection for every request. [#681493, Milan Crha] + + * Changed SoupSession so that pending SoupMessages now hold a + ref on the session. It is possible that this will break code + that was depending on the old, dumb, behavior (where + unreffing the session with messages pending would cause + those messages to be cancelled), in which case this will be + reverted before 2.40. + + * Fixed memory leaks found by valgrind. + + * Cleaned up some code in SoupCache. [#681509, Sergio] + + * New/updated translations: + Bengali (India), Chinese (Traditional), German, Marathi, + Turkish, Ukranian + Changes in libsoup from 2.39.4.1 to 2.39.5: * Fixed several bugs in the soup-message-io updates that could diff --git a/configure.ac b/configure.ac index d0d19341..95410de5 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *** Initialize automake and set version *** dnl ******************************************* AC_PREREQ(2.63) -AC_INIT([libsoup],[2.39.6],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[2.39.90],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -- cgit v1.2.1 From 20b76889515d83c2dc3b96bc10be2bdc16008a77 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 21 Aug 2012 08:29:27 -0400 Subject: soup_session_abort: clarify that it closes connections too --- libsoup/soup-session.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index c8261575..4d8836b4 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1613,7 +1613,8 @@ soup_session_real_flush_queue (SoupSession *session) * soup_session_abort: * @session: the session * - * Cancels all pending requests in @session. + * Cancels all pending requests in @session and closes all idle + * persistent connections. **/ void soup_session_abort (SoupSession *session) -- cgit v1.2.1 From 4c4862a6ac024f7c2de8865c698364ab6b324ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Dr=C4=85g?= Date: Wed, 22 Aug 2012 03:00:14 +0200 Subject: Updated Polish translation --- po/pl.po | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/po/pl.po b/po/pl.po index a4ccffcb..f1503cc0 100644 --- a/po/pl.po +++ b/po/pl.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-06-03 15:35+0200\n" -"PO-Revision-Date: 2012-06-03 15:36+0200\n" +"POT-Creation-Date: 2012-08-22 02:59+0200\n" +"PO-Revision-Date: 2012-08-22 03:00+0200\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "Language: pl\n" @@ -21,41 +21,57 @@ msgstr "" "X-Poedit-Language: Polish\n" "X-Poedit-Country: Poland\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Połączenie zostało nieoczekiwanie zakończone" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Bufor wyjściowy jest za mały" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Anulowano działanie" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Działanie spowodowałoby zablokowanie" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "Nie podano adresu URI" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Nieprawidłowy adres URI \"%s\": %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Nie można przetworzyć adresu URI \"%s\"" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nieobsługiwany schemat adresu URI \"%s\"" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Nazwa komputera jest adresem IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Nieprawidłowa nazwa komputera" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Nazwa komputera nie posiada podstawowej domeny" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Brak wystarczającej liczby domen" -- cgit v1.2.1 From 81bc02e6aae53c38d37dbf530b67ef7a752e19e5 Mon Sep 17 00:00:00 2001 From: A S Alam Date: Wed, 22 Aug 2012 08:58:10 +0530 Subject: update Punjabi Translation --- po/pa.po | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/po/pa.po b/po/pa.po index 8ea8198f..73606601 100644 --- a/po/pa.po +++ b/po/pa.po @@ -8,53 +8,69 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-05-16 03:05+0000\n" -"PO-Revision-Date: 2012-05-18 07:27+0530\n" +"POT-Creation-Date: 2012-07-16 22:04+0000\n" +"PO-Revision-Date: 2012-08-22 08:57+0530\n" "Last-Translator: A S Alam \n" "Language-Team: Punjabi/Panjabi \n" +"Language: pa\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: pa\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Lokalize 1.4\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "ਕੁਨੈਕਸ਼ਨ ਅਚਾਨਕ ਬੰਦ ਹੋ ਗਿਆ" -#: ../libsoup/soup-converter-wrapper.c:185 +#: ../libsoup/soup-converter-wrapper.c:189 #, c-format msgid "Output buffer is too small" msgstr "ਆਉਟਪੁੱਟ ਬਫ਼ਰ ਬਹੁਤ ਛੋਟਾ ਹੈ" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "ਕਾਰਵਾਈ ਰੱਦ ਕੀਤੀ ਗਈ" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:864 msgid "Operation would block" msgstr "ਕਾਰਵਾਈ ਉੱਤੇ ਪਾਬੰਦੀ ਹੋਵੇਗੀ" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "ਕੋਈ URI ਨਹੀਂ ਦਿੱਤਾ" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "ਗਲਤ '%s' URI: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "ਗ਼ੈਰ-ਸਹਾਇਕ URI ਸਕੀਮ '%s'" +#: ../libsoup/soup-tld.c:143 +msgid "Hostname is an IP address" +msgstr "ਹੋਸਟ ਨਾਂ IP ਐਡਰੈਸ ਹੈ" + +#: ../libsoup/soup-tld.c:164 +msgid "Invalid hostname" +msgstr "ਗਲਤ ਹੋਸਟ-ਨਾਂ" + +#: ../libsoup/soup-tld.c:179 ../libsoup/soup-tld.c:221 +msgid "Not enough domains" +msgstr "ਲੋੜੀਦੀਆਂ ਡੋਮੇਨ ਨਹੀਂ ਹੈ" + +#: ../libsoup/soup-tld.c:199 +msgid "Hostname has no base domain" +msgstr "ਹੋਸਟ-ਨਾਂ ਲਈ ਬੇਸ ਡੋਮੇਮ ਨਹੀਂ ਹੈ" + -- cgit v1.2.1 From dc4cf04a2b3e06570f87b566d310b98e4bf0c01b Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 23 Aug 2012 10:04:08 -0600 Subject: Add missing transfer full annotation to soup_cookie_jar_add_cookie Adding a cookie to a jar from Python (via introspection) wasn't working right, since the cookie was being freed as soon as the python object went out of scope, but soup_cookie_jar_add_cookie() explicitly states that freeing shouldn't happen. Add a missing annotation to fix this. Thanks to Benjamin Berg for the suggestion. Fixes http://bugs.sugarlabs.org/ticket/3825 https://bugzilla.gnome.org/show_bug.cgi?id=682554 --- libsoup/soup-cookie-jar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-cookie-jar.c b/libsoup/soup-cookie-jar.c index 433e7046..3180680d 100644 --- a/libsoup/soup-cookie-jar.c +++ b/libsoup/soup-cookie-jar.c @@ -432,7 +432,7 @@ soup_cookie_jar_get_cookie_list (SoupCookieJar *jar, SoupURI *uri, gboolean for_ /** * soup_cookie_jar_add_cookie: * @jar: a #SoupCookieJar - * @cookie: a #SoupCookie + * @cookie: (transfer full): a #SoupCookie * * Adds @cookie to @jar, emitting the 'changed' signal if we are modifying * an existing cookie or adding a valid new cookie ('valid' means @@ -510,7 +510,7 @@ soup_cookie_jar_add_cookie (SoupCookieJar *jar, SoupCookie *cookie) * soup_cookie_jar_add_cookie_with_first_party: * @jar: a #SoupCookieJar * @first_party: the URI for the main document - * @cookie: a #SoupCookie + * @cookie: (transfer full): a #SoupCookie * * Adds @cookie to @jar, emitting the 'changed' signal if we are modifying * an existing cookie or adding a valid new cookie ('valid' means -- cgit v1.2.1 From a62003b40bd4a7069dd30f84895068ff66f9144a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20Mazurs?= Date: Fri, 24 Aug 2012 13:14:40 +0300 Subject: Added Latvian translation --- po/LINGUAS | 1 + po/lv.po | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 po/lv.po diff --git a/po/LINGUAS b/po/LINGUAS index 4b85ad26..a4ead1a4 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -12,6 +12,7 @@ gu he id lt +lv mr nb pa diff --git a/po/lv.po b/po/lv.po new file mode 100644 index 00000000..d06d0988 --- /dev/null +++ b/po/lv.po @@ -0,0 +1,77 @@ +# Latvian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Tranzistors , 2012. +# Rūdolfs Mazurs , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-08-22 03:28+0000\n" +"PO-Revision-Date: 2012-08-24 13:13+0300\n" +"Last-Translator: Rūdolfs Mazurs \n" +"Language-Team: Latviešu \n" +"Language: lv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" +"X-Generator: Gtranslator 2.91.5\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Savienojums tika negaidīti pārtraukts" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Izvades buferis ir pārāk mazs" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Darbība tika atcelta" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Darbība bloķētu" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Nav sniegts URL" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Nederīgs “%s” URI — %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Nevarēja parsēt URI “%s”" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Neatbalstīta URI shēma “%s”" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Datora nosaukums ir IP adrese" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Nederīgs datora nosaukums" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Datora nosaukumam nav bāzes domēna" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Nepietiekami daudz domēnu" -- cgit v1.2.1 From 2e70097a13289f6e665e7bbe327d12d5b0d3cddb Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Fri, 24 Aug 2012 13:20:15 +0200 Subject: Avoid double free of hash key When soup_message_headers_get_content_disposition re-inserts the new filename we need to g_strdup the key or otherwise it will be freed by the hashtable key destroy func. https://bugzilla.gnome.org/show_bug.cgi?id=682569 --- libsoup/soup-message-headers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c index b9bab238..1dd53dda 100644 --- a/libsoup/soup-message-headers.c +++ b/libsoup/soup-message-headers.c @@ -1303,7 +1303,7 @@ soup_message_headers_get_content_disposition (SoupMessageHeaders *hdrs, char *filename = strrchr (orig_value, '/'); if (filename) - g_hash_table_insert (*params, orig_key, filename + 1); + g_hash_table_insert (*params, g_strdup (orig_key), filename + 1); } return TRUE; } -- cgit v1.2.1 From 8552f549530621cf167f77f9aa6beb20f9efa1ae Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 2 Aug 2012 13:02:06 -0400 Subject: SoupSessionAsync: rename vars to make tunnel_msg vs real msg clearer --- libsoup/soup-session-async.c | 64 +++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 6c8e1821..53cd8e41 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -126,26 +126,28 @@ message_completed (SoupMessage *msg, gpointer user_data) } static void -tunnel_complete (SoupMessageQueueItem *item) +tunnel_complete (SoupMessageQueueItem *tunnel_item) { - SoupSession *session = item->session; + SoupSession *session = tunnel_item->session; + SoupMessageQueueItem *item = tunnel_item->related; - soup_message_finished (item->msg); - if (item->related->msg->status_code) - item->related->state = SOUP_MESSAGE_FINISHING; + soup_message_finished (tunnel_item->msg); + if (item->msg->status_code) + item->state = SOUP_MESSAGE_FINISHING; else - soup_message_set_https_status (item->related->msg, item->conn); + soup_message_set_https_status (item->msg, item->conn); do_idle_run_queue (session); - soup_message_queue_item_unref (item->related); - soup_session_unqueue_item (session, item); soup_message_queue_item_unref (item); + soup_session_unqueue_item (session, tunnel_item); + soup_message_queue_item_unref (tunnel_item); } static void ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) { - SoupMessageQueueItem *item = user_data; + SoupMessageQueueItem *tunnel_item = user_data; + SoupMessageQueueItem *item = tunnel_item->related; if (SOUP_STATUS_IS_SUCCESSFUL (status)) { g_signal_connect (item->conn, "disconnected", @@ -153,50 +155,52 @@ ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); soup_connection_set_state (item->conn, SOUP_CONNECTION_IN_USE); - item->related->state = SOUP_MESSAGE_READY; + item->state = SOUP_MESSAGE_READY; } else { if (item->conn) soup_connection_disconnect (item->conn); - soup_message_set_status (item->related->msg, SOUP_STATUS_SSL_FAILED); + soup_message_set_status (item->msg, SOUP_STATUS_SSL_FAILED); } - tunnel_complete (item); + tunnel_complete (tunnel_item); } static void -tunnel_message_completed (SoupMessage *msg, gpointer user_data) +tunnel_message_completed (SoupMessage *tunnel_msg, gpointer user_data) { - SoupMessageQueueItem *item = user_data; - SoupSession *session = item->session; - - if (item->state == SOUP_MESSAGE_RESTARTING) { - soup_message_restarted (msg); - if (item->conn) { - item->state = SOUP_MESSAGE_RUNNING; - soup_session_send_queue_item (session, item, tunnel_message_completed); + SoupMessageQueueItem *tunnel_item = user_data; + SoupSession *session = tunnel_item->session; + SoupMessageQueueItem *item = tunnel_item->related; + + if (tunnel_item->state == SOUP_MESSAGE_RESTARTING) { + soup_message_restarted (tunnel_msg); + if (tunnel_item->conn) { + tunnel_item->state = SOUP_MESSAGE_RUNNING; + soup_session_send_queue_item (session, tunnel_item, + tunnel_message_completed); return; } - soup_message_set_status (msg, SOUP_STATUS_TRY_AGAIN); + soup_message_set_status (tunnel_msg, SOUP_STATUS_TRY_AGAIN); } - item->state = SOUP_MESSAGE_FINISHED; + tunnel_item->state = SOUP_MESSAGE_FINISHED; - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + if (!SOUP_STATUS_IS_SUCCESSFUL (tunnel_msg->status_code)) { if (item->conn) soup_connection_disconnect (item->conn); - if (msg->status_code == SOUP_STATUS_TRY_AGAIN) { - item->related->state = SOUP_MESSAGE_AWAITING_CONNECTION; - soup_message_queue_item_set_connection (item->related, NULL); + if (tunnel_msg->status_code == SOUP_STATUS_TRY_AGAIN) { + item->state = SOUP_MESSAGE_AWAITING_CONNECTION; + soup_message_queue_item_set_connection (item, NULL); } else - soup_message_set_status (item->related->msg, msg->status_code); + soup_message_set_status (item->msg, tunnel_msg->status_code); - tunnel_complete (item); + tunnel_complete (tunnel_item); return; } soup_connection_start_ssl_async (item->conn, item->cancellable, - ssl_tunnel_completed, item); + ssl_tunnel_completed, tunnel_item); } static void -- cgit v1.2.1 From 47744dda4fc8978aafdbdd4fc392205da6fcd668 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 10 Aug 2012 10:51:34 -0400 Subject: SoupSession: clean up message response when queueing To handle messages that get reused, we were calling soup_message_cleanup_response() from soup_message_send_request(). But it's better to do it sooner than that, like in soup_session_append_queue_item(). --- libsoup/soup-message-client-io.c | 1 - libsoup/soup-session.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c index 1310bb85..7c623681 100644 --- a/libsoup/soup-message-client-io.c +++ b/libsoup/soup-message-client-io.c @@ -150,7 +150,6 @@ soup_message_send_request (SoupMessageQueueItem *item, async_context = NULL; iostream = soup_socket_get_iostream (soup_connection_get_socket (item->conn)); - soup_message_cleanup_response (item->msg); soup_message_io_client (item, iostream, async_context, get_request_headers, parse_response_headers, diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 4d8836b4..865897e4 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1018,6 +1018,8 @@ soup_session_append_queue_item (SoupSession *session, SoupMessage *msg, SoupMessageQueueItem *item; SoupSessionHost *host; + soup_message_cleanup_response (msg); + item = soup_message_queue_append (priv->queue, msg, callback, user_data); g_mutex_lock (&priv->conn_lock); -- cgit v1.2.1 From 2e775bd7f8648fad7395cd0f63aa234bbb04675f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 14 Aug 2012 15:35:03 -0400 Subject: SoupConnection: fix up states during connection In particular, when doing an https CONNECT, make sure the connection never observably switches to the "IDLE" state. Add a test for this. --- libsoup/soup-connection.c | 14 +++-- libsoup/soup-session-async.c | 5 +- tests/connection-test.c | 133 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 10 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 48c3d00c..3c5c516a 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -432,6 +432,10 @@ clear_current_item (SoupConnection *conn) /* We're now effectively no longer proxying */ soup_uri_free (priv->proxy_uri); priv->proxy_uri = NULL; + + /* Nor are we actually IDLE... */ + if (priv->state == SOUP_CONNECTION_IDLE) + priv->state = SOUP_CONNECTION_IN_USE; } if (!soup_message_is_keepalive (item->msg) || !priv->reusable) @@ -936,7 +940,6 @@ void soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) { SoupConnectionPrivate *priv; - SoupConnectionState old_state; g_return_if_fail (SOUP_IS_CONNECTION (conn)); g_return_if_fail (state >= SOUP_CONNECTION_NEW && @@ -945,14 +948,13 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) g_object_freeze_notify (G_OBJECT (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - old_state = priv->state; priv->state = state; - if ((state == SOUP_CONNECTION_IDLE || - state == SOUP_CONNECTION_DISCONNECTED) && - old_state == SOUP_CONNECTION_IN_USE) + if (state == SOUP_CONNECTION_IDLE || + state == SOUP_CONNECTION_DISCONNECTED) clear_current_item (conn); - g_object_notify (G_OBJECT (conn), "state"); + if (priv->state == state) + g_object_notify (G_OBJECT (conn), "state"); g_object_thaw_notify (G_OBJECT (conn)); } diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 53cd8e41..90534e38 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -139,7 +139,6 @@ tunnel_complete (SoupMessageQueueItem *tunnel_item) do_idle_run_queue (session); soup_message_queue_item_unref (item); - soup_session_unqueue_item (session, tunnel_item); soup_message_queue_item_unref (tunnel_item); } @@ -152,9 +151,6 @@ ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) if (SOUP_STATUS_IS_SUCCESSFUL (status)) { g_signal_connect (item->conn, "disconnected", G_CALLBACK (connection_closed), item->session); - soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); - soup_connection_set_state (item->conn, SOUP_CONNECTION_IN_USE); - item->state = SOUP_MESSAGE_READY; } else { if (item->conn) @@ -185,6 +181,7 @@ tunnel_message_completed (SoupMessage *tunnel_msg, gpointer user_data) } tunnel_item->state = SOUP_MESSAGE_FINISHED; + soup_session_unqueue_item (session, tunnel_item); if (!SOUP_STATUS_IS_SUCCESSFUL (tunnel_msg->status_code)) { if (item->conn) diff --git a/tests/connection-test.c b/tests/connection-test.c index f8ff7c1d..f0a17034 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -5,6 +5,8 @@ #include "test-utils.h" +#include "libsoup/soup-connection.h" + SoupServer *server; SoupURI *base_uri; GMutex server_mutex; @@ -679,10 +681,138 @@ do_non_idempotent_connection_test (void) soup_test_session_abort_unref (session); } +#ifdef HAVE_APACHE + +#define HTTP_SERVER "http://127.0.0.1:47524" +#define HTTPS_SERVER "https://127.0.0.1:47525" +#define HTTP_PROXY "http://127.0.0.1:47526" + +static SoupConnectionState state_transitions[] = { + /* NEW -> */ SOUP_CONNECTION_CONNECTING, + /* CONNECTING -> */ SOUP_CONNECTION_IN_USE, + /* IDLE -> */ SOUP_CONNECTION_DISCONNECTED, + /* IN_USE -> */ SOUP_CONNECTION_IDLE, + + /* REMOTE_DISCONNECTED */ -1, + /* DISCONNECTED */ -1, +}; + +static const char *state_names[] = { + "NEW", "CONNECTING", "IDLE", "IN_USE", + "REMOTE_DISCONNECTED", "DISCONNECTED" +}; + +static void +connection_state_changed (GObject *object, GParamSpec *param, + gpointer user_data) +{ + SoupConnection *conn = SOUP_CONNECTION (object); + SoupConnectionState *state = user_data; + SoupConnectionState new_state; + + new_state = soup_connection_get_state (conn); + if (state_transitions[*state] != new_state) { + debug_printf (1, " Unexpected transition: %s -> %s\n", + state_names[*state], state_names[new_state]); + errors++; + } else { + debug_printf (2, " %s -> %s\n", + state_names[*state], state_names[new_state]); + } + + *state = new_state; +} + +static void +connection_created (SoupSession *session, SoupConnection *conn, + gpointer user_data) +{ + SoupConnectionState *state = user_data; + + *state = soup_connection_get_state (conn); + if (*state != SOUP_CONNECTION_NEW) { + debug_printf (1, " Unexpected initial state: %d\n", + *state); + errors++; + } + + g_signal_connect (conn, "notify::state", + G_CALLBACK (connection_state_changed), + state); +} + +static void +do_one_connection_state_test (SoupSession *session, const char *uri) +{ + SoupMessage *msg; + + msg = soup_message_new ("GET", uri); + soup_session_send_message (session, msg); + if (msg->status_code != SOUP_STATUS_OK) { + debug_printf (1, " Unexpected response: %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + g_object_unref (msg); + soup_session_abort (session); +} + +static void +do_connection_state_test_for_session (SoupSession *session) +{ + SoupConnectionState state; + SoupURI *proxy_uri; + + g_signal_connect (session, "connection-created", + G_CALLBACK (connection_created), + &state); + + debug_printf (1, " http\n"); + do_one_connection_state_test (session, HTTP_SERVER); + + debug_printf (1, " https\n"); + do_one_connection_state_test (session, HTTPS_SERVER); + + proxy_uri = soup_uri_new (HTTP_PROXY); + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + + debug_printf (1, " http with proxy\n"); + do_one_connection_state_test (session, HTTP_SERVER); + + debug_printf (1, " https with proxy\n"); + do_one_connection_state_test (session, HTTPS_SERVER); +} + +static void +do_connection_state_test (void) +{ + SoupSession *session; + + debug_printf (1, "\nConnection states\n"); + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_connection_state_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_connection_state_test_for_session (session); + soup_test_session_abort_unref (session); +} + +#endif + int main (int argc, char **argv) { test_init (argc, argv, NULL); +#ifdef HAVE_APACHE + apache_init (); +#endif server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_callback, "http", NULL); @@ -694,6 +824,9 @@ main (int argc, char **argv) do_max_conns_test (); do_non_persistent_connection_test (); do_non_idempotent_connection_test (); +#ifdef HAVE_APACHE + do_connection_state_test (); +#endif soup_uri_free (base_uri); soup_test_server_quit_unref (server); -- cgit v1.2.1 From 646f1cd7b54692a6b4b0f349c2e737745378be07 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 14 Aug 2012 15:37:32 -0400 Subject: SoupConnection: fix up ::event signal emissions And add a test to make sure that all expected events are emitted, in the correct order. --- libsoup/soup-connection.c | 50 ++++++++++---------- tests/connection-test.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 26 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 3c5c516a..d2746e8d 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -337,6 +337,20 @@ soup_connection_class_init (SoupConnectionClass *connection_class) G_PARAM_READABLE)); } +static void +soup_connection_event (SoupConnection *conn, + GSocketClientEvent event, + GIOStream *connection) +{ + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); + + if (!connection && priv->socket) + connection = soup_socket_get_connection (priv->socket); + + g_signal_emit (conn, signals[EVENT], 0, + event, connection); +} + static gboolean idle_timeout (gpointer conn) { @@ -394,11 +408,9 @@ set_current_item (SoupConnection *conn, SoupMessageQueueItem *item) g_signal_connect (item->msg, "restarted", G_CALLBACK (current_item_restarted), conn); - if (item->msg->method == SOUP_METHOD_CONNECT) { - g_signal_emit (conn, signals[EVENT], 0, - G_SOCKET_CLIENT_PROXY_NEGOTIATING, - soup_socket_get_connection (priv->socket)); - } else if (priv->state == SOUP_CONNECTION_IDLE) + if (item->msg->method == SOUP_METHOD_CONNECT) + soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATING, NULL); + else if (priv->state == SOUP_CONNECTION_IDLE) soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); g_object_thaw_notify (G_OBJECT (conn)); @@ -425,9 +437,7 @@ clear_current_item (SoupConnection *conn) if (item->msg->method == SOUP_METHOD_CONNECT && SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) { - g_signal_emit (conn, signals[EVENT], 0, - G_SOCKET_CLIENT_PROXY_NEGOTIATED, - soup_socket_get_connection (priv->socket)); + soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATED, NULL); /* We're now effectively no longer proxying */ soup_uri_free (priv->proxy_uri); @@ -445,20 +455,6 @@ clear_current_item (SoupConnection *conn) g_object_thaw_notify (G_OBJECT (conn)); } -static void -soup_connection_event (SoupConnection *conn, - GSocketClientEvent event, - GIOStream *connection) -{ - SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); - - if (!connection && priv->socket) - connection = soup_socket_get_connection (priv->socket); - - g_signal_emit (conn, signals[EVENT], 0, - event, connection); -} - static void proxy_socket_event (SoupSocket *socket, GSocketClientEvent event, @@ -774,9 +770,10 @@ soup_connection_start_ssl_sync (SoupConnection *conn, soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); status = soup_socket_handshake_sync (priv->socket, cancellable); - if (status == SOUP_STATUS_OK) + if (status == SOUP_STATUS_OK) { soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); - else if (status == SOUP_STATUS_TLS_FAILED) { + soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); + } else if (status == SOUP_STATUS_TLS_FAILED) { priv->ssl_fallback = TRUE; status = SOUP_STATUS_TRY_AGAIN; } @@ -790,9 +787,10 @@ start_ssl_completed (SoupSocket *socket, guint status, gpointer user_data) SoupConnectionAsyncConnectData *data = user_data; SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); - if (status == SOUP_STATUS_OK) + if (status == SOUP_STATUS_OK) { soup_connection_event (data->conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); - else if (status == SOUP_STATUS_TLS_FAILED) { + soup_connection_event (data->conn, G_SOCKET_CLIENT_COMPLETE, NULL); + } else if (status == SOUP_STATUS_TLS_FAILED) { priv->ssl_fallback = TRUE; status = SOUP_STATUS_TRY_AGAIN; } diff --git a/tests/connection-test.c b/tests/connection-test.c index f0a17034..b9dce7f5 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -804,6 +804,121 @@ do_connection_state_test (void) soup_test_session_abort_unref (session); } + +static const char *event_names[] = { + "RESOLVING", "RESOLVED", "CONNECTING", "CONNECTED", + "PROXY_NEGOTIATING", "PROXY_NEGOTIATED", + "TLS_HANDSHAKING", "TLS_HANDSHAKED", "COMPLETE" +}; + +static const char event_abbrevs[] = { + 'r', 'R', 'c', 'C', 'p', 'P', 't', 'T', 'x', '\0' +}; + +static const char * +event_name_from_abbrev (char abbrev) +{ + int evt; + + for (evt = 0; event_abbrevs[evt]; evt++) { + if (event_abbrevs[evt] == abbrev) + return event_names[evt]; + } + return "???"; +} + +static void +network_event (SoupMessage *msg, GSocketClientEvent event, + GIOStream *connection, gpointer user_data) +{ + const char **events = user_data; + + if (!**events) { + debug_printf (1, " Unexpected event: %s\n", + event_names[event]); + errors++; + } else { + if (**events == event_abbrevs[event]) + debug_printf (2, " %s\n", event_names[event]); + else { + debug_printf (1, " Unexpected event: %s (expected %s)\n", + event_names[event], + event_name_from_abbrev (**events)); + errors++; + } + *events = *events + 1; + } +} + +static void +do_one_connection_event_test (SoupSession *session, const char *uri, + const char *events) +{ + SoupMessage *msg; + + msg = soup_message_new ("GET", uri); + g_signal_connect (msg, "network-event", + G_CALLBACK (network_event), + &events); + soup_session_send_message (session, msg); + if (msg->status_code != SOUP_STATUS_OK) { + debug_printf (1, " Unexpected response: %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } else { + while (*events) { + debug_printf (1, " Expected %s\n", + event_name_from_abbrev (*events)); + events++; + errors++; + } + } + g_object_unref (msg); + soup_session_abort (session); +} + +static void +do_connection_event_test_for_session (SoupSession *session) +{ + SoupURI *proxy_uri; + + debug_printf (1, " http\n"); + do_one_connection_event_test (session, HTTP_SERVER, "rRcCx"); + + debug_printf (1, " https\n"); + do_one_connection_event_test (session, HTTPS_SERVER, "rRcCtTx"); + + proxy_uri = soup_uri_new (HTTP_PROXY); + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy_uri, + NULL); + soup_uri_free (proxy_uri); + + debug_printf (1, " http with proxy\n"); + do_one_connection_event_test (session, HTTP_SERVER, "rRcCx"); + + debug_printf (1, " https with proxy\n"); + do_one_connection_event_test (session, HTTPS_SERVER, "rRcCpPtTx"); +} + +static void +do_connection_event_test (void) +{ + SoupSession *session; + + debug_printf (1, "\nConnection events\n"); + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_connection_event_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_connection_event_test_for_session (session); + soup_test_session_abort_unref (session); +} + #endif int @@ -826,6 +941,7 @@ main (int argc, char **argv) do_non_idempotent_connection_test (); #ifdef HAVE_APACHE do_connection_state_test (); + do_connection_event_test (); #endif soup_uri_free (base_uri); -- cgit v1.2.1 From 95396a8b447160781f7db8b5ab9bb4bb95fad32b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 14 Aug 2012 20:57:00 -0400 Subject: SoupSession: move all connection tracking into the base class Since SoupConnection:state is more reliable now, SoupSession can keep track of when connections are available itself, rather than the subclasses trying to guess when connections are available. --- libsoup/soup-session-async.c | 19 +++---------------- libsoup/soup-session-sync.c | 3 --- libsoup/soup-session.c | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 90534e38..46dac509 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -105,15 +105,6 @@ soup_session_async_new_with_options (const char *optname1, ...) return session; } -static void -connection_closed (SoupConnection *conn, gpointer session) -{ - /* Run the queue in case anyone was waiting for a connection - * to be closed. - */ - do_idle_run_queue (session); -} - static void message_completed (SoupMessage *msg, gpointer user_data) { @@ -148,11 +139,9 @@ ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) SoupMessageQueueItem *tunnel_item = user_data; SoupMessageQueueItem *item = tunnel_item->related; - if (SOUP_STATUS_IS_SUCCESSFUL (status)) { - g_signal_connect (item->conn, "disconnected", - G_CALLBACK (connection_closed), item->session); + if (SOUP_STATUS_IS_SUCCESSFUL (status)) item->state = SOUP_MESSAGE_READY; - } else { + else { if (item->conn) soup_connection_disconnect (item->conn); soup_message_set_status (item->msg, SOUP_STATUS_SSL_FAILED); @@ -243,8 +232,6 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) } item->state = SOUP_MESSAGE_READY; - g_signal_connect (conn, "disconnected", - G_CALLBACK (connection_closed), session); run_queue ((SoupSessionAsync *)session); soup_message_queue_item_unref (item); } @@ -309,7 +296,7 @@ process_queue_item (SoupMessageQueueItem *item, item->callback (session, item->msg, item->callback_data); else if (item->new_api) send_request_finished (session, item); - do_idle_run_queue (session); + soup_message_queue_item_unref (item); return; diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index 81410c57..987d55dd 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -277,7 +277,6 @@ process_queue_item (SoupMessageQueueItem *item) item->state = SOUP_MESSAGE_FINISHED; soup_message_finished (item->msg); soup_session_unqueue_item (session, item); - g_cond_broadcast (&priv->cond); break; default: @@ -421,9 +420,7 @@ soup_session_sync_kick (SoupSession *session) { SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session); - g_mutex_lock (&priv->lock); g_cond_broadcast (&priv->cond); - g_mutex_unlock (&priv->lock); } static void diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 865897e4..c337c57c 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1167,6 +1167,18 @@ connection_disconnected (SoupConnection *conn, gpointer user_data) g_mutex_unlock (&priv->conn_lock); g_object_unref (conn); + + SOUP_SESSION_GET_CLASS (session)->kick (session); +} + +static void +connection_state_changed (GObject *object, GParamSpec *param, gpointer user_data) +{ + SoupSession *session = user_data; + SoupConnection *conn = SOUP_CONNECTION (object); + + if (soup_connection_get_state (conn) == SOUP_CONNECTION_IDLE) + SOUP_SESSION_GET_CLASS (session)->kick (session); } SoupMessageQueueItem * @@ -1263,6 +1275,9 @@ soup_session_get_connection (SoupSession *session, g_signal_connect (conn, "disconnected", G_CALLBACK (connection_disconnected), session); + g_signal_connect (conn, "notify::state", + G_CALLBACK (connection_state_changed), + session); g_signal_emit (session, signals[CONNECTION_CREATED], 0, conn); -- cgit v1.2.1 From 4d3762940fbce8b7db14ae57a97e476fec64840d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 2 Aug 2012 12:06:37 -0400 Subject: SoupSession: merge AWAITING_CONNECTION state into STARTING The only thing STARTING did was move directly into AWAITING_CONNECTION, so there's no need for two separate states. --- libsoup/soup-message-queue.h | 1 - libsoup/soup-session-async.c | 8 ++------ libsoup/soup-session-sync.c | 8 ++------ 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index 54c2971f..cd153813 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -15,7 +15,6 @@ G_BEGIN_DECLS typedef enum { SOUP_MESSAGE_STARTING, - SOUP_MESSAGE_AWAITING_CONNECTION, SOUP_MESSAGE_GOT_CONNECTION, SOUP_MESSAGE_CONNECTING, SOUP_MESSAGE_CONNECTED, diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 46dac509..dee7d927 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -176,7 +176,7 @@ tunnel_message_completed (SoupMessage *tunnel_msg, gpointer user_data) if (item->conn) soup_connection_disconnect (item->conn); if (tunnel_msg->status_code == SOUP_STATUS_TRY_AGAIN) { - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; + item->state = SOUP_MESSAGE_STARTING; soup_message_queue_item_set_connection (item, NULL); } else soup_message_set_status (item->msg, tunnel_msg->status_code); @@ -209,7 +209,7 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) if (status == SOUP_STATUS_TRY_AGAIN) { soup_message_queue_item_set_connection (item, NULL); - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; + item->state = SOUP_MESSAGE_STARTING; } else { soup_session_set_item_status (session, item, status); item->state = SOUP_MESSAGE_FINISHING; @@ -252,10 +252,6 @@ process_queue_item (SoupMessageQueueItem *item, switch (item->state) { case SOUP_MESSAGE_STARTING: - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; - break; - - case SOUP_MESSAGE_AWAITING_CONNECTION: if (!soup_session_get_connection (session, item, should_prune)) return; diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index 987d55dd..d753f573 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -237,16 +237,12 @@ process_queue_item (SoupMessageQueueItem *item) switch (item->state) { case SOUP_MESSAGE_STARTING: - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; - break; - - case SOUP_MESSAGE_AWAITING_CONNECTION: g_mutex_lock (&priv->lock); do { get_connection (item); - if (item->state == SOUP_MESSAGE_AWAITING_CONNECTION) + if (item->state == SOUP_MESSAGE_STARTING) g_cond_wait (&priv->cond, &priv->lock); - } while (item->state == SOUP_MESSAGE_AWAITING_CONNECTION); + } while (item->state == SOUP_MESSAGE_STARTING); g_mutex_unlock (&priv->lock); break; -- cgit v1.2.1 From 8e3295ba9852660b90f747372e29c55044e1b3f1 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 10 Aug 2012 10:42:21 -0400 Subject: SoupSessionAsync: move more logic into process_queue_item() Move various logic from the post-connect and post-tunnel callbacks into process_queue_item(). --- libsoup/soup-session-async.c | 121 ++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 71 deletions(-) diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index dee7d927..ffc306ae 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -117,37 +117,24 @@ message_completed (SoupMessage *msg, gpointer user_data) } static void -tunnel_complete (SoupMessageQueueItem *tunnel_item) +ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) { - SoupSession *session = tunnel_item->session; + SoupMessageQueueItem *tunnel_item = user_data; SoupMessageQueueItem *item = tunnel_item->related; + SoupSession *session = item->session; soup_message_finished (tunnel_item->msg); - if (item->msg->status_code) - item->state = SOUP_MESSAGE_FINISHING; - else - soup_message_set_https_status (item->msg, item->conn); - - do_idle_run_queue (session); - soup_message_queue_item_unref (item); soup_message_queue_item_unref (tunnel_item); -} - -static void -ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) -{ - SoupMessageQueueItem *tunnel_item = user_data; - SoupMessageQueueItem *item = tunnel_item->related; - if (SOUP_STATUS_IS_SUCCESSFUL (status)) - item->state = SOUP_MESSAGE_READY; - else { - if (item->conn) - soup_connection_disconnect (item->conn); - soup_message_set_status (item->msg, SOUP_STATUS_SSL_FAILED); + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + soup_connection_disconnect (item->conn); + soup_message_queue_item_set_connection (item, NULL); + soup_message_set_status (item->msg, status); } - tunnel_complete (tunnel_item); + item->state = SOUP_MESSAGE_READY; + do_idle_run_queue (session); + soup_message_queue_item_unref (item); } static void @@ -172,21 +159,13 @@ tunnel_message_completed (SoupMessage *tunnel_msg, gpointer user_data) tunnel_item->state = SOUP_MESSAGE_FINISHED; soup_session_unqueue_item (session, tunnel_item); - if (!SOUP_STATUS_IS_SUCCESSFUL (tunnel_msg->status_code)) { - if (item->conn) - soup_connection_disconnect (item->conn); - if (tunnel_msg->status_code == SOUP_STATUS_TRY_AGAIN) { - item->state = SOUP_MESSAGE_STARTING; - soup_message_queue_item_set_connection (item, NULL); - } else - soup_message_set_status (item->msg, tunnel_msg->status_code); - - tunnel_complete (tunnel_item); - return; + if (SOUP_STATUS_IS_SUCCESSFUL (tunnel_msg->status_code)) { + soup_connection_start_ssl_async (item->conn, item->cancellable, + ssl_tunnel_completed, tunnel_item); + } else { + ssl_tunnel_completed (item->conn, tunnel_msg->status_code, + tunnel_item); } - - soup_connection_start_ssl_async (item->conn, item->cancellable, - ssl_tunnel_completed, tunnel_item); } static void @@ -197,41 +176,14 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) if (item->state != SOUP_MESSAGE_CONNECTING) { soup_connection_disconnect (conn); - do_idle_run_queue (session); - soup_message_queue_item_unref (item); - return; - } - - soup_message_set_https_status (item->msg, conn); - - if (status != SOUP_STATUS_OK) { - soup_connection_disconnect (conn); - - if (status == SOUP_STATUS_TRY_AGAIN) { - soup_message_queue_item_set_connection (item, NULL); - item->state = SOUP_MESSAGE_STARTING; - } else { - soup_session_set_item_status (session, item, status); - item->state = SOUP_MESSAGE_FINISHING; - } - - do_idle_run_queue (session); - soup_message_queue_item_unref (item); - return; - } - - if (soup_connection_is_tunnelled (conn)) { - SoupMessageQueueItem *tunnel_item; - - item->state = SOUP_MESSAGE_TUNNELING; - - tunnel_item = soup_session_make_connect_message (session, conn); - tunnel_item->related = item; - soup_session_send_queue_item (session, tunnel_item, tunnel_message_completed); - return; - } + } else if (status != SOUP_STATUS_OK) { + soup_session_set_item_status (session, item, status); + soup_connection_disconnect (item->conn); + soup_message_queue_item_set_connection (item, NULL); + item->state = SOUP_MESSAGE_READY; + } else + item->state = SOUP_MESSAGE_CONNECTED; - item->state = SOUP_MESSAGE_READY; run_queue ((SoupSessionAsync *)session); soup_message_queue_item_unref (item); } @@ -266,7 +218,34 @@ process_queue_item (SoupMessageQueueItem *item, got_connection, item); return; + case SOUP_MESSAGE_CONNECTED: + if (soup_connection_is_tunnelled (item->conn)) { + SoupMessageQueueItem *tunnel_item; + + soup_message_queue_item_ref (item); + + item->state = SOUP_MESSAGE_TUNNELING; + + tunnel_item = soup_session_make_connect_message (session, item->conn); + tunnel_item->related = item; + soup_session_send_queue_item (session, tunnel_item, tunnel_message_completed); + return; + } + + item->state = SOUP_MESSAGE_READY; + break; + case SOUP_MESSAGE_READY: + soup_message_set_https_status (item->msg, item->conn); + if (item->msg->status_code) { + if (item->msg->status_code == SOUP_STATUS_TRY_AGAIN) { + soup_message_cleanup_response (item->msg); + item->state = SOUP_MESSAGE_STARTING; + } else + item->state = SOUP_MESSAGE_FINISHING; + break; + } + item->state = SOUP_MESSAGE_RUNNING; soup_session_send_queue_item (session, item, message_completed); if (item->new_api) -- cgit v1.2.1 From 94082c129374b288d9a409ecc09fccd88fd8bf9a Mon Sep 17 00:00:00 2001 From: eukim Date: Sun, 26 Aug 2012 14:58:46 +0900 Subject: Add Korean translation --- po/LINGUAS | 1 + po/ko.po | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 po/ko.po diff --git a/po/LINGUAS b/po/LINGUAS index a4ead1a4..f1b3b6b2 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -11,6 +11,7 @@ gl gu he id +ko lt lv mr diff --git a/po/ko.po b/po/ko.po new file mode 100644 index 00000000..3d83be9e --- /dev/null +++ b/po/ko.po @@ -0,0 +1,74 @@ +# Korean translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# eukim , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-08-12 00:04+0000\n" +"PO-Revision-Date: 2012-08-26 14:57+0900\n" +"Last-Translator: eukim \n" +"Language-Team: Korean \n" +"Language: ko\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Lokalize 1.0\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "예상치 않게 연결이 중지됨" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "출력 버퍼가 너무 작음" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "작업이 취소됨" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "작업이 차단됨" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI이 제공되지 않음" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "잘못된 '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s'을(를) 구문 분석할 수 없음" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "지원하지 않는 URI 스킴 '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "호스트 이름은 IP 주소임" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "잘못된 호스트 이름" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "호스트 이름에 기본 도메인이 없음" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "도메인이 충분하지 않음" -- cgit v1.2.1 From f956ed3536f858b6150d32669f26ffd7a0107c1c Mon Sep 17 00:00:00 2001 From: Takayuki KUSANO Date: Mon, 27 Aug 2012 23:50:37 +0900 Subject: Add new Japanese translation --- po/LINGUAS | 1 + po/ja.po | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 po/ja.po diff --git a/po/LINGUAS b/po/LINGUAS index f1b3b6b2..4f59d26b 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -11,6 +11,7 @@ gl gu he id +ja ko lt lv diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 00000000..1f254006 --- /dev/null +++ b/po/ja.po @@ -0,0 +1,73 @@ +# libsoup ja.po +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Takayuki KUSANO , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-08-26 05:59+0000\n" +"PO-Revision-Date: 2012-08-27 21:40+0900\n" +"Last-Translator: Takayuki KUSANO \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "接続が突然切断されました" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "出力バッファーが小さすぎます" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "動作が中止されました" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "動作はブロックします" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI が与えられていません" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "不正なスキーム '%s' の URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' をパースできませんでした" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "サポートされていない URI のスキーム '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "ホスト名が IP アドレスです" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "不正なホスト名です" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "ホスト名にトップレベルドメインがありません" + +# ソースコードと http://www.nic.ad.jp/ja/dom/system.html 参照 +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "ドメイン名が十分な数のラベルがありません" -- cgit v1.2.1 From 716a116eb3d0273187a8e92e62d18a021cb36985 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Sat, 1 Sep 2012 17:56:18 +0200 Subject: Updated French translation --- po/fr.po | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/po/fr.po b/po/fr.po index 44b5a22f..f0e0eb71 100644 --- a/po/fr.po +++ b/po/fr.po @@ -1,7 +1,7 @@ # French translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# FIRST AUTHOR , YEAR. +# # Pierre Henry , 2012. # Alain Lojewski , 2012. # @@ -10,50 +10,67 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-05-24 20:15+0000\n" -"PO-Revision-Date: 2012-05-24 19:14+0100\n" +"POT-Creation-Date: 2012-08-12 00:04+0000\n" +"PO-Revision-Date: 2012-09-01 17:56+0200\n" "Last-Translator: Alain Lojewski \n" "Language-Team: French \n" +"Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "La connexion a été interrompue de manière inattendue" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "La mémoire tampon de sortie est trop petite" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "L'opération a été annulée" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "L'opération aurait bloqué" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "Aucun URI fourni" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI « %s » non valide : %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Impossible d'analyser l'URI « %s »" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Le schéma d'URI « %s » n'est pas pris en charge" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Le nom d'hôte est une adresse IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Nom d'hôte non valide" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Le nom d'hôte n'a pas de domaine de base" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Pas assez de domaines" -- cgit v1.2.1 From a7c8b215a6a0f9bdd6d96d5f1e913b584290c226 Mon Sep 17 00:00:00 2001 From: "Dr.T.Vasudevan" Date: Sun, 2 Sep 2012 15:31:19 +0530 Subject: updated Tamil translation --- po/ta.po | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 po/ta.po diff --git a/po/ta.po b/po/ta.po new file mode 100644 index 00000000..e9458764 --- /dev/null +++ b/po/ta.po @@ -0,0 +1,76 @@ +# Tamil translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Dr.T.Vasudevan , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-01 15:56+0000\n" +"PO-Revision-Date: 2012-09-02 15:25+0530\n" +"Last-Translator: Dr.T.Vasudevan \n" +"Language-Team: Tamil \n" +"Language: ta\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.1\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "இணைப்பு எதிர்பாராமல் துண்டிக்கப்பட்டது" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "வெளியீட்டு இடைநினைவு மிகச்சிறியது" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "செயல்பாடு ரத்து செய்யப்பட்டது" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "செயல்பாடு தடை செய்யும்" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "யூஆர்ஐ ஏதும் தரப்படவில்லை" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "செல்லுபடியாகாத '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "'%s' யூஆர்ஐ ஐ அலகிட முடியவில்லை" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ஆதரவு இல்லாத யூஆர்ஐ திட்டம் '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "புரவலன் பெயர் ஒரு ஐபி முகவரி" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "செல்லுபடியாகாத கணிணிப்பெயர்" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "புரவலன் பெயருக்கு ஒரு செயற்களம் இல்லை" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "போதிய செயற்களம் இல்லை" + -- cgit v1.2.1 From 14355b978911d534b89ef06b123bd150b51beca9 Mon Sep 17 00:00:00 2001 From: "Dr.T.Vasudevan" Date: Sun, 2 Sep 2012 15:32:24 +0530 Subject: Added ta translation --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index 4f59d26b..95166781 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -24,6 +24,7 @@ ru sl sr sr@latin +ta te tr uk -- cgit v1.2.1 From d674aed919c908312553ba4cd22ce448c3824fb7 Mon Sep 17 00:00:00 2001 From: Daniel Nylander Date: Sun, 2 Sep 2012 12:37:14 +0200 Subject: Added Swedish translation --- po/LINGUAS | 1 + po/sv.po | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 po/sv.po diff --git a/po/LINGUAS b/po/LINGUAS index 95166781..321a3f66 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -24,6 +24,7 @@ ru sl sr sr@latin +sv ta te tr diff --git a/po/sv.po b/po/sv.po new file mode 100644 index 00000000..364abfa1 --- /dev/null +++ b/po/sv.po @@ -0,0 +1,75 @@ +# Swedish translation for libsoup. +# Copyright (C) 2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Daniel Nylander , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-02 12:00+0200\n" +"PO-Revision-Date: 2012-09-02 12:02+0100\n" +"Last-Translator: Daniel Nylander \n" +"Language-Team: Swedish \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 +#: ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Anslutningen avslutades oväntat" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Utmatningsbufferten är för liten" + +#: ../libsoup/soup-message-io.c:818 +#: ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Åtgärden avbröts" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Åtgärden skulle blockera" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Ingen URI angavs" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Ogiltig \"%s\"-URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Kunde inte tolka URI:n \"%s\"" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "URI-schemat \"%s\" stöds inte" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Värdnamnet är en IP-adress" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Ogiltigt värdnamn" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Värdnamnet har ingen basdomän" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Inte tillräckligt många domäner" + -- cgit v1.2.1 From ebb117daed1be6c400e08927da8806d3b5b38d60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aurimas=20=C4=8Cernius?= Date: Sun, 2 Sep 2012 15:29:56 +0300 Subject: Updated Lithuanian translation --- po/lt.po | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/po/lt.po b/po/lt.po index 30c6975b..a9c416ee 100644 --- a/po/lt.po +++ b/po/lt.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-14 11:19+0000\n" -"PO-Revision-Date: 2012-07-14 18:48+0300\n" +"POT-Creation-Date: 2012-07-16 22:04+0000\n" +"PO-Revision-Date: 2012-09-02 15:29+0300\n" "Last-Translator: Aurimas Černius \n" "Language-Team: Lithuanian \n" "Language: lt\n" @@ -20,7 +20,7 @@ msgstr "" #: ../libsoup/soup-body-input-stream.c:136 #: ../libsoup/soup-body-input-stream.c:167 #: ../libsoup/soup-body-input-stream.c:200 -#: ../libsoup/soup-message-io.c:193 +#: ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Ryšys netikėtai nutrūko" @@ -58,16 +58,20 @@ msgstr "Nepavyko perskaityti URI „%s“" msgid "Unsupported URI scheme '%s'" msgstr "Nepalaikoma URI schema „%s“" -#: ../libsoup/soup-tld.c:146 +#: ../libsoup/soup-tld.c:143 msgid "Hostname is an IP address" msgstr "Serverio vardas arba IP adresas" -#: ../libsoup/soup-tld.c:167 +#: ../libsoup/soup-tld.c:164 msgid "Invalid hostname" msgstr "Netinkamas serverio vardas" -#: ../libsoup/soup-tld.c:182 -#: ../libsoup/soup-tld.c:220 +#: ../libsoup/soup-tld.c:179 +#: ../libsoup/soup-tld.c:221 msgid "Not enough domains" msgstr "Nepakanka domenų" +#: ../libsoup/soup-tld.c:199 +msgid "Hostname has no base domain" +msgstr "Serverio vardas neturi bazinio domeno" + -- cgit v1.2.1 From 9b9ed982a529fc68447a2640a92d73da35fa508c Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Sun, 2 Sep 2012 13:03:12 +0200 Subject: Fix the win32 build Make sure glib.h is included before using G_OS_WIN32 ifdef. https://bugzilla.gnome.org/show_bug.cgi?id=683200 --- libsoup/soup-auth-digest.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libsoup/soup-auth-digest.c b/libsoup/soup-auth-digest.c index ccdbb2e5..97ef5616 100644 --- a/libsoup/soup-auth-digest.c +++ b/libsoup/soup-auth-digest.c @@ -10,14 +10,15 @@ #endif #include -#ifdef G_OS_WIN32 -#include -#endif #include "soup-auth-digest.h" #include "soup.h" #include "soup-message-private.h" +#ifdef G_OS_WIN32 +#include +#endif + typedef struct { char *user; char hex_urp[33]; -- cgit v1.2.1 From 4607faca5ae4bff978cb227a2a7fce73e7fb9fa6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 4 Sep 2012 09:07:20 -0400 Subject: 2.39.91 --- NEWS | 19 +++++++++++++++++++ configure.ac | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 514a94da..c0e6363c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,22 @@ +Changes in libsoup from 2.39.90 to 2.39.91: + + * Added missing (transfer full) annotation to + soup_cookie_jar_add_cookie() and + soup_cookie_jar_add_cookie_with_first_party(), fixing + crashes in bindings. [#682554, Daniel Drake] + + * Fixed a crash [#682569, Alexander Larsson] and a win32 build + problem [#683200, Kalev Lember] introduced by the memory + leak fixes in 2.39.90 + + * Fixed the SoupMessage:network-event signal, which had been + skipping the G_SOCKET_CLIENT_COMPLETE state in tunneled + https connections. And added a test for this. [Dan] + + * New/updated translations: + French, Japanese, Korean, Latvian, Lithuanian, Polish, + Punjabi, Swedish, Tamil + Changes in libsoup from 2.39.5 to 2.39.90: * Added SoupMultipartInputStream, for handling multipart diff --git a/configure.ac b/configure.ac index 95410de5..fb04d971 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *** Initialize automake and set version *** dnl ******************************************* AC_PREREQ(2.63) -AC_INIT([libsoup],[2.39.90],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[2.39.91],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -- cgit v1.2.1 From 5f523d99850d00d8ac80cf57675bad509d54ccc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Dr=C4=85g?= Date: Tue, 4 Sep 2012 19:05:18 +0200 Subject: Updated Polish translation --- po/pl.po | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/po/pl.po b/po/pl.po index f1503cc0..dc5dcd5a 100644 --- a/po/pl.po +++ b/po/pl.po @@ -4,12 +4,14 @@ # pomóc w jego rozwijaniu i pielęgnowaniu, napisz do nas: # gnomepl@aviary.pl # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +# Piotr Drąg , 2012. +# Aviary.pl , 2012. msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-22 02:59+0200\n" -"PO-Revision-Date: 2012-08-22 03:00+0200\n" +"POT-Creation-Date: 2012-09-04 19:04+0200\n" +"PO-Revision-Date: 2012-09-04 19:05+0200\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "Language: pl\n" -- cgit v1.2.1 From 3a96db1deee1b9259a45caabb4cb488e582471cf Mon Sep 17 00:00:00 2001 From: Bruce Cowan Date: Wed, 5 Sep 2012 13:47:39 +0100 Subject: Added British English translation --- po/LINGUAS | 1 + po/en_GB.po | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 po/en_GB.po diff --git a/po/LINGUAS b/po/LINGUAS index 321a3f66..f0d13f6c 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -4,6 +4,7 @@ bg bn_IN de el +en_GB eo es fr diff --git a/po/en_GB.po b/po/en_GB.po new file mode 100644 index 00000000..1e106add --- /dev/null +++ b/po/en_GB.po @@ -0,0 +1,75 @@ +# British English translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Bruce Cowan , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-04 17:05+0000\n" +"PO-Revision-Date: 2012-09-05 13:47+0100\n" +"Last-Translator: Bruce Cowan \n" +"Language-Team: British English \n" +"Language: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Connection terminated unexpectedly" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Output buffer is too small" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Operation was cancelled" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Operation would block" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "No URI provided" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Invalid '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Could not parse URI '%s'" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Unsupported URI scheme '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Hostname is an IP address" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Invalid hostname" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Hostname has no base domain" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Not enough domains" -- cgit v1.2.1 From 96fc865429ee5b34f2753e56754e19b0610c778b Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Wed, 5 Sep 2012 17:08:55 +0200 Subject: soup-cache: check for empy Cache-Control headers Some sites return empty "Cache-Control" headers. We should add an emptiness check to the existing NULL checks before trying to do things like soup_header_parse_param_list(). --- libsoup/soup-cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 51abbe56..50ea5928 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -331,7 +331,7 @@ soup_cache_entry_set_freshness (SoupCacheEntry *entry, SoupMessage *msg, SoupCac const char *expires, *date, *last_modified; cache_control = soup_message_headers_get_list (entry->headers, "Cache-Control"); - if (cache_control) { + if (cache_control && *cache_control) { const char *max_age, *s_maxage; gint64 freshness_lifetime = 0; GHashTable *hash; @@ -1348,7 +1348,7 @@ soup_cache_has_response (SoupCache *cache, SoupMessage *msg) return SOUP_CACHE_RESPONSE_STALE; cache_control = soup_message_headers_get_list (msg->request_headers, "Cache-Control"); - if (cache_control) { + if (cache_control && *cache_control) { GHashTable *hash = soup_header_parse_param_list (cache_control); if (g_hash_table_lookup_extended (hash, "no-store", NULL, NULL)) { -- cgit v1.2.1 From 194ba4c82272f1e7fea15c752fc426586289b720 Mon Sep 17 00:00:00 2001 From: Dirgita Date: Thu, 6 Sep 2012 10:49:50 +0700 Subject: Updated Indonesian translation --- po/id.po | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/po/id.po b/po/id.po index 336740cf..0f639f61 100644 --- a/po/id.po +++ b/po/id.po @@ -1,68 +1,76 @@ # Indonesian translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# Andika Triwidada , 2012. # +# Andika Triwidada , 2012. +# Dirgita , 2012. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-06-14 18:14+0000\n" -"PO-Revision-Date: 2012-06-28 10:25+0700\n" -"Last-Translator: Andika Triwidada \n" -"Language-Team: Indonesian \n" +"POT-Creation-Date: 2012-09-04 13:07+0000\n" +"PO-Revision-Date: 2012-09-04 17:31+0700\n" +"Last-Translator: Dirgita \n" +"Language-Team: Indonesian \n" +"Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.2\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Sambungan terputus secara tak diharapkan" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Penyangga keluaran terlalu kecil" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Operasi dibatalkan" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Operasi akan memblokir" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "URI tak diberikan" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI '%s' tak valid: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Tak bisa mengurai URI '%s'" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Skema URI '%s' tak didukung" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Nama host adalah suatu alamat IP" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Nama host tak valid" -#: ../libsoup/soup-tld.c:181 ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Nama host tidak memiliki domain dasar" + +#: ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "Tak cukup domain" -- cgit v1.2.1 From 4f628f8d92df686d94829eedb679c64f31722a96 Mon Sep 17 00:00:00 2001 From: Gabor Kelemen Date: Thu, 6 Sep 2012 16:00:23 +0200 Subject: Initial Hungarian translation added --- po/hu.po | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 po/hu.po diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 00000000..e7741a08 --- /dev/null +++ b/po/hu.po @@ -0,0 +1,75 @@ +# Hungarian translation of libsoup +# Copyright (C) 2012. Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# +# Gabor Kelemen , 2012. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-06 15:52+0200\n" +"PO-Revision-Date: 2012-09-06 15:58+0200\n" +"Last-Translator: Gabor Kelemen \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.4\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Kapcsolat váratlanul megszakítva" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "A kimeneti puffer túl kicsi" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "A művelet megszakítva" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "A művelet blokkoló lenne" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Nincs megadva URI" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Érvénytelen „%s” URI: „%s”" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Nem dolgozható fel a(z) „%s” URI" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Nem támogatott URI séma: „%s”" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "A gépnév egy IP-cím" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Érvénytelen gépnév" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "A gépnévnek nincs alap tartománya" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Nincs elég tartomány" + -- cgit v1.2.1 From 2730b232d2d6002863d17a5fa7273d2f76b0a521 Mon Sep 17 00:00:00 2001 From: Gabor Kelemen Date: Thu, 6 Sep 2012 16:00:44 +0200 Subject: Added hu to LINGUAS --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index f0d13f6c..c96366e3 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -11,6 +11,7 @@ fr gl gu he +hu id ja ko -- cgit v1.2.1 From 638aa6e28d708152cafe7ddbced952f5af2e6237 Mon Sep 17 00:00:00 2001 From: Milo Casagrande Date: Thu, 6 Sep 2012 23:06:23 +0200 Subject: [l10n] Added Italian translation. --- po/LINGUAS | 1 + po/it.po | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 po/it.po diff --git a/po/LINGUAS b/po/LINGUAS index c96366e3..34123495 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -13,6 +13,7 @@ gu he hu id +it ja ko lt diff --git a/po/it.po b/po/it.po new file mode 100644 index 00000000..74aa64e2 --- /dev/null +++ b/po/it.po @@ -0,0 +1,73 @@ +# Italian translations for libsoup package +# Copyright (C) 2012 the Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Milo Casagrande , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-06 23:05+0200\n" +"PO-Revision-Date: 2012-09-06 23:05+0200\n" +"Last-Translator: Milo Casagrande \n" +"Language-Team: Italian \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8-bit\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Connessione terminata inaspettatamente" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Il buffer di uscita è troppo piccolo" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "L'operazione è stata annullata" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "L'operazione potrebbe bloccarsi" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Nessun URI fornito" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI «%s» non valido: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Impossibile analizzare l'URI «%s»" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Schema URI «%s» non supportato" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Il nome host è un indirizzo IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Nome host non valido" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Il nome host non ha un dominio di base" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Domini insufficienti" -- cgit v1.2.1 From 701167c106abe0519773406a8f1f4930eaf06d80 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Fri, 7 Sep 2012 19:11:43 +0300 Subject: Updated Belarusian translation. --- po/be.po | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/po/be.po b/po/be.po index 53bcfe54..5ff8260d 100644 --- a/po/be.po +++ b/po/be.po @@ -5,62 +5,66 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-06-14 18:14+0000\n" -"PO-Revision-Date: 2012-07-15 14:23+0300\n" +"POT-Creation-Date: 2012-07-16 22:04+0000\n" +"PO-Revision-Date: 2012-09-07 19:11+0300\n" "Last-Translator: Ihar Hrachyshka \n" "Language-Team: Belarusian \n" +"Language: be\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: be\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Злучэнне нечакана перарвана" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-converter-wrapper.c:189 #, c-format msgid "Output buffer is too small" msgstr "Выхадны буфер надта малы" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 msgid "Operation was cancelled" msgstr "Аперацыя была скасавана" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:864 msgid "Operation would block" msgstr "Аперацыя заблакіруе працэс" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "URI-адрас не пададзены" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Хібны URI-адрас \"%s\": %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Не ўдалося разабраць URI-адрас \"%s\"" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "URI-схема \"%s\" не падтрымліваецца" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:143 msgid "Hostname is an IP address" msgstr "Назва хоста з'яўляецца IP-адрасам" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:164 msgid "Invalid hostname" msgstr "Хібная назва хоста" -#: ../libsoup/soup-tld.c:181 ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:179 ../libsoup/soup-tld.c:221 msgid "Not enough domains" msgstr "Не хапае даменаў" + +#: ../libsoup/soup-tld.c:199 +msgid "Hostname has no base domain" +msgstr "Назва хоста не мае базавага дамена" -- cgit v1.2.1 From 4ae3d48e1fa3e7ff49d81d1f2ed11dce234b9ce0 Mon Sep 17 00:00:00 2001 From: Arash Mousavi Date: Sat, 8 Sep 2012 01:00:20 +0430 Subject: l10n: Updated Persian translation --- po/fa.po | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 po/fa.po diff --git a/po/fa.po b/po/fa.po new file mode 100644 index 00000000..ed9d6af9 --- /dev/null +++ b/po/fa.po @@ -0,0 +1,73 @@ +# Persian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Arash Mousavi , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-07 16:15+0000\n" +"PO-Revision-Date: 2012-09-08 00:58+0330\n" +"Last-Translator: Arash Mousavi \n" +"Language-Team: Persian\n" +"Language: fa\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "اتصال به شکل غیرمنتظره‌ای بسته شد" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "میانگیر خروجی خیلی کوتاه است" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "عملیات لغو شده بود" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "عملیات می‌توانست بسته شود" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "هیچ URIای داده نشده است" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "«%s» نامعتبر URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "نمی‌توان URI را تجزیه کرد «%s»" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "شِما URI پشتیبانی نشده «%s»" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "نام میزبان یک آدرس آی‌پی است" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "نام‌میزبان نامعتبر" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "نام‌میزبان دامنه‌ی پایه ندارد" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "دامنه‌های کافی موجود نیست" -- cgit v1.2.1 From eb21d1ad14411a12753a60272d3804b42c5534b1 Mon Sep 17 00:00:00 2001 From: Arash Mousavi Date: Sat, 8 Sep 2012 01:03:34 +0430 Subject: l10n: Updated Persian translation --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index 34123495..b2700241 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -7,6 +7,7 @@ el en_GB eo es +fa fr gl gu -- cgit v1.2.1 From 6c979679d8f68a29c2b098c5c54b86aa77d1e7a2 Mon Sep 17 00:00:00 2001 From: "Gabriel F. Vilar" Date: Fri, 7 Sep 2012 22:40:29 -0400 Subject: Added Brazilian Portuguese translation, reviewed by Enrico Nicoletto --- po/LINGUAS | 1 + po/pt_BR.po | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 po/pt_BR.po diff --git a/po/LINGUAS b/po/LINGUAS index b2700241..1fccbd14 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -23,6 +23,7 @@ mr nb pa pl +pt_BR ro ru sl diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 00000000..2d236259 --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,73 @@ +# Brazilian Portuguese translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Gabriel F. Vilar , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-07 22:38-0400\n" +"PO-Revision-Date: 2012-09-07 21:55-0300\n" +"Last-Translator: Enrico Nicoletto \n" +"Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "A conexão terminou inesperadamente" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "O buffer de saída é muito pequeno" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "A operação foi cancelada" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "A operação será bloqueada" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Nenhuma URI foi fornecida" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI: %s inválida '%s'" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Não foi possível analisar URI '%s'" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Esquema de URI não suportado '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "O nome da máquina é um endereço de IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "O nome da máquina é inválido" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Nome da máquina não está na base do domínio" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Não há domínios suficientes" -- cgit v1.2.1 From 9e0f2ecd26d4d5835fb0a1ce03e3fcde70e9984b Mon Sep 17 00:00:00 2001 From: Duarte Loreto Date: Sun, 9 Sep 2012 02:08:24 +0100 Subject: Updated Portuguese translation --- po/LINGUAS | 1 + po/pt.po | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 po/pt.po diff --git a/po/LINGUAS b/po/LINGUAS index 1fccbd14..2a7dced8 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -23,6 +23,7 @@ mr nb pa pl +pt pt_BR ro ru diff --git a/po/pt.po b/po/pt.po new file mode 100644 index 00000000..994a940a --- /dev/null +++ b/po/pt.po @@ -0,0 +1,73 @@ +# libsoup's Portuguese translation. +# Copyright © 2012 libsoup +# This file is distributed under the same license as the libsoup package. +# Duarte Loreto , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: 3.6\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-08 02:40+0000\n" +"PO-Revision-Date: 2012-09-09 02:10+0100\n" +"Last-Translator: Duarte Loreto \n" +"Language-Team: Portuguese \n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Ligação terminou inesperadamente" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Buffer de resultado é demasiado pequeno" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "A operação foi cancelada" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "A operação iria bloquear" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Nenhum URI especificado" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI '%s' inválido: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Incapaz de processar o URI '%s'" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Esquema de URI '%s' não suportado" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Nome da máquina é um endereço IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Nome de máquina inválido" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Nome de máquina não possui domínio base" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Domínios insuficientes" -- cgit v1.2.1 From 350a9859dfec9c437c6b1044ad2ccacd8ff51bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C4=8Cernock=C3=BD?= Date: Sun, 9 Sep 2012 08:56:21 +0200 Subject: Added Czech language --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index 2a7dced8..d33c8b1a 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -2,6 +2,7 @@ as be bg bn_IN +cs de el en_GB -- cgit v1.2.1 From b6b21b451eaf1a3cfc9fb4ec66d1259b5da14eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C4=8Cernock=C3=BD?= Date: Sun, 9 Sep 2012 08:56:43 +0200 Subject: Czech translation --- po/cs.po | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 po/cs.po diff --git a/po/cs.po b/po/cs.po new file mode 100644 index 00000000..7046b2aa --- /dev/null +++ b/po/cs.po @@ -0,0 +1,75 @@ +# Czech translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Marek Černocký , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-09 00:53+0000\n" +"PO-Revision-Date: 2012-09-09 00:53+0000\n" +"Last-Translator: Marek Černocký \n" +"Language-Team: Czech \n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: ../libsoup/soup-body-input-stream.c:136 +#: ../libsoup/soup-body-input-stream.c:167 +#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Připojení bylo neočekávaně ukončeno" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Výstupní vyrovnávací paměť je příliš malá" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Operace byla zrušena" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Operace by blokovala" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Není poskytnuta žádná adresa URI" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Neplatná adresa URI „%s“: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Nelze analyzovat adresu URI „%s“" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Nepodporované schéma URI „%s“" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Název počítače je adresa IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Neplatný název počítače" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Název počítače nemá základní doménu" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Nedostatek domén" -- cgit v1.2.1 From 4b3a3a7205def4e179c40fe3c4986be4f34db7da Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 8 Sep 2012 15:29:21 -0400 Subject: SoupSession: add a missing signal disconnection Need to disconnect from notify::state when removing a connection. --- libsoup/soup-session.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index c337c57c..d35d6814 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -112,6 +112,9 @@ typedef struct { #define SOUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION, SoupSessionPrivate)) static void free_host (SoupSessionHost *host); +static void connection_state_changed (GObject *object, GParamSpec *param, + gpointer user_data); +static void connection_disconnected (SoupConnection *conn, gpointer user_data); static void auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg, SoupAuth *auth, @@ -1163,6 +1166,7 @@ connection_disconnected (SoupConnection *conn, gpointer user_data) } g_signal_handlers_disconnect_by_func (conn, connection_disconnected, session); + g_signal_handlers_disconnect_by_func (conn, connection_state_changed, session); priv->num_conns--; g_mutex_unlock (&priv->conn_lock); -- cgit v1.2.1 From 7736c2c6404a9c0dbb91d059cc3c685ce2758378 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 9 Sep 2012 09:48:41 -0400 Subject: SoupSession: ensure that no new connections are created after dispose() --- libsoup/soup-session.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index d35d6814..54f1a2d0 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -108,6 +108,8 @@ typedef struct { GResolver *resolver; char **http_aliases, **https_aliases; + + gboolean disposed; } SoupSessionPrivate; #define SOUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION, SoupSessionPrivate)) @@ -220,7 +222,9 @@ soup_session_dispose (GObject *object) SoupSession *session = SOUP_SESSION (object); SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + priv->disposed = TRUE; soup_session_abort (session); + g_warn_if_fail (g_hash_table_size (priv->conns) == 0); while (priv->features) soup_session_remove_feature (session, priv->features->data); @@ -821,8 +825,7 @@ get_host_for_message (SoupSession *session, SoupMessage *msg) static void free_host (SoupSessionHost *host) { - g_slist_free_full (host->connections, - (GDestroyNotify) soup_connection_disconnect); + g_warn_if_fail (host->connections == NULL); if (host->keep_alive_src) { g_source_destroy (host->keep_alive_src); @@ -1218,6 +1221,9 @@ soup_session_get_connection (SoupSession *session, int num_pending = 0; gboolean need_new_connection; + if (priv->disposed) + return FALSE; + if (item->conn) { g_return_val_if_fail (soup_connection_get_state (item->conn) != SOUP_CONNECTION_DISCONNECTED, FALSE); return TRUE; -- cgit v1.2.1 From 97db5d9cdea8fd4d8dca15e5d833c81bdf4dd40a Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 9 Sep 2012 10:19:00 -0400 Subject: SoupSession: when freeing an "unused" host, make sure it's still unused In a multithreaded session, it's possible that a new connection will be opened on a host while free_unused_host() is waiting to get conn_lock. So check for that before freeing it. https://bugzilla.gnome.org/show_bug.cgi?id=682923 --- libsoup/soup-session.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 54f1a2d0..d0a0e212 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1124,6 +1124,15 @@ free_unused_host (gpointer user_data) SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (host->session); g_mutex_lock (&priv->conn_lock); + + /* In a multithreaded session, a connection might have been + * added while we were waiting for conn_lock. + */ + if (host->connections) { + g_mutex_unlock (&priv->conn_lock); + return FALSE; + } + /* This will free the host in addition to removing it from the * hash table */ -- cgit v1.2.1 From f723ab8220488bcdbb639373631675a64b061d79 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Tue, 7 Aug 2012 20:16:01 +0200 Subject: SoupBodyInputStream: make it seekable SoupBodyInputStream implements now the GSeekable interface. It does not longer require a SoupFilterInputStream as base stream unless the encoding is SOUP_ENCODING_CHUNKED. https://bugzilla.gnome.org/show_bug.cgi?id=665884 --- libsoup/soup-body-input-stream.c | 136 +++++++++++++++++++++++++++++++++++++-- libsoup/soup-body-input-stream.h | 6 +- libsoup/soup-message-io.c | 2 +- 3 files changed, 136 insertions(+), 8 deletions(-) diff --git a/libsoup/soup-body-input-stream.c b/libsoup/soup-body-input-stream.c index ba4ce6a6..fff07803 100644 --- a/libsoup/soup-body-input-stream.c +++ b/libsoup/soup-body-input-stream.c @@ -33,6 +33,8 @@ struct _SoupBodyInputStreamPrivate { goffset read_length; SoupBodyInputStreamState chunked_state; gboolean eof; + + goffset pos; }; enum { @@ -50,10 +52,13 @@ enum { }; static void soup_body_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); +static void soup_body_input_stream_seekable_init (GSeekableIface *seekable_interface); G_DEFINE_TYPE_WITH_CODE (SoupBodyInputStream, soup_body_input_stream, G_TYPE_FILTER_INPUT_STREAM, G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, - soup_body_input_stream_pollable_init)) + soup_body_input_stream_pollable_init) + G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, + soup_body_input_stream_seekable_init)) static void soup_body_input_stream_init (SoupBodyInputStream *bistream) @@ -258,6 +263,9 @@ read_internal (GInputStream *stream, blocking, cancellable, error); if (bistream->priv->read_length != -1 && nread > 0) bistream->priv->read_length -= nread; + + if (bistream->priv->encoding == SOUP_ENCODING_CONTENT_LENGTH) + bistream->priv->pos += nread; return nread; default: @@ -265,6 +273,25 @@ read_internal (GInputStream *stream, } } +static gssize +soup_body_input_stream_skip (GInputStream *stream, + gsize count, + GCancellable *cancellable, + GError **error) +{ + SoupBodyInputStreamPrivate *priv = SOUP_BODY_INPUT_STREAM(stream)->priv; + gssize skipped; + + skipped = g_input_stream_skip (G_FILTER_INPUT_STREAM (stream)->base_stream, + MIN (count, priv->read_length), + cancellable, error); + + if (skipped != -1) + priv->pos += skipped; + + return skipped; +} + static gssize soup_body_input_stream_read_fn (GInputStream *stream, void *buffer, @@ -295,6 +322,15 @@ soup_body_input_stream_is_readable (GPollableInputStream *stream) g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (bistream->priv->base_stream)); } +static gboolean +soup_body_input_stream_can_poll (GPollableInputStream *pollable) +{ + GInputStream *base_stream = SOUP_BODY_INPUT_STREAM (pollable)->priv->base_stream; + + return G_IS_POLLABLE_INPUT_STREAM (base_stream) && + g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (base_stream)); +} + static gssize soup_body_input_stream_read_nonblocking (GPollableInputStream *stream, void *buffer, @@ -337,6 +373,7 @@ soup_body_input_stream_class_init (SoupBodyInputStreamClass *stream_class) object_class->set_property = soup_body_input_stream_set_property; object_class->get_property = soup_body_input_stream_get_property; + input_stream_class->skip = soup_body_input_stream_skip; input_stream_class->read_fn = soup_body_input_stream_read_fn; input_stream_class->close_fn = soup_body_input_stream_close_fn; @@ -370,16 +407,107 @@ static void soup_body_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data) { + pollable_interface->can_poll = soup_body_input_stream_can_poll; pollable_interface->is_readable = soup_body_input_stream_is_readable; pollable_interface->read_nonblocking = soup_body_input_stream_read_nonblocking; pollable_interface->create_source = soup_body_input_stream_create_source; } +static goffset +soup_body_input_stream_tell (GSeekable *seekable) +{ + return SOUP_BODY_INPUT_STREAM (seekable)->priv->pos; +} + +static gboolean +soup_body_input_stream_can_seek (GSeekable *seekable) +{ + SoupBodyInputStreamPrivate *priv = SOUP_BODY_INPUT_STREAM (seekable)->priv; + + return priv->encoding == SOUP_ENCODING_CONTENT_LENGTH + && G_IS_SEEKABLE (priv->base_stream) + && g_seekable_can_seek (G_SEEKABLE (priv->base_stream)); +} + +static gboolean +soup_body_input_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error) +{ + SoupBodyInputStreamPrivate *priv = SOUP_BODY_INPUT_STREAM (seekable)->priv; + goffset position, end_position; + + end_position = priv->pos + priv->read_length; + switch (type) { + case G_SEEK_CUR: + position = priv->pos + offset; + break; + case G_SEEK_SET: + position = offset; + break; + case G_SEEK_END: + position = end_position + offset; + break; + default: + g_return_val_if_reached (FALSE); + } + + if (position < 0 || position >= end_position) { + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Invalid seek request")); + return FALSE; + } + + if (!g_seekable_seek (G_SEEKABLE (priv->base_stream), position - priv->pos, + G_SEEK_CUR, cancellable, error)) + return FALSE; + + priv->pos = position; + + return TRUE; +} + +static gboolean +soup_body_input_stream_can_truncate (GSeekable *seekable) +{ + return FALSE; +} + +static gboolean +soup_body_input_stream_truncate_fn (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error) +{ + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Cannot truncate SoupBodyInputStream")); + return FALSE; +} + +static void +soup_body_input_stream_seekable_init (GSeekableIface *seekable_interface) +{ + seekable_interface->tell = soup_body_input_stream_tell; + seekable_interface->can_seek = soup_body_input_stream_can_seek; + seekable_interface->seek = soup_body_input_stream_seek; + seekable_interface->can_truncate = soup_body_input_stream_can_truncate; + seekable_interface->truncate_fn = soup_body_input_stream_truncate_fn; +} + GInputStream * -soup_body_input_stream_new (SoupFilterInputStream *base_stream, - SoupEncoding encoding, - goffset content_length) +soup_body_input_stream_new (GInputStream *base_stream, + SoupEncoding encoding, + goffset content_length) { + if (encoding == SOUP_ENCODING_CHUNKED) + g_return_val_if_fail (SOUP_IS_FILTER_INPUT_STREAM (base_stream), NULL); + return g_object_new (SOUP_TYPE_BODY_INPUT_STREAM, "base-stream", base_stream, "close-base-stream", FALSE, diff --git a/libsoup/soup-body-input-stream.h b/libsoup/soup-body-input-stream.h index 9e0c08e3..7732e5e5 100644 --- a/libsoup/soup-body-input-stream.h +++ b/libsoup/soup-body-input-stream.h @@ -39,9 +39,9 @@ typedef struct { GType soup_body_input_stream_get_type (void); -GInputStream *soup_body_input_stream_new (SoupFilterInputStream *base_stream, - SoupEncoding encoding, - goffset content_length); +GInputStream *soup_body_input_stream_new (GInputStream *base_stream, + SoupEncoding encoding, + goffset content_length); G_END_DECLS diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 6924e20c..52af22b5 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -231,7 +231,7 @@ setup_body_istream (SoupMessage *msg) GSList *d; io->body_istream = - soup_body_input_stream_new (io->istream, + soup_body_input_stream_new (G_INPUT_STREAM (io->istream), io->read_encoding, io->read_length); -- cgit v1.2.1 From 05eaf266fbe83f4e0b3ff08006e620a7be80a5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Dr=C4=85g?= Date: Mon, 10 Sep 2012 17:23:09 +0200 Subject: Updated Polish translation --- po/pl.po | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/po/pl.po b/po/pl.po index dc5dcd5a..e48d389a 100644 --- a/po/pl.po +++ b/po/pl.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-04 19:04+0200\n" -"PO-Revision-Date: 2012-09-04 19:05+0200\n" +"POT-Creation-Date: 2012-09-10 17:20+0200\n" +"PO-Revision-Date: 2012-09-10 17:23+0200\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "Language: pl\n" @@ -23,12 +23,20 @@ msgstr "" "X-Poedit-Language: Polish\n" "X-Poedit-Country: Poland\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Połączenie zostało nieoczekiwanie zakończone" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Nieprawidłowe żądanie przewinięcia" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Nie można skrócić SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 930bc170bc37cf83515a25d2aa04c19d1ac21006 Mon Sep 17 00:00:00 2001 From: Daniel Mustieles Date: Mon, 10 Sep 2012 18:19:58 +0200 Subject: Updated Spanish translation --- po/es.po | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/po/es.po b/po/es.po index 5b38be6e..ba6467cf 100644 --- a/po/es.po +++ b/po/es.po @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-16 22:04+0000\n" -"PO-Revision-Date: 2012-07-17 10:56+0200\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-10 18:07+0200\n" "Last-Translator: Daniel Mustieles \n" "Language-Team: Español \n" "Language: \n" @@ -19,22 +19,30 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "La conexión terminó inesperadamente" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Petición de búsqueda no válida" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No se puede truncar SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "El búfer de salida es demasiado pequeño" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Se canceló la operación" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "La operación se bloqueará" @@ -58,18 +66,18 @@ msgstr "No se pudo analizar el URI «%s»" msgid "Unsupported URI scheme '%s'" msgstr "Esquema %s de URI no soportado" -#: ../libsoup/soup-tld.c:143 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "El nombre del equipo es una dirección IP" -#: ../libsoup/soup-tld.c:164 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "El nombre del equipo no es válido" -#: ../libsoup/soup-tld.c:179 ../libsoup/soup-tld.c:221 -msgid "Not enough domains" -msgstr "No hay suficientes dominios" - -#: ../libsoup/soup-tld.c:199 +#: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "El nombre del equipo no tiene un dominio base" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "No hay suficientes dominios" -- cgit v1.2.1 From 059a5353edd06bcf399d0a75a7687c6ff7bcd48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C4=8Cernock=C3=BD?= Date: Mon, 10 Sep 2012 18:26:31 +0200 Subject: Czech translation --- po/cs.po | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/po/cs.po b/po/cs.po index 7046b2aa..ff495e02 100644 --- a/po/cs.po +++ b/po/cs.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-09 00:53+0000\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" "PO-Revision-Date: 2012-09-09 00:53+0000\n" "Last-Translator: Marek Černocký \n" "Language-Team: Czech \n" @@ -19,12 +19,20 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Připojení bylo neočekávaně ukončeno" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Neplatný požadavek na posun" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Nelze zkrátit SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From f9c454cf1f5a1cec8b10a45c4242f6140c66c869 Mon Sep 17 00:00:00 2001 From: Tom Tryfonidis Date: Mon, 10 Sep 2012 21:43:41 +0300 Subject: Updated Greek translation --- po/el.po | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/po/el.po b/po/el.po index 11dae732..60cb80b7 100644 --- a/po/el.po +++ b/po/el.po @@ -6,9 +6,10 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-16 22:04+0000\n" -"PO-Revision-Date: 2012-07-20 13:58+0200\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-10 21:43+0200\n" "Last-Translator: Tom Tryfonidis \n" "Language-Team: Greek \n" "Language: el\n" @@ -17,24 +18,30 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 -#: ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Η σύνδεση τερματίστηκε απρόσμενα" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Άκυρη αίτηση αναζήτησης" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Αδυναμία περικοπής του SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Η ενδιάμεση μνήμη εξόδου είναι πολύ μικρή" -#: ../libsoup/soup-message-io.c:817 -#: ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Η λειτουργία ακυρώθηκε" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Η λειτουργία θα μπλοκαριστεί" @@ -58,20 +65,18 @@ msgstr "Αδυναμία ανάλυσης URI '%s'" msgid "Unsupported URI scheme '%s'" msgstr "Μη υποστηριζόμενο URI σχήμα '%s'" -#: ../libsoup/soup-tld.c:143 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Το όνομα συστήματος είναι μια διεύθυνση IP" -#: ../libsoup/soup-tld.c:164 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Μη έγκυρο όνομα συστήματος" -#: ../libsoup/soup-tld.c:179 -#: ../libsoup/soup-tld.c:221 -msgid "Not enough domains" -msgstr "Δεν υπάρχουν αρκετοί τομείς" - -#: ../libsoup/soup-tld.c:199 +#: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "Το όνομα συστήματος δεν έχει βασικό τομέα" +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Δεν υπάρχουν αρκετοί τομείς" -- cgit v1.2.1 From 71178a5f776241f3ac0af5fe981acc81d17fc2f5 Mon Sep 17 00:00:00 2001 From: Milo Casagrande Date: Mon, 10 Sep 2012 21:10:03 +0200 Subject: [l10n] Updated Italian translation. --- po/it.po | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/po/it.po b/po/it.po index 74aa64e2..3d66d3cc 100644 --- a/po/it.po +++ b/po/it.po @@ -1,15 +1,15 @@ # Italian translations for libsoup package # Copyright (C) 2012 the Free Software Foundation, Inc. # This file is distributed under the same license as the libsoup package. -# Milo Casagrande , 2012. +# Milo Casagrande , 2012. # msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-06 23:05+0200\n" -"PO-Revision-Date: 2012-09-06 23:05+0200\n" -"Last-Translator: Milo Casagrande \n" +"POT-Creation-Date: 2012-09-10 21:08+0200\n" +"PO-Revision-Date: 2012-09-10 21:09+0200\n" +"Last-Translator: Milo Casagrande \n" "Language-Team: Italian \n" "Language: it\n" "MIME-Version: 1.0\n" @@ -17,12 +17,20 @@ msgstr "" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Connessione terminata inaspettatamente" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Richiesta di posizionamento non valida" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Impossibile troncare SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From f4881c442dc3e9183c2872bf0023005f0966d378 Mon Sep 17 00:00:00 2001 From: Nilamdyuti Goswami Date: Tue, 11 Sep 2012 21:16:32 +0530 Subject: Assamese translation updated --- po/as.po | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/po/as.po b/po/as.po index 011d2c01..ec6d8ac8 100644 --- a/po/as.po +++ b/po/as.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." "cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-16 22:04+0000\n" -"PO-Revision-Date: 2012-08-03 15:38+0530\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-11 21:15+0530\n" "Last-Translator: Nilamdyuti Goswami \n" "Language-Team: as_IN \n" "Language: as\n" @@ -19,22 +19,30 @@ msgstr "" "X-Generator: Lokalize 1.0\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "সংযোগ অপ্ৰত্যাশিতভাৱে অন্ত হল" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "অবৈধ সন্ধান অনুৰোধ" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream চুটি কৰিব নোৱাৰি" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "আউটপুট বাফাৰ অতি সৰু" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "কাৰ্য্য বাতিল কৰা হৈছিল" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "কাৰ্য্য প্ৰতিৰোধ কৰিব" @@ -58,19 +66,19 @@ msgstr "URI '%s' বিশ্লেষণ কৰিব পৰা নগল" msgid "Unsupported URI scheme '%s'" msgstr "অসমৰ্থিত URl আঁচনি '%s'" -#: ../libsoup/soup-tld.c:143 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "হস্টনাম এটা IP ঠিকনা" -#: ../libsoup/soup-tld.c:164 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "অবৈধ হস্টনাম" -#: ../libsoup/soup-tld.c:179 ../libsoup/soup-tld.c:221 -msgid "Not enough domains" -msgstr "পৰ্যাপ্ত ডমেইন নাই" - -#: ../libsoup/soup-tld.c:199 +#: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "হস্টনামৰ কোনো ভিত্তি ডমেইন নাই" +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "পৰ্যাপ্ত ডমেইন নাই" + -- cgit v1.2.1 From 2590e3e21d4224a193b11d6c5c915a8722f49ce4 Mon Sep 17 00:00:00 2001 From: Andika Triwidada Date: Tue, 11 Sep 2012 23:45:50 +0700 Subject: Updated Indonesian translation --- po/id.po | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/po/id.po b/po/id.po index 0f639f61..0cefc660 100644 --- a/po/id.po +++ b/po/id.po @@ -9,23 +9,31 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-04 13:07+0000\n" -"PO-Revision-Date: 2012-09-04 17:31+0700\n" -"Last-Translator: Dirgita \n" -"Language-Team: Indonesian \n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-11 23:45+0700\n" +"Last-Translator: Andika Triwidada \n" +"Language-Team: Indonesian \n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 1.2\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" +"Plural-Forms: nplurals=1; plural=0;\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Sambungan terputus secara tak diharapkan" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Permintaan seek yang tak valid" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Tak bisa memenggal SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 9f12696825faf9cbaa16c52c15f908f886c20d57 Mon Sep 17 00:00:00 2001 From: Martin Srebotnjak Date: Tue, 11 Sep 2012 19:36:54 +0200 Subject: Updated Slovenian translation --- po/sl.po | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/po/sl.po b/po/sl.po index b38e1b0c..869a94d8 100644 --- a/po/sl.po +++ b/po/sl.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-18 21:44+0000\n" -"PO-Revision-Date: 2012-07-19 09:57+0100\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-10 21:37+0100\n" "Last-Translator: Matej Urbančič \n" "Language-Team: Slovenian \n" "Language: sl\n" @@ -21,24 +21,32 @@ msgstr "" "X-Poedit-Country: SLOVENIA\n" "X-Poedit-SourceCharset: utf-8\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 #: ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Povezava je nepričakovano končana" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Neveljavna zahteva iskanja" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Ni mogoče porezati SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Odvodni medpomnilnik je premajhen." -#: ../libsoup/soup-message-io.c:817 -#: ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 +#: ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Opravilo je preklicano." -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Opravilo bi zaustavilo delovanje" @@ -62,20 +70,19 @@ msgstr "Ni mogoče razčleniti naslova URI '%s'" msgid "Unsupported URI scheme '%s'" msgstr "Nepodprta shema URI '%s'" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Ime gostitelja je naslov IP" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Neveljavno ime gostitelja" -#: ../libsoup/soup-tld.c:184 -#: ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "Ni dovolj domen" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "Ime gostitelja je brez osnovne domene" +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Ni dovolj domen" + -- cgit v1.2.1 From 98ff7ea8a9fd166a751b240901e8f7f094877b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Di=C3=A9guez?= Date: Wed, 12 Sep 2012 02:04:35 +0200 Subject: Updated Galician translations --- po/gl.po | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/po/gl.po b/po/gl.po index 90e6e749..807cadfb 100644 --- a/po/gl.po +++ b/po/gl.po @@ -1,40 +1,46 @@ # Galician translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# FIRST AUTHOR , YEAR. # Fran Dieguez , 2012. -# msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-31 02:02+0200\n" -"PO-Revision-Date: 2012-07-31 02:02+0200\n" +"POT-Creation-Date: 2012-09-12 02:04+0200\n" +"PO-Revision-Date: 2012-09-12 02:04+0200\n" "Last-Translator: Fran Dieguez \n" -"Language-Team: Galician \n" +"Language-Team: gnome-l10n-gl@gnome.org\n" "Language: gl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n!=1);\n" -"X-Generator: Gtranslator 2.91.5\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.0\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "A conexión rematou de forma non esperada" -#: ../libsoup/soup-converter-wrapper.c:191 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Petición de busca non válida" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "O búfer de saída é demasiado pequeno" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "A operación foi cancelada" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "A operación bloquearase" @@ -58,18 +64,18 @@ msgstr "Non é posíbel analizar o URI «%s»" msgid "Unsupported URI scheme '%s'" msgstr "Esquema de URI «%s» non admitido" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "O nome do computador é un enderezo IP" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "O nome do computador non é válido" -#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "Non hai dominios dabondo" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "O nome do computador non ten un dominio base" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Non hai dominios dabondo" -- cgit v1.2.1 From a42cda7a5616ef2f68cc4c4a741530000e5958b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Di=C3=A9guez?= Date: Wed, 12 Sep 2012 02:05:10 +0200 Subject: Updated Galician translations --- po/gl.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/po/gl.po b/po/gl.po index 807cadfb..eb863bb5 100644 --- a/po/gl.po +++ b/po/gl.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-12 02:04+0200\n" -"PO-Revision-Date: 2012-09-12 02:04+0200\n" +"PO-Revision-Date: 2012-09-12 02:05+0200\n" "Last-Translator: Fran Dieguez \n" "Language-Team: gnome-l10n-gl@gnome.org\n" "Language: gl\n" @@ -29,7 +29,7 @@ msgstr "Petición de busca non válida" #: ../libsoup/soup-body-input-stream.c:489 msgid "Cannot truncate SoupBodyInputStream" -msgstr "" +msgstr "Non é posíbel truncar SoupbodyInputStream" #: ../libsoup/soup-converter-wrapper.c:192 #, c-format -- cgit v1.2.1 From 3974416935c4504b580ec06f3324781ec612b3cf Mon Sep 17 00:00:00 2001 From: Sandeep Sheshrao Shedmake Date: Wed, 12 Sep 2012 18:06:11 +0530 Subject: Updated Marathi Translations --- po/mr.po | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/po/mr.po b/po/mr.po index fafc7826..eeb427f7 100644 --- a/po/mr.po +++ b/po/mr.po @@ -8,10 +8,10 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-12 00:04+0000\n" -"PO-Revision-Date: 2012-08-12 17:16+0530\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-12 18:04+0530\n" "Last-Translator: Sandeep Shedmake \n" -"Language-Team: Marathi \n" +"Language-Team: Marathi \n" "Language: mr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -19,12 +19,20 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Lokalize 1.4\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "जोडणी अनपेक्षितपणे बंद झाली" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "अवैध सीक विनंती" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ट्रंकेट करणे अशक्य" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From a02d4b0b46dadf934430ede503e6f2806aa97d94 Mon Sep 17 00:00:00 2001 From: Duarte Loreto Date: Wed, 12 Sep 2012 23:37:31 +0100 Subject: Updated Portuguese translation --- po/pt.po | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/po/pt.po b/po/pt.po index 994a940a..39bcbcb3 100644 --- a/po/pt.po +++ b/po/pt.po @@ -6,10 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: 3.6\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-08 02:40+0000\n" -"PO-Revision-Date: 2012-09-09 02:10+0100\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-12 23:36+0100\n" +"PO-Revision-Date: 2012-09-12 23:37+0100\n" "Last-Translator: Duarte Loreto \n" "Language-Team: Portuguese \n" "Language: pt\n" @@ -17,12 +16,20 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Ligação terminou inesperadamente" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Pedido de procura inválido" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Incapaz de truncar SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From cfc7d8636e8bd4abd0e0feecfa5feefd656a5bf5 Mon Sep 17 00:00:00 2001 From: Alexandre Franke Date: Thu, 13 Sep 2012 20:45:03 +0200 Subject: Update French translation --- po/fr.po | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/po/fr.po b/po/fr.po index f0e0eb71..9d11d823 100644 --- a/po/fr.po +++ b/po/fr.po @@ -4,28 +4,37 @@ # # Pierre Henry , 2012. # Alain Lojewski , 2012. +# Mickael Albertus , 2012. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-12 00:04+0000\n" -"PO-Revision-Date: 2012-09-01 17:56+0200\n" -"Last-Translator: Alain Lojewski \n" -"Language-Team: French \n" +"POT-Creation-Date: 2012-09-12 12:36+0000\n" +"PO-Revision-Date: 2012-09-13 20:44+0200\n" +"Last-Translator: Mickael Albertus \n" +"Language-Team: français \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "La connexion a été interrompue de manière inattendue" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Requête de recherche invalide" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Impossible de tronquer le SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 7116b94ee47d80bc8be47dce579e771a6e9ffbcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aurimas=20=C4=8Cernius?= Date: Thu, 13 Sep 2012 22:40:49 +0300 Subject: Updated Lithuanian translation --- po/lt.po | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/po/lt.po b/po/lt.po index a9c416ee..5775351b 100644 --- a/po/lt.po +++ b/po/lt.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-16 22:04+0000\n" -"PO-Revision-Date: 2012-09-02 15:29+0300\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-13 22:40+0300\n" "Last-Translator: Aurimas Černius \n" "Language-Team: Lithuanian \n" "Language: lt\n" @@ -17,24 +17,32 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 #: ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Ryšys netikėtai nutrūko" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Netinkama paieškos užklausa" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Negalima trumpinti SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Išvesties buferis yra per mažas" -#: ../libsoup/soup-message-io.c:817 -#: ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 +#: ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Veiksmas buvo nutrauktas" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Veiksmas blokuosis" @@ -58,20 +66,19 @@ msgstr "Nepavyko perskaityti URI „%s“" msgid "Unsupported URI scheme '%s'" msgstr "Nepalaikoma URI schema „%s“" -#: ../libsoup/soup-tld.c:143 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Serverio vardas arba IP adresas" -#: ../libsoup/soup-tld.c:164 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Netinkamas serverio vardas" -#: ../libsoup/soup-tld.c:179 -#: ../libsoup/soup-tld.c:221 -msgid "Not enough domains" -msgstr "Nepakanka domenų" - -#: ../libsoup/soup-tld.c:199 +#: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "Serverio vardas neturi bazinio domeno" +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Nepakanka domenų" + -- cgit v1.2.1 From c428ce67e5d68a779f03ae6acc0177ca10e6ceb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B8=D1=80=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=9D?= =?UTF-8?q?=D0=B8=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Fri, 14 Sep 2012 05:55:12 +0200 Subject: Updated Serbian translation --- po/sr.po | 45 +++++++++++++++++++++++++++------------------ po/sr@latin.po | 45 +++++++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/po/sr.po b/po/sr.po index 152ab0d1..8be2ed46 100644 --- a/po/sr.po +++ b/po/sr.po @@ -1,39 +1,48 @@ # Serbian translation of libsoup. # Courtesy of Prevod.org team (http://prevod.org/) -- 2012. # This file is distributed under the same license as the libsoup package. -# Мирослав Николић , 2011. +# Мирослав Николић , 2011, 2012. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-17 14:16+0000\n" -"PO-Revision-Date: 2011-03-05 22:03+0200\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-14 05:49+0200\n" "Last-Translator: Мирослав Николић \n" "Language-Team: Serbian \n" +"Language: sr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: Serbian (sr)\n" "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : " "n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Project-Style: gnome\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Веза је неочекивано затворена" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Неисправан захтев претраге" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Не могу да скратим улазни ток тела Супе" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Међумеморија излаза је премала" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Радња је отказана" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Поступак би блокирао" @@ -57,18 +66,18 @@ msgstr "Не могу да обрадим адресу „%s“" msgid "Unsupported URI scheme '%s'" msgstr "Неподржана „%s“ шема адресе" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Назив домаћина је ИП адреса" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Неисправан назив домаћина" -#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "Нема довољно домена" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "Назив домаћина нема основни домен" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Нема довољно домена" diff --git a/po/sr@latin.po b/po/sr@latin.po index 8fdeef4e..0c191a23 100644 --- a/po/sr@latin.po +++ b/po/sr@latin.po @@ -1,39 +1,48 @@ # Serbian translation of libsoup. # Courtesy of Prevod.org team (http://prevod.org/) -- 2012. # This file is distributed under the same license as the libsoup package. -# Miroslav Nikolić , 2011. +# Miroslav Nikolić , 2011, 2012. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-17 14:16+0000\n" -"PO-Revision-Date: 2011-03-05 22:03+0200\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-14 05:49+0200\n" "Last-Translator: Miroslav Nikolić \n" "Language-Team: Serbian \n" +"Language: sr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: Serbian (sr)\n" "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : " "n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Project-Style: gnome\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Veza je neočekivano zatvorena" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Neispravan zahtev pretrage" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Ne mogu da skratim ulazni tok tela Supe" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Međumemorija izlaza je premala" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Radnja je otkazana" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Postupak bi blokirao" @@ -57,18 +66,18 @@ msgstr "Ne mogu da obradim adresu „%s“" msgid "Unsupported URI scheme '%s'" msgstr "Nepodržana „%s“ šema adrese" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Naziv domaćina je IP adresa" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Neispravan naziv domaćina" -#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "Nema dovoljno domena" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "Naziv domaćina nema osnovni domen" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Nema dovoljno domena" -- cgit v1.2.1 From 0121162d759c8c366f90f74fd1ccec1135b40778 Mon Sep 17 00:00:00 2001 From: Sweta Kothari Date: Fri, 14 Sep 2012 15:54:32 +0530 Subject: Updated gujarati file --- po/gu.po | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/po/gu.po b/po/gu.po index dcca9547..4fc981a4 100644 --- a/po/gu.po +++ b/po/gu.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." "cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-26 18:48+0000\n" -"PO-Revision-Date: 2012-07-27 14:35+0530\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-14 15:54+0530\n" "Last-Translator: \n" "Language-Team: gu_IN \n" "Language: gu\n" @@ -19,22 +19,30 @@ msgstr "" "X-Generator: Lokalize 1.0\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "જોડાણ અનિચ્છનીય રીતે તૂટી ગયુ" -#: ../libsoup/soup-converter-wrapper.c:191 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "અયોગ્ય સીક માંગણી" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream કાઢી શકાતુ નથી" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "આઉટપુટ બફર ઘણુ નાનું છે" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "ક્રિયા રદ થયેલ હતી" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "ક્રિયા રોકી રખાશે" @@ -58,19 +66,19 @@ msgstr "URI '%s' ને પદચ્છેદન કરી શક્યા ન msgid "Unsupported URI scheme '%s'" msgstr "બિનઆધારભૂત URI યોજના '%s'" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "યજમાનનામ એ IP સરનામું છે" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "અમાન્ય યજમાનનામ" -#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "પૂરતુ ડોમેઇન નથી" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "યજમાન પાસે મૂળ ડોમેઇન નથી" +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "પૂરતુ ડોમેઇન નથી" + -- cgit v1.2.1 From 69a36e604d991992be5c16297e7fb3f1d0526e6b Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Fri, 14 Sep 2012 13:29:33 +0300 Subject: Updated Belarusian translation. --- po/be.po | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/po/be.po b/po/be.po index 5ff8260d..18c17f93 100644 --- a/po/be.po +++ b/po/be.po @@ -5,8 +5,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-16 22:04+0000\n" -"PO-Revision-Date: 2012-09-07 19:11+0300\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-14 13:29+0300\n" "Last-Translator: Ihar Hrachyshka \n" "Language-Team: Belarusian \n" "Language: be\n" @@ -14,22 +14,30 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Злучэнне нечакана перарвана" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Хібны запыт пракручвання змесціва" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Немагчыма абрэзаць SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Выхадны буфер надта малы" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Аперацыя была скасавана" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Аперацыя заблакіруе працэс" @@ -53,18 +61,18 @@ msgstr "Не ўдалося разабраць URI-адрас \"%s\"" msgid "Unsupported URI scheme '%s'" msgstr "URI-схема \"%s\" не падтрымліваецца" -#: ../libsoup/soup-tld.c:143 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Назва хоста з'яўляецца IP-адрасам" -#: ../libsoup/soup-tld.c:164 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Хібная назва хоста" -#: ../libsoup/soup-tld.c:179 ../libsoup/soup-tld.c:221 -msgid "Not enough domains" -msgstr "Не хапае даменаў" - -#: ../libsoup/soup-tld.c:199 +#: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "Назва хоста не мае базавага дамена" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Не хапае даменаў" -- cgit v1.2.1 From d6145ce93eb51e253d6ac9d92b6622a41117da33 Mon Sep 17 00:00:00 2001 From: Rafael Ferreira Date: Fri, 14 Sep 2012 09:15:42 -0300 Subject: Fixed plurals in Brazilian Portuguese translation --- po/pt_BR.po | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/po/pt_BR.po b/po/pt_BR.po index 2d236259..3a213e15 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -6,10 +6,11 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-07 22:38-0400\n" -"PO-Revision-Date: 2012-09-07 21:55-0300\n" -"Last-Translator: Enrico Nicoletto \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-12 12:36+0000\n" +"PO-Revision-Date: 2012-09-12 09:48-0300\n" +"Last-Translator: Rafael Ferreira \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" @@ -17,12 +18,20 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "A conexão terminou inesperadamente" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Requisição de busca inválida" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Não foi possível truncar SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From b65a38624dd634ce29e26de4fc9314153eade154 Mon Sep 17 00:00:00 2001 From: Chao-Hsiung Liao Date: Sat, 15 Sep 2012 12:53:52 +0800 Subject: Updated Traditional Chinese translation(Hong Kong and Taiwan) --- po/zh_HK.po | 18 +++++++++++++----- po/zh_TW.po | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/po/zh_HK.po b/po/zh_HK.po index 5f7e253d..ae21d89f 100644 --- a/po/zh_HK.po +++ b/po/zh_HK.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-15 15:13+0800\n" -"PO-Revision-Date: 2012-08-15 15:13+0800\n" +"POT-Creation-Date: 2012-09-15 12:53+0800\n" +"PO-Revision-Date: 2012-09-15 12:53+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: Chinese (Hong Kong) \n" "Language: zh_TW\n" @@ -16,12 +16,20 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "連線無預警的關閉了" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "無效的搜尋要求" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "不能截短 SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" diff --git a/po/zh_TW.po b/po/zh_TW.po index 20387341..7ece68cc 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-08-15 15:13+0800\n" -"PO-Revision-Date: 2012-08-15 14:52+0800\n" +"POT-Creation-Date: 2012-09-15 12:53+0800\n" +"PO-Revision-Date: 2012-09-12 20:11+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: Chinese (Taiwan) \n" "Language: zh_TW\n" @@ -16,12 +16,20 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "連線無預警的關閉了" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "無效的搜尋要求" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "不能截短 SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From e5e2b525ae18f9121e8a42bde1dcf6ef2605988d Mon Sep 17 00:00:00 2001 From: Kenneth Nielsen Date: Sat, 15 Sep 2012 23:42:58 +0200 Subject: Added da to list of languages --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index d33c8b1a..bd8ede8b 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -3,6 +3,7 @@ be bg bn_IN cs +da de el en_GB -- cgit v1.2.1 From 64c5897eeea8bc4917385f6facc654e618fb3ef0 Mon Sep 17 00:00:00 2001 From: "Ask H. Larsen" Date: Sat, 15 Sep 2012 23:42:58 +0200 Subject: Updated Danish translation --- po/da.po | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 po/da.po diff --git a/po/da.po b/po/da.po new file mode 100644 index 00000000..566a3ef2 --- /dev/null +++ b/po/da.po @@ -0,0 +1,81 @@ +# Danish translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Ask Hjorth Larsen , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-15 23:42+0200\n" +"PO-Revision-Date: 2012-09-15 18:15+0200\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Danish \n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Forbindelsen blev uventet afbrudt" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Ugyldig søgeforespørgsel" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Kan ikke afkorte SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Outputbuffer er for lille" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Operationen blev annulleret" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Operationen ville blokere" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Ingen URI givet" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Ugyldig \"%s\"-URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Kunne ikke fortolke URI \"%s\"" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Uunderstøttet URI-skema \"%s\"" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Værtsnavn er en IP-adresse" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Ugyldigt værtsnavn" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Værtsnavnet har intet basisdomæne" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Ikke nok domæner" -- cgit v1.2.1 From eee8574f876404dd24fb238224a72981bfc2f4f5 Mon Sep 17 00:00:00 2001 From: Yuri Myasoedov Date: Mon, 17 Sep 2012 16:46:08 +0400 Subject: Updated Russian translation --- po/ru.po | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/po/ru.po b/po/ru.po index aa8e7e70..35c7d55e 100644 --- a/po/ru.po +++ b/po/ru.po @@ -8,33 +8,41 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-27 09:06+0000\n" -"PO-Revision-Date: 2012-07-30 13:40+0300\n" -"Last-Translator: Alexsey Nadtochey \n" -"Language-Team: Russian \n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-17 16:46+0400\n" +"Last-Translator: Yuri Myasoedov \n" +"Language-Team: русский \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Соединение было неожиданно разорвано" -#: ../libsoup/soup-converter-wrapper.c:191 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Неверный запрос поиска" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Не удалось отсечь SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Слишком маленький буфер вывода" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Действие отменено" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Действие заблокировано" @@ -58,18 +66,18 @@ msgstr "Не удалось разобрать URI «%s»" msgid "Unsupported URI scheme '%s'" msgstr "Неподдерживаемая схема URI «%s»" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Имя компьютера является IP-адресом" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Неверное имя компьютера" -#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "Недостаточно доменных имён в адресе" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "Имя компьютера не содержит доменной части" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Недостаточно доменных имён в адресе" -- cgit v1.2.1 From 0c825d4a0b89c103ea798fe7fb816e3a0c48534e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 17 Sep 2012 13:53:48 -0400 Subject: SoupSessionAsync: destroy the I/O GSource when returning a result When a soup_request_send_async() gets cancelled, we were leaving its GSource active, causing it to be triggered later, sometimes causing criticals. Fix that. https://bugzilla.gnome.org/show_bug.cgi?id=683404 --- libsoup/soup-message-queue.c | 4 ++++ libsoup/soup-message-queue.h | 1 + libsoup/soup-session-async.c | 14 +++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index e4640358..2a60446e 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -187,6 +187,10 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) soup_uri_free (item->proxy_uri); if (item->result) g_object_unref (item->result); + if (item->io_source) { + g_source_destroy (item->io_source); + g_source_unref (item->io_source); + } soup_message_queue_item_set_connection (item, NULL); g_slice_free (SoupMessageQueueItem, item); } diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index cd153813..0f948cc3 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -41,6 +41,7 @@ struct _SoupMessageQueueItem { SoupURI *proxy_uri; SoupConnection *conn; GSimpleAsyncResult *result; + GSource *io_source; guint paused : 1; guint new_api : 1; diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index ffc306ae..398cc0fe 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -478,6 +478,11 @@ send_request_return_result (SoupMessageQueueItem *item, simple = item->result; item->result = NULL; + if (item->io_source) { + g_source_destroy (item->io_source); + g_clear_pointer (&item->io_source, g_source_unref); + } + if (error) g_simple_async_result_take_error (simple, error); else if (SOUP_STATUS_IS_TRANSPORT_ERROR (item->msg->status_code)) { @@ -614,6 +619,7 @@ read_ready_cb (SoupMessage *msg, gpointer user_data) { SoupMessageQueueItem *item = user_data; + g_clear_pointer (&item->io_source, g_source_unref); try_run_until_read (item); return FALSE; } @@ -623,7 +629,6 @@ try_run_until_read (SoupMessageQueueItem *item) { GError *error = NULL; GInputStream *stream = NULL; - GSource *source; if (soup_message_io_run_until_read (item->msg, item->cancellable, &error)) stream = soup_message_io_get_response_istream (item->msg, &error); @@ -653,10 +658,9 @@ try_run_until_read (SoupMessageQueueItem *item) } g_clear_error (&error); - source = soup_message_io_get_source (item->msg, item->cancellable, - read_ready_cb, item); - g_source_attach (source, soup_session_get_async_context (item->session)); - g_source_unref (source); + item->io_source = soup_message_io_get_source (item->msg, item->cancellable, + read_ready_cb, item); + g_source_attach (item->io_source, soup_session_get_async_context (item->session)); } static void -- cgit v1.2.1 From 8c1b842f66ba973861fbbf2b7bcabedb7ac0a398 Mon Sep 17 00:00:00 2001 From: Chris Leonard Date: Mon, 17 Sep 2012 20:29:17 +0100 Subject: Updated British English translation --- po/en_GB.po | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/po/en_GB.po b/po/en_GB.po index 1e106add..1331d1e7 100644 --- a/po/en_GB.po +++ b/po/en_GB.po @@ -2,29 +2,38 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # Bruce Cowan , 2012. +# Chris Leonard , 2012. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" -"p&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-04 17:05+0000\n" -"PO-Revision-Date: 2012-09-05 13:47+0100\n" -"Last-Translator: Bruce Cowan \n" -"Language-Team: British English \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-10 19:10+0000\n" +"PO-Revision-Date: 2012-09-10 21:39-0400\n" +"Last-Translator: Chris Leonard \n" +"Language-Team: Sugar Labs\n" "Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Virtaal 0.7.1\n" +"X-Generator: Virtaal 0.7.0\n" "X-Project-Style: gnome\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Connection terminated unexpectedly" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Invalid seek request" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Cannot truncate SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 984482a4e92108b4dbe9858c05074bf54b625ce9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 17 Sep 2012 16:43:05 -0400 Subject: 2.39.92 --- NEWS | 16 ++++++++++++++++ configure.ac | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c0e6363c..9eae8aaf 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,19 @@ +Changes in libsoup from 2.39.91 to 2.39.92: + + * Fixed some g_warnings (and a possible crash) with the + soup_request_send_async(). [#683404, Dan] + + * Fixed a hang with SoupSessionSync [#682923, Dan] + + * Handle empty "Cache-Control" headers. [Sergio] + + * New/updated translations: + Assamese, Belarusian, Brazilian Portuguese, British English, + Chinese (Traditional), Czech, Danish, French, Galician, + Greek, Gujarati, Hungarian, Indonesian, Italian, Lithuanian, + Marathi, Persian, Polish, Portuguese, Russian, Serbian, + Slovenian, Spanish + Changes in libsoup from 2.39.90 to 2.39.91: * Added missing (transfer full) annotation to diff --git a/configure.ac b/configure.ac index fb04d971..188b900b 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *** Initialize automake and set version *** dnl ******************************************* AC_PREREQ(2.63) -AC_INIT([libsoup],[2.39.91],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[2.39.92],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -- cgit v1.2.1 From 035cfc7a406909e07575c1dd9a5c4dbe5f2f977e Mon Sep 17 00:00:00 2001 From: Gabor Kelemen Date: Mon, 17 Sep 2012 23:29:36 +0200 Subject: Updated Hungarian translation --- po/hu.po | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/po/hu.po b/po/hu.po index e7741a08..3765f0f9 100644 --- a/po/hu.po +++ b/po/hu.po @@ -7,23 +7,31 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-06 15:52+0200\n" -"PO-Revision-Date: 2012-09-06 15:58+0200\n" +"POT-Creation-Date: 2012-09-17 23:23+0200\n" +"PO-Revision-Date: 2012-09-17 23:23+0200\n" "Last-Translator: Gabor Kelemen \n" "Language-Team: Hungarian \n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Lokalize 1.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: KBabel 1.11.4\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Kapcsolat váratlanul megszakítva" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Érvénytelen pozicionálási kérés" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "A SoupBodyInputStream nem csonkítható" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 397a6a59db38c887d1b5a42ff440a23dd73ab3a8 Mon Sep 17 00:00:00 2001 From: Ani Peter Date: Tue, 18 Sep 2012 23:01:53 +0530 Subject: Updated Malayalam file --- po/LINGUAS | 1 + po/ml.po | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 po/ml.po diff --git a/po/LINGUAS b/po/LINGUAS index bd8ede8b..7038ac8a 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -21,6 +21,7 @@ ja ko lt lv +ml mr nb pa diff --git a/po/ml.po b/po/ml.po new file mode 100644 index 00000000..4e38a46f --- /dev/null +++ b/po/ml.po @@ -0,0 +1,83 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Ani Peter , 2012. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-15 21:43+0000\n" +"PO-Revision-Date: 2012-09-18 23:00+0000\n" +"Last-Translator: Ani Peter \n" +"Language-Team: Malayalam \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.0\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "കണക്ഷന്‍ അപ്രതീക്ഷതമായി അവസാനിയ്ക്കുന്നു" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "തെറ്റായ തെരച്ചില്‍ ആവശ്യം" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ട്രക്കേറ്റ് ചെയ്യുവാന്‍ സാധ്യമല്ല" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "ഔട്ട്പുട്ട് ബഫര്‍ വളരെ ചെറുതാണു്" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "പ്രക്രിയ റദ്ദാക്കിയിരിയ്ക്കുന്നു" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "പ്രക്രിയ തടസ്സപ്പെടുത്തുന്നു" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "യുആര്‍ഐ ലഭ്യമാക്കിയിട്ടില്ല" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "തെറ്റായ '%s' യുആര്‍ഐ: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "യുആര്‍ഐ '%s' പാഴ്സ് ചെയ്യുവാനായില്ല" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "പിന്തുണയില്ലാത്ത യുആര്‍ഐ സ്കീം '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "ഹോസ്റ്റ്നാമം ഒരു ഐപി വിലാസമാകുന്നു" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "തെറ്റായ ഹോസ്റ്റ്നാമം" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "ഹോസ്റ്റ്നാമത്തിനു് ബെയിസ് ഡൊമെയില്‍ ലഭ്യമല്ല" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "ആവശ്യമായ ഡൊമെയിനുകള്‍ ലഭ്യമല്ല" + -- cgit v1.2.1 From 815f23ddb74e1d0b3bbe79334d14ed018387a4a0 Mon Sep 17 00:00:00 2001 From: A S Alam Date: Wed, 19 Sep 2012 20:52:58 +0530 Subject: update Punjabi Translation --- po/pa.po | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/po/pa.po b/po/pa.po index 73606601..eefaffaf 100644 --- a/po/pa.po +++ b/po/pa.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-16 22:04+0000\n" -"PO-Revision-Date: 2012-08-22 08:57+0530\n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-19 20:51+0530\n" "Last-Translator: A S Alam \n" "Language-Team: Punjabi/Panjabi \n" "Language: pa\n" @@ -19,22 +19,30 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Lokalize 1.4\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "ਕੁਨੈਕਸ਼ਨ ਅਚਾਨਕ ਬੰਦ ਹੋ ਗਿਆ" -#: ../libsoup/soup-converter-wrapper.c:189 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "ਸੀਕ ਮੰਗ ਗਲਤ ਹੈ" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ਨੂੰ ਛੋਟਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "ਆਉਟਪੁੱਟ ਬਫ਼ਰ ਬਹੁਤ ਛੋਟਾ ਹੈ" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "ਕਾਰਵਾਈ ਰੱਦ ਕੀਤੀ ਗਈ" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "ਕਾਰਵਾਈ ਉੱਤੇ ਪਾਬੰਦੀ ਹੋਵੇਗੀ" @@ -58,19 +66,19 @@ msgstr "URI '%s' ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕ msgid "Unsupported URI scheme '%s'" msgstr "ਗ਼ੈਰ-ਸਹਾਇਕ URI ਸਕੀਮ '%s'" -#: ../libsoup/soup-tld.c:143 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "ਹੋਸਟ ਨਾਂ IP ਐਡਰੈਸ ਹੈ" -#: ../libsoup/soup-tld.c:164 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "ਗਲਤ ਹੋਸਟ-ਨਾਂ" -#: ../libsoup/soup-tld.c:179 ../libsoup/soup-tld.c:221 -msgid "Not enough domains" -msgstr "ਲੋੜੀਦੀਆਂ ਡੋਮੇਨ ਨਹੀਂ ਹੈ" - -#: ../libsoup/soup-tld.c:199 +#: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "ਹੋਸਟ-ਨਾਂ ਲਈ ਬੇਸ ਡੋਮੇਮ ਨਹੀਂ ਹੈ" +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "ਲੋੜੀਦੀਆਂ ਡੋਮੇਨ ਨਹੀਂ ਹੈ" + -- cgit v1.2.1 From baad506a8d1d7934992d92f358564a2c50ff4502 Mon Sep 17 00:00:00 2001 From: "Dr.T.Vasudevan" Date: Wed, 19 Sep 2012 20:27:04 +0530 Subject: updated Tamil translation --- po/ta.po | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/po/ta.po b/po/ta.po index e9458764..c0606120 100644 --- a/po/ta.po +++ b/po/ta.po @@ -6,10 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." -"cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-01 15:56+0000\n" -"PO-Revision-Date: 2012-09-02 15:25+0530\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-19 20:16+0530\n" +"PO-Revision-Date: 2012-09-19 20:26+0530\n" "Last-Translator: Dr.T.Vasudevan \n" "Language-Team: Tamil \n" "Language: ta\n" @@ -19,12 +18,20 @@ msgstr "" "X-Generator: Lokalize 1.1\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "இணைப்பு எதிர்பாராமல் துண்டிக்கப்பட்டது" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "செல்லுபடியாகாத தேடல் கோரிக்கை" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ஐ பிரிக்க இயலாது" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 9795781144f9c0fd3756e0729c60dc277a5b92af Mon Sep 17 00:00:00 2001 From: Alexander Shopov Date: Wed, 19 Sep 2012 21:08:37 +0300 Subject: Updated Bulgarian translation --- po/bg.po | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/po/bg.po b/po/bg.po index 7781f397..2d9305ef 100644 --- a/po/bg.po +++ b/po/bg.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-05 12:37+0300\n" -"PO-Revision-Date: 2012-07-05 12:37+0300\n" +"POT-Creation-Date: 2012-09-19 21:08+0300\n" +"PO-Revision-Date: 2012-09-19 21:08+0300\n" "Last-Translator: Alexander Shopov \n" "Language-Team: Bulgarian \n" "Language: \n" @@ -17,53 +17,65 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Връзката прекъсна неочаквано" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Неправилна заявка за търсене" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Потокът SoupBodyInputStream не може да бъде прекъснат" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Прекалено малък изходен буфер" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Операцията е отменена" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Операцията ще блокира" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "Не е даден адрес" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Неправилен адрес на „%s“: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "Адресът „%s“ е неправилен" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Схемата на адреса не се поддържа „%s“" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Името на машината е адрес по IP" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Неправилно име на машина" -#: ../libsoup/soup-tld.c:181 ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Името на машината не съдържа домейн" + +#: ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "Няма достатъчно домейни" -- cgit v1.2.1 From 4031a250f8c5a5bd733339dd514eb974859a3407 Mon Sep 17 00:00:00 2001 From: Rajesh Ranjan Date: Thu, 20 Sep 2012 14:15:19 +0530 Subject: hindi updated file by Pratibha Kumari --- po/hi.po | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 po/hi.po diff --git a/po/hi.po b/po/hi.po new file mode 100644 index 00000000..f43ab73d --- /dev/null +++ b/po/hi.po @@ -0,0 +1,86 @@ +# Hindi translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# 1 <1>, 2012. +# 1 Pratibha kumari <1pratibharoshan1526@gmail.com>, 2012. + +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-15 21:43+0000\n" +"PO-Revision-Date: 2012-09-20 14:12+0530\n" +"Last-Translator: 1 Pratibha kumari <1pratibharoshan1526@gmail.com>\n" +"Language-Team: Hindi \n" +"Language: hi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Lokalize 1.2\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "मिलाप अनपेक्षित रुप से खतम हो गया " + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "अमान्य खोज अनुरोध" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream का नहीं कर सकता" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "निर्गम बफर बहुत छोटा है" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "आपरेशन रद्द कर दिया गया" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "आपरेशन बंद हो जाएगा" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "यूआरआई नहीं प्रदान किया गया" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "यूआरआई '%s' अमान्य: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' पद व्याख्या नहीं हो सका" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "URI योजना '%s' को सहारा नहीं" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "मेजबाननाम एक आईपी पता है" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "मेजबाननाम मान्य नहीं" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "मेजबाननाम को आधार डोमेन नहीं है" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "डोमेन पर्याप्त नहीं" + -- cgit v1.2.1 From 7a32597f0ae3cd13a2d25f2640f5a7d49978bd9b Mon Sep 17 00:00:00 2001 From: Rajesh Ranjan Date: Thu, 20 Sep 2012 14:15:35 +0530 Subject: hindi updated file --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index 7038ac8a..57b54ae1 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -14,6 +14,7 @@ fr gl gu he +hi hu id it -- cgit v1.2.1 From 7521d9152fba5fe01273344d4dd8990511ed0303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Bl=C3=A4ttermann?= Date: Thu, 20 Sep 2012 13:31:15 +0200 Subject: [l10n] Updated German translation --- po/de.po | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/po/de.po b/po/de.po index 67e8af75..a3555c5a 100644 --- a/po/de.po +++ b/po/de.po @@ -2,15 +2,16 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # Tobias Endrigkeit , 2012. +# Mario Blättermann , 2012. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-12 00:04+0000\n" -"PO-Revision-Date: 2012-08-06 20:20+0200\n" -"Last-Translator: Tobias Endrigkeit \n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-20 13:29+0100\n" +"Last-Translator: Mario Blättermann \n" "Language-Team: Deutsch \n" "Language: de\n" "MIME-Version: 1.0\n" @@ -19,12 +20,20 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Gtranslator 2.91.5\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Die Verbindung wurde unerwartet beendet" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Ungültige Suchanfrage" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream konnte nicht abgeschnitten werden" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 4afa6d485433c5775c3c4dcf19abe74ab7db0e47 Mon Sep 17 00:00:00 2001 From: Sayak Sarkar Date: Fri, 21 Sep 2012 10:14:35 +0530 Subject: Updated Bengali India Translations --- po/bn_IN.po | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/po/bn_IN.po b/po/bn_IN.po index 92326785..847d4b0d 100644 --- a/po/bn_IN.po +++ b/po/bn_IN.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-12 00:04+0000\n" -"PO-Revision-Date: 2012-08-02 19:33+0530\n" +"POT-Creation-Date: 2012-09-20 11:30+0000\n" +"PO-Revision-Date: 2012-09-20 22:38+0530\n" "Last-Translator: Sayak Sarkar \n" "Language-Team: Bengali (India) \n" "Language: bn\n" @@ -19,12 +19,20 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Lokalize 1.4\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "সংযোগ অপ্রত্যাশিতভাবে পর্যবসিত" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "অবৈধ সিক্ অনুরোধ" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ছাঁটা যাচ্ছে না।" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 4feab7f2e16b34752ec6c5274f62ad02f492ded2 Mon Sep 17 00:00:00 2001 From: Daniel Korostil Date: Fri, 21 Sep 2012 10:09:11 +0300 Subject: Uploaded Ukranian --- po/uk.po | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/po/uk.po b/po/uk.po index 9f91f666..7f17ca6f 100644 --- a/po/uk.po +++ b/po/uk.po @@ -2,30 +2,38 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # Daniel , 2012. +# Re. , 2012. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" -"p&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-15 07:13+0000\n" -"PO-Revision-Date: 2012-08-16 00:51-0700\n" -"Last-Translator: Daniel \n" -"Language-Team: translation@linux.org.ua\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-21 10:06+0300\n" +"PO-Revision-Date: 2012-09-21 10:09+0300\n" +"Last-Translator: Re. \n" +"Language-Team: linux.org.ua\n" "Language: uk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" "10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -"X-Generator: Virtaal 0.7.0\n" +"X-Generator: Virtaal 0.7.1\n" "X-Project-Style: gnome\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Несподівано зв'язок розірвано" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Неправильний запит пошуку" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Неможливо вкоротити SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From f1aa394746497a086466ec658251e10333ef977e Mon Sep 17 00:00:00 2001 From: Akom Chotiphantawanon Date: Fri, 21 Sep 2012 18:53:21 +0700 Subject: Added Thai translation --- po/LINGUAS | 1 + po/th.po | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 po/th.po diff --git a/po/LINGUAS b/po/LINGUAS index 57b54ae1..e11460e3 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -37,6 +37,7 @@ sr@latin sv ta te +th tr uk vi diff --git a/po/th.po b/po/th.po new file mode 100644 index 00000000..11639625 --- /dev/null +++ b/po/th.po @@ -0,0 +1,81 @@ +# Thai translation for libsoup. +# Copyright (C) 2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# knight2000 , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-21 07:06+0000\n" +"PO-Revision-Date: 2012-09-21 18:49+0700\n" +"Last-Translator: Akom Chotiphantawanon \n" +"Language-Team: Thai \n" +"Language: th\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "การเชื่อมต่อยุติกะทันหัน" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "การร้องขอการเลื่อนตำแหน่งไม่ถูกต้อง" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "ไม่สามารถตัดท้าย SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "บัฟเฟอร์ข้อมูลออกเล็กเกินไป" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "การทำงานถูกยกเลิก" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "การทำงานถูกบล็อค" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "ไม่ได้ระบุ URI" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI '%s' ไม่ถูกต้อง: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "ไม่สามารถแจง URI '%s'" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ไม่รองรับ URI แบบ '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "ชื่อโฮสต์เป็นหมายเลขไอพี" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "ชื่อโฮสต์ผิดรูปแบบ" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "ชื่อโฮสต์ไม่มีโดเมนฐาน" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "มีโดเมนน้อยเกินไป" -- cgit v1.2.1 From c437c4a3f4320dca177186da3248d174be1d9d00 Mon Sep 17 00:00:00 2001 From: Krishnababu Krothapalli Date: Fri, 21 Sep 2012 22:15:49 +0530 Subject: Updated Telugu Translations --- po/te.po | 53 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/po/te.po b/po/te.po index b76cef2a..bd9713df 100644 --- a/po/te.po +++ b/po/te.po @@ -1,68 +1,85 @@ # Telugu translation for libsoup. # Copyright (C) 2012 libsoup's to Swecha Telugu localisation Team # This file is distributed under the same license as the libsoup package. -# Sasi Bhushan Boddepalli , 2012. # +# Sasi Bhushan Boddepalli , 2012. +# Krishnababu Krothapalli , 2012. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-06-18 13:31+0000\n" -"PO-Revision-Date: 2012-06-18 13:31+0000\n" -"Last-Translator: Sasi Bhushan Boddepalli \n" -"Language-Team: Telugu \n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-21 21:25+0530\n" +"Last-Translator: Krishnababu Krothapalli \n" +"Language-Team: Telugu \n" +"Language: te\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.4\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "కనెక్షను అనుకోకుండా అంతమైంది" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "చెల్లని సీక్ అభ్యర్ధన" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ట్రంకేట్ చేయలేదు" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "అవుట్పుట్ బఫర్ మరీ చిన్నది" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "ఆపరేషన్ రద్దు చేయబడింది" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "ఆపరేషన్ బ్లాక్ చేస్తుంది" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" msgstr "URl అందించబడలేదు" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:152 #, c-format msgid "Invalid '%s' URI: %s" msgstr "చెల్లని '%s' URI: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-requester.c:219 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' అన్వయించడం సాధ్యం కాదు" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-requester.c:253 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "మద్దతు లేని URI స్కీమ్ '%s'" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "హోస్ట్ పేరు ఒక IP చిరునామా" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "చెల్లని హోస్ట్ పేరు" -#: ../libsoup/soup-tld.c:181 ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "అతిధేయిపేరు అధార డొమైన్ కలిగిలేదు" + +#: ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "సరిపోనన్ని డొమైన్ లు" + -- cgit v1.2.1 From ccc335c3a21a84cbccf753717c5340b193d758b9 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Sat, 22 Sep 2012 15:17:16 +0300 Subject: Updated Hebrew translation. --- po/he.po | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/po/he.po b/po/he.po index db9e6c30..a8467128 100644 --- a/po/he.po +++ b/po/he.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup gnome\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-24 23:14+0300\n" -"PO-Revision-Date: 2012-07-24 23:15+0200\n" +"POT-Creation-Date: 2012-09-22 15:16+0300\n" +"PO-Revision-Date: 2012-09-22 15:17+0200\n" "Last-Translator: Yaron Shahrabani \n" "Language-Team: Hebrew \n" "Language: \n" @@ -20,24 +20,32 @@ msgstr "" "X-Poedit-Country: ISRAEL\n" "X-Poedit-SourceCharset: utf-8\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 #: ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "החיבור הופסק באופן בלתי צפוי" -#: ../libsoup/soup-converter-wrapper.c:191 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "בקשת חיפוש שגויה" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "לא ניתן לקצץ את SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "אוגר הפלט קטן מדי" -#: ../libsoup/soup-message-io.c:817 -#: ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 +#: ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "הפעולה בוטלה" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "הפעולה תיחסם" @@ -61,20 +69,19 @@ msgstr "לא ניתן לנתח את הכתובת '%s'" msgid "Unsupported URI scheme '%s'" msgstr "תבנית הכתובת אינה נתמכת '%s'" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "שם המארח הוא כתובת IP" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "שם מארח שגוי" -#: ../libsoup/soup-tld.c:184 -#: ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "אין מספיק שמות מתחם" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "לשם המארח אין שם מתחם בסיסי" +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "אין מספיק שמות מתחם" + -- cgit v1.2.1 From d75179c2fe4449083c5e09d03a2079f5291d6a71 Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Sun, 23 Sep 2012 05:01:18 +0800 Subject: update Simplified Chinese (zh_CN) translation --- po/zh_CN.po | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/po/zh_CN.po b/po/zh_CN.po index 9ad60d54..964bdae4 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -4,38 +4,48 @@ # hmasterwang , 2012. # Alpha Cheng , 2012. # Cheng Lu , 2012. +# YunQiang Su , 2012. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-07-25 14:24+0000\n" -"PO-Revision-Date: 2012-07-26 13:31+0800\n" -"Last-Translator: Cheng Lu \n" +"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"PO-Revision-Date: 2012-09-23 05:00+0800\n" +"Last-Translator: YunQiang Su \n" "Language-Team: Chinese (simplified) \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" +"Content-Transfer-Encoding: 8bits\n" "Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 2.91.5\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "连接异常终止" -#: ../libsoup/soup-converter-wrapper.c:191 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "无效的 seek 请求" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "不能截断(truncate) SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "输出缓冲区太小" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "操作被取消" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "操作将阻塞" @@ -59,18 +69,18 @@ msgstr "无法解析 URI:“%s”" msgid "Unsupported URI scheme '%s'" msgstr "不支持的 URI 方案:“%s”" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "主机名是一个 IP 地址" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "主机名无效" -#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "没有足够的域" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "主机名没有基域" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "没有足够的域" -- cgit v1.2.1 From f0c7c00954d2f6e860a54908d4419ff150236047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20Mazurs?= Date: Sun, 23 Sep 2012 16:00:02 +0300 Subject: Updated Latvian translation --- po/lv.po | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/po/lv.po b/po/lv.po index d06d0988..0830eb0e 100644 --- a/po/lv.po +++ b/po/lv.po @@ -1,25 +1,25 @@ # Latvian translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. +# # Tranzistors , 2012. # Rūdolfs Mazurs , 2012. -# msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" "POT-Creation-Date: 2012-08-22 03:28+0000\n" -"PO-Revision-Date: 2012-08-24 13:13+0300\n" +"PO-Revision-Date: 2012-09-23 15:59+0300\n" "Last-Translator: Rūdolfs Mazurs \n" -"Language-Team: Latviešu \n" +"Language-Team: Latvian \n" "Language: lv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " "2);\n" -"X-Generator: Gtranslator 2.91.5\n" +"X-Generator: Lokalize 1.4\n" #: ../libsoup/soup-body-input-stream.c:136 #: ../libsoup/soup-body-input-stream.c:167 @@ -43,7 +43,7 @@ msgstr "Darbība bloķētu" #: ../libsoup/soup-request.c:142 #, c-format msgid "No URI provided" -msgstr "Nav sniegts URL" +msgstr "Nav sniegts URI" #: ../libsoup/soup-request.c:152 #, c-format @@ -75,3 +75,4 @@ msgstr "Datora nosaukumam nav bāzes domēna" #: ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "Nepietiekami daudz domēnu" + -- cgit v1.2.1 From 9f2b3e3638fa26ecbee53aa9944f4bed81dd0802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Mon, 24 Sep 2012 11:03:32 +0300 Subject: [l10n] Updated Estonian translation --- po/et.po | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 po/et.po diff --git a/po/et.po b/po/et.po new file mode 100644 index 00000000..249914f4 --- /dev/null +++ b/po/et.po @@ -0,0 +1,66 @@ +# Estonian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Mattias Põldaru , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-22 21:01+0000\n" +"PO-Revision-Date: 2012-09-23 15:11+0300\n" +"Last-Translator: Mattias Põldaru \n" +"Language-Team: Estonian \n" +"Language: et\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Connection terminated unexpectedly" +msgstr "Ühendus katkes ootamatult" + +msgid "Invalid seek request" +msgstr "Sobimatu kerimise päring" + +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream-i pole võimalik lühendada" + +#, c-format +msgid "Output buffer is too small" +msgstr "Väljundpuhver on liiga väike" + +msgid "Operation was cancelled" +msgstr "Operatsioon katkestati" + +msgid "Operation would block" +msgstr "Operatsioon blokeeruks" + +#, c-format +msgid "No URI provided" +msgstr "URI-d ei antud" + +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Sobimatu '%s' URI: %s" + +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI-d '%s' polnud võimalik parsida" + +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "URI skeem pole toetatud '%s'" + +msgid "Hostname is an IP address" +msgstr "Hostinimi on IP-aadress" + +msgid "Invalid hostname" +msgstr "Sobimatu hostinimi" + +msgid "Hostname has no base domain" +msgstr "Hostinimel puudub baasdomeen" + +msgid "Not enough domains" +msgstr "Pole piisavalt domeene" -- cgit v1.2.1 From d134af97aea21536df495f3e47b3699103907c6d Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Mon, 24 Sep 2012 11:08:25 +0300 Subject: [l10n] Added Estonian (et) to LINGUAS --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index e11460e3..267c5509 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -9,6 +9,7 @@ el en_GB eo es +et fa fr gl -- cgit v1.2.1 From bcfc0669f5fb8706015ef84b82d924457a911522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20Mazurs?= Date: Mon, 24 Sep 2012 16:54:35 +0300 Subject: Updated Latvian translation --- po/lv.po | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/po/lv.po b/po/lv.po index 0830eb0e..f92e647a 100644 --- a/po/lv.po +++ b/po/lv.po @@ -7,10 +7,9 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-22 03:28+0000\n" -"PO-Revision-Date: 2012-09-23 15:59+0300\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-24 16:54+0300\n" +"PO-Revision-Date: 2012-09-24 16:54+0300\n" "Last-Translator: Rūdolfs Mazurs \n" "Language-Team: Latvian \n" "Language: lv\n" @@ -21,12 +20,20 @@ msgstr "" "2);\n" "X-Generator: Lokalize 1.4\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Savienojums tika negaidīti pārtraukts" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Nederīgs meklēšanas pieprasījums" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Nevar apraut SoupBodyInputStream" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 7496908adfe7ef37462b621b97f1879cc2cc0271 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 24 Sep 2012 13:22:55 -0400 Subject: 2.40.0 --- NEWS | 7 +++++++ configure.ac | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 9eae8aaf..f591aa8b 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +Changes in libsoup from 2.39.92 to 2.40.0 + + * New/updated translations: + Bengali (India), Bulgarian, Chinese (Simplified), Estonian, + German, Hebrew, Hindi, Hungarian, Latvian, Malayalam, + Punjabi, Tamil, Telugu, Thai, Ukranian + Changes in libsoup from 2.39.91 to 2.39.92: * Fixed some g_warnings (and a possible crash) with the diff --git a/configure.ac b/configure.ac index 188b900b..ce382745 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *** Initialize automake and set version *** dnl ******************************************* AC_PREREQ(2.63) -AC_INIT([libsoup],[2.39.92],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[2.40.0],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -- cgit v1.2.1 From 266aea4cbdd955133c54d86983b4be165ee24072 Mon Sep 17 00:00:00 2001 From: Gil Forcada Date: Wed, 26 Sep 2012 01:23:25 +0200 Subject: [l10n] Added Catalan translation --- po/ca.po | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 po/ca.po diff --git a/po/ca.po b/po/ca.po new file mode 100644 index 00000000..9b14dd1a --- /dev/null +++ b/po/ca.po @@ -0,0 +1,83 @@ +# Catalan translation for libsoup. +# Copyright (C) 2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Gil Forcada , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-09-23 13:00+0000\n" +"PO-Revision-Date: 2012-09-23 17:22+0200\n" +"Last-Translator: Gil Forcada \n" +"Language-Team: Catalan \n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bits\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Gtranslator 2.91.5\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "S'ha finalitzat la connexió inesperadament" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "La petició de cerca no és vàlida" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No es pot truncar el SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "La memòria intermèdia de sortida és massa petita" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "S'ha canceŀlat l'operació" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "L'operació bloquejaria" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "No s'ha proporcionat cap URI" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "L'URI «%s» no és vàlid: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "No s'ha pogut analitzar l'URI «%s»" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "No es sap gestionar l'esquema d'URI «%s»" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "El nom d'ordinador és una adreça IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "El nom d'ordinador no és vàlid" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "El nom d'ordinador no té cap domini base" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "No hi ha prou dominis" -- cgit v1.2.1 From 9e6134750dbe8562cfe29ee781c7446edbc1ac36 Mon Sep 17 00:00:00 2001 From: Carles Ferrando Date: Wed, 26 Sep 2012 01:23:44 +0200 Subject: [l10n] Added Catalan (Valencian) translation --- po/LINGUAS | 2 ++ po/ca@valencia.po | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 po/ca@valencia.po diff --git a/po/LINGUAS b/po/LINGUAS index 267c5509..70ba61bf 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -2,6 +2,8 @@ as be bg bn_IN +ca +ca@valencia cs da de diff --git a/po/ca@valencia.po b/po/ca@valencia.po new file mode 100644 index 00000000..6b447f21 --- /dev/null +++ b/po/ca@valencia.po @@ -0,0 +1,82 @@ +# Catalan translation for libsoup. +# Copyright (C) 2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the libsoup package. +# Gil Forcada , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-09-26 01:23+0200\n" +"PO-Revision-Date: 2012-09-23 17:22+0200\n" +"Last-Translator: Gil Forcada \n" +"Language-Team: Catalan \n" +"Language: ca-XV\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bits\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Gtranslator 2.91.5\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "S'ha finalitzat la connexió inesperadament" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "La petició de cerca no és vàlida" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No es pot truncar el SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "La memòria intermèdia d'eixida és massa petita" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "S'ha canceŀlat l'operació" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "L'operació bloquejaria" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "No s'ha proporcionat cap URI" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "L'URI «%s» no és vàlid: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "No s'ha pogut analitzar l'URI «%s»" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "No es sap gestionar l'esquema d'URI «%s»" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "El nom d'ordinador és una adreça IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "El nom d'ordinador no és vàlid" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "El nom d'ordinador no té cap domini base" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "No hi ha prou dominis" -- cgit v1.2.1 From cb90c55a22ca5a4f97e624b2f69b3b93e6feba74 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 7 Oct 2012 18:24:12 -0400 Subject: SoupAddress: fix handling of IPv6 literals When generating a URI to pass to GProxyResolver, escape IPv6 literals properly. https://bugzilla.gnome.org/show_bug.cgi?id=684990 --- libsoup/soup-address.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index f2e698bc..c298d3e0 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -1200,20 +1200,25 @@ soup_address_connectable_proxy_enumerate (GSocketConnectable *connectable) SoupAddress *addr = SOUP_ADDRESS (connectable); SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr); GSocketAddressEnumerator *proxy_enum; - char *uri; + SoupURI *uri; + char *uri_string; /* We cheerily assume "http" here because you shouldn't be * using SoupAddress any more if you're not doing HTTP anyway. */ - uri = g_strdup_printf ("%s://%s:%u", - priv->protocol ? priv->protocol : "http", - priv->name ? priv->name : soup_address_get_physical (addr), - priv->port); + uri = soup_uri_new (NULL); + soup_uri_set_scheme (uri, priv->protocol ? priv->protocol : "http"); + soup_uri_set_host (uri, priv->name ? priv->name : soup_address_get_physical (addr)); + soup_uri_set_port (uri, priv->port); + soup_uri_set_path (uri, ""); + uri_string = soup_uri_to_string (uri, FALSE); + proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, "connectable", connectable, - "uri", uri, + "uri", uri_string, NULL); - g_free (uri); + g_free (uri_string); + soup_uri_free (uri); return proxy_enum; } -- cgit v1.2.1 From 7cf0da11fe6de396c183b11dcd17cc8e117a72c0 Mon Sep 17 00:00:00 2001 From: Kjartan Maraas Date: Sat, 13 Oct 2012 12:50:38 +0200 Subject: =?UTF-8?q?Updated=20Norwegian=20bokm=C3=A5l=20translation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- po/nb.po | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/po/nb.po b/po/nb.po index 2b6c1073..a8c2d0b9 100644 --- a/po/nb.po +++ b/po/nb.po @@ -5,10 +5,10 @@ # msgid "" msgstr "" -"Project-Id-Version: libsoup 3.5.x\n" +"Project-Id-Version: libsoup 3.6.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-07-25 16:29+0200\n" -"PO-Revision-Date: 2012-07-25 16:29+0200\n" +"POT-Creation-Date: 2012-10-13 12:50+0200\n" +"PO-Revision-Date: 2012-10-13 12:50+0200\n" "Last-Translator: Kjartan Maraas \n" "Language-Team: Norwegian bokmål \n" "Language: \n" @@ -16,22 +16,30 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Tilkoblingen ble brutt uventet" -#: ../libsoup/soup-converter-wrapper.c:191 +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Ugyldig søkeforespørsel" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Kan ikke avkorte SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Buffer for utdata er for liten" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 msgid "Operation was cancelled" msgstr "Operasjonen ble avbrutt" -#: ../libsoup/soup-message-io.c:864 +#: ../libsoup/soup-message-io.c:865 msgid "Operation would block" msgstr "Operasjonen ville blokkere" @@ -55,18 +63,18 @@ msgstr "Kunne ikke tolke URI «%s»" msgid "Unsupported URI scheme '%s'" msgstr "URI-skjema «%s» er ikke støttet" -#: ../libsoup/soup-tld.c:148 +#: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Vertsnavnet er en IP-adresse" -#: ../libsoup/soup-tld.c:169 +#: ../libsoup/soup-tld.c:175 msgid "Invalid hostname" msgstr "Ugyldig vertsnavn" -#: ../libsoup/soup-tld.c:184 ../libsoup/soup-tld.c:226 -msgid "Not enough domains" -msgstr "Ikke mange nok domener" - #: ../libsoup/soup-tld.c:204 msgid "Hostname has no base domain" msgstr "Vertsnavnet har ikke noe grunndomene" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Ikke mange nok domener" -- cgit v1.2.1 From 2d9397799e9e32a2d1e363d9b062aaa4acd24077 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Mon, 8 Oct 2012 17:10:19 -0300 Subject: Be more aggressive when looking for the termination boundary Turns out some servers may send line feeds and carriage return after the final boundary. That's the case for the following WebKit LayoutTest: http/tests/multipart/load-last-non-html-frame.php https://bugzilla.gnome.org/show_bug.cgi?id=685752 --- libsoup/soup-multipart-input-stream.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-multipart-input-stream.c b/libsoup/soup-multipart-input-stream.c index b1738efe..0867f84b 100644 --- a/libsoup/soup-multipart-input-stream.c +++ b/libsoup/soup-multipart-input-stream.c @@ -378,8 +378,10 @@ soup_multipart_input_stream_read_headers (SoupMultipartInputStream *multipart, got_boundary = TRUE; /* Now check for possible multipart termination. */ - buf = &read_buf[nread - 2]; - if (nread >= 2 && !memcmp (buf, "--", 2)) { + buf = &read_buf[nread - 4]; + if ((nread >= 4 && !memcmp (buf, "--\r\n", 4)) || + (nread >= 3 && !memcmp (buf + 1, "--\n", 3)) || + (nread >= 3 && !memcmp (buf + 2, "--", 2))) { g_byte_array_set_size (priv->meta_buf, 0); return FALSE; } -- cgit v1.2.1 From 91efda67678dbad28603ee8034a10cc6081f4b8d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 16 Oct 2012 07:35:03 -0400 Subject: 2.40.1 --- NEWS | 12 +++++++++++- configure.ac | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index f591aa8b..5c533deb 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,14 @@ -Changes in libsoup from 2.39.92 to 2.40.0 +Changes in libsoup from 2.40.0 to 2.40.1: + + * Improved the parsing of multipart/x-mixed-replace responses. + [#685752, Gustavo] + + * Fixed handling of IPv6 address literals. [#684990, Dan] + + * New/updated translations: + Catalan, Catalan (Valencian), Norwegian bokmål + +Changes in libsoup from 2.39.92 to 2.40.0: * New/updated translations: Bengali (India), Bulgarian, Chinese (Simplified), Estonian, diff --git a/configure.ac b/configure.ac index ce382745..d10d2dcc 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *** Initialize automake and set version *** dnl ******************************************* AC_PREREQ(2.63) -AC_INIT([libsoup],[2.40.0],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[2.40.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -- cgit v1.2.1 From 3d9c0aed72554d5c0ac6fd1b620588f1da115a6f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 16 Oct 2012 07:39:40 -0400 Subject: Post-branch release bump --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d10d2dcc..f0945875 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl *** Initialize automake and set version *** dnl ******************************************* AC_PREREQ(2.63) -AC_INIT([libsoup],[2.40.1],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[2.41.0],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -- cgit v1.2.1 From 501d327ad2312a97fb585369f3537563b8d296fc Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 16 Oct 2012 10:55:18 -0400 Subject: soup-auth-manager-ntlm.c: don't include the default domain in the response If the user didn't specify a domain in their username, then send "" for the domain in the response, rather than echoing back the default domain. This is apparently more compatible with what other apps do. https://bugzilla.gnome.org/show_bug.cgi?id=624613 --- libsoup/soup-auth-manager-ntlm.c | 5 ++--- tests/ntlm-test.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libsoup/soup-auth-manager-ntlm.c b/libsoup/soup-auth-manager-ntlm.c index f2b67d1d..ecb9c7c0 100644 --- a/libsoup/soup-auth-manager-ntlm.c +++ b/libsoup/soup-auth-manager-ntlm.c @@ -459,7 +459,7 @@ ssofailure: *slash = '\0'; username = slash + 1; } else - domain = conn->domain; + domain = g_strdup (""); conn->response_header = soup_ntlm_response (conn->nonce, username, password, @@ -470,8 +470,7 @@ ssofailure: soup_session_requeue_message (priv->session, msg); done: - if (domain != conn->domain) - g_free (domain); + g_free (domain); g_free (conn->domain); conn->domain = NULL; g_free (conn->nonce); diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index 00222e87..e473ba67 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -24,7 +24,7 @@ typedef enum { #define NTLM_CHALLENGE "TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=" -#define NTLM_RESPONSE_USER(response) ((response)[102] == 'E' ? NTLM_AUTHENTICATED_ALICE : NTLM_AUTHENTICATED_BOB) +#define NTLM_RESPONSE_USER(response) ((response)[86] == 'E' ? NTLM_AUTHENTICATED_ALICE : NTLM_AUTHENTICATED_BOB) static void clear_state (gpointer connections, GObject *ex_connection) -- cgit v1.2.1 From 1eb38e53c6593bb168a91d0a1b18942e162100af Mon Sep 17 00:00:00 2001 From: Bahodir Mansurov <6ahodir@gmail.com> Date: Tue, 16 Oct 2012 14:48:57 -0400 Subject: updating Uzbek@cyrillic translation --- po/uz@cyrillic.po | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 po/uz@cyrillic.po diff --git a/po/uz@cyrillic.po b/po/uz@cyrillic.po new file mode 100644 index 00000000..7060d2f1 --- /dev/null +++ b/po/uz@cyrillic.po @@ -0,0 +1,82 @@ +# Uzbek (Cyrillic) translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Bahodir Mansurov <6ahodir@gmail.com>, 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup gnome-3-6\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-10-16 12:52+0000\n" +"PO-Revision-Date: 2012-10-16 14:46-0500\n" +"Last-Translator: Bahodir Mansurov <6ahodir@gmail.com>\n" +"Language-Team: Uzbek (Cyrillic) \n" +"Language: uz@cyrillic\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Алоқа кутилмаганда узилди" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Нотўғри излаш сўрови" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStreamни тўхтатиб бўлмади" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Чиқув буфери жуда кичик" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "Амал инкор этилди" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "Амал тўсиб қўяди" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI кўрсатилмаган" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Нотўғри URI '%s': '%s'" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s' таҳлил қилиб бўлмади" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Қўллаб қувватланмаган '%s' URI чизмаси" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Компьютер номи IP адресдан иборат" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Нотўғри компьютер номи" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Компьютер номида домен қисми йўқ" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Домен исмлари етарли емас" -- cgit v1.2.1 From 0778d818235e1b16eebea351019c3c4d72941d30 Mon Sep 17 00:00:00 2001 From: Bahodir Mansurov <6ahodir@gmail.com> Date: Tue, 16 Oct 2012 14:51:54 -0400 Subject: adding uz@cyrillic to LINGUAS --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index 70ba61bf..3f589158 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -43,6 +43,7 @@ te th tr uk +uz@cyrillic vi zh_CN zh_HK -- cgit v1.2.1 From aa8e1dc5127b56bd96e9d3068a6bfeb7c1a07a94 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 2 Oct 2012 08:57:52 -0400 Subject: SoupConnection: fix a race condition with non-keepalive messages When a SoupSession sets a connection back to IDLE on a non-keepalive message, the connection then disconnects itself. However, it had been briefly setting its state to IDLE before disconnecting. Although this wasn't supposed to be observable (it doesn't emit a notification), in a SoupSessionSync, it could be observed by another thread, which might then try to claim the connection to send another request on, causing problems when the first thread then disconnected it. Fix this by inlining clear_current_item() into soup_connection_set_state() and reordering the code to not change priv->state until after deciding whether or not it's going to disconnect. https://bugzilla.gnome.org/show_bug.cgi?id=684238 --- libsoup/soup-connection.c | 93 +++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 51 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index d2746e8d..1889a940 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -66,7 +66,6 @@ enum { }; static void stop_idle_timer (SoupConnectionPrivate *priv); -static void clear_current_item (SoupConnection *conn); /* Number of seconds after which we close a connection that hasn't yet * been used. @@ -99,13 +98,7 @@ soup_connection_dispose (GObject *object) SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); stop_idle_timer (priv); - /* Make sure clear_current_item doesn't re-establish the timeout */ - priv->idle_timeout = 0; - if (priv->cur_item) { - g_warning ("Disposing connection with cur_item set"); - clear_current_item (conn); - } if (priv->socket) { g_warning ("Disposing connection while connected"); soup_connection_disconnect (conn); @@ -416,45 +409,6 @@ set_current_item (SoupConnection *conn, SoupMessageQueueItem *item) g_object_thaw_notify (G_OBJECT (conn)); } -static void -clear_current_item (SoupConnection *conn) -{ - SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); - - g_object_freeze_notify (G_OBJECT (conn)); - - priv->unused_timeout = 0; - start_idle_timer (conn); - - if (priv->cur_item) { - SoupMessageQueueItem *item; - - item = priv->cur_item; - priv->cur_item = NULL; - g_object_notify (G_OBJECT (conn), "message"); - - g_signal_handlers_disconnect_by_func (item->msg, G_CALLBACK (current_item_restarted), conn); - - if (item->msg->method == SOUP_METHOD_CONNECT && - SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) { - soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATED, NULL); - - /* We're now effectively no longer proxying */ - soup_uri_free (priv->proxy_uri); - priv->proxy_uri = NULL; - - /* Nor are we actually IDLE... */ - if (priv->state == SOUP_CONNECTION_IDLE) - priv->state = SOUP_CONNECTION_IN_USE; - } - - if (!soup_message_is_keepalive (item->msg) || !priv->reusable) - soup_connection_disconnect (conn); - } - - g_object_thaw_notify (G_OBJECT (conn)); -} - static void proxy_socket_event (SoupSocket *socket, GSocketClientEvent event, @@ -938,6 +892,7 @@ void soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) { SoupConnectionPrivate *priv; + SoupConnectionState old_state; g_return_if_fail (SOUP_IS_CONNECTION (conn)); g_return_if_fail (state >= SOUP_CONNECTION_NEW && @@ -946,13 +901,49 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) g_object_freeze_notify (G_OBJECT (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - priv->state = state; - if (state == SOUP_CONNECTION_IDLE || - state == SOUP_CONNECTION_DISCONNECTED) - clear_current_item (conn); + old_state = priv->state; + + if (old_state == SOUP_CONNECTION_IN_USE) + priv->unused_timeout = 0; + + if (priv->cur_item) { + SoupMessageQueueItem *item; + + g_warn_if_fail (state == SOUP_CONNECTION_IDLE || + state == SOUP_CONNECTION_DISCONNECTED); + + item = priv->cur_item; + priv->cur_item = NULL; + g_object_notify (G_OBJECT (conn), "message"); + + g_signal_handlers_disconnect_by_func (item->msg, G_CALLBACK (current_item_restarted), conn); + + if (item->msg->method == SOUP_METHOD_CONNECT && + SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) { + soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATED, NULL); + + /* We're now effectively no longer proxying */ + soup_uri_free (priv->proxy_uri); + priv->proxy_uri = NULL; + + /* Nor are we actually IDLE... */ + if (state == SOUP_CONNECTION_IDLE) + state = SOUP_CONNECTION_IN_USE; + } + + if (!soup_message_is_keepalive (item->msg) || !priv->reusable) + soup_connection_disconnect (conn); + } + + if (priv->state == old_state && priv->state != state) { + priv->state = state; + + if (state == SOUP_CONNECTION_IDLE) + start_idle_timer (conn); - if (priv->state == state) g_object_notify (G_OBJECT (conn), "state"); + } + g_object_thaw_notify (G_OBJECT (conn)); } -- cgit v1.2.1 From cbbde758b8ea533916fe25dc25d64bac564ea09a Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Sun, 26 Aug 2012 15:20:34 +0200 Subject: soup-request: Add support to handle gresource URI requests GFile already supports gresource when using g_file_new_for_uri() with a resource:// URI. We can add "resource" as a valid scheme for SoupRequestFile and make sure the GFile is created with the gresource URI for gresource requests. https://bugzilla.gnome.org/show_bug.cgi?id=682721 --- configure.ac | 3 + docs/reference/libsoup-2.4-sections.txt | 1 + libsoup/soup-request-file.c | 12 +- libsoup/soup-uri.c | 13 +- libsoup/soup-uri.h | 13 +- tests/Makefile.am | 29 +++- tests/resource-test.c | 296 ++++++++++++++++++++++++++++++++ tests/soup-tests.gresource.xml | 6 + 8 files changed, 355 insertions(+), 18 deletions(-) create mode 100644 tests/resource-test.c create mode 100644 tests/soup-tests.gresource.xml diff --git a/configure.ac b/configure.ac index f0945875..a6b2b708 100644 --- a/configure.ac +++ b/configure.ac @@ -307,6 +307,9 @@ else fi AM_CONDITIONAL(HAVE_CURL, test "$CURL" != no) +GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0` +AC_SUBST(GLIB_COMPILE_RESOURCES) + AC_SUBST(MISSING_REGRESSION_TEST_PACKAGES) AM_CONDITIONAL(MISSING_REGRESSION_TEST_PACKAGES, test -n "$MISSING_REGRESSION_TEST_PACKAGES") diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 6f819c32..961e4163 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -631,6 +631,7 @@ SOUP_URI_SCHEME_HTTPS SOUP_URI_SCHEME_DATA SOUP_URI_SCHEME_FILE SOUP_URI_SCHEME_FTP +SOUP_URI_SCHEME_RESOURCE soup_uri_uses_default_port SOUP_URI_IS_VALID SOUP_URI_VALID_FOR_HTTP diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c index 0b5638d2..73d0cd8c 100644 --- a/libsoup/soup-request-file.c +++ b/libsoup/soup-request-file.c @@ -128,7 +128,15 @@ soup_request_file_ensure_file (SoupRequestFile *file, windowsify_file_uri_path (decoded_path); #endif - file->priv->gfile = g_file_new_for_path (decoded_path); + if (uri->scheme == SOUP_URI_SCHEME_RESOURCE) { + char *uri_str; + + uri_str = g_strdup_printf ("resource://%s", decoded_path); + file->priv->gfile = g_file_new_for_uri (uri_str); + g_free (uri_str); + } else + file->priv->gfile = g_file_new_for_path (decoded_path); + g_free (decoded_path); return TRUE; } @@ -250,7 +258,7 @@ soup_request_file_get_content_type (SoupRequest *request) return file->priv->mime_type; } -static const char *file_schemes[] = { "file", NULL }; +static const char *file_schemes[] = { "file", "resource", NULL }; static void soup_request_file_class_init (SoupRequestFileClass *request_file_class) diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 4be679d5..d19290b0 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -110,7 +110,7 @@ static char *uri_normalized_copy (const char *str, int length, const char *unesc gpointer _SOUP_URI_SCHEME_HTTP, _SOUP_URI_SCHEME_HTTPS; gpointer _SOUP_URI_SCHEME_FTP; -gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA; +gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA, _SOUP_URI_SCHEME_RESOURCE; static inline const char * soup_uri_parse_scheme (const char *scheme, int len) @@ -119,6 +119,8 @@ soup_uri_parse_scheme (const char *scheme, int len) return SOUP_URI_SCHEME_HTTP; } else if (len == 5 && !g_ascii_strncasecmp (scheme, "https", len)) { return SOUP_URI_SCHEME_HTTPS; + } else if (len == 8 && !g_ascii_strncasecmp (scheme, "resource", len)) { + return SOUP_URI_SCHEME_RESOURCE; } else { char *lower_scheme; @@ -814,6 +816,15 @@ soup_uri_uses_default_port (SoupURI *uri) * against the value of a #SoupURI's scheme **/ +/** + * SOUP_URI_SCHEME_RESOURCE: + * + * "resource" as an interned string. This can be compared directly + * against the value of a #SoupURI's scheme + * + * Since: 2.42 + **/ + /** * soup_uri_get_scheme: * @uri: a #SoupURI diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h index b851dbec..e2195b16 100644 --- a/libsoup/soup-uri.h +++ b/libsoup/soup-uri.h @@ -31,14 +31,15 @@ struct _SoupURI { GType soup_uri_get_type (void); #define SOUP_TYPE_URI (soup_uri_get_type ()) -#define SOUP_URI_SCHEME_HTTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTP, "http") -#define SOUP_URI_SCHEME_HTTPS _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTPS, "https") -#define SOUP_URI_SCHEME_FTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FTP, "ftp") -#define SOUP_URI_SCHEME_FILE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FILE, "file") -#define SOUP_URI_SCHEME_DATA _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_DATA, "data") +#define SOUP_URI_SCHEME_HTTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTP, "http") +#define SOUP_URI_SCHEME_HTTPS _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_HTTPS, "https") +#define SOUP_URI_SCHEME_FTP _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FTP, "ftp") +#define SOUP_URI_SCHEME_FILE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_FILE, "file") +#define SOUP_URI_SCHEME_DATA _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_DATA, "data") +#define SOUP_URI_SCHEME_RESOURCE _SOUP_ATOMIC_INTERN_STRING (_SOUP_URI_SCHEME_RESOURCE, "resource") extern gpointer _SOUP_URI_SCHEME_HTTP, _SOUP_URI_SCHEME_HTTPS; extern gpointer _SOUP_URI_SCHEME_FTP; -extern gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA; +extern gpointer _SOUP_URI_SCHEME_FILE, _SOUP_URI_SCHEME_DATA, _SOUP_URI_SCHEME_RESOURCE; SoupURI *soup_uri_new_with_base (SoupURI *base, const char *uri_string); diff --git a/tests/Makefile.am b/tests/Makefile.am index d2a1cd64..085a81b3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,6 +28,7 @@ noinst_PROGRAMS = \ ntlm-test \ redirect-test \ requester-test \ + resource-test \ simple-httpd \ simple-proxy \ sniffing-test \ @@ -41,6 +42,8 @@ noinst_PROGRAMS = \ $(APACHE_TESTS) \ $(XMLRPC_TESTS) +noinst_DATA = soup-tests.gresource + TEST_SRCS = test-utils.c test-utils.h auth_test_SOURCES = auth-test.c $(TEST_SRCS) @@ -66,6 +69,7 @@ pull_api_SOURCES = pull-api.c $(TEST_SRCS) range_test_SOURCES = range-test.c $(TEST_SRCS) redirect_test_SOURCES = redirect-test.c $(TEST_SRCS) requester_test_SOURCES = requester-test.c $(TEST_SRCS) +resource_test_SOURCES = resource-test.c $(TEST_SRCS) server_auth_test_SOURCES = server-auth-test.c $(TEST_SRCS) simple_httpd_SOURCES = simple-httpd.c simple_proxy_SOURCES = simple-proxy.c @@ -89,6 +93,9 @@ if HAVE_XMLRPC_EPI_PHP XMLRPC_TESTS = xmlrpc-test xmlrpc-server-test endif +soup-tests.gresource: soup-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) + $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< + TESTS = \ chunk-test \ coding-test \ @@ -103,6 +110,7 @@ TESTS = \ ntlm-test \ redirect-test \ requester-test \ + resource-test \ sniffing-test \ socket-test \ ssl-test \ @@ -127,17 +135,20 @@ RESOURCES = \ resources/test.html \ resources/text_binary.txt -EXTRA_DIST = \ - htdigest \ - htpasswd \ - httpd.conf.in \ - index.txt \ - libsoup.supp \ - test-cert.pem \ - test-key.pem \ - xmlrpc-server.php \ +EXTRA_DIST = \ + htdigest \ + htpasswd \ + httpd.conf.in \ + index.txt \ + libsoup.supp \ + soup-tests.gresource.xml \ + test-cert.pem \ + test-key.pem \ + xmlrpc-server.php \ $(RESOURCES) +DISTCLEANFILES = soup-tests.gresource + if MISSING_REGRESSION_TEST_PACKAGES check-local: check-TESTS @echo "" diff --git a/tests/resource-test.c b/tests/resource-test.c new file mode 100644 index 00000000..449820a4 --- /dev/null +++ b/tests/resource-test.c @@ -0,0 +1,296 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia S.L. + */ + +#include "test-utils.h" + +SoupBuffer *index_buffer; + +static void +get_index (void) +{ + char *contents; + gsize length; + GError *error = NULL; + + if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) { + g_printerr ("Could not read index.txt: %s\n", + error->message); + exit (1); + } + + index_buffer = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length); +} + +static void +register_gresource (void) +{ + GResource *resource; + GError *error = NULL; + + resource = g_resource_load ("soup-tests.gresource", &error); + if (!resource) { + g_printerr ("Could not load resource soup-tests.gresource: %s\n", + error->message); + exit (1); + } + g_resources_register (resource); + g_resource_unref (resource); +} + +static void +check_results (GString *body) +{ + if (body->len != index_buffer->length) { + debug_printf (1, " body length mismatch: expected %d, got %d\n", + (int)index_buffer->length, (int)body->len); + errors++; + } else if (memcmp (body->str, index_buffer->data, body->len) != 0) { + debug_printf (1, " body data mismatch\n"); + errors++; + } +} + +typedef struct { + GString *body; + char buffer[1024]; + GMainLoop *loop; +} AsyncRequestData; + +static void +stream_closed (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GInputStream *in = G_INPUT_STREAM (source); + AsyncRequestData *data = user_data; + GError *error = NULL; + + if (!g_input_stream_close_finish (in, result, &error)) { + debug_printf (1, " close failed: %s\n", error->message); + g_error_free (error); + errors++; + } + g_main_loop_quit (data->loop); + g_object_unref (in); +} + +static void +test_read_ready (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GInputStream *in = G_INPUT_STREAM (source); + AsyncRequestData *data = user_data; + gssize nread; + GError *error = NULL; + + nread = g_input_stream_read_finish (in, result, &error); + if (nread == -1) { + debug_printf (1, " g_input_stream_read failed: %s\n", + error->message); + g_clear_error (&error); + g_input_stream_close (in, NULL, NULL); + g_object_unref (in); + errors++; + return; + } else if (nread == 0) { + g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, + stream_closed, data); + return; + } + + g_string_append_len (data->body, data->buffer, nread); + g_input_stream_read_async (in, data->buffer, sizeof (data->buffer), + G_PRIORITY_DEFAULT, NULL, + test_read_ready, data); +} + +static void +async_request_sent (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GInputStream *in; + AsyncRequestData *data = user_data; + GError *error = NULL; + + in = soup_request_send_finish (SOUP_REQUEST (source), result, &error); + if (!in) { + debug_printf (1, " soup_request_send_async failed: %s\n", + error->message); + g_clear_error (&error); + errors++; + return; + } + + g_input_stream_read_async (in, data->buffer, sizeof (data->buffer), + G_PRIORITY_DEFAULT, NULL, + test_read_ready, data); +} + +static void +do_async_request (SoupRequest *request) +{ + AsyncRequestData data; + + data.body = g_string_new (NULL); + soup_request_send_async (request, NULL, async_request_sent, &data); + + data.loop = g_main_loop_new (soup_session_get_async_context (soup_request_get_session (request)), TRUE); + g_main_loop_run (data.loop); + g_main_loop_unref (data.loop); + + check_results (data.body); + g_string_free (data.body, TRUE); +} + +static void +do_sync_request (SoupRequest *request) +{ + GInputStream *in; + GString *body; + char buffer[1024]; + gssize nread; + GError *error = NULL; + + in = soup_request_send (request, NULL, &error); + if (!in) { + debug_printf (1, " soup_request_send failed: %s\n", + error->message); + g_clear_error (&error); + errors++; + return; + } + + body = g_string_new (NULL); + do { + nread = g_input_stream_read (in, buffer, sizeof (buffer), + NULL, &error); + if (nread == -1) { + debug_printf (1, " g_input_stream_read failed: %s\n", + error->message); + g_clear_error (&error); + errors++; + break; + } + g_string_append_len (body, buffer, nread); + } while (nread > 0); + + if (!g_input_stream_close (in, NULL, &error)) { + debug_printf (1, " g_input_stream_close failed: %s\n", + error->message); + g_clear_error (&error); + errors++; + } + g_object_unref (in); + + check_results (body); + g_string_free (body, TRUE); +} + +static void +do_request_file_test (SoupRequester *requester, + gboolean async) +{ + SoupRequest *request; + GFile *index; + char *uri_string; + SoupURI *uri; + + index = g_file_new_for_path (SRCDIR "/index.txt"); + uri_string = g_file_get_uri (index); + g_object_unref (index); + + uri = soup_uri_new (uri_string); + g_free (uri_string); + + request = soup_requester_request_uri (requester, uri, NULL); + if (async) + do_async_request (request); + else + do_sync_request (request); + g_object_unref (request); + + soup_uri_free (uri); +} + +static void +do_request_data_test (SoupRequester *requester, + gboolean async) +{ + SoupRequest *request; + gchar *base64; + char *uri_string; + SoupURI *uri; + + base64 = g_base64_encode ((const guchar *)index_buffer->data, index_buffer->length); + uri_string = g_strdup_printf ("data:text/plain;charset=utf8;base64,%s", base64); + g_free (base64); + + uri = soup_uri_new (uri_string); + g_free (uri_string); + + request = soup_requester_request_uri (requester, uri, NULL); + if (async) + do_async_request (request); + else + do_sync_request (request); + g_object_unref (request); + + soup_uri_free (uri); +} + +static void +do_request_gresource_test (SoupRequester *requester, + gboolean async) +{ + SoupRequest *request; + SoupURI *uri; + + uri = soup_uri_new ("resource:///org/gnome/libsoup/tests/index.txt"); + request = soup_requester_request_uri (requester, uri, NULL); + if (async) + do_async_request (request); + else + do_sync_request (request); + g_object_unref (request); + + soup_uri_free (uri); +} + +int +main (int argc, char **argv) +{ + SoupSession *session; + SoupRequester *requester; + + test_init (argc, argv, NULL); + + get_index (); + register_gresource (); + + /* Sync tests */ + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + requester = soup_requester_new (); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); + g_object_unref (requester); + + do_request_file_test (requester, FALSE); + do_request_data_test (requester, FALSE); + do_request_gresource_test (requester, FALSE); + + soup_test_session_abort_unref (session); + + /* Async tests */ + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + requester = soup_requester_new (); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); + g_object_unref (requester); + + do_request_file_test (requester, TRUE); + do_request_data_test (requester, TRUE); + do_request_gresource_test (requester, TRUE); + + soup_test_session_abort_unref (session); + + test_cleanup (); + return errors != 0; +} diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml new file mode 100644 index 00000000..969a6bfe --- /dev/null +++ b/tests/soup-tests.gresource.xml @@ -0,0 +1,6 @@ + + + + index.txt + + \ No newline at end of file -- cgit v1.2.1 From 33cf3c6f2530732e85a93d42c153db53844feebb Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Thu, 20 Sep 2012 17:02:40 -0700 Subject: Add API to get version information Expose API to get information about the soup version. This is useful because it allows applications to use API without actually depending on it completely. https://bugzilla.gnome.org/show_bug.cgi?id=684514 --- .gitignore | 1 + configure.ac | 14 ++- docs/reference/libsoup-2.4-docs.sgml | 1 + docs/reference/libsoup-2.4-sections.txt | 15 ++++ libsoup/Makefile.am | 4 + libsoup/soup-version.c | 146 ++++++++++++++++++++++++++++++++ libsoup/soup-version.h.in | 41 +++++++++ 7 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 libsoup/soup-version.c create mode 100644 libsoup/soup-version.h.in diff --git a/.gitignore b/.gitignore index c3873607..203bd2f2 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ libsoup/Soup-2.4.typelib libsoup/SoupGNOME-2.4.gir libsoup/SoupGNOME-2.4.typelib libsoup/tld_data.inc +libsoup/soup-version.h libtool ltmain.sh m4/gtk-doc.m4 diff --git a/configure.ac b/configure.ac index a6b2b708..438df9c5 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,12 @@ dnl ******************************************* dnl *** Initialize automake and set version *** dnl ******************************************* +m4_define([soup_major_version], [2]) +m4_define([soup_minor_version], [41]) +m4_define([soup_micro_version], [0]) + AC_PREREQ(2.63) -AC_INIT([libsoup],[2.41.0],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) +AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) @@ -12,6 +16,13 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) AC_PROG_MAKE_SET +SOUP_MAJOR_VERSION=soup_major_version +SOUP_MINOR_VERSION=soup_minor_version +SOUP_MICRO_VERSION=soup_micro_version +AC_SUBST(SOUP_MAJOR_VERSION) +AC_SUBST(SOUP_MINOR_VERSION) +AC_SUBST(SOUP_MICRO_VERSION) + SOUP_API_VERSION=2.4 AC_SUBST(SOUP_API_VERSION) @@ -365,6 +376,7 @@ AC_CONFIG_FILES([ tests/httpd.conf docs/Makefile docs/reference/Makefile + libsoup/soup-version.h ]) AC_OUTPUT diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index 76aa87ea..ae74c015 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -33,6 +33,7 @@ + diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 961e4163..4c1c60b6 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -1202,3 +1202,18 @@ SoupTLDError soup_tld_error_quark
+ +
+soup-version +Version Information +soup_get_major_version +soup_get_minor_version +soup_get_micro_version +soup_check_version + + +SOUP_MAJOR_VERSION +SOUP_MINOR_VERSION +SOUP_MICRO_VERSION +SOUP_CHECK_VERSION +
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index cc99e75d..c5f0e400 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -72,6 +72,9 @@ libsoupinclude_HEADERS = \ $(soup_headers) \ soup-enum-types.h +nodist_libsoupinclude_HEADERS = \ + soup-version.h + lib_LTLIBRARIES = libsoup-2.4.la libsoup_2_4_la_LDFLAGS = \ @@ -171,6 +174,7 @@ libsoup_2_4_la_SOURCES = \ soup-tld-private.h \ soup-uri.c \ soup-value-utils.c \ + soup-version.c \ soup-xmlrpc.c # TLD rules diff --git a/libsoup/soup-version.c b/libsoup/soup-version.c new file mode 100644 index 00000000..e2ed0bfa --- /dev/null +++ b/libsoup/soup-version.c @@ -0,0 +1,146 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-version.c: Version information + * + * Copyright (C) 2012 Igalia S.L. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-version.h" + +/** + * SECTION:soup-version + * @short_description: Variables and functions to check the libsoup version + **/ + +/** + * SOUP_MAJOR_VERSION: + * + * Like soup_get_major_version(), but from the headers used at + * application compile time, rather than from the library linked + * against at application run time. + * + * Since: 2.42 + */ + +/** + * SOUP_MINOR_VERSION: + * + * Like soup_get_minor_version(), but from the headers used at + * application compile time, rather than from the library linked + * against at application run time. + * + * Since: 2.42 + */ + +/** + * SOUP_MICRO_VERSION: + * + * Like soup_get_micro_version(), but from the headers used at + * application compile time, rather than from the library linked + * against at application run time. + * + * Since: 2.42 + */ + +/** + * SOUP_CHECK_VERSION: + * @major: major version (e.g. 2 for version 2.42.0) + * @minor: minor version (e.g. 42 for version 2.42.0) + * @micro: micro version (e.g. 0 for version 2.42.0) + * + * Returns: %TRUE if the version of the libsoup header files + * is the same as or newer than the passed-in version. + * + * Since: 2.42 + */ + +/** + * soup_get_major_version: + * + * Returns the major version number of the libsoup library. + * (e.g. in libsoup version 2.42.0 this is 2.) + * + * This function is in the library, so it represents the libsoup library + * your code is running against. Contrast with the #SOUP_MAJOR_VERSION + * macro, which represents the major version of the libsoup headers you + * have included when compiling your code. + * + * Returns: the major version number of the libsoup library + * + * Since: 2.42 + */ +guint +soup_get_major_version (void) +{ + return SOUP_MAJOR_VERSION; +} + +/** + * soup_get_minor_version: + * + * Returns the minor version number of the libsoup library. + * (e.g. in libsoup version 2.42.0 this is 42.) + * + * This function is in the library, so it represents the libsoup library + * your code is running against. Contrast with the #SOUP_MINOR_VERSION + * macro, which represents the minor version of the libsoup headers you + * have included when compiling your code. + * + * Returns: the minor version number of the libsoup library + * + * Since: 2.42 + */ +guint +soup_get_minor_version (void) +{ + return SOUP_MINOR_VERSION; +} + +/** + * soup_get_micro_version: + * + * Returns the micro version number of the libsoup library. + * (e.g. in libsoup version 2.42.0 this is 0.) + * + * This function is in the library, so it represents the libsoup library + * your code is running against. Contrast with the #SOUP_MICRO_VERSION + * macro, which represents the micro version of the libsoup headers you + * have included when compiling your code. + * + * Returns: the micro version number of the libsoup library + * + * Since: 2.42 + */ +guint +soup_get_micro_version (void) +{ + return SOUP_MICRO_VERSION; +} + +/** + * soup_check_version: + * @major: the major version to check + * @minor: the minor version to check + * @micro: the micro version to check + * + * Like SOUP_CHECK_VERSION, but the check for soup_check_version is + * at runtime instead of compile time. This is useful for compiling + * against older versions of libsoup, but using features from newer + * versions. + * + * Returns: %TRUE if the version of the libsoup currently loaded + * is the same as or newer than the passed-in version. + * + * Since: 2.42 + */ +gboolean +soup_check_version (guint major, + guint minor, + guint micro) +{ + return SOUP_CHECK_VERSION (major, minor, micro); +} diff --git a/libsoup/soup-version.h.in b/libsoup/soup-version.h.in new file mode 100644 index 00000000..6332d581 --- /dev/null +++ b/libsoup/soup-version.h.in @@ -0,0 +1,41 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-version.h: Version information + * + * Copyright (C) 2012 Igalia S.L. + */ + +#ifndef SOUP_VERSION_H +#define SOUP_VERSION_H + +#include + +G_BEGIN_DECLS + +#define SOUP_MAJOR_VERSION (@SOUP_MAJOR_VERSION@) +#define SOUP_MINOR_VERSION (@SOUP_MINOR_VERSION@) +#define SOUP_MICRO_VERSION (@SOUP_MICRO_VERSION@) + +#define SOUP_CHECK_VERSION(major, minor, micro) \ + (SOUP_MAJOR_VERSION > (major) || \ + (SOUP_MAJOR_VERSION == (major) && SOUP_MINOR_VERSION > (minor)) || \ + (SOUP_MAJOR_VERSION == (major) && SOUP_MINOR_VERSION == (minor) && \ + SOUP_MICRO_VERSION >= (micro))) + +guint +soup_get_major_version (void); + +guint +soup_get_minor_version (void); + +guint +soup_get_micro_version (void); + +gboolean +soup_check_version (guint major, + guint minor, + guint micro); + +G_END_DECLS + +#endif /* SOUP_VERSION_H */ -- cgit v1.2.1 From e9ce1914f50a46db28ed6a9878f8cf12ea8938bd Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 18 Jun 2012 09:54:41 -0400 Subject: port to GTask --- configure.ac | 4 +- libsoup/soup-address.c | 34 ++++++-------- libsoup/soup-client-input-stream.c | 75 ++++++++++++++---------------- libsoup/soup-message-queue.c | 4 +- libsoup/soup-message-queue.h | 2 +- libsoup/soup-multipart-input-stream.c | 52 ++++++++------------- libsoup/soup-request-file.c | 38 ++++++--------- libsoup/soup-request-http.c | 87 ++++++++++++++--------------------- libsoup/soup-request.c | 23 +++++---- libsoup/soup-session-async.c | 46 ++++++++---------- 10 files changed, 151 insertions(+), 214 deletions(-) diff --git a/configure.ac b/configure.ac index 438df9c5..7576359d 100644 --- a/configure.ac +++ b/configure.ac @@ -83,12 +83,12 @@ dnl *********************** dnl *** Checks for glib *** dnl *********************** -GLIB_REQUIRED=2.33.1 +GLIB_REQUIRED=2.35.0 AM_PATH_GLIB_2_0($GLIB_REQUIRED,,,gobject gio) if test "$GLIB_LIBS" = ""; then AC_MSG_ERROR(GLIB $GLIB_REQUIRED or later is required to build libsoup) fi -GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_34" +GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_36" GLIB_MAKEFILE='$(top_srcdir)/Makefile.glib' AC_SUBST(GLIB_MAKEFILE) diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index c298d3e0..521ff76f 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -1111,15 +1111,19 @@ soup_address_address_enumerator_next (GSocketAddressEnumerator *enumerator, static void got_addresses (SoupAddress *addr, guint status, gpointer user_data) { - GSimpleAsyncResult *simple = user_data; + GTask *task = user_data; GError *error; error = g_object_get_data (G_OBJECT (addr), "async-resolved-error"); if (error) - g_simple_async_result_set_from_error (simple, error); + g_task_return_error (task, error); + else { + GSocketAddress *addr; - g_simple_async_result_complete (simple); - g_object_unref (simple); + addr = next_address (g_task_get_source_object (task)); + g_task_return_pointer (task, addr, g_object_unref); + } + g_object_unref (task); } static void @@ -1131,18 +1135,15 @@ soup_address_address_enumerator_next_async (GSocketAddressEnumerator *enumerato SoupAddressAddressEnumerator *addr_enum = SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator); SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr); - GSimpleAsyncResult *simple; - - simple = g_simple_async_result_new (G_OBJECT (enumerator), - callback, user_data, - soup_address_address_enumerator_next_async); + GTask *task; + task = g_task_new (enumerator, cancellable, callback, user_data); if (!priv->sockaddr) { soup_address_resolve_async (addr_enum->addr, NULL, cancellable, - got_addresses, simple); + got_addresses, task); } else { - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_pointer (task, next_address (addr_enum), g_object_unref); + g_object_unref (task); } } @@ -1151,14 +1152,7 @@ soup_address_address_enumerator_next_finish (GSocketAddressEnumerator *enumerat GAsyncResult *result, GError **error) { - SoupAddressAddressEnumerator *addr_enum = - SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator); - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - else - return next_address (addr_enum); + return g_task_propagate_pointer (G_TASK (result), error); } static void diff --git a/libsoup/soup-client-input-stream.c b/libsoup/soup-client-input-stream.c index 966b9405..ddcabaa5 100644 --- a/libsoup/soup-client-input-stream.c +++ b/libsoup/soup-client-input-stream.c @@ -157,40 +157,43 @@ soup_client_input_stream_close_fn (GInputStream *stream, cancellable, error); } -typedef struct { - SoupClientInputStream *cistream; - gint priority; - GCancellable *cancellable; - GSimpleAsyncResult *result; -} CloseAsyncData; - -static void -close_async_data_free (CloseAsyncData *cad) +static gboolean +idle_finish_close (gpointer user_data) { - g_clear_object (&cad->cancellable); - g_object_unref (cad->result); - g_slice_free (CloseAsyncData, cad); + GTask *task = user_data; + + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return FALSE; } static gboolean close_async_ready (SoupMessage *msg, gpointer user_data) { - CloseAsyncData *cad = user_data; + GTask *task = user_data; + SoupClientInputStream *cistream = g_task_get_source_object (task); GError *error = NULL; - if (!soup_message_io_run_until_finish (cad->cistream->priv->msg, - cad->cancellable, &error) && + if (!soup_message_io_run_until_finish (cistream->priv->msg, + g_task_get_cancellable (task), + &error) && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_error_free (error); return TRUE; } - if (error) - g_simple_async_result_take_error (cad->result, error); - else - g_simple_async_result_set_op_res_gboolean (cad->result, TRUE); - g_simple_async_result_complete_in_idle (cad->result); - close_async_data_free (cad); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return FALSE; + } + + /* Due to a historical accident, SoupSessionAsync relies on us + * waiting one extra cycle after run_until_finish() returns. + * Ugh. FIXME later when it's easier to do. + */ + soup_add_idle (g_main_context_get_thread_default (), + idle_finish_close, task); return FALSE; } @@ -201,22 +204,17 @@ soup_client_input_stream_close_async (GInputStream *stream, GAsyncReadyCallback callback, gpointer user_data) { - CloseAsyncData *cad; + SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (stream); + GTask *task; GSource *source; - cad = g_slice_new (CloseAsyncData); - cad->cistream = SOUP_CLIENT_INPUT_STREAM (stream); - cad->result = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - soup_client_input_stream_close_async); - cad->priority = priority; - cad->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - - source = soup_message_io_get_source (cad->cistream->priv->msg, - cancellable, - close_async_ready, cad); - g_source_set_priority (source, priority); - g_source_attach (source, g_main_context_get_thread_default ()); + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_priority (task, priority); + + source = soup_message_io_get_source (cistream->priv->msg, + cancellable, NULL, NULL); + + g_task_attach_source (task, source, (GSourceFunc) close_async_ready); g_source_unref (source); } @@ -225,12 +223,7 @@ soup_client_input_stream_close_finish (GInputStream *stream, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - else - return g_simple_async_result_get_op_res_gboolean (simple); + return g_task_propagate_boolean (G_TASK (result), error); } static void diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index 2a60446e..9afa31ee 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -185,8 +185,8 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) g_object_unref (item->proxy_addr); if (item->proxy_uri) soup_uri_free (item->proxy_uri); - if (item->result) - g_object_unref (item->result); + if (item->task) + g_object_unref (item->task); if (item->io_source) { g_source_destroy (item->io_source); g_source_unref (item->io_source); diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index 0f948cc3..627fd2d4 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -40,7 +40,7 @@ struct _SoupMessageQueueItem { SoupAddress *proxy_addr; SoupURI *proxy_uri; SoupConnection *conn; - GSimpleAsyncResult *result; + GTask *task; GSource *io_source; guint paused : 1; diff --git a/libsoup/soup-multipart-input-stream.c b/libsoup/soup-multipart-input-stream.c index 0867f84b..9cd1b3af 100644 --- a/libsoup/soup-multipart-input-stream.c +++ b/libsoup/soup-multipart-input-stream.c @@ -483,9 +483,10 @@ soup_multipart_input_stream_next_part (SoupMultipartInputStream *multipart, } static void -soup_multipart_input_stream_next_part_thread (GSimpleAsyncResult *simple, - GObject *object, - GCancellable *cancellable) +soup_multipart_input_stream_next_part_thread (GTask *task, + gpointer object, + gpointer task_data, + GCancellable *cancellable) { SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (object); GError *error = NULL; @@ -495,11 +496,10 @@ soup_multipart_input_stream_next_part_thread (GSimpleAsyncResult *simple, g_input_stream_clear_pending (G_INPUT_STREAM (multipart)); - if (g_simple_async_result_propagate_error (simple, &error)) - return; - - if (new_stream) - g_simple_async_result_set_op_res_gpointer (simple, new_stream, g_object_unref); + if (error) + g_task_return_error (task, error); + else + g_task_return_pointer (task, new_stream, g_object_unref); } /** @@ -520,31 +520,28 @@ soup_multipart_input_stream_next_part_thread (GSimpleAsyncResult *simple, */ void soup_multipart_input_stream_next_part_async (SoupMultipartInputStream *multipart, - int io_priority, + int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data) { GInputStream *stream = G_INPUT_STREAM (multipart); - GSimpleAsyncResult *simple; + GTask *task; GError *error = NULL; g_return_if_fail (SOUP_IS_MULTIPART_INPUT_STREAM (multipart)); - simple = g_simple_async_result_new (G_OBJECT (multipart), - callback, data, - soup_multipart_input_stream_next_part_async); + task = g_task_new (multipart, cancellable, callback, data); + g_task_set_priority (task, io_priority); if (!g_input_stream_set_pending (stream, &error)) { - g_simple_async_result_take_error (simple, error); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + g_task_return_error (task, error); + g_object_unref (task); return; } - g_simple_async_result_run_in_thread (simple, soup_multipart_input_stream_next_part_thread, - io_priority, cancellable); - g_object_unref (simple); + g_task_run_in_thread (task, soup_multipart_input_stream_next_part_thread); + g_object_unref (task); } /** @@ -565,22 +562,9 @@ soup_multipart_input_stream_next_part_finish (SoupMultipartInputStream *multipar GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; - GInputStream *new_stream; - - g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (multipart), - soup_multipart_input_stream_next_part_async), FALSE); - - simple = G_SIMPLE_ASYNC_RESULT (result); - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - - new_stream = g_simple_async_result_get_op_res_gpointer (simple); - if (new_stream) - return g_object_ref (new_stream); + g_return_val_if_fail (g_task_is_valid (result, multipart), FALSE); - return NULL; + return g_task_propagate_pointer (G_TASK (result), error); } /** diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c index 73d0cd8c..22642f47 100644 --- a/libsoup/soup-request-file.c +++ b/libsoup/soup-request-file.c @@ -192,36 +192,33 @@ soup_request_file_send (SoupRequest *request, } static void -soup_request_file_send_async_thread (GSimpleAsyncResult *res, - GObject *object, - GCancellable *cancellable) +soup_request_file_send_async_thread (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) { + SoupRequest *request = source_object; GInputStream *stream; - SoupRequest *request; GError *error = NULL; - request = SOUP_REQUEST (object); - stream = soup_request_file_send (request, cancellable, &error); - if (stream == NULL) - g_simple_async_result_take_error (res, error); + g_task_return_error (task, error); else - g_simple_async_result_set_op_res_gpointer (res, stream, g_object_unref); + g_task_return_pointer (task, stream, g_object_unref); } static void soup_request_file_send_async (SoupRequest *request, GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) + GAsyncReadyCallback callback, + gpointer user_data) { - GSimpleAsyncResult *res; - - res = g_simple_async_result_new (G_OBJECT (request), callback, user_data, soup_request_file_send_async); + GTask *task; - g_simple_async_result_run_in_thread (res, soup_request_file_send_async_thread, G_PRIORITY_DEFAULT, cancellable); - g_object_unref (res); + task = g_task_new (request, cancellable, callback, user_data); + g_task_run_in_thread (task, soup_request_file_send_async_thread); + g_object_unref (task); } static GInputStream * @@ -229,14 +226,9 @@ soup_request_file_send_finish (SoupRequest *request, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); - - g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == soup_request_file_send_async); - - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; + g_return_val_if_fail (g_task_is_valid (result, request), NULL); - return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); + return g_task_propagate_pointer (G_TASK (result), error); } static goffset diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index 4fc82206..d817cd08 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -99,10 +99,6 @@ soup_request_http_send (SoupRequest *request, typedef struct { - SoupRequestHTTP *http; - GCancellable *cancellable; - GSimpleAsyncResult *simple; - SoupMessage *original; GInputStream *stream; } SendAsyncData; @@ -110,10 +106,6 @@ typedef struct { static void free_send_async_data (SendAsyncData *sadata) { - g_object_unref (sadata->http); - g_object_unref (sadata->simple); - - g_clear_object (&sadata->cancellable); g_clear_object (&sadata->stream); g_clear_object (&sadata->original); @@ -123,25 +115,24 @@ free_send_async_data (SendAsyncData *sadata) static void http_input_stream_ready_cb (GObject *source, GAsyncResult *result, gpointer user_data) { - SendAsyncData *sadata = user_data; + GTask *task = user_data; GError *error = NULL; GInputStream *stream; stream = soup_session_send_request_finish (SOUP_SESSION (source), result, &error); - if (stream) { - g_simple_async_result_set_op_res_gpointer (sadata->simple, stream, g_object_unref); - } else { - g_simple_async_result_take_error (sadata->simple, error); - } - g_simple_async_result_complete (sadata->simple); - free_send_async_data (sadata); + if (stream) + g_task_return_pointer (task, stream, g_object_unref); + else + g_task_return_error (task, error); + g_object_unref (task); } - static void conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) { - SendAsyncData *sadata = user_data; + GTask *task = user_data; + SoupRequestHTTP *http = g_task_get_source_object (task); + SendAsyncData *sadata = g_task_get_task_data (task); GInputStream *stream; if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { @@ -149,16 +140,13 @@ conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_ stream = soup_cache_send_response (cache, sadata->original); if (stream) { - g_simple_async_result_set_op_res_gpointer (sadata->simple, stream, g_object_unref); - soup_message_got_headers (sadata->original); + soup_message_finished (sadata->original); - sadata->http->priv->content_type = g_strdup (soup_message_headers_get_content_type (msg->response_headers, NULL)); - - g_simple_async_result_complete (sadata->simple); + http->priv->content_type = g_strdup (soup_message_headers_get_content_type (msg->response_headers, NULL)); - soup_message_finished (sadata->original); - free_send_async_data (sadata); + g_task_return_pointer (task, stream, g_object_unref); + g_object_unref (task); return; } } @@ -168,28 +156,27 @@ conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_ * we're donwloading the resource twice, but we will change it * once the cache is integrated in the streams stack. */ - soup_session_send_request_async (session, sadata->original, sadata->cancellable, - http_input_stream_ready_cb, sadata); + soup_session_send_request_async (session, sadata->original, + g_task_get_cancellable (task), + http_input_stream_ready_cb, task); } static gboolean idle_return_from_cache_cb (gpointer data) { - SendAsyncData *sadata = data; - - g_simple_async_result_set_op_res_gpointer (sadata->simple, - g_object_ref (sadata->stream), g_object_unref); + GTask *task = data; + SoupRequestHTTP *http = g_task_get_source_object (task); + SendAsyncData *sadata = g_task_get_task_data (task); /* Issue signals */ - soup_message_got_headers (sadata->http->priv->msg); + soup_message_got_headers (http->priv->msg); + soup_message_finished (http->priv->msg); - sadata->http->priv->content_type = g_strdup (soup_message_headers_get_content_type (sadata->http->priv->msg->response_headers, NULL)); + http->priv->content_type = g_strdup (soup_message_headers_get_content_type (http->priv->msg->response_headers, NULL)); - g_simple_async_result_complete (sadata->simple); + g_task_return_pointer (task, g_object_ref (sadata->stream), g_object_unref); + g_object_unref (task); - soup_message_finished (sadata->http->priv->msg); - - free_send_async_data (sadata); return FALSE; } @@ -200,16 +187,15 @@ soup_request_http_send_async (SoupRequest *request, gpointer user_data) { SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); + GTask *task; SendAsyncData *sadata; GInputStream *stream; SoupSession *session; SoupCache *cache; + task = g_task_new (request, cancellable, callback, user_data); sadata = g_slice_new0 (SendAsyncData); - sadata->http = g_object_ref (http); - sadata->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - sadata->simple = g_simple_async_result_new (G_OBJECT (request), callback, user_data, - soup_request_http_send_async); + g_task_set_task_data (task, sadata, (GDestroyNotify)free_send_async_data); session = soup_request_get_session (request); cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); @@ -224,14 +210,14 @@ soup_request_http_send_async (SoupRequest *request, /* Cached resource file could have been deleted outside */ if (stream) { /* Do return the stream asynchronously as in - * the other cases. It's not enough to use - * g_simple_async_result_complete_in_idle as + * the other cases. It's not enough to let + * GTask do the asynchrony for us, because * the signals must be also emitted * asynchronously */ sadata->stream = stream; soup_add_completion (soup_session_get_async_context (session), - idle_return_from_cache_cb, sadata); + idle_return_from_cache_cb, task); return; } } else if (response == SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) { @@ -243,14 +229,14 @@ soup_request_http_send_async (SoupRequest *request, sadata->original = g_object_ref (http->priv->msg); soup_session_queue_message (session, conditional_msg, conditional_get_ready_cb, - sadata); + task); return; } } } soup_session_send_request_async (session, http->priv->msg, cancellable, - http_input_stream_ready_cb, sadata); + http_input_stream_ready_cb, task); } static GInputStream * @@ -258,14 +244,9 @@ soup_request_http_send_finish (SoupRequest *request, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; - - g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (request), soup_request_http_send_async), NULL); + g_return_val_if_fail (g_task_is_valid (result, request), NULL); - simple = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); + return g_task_propagate_pointer (G_TASK (result), error); } static goffset diff --git a/libsoup/soup-request.c b/libsoup/soup-request.c index e7471c1c..dbc8361b 100644 --- a/libsoup/soup-request.c +++ b/libsoup/soup-request.c @@ -173,13 +173,18 @@ soup_request_default_send_async (SoupRequest *request, GAsyncReadyCallback callback, gpointer user_data) { - GSimpleAsyncResult *simple; - - simple = g_simple_async_result_new (G_OBJECT (request), - callback, user_data, - soup_request_default_send_async); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + GTask *task; + GInputStream *stream; + GError *error = NULL; + + task = g_task_new (request, cancellable, callback, user_data); + + stream = soup_request_send (request, cancellable, &error); + if (stream) + g_task_return_pointer (task, stream, g_object_unref); + else + g_task_return_error (task, error); + g_object_unref (task); } static GInputStream * @@ -187,9 +192,7 @@ soup_request_default_send_finish (SoupRequest *request, GAsyncResult *result, GError **error) { - g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (request), soup_request_default_send_async), NULL); - - return soup_request_send (request, NULL, error); + return g_task_propagate_pointer (G_TASK (result), error); } /** diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 398cc0fe..57d8617b 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -473,10 +473,10 @@ static void send_request_return_result (SoupMessageQueueItem *item, gpointer stream, GError *error) { - GSimpleAsyncResult *simple; + GTask *task; - simple = item->result; - item->result = NULL; + task = item->task; + item->task = NULL; if (item->io_source) { g_source_destroy (item->io_source); @@ -484,20 +484,17 @@ send_request_return_result (SoupMessageQueueItem *item, } if (error) - g_simple_async_result_take_error (simple, error); + g_task_return_error (task, error); else if (SOUP_STATUS_IS_TRANSPORT_ERROR (item->msg->status_code)) { if (stream) g_object_unref (stream); - g_simple_async_result_set_error (simple, - SOUP_HTTP_ERROR, - item->msg->status_code, - "%s", - item->msg->reason_phrase); + g_task_return_new_error (task, SOUP_HTTP_ERROR, + item->msg->status_code, + "%s", + item->msg->reason_phrase); } else - g_simple_async_result_set_op_res_gpointer (simple, stream, g_object_unref); - - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_pointer (task, stream, g_object_unref); + g_object_unref (task); } static void @@ -515,12 +512,12 @@ send_request_finished (SoupSession *session, SoupMessageQueueItem *item) GInputStream *istream = NULL; GError *error = NULL; - if (!item->result) { + if (!item->task) { /* Something else already took care of it. */ return; } - mostream = g_object_get_data (G_OBJECT (item->result), "SoupSessionAsync:ostream"); + mostream = g_object_get_data (G_OBJECT (item->task), "SoupSessionAsync:ostream"); if (mostream) { gpointer data; gssize size; @@ -563,7 +560,7 @@ send_async_spliced (GObject *source, GAsyncResult *result, gpointer user_data) /* If the message was cancelled, it will be completed via other means */ if (g_cancellable_is_cancelled (item->cancellable) || - !item->result) { + !item->task) { soup_message_queue_item_unref (item); return; } @@ -591,7 +588,7 @@ send_async_maybe_complete (SoupMessageQueueItem *item, /* Message may be requeued, so gather the current message body... */ ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); - g_object_set_data_full (G_OBJECT (item->result), "SoupSessionAsync:ostream", + g_object_set_data_full (G_OBJECT (item->task), "SoupSessionAsync:ostream", ostream, g_object_unref); g_object_set_data (G_OBJECT (ostream), "istream", stream); @@ -693,10 +690,8 @@ soup_session_send_request_async (SoupSession *session, g_return_if_fail (item != NULL); item->new_api = TRUE; - item->result = g_simple_async_result_new (G_OBJECT (session), - callback, user_data, - soup_session_send_request_async); - g_simple_async_result_set_op_res_gpointer (item->result, item, (GDestroyNotify) soup_message_queue_item_unref); + item->task = g_task_new (session, cancellable, callback, user_data); + g_task_set_task_data (item->task, item, (GDestroyNotify) soup_message_queue_item_unref); if (cancellable) { g_object_unref (item->cancellable); @@ -709,15 +704,10 @@ soup_session_send_request_finish (SoupSession *session, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; - g_return_val_if_fail (SOUP_IS_SESSION_ASYNC (session), NULL); - g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (session), soup_session_send_request_async), NULL); + g_return_val_if_fail (g_task_is_valid (result, session), NULL); - simple = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (simple, error)) - return NULL; - return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); + return g_task_propagate_pointer (G_TASK (result), error); } static void -- cgit v1.2.1 From 07ad1e0728553817e7b9be9b4d192383760c201e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 22 Oct 2012 19:00:13 +0200 Subject: Remove now-unnecessary g_type_init() calls --- tests/dns.c | 2 -- tests/get.c | 2 -- tests/simple-httpd.c | 1 - tests/simple-proxy.c | 1 - tests/test-utils.c | 1 - 5 files changed, 7 deletions(-) diff --git a/tests/dns.c b/tests/dns.c index f5940647..ee9108e6 100644 --- a/tests/dns.c +++ b/tests/dns.c @@ -40,8 +40,6 @@ main (int argc, char **argv) if (argc < 2) usage (); - g_type_init (); - for (i = 1; i < argc; i++) { addr = soup_address_new (argv[i], 0); if (!addr) { diff --git a/tests/get.c b/tests/get.c index 9672ded8..15d69033 100644 --- a/tests/get.c +++ b/tests/get.c @@ -96,8 +96,6 @@ main (int argc, char **argv) gboolean synchronous = FALSE, ntlm = FALSE; int opt; - g_type_init (); - method = SOUP_METHOD_GET; while ((opt = getopt (argc, argv, "c:dhnp:qs")) != -1) { diff --git a/tests/simple-httpd.c b/tests/simple-httpd.c index 41aa8a35..0f240ca8 100644 --- a/tests/simple-httpd.c +++ b/tests/simple-httpd.c @@ -259,7 +259,6 @@ main (int argc, char **argv) int ssl_port = SOUP_ADDRESS_ANY_PORT; const char *ssl_cert_file = NULL, *ssl_key_file = NULL; - g_type_init (); signal (SIGINT, quit); while ((opt = getopt (argc, argv, "p:k:c:s:")) != -1) { diff --git a/tests/simple-proxy.c b/tests/simple-proxy.c index 0600e53d..765fa5e7 100644 --- a/tests/simple-proxy.c +++ b/tests/simple-proxy.c @@ -132,7 +132,6 @@ main (int argc, char **argv) int port = SOUP_ADDRESS_ANY_PORT; SoupAuthDomain *auth_domain = NULL; - g_type_init (); signal (SIGINT, quit); while ((opt = getopt (argc, argv, "ap:")) != -1) { diff --git a/tests/test-utils.c b/tests/test-utils.c index c34b0b71..fc5b18d3 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -82,7 +82,6 @@ test_init (int argc, char **argv, GOptionEntry *entries) GTlsBackend *tls_backend; setlocale (LC_ALL, ""); - g_type_init (); name = strrchr (argv[0], '/'); if (!name++) -- cgit v1.2.1 From af44b7b8df5bcb9bb304e36ffad9b65c6ee22594 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 22 Oct 2012 20:15:49 +0200 Subject: tests: add support for Apache 2.4 --- configure.ac | 25 +++-- tests/Makefile.am | 26 ++++- tests/httpd.conf.22.in | 293 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/httpd.conf.24.in | 278 ++++++++++++++++++++++++++++++++++++++++++++++ tests/httpd.conf.in | 293 ------------------------------------------------- tests/range-test.c | 13 ++- 6 files changed, 621 insertions(+), 307 deletions(-) create mode 100644 tests/httpd.conf.22.in create mode 100644 tests/httpd.conf.24.in delete mode 100644 tests/httpd.conf.in diff --git a/configure.ac b/configure.ac index 7576359d..8d3f0cfb 100644 --- a/configure.ac +++ b/configure.ac @@ -222,6 +222,11 @@ if test "$APACHE_HTTPD" != "no"; then case $apache_version in 2.2.*) AC_MSG_RESULT([$apache_version (ok)]) + apache_version=2.2 + ;; + 2.4.*) + AC_MSG_RESULT([$apache_version (ok)]) + apache_version=2.4 ;; *) AC_MSG_RESULT([$apache_version (ignoring)]) @@ -238,7 +243,7 @@ if test "$APACHE_HTTPD" != "no"; then AS_HELP_STRING([--with-apache-module-dir], [Apache modules dirs (for tests)]), apache_module_dirs="$withval", [apache_prefix=`dirname \`dirname $APACHE_HTTPD\`` - mpm=`$APACHE_HTTPD -V | sed -ne 's/^Server MPM: */-/p' | tr 'A-Z' 'a-z'` + mpm=`$APACHE_HTTPD -V -C "ServerName localhost" | sed -ne 's/^Server MPM: */-/p' | tr 'A-Z' 'a-z'` # This only works with bash, but should fail harmlessly in sh apache_module_dirs=`echo $apache_prefix/lib{64,}/{apache,apache2,http,http2,httpd}{$mpm,}{/modules,}`]) for dir in $apache_module_dirs; do @@ -267,6 +272,11 @@ fi if test "$APACHE_HTTPD" != "no" -a -n "$APACHE_MODULE_DIR" -a -n "$APACHE_SSL_MODULE_DIR"; then AC_DEFINE(HAVE_APACHE, 1, [Whether or not apache can be used for tests]) + if test $apache_version = 2.2; then + AC_DEFINE(HAVE_APACHE_2_2, 1, [Apache is 2.2.x]) + else + AC_DEFINE(HAVE_APACHE_2_4, 1, [Apache is 2.4.x]) + fi have_apache=1 if test -z "$APACHE_PHP_MODULE_DIR"; then MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES mod_php5" @@ -280,6 +290,8 @@ else fi fi AM_CONDITIONAL(HAVE_APACHE, test $have_apache = 1) +AM_CONDITIONAL(HAVE_APACHE_2_2, test $apache_version = 2.2) +AM_CONDITIONAL(HAVE_APACHE_2_4, test $apache_version = 2.4) if test "$have_apache" = 1; then AC_CHECK_PROGS(PHP, php php5) @@ -296,19 +308,19 @@ if test "$have_apache" = 1; then AC_MSG_RESULT($have_php) if test "$have_php" = yes; then - AC_MSG_CHECKING([for xmlrpc-epi-php]) + AC_MSG_CHECKING([for xmlrpc-php]) if $PHP --rf xmlrpc_server_create | grep -q "does not exist"; then - have_xmlrpc_epi_php=no + have_xmlrpc_php=no MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES php-xmlrpc" else - have_xmlrpc_epi_php=yes + have_xmlrpc_php=yes fi - AC_MSG_RESULT($have_xmlrpc_epi_php) + AC_MSG_RESULT($have_xmlrpc_php) fi fi AC_SUBST(IF_HAVE_PHP) -AM_CONDITIONAL(HAVE_XMLRPC_EPI_PHP, test "$have_xmlrpc_epi_php" = yes) +AM_CONDITIONAL(HAVE_XMLRPC_PHP, test "$have_xmlrpc_php" = yes) AC_PATH_PROG(CURL, curl, no) if test "$CURL" != no; then @@ -373,7 +385,6 @@ AC_CONFIG_FILES([ po/Makefile.in po/Makefile tests/Makefile - tests/httpd.conf docs/Makefile docs/reference/Makefile libsoup/soup-version.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 085a81b3..54ce7bdb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -89,10 +89,29 @@ endif if HAVE_CURL CURL_TESTS = forms-test server-auth-test endif -if HAVE_XMLRPC_EPI_PHP +if HAVE_XMLRPC_PHP XMLRPC_TESTS = xmlrpc-test xmlrpc-server-test endif +if HAVE_APACHE +if HAVE_APACHE_2_2 +httpd_conf_in = httpd.conf.22.in +else +httpd_conf_in = httpd.conf.24.in +endif +httpd.conf: $(httpd_conf_in) + $(AM_V_GEN) sed -e 's,[@]srcdir@,$(srcdir),' \ + -e 's,[@]builddir@,$(builddir),' \ + -e 's,[@]APACHE_MODULE_DIR@,$(APACHE_MODULE_DIR),' \ + -e 's,[@]APACHE_PHP_MODULE_DIR@,$(APACHE_PHP_MODULE_DIR),' \ + -e 's,[@]APACHE_PHP_MODULE@,$(APACHE_PHP_MODULE),' \ + -e 's,[@]IF_HAVE_PHP@,$(IF_HAVE_PHP),' \ + -e 's,[@]APACHE_SSL_MODULE_DIR@,$(APACHE_SSL_MODULE_DIR),' \ + $< > $@ || rm -f $@ + +BUILT_SOURCES = httpd.conf +endif + soup-tests.gresource: soup-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< @@ -138,7 +157,8 @@ RESOURCES = \ EXTRA_DIST = \ htdigest \ htpasswd \ - httpd.conf.in \ + httpd.conf.22.in \ + httpd.conf.24.in \ index.txt \ libsoup.supp \ soup-tests.gresource.xml \ @@ -147,7 +167,7 @@ EXTRA_DIST = \ xmlrpc-server.php \ $(RESOURCES) -DISTCLEANFILES = soup-tests.gresource +DISTCLEANFILES = soup-tests.gresource httpd.conf if MISSING_REGRESSION_TEST_PACKAGES check-local: check-TESTS diff --git a/tests/httpd.conf.22.in b/tests/httpd.conf.22.in new file mode 100644 index 00000000..de0b75fa --- /dev/null +++ b/tests/httpd.conf.22.in @@ -0,0 +1,293 @@ +# http.conf used for testing auth-test + +ServerName 127.0.0.1 +Listen 127.0.0.1:47524 + +PidFile @builddir@/httpd.pid +DocumentRoot @srcdir@ + +# The tests shut down apache with "graceful-stop", because that makes +# it close its listening socket right away. But it seems to sometimes +# result in apache never fully exiting. This fixes that. +GracefulShutdownTimeout 1 + +# Change this to "./error.log" if it's failing and you don't know why +ErrorLog /dev/null + +LoadModule alias_module @APACHE_MODULE_DIR@/mod_alias.so +LoadModule auth_basic_module @APACHE_MODULE_DIR@/mod_auth_basic.so +LoadModule auth_digest_module @APACHE_MODULE_DIR@/mod_auth_digest.so +LoadModule authn_file_module @APACHE_MODULE_DIR@/mod_authn_file.so +LoadModule authz_host_module @APACHE_MODULE_DIR@/mod_authz_host.so +LoadModule authz_user_module @APACHE_MODULE_DIR@/mod_authz_user.so +LoadModule dir_module @APACHE_MODULE_DIR@/mod_dir.so +LoadModule mime_module @APACHE_MODULE_DIR@/mod_mime.so +@IF_HAVE_PHP@LoadModule php5_module @APACHE_PHP_MODULE_DIR@/@APACHE_PHP_MODULE@ +LoadModule proxy_module @APACHE_MODULE_DIR@/mod_proxy.so +LoadModule proxy_http_module @APACHE_MODULE_DIR@/mod_proxy_http.so +LoadModule proxy_connect_module @APACHE_MODULE_DIR@/mod_proxy_connect.so +LoadModule ssl_module @APACHE_SSL_MODULE_DIR@/mod_ssl.so + +DirectoryIndex index.txt +TypesConfig /dev/null +AddType application/x-httpd-php .php +Redirect permanent /redirected /index.txt + +# Proxy #1: unauthenticated +Listen 127.0.0.1:47526 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Order Deny,Allow + Deny from all + + + # Allow local http connections + + Order Allow,Deny + Allow from all + + + # Allow CONNECT to local https port + + Order Allow,Deny + Allow from all + + + # Deny non-proxy requests + + Order Deny,Allow + Deny from all + + + +# Proxy #2: authenticated +Listen 127.0.0.1:47527 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Order Deny,Allow + Deny from all + + + # Allow local http connections with authentication + + Order Allow,Deny + Allow from all + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require valid-user + + + # Allow CONNECT to local https port with authentication + + Order Allow,Deny + Allow from all + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require valid-user + + + # Fail non-proxy requests + + Order Deny,Allow + Deny from all + + + +# Proxy #3: unauthenticatable-to +Listen 127.0.0.1:47528 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Order Deny,Allow + Deny from all + + + # Allow local http connections with authentication + + Order Allow,Deny + Allow from all + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user no-such-user + + + # Allow CONNECT to local https port with authentication + + Order Allow,Deny + Allow from all + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user no-such-user + + + # Fail non-proxy requests + + Order Deny,Allow + Deny from all + + + + +# SSL setup + + Listen 127.0.0.1:47525 + + + SSLEngine on + + SSLCertificateFile @srcdir@/test-cert.pem + SSLCertificateKeyFile @srcdir@/test-key.pem + + + + + +# Basic auth tests +Alias /Basic/realm1/realm2/realm1 @srcdir@ +Alias /Basic/realm1/realm2 @srcdir@ +Alias /Basic/realm1/subdir @srcdir@ +Alias /Basic/realm1/not @srcdir@ +Alias /Basic/realm1 @srcdir@ +Alias /Basic/realm12/subdir @srcdir@ +Alias /Basic/realm12 @srcdir@ +Alias /Basic/realm2 @srcdir@ +Alias /Basic/realm3 @srcdir@ +Alias /Basic @srcdir@ + + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user user1 + + + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm12 + AuthUserFile @srcdir@/htpasswd + Require user user1 user2 + + + + AuthType Basic + AuthName realm2 + AuthUserFile @srcdir@/htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user user1 + + + + AuthType Basic + AuthName realm2 + AuthUserFile @srcdir@/htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm3 + AuthUserFile @srcdir@/htpasswd + Require user user3 + + +# Digest auth tests +Alias /Digest/realm1/realm2/realm1 @srcdir@ +Alias /Digest/realm1/realm2 @srcdir@ +Alias /Digest/realm1/subdir @srcdir@ +Alias /Digest/realm1/expire @srcdir@ +Alias /Digest/realm1/not @srcdir@ +Alias /Digest/realm1 @srcdir@ +Alias /Digest/realm2 @srcdir@ +Alias /Digest/realm3 @srcdir@ +Alias /Digest @srcdir@ + + + AuthType Digest + AuthName realm1 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + AuthDigestNonceLifetime 2 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require user user2 + + + + AuthType Digest + AuthName realm2 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require valid-user + + + + AuthType Digest + AuthName realm2 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 + Require valid-user + + + + AuthType Digest + AuthName realm3 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm3 + Require valid-user + # test RFC2069-style Digest + AuthDigestQop none + diff --git a/tests/httpd.conf.24.in b/tests/httpd.conf.24.in new file mode 100644 index 00000000..2407ad75 --- /dev/null +++ b/tests/httpd.conf.24.in @@ -0,0 +1,278 @@ +# http.conf used for testing auth-test + +ServerName 127.0.0.1 +Listen 127.0.0.1:47524 + +PidFile @builddir@/httpd.pid +DefaultRuntimeDir @builddir@ +DocumentRoot @srcdir@ + +# The tests shut down apache with "graceful-stop", because that makes +# it close its listening socket right away. But it seems to sometimes +# result in apache never fully exiting. This fixes that. +GracefulShutdownTimeout 1 + +# Change this to "./error.log" if it's failing and you don't know why +ErrorLog /dev/null + +LoadModule mpm_prefork_module @APACHE_MODULE_DIR@/mod_mpm_prefork.so +LoadModule alias_module @APACHE_MODULE_DIR@/mod_alias.so +LoadModule auth_basic_module @APACHE_MODULE_DIR@/mod_auth_basic.so +LoadModule auth_digest_module @APACHE_MODULE_DIR@/mod_auth_digest.so +LoadModule authn_core_module @APACHE_MODULE_DIR@/mod_authn_core.so +LoadModule authn_file_module @APACHE_MODULE_DIR@/mod_authn_file.so +LoadModule authz_core_module @APACHE_MODULE_DIR@/mod_authz_core.so +LoadModule authz_host_module @APACHE_MODULE_DIR@/mod_authz_host.so +LoadModule authz_user_module @APACHE_MODULE_DIR@/mod_authz_user.so +LoadModule dir_module @APACHE_MODULE_DIR@/mod_dir.so +LoadModule mime_module @APACHE_MODULE_DIR@/mod_mime.so +@IF_HAVE_PHP@LoadModule php5_module @APACHE_PHP_MODULE_DIR@/@APACHE_PHP_MODULE@ +LoadModule proxy_module @APACHE_MODULE_DIR@/mod_proxy.so +LoadModule proxy_http_module @APACHE_MODULE_DIR@/mod_proxy_http.so +LoadModule proxy_connect_module @APACHE_MODULE_DIR@/mod_proxy_connect.so +LoadModule ssl_module @APACHE_SSL_MODULE_DIR@/mod_ssl.so +LoadModule unixd_module @APACHE_SSL_MODULE_DIR@/mod_unixd.so + +DirectoryIndex index.txt +TypesConfig /dev/null +AddType application/x-httpd-php .php +Redirect permanent /redirected /index.txt + +# Proxy #1: unauthenticated +Listen 127.0.0.1:47526 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Require all denied + + + # Allow local http connections + + Require all granted + + + # Allow CONNECT to local https port + + Require all granted + + + # Deny non-proxy requests + + Require all denied + + + +# Proxy #2: authenticated +Listen 127.0.0.1:47527 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Require all denied + + + # Allow local http connections with authentication + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require valid-user + + + # Allow CONNECT to local https port with authentication + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require valid-user + + + # Fail non-proxy requests + + Require all denied + + + +# Proxy #3: unauthenticatable-to +Listen 127.0.0.1:47528 + + ProxyRequests On + AllowCONNECT 47525 + + # Deny proxying by default + + Require all denied + + + # Allow local http connections with authentication + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user no-such-user + + + # Allow CONNECT to local https port with authentication + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user no-such-user + + + # Fail non-proxy requests + + Require all denied + + + + +# SSL setup + + Listen 127.0.0.1:47525 + + + SSLEngine on + + SSLCertificateFile @srcdir@/test-cert.pem + SSLCertificateKeyFile @srcdir@/test-key.pem + + + + + +# Basic auth tests +Alias /Basic/realm1/realm2/realm1 @srcdir@ +Alias /Basic/realm1/realm2 @srcdir@ +Alias /Basic/realm1/subdir @srcdir@ +Alias /Basic/realm1/not @srcdir@ +Alias /Basic/realm1 @srcdir@ +Alias /Basic/realm12/subdir @srcdir@ +Alias /Basic/realm12 @srcdir@ +Alias /Basic/realm2 @srcdir@ +Alias /Basic/realm3 @srcdir@ +Alias /Basic @srcdir@ + + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user user1 + + + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm12 + AuthUserFile @srcdir@/htpasswd + Require user user1 user2 + + + + AuthType Basic + AuthName realm2 + AuthUserFile @srcdir@/htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm1 + AuthUserFile @srcdir@/htpasswd + Require user user1 + + + + AuthType Basic + AuthName realm2 + AuthUserFile @srcdir@/htpasswd + Require user user2 + + + + AuthType Basic + AuthName realm3 + AuthUserFile @srcdir@/htpasswd + Require user user3 + + +# Digest auth tests +Alias /Digest/realm1/realm2/realm1 @srcdir@ +Alias /Digest/realm1/realm2 @srcdir@ +Alias /Digest/realm1/subdir @srcdir@ +Alias /Digest/realm1/expire @srcdir@ +Alias /Digest/realm1/not @srcdir@ +Alias /Digest/realm1 @srcdir@ +Alias /Digest/realm2 @srcdir@ +Alias /Digest/realm3 @srcdir@ +Alias /Digest @srcdir@ + + + AuthType Digest + AuthName realm1 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + AuthDigestNonceLifetime 2 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require user user2 + + + + AuthType Digest + AuthName realm2 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 + Require valid-user + + + + AuthType Digest + AuthName realm1 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 + Require valid-user + + + + AuthType Digest + AuthName realm2 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 + Require valid-user + + + + AuthType Digest + AuthName realm3 + AuthUserFile @srcdir@/htdigest + AuthDigestDomain /Digest/realm3 + Require valid-user + # test RFC2069-style Digest + AuthDigestQop none + diff --git a/tests/httpd.conf.in b/tests/httpd.conf.in deleted file mode 100644 index de0b75fa..00000000 --- a/tests/httpd.conf.in +++ /dev/null @@ -1,293 +0,0 @@ -# http.conf used for testing auth-test - -ServerName 127.0.0.1 -Listen 127.0.0.1:47524 - -PidFile @builddir@/httpd.pid -DocumentRoot @srcdir@ - -# The tests shut down apache with "graceful-stop", because that makes -# it close its listening socket right away. But it seems to sometimes -# result in apache never fully exiting. This fixes that. -GracefulShutdownTimeout 1 - -# Change this to "./error.log" if it's failing and you don't know why -ErrorLog /dev/null - -LoadModule alias_module @APACHE_MODULE_DIR@/mod_alias.so -LoadModule auth_basic_module @APACHE_MODULE_DIR@/mod_auth_basic.so -LoadModule auth_digest_module @APACHE_MODULE_DIR@/mod_auth_digest.so -LoadModule authn_file_module @APACHE_MODULE_DIR@/mod_authn_file.so -LoadModule authz_host_module @APACHE_MODULE_DIR@/mod_authz_host.so -LoadModule authz_user_module @APACHE_MODULE_DIR@/mod_authz_user.so -LoadModule dir_module @APACHE_MODULE_DIR@/mod_dir.so -LoadModule mime_module @APACHE_MODULE_DIR@/mod_mime.so -@IF_HAVE_PHP@LoadModule php5_module @APACHE_PHP_MODULE_DIR@/@APACHE_PHP_MODULE@ -LoadModule proxy_module @APACHE_MODULE_DIR@/mod_proxy.so -LoadModule proxy_http_module @APACHE_MODULE_DIR@/mod_proxy_http.so -LoadModule proxy_connect_module @APACHE_MODULE_DIR@/mod_proxy_connect.so -LoadModule ssl_module @APACHE_SSL_MODULE_DIR@/mod_ssl.so - -DirectoryIndex index.txt -TypesConfig /dev/null -AddType application/x-httpd-php .php -Redirect permanent /redirected /index.txt - -# Proxy #1: unauthenticated -Listen 127.0.0.1:47526 - - ProxyRequests On - AllowCONNECT 47525 - - # Deny proxying by default - - Order Deny,Allow - Deny from all - - - # Allow local http connections - - Order Allow,Deny - Allow from all - - - # Allow CONNECT to local https port - - Order Allow,Deny - Allow from all - - - # Deny non-proxy requests - - Order Deny,Allow - Deny from all - - - -# Proxy #2: authenticated -Listen 127.0.0.1:47527 - - ProxyRequests On - AllowCONNECT 47525 - - # Deny proxying by default - - Order Deny,Allow - Deny from all - - - # Allow local http connections with authentication - - Order Allow,Deny - Allow from all - - AuthType Basic - AuthName realm1 - AuthUserFile @srcdir@/htpasswd - Require valid-user - - - # Allow CONNECT to local https port with authentication - - Order Allow,Deny - Allow from all - - AuthType Basic - AuthName realm1 - AuthUserFile @srcdir@/htpasswd - Require valid-user - - - # Fail non-proxy requests - - Order Deny,Allow - Deny from all - - - -# Proxy #3: unauthenticatable-to -Listen 127.0.0.1:47528 - - ProxyRequests On - AllowCONNECT 47525 - - # Deny proxying by default - - Order Deny,Allow - Deny from all - - - # Allow local http connections with authentication - - Order Allow,Deny - Allow from all - - AuthType Basic - AuthName realm1 - AuthUserFile @srcdir@/htpasswd - Require user no-such-user - - - # Allow CONNECT to local https port with authentication - - Order Allow,Deny - Allow from all - - AuthType Basic - AuthName realm1 - AuthUserFile @srcdir@/htpasswd - Require user no-such-user - - - # Fail non-proxy requests - - Order Deny,Allow - Deny from all - - - - -# SSL setup - - Listen 127.0.0.1:47525 - - - SSLEngine on - - SSLCertificateFile @srcdir@/test-cert.pem - SSLCertificateKeyFile @srcdir@/test-key.pem - - - - - -# Basic auth tests -Alias /Basic/realm1/realm2/realm1 @srcdir@ -Alias /Basic/realm1/realm2 @srcdir@ -Alias /Basic/realm1/subdir @srcdir@ -Alias /Basic/realm1/not @srcdir@ -Alias /Basic/realm1 @srcdir@ -Alias /Basic/realm12/subdir @srcdir@ -Alias /Basic/realm12 @srcdir@ -Alias /Basic/realm2 @srcdir@ -Alias /Basic/realm3 @srcdir@ -Alias /Basic @srcdir@ - - - AuthType Basic - AuthName realm1 - AuthUserFile @srcdir@/htpasswd - Require user user1 - - - - AuthType Basic - AuthName realm1 - AuthUserFile @srcdir@/htpasswd - Require user user2 - - - - AuthType Basic - AuthName realm12 - AuthUserFile @srcdir@/htpasswd - Require user user1 user2 - - - - AuthType Basic - AuthName realm2 - AuthUserFile @srcdir@/htpasswd - Require user user2 - - - - AuthType Basic - AuthName realm1 - AuthUserFile @srcdir@/htpasswd - Require user user1 - - - - AuthType Basic - AuthName realm2 - AuthUserFile @srcdir@/htpasswd - Require user user2 - - - - AuthType Basic - AuthName realm3 - AuthUserFile @srcdir@/htpasswd - Require user user3 - - -# Digest auth tests -Alias /Digest/realm1/realm2/realm1 @srcdir@ -Alias /Digest/realm1/realm2 @srcdir@ -Alias /Digest/realm1/subdir @srcdir@ -Alias /Digest/realm1/expire @srcdir@ -Alias /Digest/realm1/not @srcdir@ -Alias /Digest/realm1 @srcdir@ -Alias /Digest/realm2 @srcdir@ -Alias /Digest/realm3 @srcdir@ -Alias /Digest @srcdir@ - - - AuthType Digest - AuthName realm1 - AuthUserFile @srcdir@/htdigest - AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 - Require valid-user - - - - AuthType Digest - AuthName realm1 - AuthUserFile @srcdir@/htdigest - AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 - AuthDigestNonceLifetime 2 - Require valid-user - - - - AuthType Digest - AuthName realm1 - AuthUserFile @srcdir@/htdigest - AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 - Require user user2 - - - - AuthType Digest - AuthName realm2 - AuthUserFile @srcdir@/htdigest - AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 - Require valid-user - - - - AuthType Digest - AuthName realm1 - AuthUserFile @srcdir@/htdigest - AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 - Require valid-user - - - - AuthType Digest - AuthName realm2 - AuthUserFile @srcdir@/htdigest - AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 - Require valid-user - - - - AuthType Digest - AuthName realm3 - AuthUserFile @srcdir@/htdigest - AuthDigestDomain /Digest/realm3 - Require valid-user - # test RFC2069-style Digest - AuthDigestQop none - diff --git a/tests/range-test.c b/tests/range-test.c index 98f56450..09e95f12 100644 --- a/tests/range-test.c +++ b/tests/range-test.c @@ -229,7 +229,8 @@ request_triple_range (SoupSession *session, const char *uri, } static void -do_range_test (SoupSession *session, const char *uri, gboolean expect_coalesce) +do_range_test (SoupSession *session, const char *uri, + gboolean expect_coalesce, gboolean expect_partial_coalesce) { int twelfths = full_response->length / 12; @@ -309,7 +310,7 @@ do_range_test (SoupSession *session, const char *uri, gboolean expect_coalesce) 9 * twelfths, 10 * twelfths + 5, 4 * twelfths, 5 * twelfths, 10 * twelfths - 5, 11 * twelfths, - expect_coalesce ? 2 : 3); + expect_partial_coalesce ? 2 : 3); if (memcmp (full_response->data, test_response, full_response->length) != 0) { debug_printf (1, "\nfull_response and test_response don't match\n"); @@ -346,14 +347,18 @@ main (int argc, char **argv) session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); debug_printf (1, "1. Testing against apache\n"); - do_range_test (session, "http://127.0.0.1:47524/", FALSE); +#if HAVE_APACHE_2_2 + do_range_test (session, "http://127.0.0.1:47524/", FALSE, FALSE); +#else + do_range_test (session, "http://127.0.0.1:47524/", TRUE, FALSE); +#endif debug_printf (1, "\n2. Testing against SoupServer\n"); server = soup_test_server_new (FALSE); soup_server_add_handler (server, NULL, server_handler, NULL, NULL); base_uri = g_strdup_printf ("http://127.0.0.1:%u/", soup_server_get_port (server)); - do_range_test (session, base_uri, TRUE); + do_range_test (session, base_uri, TRUE, TRUE); g_free (base_uri); soup_test_server_quit_unref (server); -- cgit v1.2.1 From d9d3e9307f98b682d98094b0e7652018ea3a18a8 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 22 Oct 2012 20:16:24 +0200 Subject: .gitignore: add tests/soup-tests.gresource --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 203bd2f2..e02235bd 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,5 @@ tests/httpd.conf tests/pull-api tests/simple-httpd tests/simple-proxy +tests/soup-tests.gresource tests/uri-parsing -- cgit v1.2.1 From bcfc1d4cbd5bc52fca3a674f281cf0966c917d0f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 22 Oct 2012 20:38:20 +0200 Subject: 2.41.1 --- NEWS | 31 +++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5c533deb..070111b7 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,34 @@ +Changes in libsoup from 2.40.1 to 2.41.1: + + * Changed the behavior of NTLM authentication to be more like + what other apps apparently do. Now if the user does not + specify a domain in the username (eg, "MYDOMAIN\username"), + then we will not specify a domain in the NTLM response + (rather than assuming that the user is in the server's + default domain). People who get broken by this change should + be able to fix it by including an explicit domain in their + username, but the theory is that no one should get broken by + this... If this change does turn out to hurt more than it + helps then it may be reverted later. [#624613, Dan, based on + a suggestion from David Woodhouse] + + * Fixed a crash caused by a race condition in SoupSessionSync. + [#684238, Dan] + + * SoupRequest now supports resource:// URIs, for reading from + gresource. [#682721, Carlos] + + * Added new compile-time and runtime APIs for checking the + libsoup version. [#684514, Martin Robinson] + + * Updated to take advantage of (and require) glib 2.35; + removed all g_type_init() calls and ported to GTask. [Dan] + + * Added support for Apache 2.4 to the unit tests. [Dan] + + * New translations: + Uzbek (Cyrillic) + Changes in libsoup from 2.40.0 to 2.40.1: * Improved the parsing of multipart/x-mixed-replace responses. diff --git a/configure.ac b/configure.ac index 8d3f0cfb..4a8df37e 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [0]) +m4_define([soup_micro_version], [1]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From c4ff1663520f2167d274ac04cad7a88e9ba5902c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 29 Oct 2012 08:05:01 -0400 Subject: soup_header_parse_param_list: return empty GHashTable instead of NULL Special-casing the "no parameters" case here complicates other code (eg, currently it causes warnings in SoupCache if you get an empty Cache-Control header). --- libsoup/soup-headers.c | 5 +---- tests/sniffing-test.c | 7 +------ 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c index ffa1e77a..9c4c8083 100644 --- a/libsoup/soup-headers.c +++ b/libsoup/soup-headers.c @@ -702,14 +702,11 @@ parse_param_list (const char *header, char delim) char *item, *eq, *name_end, *value; gboolean override; - list = parse_list (header, delim); - if (!list) - return NULL; - params = g_hash_table_new_full (soup_str_case_hash, soup_str_case_equal, g_free, NULL); + list = parse_list (header, delim); for (iter = list; iter; iter = iter->next) { item = iter->data; override = FALSE; diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index dd4eb4aa..0b5fe19f 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -350,18 +350,13 @@ sniffing_content_sniffed (SoupMessage *msg, const char *content_type, GList *keys; GList *iter; - if (params == NULL) { - *sniffed_type = g_strdup (content_type); - return; - } - full_header = g_string_new (content_type); - g_string_append (full_header, "; "); keys = g_hash_table_get_keys (params); for (iter = keys; iter != NULL; iter = iter->next) { const gchar *value = (const gchar*) g_hash_table_lookup (params, iter->data); + g_string_append (full_header, "; "); soup_header_g_string_append_param (full_header, (const gchar*) iter->data, value); -- cgit v1.2.1 From 04a0a7c674fcc8adc28da84eba1b79c4d9acb246 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 31 Oct 2012 11:08:06 -0400 Subject: tests: fix some race conditions A few tests were written such that they could fail/crash if the machine was too slow. Fix. --- tests/connection-test.c | 13 ++++++++++--- tests/misc-test.c | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/connection-test.c b/tests/connection-test.c index b9dce7f5..ef21ec97 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -541,8 +541,6 @@ do_max_conns_test (void) soup_test_session_abort_unref (session); } -GMainLoop *loop; - static void np_request_started (SoupSession *session, SoupMessage *msg, SoupSocket *socket, gpointer user_data) @@ -562,6 +560,13 @@ np_request_unqueued (SoupSession *session, SoupMessage *msg, debug_printf (1, " socket is still connected\n"); errors++; } +} + +static void +np_request_finished (SoupSession *session, SoupMessage *msg, + gpointer user_data) +{ + GMainLoop *loop = user_data; g_main_loop_quit (loop); } @@ -571,6 +576,7 @@ do_non_persistent_test_for_session (SoupSession *session) { SoupMessage *msg; SoupSocket *socket = NULL; + GMainLoop *loop; loop = g_main_loop_new (NULL, FALSE); @@ -584,7 +590,8 @@ do_non_persistent_test_for_session (SoupSession *session) msg = soup_message_new_from_uri ("GET", base_uri); soup_message_headers_append (msg->request_headers, "Connection", "close"); g_object_ref (msg); - soup_session_queue_message (session, msg, NULL, NULL); + soup_session_queue_message (session, msg, + np_request_finished, loop); g_main_loop_run (loop); g_main_loop_unref (loop); diff --git a/tests/misc-test.c b/tests/misc-test.c index a71d4aae..19e9ba09 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -928,6 +928,7 @@ cancel_request_thread (gpointer cancellable) { g_usleep (100000); /* .1s */ g_cancellable_cancel (cancellable); + g_object_unref (cancellable); return NULL; } @@ -951,7 +952,7 @@ do_cancel_while_reading_req_test_for_session (SoupRequester *requester) } else { GThread *thread; - thread = g_thread_new ("cancel_request_thread", cancel_request_thread, cancellable); + thread = g_thread_new ("cancel_request_thread", cancel_request_thread, g_object_ref (cancellable)); soup_test_request_send (req, cancellable, &error); g_thread_unref (thread); } -- cgit v1.2.1 From b7d8cb6542e4bd525764d94f437ba2a3ec561ee1 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 2 Nov 2012 11:48:08 -0400 Subject: soup-version: minor style fixes --- libsoup/Makefile.am | 2 +- libsoup/soup-version.h.in | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index c5f0e400..710e750e 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -174,7 +174,7 @@ libsoup_2_4_la_SOURCES = \ soup-tld-private.h \ soup-uri.c \ soup-value-utils.c \ - soup-version.c \ + soup-version.c \ soup-xmlrpc.c # TLD rules diff --git a/libsoup/soup-version.h.in b/libsoup/soup-version.h.in index 6332d581..96bb3021 100644 --- a/libsoup/soup-version.h.in +++ b/libsoup/soup-version.h.in @@ -22,19 +22,15 @@ G_BEGIN_DECLS (SOUP_MAJOR_VERSION == (major) && SOUP_MINOR_VERSION == (minor) && \ SOUP_MICRO_VERSION >= (micro))) -guint -soup_get_major_version (void); +guint soup_get_major_version (void); -guint -soup_get_minor_version (void); +guint soup_get_minor_version (void); -guint -soup_get_micro_version (void); +guint soup_get_micro_version (void); -gboolean -soup_check_version (guint major, - guint minor, - guint micro); +gboolean soup_check_version (guint major, + guint minor, + guint micro); G_END_DECLS -- cgit v1.2.1 From 08bc2f346534206a45be0e5ec506cd03feb9d849 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 2 Nov 2012 11:53:00 -0400 Subject: SoupSession: mark a static function static (and clarify why it's there) --- libsoup/soup-session.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index d0a0e212..5a3c5f98 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -74,7 +74,7 @@ typedef struct { SoupSession *session; } SoupSessionHost; static guint soup_host_uri_hash (gconstpointer key); -gboolean soup_host_uri_equal (gconstpointer v1, gconstpointer v2); +static gboolean soup_host_uri_equal (gconstpointer v1, gconstpointer v2); typedef struct { GTlsDatabase *tlsdb; @@ -734,6 +734,10 @@ soup_session_get_async_context (SoupSession *session) /* Hosts */ +/* Note that we can't use soup_uri_host_hash() and soup_uri_host_equal() + * because we want to ignore the protocol; http://example.com and + * webcal://example.com are the same host. + */ static guint soup_host_uri_hash (gconstpointer key) { @@ -744,7 +748,7 @@ soup_host_uri_hash (gconstpointer key) return uri->port + soup_str_case_hash (uri->host); } -gboolean +static gboolean soup_host_uri_equal (gconstpointer v1, gconstpointer v2) { const SoupURI *one = v1; -- cgit v1.2.1 From 40948122627bc65da53270238a941b8b417f6627 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 2 Nov 2012 12:07:03 -0400 Subject: soup-multipart-input-stream: belatedly add .h file to soup.h --- libsoup/soup.h | 1 + tests/multipart-test.c | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/libsoup/soup.h b/libsoup/soup.h index d4ddcead..2a2b051d 100644 --- a/libsoup/soup.h +++ b/libsoup/soup.h @@ -29,6 +29,7 @@ extern "C" { #include #include #include +#include #include #include #include diff --git a/tests/multipart-test.c b/tests/multipart-test.c index 136ee0db..a299684e 100644 --- a/tests/multipart-test.c +++ b/tests/multipart-test.c @@ -8,12 +8,6 @@ #include #include -#define LIBSOUP_USE_UNSTABLE_REQUEST_API -#include -#include -#include -#include - #include "test-utils.h" #define READ_BUFFER_SIZE 8192 -- cgit v1.2.1 From fed907815cb566ba4ebf7c6cb41e3656015eeec7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 2 Nov 2012 12:07:30 -0400 Subject: connection-test: make it not require access to private SoupConnection symbols --- tests/connection-test.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/connection-test.c b/tests/connection-test.c index ef21ec97..8050b3df 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -5,8 +5,6 @@ #include "test-utils.h" -#include "libsoup/soup-connection.h" - SoupServer *server; SoupURI *base_uri; GMutex server_mutex; @@ -713,11 +711,10 @@ static void connection_state_changed (GObject *object, GParamSpec *param, gpointer user_data) { - SoupConnection *conn = SOUP_CONNECTION (object); SoupConnectionState *state = user_data; SoupConnectionState new_state; - new_state = soup_connection_get_state (conn); + g_object_get (object, "state", &new_state, NULL); if (state_transitions[*state] != new_state) { debug_printf (1, " Unexpected transition: %s -> %s\n", state_names[*state], state_names[new_state]); @@ -731,12 +728,12 @@ connection_state_changed (GObject *object, GParamSpec *param, } static void -connection_created (SoupSession *session, SoupConnection *conn, +connection_created (SoupSession *session, GObject *conn, gpointer user_data) { SoupConnectionState *state = user_data; - *state = soup_connection_get_state (conn); + g_object_get (conn, "state", state, NULL); if (*state != SOUP_CONNECTION_NEW) { debug_printf (1, " Unexpected initial state: %d\n", *state); -- cgit v1.2.1 From 2e1e6999f627bce6fb18e5d94e256da2ac5fef30 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 2 Nov 2012 12:07:58 -0400 Subject: build: don't export private symbols in the libraries Add libsoup-2.4.sym and libsoup-gnome-2.4.sym, and use them to restrict the exported symbols in the libraries to what it's supposed to be. https://bugzilla.gnome.org/show_bug.cgi?id=595176 --- libsoup/Makefile.am | 9 +- libsoup/libsoup-2.4.sym | 485 ++++++++++++++++++++++++++++++++++++++++++ libsoup/libsoup-gnome-2.4.sym | 5 + 3 files changed, 497 insertions(+), 2 deletions(-) create mode 100644 libsoup/libsoup-2.4.sym create mode 100644 libsoup/libsoup-gnome-2.4.sym diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 710e750e..7eebe9d7 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -78,7 +78,9 @@ nodist_libsoupinclude_HEADERS = \ lib_LTLIBRARIES = libsoup-2.4.la libsoup_2_4_la_LDFLAGS = \ - -version-info $(SOUP_CURRENT):$(SOUP_REVISION):$(SOUP_AGE) -no-undefined + -version-info $(SOUP_CURRENT):$(SOUP_REVISION):$(SOUP_AGE) \ + -no-undefined \ + -export-symbols $(srcdir)/libsoup-2.4.sym libsoup_2_4_la_LIBADD = \ $(GLIB_LIBS) \ @@ -204,7 +206,10 @@ libsoupgnomeinclude_HEADERS = \ lib_LTLIBRARIES += libsoup-gnome-2.4.la -libsoup_gnome_2_4_la_LDFLAGS = $(libsoup_2_4_la_LDFLAGS) +libsoup_gnome_2_4_la_LDFLAGS = \ + -version-info $(SOUP_CURRENT):$(SOUP_REVISION):$(SOUP_AGE) \ + -no-undefined \ + -export-symbols $(srcdir)/libsoup-gnome-2.4.sym libsoup_gnome_2_4_la_LIBADD = \ libsoup-2.4.la \ diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym new file mode 100644 index 00000000..9e2fa1c0 --- /dev/null +++ b/libsoup/libsoup-2.4.sym @@ -0,0 +1,485 @@ +soup_add_completion +soup_add_idle +soup_add_io_watch +soup_address_equal_by_ip +soup_address_equal_by_name +soup_address_family_get_type +soup_address_get_gsockaddr +soup_address_get_name +soup_address_get_physical +soup_address_get_port +soup_address_get_sockaddr +soup_address_get_type +soup_address_hash_by_ip +soup_address_hash_by_name +soup_address_is_resolved +soup_address_new +soup_address_new_any +soup_address_new_from_sockaddr +soup_address_resolve_async +soup_address_resolve_sync +soup_add_timeout +soup_auth_authenticate +soup_auth_basic_get_type +soup_auth_digest_get_type +soup_auth_domain_accepts +soup_auth_domain_add_path +soup_auth_domain_basic_get_type +soup_auth_domain_basic_new +soup_auth_domain_basic_set_auth_callback +soup_auth_domain_challenge +soup_auth_domain_check_password +soup_auth_domain_covers +soup_auth_domain_digest_encode_password +soup_auth_domain_digest_get_type +soup_auth_domain_digest_new +soup_auth_domain_digest_set_auth_callback +soup_auth_domain_get_realm +soup_auth_domain_get_type +soup_auth_domain_remove_path +soup_auth_domain_set_filter +soup_auth_domain_set_generic_auth_callback +soup_auth_domain_try_generic_auth_callback +soup_auth_free_protection_space +soup_auth_get_authorization +soup_auth_get_host +soup_auth_get_info +soup_auth_get_protection_space +soup_auth_get_realm +soup_auth_get_saved_password +soup_auth_get_saved_users +soup_auth_get_scheme_name +soup_auth_get_type +soup_auth_has_saved_password +soup_auth_is_authenticated +soup_auth_is_for_proxy +soup_auth_new +soup_auth_ntlm_get_type +soup_auth_save_password +soup_auth_update +soup_buffer_copy +soup_buffer_free +soup_buffer_get_as_bytes +soup_buffer_get_data +soup_buffer_get_owner +soup_buffer_get_type +soup_buffer_new +soup_buffer_new_subbuffer +soup_buffer_new_take +soup_buffer_new_with_owner +soup_byte_array_get_type +soup_cacheability_get_type +soup_cache_clear +soup_cache_dump +soup_cache_flush +soup_cache_get_max_size +soup_cache_get_type +soup_cache_load +soup_cache_new +soup_cache_response_get_type +soup_cache_set_max_size +soup_cache_type_get_type +soup_char_attributes +soup_check_version +soup_client_context_get_address +soup_client_context_get_auth_domain +soup_client_context_get_auth_user +soup_client_context_get_host +soup_client_context_get_socket +soup_client_context_get_type +soup_connection_state_get_type +soup_content_decoder_get_type +soup_content_sniffer_get_buffer_size +soup_content_sniffer_get_type +soup_content_sniffer_new +soup_content_sniffer_sniff +soup_cookie_applies_to_uri +soup_cookie_copy +soup_cookie_domain_matches +soup_cookie_equal +soup_cookie_free +soup_cookie_get_domain +soup_cookie_get_expires +soup_cookie_get_http_only +soup_cookie_get_name +soup_cookie_get_path +soup_cookie_get_secure +soup_cookie_get_type +soup_cookie_get_value +soup_cookie_jar_accept_policy_get_type +soup_cookie_jar_add_cookie +soup_cookie_jar_add_cookie_with_first_party +soup_cookie_jar_all_cookies +soup_cookie_jar_delete_cookie +soup_cookie_jar_get_accept_policy +soup_cookie_jar_get_cookie_list +soup_cookie_jar_get_cookies +soup_cookie_jar_get_type +soup_cookie_jar_is_persistent +soup_cookie_jar_new +soup_cookie_jar_save +soup_cookie_jar_set_accept_policy +soup_cookie_jar_set_cookie +soup_cookie_jar_set_cookie_with_first_party +soup_cookie_jar_text_get_type +soup_cookie_jar_text_new +soup_cookie_new +soup_cookie_parse +soup_cookie_set_domain +soup_cookie_set_expires +soup_cookie_set_http_only +soup_cookie_set_max_age +soup_cookie_set_name +soup_cookie_set_path +soup_cookie_set_secure +soup_cookie_set_value +soup_cookies_free +soup_cookies_from_request +soup_cookies_from_response +soup_cookies_to_cookie_header +soup_cookies_to_request +soup_cookies_to_response +soup_cookie_to_cookie_header +soup_cookie_to_set_cookie_header +soup_date_copy +soup_date_format_get_type +soup_date_free +soup_date_get_day +soup_date_get_hour +soup_date_get_minute +soup_date_get_month +soup_date_get_offset +soup_date_get_second +soup_date_get_type +soup_date_get_utc +soup_date_get_year +soup_date_is_past +soup_date_new +soup_date_new_from_now +soup_date_new_from_string +soup_date_new_from_time_t +soup_date_to_string +soup_date_to_time_t +soup_date_to_timeval +soup_encoding_get_type +soup_expectation_get_type +soup_form_decode +soup_form_decode_multipart +soup_form_encode +soup_form_encode_datalist +soup_form_encode_hash +soup_form_encode_valist +soup_form_request_new +soup_form_request_new_from_datalist +soup_form_request_new_from_hash +soup_form_request_new_from_multipart +soup_get_major_version +soup_get_micro_version +soup_get_minor_version +soup_header_contains +soup_header_free_list +soup_header_free_param_list +soup_header_g_string_append_param +soup_header_g_string_append_param_quoted +soup_header_parse_list +soup_header_parse_param_list +soup_header_parse_quality_list +soup_header_parse_semi_param_list +soup_headers_parse +soup_headers_parse_request +soup_headers_parse_response +soup_headers_parse_status_line +soup_http_error_quark +soup_http_version_get_type +soup_known_status_code_get_type +soup_logger_attach +soup_logger_detach +soup_logger_get_type +soup_logger_log_level_get_type +soup_logger_new +soup_logger_set_printer +soup_logger_set_request_filter +soup_logger_set_response_filter +soup_memory_use_get_type +soup_message_add_header_handler +soup_message_add_status_code_handler +soup_message_body_append +soup_message_body_append_buffer +soup_message_body_append_take +soup_message_body_complete +soup_message_body_flatten +soup_message_body_free +soup_message_body_get_accumulate +soup_message_body_get_chunk +soup_message_body_get_type +soup_message_body_got_chunk +soup_message_body_new +soup_message_body_set_accumulate +soup_message_body_truncate +soup_message_body_wrote_chunk +soup_message_content_sniffed +soup_message_disable_feature +soup_message_finished +soup_message_flags_get_type +soup_message_get_address +soup_message_get_first_party +soup_message_get_flags +soup_message_get_https_status +soup_message_get_http_version +soup_message_get_type +soup_message_get_uri +soup_message_got_body +soup_message_got_chunk +soup_message_got_headers +soup_message_got_informational +soup_message_headers_append +soup_message_headers_clean_connection_headers +soup_message_headers_clear +soup_message_headers_foreach +soup_message_headers_free +soup_message_headers_free_ranges +soup_message_headers_get +soup_message_headers_get_content_disposition +soup_message_headers_get_content_length +soup_message_headers_get_content_range +soup_message_headers_get_content_type +soup_message_headers_get_encoding +soup_message_headers_get_expectations +soup_message_headers_get_list +soup_message_headers_get_one +soup_message_headers_get_ranges +soup_message_headers_get_type +soup_message_headers_iter_init +soup_message_headers_iter_next +soup_message_headers_new +soup_message_headers_remove +soup_message_headers_replace +soup_message_headers_set_content_disposition +soup_message_headers_set_content_length +soup_message_headers_set_content_range +soup_message_headers_set_content_type +soup_message_headers_set_encoding +soup_message_headers_set_expectations +soup_message_headers_set_range +soup_message_headers_set_ranges +soup_message_headers_type_get_type +soup_message_is_keepalive +soup_message_new +soup_message_new_from_uri +soup_message_restarted +soup_message_set_chunk_allocator +soup_message_set_first_party +soup_message_set_flags +soup_message_set_http_version +soup_message_set_redirect +soup_message_set_request +soup_message_set_response +soup_message_set_status +soup_message_set_status_full +soup_message_set_uri +soup_message_wrote_body +soup_message_wrote_body_data +soup_message_wrote_chunk +soup_message_wrote_headers +soup_message_wrote_informational +soup_multipart_append_form_file +soup_multipart_append_form_string +soup_multipart_append_part +soup_multipart_free +soup_multipart_get_length +soup_multipart_get_part +soup_multipart_get_type +soup_multipart_input_stream_get_headers +soup_multipart_input_stream_get_type +soup_multipart_input_stream_new +soup_multipart_input_stream_next_part +soup_multipart_input_stream_next_part_async +soup_multipart_input_stream_next_part_finish +soup_multipart_new +soup_multipart_new_from_message +soup_multipart_to_message +soup_password_manager_get_passwords_async +soup_password_manager_get_passwords_sync +soup_password_manager_get_type +soup_proxy_resolver_default_get_type +soup_proxy_resolver_get_proxy_async +soup_proxy_resolver_get_proxy_sync +soup_proxy_resolver_get_type +soup_proxy_uri_resolver_get_proxy_uri_async +soup_proxy_uri_resolver_get_proxy_uri_sync +soup_proxy_uri_resolver_get_type +soup_request_data_get_type +soup_requester_error_get_type +soup_requester_error_quark +soup_requester_get_type +soup_requester_new +soup_requester_request +soup_requester_request_uri +soup_request_file_get_file +soup_request_file_get_type +soup_request_get_content_length +soup_request_get_content_type +soup_request_get_session +soup_request_get_type +soup_request_get_uri +soup_request_http_get_message +soup_request_http_get_type +soup_request_send +soup_request_send_async +soup_request_send_finish +soup_server_add_auth_domain +soup_server_add_handler +soup_server_disconnect +soup_server_get_async_context +soup_server_get_listener +soup_server_get_port +soup_server_get_type +soup_server_is_https +soup_server_new +soup_server_pause_message +soup_server_quit +soup_server_remove_auth_domain +soup_server_remove_handler +soup_server_run +soup_server_run_async +soup_server_unpause_message +soup_session_abort +soup_session_add_feature +soup_session_add_feature_by_type +soup_session_async_get_type +soup_session_async_new +soup_session_async_new_with_options +soup_session_cancel_message +soup_session_feature_add_feature +soup_session_feature_attach +soup_session_feature_detach +soup_session_feature_get_type +soup_session_feature_has_feature +soup_session_feature_remove_feature +soup_session_get_async_context +soup_session_get_feature +soup_session_get_feature_for_message +soup_session_get_features +soup_session_get_type +soup_session_pause_message +soup_session_prefetch_dns +soup_session_prepare_for_uri +soup_session_queue_message +soup_session_redirect_message +soup_session_remove_feature +soup_session_remove_feature_by_type +soup_session_requeue_message +soup_session_send_message +soup_session_sync_get_type +soup_session_sync_new +soup_session_sync_new_with_options +soup_session_unpause_message +soup_session_would_redirect +soup_socket_connect_async +soup_socket_connect_sync +soup_socket_disconnect +soup_socket_get_fd +soup_socket_get_local_address +soup_socket_get_remote_address +soup_socket_get_type +soup_socket_io_status_get_type +soup_socket_is_connected +soup_socket_is_ssl +soup_socket_listen +soup_socket_new +soup_socket_read +soup_socket_read_until +soup_socket_start_proxy_ssl +soup_socket_start_ssl +soup_socket_write +soup_ssl_supported +soup_status_get_phrase +soup_status_proxify +soup_str_case_equal +soup_str_case_hash +soup_tld_domain_is_public_suffix +soup_tld_error_get_type +soup_tld_error_quark +soup_tld_get_base_domain +soup_uri_copy +soup_uri_copy_host +soup_uri_decode +soup_uri_encode +soup_uri_equal +soup_uri_free +soup_uri_get_fragment +soup_uri_get_host +soup_uri_get_password +soup_uri_get_path +soup_uri_get_port +soup_uri_get_query +soup_uri_get_scheme +soup_uri_get_type +soup_uri_get_user +soup_uri_host_equal +soup_uri_host_hash +soup_uri_new +soup_uri_new_with_base +soup_uri_normalize +soup_uri_set_fragment +soup_uri_set_host +soup_uri_set_password +soup_uri_set_path +soup_uri_set_port +soup_uri_set_query +soup_uri_set_query_from_fields +soup_uri_set_query_from_form +soup_uri_set_scheme +soup_uri_set_user +soup_uri_to_string +soup_uri_uses_default_port +soup_value_array_append +soup_value_array_append_vals +soup_value_array_from_args +soup_value_array_get_nth +soup_value_array_insert +soup_value_array_new +soup_value_array_new_with_vals +soup_value_array_to_args +soup_value_hash_insert +soup_value_hash_insert_vals +soup_value_hash_insert_value +soup_value_hash_lookup +soup_value_hash_lookup_vals +soup_value_hash_new +soup_value_hash_new_with_vals +soup_xmlrpc_build_fault +soup_xmlrpc_build_method_call +soup_xmlrpc_build_method_response +soup_xmlrpc_error_get_type +soup_xmlrpc_error_quark +soup_xmlrpc_extract_method_call +soup_xmlrpc_extract_method_response +soup_xmlrpc_fault_get_type +soup_xmlrpc_fault_quark +soup_xmlrpc_parse_method_call +soup_xmlrpc_parse_method_response +soup_xmlrpc_request_new +soup_xmlrpc_set_fault +soup_xmlrpc_set_response +_SOUP_METHOD_CONNECT +_SOUP_METHOD_COPY +_SOUP_METHOD_DELETE +_SOUP_METHOD_GET +_SOUP_METHOD_HEAD +_SOUP_METHOD_LOCK +_SOUP_METHOD_MKCOL +_SOUP_METHOD_MOVE +_SOUP_METHOD_OPTIONS +_SOUP_METHOD_POST +_SOUP_METHOD_PROPFIND +_SOUP_METHOD_PROPPATCH +_SOUP_METHOD_PUT +_SOUP_METHOD_TRACE +_SOUP_METHOD_UNLOCK +_SOUP_URI_SCHEME_DATA +_SOUP_URI_SCHEME_FILE +_SOUP_URI_SCHEME_FTP +_SOUP_URI_SCHEME_HTTP +_SOUP_URI_SCHEME_HTTPS +_SOUP_URI_SCHEME_RESOURCE diff --git a/libsoup/libsoup-gnome-2.4.sym b/libsoup/libsoup-gnome-2.4.sym new file mode 100644 index 00000000..67f62dec --- /dev/null +++ b/libsoup/libsoup-gnome-2.4.sym @@ -0,0 +1,5 @@ +soup_cookie_jar_sqlite_get_type +soup_cookie_jar_sqlite_new +soup_gnome_features_2_26_get_type +soup_password_manager_gnome_get_type +soup_proxy_resolver_gnome_get_type -- cgit v1.2.1 From 4bec9ebc81ffb5d20dc121ee7818272c697faaa6 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 30 Jul 2012 13:31:05 +0200 Subject: SoupContentProcessor: new interface New SoupContentProcessor interface. It defines a _wrap_input() function which implementors will use to add their own stream on top of the given base stream. https://bugzilla.gnome.org/show_bug.cgi?id=682112 --- libsoup/Makefile.am | 2 ++ libsoup/soup-content-processor.c | 51 ++++++++++++++++++++++++++++++++++++ libsoup/soup-content-processor.h | 56 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 libsoup/soup-content-processor.c create mode 100644 libsoup/soup-content-processor.h diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 7eebe9d7..98f0b4b0 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -115,6 +115,8 @@ libsoup_2_4_la_SOURCES = \ soup-connection.h \ soup-connection.c \ soup-content-decoder.c \ + soup-content-processor.h \ + soup-content-processor.c \ soup-content-sniffer.c \ soup-content-sniffer-stream.h \ soup-content-sniffer-stream.c \ diff --git a/libsoup/soup-content-processor.c b/libsoup/soup-content-processor.c new file mode 100644 index 00000000..8b959ebe --- /dev/null +++ b/libsoup/soup-content-processor.c @@ -0,0 +1,51 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia, S.L. + */ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-content-processor.h" +#include "soup.h" + +static void soup_content_processor_default_init (SoupContentProcessorInterface *interface); + +G_DEFINE_INTERFACE (SoupContentProcessor, soup_content_processor, G_TYPE_OBJECT) + +static GInputStream * +soup_content_processor_real_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + g_return_val_if_reached (NULL); +} + +static void +soup_content_processor_default_init (SoupContentProcessorInterface *interface) +{ + interface->processing_stage = SOUP_STAGE_INVALID; + interface->wrap_input = soup_content_processor_real_wrap_input; +} + +GInputStream * +soup_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + g_return_val_if_fail (SOUP_IS_CONTENT_PROCESSOR (processor), NULL); + + return SOUP_CONTENT_PROCESSOR_GET_INTERFACE (processor)->wrap_input (processor, base_stream, msg, error); +} + +SoupProcessingStage +soup_content_processor_get_processing_stage (SoupContentProcessor *processor) +{ + g_return_val_if_fail (SOUP_IS_CONTENT_PROCESSOR (processor), SOUP_STAGE_INVALID); + + return SOUP_CONTENT_PROCESSOR_GET_INTERFACE (processor)->processing_stage; +} diff --git a/libsoup/soup-content-processor.h b/libsoup/soup-content-processor.h new file mode 100644 index 00000000..8ee04b2f --- /dev/null +++ b/libsoup/soup-content-processor.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia, S.L. + */ + + +#ifndef SOUP_CONTENT_PROCESSOR_H +#define SOUP_CONTENT_PROCESSOR_H 1 + +#include +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONTENT_PROCESSOR (soup_content_processor_get_type ()) +#define SOUP_CONTENT_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CONTENT_PROCESSOR, SoupContentProcessor)) +#define SOUP_IS_CONTENT_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CONTENT_PROCESSOR)) +#define SOUP_CONTENT_PROCESSOR_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), SOUP_TYPE_CONTENT_PROCESSOR, SoupContentProcessorInterface)) + +typedef enum { + SOUP_STAGE_INVALID, + + SOUP_STAGE_MESSAGE_BODY, /* Raw network data */ + SOUP_STAGE_TRANSFER_ENCODING, /* SoupBodyInputStream is here */ + SOUP_STAGE_ENTITY_BODY, /* Has Transfer-Encoding removed */ + SOUP_STAGE_CONTENT_ENCODING, /* SoupContentDecoder works here */ + SOUP_STAGE_BODY_DATA /* Actual body data */ +} SoupProcessingStage; + +typedef struct _SoupContentProcessor SoupContentProcessor; +typedef struct _SoupContentProcessorInterface SoupContentProcessorInterface; + +struct _SoupContentProcessorInterface { + GTypeInterface parent; + + SoupProcessingStage processing_stage; + + /* methods */ + GInputStream* (*wrap_input) (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error); +}; + +GType soup_content_processor_get_type (void); + +GInputStream *soup_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error); + +SoupProcessingStage soup_content_processor_get_processing_stage (SoupContentProcessor *processor); + +G_END_DECLS + +#endif /* SOUP_CONTENT_PROCESSOR_H */ -- cgit v1.2.1 From c79bf2770c8a239c7495d92e5c885e1dea42fc6f Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Tue, 21 Aug 2012 16:44:43 +0200 Subject: Added SoupContentProcessor support to SoupMessage, SoupContentDecoder & SoupContentSniffer soup-message-io uses the content processors registered for each SoupMessage to properly setup the stack of streams used to read a particular resource either downloaded from the network or read from a local cached file. Note that server-side messages do not have content processor support yet. SoupContentDecoder becomes a content processor and wraps the given base stream with a list of decoders when required. SoupContentSniffer becomes a content processor working at the SOUP_STAGE_BODY_DATA stage. https://bugzilla.gnome.org/show_bug.cgi?id=682112 --- libsoup/soup-content-decoder.c | 182 ++++++++++++++++++++-------------- libsoup/soup-content-sniffer-stream.c | 12 --- libsoup/soup-content-sniffer-stream.h | 4 - libsoup/soup-content-sniffer.c | 35 ++++++- libsoup/soup-message-io.c | 94 ++++++++++++------ libsoup/soup-message-private.h | 8 +- libsoup/soup-message.c | 4 - 7 files changed, 210 insertions(+), 129 deletions(-) diff --git a/libsoup/soup-content-decoder.c b/libsoup/soup-content-decoder.c index 85dcef49..fa7629af 100644 --- a/libsoup/soup-content-decoder.c +++ b/libsoup/soup-content-decoder.c @@ -10,6 +10,7 @@ #endif #include "soup-content-decoder.h" +#include "soup-converter-wrapper.h" #include "soup.h" #include "soup-message-private.h" @@ -50,9 +51,114 @@ typedef GConverter * (*SoupContentDecoderCreator) (void); static void soup_content_decoder_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); +static SoupContentProcessorInterface *soup_content_decoder_default_content_processor_interface; +static void soup_content_decoder_content_processor_init (SoupContentProcessorInterface *interface, gpointer interface_data); + + G_DEFINE_TYPE_WITH_CODE (SoupContentDecoder, soup_content_decoder, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, - soup_content_decoder_session_feature_init)) + soup_content_decoder_session_feature_init) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_CONTENT_PROCESSOR, + soup_content_decoder_content_processor_init)) + +static GSList * +soup_content_decoder_get_decoders_for_msg (SoupContentDecoder *decoder, SoupMessage *msg) +{ + const char *header; + GSList *encodings, *e, *decoders = NULL; + SoupContentDecoderCreator converter_creator; + GConverter *converter; + + header = soup_message_headers_get_list (msg->response_headers, + "Content-Encoding"); + if (!header) + return NULL; + + /* Workaround for an apache bug (bgo 613361) */ + if (!g_ascii_strcasecmp (header, "gzip") || + !g_ascii_strcasecmp (header, "x-gzip")) { + const char *content_type = soup_message_headers_get_content_type (msg->response_headers, NULL); + + if (content_type && + (!g_ascii_strcasecmp (content_type, "application/gzip") || + !g_ascii_strcasecmp (content_type, "application/x-gzip"))) + return NULL; + } + + /* OK, really, no one is ever going to use more than one + * encoding, but we'll be robust. + */ + encodings = soup_header_parse_list (header); + if (!encodings) + return NULL; + + for (e = encodings; e; e = e->next) { + if (!g_hash_table_lookup (decoder->priv->decoders, e->data)) { + soup_header_free_list (encodings); + return NULL; + } + } + + for (e = encodings; e; e = e->next) { + converter_creator = g_hash_table_lookup (decoder->priv->decoders, e->data); + converter = converter_creator (); + + /* Content-Encoding lists the codings in the order + * they were applied in, so we put decoders in reverse + * order so the last-applied will be the first + * decoded. + */ + decoders = g_slist_prepend (decoders, converter); + } + soup_header_free_list (encodings); + + return decoders; +} + +static GInputStream* +soup_content_decoder_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + GSList *decoders, *d; + GInputStream *istream; + + decoders = soup_content_decoder_get_decoders_for_msg (SOUP_CONTENT_DECODER (processor), msg); + if (!decoders) + return NULL; + + istream = g_object_ref (base_stream); + for (d = decoders; d; d = d->next) { + GConverter *decoder, *wrapper; + GInputStream *filter; + + decoder = d->data; + wrapper = soup_converter_wrapper_new (decoder, msg); + filter = g_object_new (G_TYPE_CONVERTER_INPUT_STREAM, + "base-stream", istream, + "converter", wrapper, + NULL); + g_object_unref (istream); + g_object_unref (wrapper); + istream = filter; + } + + g_slist_free_full (decoders, g_object_unref); + + return istream; +} + +static void +soup_content_decoder_content_processor_init (SoupContentProcessorInterface *processor_interface, + gpointer interface_data) +{ + soup_content_decoder_default_content_processor_interface = + g_type_default_interface_peek (SOUP_TYPE_CONTENT_PROCESSOR); + + processor_interface->processing_stage = SOUP_STAGE_CONTENT_ENCODING; + processor_interface->wrap_input = soup_content_decoder_content_processor_wrap_input; +} /* This is constant for now */ #define ACCEPT_ENCODING_HEADER "gzip, deflate" @@ -106,90 +212,17 @@ soup_content_decoder_class_init (SoupContentDecoderClass *decoder_class) object_class->finalize = soup_content_decoder_finalize; } -static void -soup_content_decoder_got_headers_cb (SoupMessage *msg, SoupContentDecoder *decoder) -{ - SoupMessagePrivate *msgpriv = SOUP_MESSAGE_GET_PRIVATE (msg); - const char *header; - GSList *encodings, *e; - SoupContentDecoderCreator converter_creator; - GConverter *converter; - - header = soup_message_headers_get_list (msg->response_headers, - "Content-Encoding"); - if (!header) - return; - - /* Workaround for an apache bug (bgo 613361) */ - if (!g_ascii_strcasecmp (header, "gzip") || - !g_ascii_strcasecmp (header, "x-gzip")) { - const char *content_type = soup_message_headers_get_content_type (msg->response_headers, NULL); - - if (content_type && - (!g_ascii_strcasecmp (content_type, "application/gzip") || - !g_ascii_strcasecmp (content_type, "application/x-gzip"))) - return; - } - - /* OK, really, no one is ever going to use more than one - * encoding, but we'll be robust. - */ - encodings = soup_header_parse_list (header); - if (!encodings) - return; - - for (e = encodings; e; e = e->next) { - if (!g_hash_table_lookup (decoder->priv->decoders, e->data)) { - soup_header_free_list (encodings); - return; - } - } - - /* msgpriv->decoders should be empty at this point anyway, but - * clean it up if it's not. - */ - g_slist_free_full (msgpriv->decoders, g_object_unref); - msgpriv->decoders = NULL; - - for (e = encodings; e; e = e->next) { - converter_creator = g_hash_table_lookup (decoder->priv->decoders, e->data); - converter = converter_creator (); - - /* Content-Encoding lists the codings in the order - * they were applied in, so we put decoders in reverse - * order so the last-applied will be the first - * decoded. - */ - msgpriv->decoders = g_slist_prepend (msgpriv->decoders, converter); - } - soup_header_free_list (encodings); -} - static void soup_content_decoder_request_queued (SoupSessionFeature *feature, SoupSession *session, SoupMessage *msg) { - SoupContentDecoder *decoder = SOUP_CONTENT_DECODER (feature); - if (!soup_message_headers_get_one (msg->request_headers, "Accept-Encoding")) { soup_message_headers_append (msg->request_headers, "Accept-Encoding", ACCEPT_ENCODING_HEADER); } - - g_signal_connect (msg, "got-headers", - G_CALLBACK (soup_content_decoder_got_headers_cb), - decoder); -} - -static void -soup_content_decoder_request_unqueued (SoupSessionFeature *feature, - SoupSession *session, - SoupMessage *msg) -{ - g_signal_handlers_disconnect_by_func (msg, soup_content_decoder_got_headers_cb, feature); } static void @@ -197,5 +230,4 @@ soup_content_decoder_session_feature_init (SoupSessionFeatureInterface *feature_ gpointer interface_data) { feature_interface->request_queued = soup_content_decoder_request_queued; - feature_interface->request_unqueued = soup_content_decoder_request_unqueued; } diff --git a/libsoup/soup-content-sniffer-stream.c b/libsoup/soup-content-sniffer-stream.c index 173f9021..d358a19e 100644 --- a/libsoup/soup-content-sniffer-stream.c +++ b/libsoup/soup-content-sniffer-stream.c @@ -336,18 +336,6 @@ soup_content_sniffer_stream_pollable_init (GPollableInputStreamInterface *pollab pollable_interface->create_source = soup_content_sniffer_stream_create_source; } -GInputStream * -soup_content_sniffer_stream_new (SoupContentSniffer *sniffer, - SoupMessage *msg, - GInputStream *base_stream) -{ - return g_object_new (SOUP_TYPE_CONTENT_SNIFFER_STREAM, - "base-stream", base_stream, - "message", msg, - "sniffer", sniffer, - NULL); -} - gboolean soup_content_sniffer_stream_is_ready (SoupContentSnifferStream *sniffer, gboolean blocking, diff --git a/libsoup/soup-content-sniffer-stream.h b/libsoup/soup-content-sniffer-stream.h index fb4889ce..ab230f3e 100644 --- a/libsoup/soup-content-sniffer-stream.h +++ b/libsoup/soup-content-sniffer-stream.h @@ -36,10 +36,6 @@ struct _SoupContentSnifferStreamClass { GType soup_content_sniffer_stream_get_type (void) G_GNUC_CONST; -GInputStream *soup_content_sniffer_stream_new (SoupContentSniffer *sniffer, - SoupMessage *msg, - GInputStream *base_stream); - gboolean soup_content_sniffer_stream_is_ready (SoupContentSnifferStream *sniffer, gboolean blocking, GCancellable *cancellable, diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index 0986bbe3..012c0dc0 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -13,6 +13,8 @@ #include "soup-content-sniffer.h" #include "soup.h" +#include "soup-content-processor.h" +#include "soup-content-sniffer-stream.h" #include "soup-message-private.h" /** @@ -31,9 +33,40 @@ static void soup_content_sniffer_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); +static SoupContentProcessorInterface *soup_content_sniffer_default_content_processor_interface; +static void soup_content_sniffer_content_processor_init (SoupContentProcessorInterface *interface, gpointer interface_data); + + G_DEFINE_TYPE_WITH_CODE (SoupContentSniffer, soup_content_sniffer, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, - soup_content_sniffer_session_feature_init)) + soup_content_sniffer_session_feature_init) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_CONTENT_PROCESSOR, + soup_content_sniffer_content_processor_init)) + + +static GInputStream * +soup_content_sniffer_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + return g_object_new (SOUP_TYPE_CONTENT_SNIFFER_STREAM, + "base-stream", base_stream, + "message", msg, + "sniffer", SOUP_CONTENT_SNIFFER (processor), + NULL); +} + +static void +soup_content_sniffer_content_processor_init (SoupContentProcessorInterface *processor_interface, + gpointer interface_data) +{ + soup_content_sniffer_default_content_processor_interface = + g_type_default_interface_peek (SOUP_TYPE_CONTENT_PROCESSOR); + + processor_interface->processing_stage = SOUP_STAGE_BODY_DATA; + processor_interface->wrap_input = soup_content_sniffer_content_processor_wrap_input; +} static void soup_content_sniffer_init (SoupContentSniffer *content_sniffer) diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 52af22b5..e851ac4f 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -16,8 +16,8 @@ #include "soup-body-output-stream.h" #include "soup-client-input-stream.h" #include "soup-connection.h" +#include "soup-content-processor.h" #include "soup-content-sniffer-stream.h" -#include "soup-converter-wrapper.h" #include "soup-filter-input-stream.h" #include "soup-message-private.h" #include "soup-message-queue.h" @@ -221,38 +221,53 @@ read_headers (SoupMessage *msg, GCancellable *cancellable, GError **error) return TRUE; } -static void -setup_body_istream (SoupMessage *msg) +static gint +processing_stage_cmp (gconstpointer a, + gconstpointer b) { - SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); - SoupMessageIOData *io = priv->io_data; - GConverter *decoder, *wrapper; - GInputStream *filter; - GSList *d; - - io->body_istream = - soup_body_input_stream_new (G_INPUT_STREAM (io->istream), - io->read_encoding, - io->read_length); - - for (d = priv->decoders; d; d = d->next) { - decoder = d->data; - wrapper = soup_converter_wrapper_new (decoder, msg); - filter = g_object_new (G_TYPE_CONVERTER_INPUT_STREAM, - "base-stream", io->body_istream, - "converter", wrapper, - NULL); - g_object_unref (io->body_istream); - g_object_unref (wrapper); - io->body_istream = filter; - } + SoupProcessingStage stage_a = soup_content_processor_get_processing_stage (SOUP_CONTENT_PROCESSOR (a)); + SoupProcessingStage stage_b = soup_content_processor_get_processing_stage (SOUP_CONTENT_PROCESSOR (b)); + + if (stage_a > stage_b) + return 1; + if (stage_a == stage_b) + return 0; + return -1; +} - if (priv->sniffer) { - filter = soup_content_sniffer_stream_new (priv->sniffer, - msg, io->body_istream); - g_object_unref (io->body_istream); - io->body_istream = filter; +GInputStream * +soup_message_setup_body_istream (GInputStream *body_stream, + SoupMessage *msg, + SoupSession *session, + SoupProcessingStage start_at_stage) +{ + GInputStream *istream; + GSList *p, *processors; + + istream = g_object_ref (body_stream); + + processors = soup_session_get_features (session, SOUP_TYPE_CONTENT_PROCESSOR); + processors = g_slist_sort (processors, processing_stage_cmp); + + for (p = processors; p; p = p->next) { + GInputStream *wrapper; + SoupContentProcessor *processor; + + processor = SOUP_CONTENT_PROCESSOR (p->data); + if (soup_message_disables_feature (msg, p->data) || + soup_content_processor_get_processing_stage (processor) < start_at_stage) + continue; + + wrapper = soup_content_processor_wrap_input (processor, istream, msg, NULL); + if (wrapper) { + g_object_unref (istream); + istream = wrapper; + } } + + g_slist_free (processors); + + return istream; } /* @@ -570,8 +585,23 @@ io_read (SoupMessage *msg, GCancellable *cancellable, GError **error) case SOUP_MESSAGE_IO_STATE_BODY_START: - if (!io->body_istream) - setup_body_istream (msg); + if (!io->body_istream) { + GInputStream *body_istream = soup_body_input_stream_new (G_INPUT_STREAM (io->istream), + io->read_encoding, + io->read_length); + + /* TODO: server-side messages do not have a io->item. This means + * that we cannot use content processors for them right now. + */ + if (io->mode == SOUP_MESSAGE_IO_CLIENT) { + io->body_istream = soup_message_setup_body_istream (body_istream, msg, + io->item->session, + SOUP_STAGE_MESSAGE_BODY); + g_object_unref (body_istream); + } else { + io->body_istream = body_istream; + } + } if (priv->sniffer) { SoupContentSnifferStream *sniffer_stream = SOUP_CONTENT_SNIFFER_STREAM (io->body_istream); diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index 69490e94..86650077 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -8,7 +8,9 @@ #include "soup-message.h" #include "soup-auth.h" +#include "soup-content-processor.h" #include "soup-content-sniffer.h" +#include "soup-session.h" typedef struct { gpointer io_data; @@ -31,7 +33,6 @@ typedef struct { SoupAuth *auth, *proxy_auth; GSList *disabled_features; - GSList *decoders; SoupURI *first_party; @@ -126,4 +127,9 @@ void soup_message_network_event (SoupMessage *msg, GSocketClientEvent event, GIOStream *connection); +GInputStream *soup_message_setup_body_istream (GInputStream *body_stream, + SoupMessage *msg, + SoupSession *session, + SoupProcessingStage start_at_stage); + #endif /* SOUP_MESSAGE_PRIVATE_H */ diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 2271cd0a..5ff836f4 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -162,8 +162,6 @@ soup_message_finalize (GObject *object) g_slist_free (priv->disabled_features); - g_slist_free_full (priv->decoders, g_object_unref); - g_clear_object (&priv->tls_certificate); soup_message_body_free (msg->request_body); @@ -1413,8 +1411,6 @@ soup_message_cleanup_response (SoupMessage *req) SOUP_ENCODING_CONTENT_LENGTH); } - g_slist_free_full (priv->decoders, g_object_unref); - priv->decoders = NULL; priv->msg_flags &= ~SOUP_MESSAGE_CONTENT_DECODED; req->status_code = SOUP_STATUS_NONE; -- cgit v1.2.1 From 3294110d20c189805940996623d6a35fe8cfa9ad Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 27 Sep 2012 21:39:43 -0400 Subject: SoupConnection: don't listen to SoupSocket::disconnected No one except SoupConnection ever calls soup_socket_disconnect() any more, so we don't need to listen to SoupSocket::disconnected to know when it happens. --- libsoup/soup-connection.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 1889a940..2caded18 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -422,12 +422,6 @@ proxy_socket_event (SoupSocket *socket, soup_connection_event (conn, event, connection); } -static void -socket_disconnected (SoupSocket *sock, gpointer conn) -{ - soup_connection_disconnect (conn); -} - typedef struct { SoupConnection *conn; SoupConnectionCallback callback; @@ -445,9 +439,6 @@ socket_connect_finished (SoupSocket *socket, guint status, gpointer user_data) g_signal_handler_disconnect (socket, data->event_id); if (SOUP_STATUS_IS_SUCCESSFUL (status)) { - g_signal_connect (priv->socket, "disconnected", - G_CALLBACK (socket_disconnected), data->conn); - if (priv->ssl && !priv->proxy_uri) { soup_connection_event (data->conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, @@ -668,9 +659,6 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) } if (SOUP_STATUS_IS_SUCCESSFUL (status)) { - g_signal_connect (priv->socket, "disconnected", - G_CALLBACK (socket_disconnected), conn); - if (!priv->ssl || !priv->proxy_uri) { soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, @@ -820,14 +808,9 @@ soup_connection_disconnect (SoupConnection *conn) soup_connection_set_state (conn, SOUP_CONNECTION_DISCONNECTED); if (priv->socket) { - /* Set the socket to NULL at the beginning to avoid reentrancy - * issues. soup_socket_disconnect() could trigger a reentrant - * call unref'ing and disconnecting the socket twice. - */ SoupSocket *socket = priv->socket; + priv->socket = NULL; - g_signal_handlers_disconnect_by_func (socket, - socket_disconnected, conn); soup_socket_disconnect (socket); g_object_unref (socket); } -- cgit v1.2.1 From 24087e3c48c1d2c56be31e85af7a3b89df291f20 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 24 Oct 2012 13:08:33 +0200 Subject: SoupConnection: drop "message" property epiphany-extensions is dead, so there's no reason to support the undocumented SoupConnection:message property for soup-fly any more. --- libsoup/soup-connection.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 2caded18..e59ffadf 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -60,7 +60,6 @@ enum { PROP_TIMEOUT, PROP_IDLE_TIMEOUT, PROP_STATE, - PROP_MESSAGE, LAST_PROP }; @@ -199,12 +198,6 @@ soup_connection_get_property (GObject *object, guint prop_id, case PROP_STATE: g_value_set_enum (value, priv->state); break; - case PROP_MESSAGE: - if (priv->cur_item) - g_value_set_object (value, priv->cur_item->msg); - else - g_value_set_object (value, NULL); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -321,13 +314,6 @@ soup_connection_class_init (SoupConnectionClass *connection_class) "Current state of connection", SOUP_TYPE_CONNECTION_STATE, SOUP_CONNECTION_NEW, G_PARAM_READWRITE)); - g_object_class_install_property ( - object_class, PROP_MESSAGE, - g_param_spec_object (SOUP_CONNECTION_MESSAGE, - "Message", - "Message being processed", - SOUP_TYPE_MESSAGE, - G_PARAM_READABLE)); } static void @@ -395,7 +381,6 @@ set_current_item (SoupConnection *conn, SoupMessageQueueItem *item) item->state = SOUP_MESSAGE_RUNNING; priv->cur_item = item; - g_object_notify (G_OBJECT (conn), "message"); priv->reusable = FALSE; g_signal_connect (item->msg, "restarted", @@ -897,7 +882,6 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) item = priv->cur_item; priv->cur_item = NULL; - g_object_notify (G_OBJECT (conn), "message"); g_signal_handlers_disconnect_by_func (item->msg, G_CALLBACK (current_item_restarted), conn); -- cgit v1.2.1 From 79d952dfc05948d4ac6d3a50d8e99bbaf644e71e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 24 Oct 2012 13:12:12 +0200 Subject: SoupConnection: track current message, not current item SoupConnection doesn't need to care about anything SoupMessageQueueItem-specific (the one place where it did was redundant with other code), so go back to only tracking the current SoupMessage. --- libsoup/soup-connection.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index e59ffadf..d677ee67 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -27,7 +27,7 @@ typedef struct { GMainContext *async_context; gboolean use_thread_context; - SoupMessageQueueItem *cur_item; + SoupMessage *current_msg; SoupConnectionState state; time_t unused_timeout; guint io_timeout, idle_timeout; @@ -360,7 +360,7 @@ stop_idle_timer (SoupConnectionPrivate *priv) } static void -current_item_restarted (SoupMessage *msg, gpointer user_data) +current_msg_restarted (SoupMessage *msg, gpointer user_data) { SoupConnection *conn = user_data; SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); @@ -369,24 +369,23 @@ current_item_restarted (SoupMessage *msg, gpointer user_data) } static void -set_current_item (SoupConnection *conn, SoupMessageQueueItem *item) +set_current_msg (SoupConnection *conn, SoupMessage *msg) { SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); - g_return_if_fail (priv->cur_item == NULL); + g_return_if_fail (priv->current_msg == NULL); g_object_freeze_notify (G_OBJECT (conn)); stop_idle_timer (priv); - item->state = SOUP_MESSAGE_RUNNING; - priv->cur_item = item; + priv->current_msg = msg; priv->reusable = FALSE; - g_signal_connect (item->msg, "restarted", - G_CALLBACK (current_item_restarted), conn); + g_signal_connect (msg, "restarted", + G_CALLBACK (current_msg_restarted), conn); - if (item->msg->method == SOUP_METHOD_CONNECT) + if (msg->method == SOUP_METHOD_CONNECT) soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATING, NULL); else if (priv->state == SOUP_CONNECTION_IDLE) soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); @@ -874,19 +873,19 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) if (old_state == SOUP_CONNECTION_IN_USE) priv->unused_timeout = 0; - if (priv->cur_item) { - SoupMessageQueueItem *item; + if (priv->current_msg) { + SoupMessage *msg; g_warn_if_fail (state == SOUP_CONNECTION_IDLE || state == SOUP_CONNECTION_DISCONNECTED); - item = priv->cur_item; - priv->cur_item = NULL; + msg = priv->current_msg; + priv->current_msg = NULL; - g_signal_handlers_disconnect_by_func (item->msg, G_CALLBACK (current_item_restarted), conn); + g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (current_msg_restarted), conn); - if (item->msg->method == SOUP_METHOD_CONNECT && - SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) { + if (msg->method == SOUP_METHOD_CONNECT && + SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATED, NULL); /* We're now effectively no longer proxying */ @@ -898,7 +897,7 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) state = SOUP_CONNECTION_IN_USE; } - if (!soup_message_is_keepalive (item->msg) || !priv->reusable) + if (!soup_message_is_keepalive (msg) || !priv->reusable) soup_connection_disconnect (conn); } @@ -947,7 +946,7 @@ soup_connection_send_request (SoupConnection *conn, priv = SOUP_CONNECTION_GET_PRIVATE (conn); g_return_if_fail (priv->state != SOUP_CONNECTION_NEW && priv->state != SOUP_CONNECTION_DISCONNECTED); - if (item != priv->cur_item) - set_current_item (conn, item); + if (item->msg != priv->current_msg) + set_current_msg (conn, item->msg); soup_message_send_request (item, completion_cb, user_data); } -- cgit v1.2.1 From 2d03d2cc815d66cffffbb19cea3f0a05af5273ca Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 28 Sep 2012 17:17:11 -0400 Subject: SoupConnection: track reusability internally Rather than relying on soup-message-io to tell us when a connection can be reused, track it directly within SoupConnection. --- libsoup/soup-connection.c | 39 ++++++++++++++++++--------------------- libsoup/soup-connection.h | 1 - libsoup/soup-message-io.c | 2 -- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index d677ee67..783ab591 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -360,12 +360,23 @@ stop_idle_timer (SoupConnectionPrivate *priv) } static void -current_msg_restarted (SoupMessage *msg, gpointer user_data) +current_msg_got_body (SoupMessage *msg, gpointer user_data) { SoupConnection *conn = user_data; SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); priv->unused_timeout = 0; + + if (priv->proxy_uri && + msg->method == SOUP_METHOD_CONNECT && + SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATED, NULL); + + /* We're now effectively no longer proxying */ + g_clear_pointer (&priv->proxy_uri, soup_uri_free); + } + + priv->reusable = soup_message_is_keepalive (msg); } static void @@ -374,6 +385,7 @@ set_current_msg (SoupConnection *conn, SoupMessage *msg) SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); g_return_if_fail (priv->current_msg == NULL); + g_return_if_fail (priv->state == SOUP_CONNECTION_IN_USE); g_object_freeze_notify (G_OBJECT (conn)); @@ -382,13 +394,11 @@ set_current_msg (SoupConnection *conn, SoupMessage *msg) priv->current_msg = msg; priv->reusable = FALSE; - g_signal_connect (msg, "restarted", - G_CALLBACK (current_msg_restarted), conn); + g_signal_connect (msg, "got-body", + G_CALLBACK (current_msg_got_body), conn); - if (msg->method == SOUP_METHOD_CONNECT) + if (priv->proxy_uri && msg->method == SOUP_METHOD_CONNECT) soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATING, NULL); - else if (priv->state == SOUP_CONNECTION_IDLE) - soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); g_object_thaw_notify (G_OBJECT (conn)); } @@ -882,22 +892,15 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) msg = priv->current_msg; priv->current_msg = NULL; - g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (current_msg_restarted), conn); + g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (current_msg_got_body), conn); if (msg->method == SOUP_METHOD_CONNECT && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - soup_connection_event (conn, G_SOCKET_CLIENT_PROXY_NEGOTIATED, NULL); - - /* We're now effectively no longer proxying */ - soup_uri_free (priv->proxy_uri); - priv->proxy_uri = NULL; - - /* Nor are we actually IDLE... */ if (state == SOUP_CONNECTION_IDLE) state = SOUP_CONNECTION_IN_USE; } - if (!soup_message_is_keepalive (msg) || !priv->reusable) + if (!priv->reusable) soup_connection_disconnect (conn); } @@ -913,12 +916,6 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) g_object_thaw_notify (G_OBJECT (conn)); } -void -soup_connection_set_reusable (SoupConnection *conn) -{ - SOUP_CONNECTION_GET_PRIVATE (conn)->reusable = TRUE; -} - gboolean soup_connection_get_ever_used (SoupConnection *conn) { diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h index ad3a1b13..52e638f5 100644 --- a/libsoup/soup-connection.h +++ b/libsoup/soup-connection.h @@ -76,7 +76,6 @@ gboolean soup_connection_is_tunnelled (SoupConnection *conn); SoupConnectionState soup_connection_get_state (SoupConnection *conn); void soup_connection_set_state (SoupConnection *conn, SoupConnectionState state); -void soup_connection_set_reusable (SoupConnection *conn); gboolean soup_connection_get_ever_used (SoupConnection *conn); diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index e851ac4f..d38d7432 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -659,8 +659,6 @@ io_read (SoupMessage *msg, GCancellable *cancellable, GError **error) case SOUP_MESSAGE_IO_STATE_BODY_DONE: io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; - if (io->item && io->item->conn) - soup_connection_set_reusable (io->item->conn); soup_message_got_body (msg); break; -- cgit v1.2.1 From 6d15cbe99d93a6c6284cc9a571a4aaab52d422b9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 28 Sep 2012 17:44:54 -0400 Subject: SoupConnection: hide a special case Previously SoupConnection required SoupSession to request that the connection's state be changed from IN_USE to IDLE after a CONNECT, even though this would not actually result in the connection's state changing, and even though SoupSession would have broken if the state had changed. Fix this up so that SoupSession can just leave the connection IN_USE in this case, and SoupConnection deals with fixing up its internal state accordingly. --- libsoup/soup-connection.c | 53 ++++++++++++++++++++++++----------------------- libsoup/soup-session.c | 4 +++- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 783ab591..2cdcc308 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -379,19 +379,36 @@ current_msg_got_body (SoupMessage *msg, gpointer user_data) priv->reusable = soup_message_is_keepalive (msg); } +static void +clear_current_msg (SoupConnection *conn) +{ + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); + SoupMessage *msg; + + msg = priv->current_msg; + priv->current_msg = NULL; + + g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (current_msg_got_body), conn); + g_object_unref (msg); +} + static void set_current_msg (SoupConnection *conn, SoupMessage *msg) { SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); - g_return_if_fail (priv->current_msg == NULL); g_return_if_fail (priv->state == SOUP_CONNECTION_IN_USE); g_object_freeze_notify (G_OBJECT (conn)); + if (priv->current_msg) { + g_return_if_fail (priv->current_msg->method == SOUP_METHOD_CONNECT); + clear_current_msg (conn); + } + stop_idle_timer (priv); - priv->current_msg = msg; + priv->current_msg = g_object_ref (msg); priv->reusable = FALSE; g_signal_connect (msg, "got-body", @@ -869,7 +886,6 @@ void soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) { SoupConnectionPrivate *priv; - SoupConnectionState old_state; g_return_if_fail (SOUP_IS_CONNECTION (conn)); g_return_if_fail (state >= SOUP_CONNECTION_NEW && @@ -878,36 +894,20 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state) g_object_freeze_notify (G_OBJECT (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - old_state = priv->state; - - if (old_state == SOUP_CONNECTION_IN_USE) - priv->unused_timeout = 0; if (priv->current_msg) { - SoupMessage *msg; - g_warn_if_fail (state == SOUP_CONNECTION_IDLE || state == SOUP_CONNECTION_DISCONNECTED); - - msg = priv->current_msg; - priv->current_msg = NULL; - - g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (current_msg_got_body), conn); - - if (msg->method == SOUP_METHOD_CONNECT && - SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - if (state == SOUP_CONNECTION_IDLE) - state = SOUP_CONNECTION_IN_USE; - } - - if (!priv->reusable) - soup_connection_disconnect (conn); + clear_current_msg (conn); } - if (priv->state == old_state && priv->state != state) { + if (state == SOUP_CONNECTION_IDLE && !priv->reusable) { + /* This will recursively call set_state() */ + soup_connection_disconnect (conn); + } else { priv->state = state; - if (state == SOUP_CONNECTION_IDLE) + if (priv->state == SOUP_CONNECTION_IDLE) start_idle_timer (conn); g_object_notify (G_OBJECT (conn), "state"); @@ -941,7 +941,8 @@ soup_connection_send_request (SoupConnection *conn, g_return_if_fail (SOUP_IS_CONNECTION (conn)); g_return_if_fail (item != NULL); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - g_return_if_fail (priv->state != SOUP_CONNECTION_NEW && priv->state != SOUP_CONNECTION_DISCONNECTED); + g_return_if_fail (priv->state != SOUP_CONNECTION_NEW && + priv->state != SOUP_CONNECTION_DISCONNECTED); if (item->msg != priv->current_msg) set_current_msg (conn, item->msg); diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 5a3c5f98..fe51a400 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1337,7 +1337,9 @@ soup_session_unqueue_item (SoupSession *session, SoupSessionHost *host; if (item->conn) { - if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_IN_USE) + if ((soup_connection_get_state (item->conn) == SOUP_CONNECTION_IN_USE) && + (item->msg->method != SOUP_METHOD_CONNECT || + !SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code))) soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); soup_message_queue_item_set_connection (item, NULL); } -- cgit v1.2.1 From 6008e4c5fd5e0d3e08d8c82f0d0ffad059d98c06 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 29 Sep 2012 08:56:48 -0400 Subject: SoupSession: move some code from SoupMessageQueue here Move soup_message_queue_item_set_connection() into SoupSession, since connection management is the session's job, not the queue's. Likewise, move the non-queue-item-specific parts of queue_message_restarted() into SoupSession. --- libsoup/soup-message-queue.c | 53 ++++----------------------------------- libsoup/soup-message-queue.h | 2 -- libsoup/soup-session-async.c | 4 +-- libsoup/soup-session-private.h | 3 +++ libsoup/soup-session-sync.c | 6 ++--- libsoup/soup-session.c | 56 +++++++++++++++++++++++++++++++++++++++--- 6 files changed, 65 insertions(+), 59 deletions(-) diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index 9afa31ee..ac00f163 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -67,19 +67,7 @@ queue_message_restarted (SoupMessage *msg, gpointer user_data) item->proxy_uri = NULL; } - if (item->conn && - (!soup_message_is_keepalive (msg) || - SOUP_STATUS_IS_REDIRECTION (msg->status_code))) { - if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_IN_USE) - soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); - soup_message_queue_item_set_connection (item, NULL); - } - - soup_message_cleanup_response (msg); - g_cancellable_reset (item->cancellable); - - item->state = SOUP_MESSAGE_STARTING; } /** @@ -163,6 +151,8 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) return; } + g_warn_if_fail (item->conn == NULL); + /* OK, @item is dead. Rewrite @queue around it */ if (item->prev) item->prev->next = item->next; @@ -181,49 +171,16 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) g_object_unref (item->session); g_object_unref (item->msg); g_object_unref (item->cancellable); - if (item->proxy_addr) - g_object_unref (item->proxy_addr); - if (item->proxy_uri) - soup_uri_free (item->proxy_uri); - if (item->task) - g_object_unref (item->task); + g_clear_object (&item->proxy_addr); + g_clear_pointer (&item->proxy_uri, soup_uri_free); + g_clear_object (&item->task); if (item->io_source) { g_source_destroy (item->io_source); g_source_unref (item->io_source); } - soup_message_queue_item_set_connection (item, NULL); g_slice_free (SoupMessageQueueItem, item); } -static void -proxy_connection_event (SoupConnection *conn, - GSocketClientEvent event, - GIOStream *connection, - gpointer user_data) -{ - SoupMessageQueueItem *item = user_data; - - soup_message_network_event (item->msg, event, connection); -} - -void -soup_message_queue_item_set_connection (SoupMessageQueueItem *item, - SoupConnection *conn) -{ - if (item->conn) { - g_signal_handlers_disconnect_by_func (item->conn, proxy_connection_event, item); - g_object_unref (item->conn); - } - - item->conn = conn; - - if (item->conn) { - g_object_ref (item->conn); - g_signal_connect (item->conn, "event", - G_CALLBACK (proxy_connection_event), item); - } -} - /** * soup_message_queue_lookup: * @queue: a #SoupMessageQueue diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index 627fd2d4..d3341bd7 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -77,8 +77,6 @@ void soup_message_queue_destroy (SoupMessageQueue *queue void soup_message_queue_item_ref (SoupMessageQueueItem *item); void soup_message_queue_item_unref (SoupMessageQueueItem *item); -void soup_message_queue_item_set_connection (SoupMessageQueueItem *item, - SoupConnection *conn); G_END_DECLS diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 57d8617b..87060915 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -128,7 +128,7 @@ ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { soup_connection_disconnect (item->conn); - soup_message_queue_item_set_connection (item, NULL); + soup_session_set_item_connection (session, item, NULL); soup_message_set_status (item->msg, status); } @@ -179,7 +179,7 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) } else if (status != SOUP_STATUS_OK) { soup_session_set_item_status (session, item, status); soup_connection_disconnect (item->conn); - soup_message_queue_item_set_connection (item, NULL); + soup_session_set_item_connection (session, item, NULL); item->state = SOUP_MESSAGE_READY; } else item->state = SOUP_MESSAGE_CONNECTED; diff --git a/libsoup/soup-session-private.h b/libsoup/soup-session-private.h index b5e24e33..297faf57 100644 --- a/libsoup/soup-session-private.h +++ b/libsoup/soup-session-private.h @@ -31,6 +31,9 @@ void soup_session_send_queue_item (SoupSession *s SoupMessageCompletionFn completion_cb); void soup_session_unqueue_item (SoupSession *session, SoupMessageQueueItem *item); +void soup_session_set_item_connection (SoupSession *session, + SoupMessageQueueItem *item, + SoupConnection *conn); void soup_session_set_item_status (SoupSession *session, SoupMessageQueueItem *item, guint status_code); diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index d753f573..c532c974 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -175,7 +175,7 @@ try_again: status = soup_connection_connect_sync (item->conn, item->cancellable); if (status == SOUP_STATUS_TRY_AGAIN) { soup_connection_disconnect (item->conn); - soup_message_queue_item_set_connection (item, NULL); + soup_session_set_item_connection (session, item, NULL); goto try_again; } @@ -186,7 +186,7 @@ try_again: soup_session_set_item_status (session, item, status); item->state = SOUP_MESSAGE_FINISHING; soup_connection_disconnect (item->conn); - soup_message_queue_item_set_connection (item, NULL); + soup_session_set_item_connection (session, item, NULL); return; } @@ -194,7 +194,7 @@ try_again: status = tunnel_connect (session, item); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { soup_connection_disconnect (item->conn); - soup_message_queue_item_set_connection (item, NULL); + soup_session_set_item_connection (session, item, NULL); if (status == SOUP_STATUS_TRY_AGAIN) goto try_again; soup_session_set_item_status (session, item, status); diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index fe51a400..97156885 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1020,6 +1020,22 @@ redirect_handler (SoupMessage *msg, gpointer user_data) soup_session_redirect_message (session, msg); } +static void +message_restarted (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + if (item->conn && + (!soup_message_is_keepalive (msg) || + SOUP_STATUS_IS_REDIRECTION (msg->status_code))) { + if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_IN_USE) + soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); + soup_session_set_item_connection (item->session, item, NULL); + } + + soup_message_cleanup_response (msg); +} + SoupMessageQueueItem * soup_session_append_queue_item (SoupSession *session, SoupMessage *msg, SoupSessionCallback callback, gpointer user_data) @@ -1042,6 +1058,8 @@ soup_session_append_queue_item (SoupSession *session, SoupMessage *msg, msg, "got_body", "Location", G_CALLBACK (redirect_handler), item); } + g_signal_connect (msg, "restarted", + G_CALLBACK (message_restarted), item); g_signal_emit (session, signals[REQUEST_QUEUED], 0, msg); @@ -1214,7 +1232,7 @@ soup_session_make_connect_message (SoupSession *session, soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); item = soup_session_append_queue_item (session, msg, NULL, NULL); - soup_message_queue_item_set_connection (item, conn); + soup_session_set_item_connection (session, item, conn); g_object_unref (msg); item->state = SOUP_MESSAGE_RUNNING; @@ -1254,7 +1272,7 @@ soup_session_get_connection (SoupSession *session, if (!need_new_connection && soup_connection_get_state (conns->data) == SOUP_CONNECTION_IDLE) { soup_connection_set_state (conns->data, SOUP_CONNECTION_IN_USE); g_mutex_unlock (&priv->conn_lock); - soup_message_queue_item_set_connection (item, conns->data); + soup_session_set_item_connection (session, item, conns->data); soup_message_set_https_status (item->msg, item->conn); return TRUE; } else if (soup_connection_get_state (conns->data) == SOUP_CONNECTION_CONNECTING) @@ -1317,7 +1335,7 @@ soup_session_get_connection (SoupSession *session, } g_mutex_unlock (&priv->conn_lock); - soup_message_queue_item_set_connection (item, conn); + soup_session_set_item_connection (session, item, conn); return TRUE; } @@ -1341,7 +1359,7 @@ soup_session_unqueue_item (SoupSession *session, (item->msg->method != SOUP_METHOD_CONNECT || !SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code))) soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); - soup_message_queue_item_set_connection (item, NULL); + soup_session_set_item_connection (session, item, NULL); } if (item->state != SOUP_MESSAGE_FINISHED) { @@ -1366,6 +1384,36 @@ soup_session_unqueue_item (SoupSession *session, soup_message_queue_item_unref (item); } +static void +proxy_connection_event (SoupConnection *conn, + GSocketClientEvent event, + GIOStream *connection, + gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + soup_message_network_event (item->msg, event, connection); +} + +void +soup_session_set_item_connection (SoupSession *session, + SoupMessageQueueItem *item, + SoupConnection *conn) +{ + if (item->conn) { + g_signal_handlers_disconnect_by_func (item->conn, proxy_connection_event, item); + g_object_unref (item->conn); + } + + item->conn = conn; + + if (item->conn) { + g_object_ref (item->conn); + g_signal_connect (item->conn, "event", + G_CALLBACK (proxy_connection_event), item); + } +} + void soup_session_set_item_status (SoupSession *session, SoupMessageQueueItem *item, -- cgit v1.2.1 From 21d707d66460233596a04f6dc99c945d2dbc3085 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 24 Oct 2012 14:04:48 +0200 Subject: SoupConnection: disconnect on failed connections/tunnels Rather than relying on SoupSession to call soup_connection_disconnect() after a connection or tunnel attempt fails, have SoupConnection do it itself. --- libsoup/soup-connection.c | 16 +++++++++++++--- libsoup/soup-session-async.c | 14 ++++++-------- libsoup/soup-session-sync.c | 34 +++++++++++++++------------------- libsoup/soup-session.c | 5 ++--- 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 2cdcc308..34b9b2d1 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -474,6 +474,8 @@ socket_connect_finished (SoupSocket *socket, guint status, gpointer user_data) status = soup_status_proxify (status); data->callback (data->conn, status, data->callback_data); } + if (!SOUP_STATUS_IS_SUCCESSFUL (status) && status != SOUP_STATUS_TRY_AGAIN) + soup_connection_disconnect (data->conn); g_object_unref (data->conn); if (data->cancellable) g_object_unref (data->cancellable); @@ -639,7 +641,6 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) SOUP_SOCKET_CLEAN_DISPOSE, TRUE, NULL); g_object_unref (remote_addr); - event_id = g_signal_connect (priv->socket, "event", G_CALLBACK (proxy_socket_event), conn); status = soup_socket_connect_sync (priv->socket, cancellable); @@ -678,13 +679,15 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; start_idle_timer (conn); - } else { + } else if (status != SOUP_STATUS_TRY_AGAIN) { fail: if (priv->socket) { soup_socket_disconnect (priv->socket); g_object_unref (priv->socket); priv->socket = NULL; } + + soup_connection_disconnect (conn); } if (priv->socket) @@ -718,8 +721,10 @@ soup_connection_start_ssl_sync (SoupConnection *conn, if (!soup_socket_start_proxy_ssl (priv->socket, priv->remote_uri->host, - cancellable)) + cancellable)) { + soup_connection_disconnect (conn); return SOUP_STATUS_SSL_FAILED; + } soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); status = soup_socket_handshake_sync (priv->socket, cancellable); @@ -731,6 +736,9 @@ soup_connection_start_ssl_sync (SoupConnection *conn, status = SOUP_STATUS_TRY_AGAIN; } + if (!SOUP_STATUS_IS_SUCCESSFUL (status) && status != SOUP_STATUS_TRY_AGAIN) + soup_connection_disconnect (conn); + return status; } @@ -749,6 +757,8 @@ start_ssl_completed (SoupSocket *socket, guint status, gpointer user_data) } data->callback (data->conn, status, data->callback_data); + if (!SOUP_STATUS_IS_SUCCESSFUL (status) && status != SOUP_STATUS_TRY_AGAIN) + soup_connection_disconnect (data->conn); g_object_unref (data->conn); g_slice_free (SoupConnectionAsyncConnectData, data); } diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 87060915..d26fbe21 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -127,7 +127,6 @@ ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) soup_message_queue_item_unref (tunnel_item); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - soup_connection_disconnect (item->conn); soup_session_set_item_connection (session, item, NULL); soup_message_set_status (item->msg, status); } @@ -174,13 +173,12 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) SoupMessageQueueItem *item = user_data; SoupSession *session = item->session; - if (item->state != SOUP_MESSAGE_CONNECTING) { - soup_connection_disconnect (conn); - } else if (status != SOUP_STATUS_OK) { - soup_session_set_item_status (session, item, status); - soup_connection_disconnect (item->conn); - soup_session_set_item_connection (session, item, NULL); - item->state = SOUP_MESSAGE_READY; + if (status != SOUP_STATUS_OK) { + if (item->state == SOUP_MESSAGE_CONNECTING) { + soup_session_set_item_status (session, item, status); + soup_session_set_item_connection (session, item, NULL); + item->state = SOUP_MESSAGE_READY; + } } else item->state = SOUP_MESSAGE_CONNECTED; diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index c532c974..43d0a491 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -140,9 +140,6 @@ tunnel_connect (SoupSession *session, SoupMessageQueueItem *related) soup_message_set_https_status (related->msg, conn); } - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) - soup_connection_disconnect (conn); - g_object_unref (conn); return status; } @@ -167,33 +164,32 @@ try_again: try_pruning = FALSE; } - if (soup_connection_get_state (item->conn) != SOUP_CONNECTION_NEW) { + if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_IDLE) { item->state = SOUP_MESSAGE_READY; return; } - status = soup_connection_connect_sync (item->conn, item->cancellable); - if (status == SOUP_STATUS_TRY_AGAIN) { - soup_connection_disconnect (item->conn); - soup_session_set_item_connection (session, item, NULL); - goto try_again; - } + if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_NEW) { + status = soup_connection_connect_sync (item->conn, item->cancellable); + if (status == SOUP_STATUS_TRY_AGAIN) { + soup_session_set_item_connection (session, item, NULL); + goto try_again; + } - soup_message_set_https_status (msg, item->conn); + soup_message_set_https_status (msg, item->conn); - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - if (!msg->status_code) - soup_session_set_item_status (session, item, status); - item->state = SOUP_MESSAGE_FINISHING; - soup_connection_disconnect (item->conn); - soup_session_set_item_connection (session, item, NULL); - return; + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + if (!msg->status_code) + soup_session_set_item_status (session, item, status); + item->state = SOUP_MESSAGE_FINISHING; + soup_session_set_item_connection (session, item, NULL); + return; + } } if (soup_connection_is_tunnelled (item->conn)) { status = tunnel_connect (session, item); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - soup_connection_disconnect (item->conn); soup_session_set_item_connection (session, item, NULL); if (status == SOUP_STATUS_TRY_AGAIN) goto try_again; diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 97156885..b0a98628 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1355,9 +1355,8 @@ soup_session_unqueue_item (SoupSession *session, SoupSessionHost *host; if (item->conn) { - if ((soup_connection_get_state (item->conn) == SOUP_CONNECTION_IN_USE) && - (item->msg->method != SOUP_METHOD_CONNECT || - !SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code))) + if (item->msg->method != SOUP_METHOD_CONNECT || + !SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); soup_session_set_item_connection (session, item, NULL); } -- cgit v1.2.1 From 1fa24555b7b0d1f35f24ec05950f218493cbebc2 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 25 Oct 2012 11:19:37 +0200 Subject: SoupSession: don't disconnect connections outside of conn_lock Always acquire conn_lock before disconnecting IDLE connections, to avoid race conditions. --- libsoup/soup-session.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index b0a98628..f571b9ec 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -96,9 +96,11 @@ typedef struct { guint max_conns, max_conns_per_host; guint io_timeout, idle_timeout; - /* Must hold the conn_lock before potentially creating a - * new SoupSessionHost, or adding/removing a connection. - * Must not emit signals or destroy objects while holding it. + /* Must hold the conn_lock before potentially creating a new + * SoupSessionHost, adding/removing a connection, + * disconnecting a connection, or moving a connection from + * IDLE to IN_USE. Must not emit signals or destroy objects + * while holding it. */ GMutex conn_lock; @@ -117,6 +119,8 @@ static void free_host (SoupSessionHost *host); static void connection_state_changed (GObject *object, GParamSpec *param, gpointer user_data); static void connection_disconnected (SoupConnection *conn, gpointer user_data); +static void drop_connection (SoupSession *session, SoupSessionHost *host, + SoupConnection *conn); static void auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg, SoupAuth *auth, @@ -1121,8 +1125,11 @@ soup_session_cleanup_connections (SoupSession *session, while (g_hash_table_iter_next (&iter, &conn, &host)) { state = soup_connection_get_state (conn); if (state == SOUP_CONNECTION_REMOTE_DISCONNECTED || - (prune_idle && state == SOUP_CONNECTION_IDLE)) + (prune_idle && state == SOUP_CONNECTION_IDLE)) { conns = g_slist_prepend (conns, g_object_ref (conn)); + g_hash_table_iter_remove (&iter); + drop_connection (session, host, conn); + } } g_mutex_unlock (&priv->conn_lock); @@ -1168,17 +1175,15 @@ free_unused_host (gpointer user_data) } static void -connection_disconnected (SoupConnection *conn, gpointer user_data) +drop_connection (SoupSession *session, SoupSessionHost *host, SoupConnection *conn) { - SoupSession *session = user_data; SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - SoupSessionHost *host; - g_mutex_lock (&priv->conn_lock); + /* Note: caller must hold conn_lock, and must remove @conn + * from priv->conns itself. + */ - host = g_hash_table_lookup (priv->conns, conn); if (host) { - g_hash_table_remove (priv->conns, conn); host->connections = g_slist_remove (host->connections, conn); host->num_conns--; @@ -1203,8 +1208,24 @@ connection_disconnected (SoupConnection *conn, gpointer user_data) g_signal_handlers_disconnect_by_func (conn, connection_state_changed, session); priv->num_conns--; - g_mutex_unlock (&priv->conn_lock); g_object_unref (conn); +} + +static void +connection_disconnected (SoupConnection *conn, gpointer user_data) +{ + SoupSession *session = user_data; + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + SoupSessionHost *host; + + g_mutex_lock (&priv->conn_lock); + + host = g_hash_table_lookup (priv->conns, conn); + if (host) + g_hash_table_remove (priv->conns, conn); + drop_connection (session, host, conn); + + g_mutex_unlock (&priv->conn_lock); SOUP_SESSION_GET_CLASS (session)->kick (session); } @@ -1722,8 +1743,11 @@ soup_session_abort (SoupSession *session) g_mutex_lock (&priv->conn_lock); conns = NULL; g_hash_table_iter_init (&iter, priv->conns); - while (g_hash_table_iter_next (&iter, &conn, &host)) + while (g_hash_table_iter_next (&iter, &conn, &host)) { conns = g_slist_prepend (conns, g_object_ref (conn)); + g_hash_table_iter_remove (&iter); + drop_connection (session, host, conn); + } g_mutex_unlock (&priv->conn_lock); for (c = conns; c; c = c->next) { -- cgit v1.2.1 From 99db31881e47b95f5a4f2e4d1150c89aecdb53e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavol=20Kla=C4=8Dansk=C3=BD?= Date: Sun, 4 Nov 2012 20:36:44 +0100 Subject: Updated slovak translation --- po/LINGUAS | 1 + po/sk.po | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 po/sk.po diff --git a/po/LINGUAS b/po/LINGUAS index 3f589158..1de8b47f 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -34,6 +34,7 @@ pt pt_BR ro ru +sk sl sr sr@latin diff --git a/po/sk.po b/po/sk.po new file mode 100644 index 00000000..1ced9bff --- /dev/null +++ b/po/sk.po @@ -0,0 +1,90 @@ +# Slovak translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Pavol Klačanský , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-11-02 19:31+0000\n" +"PO-Revision-Date: 2012-11-03 14:46+0000\n" +"Last-Translator: Dušan Kazik \n" +"Language-Team: Slovak \n" +"Language: sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Pripojenie bolo neočakávane ukončené" + +# PM:seek je aj posunutie zvlášť ked ide o vstupný stream +#: ../libsoup/soup-body-input-stream.c:461 +#, fuzzy +msgid "Invalid seek request" +msgstr "Neplatná požiadavka hľadania" + +# struct +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream sa nedá skrátiť" + +# PM: buffer by som preložil ako schránka +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Výstupná vyrovnávacia pamäť je príliš malá" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "Operácia bola zrušená" + +# PK: tu neviem ako to povedat, malo by ist o to, ze proste ta operacia neni async +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "Operácia by blokovala spracovanie" + +# error +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "Nebol poskytnutý identifikáror URI" + +# first %s - scheme (http, ftp, ...) +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Neplatná schéma „%s“ identifikátora URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Nepodarilo sa analyzovať identifikátor URI „%s“" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Nepodporovaná schéma „%s“ pre identifikátor URI" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Názov hostiteľa je adresa IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Neplatný názov hostiteľa" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Názov hostiteľa neobsahuje základnú doménu" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "Nedostatočný počet domén" -- cgit v1.2.1 From 3026b72d71ec57be4ee565c899b3199ef3f1fa53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavol=20Kla=C4=8Dansk=C3=BD?= Date: Sun, 4 Nov 2012 21:41:09 +0100 Subject: Updated slovak translation --- po/sk.po | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/po/sk.po b/po/sk.po index 1ced9bff..0081c92b 100644 --- a/po/sk.po +++ b/po/sk.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-11-02 19:31+0000\n" -"PO-Revision-Date: 2012-11-03 14:46+0000\n" +"POT-Creation-Date: 2012-11-04 19:36+0000\n" +"PO-Revision-Date: 2012-11-04 20:20+0000\n" "Last-Translator: Dušan Kazik \n" "Language-Team: Slovak \n" "Language: sk\n" @@ -25,11 +25,9 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Pripojenie bolo neočakávane ukončené" -# PM:seek je aj posunutie zvlášť ked ide o vstupný stream #: ../libsoup/soup-body-input-stream.c:461 -#, fuzzy msgid "Invalid seek request" -msgstr "Neplatná požiadavka hľadania" +msgstr "Neplatná požiadavka na posunutie" # struct #: ../libsoup/soup-body-input-stream.c:489 @@ -37,6 +35,7 @@ msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream sa nedá skrátiť" # PM: buffer by som preložil ako schránka +# PK: schranka je clipboard, buffer je jednoznacne vyrovnavacia pamet #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From d10215fcc77e2bace075104b8ef4bc48ad63f5f8 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 5 Nov 2012 12:55:48 -0500 Subject: SoupProxyResolver: remove evil hack Back when I deprecated SoupProxyResolver in favor of SoupProxyURIResolver, I added an evil hack so that if anyone created a SoupProxyResolver implementation, we'd automatically add a SoupProxyURIResolver implementation on top of it (so that SoupSession only needed to worry about SoupProxyURIResolver). Anyway, (a) it's evil, (b) I'm pretty sure no one else ever implemented a SoupProxyResolver anyway, and (c) if they did, they really ought to have migrated to SoupProxyURIResolver by now. So, remove the evil hack so that desrt can drop support for adding interfaces after class_init. https://bugzilla.gnome.org/show_bug.cgi?id=687659 --- libsoup/soup-proxy-resolver.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/libsoup/soup-proxy-resolver.c b/libsoup/soup-proxy-resolver.c index 8092175f..75122787 100644 --- a/libsoup/soup-proxy-resolver.c +++ b/libsoup/soup-proxy-resolver.c @@ -19,40 +19,9 @@ G_DEFINE_INTERFACE_WITH_CODE (SoupProxyResolver, soup_proxy_resolver, G_TYPE_OBJ g_type_interface_add_prerequisite (g_define_type_id, SOUP_TYPE_SESSION_FEATURE); ) -static void -proxy_resolver_interface_check (gpointer func_data, gpointer g_iface) -{ - GTypeInterface *iface = g_iface; - - if (iface->g_type != SOUP_TYPE_PROXY_RESOLVER) - return; - - /* If the class hasn't already declared that it implements - * SoupProxyURIResolver, add our own compat implementation. - */ - if (!g_type_is_a (iface->g_instance_type, SOUP_TYPE_PROXY_URI_RESOLVER)) { - const GInterfaceInfo uri_resolver_interface_info = { - (GInterfaceInitFunc) soup_proxy_resolver_uri_resolver_interface_init, NULL, NULL - }; - g_type_add_interface_static (iface->g_instance_type, - SOUP_TYPE_PROXY_URI_RESOLVER, - &uri_resolver_interface_info); - } -} - - static void soup_proxy_resolver_default_init (SoupProxyResolverInterface *iface) { - /* Add an interface_check where we can kludgily add the - * SoupProxyURIResolver interface to all SoupProxyResolvers. - * (SoupProxyResolver can't just implement - * SoupProxyURIResolver itself because interface types can't - * implement other interfaces.) This is an ugly hack, but it - * only gets used if someone actually creates a - * SoupProxyResolver... - */ - g_type_add_interface_check (NULL, proxy_resolver_interface_check); } void -- cgit v1.2.1 From da70b77bdc45e9d6e3fd3ee76c6fec3fb4e8ba73 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 6 Nov 2012 09:14:55 -0500 Subject: libsoup-2.4.sym: temporarily export soup_message_io_cleanup Temporarily export soup_message_io_cleanup() to unbreak gvfs. Will be reverted once gvfs is fixed. --- libsoup/libsoup-2.4.sym | 1 + 1 file changed, 1 insertion(+) diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 9e2fa1c0..62cb933e 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -263,6 +263,7 @@ soup_message_headers_set_expectations soup_message_headers_set_range soup_message_headers_set_ranges soup_message_headers_type_get_type +soup_message_io_cleanup soup_message_is_keepalive soup_message_new soup_message_new_from_uri -- cgit v1.2.1 From 69c489d590ddeb7d532ddb99943e0990173a8110 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 8 Nov 2012 11:28:39 -0500 Subject: Add per-version deprecation/availability warnings Add SOUP_VERSION_X_XX, SOUP_VERSION_MIN_REQUIRED, and SOUP_VERSION_MAX_ALLOWED, to enable version-based warnings. Tag all functions with appropriate SOUP_AVAILABLE_IN_ and SOUP_DEPRECATED_IN_ macros. Also, fix up some "Since" tags to not refer to unstable releases or non-.0 point releases. --- docs/reference/libsoup-2.4-sections.txt | 14 ++- libsoup/soup-address.h | 5 ++ libsoup/soup-auth.h | 3 + libsoup/soup-cache.h | 8 ++ libsoup/soup-content-decoder.c | 2 +- libsoup/soup-content-decoder.h | 3 +- libsoup/soup-content-sniffer.c | 17 +++- libsoup/soup-content-sniffer.h | 4 + libsoup/soup-cookie-jar-sqlite.h | 2 + libsoup/soup-cookie-jar-text.h | 2 + libsoup/soup-cookie-jar.c | 4 + libsoup/soup-cookie-jar.h | 20 ++++- libsoup/soup-cookie.c | 2 + libsoup/soup-cookie.h | 31 +++++++ libsoup/soup-date.c | 4 + libsoup/soup-date.h | 19 ++++ libsoup/soup-form.h | 2 + libsoup/soup-gnome-features.h | 3 + libsoup/soup-headers.h | 4 + libsoup/soup-logger.h | 8 +- libsoup/soup-message-body.c | 8 +- libsoup/soup-message-body.h | 11 ++- libsoup/soup-message-headers.c | 4 +- libsoup/soup-message-headers.h | 17 +++- libsoup/soup-message.c | 4 +- libsoup/soup-message.h | 6 ++ libsoup/soup-misc.h | 3 +- libsoup/soup-multipart-input-stream.h | 6 ++ libsoup/soup-multipart.h | 9 ++ libsoup/soup-proxy-resolver.c | 101 +++------------------ libsoup/soup-proxy-resolver.h | 3 + libsoup/soup-proxy-uri-resolver.h | 3 + libsoup/soup-request-data.h | 1 + libsoup/soup-request-file.h | 2 + libsoup/soup-request-http.h | 2 + libsoup/soup-request.h | 8 ++ libsoup/soup-requester.h | 5 ++ libsoup/soup-session-feature.h | 6 ++ libsoup/soup-session.c | 52 ++++++----- libsoup/soup-session.h | 12 +++ libsoup/soup-socket.c | 4 +- libsoup/soup-status.h | 3 +- libsoup/soup-tld.h | 5 +- libsoup/soup-types.h | 1 + libsoup/soup-uri.c | 6 +- libsoup/soup-uri.h | 11 +++ libsoup/soup-version.c | 140 +++++++++++++++++++++++++++++ libsoup/soup-version.h.in | 152 ++++++++++++++++++++++++++++++++ 48 files changed, 597 insertions(+), 145 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 4c1c60b6..81f4b77e 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -1210,10 +1210,22 @@ soup_get_major_version soup_get_minor_version soup_get_micro_version soup_check_version - SOUP_MAJOR_VERSION SOUP_MINOR_VERSION SOUP_MICRO_VERSION SOUP_CHECK_VERSION + +SOUP_VERSION_MIN_REQUIRED +SOUP_VERSION_MAX_ALLOWED +SOUP_VERSION_2_24 +SOUP_VERSION_2_26 +SOUP_VERSION_2_28 +SOUP_VERSION_2_30 +SOUP_VERSION_2_32 +SOUP_VERSION_2_34 +SOUP_VERSION_2_36 +SOUP_VERSION_2_38 +SOUP_VERSION_2_40 +SOUP_VERSION_2_42 diff --git a/libsoup/soup-address.h b/libsoup/soup-address.h index 579d1d3c..dd4c275d 100644 --- a/libsoup/soup-address.h +++ b/libsoup/soup-address.h @@ -77,13 +77,18 @@ const char *soup_address_get_physical (SoupAddress *addr); guint soup_address_get_port (SoupAddress *addr); struct sockaddr *soup_address_get_sockaddr (SoupAddress *addr, int *len); +SOUP_AVAILABLE_IN_2_32 GSocketAddress *soup_address_get_gsockaddr (SoupAddress *addr); gboolean soup_address_is_resolved (SoupAddress *addr); +SOUP_AVAILABLE_IN_2_26 guint soup_address_hash_by_name (gconstpointer addr); +SOUP_AVAILABLE_IN_2_26 gboolean soup_address_equal_by_name (gconstpointer addr1, gconstpointer addr2); +SOUP_AVAILABLE_IN_2_26 guint soup_address_hash_by_ip (gconstpointer addr); +SOUP_AVAILABLE_IN_2_26 gboolean soup_address_equal_by_ip (gconstpointer addr1, gconstpointer addr2); diff --git a/libsoup/soup-auth.h b/libsoup/soup-auth.h index 18f11c7b..99510216 100644 --- a/libsoup/soup-auth.h +++ b/libsoup/soup-auth.h @@ -73,9 +73,12 @@ const char *soup_auth_get_realm (SoupAuth *auth); char *soup_auth_get_info (SoupAuth *auth); #ifdef LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY +SOUP_AVAILABLE_IN_2_28 GSList *soup_auth_get_saved_users (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_28 const char *soup_auth_get_saved_password (SoupAuth *auth, const char *user); +SOUP_AVAILABLE_IN_2_28 void soup_auth_save_password (SoupAuth *auth, const char *username, const char *password); diff --git a/libsoup/soup-cache.h b/libsoup/soup-cache.h index 8585d51f..64dcb787 100644 --- a/libsoup/soup-cache.h +++ b/libsoup/soup-cache.h @@ -77,17 +77,25 @@ typedef struct { void (*_libsoup_reserved3)(void); } SoupCacheClass; +SOUP_AVAILABLE_IN_2_34 GType soup_cache_get_type (void); +SOUP_AVAILABLE_IN_2_34 SoupCache *soup_cache_new (const char *cache_dir, SoupCacheType cache_type); +SOUP_AVAILABLE_IN_2_34 void soup_cache_flush (SoupCache *cache); +SOUP_AVAILABLE_IN_2_34 void soup_cache_clear (SoupCache *cache); +SOUP_AVAILABLE_IN_2_34 void soup_cache_dump (SoupCache *cache); +SOUP_AVAILABLE_IN_2_34 void soup_cache_load (SoupCache *cache); +SOUP_AVAILABLE_IN_2_34 void soup_cache_set_max_size (SoupCache *cache, guint max_size); +SOUP_AVAILABLE_IN_2_34 guint soup_cache_get_max_size (SoupCache *cache); G_END_DECLS diff --git a/libsoup/soup-content-decoder.c b/libsoup/soup-content-decoder.c index fa7629af..8aac8a8a 100644 --- a/libsoup/soup-content-decoder.c +++ b/libsoup/soup-content-decoder.c @@ -40,7 +40,7 @@ * will be decoded (and the %SOUP_MESSAGE_CONTENT_DECODED flag will * not be set). * - * Since: 2.28.2 + * Since: 2.30 **/ struct _SoupContentDecoderPrivate { diff --git a/libsoup/soup-content-decoder.h b/libsoup/soup-content-decoder.h index e0b22383..471f8138 100644 --- a/libsoup/soup-content-decoder.h +++ b/libsoup/soup-content-decoder.h @@ -37,7 +37,8 @@ typedef struct { void (*_libsoup_reserved5) (void); } SoupContentDecoderClass; -GType soup_content_decoder_get_type (void); +SOUP_AVAILABLE_IN_2_30 +GType soup_content_decoder_get_type (void); G_END_DECLS diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index 012c0dc0..e8f69d47 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -28,7 +28,7 @@ * content sniffing to a session with soup_session_add_feature() or * soup_session_add_feature_by_type(). * - * Since: 2.27.3 + * Since: 2.28 **/ static void soup_content_sniffer_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); @@ -567,7 +567,7 @@ soup_content_sniffer_session_feature_init (SoupSessionFeatureInterface *feature_ * * Returns: a new #SoupContentSniffer * - * Since: 2.27.3 + * Since: 2.28 **/ SoupContentSniffer * soup_content_sniffer_new () @@ -589,6 +589,8 @@ soup_content_sniffer_new () * * Return value: the sniffed Content-Type of @buffer; this will never be %NULL, * but may be "application/octet-stream". + * + * Since: 2.28 */ char * soup_content_sniffer_sniff (SoupContentSniffer *sniffer, @@ -602,6 +604,17 @@ soup_content_sniffer_sniff (SoupContentSniffer *sniffer, return SOUP_CONTENT_SNIFFER_GET_CLASS (sniffer)->sniff (sniffer, msg, buffer, params); } +/** + * soup_content_sniffer_get_buffer_size: + * @sniffer: a #SoupContentSniffer + * + * Gets the number of bytes @sniffer needs in order to properly sniff + * a buffer. + * + * Return value: the number of bytes to sniff + * + * Since: 2.28 + */ gsize soup_content_sniffer_get_buffer_size (SoupContentSniffer *sniffer) { diff --git a/libsoup/soup-content-sniffer.h b/libsoup/soup-content-sniffer.h index 59c01546..eb1e4bd8 100644 --- a/libsoup/soup-content-sniffer.h +++ b/libsoup/soup-content-sniffer.h @@ -43,14 +43,18 @@ typedef struct { void (*_libsoup_reserved5) (void); } SoupContentSnifferClass; +SOUP_AVAILABLE_IN_2_28 GType soup_content_sniffer_get_type (void); +SOUP_AVAILABLE_IN_2_28 SoupContentSniffer *soup_content_sniffer_new (void); +SOUP_AVAILABLE_IN_2_28 char *soup_content_sniffer_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, SoupBuffer *buffer, GHashTable **params); +SOUP_AVAILABLE_IN_2_28 gsize soup_content_sniffer_get_buffer_size (SoupContentSniffer *sniffer); G_END_DECLS diff --git a/libsoup/soup-cookie-jar-sqlite.h b/libsoup/soup-cookie-jar-sqlite.h index 19dfbfa1..97cdf331 100644 --- a/libsoup/soup-cookie-jar-sqlite.h +++ b/libsoup/soup-cookie-jar-sqlite.h @@ -34,8 +34,10 @@ typedef struct { #define SOUP_COOKIE_JAR_SQLITE_FILENAME "filename" +SOUP_AVAILABLE_IN_2_26 GType soup_cookie_jar_sqlite_get_type (void); +SOUP_AVAILABLE_IN_2_26 SoupCookieJar *soup_cookie_jar_sqlite_new (const char *filename, gboolean read_only); diff --git a/libsoup/soup-cookie-jar-text.h b/libsoup/soup-cookie-jar-text.h index cc186dd1..83b8f280 100644 --- a/libsoup/soup-cookie-jar-text.h +++ b/libsoup/soup-cookie-jar-text.h @@ -34,8 +34,10 @@ typedef struct { #define SOUP_COOKIE_JAR_TEXT_FILENAME "filename" +SOUP_AVAILABLE_IN_2_26 GType soup_cookie_jar_text_get_type (void); +SOUP_AVAILABLE_IN_2_26 SoupCookieJar *soup_cookie_jar_text_new (const char *filename, gboolean read_only); diff --git a/libsoup/soup-cookie-jar.c b/libsoup/soup-cookie-jar.c index 3180680d..80bb8327 100644 --- a/libsoup/soup-cookie-jar.c +++ b/libsoup/soup-cookie-jar.c @@ -241,6 +241,10 @@ soup_cookie_jar_new (void) * This function exists for backward compatibility, but does not do * anything any more; cookie jars are saved automatically when they * are changed. + * + * Since: 2.24 + * + * Deprecated: This is a no-op. */ void soup_cookie_jar_save (SoupCookieJar *jar) diff --git a/libsoup/soup-cookie-jar.h b/libsoup/soup-cookie-jar.h index 7ef05066..395fbe36 100644 --- a/libsoup/soup-cookie-jar.h +++ b/libsoup/soup-cookie-jar.h @@ -47,37 +47,51 @@ typedef enum { SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY } SoupCookieJarAcceptPolicy; +SOUP_AVAILABLE_IN_2_24 GType soup_cookie_jar_get_type (void); +SOUP_AVAILABLE_IN_2_24 SoupCookieJar * soup_cookie_jar_new (void); -#ifndef LIBSOUP_DISABLE_DEPRECATED -void soup_cookie_jar_save (SoupCookieJar *jar); -#endif +SOUP_AVAILABLE_IN_2_24 char * soup_cookie_jar_get_cookies (SoupCookieJar *jar, SoupURI *uri, gboolean for_http); +SOUP_AVAILABLE_IN_2_40 GSList * soup_cookie_jar_get_cookie_list (SoupCookieJar *jar, SoupURI *uri, gboolean for_http); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_jar_set_cookie (SoupCookieJar *jar, SoupURI *uri, const char *cookie); +SOUP_AVAILABLE_IN_2_30 void soup_cookie_jar_set_cookie_with_first_party (SoupCookieJar *jar, SoupURI *uri, SoupURI *first_party, const char *cookie); +SOUP_AVAILABLE_IN_2_26 void soup_cookie_jar_add_cookie (SoupCookieJar *jar, SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_40 void soup_cookie_jar_add_cookie_with_first_party (SoupCookieJar *jar, SoupURI *first_party, SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_26 void soup_cookie_jar_delete_cookie (SoupCookieJar *jar, SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_26 GSList * soup_cookie_jar_all_cookies (SoupCookieJar *jar); +SOUP_AVAILABLE_IN_2_30 void soup_cookie_jar_set_accept_policy (SoupCookieJar *jar, SoupCookieJarAcceptPolicy policy); +SOUP_AVAILABLE_IN_2_30 SoupCookieJarAcceptPolicy soup_cookie_jar_get_accept_policy (SoupCookieJar *jar); +SOUP_AVAILABLE_IN_2_40 gboolean soup_cookie_jar_is_persistent (SoupCookieJar *jar); +SOUP_AVAILABLE_IN_2_24 +SOUP_DEPRECATED_IN_2_26 +void soup_cookie_jar_save (SoupCookieJar *jar); + G_END_DECLS #endif /* SOUP_COOKIE_JAR_H */ diff --git a/libsoup/soup-cookie.c b/libsoup/soup-cookie.c index c553c52e..731a4a5a 100755 --- a/libsoup/soup-cookie.c +++ b/libsoup/soup-cookie.c @@ -1065,6 +1065,8 @@ soup_cookie_applies_to_uri (SoupCookie *cookie, SoupURI *uri) * match. This may change in the future. * * Return value: whether the cookies are equal. + * + * Since: 2.24 */ gboolean soup_cookie_equal (SoupCookie *cookie1, SoupCookie *cookie2) diff --git a/libsoup/soup-cookie.h b/libsoup/soup-cookie.h index 3a3c3886..96242913 100644 --- a/libsoup/soup-cookie.h +++ b/libsoup/soup-cookie.h @@ -20,6 +20,7 @@ struct _SoupCookie { gboolean http_only; }; +SOUP_AVAILABLE_IN_2_24 GType soup_cookie_get_type (void); #define SOUP_TYPE_COOKIE (soup_cookie_get_type()) @@ -28,61 +29,91 @@ GType soup_cookie_get_type (void); #define SOUP_COOKIE_MAX_AGE_ONE_WEEK (SOUP_COOKIE_MAX_AGE_ONE_DAY * 7) #define SOUP_COOKIE_MAX_AGE_ONE_YEAR (SOUP_COOKIE_MAX_AGE_ONE_DAY * 365.2422) +SOUP_AVAILABLE_IN_2_24 SoupCookie *soup_cookie_new (const char *name, const char *value, const char *domain, const char *path, int max_age); +SOUP_AVAILABLE_IN_2_24 SoupCookie *soup_cookie_parse (const char *header, SoupURI *origin); +SOUP_AVAILABLE_IN_2_24 SoupCookie *soup_cookie_copy (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_32 const char *soup_cookie_get_name (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_name (SoupCookie *cookie, const char *name); +SOUP_AVAILABLE_IN_2_32 const char *soup_cookie_get_value (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_value (SoupCookie *cookie, const char *value); +SOUP_AVAILABLE_IN_2_32 const char *soup_cookie_get_domain (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_domain (SoupCookie *cookie, const char *domain); +SOUP_AVAILABLE_IN_2_32 const char *soup_cookie_get_path (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_path (SoupCookie *cookie, const char *path); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_max_age (SoupCookie *cookie, int max_age); +SOUP_AVAILABLE_IN_2_32 SoupDate *soup_cookie_get_expires (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_expires (SoupCookie *cookie, SoupDate *expires); +SOUP_AVAILABLE_IN_2_32 gboolean soup_cookie_get_secure (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_secure (SoupCookie *cookie, gboolean secure); +SOUP_AVAILABLE_IN_2_32 gboolean soup_cookie_get_http_only (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_set_http_only (SoupCookie *cookie, gboolean http_only); +SOUP_AVAILABLE_IN_2_24 char *soup_cookie_to_set_cookie_header (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 char *soup_cookie_to_cookie_header (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 gboolean soup_cookie_applies_to_uri (SoupCookie *cookie, SoupURI *uri); +SOUP_AVAILABLE_IN_2_24 gboolean soup_cookie_equal (SoupCookie *cookie1, SoupCookie *cookie2); +SOUP_AVAILABLE_IN_2_24 void soup_cookie_free (SoupCookie *cookie); +SOUP_AVAILABLE_IN_2_24 GSList *soup_cookies_from_response (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_24 GSList *soup_cookies_from_request (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_24 void soup_cookies_to_response (GSList *cookies, SoupMessage *msg); +SOUP_AVAILABLE_IN_2_24 void soup_cookies_to_request (GSList *cookies, SoupMessage *msg); +SOUP_AVAILABLE_IN_2_24 void soup_cookies_free (GSList *cookies); +SOUP_AVAILABLE_IN_2_24 char *soup_cookies_to_cookie_header (GSList *cookies); +SOUP_AVAILABLE_IN_2_30 gboolean soup_cookie_domain_matches (SoupCookie *cookie, const char *host); diff --git a/libsoup/soup-date.c b/libsoup/soup-date.c index 99730786..16988f41 100644 --- a/libsoup/soup-date.c +++ b/libsoup/soup-date.c @@ -897,6 +897,8 @@ soup_date_get_offset (SoupDate *date) * @date: a #SoupDate * * Copies @date. + * + * Since: 2.24 **/ SoupDate * soup_date_copy (SoupDate *date) @@ -915,6 +917,8 @@ soup_date_copy (SoupDate *date) * @date: a #SoupDate * * Frees @date. + * + * Since: 2.24 **/ void soup_date_free (SoupDate *date) diff --git a/libsoup/soup-date.h b/libsoup/soup-date.h index 09246072..c6414c16 100644 --- a/libsoup/soup-date.h +++ b/libsoup/soup-date.h @@ -35,37 +35,56 @@ typedef enum { SOUP_DATE_ISO8601_XMLRPC } SoupDateFormat; +SOUP_AVAILABLE_IN_2_24 GType soup_date_get_type (void); #define SOUP_TYPE_DATE (soup_date_get_type ()) +SOUP_AVAILABLE_IN_2_24 SoupDate *soup_date_new (int year, int month, int day, int hour, int minute, int second); +SOUP_AVAILABLE_IN_2_24 SoupDate *soup_date_new_from_string (const char *date_string); +SOUP_AVAILABLE_IN_2_24 SoupDate *soup_date_new_from_time_t (time_t when); +SOUP_AVAILABLE_IN_2_24 SoupDate *soup_date_new_from_now (int offset_seconds); +SOUP_AVAILABLE_IN_2_24 char *soup_date_to_string (SoupDate *date, SoupDateFormat format); +SOUP_AVAILABLE_IN_2_24 time_t soup_date_to_time_t (SoupDate *date); +SOUP_AVAILABLE_IN_2_24 void soup_date_to_timeval (SoupDate *date, GTimeVal *time); +SOUP_AVAILABLE_IN_2_24 gboolean soup_date_is_past (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 int soup_date_get_year (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 int soup_date_get_month (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 int soup_date_get_day (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 int soup_date_get_hour (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 int soup_date_get_minute (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 int soup_date_get_second (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 int soup_date_get_utc (SoupDate *date); +SOUP_AVAILABLE_IN_2_32 int soup_date_get_offset (SoupDate *date); +SOUP_AVAILABLE_IN_2_24 SoupDate *soup_date_copy (SoupDate *date); +SOUP_AVAILABLE_IN_2_24 void soup_date_free (SoupDate *date); G_END_DECLS diff --git a/libsoup/soup-form.h b/libsoup/soup-form.h index f2be1bcf..fa080c48 100644 --- a/libsoup/soup-form.h +++ b/libsoup/soup-form.h @@ -15,6 +15,7 @@ G_BEGIN_DECLS #define SOUP_FORM_MIME_TYPE_MULTIPART "multipart/form-data" GHashTable *soup_form_decode (const char *encoded_form); +SOUP_AVAILABLE_IN_2_26 GHashTable *soup_form_decode_multipart (SoupMessage *msg, const char *file_control_name, char **filename, @@ -45,6 +46,7 @@ SoupMessage *soup_form_request_new_from_hash (const char *method, SoupMessage *soup_form_request_new_from_datalist (const char *method, const char *uri, GData **form_data_set); +SOUP_AVAILABLE_IN_2_26 SoupMessage *soup_form_request_new_from_multipart (const char *uri, SoupMultipart *multipart); diff --git a/libsoup/soup-gnome-features.h b/libsoup/soup-gnome-features.h index 84d64597..6e36b0ee 100644 --- a/libsoup/soup-gnome-features.h +++ b/libsoup/soup-gnome-features.h @@ -10,14 +10,17 @@ G_BEGIN_DECLS +SOUP_AVAILABLE_IN_2_26 GType soup_proxy_resolver_gnome_get_type (void); #define SOUP_TYPE_PROXY_RESOLVER_GNOME (soup_proxy_resolver_gnome_get_type ()) +SOUP_AVAILABLE_IN_2_26 GType soup_gnome_features_2_26_get_type (void); #define SOUP_TYPE_GNOME_FEATURES_2_26 (soup_gnome_features_2_26_get_type ()) #ifndef G_OS_WIN32 #ifdef LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY +SOUP_AVAILABLE_IN_2_28 GType soup_password_manager_gnome_get_type (void); #define SOUP_TYPE_PASSWORD_MANAGER_GNOME (soup_password_manager_gnome_get_type ()) #endif /* LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY */ diff --git a/libsoup/soup-headers.h b/libsoup/soup-headers.h index cc542c34..687ea41e 100644 --- a/libsoup/soup-headers.h +++ b/libsoup/soup-headers.h @@ -13,6 +13,7 @@ G_BEGIN_DECLS /* HTTP Header Parsing */ +SOUP_AVAILABLE_IN_2_26 gboolean soup_headers_parse (const char *str, int len, SoupMessageHeaders *dest); @@ -47,12 +48,15 @@ gboolean soup_header_contains (const char *header, const char *token); GHashTable *soup_header_parse_param_list (const char *header); +SOUP_AVAILABLE_IN_2_24 GHashTable *soup_header_parse_semi_param_list (const char *header); void soup_header_free_param_list (GHashTable *param_list); +SOUP_AVAILABLE_IN_2_26 void soup_header_g_string_append_param (GString *string, const char *name, const char *value); +SOUP_AVAILABLE_IN_2_30 void soup_header_g_string_append_param_quoted (GString *string, const char *name, const char *value); diff --git a/libsoup/soup-logger.h b/libsoup/soup-logger.h index 8ada23d0..a33f3fa6 100644 --- a/libsoup/soup-logger.h +++ b/libsoup/soup-logger.h @@ -53,15 +53,13 @@ GType soup_logger_get_type (void); SoupLogger *soup_logger_new (SoupLoggerLogLevel level, int max_body_size); -#ifndef LIBSOUP_DISABLE_DEPRECATED -/* Use soup_session_add/remove_feature */ -G_DEPRECATED_FOR(soup_session_add_feature) + +SOUP_DEPRECATED_IN_2_24_FOR(soup_session_add_feature) void soup_logger_attach (SoupLogger *logger, SoupSession *session); -G_DEPRECATED_FOR(soup_session_remove_feature) +SOUP_DEPRECATED_IN_2_24_FOR(soup_session_remove_feature) void soup_logger_detach (SoupLogger *logger, SoupSession *session); -#endif void soup_logger_set_request_filter (SoupLogger *logger, SoupLoggerFilter request_filter, diff --git a/libsoup/soup-message-body.c b/libsoup/soup-message-body.c index 0868d841..c541887f 100644 --- a/libsoup/soup-message-body.c +++ b/libsoup/soup-message-body.c @@ -415,7 +415,7 @@ soup_message_body_new (void) * be discarded, and you will be responsible for recreating the * request body after the #SoupMessage::restarted signal is emitted. * - * Since: 2.4.1 + * Since: 2.24 **/ void soup_message_body_set_accumulate (SoupMessageBody *body, @@ -435,7 +435,7 @@ soup_message_body_set_accumulate (SoupMessageBody *body, * * Return value: the accumulate flag for @body. * - * Since: 2.4.1 + * Since: 2.24 **/ gboolean soup_message_body_get_accumulate (SoupMessageBody *body) @@ -664,7 +664,7 @@ soup_message_body_get_chunk (SoupMessageBody *body, goffset offset) * This is a low-level method which you should not normally need to * use. * - * Since: 2.4.1 + * Since: 2.24 **/ void soup_message_body_got_chunk (SoupMessageBody *body, SoupBuffer *chunk) @@ -691,7 +691,7 @@ soup_message_body_got_chunk (SoupMessageBody *body, SoupBuffer *chunk) * there are further restrictions on its proper use which are not * documented here. * - * Since: 2.4.1 + * Since: 2.24 **/ void soup_message_body_wrote_chunk (SoupMessageBody *body, SoupBuffer *chunk) diff --git a/libsoup/soup-message-body.h b/libsoup/soup-message-body.h index ee840837..885cfd00 100644 --- a/libsoup/soup-message-body.h +++ b/libsoup/soup-message-body.h @@ -28,6 +28,7 @@ GType soup_buffer_get_type (void); SoupBuffer *soup_buffer_new (SoupMemoryUse use, gconstpointer data, gsize length); +SOUP_AVAILABLE_IN_2_32 SoupBuffer *soup_buffer_new_take (guchar *data, gsize length); SoupBuffer *soup_buffer_new_subbuffer (SoupBuffer *parent, @@ -39,12 +40,15 @@ SoupBuffer *soup_buffer_new_with_owner (gconstpointer data, gpointer owner, GDestroyNotify owner_dnotify); gpointer soup_buffer_get_owner (SoupBuffer *buffer); +SOUP_AVAILABLE_IN_2_32 void soup_buffer_get_data (SoupBuffer *buffer, const guint8 **data, gsize *length); +SOUP_AVAILABLE_IN_2_40 +GBytes *soup_buffer_get_as_bytes (SoupBuffer *buffer); + SoupBuffer *soup_buffer_copy (SoupBuffer *buffer); void soup_buffer_free (SoupBuffer *buffer); -GBytes *soup_buffer_get_as_bytes (SoupBuffer *buffer); typedef struct { const char *data; @@ -56,14 +60,17 @@ GType soup_message_body_get_type (void); SoupMessageBody *soup_message_body_new (void); +SOUP_AVAILABLE_IN_2_24 void soup_message_body_set_accumulate(SoupMessageBody *body, gboolean accumulate); +SOUP_AVAILABLE_IN_2_24 gboolean soup_message_body_get_accumulate(SoupMessageBody *body); void soup_message_body_append (SoupMessageBody *body, SoupMemoryUse use, gconstpointer data, gsize length); +SOUP_AVAILABLE_IN_2_32 void soup_message_body_append_take (SoupMessageBody *body, guchar *data, gsize length); @@ -77,8 +84,10 @@ SoupBuffer *soup_message_body_flatten (SoupMessageBody *body); SoupBuffer *soup_message_body_get_chunk (SoupMessageBody *body, goffset offset); +SOUP_AVAILABLE_IN_2_24 void soup_message_body_got_chunk (SoupMessageBody *body, SoupBuffer *chunk); +SOUP_AVAILABLE_IN_2_24 void soup_message_body_wrote_chunk (SoupMessageBody *body, SoupBuffer *chunk); diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c index 1dd53dda..876db61c 100644 --- a/libsoup/soup-message-headers.c +++ b/libsoup/soup-message-headers.c @@ -300,7 +300,7 @@ soup_message_headers_remove (SoupMessageHeaders *hdrs, const char *name) * * Return value: the header's value or %NULL if not found. * - * Since: 2.26.1 + * Since: 2.28 **/ const char * soup_message_headers_get_one (SoupMessageHeaders *hdrs, const char *name) @@ -338,7 +338,7 @@ soup_message_headers_get_one (SoupMessageHeaders *hdrs, const char *name) * * Return value: the header's value or %NULL if not found. * - * Since: 2.26.1 + * Since: 2.28 **/ const char * soup_message_headers_get_list (SoupMessageHeaders *hdrs, const char *name) diff --git a/libsoup/soup-message-headers.h b/libsoup/soup-message-headers.h index da66f7a9..c6c43d5f 100644 --- a/libsoup/soup-message-headers.h +++ b/libsoup/soup-message-headers.h @@ -33,15 +33,16 @@ void soup_message_headers_remove (SoupMessageHeaders *hdrs, const char *name); void soup_message_headers_clear (SoupMessageHeaders *hdrs); +SOUP_AVAILABLE_IN_2_36 void soup_message_headers_clean_connection_headers (SoupMessageHeaders *hdrs); -#ifndef LIBSOUP_DISABLE_DEPRECATED -G_DEPRECATED_FOR(soup_message_headers_get_one or soup_message_headers_get_list) +SOUP_DEPRECATED_IN_2_28_FOR ("soup_message_headers_get_one or soup_message_headers_get_list") const char *soup_message_headers_get (SoupMessageHeaders *hdrs, const char *name); -#endif +SOUP_AVAILABLE_IN_2_28 const char *soup_message_headers_get_one (SoupMessageHeaders *hdrs, const char *name); +SOUP_AVAILABLE_IN_2_28 const char *soup_message_headers_get_list (SoupMessageHeaders *hdrs, const char *name); @@ -97,38 +98,48 @@ typedef struct { goffset end; } SoupRange; +SOUP_AVAILABLE_IN_2_26 gboolean soup_message_headers_get_ranges (SoupMessageHeaders *hdrs, goffset total_length, SoupRange **ranges, int *length); +SOUP_AVAILABLE_IN_2_26 void soup_message_headers_free_ranges (SoupMessageHeaders *hdrs, SoupRange *ranges); +SOUP_AVAILABLE_IN_2_26 void soup_message_headers_set_ranges (SoupMessageHeaders *hdrs, SoupRange *ranges, int length); +SOUP_AVAILABLE_IN_2_26 void soup_message_headers_set_range (SoupMessageHeaders *hdrs, goffset start, goffset end); +SOUP_AVAILABLE_IN_2_26 gboolean soup_message_headers_get_content_range (SoupMessageHeaders *hdrs, goffset *start, goffset *end, goffset *total_length); +SOUP_AVAILABLE_IN_2_26 void soup_message_headers_set_content_range (SoupMessageHeaders *hdrs, goffset start, goffset end, goffset total_length); +SOUP_AVAILABLE_IN_2_26 const char *soup_message_headers_get_content_type (SoupMessageHeaders *hdrs, GHashTable **params); +SOUP_AVAILABLE_IN_2_26 void soup_message_headers_set_content_type (SoupMessageHeaders *hdrs, const char *content_type, GHashTable *params); +SOUP_AVAILABLE_IN_2_26 gboolean soup_message_headers_get_content_disposition (SoupMessageHeaders *hdrs, char **disposition, GHashTable **params); +SOUP_AVAILABLE_IN_2_26 void soup_message_headers_set_content_disposition (SoupMessageHeaders *hdrs, const char *disposition, GHashTable *params); diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 5ff836f4..445cdff2 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -389,7 +389,7 @@ soup_message_class_init (SoupMessageClass *message_class) * every successful write() call, not only after finishing a * complete "chunk". * - * Since: 2.4.1 + * Since: 2.24 **/ signals[WROTE_BODY_DATA] = g_signal_new ("wrote_body_data", @@ -554,7 +554,7 @@ soup_message_class_init (SoupMessageClass *message_class) * that sniffing could be done is delivered on the first * emission of #SoupMessage::got-chunk. * - * Since: 2.27.3 + * Since: 2.28 **/ signals[CONTENT_SNIFFED] = g_signal_new ("content_sniffed", diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index d74ee131..676de66b 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -105,9 +105,12 @@ gboolean soup_message_is_keepalive (SoupMessage *msg); SoupURI *soup_message_get_uri (SoupMessage *msg); void soup_message_set_uri (SoupMessage *msg, SoupURI *uri); +SOUP_AVAILABLE_IN_2_26 SoupAddress *soup_message_get_address (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_30 SoupURI *soup_message_get_first_party (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_30 void soup_message_set_first_party (SoupMessage *msg, SoupURI *first_party); @@ -128,6 +131,7 @@ void soup_message_set_flags (SoupMessage *msg, SoupMessageFlags soup_message_get_flags (SoupMessage *msg); +SOUP_AVAILABLE_IN_2_34 gboolean soup_message_get_https_status (SoupMessage *msg, GTlsCertificate **certificate, GTlsCertificateFlags *errors); @@ -157,6 +161,7 @@ void soup_message_set_status_full (SoupMessage *msg, guint status_code, const char *reason_phrase); +SOUP_AVAILABLE_IN_2_38 void soup_message_set_redirect (SoupMessage *msg, guint status_code, const char *redirect_uri); @@ -171,6 +176,7 @@ void soup_message_set_chunk_allocator (SoupMessage *msg, gpointer user_data, GDestroyNotify destroy_notify); +SOUP_AVAILABLE_IN_2_28 void soup_message_disable_feature (SoupMessage *msg, GType feature_type); diff --git a/libsoup/soup-misc.h b/libsoup/soup-misc.h index 0807b5f7..534b59d6 100644 --- a/libsoup/soup-misc.h +++ b/libsoup/soup-misc.h @@ -6,7 +6,7 @@ #ifndef SOUP_MISC_H #define SOUP_MISC_H 1 -#include +#include G_BEGIN_DECLS @@ -19,6 +19,7 @@ GSource *soup_add_io_watch (GMainContext *async_context, GSource *soup_add_idle (GMainContext *async_context, GSourceFunc function, gpointer data); +SOUP_AVAILABLE_IN_2_24 GSource *soup_add_completion (GMainContext *async_context, GSourceFunc function, gpointer data); diff --git a/libsoup/soup-multipart-input-stream.h b/libsoup/soup-multipart-input-stream.h index 77f0f817..20cdefdf 100644 --- a/libsoup/soup-multipart-input-stream.h +++ b/libsoup/soup-multipart-input-stream.h @@ -33,25 +33,31 @@ struct _SoupMultipartInputStreamClass { GFilterInputStreamClass parent_class; }; +SOUP_AVAILABLE_IN_2_40 GType soup_multipart_input_stream_get_type (void) G_GNUC_CONST; +SOUP_AVAILABLE_IN_2_40 SoupMultipartInputStream *soup_multipart_input_stream_new (SoupMessage *msg, GInputStream *base_stream); +SOUP_AVAILABLE_IN_2_40 GInputStream *soup_multipart_input_stream_next_part (SoupMultipartInputStream *multipart, GCancellable *cancellable, GError **error); +SOUP_AVAILABLE_IN_2_40 void soup_multipart_input_stream_next_part_async (SoupMultipartInputStream *multipart, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data); +SOUP_AVAILABLE_IN_2_40 GInputStream *soup_multipart_input_stream_next_part_finish (SoupMultipartInputStream *multipart, GAsyncResult *res, GError **error); +SOUP_AVAILABLE_IN_2_40 SoupMessageHeaders *soup_multipart_input_stream_get_headers (SoupMultipartInputStream *multipart); diff --git a/libsoup/soup-multipart.h b/libsoup/soup-multipart.h index cc01eec6..ef2e36c7 100644 --- a/libsoup/soup-multipart.h +++ b/libsoup/soup-multipart.h @@ -17,33 +17,42 @@ typedef struct SoupMultipart SoupMultipart; GType soup_multipart_get_type (void); #define SOUP_TYPE_MULTIPART (soup_multipart_get_type ()) +SOUP_AVAILABLE_IN_2_26 SoupMultipart *soup_multipart_new (const char *mime_type); +SOUP_AVAILABLE_IN_2_26 SoupMultipart *soup_multipart_new_from_message (SoupMessageHeaders *headers, SoupMessageBody *body); +SOUP_AVAILABLE_IN_2_26 int soup_multipart_get_length (SoupMultipart *multipart); +SOUP_AVAILABLE_IN_2_26 gboolean soup_multipart_get_part (SoupMultipart *multipart, int part, SoupMessageHeaders **headers, SoupBuffer **body); +SOUP_AVAILABLE_IN_2_26 void soup_multipart_append_part (SoupMultipart *multipart, SoupMessageHeaders *headers, SoupBuffer *body); +SOUP_AVAILABLE_IN_2_26 void soup_multipart_append_form_string (SoupMultipart *multipart, const char *control_name, const char *data); +SOUP_AVAILABLE_IN_2_26 void soup_multipart_append_form_file (SoupMultipart *multipart, const char *control_name, const char *filename, const char *content_type, SoupBuffer *body); +SOUP_AVAILABLE_IN_2_26 void soup_multipart_to_message (SoupMultipart *multipart, SoupMessageHeaders *dest_headers, SoupMessageBody *dest_body); +SOUP_AVAILABLE_IN_2_26 void soup_multipart_free (SoupMultipart *multipart); G_END_DECLS diff --git a/libsoup/soup-proxy-resolver.c b/libsoup/soup-proxy-resolver.c index 75122787..a84c27ab 100644 --- a/libsoup/soup-proxy-resolver.c +++ b/libsoup/soup-proxy-resolver.c @@ -13,7 +13,6 @@ #include "soup.h" static void soup_proxy_resolver_default_init (SoupProxyResolverInterface *iface); -static void soup_proxy_resolver_uri_resolver_interface_init (SoupProxyURIResolverInterface *uri_resolver_interface); G_DEFINE_INTERFACE_WITH_CODE (SoupProxyResolver, soup_proxy_resolver, G_TYPE_OBJECT, g_type_interface_add_prerequisite (g_define_type_id, SOUP_TYPE_SESSION_FEATURE); @@ -32,10 +31,16 @@ soup_proxy_resolver_get_proxy_async (SoupProxyResolver *proxy_resolver, SoupProxyResolverCallback callback, gpointer user_data) { +#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#endif SOUP_PROXY_RESOLVER_GET_CLASS (proxy_resolver)-> get_proxy_async (proxy_resolver, msg, async_context, cancellable, callback, user_data); +#ifdef G_GNUC_END_IGNORE_DEPRECATIONS +G_GNUC_END_IGNORE_DEPRECATIONS +#endif } guint @@ -44,94 +49,12 @@ soup_proxy_resolver_get_proxy_sync (SoupProxyResolver *proxy_resolver, GCancellable *cancellable, SoupAddress **addr) { +#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#endif return SOUP_PROXY_RESOLVER_GET_CLASS (proxy_resolver)-> get_proxy_sync (proxy_resolver, msg, cancellable, addr); -} - -/* SoupProxyURIResolver implementation */ - -static SoupURI * -uri_from_address (SoupAddress *addr) -{ - SoupURI *proxy_uri; - - proxy_uri = soup_uri_new (NULL); - soup_uri_set_scheme (proxy_uri, SOUP_URI_SCHEME_HTTP); - soup_uri_set_host (proxy_uri, soup_address_get_name (addr)); - soup_uri_set_port (proxy_uri, soup_address_get_port (addr)); - soup_uri_set_path (proxy_uri, ""); - return proxy_uri; -} - -typedef struct { - SoupProxyURIResolverCallback callback; - gpointer user_data; -} ProxyURIResolverAsyncData; - -static void -compat_got_proxy (SoupProxyResolver *proxy_resolver, - SoupMessage *msg, guint status, SoupAddress *proxy_addr, - gpointer user_data) -{ - ProxyURIResolverAsyncData *purad = user_data; - SoupURI *proxy_uri; - - proxy_uri = proxy_addr ? uri_from_address (proxy_addr) : NULL; - purad->callback (SOUP_PROXY_URI_RESOLVER (proxy_resolver), - status, proxy_uri, purad->user_data); - g_object_unref (msg); - if (proxy_uri) - soup_uri_free (proxy_uri); - g_slice_free (ProxyURIResolverAsyncData, purad); -} - -static void -compat_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_resolver, - SoupURI *uri, GMainContext *async_context, - GCancellable *cancellable, - SoupProxyURIResolverCallback callback, - gpointer user_data) -{ - SoupMessage *dummy_msg; - ProxyURIResolverAsyncData *purad; - - dummy_msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri); - - purad = g_slice_new (ProxyURIResolverAsyncData); - purad->callback = callback; - purad->user_data = user_data; - - soup_proxy_resolver_get_proxy_async ( - SOUP_PROXY_RESOLVER (proxy_uri_resolver), dummy_msg, - async_context, cancellable, - compat_got_proxy, purad); -} - -static guint -compat_get_proxy_uri_sync (SoupProxyURIResolver *proxy_uri_resolver, - SoupURI *uri, GCancellable *cancellable, - SoupURI **proxy_uri) -{ - SoupMessage *dummy_msg; - SoupAddress *proxy_addr = NULL; - guint status; - - dummy_msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri); - status = soup_proxy_resolver_get_proxy_sync ( - SOUP_PROXY_RESOLVER (proxy_uri_resolver), dummy_msg, - cancellable, &proxy_addr); - g_object_unref (dummy_msg); - if (!proxy_addr) - return status; - - *proxy_uri = uri_from_address (proxy_addr); - g_object_unref (proxy_addr); - return status; -} - -static void -soup_proxy_resolver_uri_resolver_interface_init (SoupProxyURIResolverInterface *uri_resolver_interface) -{ - uri_resolver_interface->get_proxy_uri_async = compat_get_proxy_uri_async; - uri_resolver_interface->get_proxy_uri_sync = compat_get_proxy_uri_sync; +#ifdef G_GNUC_END_IGNORE_DEPRECATIONS +G_GNUC_END_IGNORE_DEPRECATIONS +#endif } diff --git a/libsoup/soup-proxy-resolver.h b/libsoup/soup-proxy-resolver.h index dd787143..f5933d9e 100644 --- a/libsoup/soup-proxy-resolver.h +++ b/libsoup/soup-proxy-resolver.h @@ -39,14 +39,17 @@ typedef struct { } SoupProxyResolverInterface; +SOUP_DEPRECATED_IN_2_28_FOR(SoupProxyURIResolver) GType soup_proxy_resolver_get_type (void); +SOUP_DEPRECATED_IN_2_28 void soup_proxy_resolver_get_proxy_async (SoupProxyResolver *proxy_resolver, SoupMessage *msg, GMainContext *async_context, GCancellable *cancellable, SoupProxyResolverCallback callback, gpointer user_data); +SOUP_DEPRECATED_IN_2_28 guint soup_proxy_resolver_get_proxy_sync (SoupProxyResolver *proxy_resolver, SoupMessage *msg, GCancellable *cancellable, diff --git a/libsoup/soup-proxy-uri-resolver.h b/libsoup/soup-proxy-uri-resolver.h index 1d15b8de..95c118fe 100644 --- a/libsoup/soup-proxy-uri-resolver.h +++ b/libsoup/soup-proxy-uri-resolver.h @@ -43,14 +43,17 @@ typedef struct { void (*_libsoup_reserved4) (void); } SoupProxyURIResolverInterface; +SOUP_AVAILABLE_IN_2_28 GType soup_proxy_uri_resolver_get_type (void); +SOUP_AVAILABLE_IN_2_28 void soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_resolver, SoupURI *uri, GMainContext *async_context, GCancellable *cancellable, SoupProxyURIResolverCallback callback, gpointer user_data); +SOUP_AVAILABLE_IN_2_28 guint soup_proxy_uri_resolver_get_proxy_uri_sync (SoupProxyURIResolver *proxy_uri_resolver, SoupURI *uri, GCancellable *cancellable, diff --git a/libsoup/soup-request-data.h b/libsoup/soup-request-data.h index aeb95995..f750b048 100644 --- a/libsoup/soup-request-data.h +++ b/libsoup/soup-request-data.h @@ -47,6 +47,7 @@ typedef struct { SoupRequestClass parent; } SoupRequestDataClass; +SOUP_AVAILABLE_IN_2_34 GType soup_request_data_get_type (void); G_END_DECLS diff --git a/libsoup/soup-request-file.h b/libsoup/soup-request-file.h index acb1a085..e86c5978 100644 --- a/libsoup/soup-request-file.h +++ b/libsoup/soup-request-file.h @@ -47,8 +47,10 @@ typedef struct { SoupRequestClass parent; } SoupRequestFileClass; +SOUP_AVAILABLE_IN_2_34 GType soup_request_file_get_type (void); +SOUP_AVAILABLE_IN_2_34 GFile *soup_request_file_get_file (SoupRequestFile *file); G_END_DECLS diff --git a/libsoup/soup-request-http.h b/libsoup/soup-request-http.h index 6402646c..750005af 100644 --- a/libsoup/soup-request-http.h +++ b/libsoup/soup-request-http.h @@ -47,8 +47,10 @@ typedef struct { SoupRequestClass parent; } SoupRequestHTTPClass; +SOUP_AVAILABLE_IN_2_34 GType soup_request_http_get_type (void); +SOUP_AVAILABLE_IN_2_34 SoupMessage *soup_request_http_get_message (SoupRequestHTTP *http); G_END_DECLS diff --git a/libsoup/soup-request.h b/libsoup/soup-request.h index a48e9174..bc6cdffe 100644 --- a/libsoup/soup-request.h +++ b/libsoup/soup-request.h @@ -71,26 +71,34 @@ struct _SoupRequestClass { const char * (*get_content_type) (SoupRequest *request); }; +SOUP_AVAILABLE_IN_2_34 GType soup_request_get_type (void); #define SOUP_REQUEST_URI "uri" #define SOUP_REQUEST_SESSION "session" +SOUP_AVAILABLE_IN_2_34 GInputStream *soup_request_send (SoupRequest *request, GCancellable *cancellable, GError **error); +SOUP_AVAILABLE_IN_2_34 void soup_request_send_async (SoupRequest *request, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); +SOUP_AVAILABLE_IN_2_34 GInputStream *soup_request_send_finish (SoupRequest *request, GAsyncResult *result, GError **error); +SOUP_AVAILABLE_IN_2_34 SoupURI *soup_request_get_uri (SoupRequest *request); +SOUP_AVAILABLE_IN_2_34 SoupSession *soup_request_get_session (SoupRequest *request); +SOUP_AVAILABLE_IN_2_34 goffset soup_request_get_content_length (SoupRequest *request); +SOUP_AVAILABLE_IN_2_34 const char *soup_request_get_content_type (SoupRequest *request); G_END_DECLS diff --git a/libsoup/soup-requester.h b/libsoup/soup-requester.h index a10f1e55..3bf249c8 100644 --- a/libsoup/soup-requester.h +++ b/libsoup/soup-requester.h @@ -48,18 +48,23 @@ typedef struct { GObjectClass parent_class; } SoupRequesterClass; +SOUP_AVAILABLE_IN_2_34 GType soup_requester_get_type (void); +SOUP_AVAILABLE_IN_2_34 SoupRequester *soup_requester_new (void); +SOUP_AVAILABLE_IN_2_34 SoupRequest *soup_requester_request (SoupRequester *requester, const char *uri_string, GError **error); +SOUP_AVAILABLE_IN_2_34 SoupRequest *soup_requester_request_uri (SoupRequester *requester, SoupURI *uri, GError **error); +SOUP_AVAILABLE_IN_2_34 GQuark soup_requester_error_quark (void); #define SOUP_REQUESTER_ERROR soup_requester_error_quark () diff --git a/libsoup/soup-session-feature.h b/libsoup/soup-session-feature.h index aa64aa0f..962c8e11 100644 --- a/libsoup/soup-session-feature.h +++ b/libsoup/soup-session-feature.h @@ -46,17 +46,23 @@ typedef struct { } SoupSessionFeatureInterface; +SOUP_AVAILABLE_IN_2_24 GType soup_session_feature_get_type (void); +SOUP_AVAILABLE_IN_2_24 void soup_session_feature_attach (SoupSessionFeature *feature, SoupSession *session); +SOUP_AVAILABLE_IN_2_24 void soup_session_feature_detach (SoupSessionFeature *feature, SoupSession *session); +SOUP_AVAILABLE_IN_2_34 gboolean soup_session_feature_add_feature (SoupSessionFeature *feature, GType type); +SOUP_AVAILABLE_IN_2_34 gboolean soup_session_feature_remove_feature (SoupSessionFeature *feature, GType type); +SOUP_AVAILABLE_IN_2_34 gboolean soup_session_feature_has_feature (SoupSessionFeature *feature, GType type); diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index f571b9ec..3eecd06b 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -476,7 +476,13 @@ soup_session_set_property (GObject *object, guint prop_id, uri = g_value_get_boxed (value); if (uri) { +#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#endif soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER); +#ifdef G_GNUC_END_IGNORE_DEPRECATIONS +G_GNUC_END_IGNORE_DEPRECATIONS +#endif feature = SOUP_SESSION_FEATURE (soup_proxy_resolver_static_new (uri)); soup_session_add_feature (session, feature); g_object_unref (feature); @@ -1781,23 +1787,23 @@ prefetch_uri (SoupSession *session, SoupURI *uri, } /** -* soup_session_prepare_for_uri: -* @session: a #SoupSession -* @uri: a #SoupURI which may be required -* -* Tells @session that @uri may be requested shortly, and so the -* session can try to prepare (resolving the domain name, obtaining -* proxy address, etc.) in order to work more quickly once the URI is -* actually requested. -* -* This method acts asynchronously, in @session's -* #SoupSession:async_context. If you are using #SoupSessionSync and do -* not have a main loop running, then you can't use this method. -* -* Since: 2.30 -* -* Deprecated: 2.38: use soup_session_prefetch_dns() instead -**/ + * soup_session_prepare_for_uri: + * @session: a #SoupSession + * @uri: a #SoupURI which may be required + * + * Tells @session that @uri may be requested shortly, and so the + * session can try to prepare (resolving the domain name, obtaining + * proxy address, etc.) in order to work more quickly once the URI is + * actually requested. + * + * This method acts asynchronously, in @session's + * #SoupSession:async_context. If you are using #SoupSessionSync and do + * not have a main loop running, then you can't use this method. + * + * Since: 2.30 + * + * Deprecated: 2.38: use soup_session_prefetch_dns() instead + **/ void soup_session_prepare_for_uri (SoupSession *session, SoupURI *uri) { @@ -2151,7 +2157,7 @@ soup_session_class_init (SoupSessionClass *session_class) * #SoupMessage::finished (and all of the other #SoupMessage * signals) may be invoked multiple times for a given message. * - * Since: 2.4.1 + * Since: 2.24 **/ signals[REQUEST_QUEUED] = g_signal_new ("request-queued", @@ -2194,7 +2200,7 @@ soup_session_class_init (SoupSessionClass *session_class) * #SoupSession::request_queued for a detailed description of the * message lifecycle within a session. * - * Since: 2.4.1 + * Since: 2.24 **/ signals[REQUEST_UNQUEUED] = g_signal_new ("request-unqueued", @@ -2347,7 +2353,7 @@ soup_session_class_init (SoupSessionClass *session_class) * if you want to ensure that all future connections will have * this timeout value. * - * Since: 2.4.1 + * Since: 2.24 **/ /** * SOUP_SESSION_IDLE_TIMEOUT: @@ -2355,7 +2361,7 @@ soup_session_class_init (SoupSessionClass *session_class) * Alias for the #SoupSession:idle-timeout property. (The idle * connection lifetime.) * - * Since: 2.4.1 + * Since: 2.24 **/ g_object_class_install_property ( object_class, PROP_IDLE_TIMEOUT, @@ -2384,7 +2390,7 @@ soup_session_class_init (SoupSessionClass *session_class) "Use NTLM", "Whether or not to use NTLM authentication", FALSE, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | G_PARAM_DEPRECATED)); /** * SoupSession:ssl-ca-file: * @@ -2408,7 +2414,7 @@ soup_session_class_init (SoupSessionClass *session_class) "SSL CA file", "File containing SSL CA certificates", NULL, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | G_PARAM_DEPRECATED)); /** * SOUP_SESSION_USE_SYSTEM_CA_FILE: * diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index 8748a764..4dd79ffd 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -103,32 +103,44 @@ void soup_session_cancel_message (SoupSession *session, guint status_code); void soup_session_abort (SoupSession *session); +SOUP_AVAILABLE_IN_2_30 +SOUP_DEPRECATED_IN_2_38_FOR (soup_session_prefetch_dns) void soup_session_prepare_for_uri (SoupSession *session, SoupURI *uri); +SOUP_AVAILABLE_IN_2_38 void soup_session_prefetch_dns (SoupSession *session, const char *hostname, GCancellable *cancellable, SoupAddressCallback callback, gpointer user_data); +SOUP_AVAILABLE_IN_2_38 gboolean soup_session_would_redirect (SoupSession *session, SoupMessage *msg); +SOUP_AVAILABLE_IN_2_38 gboolean soup_session_redirect_message (SoupSession *session, SoupMessage *msg); +SOUP_AVAILABLE_IN_2_24 void soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature); +SOUP_AVAILABLE_IN_2_24 void soup_session_add_feature_by_type (SoupSession *session, GType feature_type); +SOUP_AVAILABLE_IN_2_24 void soup_session_remove_feature (SoupSession *session, SoupSessionFeature *feature); +SOUP_AVAILABLE_IN_2_24 void soup_session_remove_feature_by_type (SoupSession *session, GType feature_type); +SOUP_AVAILABLE_IN_2_26 GSList *soup_session_get_features (SoupSession *session, GType feature_type); +SOUP_AVAILABLE_IN_2_26 SoupSessionFeature *soup_session_get_feature (SoupSession *session, GType feature_type); +SOUP_AVAILABLE_IN_2_28 SoupSessionFeature *soup_session_get_feature_for_message(SoupSession *session, GType feature_type, SoupMessage *msg); diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index a9d6bd58..cd4bf761 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -544,14 +544,14 @@ soup_socket_class_init (SoupSocketClass *socket_class) * Alias for the #SoupSocket:use-thread-context property. (Use * g_main_context_get_thread_default()) * - * Since: 2.36.1 + * Since: 2.38 */ /** * SoupSocket:use-thread-context: * * Use g_main_context_get_thread_default(). * - * Since: 2.36.1 + * Since: 2.38 */ g_object_class_install_property ( object_class, PROP_USE_THREAD_CONTEXT, diff --git a/libsoup/soup-status.h b/libsoup/soup-status.h index fc8d5a36..669c1224 100644 --- a/libsoup/soup-status.h +++ b/libsoup/soup-status.h @@ -8,7 +8,7 @@ #ifndef SOUP_STATUS_H #define SOUP_STATUS_H 1 -#include +#include G_BEGIN_DECLS @@ -94,6 +94,7 @@ typedef enum { } SoupKnownStatusCode; const char *soup_status_get_phrase (guint status_code); +SOUP_AVAILABLE_IN_2_26 guint soup_status_proxify (guint status_code); #define SOUP_HTTP_ERROR soup_http_error_quark() diff --git a/libsoup/soup-tld.h b/libsoup/soup-tld.h index 38de46a6..4b099a26 100644 --- a/libsoup/soup-tld.h +++ b/libsoup/soup-tld.h @@ -10,14 +10,17 @@ G_BEGIN_DECLS +SOUP_AVAILABLE_IN_2_40 const char *soup_tld_get_base_domain (const char *hostname, GError **error); +SOUP_AVAILABLE_IN_2_40 gboolean soup_tld_domain_is_public_suffix (const char *domain); /* Errors */ -#define SOUP_TLD_ERROR soup_tld_error_quark() +SOUP_AVAILABLE_IN_2_40 GQuark soup_tld_error_quark (void); +#define SOUP_TLD_ERROR soup_tld_error_quark() typedef enum { SOUP_TLD_ERROR_INVALID_HOSTNAME, diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h index d0220399..77e5425b 100644 --- a/libsoup/soup-types.h +++ b/libsoup/soup-types.h @@ -8,6 +8,7 @@ #include +#include #include G_BEGIN_DECLS diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index d19290b0..709d3ad3 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -1163,7 +1163,7 @@ soup_uri_set_fragment (SoupURI *uri, const char *fragment) * * Return value: the new #SoupURI * - * Since: 2.26.3 + * Since: 2.28 **/ SoupURI * soup_uri_copy_host (SoupURI *uri) @@ -1190,7 +1190,7 @@ soup_uri_copy_host (SoupURI *uri) * * Return value: a hash * - * Since: 2.26.3 + * Since: 2.28 **/ guint soup_uri_host_hash (gconstpointer key) @@ -1214,7 +1214,7 @@ soup_uri_host_hash (gconstpointer key) * Return value: whether or not the URIs are equal in scheme, host, * and port. * - * Since: 2.26.3 + * Since: 2.28 **/ gboolean soup_uri_host_equal (gconstpointer v1, gconstpointer v2) diff --git a/libsoup/soup-uri.h b/libsoup/soup-uri.h index e2195b16..fca97f76 100644 --- a/libsoup/soup-uri.h +++ b/libsoup/soup-uri.h @@ -63,24 +63,31 @@ char *soup_uri_normalize (const char *part, gboolean soup_uri_uses_default_port (SoupURI *uri); +SOUP_AVAILABLE_IN_2_32 const char *soup_uri_get_scheme (SoupURI *uri); void soup_uri_set_scheme (SoupURI *uri, const char *scheme); +SOUP_AVAILABLE_IN_2_32 const char *soup_uri_get_user (SoupURI *uri); void soup_uri_set_user (SoupURI *uri, const char *user); +SOUP_AVAILABLE_IN_2_32 const char *soup_uri_get_password (SoupURI *uri); void soup_uri_set_password (SoupURI *uri, const char *password); +SOUP_AVAILABLE_IN_2_32 const char *soup_uri_get_host (SoupURI *uri); void soup_uri_set_host (SoupURI *uri, const char *host); +SOUP_AVAILABLE_IN_2_32 guint soup_uri_get_port (SoupURI *uri); void soup_uri_set_port (SoupURI *uri, guint port); +SOUP_AVAILABLE_IN_2_32 const char *soup_uri_get_path (SoupURI *uri); void soup_uri_set_path (SoupURI *uri, const char *path); +SOUP_AVAILABLE_IN_2_32 const char *soup_uri_get_query (SoupURI *uri); void soup_uri_set_query (SoupURI *uri, const char *query); @@ -89,12 +96,16 @@ void soup_uri_set_query_from_form (SoupURI *uri, void soup_uri_set_query_from_fields (SoupURI *uri, const char *first_field, ...) G_GNUC_NULL_TERMINATED; +SOUP_AVAILABLE_IN_2_32 const char *soup_uri_get_fragment (SoupURI *uri); void soup_uri_set_fragment (SoupURI *uri, const char *fragment); +SOUP_AVAILABLE_IN_2_28 SoupURI *soup_uri_copy_host (SoupURI *uri); +SOUP_AVAILABLE_IN_2_28 guint soup_uri_host_hash (gconstpointer key); +SOUP_AVAILABLE_IN_2_28 gboolean soup_uri_host_equal (gconstpointer v1, gconstpointer v2); diff --git a/libsoup/soup-version.c b/libsoup/soup-version.c index e2ed0bfa..84c146eb 100644 --- a/libsoup/soup-version.c +++ b/libsoup/soup-version.c @@ -144,3 +144,143 @@ soup_check_version (guint major, { return SOUP_CHECK_VERSION (major, minor, micro); } + +/** + * SOUP_VERSION_MIN_REQUIRED: + * + * A macro that should be defined by the user prior to including + * libsoup.h. The definition should be one of the predefined libsoup + * version macros: %SOUP_VERSION_2_24, %SOUP_VERSION_2_26, ... + * + * This macro defines the earliest version of libsoup that the package + * is required to be able to compile against. + * + * If the compiler is configured to warn about the use of deprecated + * functions, then using functions that were deprecated in version + * %SOUP_VERSION_MIN_REQUIRED or earlier will cause warnings (but + * using functions deprecated in later releases will not). + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_MAX_ALLOWED: + * + * A macro that should be defined by the user prior to including + * libsoup.h. The definition should be one of the predefined libsoup + * version macros: %SOUP_VERSION_2_24, %SOUP_VERSION_2_26, ... + * + * This macro defines the latest version of the libsoup API that the + * package is allowed to make use of. + * + * If the compiler is configured to warn about the use of deprecated + * functions, then using functions added after version + * %SOUP_VERSION_MAX_ALLOWED will cause warnings. + * + * Unless you are using SOUP_CHECK_VERSION() or the like to compile + * different code depending on the libsoup version, then this should be + * set to the same value as %SOUP_VERSION_MIN_REQUIRED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_24: + * + * A macro that evaluates to the 2.24 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_26: + * + * A macro that evaluates to the 2.26 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_28: + * + * A macro that evaluates to the 2.28 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_30: + * + * A macro that evaluates to the 2.30 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_32: + * + * A macro that evaluates to the 2.32 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_34: + * + * A macro that evaluates to the 2.34 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_36: + * + * A macro that evaluates to the 2.36 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_38: + * + * A macro that evaluates to the 2.38 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_40: + * + * A macro that evaluates to the 2.40 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + +/** + * SOUP_VERSION_2_42: + * + * A macro that evaluates to the 2.42 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.42 + */ + diff --git a/libsoup/soup-version.h.in b/libsoup/soup-version.h.in index 96bb3021..f873aa1c 100644 --- a/libsoup/soup-version.h.in +++ b/libsoup/soup-version.h.in @@ -32,6 +32,158 @@ gboolean soup_check_version (guint major, guint minor, guint micro); +/* Deprecation / Availability macros */ + +#define SOUP_ENCODE_VERSION(major,minor) ((major) << 16 | (minor) << 8) + +#define SOUP_VERSION_2_24 (SOUP_ENCODE_VERSION (2, 24)) +#define SOUP_VERSION_2_26 (SOUP_ENCODE_VERSION (2, 26)) +#define SOUP_VERSION_2_28 (SOUP_ENCODE_VERSION (2, 28)) +#define SOUP_VERSION_2_30 (SOUP_ENCODE_VERSION (2, 30)) +#define SOUP_VERSION_2_32 (SOUP_ENCODE_VERSION (2, 32)) +#define SOUP_VERSION_2_34 (SOUP_ENCODE_VERSION (2, 34)) +#define SOUP_VERSION_2_36 (SOUP_ENCODE_VERSION (2, 36)) +#define SOUP_VERSION_2_38 (SOUP_ENCODE_VERSION (2, 38)) +#define SOUP_VERSION_2_40 (SOUP_ENCODE_VERSION (2, 40)) +#define SOUP_VERSION_2_42 (SOUP_ENCODE_VERSION (2, 42)) + +/* evaluates to the current stable version; for development cycles, + * this means the next stable target + */ +#if (SOUP_MINOR_VERSION % 2) +#define SOUP_VERSION_CUR_STABLE (SOUP_ENCODE_VERSION (SOUP_MAJOR_VERSION, SOUP_MINOR_VERSION + 1)) +#else +#define SOUP_VERSION_CUR_STABLE (SOUP_ENCODE_VERSION (SOUP_MAJOR_VERSION, SOUP_MINOR_VERSION)) +#endif + +/* evaluates to the previous stable version */ +#if (SOUP_MINOR_VERSION % 2) +#define SOUP_VERSION_PREV_STABLE (SOUP_ENCODE_VERSION (SOUP_MAJOR_VERSION, SOUP_MINOR_VERSION - 1)) +#else +#define SOUP_VERSION_PREV_STABLE (SOUP_ENCODE_VERSION (SOUP_MAJOR_VERSION, SOUP_MINOR_VERSION - 2)) +#endif + +#ifndef SOUP_VERSION_MIN_REQUIRED +# define SOUP_VERSION_MIN_REQUIRED (SOUP_VERSION_CUR_STABLE) +#elif SOUP_VERSION_MIN_REQUIRED == 0 +# undef SOUP_VERSION_MIN_REQUIRED +# define SOUP_VERSION_MIN_REQUIRED (SOUP_VERSION_CUR_STABLE + 2) +#endif + +#if !defined (SOUP_VERSION_MAX_ALLOWED) || (SOUP_VERSION_MAX_ALLOWED == 0) +# undef SOUP_VERSION_MAX_ALLOWED +# define SOUP_VERSION_MAX_ALLOWED (SOUP_VERSION_CUR_STABLE) +#endif + +/* sanity checks */ +#if SOUP_VERSION_MIN_REQUIRED > SOUP_VERSION_CUR_STABLE +#error "SOUP_VERSION_MIN_REQUIRED must be <= SOUP_VERSION_CUR_STABLE" +#endif +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_MIN_REQUIRED +#error "SOUP_VERSION_MAX_ALLOWED must be >= SOUP_VERSION_MIN_REQUIRED" +#endif +#if SOUP_VERSION_MIN_REQUIRED < SOUP_VERSION_2_24 +#error "SOUP_VERSION_MIN_REQUIRED must be >= SOUP_VERSION_2_24" +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_24 +# define SOUP_DEPRECATED_IN_2_24 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_24_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_24 +# define SOUP_DEPRECATED_IN_2_24_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_24 +# define SOUP_AVAILABLE_IN_2_24 GLIB_UNAVAILABLE(2, 24) +#else +# define SOUP_AVAILABLE_IN_2_24 +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_26 +# define SOUP_DEPRECATED_IN_2_26 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_26_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_26 +# define SOUP_DEPRECATED_IN_2_26_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_26 +# define SOUP_AVAILABLE_IN_2_26 GLIB_UNAVAILABLE(2, 26) +#else +# define SOUP_AVAILABLE_IN_2_26 +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_28 +# define SOUP_DEPRECATED_IN_2_28 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_28_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_28 +# define SOUP_DEPRECATED_IN_2_28_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_28 +# define SOUP_AVAILABLE_IN_2_28 GLIB_UNAVAILABLE(2, 28) +#else +# define SOUP_AVAILABLE_IN_2_28 +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_30 +# define SOUP_DEPRECATED_IN_2_30 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_30_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_30 +# define SOUP_DEPRECATED_IN_2_30_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_30 +# define SOUP_AVAILABLE_IN_2_30 GLIB_UNAVAILABLE(2, 30) +#else +# define SOUP_AVAILABLE_IN_2_30 +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_32 +# define SOUP_DEPRECATED_IN_2_32 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_32_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_32 +# define SOUP_DEPRECATED_IN_2_32_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_32 +# define SOUP_AVAILABLE_IN_2_32 GLIB_UNAVAILABLE(2, 32) +#else +# define SOUP_AVAILABLE_IN_2_32 +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_34 +# define SOUP_DEPRECATED_IN_2_34 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_34_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_34 +# define SOUP_DEPRECATED_IN_2_34_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_34 +# define SOUP_AVAILABLE_IN_2_34 GLIB_UNAVAILABLE(2, 34) +#else +# define SOUP_AVAILABLE_IN_2_34 +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_36 +# define SOUP_DEPRECATED_IN_2_36 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_36_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_36 +# define SOUP_DEPRECATED_IN_2_36_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_36 +# define SOUP_AVAILABLE_IN_2_36 GLIB_UNAVAILABLE(2, 36) +#else +# define SOUP_AVAILABLE_IN_2_36 +#endif + G_END_DECLS #endif /* SOUP_VERSION_H */ -- cgit v1.2.1 From 2ce20f15379594edc07f1109bcd7b12a326acfbd Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 10 Nov 2012 12:13:42 -0500 Subject: build: fix I'd previously applied a fix to soup-version.h rather than soup-version.h.in, causing it to compile fine for me, but not from a clean checkout. --- libsoup/soup-version.h.in | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libsoup/soup-version.h.in b/libsoup/soup-version.h.in index f873aa1c..4466a481 100644 --- a/libsoup/soup-version.h.in +++ b/libsoup/soup-version.h.in @@ -184,6 +184,48 @@ gboolean soup_check_version (guint major, # define SOUP_AVAILABLE_IN_2_36 #endif +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_38 +# define SOUP_DEPRECATED_IN_2_38 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_38_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_38 +# define SOUP_DEPRECATED_IN_2_38_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_38 +# define SOUP_AVAILABLE_IN_2_38 GLIB_UNAVAILABLE(2, 38) +#else +# define SOUP_AVAILABLE_IN_2_38 +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_40 +# define SOUP_DEPRECATED_IN_2_40 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_40_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_40 +# define SOUP_DEPRECATED_IN_2_40_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_40 +# define SOUP_AVAILABLE_IN_2_40 GLIB_UNAVAILABLE(2, 40) +#else +# define SOUP_AVAILABLE_IN_2_40 +#endif + +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_42 +# define SOUP_DEPRECATED_IN_2_42 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_42_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_42 +# define SOUP_DEPRECATED_IN_2_42_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_42 +# define SOUP_AVAILABLE_IN_2_42 GLIB_UNAVAILABLE(2, 42) +#else +# define SOUP_AVAILABLE_IN_2_42 +#endif + G_END_DECLS #endif /* SOUP_VERSION_H */ -- cgit v1.2.1 From 8e3ce27feebbee0b11e22384ad23d5fec2c99ed2 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 10 Nov 2012 13:46:53 -0500 Subject: build: distcheck fixes, including one generic srcdir!=builddir fix --- docs/reference/Makefile.am | 11 +++++++---- libsoup/Makefile.am | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index f21e710e..add7be83 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -32,13 +32,16 @@ CFILE_GLOB= IGNORE_HFILES= soup.h soup-marshal.h soup-enum-types.h \ soup-message-private.h soup-session-private.h \ soup-auth-basic.h soup-auth-digest.h soup-auth-ntlm.h \ - soup-connection.h soup-connection-ntlm.h \ - soup-dns.h soup-auth-manager.h soup-auth-manager-ntlm.h \ - soup-message-queue.h soup-path-map.h soup-ssl.h \ + soup-connection.h soup-auth-manager.h soup-auth-manager-ntlm.h \ + soup-message-queue.h soup-path-map.h \ soup-proxy-resolver.h soup-proxy-resolver-gnome.h \ soup-proxy-resolver-static.h soup-directory-input-stream.h \ soup-http-input-stream.h soup-password-manager.h \ - soup-password-manager-gnome.h + soup-password-manager-gnome.h soup-converter-wrapper.h \ + soup-body-input-stream.h soup-body-output-stream.h \ + soup-client-input-stream.h soup-content-processor.h \ + soup-content-sniffer-stream.h soup-io-stream.h \ + soup-filter-input-stream.h # Images to copy into HTML directory. HTML_IMAGES = diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 98f0b4b0..31267a37 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -12,6 +12,7 @@ INCLUDES = \ -DG_LOG_DOMAIN=\"libsoup\" \ -DLOCALEDIR=\"$(localedir)\" \ -I$(top_srcdir) \ + -I$(top_builddir) \ $(SOUP_DEBUG_FLAGS) \ $(SOUP_MAINTAINER_FLAGS) \ $(GLIB_CFLAGS) \ @@ -82,6 +83,8 @@ libsoup_2_4_la_LDFLAGS = \ -no-undefined \ -export-symbols $(srcdir)/libsoup-2.4.sym +EXTRA_DIST += libsoup-2.4.sym + libsoup_2_4_la_LIBADD = \ $(GLIB_LIBS) \ $(XML_LIBS) \ @@ -213,6 +216,8 @@ libsoup_gnome_2_4_la_LDFLAGS = \ -no-undefined \ -export-symbols $(srcdir)/libsoup-gnome-2.4.sym +EXTRA_DIST += libsoup-gnome-2.4.sym + libsoup_gnome_2_4_la_LIBADD = \ libsoup-2.4.la \ $(GLIB_LIBS) \ -- cgit v1.2.1 From f605541916587bac0888203a4ccff0173dec5835 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 10 Nov 2012 19:36:04 -0500 Subject: configure.ac: add some missing quotes to fix error messages when apache wasn't installed --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 4a8df37e..48ff4011 100644 --- a/configure.ac +++ b/configure.ac @@ -289,9 +289,9 @@ else MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES mod_ssl" fi fi -AM_CONDITIONAL(HAVE_APACHE, test $have_apache = 1) -AM_CONDITIONAL(HAVE_APACHE_2_2, test $apache_version = 2.2) -AM_CONDITIONAL(HAVE_APACHE_2_4, test $apache_version = 2.4) +AM_CONDITIONAL(HAVE_APACHE, test "$have_apache" = 1) +AM_CONDITIONAL(HAVE_APACHE_2_2, test "$apache_version" = 2.2) +AM_CONDITIONAL(HAVE_APACHE_2_4, test "$apache_version" = 2.4) if test "$have_apache" = 1; then AC_CHECK_PROGS(PHP, php php5) -- cgit v1.2.1 From b2c900e20590c2fce99c4c37920fd2962dd0b955 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Thu, 15 Nov 2012 08:58:15 +0100 Subject: Crash in lookup_resolved(), g_error_free() The problem is that g_task_return_error() "eats" the error, it doesn't create its own copy, thus, in this case, copy the error. https://bugzilla.gnome.org/show_bug.cgi?id=688330 --- libsoup/soup-address.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index 521ff76f..82beb1ea 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -1116,7 +1116,7 @@ got_addresses (SoupAddress *addr, guint status, gpointer user_data) error = g_object_get_data (G_OBJECT (addr), "async-resolved-error"); if (error) - g_task_return_error (task, error); + g_task_return_error (task, g_error_copy (error)); else { GSocketAddress *addr; -- cgit v1.2.1 From 2d58084816390a61d384bfc150e5383dabdf7448 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 17 Nov 2012 11:35:24 -0500 Subject: soup-message-client-io: add a Host header to HTTP/1.0 messages too per recommendation of the httpbis spec --- libsoup/soup-message-client-io.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c index 7c623681..06fe5cc6 100644 --- a/libsoup/soup-message-client-io.c +++ b/libsoup/soup-message-client-io.c @@ -97,20 +97,17 @@ get_request_headers (SoupMessage *req, GString *header, } } - if (priv->http_version == SOUP_HTTP_1_0) { - g_string_append_printf (header, "%s %s HTTP/1.0\r\n", - req->method, uri_string); - } else { - g_string_append_printf (header, "%s %s HTTP/1.1\r\n", - req->method, uri_string); - if (!soup_message_headers_get_one (req->request_headers, "Host")) { - if (soup_uri_uses_default_port (uri)) { - g_string_append_printf (header, "Host: %s\r\n", - uri_host); - } else { - g_string_append_printf (header, "Host: %s:%d\r\n", - uri_host, uri->port); - } + g_string_append_printf (header, "%s %s HTTP/1.%d\r\n", + req->method, uri_string, + (priv->http_version == SOUP_HTTP_1_0) ? 0 : 1); + + if (!soup_message_headers_get_one (req->request_headers, "Host")) { + if (soup_uri_uses_default_port (uri)) { + g_string_append_printf (header, "Host: %s\r\n", + uri_host); + } else { + g_string_append_printf (header, "Host: %s:%d\r\n", + uri_host, uri->port); } } g_free (uri_string); -- cgit v1.2.1 From d51d1d2b513439798024cf9474a2ed4f00f4c2d3 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 17 Nov 2012 11:36:00 -0500 Subject: SoupLogger: fix printing of Host header with IPv6 literal SoupLogger was misprinting Host headers with IPv6 literals (even though soup-message-client-io was sending them correctly). Fix that. Also includes an addition to misc-test to verify that the Host header received by the server is correct (which it already was, but the SoupLogger bug made me think it wasn't.) --- libsoup/soup-logger.c | 14 +++++++++++++- tests/misc-test.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-logger.c b/libsoup/soup-logger.c index 3183cced..a9f49bfb 100644 --- a/libsoup/soup-logger.c +++ b/libsoup/soup-logger.c @@ -481,10 +481,22 @@ print_request (SoupLogger *logger, SoupMessage *msg, return; if (!soup_message_headers_get_one (msg->request_headers, "Host")) { + char *uri_host; + + if (strchr (uri->host, ':')) + uri_host = g_strdup_printf ("[%s]", uri->host); + else if (g_hostname_is_non_ascii (uri->host)) + uri_host = g_hostname_to_ascii (uri->host); + else + uri_host = uri->host; + soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>', - "Host: %s%c%u", uri->host, + "Host: %s%c%u", uri_host, soup_uri_uses_default_port (uri) ? '\0' : ':', uri->port); + + if (uri_host != uri->host) + g_free (uri_host); } soup_message_headers_iter_init (&iter, msg->request_headers); while (soup_message_headers_iter_next (&iter, &name, &value)) { diff --git a/tests/misc-test.c b/tests/misc-test.c index 19e9ba09..b564f269 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -1087,6 +1087,34 @@ do_dot_dot_test (void) soup_test_session_abort_unref (session); } +static void +ipv6_server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + const char *host; + char expected_host[128]; + + host = soup_message_headers_get_one (msg->request_headers, "Host"); + if (!host) { + debug_printf (1, " request has no Host header!\n"); + errors++; + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + + g_snprintf (expected_host, sizeof (expected_host), + "[::1]:%d", soup_server_get_port (server)); + + if (strcmp (host, expected_host) == 0) + soup_message_set_status (msg, SOUP_STATUS_OK); + else { + debug_printf (1, " request has incorrect Host header '%s'\n", host); + errors++; + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + } +} + static void do_ipv6_test (void) { @@ -1103,7 +1131,7 @@ do_ipv6_test (void) ipv6_server = soup_server_new (SOUP_SERVER_INTERFACE, ipv6_addr, NULL); g_object_unref (ipv6_addr); - soup_server_add_handler (ipv6_server, NULL, server_callback, NULL, NULL); + soup_server_add_handler (ipv6_server, NULL, ipv6_server_callback, NULL, NULL); soup_server_run_async (ipv6_server); ipv6_uri = soup_uri_new ("http://[::1]/"); -- cgit v1.2.1 From 244b72793d358711df84bc3f678ca62c5744dfe4 Mon Sep 17 00:00:00 2001 From: Gheyret Kenji Date: Sun, 11 Nov 2012 19:57:22 +0900 Subject: Uyghur translation added. --- po/LINGUAS | 1 + po/ug.po | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 po/ug.po diff --git a/po/LINGUAS b/po/LINGUAS index 1de8b47f..926107c6 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -43,6 +43,7 @@ ta te th tr +ug uk uz@cyrillic vi diff --git a/po/ug.po b/po/ug.po new file mode 100644 index 00000000..c10bbc5c --- /dev/null +++ b/po/ug.po @@ -0,0 +1,80 @@ +# Uyghur translation for libsoup. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Gheyret Kenji , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-11-04 20:02+0000\n" +"PO-Revision-Date: 2011-11-09 16:10+0900\n" +"Last-Translator: Gheyret Kenji \n" +"Language-Team: Uyghur Computer Science Association \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "ئىناۋەتسىز ئىزدەش ئىلتىماسى" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "چىقىرىش يىغلەكى بەك كىچىك" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "مەشغۇلات بىكار قىلىندى" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "مەشغۇلات توسۇلىدۇ" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "URI تەمىنلەنمىدى" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "ئىناۋەتسىز ‹%s› URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI «%s» نى تەھلىل قىلالمىدى" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "كومپيۇتېر ئاتى دېگەن بىر دانە IP ئادرېستۇر" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "باش ماشىنا ئاتى ئىناۋەتسىز" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "" -- cgit v1.2.1 From 1c878e36caa1c0abfefb0a52346dc93dcf5ee44e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 19 Nov 2012 17:12:45 -0500 Subject: 2.41.2 --- NEWS | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 070111b7..98f6e05b 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,62 @@ +Changes in libsoup from 2.41.1 to 2.41.2: + + * libsoup-2.4.so and libsoup-gnome-2.4.so now only export the + symbols that are part of the public API. (Plus, temporarily, + one additional symbol, soup_message_io_cleanup, which is + used by gvfs and possibly a few other modules, even though + it shouldn't be. If you copied soup-input-stream.c from + gvfs, you should port your code to use SoupRequest instead.) + [Dan, #595176] + + * Added SOUP_VERSION_MIN_REQUIRED / SOUP_VERSION_MAX_ALLOWED + macros like the corresponding glib ones, to allow libsoup + users to request per-version deprecation/availability + warnings. [Dan] + + * Fixed a crash caused by a race condition in SoupSessionSync, + and reorganized some code to avoid other possible similar + race conditions. [#684238, Dan] + + * Fixed a crash when a DNS resolution failed, caused by a bug + in the GTask porting in 2.41.1. [#688330, Milan Crha] + + * Fixed a problem that would cause g_warning()s in epiphany + when browsing sites that (incorrectly) returned empty + Cache-Control headers. [#683433, Dan] + + * We now add a Host header to HTTP/1.0 requests as well as + HTTP/1.1 ones. [Dan] + + * Fixed a bug in the printing of IPv6 address literals in the + Host header in SoupLogger. (They were being sent across the + wire correctly, they were just printed wrong by SoupLogger.) + [Dan] + + * Belatedly added soup-multipart-input-stream.h to soup.h. + [Dan] + + * Removed an evil hack in the long-deprecated + SoupProxyResolver code (not to be confused with + SoupProxyURIResolver), to avoid warnings with glib master. + If you had previously implemented a custom + SoupProxyResolver, then it will probably (silently) stop + working, but you should have ported it to + SoupProxyURIResolver years ago anyway... [Dan, #687659] + + * Fixed a few race conditions in the test programs that could + cause "make check" to fail on slow or heavily-loaded + machines. [Dan] + + * Further cleaned up and reorganized the internal HTTP I/O + codepaths, in preparation for an improved SoupCache. + [#682112, Sergio] (This change should not actually be + externally noticeable. But if SoupContentDecoder or + SoupContentSniffer turns out to be broken in this release, + this would be why). + + * New/updated translations: + Slovak, Uyghur + Changes in libsoup from 2.40.1 to 2.41.1: * Changed the behavior of NTLM authentication to be more like diff --git a/configure.ac b/configure.ac index 48ff4011..ccabae47 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [1]) +m4_define([soup_micro_version], [2]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From c6a1a3956394494c60d875934a2924971e5cf582 Mon Sep 17 00:00:00 2001 From: Takayuki KUSANO Date: Wed, 28 Nov 2012 21:31:19 +0900 Subject: [l10n] Update Japanese translation --- po/ja.po | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/po/ja.po b/po/ja.po index 1f254006..795fa84a 100644 --- a/po/ja.po +++ b/po/ja.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-26 05:59+0000\n" -"PO-Revision-Date: 2012-08-27 21:40+0900\n" +"POT-Creation-Date: 2012-11-02 19:31+0000\n" +"PO-Revision-Date: 2012-10-12 13:30+0900\n" "Last-Translator: Takayuki KUSANO \n" "Language-Team: Japanese \n" "Language: ja\n" @@ -16,22 +16,30 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "接続が突然切断されました" +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "無効な seek 要求" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream は truncate できません" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "出力バッファーが小さすぎます" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "動作が中止されました" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "動作はブロックします" -- cgit v1.2.1 From e573d4fc26ce1c80187f8d6254661878439d215d Mon Sep 17 00:00:00 2001 From: ManojKumar Giri Date: Mon, 3 Dec 2012 17:00:20 +0530 Subject: Updated Odia Translation with FUEL implementation. --- po/or.po | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 po/or.po diff --git a/po/or.po b/po/or.po new file mode 100644 index 00000000..e8e13d65 --- /dev/null +++ b/po/or.po @@ -0,0 +1,83 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Manoj Kumar Giri , 2012. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-11-12 21:50+0000\n" +"PO-Revision-Date: 2012-12-03 14:43+0530\n" +"Last-Translator: Manoj Kumar Giri \n" +"Language-Team: Oriya \n" +"Language: or\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "ସଂଯୋଗଟି ଅପ୍ରତ୍ୟାଶିତ ଭାବରେ ବନ୍ଦ ହୋଇଛି" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "ଅବୈଧ ଅନୁସନ୍ଧାନ ଅନୁରୋଧ" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr " SoupBodyInputStream କୁ ବିଚ୍ଛିନ୍ନ କରିହେବ ନାହିଁ " + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "ଫଳାଫଳ ବଫରଟି ଅତି ଛୋଟ ଅଟେ" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "ପ୍ରୟୋଗକୁ ବାତିଲ କରାଯାଇଛି" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "ପ୍ରୟୋଗଟି ବନ୍ଦ ହୋଇପାରେ" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "କୌଣସି URI ଦିଆଯାଇ ନାହିଁ" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "ଅବୈଧ '%s' URI: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "URI '%s'କୁ ବିଶ୍ଳେଷଣ କରିପାରିଲା ନାହିଁ" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ଅସମର୍ଥିତ URI ଯୋଜନା '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "ହୋଷ୍ଟନାମଟି ଏକ IP ଠିକଣା ଅଟେ" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "ଅବୈଧ ହୋଷ୍ଟ ନାମ" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "ହୋଷ୍ଟ ନାମରେ କୌଣସି ମୂଳ ଡମେନ ନଥାଏ" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "ଯଥେଷ୍ଟ ଡମେନ ନାହିଁ" + -- cgit v1.2.1 From 9457c058330b394c7e531479c368bcacb998a01d Mon Sep 17 00:00:00 2001 From: ManojKumar Giri Date: Mon, 3 Dec 2012 17:01:39 +0530 Subject: Added Odia Language into the List. --- po/LINGUAS | 1 + 1 file changed, 1 insertion(+) diff --git a/po/LINGUAS b/po/LINGUAS index 926107c6..194b99bc 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -28,6 +28,7 @@ lv ml mr nb +or pa pl pt -- cgit v1.2.1 From 3f716d732b8473ffbb68daf192958dbe1702aa39 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 4 Dec 2012 11:41:29 -0500 Subject: tests/simple-httpd: use GMappedFile rather than mmap (fixing a fd leak in the process) --- configure.ac | 1 - tests/simple-httpd.c | 57 +++++++++++----------------------------------------- 2 files changed, 12 insertions(+), 46 deletions(-) diff --git a/configure.ac b/configure.ac index ccabae47..2ef8cb85 100644 --- a/configure.ac +++ b/configure.ac @@ -127,7 +127,6 @@ dnl ******************* dnl *** Misc checks *** dnl ******************* AC_CHECK_FUNCS(gmtime_r) -AC_CHECK_FUNCS(mmap) AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket)) dnl ********************* diff --git a/tests/simple-httpd.c b/tests/simple-httpd.c index 0f240ca8..75b7cd4a 100644 --- a/tests/simple-httpd.c +++ b/tests/simple-httpd.c @@ -15,25 +15,6 @@ #include #endif -#ifdef HAVE_MMAP -#include -#endif - -#ifdef HAVE_MMAP -struct mapping { - void *start; - size_t length; -}; - -static void -free_mapping (gpointer data) -{ - struct mapping *mapping = data; - munmap (mapping->start, mapping->length); - g_slice_free (struct mapping, mapping); -} -#endif - static int compare_strings (gconstpointer a, gconstpointer b) { @@ -91,7 +72,6 @@ do_get (SoupServer *server, SoupMessage *msg, const char *path) { char *slash; struct stat st; - int fd; if (stat (path, &st) == -1) { if (errno == EPERM) @@ -134,40 +114,27 @@ do_get (SoupServer *server, SoupMessage *msg, const char *path) return; } - fd = open (path, O_RDONLY); - if (fd == -1) { - soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - if (msg->method == SOUP_METHOD_GET) { -#ifdef HAVE_MMAP - struct mapping *mapping = g_slice_new (struct mapping); + GMappedFile *mapping; SoupBuffer *buffer; - mapping->start = mmap (NULL, st.st_size, PROT_READ, - MAP_PRIVATE, fd, 0); - mapping->length = st.st_size; - buffer = soup_buffer_new_with_owner (mapping->start, - mapping->length, - mapping, free_mapping); + mapping = g_mapped_file_new (path, FALSE, NULL); + if (!mapping) { + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + buffer = soup_buffer_new_with_owner (g_mapped_file_get_contents (mapping), + g_mapped_file_get_length (mapping), + mapping, (GDestroyNotify)g_mapped_file_unref); soup_message_body_append_buffer (msg->response_body, buffer); soup_buffer_free (buffer); -#else - char *buf; - - buf = g_malloc (st.st_size); - read (fd, buf, st.st_size); - close (fd); - soup_message_body_append (msg->response_body, SOUP_MEMORY_TAKE, - buf, st.st_size); -#endif } else /* msg->method == SOUP_METHOD_HEAD */ { char *length; /* We could just use the same code for both GET and - * HEAD. But we'll optimize and avoid the extra - * malloc. + * HEAD (soup-message-server-io.c will fix things up). + * But we'll optimize and avoid the extra I/O. */ length = g_strdup_printf ("%lu", (gulong)st.st_size); soup_message_headers_append (msg->response_headers, -- cgit v1.2.1 From fb840471fd06dd52fbf9f656204561028682264c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 4 Dec 2012 11:44:02 -0500 Subject: tests: fix a few bugs Fix a few places where the test might crash rather than reporting an error when something went wrong. --- tests/continue-test.c | 2 +- tests/header-parsing.c | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/continue-test.c b/tests/continue-test.c index fa9ef809..7cc9f692 100644 --- a/tests/continue-test.c +++ b/tests/continue-test.c @@ -106,10 +106,10 @@ do_message (const char *path, gboolean long_body, while ((expected_event = va_arg (ap, const char *))) { if (!events) { - actual_event = g_strdup (""); debug_printf (1, " Expected '%s', got end of list\n", expected_event); errors++; + continue; } else { actual_event = events->data; if (strcmp (expected_event, actual_event) != 0) { diff --git a/tests/header-parsing.c b/tests/header-parsing.c index e57d7d83..5b2950fc 100644 --- a/tests/header-parsing.c +++ b/tests/header-parsing.c @@ -732,7 +732,7 @@ check_headers (Header *headers, SoupMessageHeaders *hdrs) break; } value = soup_message_headers_get_list (hdrs, headers[i].name); - if (strcmp (value, headers[i].value) != 0) { + if (!value || strcmp (value, headers[i].value) != 0) { ok = FALSE; break; } @@ -981,11 +981,12 @@ do_content_disposition_tests (void) g_hash_table_destroy (params); header = soup_message_headers_get_one (hdrs, "Content-Disposition"); - if (!strcmp (header, RFC5987_TEST_HEADER_ENCODED)) + if (!g_strcmp0 (header, RFC5987_TEST_HEADER_ENCODED)) debug_printf (1, " encoded OK\n"); else { debug_printf (1, " encoding FAILED!\n expected: %s\n got: %s\n", - RFC5987_TEST_HEADER_ENCODED, header); + RFC5987_TEST_HEADER_ENCODED, + header ? header : "(none)"); errors++; } @@ -1117,11 +1118,12 @@ do_content_type_tests (void) g_hash_table_destroy (params); header = soup_message_headers_get_one (hdrs, "Content-Type"); - if (!strcmp (header, CONTENT_TYPE_TEST_HEADER)) + if (!g_strcmp0 (header, CONTENT_TYPE_TEST_HEADER)) debug_printf (1, " encoded OK\n"); else { debug_printf (1, " encoding FAILED!\n expected: %s\n got: %s\n", - CONTENT_TYPE_TEST_HEADER, header); + CONTENT_TYPE_TEST_HEADER, + header ? header : "(none)"); errors++; } -- cgit v1.2.1 From 160021d315e1df7d6523283d83d1e6052fa1b1f7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 4 Dec 2012 11:44:53 -0500 Subject: soup-tld: fix a return-if-fail check --- libsoup/soup-tld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-tld.c b/libsoup/soup-tld.c index 8782a82c..5fdb44a0 100644 --- a/libsoup/soup-tld.c +++ b/libsoup/soup-tld.c @@ -106,7 +106,7 @@ soup_tld_domain_is_public_suffix (const char *domain) g_return_val_if_fail (domain, FALSE); /* Skip the leading '.' if present */ - if (*domain == '.' && !(++domain)) + if (*domain == '.' && !*(++domain)) g_return_val_if_reached (FALSE); base_domain = soup_tld_get_base_domain_internal (domain, 0, &error); -- cgit v1.2.1 From f9816e366e53004618abcee1741885b69e9466a8 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 4 Dec 2012 17:48:45 -0800 Subject: Better handle the failure of URI embedded credentials When using credentials embedded in the URI, clear them so that a failure will trigger the authentication signal and the use of previously remembered credentials. --- libsoup/soup-auth-manager.c | 7 ++++--- tests/auth-test.c | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index b3ef9f65..2a2030cb 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -411,9 +411,10 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, /* If a password is specified explicitly in the URI, use it * even if the auth had previously already been authenticated. */ - if (uri->password) { - if (!prior_auth_failed) - soup_auth_authenticate (auth, uri->user, uri->password); + if (uri->password && uri->user) { + soup_auth_authenticate (auth, uri->user, uri->password); + soup_uri_set_password (uri, NULL); + soup_uri_set_user (uri, NULL); } else if (!soup_auth_is_authenticated (auth) && can_interact) { soup_auth_manager_emit_authenticate (manager, msg, auth, prior_auth_failed); diff --git a/tests/auth-test.c b/tests/auth-test.c index 85c4d414..334033b3 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -146,7 +146,10 @@ static SoupAuthTest main_tests[] = { "Digest/realm1/not/", "1", FALSE, /* should not be used */ "1", SOUP_STATUS_UNAUTHORIZED }, { "Make sure we've forgotten it", - "Digest/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED } + "Digest/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }, + + { "Fail with URI-embedded password, then use right password in the authenticate signal", + "Basic/realm3/", "43", TRUE, "43", SOUP_STATUS_OK } }; static const char *auths[] = { -- cgit v1.2.1 From 66650e5c52a59e1c57e5b932f2dbbc3c415973d7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 9 Dec 2012 10:31:08 +0100 Subject: tests/uri-parsing: check empty username/password Make sure that zero-length username/password are recognized as different from no username/password. --- tests/uri-parsing.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index 08274a28..166a6d87 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -120,6 +120,11 @@ static struct { { "HTTP:////////////////", "http:////////////////", { "http", NULL, NULL, "", 80, "//////////////", NULL, NULL } }, + + { "http://@host", "http://@host/", + { "http", "", NULL, "host", 80, "/", NULL, NULL } }, + { "http://:@host", "http://@host/", + { "http", "", "", "host", 80, "/", NULL, NULL } }, }; static int num_abs_tests = G_N_ELEMENTS(abs_tests); -- cgit v1.2.1 From d84102c84064d1f855598fcf3fa30db36a0eb973 Mon Sep 17 00:00:00 2001 From: Shankar Prasad Date: Mon, 10 Dec 2012 15:50:11 +0530 Subject: Added and Updated Kannada Translations --- po/LINGUAS | 1 + po/kn.po | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 po/kn.po diff --git a/po/LINGUAS b/po/LINGUAS index 194b99bc..35c4f992 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -22,6 +22,7 @@ hu id it ja +kn ko lt lv diff --git a/po/kn.po b/po/kn.po new file mode 100644 index 00000000..8d2e7118 --- /dev/null +++ b/po/kn.po @@ -0,0 +1,83 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Shankar Prasad , 2012. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-12-03 11:35+0000\n" +"PO-Revision-Date: 2012-12-10 15:49+0530\n" +"Last-Translator: Shankar Prasad \n" +"Language-Team: Kannada \n" +"Language: kn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.5\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "ಸಂಪರ್ಕವು ಅನಿರೀಕ್ಷಿತವಾಗಿ ಕೊನೆಗೊಂಡಿದೆ" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "ಅಮಾನ್ಯವಾದ ಕೋರಿಕೆಯ ಮನವಿ" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream ಅನ್ನು ತುಂಡರಿಸಲಾಗಿಲ್ಲ" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "ಔಟ್‌ಪುಟ್ ಬಫರ್ ಬಹಳ ಚಿಕ್ಕದಾಗಿದೆ" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "ಕಾರ್ಯಾಚರಣೆ ತಡೆಯಲ್ಪಡಬಹುದು" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "ಯಾವುದೆ URI ಅನ್ನು ಒದಗಿಸಲಾಗಿಲ್ಲ." + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "ಅಮಾನ್ಯವಾದ '%s' URI:'%s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "'%s' URL ಅನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "ಬೆಂಬಲವಿಲ್ಲದ ಯುಆರ್ಐ ಮಾದರಿ '%s'" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "ಆತಿಥೇಯವು ಒಂದು IP ವಿಳಾಸವಾಗಿದೆ" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "ಅಮಾನ್ಯವಾದ ಅತಿಥೇಯದ ಹೆಸರು" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "ಆತಿಥೇಯದ ಹೆಸರಿನಲ್ಲಿ ಯಾವುದೆ ಮೂಲ ಡೊಮೈನ್ ಇಲ್ಲ" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "ಬೇಕಾದಷ್ಟು ಡೊಮೈನ್‌ಗಳಿಲ್ಲ" + -- cgit v1.2.1 From 596e64f858ebccb32b987bc76e3376f3bb5bcbe7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 8 Jun 2012 03:31:14 -0400 Subject: SoupSessionAsync: don't allow restart-from-FINISHED in new_api --- libsoup/soup-session-async.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index d26fbe21..99edf32f 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -260,8 +260,10 @@ process_queue_item (SoupMessageQueueItem *item, case SOUP_MESSAGE_FINISHING: item->state = SOUP_MESSAGE_FINISHED; soup_message_finished (item->msg); - if (item->state != SOUP_MESSAGE_FINISHED) + if (item->state != SOUP_MESSAGE_FINISHED) { + g_return_if_fail (!item->new_api); break; + } soup_message_queue_item_ref (item); soup_session_unqueue_item (session, item); -- cgit v1.2.1 From 98d7c7372d276eacdcf86f82b7a8a5114a83fe60 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 27 May 2012 11:42:45 -0400 Subject: SoupSession: allow creating a "plain" SoupSession for use with new APIs In gio-based APIs, async vs sync is a function-level distinction, not a class-level distinction. Merge most of the existing SoupSessionAsync and SoupSessionSync code up into SoupSession, and make SoupSession non-abstract, so that you can create a SoupSession and then use either sync or async SoupRequest-based APIs on it. (The traditional APIs still require one of the traditional subclasses, although the code reorg does affect them in some ways, such as making SoupSessionAsync more thread-safe.) --- libsoup/soup-message-queue.h | 3 +- libsoup/soup-session-async.c | 565 +------------------- libsoup/soup-session-private.h | 27 +- libsoup/soup-session-sync.c | 388 +------------- libsoup/soup-session.c | 1109 ++++++++++++++++++++++++++++++++++------ tests/requester-test.c | 63 ++- 6 files changed, 1024 insertions(+), 1131 deletions(-) diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index d3341bd7..dd619244 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -46,7 +46,8 @@ struct _SoupMessageQueueItem { guint paused : 1; guint new_api : 1; guint io_started : 1; - guint redirection_count : 29; + guint async : 1; + guint redirection_count : 28; SoupMessageQueueItemState state; diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 99edf32f..a24f4bab 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -27,48 +27,13 @@ * single-threaded programs. **/ -static void run_queue (SoupSessionAsync *sa); -static void do_idle_run_queue (SoupSession *session); - -static void send_request_running (SoupSession *session, SoupMessageQueueItem *item); -static void send_request_restarted (SoupSession *session, SoupMessageQueueItem *item); -static void send_request_finished (SoupSession *session, SoupMessageQueueItem *item); - G_DEFINE_TYPE (SoupSessionAsync, soup_session_async, SOUP_TYPE_SESSION) -typedef struct { - SoupSessionAsync *sa; - GSList *sources; - gboolean disposed; - -} SoupSessionAsyncPrivate; -#define SOUP_SESSION_ASYNC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION_ASYNC, SoupSessionAsyncPrivate)) - static void soup_session_async_init (SoupSessionAsync *sa) { - SoupSessionAsyncPrivate *priv = SOUP_SESSION_ASYNC_GET_PRIVATE (sa); - - priv->sa = sa; } -static void -soup_session_async_dispose (GObject *object) -{ - SoupSessionAsyncPrivate *priv = SOUP_SESSION_ASYNC_GET_PRIVATE (object); - GSList *iter; - - priv->disposed = TRUE; - for (iter = priv->sources; iter; iter = iter->next) { - g_source_destroy (iter->data); - g_source_unref (iter->data); - } - g_clear_pointer (&priv->sources, g_slist_free); - - G_OBJECT_CLASS (soup_session_async_parent_class)->dispose (object); -} - - /** * soup_session_async_new: * @@ -105,275 +70,16 @@ soup_session_async_new_with_options (const char *optname1, ...) return session; } -static void -message_completed (SoupMessage *msg, gpointer user_data) -{ - SoupMessageQueueItem *item = user_data; - - do_idle_run_queue (item->session); - - if (item->state != SOUP_MESSAGE_RESTARTING) - item->state = SOUP_MESSAGE_FINISHING; -} - -static void -ssl_tunnel_completed (SoupConnection *conn, guint status, gpointer user_data) -{ - SoupMessageQueueItem *tunnel_item = user_data; - SoupMessageQueueItem *item = tunnel_item->related; - SoupSession *session = item->session; - - soup_message_finished (tunnel_item->msg); - soup_message_queue_item_unref (tunnel_item); - - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - soup_session_set_item_connection (session, item, NULL); - soup_message_set_status (item->msg, status); - } - - item->state = SOUP_MESSAGE_READY; - do_idle_run_queue (session); - soup_message_queue_item_unref (item); -} - -static void -tunnel_message_completed (SoupMessage *tunnel_msg, gpointer user_data) -{ - SoupMessageQueueItem *tunnel_item = user_data; - SoupSession *session = tunnel_item->session; - SoupMessageQueueItem *item = tunnel_item->related; - - if (tunnel_item->state == SOUP_MESSAGE_RESTARTING) { - soup_message_restarted (tunnel_msg); - if (tunnel_item->conn) { - tunnel_item->state = SOUP_MESSAGE_RUNNING; - soup_session_send_queue_item (session, tunnel_item, - tunnel_message_completed); - return; - } - - soup_message_set_status (tunnel_msg, SOUP_STATUS_TRY_AGAIN); - } - - tunnel_item->state = SOUP_MESSAGE_FINISHED; - soup_session_unqueue_item (session, tunnel_item); - - if (SOUP_STATUS_IS_SUCCESSFUL (tunnel_msg->status_code)) { - soup_connection_start_ssl_async (item->conn, item->cancellable, - ssl_tunnel_completed, tunnel_item); - } else { - ssl_tunnel_completed (item->conn, tunnel_msg->status_code, - tunnel_item); - } -} - -static void -got_connection (SoupConnection *conn, guint status, gpointer user_data) -{ - SoupMessageQueueItem *item = user_data; - SoupSession *session = item->session; - - if (status != SOUP_STATUS_OK) { - if (item->state == SOUP_MESSAGE_CONNECTING) { - soup_session_set_item_status (session, item, status); - soup_session_set_item_connection (session, item, NULL); - item->state = SOUP_MESSAGE_READY; - } - } else - item->state = SOUP_MESSAGE_CONNECTED; - - run_queue ((SoupSessionAsync *)session); - soup_message_queue_item_unref (item); -} - -static void -process_queue_item (SoupMessageQueueItem *item, - gboolean *should_prune, - gboolean loop) -{ - SoupSession *session = item->session; - - if (item->async_context != soup_session_get_async_context (session)) - return; - - do { - if (item->paused) - return; - - switch (item->state) { - case SOUP_MESSAGE_STARTING: - if (!soup_session_get_connection (session, item, should_prune)) - return; - - if (soup_connection_get_state (item->conn) != SOUP_CONNECTION_NEW) { - item->state = SOUP_MESSAGE_READY; - break; - } - - item->state = SOUP_MESSAGE_CONNECTING; - soup_message_queue_item_ref (item); - soup_connection_connect_async (item->conn, item->cancellable, - got_connection, item); - return; - - case SOUP_MESSAGE_CONNECTED: - if (soup_connection_is_tunnelled (item->conn)) { - SoupMessageQueueItem *tunnel_item; - - soup_message_queue_item_ref (item); - - item->state = SOUP_MESSAGE_TUNNELING; - - tunnel_item = soup_session_make_connect_message (session, item->conn); - tunnel_item->related = item; - soup_session_send_queue_item (session, tunnel_item, tunnel_message_completed); - return; - } - - item->state = SOUP_MESSAGE_READY; - break; - - case SOUP_MESSAGE_READY: - soup_message_set_https_status (item->msg, item->conn); - if (item->msg->status_code) { - if (item->msg->status_code == SOUP_STATUS_TRY_AGAIN) { - soup_message_cleanup_response (item->msg); - item->state = SOUP_MESSAGE_STARTING; - } else - item->state = SOUP_MESSAGE_FINISHING; - break; - } - - item->state = SOUP_MESSAGE_RUNNING; - soup_session_send_queue_item (session, item, message_completed); - if (item->new_api) - send_request_running (session, item); - break; - - case SOUP_MESSAGE_RESTARTING: - item->state = SOUP_MESSAGE_STARTING; - soup_message_restarted (item->msg); - if (item->new_api) - send_request_restarted (session, item); - break; - - case SOUP_MESSAGE_FINISHING: - item->state = SOUP_MESSAGE_FINISHED; - soup_message_finished (item->msg); - if (item->state != SOUP_MESSAGE_FINISHED) { - g_return_if_fail (!item->new_api); - break; - } - - soup_message_queue_item_ref (item); - soup_session_unqueue_item (session, item); - if (item->callback) - item->callback (session, item->msg, item->callback_data); - else if (item->new_api) - send_request_finished (session, item); - - soup_message_queue_item_unref (item); - return; - - default: - /* Nothing to do with this message in any - * other state. - */ - return; - } - } while (loop && item->state != SOUP_MESSAGE_FINISHED); -} - -static void -run_queue (SoupSessionAsync *sa) -{ - SoupSession *session = SOUP_SESSION (sa); - SoupMessageQueue *queue = soup_session_get_queue (session); - SoupMessageQueueItem *item; - SoupMessage *msg; - gboolean try_pruning = TRUE, should_prune = FALSE; - - g_object_ref (session); - soup_session_cleanup_connections (session, FALSE); - - try_again: - for (item = soup_message_queue_first (queue); - item; - item = soup_message_queue_next (queue, item)) { - msg = item->msg; - - /* CONNECT messages are handled specially */ - if (msg->method != SOUP_METHOD_CONNECT) - process_queue_item (item, &should_prune, TRUE); - } - - if (try_pruning && should_prune) { - /* There is at least one message in the queue that - * could be sent if we pruned an idle connection from - * some other server. - */ - if (soup_session_cleanup_connections (session, TRUE)) { - try_pruning = should_prune = FALSE; - goto try_again; - } - } - - g_object_unref (session); -} - -static gboolean -idle_run_queue (gpointer user_data) -{ - SoupSessionAsyncPrivate *priv = user_data; - GSource *source; - - if (priv->disposed) - return FALSE; - - source = g_main_current_source (); - priv->sources = g_slist_remove (priv->sources, source); - - /* Ensure that the source is destroyed before running the queue */ - g_source_destroy (source); - g_source_unref (source); - - run_queue (priv->sa); - return FALSE; -} - -static void -do_idle_run_queue (SoupSession *session) -{ - SoupSessionAsyncPrivate *priv = SOUP_SESSION_ASYNC_GET_PRIVATE (session); - GMainContext *async_context = soup_session_get_async_context (session); - GSource *source; - - if (priv->disposed) - return; - - /* We use priv rather than session as the source data, because - * other parts of libsoup (or the calling app) may have sources - * using the session as the source data. - */ - - source = g_main_context_find_source_by_user_data (async_context, priv); - if (source) - return; - - source = soup_add_completion_reffed (async_context, idle_run_queue, priv); - priv->sources = g_slist_prepend (priv->sources, source); -} - static void soup_session_async_queue_message (SoupSession *session, SoupMessage *req, SoupSessionCallback callback, gpointer user_data) { SoupMessageQueueItem *item; - item = soup_session_append_queue_item (session, req, callback, user_data); + item = soup_session_append_queue_item (session, req, TRUE, FALSE, + callback, user_data); + soup_session_kick_queue (session); soup_message_queue_item_unref (item); - - do_idle_run_queue (session); } static guint @@ -383,10 +89,9 @@ soup_session_async_send_message (SoupSession *session, SoupMessage *req) GMainContext *async_context = soup_session_get_async_context (session); - soup_session_async_queue_message (session, req, NULL, NULL); - - item = soup_message_queue_lookup (soup_session_get_queue (session), req); - g_return_val_if_fail (item != NULL, SOUP_STATUS_MALFORMED); + item = soup_session_append_queue_item (session, req, TRUE, FALSE, + NULL, NULL); + soup_session_kick_queue (session); while (item->state != SOUP_MESSAGE_FINISHED) g_main_context_iteration (async_context, TRUE); @@ -402,7 +107,6 @@ soup_session_async_cancel_message (SoupSession *session, SoupMessage *msg, { SoupMessageQueue *queue; SoupMessageQueueItem *item; - gboolean dummy; SOUP_SESSION_CLASS (soup_session_async_parent_class)-> cancel_message (session, msg, status_code); @@ -424,7 +128,7 @@ soup_session_async_cancel_message (SoupSession *session, SoupMessage *msg, item->state = SOUP_MESSAGE_FINISHING; if (item->state != SOUP_MESSAGE_FINISHED) - process_queue_item (item, &dummy, FALSE); + soup_session_process_queue_item (session, item, NULL, FALSE); soup_message_queue_item_unref (item); } @@ -462,269 +166,14 @@ soup_session_async_auth_required (SoupSession *session, SoupMessage *msg, } } -static void -soup_session_async_kick (SoupSession *session) -{ - do_idle_run_queue (session); -} - - -static void -send_request_return_result (SoupMessageQueueItem *item, - gpointer stream, GError *error) -{ - GTask *task; - - task = item->task; - item->task = NULL; - - if (item->io_source) { - g_source_destroy (item->io_source); - g_clear_pointer (&item->io_source, g_source_unref); - } - - if (error) - g_task_return_error (task, error); - else if (SOUP_STATUS_IS_TRANSPORT_ERROR (item->msg->status_code)) { - if (stream) - g_object_unref (stream); - g_task_return_new_error (task, SOUP_HTTP_ERROR, - item->msg->status_code, - "%s", - item->msg->reason_phrase); - } else - g_task_return_pointer (task, stream, g_object_unref); - g_object_unref (task); -} - -static void -send_request_restarted (SoupSession *session, SoupMessageQueueItem *item) -{ - /* We won't be needing this, then. */ - g_object_set_data (G_OBJECT (item->msg), "SoupSessionAsync:ostream", NULL); - item->io_started = FALSE; -} - -static void -send_request_finished (SoupSession *session, SoupMessageQueueItem *item) -{ - GMemoryOutputStream *mostream; - GInputStream *istream = NULL; - GError *error = NULL; - - if (!item->task) { - /* Something else already took care of it. */ - return; - } - - mostream = g_object_get_data (G_OBJECT (item->task), "SoupSessionAsync:ostream"); - if (mostream) { - gpointer data; - gssize size; - - /* We thought it would be requeued, but it wasn't, so - * return the original body. - */ - size = g_memory_output_stream_get_data_size (mostream); - data = size ? g_memory_output_stream_steal_data (mostream) : g_strdup (""); - istream = g_memory_input_stream_new_from_data (data, size, g_free); - } else if (item->io_started) { - /* The message finished before becoming readable. This - * will happen, eg, if it's cancelled from got-headers. - * Do nothing; the op will complete via read_ready_cb() - * after we return; - */ - return; - } else { - /* The message finished before even being started; - * probably a tunnel connect failure. - */ - istream = g_memory_input_stream_new (); - } - - send_request_return_result (item, istream, error); -} - -static void -send_async_spliced (GObject *source, GAsyncResult *result, gpointer user_data) -{ - SoupMessageQueueItem *item = user_data; - GInputStream *istream = g_object_get_data (source, "istream"); - GError *error = NULL; - - /* It should be safe to call the sync close() method here since - * the message body has already been written. - */ - g_input_stream_close (istream, NULL, NULL); - g_object_unref (istream); - - /* If the message was cancelled, it will be completed via other means */ - if (g_cancellable_is_cancelled (item->cancellable) || - !item->task) { - soup_message_queue_item_unref (item); - return; - } - - if (g_output_stream_splice_finish (G_OUTPUT_STREAM (source), - result, &error) == -1) { - send_request_return_result (item, NULL, error); - soup_message_queue_item_unref (item); - return; - } - - /* Otherwise either restarted or finished will eventually be called. */ - do_idle_run_queue (item->session); - soup_message_queue_item_unref (item); -} - -static void -send_async_maybe_complete (SoupMessageQueueItem *item, - GInputStream *stream) -{ - if (item->msg->status_code == SOUP_STATUS_UNAUTHORIZED || - item->msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED || - soup_session_would_redirect (item->session, item->msg)) { - GOutputStream *ostream; - - /* Message may be requeued, so gather the current message body... */ - ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); - g_object_set_data_full (G_OBJECT (item->task), "SoupSessionAsync:ostream", - ostream, g_object_unref); - - g_object_set_data (G_OBJECT (ostream), "istream", stream); - - /* Give the splice op its own ref on item */ - soup_message_queue_item_ref (item); - g_output_stream_splice_async (ostream, stream, - /* We can't use CLOSE_SOURCE because it - * might get closed in the wrong thread. - */ - G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, - G_PRIORITY_DEFAULT, - item->cancellable, - send_async_spliced, item); - return; - } - - send_request_return_result (item, stream, NULL); -} - -static void try_run_until_read (SoupMessageQueueItem *item); - -static gboolean -read_ready_cb (SoupMessage *msg, gpointer user_data) -{ - SoupMessageQueueItem *item = user_data; - - g_clear_pointer (&item->io_source, g_source_unref); - try_run_until_read (item); - return FALSE; -} - -static void -try_run_until_read (SoupMessageQueueItem *item) -{ - GError *error = NULL; - GInputStream *stream = NULL; - - if (soup_message_io_run_until_read (item->msg, item->cancellable, &error)) - stream = soup_message_io_get_response_istream (item->msg, &error); - if (stream) { - send_async_maybe_complete (item, stream); - return; - } - - if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) { - item->state = SOUP_MESSAGE_RESTARTING; - soup_message_io_finished (item->msg); - g_error_free (error); - return; - } - - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { - if (item->state != SOUP_MESSAGE_FINISHED) { - gboolean dummy; - - if (soup_message_io_in_progress (item->msg)) - soup_message_io_finished (item->msg); - item->state = SOUP_MESSAGE_FINISHING; - process_queue_item (item, &dummy, FALSE); - } - send_request_return_result (item, NULL, error); - return; - } - - g_clear_error (&error); - item->io_source = soup_message_io_get_source (item->msg, item->cancellable, - read_ready_cb, item); - g_source_attach (item->io_source, soup_session_get_async_context (item->session)); -} - -static void -send_request_running (SoupSession *session, SoupMessageQueueItem *item) -{ - item->io_started = TRUE; - try_run_until_read (item); -} - -void -soup_session_send_request_async (SoupSession *session, - SoupMessage *msg, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SoupMessageQueueItem *item; - gboolean use_thread_context; - - g_return_if_fail (SOUP_IS_SESSION_ASYNC (session)); - - g_object_get (G_OBJECT (session), - SOUP_SESSION_USE_THREAD_CONTEXT, &use_thread_context, - NULL); - g_return_if_fail (use_thread_context); - - soup_session_async_queue_message (session, msg, NULL, NULL); - - item = soup_message_queue_lookup (soup_session_get_queue (session), msg); - g_return_if_fail (item != NULL); - - item->new_api = TRUE; - item->task = g_task_new (session, cancellable, callback, user_data); - g_task_set_task_data (item->task, item, (GDestroyNotify) soup_message_queue_item_unref); - - if (cancellable) { - g_object_unref (item->cancellable); - item->cancellable = g_object_ref (cancellable); - } -} - -GInputStream * -soup_session_send_request_finish (SoupSession *session, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (SOUP_IS_SESSION_ASYNC (session), NULL); - g_return_val_if_fail (g_task_is_valid (result, session), NULL); - - return g_task_propagate_pointer (G_TASK (result), error); -} - static void soup_session_async_class_init (SoupSessionAsyncClass *soup_session_async_class) { SoupSessionClass *session_class = SOUP_SESSION_CLASS (soup_session_async_class); - GObjectClass *object_class = G_OBJECT_CLASS (session_class); - - g_type_class_add_private (soup_session_async_class, - sizeof (SoupSessionAsyncPrivate)); /* virtual method override */ session_class->queue_message = soup_session_async_queue_message; session_class->send_message = soup_session_async_send_message; session_class->cancel_message = soup_session_async_cancel_message; session_class->auth_required = soup_session_async_auth_required; - session_class->kick = soup_session_async_kick; - - object_class->dispose = soup_session_async_dispose; } diff --git a/libsoup/soup-session-private.h b/libsoup/soup-session-private.h index 297faf57..dc4d300b 100644 --- a/libsoup/soup-session-private.h +++ b/libsoup/soup-session-private.h @@ -17,26 +17,12 @@ SoupMessageQueue *soup_session_get_queue (SoupSession *s SoupMessageQueueItem *soup_session_append_queue_item (SoupSession *session, SoupMessage *msg, + gboolean async, + gboolean new_api, SoupSessionCallback callback, gpointer user_data); -SoupMessageQueueItem *soup_session_make_connect_message (SoupSession *session, - SoupConnection *conn); -gboolean soup_session_get_connection (SoupSession *session, - SoupMessageQueueItem *item, - gboolean *try_pruning); -gboolean soup_session_cleanup_connections (SoupSession *session, - gboolean prune_idle); -void soup_session_send_queue_item (SoupSession *session, - SoupMessageQueueItem *item, - SoupMessageCompletionFn completion_cb); -void soup_session_unqueue_item (SoupSession *session, - SoupMessageQueueItem *item); -void soup_session_set_item_connection (SoupSession *session, - SoupMessageQueueItem *item, - SoupConnection *conn); -void soup_session_set_item_status (SoupSession *session, - SoupMessageQueueItem *item, - guint status_code); + +void soup_session_kick_queue (SoupSession *session); GInputStream *soup_session_send_request (SoupSession *session, SoupMessage *msg, @@ -52,6 +38,11 @@ GInputStream *soup_session_send_request_finish (SoupSession *s GAsyncResult *result, GError **error); +void soup_session_process_queue_item (SoupSession *session, + SoupMessageQueueItem *item, + gboolean *should_prune, + gboolean loop); + G_END_DECLS #endif /* SOUP_SESSION_PRIVATE_H */ diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index 43d0a491..cbd24606 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -42,35 +42,13 @@ * handler callbacks, until I/O is complete. **/ -typedef struct { - GMutex lock; - GCond cond; -} SoupSessionSyncPrivate; -#define SOUP_SESSION_SYNC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION_SYNC, SoupSessionSyncPrivate)) - G_DEFINE_TYPE (SoupSessionSync, soup_session_sync, SOUP_TYPE_SESSION) static void soup_session_sync_init (SoupSessionSync *ss) { - SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (ss); - - g_mutex_init (&priv->lock); - g_cond_init (&priv->cond); -} - -static void -soup_session_sync_finalize (GObject *object) -{ - SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (object); - - g_mutex_clear (&priv->lock); - g_cond_clear (&priv->cond); - - G_OBJECT_CLASS (soup_session_sync_parent_class)->finalize (object); } - /** * soup_session_sync_new: * @@ -107,181 +85,6 @@ soup_session_sync_new_with_options (const char *optname1, ...) return session; } -static guint -tunnel_connect (SoupSession *session, SoupMessageQueueItem *related) -{ - SoupConnection *conn = related->conn; - SoupMessageQueueItem *item; - guint status; - - g_object_ref (conn); - - item = soup_session_make_connect_message (session, conn); - do { - soup_session_send_queue_item (session, item, NULL); - status = item->msg->status_code; - if (item->state == SOUP_MESSAGE_RESTARTING && - soup_message_io_in_progress (item->msg)) { - soup_message_restarted (item->msg); - item->state = SOUP_MESSAGE_RUNNING; - } else { - if (item->state == SOUP_MESSAGE_RESTARTING) - status = SOUP_STATUS_TRY_AGAIN; - item->state = SOUP_MESSAGE_FINISHED; - soup_message_finished (item->msg); - } - } while (item->state == SOUP_MESSAGE_STARTING); - soup_session_unqueue_item (session, item); - soup_message_queue_item_unref (item); - - if (SOUP_STATUS_IS_SUCCESSFUL (status)) { - if (!soup_connection_start_ssl_sync (conn, related->cancellable)) - status = SOUP_STATUS_SSL_FAILED; - soup_message_set_https_status (related->msg, conn); - } - - g_object_unref (conn); - return status; -} - -static void -get_connection (SoupMessageQueueItem *item) -{ - SoupSession *session = item->session; - SoupMessage *msg = item->msg; - gboolean try_pruning = FALSE; - guint status; - -try_again: - soup_session_cleanup_connections (session, FALSE); - - if (!soup_session_get_connection (session, item, &try_pruning)) { - if (!try_pruning) - return; - soup_session_cleanup_connections (session, TRUE); - if (!soup_session_get_connection (session, item, &try_pruning)) - return; - try_pruning = FALSE; - } - - if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_IDLE) { - item->state = SOUP_MESSAGE_READY; - return; - } - - if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_NEW) { - status = soup_connection_connect_sync (item->conn, item->cancellable); - if (status == SOUP_STATUS_TRY_AGAIN) { - soup_session_set_item_connection (session, item, NULL); - goto try_again; - } - - soup_message_set_https_status (msg, item->conn); - - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - if (!msg->status_code) - soup_session_set_item_status (session, item, status); - item->state = SOUP_MESSAGE_FINISHING; - soup_session_set_item_connection (session, item, NULL); - return; - } - } - - if (soup_connection_is_tunnelled (item->conn)) { - status = tunnel_connect (session, item); - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - soup_session_set_item_connection (session, item, NULL); - if (status == SOUP_STATUS_TRY_AGAIN) - goto try_again; - soup_session_set_item_status (session, item, status); - item->state = SOUP_MESSAGE_FINISHING; - return; - } - } - - item->state = SOUP_MESSAGE_READY; -} - -static void process_queue_item (SoupMessageQueueItem *item); - -static void -new_api_message_completed (SoupMessage *msg, gpointer user_data) -{ - SoupMessageQueueItem *item = user_data; - - if (item->state != SOUP_MESSAGE_RESTARTING) { - item->state = SOUP_MESSAGE_FINISHING; - process_queue_item (item); - } -} - -static void -process_queue_item (SoupMessageQueueItem *item) -{ - SoupSession *session = item->session; - SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session); - - soup_message_queue_item_ref (item); - - do { - if (item->paused) { - g_mutex_lock (&priv->lock); - while (item->paused) - g_cond_wait (&priv->cond, &priv->lock); - g_mutex_unlock (&priv->lock); - } - - switch (item->state) { - case SOUP_MESSAGE_STARTING: - g_mutex_lock (&priv->lock); - do { - get_connection (item); - if (item->state == SOUP_MESSAGE_STARTING) - g_cond_wait (&priv->cond, &priv->lock); - } while (item->state == SOUP_MESSAGE_STARTING); - g_mutex_unlock (&priv->lock); - break; - - case SOUP_MESSAGE_READY: - item->state = SOUP_MESSAGE_RUNNING; - - if (item->new_api) { - soup_session_send_queue_item (item->session, item, new_api_message_completed); - goto out; - } - - soup_session_send_queue_item (item->session, item, NULL); - if (item->state != SOUP_MESSAGE_RESTARTING) - item->state = SOUP_MESSAGE_FINISHING; - break; - - case SOUP_MESSAGE_RUNNING: - g_warn_if_fail (item->new_api); - item->state = SOUP_MESSAGE_FINISHING; - break; - - case SOUP_MESSAGE_RESTARTING: - item->state = SOUP_MESSAGE_STARTING; - soup_message_restarted (item->msg); - break; - - case SOUP_MESSAGE_FINISHING: - item->state = SOUP_MESSAGE_FINISHED; - soup_message_finished (item->msg); - soup_session_unqueue_item (session, item); - break; - - default: - g_warn_if_reached (); - item->state = SOUP_MESSAGE_FINISHING; - break; - } - } while (item->state != SOUP_MESSAGE_FINISHED); - - out: - soup_message_queue_item_unref (item); -} - static gboolean queue_message_callback (gpointer data) { @@ -297,7 +100,7 @@ queue_message_thread (gpointer data) { SoupMessageQueueItem *item = data; - process_queue_item (item); + soup_session_process_queue_item (item->session, item, NULL, TRUE); if (item->callback) { soup_add_completion (soup_session_get_async_context (item->session), queue_message_callback, item); @@ -314,7 +117,8 @@ soup_session_sync_queue_message (SoupSession *session, SoupMessage *msg, SoupMessageQueueItem *item; GThread *thread; - item = soup_session_append_queue_item (session, msg, callback, user_data); + item = soup_session_append_queue_item (session, msg, FALSE, FALSE, + callback, user_data); thread = g_thread_new ("SoupSessionSync:queue_message", queue_message_thread, item); g_thread_unref (thread); @@ -326,24 +130,14 @@ soup_session_sync_send_message (SoupSession *session, SoupMessage *msg) SoupMessageQueueItem *item; guint status; - item = soup_session_append_queue_item (session, msg, NULL, NULL); - process_queue_item (item); + item = soup_session_append_queue_item (session, msg, FALSE, FALSE, + NULL, NULL); + soup_session_process_queue_item (session, item, NULL, TRUE); status = msg->status_code; soup_message_queue_item_unref (item); return status; } -static void -soup_session_sync_cancel_message (SoupSession *session, SoupMessage *msg, guint status_code) -{ - SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session); - - g_mutex_lock (&priv->lock); - SOUP_SESSION_CLASS (soup_session_sync_parent_class)->cancel_message (session, msg, status_code); - g_cond_broadcast (&priv->cond); - g_mutex_unlock (&priv->lock); -} - static void soup_session_sync_auth_required (SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying) @@ -362,183 +156,13 @@ soup_session_sync_auth_required (SoupSession *session, SoupMessage *msg, auth_required (session, msg, auth, retrying); } -static void -soup_session_sync_flush_queue (SoupSession *session) -{ - SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session); - SoupMessageQueue *queue; - SoupMessageQueueItem *item; - GHashTable *current; - gboolean done = FALSE; - - /* Record the current contents of the queue */ - current = g_hash_table_new (NULL, NULL); - queue = soup_session_get_queue (session); - for (item = soup_message_queue_first (queue); - item; - item = soup_message_queue_next (queue, item)) - g_hash_table_insert (current, item, item); - - /* Cancel everything */ - SOUP_SESSION_CLASS (soup_session_sync_parent_class)->flush_queue (session); - - /* Wait until all of the items in @current have been removed - * from the queue. (This is not the same as "wait for the - * queue to be empty", because the app may queue new requests - * in response to the cancellation of the old ones. We don't - * try to cancel those requests as well, since we'd likely - * just end up looping forever.) - */ - g_mutex_lock (&priv->lock); - do { - done = TRUE; - for (item = soup_message_queue_first (queue); - item; - item = soup_message_queue_next (queue, item)) { - if (g_hash_table_lookup (current, item)) - done = FALSE; - } - - if (!done) - g_cond_wait (&priv->cond, &priv->lock); - } while (!done); - g_mutex_unlock (&priv->lock); - - g_hash_table_destroy (current); -} - -static void -soup_session_sync_kick (SoupSession *session) -{ - SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session); - - g_cond_broadcast (&priv->cond); -} - static void soup_session_sync_class_init (SoupSessionSyncClass *session_sync_class) { - GObjectClass *object_class = G_OBJECT_CLASS (session_sync_class); SoupSessionClass *session_class = SOUP_SESSION_CLASS (session_sync_class); - g_type_class_add_private (session_sync_class, sizeof (SoupSessionSyncPrivate)); - /* virtual method override */ session_class->queue_message = soup_session_sync_queue_message; session_class->send_message = soup_session_sync_send_message; - session_class->cancel_message = soup_session_sync_cancel_message; session_class->auth_required = soup_session_sync_auth_required; - session_class->flush_queue = soup_session_sync_flush_queue; - session_class->kick = soup_session_sync_kick; - - object_class->finalize = soup_session_sync_finalize; -} - - -GInputStream * -soup_session_send_request (SoupSession *session, - SoupMessage *msg, - GCancellable *cancellable, - GError **error) -{ - SoupMessageQueueItem *item; - GInputStream *stream = NULL; - GOutputStream *ostream; - GMemoryOutputStream *mostream; - gssize size; - GError *my_error = NULL; - - g_return_val_if_fail (SOUP_IS_SESSION_SYNC (session), NULL); - - item = soup_session_append_queue_item (session, msg, NULL, NULL); - - item->new_api = TRUE; - if (cancellable) { - g_object_unref (item->cancellable); - item->cancellable = g_object_ref (cancellable); - } - - while (!stream) { - /* Get a connection, etc */ - process_queue_item (item); - if (item->state != SOUP_MESSAGE_RUNNING) - break; - - /* Send request, read headers */ - if (!soup_message_io_run_until_read (msg, item->cancellable, &my_error)) { - if (g_error_matches (my_error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) { - item->state = SOUP_MESSAGE_RESTARTING; - soup_message_io_finished (item->msg); - g_clear_error (&my_error); - continue; - } else - break; - } - - stream = soup_message_io_get_response_istream (msg, &my_error); - if (!stream) - break; - - /* Break if the message doesn't look likely-to-be-requeued */ - if (msg->status_code != SOUP_STATUS_UNAUTHORIZED && - msg->status_code != SOUP_STATUS_PROXY_UNAUTHORIZED && - !soup_session_would_redirect (session, msg)) - break; - - /* Gather the current message body... */ - ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); - if (g_output_stream_splice (ostream, stream, - G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | - G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, - item->cancellable, &my_error) == -1) { - g_object_unref (stream); - g_object_unref (ostream); - stream = NULL; - break; - } - g_object_unref (stream); - stream = NULL; - - /* If the message was requeued, loop */ - if (item->state == SOUP_MESSAGE_RESTARTING) { - g_object_unref (ostream); - continue; - } - - /* Not requeued, so return the original body */ - mostream = G_MEMORY_OUTPUT_STREAM (ostream); - size = g_memory_output_stream_get_data_size (mostream); - stream = g_memory_input_stream_new (); - if (size) { - g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (stream), - g_memory_output_stream_steal_data (mostream), - size, g_free); - } - g_object_unref (ostream); - } - - if (my_error) - g_propagate_error (error, my_error); - else if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { - if (stream) { - g_object_unref (stream); - stream = NULL; - } - g_set_error_literal (error, SOUP_HTTP_ERROR, msg->status_code, - msg->reason_phrase); - } else if (!stream) - stream = g_memory_input_stream_new (); - - if (!stream) { - if (soup_message_io_in_progress (msg)) - soup_message_io_finished (msg); - else if (item->state != SOUP_MESSAGE_FINISHED) - item->state = SOUP_MESSAGE_FINISHING; - - if (item->state != SOUP_MESSAGE_FINISHED) - process_queue_item (item); - } - - soup_message_queue_item_unref (item); - return stream; } diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 3eecd06b..f5d93d4d 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -77,6 +77,8 @@ static guint soup_host_uri_hash (gconstpointer key); static gboolean soup_host_uri_equal (gconstpointer v1, gconstpointer v2); typedef struct { + SoupSession *session; + GTlsDatabase *tlsdb; char *ssl_ca_file; gboolean ssl_strict; @@ -100,12 +102,15 @@ typedef struct { * SoupSessionHost, adding/removing a connection, * disconnecting a connection, or moving a connection from * IDLE to IN_USE. Must not emit signals or destroy objects - * while holding it. + * while holding it. conn_cond is signaled when it may be + * possible for a previously-blocked message to continue. */ GMutex conn_lock; + GCond conn_cond; GMainContext *async_context; gboolean use_thread_context; + GSList *run_queue_sources; GResolver *resolver; @@ -126,6 +131,10 @@ static void auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer user_data); +static void async_run_queue (SoupSession *session); + +static void async_send_request_running (SoupSession *session, SoupMessageQueueItem *item); + #define SOUP_SESSION_MAX_CONNS_DEFAULT 10 #define SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT 2 @@ -133,9 +142,9 @@ static void auth_manager_authenticate (SoupAuthManager *manager, #define SOUP_SESSION_USER_AGENT_BASE "libsoup/" PACKAGE_VERSION -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (SoupSession, soup_session, G_TYPE_OBJECT, - soup_init (); - ) +G_DEFINE_TYPE_WITH_CODE (SoupSession, soup_session, G_TYPE_OBJECT, + soup_init (); + ) enum { REQUEST_QUEUED, @@ -182,9 +191,12 @@ soup_session_init (SoupSession *session) SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupAuthManager *auth_manager; + priv->session = session; + priv->queue = soup_message_queue_new (session); g_mutex_init (&priv->conn_lock); + g_cond_init (&priv->conn_cond); priv->http_hosts = g_hash_table_new_full (soup_host_uri_hash, soup_host_uri_equal, NULL, (GDestroyNotify)free_host); @@ -225,6 +237,15 @@ soup_session_dispose (GObject *object) { SoupSession *session = SOUP_SESSION (object); SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + GSList *iter; + + priv->disposed = TRUE; + + for (iter = priv->run_queue_sources; iter; iter = iter->next) { + g_source_destroy (iter->data); + g_source_unref (iter->data); + } + g_clear_pointer (&priv->run_queue_sources, g_slist_free); priv->disposed = TRUE; soup_session_abort (session); @@ -245,6 +266,7 @@ soup_session_finalize (GObject *object) soup_message_queue_destroy (priv->queue); g_mutex_clear (&priv->conn_lock); + g_cond_clear (&priv->conn_cond); g_hash_table_destroy (priv->http_hosts); g_hash_table_destroy (priv->https_hosts); g_hash_table_destroy (priv->conns); @@ -826,10 +848,7 @@ get_host_for_uri (SoupSession *session, SoupURI *uri) return host; } -/* Note: get_host_for_message doesn't lock the conn_lock. The caller - * must do it itself if there's a chance the host doesn't already - * exist. - */ +/* Requires conn_lock to be locked */ static SoupSessionHost * get_host_for_message (SoupSession *session, SoupMessage *msg) { @@ -1030,6 +1049,36 @@ redirect_handler (SoupMessage *msg, gpointer user_data) soup_session_redirect_message (session, msg); } +static void +proxy_connection_event (SoupConnection *conn, + GSocketClientEvent event, + GIOStream *connection, + gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + soup_message_network_event (item->msg, event, connection); +} + +static void +soup_session_set_item_connection (SoupSession *session, + SoupMessageQueueItem *item, + SoupConnection *conn) +{ + if (item->conn) { + g_signal_handlers_disconnect_by_func (item->conn, proxy_connection_event, item); + g_object_unref (item->conn); + } + + item->conn = conn; + + if (item->conn) { + g_object_ref (item->conn); + g_signal_connect (item->conn, "event", + G_CALLBACK (proxy_connection_event), item); + } +} + static void message_restarted (SoupMessage *msg, gpointer user_data) { @@ -1048,6 +1097,7 @@ message_restarted (SoupMessage *msg, gpointer user_data) SoupMessageQueueItem * soup_session_append_queue_item (SoupSession *session, SoupMessage *msg, + gboolean async, gboolean new_api, SoupSessionCallback callback, gpointer user_data) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); @@ -1057,6 +1107,8 @@ soup_session_append_queue_item (SoupSession *session, SoupMessage *msg, soup_message_cleanup_response (msg); item = soup_message_queue_append (priv->queue, msg, callback, user_data); + item->async = async; + item->new_api = new_api; g_mutex_lock (&priv->conn_lock); host = get_host_for_message (session, item->msg); @@ -1077,7 +1129,7 @@ soup_session_append_queue_item (SoupSession *session, SoupMessage *msg, return item; } -void +static void soup_session_send_queue_item (SoupSession *session, SoupMessageQueueItem *item, SoupMessageCompletionFn completion_cb) @@ -1116,9 +1168,9 @@ soup_session_send_queue_item (SoupSession *session, soup_connection_send_request (item->conn, item, completion_cb, item); } -gboolean +static gboolean soup_session_cleanup_connections (SoupSession *session, - gboolean prune_idle) + gboolean cleanup_idle) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); GSList *conns = NULL, *c; @@ -1131,7 +1183,7 @@ soup_session_cleanup_connections (SoupSession *session, while (g_hash_table_iter_next (&iter, &conn, &host)) { state = soup_connection_get_state (conn); if (state == SOUP_CONNECTION_REMOTE_DISCONNECTED || - (prune_idle && state == SOUP_CONNECTION_IDLE)) { + (cleanup_idle && state == SOUP_CONNECTION_IDLE)) { conns = g_slist_prepend (conns, g_object_ref (conn)); g_hash_table_iter_remove (&iter); drop_connection (session, host, conn); @@ -1233,7 +1285,7 @@ connection_disconnected (SoupConnection *conn, gpointer user_data) g_mutex_unlock (&priv->conn_lock); - SOUP_SESSION_GET_CLASS (session)->kick (session); + soup_session_kick_queue (session); } static void @@ -1243,88 +1295,281 @@ connection_state_changed (GObject *object, GParamSpec *param, gpointer user_data SoupConnection *conn = SOUP_CONNECTION (object); if (soup_connection_get_state (conn) == SOUP_CONNECTION_IDLE) - SOUP_SESSION_GET_CLASS (session)->kick (session); + soup_session_kick_queue (session); } -SoupMessageQueueItem * -soup_session_make_connect_message (SoupSession *session, - SoupConnection *conn) +SoupMessageQueue * +soup_session_get_queue (SoupSession *session) +{ + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + + return priv->queue; +} + +static void +soup_session_unqueue_item (SoupSession *session, + SoupMessageQueueItem *item) +{ + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + SoupSessionHost *host; + + if (item->conn) { + if (item->msg->method != SOUP_METHOD_CONNECT || + !SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) + soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); + soup_session_set_item_connection (session, item, NULL); + } + + if (item->state != SOUP_MESSAGE_FINISHED) { + g_warning ("finished an item with state %d", item->state); + return; + } + + soup_message_queue_remove (priv->queue, item); + + g_mutex_lock (&priv->conn_lock); + host = get_host_for_message (session, item->msg); + host->num_messages--; + g_mutex_unlock (&priv->conn_lock); + + /* g_signal_handlers_disconnect_by_func doesn't work if you + * have a metamarshal, meaning it doesn't work with + * soup_message_add_header_handler() + */ + g_signal_handlers_disconnect_matched (item->msg, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, item); + g_signal_emit (session, signals[REQUEST_UNQUEUED], 0, item->msg); + soup_message_queue_item_unref (item); +} + +static void +soup_session_set_item_status (SoupSession *session, + SoupMessageQueueItem *item, + guint status_code) +{ + SoupURI *uri; + char *msg; + + switch (status_code) { + case SOUP_STATUS_CANT_RESOLVE: + case SOUP_STATUS_CANT_CONNECT: + uri = soup_message_get_uri (item->msg); + msg = g_strdup_printf ("%s (%s)", + soup_status_get_phrase (status_code), + uri->host); + soup_message_set_status_full (item->msg, status_code, msg); + g_free (msg); + break; + + case SOUP_STATUS_CANT_RESOLVE_PROXY: + case SOUP_STATUS_CANT_CONNECT_PROXY: + if (item->proxy_uri && item->proxy_uri->host) { + msg = g_strdup_printf ("%s (%s)", + soup_status_get_phrase (status_code), + item->proxy_uri->host); + soup_message_set_status_full (item->msg, status_code, msg); + g_free (msg); + break; + } + soup_message_set_status (item->msg, status_code); + break; + + case SOUP_STATUS_SSL_FAILED: + if (!g_tls_backend_supports_tls (g_tls_backend_get_default ())) { + soup_message_set_status_full (item->msg, status_code, + "TLS/SSL support not available; install glib-networking"); + } else + soup_message_set_status (item->msg, status_code); + break; + + default: + soup_message_set_status (item->msg, status_code); + break; + } +} + + +static void +message_completed (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + if (item->async) + soup_session_kick_queue (item->session); + + if (item->state != SOUP_MESSAGE_RESTARTING) { + item->state = SOUP_MESSAGE_FINISHING; + + if (item->new_api && !item->async) + soup_session_process_queue_item (item->session, item, NULL, TRUE); + } +} + +static void +tunnel_complete (SoupConnection *conn, guint status, gpointer user_data) +{ + SoupMessageQueueItem *tunnel_item = user_data; + SoupMessageQueueItem *item = tunnel_item->related; + SoupSession *session = tunnel_item->session; + + soup_message_finished (tunnel_item->msg); + soup_message_queue_item_unref (tunnel_item); + + if (item->msg->status_code) + item->state = SOUP_MESSAGE_FINISHING; + else + soup_message_set_https_status (item->msg, item->conn); + + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + soup_session_set_item_connection (session, item, NULL); + soup_session_set_item_status (session, item, status); + } + + item->state = SOUP_MESSAGE_READY; + if (item->async) + soup_session_kick_queue (session); + soup_message_queue_item_unref (item); +} + +static void +tunnel_message_completed (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *tunnel_item = user_data; + SoupMessageQueueItem *item = tunnel_item->related; + SoupSession *session = tunnel_item->session; + guint status; + + if (tunnel_item->state == SOUP_MESSAGE_RESTARTING) { + soup_message_restarted (msg); + if (tunnel_item->conn) { + tunnel_item->state = SOUP_MESSAGE_RUNNING; + soup_session_send_queue_item (session, tunnel_item, + tunnel_message_completed); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_TRY_AGAIN); + } + + tunnel_item->state = SOUP_MESSAGE_FINISHED; + soup_session_unqueue_item (session, tunnel_item); + + status = tunnel_item->msg->status_code; + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + tunnel_complete (item->conn, status, tunnel_item); + return; + } + + if (tunnel_item->async) { + soup_connection_start_ssl_async (item->conn, item->cancellable, + tunnel_complete, tunnel_item); + } else { + status = soup_connection_start_ssl_sync (item->conn, item->cancellable); + tunnel_complete (item->conn, status, tunnel_item); + } +} + +static void +tunnel_connect (SoupMessageQueueItem *item) { + SoupSession *session = item->session; + SoupMessageQueueItem *tunnel_item; SoupURI *uri; SoupMessage *msg; - SoupMessageQueueItem *item; - uri = soup_connection_get_remote_uri (conn); + item->state = SOUP_MESSAGE_TUNNELING; + + uri = soup_connection_get_remote_uri (item->conn); msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT, uri); soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); - item = soup_session_append_queue_item (session, msg, NULL, NULL); - soup_session_set_item_connection (session, item, conn); + tunnel_item = soup_session_append_queue_item (session, msg, + item->async, FALSE, + NULL, NULL); g_object_unref (msg); - item->state = SOUP_MESSAGE_RUNNING; + tunnel_item->related = item; + soup_message_queue_item_ref (item); + soup_session_set_item_connection (session, tunnel_item, item->conn); + tunnel_item->state = SOUP_MESSAGE_RUNNING; - g_signal_emit (session, signals[TUNNELING], 0, conn); - return item; + g_signal_emit (session, signals[TUNNELING], 0, tunnel_item->conn); + + soup_session_send_queue_item (session, tunnel_item, + tunnel_message_completed); } -gboolean -soup_session_get_connection (SoupSession *session, - SoupMessageQueueItem *item, - gboolean *try_pruning) +static void +got_connection (SoupConnection *conn, guint status, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + SoupSession *session = item->session; + + if (status != SOUP_STATUS_OK) { + if (item->state == SOUP_MESSAGE_CONNECTING) { + soup_session_set_item_status (session, item, status); + soup_session_set_item_connection (session, item, NULL); + item->state = SOUP_MESSAGE_READY; + } + } else + item->state = SOUP_MESSAGE_CONNECTED; + + if (item->async) { + if (item->state == SOUP_MESSAGE_CONNECTED || + item->state == SOUP_MESSAGE_READY) + async_run_queue (item->session); + else + soup_session_kick_queue (item->session); + + soup_message_queue_item_unref (item); + } +} + +/* requires conn_lock */ +static SoupConnection * +get_connection_for_host (SoupSession *session, + SoupMessageQueueItem *item, + SoupSessionHost *host, + gboolean need_new_connection, + gboolean *try_cleanup) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupConnection *conn; - SoupSessionHost *host; GSList *conns; int num_pending = 0; - gboolean need_new_connection; if (priv->disposed) return FALSE; if (item->conn) { g_return_val_if_fail (soup_connection_get_state (item->conn) != SOUP_CONNECTION_DISCONNECTED, FALSE); - return TRUE; + return item->conn; } - need_new_connection = - (soup_message_get_flags (item->msg) & SOUP_MESSAGE_NEW_CONNECTION) || - (!(soup_message_get_flags (item->msg) & SOUP_MESSAGE_IDEMPOTENT) && - !SOUP_METHOD_IS_IDEMPOTENT (item->msg->method)); - - g_mutex_lock (&priv->conn_lock); - - host = get_host_for_message (session, item->msg); for (conns = host->connections; conns; conns = conns->next) { - if (!need_new_connection && soup_connection_get_state (conns->data) == SOUP_CONNECTION_IDLE) { - soup_connection_set_state (conns->data, SOUP_CONNECTION_IN_USE); - g_mutex_unlock (&priv->conn_lock); - soup_session_set_item_connection (session, item, conns->data); - soup_message_set_https_status (item->msg, item->conn); - return TRUE; - } else if (soup_connection_get_state (conns->data) == SOUP_CONNECTION_CONNECTING) + conn = conns->data; + + if (!need_new_connection && soup_connection_get_state (conn) == SOUP_CONNECTION_IDLE) { + soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); + return conn; + } else if (soup_connection_get_state (conn) == SOUP_CONNECTION_CONNECTING) num_pending++; } /* Limit the number of pending connections; num_messages / 2 * is somewhat arbitrary... */ - if (num_pending > host->num_messages / 2) { - g_mutex_unlock (&priv->conn_lock); - return FALSE; - } + if (num_pending > host->num_messages / 2) + return NULL; if (host->num_conns >= priv->max_conns_per_host) { if (need_new_connection) - *try_pruning = TRUE; - g_mutex_unlock (&priv->conn_lock); - return FALSE; + *try_cleanup = TRUE; + return NULL; } if (priv->num_conns >= priv->max_conns) { - *try_pruning = TRUE; - g_mutex_unlock (&priv->conn_lock); - return FALSE; + *try_cleanup = TRUE; + return NULL; } conn = g_object_new ( @@ -1347,6 +1592,10 @@ soup_session_get_connection (SoupSession *session, G_CALLBACK (connection_state_changed), session); + /* This is a debugging-related signal, and so can ignore the + * usual rule about not emitting signals while holding + * conn_lock. + */ g_signal_emit (session, signals[CONNECTION_CREATED], 0, conn); g_hash_table_insert (priv->conns, conn, host); @@ -1361,129 +1610,220 @@ soup_session_get_connection (SoupSession *session, host->keep_alive_src = NULL; } - g_mutex_unlock (&priv->conn_lock); - soup_session_set_item_connection (session, item, conn); - return TRUE; + return conn; } -SoupMessageQueue * -soup_session_get_queue (SoupSession *session) +static gboolean +get_connection (SoupMessageQueueItem *item, gboolean *should_cleanup) { + SoupSession *session = item->session; SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + SoupSessionHost *host; + SoupConnection *conn = NULL; + gboolean my_should_cleanup = FALSE; + gboolean need_new_connection; - return priv->queue; + need_new_connection = + (soup_message_get_flags (item->msg) & SOUP_MESSAGE_NEW_CONNECTION) || + (!(soup_message_get_flags (item->msg) & SOUP_MESSAGE_IDEMPOTENT) && + !SOUP_METHOD_IS_IDEMPOTENT (item->msg->method)); + + g_mutex_lock (&priv->conn_lock); + host = get_host_for_message (session, item->msg); + while (TRUE) { + conn = get_connection_for_host (session, item, host, + need_new_connection, + &my_should_cleanup); + if (conn || item->async) + break; + + if (my_should_cleanup) { + g_mutex_unlock (&priv->conn_lock); + soup_session_cleanup_connections (session, TRUE); + g_mutex_lock (&priv->conn_lock); + + my_should_cleanup = FALSE; + continue; + } + + g_cond_wait (&priv->conn_cond, &priv->conn_lock); + } + g_mutex_unlock (&priv->conn_lock); + + if (!conn) { + if (should_cleanup) + *should_cleanup = my_should_cleanup; + return FALSE; + } + + soup_session_set_item_connection (session, item, conn); + soup_message_set_https_status (item->msg, item->conn); + + if (soup_connection_get_state (item->conn) != SOUP_CONNECTION_NEW) { + item->state = SOUP_MESSAGE_READY; + return TRUE; + } + + item->state = SOUP_MESSAGE_CONNECTING; + + if (item->async) { + soup_message_queue_item_ref (item); + soup_connection_connect_async (item->conn, item->cancellable, + got_connection, item); + return FALSE; + } else { + guint status; + + status = soup_connection_connect_sync (item->conn, item->cancellable); + got_connection (item->conn, status, item); + + return TRUE; + } } void -soup_session_unqueue_item (SoupSession *session, - SoupMessageQueueItem *item) +soup_session_process_queue_item (SoupSession *session, + SoupMessageQueueItem *item, + gboolean *should_cleanup, + gboolean loop) { - SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - SoupSessionHost *host; + g_assert (item->session == session); - if (item->conn) { - if (item->msg->method != SOUP_METHOD_CONNECT || - !SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) - soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); - soup_session_set_item_connection (session, item, NULL); - } + do { + if (item->paused) + return; - if (item->state != SOUP_MESSAGE_FINISHED) { - g_warning ("finished an item with state %d", item->state); - return; - } + switch (item->state) { + case SOUP_MESSAGE_STARTING: + if (!get_connection (item, should_cleanup)) + return; + break; - soup_message_queue_remove (priv->queue, item); + case SOUP_MESSAGE_CONNECTED: + if (soup_connection_is_tunnelled (item->conn)) + tunnel_connect (item); + else + item->state = SOUP_MESSAGE_READY; + break; - g_mutex_lock (&priv->conn_lock); - host = get_host_for_message (session, item->msg); - host->num_messages--; - g_mutex_unlock (&priv->conn_lock); + case SOUP_MESSAGE_READY: + soup_message_set_https_status (item->msg, item->conn); + if (item->msg->status_code) { + if (item->msg->status_code == SOUP_STATUS_TRY_AGAIN) { + soup_message_cleanup_response (item->msg); + item->state = SOUP_MESSAGE_STARTING; + } else + item->state = SOUP_MESSAGE_FINISHING; + break; + } - /* g_signal_handlers_disconnect_by_func doesn't work if you - * have a metamarshal, meaning it doesn't work with - * soup_message_add_header_handler() - */ - g_signal_handlers_disconnect_matched (item->msg, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, item); - g_signal_emit (session, signals[REQUEST_UNQUEUED], 0, item->msg); - soup_message_queue_item_unref (item); + item->state = SOUP_MESSAGE_RUNNING; + + soup_session_send_queue_item (session, item, message_completed); + + if (item->new_api) { + if (item->async) + async_send_request_running (session, item); + return; + } + break; + + case SOUP_MESSAGE_RUNNING: + if (item->async) + return; + + g_warn_if_fail (item->new_api); + item->state = SOUP_MESSAGE_FINISHING; + break; + + case SOUP_MESSAGE_RESTARTING: + item->state = SOUP_MESSAGE_STARTING; + soup_message_restarted (item->msg); + break; + + case SOUP_MESSAGE_FINISHING: + item->state = SOUP_MESSAGE_FINISHED; + soup_message_finished (item->msg); + if (item->state != SOUP_MESSAGE_FINISHED) { + g_return_if_fail (!item->new_api); + break; + } + + soup_session_unqueue_item (session, item); + if (item->async && item->callback) + item->callback (session, item->msg, item->callback_data); + return; + + default: + /* Nothing to do with this message in any + * other state. + */ + g_warn_if_fail (item->async); + return; + } + } while (loop && item->state != SOUP_MESSAGE_FINISHED); } static void -proxy_connection_event (SoupConnection *conn, - GSocketClientEvent event, - GIOStream *connection, - gpointer user_data) +async_run_queue (SoupSession *session) { - SoupMessageQueueItem *item = user_data; + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + SoupMessageQueueItem *item; + SoupMessage *msg; + gboolean try_cleanup = TRUE, should_cleanup = FALSE; - soup_message_network_event (item->msg, event, connection); -} + g_object_ref (session); + soup_session_cleanup_connections (session, FALSE); -void -soup_session_set_item_connection (SoupSession *session, - SoupMessageQueueItem *item, - SoupConnection *conn) -{ - if (item->conn) { - g_signal_handlers_disconnect_by_func (item->conn, proxy_connection_event, item); - g_object_unref (item->conn); - } + try_again: + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) { + msg = item->msg; - item->conn = conn; + /* CONNECT messages are handled specially */ + if (msg->method == SOUP_METHOD_CONNECT) + continue; - if (item->conn) { - g_object_ref (item->conn); - g_signal_connect (item->conn, "event", - G_CALLBACK (proxy_connection_event), item); + if (item->async_context != soup_session_get_async_context (session)) + continue; + + soup_session_process_queue_item (session, item, &should_cleanup, TRUE); + } + + if (try_cleanup && should_cleanup) { + /* There is at least one message in the queue that + * could be sent if we cleanupd an idle connection from + * some other server. + */ + if (soup_session_cleanup_connections (session, TRUE)) { + try_cleanup = should_cleanup = FALSE; + goto try_again; + } } + + g_object_unref (session); } -void -soup_session_set_item_status (SoupSession *session, - SoupMessageQueueItem *item, - guint status_code) +static gboolean +idle_run_queue (gpointer user_data) { - SoupURI *uri; - char *msg; + SoupSessionPrivate *priv = user_data; + GSource *source; - switch (status_code) { - case SOUP_STATUS_CANT_RESOLVE: - case SOUP_STATUS_CANT_CONNECT: - uri = soup_message_get_uri (item->msg); - msg = g_strdup_printf ("%s (%s)", - soup_status_get_phrase (status_code), - uri->host); - soup_message_set_status_full (item->msg, status_code, msg); - g_free (msg); - break; + if (priv->disposed) + return FALSE; - case SOUP_STATUS_CANT_RESOLVE_PROXY: - case SOUP_STATUS_CANT_CONNECT_PROXY: - if (item->proxy_uri && item->proxy_uri->host) { - msg = g_strdup_printf ("%s (%s)", - soup_status_get_phrase (status_code), - item->proxy_uri->host); - soup_message_set_status_full (item->msg, status_code, msg); - g_free (msg); - break; - } - soup_message_set_status (item->msg, status_code); - break; + source = g_main_current_source (); + priv->run_queue_sources = g_slist_remove (priv->run_queue_sources, source); - case SOUP_STATUS_SSL_FAILED: - if (!g_tls_backend_supports_tls (g_tls_backend_get_default ())) { - soup_message_set_status_full (item->msg, status_code, - "TLS/SSL support not available; install glib-networking"); - } else - soup_message_set_status (item->msg, status_code); - break; + /* Ensure that the source is destroyed before running the queue */ + g_source_destroy (source); + g_source_unref (source); - default: - soup_message_set_status (item->msg, status_code); - break; - } + g_assert (priv->session); + async_run_queue (priv->session); + return FALSE; } /** @@ -1517,7 +1857,7 @@ void soup_session_queue_message (SoupSession *session, SoupMessage *msg, SoupSessionCallback callback, gpointer user_data) { - g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (SOUP_IS_SESSION_ASYNC (session) || SOUP_IS_SESSION_SYNC (session)); g_return_if_fail (SOUP_IS_MESSAGE (msg)); SOUP_SESSION_GET_CLASS (session)->queue_message (session, msg, @@ -1557,7 +1897,6 @@ soup_session_requeue_message (SoupSession *session, SoupMessage *msg) SOUP_SESSION_GET_CLASS (session)->requeue_message (session, msg); } - /** * soup_session_send_message: * @session: a #SoupSession @@ -1574,7 +1913,7 @@ soup_session_requeue_message (SoupSession *session, SoupMessage *msg) guint soup_session_send_message (SoupSession *session, SoupMessage *msg) { - g_return_val_if_fail (SOUP_IS_SESSION (session), SOUP_STATUS_MALFORMED); + g_return_val_if_fail (SOUP_IS_SESSION_ASYNC (session) || SOUP_IS_SESSION_SYNC (session), SOUP_STATUS_MALFORMED); g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_STATUS_MALFORMED); return SOUP_SESSION_GET_CLASS (session)->send_message (session, msg); @@ -1609,6 +1948,48 @@ soup_session_pause_message (SoupSession *session, soup_message_queue_item_unref (item); } +static void +soup_session_real_kick_queue (SoupSession *session) +{ + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + SoupMessageQueueItem *item; + gboolean have_sync_items = FALSE; + + if (priv->disposed) + return; + + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) { + if (item->async) { + GSource *source; + + /* We use priv rather than session as the + * source data, because other parts of libsoup + * (or the calling app) may have sources using + * the session as the source data. + */ + source = g_main_context_find_source_by_user_data (item->async_context, priv); + if (!source) { + source = soup_add_completion_reffed (item->async_context, + idle_run_queue, priv); + priv->run_queue_sources = g_slist_prepend (priv->run_queue_sources, + source); + } + } else + have_sync_items = TRUE; + } + + if (have_sync_items) + g_cond_broadcast (&priv->conn_cond); +} + +void +soup_session_kick_queue (SoupSession *session) +{ + SOUP_SESSION_GET_CLASS (session)->kick (session); +} + /** * soup_session_unpause_message: * @session: a #SoupSession @@ -1640,7 +2021,7 @@ soup_session_unpause_message (SoupSession *session, soup_message_io_unpause (msg); soup_message_queue_item_unref (item); - SOUP_SESSION_GET_CLASS (session)->kick (session); + soup_session_kick_queue (session); } @@ -1657,6 +2038,7 @@ soup_session_real_cancel_message (SoupSession *session, SoupMessage *msg, guint soup_message_set_status (msg, status_code); g_cancellable_cancel (item->cancellable); + soup_session_kick_queue (item->session); soup_message_queue_item_unref (item); } @@ -1716,13 +2098,52 @@ soup_session_real_flush_queue (SoupSession *session) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupMessageQueueItem *item; + GHashTable *current = NULL; + gboolean done = FALSE; + + if (SOUP_IS_SESSION_SYNC (session)) { + /* Record the current contents of the queue */ + current = g_hash_table_new (NULL, NULL); + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) + g_hash_table_insert (current, item, item); + } + /* Cancel everything */ for (item = soup_message_queue_first (priv->queue); item; item = soup_message_queue_next (priv->queue, item)) { soup_session_cancel_message (session, item->msg, SOUP_STATUS_CANCELLED); } + + if (SOUP_IS_SESSION_SYNC (session)) { + /* Wait until all of the items in @current have been + * removed from the queue. (This is not the same as + * "wait for the queue to be empty", because the app + * may queue new requests in response to the + * cancellation of the old ones. We don't try to + * cancel those requests as well, since we'd likely + * just end up looping forever.) + */ + g_mutex_lock (&priv->conn_lock); + do { + done = TRUE; + for (item = soup_message_queue_first (priv->queue); + item; + item = soup_message_queue_next (priv->queue, item)) { + if (g_hash_table_lookup (current, item)) + done = FALSE; + } + + if (!done) + g_cond_wait (&priv->conn_cond, &priv->conn_lock); + } while (!done); + g_mutex_unlock (&priv->conn_lock); + + g_hash_table_destroy (current); + } } /** @@ -2107,6 +2528,7 @@ soup_session_class_init (SoupSessionClass *session_class) session_class->cancel_message = soup_session_real_cancel_message; session_class->auth_required = soup_session_real_auth_required; session_class->flush_queue = soup_session_real_flush_queue; + session_class->kick = soup_session_real_kick_queue; /* virtual method override */ object_class->dispose = soup_session_dispose; @@ -2808,3 +3230,384 @@ soup_session_class_init (SoupSessionClass *session_class) G_TYPE_STRV, G_PARAM_READWRITE)); } + + +/* send_request_async */ + +static void +async_send_request_return_result (SoupMessageQueueItem *item, + gpointer stream, GError *error) +{ + GTask *task; + + g_return_if_fail (item->task != NULL); + + g_signal_handlers_disconnect_matched (item->msg, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, item); + + task = item->task; + item->task = NULL; + + if (item->io_source) { + g_source_destroy (item->io_source); + g_clear_pointer (&item->io_source, g_source_unref); + } + + if (error) + g_task_return_error (task, error); + else if (SOUP_STATUS_IS_TRANSPORT_ERROR (item->msg->status_code)) { + if (stream) + g_object_unref (stream); + g_task_return_new_error (task, SOUP_HTTP_ERROR, + item->msg->status_code, + "%s", + item->msg->reason_phrase); + } else + g_task_return_pointer (task, stream, g_object_unref); + g_object_unref (task); +} + +static void +async_send_request_restarted (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + /* We won't be needing this, then. */ + g_object_set_data (G_OBJECT (item->msg), "SoupSession:ostream", NULL); + item->io_started = FALSE; +} + +static void +async_send_request_finished (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + GMemoryOutputStream *mostream; + GInputStream *istream = NULL; + GError *error = NULL; + + if (!item->task) { + /* Something else already took care of it. */ + return; + } + + mostream = g_object_get_data (G_OBJECT (item->task), "SoupSession:ostream"); + if (mostream) { + gpointer data; + gssize size; + + /* We thought it would be requeued, but it wasn't, so + * return the original body. + */ + size = g_memory_output_stream_get_data_size (mostream); + data = size ? g_memory_output_stream_steal_data (mostream) : g_strdup (""); + istream = g_memory_input_stream_new_from_data (data, size, g_free); + } else if (item->io_started) { + /* The message finished before becoming readable. This + * will happen, eg, if it's cancelled from got-headers. + * Do nothing; the op will complete via read_ready_cb() + * after we return; + */ + return; + } else { + /* The message finished before even being started; + * probably a tunnel connect failure. + */ + istream = g_memory_input_stream_new (); + } + + async_send_request_return_result (item, istream, error); +} + +static void +send_async_spliced (GObject *source, GAsyncResult *result, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + GInputStream *istream = g_object_get_data (source, "istream"); + GError *error = NULL; + + /* It should be safe to call the sync close() method here since + * the message body has already been written. + */ + g_input_stream_close (istream, NULL, NULL); + g_object_unref (istream); + + /* If the message was cancelled, it will be completed via other means */ + if (g_cancellable_is_cancelled (item->cancellable) || + !item->task) { + soup_message_queue_item_unref (item); + return; + } + + if (g_output_stream_splice_finish (G_OUTPUT_STREAM (source), + result, &error) == -1) { + async_send_request_return_result (item, NULL, error); + soup_message_queue_item_unref (item); + return; + } + + /* Otherwise either restarted or finished will eventually be called. */ + soup_session_kick_queue (item->session); + soup_message_queue_item_unref (item); +} + +static void +send_async_maybe_complete (SoupMessageQueueItem *item, + GInputStream *stream) +{ + if (item->msg->status_code == SOUP_STATUS_UNAUTHORIZED || + item->msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED || + soup_session_would_redirect (item->session, item->msg)) { + GOutputStream *ostream; + + /* Message may be requeued, so gather the current message body... */ + ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); + g_object_set_data_full (G_OBJECT (item->task), "SoupSession:ostream", + ostream, g_object_unref); + + g_object_set_data (G_OBJECT (ostream), "istream", stream); + + /* Give the splice op its own ref on item */ + soup_message_queue_item_ref (item); + g_output_stream_splice_async (ostream, stream, + /* We can't use CLOSE_SOURCE because it + * might get closed in the wrong thread. + */ + G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, + G_PRIORITY_DEFAULT, + item->cancellable, + send_async_spliced, item); + return; + } + + async_send_request_return_result (item, stream, NULL); +} + +static void try_run_until_read (SoupMessageQueueItem *item); + +static gboolean +read_ready_cb (SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + + g_clear_pointer (&item->io_source, g_source_unref); + try_run_until_read (item); + return FALSE; +} + +static void +try_run_until_read (SoupMessageQueueItem *item) +{ + GError *error = NULL; + GInputStream *stream = NULL; + + if (soup_message_io_run_until_read (item->msg, item->cancellable, &error)) + stream = soup_message_io_get_response_istream (item->msg, &error); + if (stream) { + send_async_maybe_complete (item, stream); + return; + } + + if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) { + item->state = SOUP_MESSAGE_RESTARTING; + soup_message_io_finished (item->msg); + g_error_free (error); + return; + } + + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + if (item->state != SOUP_MESSAGE_FINISHED) { + if (soup_message_io_in_progress (item->msg)) + soup_message_io_finished (item->msg); + item->state = SOUP_MESSAGE_FINISHING; + soup_session_process_queue_item (item->session, item, NULL, FALSE); + } + async_send_request_return_result (item, NULL, error); + return; + } + + g_clear_error (&error); + item->io_source = soup_message_io_get_source (item->msg, item->cancellable, + read_ready_cb, item); + g_source_attach (item->io_source, soup_session_get_async_context (item->session)); +} + +static void +async_send_request_running (SoupSession *session, SoupMessageQueueItem *item) +{ + item->io_started = TRUE; + try_run_until_read (item); +} + +void +soup_session_send_request_async (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupMessageQueueItem *item; + gboolean use_thread_context; + + g_return_if_fail (SOUP_IS_SESSION (session)); + g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); + + g_object_get (G_OBJECT (session), + SOUP_SESSION_USE_THREAD_CONTEXT, &use_thread_context, + NULL); + g_return_if_fail (use_thread_context); + + item = soup_session_append_queue_item (session, msg, TRUE, TRUE, + NULL, NULL); + g_signal_connect (msg, "restarted", + G_CALLBACK (async_send_request_restarted), item); + g_signal_connect (msg, "finished", + G_CALLBACK (async_send_request_finished), item); + + item->new_api = TRUE; + item->task = g_task_new (session, cancellable, callback, user_data); + g_task_set_task_data (item->task, item, (GDestroyNotify) soup_message_queue_item_unref); + + if (cancellable) { + g_object_unref (item->cancellable); + item->cancellable = g_object_ref (cancellable); + } + + soup_session_kick_queue (session); +} + +GInputStream * +soup_session_send_request_finish (SoupSession *session, + GAsyncResult *result, + GError **error) +{ + GTask *task; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + g_return_val_if_fail (!SOUP_IS_SESSION_SYNC (session), NULL); + g_return_val_if_fail (g_task_is_valid (result, session), NULL); + + task = G_TASK (result); + if (g_task_had_error (task)) { + SoupMessageQueueItem *item = g_task_get_task_data (task); + + if (soup_message_io_in_progress (item->msg)) + soup_message_io_finished (item->msg); + else if (item->state != SOUP_MESSAGE_FINISHED) + item->state = SOUP_MESSAGE_FINISHING; + + if (item->state != SOUP_MESSAGE_FINISHED) + soup_session_process_queue_item (session, item, NULL, FALSE); + } + + return g_task_propagate_pointer (task, error); +} + +GInputStream * +soup_session_send_request (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GError **error) +{ + SoupMessageQueueItem *item; + GInputStream *stream = NULL; + GOutputStream *ostream; + GMemoryOutputStream *mostream; + gssize size; + GError *my_error = NULL; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + g_return_val_if_fail (!SOUP_IS_SESSION_ASYNC (session), NULL); + + item = soup_session_append_queue_item (session, msg, FALSE, TRUE, + NULL, NULL); + + item->new_api = TRUE; + if (cancellable) { + g_object_unref (item->cancellable); + item->cancellable = g_object_ref (cancellable); + } + + while (!stream) { + /* Get a connection, etc */ + soup_session_process_queue_item (session, item, NULL, TRUE); + if (item->state != SOUP_MESSAGE_RUNNING) + break; + + /* Send request, read headers */ + if (!soup_message_io_run_until_read (msg, item->cancellable, &my_error)) { + if (g_error_matches (my_error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) { + item->state = SOUP_MESSAGE_RESTARTING; + soup_message_io_finished (item->msg); + g_clear_error (&my_error); + continue; + } else + break; + } + + stream = soup_message_io_get_response_istream (msg, &my_error); + if (!stream) + break; + + /* Break if the message doesn't look likely-to-be-requeued */ + if (msg->status_code != SOUP_STATUS_UNAUTHORIZED && + msg->status_code != SOUP_STATUS_PROXY_UNAUTHORIZED && + !soup_session_would_redirect (session, msg)) + break; + + /* Gather the current message body... */ + ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); + if (g_output_stream_splice (ostream, stream, + G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | + G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, + item->cancellable, &my_error) == -1) { + g_object_unref (stream); + g_object_unref (ostream); + stream = NULL; + break; + } + g_object_unref (stream); + stream = NULL; + + /* If the message was requeued, loop */ + if (item->state == SOUP_MESSAGE_RESTARTING) { + g_object_unref (ostream); + continue; + } + + /* Not requeued, so return the original body */ + mostream = G_MEMORY_OUTPUT_STREAM (ostream); + size = g_memory_output_stream_get_data_size (mostream); + stream = g_memory_input_stream_new (); + if (size) { + g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (stream), + g_memory_output_stream_steal_data (mostream), + size, g_free); + } + g_object_unref (ostream); + } + + if (my_error) + g_propagate_error (error, my_error); + else if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { + if (stream) { + g_object_unref (stream); + stream = NULL; + } + g_set_error_literal (error, SOUP_HTTP_ERROR, msg->status_code, + msg->reason_phrase); + } else if (!stream) + stream = g_memory_input_stream_new (); + + if (!stream) { + if (soup_message_io_in_progress (msg)) + soup_message_io_finished (msg); + else if (item->state != SOUP_MESSAGE_FINISHED) + item->state = SOUP_MESSAGE_FINISHING; + + if (item->state != SOUP_MESSAGE_FINISHED) + soup_session_process_queue_item (session, item, NULL, TRUE); + } + + soup_message_queue_item_unref (item); + return stream; +} diff --git a/tests/requester-test.c b/tests/requester-test.c index bc45e9f6..a4379377 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -372,21 +372,22 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri) } static void -do_simple_test (const char *uri) +do_simple_test (const char *uri, gboolean plain_session) { SoupSession *session; - debug_printf (1, "Simple streaming test\n"); + debug_printf (1, "Simple streaming test with %s\n", + plain_session ? "SoupSession" : "SoupSessionAsync"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); do_test_for_thread_and_context (session, uri); soup_test_session_abort_unref (session); } -static gpointer -do_test_with_context (const char *uri) +static void +do_test_with_context_and_type (const char *uri, gboolean plain_session) { GMainContext *async_context; SoupSession *session; @@ -394,7 +395,7 @@ do_test_with_context (const char *uri) async_context = g_main_context_new (); g_main_context_push_thread_default (async_context); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_ASYNC_CONTEXT, async_context, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -404,25 +405,43 @@ do_test_with_context (const char *uri) g_main_context_pop_thread_default (async_context); g_main_context_unref (async_context); +} + +static gpointer +do_test_with_context (gpointer uri) +{ + do_test_with_context_and_type (uri, FALSE); + return NULL; +} + +static gpointer +do_plain_test_with_context (gpointer uri) +{ + do_test_with_context_and_type (uri, TRUE); return NULL; } static void -do_context_test (const char *uri) +do_context_test (const char *uri, gboolean plain_session) { - debug_printf (1, "Streaming with a non-default-context\n"); - do_test_with_context (uri); + debug_printf (1, "Streaming with a non-default-context with %s\n", + plain_session ? "SoupSession" : "SoupSessionAsync"); + if (plain_session) + do_plain_test_with_context ((gpointer)uri); + else + do_test_with_context ((gpointer)uri); } static void -do_thread_test (const char *uri) +do_thread_test (const char *uri, gboolean plain_session) { GThread *thread; - debug_printf (1, "Streaming in another thread\n"); + debug_printf (1, "Streaming in another thread with %s\n", + plain_session ? "SoupSession" : "SoupSessionAsync"); thread = g_thread_new ("do_test_with_context", - (GThreadFunc)do_test_with_context, + plain_session ? do_plain_test_with_context : do_test_with_context, (gpointer)uri); g_thread_join (thread); } @@ -542,16 +561,17 @@ do_sync_request (SoupSession *session, SoupRequest *request, } static void -do_sync_test (const char *uri_string) +do_sync_test (const char *uri_string, gboolean plain_session) { SoupSession *session; SoupRequester *requester; SoupRequest *request; SoupURI *uri; - debug_printf (1, "Sync streaming\n"); + debug_printf (1, "Sync streaming with %s\n", + plain_session ? "SoupSession" : "SoupSessionSync"); - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_SYNC, NULL); requester = soup_requester_new (); soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); g_object_unref (requester); @@ -614,10 +634,15 @@ main (int argc, char **argv) uri = g_strdup_printf ("http://127.0.0.1:%u/foo", soup_server_get_port (server)); - do_simple_test (uri); - do_thread_test (uri); - do_context_test (uri); - do_sync_test (uri); + do_simple_test (uri, FALSE); + do_thread_test (uri, FALSE); + do_context_test (uri, FALSE); + do_sync_test (uri, FALSE); + + do_simple_test (uri, TRUE); + do_thread_test (uri, TRUE); + do_context_test (uri, TRUE); + do_sync_test (uri, TRUE); g_free (uri); soup_buffer_free (response); -- cgit v1.2.1 From 6863c37db17db41ec027d3b17f0b9d5d0be96c72 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 6 Oct 2011 10:26:57 -0400 Subject: Make default property values/features more sane on plain SoupSession (can't do this for SoupSessionAsync/SoupSessionSync because of backward compatibility) Also, make it illegal to set certain deprecated properties on a plain SoupSession. --- libsoup/soup-session.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index f5d93d4d..eb26e8cb 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -120,6 +120,8 @@ typedef struct { } SoupSessionPrivate; #define SOUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION, SoupSessionPrivate)) +#define SOUP_IS_PLAIN_SESSION(o) (G_TYPE_FROM_INSTANCE (o) == SOUP_TYPE_SESSION) + static void free_host (SoupSessionHost *host); static void connection_state_changed (GObject *object, GParamSpec *param, gpointer user_data); @@ -232,6 +234,40 @@ soup_session_init (SoupSession *session) priv->http_aliases[1] = NULL; } +static GObject * +soup_session_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_params) +{ + GObject *object; + + object = G_OBJECT_CLASS (soup_session_parent_class)->constructor (type, n_construct_properties, construct_params); + + /* If this is a "plain" SoupSession, fix up the default + * properties values, etc. + */ + if (type == SOUP_TYPE_SESSION) { + SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + + g_clear_object (&priv->tlsdb); + priv->tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); + + g_clear_pointer (&priv->async_context, g_main_context_unref); + priv->async_context = g_main_context_ref_thread_default (); + priv->use_thread_context = TRUE; + + priv->io_timeout = priv->idle_timeout = 60; + + priv->http_aliases[0] = NULL; + + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); + soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_DEFAULT); + } + + return object; +} + static void soup_session_dispose (GObject *object) { @@ -492,6 +528,7 @@ soup_session_set_property (GObject *object, guint prop_id, SoupURI *uri; const char *user_agent; SoupSessionFeature *feature; + GMainContext *async_context; switch (prop_id) { case PROP_PROXY_URI: @@ -520,6 +557,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS priv->max_conns_per_host = g_value_get_int (value); break; case PROP_USE_NTLM: + g_return_if_fail (!SOUP_IS_PLAIN_SESSION (session)); feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER_NTLM); if (feature) { if (g_value_get_boolean (value)) @@ -542,11 +580,16 @@ G_GNUC_END_IGNORE_DEPRECATIONS priv->ssl_strict = g_value_get_boolean (value); break; case PROP_ASYNC_CONTEXT: - priv->async_context = g_value_get_pointer (value); + async_context = g_value_get_pointer (value); + if (async_context && async_context != g_main_context_get_thread_default ()) + g_return_if_fail (!SOUP_IS_PLAIN_SESSION (session)); + priv->async_context = async_context; if (priv->async_context) g_main_context_ref (priv->async_context); break; case PROP_USE_THREAD_CONTEXT: + if (!g_value_get_boolean (value)) + g_return_if_fail (!SOUP_IS_PLAIN_SESSION (session)); priv->use_thread_context = g_value_get_boolean (value); if (priv->use_thread_context) { if (priv->async_context) @@ -2531,6 +2574,7 @@ soup_session_class_init (SoupSessionClass *session_class) session_class->kick = soup_session_real_kick_queue; /* virtual method override */ + object_class->constructor = soup_session_constructor; object_class->dispose = soup_session_dispose; object_class->finalize = soup_session_finalize; object_class->set_property = soup_session_set_property; -- cgit v1.2.1 From e00cf242322f82f0800956b17d726f0437db683a Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 5 Dec 2011 16:00:40 -0500 Subject: Move SoupRequester API into SoupSession, declare SoupRequest stable Add soup_session_request() and soup_session_request_uri(), implementing basically the same behavior as soup_requester_request() and soup_requester_request_uri() (but without requiring a separate SoupSessionFeature), and remove the unstable-api ifdefs from soup-request*.h. SoupRequester still exists, but it is still guarded by the unstable-api ifdefs, and is just a dummy wrapper around the functionality that is now in SoupSession. --- docs/reference/libsoup-2.4-docs.sgml | 17 +-- docs/reference/libsoup-2.4-sections.txt | 33 ++--- libsoup/libsoup-2.4.sym | 5 + libsoup/soup-cache.c | 2 - libsoup/soup-cache.h | 4 - libsoup/soup-request-data.c | 4 +- libsoup/soup-request-data.h | 4 - libsoup/soup-request-file.c | 6 +- libsoup/soup-request-file.h | 4 - libsoup/soup-request-http.c | 15 +-- libsoup/soup-request-http.h | 4 - libsoup/soup-request.c | 45 ++++--- libsoup/soup-request.h | 5 - libsoup/soup-requester.c | 213 ++++++-------------------------- libsoup/soup-requester.h | 6 +- libsoup/soup-session.c | 187 +++++++++++++++++++++++++++- libsoup/soup-session.h | 21 ++++ libsoup/soup-types.h | 1 + libsoup/soup.h | 5 + po/POTFILES.in | 2 +- tests/coding-test.c | 26 ++-- tests/connection-test.c | 9 +- tests/misc-test.c | 34 ++--- tests/proxy-test.c | 7 +- tests/redirect-test.c | 8 +- tests/requester-test.c | 51 ++++++-- tests/timeout-test.c | 32 ++--- 27 files changed, 380 insertions(+), 370 deletions(-) diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index ae74c015..3f246767 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -19,6 +19,7 @@ + @@ -26,6 +27,11 @@ + + + + + @@ -67,17 +73,6 @@ - - Experimental streaming API - - - - - - - - - Index diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 81f4b77e..237d3f06 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -386,11 +386,17 @@ SoupAddressClass SoupSession SoupSession +soup_session_request +soup_session_request_uri +SoupRequestError +SOUP_REQUEST_ERROR + SoupSessionCallback soup_session_queue_message soup_session_requeue_message soup_session_send_message soup_session_cancel_message + soup_session_prefetch_dns soup_session_prepare_for_uri soup_session_abort @@ -410,6 +416,7 @@ soup_session_remove_feature_by_type soup_session_get_features soup_session_get_feature soup_session_get_feature_for_message +soup_session_has_feature SOUP_SESSION_PROXY_URI SOUP_SESSION_MAX_CONNS @@ -440,6 +447,8 @@ SOUP_SESSION_GET_CLASS SOUP_TYPE_SESSION SoupSessionClass soup_session_get_type +soup_request_error_get_type +soup_request_error_quark SoupConnection SoupConnectionState @@ -1089,30 +1098,6 @@ SOUP_IS_PROXY_RESOLVER_DEFAULT SOUP_IS_PROXY_RESOLVER_DEFAULT_CLASS -
-soup-requester -SoupRequester -SoupRequester -soup_requester_new -soup_requester_request -soup_requester_request_uri - -SoupRequesterError -SOUP_REQUESTER_ERROR - -soup_requester_get_type -SoupRequesterClass -SoupRequesterPrivate -SOUP_TYPE_REQUESTER -SOUP_REQUESTER -SOUP_REQUESTER_CLASS -SOUP_REQUESTER_GET_CLASS -SOUP_IS_REQUESTER -SOUP_IS_REQUESTER_CLASS - -soup_requester_error_quark -
-
soup-request SoupRequest diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 62cb933e..24dcc17d 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -316,6 +316,8 @@ soup_requester_get_type soup_requester_new soup_requester_request soup_requester_request_uri +soup_request_error_get_type +soup_request_error_quark soup_request_file_get_file soup_request_file_get_type soup_request_get_content_length @@ -362,6 +364,7 @@ soup_session_get_feature soup_session_get_feature_for_message soup_session_get_features soup_session_get_type +soup_session_has_feature soup_session_pause_message soup_session_prefetch_dns soup_session_prepare_for_uri @@ -369,6 +372,8 @@ soup_session_queue_message soup_session_redirect_message soup_session_remove_feature soup_session_remove_feature_by_type +soup_session_request +soup_session_request_uri soup_session_requeue_message soup_session_send_message soup_session_sync_get_type diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 50ea5928..24a4b2c6 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -31,8 +31,6 @@ #include -#define LIBSOUP_USE_UNSTABLE_REQUEST_API - #include "soup-cache.h" #include "soup-cache-private.h" #include "soup.h" diff --git a/libsoup/soup-cache.h b/libsoup/soup-cache.h index 64dcb787..ce19b5e1 100644 --- a/libsoup/soup-cache.h +++ b/libsoup/soup-cache.h @@ -23,8 +23,6 @@ #ifndef SOUP_CACHE_H #define SOUP_CACHE_H 1 -#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API - #include #include @@ -100,7 +98,5 @@ guint soup_cache_get_max_size (SoupCache *cache); G_END_DECLS -#endif /* LIBSOUP_USE_UNSTABLE_REQUEST_API */ - #endif /* SOUP_CACHE_H */ diff --git a/libsoup/soup-request-data.c b/libsoup/soup-request-data.c index 933d7522..0ff30c94 100644 --- a/libsoup/soup-request-data.c +++ b/libsoup/soup-request-data.c @@ -25,9 +25,7 @@ #include #endif -#include - -#define LIBSOUP_USE_UNSTABLE_REQUEST_API +#include #include "soup-request-data.h" #include "soup.h" diff --git a/libsoup/soup-request-data.h b/libsoup/soup-request-data.h index f750b048..929c5908 100644 --- a/libsoup/soup-request-data.h +++ b/libsoup/soup-request-data.h @@ -22,8 +22,6 @@ #ifndef SOUP_REQUEST_DATA_H #define SOUP_REQUEST_DATA_H 1 -#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API - #include "soup-request.h" G_BEGIN_DECLS @@ -52,6 +50,4 @@ GType soup_request_data_get_type (void); G_END_DECLS -#endif /* LIBSOUP_USE_UNSTABLE_REQUEST_API */ - #endif /* SOUP_REQUEST_DATA_H */ diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c index 22642f47..a71827bb 100644 --- a/libsoup/soup-request-file.c +++ b/libsoup/soup-request-file.c @@ -25,10 +25,6 @@ #include #endif -#include - -#define LIBSOUP_USE_UNSTABLE_REQUEST_API - #include "soup-request-file.h" #include "soup.h" #include "soup-directory-input-stream.h" @@ -281,7 +277,7 @@ soup_request_file_class_init (SoupRequestFileClass *request_file_class) * * Return value: (transfer full): a #GFile corresponding to @file * - * Since: 2.34 + * Since: 2.40 */ GFile * soup_request_file_get_file (SoupRequestFile *file) diff --git a/libsoup/soup-request-file.h b/libsoup/soup-request-file.h index e86c5978..df2cbab1 100644 --- a/libsoup/soup-request-file.h +++ b/libsoup/soup-request-file.h @@ -22,8 +22,6 @@ #ifndef SOUP_REQUEST_FILE_H #define SOUP_REQUEST_FILE_H 1 -#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API - #include "soup-request.h" G_BEGIN_DECLS @@ -55,6 +53,4 @@ GFile *soup_request_file_get_file (SoupRequestFile *file); G_END_DECLS -#endif /* LIBSOUP_USE_UNSTABLE_REQUEST_API */ - #endif /* SOUP_REQUEST_FILE_H */ diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index d817cd08..96ba251b 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -27,8 +27,6 @@ #include -#define LIBSOUP_USE_UNSTABLE_REQUEST_API - #include "soup-request-http.h" #include "soup.h" #include "soup-cache-private.h" @@ -91,9 +89,11 @@ soup_request_http_send (SoupRequest *request, GError **error) { SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); + SoupSession *session = soup_request_get_session (request); + + g_return_val_if_fail (!SOUP_IS_SESSION_ASYNC (session), NULL); - return soup_session_send_request (soup_request_get_session (request), - http->priv->msg, + return soup_session_send_request (session, http->priv->msg, cancellable, error); } @@ -187,17 +187,18 @@ soup_request_http_send_async (SoupRequest *request, gpointer user_data) { SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); + SoupSession *session = soup_request_get_session (request); GTask *task; SendAsyncData *sadata; GInputStream *stream; - SoupSession *session; SoupCache *cache; + g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); + task = g_task_new (request, cancellable, callback, user_data); sadata = g_slice_new0 (SendAsyncData); g_task_set_task_data (task, sadata, (GDestroyNotify)free_send_async_data); - session = soup_request_get_session (request); cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); if (cache) { @@ -320,7 +321,7 @@ soup_request_http_class_init (SoupRequestHTTPClass *request_http_class) * * Returns: (transfer full): a new reference to the #SoupMessage * - * Since: 2.34 + * Since: 2.40 */ SoupMessage * soup_request_http_get_message (SoupRequestHTTP *http) diff --git a/libsoup/soup-request-http.h b/libsoup/soup-request-http.h index 750005af..bad4345c 100644 --- a/libsoup/soup-request-http.h +++ b/libsoup/soup-request-http.h @@ -22,8 +22,6 @@ #ifndef SOUP_REQUEST_HTTP_H #define SOUP_REQUEST_HTTP_H 1 -#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API - #include "soup-request.h" G_BEGIN_DECLS @@ -55,6 +53,4 @@ SoupMessage *soup_request_http_get_message (SoupRequestHTTP *http); G_END_DECLS -#endif /* LIBSOUP_USE_UNSTABLE_REQUEST_API */ - #endif /* SOUP_REQUEST_HTTP_H */ diff --git a/libsoup/soup-request.c b/libsoup/soup-request.c index dbc8361b..006a2537 100644 --- a/libsoup/soup-request.c +++ b/libsoup/soup-request.c @@ -27,8 +27,6 @@ #include -#define LIBSOUP_USE_UNSTABLE_REQUEST_API - #include "soup-request.h" #include "soup.h" #include "soup-requester.h" @@ -37,8 +35,8 @@ * SECTION:soup-request * @short_description: Protocol-independent streaming request interface * - * A #SoupRequest is created by #SoupRequester, and represents a - * request to retrieve a particular URI. + * A #SoupRequest is created by #SoupSession, and represents a request + * to retrieve a particular URI. */ /** @@ -46,7 +44,7 @@ * * A request to retrieve a particular URI. * - * Since: 2.34 + * Since: 2.42 */ static void soup_request_initable_interface_init (GInitableIface *initable_interface); @@ -138,7 +136,7 @@ soup_request_initable_init (GInitable *initable, gboolean ok; if (!request->priv->uri) { - g_set_error (error, SOUP_REQUESTER_ERROR, SOUP_REQUESTER_ERROR_BAD_URI, + g_set_error (error, SOUP_REQUEST_ERROR, SOUP_REQUEST_ERROR_BAD_URI, _("No URI provided")); return FALSE; } @@ -148,7 +146,7 @@ soup_request_initable_init (GInitable *initable, if (!ok && error && !*error) { char *uri_string = soup_uri_to_string (request->priv->uri, FALSE); - g_set_error (error, SOUP_REQUESTER_ERROR, SOUP_REQUESTER_ERROR_BAD_URI, + g_set_error (error, SOUP_REQUEST_ERROR, SOUP_REQUEST_ERROR_BAD_URI, _("Invalid '%s' URI: %s"), request->priv->uri->scheme, uri_string); @@ -204,10 +202,13 @@ soup_request_default_send_finish (SoupRequest *request, * Synchronously requests the URI pointed to by @request, and returns * a #GInputStream that can be used to read its contents. * + * Note that you cannot use this method with #SoupRequests attached to + * a #SoupSessionAsync. + * * Return value: (transfer full): a #GInputStream that can be used to * read from the URI pointed to by @request. * - * Since: 2.34 + * Since: 2.42 */ GInputStream * soup_request_send (SoupRequest *request, @@ -228,7 +229,10 @@ soup_request_send (SoupRequest *request, * Begins an asynchronously request for the URI pointed to by * @request. * - * Since: 2.34 + * Note that you cannot use this method with #SoupRequests attached to + * a #SoupSessionSync. + * + * Since: 2.42 */ void soup_request_send_async (SoupRequest *request, @@ -251,7 +255,7 @@ soup_request_send_async (SoupRequest *request, * Return value: (transfer full): a #GInputStream that can be used to * read from the URI pointed to by @request. * - * Since: 2.34 + * Since: 2.42 */ GInputStream * soup_request_send_finish (SoupRequest *request, @@ -307,7 +311,7 @@ soup_request_initable_interface_init (GInitableIface *initable_interface) * * Return value: (transfer none): @request's URI * - * Since: 2.34 + * Since: 2.42 */ SoupURI * soup_request_get_uri (SoupRequest *request) @@ -323,7 +327,7 @@ soup_request_get_uri (SoupRequest *request) * * Return value: (transfer none): @request's #SoupSession * - * Since: 2.34 + * Since: 2.42 */ SoupSession * soup_request_get_session (SoupRequest *request) @@ -335,12 +339,14 @@ soup_request_get_session (SoupRequest *request) * soup_request_get_content_length: * @request: a #SoupRequest * - * Gets the length of the data represented by @request. + * Gets the length of the data represented by @request. For most + * request types, this will not be known until after you call + * soup_request_send() or soup_request_send_finish(). * * Return value: the length of the data represented by @request, * or -1 if not known. * - * Since: 2.34 + * Since: 2.42 */ goffset soup_request_get_content_length (SoupRequest *request) @@ -352,14 +358,17 @@ soup_request_get_content_length (SoupRequest *request) * soup_request_get_content_type: * @request: a #SoupRequest * - * Gets the type of the data represented by @request. As in the - * HTTP Content-Type header, this may include parameters after - * the MIME type. + * Gets the type of the data represented by @request. For most request + * types, this will not be known until after you call + * soup_request_send() or soup_request_send_finish(). + * + * As in the HTTP Content-Type header, this may include parameters + * after the MIME type. * * Return value: the type of the data represented by @request, * or %NULL if not known. * - * Since: 2.34 + * Since: 2.42 */ const char * soup_request_get_content_type (SoupRequest *request) diff --git a/libsoup/soup-request.h b/libsoup/soup-request.h index bc6cdffe..84ad6d6b 100644 --- a/libsoup/soup-request.h +++ b/libsoup/soup-request.h @@ -22,8 +22,6 @@ #ifndef SOUP_REQUEST_H #define SOUP_REQUEST_H 1 -#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API - #include #include @@ -37,7 +35,6 @@ G_BEGIN_DECLS #define SOUP_IS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_REQUEST)) #define SOUP_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_REQUEST, SoupRequestClass)) -typedef struct _SoupRequest SoupRequest; typedef struct _SoupRequestPrivate SoupRequestPrivate; typedef struct _SoupRequestClass SoupRequestClass; @@ -103,6 +100,4 @@ const char *soup_request_get_content_type (SoupRequest *request); G_END_DECLS -#endif /* LIBSOUP_USE_UNSTABLE_REQUEST_API */ - #endif /* SOUP_REQUEST_H */ diff --git a/libsoup/soup-requester.c b/libsoup/soup-requester.c index 281ebb17..ce679821 100644 --- a/libsoup/soup-requester.c +++ b/libsoup/soup-requester.c @@ -22,22 +22,18 @@ #include "config.h" -#include - #define LIBSOUP_USE_UNSTABLE_REQUEST_API #include "soup-requester.h" #include "soup.h" -#include "soup-request-data.h" -#include "soup-request-file.h" -#include "soup-request-http.h" + +G_GNUC_BEGIN_IGNORE_DEPRECATIONS static SoupSessionFeatureInterface *soup_requester_default_feature_interface; static void soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); struct _SoupRequesterPrivate { SoupSession *session; - GHashTable *request_types; }; G_DEFINE_TYPE_WITH_CODE (SoupRequester, soup_requester, G_TYPE_OBJECT, @@ -47,44 +43,19 @@ G_DEFINE_TYPE_WITH_CODE (SoupRequester, soup_requester, G_TYPE_OBJECT, static void soup_requester_init (SoupRequester *requester) { - SoupSessionFeature *feature; - requester->priv = G_TYPE_INSTANCE_GET_PRIVATE (requester, SOUP_TYPE_REQUESTER, SoupRequesterPrivate); - - requester->priv->request_types = g_hash_table_new (soup_str_case_hash, - soup_str_case_equal); - - feature = SOUP_SESSION_FEATURE (requester); - soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_HTTP); - soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_FILE); - soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_DATA); -} - -static void -soup_requester_finalize (GObject *object) -{ - SoupRequester *requester = SOUP_REQUESTER (object); - - g_hash_table_destroy (requester->priv->request_types); - - G_OBJECT_CLASS (soup_requester_parent_class)->finalize (object); } static void soup_requester_class_init (SoupRequesterClass *requester_class) { - GObjectClass *object_class = G_OBJECT_CLASS (requester_class); - g_type_class_add_private (requester_class, sizeof (SoupRequesterPrivate)); - - /* virtual method override */ - object_class->finalize = soup_requester_finalize; } static void -attach (SoupSessionFeature *feature, SoupSession *session) +soup_requester_attach (SoupSessionFeature *feature, SoupSession *session) { SoupRequester *requester = SOUP_REQUESTER (feature); @@ -94,7 +65,7 @@ attach (SoupSessionFeature *feature, SoupSession *session) } static void -detach (SoupSessionFeature *feature, SoupSession *session) +soup_requester_detach (SoupSessionFeature *feature, SoupSession *session) { SoupRequester *requester = SOUP_REQUESTER (feature); @@ -103,66 +74,6 @@ detach (SoupSessionFeature *feature, SoupSession *session) soup_requester_default_feature_interface->detach (feature, session); } -static gboolean -add_feature (SoupSessionFeature *feature, GType type) -{ - SoupRequester *requester = SOUP_REQUESTER (feature); - SoupRequestClass *request_class; - int i; - - if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) - return FALSE; - - request_class = g_type_class_ref (type); - for (i = 0; request_class->schemes[i]; i++) { - g_hash_table_insert (requester->priv->request_types, - (char *)request_class->schemes[i], - GSIZE_TO_POINTER (type)); - } - return TRUE; -} - -static gboolean -remove_feature (SoupSessionFeature *feature, GType type) -{ - SoupRequester *requester = SOUP_REQUESTER (feature); - SoupRequestClass *request_class; - int i, orig_size; - - if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) - return FALSE; - - request_class = g_type_class_peek (type); - if (!request_class) - return FALSE; - - orig_size = g_hash_table_size (requester->priv->request_types); - for (i = 0; request_class->schemes[i]; i++) { - g_hash_table_remove (requester->priv->request_types, - request_class->schemes[i]); - } - - return g_hash_table_size (requester->priv->request_types) != orig_size; -} - -static gboolean -has_feature (SoupSessionFeature *feature, GType type) -{ - SoupRequester *requester = SOUP_REQUESTER (feature); - GHashTableIter iter; - gpointer key, value; - - if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) - return FALSE; - - g_hash_table_iter_init (&iter, requester->priv->request_types); - while (g_hash_table_iter_next (&iter, &key, &value)) { - if (value == GSIZE_TO_POINTER (type)) - return TRUE; - } - return FALSE; -} - static void soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data) @@ -170,115 +81,65 @@ soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interf soup_requester_default_feature_interface = g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE); - feature_interface->attach = attach; - feature_interface->detach = detach; - feature_interface->add_feature = add_feature; - feature_interface->remove_feature = remove_feature; - feature_interface->has_feature = has_feature; + feature_interface->attach = soup_requester_attach; + feature_interface->detach = soup_requester_detach; } -/** - * soup_requester_new: - * - * Creates a new #SoupRequester object, which can be added to - * a #SoupSession with soup_session_add_feature(). - * - * Return value: the new #SoupRequester - * - * Since: 2.34 - */ SoupRequester * soup_requester_new (void) { return g_object_new (SOUP_TYPE_REQUESTER, NULL); } -/** - * soup_requester_request: - * @requester: a #SoupRequester - * @uri_string: a URI, in string form - * @error: return location for a #GError, or %NULL - * - * Creates a #SoupRequest for retrieving @uri_string. - * - * Return value: (transfer full): a new #SoupRequest, or - * %NULL on error. - * - * Since: 2.34 - */ +static void +translate_error (GError *error) +{ + if (error->domain != SOUP_REQUEST_ERROR) + return; + + error->domain = SOUP_REQUESTER_ERROR; + if (error->code == SOUP_REQUEST_ERROR_BAD_URI) + error->code = SOUP_REQUESTER_ERROR_BAD_URI; + else if (error->code == SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME) + error->code = SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME; + else + g_warn_if_reached (); +} + SoupRequest * soup_requester_request (SoupRequester *requester, const char *uri_string, GError **error) { - SoupURI *uri; SoupRequest *req; - uri = soup_uri_new (uri_string); - if (!uri) { - g_set_error (error, SOUP_REQUESTER_ERROR, SOUP_REQUESTER_ERROR_BAD_URI, - _("Could not parse URI '%s'"), uri_string); - return NULL; - } + g_return_val_if_fail (SOUP_IS_REQUESTER (requester), NULL); + + req = soup_session_request (requester->priv->session, + uri_string, error); + if (req || !error) + return req; - req = soup_requester_request_uri (requester, uri, error); - soup_uri_free (uri); - return req; + translate_error (*error); + return NULL; } -/** - * soup_requester_request_uri: - * @requester: a #SoupRequester - * @uri: a #SoupURI representing the URI to retrieve - * @error: return location for a #GError, or %NULL - * - * Creates a #SoupRequest for retrieving @uri. - * - * Return value: (transfer full): a new #SoupRequest, or - * %NULL on error. - * - * Since: 2.34 - */ SoupRequest * soup_requester_request_uri (SoupRequester *requester, SoupURI *uri, GError **error) { - GType request_type; + SoupRequest *req; g_return_val_if_fail (SOUP_IS_REQUESTER (requester), NULL); - request_type = (GType)GPOINTER_TO_SIZE (g_hash_table_lookup (requester->priv->request_types, uri->scheme)); - if (!request_type) { - g_set_error (error, SOUP_REQUESTER_ERROR, - SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME, - _("Unsupported URI scheme '%s'"), uri->scheme); - return NULL; - } + req = soup_session_request_uri (requester->priv->session, + uri, error); + if (req || !error) + return req; - return g_initable_new (request_type, NULL, error, - "uri", uri, - "session", requester->priv->session, - NULL); + translate_error (*error); + return NULL; } -/** - * SOUP_REQUESTER_ERROR: - * - * A #GError domain for #SoupRequester errors. Used with - * #SoupRequesterError. - * - * Since: 2.34 - */ -/** - * SoupRequesterError: - * @SOUP_REQUESTER_ERROR_BAD_URI: the URI could not be parsed - * @SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME: the URI scheme is not - * supported by this #SoupRequester - * - * A #SoupRequester error. - * - * Since: 2.34 - */ - GQuark soup_requester_error_quark (void) { @@ -287,3 +148,5 @@ soup_requester_error_quark (void) error = g_quark_from_static_string ("soup_requester_error_quark"); return error; } + +G_GNUC_END_IGNORE_DEPRECATIONS diff --git a/libsoup/soup-requester.h b/libsoup/soup-requester.h index 3bf249c8..06355131 100644 --- a/libsoup/soup-requester.h +++ b/libsoup/soup-requester.h @@ -24,7 +24,6 @@ #ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API #include -#include G_BEGIN_DECLS @@ -49,22 +48,27 @@ typedef struct { } SoupRequesterClass; SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42 GType soup_requester_get_type (void); SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42 SoupRequester *soup_requester_new (void); SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42_FOR(soup_session_request) SoupRequest *soup_requester_request (SoupRequester *requester, const char *uri_string, GError **error); SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42_FOR(soup_session_request_uri) SoupRequest *soup_requester_request_uri (SoupRequester *requester, SoupURI *uri, GError **error); SOUP_AVAILABLE_IN_2_34 +SOUP_DEPRECATED_IN_2_42_FOR(SOUP_REQUEST_ERROR) GQuark soup_requester_error_quark (void); #define SOUP_REQUESTER_ERROR soup_requester_error_quark () diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index eb26e8cb..20d1c062 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -78,6 +78,7 @@ static gboolean soup_host_uri_equal (gconstpointer v1, gconstpointer v2); typedef struct { SoupSession *session; + gboolean disposed; GTlsDatabase *tlsdb; char *ssl_ca_file; @@ -116,7 +117,7 @@ typedef struct { char **http_aliases, **https_aliases; - gboolean disposed; + GHashTable *request_types; } SoupSessionPrivate; #define SOUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION, SoupSessionPrivate)) @@ -232,6 +233,12 @@ soup_session_init (SoupSession *session) priv->http_aliases = g_new (char *, 2); priv->http_aliases[0] = (char *)g_intern_string ("*"); priv->http_aliases[1] = NULL; + + priv->request_types = g_hash_table_new (soup_str_case_hash, + soup_str_case_equal); + soup_session_add_feature_by_type (session, SOUP_TYPE_REQUEST_HTTP); + soup_session_add_feature_by_type (session, SOUP_TYPE_REQUEST_FILE); + soup_session_add_feature_by_type (session, SOUP_TYPE_REQUEST_DATA); } static GObject * @@ -322,6 +329,8 @@ soup_session_finalize (GObject *object) g_free (priv->http_aliases); g_free (priv->https_aliases); + g_hash_table_destroy (priv->request_types); + G_OBJECT_CLASS (soup_session_parent_class)->finalize (object); } @@ -2359,10 +2368,10 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature) * adds it to @session as with soup_session_add_feature(). You can use * this when you don't need to customize the new feature in any way. * - * If @feature_type is not a #SoupSessionFeature type, this gives - * each existing feature on @session the chance to accept @feature_type - * as a "subfeature". This can be used to add new #SoupAuth types, - * for instance. + * If @feature_type is not a #SoupSessionFeature type, this gives each + * existing feature on @session the chance to accept @feature_type as + * a "subfeature". This can be used to add new #SoupAuth or + * #SoupRequest types, for instance. * * You can also add a feature to the session at construct time by * using the %SOUP_SESSION_ADD_FEATURE_BY_TYPE property. @@ -2372,16 +2381,29 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature) void soup_session_add_feature_by_type (SoupSession *session, GType feature_type) { + SoupSessionPrivate *priv; + g_return_if_fail (SOUP_IS_SESSION (session)); + priv = SOUP_SESSION_GET_PRIVATE (session); + if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) { SoupSessionFeature *feature; feature = g_object_new (feature_type, NULL); soup_session_add_feature (session, feature); g_object_unref (feature); + } else if (g_type_is_a (feature_type, SOUP_TYPE_REQUEST)) { + SoupRequestClass *request_class; + int i; + + request_class = g_type_class_ref (feature_type); + for (i = 0; request_class->schemes[i]; i++) { + g_hash_table_insert (priv->request_types, + (char *)request_class->schemes[i], + GSIZE_TO_POINTER (feature_type)); + } } else { - SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); GSList *f; for (f = priv->features; f; f = f->next) { @@ -2447,6 +2469,17 @@ soup_session_remove_feature_by_type (SoupSession *session, GType feature_type) goto restart; } } + } else if (g_type_is_a (feature_type, SOUP_TYPE_REQUEST)) { + SoupRequestClass *request_class; + int i; + + request_class = g_type_class_peek (feature_type); + if (!request_class) + return; + for (i = 0; request_class->schemes[i]; i++) { + g_hash_table_remove (priv->request_types, + request_class->schemes[i]); + } } else { for (f = priv->features; f; f = f->next) { if (soup_session_feature_remove_feature (f->data, feature_type)) @@ -2456,6 +2489,49 @@ soup_session_remove_feature_by_type (SoupSession *session, GType feature_type) } } +/** + * soup_session_has_feature: + * @session: a #SoupSession + * @feature_type: the #GType of the class of features to check for + * + * Tests if @session has at a feature of type @feature_type (which can + * be the type of either a #SoupSessionFeature, or else a subtype of + * some class managed by another feature, such as #SoupAuth or + * #SoupRequest). + * + * Return value: %TRUE or %FALSE + * + * Since: 2.42 + **/ +gboolean +soup_session_has_feature (SoupSession *session, + GType feature_type) +{ + SoupSessionPrivate *priv; + GSList *f; + + g_return_val_if_fail (SOUP_IS_SESSION (session), FALSE); + + priv = SOUP_SESSION_GET_PRIVATE (session); + + if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) { + for (f = priv->features; f; f = f->next) { + if (G_TYPE_CHECK_INSTANCE_TYPE (f->data, feature_type)) + return TRUE; + } + } else if (g_type_is_a (feature_type, SOUP_TYPE_REQUEST)) { + return g_hash_table_lookup (priv->request_types, + GSIZE_TO_POINTER (feature_type)) != NULL; + } else { + for (f = priv->features; f; f = f->next) { + if (soup_session_feature_has_feature (f->data, feature_type)) + return TRUE; + } + } + + return FALSE; +} + /** * soup_session_get_features: * @session: a #SoupSession @@ -3655,3 +3731,102 @@ soup_session_send_request (SoupSession *session, soup_message_queue_item_unref (item); return stream; } + +/** + * soup_session_request: + * @session: a #SoupSession + * @uri_string: a URI, in string form + * @error: return location for a #GError, or %NULL + * + * Creates a #SoupRequest for retrieving @uri_string. + * + * Return value: (transfer full): a new #SoupRequest, or + * %NULL on error. + * + * Since: 2.42 + */ +SoupRequest * +soup_session_request (SoupSession *session, const char *uri_string, + GError **error) +{ + SoupURI *uri; + SoupRequest *req; + + uri = soup_uri_new (uri_string); + if (!uri) { + g_set_error (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_BAD_URI, + _("Could not parse URI '%s'"), uri_string); + return NULL; + } + + req = soup_session_request_uri (session, uri, error); + soup_uri_free (uri); + return req; +} + +/** + * soup_session_request_uri: + * @session: a #SoupSession + * @uri: a #SoupURI representing the URI to retrieve + * @error: return location for a #GError, or %NULL + * + * Creates a #SoupRequest for retrieving @uri. + * + * Return value: (transfer full): a new #SoupRequest, or + * %NULL on error. + * + * Since: 2.42 + */ +SoupRequest * +soup_session_request_uri (SoupSession *session, SoupURI *uri, + GError **error) +{ + SoupSessionPrivate *priv; + GType request_type; + + g_return_val_if_fail (SOUP_IS_SESSION (session), NULL); + + priv = SOUP_SESSION_GET_PRIVATE (session); + + request_type = (GType)GPOINTER_TO_SIZE (g_hash_table_lookup (priv->request_types, uri->scheme)); + if (!request_type) { + g_set_error (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME, + _("Unsupported URI scheme '%s'"), uri->scheme); + return NULL; + } + + return g_initable_new (request_type, NULL, error, + "uri", uri, + "session", session, + NULL); +} + +/** + * SOUP_REQUEST_ERROR: + * + * A #GError domain for #SoupRequest-related errors. Used with + * #SoupRequestError. + * + * Since: 2.42 + */ +/** + * SoupRequestError: + * @SOUP_REQUEST_ERROR_BAD_URI: the URI could not be parsed + * @SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME: the URI scheme is not + * supported by this #SoupSession + * + * A #SoupRequest error. + * + * Since: 2.42 + */ + +GQuark +soup_request_error_quark (void) +{ + static GQuark error; + if (!error) + error = g_quark_from_static_string ("soup_request_error_quark"); + return error; +} diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index 4dd79ffd..acc12a9a 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -134,6 +134,9 @@ void soup_session_remove_feature (SoupSession *ses SOUP_AVAILABLE_IN_2_24 void soup_session_remove_feature_by_type (SoupSession *session, GType feature_type); +SOUP_AVAILABLE_IN_2_42 +gboolean soup_session_has_feature (SoupSession *session, + GType feature_type); SOUP_AVAILABLE_IN_2_26 GSList *soup_session_get_features (SoupSession *session, GType feature_type); @@ -145,6 +148,24 @@ SoupSessionFeature *soup_session_get_feature_for_message(SoupSession *ses GType feature_type, SoupMessage *msg); +SOUP_AVAILABLE_IN_2_42 +SoupRequest *soup_session_request (SoupSession *session, + const char *uri_string, + GError **error); +SOUP_AVAILABLE_IN_2_42 +SoupRequest *soup_session_request_uri (SoupSession *session, + SoupURI *uri, + GError **error); + +SOUP_AVAILABLE_IN_2_42 +GQuark soup_request_error_quark (void); +#define SOUP_REQUEST_ERROR soup_request_error_quark () + +typedef enum { + SOUP_REQUEST_ERROR_BAD_URI, + SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME +} SoupRequestError; + G_END_DECLS #endif /* SOUP_SESSION_H */ diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h index 77e5425b..4134b834 100644 --- a/libsoup/soup-types.h +++ b/libsoup/soup-types.h @@ -20,6 +20,7 @@ typedef struct _SoupCookie SoupCookie; typedef struct _SoupCookieJar SoupCookieJar; typedef struct _SoupDate SoupDate; typedef struct _SoupMessage SoupMessage; +typedef struct _SoupRequest SoupRequest; typedef struct _SoupServer SoupServer; typedef struct _SoupSession SoupSession; typedef struct _SoupSessionAsync SoupSessionAsync; diff --git a/libsoup/soup.h b/libsoup/soup.h index 2a2b051d..f99f3e68 100644 --- a/libsoup/soup.h +++ b/libsoup/soup.h @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -34,6 +35,10 @@ extern "C" { #include #include #include +#include +#include +#include +#include #include #include #include diff --git a/po/POTFILES.in b/po/POTFILES.in index a05aa79b..ba5d82dd 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,5 +2,5 @@ libsoup/soup-body-input-stream.c libsoup/soup-converter-wrapper.c libsoup/soup-message-io.c libsoup/soup-request.c -libsoup/soup-requester.c +libsoup/soup-session.c libsoup/soup-tld.c diff --git a/tests/coding-test.c b/tests/coding-test.c index cd7321ed..2718353b 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -397,7 +397,6 @@ static void do_coding_req_test (void) { SoupSession *session; - SoupRequester *requester; SoupRequest *req; SoupMessage *msg; SoupURI *uri; @@ -407,21 +406,19 @@ do_coding_req_test (void) session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, NULL); - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); uri = soup_uri_new_with_base (base_uri, "/mbox"); /* Plain text data, no claim */ debug_printf (1, " GET /mbox, plain\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); plain = do_single_coding_req_test (req, NULL, "text/plain", EXPECT_NOT_DECODED); g_object_unref (req); /* Plain text data, claim gzip */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n"); soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed"); g_byte_array_free (cmp, TRUE); @@ -429,7 +426,7 @@ do_coding_req_test (void) /* Plain text data, claim gzip w/ junk */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_headers_append (msg->request_headers, "X-Test-Options", "trailing-junk"); @@ -441,7 +438,7 @@ do_coding_req_test (void) /* Plain text data, claim gzip with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_headers_append (msg->request_headers, "X-Test-Options", "force-encode"); @@ -458,7 +455,7 @@ do_coding_req_test (void) /* Plain text data, claim deflate */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_headers_append (msg->request_headers, "X-Test-Options", "prefer-deflate-zlib"); @@ -470,7 +467,7 @@ do_coding_req_test (void) /* Plain text data, claim deflate w/ junk */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_headers_append (msg->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); @@ -482,7 +479,7 @@ do_coding_req_test (void) /* Plain text data, claim deflate with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_headers_append (msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); @@ -494,7 +491,7 @@ do_coding_req_test (void) /* Plain text data, claim deflate (no zlib headers)*/ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_headers_append (msg->request_headers, "X-Test-Options", "prefer-deflate-raw"); @@ -506,7 +503,7 @@ do_coding_req_test (void) /* Plain text data, claim deflate with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_headers_append (msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-raw"); @@ -528,7 +525,6 @@ do_coding_empty_test (void) SoupSession *session; SoupMessage *msg; SoupURI *uri; - SoupRequester *requester; SoupRequest *req; GByteArray *body; @@ -537,9 +533,7 @@ do_coding_empty_test (void) session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, NULL); - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); uri = soup_uri_new_with_base (base_uri, "/mbox"); debug_printf (1, " SoupMessage\n"); @@ -551,7 +545,7 @@ do_coding_empty_test (void) g_object_unref (msg); debug_printf (1, " SoupRequest\n"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_headers_append (msg->request_headers, "X-Test-Options", "empty"); diff --git a/tests/connection-test.c b/tests/connection-test.c index 8050b3df..6b57f24d 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -299,7 +299,6 @@ do_timeout_test_for_session (SoupSession *session) static void do_timeout_req_test_for_session (SoupSession *session) { - SoupRequester *requester; SoupRequest *req; SoupMessage *msg; GInputStream *stream; @@ -308,17 +307,13 @@ do_timeout_req_test_for_session (SoupSession *session) GError *error = NULL; int i; - requester = soup_requester_new (); - soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); - g_object_unref (requester); - g_signal_connect (session, "request-started", G_CALLBACK (request_started_socket_collector), &sockets); debug_printf (1, " First request\n"); timeout_uri = soup_uri_new_with_base (base_uri, "/timeout-persistent"); - req = soup_requester_request_uri (requester, timeout_uri, NULL); + req = soup_session_request_uri (session, timeout_uri, NULL); soup_uri_free (timeout_uri); stream = soup_test_request_send (req, NULL, &error); @@ -346,7 +341,7 @@ do_timeout_req_test_for_session (SoupSession *session) g_object_unref (req); debug_printf (1, " Second request\n"); - req = soup_requester_request_uri (requester, base_uri, NULL); + req = soup_session_request_uri (session, base_uri, NULL); stream = soup_test_request_send (req, NULL, &error); if (!stream) { diff --git a/tests/misc-test.c b/tests/misc-test.c index b564f269..b243ce46 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -318,7 +318,6 @@ do_callback_unref_req_test (void) SoupServer *bad_server; SoupAddress *addr; SoupSession *session; - SoupRequester *requester; SoupRequest *one, *two; GMainLoop *loop; char *bad_uri; @@ -337,18 +336,15 @@ do_callback_unref_req_test (void) g_object_unref (bad_server); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session); - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); - loop = g_main_loop_new (NULL, TRUE); - one = soup_requester_request (requester, bad_uri, NULL); + one = soup_session_request (session, bad_uri, NULL); g_object_add_weak_pointer (G_OBJECT (one), (gpointer *)&one); - two = soup_requester_request (requester, bad_uri, NULL); + two = soup_session_request (session, bad_uri, NULL); g_object_add_weak_pointer (G_OBJECT (two), (gpointer *)&two); g_free (bad_uri); @@ -708,7 +704,6 @@ static void do_early_abort_req_test (void) { SoupSession *session; - SoupRequester *requester; SoupRequest *req; GMainContext *context; GMainLoop *loop; @@ -717,11 +712,9 @@ do_early_abort_req_test (void) debug_printf (1, "\nAbort with pending connection (request api)\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); - req = soup_requester_request_uri (requester, base_uri, NULL); + req = soup_session_request_uri (session, base_uri, NULL); context = g_main_context_default (); loop = g_main_loop_new (context, TRUE); @@ -735,11 +728,9 @@ do_early_abort_req_test (void) soup_test_session_abort_unref (session); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); - req = soup_requester_request_uri (requester, base_uri, NULL); + req = soup_session_request_uri (session, base_uri, NULL); g_signal_connect (session, "connection-created", G_CALLBACK (ea_connection_created), NULL); @@ -753,11 +744,9 @@ do_early_abort_req_test (void) soup_test_session_abort_unref (session); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); - req = soup_requester_request_uri (requester, base_uri, NULL); + req = soup_session_request_uri (session, base_uri, NULL); cancellable = g_cancellable_new (); g_signal_connect (session, "request-started", @@ -933,7 +922,7 @@ cancel_request_thread (gpointer cancellable) } static void -do_cancel_while_reading_req_test_for_session (SoupRequester *requester) +do_cancel_while_reading_req_test_for_session (SoupSession *session) { SoupRequest *req; SoupURI *uri; @@ -941,7 +930,7 @@ do_cancel_while_reading_req_test_for_session (SoupRequester *requester) GError *error = NULL; uri = soup_uri_new_with_base (base_uri, "/slow"); - req = soup_requester_request_uri (requester, uri, NULL); + req = soup_session_request_uri (session, uri, NULL); soup_uri_free (uri); cancellable = g_cancellable_new (); @@ -975,25 +964,20 @@ static void do_cancel_while_reading_req_test (void) { SoupSession *session; - SoupRequester *requester; debug_printf (1, "\nCancelling message while reading response (request api)\n"); debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); - do_cancel_while_reading_req_test_for_session (requester); + do_cancel_while_reading_req_test_for_session (session); soup_test_session_abort_unref (session); debug_printf (1, " Sync session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, NULL); - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); - do_cancel_while_reading_req_test_for_session (requester); + do_cancel_while_reading_req_test_for_session (session); soup_test_session_abort_unref (session); } diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 94e548a8..048acfa7 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -132,7 +132,6 @@ test_url_new_api (const char *url, int proxy, guint expected, SoupSession *session; SoupURI *proxy_uri; SoupMessage *msg; - SoupRequester *requester; SoupRequest *request; GInputStream *stream; GError *error = NULL; @@ -140,7 +139,7 @@ test_url_new_api (const char *url, int proxy, guint expected, if (!tls_available && g_str_has_prefix (url, "https:")) return; - debug_printf (1, " GET (requester API) %s via %s%s\n", url, proxy_names[proxy], + debug_printf (1, " GET (request API) %s via %s%s\n", url, proxy_names[proxy], close ? " (with Connection: close)" : ""); if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN) expected = SOUP_STATUS_PROXY_UNAUTHORIZED; @@ -150,7 +149,6 @@ test_url_new_api (const char *url, int proxy, guint expected, */ proxy_uri = soup_uri_new (proxies[proxy]); session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, SOUP_SESSION_PROXY_URI, proxy_uri, NULL); @@ -163,8 +161,7 @@ test_url_new_api (const char *url, int proxy, guint expected, G_CALLBACK (set_close_on_connect), NULL); } - requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); - request = soup_requester_request (requester, url, NULL); + request = soup_session_request (session, url, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); stream = soup_test_request_send (request, NULL, &error); diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 3708d865..9adf5d5a 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -208,7 +208,6 @@ do_message_api_test (SoupSession *session, SoupURI *base_uri, int n) static void do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) { - SoupRequester *requester = (SoupRequester *)soup_session_get_feature (session, SOUP_TYPE_REQUESTER); SoupURI *uri; SoupRequest *req; SoupMessage *msg; @@ -226,7 +225,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) final_status = tests[n].final_status; uri = soup_uri_new_with_base (base_uri, tests[n].requests[0].path); - req = soup_requester_request_uri (requester, uri, &error); + req = soup_session_request_uri (session, uri, &error); soup_uri_free (uri); if (!req) { debug_printf (1, " could not create request: %s\n", @@ -315,7 +314,6 @@ do_redirect_tests (SoupURI *base_uri) int n; session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); debug_printf (1, "Async session, SoupMessage\n"); @@ -326,9 +324,7 @@ do_redirect_tests (SoupURI *base_uri) do_request_api_test (session, base_uri, n); soup_test_session_abort_unref (session); - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER, - NULL); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); debug_printf (1, "\nSync session, SoupMessage\n"); for (n = 0; n < n_tests; n++) do_message_api_test (session, base_uri, n); diff --git a/tests/requester-test.c b/tests/requester-test.c index a4379377..660669a0 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -252,11 +252,17 @@ do_async_test (SoupSession *session, SoupURI *uri, SoupMessage *msg; RequestData data; - requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER)); + if (SOUP_IS_SESSION_ASYNC (session)) + requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER)); + else + requester = NULL; data.body = g_string_new (NULL); data.cancel = cancel; - request = soup_requester_request_uri (requester, uri, NULL); + if (requester) + request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); if (cancel) { @@ -326,9 +332,11 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri) SoupRequester *requester; SoupURI *uri; - requester = soup_requester_new (); - soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); - g_object_unref (requester); + if (SOUP_IS_SESSION_ASYNC (session)) { + requester = soup_requester_new (); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); + g_object_unref (requester); + } soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); debug_printf (1, " basic test\n"); @@ -572,14 +580,19 @@ do_sync_test (const char *uri_string, gboolean plain_session) plain_session ? "SoupSession" : "SoupSessionSync"); session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_SYNC, NULL); - requester = soup_requester_new (); - soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); - g_object_unref (requester); + if (!plain_session) { + requester = soup_requester_new (); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); + g_object_unref (requester); + } uri = soup_uri_new (uri_string); debug_printf (1, " basic test\n"); - request = soup_requester_request_uri (requester, uri, NULL); + if (plain_session) + request = soup_session_request_uri (session, uri, NULL); + else + request = soup_requester_request_uri (requester, uri, NULL); do_sync_request (session, request, SOUP_STATUS_OK, response, TRUE, FALSE); @@ -587,7 +600,10 @@ do_sync_test (const char *uri_string, gboolean plain_session) debug_printf (1, " chunked test\n"); soup_uri_set_path (uri, "/chunked"); - request = soup_requester_request_uri (requester, uri, NULL); + if (plain_session) + request = soup_session_request_uri (session, uri, NULL); + else + request = soup_requester_request_uri (requester, uri, NULL); do_sync_request (session, request, SOUP_STATUS_OK, response, TRUE, FALSE); @@ -595,7 +611,10 @@ do_sync_test (const char *uri_string, gboolean plain_session) debug_printf (1, " auth test\n"); soup_uri_set_path (uri, "/auth"); - request = soup_requester_request_uri (requester, uri, NULL); + if (plain_session) + request = soup_session_request_uri (session, uri, NULL); + else + request = soup_requester_request_uri (requester, uri, NULL); do_sync_request (session, request, SOUP_STATUS_UNAUTHORIZED, auth_response, TRUE, FALSE); @@ -603,7 +622,10 @@ do_sync_test (const char *uri_string, gboolean plain_session) debug_printf (1, " non-persistent test\n"); soup_uri_set_path (uri, "/non-persistent"); - request = soup_requester_request_uri (requester, uri, NULL); + if (plain_session) + request = soup_session_request_uri (session, uri, NULL); + else + request = soup_requester_request_uri (requester, uri, NULL); do_sync_request (session, request, SOUP_STATUS_OK, response, FALSE, FALSE); @@ -611,7 +633,10 @@ do_sync_test (const char *uri_string, gboolean plain_session) debug_printf (1, " cancel test\n"); soup_uri_set_path (uri, "/"); - request = soup_requester_request_uri (requester, uri, NULL); + if (plain_session) + request = soup_session_request_uri (session, uri, NULL); + else + request = soup_requester_request_uri (requester, uri, NULL); do_sync_request (session, request, SOUP_STATUS_FORBIDDEN, NULL, TRUE, TRUE); diff --git a/tests/timeout-test.c b/tests/timeout-test.c index 9d9b2d13..e523f2db 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -112,7 +112,7 @@ do_msg_tests_for_session (SoupSession *timeout_session, } static void -do_request_to_session (SoupRequester *requester, const char *uri, +do_request_to_session (SoupSession *session, const char *uri, const char *comment, gboolean expect_timeout) { SoupRequest *req; @@ -122,7 +122,7 @@ do_request_to_session (SoupRequester *requester, const char *uri, gboolean finished = FALSE; debug_printf (1, " req %s\n", comment); - req = soup_requester_request (requester, uri, NULL); + req = soup_session_request (session, uri, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); g_signal_connect (msg, "finished", @@ -179,46 +179,30 @@ do_req_tests_for_session (SoupSession *timeout_session, SoupSession *plain_session, char *fast_uri, char *slow_uri) { - SoupRequester *timeout_requester, *idle_requester, *plain_requester; SoupSocket *ret, *idle_first, *idle_second; SoupSocket *plain_first, *plain_second; debug_printf (1, "\n"); if (idle_session) { - idle_requester = soup_requester_new (); - soup_session_add_feature (idle_session, - SOUP_SESSION_FEATURE (idle_requester)); - g_object_unref (idle_requester); - g_signal_connect (idle_session, "request-started", G_CALLBACK (request_started_cb), &ret); - do_request_to_session (idle_requester, fast_uri, "fast to idle", FALSE); + do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE); idle_first = ret; } if (plain_session) { - plain_requester = soup_requester_new (); - soup_session_add_feature (plain_session, - SOUP_SESSION_FEATURE (plain_requester)); - g_object_unref (plain_requester); - g_signal_connect (plain_session, "request-started", G_CALLBACK (request_started_cb), &ret); - do_request_to_session (plain_requester, fast_uri, "fast to plain", FALSE); + do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE); plain_first = ret; } - timeout_requester = soup_requester_new (); - soup_session_add_feature (timeout_session, - SOUP_SESSION_FEATURE (timeout_requester)); - g_object_unref (timeout_requester); - - do_request_to_session (timeout_requester, fast_uri, "fast to timeout", FALSE); - do_request_to_session (timeout_requester, slow_uri, "slow to timeout", TRUE); + do_request_to_session (timeout_session, fast_uri, "fast to timeout", FALSE); + do_request_to_session (timeout_session, slow_uri, "slow to timeout", TRUE); if (idle_session) { - do_request_to_session (idle_requester, fast_uri, "fast to idle", FALSE); + do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE); idle_second = ret; g_signal_handlers_disconnect_by_func (idle_session, (gpointer)request_started_cb, @@ -231,7 +215,7 @@ do_req_tests_for_session (SoupSession *timeout_session, } if (plain_session) { - do_request_to_session (plain_requester, fast_uri, "fast to plain", FALSE); + do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE); plain_second = ret; g_signal_handlers_disconnect_by_func (plain_session, (gpointer)request_started_cb, -- cgit v1.2.1 From fea7925589f6b768252b07c9df8f44ee70bca032 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 14 Jul 2012 09:24:29 -0400 Subject: SoupRequest: Return better GErrors on parsing failures In cases where the SoupMessage API would return SOUP_STATUS_MALFORMED, return a clearer GError in the SoupRequest API. --- libsoup/soup-message-client-io.c | 17 ++++++++++++++--- libsoup/soup-message-io.c | 2 +- libsoup/soup-message-private.h | 3 ++- libsoup/soup-message-server-io.c | 12 ++++++++++-- libsoup/soup-session.c | 4 ++++ libsoup/soup-session.h | 4 +++- po/POTFILES.in | 2 ++ 7 files changed, 36 insertions(+), 8 deletions(-) diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c index 06fe5cc6..1ee4cbb2 100644 --- a/libsoup/soup-message-client-io.c +++ b/libsoup/soup-message-client-io.c @@ -11,6 +11,8 @@ #include +#include + #include "soup.h" #include "soup-connection.h" #include "soup-message-private.h" @@ -21,7 +23,8 @@ static guint parse_response_headers (SoupMessage *req, char *headers, guint headers_len, SoupEncoding *encoding, - gpointer user_data) + gpointer user_data, + GError **error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req); SoupHTTPVersion version; @@ -32,8 +35,12 @@ parse_response_headers (SoupMessage *req, req->response_headers, &version, &req->status_code, - &req->reason_phrase)) + &req->reason_phrase)) { + g_set_error_literal (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_PARSING, + _("Could not parse HTTP response")); return SOUP_STATUS_MALFORMED; + } g_object_notify (G_OBJECT (req), SOUP_MESSAGE_STATUS_CODE); g_object_notify (G_OBJECT (req), SOUP_MESSAGE_REASON_PHRASE); @@ -53,8 +60,12 @@ parse_response_headers (SoupMessage *req, else *encoding = soup_message_headers_get_encoding (req->response_headers); - if (*encoding == SOUP_ENCODING_UNRECOGNIZED) + if (*encoding == SOUP_ENCODING_UNRECOGNIZED) { + g_set_error_literal (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_ENCODING, + _("Unrecognized HTTP response encoding")); return SOUP_STATUS_MALFORMED; + } return SOUP_STATUS_OK; } diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index d38d7432..03f8c0a1 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -503,7 +503,7 @@ io_read (SoupMessage *msg, GCancellable *cancellable, GError **error) status = io->parse_headers_cb (msg, (char *)io->read_header_buf->data, io->read_header_buf->len, &io->read_encoding, - io->header_data); + io->header_data, error); g_byte_array_set_size (io->read_header_buf, 0); if (status != SOUP_STATUS_OK) { diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index 86650077..f688515a 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -52,7 +52,8 @@ typedef guint (*SoupMessageParseHeadersFn)(SoupMessage *msg, char *headers, guint header_len, SoupEncoding *encoding, - gpointer user_data); + gpointer user_data, + GError **error); typedef void (*SoupMessageCompletionFn) (SoupMessage *msg, gpointer user_data); diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c index a53e5b7b..e85896b3 100644 --- a/libsoup/soup-message-server-io.c +++ b/libsoup/soup-message-server-io.c @@ -11,13 +11,15 @@ #include +#include + #include "soup.h" #include "soup-message-private.h" #include "soup-misc-private.h" static guint parse_request_headers (SoupMessage *msg, char *headers, guint headers_len, - SoupEncoding *encoding, gpointer sock) + SoupEncoding *encoding, gpointer sock, GError **error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); char *req_method, *req_path, *url; @@ -31,8 +33,14 @@ parse_request_headers (SoupMessage *msg, char *headers, guint headers_len, &req_method, &req_path, &version); - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + if (status == SOUP_STATUS_MALFORMED) { + g_set_error_literal (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_PARSING, + _("Could not parse HTTP request")); + } return status; + } g_object_set (G_OBJECT (msg), SOUP_MESSAGE_METHOD, req_method, diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 20d1c062..85d705a6 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3816,6 +3816,10 @@ soup_session_request_uri (SoupSession *session, SoupURI *uri, * @SOUP_REQUEST_ERROR_BAD_URI: the URI could not be parsed * @SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME: the URI scheme is not * supported by this #SoupSession + * @SOUP_REQUEST_ERROR_PARSING: the server's response could not + * be parsed + * @SOUP_REQUEST_ERROR_ENCODING: the server's response was in an + * unsupported format * * A #SoupRequest error. * diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index acc12a9a..03908625 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -163,7 +163,9 @@ GQuark soup_request_error_quark (void); typedef enum { SOUP_REQUEST_ERROR_BAD_URI, - SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME + SOUP_REQUEST_ERROR_UNSUPPORTED_URI_SCHEME, + SOUP_REQUEST_ERROR_PARSING, + SOUP_REQUEST_ERROR_ENCODING } SoupRequestError; G_END_DECLS diff --git a/po/POTFILES.in b/po/POTFILES.in index ba5d82dd..fff1f0ea 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,6 +1,8 @@ libsoup/soup-body-input-stream.c libsoup/soup-converter-wrapper.c +libsoup/soup-message-client-io.c libsoup/soup-message-io.c +libsoup/soup-message-server-io.c libsoup/soup-request.c libsoup/soup-session.c libsoup/soup-tld.c -- cgit v1.2.1 From d7117329400e47d2187ed033099d921d555f8d71 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 15 Jul 2012 18:21:37 -0400 Subject: SoupRequestHTTP: mirror SoupMessage fields/API Mirror various SoupMessage-related API onto SoupRequestHTTP so that you don't need to resort to soup_request_http_get_message(). --- docs/reference/libsoup-2.4-sections.txt | 8 + libsoup/libsoup-2.4.sym | 7 + libsoup/soup-request-http.c | 478 +++++++++++++++++++++++++++++++- libsoup/soup-request-http.h | 41 ++- libsoup/soup-request.c | 1 + tests/connection-test.c | 9 +- tests/proxy-test.c | 9 +- tests/requester-test.c | 30 +- 8 files changed, 554 insertions(+), 29 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 237d3f06..b46c9f97 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -1162,6 +1162,14 @@ soup_request_file_get_type soup-request-http SoupRequestHTTP SoupRequestHTTP +soup_request_http_set_method +soup_request_http_set_request_version +soup_request_http_set_flags +soup_request_http_get_flags +soup_request_http_set_first_party +soup_request_http_get_first_party +soup_request_http_get_https_status + soup_request_http_get_message SOUP_IS_REQUEST_HTTP diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 24dcc17d..9a1c7dfa 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -325,8 +325,15 @@ soup_request_get_content_type soup_request_get_session soup_request_get_type soup_request_get_uri +soup_request_http_get_first_party +soup_request_http_get_flags +soup_request_http_get_https_status soup_request_http_get_message soup_request_http_get_type +soup_request_http_set_first_party +soup_request_http_set_flags +soup_request_http_set_method +soup_request_http_set_request_version soup_request_send soup_request_send_async soup_request_send_finish diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index 96ba251b..01c37e3a 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -34,9 +34,30 @@ G_DEFINE_TYPE (SoupRequestHTTP, soup_request_http, SOUP_TYPE_REQUEST) +enum { + PROP_0, + + PROP_METHOD, + PROP_REQUEST_URI, + PROP_REQUEST_VERSION, + PROP_REQUEST_HEADERS, + PROP_STATUS_CODE, + PROP_REASON_PHRASE, + PROP_RESPONSE_VERSION, + PROP_RESPONSE_HEADERS, + + PROP_FLAGS, + PROP_FIRST_PARTY, + PROP_TLS_CERTIFICATE, + PROP_TLS_ERRORS, + + LAST_PROP +}; + struct _SoupRequestHTTPPrivate { SoupMessage *msg; char *content_type; + gboolean sent; }; static void content_sniffed (SoupMessage *msg, @@ -50,6 +71,125 @@ soup_request_http_init (SoupRequestHTTP *http) http->priv = G_TYPE_INSTANCE_GET_PRIVATE (http, SOUP_TYPE_REQUEST_HTTP, SoupRequestHTTPPrivate); } +static void +soup_request_http_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (object); + + switch (prop_id) { + case PROP_METHOD: + soup_request_http_set_method (http, g_value_get_string (value)); + break; + case PROP_REQUEST_VERSION: + soup_request_http_set_request_version (http, g_value_get_enum (value)); + break; + case PROP_FLAGS: + soup_request_http_set_flags (http, g_value_get_flags (value)); + break; + case PROP_FIRST_PARTY: + soup_request_http_set_first_party (http, g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_request_http_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (object); + GTlsCertificate *cert; + GTlsCertificateFlags errors; + + switch (prop_id) { + case PROP_METHOD: + g_value_set_string (value, http->method); + break; + case PROP_REQUEST_URI: + g_value_set_boxed (value, http->request_uri); + break; + case PROP_REQUEST_VERSION: + g_value_set_enum (value, http->request_version); + break; + case PROP_REQUEST_HEADERS: + g_value_set_boxed (value, http->request_headers); + break; + case PROP_STATUS_CODE: + g_value_set_uint (value, http->status_code); + break; + case PROP_REASON_PHRASE: + g_value_set_string (value, http->reason_phrase); + break; + case PROP_RESPONSE_VERSION: + g_value_set_enum (value, http->response_version); + break; + case PROP_RESPONSE_HEADERS: + g_value_set_boxed (value, http->request_headers); + break; + case PROP_FLAGS: + g_value_set_flags (value, soup_message_get_flags (http->priv->msg)); + break; + case PROP_FIRST_PARTY: + g_value_set_boxed (value, soup_message_get_first_party (http->priv->msg)); + break; + case PROP_TLS_CERTIFICATE: + g_object_get (G_OBJECT (http->priv->msg), + "tls-certificate", &cert, + NULL); + g_value_set_object (value, cert); + break; + case PROP_TLS_ERRORS: + g_object_get (G_OBJECT (http->priv->msg), + "tls-errors", &errors, + NULL); + g_value_set_flags (value, errors); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +message_property_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + SoupRequestHTTP *http = user_data; + + if (!strcmp (pspec->name, "method")) { + http->method = http->priv->msg->method; + g_object_notify (G_OBJECT (http), "method"); + } else if (!strcmp (pspec->name, "uri")) { + http->request_uri = soup_message_get_uri (http->priv->msg); + g_object_notify (G_OBJECT (http), "request-uri"); + } else if (!strcmp (pspec->name, "status-code")) { + http->status_code = http->priv->msg->status_code; + g_object_notify (G_OBJECT (http), "status-code"); + } else if (!strcmp (pspec->name, "reason-phrase")) { + http->reason_phrase = http->priv->msg->reason_phrase; + g_object_notify (G_OBJECT (http), "reason-phrase"); + } else if (!strcmp (pspec->name, "http-version")) { + if (!http->priv->sent) { + http->request_version = soup_message_get_http_version (http->priv->msg); + g_object_notify (G_OBJECT (http), "request-version"); + } else { + http->response_version = soup_message_get_http_version (http->priv->msg); + g_object_notify (G_OBJECT (http), "response-version"); + } + } else if (!strcmp (pspec->name, "flags")) + g_object_notify (G_OBJECT (http), "flags"); + else if (!strcmp (pspec->name, "first-party")) + g_object_notify (G_OBJECT (http), "first-party"); + else if (!strcmp (pspec->name, "tls-certificate")) + g_object_notify (G_OBJECT (http), "tls-certificate"); + else if (!strcmp (pspec->name, "tls-errors")) + g_object_notify (G_OBJECT (http), "tls-errors"); +} + static gboolean soup_request_http_check_uri (SoupRequest *request, SoupURI *uri, @@ -63,6 +203,17 @@ soup_request_http_check_uri (SoupRequest *request, http->priv->msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri); g_signal_connect (http->priv->msg, "content-sniffed", G_CALLBACK (content_sniffed), http); + + g_signal_connect (http->priv->msg, "notify", + G_CALLBACK (message_property_changed), http); + + http->method = http->priv->msg->method; + http->request_uri = soup_message_get_uri (http->priv->msg); + http->request_version = SOUP_HTTP_1_1; + http->request_headers = http->priv->msg->request_headers; + http->response_version = SOUP_HTTP_1_1; + http->response_headers = http->priv->msg->response_headers; + return TRUE; } @@ -75,6 +226,9 @@ soup_request_http_finalize (GObject *object) g_signal_handlers_disconnect_by_func (http->priv->msg, G_CALLBACK (content_sniffed), http); + g_signal_handlers_disconnect_by_func (http->priv->msg, + G_CALLBACK (message_property_changed), + http); g_object_unref (http->priv->msg); } @@ -93,6 +247,7 @@ soup_request_http_send (SoupRequest *request, g_return_val_if_fail (!SOUP_IS_SESSION_ASYNC (session), NULL); + http->priv->sent = TRUE; return soup_session_send_request (session, http->priv->msg, cancellable, error); } @@ -195,6 +350,8 @@ soup_request_http_send_async (SoupRequest *request, g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); + http->priv->sent = TRUE; + task = g_task_new (request, cancellable, callback, user_data); sadata = g_slice_new0 (SendAsyncData); g_task_set_task_data (task, sadata, (GDestroyNotify)free_send_async_data); @@ -303,6 +460,8 @@ soup_request_http_class_init (SoupRequestHTTPClass *request_http_class) request_class->schemes = http_schemes; + object_class->set_property = soup_request_http_set_property; + object_class->get_property = soup_request_http_get_property; object_class->finalize = soup_request_http_finalize; request_class->check_uri = soup_request_http_check_uri; @@ -311,6 +470,199 @@ soup_request_http_class_init (SoupRequestHTTPClass *request_http_class) request_class->send_finish = soup_request_http_send_finish; request_class->get_content_length = soup_request_http_get_content_length; request_class->get_content_type = soup_request_http_get_content_type; + + /** + * SoupRequestHTTP:method: + * + * The request's HTTP method; "GET" by default. Note that in + * C you can simply read the method field + * of the #SoupRequestHTTP. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_METHOD, + g_param_spec_string ("method", + "Method", + "The HTTP method", + SOUP_METHOD_GET, + G_PARAM_READWRITE)); + /** + * SoupRequestHTTP:request-uri: + * + * The request's #SoupURI. Note that in C you can simply read + * the request_uri field of the + * #SoupRequestHTTP. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_REQUEST_URI, + g_param_spec_boxed ("request-uri", + "URI", + "The Request-URI", + SOUP_TYPE_URI, + G_PARAM_READWRITE)); + /** + * SoupRequestHTTP:request-version: + * + * The #SoupHTTPVersion used when sending the request; + * %SOUP_HTTP_1_1 by default. Note that in C you can simply + * read the request_version field of the + * #SoupRequestHTTP. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_REQUEST_VERSION, + g_param_spec_enum ("request-version", + "Request HTTP Version", + "The SoupHTTPVersion used when sending the request", + SOUP_TYPE_HTTP_VERSION, + SOUP_HTTP_1_1, + G_PARAM_READWRITE)); + /** + * SoupRequestHTTP:request-headers: + * + * The request's HTTP request headers. Note that in C you can + * simply read the request_headers field of + * the #SoupRequestHTTP. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_REQUEST_HEADERS, + g_param_spec_boxed ("request-headers", + "Request Headers", + "The HTTP request headers", + SOUP_TYPE_MESSAGE_HEADERS, + G_PARAM_READABLE)); + + /** + * SoupRequestHTTP:status-code: + * + * The request's HTTP response status code. Note that in C you + * can simply read the status_code field of + * the #SoupRequestHTTP. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_STATUS_CODE, + g_param_spec_uint ("status-code", + "Status code", + "The HTTP response status code", + 0, 599, 0, + G_PARAM_READABLE)); + /** + * SoupRequestHTTP:reason-phrase: + * + * The request's HTTP response reason phrase. Note that in C + * you can simply read the reason_phrase + * field of the #SoupRequestHTTP. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_REASON_PHRASE, + g_param_spec_string ("reason-phrase", + "Reason phrase", + "The HTTP response reason phrase", + NULL, + G_PARAM_READABLE)); + /** + * SoupRequestHTTP:response-version: + * + * The #SoupHTTPVersion that the server replied with. Note + * that in C you can simply read the + * response_version field of the + * #SoupRequestHTTP. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_RESPONSE_VERSION, + g_param_spec_enum ("response-version", + "Response HTTP Version", + "The SoupHTTPVersion that the server replied with", + SOUP_TYPE_HTTP_VERSION, + SOUP_HTTP_1_1, + G_PARAM_READABLE)); + /** + * SoupRequestHTTP:response-headers: + * + * The request's HTTP response headers. Note that in C you can + * simply read the response_headers field + * of the #SoupRequestHTTP. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_RESPONSE_HEADERS, + g_param_spec_boxed ("response-headers", + "Response Headers", + "The HTTP response headers", + SOUP_TYPE_MESSAGE_HEADERS, + G_PARAM_READABLE)); + + /** + * SoupRequestHTTP:flags: + * + * The request's #SoupMessageFlags. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_FLAGS, + g_param_spec_flags ("flags", + "Flags", + "Various request options", + SOUP_TYPE_MESSAGE_FLAGS, + 0, + G_PARAM_READWRITE)); + /** + * SoupRequestHTTP:first-party: + * + * The #SoupURI loaded in the application when the request was + * queued. + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_FIRST_PARTY, + g_param_spec_boxed ("first-party", + "First party", + "The URI loaded in the application when the request was queued.", + SOUP_TYPE_URI, + G_PARAM_READWRITE)); + /** + * SoupRequestHTTP:tls-certificate: + * + * The #GTlsCertificate associated with the request + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_TLS_CERTIFICATE, + g_param_spec_object ("tls-certificate", + "TLS Certificate", + "The TLS certificate associated with the request", + G_TYPE_TLS_CERTIFICATE, + G_PARAM_READABLE)); + /** + * SoupRequestHTTP:tls-errors: + * + * The verification errors on #SoupRequestHTTP:tls-certificate + * + * Since: 2.42 + */ + g_object_class_install_property ( + object_class, PROP_TLS_ERRORS, + g_param_spec_flags ("tls-errors", + "TLS Errors", + "The verification errors on the request's TLS certificate", + G_TYPE_TLS_CERTIFICATE_FLAGS, 0, + G_PARAM_READABLE)); } /** @@ -321,7 +673,7 @@ soup_request_http_class_init (SoupRequestHTTPClass *request_http_class) * * Returns: (transfer full): a new reference to the #SoupMessage * - * Since: 2.40 + * Since: 2.42 */ SoupMessage * soup_request_http_get_message (SoupRequestHTTP *http) @@ -330,3 +682,127 @@ soup_request_http_get_message (SoupRequestHTTP *http) return g_object_ref (http->priv->msg); } + +void +soup_request_http_set_method (SoupRequestHTTP *http, + const char *method) +{ + g_object_set (G_OBJECT (http->priv->msg), + "method", method, + NULL); +} + +/** + * soup_request_http_set_request_version: + * @http: a #SoupRequestHTTP + * @version: the version of HTTP to use + * + * Sets @http to use the version of HTTP specified by @version in its + * request. + * + * Since: 2.42 + */ +void +soup_request_http_set_request_version (SoupRequestHTTP *http, + SoupHTTPVersion version) +{ + g_return_if_fail (!http->priv->sent); + + g_object_set (G_OBJECT (http->priv->msg), + "http-version", version, + NULL); +} + +/** + * soup_request_http_get_first_party: + * @http: a #SoupRequestHTTP + * + * Gets @http's first-party #SoupURI; see the documentation + * for #SoupCookieJarAcceptPolicy for more details. + * + * Returns: (transfer none): @http's first-party URI + * + * Since: 2.42 + */ +SoupURI * +soup_request_http_get_first_party (SoupRequestHTTP *http) +{ + return soup_message_get_first_party (http->priv->msg); +} + +/** + * soup_request_http_set_first_party: + * @http: a #SoupRequestHTTP + * @first_party: the #SoupURI for the request's first party + * + * Sets @first_party as the main document #SoupURI for @http. For + * details of when and how this is used refer to the documentation for + * #SoupCookieJarAcceptPolicy. + * + * Since: 2.42 + */ +void +soup_request_http_set_first_party (SoupRequestHTTP *http, + SoupURI *first_party) +{ + soup_message_set_first_party (http->priv->msg, + first_party); +} + +/** + * soup_request_http_get_flags: + * @http: a #SoupRequestHTTP + * + * Gets @http's message flags. + * + * Returns: @http's message flags + * + * Since: 2.42 + */ +SoupMessageFlags +soup_request_http_get_flags (SoupRequestHTTP *http) +{ + return soup_message_get_flags (http->priv->msg); +} + +/** + * soup_request_http_set_flags: + * @http: a #SoupRequestHTTP + * @flags: a set of #SoupMessageFlags values + * + * Sets the specified flags on @msg. Note that some #SoupMessageFlags + * (such as %SOUP_MESSAGE_CAN_REBUILD and + * %SOUP_MESSAGE_OVERWRITE_CHUNKS) have no effect in the #SoupRequest + * API. + * + * Since: 2.42 + */ +void +soup_request_http_set_flags (SoupRequestHTTP *http, + SoupMessageFlags flags) +{ + soup_message_set_flags (http->priv->msg, flags); +} + +/** + * soup_request_http_get_https_status: + * @http: a #SoupRequestHTTP + * @certificate: (out) (transfer none): @http's TLS certificate + * @errors: (out): the verification status of @certificate + * + * If @http is using https, this retrieves the #GTlsCertificate + * associated with its connection, and the #GTlsCertificateFlags showing + * what problems, if any, have been found with that certificate. + * + * Return value: %TRUE if @http uses https, %FALSE if not + * + * Since: 2.42 + */ +gboolean +soup_request_http_get_https_status (SoupRequestHTTP *http, + GTlsCertificate **certificate, + GTlsCertificateFlags *errors) +{ + return soup_message_get_https_status (http->priv->msg, + certificate, errors); +} diff --git a/libsoup/soup-request-http.h b/libsoup/soup-request-http.h index bad4345c..58fbbfd9 100644 --- a/libsoup/soup-request-http.h +++ b/libsoup/soup-request-http.h @@ -23,6 +23,8 @@ #define SOUP_REQUEST_HTTP_H 1 #include "soup-request.h" +#include "soup-message.h" +#include "soup-message-headers.h" G_BEGIN_DECLS @@ -38,7 +40,20 @@ typedef struct _SoupRequestHTTPPrivate SoupRequestHTTPPrivate; typedef struct { SoupRequest parent; + /*< public >*/ + const char *method; + SoupURI *request_uri; + SoupHTTPVersion request_version; + SoupMessageHeaders *request_headers; + + guint status_code; + char *reason_phrase; + SoupHTTPVersion response_version; + SoupMessageHeaders *response_headers; + + /*< private >*/ SoupRequestHTTPPrivate *priv; + } SoupRequestHTTP; typedef struct { @@ -49,7 +64,31 @@ SOUP_AVAILABLE_IN_2_34 GType soup_request_http_get_type (void); SOUP_AVAILABLE_IN_2_34 -SoupMessage *soup_request_http_get_message (SoupRequestHTTP *http); +SoupMessage *soup_request_http_get_message (SoupRequestHTTP *http); + +SOUP_AVAILABLE_IN_2_42 +void soup_request_http_set_method (SoupRequestHTTP *http, + const char *method); +SOUP_AVAILABLE_IN_2_42 +void soup_request_http_set_request_version (SoupRequestHTTP *http, + SoupHTTPVersion version); + +SOUP_AVAILABLE_IN_2_42 +SoupURI *soup_request_http_get_first_party (SoupRequestHTTP *http); +SOUP_AVAILABLE_IN_2_42 +void soup_request_http_set_first_party (SoupRequestHTTP *http, + SoupURI *first_party); + +SOUP_AVAILABLE_IN_2_42 +SoupMessageFlags soup_request_http_get_flags (SoupRequestHTTP *http); +SOUP_AVAILABLE_IN_2_42 +void soup_request_http_set_flags (SoupRequestHTTP *http, + SoupMessageFlags flags); + +SOUP_AVAILABLE_IN_2_42 +gboolean soup_request_http_get_https_status (SoupRequestHTTP *http, + GTlsCertificate **certificate, + GTlsCertificateFlags *errors); G_END_DECLS diff --git a/libsoup/soup-request.c b/libsoup/soup-request.c index 006a2537..e19547b6 100644 --- a/libsoup/soup-request.c +++ b/libsoup/soup-request.c @@ -30,6 +30,7 @@ #include "soup-request.h" #include "soup.h" #include "soup-requester.h" +#include "soup-request-http.h" /** * SECTION:soup-request diff --git a/tests/connection-test.c b/tests/connection-test.c index 6b57f24d..938c7deb 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -300,7 +300,7 @@ static void do_timeout_req_test_for_session (SoupSession *session) { SoupRequest *req; - SoupMessage *msg; + SoupRequestHTTP *http; GInputStream *stream; SoupSocket *sockets[4] = { NULL, NULL, NULL, NULL }; SoupURI *timeout_uri; @@ -360,10 +360,10 @@ do_timeout_req_test_for_session (SoupSession *session) g_object_unref (stream); } - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - if (msg->status_code != SOUP_STATUS_OK) { + http = SOUP_REQUEST_HTTP (req); + if (http->status_code != SOUP_STATUS_OK) { debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); + http->status_code, http->reason_phrase); errors++; } if (sockets[1] != sockets[0]) { @@ -379,7 +379,6 @@ do_timeout_req_test_for_session (SoupSession *session) debug_printf (1, " Message was retried again??\n"); errors++; } - g_object_unref (msg); g_object_unref (req); for (i = 0; sockets[i]; i++) diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 048acfa7..3466c569 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -131,8 +131,8 @@ test_url_new_api (const char *url, int proxy, guint expected, { SoupSession *session; SoupURI *proxy_uri; - SoupMessage *msg; SoupRequest *request; + SoupRequestHTTP *http; GInputStream *stream; GError *error = NULL; @@ -162,7 +162,6 @@ test_url_new_api (const char *url, int proxy, guint expected, } request = soup_session_request (session, url, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); stream = soup_test_request_send (request, NULL, &error); if (!stream) { @@ -183,13 +182,13 @@ test_url_new_api (const char *url, int proxy, guint expected, g_object_unref (stream); } - debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); - if (msg->status_code != expected) { + http = SOUP_REQUEST_HTTP (request); + debug_printf (1, " %d %s\n", http->status_code, http->reason_phrase); + if (http->status_code != expected) { debug_printf (1, " EXPECTED %d!\n", expected); errors++; } - g_object_unref (msg); g_object_unref (request); soup_test_session_abort_unref (session); diff --git a/tests/requester-test.c b/tests/requester-test.c index 660669a0..4a276783 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -142,10 +142,10 @@ test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data) static void auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data) { + SoupRequestHTTP *http = SOUP_REQUEST_HTTP (source); RequestData *data = user_data; GInputStream *stream; GError *error = NULL; - SoupMessage *msg; const char *content_type; stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error); @@ -157,15 +157,14 @@ auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data) return; } - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (source)); - if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { - debug_printf (1, " GET failed: %d %s\n", msg->status_code, - msg->reason_phrase); + + if (http->status_code != SOUP_STATUS_UNAUTHORIZED) { + debug_printf (1, " GET failed: %d %s\n", http->status_code, + http->reason_phrase); errors++; g_main_loop_quit (loop); return; } - g_object_unref (msg); content_type = soup_request_get_content_type (SOUP_REQUEST (source)); if (g_strcmp0 (content_type, "text/html") != 0) { @@ -263,11 +262,12 @@ do_async_test (SoupSession *session, SoupURI *uri, request = soup_requester_request_uri (requester, uri, NULL); else request = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); if (cancel) { + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); g_signal_connect (msg, "got-headers", G_CALLBACK (cancel_message), session); + g_object_unref (msg); } started_id = g_signal_connect (session, "request-started", @@ -275,7 +275,6 @@ do_async_test (SoupSession *session, SoupURI *uri, &socket); soup_request_send_async (request, NULL, callback, &data); - g_object_unref (request); loop = g_main_loop_new (soup_session_get_async_context (session), TRUE); g_main_loop_run (loop); @@ -283,16 +282,16 @@ do_async_test (SoupSession *session, SoupURI *uri, g_signal_handler_disconnect (session, started_id); - if (msg->status_code != expected_status) { + if (SOUP_REQUEST_HTTP (request)->status_code != expected_status) { debug_printf (1, " GET failed: %d %s (expected %d)\n", msg->status_code, msg->reason_phrase, expected_status); - g_object_unref (msg); g_object_unref (socket); + g_object_unref (request); errors++; return; } - g_object_unref (msg); + g_object_unref (request); if (!expected_response) { if (data.body->len) { @@ -468,10 +467,11 @@ do_sync_request (SoupSession *session, SoupRequest *request, guint started_id; SoupSocket *socket = NULL; - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); if (cancel) { + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); g_signal_connect (msg, "got-headers", G_CALLBACK (cancel_message), session); + g_object_unref (msg); } started_id = g_signal_connect (session, "request-started", @@ -491,29 +491,25 @@ do_sync_request (SoupSession *session, SoupRequest *request, errors++; } g_clear_error (&error); - g_object_unref (msg); g_object_unref (socket); return; } else if (!in) { debug_printf (1, " soup_request_send failed: %s\n", error->message); - g_object_unref (msg); g_clear_error (&error); g_object_unref (socket); errors++; return; } - if (msg->status_code != expected_status) { + if (SOUP_REQUEST_HTTP (request)->status_code != expected_status) { debug_printf (1, " GET failed: %d %s\n", msg->status_code, msg->reason_phrase); - g_object_unref (msg); g_object_unref (in); g_object_unref (socket); errors++; return; } - g_object_unref (msg); body = g_string_new (NULL); do { -- cgit v1.2.1 From 76883f68eaed736caa298a0177da9fbcef5f31e3 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 25 Jul 2012 08:44:02 -0400 Subject: SoupMessage: add soup_message_get_soup_request() When dealing with SoupMessage-related signals in SoupRequest-using code, it's useful to be able to get the message's associated SoupRequest. --- docs/reference/libsoup-2.4-sections.txt | 1 + libsoup/libsoup-2.4.sym | 1 + libsoup/soup-message-private.h | 5 +++++ libsoup/soup-message.c | 32 ++++++++++++++++++++++++++++++++ libsoup/soup-message.h | 3 +++ libsoup/soup-request-http.c | 3 +++ 6 files changed, 45 insertions(+) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index b46c9f97..52cdc37b 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -35,6 +35,7 @@ SoupChunkAllocator soup_message_set_chunk_allocator soup_message_disable_feature +soup_message_get_soup_request SOUP_MESSAGE_METHOD SOUP_MESSAGE_URI diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 9a1c7dfa..63fda177 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -226,6 +226,7 @@ soup_message_get_first_party soup_message_get_flags soup_message_get_https_status soup_message_get_http_version +soup_message_get_soup_request soup_message_get_type soup_message_get_uri soup_message_got_body diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index f688515a..53f8e817 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -38,6 +38,8 @@ typedef struct { GTlsCertificate *tls_certificate; GTlsCertificateFlags tls_errors; + + SoupRequest *request; } SoupMessagePrivate; #define SOUP_MESSAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_MESSAGE, SoupMessagePrivate)) @@ -133,4 +135,7 @@ GInputStream *soup_message_setup_body_istream (GInputStream *body_stream, SoupSession *session, SoupProcessingStage start_at_stage); +void soup_message_set_soup_request (SoupMessage *msg, + SoupRequest *req); + #endif /* SOUP_MESSAGE_PRIVATE_H */ diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 445cdff2..7a1d0b7a 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1995,3 +1995,35 @@ soup_message_set_redirect (SoupMessage *msg, guint status_code, g_free (location_str); soup_uri_free (location); } + +void +soup_message_set_soup_request (SoupMessage *msg, + SoupRequest *req) +{ + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + + priv->request = req; +} + +/** + * soup_message_get_soup_request: + * @msg: a #SoupMessage + * + * If @msg is associated with a #SoupRequest, this returns that + * request. Otherwise it returns %NULL. + * + * Return value: @msg's associated #SoupRequest + * + * Since: 2.40 + */ +SoupRequest * +soup_message_get_soup_request (SoupMessage *msg) +{ + SoupMessagePrivate *priv; + + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL); + + priv = SOUP_MESSAGE_GET_PRIVATE (msg); + return priv->request; +} + diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index 676de66b..6692c38d 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -180,6 +180,9 @@ SOUP_AVAILABLE_IN_2_28 void soup_message_disable_feature (SoupMessage *msg, GType feature_type); +SOUP_AVAILABLE_IN_2_42 +SoupRequest *soup_message_get_soup_request (SoupMessage *msg); + void soup_message_wrote_informational (SoupMessage *msg); void soup_message_wrote_headers (SoupMessage *msg); void soup_message_wrote_chunk (SoupMessage *msg); diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index 01c37e3a..fe1a9746 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -30,6 +30,7 @@ #include "soup-request-http.h" #include "soup.h" #include "soup-cache-private.h" +#include "soup-message-private.h" #include "soup-session-private.h" G_DEFINE_TYPE (SoupRequestHTTP, soup_request_http, SOUP_TYPE_REQUEST) @@ -201,6 +202,8 @@ soup_request_http_check_uri (SoupRequest *request, return FALSE; http->priv->msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri); + soup_message_set_soup_request (http->priv->msg, request); + g_signal_connect (http->priv->msg, "content-sniffed", G_CALLBACK (content_sniffed), http); -- cgit v1.2.1 From 53c270d0e2868fa5ad48ce864f10a9486b11a071 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 25 Jul 2012 09:20:32 -0400 Subject: SoupRequest: add soup_request_disable_feature() Add soup_request_disable_feature(), which proxies to soup_message_disable_feature() for SoupRequestHTTP and is a no-op otherwise. Add SoupRequest tests to sniffing-test, which also tests soup_request_disable_feature() now. --- docs/reference/libsoup-2.4-sections.txt | 2 + libsoup/libsoup-2.4.sym | 1 + libsoup/soup-request.c | 29 ++++++++ libsoup/soup-request.h | 4 + tests/sniffing-test.c | 126 +++++++++++++++++++------------- 5 files changed, 111 insertions(+), 51 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 52cdc37b..46978535 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -1112,6 +1112,8 @@ soup_request_get_content_type soup_request_get_session soup_request_get_uri +soup_request_disable_feature + SOUP_REQUEST_SESSION SOUP_REQUEST_URI diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 63fda177..900cb049 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -317,6 +317,7 @@ soup_requester_get_type soup_requester_new soup_requester_request soup_requester_request_uri +soup_request_disable_feature soup_request_error_get_type soup_request_error_quark soup_request_file_get_file diff --git a/libsoup/soup-request.c b/libsoup/soup-request.c index e19547b6..5fd4a02a 100644 --- a/libsoup/soup-request.c +++ b/libsoup/soup-request.c @@ -376,3 +376,32 @@ soup_request_get_content_type (SoupRequest *request) { return SOUP_REQUEST_GET_CLASS (request)->get_content_type (request); } + +/** + * soup_request_disable_feature: + * @request: a #SoupRequest + * @feature_type: the #GType of a #SoupSessionFeature + * + * This disables the actions of #SoupSessionFeatures with the + * given @feature_type (or a subclass of that type) on @request, so + * that @request is processed as though the feature(s) hadn't been + * added to the session. Eg, passing #SOUP_TYPE_PROXY_URI_RESOLVER for + * @feature_type will disable proxy handling and cause @request to be + * sent directly to the indicated origin server, regardless of system + * proxy configuration. + * + * Since: 2.42 + */ +void +soup_request_disable_feature (SoupRequest *request, + GType feature_type) +{ + SoupMessage *msg; + + /* For now, features only affect SoupMessages, so... */ + if (SOUP_IS_REQUEST_HTTP (request)) { + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + soup_message_disable_feature (msg, feature_type); + g_object_unref (msg); + } +} diff --git a/libsoup/soup-request.h b/libsoup/soup-request.h index 84ad6d6b..e44a7f24 100644 --- a/libsoup/soup-request.h +++ b/libsoup/soup-request.h @@ -98,6 +98,10 @@ goffset soup_request_get_content_length (SoupRequest *request); SOUP_AVAILABLE_IN_2_34 const char *soup_request_get_content_type (SoupRequest *request); +SOUP_AVAILABLE_IN_2_42 +void soup_request_disable_feature (SoupRequest *request, + GType feature_type); + G_END_DECLS #endif /* SOUP_REQUEST_H */ diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index 0b5fe19f..e77154e1 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -232,13 +232,6 @@ got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer data) } } -static void -finished (SoupSession *session, SoupMessage *msg, gpointer data) -{ - GMainLoop *loop = (GMainLoop*)data; - g_main_loop_quit (loop); -} - static void do_signals_test (gboolean should_content_sniff, gboolean should_pause, @@ -248,7 +241,6 @@ do_signals_test (gboolean should_content_sniff, { SoupURI *uri = soup_uri_new_with_base (base_uri, "/mbox"); SoupMessage *msg = soup_message_new_from_uri ("GET", uri); - GMainLoop *loop = g_main_loop_new (NULL, TRUE); char *contents; gsize length; GError *error = NULL; @@ -283,10 +275,7 @@ do_signals_test (gboolean should_content_sniff, "signal::content_sniffed", content_sniffed, GINT_TO_POINTER (should_pause), NULL); - g_object_ref (msg); - soup_session_queue_message (session, msg, finished, loop); - - g_main_loop_run (loop); + soup_session_send_message (session, msg); if (!should_content_sniff && g_object_get_data (G_OBJECT (msg), "content-sniffed")) { @@ -338,7 +327,6 @@ do_signals_test (gboolean should_content_sniff, soup_uri_free (uri); g_object_unref (msg); - g_main_loop_unref (loop); } static void @@ -347,91 +335,124 @@ sniffing_content_sniffed (SoupMessage *msg, const char *content_type, { char **sniffed_type = (char **)data; GString *full_header; - GList *keys; - GList *iter; + GHashTableIter iter; + gpointer key, value; full_header = g_string_new (content_type); - keys = g_hash_table_get_keys (params); - for (iter = keys; iter != NULL; iter = iter->next) { - const gchar *value = (const gchar*) g_hash_table_lookup (params, iter->data); - - g_string_append (full_header, "; "); + g_hash_table_iter_init (&iter, params); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (full_header->len) + g_string_append (full_header, "; "); soup_header_g_string_append_param (full_header, - (const gchar*) iter->data, - value); + (const char *) key, + (const char *) value); } - *sniffed_type = full_header->str; - - g_string_free (full_header, FALSE); - g_list_free (keys); + *sniffed_type = g_string_free (full_header, FALSE); } static void test_sniffing (const char *path, const char *expected_type) { - SoupURI *uri = soup_uri_new_with_base (base_uri, path); - SoupMessage *msg = soup_message_new_from_uri ("GET", uri); - GMainLoop *loop = g_main_loop_new (NULL, TRUE); + SoupURI *uri; + SoupMessage *msg; + SoupRequest *req; + GInputStream *stream; char *sniffed_type = NULL; + GError *error = NULL; debug_printf (1, "test_sniffing(\"%s\", \"%s\")\n", path, expected_type); + uri = soup_uri_new_with_base (base_uri, path); + msg = soup_message_new_from_uri ("GET", uri); + g_signal_connect (msg, "content-sniffed", G_CALLBACK (sniffing_content_sniffed), &sniffed_type); - g_object_ref (msg); - - soup_session_queue_message (session, msg, finished, loop); - - g_main_loop_run (loop); - + soup_session_send_message (session, msg); if (!sniffed_type) { debug_printf (1, " message was not sniffed!\n"); errors++; } else if (strcmp (sniffed_type, expected_type) != 0) { - debug_printf (1, " sniffing failed! expected %s, got %s\n", + debug_printf (1, " message sniffing failed! expected %s, got %s\n", expected_type, sniffed_type); errors++; } g_free (sniffed_type); + g_object_unref (msg); + + req = soup_session_request_uri (session, uri, NULL); + stream = soup_test_request_send (req, NULL, &error); + if (stream) + soup_test_request_close_stream (req, stream, NULL, &error); + if (error) { + debug_printf (1, " request failed: %s\n", error->message); + g_clear_error (&error); + } else { + const char *req_sniffed_type; + + req_sniffed_type = soup_request_get_content_type (req); + if (strcmp (req_sniffed_type, expected_type) != 0) { + debug_printf (1, " request sniffing failed! expected %s, got %s\n", + expected_type, req_sniffed_type); + errors++; + } + } + g_object_unref (req); soup_uri_free (uri); - g_object_unref (msg); - g_main_loop_unref (loop); } static void test_disabled (const char *path) { - SoupURI *uri = soup_uri_new_with_base (base_uri, path); - SoupMessage *msg = soup_message_new_from_uri ("GET", uri); - GMainLoop *loop = g_main_loop_new (NULL, TRUE); + SoupURI *uri; + SoupMessage *msg; + SoupRequest *req; + GInputStream *stream; char *sniffed_type = NULL; - - soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER); + GError *error = NULL; debug_printf (1, "test_disabled(\"%s\")\n", path); - g_signal_connect (msg, "content-sniffed", - G_CALLBACK (sniffing_content_sniffed), &sniffed_type); + uri = soup_uri_new_with_base (base_uri, path); - g_object_ref (msg); + msg = soup_message_new_from_uri ("GET", uri); + soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER); - soup_session_queue_message (session, msg, finished, loop); + g_signal_connect (msg, "content-sniffed", + G_CALLBACK (sniffing_content_sniffed), &sniffed_type); - g_main_loop_run (loop); + soup_session_send_message (session, msg); if (sniffed_type) { debug_printf (1, " message was sniffed!\n"); errors++; g_free (sniffed_type); } + g_object_unref (msg); + + req = soup_session_request_uri (session, uri, NULL); + soup_request_disable_feature (req, SOUP_TYPE_CONTENT_SNIFFER); + stream = soup_test_request_send (req, NULL, &error); + if (stream) + soup_test_request_close_stream (req, stream, NULL, &error); + if (error) { + debug_printf (1, " request failed: %s\n", error->message); + g_clear_error (&error); + } else { + const char *sniffed_content_type; + + sniffed_content_type = soup_request_get_content_type (req); + if (sniffed_content_type != NULL) { + debug_printf (1, " request was sniffed!\n"); + errors++; + } + } + g_object_unref (req); soup_uri_free (uri); - g_object_unref (msg); - g_main_loop_unref (loop); } int @@ -446,7 +467,9 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); /* No sniffer, no content_sniffed should be emitted */ do_signals_test (FALSE, FALSE, FALSE, FALSE, FALSE); @@ -552,6 +575,7 @@ main (int argc, char **argv) soup_test_session_abort_unref (session); soup_test_server_quit_unref (server); + test_cleanup (); return errors != 0; } -- cgit v1.2.1 From 17499abfc0c1fc23c54114f09e8fec348a8bd42d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 25 Jul 2012 09:35:58 -0400 Subject: SoupSession: add soup_session_request_http() and _request_http_uri() Add SoupSession helpers to return SoupRequestHTTP directly and allow overriding the request method. --- docs/reference/libsoup-2.4-sections.txt | 2 + libsoup/libsoup-2.4.sym | 2 + libsoup/soup-request-http.h | 4 +- libsoup/soup-session.c | 88 ++++++++++++++++++++++++++ libsoup/soup-session.h | 22 +++++-- libsoup/soup-types.h | 1 + tests/coding-test.c | 106 +++++++++++++------------------- tests/redirect-test.c | 26 ++++---- 8 files changed, 166 insertions(+), 85 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 46978535..43388ef4 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -389,6 +389,8 @@ SoupSession soup_session_request soup_session_request_uri +soup_session_request_http +soup_session_request_http_uri SoupRequestError SOUP_REQUEST_ERROR diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 900cb049..aa302c67 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -382,6 +382,8 @@ soup_session_redirect_message soup_session_remove_feature soup_session_remove_feature_by_type soup_session_request +soup_session_request_http +soup_session_request_http_uri soup_session_request_uri soup_session_requeue_message soup_session_send_message diff --git a/libsoup/soup-request-http.h b/libsoup/soup-request-http.h index 58fbbfd9..5335b10b 100644 --- a/libsoup/soup-request-http.h +++ b/libsoup/soup-request-http.h @@ -37,7 +37,7 @@ G_BEGIN_DECLS typedef struct _SoupRequestHTTPPrivate SoupRequestHTTPPrivate; -typedef struct { +struct _SoupRequestHTTP { SoupRequest parent; /*< public >*/ @@ -54,7 +54,7 @@ typedef struct { /*< private >*/ SoupRequestHTTPPrivate *priv; -} SoupRequestHTTP; +}; typedef struct { SoupRequestClass parent; diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 85d705a6..94a2214e 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3803,6 +3803,94 @@ soup_session_request_uri (SoupSession *session, SoupURI *uri, NULL); } +static SoupRequestHTTP * +initialize_http_request (SoupRequest *req, + const char *method, + GError **error) +{ + SoupRequestHTTP *http; + SoupMessage *msg; + + if (!SOUP_IS_REQUEST_HTTP (req)) { + g_object_unref (req); + g_set_error (error, SOUP_REQUEST_ERROR, + SOUP_REQUEST_ERROR_BAD_URI, + _("Not an HTTP URI")); + return NULL; + } + + http = SOUP_REQUEST_HTTP (req); + msg = soup_request_http_get_message (http); + g_object_set (G_OBJECT (msg), + SOUP_MESSAGE_METHOD, method, + NULL); + g_object_unref (msg); + + return http; +} + +/** + * soup_session_request_http: + * @session: a #SoupSession + * @method: an HTTP method + * @uri_string: a URI, in string form + * @error: return location for a #GError, or %NULL + * + * Creates a #SoupRequest for retrieving @uri_string, which must be an + * "http" or "https" URI (or another protocol listed in @session's + * #SoupSession:http-aliases or #SoupSession:https-aliases). + * + * Return value: (transfer full): a new #SoupRequestHTTP, or + * %NULL on error. + * + * Since: 2.42 + */ +SoupRequestHTTP * +soup_session_request_http (SoupSession *session, + const char *method, + const char *uri_string, + GError **error) +{ + SoupRequest *req; + + req = soup_session_request (session, uri_string, error); + if (!req) + return NULL; + + return initialize_http_request (req, method, error); +} + +/** + * soup_session_request_http_uri: + * @session: a #SoupSession + * @method: an HTTP method + * @uri: a #SoupURI representing the URI to retrieve + * @error: return location for a #GError, or %NULL + * + * Creates a #SoupRequest for retrieving @uri, which must be an + * "http" or "https" URI (or another protocol listed in @session's + * #SoupSession:http-aliases or #SoupSession:https-aliases). + * + * Return value: (transfer full): a new #SoupRequestHTTP, or + * %NULL on error. + * + * Since: 2.42 + */ +SoupRequestHTTP * +soup_session_request_http_uri (SoupSession *session, + const char *method, + SoupURI *uri, + GError **error) +{ + SoupRequest *req; + + req = soup_session_request_uri (session, uri, error); + if (!req) + return NULL; + + return initialize_http_request (req, method, error); +} + /** * SOUP_REQUEST_ERROR: * diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index 03908625..ca5060ee 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -149,13 +149,23 @@ SoupSessionFeature *soup_session_get_feature_for_message(SoupSession *ses SoupMessage *msg); SOUP_AVAILABLE_IN_2_42 -SoupRequest *soup_session_request (SoupSession *session, - const char *uri_string, - GError **error); +SoupRequest *soup_session_request (SoupSession *session, + const char *uri_string, + GError **error); SOUP_AVAILABLE_IN_2_42 -SoupRequest *soup_session_request_uri (SoupSession *session, - SoupURI *uri, - GError **error); +SoupRequest *soup_session_request_uri (SoupSession *session, + SoupURI *uri, + GError **error); +SOUP_AVAILABLE_IN_2_42 +SoupRequestHTTP *soup_session_request_http (SoupSession *session, + const char *method, + const char *uri_string, + GError **error); +SOUP_AVAILABLE_IN_2_42 +SoupRequestHTTP *soup_session_request_http_uri (SoupSession *session, + const char *method, + SoupURI *uri, + GError **error); SOUP_AVAILABLE_IN_2_42 GQuark soup_request_error_quark (void); diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h index 4134b834..0776bdbf 100644 --- a/libsoup/soup-types.h +++ b/libsoup/soup-types.h @@ -21,6 +21,7 @@ typedef struct _SoupCookieJar SoupCookieJar; typedef struct _SoupDate SoupDate; typedef struct _SoupMessage SoupMessage; typedef struct _SoupRequest SoupRequest; +typedef struct _SoupRequestHTTP SoupRequestHTTP; typedef struct _SoupServer SoupServer; typedef struct _SoupSession SoupSession; typedef struct _SoupSessionAsync SoupSessionAsync; diff --git a/tests/coding-test.c b/tests/coding-test.c index 2718353b..7723c19d 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -323,7 +323,7 @@ read_finished (GObject *stream, GAsyncResult *result, gpointer user_data) } static GByteArray * -do_single_coding_req_test (SoupRequest *req, +do_single_coding_req_test (SoupRequestHTTP *reqh, const char *expected_encoding, const char *expected_content_type, MessageContentStatus status) @@ -337,9 +337,7 @@ do_single_coding_req_test (SoupRequest *req, data = g_byte_array_new (); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - - stream = soup_test_request_send (req, NULL, &error); + stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, &error); if (error) { debug_printf (1, " Error sending request: %s\n", error->message); @@ -360,7 +358,7 @@ do_single_coding_req_test (SoupRequest *req, g_byte_array_append (data, buf, nread); } while (nread > 0); - soup_test_request_close_stream (req, stream, NULL, &error); + soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error); if (error) { debug_printf (1, " error closing stream: %s\n", error->message); @@ -369,6 +367,7 @@ do_single_coding_req_test (SoupRequest *req, } g_object_unref (stream); + msg = soup_request_http_get_message (reqh); check_response (msg, expected_encoding, expected_content_type, status); g_object_unref (msg); @@ -397,8 +396,7 @@ static void do_coding_req_test (void) { SoupSession *session; - SoupRequest *req; - SoupMessage *msg; + SoupRequestHTTP *reqh; SoupURI *uri; GByteArray *plain, *cmp; @@ -411,38 +409,35 @@ do_coding_req_test (void) /* Plain text data, no claim */ debug_printf (1, " GET /mbox, plain\n"); - req = soup_session_request_uri (session, uri, NULL); - plain = do_single_coding_req_test (req, NULL, "text/plain", EXPECT_NOT_DECODED); - g_object_unref (req); + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + plain = do_single_coding_req_test (reqh, NULL, "text/plain", EXPECT_NOT_DECODED); + g_object_unref (reqh); /* Plain text data, claim gzip */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n"); soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); - req = soup_session_request_uri (session, uri, NULL); - cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED); + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed"); g_byte_array_free (cmp, TRUE); - g_object_unref (req); + g_object_unref (reqh); /* Plain text data, claim gzip w/ junk */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n"); - req = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - soup_message_headers_append (msg->request_headers, + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_message_headers_append (reqh->request_headers, "X-Test-Options", "trailing-junk"); - cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_DECODED); + cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed w/ junk"); g_byte_array_free (cmp, TRUE); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); /* Plain text data, claim gzip with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n"); - req = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - soup_message_headers_append (msg->request_headers, + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_message_headers_append (reqh->request_headers, "X-Test-Options", "force-encode"); - cmp = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_NOT_DECODED); + cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_NOT_DECODED); /* Failed content-decoding should have left the body untouched * from what the server sent... which happens to be the @@ -450,68 +445,57 @@ do_coding_req_test (void) */ check_req_bodies (plain, cmp, "plain", "mis-encoded"); g_byte_array_free (cmp, TRUE); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); /* Plain text data, claim deflate */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n"); - req = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - soup_message_headers_append (msg->request_headers, + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_message_headers_append (reqh->request_headers, "X-Test-Options", "prefer-deflate-zlib"); - cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED); + cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed"); g_byte_array_free (cmp, TRUE); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); /* Plain text data, claim deflate w/ junk */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n"); - req = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - soup_message_headers_append (msg->request_headers, + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_message_headers_append (reqh->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); - cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED); + cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed w/ junk"); g_byte_array_free (cmp, TRUE); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); /* Plain text data, claim deflate with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n"); - req = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - soup_message_headers_append (msg->request_headers, + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_message_headers_append (reqh->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); - cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED); + cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED); check_req_bodies (plain, cmp, "plain", "mis-encoded"); g_byte_array_free (cmp, TRUE); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); /* Plain text data, claim deflate (no zlib headers)*/ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n"); - req = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - soup_message_headers_append (msg->request_headers, + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_message_headers_append (reqh->request_headers, "X-Test-Options", "prefer-deflate-raw"); - cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_DECODED); + cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed"); g_byte_array_free (cmp, TRUE); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); /* Plain text data, claim deflate with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n"); - req = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - soup_message_headers_append (msg->request_headers, + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_message_headers_append (reqh->request_headers, "X-Test-Options", "force-encode, prefer-deflate-raw"); - cmp = do_single_coding_req_test (req, "deflate", "text/plain", EXPECT_NOT_DECODED); + cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED); check_req_bodies (plain, cmp, "plain", "mis-encoded"); g_byte_array_free (cmp, TRUE); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); g_byte_array_free (plain, TRUE); soup_uri_free (uri); @@ -525,7 +509,7 @@ do_coding_empty_test (void) SoupSession *session; SoupMessage *msg; SoupURI *uri; - SoupRequest *req; + SoupRequestHTTP *reqh; GByteArray *body; debug_printf (1, "\nEmpty allegedly-encoded body test\n"); @@ -545,14 +529,12 @@ do_coding_empty_test (void) g_object_unref (msg); debug_printf (1, " SoupRequest\n"); - req = soup_session_request_uri (session, uri, NULL); - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - soup_message_headers_append (msg->request_headers, + reqh = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_message_headers_append (reqh->request_headers, "X-Test-Options", "empty"); - g_object_unref (msg); - body = do_single_coding_req_test (req, "gzip", "text/plain", EXPECT_NOT_DECODED); + body = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_NOT_DECODED); g_byte_array_free (body, TRUE); - g_object_unref (req); + g_object_unref (reqh); soup_uri_free (uri); soup_test_session_abort_unref (session); diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 9adf5d5a..f820d003 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -209,7 +209,7 @@ static void do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) { SoupURI *uri; - SoupRequest *req; + SoupRequestHTTP *reqh; SoupMessage *msg; TestRequest *treq; GInputStream *stream; @@ -225,9 +225,11 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) final_status = tests[n].final_status; uri = soup_uri_new_with_base (base_uri, tests[n].requests[0].path); - req = soup_session_request_uri (session, uri, &error); + reqh = soup_session_request_http_uri (session, + tests[n].requests[0].method, + uri, &error); soup_uri_free (uri); - if (!req) { + if (!reqh) { debug_printf (1, " could not create request: %s\n", error->message); g_error_free (error); @@ -236,11 +238,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) return; } - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - g_object_set (G_OBJECT (msg), - SOUP_MESSAGE_METHOD, tests[n].requests[0].method, - NULL); - + msg = soup_request_http_get_message (reqh); if (msg->method == SOUP_METHOD_POST) { soup_message_set_request (msg, "text/plain", SOUP_MEMORY_STATIC, @@ -254,7 +252,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) g_signal_connect (msg, "restarted", G_CALLBACK (restarted), &treq); - stream = soup_test_request_send (req, NULL, &error); + stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, &error); if (SOUP_STATUS_IS_TRANSPORT_ERROR (final_status)) { if (stream) { @@ -272,22 +270,20 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) } g_error_free (error); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); debug_printf (2, "\n"); return; } else if (!stream) { debug_printf (1, " could not send request: %s\n", error->message); g_error_free (error); - g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); errors++; debug_printf (2, "\n"); return; } - soup_test_request_close_stream (req, stream, NULL, &error); + soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error); if (error) { debug_printf (1, " could not close stream: %s\n", error->message); @@ -303,7 +299,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) } g_object_unref (msg); - g_object_unref (req); + g_object_unref (reqh); debug_printf (2, "\n"); } -- cgit v1.2.1 From 64272f77902c91145f6dcbaad5919791b4bc7e36 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 10 Dec 2012 17:30:21 +0100 Subject: tests: fix SoupRequester deprecation warnings Fix multipart-test and resource-test to use the new SoupSession APIs rather than SoupRequester. Fix requester-test (which intentionally tests that SoupRequester still works too) to not show deprecation warnings. --- tests/multipart-test.c | 8 ++------ tests/requester-test.c | 3 +++ tests/resource-test.c | 37 +++++++++++++++---------------------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/tests/multipart-test.c b/tests/multipart-test.c index a299684e..8bcc4cd4 100644 --- a/tests/multipart-test.c +++ b/tests/multipart-test.c @@ -20,7 +20,7 @@ typedef enum { } MultipartMode; char *buffer; -SoupRequester *requester; +SoupSession *session; char *base_uri_string; SoupURI *base_uri; SoupMultipartInputStream *multipart; @@ -494,7 +494,7 @@ static void test_multipart (int headers_expected, int sniffed_expected, MultipartMode multipart_mode) { GError* error = NULL; - SoupRequest* request = soup_requester_request (requester, base_uri_string, &error); + SoupRequest* request = soup_session_request (session, base_uri_string, &error); SoupMessage *msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); GMainLoop *loop = g_main_loop_new (NULL, TRUE); @@ -571,7 +571,6 @@ int main (int argc, char **argv) { SoupServer *server; - SoupSession *session; test_init (argc, argv, NULL); @@ -591,11 +590,8 @@ main (int argc, char **argv) "max-conns", 20, "max-conns-per-host", 20, NULL); - soup_session_add_feature_by_type (session, SOUP_TYPE_REQUESTER); soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); - requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER)); - test_multipart (1, 1, NO_MULTIPART); test_multipart (1, 1, SYNC_MULTIPART); test_multipart (1, 1, ASYNC_MULTIPART); diff --git a/tests/requester-test.c b/tests/requester-test.c index 4a276783..0a61815b 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -3,6 +3,9 @@ * Copyright (C) 2011 Red Hat, Inc. */ +/* Kill SoupRequester-related deprecation warnings */ +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_40 + #include "test-utils.h" SoupServer *server; diff --git a/tests/resource-test.c b/tests/resource-test.c index 449820a4..21e2f98e 100644 --- a/tests/resource-test.c +++ b/tests/resource-test.c @@ -185,8 +185,8 @@ do_sync_request (SoupRequest *request) } static void -do_request_file_test (SoupRequester *requester, - gboolean async) +do_request_file_test (SoupSession *session, + gboolean async) { SoupRequest *request; GFile *index; @@ -200,7 +200,7 @@ do_request_file_test (SoupRequester *requester, uri = soup_uri_new (uri_string); g_free (uri_string); - request = soup_requester_request_uri (requester, uri, NULL); + request = soup_session_request_uri (session, uri, NULL); if (async) do_async_request (request); else @@ -211,8 +211,8 @@ do_request_file_test (SoupRequester *requester, } static void -do_request_data_test (SoupRequester *requester, - gboolean async) +do_request_data_test (SoupSession *session, + gboolean async) { SoupRequest *request; gchar *base64; @@ -226,7 +226,7 @@ do_request_data_test (SoupRequester *requester, uri = soup_uri_new (uri_string); g_free (uri_string); - request = soup_requester_request_uri (requester, uri, NULL); + request = soup_session_request_uri (session, uri, NULL); if (async) do_async_request (request); else @@ -237,14 +237,14 @@ do_request_data_test (SoupRequester *requester, } static void -do_request_gresource_test (SoupRequester *requester, - gboolean async) +do_request_gresource_test (SoupSession *session, + gboolean async) { SoupRequest *request; SoupURI *uri; uri = soup_uri_new ("resource:///org/gnome/libsoup/tests/index.txt"); - request = soup_requester_request_uri (requester, uri, NULL); + request = soup_session_request_uri (session, uri, NULL); if (async) do_async_request (request); else @@ -258,7 +258,6 @@ int main (int argc, char **argv) { SoupSession *session; - SoupRequester *requester; test_init (argc, argv, NULL); @@ -267,13 +266,10 @@ main (int argc, char **argv) /* Sync tests */ session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - requester = soup_requester_new (); - soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); - g_object_unref (requester); - do_request_file_test (requester, FALSE); - do_request_data_test (requester, FALSE); - do_request_gresource_test (requester, FALSE); + do_request_file_test (session, FALSE); + do_request_data_test (session, FALSE); + do_request_gresource_test (session, FALSE); soup_test_session_abort_unref (session); @@ -281,13 +277,10 @@ main (int argc, char **argv) session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); - requester = soup_requester_new (); - soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); - g_object_unref (requester); - do_request_file_test (requester, TRUE); - do_request_data_test (requester, TRUE); - do_request_gresource_test (requester, TRUE); + do_request_file_test (session, TRUE); + do_request_data_test (session, TRUE); + do_request_gresource_test (session, TRUE); soup_test_session_abort_unref (session); -- cgit v1.2.1 From 93c0b8808b9cfa4cbcf3ef014385016ed8bd5038 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 10 Dec 2012 22:20:59 +0100 Subject: soup-uri: don't decode %00 in URIs We were accidentally decoding %00 to '\0' in URIs, causing a few WebKit tests to fail. Leave it undecoded instead. --- libsoup/soup-uri.c | 2 +- tests/uri-parsing.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 709d3ad3..c1d5720f 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -709,7 +709,7 @@ uri_normalized_copy (const char *part, int length, c = HEXCHAR (s); if (soup_char_is_uri_unreserved (c) || - strchr (unescape_extra, c)) { + (c && strchr (unescape_extra, c))) { *d++ = c; s += 3; } else { diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index 166a6d87..892ee2b9 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -125,6 +125,9 @@ static struct { { "http", "", NULL, "host", 80, "/", NULL, NULL } }, { "http://:@host", "http://@host/", { "http", "", "", "host", 80, "/", NULL, NULL } }, + + { "http://host/keep%00nuls", "http://host/keep%00nuls", + { "http", NULL, NULL, "host", 80, "/keep%00nuls", NULL, NULL } }, }; static int num_abs_tests = G_N_ELEMENTS(abs_tests); -- cgit v1.2.1 From 5651d18eb8c9edff5961a32c488641bf6776ca6b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 11 Dec 2012 10:52:00 +0100 Subject: soup-message-io: fix crash when doing unpause+cancel soup_message_io_stop() was unreffing unpause_source (if it was set), but it didn't actually own a ref on it, so this would crash. Fortunately this would only happen if you unpaused a message and then immediately cancelled it, which isn't very common. Fixes a sporadic chunk-test crash though. --- libsoup/soup-message-io.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 03f8c0a1..928b73ef 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -1134,6 +1134,7 @@ soup_message_io_pause (SoupMessage *msg) if (io->unpause_source) { g_source_destroy (io->unpause_source); + g_source_unref (io->unpause_source); io->unpause_source = NULL; } @@ -1147,6 +1148,8 @@ io_unpause_internal (gpointer msg) SoupMessageIOData *io = priv->io_data; g_return_val_if_fail (io != NULL, FALSE); + + g_source_unref (io->unpause_source); io->unpause_source = NULL; io->paused = FALSE; @@ -1173,7 +1176,7 @@ soup_message_io_unpause (SoupMessage *msg) if (!io->blocking) { if (!io->unpause_source) { - io->unpause_source = soup_add_completion ( + io->unpause_source = soup_add_completion_reffed ( io->async_context, io_unpause_internal, msg); } } else -- cgit v1.2.1 From 0ce58e3a12410255c643ce5d7be60b30ec1e4960 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 11 Dec 2012 15:34:52 +0100 Subject: SoupRequester: compatibility fix Epiphany was registering its "ephy-about" handler by directly calling soup_session_feature_add_feature() on the SoupRequester, rather than calling soup_session_add_feature_by_type() on the session. Fix it so that will still work. --- libsoup/soup-requester.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/libsoup/soup-requester.c b/libsoup/soup-requester.c index ce679821..60648e11 100644 --- a/libsoup/soup-requester.c +++ b/libsoup/soup-requester.c @@ -74,6 +74,41 @@ soup_requester_detach (SoupSessionFeature *feature, SoupSession *session) soup_requester_default_feature_interface->detach (feature, session); } +static gboolean +soup_requester_add_feature (SoupSessionFeature *feature, GType type) +{ + SoupRequester *requester = SOUP_REQUESTER (feature); + + if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) + return FALSE; + + soup_session_add_feature_by_type (requester->priv->session, type); + return TRUE; +} + +static gboolean +soup_requester_remove_feature (SoupSessionFeature *feature, GType type) +{ + SoupRequester *requester = SOUP_REQUESTER (feature); + + if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) + return FALSE; + + soup_session_remove_feature_by_type (requester->priv->session, type); + return TRUE; +} + +static gboolean +soup_requester_has_feature (SoupSessionFeature *feature, GType type) +{ + SoupRequester *requester = SOUP_REQUESTER (feature); + + if (!g_type_is_a (type, SOUP_TYPE_REQUEST)) + return FALSE; + + return soup_session_has_feature (requester->priv->session, type); +} + static void soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data) @@ -83,6 +118,9 @@ soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interf feature_interface->attach = soup_requester_attach; feature_interface->detach = soup_requester_detach; + feature_interface->add_feature = soup_requester_add_feature; + feature_interface->remove_feature = soup_requester_remove_feature; + feature_interface->has_feature = soup_requester_has_feature; } SoupRequester * -- cgit v1.2.1 From 65890298dbe26d1058f523a6eb4741d57b05142c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 22 Aug 2012 11:40:04 -0400 Subject: SoupPasswordManager: kill Deprecate and remove support for SoupPasswordManager; SoupPasswordManagerGNOME is now a dummy class, and the related SoupAuth methods are all no-ops. SoupSession also no longer has any special support for SoupPasswordManager. To avoid breaking old builds, the functions/types are still around, but are now marked as having always been deprecated (which, really, they were). https://bugzilla.gnome.org/show_bug.cgi?id=594377 https://bugzilla.gnome.org/show_bug.cgi?id=679866 --- configure.ac | 10 -- libsoup/Makefile.am | 14 +-- libsoup/soup-auth.c | 154 +------------------------- libsoup/soup-auth.h | 37 +++---- libsoup/soup-gnome-features.h | 5 +- libsoup/soup-password-manager-gnome.c | 198 +--------------------------------- libsoup/soup-password-manager.c | 47 +------- libsoup/soup-password-manager.h | 10 +- libsoup/soup-session-async.c | 36 ------- libsoup/soup-session-sync.c | 21 ---- libsoup/soup-session.c | 11 +- libsoup/soup.h | 1 - 12 files changed, 37 insertions(+), 507 deletions(-) diff --git a/configure.ac b/configure.ac index 2ef8cb85..3f5097c2 100644 --- a/configure.ac +++ b/configure.ac @@ -138,16 +138,6 @@ AC_ARG_WITH(gnome, :, [if test $os_win32 = yes; then with_gnome=no; else with_gnome=yes; fi]) AC_MSG_RESULT($with_gnome) -if test $with_gnome != no -a $os_win32 != yes; then - PKG_CHECK_MODULES(GNOME_KEYRING, gnome-keyring-1, :, - AC_MSG_ERROR( -[Could not find gnome-keyring devel files. -Configure with --without-gnome if you wish to build only libsoup -without GNOME-specific features.])) -fi -AC_SUBST(GNOME_KEYRING_CFLAGS) -AC_SUBST(GNOME_KEYRING_LIBS) - AM_CONDITIONAL(BUILD_LIBSOUP_GNOME, test $with_gnome != no) if test $with_gnome != no; then diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 31267a37..3a256e02 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -194,14 +194,6 @@ tld_data.inc: tld-parser.py $(TLD_DATA_FILE) if BUILD_LIBSOUP_GNOME -if OS_WIN32 -soup_password_manager_gnome_files = -else -soup_password_manager_gnome_files = \ - soup-password-manager-gnome.h \ - soup-password-manager-gnome.c -endif - libsoupgnomeincludedir = $(includedir)/libsoup-gnome-2.4/libsoup libsoupgnomeinclude_HEADERS = \ @@ -221,15 +213,15 @@ EXTRA_DIST += libsoup-gnome-2.4.sym libsoup_gnome_2_4_la_LIBADD = \ libsoup-2.4.la \ $(GLIB_LIBS) \ - $(SQLITE_LIBS) \ - $(GNOME_KEYRING_LIBS) + $(SQLITE_LIBS) libsoup_gnome_2_4_la_SOURCES = \ soup-cookie-jar-sqlite.c \ soup-gnome-features.c \ soup-proxy-resolver-gnome.h \ soup-proxy-resolver-gnome.c \ - $(soup_password_manager_gnome_files) + soup-password-manager-gnome.h \ + soup-password-manager-gnome.c endif diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c index 6960e520..bb6f3b45 100644 --- a/libsoup/soup-auth.c +++ b/libsoup/soup-auth.c @@ -9,8 +9,6 @@ #include #endif -#define LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY - #include #include "soup-auth.h" @@ -40,20 +38,11 @@ typedef struct { gboolean proxy; char *host; - - GHashTable *saved_passwords; } SoupAuthPrivate; #define SOUP_AUTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH, SoupAuthPrivate)) G_DEFINE_ABSTRACT_TYPE (SoupAuth, soup_auth, G_TYPE_OBJECT) -enum { - SAVE_PASSWORD, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - enum { PROP_0, @@ -79,8 +68,6 @@ soup_auth_finalize (GObject *object) g_free (auth->realm); g_free (priv->host); - if (priv->saved_passwords) - g_hash_table_destroy (priv->saved_passwords); G_OBJECT_CLASS (soup_auth_parent_class)->finalize (object); } @@ -149,30 +136,6 @@ soup_auth_class_init (SoupAuthClass *auth_class) object_class->set_property = soup_auth_set_property; object_class->get_property = soup_auth_get_property; - /** - * SoupAuth::save-password: - * @auth: the auth - * @username: the username to save - * @password: the password to save - * - * Emitted to request that the @username/@password pair be - * saved. If the session supports password-saving, it will - * connect to this signal before emitting - * #SoupSession::authenticate, so that it record the password - * if requested by the caller. - * - * Since: 2.28 - **/ - signals[SAVE_PASSWORD] = - g_signal_new ("save-password", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - _soup_marshal_NONE__STRING_STRING, - G_TYPE_NONE, 2, - G_TYPE_STRING, - G_TYPE_STRING); - /* properties */ /** * SOUP_AUTH_SCHEME_NAME: @@ -356,9 +319,6 @@ soup_auth_update (SoupAuth *auth, SoupMessage *msg, const char *auth_header) * * Call this on an auth to authenticate it; normally this will cause * the auth's message to be requeued with the new authentication info. - * - * This does not cause the password to be saved to persistent storage; - * see soup_auth_save_password() for that. **/ void soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password) @@ -537,136 +497,26 @@ soup_auth_free_protection_space (SoupAuth *auth, GSList *space) g_slist_free_full (space, g_free); } -/** - * soup_auth_get_saved_users: - * @auth: a #SoupAuth - * - * Gets a list of usernames for which a saved password is available. - * (If the session is not configured to save passwords, this will - * always be %NULL.) - * - * Return value: (transfer container): the list of usernames. You must - * free the list with g_slist_free(), but do not free or modify the - * contents. - * - * Since: 2.28 - **/ GSList * soup_auth_get_saved_users (SoupAuth *auth) { - SoupAuthPrivate *priv; - GSList *users; - - g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); - - priv = SOUP_AUTH_GET_PRIVATE (auth); - users = NULL; - - if (priv->saved_passwords) { - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, priv->saved_passwords); - while (g_hash_table_iter_next (&iter, &key, &value)) - users = g_slist_prepend (users, key); - } - return users; + return NULL; } -/** - * soup_auth_get_saved_password: - * @auth: a #SoupAuth - * @user: a username from the list returned from - * soup_auth_get_saved_users(). - * - * Given a username for which @auth has a saved password, this returns - * that password. If @auth doesn't have a passwords saved for @user, it - * returns %NULL. - * - * Return value: the saved password, or %NULL. - * - * Since: 2.28 - **/ const char * soup_auth_get_saved_password (SoupAuth *auth, const char *user) { - SoupAuthPrivate *priv; - - g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); - g_return_val_if_fail (user != NULL, NULL); - - priv = SOUP_AUTH_GET_PRIVATE (auth); - if (!priv->saved_passwords) - return NULL; - return g_hash_table_lookup (priv->saved_passwords, user); -} - -static void -free_password (gpointer password) -{ - memset (password, 0, strlen (password)); - g_free (password); -} - -static inline void -init_saved_passwords (SoupAuthPrivate *priv) -{ - priv->saved_passwords = g_hash_table_new_full ( - g_str_hash, g_str_equal, g_free, free_password); + return NULL; } -/** - * soup_auth_has_saved_password: - * @auth: a #SoupAuth - * @username: a username - * @password: a password - * - * Updates @auth to be aware of an already-saved username/password - * combination. This method does not cause the - * given @username and @password to be saved; use - * soup_auth_save_password() for that. (soup_auth_has_saved_password() - * is an internal method, which is used by the code that actually - * saves and restores the passwords.) - * - * Since: 2.28 - **/ void soup_auth_has_saved_password (SoupAuth *auth, const char *username, const char *password) { - SoupAuthPrivate *priv; - - g_return_if_fail (SOUP_IS_AUTH (auth)); - g_return_if_fail (username != NULL); - g_return_if_fail (password != NULL); - - priv = SOUP_AUTH_GET_PRIVATE (auth); - - if (!priv->saved_passwords) - init_saved_passwords (priv); - g_hash_table_insert (priv->saved_passwords, - g_strdup (username), g_strdup (password)); } -/** - * soup_auth_save_password: - * @auth: a #SoupAuth - * @username: the username provided by the user or client - * @password: the password provided by the user or client - * - * Requests that the username/password pair be saved to whatever form - * of persistent password storage the session supports. - * - * Since: 2.28 - **/ void soup_auth_save_password (SoupAuth *auth, const char *username, const char *password) { - g_return_if_fail (SOUP_IS_AUTH (auth)); - g_return_if_fail (username != NULL); - g_return_if_fail (password != NULL); - - g_signal_emit (auth, signals[SAVE_PASSWORD], 0, - username, password); } diff --git a/libsoup/soup-auth.h b/libsoup/soup-auth.h index 99510216..8abda8e0 100644 --- a/libsoup/soup-auth.h +++ b/libsoup/soup-auth.h @@ -72,18 +72,6 @@ const char *soup_auth_get_host (SoupAuth *auth); const char *soup_auth_get_realm (SoupAuth *auth); char *soup_auth_get_info (SoupAuth *auth); -#ifdef LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY -SOUP_AVAILABLE_IN_2_28 -GSList *soup_auth_get_saved_users (SoupAuth *auth); -SOUP_AVAILABLE_IN_2_28 -const char *soup_auth_get_saved_password (SoupAuth *auth, - const char *user); -SOUP_AVAILABLE_IN_2_28 -void soup_auth_save_password (SoupAuth *auth, - const char *username, - const char *password); -#endif - void soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password); @@ -97,12 +85,6 @@ GSList *soup_auth_get_protection_space (SoupAuth *auth, void soup_auth_free_protection_space (SoupAuth *auth, GSList *space); -#ifdef LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY -void soup_auth_has_saved_password (SoupAuth *auth, - const char *username, - const char *password); -#endif - /* The actual auth types, which can be added/removed as features */ #define SOUP_TYPE_AUTH_BASIC (soup_auth_basic_get_type ()) @@ -112,6 +94,25 @@ GType soup_auth_digest_get_type (void); #define SOUP_TYPE_AUTH_NTLM (soup_auth_ntlm_get_type ()) GType soup_auth_ntlm_get_type (void); +/* Deprecated SoupPasswordManager-related APIs: all are now no-ops */ +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +GSList *soup_auth_get_saved_users (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +const char *soup_auth_get_saved_password (SoupAuth *auth, + const char *user); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +void soup_auth_save_password (SoupAuth *auth, + const char *username, + const char *password); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 +void soup_auth_has_saved_password (SoupAuth *auth, + const char *username, + const char *password); + G_END_DECLS #endif /* SOUP_AUTH_H */ diff --git a/libsoup/soup-gnome-features.h b/libsoup/soup-gnome-features.h index 6e36b0ee..34856722 100644 --- a/libsoup/soup-gnome-features.h +++ b/libsoup/soup-gnome-features.h @@ -18,13 +18,10 @@ SOUP_AVAILABLE_IN_2_26 GType soup_gnome_features_2_26_get_type (void); #define SOUP_TYPE_GNOME_FEATURES_2_26 (soup_gnome_features_2_26_get_type ()) -#ifndef G_OS_WIN32 -#ifdef LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 GType soup_password_manager_gnome_get_type (void); #define SOUP_TYPE_PASSWORD_MANAGER_GNOME (soup_password_manager_gnome_get_type ()) -#endif /* LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY */ -#endif G_END_DECLS diff --git a/libsoup/soup-password-manager-gnome.c b/libsoup/soup-password-manager-gnome.c index 475cb594..8101683d 100644 --- a/libsoup/soup-password-manager-gnome.c +++ b/libsoup/soup-password-manager-gnome.c @@ -5,216 +5,24 @@ * Copyright (C) 2008 Red Hat, Inc. */ +/* This is just a stub now; eventually it will go away completely. */ + #ifdef HAVE_CONFIG_H #include #endif -#include - -#define LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY - #include "soup-password-manager-gnome.h" #include "soup.h" -static void soup_password_manager_gnome_interface_init (SoupPasswordManagerInterface *password_manager_interface); - G_DEFINE_TYPE_EXTENDED (SoupPasswordManagerGNOME, soup_password_manager_gnome, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL) - G_IMPLEMENT_INTERFACE (SOUP_TYPE_PASSWORD_MANAGER, soup_password_manager_gnome_interface_init)) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL)) static void soup_password_manager_gnome_init (SoupPasswordManagerGNOME *manager_gnome) { } - -static void -save_password_callback (GnomeKeyringResult result, guint32 val, gpointer data) -{ -} - -static void -async_save_password (SoupAuth *auth, const char *username, - const char *password, gpointer user_data) -{ - SoupURI *uri = user_data; - - gnome_keyring_set_network_password ( - NULL, /* use default keyring */ - username, - soup_auth_get_realm (auth), - uri->host, - NULL, - uri->scheme, - soup_auth_get_scheme_name (auth), - uri->port, - password, - save_password_callback, NULL, NULL); -} - -static void -sync_save_password (SoupAuth *auth, const char *username, - const char *password, gpointer user_data) -{ - SoupURI *uri = user_data; - guint32 item_id; - - gnome_keyring_set_network_password_sync ( - NULL, /* use default keyring */ - username, - soup_auth_get_realm (auth), - uri->host, - NULL, - uri->scheme, - soup_auth_get_scheme_name (auth), - uri->port, - password, - &item_id); -} - -static void -update_auth_for_passwords (SoupAuth *auth, SoupMessage *msg, - GList *passwords, gboolean async) -{ - GnomeKeyringNetworkPasswordData *pdata; - SoupURI *uri; - - while (passwords) { - pdata = passwords->data; - soup_auth_has_saved_password (auth, pdata->user, - pdata->password); - passwords = passwords->next; - } - - uri = g_object_get_data (G_OBJECT (auth), - "SoupPasswordManagerGNOME-save_password-uri"); - if (uri) { - g_signal_handlers_disconnect_by_func (auth, async_save_password, uri); - g_signal_handlers_disconnect_by_func (auth, sync_save_password, uri); - } - - uri = soup_uri_copy (soup_message_get_uri (msg)); - g_signal_connect (auth, "save_password", - G_CALLBACK (async ? async_save_password : sync_save_password), - uri); - g_object_set_data_full (G_OBJECT (auth), - "SoupPasswordManagerGNOME-save_password-uri", - uri, (GDestroyNotify)soup_uri_free); -} - -typedef struct { - SoupPasswordManager *password_manager; - SoupMessage *msg; - SoupAuth *auth; - gboolean retrying; - - SoupPasswordManagerCallback callback; - gpointer user_data; - - gpointer request; -} SoupPasswordManagerGNOMEAuthData; - -static void -find_password_callback (GnomeKeyringResult result, GList *list, - gpointer user_data) -{ - SoupPasswordManagerGNOMEAuthData *auth_data = user_data; - - /* FIXME: check result? */ - - update_auth_for_passwords (auth_data->auth, auth_data->msg, list, TRUE); - auth_data->callback (auth_data->password_manager, - auth_data->msg, auth_data->auth, - auth_data->retrying, auth_data->user_data); - - /* gnome-keyring will call free_auth_data to clean up for us. */ -} - -static void -free_auth_data (gpointer data) -{ - SoupPasswordManagerGNOMEAuthData *auth_data = data; - - g_object_unref (auth_data->auth); - g_object_unref (auth_data->msg); - g_slice_free (SoupPasswordManagerGNOMEAuthData, auth_data); -} - -static void -soup_password_manager_gnome_get_passwords_async (SoupPasswordManager *password_manager, - SoupMessage *msg, - SoupAuth *auth, - gboolean retrying, - GMainContext *async_context, - GCancellable *cancellable, - SoupPasswordManagerCallback callback, - gpointer user_data) -{ - SoupPasswordManagerGNOMEAuthData *auth_data; - SoupURI *uri = soup_message_get_uri (msg); - - auth_data = g_slice_new (SoupPasswordManagerGNOMEAuthData); - auth_data->password_manager = password_manager; - auth_data->msg = g_object_ref (msg); - auth_data->auth = g_object_ref (auth); - auth_data->retrying = retrying; - - /* FIXME: async_context, cancellable */ - - auth_data->callback = callback; - auth_data->user_data = user_data; - - /* FIXME: should we be specifying protocol and port here, or - * leaving them NULL/0 and filtering results in the callback? - * We don't want to send https passwords to http, but the - * reverse might be OK (if that's how other clients tend to - * behave). - */ - auth_data->request = gnome_keyring_find_network_password ( - NULL, /* user -- accept any */ - soup_auth_get_realm (auth), /* domain */ - uri->host, /* server */ - NULL, /* object -- unused */ - uri->scheme, /* protocol */ - soup_auth_get_scheme_name (auth), /* authtype */ - uri->port, /* port */ - find_password_callback, auth_data, free_auth_data); -} - -static void -soup_password_manager_gnome_get_passwords_sync (SoupPasswordManager *password_manager, - SoupMessage *msg, - SoupAuth *auth, - GCancellable *cancellable) -{ - SoupURI *uri = soup_message_get_uri (msg); - GList *results = NULL; - - /* FIXME: cancellable */ - - gnome_keyring_find_network_password_sync ( - NULL, /* user -- accept any */ - soup_auth_get_realm (auth), /* domain */ - uri->host, /* server */ - NULL, /* object -- unused */ - uri->scheme, /* protocol */ - soup_auth_get_scheme_name (auth), /* authtype */ - uri->port, /* port */ - &results); - - update_auth_for_passwords (auth, msg, results, FALSE); -} - static void soup_password_manager_gnome_class_init (SoupPasswordManagerGNOMEClass *gnome_class) { } - -static void -soup_password_manager_gnome_interface_init (SoupPasswordManagerInterface *password_manager_interface) -{ - password_manager_interface->get_passwords_async = - soup_password_manager_gnome_get_passwords_async; - password_manager_interface->get_passwords_sync = - soup_password_manager_gnome_get_passwords_sync; -} diff --git a/libsoup/soup-password-manager.c b/libsoup/soup-password-manager.c index 3914179f..d9cf81c3 100644 --- a/libsoup/soup-password-manager.c +++ b/libsoup/soup-password-manager.c @@ -9,8 +9,6 @@ #include #endif -#define LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY - #include "soup-password-manager.h" #include "soup.h" @@ -23,29 +21,6 @@ soup_password_manager_default_init (SoupPasswordManagerInterface *iface) { } -/** - * soup_password_manager_get_passwords_async: - * @password_manager: the #SoupPasswordManager - * @msg: the #SoupMessage being authenticated - * @auth: the #SoupAuth being authenticated - * @retrying: whether or not this is a re-attempt to authenticate - * @async_context: (allow-none): the #GMainContext to invoke @callback in - * @cancellable: a #GCancellable, or %NULL - * @callback: callback to invoke after fetching passwords - * @user_data: data for @callback - * - * Asynchronously attempts to look up saved passwords for @auth/@msg - * and then calls @callback after updating @auth with the information. - * Also registers @auth with @password_manager so that if the caller - * calls soup_auth_save_password() on it, the password will be saved. - * - * #SoupPasswordManager does not actually use the @retrying flag itself; - * it just passes its value on to @callback. - * - * If @cancellable is cancelled, @callback will still be invoked. - * - * Since: 2.28 - **/ void soup_password_manager_get_passwords_async (SoupPasswordManager *password_manager, SoupMessage *msg, @@ -56,32 +31,14 @@ soup_password_manager_get_passwords_async (SoupPasswordManager *password_manage SoupPasswordManagerCallback callback, gpointer user_data) { - SOUP_PASSWORD_MANAGER_GET_CLASS (password_manager)-> - get_passwords_async (password_manager, msg, auth, retrying, - async_context, cancellable, - callback, user_data); + g_warn_if_reached (); } -/** - * soup_password_manager_get_passwords_sync: - * @password_manager: the #SoupPasswordManager - * @msg: the #SoupMessage being authenticated - * @auth: the #SoupAuth being authenticated - * @cancellable: a #GCancellable, or %NULL - * - * Synchronously attempts to look up saved passwords for @auth/@msg - * and updates @auth with the information. Also registers @auth with - * @password_manager so that if the caller calls - * soup_auth_save_password() on it, the password will be saved. - * - * Since: 2.28 - **/ void soup_password_manager_get_passwords_sync (SoupPasswordManager *password_manager, SoupMessage *msg, SoupAuth *auth, GCancellable *cancellable) { - SOUP_PASSWORD_MANAGER_GET_CLASS (password_manager)-> - get_passwords_sync (password_manager, msg, auth, cancellable); + g_warn_if_reached (); } diff --git a/libsoup/soup-password-manager.h b/libsoup/soup-password-manager.h index 775f84c5..d4e60ac7 100644 --- a/libsoup/soup-password-manager.h +++ b/libsoup/soup-password-manager.h @@ -6,8 +6,6 @@ #ifndef SOUP_PASSWORD_MANAGER_H #define SOUP_PASSWORD_MANAGER_H 1 -#ifdef LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY - #include #define SOUP_TYPE_PASSWORD_MANAGER (soup_password_manager_get_type ()) @@ -37,8 +35,12 @@ typedef struct { } SoupPasswordManagerInterface; +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 GType soup_password_manager_get_type (void); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 void soup_password_manager_get_passwords_async (SoupPasswordManager *password_manager, SoupMessage *msg, SoupAuth *auth, @@ -48,11 +50,11 @@ void soup_password_manager_get_passwords_async (SoupPasswordManager *password_ SoupPasswordManagerCallback callback, gpointer user_data); +SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_28 void soup_password_manager_get_passwords_sync (SoupPasswordManager *password_manager, SoupMessage *msg, SoupAuth *auth, GCancellable *cancellable); -#endif /* LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY */ - #endif /* SOUP_PASSWORD_MANAGER_H */ diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index a24f4bab..4c08a617 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -9,8 +9,6 @@ #include #endif -#define LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY - #include "soup-session-async.h" #include "soup.h" #include "soup-session-private.h" @@ -133,39 +131,6 @@ soup_session_async_cancel_message (SoupSession *session, SoupMessage *msg, soup_message_queue_item_unref (item); } -static void -got_passwords (SoupPasswordManager *password_manager, SoupMessage *msg, - SoupAuth *auth, gboolean retrying, gpointer session) -{ - soup_session_unpause_message (session, msg); - SOUP_SESSION_CLASS (soup_session_async_parent_class)-> - auth_required (session, msg, auth, retrying); - g_object_unref (auth); -} - -static void -soup_session_async_auth_required (SoupSession *session, SoupMessage *msg, - SoupAuth *auth, gboolean retrying) -{ - SoupSessionFeature *password_manager; - - password_manager = soup_session_get_feature_for_message ( - session, SOUP_TYPE_PASSWORD_MANAGER, msg); - if (password_manager) { - soup_session_pause_message (session, msg); - g_object_ref (auth); - soup_password_manager_get_passwords_async ( - SOUP_PASSWORD_MANAGER (password_manager), - msg, auth, retrying, - soup_session_get_async_context (session), - NULL, /* FIXME cancellable */ - got_passwords, session); - } else { - SOUP_SESSION_CLASS (soup_session_async_parent_class)-> - auth_required (session, msg, auth, retrying); - } -} - static void soup_session_async_class_init (SoupSessionAsyncClass *soup_session_async_class) { @@ -175,5 +140,4 @@ soup_session_async_class_init (SoupSessionAsyncClass *soup_session_async_class) session_class->queue_message = soup_session_async_queue_message; session_class->send_message = soup_session_async_send_message; session_class->cancel_message = soup_session_async_cancel_message; - session_class->auth_required = soup_session_async_auth_required; } diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index cbd24606..f6ae9682 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -9,8 +9,6 @@ #include #endif -#define LIBSOUP_I_HAVE_READ_BUG_594377_AND_KNOW_SOUP_PASSWORD_MANAGER_MIGHT_GO_AWAY - #include "soup-session-sync.h" #include "soup.h" #include "soup-session-private.h" @@ -138,24 +136,6 @@ soup_session_sync_send_message (SoupSession *session, SoupMessage *msg) return status; } -static void -soup_session_sync_auth_required (SoupSession *session, SoupMessage *msg, - SoupAuth *auth, gboolean retrying) -{ - SoupSessionFeature *password_manager; - - password_manager = soup_session_get_feature_for_message ( - session, SOUP_TYPE_PASSWORD_MANAGER, msg); - if (password_manager) { - soup_password_manager_get_passwords_sync ( - SOUP_PASSWORD_MANAGER (password_manager), - msg, auth, NULL); /* FIXME cancellable */ - } - - SOUP_SESSION_CLASS (soup_session_sync_parent_class)-> - auth_required (session, msg, auth, retrying); -} - static void soup_session_sync_class_init (SoupSessionSyncClass *session_sync_class) { @@ -164,5 +144,4 @@ soup_session_sync_class_init (SoupSessionSyncClass *session_sync_class) /* virtual method override */ session_class->queue_message = soup_session_sync_queue_message; session_class->send_message = soup_session_sync_send_message; - session_class->auth_required = soup_session_sync_auth_required; } diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 94a2214e..a5fac7de 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -922,20 +922,12 @@ free_host (SoupSessionHost *host) g_slice_free (SoupSessionHost, host); } -static void -soup_session_real_auth_required (SoupSession *session, SoupMessage *msg, - SoupAuth *auth, gboolean retrying) -{ - g_signal_emit (session, signals[AUTHENTICATE], 0, msg, auth, retrying); -} - static void auth_manager_authenticate (SoupAuthManager *manager, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer session) { - SOUP_SESSION_GET_CLASS (session)->auth_required ( - session, msg, auth, retrying); + g_signal_emit (session, signals[AUTHENTICATE], 0, msg, auth, retrying); } #define SOUP_SESSION_WOULD_REDIRECT_AS_GET(session, msg) \ @@ -2645,7 +2637,6 @@ soup_session_class_init (SoupSessionClass *session_class) /* virtual method definition */ session_class->requeue_message = soup_session_real_requeue_message; session_class->cancel_message = soup_session_real_cancel_message; - session_class->auth_required = soup_session_real_auth_required; session_class->flush_queue = soup_session_real_flush_queue; session_class->kick = soup_session_real_kick_queue; diff --git a/libsoup/soup.h b/libsoup/soup.h index f99f3e68..b1b74721 100644 --- a/libsoup/soup.h +++ b/libsoup/soup.h @@ -31,7 +31,6 @@ extern "C" { #include #include #include -#include #include #include #include -- cgit v1.2.1 From a2a4fccfa8ebd09aea232913eaa3bf1752038e40 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 11 Dec 2012 17:33:14 +0100 Subject: soup-session: fix a possible crash Calling soup_session_unqueue_item() will unref the item, so we need to add an extra ref if we want to ensure that it's still valid afterward. --- libsoup/soup-session.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index a5fac7de..f44bf8e1 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1793,9 +1793,11 @@ soup_session_process_queue_item (SoupSession *session, break; } + soup_message_queue_item_ref (item); soup_session_unqueue_item (session, item); if (item->async && item->callback) item->callback (session, item->msg, item->callback_data); + soup_message_queue_item_unref (item); return; default: -- cgit v1.2.1 From db084cb64d226afc8489386c7e3f45e6f584e43c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 11 Dec 2012 17:34:06 +0100 Subject: tests: fix memory leaks --- tests/libsoup.supp | 13 +++++++++++++ tests/multipart-test.c | 19 ++++++++++++++++--- tests/redirect-test.c | 2 ++ tests/sniffing-test.c | 8 ++++++-- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/tests/libsoup.supp b/tests/libsoup.supp index ac21e96a..ae8bda38 100644 --- a/tests/libsoup.supp +++ b/tests/libsoup.supp @@ -401,6 +401,19 @@ ... fun:thread_memory_from_self } +{ + glib/gobjectinit + Memcheck:Leak + ... + fun:gobject_init_ctor +} +{ + glib/gtask threadpool + Memcheck:Leak + ... + fun:g_thread_pool_new + fun:g_task_thread_pool_init +} # probably inlines the aggressive memcpy/memcmp { diff --git a/tests/multipart-test.c b/tests/multipart-test.c index 8bcc4cd4..a9b3425d 100644 --- a/tests/multipart-test.c +++ b/tests/multipart-test.c @@ -130,16 +130,19 @@ read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) GInputStream *stream = G_INPUT_STREAM (source); GError *error = NULL; gssize bytes_read = g_input_stream_read_finish (stream, asyncResult, &error); + if (error) { debug_printf (1, " failed read: %s\n", error->message); errors++; + g_object_unref (stream); g_main_loop_quit (loop); return; } if (!bytes_read) { g_input_stream_close (stream, NULL, &error); + g_object_unref (stream); if (error) { debug_printf (1, " failed close: %s\n", error->message); @@ -246,6 +249,7 @@ multipart_read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, multipart_close_part_cb, NULL); + g_object_unref (in); g_main_loop_quit (loop); return; @@ -259,6 +263,7 @@ multipart_read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, multipart_close_part_cb, NULL); + g_object_unref (in); soup_multipart_input_stream_next_part_async (multipart, G_PRIORITY_DEFAULT, NULL, multipart_next_part_cb, data); @@ -362,8 +367,10 @@ multipart_next_part_cb (GObject *source, GAsyncResult *res, gpointer data) if (error) { debug_printf (1, " failed next part: %s\n", error->message); + g_clear_error (&error); errors++; + g_object_unref (multipart); g_main_loop_quit (loop); return; } @@ -374,6 +381,7 @@ multipart_next_part_cb (GObject *source, GAsyncResult *res, gpointer data) errors++; } + g_object_unref (multipart); g_main_loop_quit (loop); return; } @@ -400,6 +408,8 @@ multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) in = soup_request_send_finish (request, res, &error); message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); multipart = soup_multipart_input_stream_new (message, in); + g_object_unref (message); + g_object_unref (in); if (error) { debug_printf (1, " failed send: %s\n", error->message); @@ -430,6 +440,8 @@ sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) in = soup_request_send_finish (request, res, &error); message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); multipart = soup_multipart_input_stream_new (message, in); + g_object_unref (message); + g_object_unref (in); if (error) { debug_printf (1, " failed send: %s\n", error->message); @@ -460,12 +472,14 @@ sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) debug_printf (1, " failed sync read: %s\n", error->message); errors++; g_clear_error (&error); + g_object_unref (in); break; } check_read (bytes_read, passes); passes++; + g_object_unref (in); } if (passes != 4) { @@ -474,7 +488,7 @@ sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) } g_main_loop_quit (loop); - + g_object_unref (multipart); } static const char* @@ -519,8 +533,6 @@ test_multipart (int headers_expected, int sniffed_expected, MultipartMode multip g_signal_connect (msg, "content-sniffed", G_CALLBACK (content_sniffed), &sniffed_count); - g_object_ref (msg); - if (multipart_mode == ASYNC_MULTIPART) soup_request_send_async (request, NULL, multipart_handling_cb, loop); else if (multipart_mode == ASYNC_MULTIPART_SMALL_READS) { @@ -599,6 +611,7 @@ main (int argc, char **argv) soup_uri_free (base_uri); g_free (base_uri_string); + g_free (buffer); soup_test_session_abort_unref (session); soup_test_server_quit_unref (server); diff --git a/tests/redirect-test.c b/tests/redirect-test.c index f820d003..3307ce63 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -270,6 +270,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) } g_error_free (error); + g_object_unref (msg); g_object_unref (reqh); debug_printf (2, "\n"); return; @@ -277,6 +278,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) debug_printf (1, " could not send request: %s\n", error->message); g_error_free (error); + g_object_unref (msg); g_object_unref (reqh); errors++; debug_printf (2, "\n"); diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index e77154e1..ab8099da 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -384,8 +384,10 @@ test_sniffing (const char *path, const char *expected_type) req = soup_session_request_uri (session, uri, NULL); stream = soup_test_request_send (req, NULL, &error); - if (stream) + if (stream) { soup_test_request_close_stream (req, stream, NULL, &error); + g_object_unref (stream); + } if (error) { debug_printf (1, " request failed: %s\n", error->message); g_clear_error (&error); @@ -436,8 +438,10 @@ test_disabled (const char *path) req = soup_session_request_uri (session, uri, NULL); soup_request_disable_feature (req, SOUP_TYPE_CONTENT_SNIFFER); stream = soup_test_request_send (req, NULL, &error); - if (stream) + if (stream) { soup_test_request_close_stream (req, stream, NULL, &error); + g_object_unref (stream); + } if (error) { debug_printf (1, " request failed: %s\n", error->message); g_clear_error (&error); -- cgit v1.2.1 From ade7a484f33f223defad9acb50396058767781e1 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 11 Dec 2012 18:43:42 +0100 Subject: Add SoupCookieJarDB to replace SoupCookieJarSqlite Move SoupCookieJarSqlite (and its sqlite3 dependency) into libsoup from libsoup-gnome, but rename it to SoupCookieJarDB so libsoup-gnome can keep using the old name. SoupCookieJarSqlite is now just a wrapper around SoupCookieJarDB. --- configure.ac | 14 +- docs/reference/libsoup-2.4-docs.sgml | 2 +- docs/reference/libsoup-2.4-sections.txt | 27 ++- libsoup/Makefile.am | 6 +- libsoup/libsoup-2.4.sym | 2 + libsoup/soup-cookie-jar-db.c | 337 ++++++++++++++++++++++++++++++++ libsoup/soup-cookie-jar-db.h | 46 +++++ libsoup/soup-cookie-jar-sqlite.c | 298 +--------------------------- libsoup/soup-cookie-jar-sqlite.h | 13 +- libsoup/soup.h | 1 + 10 files changed, 419 insertions(+), 327 deletions(-) create mode 100644 libsoup/soup-cookie-jar-db.c create mode 100644 libsoup/soup-cookie-jar-db.h diff --git a/configure.ac b/configure.ac index 3f5097c2..fe5403b8 100644 --- a/configure.ac +++ b/configure.ac @@ -97,6 +97,10 @@ PKG_CHECK_MODULES(XML, libxml-2.0) AC_SUBST(XML_CFLAGS) AC_SUBST(XML_LIBS) +PKG_CHECK_MODULES(SQLITE, sqlite3) +AC_SUBST(SQLITE_CFLAGS) +AC_SUBST(SQLITE_LIBS) + dnl *********************** dnl *** Check for Win32 *** dnl *********************** @@ -142,18 +146,8 @@ AM_CONDITIONAL(BUILD_LIBSOUP_GNOME, test $with_gnome != no) if test $with_gnome != no; then AC_DEFINE(HAVE_GNOME, 1, [Defined if GNOME support is enabled]) - - PKG_CHECK_MODULES(SQLITE, sqlite3, :, [AC_MSG_ERROR(dnl -[Could not find sqlite3 devel files: - -$SQLITE_PKG_ERRORS - -Pass "--without-gnome" to configure if you want to build libsoup -without GNOME support.])]) fi AC_SUBST(HAVE_GNOME) -AC_SUBST(SQLITE_CFLAGS) -AC_SUBST(SQLITE_LIBS) dnl *************** diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index 3f246767..1273ecaa 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -49,6 +49,7 @@ + @@ -64,7 +65,6 @@ GNOME integration - diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 43388ef4..f8e6dbf1 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -973,22 +973,21 @@ soup_cookie_jar_text_get_type
-libsoup/soup-gnome.h -soup-cookie-jar-sqlite -SoupCookieJarSqlite -SoupCookieJarSqlite -soup_cookie_jar_sqlite_new +soup-cookie-jar-db +SoupCookieJarDB +SoupCookieJarDB +soup_cookie_jar_db_new -SOUP_COOKIE_JAR_SQLITE_FILENAME +SOUP_COOKIE_JAR_DB_FILENAME -SoupCookieJarSqliteClass -SOUP_COOKIE_JAR_SQLITE -SOUP_COOKIE_JAR_SQLITE_CLASS -SOUP_COOKIE_JAR_SQLITE_GET_CLASS -SOUP_TYPE_COOKIE_JAR_SQLITE -SOUP_IS_COOKIE_JAR_SQLITE -SOUP_IS_COOKIE_JAR_SQLITE_CLASS -soup_cookie_jar_sqlite_get_type +SoupCookieJarDBClass +SOUP_COOKIE_JAR_DB +SOUP_COOKIE_JAR_DB_CLASS +SOUP_COOKIE_JAR_DB_GET_CLASS +SOUP_TYPE_COOKIE_JAR_DB +SOUP_IS_COOKIE_JAR_DB +SOUP_IS_COOKIE_JAR_DB_CLASS +soup_cookie_jar_db_get_type
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 3a256e02..87629ed1 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -34,6 +34,7 @@ soup_headers = \ soup-content-sniffer.h \ soup-cookie.h \ soup-cookie-jar.h \ + soup-cookie-jar-db.h \ soup-cookie-jar-text.h \ soup-date.h \ soup-form.h \ @@ -88,6 +89,7 @@ EXTRA_DIST += libsoup-2.4.sym libsoup_2_4_la_LIBADD = \ $(GLIB_LIBS) \ $(XML_LIBS) \ + $(SQLITE_LIBS) \ -lz \ $(LIBWS2_32) @@ -127,6 +129,7 @@ libsoup_2_4_la_SOURCES = \ soup-converter-wrapper.c \ soup-cookie.c \ soup-cookie-jar.c \ + soup-cookie-jar-db.c \ soup-cookie-jar-text.c \ soup-date.c \ soup-directory-input-stream.h \ @@ -212,8 +215,7 @@ EXTRA_DIST += libsoup-gnome-2.4.sym libsoup_gnome_2_4_la_LIBADD = \ libsoup-2.4.la \ - $(GLIB_LIBS) \ - $(SQLITE_LIBS) + $(GLIB_LIBS) libsoup_gnome_2_4_la_SOURCES = \ soup-cookie-jar-sqlite.c \ diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index aa302c67..66e5bf7f 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -110,6 +110,8 @@ soup_cookie_jar_accept_policy_get_type soup_cookie_jar_add_cookie soup_cookie_jar_add_cookie_with_first_party soup_cookie_jar_all_cookies +soup_cookie_jar_db_get_type +soup_cookie_jar_db_new soup_cookie_jar_delete_cookie soup_cookie_jar_get_accept_policy soup_cookie_jar_get_cookie_list diff --git a/libsoup/soup-cookie-jar-db.c b/libsoup/soup-cookie-jar-db.c new file mode 100644 index 00000000..8f21baab --- /dev/null +++ b/libsoup/soup-cookie-jar-db.c @@ -0,0 +1,337 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cookie-jar-db.c: database-based cookie storage + * + * Using danw's soup-cookie-jar-text as template + * Copyright (C) 2008 Diego Escalante Urrelo + * Copyright (C) 2009 Collabora Ltd. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include + +#include "soup-cookie-jar-db.h" +#include "soup.h" + +/** + * SECTION:soup-cookie-jar-db + * @short_description: Database-based Cookie Jar + * + * #SoupCookieJarDB is a #SoupCookieJar that reads cookies from and + * writes them to a sqlite database in the new Mozilla format. + * + * (This is identical to SoupCookieJarSqlite in + * libsoup-gnome; it has just been moved into libsoup proper, and + * renamed to avoid conflicting.) + **/ + +enum { + PROP_0, + + PROP_FILENAME, + + LAST_PROP +}; + +typedef struct { + char *filename; + sqlite3 *db; +} SoupCookieJarDBPrivate; + +#define SOUP_COOKIE_JAR_DB_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_COOKIE_JAR_DB, SoupCookieJarDBPrivate)) + +G_DEFINE_TYPE (SoupCookieJarDB, soup_cookie_jar_db, SOUP_TYPE_COOKIE_JAR) + +static void load (SoupCookieJar *jar); + +static void +soup_cookie_jar_db_init (SoupCookieJarDB *db) +{ +} + +static void +soup_cookie_jar_db_finalize (GObject *object) +{ + SoupCookieJarDBPrivate *priv = + SOUP_COOKIE_JAR_DB_GET_PRIVATE (object); + + g_free (priv->filename); + g_clear_pointer (&priv->db, sqlite3_close); + + G_OBJECT_CLASS (soup_cookie_jar_db_parent_class)->finalize (object); +} + +static void +soup_cookie_jar_db_set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + SoupCookieJarDBPrivate *priv = + SOUP_COOKIE_JAR_DB_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_FILENAME: + priv->filename = g_value_dup_string (value); + load (SOUP_COOKIE_JAR (object)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +soup_cookie_jar_db_get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + SoupCookieJarDBPrivate *priv = + SOUP_COOKIE_JAR_DB_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_FILENAME: + g_value_set_string (value, priv->filename); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * soup_cookie_jar_db_new: + * @filename: the filename to read to/write from, or %NULL + * @read_only: %TRUE if @filename is read-only + * + * Creates a #SoupCookieJarDB. + * + * @filename will be read in at startup to create an initial set of + * cookies. If @read_only is %FALSE, then the non-session cookies will + * be written to @filename when the 'changed' signal is emitted from + * the jar. (If @read_only is %TRUE, then the cookie jar will only be + * used for this session, and changes made to it will be lost when the + * jar is destroyed.) + * + * Return value: the new #SoupCookieJar + * + * Since: 2.42 + **/ +SoupCookieJar * +soup_cookie_jar_db_new (const char *filename, gboolean read_only) +{ + g_return_val_if_fail (filename != NULL, NULL); + + return g_object_new (SOUP_TYPE_COOKIE_JAR_DB, + SOUP_COOKIE_JAR_DB_FILENAME, filename, + SOUP_COOKIE_JAR_READ_ONLY, read_only, + NULL); +} + +#define QUERY_ALL "SELECT id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly FROM moz_cookies;" +#define CREATE_TABLE "CREATE TABLE moz_cookies (id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,expiry INTEGER, lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)" +#define QUERY_INSERT "INSERT INTO moz_cookies VALUES(NULL, %Q, %Q, %Q, %Q, %d, NULL, %d, %d);" +#define QUERY_DELETE "DELETE FROM moz_cookies WHERE name=%Q AND host=%Q;" + +enum { + COL_ID, + COL_NAME, + COL_VALUE, + COL_HOST, + COL_PATH, + COL_EXPIRY, + COL_LAST_ACCESS, + COL_SECURE, + COL_HTTP_ONLY, + N_COL, +}; + +static int +callback (void *data, int argc, char **argv, char **colname) +{ + SoupCookie *cookie = NULL; + SoupCookieJar *jar = SOUP_COOKIE_JAR (data); + + char *name, *value, *host, *path; + gulong expire_time; + time_t now; + int max_age; + gboolean http_only = FALSE, secure = FALSE; + + now = time (NULL); + + name = argv[COL_NAME]; + value = argv[COL_VALUE]; + host = argv[COL_HOST]; + path = argv[COL_PATH]; + expire_time = strtoul (argv[COL_EXPIRY], NULL, 10); + + if (now >= expire_time) + return 0; + max_age = (expire_time - now <= G_MAXINT ? expire_time - now : G_MAXINT); + + http_only = (g_strcmp0 (argv[COL_HTTP_ONLY], "1") == 0); + secure = (g_strcmp0 (argv[COL_SECURE], "1") == 0); + + cookie = soup_cookie_new (name, value, host, path, max_age); + + if (secure) + soup_cookie_set_secure (cookie, TRUE); + if (http_only) + soup_cookie_set_http_only (cookie, TRUE); + + soup_cookie_jar_add_cookie (jar, cookie); + + return 0; +} + +static void +try_create_table (sqlite3 *db) +{ + char *error = NULL; + + if (sqlite3_exec (db, CREATE_TABLE, NULL, NULL, &error)) { + g_warning ("Failed to execute query: %s", error); + sqlite3_free (error); + } +} + +static void +exec_query_with_try_create_table (sqlite3 *db, + const char *sql, + int (*callback)(void*,int,char**,char**), + void *argument) +{ + char *error = NULL; + gboolean try_create = TRUE; + +try_exec: + if (sqlite3_exec (db, sql, callback, argument, &error)) { + if (try_create) { + try_create = FALSE; + try_create_table (db); + sqlite3_free (error); + error = NULL; + goto try_exec; + } else { + g_warning ("Failed to execute query: %s", error); + sqlite3_free (error); + } + } +} + +/* Follows sqlite3 convention; returns TRUE on error */ +static gboolean +open_db (SoupCookieJar *jar) +{ + SoupCookieJarDBPrivate *priv = + SOUP_COOKIE_JAR_DB_GET_PRIVATE (jar); + + char *error = NULL; + + if (sqlite3_open (priv->filename, &priv->db)) { + sqlite3_close (priv->db); + priv->db = NULL; + g_warning ("Can't open %s", priv->filename); + return TRUE; + } + + if (sqlite3_exec (priv->db, "PRAGMA synchronous = OFF; PRAGMA secure_delete = 1;", NULL, NULL, &error)) { + g_warning ("Failed to execute query: %s", error); + sqlite3_free (error); + } + + return FALSE; +} + +static void +load (SoupCookieJar *jar) +{ + SoupCookieJarDBPrivate *priv = + SOUP_COOKIE_JAR_DB_GET_PRIVATE (jar); + + if (priv->db == NULL) { + if (open_db (jar)) + return; + } + + exec_query_with_try_create_table (priv->db, QUERY_ALL, callback, jar); +} + +static void +soup_cookie_jar_db_changed (SoupCookieJar *jar, + SoupCookie *old_cookie, + SoupCookie *new_cookie) +{ + SoupCookieJarDBPrivate *priv = + SOUP_COOKIE_JAR_DB_GET_PRIVATE (jar); + char *query; + + if (priv->db == NULL) { + if (open_db (jar)) + return; + } + + if (old_cookie) { + query = sqlite3_mprintf (QUERY_DELETE, + old_cookie->name, + old_cookie->domain); + exec_query_with_try_create_table (priv->db, query, NULL, NULL); + sqlite3_free (query); + } + + if (new_cookie && new_cookie->expires) { + gulong expires; + + expires = (gulong)soup_date_to_time_t (new_cookie->expires); + query = sqlite3_mprintf (QUERY_INSERT, + new_cookie->name, + new_cookie->value, + new_cookie->domain, + new_cookie->path, + expires, + new_cookie->secure, + new_cookie->http_only); + exec_query_with_try_create_table (priv->db, query, NULL, NULL); + sqlite3_free (query); + } +} + +static gboolean +soup_cookie_jar_db_is_persistent (SoupCookieJar *jar) +{ + return TRUE; +} + +static void +soup_cookie_jar_db_class_init (SoupCookieJarDBClass *db_class) +{ + SoupCookieJarClass *cookie_jar_class = + SOUP_COOKIE_JAR_CLASS (db_class); + GObjectClass *object_class = G_OBJECT_CLASS (db_class); + + g_type_class_add_private (db_class, sizeof (SoupCookieJarDBPrivate)); + + cookie_jar_class->is_persistent = soup_cookie_jar_db_is_persistent; + cookie_jar_class->changed = soup_cookie_jar_db_changed; + + object_class->finalize = soup_cookie_jar_db_finalize; + object_class->set_property = soup_cookie_jar_db_set_property; + object_class->get_property = soup_cookie_jar_db_get_property; + + /** + * SOUP_COOKIE_JAR_DB_FILENAME: + * + * Alias for the #SoupCookieJarDB:filename property. (The + * cookie-storage filename.) + **/ + g_object_class_install_property ( + object_class, PROP_FILENAME, + g_param_spec_string (SOUP_COOKIE_JAR_DB_FILENAME, + "Filename", + "Cookie-storage filename", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} diff --git a/libsoup/soup-cookie-jar-db.h b/libsoup/soup-cookie-jar-db.h new file mode 100644 index 00000000..1a989015 --- /dev/null +++ b/libsoup/soup-cookie-jar-db.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Diego Escalante Urrelo + */ + +#ifndef SOUP_COOKIE_JAR_DB_H +#define SOUP_COOKIE_JAR_DB_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_COOKIE_JAR_DB (soup_cookie_jar_db_get_type ()) +#define SOUP_COOKIE_JAR_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_COOKIE_JAR_DB, SoupCookieJarDB)) +#define SOUP_COOKIE_JAR_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_COOKIE_JAR_DB, SoupCookieJarDBClass)) +#define SOUP_IS_COOKIE_JAR_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_DB)) +#define SOUP_IS_COOKIE_JAR_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_COOKIE_JAR_DB)) +#define SOUP_COOKIE_JAR_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_COOKIE_JAR_DB, SoupCookieJarDBClass)) + +typedef struct { + SoupCookieJar parent; + +} SoupCookieJarDB; + +typedef struct { + SoupCookieJarClass parent_class; + + /* Padding for future expansion */ + void (*_libsoup_reserved1) (void); + void (*_libsoup_reserved2) (void); + void (*_libsoup_reserved3) (void); + void (*_libsoup_reserved4) (void); +} SoupCookieJarDBClass; + +#define SOUP_COOKIE_JAR_DB_FILENAME "filename" + +SOUP_AVAILABLE_IN_2_42 +GType soup_cookie_jar_db_get_type (void); + +SOUP_AVAILABLE_IN_2_42 +SoupCookieJar *soup_cookie_jar_db_new (const char *filename, + gboolean read_only); + +G_END_DECLS + +#endif /* SOUP_COOKIE_JAR_DB_H */ diff --git a/libsoup/soup-cookie-jar-sqlite.c b/libsoup/soup-cookie-jar-sqlite.c index 97e6a0e6..705e0478 100644 --- a/libsoup/soup-cookie-jar-sqlite.c +++ b/libsoup/soup-cookie-jar-sqlite.c @@ -1,10 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * soup-cookie-jar-sqlite.c: ff sqlite-based cookie storage + * soup-cookie-jar-sqlite.c: deprecated version of sqlite-based cookie storage * - * Using danw's soup-cookie-jar-text as template - * Copyright (C) 2008 Diego Escalante Urrelo - * Copyright (C) 2009 Collabora Ltd. + * Copyright 2012 Red Hat, Inc. */ #ifdef HAVE_CONFIG_H @@ -13,18 +11,11 @@ #include -#include +/* Avoid deprecation warnings */ +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_40 -#include "soup-cookie-jar-sqlite.h" #include "soup.h" - -/** - * SECTION:soup-cookie-jar-sqlite - * @short_description: SQLite-based Cookie Jar - * - * #SoupCookieJarSqlite is a #SoupCookieJar that reads cookies from and - * writes them to an SQLite file in the new Mozilla format. - **/ +#include "soup-cookie-jar-sqlite.h" enum { PROP_0, @@ -34,89 +25,13 @@ enum { LAST_PROP }; -typedef struct { - char *filename; - sqlite3 *db; -} SoupCookieJarSqlitePrivate; - -#define SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqlitePrivate)) - -G_DEFINE_TYPE (SoupCookieJarSqlite, soup_cookie_jar_sqlite, SOUP_TYPE_COOKIE_JAR) - -static void load (SoupCookieJar *jar); +G_DEFINE_TYPE (SoupCookieJarSqlite, soup_cookie_jar_sqlite, SOUP_TYPE_COOKIE_JAR_DB) static void soup_cookie_jar_sqlite_init (SoupCookieJarSqlite *sqlite) { } -static void -soup_cookie_jar_sqlite_finalize (GObject *object) -{ - SoupCookieJarSqlitePrivate *priv = - SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (object); - - g_free (priv->filename); - - if (priv->db) - sqlite3_close (priv->db); - - G_OBJECT_CLASS (soup_cookie_jar_sqlite_parent_class)->finalize (object); -} - -static void -soup_cookie_jar_sqlite_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - SoupCookieJarSqlitePrivate *priv = - SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_FILENAME: - priv->filename = g_value_dup_string (value); - load (SOUP_COOKIE_JAR (object)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -soup_cookie_jar_sqlite_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - SoupCookieJarSqlitePrivate *priv = - SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_FILENAME: - g_value_set_string (value, priv->filename); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * soup_cookie_jar_sqlite_new: - * @filename: the filename to read to/write from, or %NULL - * @read_only: %TRUE if @filename is read-only - * - * Creates a #SoupCookieJarSqlite. - * - * @filename will be read in at startup to create an initial set of - * cookies. If @read_only is %FALSE, then the non-session cookies will - * be written to @filename when the 'changed' signal is emitted from - * the jar. (If @read_only is %TRUE, then the cookie jar will only be - * used for this session, and changes made to it will be lost when the - * jar is destroyed.) - * - * Return value: the new #SoupCookieJar - * - * Since: 2.26 - **/ SoupCookieJar * soup_cookie_jar_sqlite_new (const char *filename, gboolean read_only) { @@ -128,208 +43,7 @@ soup_cookie_jar_sqlite_new (const char *filename, gboolean read_only) NULL); } -#define QUERY_ALL "SELECT id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly FROM moz_cookies;" -#define CREATE_TABLE "CREATE TABLE moz_cookies (id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,expiry INTEGER, lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)" -#define QUERY_INSERT "INSERT INTO moz_cookies VALUES(NULL, %Q, %Q, %Q, %Q, %d, NULL, %d, %d);" -#define QUERY_DELETE "DELETE FROM moz_cookies WHERE name=%Q AND host=%Q;" - -enum { - COL_ID, - COL_NAME, - COL_VALUE, - COL_HOST, - COL_PATH, - COL_EXPIRY, - COL_LAST_ACCESS, - COL_SECURE, - COL_HTTP_ONLY, - N_COL, -}; - -static int -callback (void *data, int argc, char **argv, char **colname) -{ - SoupCookie *cookie = NULL; - SoupCookieJar *jar = SOUP_COOKIE_JAR (data); - - char *name, *value, *host, *path; - gulong expire_time; - time_t now; - int max_age; - gboolean http_only = FALSE, secure = FALSE; - - now = time (NULL); - - name = argv[COL_NAME]; - value = argv[COL_VALUE]; - host = argv[COL_HOST]; - path = argv[COL_PATH]; - expire_time = strtoul (argv[COL_EXPIRY], NULL, 10); - - if (now >= expire_time) - return 0; - max_age = (expire_time - now <= G_MAXINT ? expire_time - now : G_MAXINT); - - http_only = (g_strcmp0 (argv[COL_HTTP_ONLY], "1") == 0); - secure = (g_strcmp0 (argv[COL_SECURE], "1") == 0); - - cookie = soup_cookie_new (name, value, host, path, max_age); - - if (secure) - soup_cookie_set_secure (cookie, TRUE); - if (http_only) - soup_cookie_set_http_only (cookie, TRUE); - - soup_cookie_jar_add_cookie (jar, cookie); - - return 0; -} - -static void -try_create_table (sqlite3 *db) -{ - char *error = NULL; - - if (sqlite3_exec (db, CREATE_TABLE, NULL, NULL, &error)) { - g_warning ("Failed to execute query: %s", error); - sqlite3_free (error); - } -} - -static void -exec_query_with_try_create_table (sqlite3 *db, - const char *sql, - int (*callback)(void*,int,char**,char**), - void *argument) -{ - char *error = NULL; - gboolean try_create = TRUE; - -try_exec: - if (sqlite3_exec (db, sql, callback, argument, &error)) { - if (try_create) { - try_create = FALSE; - try_create_table (db); - sqlite3_free (error); - error = NULL; - goto try_exec; - } else { - g_warning ("Failed to execute query: %s", error); - sqlite3_free (error); - } - } -} - -/* Follows sqlite3 convention; returns TRUE on error */ -static gboolean -open_db (SoupCookieJar *jar) -{ - SoupCookieJarSqlitePrivate *priv = - SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (jar); - - char *error = NULL; - - if (sqlite3_open (priv->filename, &priv->db)) { - sqlite3_close (priv->db); - priv->db = NULL; - g_warning ("Can't open %s", priv->filename); - return TRUE; - } - - if (sqlite3_exec (priv->db, "PRAGMA synchronous = OFF; PRAGMA secure_delete = 1;", NULL, NULL, &error)) { - g_warning ("Failed to execute query: %s", error); - sqlite3_free (error); - } - - return FALSE; -} - -static void -load (SoupCookieJar *jar) -{ - SoupCookieJarSqlitePrivate *priv = - SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (jar); - - if (priv->db == NULL) { - if (open_db (jar)) - return; - } - - exec_query_with_try_create_table (priv->db, QUERY_ALL, callback, jar); -} - -static void -soup_cookie_jar_sqlite_changed (SoupCookieJar *jar, - SoupCookie *old_cookie, - SoupCookie *new_cookie) -{ - SoupCookieJarSqlitePrivate *priv = - SOUP_COOKIE_JAR_SQLITE_GET_PRIVATE (jar); - char *query; - - if (priv->db == NULL) { - if (open_db (jar)) - return; - } - - if (old_cookie) { - query = sqlite3_mprintf (QUERY_DELETE, - old_cookie->name, - old_cookie->domain); - exec_query_with_try_create_table (priv->db, query, NULL, NULL); - sqlite3_free (query); - } - - if (new_cookie && new_cookie->expires) { - gulong expires; - - expires = (gulong)soup_date_to_time_t (new_cookie->expires); - query = sqlite3_mprintf (QUERY_INSERT, - new_cookie->name, - new_cookie->value, - new_cookie->domain, - new_cookie->path, - expires, - new_cookie->secure, - new_cookie->http_only); - exec_query_with_try_create_table (priv->db, query, NULL, NULL); - sqlite3_free (query); - } -} - -static gboolean -soup_cookie_jar_sqlite_is_persistent (SoupCookieJar *jar) -{ - return TRUE; -} - static void soup_cookie_jar_sqlite_class_init (SoupCookieJarSqliteClass *sqlite_class) { - SoupCookieJarClass *cookie_jar_class = - SOUP_COOKIE_JAR_CLASS (sqlite_class); - GObjectClass *object_class = G_OBJECT_CLASS (sqlite_class); - - g_type_class_add_private (sqlite_class, sizeof (SoupCookieJarSqlitePrivate)); - - cookie_jar_class->is_persistent = soup_cookie_jar_sqlite_is_persistent; - cookie_jar_class->changed = soup_cookie_jar_sqlite_changed; - - object_class->finalize = soup_cookie_jar_sqlite_finalize; - object_class->set_property = soup_cookie_jar_sqlite_set_property; - object_class->get_property = soup_cookie_jar_sqlite_get_property; - - /** - * SOUP_COOKIE_JAR_SQLITE_FILENAME: - * - * Alias for the #SoupCookieJarSqlite:filename property. (The - * cookie-storage filename.) - **/ - g_object_class_install_property ( - object_class, PROP_FILENAME, - g_param_spec_string (SOUP_COOKIE_JAR_SQLITE_FILENAME, - "Filename", - "Cookie-storage filename", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } diff --git a/libsoup/soup-cookie-jar-sqlite.h b/libsoup/soup-cookie-jar-sqlite.h index 97cdf331..adc27868 100644 --- a/libsoup/soup-cookie-jar-sqlite.h +++ b/libsoup/soup-cookie-jar-sqlite.h @@ -6,7 +6,7 @@ #ifndef SOUP_COOKIE_JAR_SQLITE_H #define SOUP_COOKIE_JAR_SQLITE_H 1 -#include +#include G_BEGIN_DECLS @@ -18,26 +18,23 @@ G_BEGIN_DECLS #define SOUP_COOKIE_JAR_SQLITE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_COOKIE_JAR_SQLITE, SoupCookieJarSqliteClass)) typedef struct { - SoupCookieJar parent; + SoupCookieJarDB parent; } SoupCookieJarSqlite; typedef struct { - SoupCookieJarClass parent_class; + SoupCookieJarDBClass parent_class; - /* Padding for future expansion */ - void (*_libsoup_reserved1) (void); - void (*_libsoup_reserved2) (void); - void (*_libsoup_reserved3) (void); - void (*_libsoup_reserved4) (void); } SoupCookieJarSqliteClass; #define SOUP_COOKIE_JAR_SQLITE_FILENAME "filename" SOUP_AVAILABLE_IN_2_26 +SOUP_DEPRECATED_IN_2_42_FOR(soup_cookie_jar_db_get_type) GType soup_cookie_jar_sqlite_get_type (void); SOUP_AVAILABLE_IN_2_26 +SOUP_DEPRECATED_IN_2_42_FOR(soup_cookie_jar_db_new) SoupCookieJar *soup_cookie_jar_sqlite_new (const char *filename, gboolean read_only); diff --git a/libsoup/soup.h b/libsoup/soup.h index b1b74721..fd836feb 100644 --- a/libsoup/soup.h +++ b/libsoup/soup.h @@ -20,6 +20,7 @@ extern "C" { #include #include #include +#include #include #include #include -- cgit v1.2.1 From 4ded0924fd82e006f31a8e9089fd297fac15eef9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 11 Dec 2012 19:03:36 +0100 Subject: soup-gnome: belatedly deprecate SoupProxyResolverGNOME There's no real reason to use SoupProxyResolverGNOME rather than SoupProxyResolverDefault, so deprecate that too. libsoup-gnome now consists entirely of deprecated functions. --- docs/reference/libsoup-2.4-docs.sgml | 5 ----- docs/reference/libsoup-2.4-sections.txt | 12 ----------- libsoup/soup-gnome-features.c | 35 ++------------------------------- libsoup/soup-gnome-features.h | 2 ++ 4 files changed, 4 insertions(+), 50 deletions(-) diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index 1273ecaa..95ff9c98 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -62,11 +62,6 @@ - - GNOME integration - - - Low-level Networking API diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index f8e6dbf1..b2952fd0 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -1008,18 +1008,6 @@ SOUP_TYPE_PROXY_URI_RESOLVER soup_proxy_uri_resolver_get_type
-
-libsoup/soup-gnome.h -soup-gnome-features -SOUP_TYPE_GNOME_FEATURES_2_26 -SOUP_TYPE_PROXY_RESOLVER_GNOME - -soup_proxy_resolver_gnome_get_type -soup_gnome_features_2_26_get_type -SOUP_TYPE_PASSWORD_MANAGER_GNOME -soup_password_manager_gnome_get_type -
-
soup-content-sniffer SoupContentSniffer diff --git a/libsoup/soup-gnome-features.c b/libsoup/soup-gnome-features.c index 798712a2..4b40f34c 100644 --- a/libsoup/soup-gnome-features.c +++ b/libsoup/soup-gnome-features.c @@ -11,42 +11,11 @@ #include "soup-gnome-features.h" -/** - * SOUP_TYPE_PROXY_RESOLVER_GNOME: - * - * This returns the #GType of a #SoupProxyURIResolver that can be used to - * resolve HTTP proxies for GNOME applications. You can add this to - * a session using soup_session_add_feature_by_type() or by using the - * %SOUP_SESSION_ADD_FEATURE_BY_TYPE construct-time property. - * - * This feature is included in %SOUP_TYPE_GNOME_FEATURES_2_26, so if - * you are using that feature, you do not need to include this feature - * separately. - * - * Since: 2.26 - **/ -/* This is actually declared in soup-proxy-resolver-gnome now */ - -/** - * SOUP_TYPE_GNOME_FEATURES_2_26: - * - * This returns the #GType of a #SoupSessionFeature that automatically - * adds all of the GNOME features defined for libsoup 2.26 (which is - * just %SOUP_TYPE_PROXY_RESOLVER_GNOME). - * - * You can add this to a session using - * soup_session_add_feature_by_type() or by using the - * %SOUP_SESSION_ADD_FEATURE_BY_TYPE construct-time property. - * - * Since: 2.26 - **/ GType soup_gnome_features_2_26_get_type (void) { - /* Eventually this needs to be a special SoupSessionFeature - * class that registers other features. But for now we can - * just do this: - */ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; return SOUP_TYPE_PROXY_RESOLVER_GNOME; + G_GNUC_END_IGNORE_DEPRECATIONS; } diff --git a/libsoup/soup-gnome-features.h b/libsoup/soup-gnome-features.h index 34856722..648d5043 100644 --- a/libsoup/soup-gnome-features.h +++ b/libsoup/soup-gnome-features.h @@ -11,10 +11,12 @@ G_BEGIN_DECLS SOUP_AVAILABLE_IN_2_26 +SOUP_DEPRECATED_IN_2_42_FOR(SOUP_TYPE_PROXY_RESOLVER_DEFAULT) GType soup_proxy_resolver_gnome_get_type (void); #define SOUP_TYPE_PROXY_RESOLVER_GNOME (soup_proxy_resolver_gnome_get_type ()) SOUP_AVAILABLE_IN_2_26 +SOUP_DEPRECATED_IN_2_42 GType soup_gnome_features_2_26_get_type (void); #define SOUP_TYPE_GNOME_FEATURES_2_26 (soup_gnome_features_2_26_get_type ()) -- cgit v1.2.1 From b62854f057dc6fba9d4cab976157231427a26a79 Mon Sep 17 00:00:00 2001 From: Nilamdyuti Goswami Date: Wed, 12 Dec 2012 13:50:53 +0530 Subject: Assamese translation updated --- po/as.po | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/po/as.po b/po/as.po index ec6d8ac8..4992402e 100644 --- a/po/as.po +++ b/po/as.po @@ -6,17 +6,17 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." -"cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-11 21:15+0530\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-12-10 16:22+0000\n" +"PO-Revision-Date: 2012-12-12 13:50+0530\n" "Last-Translator: Nilamdyuti Goswami \n" -"Language-Team: as_IN \n" +"Language-Team: Assamese \n" "Language: as\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Lokalize 1.0\n" +"X-Generator: Lokalize 1.5\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: ../libsoup/soup-body-input-stream.c:141 @@ -38,34 +38,53 @@ msgstr "SoupBodyInputStream চুটি কৰিব নোৱাৰি" msgid "Output buffer is too small" msgstr "আউটপুট বাফাৰ অতি সৰু" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP প্ৰতিক্ৰিয়া বিশ্লেষণ কৰিব পৰা নগল" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "অপৰিচিত HTTP প্ৰতিক্ৰিয়া এনক'ডিং" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "কাৰ্য্য বাতিল কৰা হৈছিল" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "কাৰ্য্য প্ৰতিৰোধ কৰিব" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP অনুৰোধ বিশ্লেষণ কৰিব পৰা নগল" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "কোনো URl প্ৰদান কৰা হোৱা নাই" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "অবৈধ '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3759 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' বিশ্লেষণ কৰিব পৰা নগল" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3796 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "অসমৰ্থিত URl আঁচনি '%s'" +#: ../libsoup/soup-session.c:3818 +#, c-format +msgid "Not an HTTP URI" +msgstr "এটা HTTP URI নহয়" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "হস্টনাম এটা IP ঠিকনা" -- cgit v1.2.1 From 6c539304a552f3bc52cab0770fb34ab966f55480 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 26 Nov 2012 17:24:36 -0500 Subject: soup-body-output-stream: fix non-blocking writing Since soup_body_output_stream_write_chunked() sometimes loops and does multiple writes, it's not enough to just check is_writable() first and then do a blocking write. Implement write_nonblocking() to fix this. Noticed by Milan Plzik. https://bugzilla.gnome.org/show_bug.cgi?id=688974 --- libsoup/soup-body-output-stream.c | 47 ++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/libsoup/soup-body-output-stream.c b/libsoup/soup-body-output-stream.c index 86f131ab..a1419754 100644 --- a/libsoup/soup-body-output-stream.c +++ b/libsoup/soup-body-output-stream.c @@ -104,6 +104,7 @@ static gssize soup_body_output_stream_write_raw (SoupBodyOutputStream *bostream, const void *buffer, gsize count, + gboolean blocking, GCancellable *cancellable, GError **error) { @@ -122,9 +123,9 @@ soup_body_output_stream_write_raw (SoupBodyOutputStream *bostream, } else my_count = count; - nwrote = g_output_stream_write (bostream->priv->base_stream, - buffer, my_count, - cancellable, error); + nwrote = g_pollable_stream_write (bostream->priv->base_stream, + buffer, my_count, + blocking, cancellable, error); if (nwrote > 0 && bostream->priv->write_length) bostream->priv->written += nwrote; @@ -139,6 +140,7 @@ static gssize soup_body_output_stream_write_chunked (SoupBodyOutputStream *bostream, const void *buffer, gsize count, + gboolean blocking, GCancellable *cancellable, GError **error) { @@ -148,8 +150,9 @@ soup_body_output_stream_write_chunked (SoupBodyOutputStream *bostream, again: len = strlen (buf); if (len) { - nwrote = g_output_stream_write (bostream->priv->base_stream, - buf, len, cancellable, error); + nwrote = g_pollable_stream_write (bostream->priv->base_stream, + buf, len, blocking, + cancellable, error); if (nwrote < 0) return nwrote; memmove (buf, buf + nwrote, len + 1 - nwrote); @@ -169,8 +172,9 @@ again: break; case SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK: - nwrote = g_output_stream_write (bostream->priv->base_stream, - buffer, count, cancellable, error); + nwrote = g_pollable_stream_write (bostream->priv->base_stream, + buffer, count, blocking, + cancellable, error); if (nwrote < (gssize)count) return nwrote; @@ -212,11 +216,11 @@ soup_body_output_stream_write_fn (GOutputStream *stream, switch (bostream->priv->encoding) { case SOUP_ENCODING_CHUNKED: return soup_body_output_stream_write_chunked (bostream, buffer, count, - cancellable, error); + TRUE, cancellable, error); default: return soup_body_output_stream_write_raw (bostream, buffer, count, - cancellable, error); + TRUE, cancellable, error); } } @@ -228,7 +232,7 @@ soup_body_output_stream_close_fn (GOutputStream *stream, SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (stream); if (bostream->priv->encoding == SOUP_ENCODING_CHUNKED) { - if (soup_body_output_stream_write_chunked (bostream, NULL, 0, cancellable, error) == -1) + if (soup_body_output_stream_write_chunked (bostream, NULL, 0, TRUE, cancellable, error) == -1) return FALSE; } @@ -244,6 +248,28 @@ soup_body_output_stream_is_writable (GPollableOutputStream *stream) g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (bostream->priv->base_stream)); } +static gssize +soup_body_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize count, + GError **error) +{ + SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (stream); + + if (bostream->priv->eof) + return count; + + switch (bostream->priv->encoding) { + case SOUP_ENCODING_CHUNKED: + return soup_body_output_stream_write_chunked (bostream, buffer, count, + FALSE, NULL, error); + + default: + return soup_body_output_stream_write_raw (bostream, buffer, count, + FALSE, NULL, error); + } +} + static GSource * soup_body_output_stream_create_source (GPollableOutputStream *stream, GCancellable *cancellable) @@ -301,6 +327,7 @@ soup_body_output_stream_pollable_init (GPollableOutputStreamInterface *pollable_ gpointer interface_data) { pollable_interface->is_writable = soup_body_output_stream_is_writable; + pollable_interface->write_nonblocking = soup_body_output_stream_write_nonblocking; pollable_interface->create_source = soup_body_output_stream_create_source; } -- cgit v1.2.1 From 0243f71b16cd915f4ab0fdccb65f479b075613e5 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 12 Dec 2012 11:16:47 +0100 Subject: docs: remove libsoup-gnome references from the build Since everything in libsoup-gnome is now deprecated and undocumented, don't depend on it when building docs. https://bugzilla.gnome.org/show_bug.cgi?id=573685 --- docs/reference/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index add7be83..2e2a8af6 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -33,7 +33,7 @@ IGNORE_HFILES= soup.h soup-marshal.h soup-enum-types.h \ soup-message-private.h soup-session-private.h \ soup-auth-basic.h soup-auth-digest.h soup-auth-ntlm.h \ soup-connection.h soup-auth-manager.h soup-auth-manager-ntlm.h \ - soup-message-queue.h soup-path-map.h \ + soup-message-queue.h soup-path-map.h soup-gnome-features.h \ soup-proxy-resolver.h soup-proxy-resolver-gnome.h \ soup-proxy-resolver-static.h soup-directory-input-stream.h \ soup-http-input-stream.h soup-password-manager.h \ @@ -67,7 +67,6 @@ GTKDOC_CFLAGS = \ GTKDOC_LIBS = \ $(top_builddir)/libsoup/libsoup-2.4.la \ - $(top_builddir)/libsoup/libsoup-gnome-2.4.la \ $(GLIB_LIBS) # include common portion ... -- cgit v1.2.1 From 33170885f097133e609d9322405bcf3dcb70a546 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 12 Dec 2012 17:16:40 +0100 Subject: soup-filter-input-stream: fix non-blocking behavior to not spin Just having a non-empty internal buffer isn't enough to guarantee we can do a non-blocking read; if the caller is doing a read_until, we might have some data in the buffer but still be waiting to find the boundary. So track that. Based on a patch from Gustavo Noronha Silva. --- libsoup/soup-filter-input-stream.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/libsoup/soup-filter-input-stream.c b/libsoup/soup-filter-input-stream.c index f8c72515..3b76386b 100644 --- a/libsoup/soup-filter-input-stream.c +++ b/libsoup/soup-filter-input-stream.c @@ -22,6 +22,7 @@ struct _SoupFilterInputStreamPrivate { GByteArray *buf; + gboolean need_more; }; static void soup_filter_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); @@ -78,6 +79,7 @@ soup_filter_input_stream_read_fn (GInputStream *stream, { SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); + fstream->priv->need_more = FALSE; if (fstream->priv->buf) { return read_from_buf (fstream, buffer, count); } else { @@ -92,7 +94,7 @@ soup_filter_input_stream_is_readable (GPollableInputStream *stream) { SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); - if (fstream->priv->buf) + if (fstream->priv->buf && !fstream->priv->need_more) return TRUE; else return g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (fstream)->base_stream)); @@ -106,6 +108,7 @@ soup_filter_input_stream_read_nonblocking (GPollableInputStream *stream, { SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); + fstream->priv->need_more = FALSE; if (fstream->priv->buf) { return read_from_buf (fstream, buffer, count); } else { @@ -122,7 +125,7 @@ soup_filter_input_stream_create_source (GPollableInputStream *stream, SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); GSource *base_source, *pollable_source; - if (fstream->priv->buf) + if (fstream->priv->buf && !fstream->priv->need_more) base_source = g_timeout_source_new (0); else base_source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (G_FILTER_INPUT_STREAM (fstream)->base_stream), cancellable); @@ -196,11 +199,13 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, gssize nread; guint8 *p, *buf, *end; gboolean eof = FALSE; + GError *my_error = NULL; g_return_val_if_fail (SOUP_IS_FILTER_INPUT_STREAM (fstream), -1); g_return_val_if_fail (!include_boundary || (boundary_length < length), -1); *got_boundary = FALSE; + fstream->priv->need_more = FALSE; if (!fstream->priv->buf || fstream->priv->buf->len < boundary_length) { guint prev_len; @@ -215,7 +220,7 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, nread = g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, buf + prev_len, length - prev_len, blocking, - cancellable, error); + cancellable, &my_error); if (nread <= 0) { if (prev_len) fstream->priv->buf->len = prev_len; @@ -226,8 +231,17 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, if (nread == 0 && prev_len) eof = TRUE; - else + else { + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) + fstream->priv->need_more = TRUE; + if (my_error) + g_propagate_error (error, my_error); + return nread; + } + + if (my_error) + g_propagate_error (error, my_error); } else fstream->priv->buf->len = prev_len + nread; } else -- cgit v1.2.1 From 4a40d1188d34eee3a5ae55869e09aac0c97b6443 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 14 Dec 2012 16:02:48 -0500 Subject: SoupConnection: Quiet a (mistaken) compiler warning gcc claims 'event_id' might be uninitialized; it's wrong, but it's hard for the optimizer to know that. Placate it in the name of reducing warnings. https://bugzilla.gnome.org/show_bug.cgi?id=690224 --- libsoup/soup-connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 34b9b2d1..21613946 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -604,7 +604,7 @@ guint soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) { SoupConnectionPrivate *priv; - guint status, event_id; + guint status, event_id = 0; SoupURI *connect_uri; SoupAddress *remote_addr; @@ -690,7 +690,7 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) soup_connection_disconnect (conn); } - if (priv->socket) + if (priv->socket && event_id) g_signal_handler_disconnect (priv->socket, event_id); if (priv->proxy_uri != NULL) -- cgit v1.2.1 From 8404dca75b79d64f005735ebf7bc549192892460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Di=C3=A9guez?= Date: Sat, 15 Dec 2012 00:16:29 +0100 Subject: Updated Galician translations --- po/gl.po | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/po/gl.po b/po/gl.po index eb863bb5..e6d862b8 100644 --- a/po/gl.po +++ b/po/gl.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-12 02:04+0200\n" -"PO-Revision-Date: 2012-09-12 02:05+0200\n" +"POT-Creation-Date: 2012-12-15 00:15+0100\n" +"PO-Revision-Date: 2012-12-15 00:16+0200\n" "Last-Translator: Fran Dieguez \n" "Language-Team: gnome-l10n-gl@gnome.org\n" "Language: gl\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Virtaal 0.7.0\n" +"X-Generator: Virtaal 0.7.1\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -36,34 +36,51 @@ msgstr "Non é posíbel truncar SoupbodyInputStream" msgid "Output buffer is too small" msgstr "O búfer de saída é demasiado pequeno" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Non é posíbel analizar a resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificación da resposta HTTP non recoñecida" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "A operación foi cancelada" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "A operación bloquearase" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Non é posíbel analizar a consulta HTTP" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "Non se forneceu un URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI «%s» non válida: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "Non é posíbel analizar o URI «%s»" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Esquema de URI «%s» non admitido" +#: ../libsoup/soup-session.c:3811 +#, c-format +msgid "Not an HTTP URI" +msgstr "Non é unha URI de HTTP" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "O nome do computador é un enderezo IP" -- cgit v1.2.1 From ad40c0f85f67f484321464f52a56ac14ce68daa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Dr=C4=85g?= Date: Sun, 16 Dec 2012 03:29:05 +0100 Subject: Updated Polish translation --- po/pl.po | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/po/pl.po b/po/pl.po index e48d389a..1eb3234d 100644 --- a/po/pl.po +++ b/po/pl.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-10 17:20+0200\n" -"PO-Revision-Date: 2012-09-10 17:23+0200\n" +"POT-Creation-Date: 2012-12-16 03:27+0100\n" +"PO-Revision-Date: 2012-12-16 03:28+0100\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "Language: pl\n" @@ -42,34 +42,51 @@ msgstr "Nie można skrócić SoupBodyInputStream" msgid "Output buffer is too small" msgstr "Bufor wyjściowy jest za mały" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nie można przetworzyć odpowiedzi HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nierozpoznane kodowanie odpowiedzi HTTP" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Anulowano działanie" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Działanie spowodowałoby zablokowanie" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Nie można przetworzyć żądania HTTP" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "Nie podano adresu URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Nieprawidłowy adres URI \"%s\": %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "Nie można przetworzyć adresu URI \"%s\"" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nieobsługiwany schemat adresu URI \"%s\"" +#: ../libsoup/soup-session.c:3811 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nie jest adresem URI protokołu HTTP" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Nazwa komputera jest adresem IP" -- cgit v1.2.1 From 887e9e40c010d5120e39ff59cc95fe9a1750d75c Mon Sep 17 00:00:00 2001 From: Daniel Mustieles Date: Sun, 16 Dec 2012 20:48:53 +0100 Subject: Updated Spanish translation --- po/es.po | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/po/es.po b/po/es.po index ba6467cf..5624693c 100644 --- a/po/es.po +++ b/po/es.po @@ -9,15 +9,16 @@ msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-10 18:07+0200\n" +"POT-Creation-Date: 2012-12-10 16:22+0000\n" +"PO-Revision-Date: 2012-12-16 20:34+0100\n" "Last-Translator: Daniel Mustieles \n" -"Language-Team: Español \n" +"Language-Team: Español; Castellano \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.5\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -38,34 +39,53 @@ msgstr "No se puede truncar SoupBodyInputStream" msgid "Output buffer is too small" msgstr "El búfer de salida es demasiado pequeño" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "No se pudo analizar la respuesta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificación de la respuesta HTTP no reconocida" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Se canceló la operación" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "La operación se bloqueará" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "No se pudo analizar la solicitud HTTP" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "No se ha proporcionado un URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI «%s» no válida: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3759 #, c-format msgid "Could not parse URI '%s'" msgstr "No se pudo analizar el URI «%s»" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3796 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Esquema %s de URI no soportado" +#: ../libsoup/soup-session.c:3818 +#, c-format +msgid "Not an HTTP URI" +msgstr "No es un URI HTTP" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "El nombre del equipo es una dirección IP" -- cgit v1.2.1 From 6d28a5d6e8cad579ea4f38df146d777083f73bb6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 13 Dec 2012 15:52:59 +0100 Subject: soup-message: remove gtk-docs on internal methods --- libsoup/soup-message.c | 127 ------------------------------------------------- 1 file changed, 127 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 7a1d0b7a..8eb391eb 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -968,150 +968,66 @@ soup_message_set_response (SoupMessage *msg, } } -/** - * soup_message_wrote_informational: - * @msg: a #SoupMessage - * - * Emits the %wrote_informational signal, indicating that the IO layer - * finished writing an informational (1xx) response for @msg. - **/ void soup_message_wrote_informational (SoupMessage *msg) { g_signal_emit (msg, signals[WROTE_INFORMATIONAL], 0); } -/** - * soup_message_wrote_headers: - * @msg: a #SoupMessage - * - * Emits the %wrote_headers signal, indicating that the IO layer - * finished writing the (non-informational) headers for @msg. - **/ void soup_message_wrote_headers (SoupMessage *msg) { g_signal_emit (msg, signals[WROTE_HEADERS], 0); } -/** - * soup_message_wrote_chunk: - * @msg: a #SoupMessage - * - * Emits the %wrote_chunk signal, indicating that the IO layer - * finished writing a chunk of @msg's body. - **/ void soup_message_wrote_chunk (SoupMessage *msg) { g_signal_emit (msg, signals[WROTE_CHUNK], 0); } -/** - * soup_message_wrote_body_data: - * @msg: a #SoupMessage - * @chunk: the data written - * - * Emits the %wrote_body_data signal, indicating that the IO layer - * finished writing a portion of @msg's body. - **/ void soup_message_wrote_body_data (SoupMessage *msg, SoupBuffer *chunk) { g_signal_emit (msg, signals[WROTE_BODY_DATA], 0, chunk); } -/** - * soup_message_wrote_body: - * @msg: a #SoupMessage - * - * Emits the %wrote_body signal, indicating that the IO layer finished - * writing the body for @msg. - **/ void soup_message_wrote_body (SoupMessage *msg) { g_signal_emit (msg, signals[WROTE_BODY], 0); } -/** - * soup_message_got_informational: - * @msg: a #SoupMessage - * - * Emits the #SoupMessage::got_informational signal, indicating that - * the IO layer read a complete informational (1xx) response for @msg. - **/ void soup_message_got_informational (SoupMessage *msg) { g_signal_emit (msg, signals[GOT_INFORMATIONAL], 0); } -/** - * soup_message_got_headers: - * @msg: a #SoupMessage - * - * Emits the #SoupMessage::got_headers signal, indicating that the IO - * layer finished reading the (non-informational) headers for @msg. - **/ void soup_message_got_headers (SoupMessage *msg) { g_signal_emit (msg, signals[GOT_HEADERS], 0); } -/** - * soup_message_got_chunk: - * @msg: a #SoupMessage - * @chunk: the newly-read chunk - * - * Emits the #SoupMessage::got_chunk signal, indicating that the IO - * layer finished reading a chunk of @msg's body. - **/ void soup_message_got_chunk (SoupMessage *msg, SoupBuffer *chunk) { g_signal_emit (msg, signals[GOT_CHUNK], 0, chunk); } -/** - * soup_message_got_body: - * @msg: a #SoupMessage - * - * Emits the #SoupMessage::got_body signal, indicating that the IO - * layer finished reading the body for @msg. - **/ void soup_message_got_body (SoupMessage *msg) { g_signal_emit (msg, signals[GOT_BODY], 0); } -/** - * soup_message_content_sniffed: - * @msg: a #SoupMessage - * @content_type: a string with the sniffed content type - * @params: a #GHashTable with the parameters - * - * Emits the %content_sniffed signal, indicating that the IO layer - * finished sniffing the content type for @msg. If content sniffing - * will not be performed, due to the sniffer deciding to trust the - * Content-Type sent by the server, this signal is emitted immediately - * after #SoupMessage::got_headers, with %NULL as @content_type. - **/ void soup_message_content_sniffed (SoupMessage *msg, const char *content_type, GHashTable *params) { g_signal_emit (msg, signals[CONTENT_SNIFFED], 0, content_type, params); } -/** - * soup_message_restarted: - * @msg: a #SoupMessage - * - * Emits the %restarted signal, indicating that @msg should be - * requeued. - **/ void soup_message_restarted (SoupMessage *msg) { @@ -1123,13 +1039,6 @@ soup_message_restarted (SoupMessage *msg) g_signal_emit (msg, signals[RESTARTED], 0); } -/** - * soup_message_finished: - * @msg: a #SoupMessage - * - * Emits the %finished signal, indicating that @msg has been completely - * processed. - **/ void soup_message_finished (SoupMessage *msg) { @@ -1283,15 +1192,6 @@ soup_message_add_status_code_handler (SoupMessage *msg, } -/** - * soup_message_set_auth: - * @msg: a #SoupMessage - * @auth: a #SoupAuth, or %NULL - * - * Sets @msg to authenticate to its destination using @auth, which - * must have already been fully authenticated. If @auth is %NULL, @msg - * will not authenticate to its destination. - **/ void soup_message_set_auth (SoupMessage *msg, SoupAuth *auth) { @@ -1320,15 +1220,6 @@ soup_message_set_auth (SoupMessage *msg, SoupAuth *auth) g_free (token); } -/** - * soup_message_get_auth: - * @msg: a #SoupMessage - * - * Gets the #SoupAuth used by @msg for authentication. - * - * Return value: (transfer none): the #SoupAuth used by @msg for - * authentication, or %NULL if @msg is unauthenticated. - **/ SoupAuth * soup_message_get_auth (SoupMessage *msg) { @@ -1337,15 +1228,6 @@ soup_message_get_auth (SoupMessage *msg) return SOUP_MESSAGE_GET_PRIVATE (msg)->auth; } -/** - * soup_message_set_proxy_auth: - * @msg: a #SoupMessage - * @auth: a #SoupAuth, or %NULL - * - * Sets @msg to authenticate to its proxy using @auth, which must have - * already been fully authenticated. If @auth is %NULL, @msg will not - * authenticate to its proxy. - **/ void soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth) { @@ -1374,15 +1256,6 @@ soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth) g_free (token); } -/** - * soup_message_get_proxy_auth: - * @msg: a #SoupMessage - * - * Gets the #SoupAuth used by @msg for authentication to its proxy.. - * - * Return value: the #SoupAuth used by @msg for authentication to its - * proxy, or %NULL if @msg isn't authenticated to its proxy. - **/ SoupAuth * soup_message_get_proxy_auth (SoupMessage *msg) { -- cgit v1.2.1 From 81df4008fe06b7ccb0ddee69d190608a13aa4020 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 13 Dec 2012 15:55:27 +0100 Subject: soup-message: fix up add_header_handler()/add_status_handler() docs soup_message_add_header_handler() and soup_message_add_status_handler() used to have the semantics that the handlers they added wouldn't be called if the message was cancelled by a preceding signal handler. This feature accidentally got lost in 2.32, but no one appears to have noticed. Fix up the docs to correspond to the current reality. Also, fix part of the add_header_handler() docs that *never* corresponded to reality. --- libsoup/soup-message.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 8eb391eb..2ce4a9b2 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1070,11 +1070,6 @@ header_handler_metamarshal (GClosure *closure, GValue *return_value, const char *header_name = marshal_data; SoupMessageHeaders *hdrs; -#ifdef FIXME - if (priv->io_status != SOUP_MESSAGE_IO_STATUS_RUNNING) - return; -#endif - hdrs = priv->server_side ? msg->request_headers : msg->response_headers; if (soup_message_headers_get_one (hdrs, header_name)) { closure->marshal (closure, return_value, n_param_values, @@ -1092,16 +1087,11 @@ header_handler_metamarshal (GClosure *closure, GValue *return_value, * @user_data: data to pass to @handler_cb * * Adds a signal handler to @msg for @signal, as with - * g_signal_connect(), but with two differences: the @callback will - * only be run if @msg has a header named @header, and it will only be - * run if no earlier handler cancelled or requeued the message. - * - * If @signal is one of the "got" signals (eg, "got_headers"), or - * "finished" or "restarted", then @header is matched against the - * incoming message headers (that is, the #request_headers for a - * client #SoupMessage, or the #response_headers for a server - * #SoupMessage). If @signal is one of the "wrote" signals, then - * @header is matched against the outgoing message headers. + * g_signal_connect(), but the @callback will only be run if @msg's + * incoming messages headers (that is, the + * request_headers for a client #SoupMessage, or + * the response_headers for a server #SoupMessage) + * contain a header named @header. * * Return value: the handler ID from g_signal_connect() **/ @@ -1139,11 +1129,6 @@ status_handler_metamarshal (GClosure *closure, GValue *return_value, SoupMessage *msg = g_value_get_object (¶m_values[0]); guint status = GPOINTER_TO_UINT (marshal_data); -#ifdef FIXME - if (priv->io_status != SOUP_MESSAGE_IO_STATUS_RUNNING) - return; -#endif - if (msg->status_code == status) { closure->marshal (closure, return_value, n_param_values, param_values, invocation_hint, @@ -1160,9 +1145,8 @@ status_handler_metamarshal (GClosure *closure, GValue *return_value, * @user_data: data to pass to @handler_cb * * Adds a signal handler to @msg for @signal, as with - * g_signal_connect() but with two differences: the @callback will - * only be run if @msg has the status @status_code, and it will only - * be run if no earlier handler cancelled or requeued the message. + * g_signal_connect(), but the @callback will only be run if @msg has + * the status @status_code. * * @signal must be a signal that will be emitted after @msg's status * is set. For a client #SoupMessage, this means it can't be a "wrote" -- cgit v1.2.1 From b4f85bccc9ea4b28c4fcb86da6fe44bb48d9bb52 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 13 Dec 2012 15:58:28 +0100 Subject: soup-message: deprecate soup_message_set_chunk_allocator() This was added as a hacky way to avoid extra memcpy()s in certain use cases by reading data directly into a caller-provided buffer. However, SoupRequest now provides a vastly simpler way of doing this. --- libsoup/soup-message.c | 12 ++++++++++-- libsoup/soup-message.h | 1 + tests/chunk-test.c | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 2ce4a9b2..ffcae72b 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1597,6 +1597,9 @@ soup_message_set_status_full (SoupMessage *msg, * becomes possible to allocate a new buffer. * * Return value: the new buffer (or %NULL) + * + * Deprecated: Use #SoupRequest if you want to read into your + * own buffers. **/ /** @@ -1608,8 +1611,9 @@ soup_message_set_status_full (SoupMessage *msg, * destroyed * * Sets an alternate chunk-allocation function to use when reading - * @msg's body. Every time data is available to read, libsoup will - * call @allocator, which should return a #SoupBuffer. (See + * @msg's body when using the traditional (ie, non-#SoupRequest-based) + * API. Every time data is available to read, libsoup will call + * @allocator, which should return a #SoupBuffer. (See * #SoupChunkAllocator for additional details.) Libsoup will then read * data from the network into that buffer, and update the buffer's * length to indicate how much data it read. @@ -1633,6 +1637,10 @@ soup_message_set_status_full (SoupMessage *msg, * you'll need to ref the #SoupBuffer (or its owner, in the * soup_buffer_new_with_owner() case) to ensure that the data remains * valid. + * + * Deprecated: #SoupRequest provides a much simpler API that lets you + * read the response directly into your own buffers without needing to + * mess with callbacks, pausing/unpausing, etc. **/ void soup_message_set_chunk_allocator (SoupMessage *msg, diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index 6692c38d..f0fbeb37 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -171,6 +171,7 @@ typedef SoupBuffer * (*SoupChunkAllocator) (SoupMessage *msg, gsize max_len, gpointer user_data); +SOUP_DEPRECATED_IN_2_42_FOR(SoupRequest) void soup_message_set_chunk_allocator (SoupMessage *msg, SoupChunkAllocator allocator, gpointer user_data, diff --git a/tests/chunk-test.c b/tests/chunk-test.c index cce7127f..ce929565 100644 --- a/tests/chunk-test.c +++ b/tests/chunk-test.c @@ -284,7 +284,9 @@ do_response_test (SoupSession *session, SoupURI *base_uri) msg = soup_message_new_from_uri ("GET", base_uri); soup_message_body_set_accumulate (msg->response_body, FALSE); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; soup_message_set_chunk_allocator (msg, chunk_allocator, >d, NULL); + G_GNUC_END_IGNORE_DEPRECATIONS; g_signal_connect (msg, "got_chunk", G_CALLBACK (got_chunk), >d); soup_session_send_message (session, msg); -- cgit v1.2.1 From a11304268326e26317883309e10af92935efd663 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 13 Dec 2012 16:02:30 +0100 Subject: soup-message: update docs to mention SoupRequest where appropriate --- libsoup/soup-message.c | 48 ++++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index ffcae72b..5362fc6d 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -22,9 +22,16 @@ * A #SoupMessage represents an HTTP message that is being sent or * received. * - * For client-side usage, you would create a #SoupMessage with + * For client-side usage, if you are using the traditional + * #SoupSession APIs (soup_session_queue_message() and + * soup_session_send_message()), you would create a #SoupMessage with * soup_message_new() or soup_message_new_from_uri(), set up its - * fields appropriate, and send it via a #SoupSession. + * fields appropriately, and send it. If you are using the newer + * #SoupRequest API, you would create a request with + * soup_session_request_http() or soup_session_request_http_uri(), and + * the returned #SoupRequestHTTP will already have an associated + * #SoupMessage that you can retrieve via + * soup_request_http_get_message(). * * For server-side usage, #SoupServer will create #SoupMessages automatically for incoming requests, which your application @@ -62,17 +69,22 @@ * * As described in the #SoupMessageBody documentation, the * @request_body and @response_body data fields - * will not necessarily be filled in at all times. When they are - * filled in, they will be terminated with a '\0' byte (which is not - * included in the length), so you can use them as - * ordinary C strings (assuming that you know that the body doesn't - * have any other '\0' bytes). + * will not necessarily be filled in at all times. When the body + * fields are filled in, they will be terminated with a '\0' byte + * (which is not included in the length), so you + * can use them as ordinary C strings (assuming that you know that the + * body doesn't have any other '\0' bytes). * - * For a client-side #SoupMessage, @request_body's %data is usually - * filled in right before libsoup writes the request to the network, - * but you should not count on this; use soup_message_body_flatten() - * if you want to ensure that %data is filled in. @response_body's - * %data will be filled in before #SoupMessage::finished is emitted. + * For a client-side #SoupMessage, @request_body's + * data is usually filled in right before libsoup + * writes the request to the network, but you should not count on + * this; use soup_message_body_flatten() if you want to ensure that + * data is filled in. If you are not using + * #SoupRequest to read the response, then @response_body's + * data will be filled in before + * #SoupMessage::finished is emitted. (If you are using #SoupRequest, + * then the message body is not accumulated by default, so + * @response_body's data will always be %NULL.) * * For a server-side #SoupMessage, @request_body's %data will be * filled in before #SoupMessage::got_body is emitted. @@ -1303,11 +1315,11 @@ soup_message_cleanup_response (SoupMessage *req) * @SOUP_MESSAGE_CERTIFICATE_TRUSTED: if set after an https response * has been received, indicates that the server's SSL certificate is * trusted according to the session's CA. - * @SOUP_MESSAGE_NEW_CONNECTION: The message should be sent on a - * newly-created connection, not reusing an existing persistent - * connection. Note that messages with non-idempotent - * #SoupMessage:methods behave this way by default, - * unless #SOUP_MESSAGE_IDEMPOTENT is set. + * @SOUP_MESSAGE_NEW_CONNECTION: Requests that the message should be + * sent on a newly-created connection, not reusing an existing + * persistent connection. Note that messages with non-idempotent + * #SoupMessage:methods behave this way by default, unless + * #SOUP_MESSAGE_IDEMPOTENT is set. * @SOUP_MESSAGE_IDEMPOTENT: The message is considered idempotent, * regardless its #SoupMessage:method, and allows reuse of existing * idle connections, instead of always requiring a new one, unless @@ -1879,7 +1891,7 @@ soup_message_set_soup_request (SoupMessage *msg, * * Return value: @msg's associated #SoupRequest * - * Since: 2.40 + * Since: 2.42 */ SoupRequest * soup_message_get_soup_request (SoupMessage *msg) -- cgit v1.2.1 From 89dd1240a6077b18f6d6e4b119b403de38b73141 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 13 Dec 2012 16:07:57 +0100 Subject: Rename all remaining "SoupMessage *req"s to "msg" Originally (ie, 12 years ago last week) the HTTP message type in soup was called SoupRequest, and most SoupRequest variables were called "req". Shortly after, SoupRequest was renamed to SoupMessage, but none of the existing "req"s were renamed, and in fact, new ones kept getting added. Eventually, "msg" became the standard name for a SoupMessage variable, but a handful of "req"s have managed to survive to this day. With the increasing integration of the modern-day SoupRequest, this has gone from "inconsistent" to "confusing", so fix all the remaining stray "SoupMessage *req"s. --- libsoup/soup-message-client-io.c | 60 ++++++++++++++++++++-------------------- libsoup/soup-message-private.h | 4 +-- libsoup/soup-message.c | 40 +++++++++++++-------------- libsoup/soup-server.c | 28 +++++++++---------- libsoup/soup-session-async.c | 10 +++---- 5 files changed, 71 insertions(+), 71 deletions(-) diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c index 1ee4cbb2..0d3df282 100644 --- a/libsoup/soup-message-client-io.c +++ b/libsoup/soup-message-client-io.c @@ -20,45 +20,45 @@ #include "soup-misc-private.h" static guint -parse_response_headers (SoupMessage *req, +parse_response_headers (SoupMessage *msg, char *headers, guint headers_len, SoupEncoding *encoding, gpointer user_data, GError **error) { - SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req); + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupHTTPVersion version; - g_free(req->reason_phrase); - req->reason_phrase = NULL; + g_free(msg->reason_phrase); + msg->reason_phrase = NULL; if (!soup_headers_parse_response (headers, headers_len, - req->response_headers, + msg->response_headers, &version, - &req->status_code, - &req->reason_phrase)) { + &msg->status_code, + &msg->reason_phrase)) { g_set_error_literal (error, SOUP_REQUEST_ERROR, SOUP_REQUEST_ERROR_PARSING, _("Could not parse HTTP response")); return SOUP_STATUS_MALFORMED; } - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_STATUS_CODE); - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_REASON_PHRASE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE); if (version < priv->http_version) { priv->http_version = version; - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_HTTP_VERSION); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION); } - if ((req->method == SOUP_METHOD_HEAD || - req->status_code == SOUP_STATUS_NO_CONTENT || - req->status_code == SOUP_STATUS_NOT_MODIFIED || - SOUP_STATUS_IS_INFORMATIONAL (req->status_code)) || - (req->method == SOUP_METHOD_CONNECT && - SOUP_STATUS_IS_SUCCESSFUL (req->status_code))) + if ((msg->method == SOUP_METHOD_HEAD || + msg->status_code == SOUP_STATUS_NO_CONTENT || + msg->status_code == SOUP_STATUS_NOT_MODIFIED || + SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) || + (msg->method == SOUP_METHOD_CONNECT && + SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))) *encoding = SOUP_ENCODING_NONE; else - *encoding = soup_message_headers_get_encoding (req->response_headers); + *encoding = soup_message_headers_get_encoding (msg->response_headers); if (*encoding == SOUP_ENCODING_UNRECOGNIZED) { g_set_error_literal (error, SOUP_REQUEST_ERROR, @@ -71,12 +71,12 @@ parse_response_headers (SoupMessage *req, } static void -get_request_headers (SoupMessage *req, GString *header, +get_request_headers (SoupMessage *msg, GString *header, SoupEncoding *encoding, gpointer user_data) { - SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req); + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageQueueItem *item = user_data; - SoupURI *uri = soup_message_get_uri (req); + SoupURI *uri = soup_message_get_uri (msg); char *uri_host; char *uri_string; SoupMessageHeadersIter iter; @@ -89,7 +89,7 @@ get_request_headers (SoupMessage *req, GString *header, else uri_host = uri->host; - if (req->method == SOUP_METHOD_CONNECT) { + if (msg->method == SOUP_METHOD_CONNECT) { /* CONNECT URI is hostname:port for tunnel destination */ uri_string = g_strdup_printf ("%s:%d", uri_host, uri->port); } else { @@ -109,10 +109,10 @@ get_request_headers (SoupMessage *req, GString *header, } g_string_append_printf (header, "%s %s HTTP/1.%d\r\n", - req->method, uri_string, + msg->method, uri_string, (priv->http_version == SOUP_HTTP_1_0) ? 0 : 1); - if (!soup_message_headers_get_one (req->request_headers, "Host")) { + if (!soup_message_headers_get_one (msg->request_headers, "Host")) { if (soup_uri_uses_default_port (uri)) { g_string_append_printf (header, "Host: %s\r\n", uri_host); @@ -125,18 +125,18 @@ get_request_headers (SoupMessage *req, GString *header, if (uri_host != uri->host) g_free (uri_host); - *encoding = soup_message_headers_get_encoding (req->request_headers); + *encoding = soup_message_headers_get_encoding (msg->request_headers); if ((*encoding == SOUP_ENCODING_CONTENT_LENGTH || *encoding == SOUP_ENCODING_NONE) && - (req->request_body->length > 0 || - soup_message_headers_get_one (req->request_headers, "Content-Type")) && - !soup_message_headers_get_content_length (req->request_headers)) { + (msg->request_body->length > 0 || + soup_message_headers_get_one (msg->request_headers, "Content-Type")) && + !soup_message_headers_get_content_length (msg->request_headers)) { *encoding = SOUP_ENCODING_CONTENT_LENGTH; - soup_message_headers_set_content_length (req->request_headers, - req->request_body->length); + soup_message_headers_set_content_length (msg->request_headers, + msg->request_body->length); } - soup_message_headers_iter_init (&iter, req->request_headers); + soup_message_headers_iter_init (&iter, msg->request_headers); while (soup_message_headers_iter_next (&iter, &name, &value)) g_string_append_printf (header, "%s: %s\r\n", name, value); g_string_append (header, "\r\n"); diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index 53f8e817..74b6e0d7 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -43,7 +43,7 @@ typedef struct { } SoupMessagePrivate; #define SOUP_MESSAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_MESSAGE, SoupMessagePrivate)) -void soup_message_cleanup_response (SoupMessage *req); +void soup_message_cleanup_response (SoupMessage *msg); typedef void (*SoupMessageGetHeadersFn) (SoupMessage *msg, @@ -63,7 +63,7 @@ typedef void (*SoupMessageCompletionFn) (SoupMessage *msg, void soup_message_send_request (SoupMessageQueueItem *item, SoupMessageCompletionFn completion_cb, gpointer user_data); -void soup_message_read_request (SoupMessage *req, +void soup_message_read_request (SoupMessage *msg, SoupSocket *sock, SoupMessageCompletionFn completion_cb, gpointer user_data); diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 5362fc6d..6c62b27d 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -302,12 +302,12 @@ soup_message_get_property (GObject *object, guint prop_id, } static void -soup_message_real_got_body (SoupMessage *req) +soup_message_real_got_body (SoupMessage *msg) { - SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req); + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageBody *body; - body = priv->server_side ? req->request_body : req->response_body; + body = priv->server_side ? msg->request_body : msg->response_body; if (soup_message_body_get_accumulate (body)) { SoupBuffer *buffer; @@ -1262,39 +1262,39 @@ soup_message_get_proxy_auth (SoupMessage *msg) /** * soup_message_cleanup_response: - * @req: a #SoupMessage + * @msg: a #SoupMessage * - * Cleans up all response data on @req, so that the request can be sent + * Cleans up all response data on @msg, so that the request can be sent * again and receive a new response. (Eg, as a result of a redirect or * authorization request.) **/ void -soup_message_cleanup_response (SoupMessage *req) +soup_message_cleanup_response (SoupMessage *msg) { - SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req); + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); - soup_message_body_truncate (req->response_body); - soup_message_headers_clear (req->response_headers); + soup_message_body_truncate (msg->response_body); + soup_message_headers_clear (msg->response_headers); if (priv->server_side) { - soup_message_headers_set_encoding (req->response_headers, + soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CONTENT_LENGTH); } priv->msg_flags &= ~SOUP_MESSAGE_CONTENT_DECODED; - req->status_code = SOUP_STATUS_NONE; - if (req->reason_phrase) { - g_free (req->reason_phrase); - req->reason_phrase = NULL; + msg->status_code = SOUP_STATUS_NONE; + if (msg->reason_phrase) { + g_free (msg->reason_phrase); + msg->reason_phrase = NULL; } priv->http_version = priv->orig_http_version; - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_STATUS_CODE); - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_REASON_PHRASE); - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_HTTP_VERSION); - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_FLAGS); - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_TLS_CERTIFICATE); - g_object_notify (G_OBJECT (req), SOUP_MESSAGE_TLS_ERRORS); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_FLAGS); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_TLS_CERTIFICATE); + g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_TLS_ERRORS); } /** diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index 1e462ea2..cea950db 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -805,7 +805,7 @@ soup_server_get_handler (SoupServer *server, const char *path) } static void -got_headers (SoupMessage *req, SoupClientContext *client) +got_headers (SoupMessage *msg, SoupClientContext *client) { SoupServer *server = client->server; SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server); @@ -820,14 +820,14 @@ got_headers (SoupMessage *req, SoupClientContext *client) if (!priv->raw_paths) { char *decoded_path; - uri = soup_message_get_uri (req); + uri = soup_message_get_uri (msg); decoded_path = soup_uri_decode (uri->path); if (strstr (decoded_path, "/../") || g_str_has_suffix (decoded_path, "/..")) { /* Introducing new ".." segments is not allowed */ g_free (decoded_path); - soup_message_set_status (req, SOUP_STATUS_BAD_REQUEST); + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); return; } @@ -838,7 +838,7 @@ got_headers (SoupMessage *req, SoupClientContext *client) /* Add required response headers */ date = soup_date_new_from_now (0); date_string = soup_date_to_string (date, SOUP_DATE_HTTP); - soup_message_headers_replace (req->response_headers, "Date", + soup_message_headers_replace (msg->response_headers, "Date", date_string); g_free (date_string); soup_date_free (date); @@ -851,8 +851,8 @@ got_headers (SoupMessage *req, SoupClientContext *client) for (iter = priv->auth_domains; iter; iter = iter->next) { domain = iter->data; - if (soup_auth_domain_covers (domain, req)) { - auth_user = soup_auth_domain_accepts (domain, req); + if (soup_auth_domain_covers (domain, msg)) { + auth_user = soup_auth_domain_accepts (domain, msg); if (auth_user) { client->auth_domain = g_object_ref (domain); client->auth_user = auth_user; @@ -870,27 +870,27 @@ got_headers (SoupMessage *req, SoupClientContext *client) for (iter = priv->auth_domains; iter; iter = iter->next) { domain = iter->data; - if (soup_auth_domain_covers (domain, req)) - soup_auth_domain_challenge (domain, req); + if (soup_auth_domain_covers (domain, msg)) + soup_auth_domain_challenge (domain, msg); } } static void -call_handler (SoupMessage *req, SoupClientContext *client) +call_handler (SoupMessage *msg, SoupClientContext *client) { SoupServer *server = client->server; SoupServerHandler *hand; SoupURI *uri; - g_signal_emit (server, signals[REQUEST_READ], 0, req, client); + g_signal_emit (server, signals[REQUEST_READ], 0, msg, client); - if (req->status_code != 0) + if (msg->status_code != 0) return; - uri = soup_message_get_uri (req); + uri = soup_message_get_uri (msg); hand = soup_server_get_handler (server, uri->path); if (!hand) { - soup_message_set_status (req, SOUP_STATUS_NOT_FOUND); + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); return; } @@ -903,7 +903,7 @@ call_handler (SoupMessage *req, SoupClientContext *client) form_data_set = NULL; /* Call method handler */ - (*hand->callback) (server, req, + (*hand->callback) (server, msg, uri->path, form_data_set, client, hand->user_data); diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 4c08a617..c416646d 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -69,25 +69,25 @@ soup_session_async_new_with_options (const char *optname1, ...) } static void -soup_session_async_queue_message (SoupSession *session, SoupMessage *req, +soup_session_async_queue_message (SoupSession *session, SoupMessage *msg, SoupSessionCallback callback, gpointer user_data) { SoupMessageQueueItem *item; - item = soup_session_append_queue_item (session, req, TRUE, FALSE, + item = soup_session_append_queue_item (session, msg, TRUE, FALSE, callback, user_data); soup_session_kick_queue (session); soup_message_queue_item_unref (item); } static guint -soup_session_async_send_message (SoupSession *session, SoupMessage *req) +soup_session_async_send_message (SoupSession *session, SoupMessage *msg) { SoupMessageQueueItem *item; GMainContext *async_context = soup_session_get_async_context (session); - item = soup_session_append_queue_item (session, req, TRUE, FALSE, + item = soup_session_append_queue_item (session, msg, TRUE, FALSE, NULL, NULL); soup_session_kick_queue (session); @@ -96,7 +96,7 @@ soup_session_async_send_message (SoupSession *session, SoupMessage *req) soup_message_queue_item_unref (item); - return req->status_code; + return msg->status_code; } static void -- cgit v1.2.1 From 38c13f1d28ee5e86dbdaf2e7a121fb0c148d41d1 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 17 Dec 2012 20:29:26 -0500 Subject: 2.41.3 --- NEWS | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 98f6e05b..27459a5b 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,98 @@ +Changes in libsoup from 2.41.2 to 2.41.3 (codename: "I Left My +Deprecated APIs in A Coruña"): + + * BUILD DEPENDENCY CHANGES: libsoup-gnome no longer depends on + libgnome-keyring, and the sqlite3 dependency has been moved + from libsoup-gnome to libsoup proper. (See below). + + + * SoupRequest is now stable API. SoupRequester, however, is + deprecated. Instead you can now call soup_session_request() + or soup_session_request_uri() to create a SoupRequest. + + Some documentation has been updated to reflect this, but + much more still needs to be (in particular the "Client-side + Tutorial"). + + * SoupRequestHTTP now has a number of fields and methods that + mirror the SoupMessage data, so you don't have to use + soup_request_http_get_message() in many cases. On the flip + side, there is also now soup_message_get_request(). And you + can create a SoupRequestHTTP directly (and override its + request method) by using soup_session_request_http() or + soup_session_request_http_uri()). + + * soup_message_set_chunk_allocator() is now deprecated; apps + that want to do streaming reads should just use SoupRequest, + which is vastly more sane. + + + * SoupPasswordManager is now deprecated, and + SoupPasswordManagerGNOME is now a no-op (and libsoup-gnome + no longer links against libgnome-keyring). [#594377, #679866] + + * SoupCookieJarSqlite is now deprecated in favor of + SoupCookieJarDB, which is exactly the same thing except that + it's in libsoup itself rather than being in libsoup-gnome + (something that many people have requested). This means that + libsoup now requires sqlite3... if this offends you horribly + then you have a few months to speak up... + + * SoupProxyResolverGNOME is now deprecated; there hasn't been + any real reason to use it since SoupProxyResolverDefault was + added. + + * As a result of the last three items, libsoup-gnome now + consists entirely of deprecated APIs, and there is no reason + you should use it any more (though packagers need to keep + building it, for backward compatibility). + + + * SoupSession is no longer an abstract class, and you can + create a plain SoupSession, which behaves in a more + traditionally-gio-like way (allowing a mix of sync and async + methods, etc). This "plain" SoupSession also has more sane + default values of certain properties, and has certain + SoupSessionFeatures built in. + + This will eventually replace SoupSessionAsync and + SoupSessionSync completely, but most of the documentation + hasn't yet been updated at this point... + + This change involved merging the majority of the + SoupSessionAsync and SoupSessionSync code into SoupSession, + getting rid of lots of redundancy in the process. There may + be some bug fallout from this (probably on the + SoupSessionSync side, since WebKit's tests tend to shake out + all SoupSessionAsync bugs). However, this should help to + avoid SoupSessionSync-only bugs in the future, since much + more of the code is now shared. + + + * Usernames and passwords passed into SoupSession a URI will + now be cleared after they're used, so that if they are + wrong, the authenticate signal will be emitted on the next + round. [#689673, Martin Robinson] + + * SoupURI now leaves "%00" in URIs as-is, rather than decoding + it to "\0", which was not intended and is never useful. + + * Fixed a bug in SoupBodyOutputStream that could cause libsoup + to sometimes use blocking I/O rather than non-blocking when + writing chunked message bodies. [#688974, Milan Plzik] + + * Fixed a bug in SoupFilterInputStream that could cause some + non-blocking reads to suck up CPU while waiting for the + network. (This was noticed with multipart/x-mixed-replace + processing; it's not clear if it affected anything else.) + [Gustavo] + + * tests: misc small fixes + + + * New/updated translations: + Assamese, Galician, Japanese, Odia, Polish, Spanish + Changes in libsoup from 2.41.1 to 2.41.2: * libsoup-2.4.so and libsoup-gnome-2.4.so now only export the diff --git a/configure.ac b/configure.ac index fe5403b8..43874110 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [2]) +m4_define([soup_micro_version], [3]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From d12d25e3515b329f65da8f276965fe46c7c628ac Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 30 Jul 2012 12:40:32 +0200 Subject: SoupCacheInputStream: new input stream filter that writes to the cache The SoupCacheInputStream will be added to the stream stack as any other GPollableInputStream. It will transparently read data from the underlying stream and will pass it unmodified to the upper level. Apart from that the stream writes everything it reads to a local file. Once the caching finishes a callback will be called. Caching may be cancelled at any point by providing a GCancellable. https://bugzilla.gnome.org/show_bug.cgi?id=682112 --- libsoup/Makefile.am | 2 + libsoup/soup-cache-input-stream.c | 333 ++++++++++++++++++++++++++++++++++++++ libsoup/soup-cache-input-stream.h | 52 ++++++ po/POTFILES.in | 1 + 4 files changed, 388 insertions(+) create mode 100644 libsoup/soup-cache-input-stream.c create mode 100644 libsoup/soup-cache-input-stream.h diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 87629ed1..59553f04 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -114,6 +114,8 @@ libsoup_2_4_la_SOURCES = \ soup-body-output-stream.h \ soup-body-output-stream.c \ soup-cache.c \ + soup-cache-input-stream.h \ + soup-cache-input-stream.c \ soup-cache-private.h \ soup-client-input-stream.h \ soup-client-input-stream.c \ diff --git a/libsoup/soup-cache-input-stream.c b/libsoup/soup-cache-input-stream.c new file mode 100644 index 00000000..a44652a8 --- /dev/null +++ b/libsoup/soup-cache-input-stream.c @@ -0,0 +1,333 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2012 Igalia, S.L. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "soup-cache-input-stream.h" +#include "soup-message-body.h" + +static void soup_cache_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SoupCacheInputStream, soup_cache_input_stream, SOUP_TYPE_FILTER_INPUT_STREAM, + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, + soup_cache_input_stream_pollable_init)) + +/* properties */ +enum { + PROP_0, + + PROP_OUTPUT_STREAM, + + LAST_PROP +}; + +struct _SoupCacheInputStreamPrivate +{ + GOutputStream *output_stream; + gsize bytes_written; + + gboolean read_finished; + SoupBuffer *current_writing_buffer; + GQueue *buffer_queue; + + GTask *task; +}; + +static void soup_cache_input_stream_write_next_buffer (SoupCacheInputStream *istream); + +static inline void +notify_and_clear (SoupCacheInputStream *istream, GError *error) +{ + SoupCacheInputStreamPrivate *priv = istream->priv; + + if (error) + g_task_return_error (priv->task, error); + else + g_task_return_int (priv->task, priv->bytes_written); + + g_clear_object (&priv->output_stream); + g_clear_object (&priv->task); +} + +gsize +soup_cache_input_stream_cache_finish (SoupCacheInputStream *istream, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_int (G_TASK (result), error); +} + +static inline void +try_write_next_buffer (SoupCacheInputStream *istream) +{ + SoupCacheInputStreamPrivate *priv = istream->priv; + + if (priv->current_writing_buffer == NULL && priv->buffer_queue->length) + soup_cache_input_stream_write_next_buffer (istream); + else if (priv->read_finished) + notify_and_clear (istream, NULL); + else if (g_input_stream_is_closed (G_INPUT_STREAM (istream))) { + GError *error = NULL; + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_CLOSED, + _("Network stream unexpectedly closed")); + notify_and_clear (istream, error); + } +} + +static void +file_replaced_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (user_data); + SoupCacheInputStreamPrivate *priv = istream->priv; + GError *error = NULL; + + priv->output_stream = (GOutputStream *) g_file_replace_finish (G_FILE (source), res, &error); + + if (error) + g_task_return_error (priv->task, error); + else + try_write_next_buffer (istream); +} + +void +soup_cache_input_stream_cache (SoupCacheInputStream *istream, + GFile *file, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupCacheInputStreamPrivate *priv = istream->priv; + + priv->task = g_task_new (istream, cancellable, callback, user_data); + + g_file_replace_async (file, NULL, FALSE, + G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, + G_PRIORITY_LOW, cancellable, file_replaced_cb, istream); +} + +static void +soup_cache_input_stream_init (SoupCacheInputStream *self) +{ + SoupCacheInputStreamPrivate *priv = + G_TYPE_INSTANCE_GET_PRIVATE (self, SOUP_TYPE_CACHE_INPUT_STREAM, + SoupCacheInputStreamPrivate); + + priv->buffer_queue = g_queue_new (); + self->priv = priv; +} + +static void +soup_cache_input_stream_get_property (GObject *object, + guint property_id, GValue *value, GParamSpec *pspec) +{ + SoupCacheInputStream *self = SOUP_CACHE_INPUT_STREAM (object); + SoupCacheInputStreamPrivate *priv = self->priv; + + switch (property_id) { + case PROP_OUTPUT_STREAM: + g_value_set_object (value, priv->output_stream); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +soup_cache_input_stream_set_property (GObject *object, + guint property_id, const GValue *value, GParamSpec *pspec) +{ + SoupCacheInputStream *self = SOUP_CACHE_INPUT_STREAM (object); + SoupCacheInputStreamPrivate *priv = self->priv; + + switch (property_id) { + case PROP_OUTPUT_STREAM: + priv->output_stream = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +soup_cache_input_stream_dispose (GObject *object) +{ + SoupCacheInputStreamPrivate *priv = SOUP_CACHE_INPUT_STREAM (object)->priv; + + g_clear_object (&priv->output_stream); + g_clear_object (&priv->task); + + G_OBJECT_CLASS (soup_cache_input_stream_parent_class)->dispose (object); +} + +static void +soup_cache_input_stream_finalize (GObject *object) +{ + SoupCacheInputStream *self = (SoupCacheInputStream *)object; + SoupCacheInputStreamPrivate *priv = self->priv; + + g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); + g_queue_free_full (priv->buffer_queue, (GDestroyNotify) soup_buffer_free); + + G_OBJECT_CLASS (soup_cache_input_stream_parent_class)->finalize (object); +} + +static void +write_ready_cb (GObject *source, GAsyncResult *result, SoupCacheInputStream *istream) +{ + GOutputStream *ostream = G_OUTPUT_STREAM (source); + SoupCacheInputStreamPrivate *priv = istream->priv; + gssize write_size; + gsize pending; + GError *error = NULL; + + write_size = g_output_stream_write_finish (ostream, result, &error); + if (error) { + notify_and_clear (istream, error); + g_object_unref (istream); + return; + } + + /* Check that we have written everything */ + pending = priv->current_writing_buffer->length - write_size; + if (pending) { + SoupBuffer *subbuffer = soup_buffer_new_subbuffer (priv->current_writing_buffer, + write_size, pending); + g_queue_push_head (priv->buffer_queue, subbuffer); + } + + priv->bytes_written += write_size; + g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); + + try_write_next_buffer (istream); + g_object_unref (istream); +} + +static void +soup_cache_input_stream_write_next_buffer (SoupCacheInputStream *istream) +{ + SoupCacheInputStreamPrivate *priv = istream->priv; + SoupBuffer *buffer = g_queue_pop_head (priv->buffer_queue); + int priority; + + g_assert (priv->output_stream && !g_output_stream_is_closed (priv->output_stream)); + g_assert (priv->task); + + g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); + priv->current_writing_buffer = buffer; + + if (priv->buffer_queue->length > 10) + priority = G_PRIORITY_DEFAULT; + else + priority = G_PRIORITY_LOW; + + g_output_stream_write_async (priv->output_stream, buffer->data, buffer->length, + priority, g_task_get_cancellable (priv->task), + (GAsyncReadyCallback) write_ready_cb, + g_object_ref (istream)); +} + +static gssize +read_internal (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (stream); + SoupCacheInputStreamPrivate *priv = istream->priv; + GInputStream *base_stream; + gssize nread; + + base_stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream)); + nread = g_pollable_stream_read (base_stream, buffer, count, blocking, + cancellable, error); + + if (G_UNLIKELY (nread == -1 || priv->read_finished || !priv->task)) + return nread; + + if (nread == 0) { + priv->read_finished = TRUE; + + if (priv->current_writing_buffer == NULL && priv->output_stream) + notify_and_clear (istream, NULL); + } else { + SoupBuffer *soup_buffer = soup_buffer_new (SOUP_MEMORY_COPY, buffer, nread); + g_queue_push_tail (priv->buffer_queue, soup_buffer); + + if (priv->current_writing_buffer == NULL && priv->output_stream) + soup_cache_input_stream_write_next_buffer (istream); + } + + return nread; +} + +static gssize +soup_cache_input_stream_read_fn (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return read_internal (stream, buffer, count, TRUE, + cancellable, error); +} + +static gssize +soup_cache_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + return read_internal (G_INPUT_STREAM (stream), buffer, count, FALSE, + NULL, error); +} + +static void +soup_cache_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->read_nonblocking = soup_cache_input_stream_read_nonblocking; +} + +static void +soup_cache_input_stream_class_init (SoupCacheInputStreamClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GInputStreamClass *istream_class = G_INPUT_STREAM_CLASS (klass); + + g_type_class_add_private (klass, sizeof (SoupCacheInputStreamPrivate)); + + gobject_class->get_property = soup_cache_input_stream_get_property; + gobject_class->set_property = soup_cache_input_stream_set_property; + gobject_class->dispose = soup_cache_input_stream_dispose; + gobject_class->finalize = soup_cache_input_stream_finalize; + + istream_class->read_fn = soup_cache_input_stream_read_fn; + + g_object_class_install_property (gobject_class, PROP_OUTPUT_STREAM, + g_param_spec_object ("output-stream", "Output stream", + "the output stream where to write.", + G_TYPE_OUTPUT_STREAM, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); +} + +GInputStream * +soup_cache_input_stream_new (GInputStream *base_stream) +{ + return g_object_new (SOUP_TYPE_CACHE_INPUT_STREAM, + "base-stream", base_stream, + "close-base-stream", FALSE, + NULL); +} diff --git a/libsoup/soup-cache-input-stream.h b/libsoup/soup-cache-input-stream.h new file mode 100644 index 00000000..c999d102 --- /dev/null +++ b/libsoup/soup-cache-input-stream.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-cache-input-stream.h - Header for SoupCacheInputStream + */ + +#ifndef __SOUP_CACHE_INPUT_STREAM_H__ +#define __SOUP_CACHE_INPUT_STREAM_H__ + +#include "soup-filter-input-stream.h" + +G_BEGIN_DECLS + +#define SOUP_TYPE_CACHE_INPUT_STREAM (soup_cache_input_stream_get_type()) +#define SOUP_CACHE_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_CACHE_INPUT_STREAM, SoupCacheInputStream)) +#define SOUP_CACHE_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CACHE_INPUT_STREAM, SoupCacheInputStreamClass)) +#define SOUP_IS_CACHE_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_CACHE_INPUT_STREAM)) +#define SOUP_IS_CACHE_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_CACHE_INPUT_STREAM)) +#define SOUP_CACHE_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CACHE_INPUT_STREAM, SoupCacheInputStreamClass)) + +typedef struct _SoupCacheInputStream SoupCacheInputStream; +typedef struct _SoupCacheInputStreamClass SoupCacheInputStreamClass; +typedef struct _SoupCacheInputStreamPrivate SoupCacheInputStreamPrivate; + +struct _SoupCacheInputStreamClass +{ + SoupFilterInputStreamClass parent_class; +}; + +struct _SoupCacheInputStream +{ + SoupFilterInputStream parent; + + SoupCacheInputStreamPrivate *priv; +}; + +GType soup_cache_input_stream_get_type (void) G_GNUC_CONST; + +GInputStream *soup_cache_input_stream_new (GInputStream *base_stream); + +void soup_cache_input_stream_cache (SoupCacheInputStream *istream, + GFile *file, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gsize soup_cache_input_stream_cache_finish (SoupCacheInputStream *istream, + GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* __SOUP_CACHE_INPUT_STREAM_H__ */ diff --git a/po/POTFILES.in b/po/POTFILES.in index fff1f0ea..21c70d42 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,5 @@ libsoup/soup-body-input-stream.c +libsoup/soup-cache-input-stream.c libsoup/soup-converter-wrapper.c libsoup/soup-message-client-io.c libsoup/soup-message-io.c -- cgit v1.2.1 From 1fd0404b4c8fe5e6da8e04dfef44bf63a4af0a75 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Thu, 23 Aug 2012 17:55:05 +0200 Subject: SoupCache: add SoupContentProcessor support SoupCache now implements the SoupContentProcessor interface. This means that soup-message-io will ask it to wrap a given base stream. By doing that the cache will backup up every byte readed from that base stream into a local file using a SoupCacheInputStream. Apart from that, this removes all the old resource writing infrastructure that was moved to the new SoupCacheInputStream. The SoupCache just needs to pass a callback to the stream in order to be notified once the caching operation finishes. This also involves moving the caching decision from the "got-headers" callback to the _wrap_input() implementation. https://bugzilla.gnome.org/show_bug.cgi?id=682112 --- libsoup/soup-cache.c | 572 ++++++++++++------------------------- libsoup/soup-client-input-stream.c | 23 -- 2 files changed, 178 insertions(+), 417 deletions(-) diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 24a4b2c6..da89ddff 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -32,12 +32,19 @@ #include #include "soup-cache.h" +#include "soup-body-input-stream.h" +#include "soup-cache-input-stream.h" #include "soup-cache-private.h" +#include "soup-content-processor.h" +#include "soup-message-private.h" #include "soup.h" static SoupSessionFeatureInterface *soup_cache_default_feature_interface; static void soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); +static SoupContentProcessorInterface *soup_cache_default_content_processor_interface; +static void soup_cache_content_processor_init (SoupContentProcessorInterface *interface, gpointer interface_data); + #define DEFAULT_MAX_SIZE 50 * 1024 * 1024 #define MAX_ENTRY_DATA_PERCENTAGE 10 /* Percentage of the total size of the cache that can be @@ -104,21 +111,6 @@ struct _SoupCachePrivate { GList *lru_start; }; -typedef struct { - SoupCache *cache; - SoupCacheEntry *entry; - SoupMessage *msg; - gulong content_sniffed_handler; - gulong got_chunk_handler; - gulong got_body_handler; - gulong restarted_handler; - GQueue *buffer_queue; - gboolean got_body; - SoupBuffer *current_writing_buffer; - GError *error; - GOutputStream *ostream; -} SoupCacheWritingFixture; - enum { PROP_0, PROP_CACHE_DIR, @@ -129,12 +121,13 @@ enum { G_DEFINE_TYPE_WITH_CODE (SoupCache, soup_cache, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, - soup_cache_session_feature_init)) + soup_cache_session_feature_init) + G_IMPLEMENT_INTERFACE (SOUP_TYPE_CONTENT_PROCESSOR, + soup_cache_content_processor_init)) static gboolean soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry, gboolean purge); static void make_room_for_new_entry (SoupCache *cache, guint length_to_add); static gboolean cache_accepts_entries_of_size (SoupCache *cache, guint length_to_add); -static gboolean write_next_buffer (SoupCacheEntry *entry, SoupCacheWritingFixture *fixture); static GFile * get_file_from_entry (SoupCache *cache, SoupCacheEntry *entry) @@ -489,232 +482,11 @@ soup_cache_entry_new (SoupCache *cache, SoupMessage *msg, time_t request_time, t return entry; } -static void -soup_cache_writing_fixture_free (SoupCacheWritingFixture *fixture) -{ - /* Free fixture. And disconnect signals, we don't want to - listen to more SoupMessage events as we're finished with - this resource */ - if (g_signal_handler_is_connected (fixture->msg, fixture->content_sniffed_handler)) - g_signal_handler_disconnect (fixture->msg, fixture->content_sniffed_handler); - if (g_signal_handler_is_connected (fixture->msg, fixture->got_chunk_handler)) - g_signal_handler_disconnect (fixture->msg, fixture->got_chunk_handler); - if (g_signal_handler_is_connected (fixture->msg, fixture->got_body_handler)) - g_signal_handler_disconnect (fixture->msg, fixture->got_body_handler); - if (g_signal_handler_is_connected (fixture->msg, fixture->restarted_handler)) - g_signal_handler_disconnect (fixture->msg, fixture->restarted_handler); - g_clear_pointer (&fixture->current_writing_buffer, soup_buffer_free); - g_clear_object (&fixture->ostream); - g_clear_error (&fixture->error); - g_queue_foreach (fixture->buffer_queue, (GFunc) soup_buffer_free, NULL); - g_queue_free (fixture->buffer_queue); - g_object_unref (fixture->msg); - g_object_unref (fixture->cache); - g_slice_free (SoupCacheWritingFixture, fixture); -} - -static void -msg_content_sniffed_cb (SoupMessage *msg, gchar *content_type, GHashTable *params, SoupCacheWritingFixture *fixture) -{ - soup_message_headers_set_content_type (fixture->entry->headers, content_type, params); -} - -static void -close_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture *fixture) -{ - SoupCacheEntry *entry = fixture->entry; - SoupCache *cache = fixture->cache; - GOutputStream *stream = G_OUTPUT_STREAM (source); - goffset content_length; - - g_warn_if_fail (fixture->error == NULL); - - /* FIXME: what do we do on error ? */ - - if (stream) { - g_output_stream_close_finish (stream, result, NULL); - g_object_unref (stream); - } - fixture->ostream = NULL; - - content_length = soup_message_headers_get_content_length (entry->headers); - - /* If the process was cancelled, then delete the entry from - the cache. Do it also if the size of a chunked resource is - too much for the cache */ - if (g_cancellable_is_cancelled (entry->cancellable)) { - entry->dirty = FALSE; - soup_cache_entry_remove (cache, entry, TRUE); - entry = NULL; - } else if ((soup_message_headers_get_encoding (entry->headers) == SOUP_ENCODING_CHUNKED) || - entry->length != (gsize) content_length) { - /* Two options here: - * - * 1. "chunked" data, entry was temporarily added to - * cache (as content-length is 0) and now that we have - * the actual size we have to evaluate if we want it - * in the cache or not - * - * 2. Content-Length has a different value than actual - * length, means that the content was encoded for - * transmission (typically compressed) and thus we - * have to substract the content-length value that was - * added to the cache and add the unencoded length - */ - gint length_to_add = entry->length - content_length; - - /* Make room in cache if needed */ - if (cache_accepts_entries_of_size (cache, length_to_add)) { - make_room_for_new_entry (cache, length_to_add); - - cache->priv->size += length_to_add; - } else { - entry->dirty = FALSE; - soup_cache_entry_remove (cache, entry, TRUE); - entry = NULL; - } - } - - if (entry) { - entry->dirty = FALSE; - fixture->got_body = FALSE; - - g_clear_pointer (&fixture->current_writing_buffer, soup_buffer_free); - g_clear_object (&entry->cancellable); - } - - cache->priv->n_pending--; - - /* Frees */ - soup_cache_writing_fixture_free (fixture); -} - -static void -write_ready_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture *fixture) -{ - GOutputStream *stream = G_OUTPUT_STREAM (source); - gssize write_size; - SoupCacheEntry *entry = fixture->entry; - - if (g_cancellable_is_cancelled (entry->cancellable)) { - g_output_stream_close_async (stream, - G_PRIORITY_LOW, - entry->cancellable, - (GAsyncReadyCallback)close_ready_cb, - fixture); - return; - } - - write_size = g_output_stream_write_finish (stream, result, &fixture->error); - if (write_size <= 0 || fixture->error) { - g_output_stream_close_async (stream, - G_PRIORITY_LOW, - entry->cancellable, - (GAsyncReadyCallback)close_ready_cb, - fixture); - /* FIXME: We should completely stop caching the - resource at this point */ - } else { - /* Are we still writing and is there new data to write - already ? */ - if (fixture->buffer_queue->length > 0) - write_next_buffer (entry, fixture); - else { - g_clear_pointer (&fixture->current_writing_buffer, soup_buffer_free); - - if (fixture->got_body) { - /* If we already received 'got-body' - and we have written all the data, - we can close the stream */ - g_output_stream_close_async (fixture->ostream, - G_PRIORITY_LOW, - entry->cancellable, - (GAsyncReadyCallback)close_ready_cb, - fixture); - } - } - } -} - -static gboolean -write_next_buffer (SoupCacheEntry *entry, SoupCacheWritingFixture *fixture) -{ - SoupBuffer *buffer = g_queue_pop_head (fixture->buffer_queue); - - if (buffer == NULL) - return FALSE; - - /* Free the old buffer */ - g_clear_pointer (&fixture->current_writing_buffer, soup_buffer_free); - fixture->current_writing_buffer = buffer; - - g_output_stream_write_async (fixture->ostream, buffer->data, buffer->length, - G_PRIORITY_LOW, entry->cancellable, - (GAsyncReadyCallback) write_ready_cb, - fixture); - return TRUE; -} - -static void -msg_got_chunk_cb (SoupMessage *msg, SoupBuffer *chunk, SoupCacheWritingFixture *fixture) -{ - SoupCacheEntry *entry = fixture->entry; - - /* Ignore this if the writing or appending was cancelled */ - if (!g_cancellable_is_cancelled (entry->cancellable)) { - g_queue_push_tail (fixture->buffer_queue, soup_buffer_copy (chunk)); - entry->length += chunk->length; - - if (!cache_accepts_entries_of_size (fixture->cache, entry->length)) { - /* Quickly cancel the caching of the resource */ - g_cancellable_cancel (entry->cancellable); - } - } - - /* FIXME: remove the error check when we cancel the caching at - the first write error */ - /* Only write if the entry stream is ready */ - if (fixture->current_writing_buffer == NULL && fixture->error == NULL && fixture->ostream) - write_next_buffer (entry, fixture); -} - -static void -msg_got_body_cb (SoupMessage *msg, SoupCacheWritingFixture *fixture) -{ - SoupCacheEntry *entry = fixture->entry; - g_return_if_fail (entry); - - fixture->got_body = TRUE; - - if (!fixture->ostream && fixture->buffer_queue->length > 0) - /* The stream is not ready to be written but we still - have data to write, we'll write it when the stream - is opened for writing */ - return; - - - if (fixture->buffer_queue->length > 0) { - /* If we still have data to write, write it, - write_ready_cb will close the stream */ - if (fixture->current_writing_buffer == NULL && fixture->error == NULL && fixture->ostream) - write_next_buffer (entry, fixture); - return; - } - - if (fixture->ostream && fixture->current_writing_buffer == NULL) - g_output_stream_close_async (fixture->ostream, - G_PRIORITY_LOW, - entry->cancellable, - (GAsyncReadyCallback)close_ready_cb, - fixture); -} - static gboolean soup_cache_entry_remove (SoupCache *cache, SoupCacheEntry *entry, gboolean purge) { GList *lru_item; - /* if (entry->dirty && !g_cancellable_is_cancelled (entry->cancellable)) { */ if (entry->dirty) { g_cancellable_cancel (entry->cancellable); return FALSE; @@ -819,7 +591,7 @@ soup_cache_entry_insert (SoupCache *cache, /* Fill the key */ entry->key = get_cache_key_from_uri ((const char *) entry->uri); - if (soup_message_headers_get_encoding (entry->headers) != SOUP_ENCODING_CHUNKED) + if (soup_message_headers_get_encoding (entry->headers) == SOUP_ENCODING_CONTENT_LENGTH) length_to_add = soup_message_headers_get_content_length (entry->headers); /* Check if we are going to store the resource depending on its size */ @@ -874,151 +646,12 @@ soup_cache_entry_lookup (SoupCache *cache, return entry; } -static void -msg_restarted_cb (SoupMessage *msg, SoupCacheEntry *entry) -{ - /* FIXME: What should we do here exactly? */ -} - -static void -replace_cb (GObject *source, GAsyncResult *result, SoupCacheWritingFixture *fixture) -{ - SoupCacheEntry *entry = fixture->entry; - GOutputStream *ostream = (GOutputStream *) g_file_replace_finish (G_FILE (source), - result, &fixture->error); - - if (g_cancellable_is_cancelled (entry->cancellable) || fixture->error) { - g_clear_object (&ostream); - fixture->cache->priv->n_pending--; - entry->dirty = FALSE; - soup_cache_entry_remove (fixture->cache, entry, TRUE); - soup_cache_writing_fixture_free (fixture); - return; - } - - fixture->ostream = ostream; - - /* If we already got all the data we have to initiate the - * writing here, since we won't get more 'got-chunk' - * signals - */ - if (!fixture->got_body) - return; - - /* It could happen that reading the data from server - * was completed before this happens. In that case - * there is no data - */ - if (!write_next_buffer (entry, fixture)) - /* Could happen if the resource is empty */ - g_output_stream_close_async (ostream, G_PRIORITY_LOW, entry->cancellable, - (GAsyncReadyCallback) close_ready_cb, - fixture); -} - -typedef struct { - time_t request_time; - SoupSessionFeature *feature; - gulong got_headers_handler; -} RequestHelper; - -static void -msg_got_headers_cb (SoupMessage *msg, gpointer user_data) -{ - SoupCache *cache; - SoupCacheability cacheable; - RequestHelper *helper; - time_t request_time, response_time; - SoupCacheEntry *entry; - - response_time = time (NULL); - - helper = (RequestHelper *)user_data; - cache = SOUP_CACHE (helper->feature); - request_time = helper->request_time; - g_signal_handlers_disconnect_by_func (msg, msg_got_headers_cb, user_data); - g_slice_free (RequestHelper, helper); - - cacheable = soup_cache_get_cacheability (cache, msg); - - if (cacheable & SOUP_CACHE_CACHEABLE) { - GFile *file; - SoupCacheWritingFixture *fixture; - - /* Check if we are already caching this resource */ - entry = soup_cache_entry_lookup (cache, msg); - - if (entry && (entry->dirty || entry->being_validated)) - return; - - /* Create a new entry, deleting any old one if present */ - if (entry) - soup_cache_entry_remove (cache, entry, TRUE); - - entry = soup_cache_entry_new (cache, msg, request_time, response_time); - entry->hits = 1; - - /* Do not continue if it can not be stored */ - if (!soup_cache_entry_insert (cache, entry, TRUE)) { - soup_cache_entry_free (entry); - return; - } - - fixture = g_slice_new0 (SoupCacheWritingFixture); - fixture->cache = g_object_ref (cache); - fixture->entry = entry; - fixture->msg = g_object_ref (msg); - fixture->buffer_queue = g_queue_new (); - - /* We connect now to these signals and buffer the data - if it comes before the file is ready for writing */ - fixture->content_sniffed_handler = - g_signal_connect (msg, "content-sniffed", G_CALLBACK (msg_content_sniffed_cb), fixture); - fixture->got_chunk_handler = - g_signal_connect (msg, "got-chunk", G_CALLBACK (msg_got_chunk_cb), fixture); - fixture->got_body_handler = - g_signal_connect (msg, "got-body", G_CALLBACK (msg_got_body_cb), fixture); - fixture->restarted_handler = - g_signal_connect (msg, "restarted", G_CALLBACK (msg_restarted_cb), entry); - - /* Prepare entry */ - cache->priv->n_pending++; - - entry->dirty = TRUE; - entry->cancellable = g_cancellable_new (); - file = get_file_from_entry (cache, entry); - g_file_replace_async (file, NULL, FALSE, - G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, - G_PRIORITY_LOW, entry->cancellable, - (GAsyncReadyCallback) replace_cb, fixture); - g_object_unref (file); - } else if (cacheable & SOUP_CACHE_INVALIDATES) { - entry = soup_cache_entry_lookup (cache, msg); - - if (entry) - soup_cache_entry_remove (cache, entry, TRUE); - } else if (cacheable & SOUP_CACHE_VALIDATES) { - entry = soup_cache_entry_lookup (cache, msg); - - /* It's possible to get a CACHE_VALIDATES with no - * entry in the hash table. This could happen if for - * example the soup client is the one creating the - * conditional request. - */ - if (entry) { - entry->being_validated = FALSE; - copy_end_to_end_headers (msg->response_headers, entry->headers); - soup_cache_entry_set_freshness (entry, msg, cache); - } - } -} - GInputStream * soup_cache_send_response (SoupCache *cache, SoupMessage *msg) { SoupCacheEntry *entry; char *current_age; - GInputStream *stream = NULL; + GInputStream *file_stream, *body_stream, *cache_stream; GFile *file; g_return_val_if_fail (SOUP_IS_CACHE (cache), NULL); @@ -1027,18 +660,19 @@ soup_cache_send_response (SoupCache *cache, SoupMessage *msg) entry = soup_cache_entry_lookup (cache, msg); g_return_val_if_fail (entry, NULL); - /* TODO: the original idea was to save reads, but current code - assumes that a stream is always returned. Need to reach - some agreement here. Also we have to handle the situation - were the file was no longer there (for example files - removed without notifying the cache */ file = get_file_from_entry (cache, entry); - stream = G_INPUT_STREAM (g_file_read (file, NULL, NULL)); + file_stream = G_INPUT_STREAM (g_file_read (file, NULL, NULL)); g_object_unref (file); /* Do not change the original message if there is no resource */ - if (stream == NULL) - return stream; + if (!file_stream) + return NULL; + + body_stream = soup_body_input_stream_new (file_stream, SOUP_ENCODING_CONTENT_LENGTH, entry->length); + g_object_unref (file_stream); + + if (!body_stream) + return NULL; /* If we are told to send a response from cache any validation in course is over by now */ @@ -1057,19 +691,29 @@ soup_cache_send_response (SoupCache *cache, SoupMessage *msg) current_age); g_free (current_age); - return stream; + /* Create the cache stream. */ + soup_message_disable_feature (msg, SOUP_TYPE_CACHE); + cache_stream = soup_message_setup_body_istream (body_stream, msg, + cache->priv->session, + SOUP_STAGE_ENTITY_BODY); + g_object_unref (body_stream); + + return cache_stream; +} + +static void +msg_got_headers_cb (SoupMessage *msg, gpointer user_data) +{ + g_object_set_data (G_OBJECT (msg), "response-time", GINT_TO_POINTER (time (NULL))); + g_signal_handlers_disconnect_by_func (msg, msg_got_headers_cb, user_data); } static void request_started (SoupSessionFeature *feature, SoupSession *session, SoupMessage *msg, SoupSocket *socket) { - RequestHelper *helper = g_slice_new0 (RequestHelper); - helper->request_time = time (NULL); - helper->feature = feature; - helper->got_headers_handler = g_signal_connect (msg, "got-headers", - G_CALLBACK (msg_got_headers_cb), - helper); + g_object_set_data (G_OBJECT (msg), "request-time", GINT_TO_POINTER (time (NULL))); + g_signal_connect (msg, "got-headers", G_CALLBACK (msg_got_headers_cb), NULL); } static void @@ -1092,6 +736,145 @@ soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface, feature_interface->request_started = request_started; } +typedef struct { + SoupCache *cache; + SoupCacheEntry *entry; +} StreamHelper; + +static void +istream_cache_cb (GObject *source, + GAsyncResult *res, + gpointer user_data) +{ + SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (source); + StreamHelper *helper = (StreamHelper *) user_data; + SoupCache *cache = helper->cache; + SoupCacheEntry *entry = helper->entry; + GError *error = NULL; + + entry->dirty = FALSE; + g_clear_object (&entry->cancellable); + --cache->priv->n_pending; + + entry->length = soup_cache_input_stream_cache_finish (istream, res, &error); + + if (error) { + /* Update cache size */ + if (soup_message_headers_get_encoding (entry->headers) == SOUP_ENCODING_CONTENT_LENGTH) + cache->priv->size -= soup_message_headers_get_content_length (entry->headers); + + soup_cache_entry_remove (cache, entry, TRUE); + helper->entry = entry = NULL; + goto cleanup; + } + + if (soup_message_headers_get_encoding (entry->headers) != SOUP_ENCODING_CONTENT_LENGTH) { + + if (cache_accepts_entries_of_size (cache, entry->length)) { + make_room_for_new_entry (cache, entry->length); + cache->priv->size += entry->length; + } else { + soup_cache_entry_remove (cache, entry, TRUE); + helper->entry = entry = NULL; + } + } + + cleanup: + g_object_unref (helper->cache); + g_slice_free (StreamHelper, helper); +} + + +static GInputStream* +soup_cache_content_processor_wrap_input (SoupContentProcessor *processor, + GInputStream *base_stream, + SoupMessage *msg, + GError **error) +{ + SoupCache *cache = (SoupCache*) processor; + SoupCacheEntry *entry; + SoupCacheability cacheability; + GInputStream *istream; + GFile *file; + StreamHelper *helper; + time_t request_time, response_time; + + /* First of all, check if we should cache the resource. */ + cacheability = soup_cache_get_cacheability (cache, msg); + entry = soup_cache_entry_lookup (cache, msg); + + if (cacheability & SOUP_CACHE_INVALIDATES) { + if (entry) + soup_cache_entry_remove (cache, entry, TRUE); + return NULL; + } + + if (cacheability & SOUP_CACHE_VALIDATES) { + /* It's possible to get a CACHE_VALIDATES with no + * entry in the hash table. This could happen if for + * example the soup client is the one creating the + * conditional request. + */ + if (entry) { + entry->being_validated = FALSE; + copy_end_to_end_headers (msg->response_headers, entry->headers); + soup_cache_entry_set_freshness (entry, msg, cache); + } + return NULL; + } + + if (!(cacheability & SOUP_CACHE_CACHEABLE)) + return NULL; + + /* Check if we are already caching this resource */ + if (entry && (entry->dirty || entry->being_validated)) + return NULL; + + /* Create a new entry, deleting any old one if present */ + if (entry) + soup_cache_entry_remove (cache, entry, TRUE); + + request_time = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "request-time")); + response_time = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "request-time")); + entry = soup_cache_entry_new (cache, msg, request_time, response_time); + entry->hits = 1; + entry->dirty = TRUE; + + /* Do not continue if it can not be stored */ + if (!soup_cache_entry_insert (cache, entry, TRUE)) { + soup_cache_entry_free (entry); + return NULL; + } + + ++cache->priv->n_pending; + + istream = soup_cache_input_stream_new (base_stream); + + file = get_file_from_entry (cache, entry); + entry->cancellable = g_cancellable_new (); + + helper = g_slice_new (StreamHelper); + helper->cache = g_object_ref (cache); + helper->entry = entry; + + soup_cache_input_stream_cache (SOUP_CACHE_INPUT_STREAM (istream), file, entry->cancellable, + (GAsyncReadyCallback) istream_cache_cb, helper); + g_object_unref (file); + + return istream; +} + +static void +soup_cache_content_processor_init (SoupContentProcessorInterface *processor_interface, + gpointer interface_data) +{ + soup_cache_default_content_processor_interface = + g_type_default_interface_peek (SOUP_TYPE_CONTENT_PROCESSOR); + + processor_interface->processing_stage = SOUP_STAGE_ENTITY_BODY; + processor_interface->wrap_input = soup_cache_content_processor_wrap_input; +} + static void soup_cache_init (SoupCache *cache) { @@ -1565,6 +1348,7 @@ soup_cache_generate_conditional_request (SoupCache *cache, SoupMessage *original /* Copy the data we need from the original message */ uri = soup_message_get_uri (original); msg = soup_message_new_from_uri (original->method, uri); + soup_message_disable_feature (msg, SOUP_TYPE_CACHE); soup_message_headers_foreach (original->request_headers, (SoupMessageHeadersForeachFunc)copy_headers, diff --git a/libsoup/soup-client-input-stream.c b/libsoup/soup-client-input-stream.c index ddcabaa5..78bc15f1 100644 --- a/libsoup/soup-client-input-stream.c +++ b/libsoup/soup-client-input-stream.c @@ -88,17 +88,6 @@ soup_client_input_stream_get_property (GObject *object, guint prop_id, } } -/* Temporary HACK to keep SoupCache working. See soup_client_input_stream_read_fn() - * and soup_client_input_stream_read_nonblocking(). - */ -static void -soup_client_input_stream_emit_got_chunk (SoupClientInputStream *stream, void *data, gssize nread) -{ - SoupBuffer *buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY, data, nread); - soup_message_got_chunk (stream->priv->msg, buffer); - soup_buffer_free (buffer); -} - static gssize soup_client_input_stream_read_fn (GInputStream *stream, void *buffer, @@ -114,12 +103,6 @@ soup_client_input_stream_read_fn (GInputStream *stream, if (nread == 0) g_signal_emit (stream, signals[EOF], 0); - /* Temporary HACK to keep SoupCache working */ - if (nread > 0) { - soup_client_input_stream_emit_got_chunk (SOUP_CLIENT_INPUT_STREAM (stream), - buffer, nread); - } - return nread; } @@ -137,12 +120,6 @@ soup_client_input_stream_read_nonblocking (GPollableInputStream *stream, if (nread == 0) g_signal_emit (stream, signals[EOF], 0); - /* Temporary HACK to keep SoupCache working */ - if (nread > 0) { - soup_client_input_stream_emit_got_chunk (SOUP_CLIENT_INPUT_STREAM (stream), - buffer, nread); - } - return nread; } -- cgit v1.2.1 From 00fa1ad0dc9df59c3de3131c85ef3891c61cbe2b Mon Sep 17 00:00:00 2001 From: Nilamdyuti Goswami Date: Wed, 19 Dec 2012 12:57:28 +0530 Subject: Assamese translation updated --- po/as.po | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/po/as.po b/po/as.po index 4992402e..734724ed 100644 --- a/po/as.po +++ b/po/as.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-10 16:22+0000\n" -"PO-Revision-Date: 2012-12-12 13:50+0530\n" +"POT-Creation-Date: 2012-12-18 15:49+0000\n" +"PO-Revision-Date: 2012-12-19 12:56+0530\n" "Last-Translator: Nilamdyuti Goswami \n" "Language-Team: Assamese \n" "Language: as\n" @@ -33,13 +33,16 @@ msgstr "অবৈধ সন্ধান অনুৰোধ" msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream চুটি কৰিব নোৱাৰি" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "নেটৱাৰ্ক স্ট্ৰিম অপ্ৰত্যাশিতভাৱে বন্ধ হল" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "আউটপুট বাফাৰ অতি সৰু" #: ../libsoup/soup-message-client-io.c:41 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" msgstr "HTTP প্ৰতিক্ৰিয়া বিশ্লেষণ কৰিব পৰা নগল" @@ -56,7 +59,6 @@ msgid "Operation would block" msgstr "কাৰ্য্য প্ৰতিৰোধ কৰিব" #: ../libsoup/soup-message-server-io.c:40 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" msgstr "HTTP অনুৰোধ বিশ্লেষণ কৰিব পৰা নগল" @@ -70,17 +72,17 @@ msgstr "কোনো URl প্ৰদান কৰা হোৱা নাই" msgid "Invalid '%s' URI: %s" msgstr "অবৈধ '%s' URI: %s" -#: ../libsoup/soup-session.c:3759 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' বিশ্লেষণ কৰিব পৰা নগল" -#: ../libsoup/soup-session.c:3796 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "অসমৰ্থিত URl আঁচনি '%s'" -#: ../libsoup/soup-session.c:3818 +#: ../libsoup/soup-session.c:3811 #, c-format msgid "Not an HTTP URI" msgstr "এটা HTTP URI নহয়" -- cgit v1.2.1 From 4eed2047493d1956184d9310e1b1b3b28472763d Mon Sep 17 00:00:00 2001 From: Sudarsana Nagineni Date: Tue, 18 Dec 2012 00:11:13 +0200 Subject: soup-cache: Fix a memory leak. The GFileInfo returned by g_file_enumerator_next_file() must be freed with g_object_unref(). https://bugzilla.gnome.org/show_bug.cgi?id=690382 --- libsoup/soup-cache.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index da89ddff..7130c5ce 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -1291,6 +1291,7 @@ clear_cache_files (SoupCache *cache) g_file_delete (cache_file, NULL, NULL); g_object_unref (cache_file); } + g_object_unref (file_info); } g_object_unref (file_enumerator); } -- cgit v1.2.1 From 2f5e0b1e0d8c4896c0c851df24ef979da1a75677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Wed, 19 Dec 2012 18:22:22 +0200 Subject: [l10n] Updated Estonian translation --- po/et.po | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/po/et.po b/po/et.po index 249914f4..7f23ec4a 100644 --- a/po/et.po +++ b/po/et.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-22 21:01+0000\n" -"PO-Revision-Date: 2012-09-23 15:11+0300\n" +"POT-Creation-Date: 2012-12-19 09:41+0000\n" +"PO-Revision-Date: 2012-12-19 17:55+0300\n" "Last-Translator: Mattias Põldaru \n" "Language-Team: Estonian \n" "Language: et\n" @@ -27,16 +27,28 @@ msgstr "Sobimatu kerimise päring" msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream-i pole võimalik lühendada" +msgid "Network stream unexpectedly closed" +msgstr "Võrguvoog sulgus ootamatult" + #, c-format msgid "Output buffer is too small" msgstr "Väljundpuhver on liiga väike" +msgid "Could not parse HTTP response" +msgstr "HTTP vastust polnud võimalik parsida" + +msgid "Unrecognized HTTP response encoding" +msgstr "Tundmatu HTTP vastuse kodeering" + msgid "Operation was cancelled" msgstr "Operatsioon katkestati" msgid "Operation would block" msgstr "Operatsioon blokeeruks" +msgid "Could not parse HTTP request" +msgstr "HTTP päringut polnud võimalik parsida" + #, c-format msgid "No URI provided" msgstr "URI-d ei antud" @@ -53,6 +65,10 @@ msgstr "URI-d '%s' polnud võimalik parsida" msgid "Unsupported URI scheme '%s'" msgstr "URI skeem pole toetatud '%s'" +#, c-format +msgid "Not an HTTP URI" +msgstr "Pole HTTP URI" + msgid "Hostname is an IP address" msgstr "Hostinimi on IP-aadress" -- cgit v1.2.1 From 2705c172c20de7f8da0df61bf1a924a6336acdb7 Mon Sep 17 00:00:00 2001 From: Daniel Mustieles Date: Thu, 20 Dec 2012 11:10:21 +0100 Subject: Updated Spanish translation --- po/es.po | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/po/es.po b/po/es.po index 5624693c..c505a424 100644 --- a/po/es.po +++ b/po/es.po @@ -9,15 +9,15 @@ msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-10 16:22+0000\n" -"PO-Revision-Date: 2012-12-16 20:34+0100\n" +"POT-Creation-Date: 2012-12-18 15:49+0000\n" +"PO-Revision-Date: 2012-12-20 11:07+0100\n" "Last-Translator: Daniel Mustieles \n" -"Language-Team: Español; Castellano \n" +"Language-Team: Español \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" "X-Generator: Gtranslator 2.91.5\n" #: ../libsoup/soup-body-input-stream.c:141 @@ -34,13 +34,16 @@ msgstr "Petición de búsqueda no válida" msgid "Cannot truncate SoupBodyInputStream" msgstr "No se puede truncar SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "El flujo de red se cerró inesperadamente" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "El búfer de salida es demasiado pequeño" #: ../libsoup/soup-message-client-io.c:41 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" msgstr "No se pudo analizar la respuesta HTTP" @@ -57,7 +60,6 @@ msgid "Operation would block" msgstr "La operación se bloqueará" #: ../libsoup/soup-message-server-io.c:40 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" msgstr "No se pudo analizar la solicitud HTTP" @@ -71,17 +73,17 @@ msgstr "No se ha proporcionado un URI" msgid "Invalid '%s' URI: %s" msgstr "URI «%s» no válida: %s" -#: ../libsoup/soup-session.c:3759 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "No se pudo analizar el URI «%s»" -#: ../libsoup/soup-session.c:3796 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Esquema %s de URI no soportado" -#: ../libsoup/soup-session.c:3818 +#: ../libsoup/soup-session.c:3811 #, c-format msgid "Not an HTTP URI" msgstr "No es un URI HTTP" -- cgit v1.2.1 From 16ac5f757108ac9f79fa1085294ea9f973a7e57e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Urban=C4=8Di=C4=8D?= Date: Sat, 22 Dec 2012 15:22:49 +0100 Subject: Updated Slovenian translation --- po/sl.po | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/po/sl.po b/po/sl.po index 869a94d8..2573f87e 100644 --- a/po/sl.po +++ b/po/sl.po @@ -7,24 +7,24 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-10 21:37+0100\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-12-20 10:15+0000\n" +"PO-Revision-Date: 2012-12-22 15:17+0100\n" "Last-Translator: Matej Urbančič \n" "Language-Team: Slovenian \n" "Language: sl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);\n" -"X-Poedit-Language: Slovenian\n" -"X-Poedit-Country: SLOVENIA\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" +"%100==4 ? 3 : 0);\n" "X-Poedit-SourceCharset: utf-8\n" +"X-Generator: Poedit 1.5.4\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 -#: ../libsoup/soup-body-input-stream.c:205 -#: ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Povezava je nepričakovano končana" @@ -36,40 +36,60 @@ msgstr "Neveljavna zahteva iskanja" msgid "Cannot truncate SoupBodyInputStream" msgstr "Ni mogoče porezati SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Omrežni pretok se je nepričakovano zaprl" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Odvodni medpomnilnik je premajhen." -#: ../libsoup/soup-message-io.c:818 -#: ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Odziva HTTP ni mogoče razčleniti" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Neprepoznano kodiranje odziva HTTP" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Opravilo je preklicano." -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Opravilo bi zaustavilo delovanje" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Zahteve HTTP ni mogoče razčleniti" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "Ni podanega naslova URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Neveljaven naslov URI '%s': %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "Ni mogoče razčleniti naslova URI '%s'" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nepodprta shema URI '%s'" +#: ../libsoup/soup-session.c:3811 +#, c-format +msgid "Not an HTTP URI" +msgstr "Naslov ni v obliki HTTP URI" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Ime gostitelja je naslov IP" @@ -85,4 +105,3 @@ msgstr "Ime gostitelja je brez osnovne domene" #: ../libsoup/soup-tld.c:226 msgid "Not enough domains" msgstr "Ni dovolj domen" - -- cgit v1.2.1 From 052343c84cbdc077dc8e07c5fdfe74f2ec282018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Di=C3=A9guez?= Date: Sun, 23 Dec 2012 04:04:03 +0100 Subject: Updated Galician translations --- po/gl.po | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/po/gl.po b/po/gl.po index e6d862b8..412d5d11 100644 --- a/po/gl.po +++ b/po/gl.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-12-15 00:15+0100\n" -"PO-Revision-Date: 2012-12-15 00:16+0200\n" +"POT-Creation-Date: 2012-12-23 04:03+0100\n" +"PO-Revision-Date: 2012-12-23 04:04+0200\n" "Last-Translator: Fran Dieguez \n" "Language-Team: gnome-l10n-gl@gnome.org\n" "Language: gl\n" @@ -31,6 +31,10 @@ msgstr "Petición de busca non válida" msgid "Cannot truncate SoupBodyInputStream" msgstr "Non é posíbel truncar SoupbodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Fluxo de rede pechado de forma non esperada" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 41e71fb1c5fab4d43821bfa0faaf686b73c14c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Dr=C4=85g?= Date: Sun, 23 Dec 2012 04:29:54 +0100 Subject: Updated Polish translation --- po/pl.po | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/po/pl.po b/po/pl.po index 1eb3234d..15e5701a 100644 --- a/po/pl.po +++ b/po/pl.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-12-16 03:27+0100\n" -"PO-Revision-Date: 2012-12-16 03:28+0100\n" +"POT-Creation-Date: 2012-12-23 04:28+0100\n" +"PO-Revision-Date: 2012-12-23 04:29+0100\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "Language: pl\n" @@ -37,6 +37,10 @@ msgstr "Nieprawidłowe żądanie przewinięcia" msgid "Cannot truncate SoupBodyInputStream" msgstr "Nie można skrócić SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Strumień sieciowy został nieoczekiwanie zamknięty" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -- cgit v1.2.1 From 24c61497852838b10854b79a8f332f819a72c2eb Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 25 Dec 2012 12:04:46 -0500 Subject: test-utils: remove unnecessary #includes --- tests/test-utils.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test-utils.h b/tests/test-utils.h index 2783aab3..ca1003f4 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -9,9 +9,6 @@ #include "libsoup/soup.h" #include "libsoup/soup-requester.h" -#include "libsoup/soup-request-data.h" -#include "libsoup/soup-request-file.h" -#include "libsoup/soup-request-http.h" void test_init (int argc, char **argv, GOptionEntry *entries); void test_cleanup (void); -- cgit v1.2.1 From e25e9ee4704398f0f276f6f9e91d948b8924356e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 25 Dec 2012 18:17:05 -0500 Subject: tests: add cache-test Add a test of basic cache functionality (finally!) Still needs more tests... --- tests/Makefile.am | 3 + tests/cache-test.c | 441 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 444 insertions(+) create mode 100644 tests/cache-test.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 54ce7bdb..a9184055 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -12,6 +12,7 @@ LIBS = \ $(GLIB_LIBS) noinst_PROGRAMS = \ + cache-test \ chunk-test \ coding-test \ connection-test \ @@ -47,6 +48,7 @@ noinst_DATA = soup-tests.gresource TEST_SRCS = test-utils.c test-utils.h auth_test_SOURCES = auth-test.c $(TEST_SRCS) +cache_test_SOURCES = cache-test.c $(TEST_SRCS) chunk_test_SOURCES = chunk-test.c $(TEST_SRCS) coding_test_SOURCES = coding-test.c $(TEST_SRCS) connection_test_SOURCES = connection-test.c $(TEST_SRCS) @@ -116,6 +118,7 @@ soup-tests.gresource: soup-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< TESTS = \ + cache-test \ chunk-test \ coding-test \ connection-test \ diff --git a/tests/cache-test.c b/tests/cache-test.c new file mode 100644 index 00000000..8f8d2b04 --- /dev/null +++ b/tests/cache-test.c @@ -0,0 +1,441 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2012 Red Hat, Inc. + */ + +#include "test-utils.h" + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + const char *last_modified, *etag; + const char *header; + guint status = SOUP_STATUS_OK; + + if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + header = soup_message_headers_get_one (msg->request_headers, + "Test-Set-Expires"); + if (header) { + soup_message_headers_append (msg->response_headers, + "Expires", + header); + } + + header = soup_message_headers_get_one (msg->request_headers, + "Test-Set-Cache-Control"); + if (header) { + soup_message_headers_append (msg->response_headers, + "Cache-Control", + header); + } + + last_modified = soup_message_headers_get_one (msg->request_headers, + "Test-Set-Last-Modified"); + if (last_modified) { + soup_message_headers_append (msg->response_headers, + "Last-Modified", + last_modified); + } + + etag = soup_message_headers_get_one (msg->request_headers, + "Test-Set-ETag"); + if (etag) { + soup_message_headers_append (msg->response_headers, + "ETag", + etag); + } + + + header = soup_message_headers_get_one (msg->request_headers, + "If-Modified-Since"); + if (header && last_modified) { + SoupDate *date; + time_t lastmod, check; + + date = soup_date_new_from_string (last_modified); + lastmod = soup_date_to_time_t (date); + soup_date_free (date); + + date = soup_date_new_from_string (header); + check = soup_date_to_time_t (date); + soup_date_free (date); + + if (lastmod <= check) + status = SOUP_STATUS_NOT_MODIFIED; + } + + header = soup_message_headers_get_one (msg->request_headers, + "If-None-Match"); + if (header && etag) { + if (!strcmp (header, etag)) + status = SOUP_STATUS_NOT_MODIFIED; + } + + if (status == SOUP_STATUS_OK) { + GChecksum *sum; + const char *body; + + sum = g_checksum_new (G_CHECKSUM_SHA256); + g_checksum_update (sum, (guchar *)path, strlen (path)); + if (last_modified) + g_checksum_update (sum, (guchar *)last_modified, strlen (last_modified)); + if (etag) + g_checksum_update (sum, (guchar *)etag, strlen (etag)); + body = g_checksum_get_string (sum); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_COPY, + body, strlen (body) + 1); + g_checksum_free (sum); + } + soup_message_set_status (msg, status); +} + +static gboolean +is_network_stream (GInputStream *stream) +{ + while (G_IS_FILTER_INPUT_STREAM (stream)) + stream = G_FILTER_INPUT_STREAM (stream)->base_stream; + + return !G_IS_FILE_INPUT_STREAM (stream); +} + +static char *do_request (SoupSession *session, + SoupURI *base_uri, + const char *method, + const char *path, + ...) G_GNUC_NULL_TERMINATED; + +static gboolean last_request_hit_network; +static gboolean last_request_validated; + +static char * +do_request (SoupSession *session, + SoupURI *base_uri, + const char *method, + const char *path, + ...) +{ + SoupRequestHTTP *req; + GInputStream *stream; + SoupURI *uri; + va_list ap; + const char *header, *value; + char buf[256]; + gsize nread; + GError *error = NULL; + + last_request_validated = last_request_hit_network = FALSE; + + uri = soup_uri_new_with_base (base_uri, path); + req = soup_session_request_http_uri (session, method, uri, NULL); + soup_uri_free (uri); + + va_start (ap, path); + while ((header = va_arg (ap, const char *))) { + value = va_arg (ap, const char *); + soup_message_headers_append (req->request_headers, + header, value); + } + + stream = soup_test_request_send (SOUP_REQUEST (req), NULL, &error); + if (!stream) { + debug_printf (1, " could not send request: %s\n", + error->message); + g_error_free (error); + g_object_unref (req); + return NULL; + } + + last_request_hit_network = is_network_stream (stream); + + g_input_stream_read_all (stream, buf, sizeof (buf), &nread, + NULL, &error); + if (error) { + debug_printf (1, " could not read response: %s\n", + error->message); + g_clear_error (&error); + } + soup_test_request_close_stream (SOUP_REQUEST (req), stream, + NULL, &error); + if (error) { + debug_printf (1, " could not close stream: %s\n", + error->message); + g_clear_error (&error); + } + g_object_unref (stream); + g_object_unref (req); + + /* Cache writes are G_PRIORITY_LOW, so they won't have happened yet... */ + soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE)); + + return nread ? g_memdup (buf, nread) : g_strdup (""); +} + +static void +request_started (SoupSession *session, SoupMessage *msg, + SoupSocket *socket) +{ + if (soup_message_headers_get_one (msg->request_headers, + "If-Modified-Since") || + soup_message_headers_get_one (msg->request_headers, + "If-None-Match")) { + debug_printf (2, " Conditional request for %s\n", + soup_message_get_uri (msg)->path); + last_request_validated = TRUE; + } +} + +static void +do_basics_test (SoupURI *base_uri) +{ + SoupSession *session; + SoupCache *cache; + char *cache_dir; + char *body1, *body2, *body3, *body4, *body5, *cmp; + + debug_printf (1, "Cache basics\n"); + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + g_signal_connect (session, "request-started", + G_CALLBACK (request_started), NULL); + + debug_printf (2, " Initial requests\n"); + body1 = do_request (session, base_uri, "GET", "/1", + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + body2 = do_request (session, base_uri, "GET", "/2", + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + NULL); + body3 = do_request (session, base_uri, "GET", "/3", + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + body4 = do_request (session, base_uri, "GET", "/4", + "Test-Set-ETag", "\"abcdefg\"", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + body5 = do_request (session, base_uri, "GET", "/5", + "Test-Set-Cache-Control", "no-cache", + NULL); + + + /* Resource with future Expires should have been cached */ + debug_printf (1, " Fresh cached resource\n"); + cmp = do_request (session, base_uri, "GET", "/1", + NULL); + if (last_request_hit_network) { + debug_printf (1, " Request for /1 not filled from cache!\n"); + errors++; + } + if (strcmp (body1, cmp) != 0) { + debug_printf (1, " Cached response (%s) did not match original (%s)\n", + cmp, body1); + errors++; + } + g_free (cmp); + + + /* Resource with long-ago Last-Modified should have been cached */ + debug_printf (1, " Heuristically-fresh cached resource\n"); + cmp = do_request (session, base_uri, "GET", "/2", + NULL); + if (last_request_hit_network) { + debug_printf (1, " Request for /2 not filled from cache!\n"); + errors++; + } + if (strcmp (body2, cmp) != 0) { + debug_printf (1, " Cached response (%s) did not match original (%s)\n", + cmp, body2); + errors++; + } + g_free (cmp); + + + /* Adding a query string should bypass the cache but not invalidate it */ + debug_printf (1, " Fresh cached resource with a query\n"); + cmp = do_request (session, base_uri, "GET", "/1?attr=value", + NULL); + if (!last_request_hit_network) { + debug_printf (1, " Request for /1?attr=value filled from cache!\n"); + errors++; + } + g_free (cmp); + debug_printf (2, " Second request\n"); + cmp = do_request (session, base_uri, "GET", "/1", + NULL); + if (last_request_hit_network) { + debug_printf (1, " Second request for /1 not filled from cache!\n"); + errors++; + } + if (strcmp (body1, cmp) != 0) { + debug_printf (1, " Cached response (%s) did not match original (%s)\n", + cmp, body1); + errors++; + } + g_free (cmp); + + + /* Last-Modified + must-revalidate causes a conditional request */ + debug_printf (1, " Unchanged must-revalidate resource w/ Last-Modified\n"); + cmp = do_request (session, base_uri, "GET", "/3", + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + if (!last_request_validated) { + debug_printf (1, " Request for /3 not validated!\n"); + errors++; + } + if (last_request_hit_network) { + debug_printf (1, " Request for /3 not filled from cache!\n"); + errors++; + } + if (strcmp (body3, cmp) != 0) { + debug_printf (1, " Cached response (%s) did not match original (%s)\n", + cmp, body3); + errors++; + } + g_free (cmp); + + + /* Validation failure should update cache */ + debug_printf (1, " Changed must-revalidate resource w/ Last-Modified\n"); + cmp = do_request (session, base_uri, "GET", "/3", + "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + if (!last_request_validated) { + debug_printf (1, " Request for /3 not validated!\n"); + errors++; + } + if (!last_request_hit_network) { + debug_printf (1, " Request for /3 filled from cache!\n"); + errors++; + } + if (strcmp (body3, cmp) == 0) { + debug_printf (1, " Request for /3 returned cached response\n"); + errors++; + } + g_free (cmp); + +#if 0 /* This doesn't work... is the test wrong or is SoupCache? */ + debug_printf (2, " Second request\n"); + cmp = do_request (session, base_uri, "GET", "/3", + "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + if (!last_request_validated) { + debug_printf (1, " Second request for /3 not validated!\n"); + errors++; + } + if (last_request_hit_network) { + debug_printf (1, " Second request for /3 not filled from cache!\n"); + errors++; + } + if (strcmp (body3, cmp) == 0) { + debug_printf (1, " Replacement body for /3 not cached!\n"); + errors++; + } + g_free (cmp); +#endif + + + /* ETag + must-revalidate causes a conditional request */ + debug_printf (1, " Unchanged must-revalidate resource w/ ETag\n"); + cmp = do_request (session, base_uri, "GET", "/4", + "Test-Set-ETag", "\"abcdefg\"", + NULL); + if (!last_request_validated) { + debug_printf (1, " Request for /4 not validated!\n"); + errors++; + } + if (last_request_hit_network) { + debug_printf (1, " Request for /4 not filled from cache!\n"); + errors++; + } + if (strcmp (body4, cmp) != 0) { + debug_printf (1, " Cached response (%s) did not match original (%s)\n", + cmp, body4); + errors++; + } + g_free (cmp); + + + /* Cache-Control: no-cache prevents caching */ + debug_printf (1, " Uncacheable resource\n"); + cmp = do_request (session, base_uri, "GET", "/5", + "Test-Set-Cache-Control", "no-cache", + NULL); + if (!last_request_hit_network) { + debug_printf (1, " Request for /5 filled from cache!\n"); + errors++; + } + if (strcmp (body5, cmp) != 0) { + debug_printf (1, " Re-retrieved response (%s) did not match original (%s)\n", + cmp, body5); + errors++; + } + g_free (cmp); + + + /* PUT to a URI invalidates the cache entry */ + debug_printf (1, " Invalidating and re-requesting a cached resource\n"); + cmp = do_request (session, base_uri, "PUT", "/1", + NULL); + if (!last_request_hit_network) { + debug_printf (1, " PUT filled from cache!\n"); + errors++; + } + g_free (cmp); + cmp = do_request (session, base_uri, "GET", "/1", + NULL); + if (!last_request_hit_network) { + debug_printf (1, " PUT failed to invalidate cache entry!\n"); + errors++; + } + g_free (cmp); + + + soup_test_session_abort_unref (session); + g_object_unref (cache); + + g_free (cache_dir); + g_free (body1); + g_free (body2); + g_free (body3); + g_free (body4); + g_free (body5); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + SoupURI *base_uri; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + base_uri = soup_uri_new ("http://127.0.0.1/"); + soup_uri_set_port (base_uri, soup_server_get_port (server)); + + do_basics_test (base_uri); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return errors != 0; +} -- cgit v1.2.1 From b55d54a50ab5586dba439cdadde9418f0ae96783 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 26 Dec 2012 14:50:11 -0500 Subject: soup-session: move cache handling here Move the SoupCache special handling from SoupRequestHTTP to SoupSession (as another step towards making SoupCache not such a magical special case hack that only works in certain situations). --- libsoup/soup-message-queue.h | 1 + libsoup/soup-request-http.c | 111 -------------------------------------- libsoup/soup-session.c | 125 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 125 insertions(+), 112 deletions(-) diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index dd619244..490f9a29 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -22,6 +22,7 @@ typedef enum { SOUP_MESSAGE_TUNNELED, SOUP_MESSAGE_READY, SOUP_MESSAGE_RUNNING, + SOUP_MESSAGE_CACHED, SOUP_MESSAGE_RESTARTING, SOUP_MESSAGE_FINISHING, SOUP_MESSAGE_FINISHED diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index fe1a9746..15e087a8 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -29,7 +29,6 @@ #include "soup-request-http.h" #include "soup.h" -#include "soup-cache-private.h" #include "soup-message-private.h" #include "soup-session-private.h" @@ -256,20 +255,6 @@ soup_request_http_send (SoupRequest *request, } -typedef struct { - SoupMessage *original; - GInputStream *stream; -} SendAsyncData; - -static void -free_send_async_data (SendAsyncData *sadata) -{ - g_clear_object (&sadata->stream); - g_clear_object (&sadata->original); - - g_slice_free (SendAsyncData, sadata); -} - static void http_input_stream_ready_cb (GObject *source, GAsyncResult *result, gpointer user_data) { @@ -285,59 +270,6 @@ http_input_stream_ready_cb (GObject *source, GAsyncResult *result, gpointer user g_object_unref (task); } -static void -conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) -{ - GTask *task = user_data; - SoupRequestHTTP *http = g_task_get_source_object (task); - SendAsyncData *sadata = g_task_get_task_data (task); - GInputStream *stream; - - if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { - SoupCache *cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); - - stream = soup_cache_send_response (cache, sadata->original); - if (stream) { - soup_message_got_headers (sadata->original); - soup_message_finished (sadata->original); - - http->priv->content_type = g_strdup (soup_message_headers_get_content_type (msg->response_headers, NULL)); - - g_task_return_pointer (task, stream, g_object_unref); - g_object_unref (task); - return; - } - } - - /* The resource was modified or the server returned a 200 - * OK. Either way we reload it. This is far from optimal as - * we're donwloading the resource twice, but we will change it - * once the cache is integrated in the streams stack. - */ - soup_session_send_request_async (session, sadata->original, - g_task_get_cancellable (task), - http_input_stream_ready_cb, task); -} - -static gboolean -idle_return_from_cache_cb (gpointer data) -{ - GTask *task = data; - SoupRequestHTTP *http = g_task_get_source_object (task); - SendAsyncData *sadata = g_task_get_task_data (task); - - /* Issue signals */ - soup_message_got_headers (http->priv->msg); - soup_message_finished (http->priv->msg); - - http->priv->content_type = g_strdup (soup_message_headers_get_content_type (http->priv->msg->response_headers, NULL)); - - g_task_return_pointer (task, g_object_ref (sadata->stream), g_object_unref); - g_object_unref (task); - - return FALSE; -} - static void soup_request_http_send_async (SoupRequest *request, GCancellable *cancellable, @@ -347,55 +279,12 @@ soup_request_http_send_async (SoupRequest *request, SoupRequestHTTP *http = SOUP_REQUEST_HTTP (request); SoupSession *session = soup_request_get_session (request); GTask *task; - SendAsyncData *sadata; - GInputStream *stream; - SoupCache *cache; g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); http->priv->sent = TRUE; task = g_task_new (request, cancellable, callback, user_data); - sadata = g_slice_new0 (SendAsyncData); - g_task_set_task_data (task, sadata, (GDestroyNotify)free_send_async_data); - - cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); - - if (cache) { - SoupCacheResponse response; - - response = soup_cache_has_response (cache, http->priv->msg); - if (response == SOUP_CACHE_RESPONSE_FRESH) { - stream = soup_cache_send_response (cache, http->priv->msg); - - /* Cached resource file could have been deleted outside */ - if (stream) { - /* Do return the stream asynchronously as in - * the other cases. It's not enough to let - * GTask do the asynchrony for us, because - * the signals must be also emitted - * asynchronously - */ - sadata->stream = stream; - soup_add_completion (soup_session_get_async_context (session), - idle_return_from_cache_cb, task); - return; - } - } else if (response == SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) { - SoupMessage *conditional_msg; - - conditional_msg = soup_cache_generate_conditional_request (cache, http->priv->msg); - - if (conditional_msg) { - sadata->original = g_object_ref (http->priv->msg); - soup_session_queue_message (session, conditional_msg, - conditional_get_ready_cb, - task); - return; - } - } - } - soup_session_send_request_async (session, http->priv->msg, cancellable, http_input_stream_ready_cb, task); } diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index f44bf8e1..cfcadb27 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -14,6 +14,7 @@ #include "soup-session.h" #include "soup.h" #include "soup-auth-manager-ntlm.h" +#include "soup-cache-private.h" #include "soup-connection.h" #include "soup-marshal.h" #include "soup-message-private.h" @@ -1780,6 +1781,10 @@ soup_session_process_queue_item (SoupSession *session, item->state = SOUP_MESSAGE_FINISHING; break; + case SOUP_MESSAGE_CACHED: + /* Will be handled elsewhere */ + return; + case SOUP_MESSAGE_RESTARTING: item->state = SOUP_MESSAGE_STARTING; soup_message_restarted (item->msg); @@ -3551,6 +3556,121 @@ async_send_request_running (SoupSession *session, SoupMessageQueueItem *item) try_run_until_read (item); } +static void +async_return_from_cache (SoupMessageQueueItem *item, + GInputStream *stream) +{ + const char *content_type; + GHashTable *params; + + soup_message_got_headers (item->msg); + + content_type = soup_message_headers_get_content_type (item->msg->response_headers, ¶ms); + soup_message_content_sniffed (item->msg, content_type, params); + g_hash_table_unref (params); + + item->state = SOUP_MESSAGE_FINISHING; + async_send_request_return_result (item, g_object_ref (stream), NULL); +} + +static void +conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + SoupMessageQueueItem *item = user_data; + GInputStream *stream; + + if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { + SoupCache *cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); + + stream = soup_cache_send_response (cache, item->msg); + if (stream) { + async_return_from_cache (item, stream); + g_object_unref (stream); + return; + } + } + + /* The resource was modified or the server returned a 200 + * OK. Either way we reload it. FIXME. + */ + item->state = SOUP_MESSAGE_STARTING; + soup_session_kick_queue (session); +} + +typedef struct { + SoupMessageQueueItem *item; + GInputStream *stream; +} SendAsyncCacheData; + +static void +free_send_async_cache_data (SendAsyncCacheData *sacd) +{ + soup_message_queue_item_unref (sacd->item); + g_object_unref (sacd->stream); + g_slice_free (SendAsyncCacheData, sacd); +} + +static gboolean +idle_return_from_cache_cb (gpointer data) +{ + GTask *task = data; + SendAsyncCacheData *sacd = g_task_get_task_data (task); + + async_return_from_cache (sacd->item, sacd->stream); + return FALSE; +} + +static gboolean +async_respond_from_cache (SoupSession *session, + SoupMessageQueueItem *item) +{ + SoupCache *cache; + SoupCacheResponse response; + + cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); + if (!cache) + return FALSE; + + response = soup_cache_has_response (cache, item->msg); + if (response == SOUP_CACHE_RESPONSE_FRESH) { + GInputStream *stream; + SendAsyncCacheData *sacd; + GSource *source; + + stream = soup_cache_send_response (cache, item->msg); + if (!stream) { + /* Cached file was deleted? */ + return FALSE; + } + + sacd = g_slice_new (SendAsyncCacheData); + sacd->item = item; + soup_message_queue_item_ref (item); + sacd->stream = stream; + + g_task_set_task_data (item->task, sacd, + (GDestroyNotify) free_send_async_cache_data); + + source = g_timeout_source_new (0); + g_task_attach_source (item->task, source, + (GSourceFunc) idle_return_from_cache_cb); + g_source_unref (source); + return TRUE; + } else if (response == SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) { + SoupMessage *conditional_msg; + + conditional_msg = soup_cache_generate_conditional_request (cache, item->msg); + if (!conditional_msg) + return FALSE; + + soup_session_queue_message (session, conditional_msg, + conditional_get_ready_cb, + item); + return TRUE; + } else + return FALSE; +} + void soup_session_send_request_async (SoupSession *session, SoupMessage *msg, @@ -3585,7 +3705,10 @@ soup_session_send_request_async (SoupSession *session, item->cancellable = g_object_ref (cancellable); } - soup_session_kick_queue (session); + if (async_respond_from_cache (session, item)) + item->state = SOUP_MESSAGE_CACHED; + else + soup_session_kick_queue (session); } GInputStream * -- cgit v1.2.1 From fb30256920503cc5e4dc33210921a2ee2a9ff7c8 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Thu, 27 Dec 2012 00:50:21 +0200 Subject: Updated Hebrew translation. --- po/he.po | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/po/he.po b/po/he.po index a8467128..72bac9e4 100644 --- a/po/he.po +++ b/po/he.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup gnome\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-22 15:16+0300\n" -"PO-Revision-Date: 2012-09-22 15:17+0200\n" +"POT-Creation-Date: 2012-12-27 00:49+0200\n" +"PO-Revision-Date: 2012-12-27 00:50+0200\n" "Last-Translator: Yaron Shahrabani \n" "Language-Team: Hebrew \n" "Language: \n" @@ -35,40 +35,61 @@ msgstr "בקשת חיפוש שגויה" msgid "Cannot truncate SoupBodyInputStream" msgstr "לא ניתן לקצץ את SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "תזרים הרשת נסגר בפתאומיות" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "אוגר הפלט קטן מדי" -#: ../libsoup/soup-message-io.c:818 -#: ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "לא ניתן לנתח את תגובת ה־HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "קידוד תגובת ה־HTTP אינו מוכר" + +#: ../libsoup/soup-message-io.c:846 +#: ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "הפעולה בוטלה" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "הפעולה תיחסם" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "לא ניתן לנתח את תגובת ה־HTTP" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "לא סופקה כתובת" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "כתובת '%s' שגויה: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3875 #, c-format msgid "Could not parse URI '%s'" msgstr "לא ניתן לנתח את הכתובת '%s'" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3912 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "תבנית הכתובת אינה נתמכת '%s'" +#: ../libsoup/soup-session.c:3934 +#, c-format +msgid "Not an HTTP URI" +msgstr "כתובת שאינה HTTP" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "שם המארח הוא כתובת IP" -- cgit v1.2.1 From 0aeb67d4934d2748002349669caeffe481dd5a11 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 27 Dec 2012 21:13:34 -0500 Subject: docs: Lots of minor fixes and additions --- docs/reference/Makefile.am | 6 ++-- docs/reference/client-howto.xml | 15 +++------ docs/reference/libsoup-2.4-sections.txt | 54 +++++++++++++++++++++++++++------ libsoup/soup-address.c | 4 +++ libsoup/soup-auth-basic.c | 11 +++++++ libsoup/soup-auth-digest.c | 11 +++++++ libsoup/soup-auth-ntlm.c | 11 +++++++ libsoup/soup-cache.c | 43 ++++++++++++++++++++++++++ libsoup/soup-cookie-jar.c | 3 ++ libsoup/soup-date.c | 14 ++++----- libsoup/soup-logger.c | 2 +- libsoup/soup-message-body.c | 4 +++ libsoup/soup-message.c | 13 ++++---- libsoup/soup-multipart-input-stream.c | 4 +-- libsoup/soup-multipart-input-stream.h | 2 +- libsoup/soup-request-http.c | 28 +++++++++++++++++ libsoup/soup-request.c | 28 +++++++++++++++++ libsoup/soup-session.c | 8 ++--- libsoup/soup-socket.c | 11 +++++++ libsoup/soup-tld.c | 39 +++++++++++++++++++++--- libsoup/soup-uri.c | 51 +++++++++++++++++++++++++++++++ libsoup/soup-version.c | 2 ++ 22 files changed, 315 insertions(+), 49 deletions(-) diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 2e2a8af6..9dbadb30 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -13,7 +13,7 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml DOC_SOURCE_DIR=../../libsoup # Extra options to supply to gtkdoc-scan. -SCAN_OPTIONS=--deprecated-guards=LIBSOUP_DISABLE_DEPRECATED --rebuild-types +SCAN_OPTIONS=--rebuild-types # Extra options to supply to gtkdoc-scangobj. SCANGOBJ_OPTIONS= @@ -41,7 +41,9 @@ IGNORE_HFILES= soup.h soup-marshal.h soup-enum-types.h \ soup-body-input-stream.h soup-body-output-stream.h \ soup-client-input-stream.h soup-content-processor.h \ soup-content-sniffer-stream.h soup-io-stream.h \ - soup-filter-input-stream.h + soup-cache-input-stream.h soup-filter-input-stream.h \ + soup-cookie-jar-sqlite.h soup-requester.h soup-tld-private.h \ + soup-misc-private.h # Images to copy into HTML directory. HTML_IMAGES = diff --git a/docs/reference/client-howto.xml b/docs/reference/client-howto.xml index a53f2ac3..3cf5a4e1 100644 --- a/docs/reference/client-howto.xml +++ b/docs/reference/client-howto.xml @@ -164,22 +164,15 @@ functions. Some of the features available in track of cookies between sessions. - - - -And in libsoup-gnome: - - - - SoupProxyResolverGNOME + SoupProxyResolverDefault A feature that automatically determines the correct HTTP proxy to use for requests. - SoupCookieJarSqlite + SoupCookieJarDB Support for HTTP cookies stored in an SQLite database. @@ -190,7 +183,7 @@ And in libsoup-gnome: Use the "add_feature_by_type" property/function to add features that don't require any configuration (such as SoupProxyResolverGNOME), +linkend="SoupProxyResolverDefault">SoupProxyResolverDefault), and the "add_feature" property/function to add features that must be constructed first (such as SoupLogger). For example, an @@ -200,7 +193,7 @@ application might do something like the following: session = soup_session_async_new_with_options ( #ifdef HAVE_LIBSOUP_GNOME - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_GNOME, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT, #endif NULL); if (debug_level) { diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index b2952fd0..23f55c0f 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -371,6 +371,7 @@ SOUP_ADDRESS_NAME SOUP_ADDRESS_PHYSICAL SOUP_ADDRESS_PORT SOUP_ADDRESS_SOCKADDR +SOUP_ADDRESS_PROTOCOL SOUP_ADDRESS SOUP_IS_ADDRESS @@ -583,6 +584,7 @@ soup_socket_is_connected soup_socket_get_local_address soup_socket_get_remote_address +soup_socket_get_fd SoupSocketIOStatus soup_socket_read @@ -611,12 +613,6 @@ SOUP_SOCKET_CLASS SOUP_IS_SOCKET_CLASS SOUP_SOCKET_GET_CLASS SoupSocketClass - -soup_socket_get_fd -soup_socket_handshake_async -soup_socket_handshake_sync -soup_socket_get_gsocket -soup_socket_get_iostream
@@ -669,8 +665,6 @@ soup_uri_get_fragment SOUP_TYPE_URI soup_uri_get_type - -uri_decoded_copy
@@ -718,8 +712,6 @@ soup_add_completion soup_add_idle soup_add_io_watch soup_add_timeout - -soup_ssl_supported soup_date_copy SOUP_TYPE_DATE @@ -734,6 +726,7 @@ SOUP_CHAR_HTTP_SEPARATOR SOUP_CHAR_URI_GEN_DELIMS SOUP_CHAR_URI_PERCENT_ENCODED SOUP_CHAR_URI_SUB_DELIMS +soup_ssl_supported
@@ -950,8 +943,14 @@ soup_multipart_input_stream_next_part soup_multipart_input_stream_next_part_async soup_multipart_input_stream_next_part_finish +SOUP_IS_MULTIPART_INPUT_STREAM +SOUP_IS_MULTIPART_INPUT_STREAM_CLASS +SOUP_MULTIPART_INPUT_STREAM +SOUP_MULTIPART_INPUT_STREAM_CLASS +SOUP_MULTIPART_INPUT_STREAM_GET_CLASS SOUP_TYPE_MULTIPART_INPUT_STREAM soup_multipart_input_stream_get_type +SoupMultipartInputStreamPrivate
@@ -1014,6 +1013,7 @@ soup_proxy_uri_resolver_get_type SoupContentSniffer soup_content_sniffer_new soup_content_sniffer_sniff +soup_content_sniffer_get_buffer_size SOUP_CONTENT_SNIFFER SOUP_CONTENT_SNIFFER_CLASS @@ -1213,4 +1213,38 @@ SOUP_VERSION_2_36 SOUP_VERSION_2_38 SOUP_VERSION_2_40 SOUP_VERSION_2_42 + +SOUP_AVAILABLE_IN_2_24 +SOUP_AVAILABLE_IN_2_26 +SOUP_AVAILABLE_IN_2_28 +SOUP_AVAILABLE_IN_2_30 +SOUP_AVAILABLE_IN_2_32 +SOUP_AVAILABLE_IN_2_34 +SOUP_AVAILABLE_IN_2_36 +SOUP_AVAILABLE_IN_2_38 +SOUP_AVAILABLE_IN_2_40 +SOUP_AVAILABLE_IN_2_42 +SOUP_DEPRECATED_IN_2_24 +SOUP_DEPRECATED_IN_2_24_FOR +SOUP_DEPRECATED_IN_2_26 +SOUP_DEPRECATED_IN_2_26_FOR +SOUP_DEPRECATED_IN_2_28 +SOUP_DEPRECATED_IN_2_28_FOR +SOUP_DEPRECATED_IN_2_30 +SOUP_DEPRECATED_IN_2_30_FOR +SOUP_DEPRECATED_IN_2_32 +SOUP_DEPRECATED_IN_2_32_FOR +SOUP_DEPRECATED_IN_2_34 +SOUP_DEPRECATED_IN_2_34_FOR +SOUP_DEPRECATED_IN_2_36 +SOUP_DEPRECATED_IN_2_36_FOR +SOUP_DEPRECATED_IN_2_38 +SOUP_DEPRECATED_IN_2_38_FOR +SOUP_DEPRECATED_IN_2_40 +SOUP_DEPRECATED_IN_2_40_FOR +SOUP_DEPRECATED_IN_2_42 +SOUP_DEPRECATED_IN_2_42_FOR +SOUP_ENCODE_VERSION +SOUP_VERSION_CUR_STABLE +SOUP_VERSION_PREV_STABLE
diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index 82beb1ea..e1696fb0 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -22,6 +22,10 @@ * #SoupAddress represents the address of a TCP connection endpoint: * both the IP address and the port. (It is somewhat like an * object-oriented version of struct sockaddr.) + * + * Although #SoupAddress is still used in some libsoup API's, it + * should not be used in new code; use GLib's #GNetworkAddress or + * #GSocketAddress instead. **/ enum { diff --git a/libsoup/soup-auth-basic.c b/libsoup/soup-auth-basic.c index fb491c71..fefe1c7e 100644 --- a/libsoup/soup-auth-basic.c +++ b/libsoup/soup-auth-basic.c @@ -19,6 +19,17 @@ typedef struct { } SoupAuthBasicPrivate; #define SOUP_AUTH_BASIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_BASIC, SoupAuthBasicPrivate)) +/** + * SOUP_TYPE_AUTH_BASIC: + * + * A #GType corresponding to HTTP "Basic" authentication. + * #SoupSessions support this by default; if you want to disable + * support for it, call soup_session_remove_feature_by_type(), + * passing %SOUP_TYPE_AUTH_BASIC. + * + * Since: 2.34 + */ + G_DEFINE_TYPE (SoupAuthBasic, soup_auth_basic, SOUP_TYPE_AUTH) static void diff --git a/libsoup/soup-auth-digest.c b/libsoup/soup-auth-digest.c index 97ef5616..b95a996f 100644 --- a/libsoup/soup-auth-digest.c +++ b/libsoup/soup-auth-digest.c @@ -40,6 +40,17 @@ typedef struct { static void recompute_hex_a1 (SoupAuthDigestPrivate *priv); +/** + * SOUP_TYPE_AUTH_DIGEST: + * + * A #GType corresponding to HTTP "Digest" authentication. + * #SoupSessions support this by default; if you want to disable + * support for it, call soup_session_remove_feature_by_type(), + * passing %SOUP_TYPE_AUTH_DIGEST. + * + * Since: 2.34 + */ + G_DEFINE_TYPE (SoupAuthDigest, soup_auth_digest, SOUP_TYPE_AUTH) static void diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index 391c1c28..dc24d51f 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -19,6 +19,17 @@ typedef struct { } SoupAuthNTLMPrivate; #define SOUP_AUTH_NTLM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMPrivate)) +/** + * SOUP_TYPE_AUTH_NTLM: + * + * A #GType corresponding to HTTP-based NTLM authentication. + * #SoupSessions do not support this type by default; if you want to + * enable support for it, call soup_session_add_feature_by_type(), + * passing %SOUP_TYPE_AUTH_NTLM. + * + * Since: 2.34 + */ + G_DEFINE_TYPE (SoupAuthNTLM, soup_auth_ntlm, SOUP_TYPE_AUTH) static void diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 7130c5ce..6df16655 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -1238,6 +1238,9 @@ force_flush_timeout (gpointer data) * committed to disk. For doing so it will iterate the #GMainContext * associated with @cache's session as long as needed. * + * Contrast with soup_cache_dump(), which writes out the cache index + * file. + * * Since: 2.34 */ void @@ -1402,6 +1405,19 @@ pack_entry (gpointer data, g_variant_builder_close (entries_builder); /* SOUP_CACHE_PHEADERS_FORMAT */ } +/** + * soup_cache_dump: + * @cache: a #SoupCache + * + * Synchronously writes the cache index out to disk. Contrast with + * soup_cache_flush(), which writes pending cache + * entries to disk. + * + * You must call this before exiting if you want your cache data to + * persist between sessions. + * + * Since: 2.34. + */ void soup_cache_dump (SoupCache *cache) { @@ -1430,6 +1446,14 @@ soup_cache_dump (SoupCache *cache) g_variant_unref (cache_variant); } +/** + * soup_cache_load: + * @cache: a #SoupCache + * + * Loads the contents of @cache's index into memory. + * + * Since: 2.34 + */ void soup_cache_load (SoupCache *cache) { @@ -1507,6 +1531,15 @@ soup_cache_load (SoupCache *cache) g_variant_unref (cache_variant); } +/** + * soup_cache_set_max_size: + * @cache: a #SoupCache + * @max_size: the maximum size of the cache, in bytes + * + * Sets the maximum size of the cache. + * + * Since: 2.34 + */ void soup_cache_set_max_size (SoupCache *cache, guint max_size) @@ -1515,6 +1548,16 @@ soup_cache_set_max_size (SoupCache *cache, cache->priv->max_entry_data_size = cache->priv->max_size / MAX_ENTRY_DATA_PERCENTAGE; } +/** + * soup_cache_get_max_size: + * @cache: a #SoupCache + * + * Gets the maximum size of the cache. + * + * Return value: the maximum size of the cache, in bytes. + * + * Since: 2.34 + */ guint soup_cache_get_max_size (SoupCache *cache) { diff --git a/libsoup/soup-cookie-jar.c b/libsoup/soup-cookie-jar.c index 80bb8327..38ddf923 100644 --- a/libsoup/soup-cookie-jar.c +++ b/libsoup/soup-cookie-jar.c @@ -795,6 +795,9 @@ soup_cookie_jar_delete_cookie (SoupCookieJar *jar, * document. If no first party is set in a message when this policy is * in effect, cookies will be assumed to be third party by default. * + * The policy for accepting or rejecting cookies returned in + * responses. + * * Since: 2.30 */ diff --git a/libsoup/soup-date.c b/libsoup/soup-date.c index 16988f41..d3dcf6f4 100644 --- a/libsoup/soup-date.c +++ b/libsoup/soup-date.c @@ -188,7 +188,7 @@ soup_date_new (int year, int month, int day, * offset_seconds is 0, returns the current time. * * If @offset_seconds would indicate a time not expressible as a - * #time_t, the return value will be clamped into range. + * time_t, the return value will be clamped into range. * * Return value: a new #SoupDate **/ @@ -525,7 +525,7 @@ soup_date_new_from_string (const char *date_string) /** * soup_date_new_from_time_t: - * @when: a #time_t + * @when: a time_t * * Creates a #SoupDate corresponding to @when * @@ -680,13 +680,13 @@ soup_date_to_string (SoupDate *date, SoupDateFormat format) * soup_date_to_time_t: * @date: a #SoupDate * - * Converts @date to a %time_t. + * Converts @date to a time_t. * - * If @date is not representable as a %time_t, it will be clamped into - * range. (In particular, some HTTP cookies have expiration dates - * after "Y2.038k" (2038-01-19T03:14:07Z).) + * If @date is not representable as a time_t, it will be + * clamped into range. (In particular, some HTTP cookies have + * expiration dates after "Y2.038k" (2038-01-19T03:14:07Z).) * - * Return value: @date as a %time_t + * Return value: @date as a time_t **/ time_t soup_date_to_time_t (SoupDate *date) diff --git a/libsoup/soup-logger.c b/libsoup/soup-logger.c index a9f49bfb..52d74cda 100644 --- a/libsoup/soup-logger.c +++ b/libsoup/soup-logger.c @@ -52,7 +52,7 @@ * * * The Soup-Debug-Timestamp line gives the time (as - * a #time_t) when the request was sent, or the response fully + * a time_t) when the request was sent, or the response fully * received. * * The Soup-Debug line gives further debugging diff --git a/libsoup/soup-message-body.c b/libsoup/soup-message-body.c index c541887f..dfc29fae 100644 --- a/libsoup/soup-message-body.c +++ b/libsoup/soup-message-body.c @@ -313,6 +313,10 @@ soup_buffer_free (SoupBuffer *buffer) * soup_buffer_get_as_bytes: * @buffer: a #SoupBuffer * + * Creates a #GBytes pointing to the same memory as @buffer. The + * #GBytes will hold a reference on @buffer to ensure that it is not + * freed while the #GBytes is still valid. + * * Returns: (transfer full): a new #GBytes which has the same content * as the #SoupBuffer. * diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 6c62b27d..badcd166 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1623,12 +1623,13 @@ soup_message_set_status_full (SoupMessage *msg, * destroyed * * Sets an alternate chunk-allocation function to use when reading - * @msg's body when using the traditional (ie, non-#SoupRequest-based) - * API. Every time data is available to read, libsoup will call - * @allocator, which should return a #SoupBuffer. (See - * #SoupChunkAllocator for additional details.) Libsoup will then read - * data from the network into that buffer, and update the buffer's - * length to indicate how much data it read. + * @msg's body when using the traditional (ie, + * non-#SoupRequest-based) API. Every time data is available + * to read, libsoup will call @allocator, which should return a + * #SoupBuffer. (See #SoupChunkAllocator for additional details.) + * Libsoup will then read data from the network into that buffer, and + * update the buffer's length to indicate how much + * data it read. * * Generally, a custom chunk allocator would be used in conjunction * with soup_message_body_set_accumulate() %FALSE and diff --git a/libsoup/soup-multipart-input-stream.c b/libsoup/soup-multipart-input-stream.c index 9cd1b3af..dee4e59f 100644 --- a/libsoup/soup-multipart-input-stream.c +++ b/libsoup/soup-multipart-input-stream.c @@ -508,14 +508,12 @@ soup_multipart_input_stream_next_part_thread (GTask *task, * @io_priority: the I/O priority for the request. * @cancellable: a #GCancellable. * @callback: callback to call when request is satisfied. + * @data: data for @callback * * Obtains a #GInputStream for the next request. See * soup_multipart_input_stream_next_part() for details on the * workflow. * - * Return value: a new #GInputStream, or %NULL if there are no more - * parts - * * Since: 2.40 */ void diff --git a/libsoup/soup-multipart-input-stream.h b/libsoup/soup-multipart-input-stream.h index 20cdefdf..8b735063 100644 --- a/libsoup/soup-multipart-input-stream.h +++ b/libsoup/soup-multipart-input-stream.h @@ -54,7 +54,7 @@ void soup_multipart_input_stream_next_part_async (SoupMult SOUP_AVAILABLE_IN_2_40 GInputStream *soup_multipart_input_stream_next_part_finish (SoupMultipartInputStream *multipart, - GAsyncResult *res, + GAsyncResult *result, GError **error); SOUP_AVAILABLE_IN_2_40 diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index 15e087a8..871ca0ea 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -34,6 +34,25 @@ G_DEFINE_TYPE (SoupRequestHTTP, soup_request_http, SOUP_TYPE_REQUEST) +/** + * SoupRequestHTTP: + * @method: the HTTP method + * @request_uri: the request URI + * @request_version: the HTTP version of the request + * @request_headers: the request headers + * @status_code: the HTTP status code + * @reason_phrase: the status phrase associated with @status_code + * @response_version: the HTTP version of the response + * @response_headers: the response headers + * + * Represents an HTTP message being sent or received via the + * #SoupRequest API. The fields on this object reflect the values on + * the request's underlying #SoupMessage; see the #SoupMessage + * documentation for more information. + * + * Since: 2.42 + */ + enum { PROP_0, @@ -575,6 +594,15 @@ soup_request_http_get_message (SoupRequestHTTP *http) return g_object_ref (http->priv->msg); } +/** + * soup_request_http_set_method: + * @http: a #SoupRequestHTTP + * @method: the HTTP method + * + * Sets @http to use @method as its request method. + * + * Since: 2.42 + */ void soup_request_http_set_method (SoupRequestHTTP *http, const char *method) diff --git a/libsoup/soup-request.c b/libsoup/soup-request.c index 5fd4a02a..02d0ca47 100644 --- a/libsoup/soup-request.c +++ b/libsoup/soup-request.c @@ -282,6 +282,20 @@ soup_request_class_init (SoupRequestClass *request_class) object_class->set_property = soup_request_set_property; object_class->get_property = soup_request_get_property; + /** + * SOUP_REQUEST_URI: + * + * Alias for the #SoupRequest:uri property, qv. + * + * Since: 2.42 + */ + /** + * SoupRequest:uri: + * + * The request URI. + * + * Since: 2.42 + */ g_object_class_install_property ( object_class, PROP_URI, g_param_spec_boxed (SOUP_REQUEST_URI, @@ -289,6 +303,20 @@ soup_request_class_init (SoupRequestClass *request_class) "The request URI", SOUP_TYPE_URI, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * SOUP_REQUEST_SESSION: + * + * Alias for the #SoupRequest:session property, qv. + * + * Since: 2.42 + */ + /** + * SoupRequest:session: + * + * The request's #SoupSession. + * + * Since: 2.42 + */ g_object_class_install_property ( object_class, PROP_SESSION, g_param_spec_object (SOUP_REQUEST_SESSION, diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index cfcadb27..43e5f6be 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -2956,7 +2956,7 @@ soup_session_class_init (SoupSessionClass *session_class) NULL, G_PARAM_READWRITE | G_PARAM_DEPRECATED)); /** - * SOUP_SESSION_USE_SYSTEM_CA_FILE: + * SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE: * * Alias for the #SoupSession:ssl-use-system-ca-file property, * qv. @@ -3027,8 +3027,8 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SoupSession:ssl-strict: * - * Normally, if #SoupSession:tlsdb is set (including if it was - * set via #SoupSession:ssl-use-system-ca-file or + * Normally, if #SoupSession:tls-database is set (including if + * it was set via #SoupSession:ssl-use-system-ca-file or * #SoupSession:ssl-ca-file), then libsoup will reject any * certificate that is invalid (ie, expired) or that is not * signed by one of the given CA certificates, and the @@ -4010,7 +4010,7 @@ soup_session_request_http_uri (SoupSession *session, /** * SOUP_REQUEST_ERROR: * - * A #GError domain for #SoupRequest-related errors. Used with + * A #GError domain for #SoupRequest-related errors. Used with * #SoupRequestError. * * Since: 2.42 diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index cd4bf761..6b485bab 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -836,6 +836,17 @@ soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable) return socket_connected (sock, conn, error); } +/** + * soup_socket_get_fd: + * @sock: a #SoupSocket + * + * Gets @sock's underlying file descriptor. + * + * Note that fiddling with the file descriptor may break the + * #SoupSocket. + * + * Return value: @sock's file descriptor. + */ int soup_socket_get_fd (SoupSocket *sock) { diff --git a/libsoup/soup-tld.c b/libsoup/soup-tld.c index 5fdb44a0..c6faed13 100644 --- a/libsoup/soup-tld.c +++ b/libsoup/soup-tld.c @@ -17,6 +17,15 @@ #include "soup.h" #include "soup-tld-private.h" +/** + * SECTION:soup-tld + * @short_description: Top-Level Domain Utilities + * + * These functions can be used to parse hostnames to attempt to determine + * what part of the name belongs to the domain owner, and what part is + * simply a "public suffix" such as ".com". + */ + static void soup_tld_ensure_rules_hash_table (void); static const char *soup_tld_get_base_domain_internal (const char *hostname, guint additional_domains, @@ -27,8 +36,7 @@ static SoupTLDEntry tld_entries[] = { #include "tld_data.inc" }; -/** - * Stores the entries data in a hash table to ease and speed up +/* Stores the entries data in a hash table to ease and speed up * searches. */ static void @@ -49,7 +57,6 @@ soup_tld_ensure_rules_hash_table (void) /** * soup_tld_get_base_domain: - * @tld: a #SoupTLD * @hostname: a UTF-8 hostname in its canonical representation form * @error: return location for a #GError, or %NULL to ignore * errors. See #SoupTLDError for the available error codes @@ -83,7 +90,6 @@ soup_tld_get_base_domain (const char *hostname, GError **error) /** * soup_tld_domain_is_public_suffix: - * @tld: a #SoupTLD * @domain: a UTF-8 domain in its canonical representation form * * Looks whether the @domain passed as argument is a public domain @@ -131,6 +137,31 @@ soup_tld_domain_is_public_suffix (const char *domain) return TRUE; } +/** + * SOUP_TLD_ERROR: + * + * The #GError domain for soup-tld-related errors. + * + * Since: 2.40 + */ +/** + * SoupTLDError: + * @SOUP_TLD_ERROR_INVALID_HOSTNAME: A hostname was syntactically + * invalid. + * @SOUP_TLD_ERROR_IS_IP_ADDRESS: The passed-in "hostname" was + * actually an IP address (and thus has no base domain or + * public suffix). + * @SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS: The passed-in hostname + * did not have enough components. Eg, calling + * soup_tld_get_base_domain() on "co.uk". + * @SOUP_TLD_ERROR_NO_BASE_DOMAIN: The passed-in hostname has + * no recognized public suffix. + * + * Error codes for %SOUP_TLD_ERROR. + * + * Since: 2.40 + */ + GQuark soup_tld_error_quark (void) { diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index c1d5720f..28b3025c 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -105,6 +105,57 @@ * Since: 2.24 **/ +/** + * SOUP_URI_SCHEME_HTTP: + * + * "http" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + */ +/** + * SOUP_URI_SCHEME_HTTPS: + * + * "https" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + */ +/** + * SOUP_URI_SCHEME_FTP: + * + * "ftp" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + * + * Since: 2.30 + */ +/** + * SOUP_URI_SCHEME_FILE: + * + * "file" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + * + * Since: 2.30 + */ +/** + * SOUP_URI_SCHEME_DATA: + * + * "data" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + * + * Since: 2.30 + */ +/** + * SOUP_URI_SCHEME_RESOURCE: + * + * "data" as an interned string; you can compare this directly to a + * #SoupURI's scheme field using + * ==. + * + * Since: 2.42 + */ + static void append_uri_encoded (GString *str, const char *in, const char *extra_enc_chars); static char *uri_normalized_copy (const char *str, int length, const char *unescape_extra); diff --git a/libsoup/soup-version.c b/libsoup/soup-version.c index 84c146eb..8a0fa929 100644 --- a/libsoup/soup-version.c +++ b/libsoup/soup-version.c @@ -52,6 +52,8 @@ * @minor: minor version (e.g. 42 for version 2.42.0) * @micro: micro version (e.g. 0 for version 2.42.0) * + * Macro to test the version of libsoup being compiled against. + * * Returns: %TRUE if the version of the libsoup header files * is the same as or newer than the passed-in version. * -- cgit v1.2.1 From 360a32a81904ce6f662de420cfa57961f2726d14 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 28 Dec 2012 10:32:30 -0500 Subject: docs: more fixes --- docs/reference/Makefile.am | 2 +- docs/reference/build-howto.xml | 73 +++++++++++++++++---------------- docs/reference/libsoup-2.4-sections.txt | 1 - libsoup/soup-cache.c | 7 ++++ libsoup/soup-proxy-resolver-default.c | 7 ++-- libsoup/soup-proxy-uri-resolver.c | 12 ++++++ libsoup/soup-request-data.c | 7 ++++ libsoup/soup-request-file.c | 8 ++++ libsoup/soup-request-http.c | 12 ++++++ libsoup/soup-session.h | 2 +- libsoup/soup-value-utils.c | 2 +- 11 files changed, 90 insertions(+), 43 deletions(-) diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 9dbadb30..019746b3 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -13,7 +13,7 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml DOC_SOURCE_DIR=../../libsoup # Extra options to supply to gtkdoc-scan. -SCAN_OPTIONS=--rebuild-types +SCAN_OPTIONS=--rebuild-types --ignore-decorators='SOUP_DEPRECATED\w*\s*\([^)]*\)|SOUP_DEPRECATED\w*|SOUP_AVAILABLE\w*' # Extra options to supply to gtkdoc-scangobj. SCANGOBJ_OPTIONS= diff --git a/docs/reference/build-howto.xml b/docs/reference/build-howto.xml index 975dfd55..bec9a454 100644 --- a/docs/reference/build-howto.xml +++ b/docs/reference/build-howto.xml @@ -35,41 +35,52 @@ that first appeared in version 2.4") and is essentially just part of the package name. + + + +API Availability and Deprecation Warnings + -If you are using any of the GNOME-specific features of -libsoup (such as automatic proxy -configuration), you must require -"libsoup-gnome-2.4" instead: +If you want to restrict your program to a particular +libsoup version or range of versions, you +can define SOUP_VERSION_MIN_REQUIRED +and/or SOUP_VERSION_MAX_ALLOWED. +Eg: -PKG_CHECK_MODULES(LIBSOUP, [libsoup-gnome-2.4 >= 2.26]) -AC_SUBST(LIBSOUP_CFLAGS) -AC_SUBST(LIBSOUP_LIBS) +LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MIN_REQUIRED=SOUP_VERSION_2_36" +LIBSOUP_CFLAGS="$LIBSOUP_CFLAGS -DSOUP_VERSION_MAX_ALLOWED=SOUP_VERSION_2_40" -You can also make libsoup-gnome an optional -dependency: +The SOUP_VERSION_MIN_REQUIRED declaration states +that the code is not expected to compile on versions of +libsoup older than the indicated version +(here, 2.36), and so the compiler should print warnings if the code +uses functions that were deprecated as of that release. - -PKG_CHECK_MODULES(LIBSOUP_GNOME, - [libsoup-gnome-2.4 >= 2.26], - [LIBSOUP_CFLAGS="$LIBSOUP_GNOME_CFLAGS" - LIBSOUP_LIBS="$LIBSOUP_GNOME_LIBS" - AC_DEFINE(HAVE_LIBSOUP_GNOME, 1, [Have libsoup-gnome])], - [PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26])]) -AC_SUBST(LIBSOUP_CFLAGS) -AC_SUBST(LIBSOUP_LIBS) - + +The SOUP_VERSION_MAX_ALLOWED declaration states +that the code is expected to compile on versions +of libsoup up to the indicated version +(here, 2.40), and so, when compiling the program against a newer +version than that, the compiler should print warnings if the code uses +functions that did not yet exist in the max-allowed release. + -This will allow the application to be built with either plain -libsoup or with -libsoup-gnome, and it will define the C -preprocessor symbol HAVE_LIBSOUP_GNOME if -libsoup-gnome features are available. +You can use SOUP_CHECK_VERSION +to check the version of libsoup at compile time, to compile different +code for different libsoup versions. (If +you are setting SOUP_VERSION_MIN_REQUIRED and +SOUP_VERSION_MAX_ALLOWED to different versions, as +in the example above, then you almost certainly need to be doing +this.) @@ -86,18 +97,8 @@ Code using libsoup should do: -or, for libsoup-gnome: - - - -#include <libsoup/soup-gnome.h> - - - -Including individual headers besides the two main header files is not -recommended. You may include both soup.h and -soup-gnome.h (though this is not required; the -latter automatically includes the former). +Including individual headers rather than soup.h is not +recommended. diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 23f55c0f..db45167f 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -451,7 +451,6 @@ SOUP_SESSION_GET_CLASS SOUP_TYPE_SESSION SoupSessionClass soup_session_get_type -soup_request_error_get_type soup_request_error_quark SoupConnection diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 6df16655..5569d6b6 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -39,6 +39,13 @@ #include "soup-message-private.h" #include "soup.h" +/** + * SECTION:soup-cache + * @short_description: Caching support + * + * #SoupCache implements a file-based cache for HTTP resources. + */ + static SoupSessionFeatureInterface *soup_cache_default_feature_interface; static void soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); diff --git a/libsoup/soup-proxy-resolver-default.c b/libsoup/soup-proxy-resolver-default.c index 76e9ff6d..0fc8780c 100644 --- a/libsoup/soup-proxy-resolver-default.c +++ b/libsoup/soup-proxy-resolver-default.c @@ -13,10 +13,11 @@ #include "soup.h" /** - * SoupProxyResolverDefault: + * SECTION:soup-proxy-resolver-default + * @short_description: System proxy configuration integration * - * A #SoupProxyURIResolver implementation that uses the default gio - * #GProxyResolver to resolve proxies. + * #SoupProxyResolverDefault is a #SoupProxyURIResolver implementation + * that uses the default gio GProxyResolver to resolve proxies. * * Since: 2.34 */ diff --git a/libsoup/soup-proxy-uri-resolver.c b/libsoup/soup-proxy-uri-resolver.c index 8aecec47..65f65d4b 100644 --- a/libsoup/soup-proxy-uri-resolver.c +++ b/libsoup/soup-proxy-uri-resolver.c @@ -12,6 +12,18 @@ #include "soup-proxy-uri-resolver.h" #include "soup.h" +/** + * SECTION:soup-proxy-uri-resolver + * @short_description: Interface for locating HTTP proxies + * + * #SoupProxyURIResolver is an interface for finding appropriate HTTP + * proxies to use. + * + * You are not likely to have to implement this interface on your own; + * instead, you should usually just be able to use + * #SoupProxyResolverDefault. + */ + G_DEFINE_INTERFACE (SoupProxyURIResolver, soup_proxy_uri_resolver, G_TYPE_OBJECT) static void diff --git a/libsoup/soup-request-data.c b/libsoup/soup-request-data.c index 0ff30c94..66836a5b 100644 --- a/libsoup/soup-request-data.c +++ b/libsoup/soup-request-data.c @@ -31,6 +31,13 @@ #include "soup.h" #include "soup-misc-private.h" +/** + * SECTION:soup-request-data + * @short_description: SoupRequest support for "data" URIs + * + * #SoupRequestData implements #SoupRequest for "data" URIs. + */ + G_DEFINE_TYPE (SoupRequestData, soup_request_data, SOUP_TYPE_REQUEST) struct _SoupRequestDataPrivate { diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c index a71827bb..49b741d0 100644 --- a/libsoup/soup-request-file.c +++ b/libsoup/soup-request-file.c @@ -30,6 +30,14 @@ #include "soup-directory-input-stream.h" #include "soup-requester.h" +/** + * SECTION:soup-request-file + * @short_description: SoupRequest support for "file" and "resource" URIs + * + * #SoupRequestFile implements #SoupRequest for "file" and "resource" + * URIs. + */ + G_DEFINE_TYPE (SoupRequestFile, soup_request_file, SOUP_TYPE_REQUEST) struct _SoupRequestFilePrivate { diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index 871ca0ea..e932217a 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -32,6 +32,18 @@ #include "soup-message-private.h" #include "soup-session-private.h" +/** + * SECTION:soup-request-http + * @short_description: SoupRequest support for "http" and "https" URIs + * + * #SoupRequestHTTP implements #SoupRequest for "http" and "https" + * URIs. + * + * To do more complicated HTTP operations using the #SoupRequest APIs, + * call soup_request_http_get_message() to get the request's + * #SoupMessage. + */ + G_DEFINE_TYPE (SoupRequestHTTP, soup_request_http, SOUP_TYPE_REQUEST) /** diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index ca5060ee..b64fcaeb 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -103,7 +103,7 @@ void soup_session_cancel_message (SoupSession *session, guint status_code); void soup_session_abort (SoupSession *session); -SOUP_AVAILABLE_IN_2_30 +/* SOUP_AVAILABLE_IN_2_30 -- this trips up gtkdoc-scan */ SOUP_DEPRECATED_IN_2_38_FOR (soup_session_prefetch_dns) void soup_session_prepare_for_uri (SoupSession *session, SoupURI *uri); diff --git a/libsoup/soup-value-utils.c b/libsoup/soup-value-utils.c index b929544b..e1f7c92f 100644 --- a/libsoup/soup-value-utils.c +++ b/libsoup/soup-value-utils.c @@ -15,7 +15,7 @@ /** * SECTION:soup-value-utils - * @short_description: #GValue utilities + * @short_description: GValue utilities * * These methods are useful for manipulating #GValues, and in * particular, arrays and hash tables of #GValues, in a -- cgit v1.2.1 From ddfbe30e04c8a9a8981d43b21c27b8bd8336e85b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 28 Dec 2012 10:32:11 -0500 Subject: Add back LIBSOUP_DISABLE_DEPRECATED gtk-doc expects "Deprecated:" notes in docs to be matched up with some deprecation-guard #define. So even though we don't want people to use it any more, add LIBSOUP_DISABLE_DEPRECATED back. --- docs/reference/Makefile.am | 2 +- libsoup/soup-cookie-jar.h | 2 ++ libsoup/soup-logger.h | 2 ++ libsoup/soup-message-headers.h | 2 ++ libsoup/soup-message.h | 2 ++ libsoup/soup-session.h | 2 ++ tests/Makefile.am | 1 - 7 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 019746b3..7e6c180b 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -13,7 +13,7 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml DOC_SOURCE_DIR=../../libsoup # Extra options to supply to gtkdoc-scan. -SCAN_OPTIONS=--rebuild-types --ignore-decorators='SOUP_DEPRECATED\w*\s*\([^)]*\)|SOUP_DEPRECATED\w*|SOUP_AVAILABLE\w*' +SCAN_OPTIONS=--deprecated-guards=LIBSOUP_DISABLE_DEPRECATED --rebuild-types --ignore-decorators='SOUP_DEPRECATED\w*\s*\([^)]*\)|SOUP_DEPRECATED\w*|SOUP_AVAILABLE\w*' # Extra options to supply to gtkdoc-scangobj. SCANGOBJ_OPTIONS= diff --git a/libsoup/soup-cookie-jar.h b/libsoup/soup-cookie-jar.h index 395fbe36..80497368 100644 --- a/libsoup/soup-cookie-jar.h +++ b/libsoup/soup-cookie-jar.h @@ -88,9 +88,11 @@ SoupCookieJarAcceptPolicy soup_cookie_jar_get_accept_policy (SoupCooki SOUP_AVAILABLE_IN_2_40 gboolean soup_cookie_jar_is_persistent (SoupCookieJar *jar); +#ifndef LIBSOUP_DISABLE_DEPRECATED SOUP_AVAILABLE_IN_2_24 SOUP_DEPRECATED_IN_2_26 void soup_cookie_jar_save (SoupCookieJar *jar); +#endif G_END_DECLS diff --git a/libsoup/soup-logger.h b/libsoup/soup-logger.h index a33f3fa6..7cf95c4c 100644 --- a/libsoup/soup-logger.h +++ b/libsoup/soup-logger.h @@ -54,12 +54,14 @@ GType soup_logger_get_type (void); SoupLogger *soup_logger_new (SoupLoggerLogLevel level, int max_body_size); +#ifndef LIBSOUP_DISABLE_DEPRECATED SOUP_DEPRECATED_IN_2_24_FOR(soup_session_add_feature) void soup_logger_attach (SoupLogger *logger, SoupSession *session); SOUP_DEPRECATED_IN_2_24_FOR(soup_session_remove_feature) void soup_logger_detach (SoupLogger *logger, SoupSession *session); +#endif void soup_logger_set_request_filter (SoupLogger *logger, SoupLoggerFilter request_filter, diff --git a/libsoup/soup-message-headers.h b/libsoup/soup-message-headers.h index c6c43d5f..388d75b1 100644 --- a/libsoup/soup-message-headers.h +++ b/libsoup/soup-message-headers.h @@ -36,9 +36,11 @@ void soup_message_headers_clear (SoupMessageHeaders *hdrs); SOUP_AVAILABLE_IN_2_36 void soup_message_headers_clean_connection_headers (SoupMessageHeaders *hdrs); +#ifndef LIBSOUP_DISABLE_DEPRECATED SOUP_DEPRECATED_IN_2_28_FOR ("soup_message_headers_get_one or soup_message_headers_get_list") const char *soup_message_headers_get (SoupMessageHeaders *hdrs, const char *name); +#endif SOUP_AVAILABLE_IN_2_28 const char *soup_message_headers_get_one (SoupMessageHeaders *hdrs, const char *name); diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index f0fbeb37..efcb923a 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -167,6 +167,7 @@ void soup_message_set_redirect (SoupMessage *msg, const char *redirect_uri); /* I/O */ +#ifndef LIBSOUP_DISABLE_DEPRECATED typedef SoupBuffer * (*SoupChunkAllocator) (SoupMessage *msg, gsize max_len, gpointer user_data); @@ -176,6 +177,7 @@ void soup_message_set_chunk_allocator (SoupMessage *msg, SoupChunkAllocator allocator, gpointer user_data, GDestroyNotify destroy_notify); +#endif SOUP_AVAILABLE_IN_2_28 void soup_message_disable_feature (SoupMessage *msg, diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index b64fcaeb..40f1a8d5 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -103,10 +103,12 @@ void soup_session_cancel_message (SoupSession *session, guint status_code); void soup_session_abort (SoupSession *session); +#ifndef LIBSOUP_DISABLE_DEPRECATED /* SOUP_AVAILABLE_IN_2_30 -- this trips up gtkdoc-scan */ SOUP_DEPRECATED_IN_2_38_FOR (soup_session_prefetch_dns) void soup_session_prepare_for_uri (SoupSession *session, SoupURI *uri); +#endif SOUP_AVAILABLE_IN_2_38 void soup_session_prefetch_dns (SoupSession *session, diff --git a/tests/Makefile.am b/tests/Makefile.am index a9184055..cd132bd6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,6 @@ INCLUDES = \ -I$(top_srcdir) \ -DSRCDIR=\""$(abs_srcdir)"\" \ - -DLIBSOUP_DISABLE_DEPRECATED \ $(SOUP_MAINTAINER_FLAGS) \ $(XML_CFLAGS) \ $(GLIB_CFLAGS) -- cgit v1.2.1 From 2357f3501718967003914da4f1f7659b6593aa0d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 28 Dec 2012 10:41:20 -0500 Subject: Revert the mirroring of SoupMessage API onto SoupRequestHTTP. SoupMessage isn't being deprecated, and mirroring its API onto SoupRequestHTTP is just going to result in always having to add every new API twice. Also, it turns out to be less useful than originally expected anyway, since you end up having to cast between SoupRequest and SoupRequestHTTP frequently anyway. This reverts commit d7117329400e47d2187ed033099d921d555f8d71 and most of commit 53c270d0e2868fa5ad48ce864f10a9486b11a071. --- docs/reference/libsoup-2.4-sections.txt | 10 - libsoup/libsoup-2.4.sym | 8 - libsoup/soup-request-http.c | 506 +------------------------------- libsoup/soup-request-http.h | 41 +-- libsoup/soup-request.c | 30 -- libsoup/soup-request.h | 4 - tests/cache-test.c | 5 +- tests/coding-test.c | 33 ++- tests/connection-test.c | 9 +- tests/proxy-test.c | 9 +- tests/requester-test.c | 30 +- tests/sniffing-test.c | 4 +- 12 files changed, 61 insertions(+), 628 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index db45167f..f3595973 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -1100,8 +1100,6 @@ soup_request_get_content_type soup_request_get_session soup_request_get_uri -soup_request_disable_feature - SOUP_REQUEST_SESSION SOUP_REQUEST_URI @@ -1153,14 +1151,6 @@ soup_request_file_get_type soup-request-http SoupRequestHTTP SoupRequestHTTP -soup_request_http_set_method -soup_request_http_set_request_version -soup_request_http_set_flags -soup_request_http_get_flags -soup_request_http_set_first_party -soup_request_http_get_first_party -soup_request_http_get_https_status - soup_request_http_get_message SOUP_IS_REQUEST_HTTP diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 66e5bf7f..7080ac5b 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -319,7 +319,6 @@ soup_requester_get_type soup_requester_new soup_requester_request soup_requester_request_uri -soup_request_disable_feature soup_request_error_get_type soup_request_error_quark soup_request_file_get_file @@ -329,15 +328,8 @@ soup_request_get_content_type soup_request_get_session soup_request_get_type soup_request_get_uri -soup_request_http_get_first_party -soup_request_http_get_flags -soup_request_http_get_https_status soup_request_http_get_message soup_request_http_get_type -soup_request_http_set_first_party -soup_request_http_set_flags -soup_request_http_set_method -soup_request_http_set_request_version soup_request_send soup_request_send_async soup_request_send_finish diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index e932217a..4e527ccd 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -46,49 +46,9 @@ G_DEFINE_TYPE (SoupRequestHTTP, soup_request_http, SOUP_TYPE_REQUEST) -/** - * SoupRequestHTTP: - * @method: the HTTP method - * @request_uri: the request URI - * @request_version: the HTTP version of the request - * @request_headers: the request headers - * @status_code: the HTTP status code - * @reason_phrase: the status phrase associated with @status_code - * @response_version: the HTTP version of the response - * @response_headers: the response headers - * - * Represents an HTTP message being sent or received via the - * #SoupRequest API. The fields on this object reflect the values on - * the request's underlying #SoupMessage; see the #SoupMessage - * documentation for more information. - * - * Since: 2.42 - */ - -enum { - PROP_0, - - PROP_METHOD, - PROP_REQUEST_URI, - PROP_REQUEST_VERSION, - PROP_REQUEST_HEADERS, - PROP_STATUS_CODE, - PROP_REASON_PHRASE, - PROP_RESPONSE_VERSION, - PROP_RESPONSE_HEADERS, - - PROP_FLAGS, - PROP_FIRST_PARTY, - PROP_TLS_CERTIFICATE, - PROP_TLS_ERRORS, - - LAST_PROP -}; - struct _SoupRequestHTTPPrivate { SoupMessage *msg; char *content_type; - gboolean sent; }; static void content_sniffed (SoupMessage *msg, @@ -102,125 +62,6 @@ soup_request_http_init (SoupRequestHTTP *http) http->priv = G_TYPE_INSTANCE_GET_PRIVATE (http, SOUP_TYPE_REQUEST_HTTP, SoupRequestHTTPPrivate); } -static void -soup_request_http_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - SoupRequestHTTP *http = SOUP_REQUEST_HTTP (object); - - switch (prop_id) { - case PROP_METHOD: - soup_request_http_set_method (http, g_value_get_string (value)); - break; - case PROP_REQUEST_VERSION: - soup_request_http_set_request_version (http, g_value_get_enum (value)); - break; - case PROP_FLAGS: - soup_request_http_set_flags (http, g_value_get_flags (value)); - break; - case PROP_FIRST_PARTY: - soup_request_http_set_first_party (http, g_value_get_boxed (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -soup_request_http_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - SoupRequestHTTP *http = SOUP_REQUEST_HTTP (object); - GTlsCertificate *cert; - GTlsCertificateFlags errors; - - switch (prop_id) { - case PROP_METHOD: - g_value_set_string (value, http->method); - break; - case PROP_REQUEST_URI: - g_value_set_boxed (value, http->request_uri); - break; - case PROP_REQUEST_VERSION: - g_value_set_enum (value, http->request_version); - break; - case PROP_REQUEST_HEADERS: - g_value_set_boxed (value, http->request_headers); - break; - case PROP_STATUS_CODE: - g_value_set_uint (value, http->status_code); - break; - case PROP_REASON_PHRASE: - g_value_set_string (value, http->reason_phrase); - break; - case PROP_RESPONSE_VERSION: - g_value_set_enum (value, http->response_version); - break; - case PROP_RESPONSE_HEADERS: - g_value_set_boxed (value, http->request_headers); - break; - case PROP_FLAGS: - g_value_set_flags (value, soup_message_get_flags (http->priv->msg)); - break; - case PROP_FIRST_PARTY: - g_value_set_boxed (value, soup_message_get_first_party (http->priv->msg)); - break; - case PROP_TLS_CERTIFICATE: - g_object_get (G_OBJECT (http->priv->msg), - "tls-certificate", &cert, - NULL); - g_value_set_object (value, cert); - break; - case PROP_TLS_ERRORS: - g_object_get (G_OBJECT (http->priv->msg), - "tls-errors", &errors, - NULL); - g_value_set_flags (value, errors); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -message_property_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - SoupRequestHTTP *http = user_data; - - if (!strcmp (pspec->name, "method")) { - http->method = http->priv->msg->method; - g_object_notify (G_OBJECT (http), "method"); - } else if (!strcmp (pspec->name, "uri")) { - http->request_uri = soup_message_get_uri (http->priv->msg); - g_object_notify (G_OBJECT (http), "request-uri"); - } else if (!strcmp (pspec->name, "status-code")) { - http->status_code = http->priv->msg->status_code; - g_object_notify (G_OBJECT (http), "status-code"); - } else if (!strcmp (pspec->name, "reason-phrase")) { - http->reason_phrase = http->priv->msg->reason_phrase; - g_object_notify (G_OBJECT (http), "reason-phrase"); - } else if (!strcmp (pspec->name, "http-version")) { - if (!http->priv->sent) { - http->request_version = soup_message_get_http_version (http->priv->msg); - g_object_notify (G_OBJECT (http), "request-version"); - } else { - http->response_version = soup_message_get_http_version (http->priv->msg); - g_object_notify (G_OBJECT (http), "response-version"); - } - } else if (!strcmp (pspec->name, "flags")) - g_object_notify (G_OBJECT (http), "flags"); - else if (!strcmp (pspec->name, "first-party")) - g_object_notify (G_OBJECT (http), "first-party"); - else if (!strcmp (pspec->name, "tls-certificate")) - g_object_notify (G_OBJECT (http), "tls-certificate"); - else if (!strcmp (pspec->name, "tls-errors")) - g_object_notify (G_OBJECT (http), "tls-errors"); -} - static gboolean soup_request_http_check_uri (SoupRequest *request, SoupURI *uri, @@ -236,17 +77,6 @@ soup_request_http_check_uri (SoupRequest *request, g_signal_connect (http->priv->msg, "content-sniffed", G_CALLBACK (content_sniffed), http); - - g_signal_connect (http->priv->msg, "notify", - G_CALLBACK (message_property_changed), http); - - http->method = http->priv->msg->method; - http->request_uri = soup_message_get_uri (http->priv->msg); - http->request_version = SOUP_HTTP_1_1; - http->request_headers = http->priv->msg->request_headers; - http->response_version = SOUP_HTTP_1_1; - http->response_headers = http->priv->msg->response_headers; - return TRUE; } @@ -259,9 +89,6 @@ soup_request_http_finalize (GObject *object) g_signal_handlers_disconnect_by_func (http->priv->msg, G_CALLBACK (content_sniffed), http); - g_signal_handlers_disconnect_by_func (http->priv->msg, - G_CALLBACK (message_property_changed), - http); g_object_unref (http->priv->msg); } @@ -280,7 +107,6 @@ soup_request_http_send (SoupRequest *request, g_return_val_if_fail (!SOUP_IS_SESSION_ASYNC (session), NULL); - http->priv->sent = TRUE; return soup_session_send_request (session, http->priv->msg, cancellable, error); } @@ -313,8 +139,6 @@ soup_request_http_send_async (SoupRequest *request, g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); - http->priv->sent = TRUE; - task = g_task_new (request, cancellable, callback, user_data); soup_session_send_request_async (session, http->priv->msg, cancellable, http_input_stream_ready_cb, task); @@ -383,8 +207,6 @@ soup_request_http_class_init (SoupRequestHTTPClass *request_http_class) request_class->schemes = http_schemes; - object_class->set_property = soup_request_http_set_property; - object_class->get_property = soup_request_http_get_property; object_class->finalize = soup_request_http_finalize; request_class->check_uri = soup_request_http_check_uri; @@ -393,199 +215,6 @@ soup_request_http_class_init (SoupRequestHTTPClass *request_http_class) request_class->send_finish = soup_request_http_send_finish; request_class->get_content_length = soup_request_http_get_content_length; request_class->get_content_type = soup_request_http_get_content_type; - - /** - * SoupRequestHTTP:method: - * - * The request's HTTP method; "GET" by default. Note that in - * C you can simply read the method field - * of the #SoupRequestHTTP. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_METHOD, - g_param_spec_string ("method", - "Method", - "The HTTP method", - SOUP_METHOD_GET, - G_PARAM_READWRITE)); - /** - * SoupRequestHTTP:request-uri: - * - * The request's #SoupURI. Note that in C you can simply read - * the request_uri field of the - * #SoupRequestHTTP. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_REQUEST_URI, - g_param_spec_boxed ("request-uri", - "URI", - "The Request-URI", - SOUP_TYPE_URI, - G_PARAM_READWRITE)); - /** - * SoupRequestHTTP:request-version: - * - * The #SoupHTTPVersion used when sending the request; - * %SOUP_HTTP_1_1 by default. Note that in C you can simply - * read the request_version field of the - * #SoupRequestHTTP. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_REQUEST_VERSION, - g_param_spec_enum ("request-version", - "Request HTTP Version", - "The SoupHTTPVersion used when sending the request", - SOUP_TYPE_HTTP_VERSION, - SOUP_HTTP_1_1, - G_PARAM_READWRITE)); - /** - * SoupRequestHTTP:request-headers: - * - * The request's HTTP request headers. Note that in C you can - * simply read the request_headers field of - * the #SoupRequestHTTP. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_REQUEST_HEADERS, - g_param_spec_boxed ("request-headers", - "Request Headers", - "The HTTP request headers", - SOUP_TYPE_MESSAGE_HEADERS, - G_PARAM_READABLE)); - - /** - * SoupRequestHTTP:status-code: - * - * The request's HTTP response status code. Note that in C you - * can simply read the status_code field of - * the #SoupRequestHTTP. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_STATUS_CODE, - g_param_spec_uint ("status-code", - "Status code", - "The HTTP response status code", - 0, 599, 0, - G_PARAM_READABLE)); - /** - * SoupRequestHTTP:reason-phrase: - * - * The request's HTTP response reason phrase. Note that in C - * you can simply read the reason_phrase - * field of the #SoupRequestHTTP. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_REASON_PHRASE, - g_param_spec_string ("reason-phrase", - "Reason phrase", - "The HTTP response reason phrase", - NULL, - G_PARAM_READABLE)); - /** - * SoupRequestHTTP:response-version: - * - * The #SoupHTTPVersion that the server replied with. Note - * that in C you can simply read the - * response_version field of the - * #SoupRequestHTTP. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_RESPONSE_VERSION, - g_param_spec_enum ("response-version", - "Response HTTP Version", - "The SoupHTTPVersion that the server replied with", - SOUP_TYPE_HTTP_VERSION, - SOUP_HTTP_1_1, - G_PARAM_READABLE)); - /** - * SoupRequestHTTP:response-headers: - * - * The request's HTTP response headers. Note that in C you can - * simply read the response_headers field - * of the #SoupRequestHTTP. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_RESPONSE_HEADERS, - g_param_spec_boxed ("response-headers", - "Response Headers", - "The HTTP response headers", - SOUP_TYPE_MESSAGE_HEADERS, - G_PARAM_READABLE)); - - /** - * SoupRequestHTTP:flags: - * - * The request's #SoupMessageFlags. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_FLAGS, - g_param_spec_flags ("flags", - "Flags", - "Various request options", - SOUP_TYPE_MESSAGE_FLAGS, - 0, - G_PARAM_READWRITE)); - /** - * SoupRequestHTTP:first-party: - * - * The #SoupURI loaded in the application when the request was - * queued. - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_FIRST_PARTY, - g_param_spec_boxed ("first-party", - "First party", - "The URI loaded in the application when the request was queued.", - SOUP_TYPE_URI, - G_PARAM_READWRITE)); - /** - * SoupRequestHTTP:tls-certificate: - * - * The #GTlsCertificate associated with the request - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_TLS_CERTIFICATE, - g_param_spec_object ("tls-certificate", - "TLS Certificate", - "The TLS certificate associated with the request", - G_TYPE_TLS_CERTIFICATE, - G_PARAM_READABLE)); - /** - * SoupRequestHTTP:tls-errors: - * - * The verification errors on #SoupRequestHTTP:tls-certificate - * - * Since: 2.42 - */ - g_object_class_install_property ( - object_class, PROP_TLS_ERRORS, - g_param_spec_flags ("tls-errors", - "TLS Errors", - "The verification errors on the request's TLS certificate", - G_TYPE_TLS_CERTIFICATE_FLAGS, 0, - G_PARAM_READABLE)); } /** @@ -596,7 +225,7 @@ soup_request_http_class_init (SoupRequestHTTPClass *request_http_class) * * Returns: (transfer full): a new reference to the #SoupMessage * - * Since: 2.42 + * Since: 2.40 */ SoupMessage * soup_request_http_get_message (SoupRequestHTTP *http) @@ -605,136 +234,3 @@ soup_request_http_get_message (SoupRequestHTTP *http) return g_object_ref (http->priv->msg); } - -/** - * soup_request_http_set_method: - * @http: a #SoupRequestHTTP - * @method: the HTTP method - * - * Sets @http to use @method as its request method. - * - * Since: 2.42 - */ -void -soup_request_http_set_method (SoupRequestHTTP *http, - const char *method) -{ - g_object_set (G_OBJECT (http->priv->msg), - "method", method, - NULL); -} - -/** - * soup_request_http_set_request_version: - * @http: a #SoupRequestHTTP - * @version: the version of HTTP to use - * - * Sets @http to use the version of HTTP specified by @version in its - * request. - * - * Since: 2.42 - */ -void -soup_request_http_set_request_version (SoupRequestHTTP *http, - SoupHTTPVersion version) -{ - g_return_if_fail (!http->priv->sent); - - g_object_set (G_OBJECT (http->priv->msg), - "http-version", version, - NULL); -} - -/** - * soup_request_http_get_first_party: - * @http: a #SoupRequestHTTP - * - * Gets @http's first-party #SoupURI; see the documentation - * for #SoupCookieJarAcceptPolicy for more details. - * - * Returns: (transfer none): @http's first-party URI - * - * Since: 2.42 - */ -SoupURI * -soup_request_http_get_first_party (SoupRequestHTTP *http) -{ - return soup_message_get_first_party (http->priv->msg); -} - -/** - * soup_request_http_set_first_party: - * @http: a #SoupRequestHTTP - * @first_party: the #SoupURI for the request's first party - * - * Sets @first_party as the main document #SoupURI for @http. For - * details of when and how this is used refer to the documentation for - * #SoupCookieJarAcceptPolicy. - * - * Since: 2.42 - */ -void -soup_request_http_set_first_party (SoupRequestHTTP *http, - SoupURI *first_party) -{ - soup_message_set_first_party (http->priv->msg, - first_party); -} - -/** - * soup_request_http_get_flags: - * @http: a #SoupRequestHTTP - * - * Gets @http's message flags. - * - * Returns: @http's message flags - * - * Since: 2.42 - */ -SoupMessageFlags -soup_request_http_get_flags (SoupRequestHTTP *http) -{ - return soup_message_get_flags (http->priv->msg); -} - -/** - * soup_request_http_set_flags: - * @http: a #SoupRequestHTTP - * @flags: a set of #SoupMessageFlags values - * - * Sets the specified flags on @msg. Note that some #SoupMessageFlags - * (such as %SOUP_MESSAGE_CAN_REBUILD and - * %SOUP_MESSAGE_OVERWRITE_CHUNKS) have no effect in the #SoupRequest - * API. - * - * Since: 2.42 - */ -void -soup_request_http_set_flags (SoupRequestHTTP *http, - SoupMessageFlags flags) -{ - soup_message_set_flags (http->priv->msg, flags); -} - -/** - * soup_request_http_get_https_status: - * @http: a #SoupRequestHTTP - * @certificate: (out) (transfer none): @http's TLS certificate - * @errors: (out): the verification status of @certificate - * - * If @http is using https, this retrieves the #GTlsCertificate - * associated with its connection, and the #GTlsCertificateFlags showing - * what problems, if any, have been found with that certificate. - * - * Return value: %TRUE if @http uses https, %FALSE if not - * - * Since: 2.42 - */ -gboolean -soup_request_http_get_https_status (SoupRequestHTTP *http, - GTlsCertificate **certificate, - GTlsCertificateFlags *errors) -{ - return soup_message_get_https_status (http->priv->msg, - certificate, errors); -} diff --git a/libsoup/soup-request-http.h b/libsoup/soup-request-http.h index 5335b10b..271a8052 100644 --- a/libsoup/soup-request-http.h +++ b/libsoup/soup-request-http.h @@ -23,8 +23,6 @@ #define SOUP_REQUEST_HTTP_H 1 #include "soup-request.h" -#include "soup-message.h" -#include "soup-message-headers.h" G_BEGIN_DECLS @@ -40,20 +38,7 @@ typedef struct _SoupRequestHTTPPrivate SoupRequestHTTPPrivate; struct _SoupRequestHTTP { SoupRequest parent; - /*< public >*/ - const char *method; - SoupURI *request_uri; - SoupHTTPVersion request_version; - SoupMessageHeaders *request_headers; - - guint status_code; - char *reason_phrase; - SoupHTTPVersion response_version; - SoupMessageHeaders *response_headers; - - /*< private >*/ SoupRequestHTTPPrivate *priv; - }; typedef struct { @@ -64,31 +49,7 @@ SOUP_AVAILABLE_IN_2_34 GType soup_request_http_get_type (void); SOUP_AVAILABLE_IN_2_34 -SoupMessage *soup_request_http_get_message (SoupRequestHTTP *http); - -SOUP_AVAILABLE_IN_2_42 -void soup_request_http_set_method (SoupRequestHTTP *http, - const char *method); -SOUP_AVAILABLE_IN_2_42 -void soup_request_http_set_request_version (SoupRequestHTTP *http, - SoupHTTPVersion version); - -SOUP_AVAILABLE_IN_2_42 -SoupURI *soup_request_http_get_first_party (SoupRequestHTTP *http); -SOUP_AVAILABLE_IN_2_42 -void soup_request_http_set_first_party (SoupRequestHTTP *http, - SoupURI *first_party); - -SOUP_AVAILABLE_IN_2_42 -SoupMessageFlags soup_request_http_get_flags (SoupRequestHTTP *http); -SOUP_AVAILABLE_IN_2_42 -void soup_request_http_set_flags (SoupRequestHTTP *http, - SoupMessageFlags flags); - -SOUP_AVAILABLE_IN_2_42 -gboolean soup_request_http_get_https_status (SoupRequestHTTP *http, - GTlsCertificate **certificate, - GTlsCertificateFlags *errors); +SoupMessage *soup_request_http_get_message (SoupRequestHTTP *http); G_END_DECLS diff --git a/libsoup/soup-request.c b/libsoup/soup-request.c index 02d0ca47..0dfe3eff 100644 --- a/libsoup/soup-request.c +++ b/libsoup/soup-request.c @@ -30,7 +30,6 @@ #include "soup-request.h" #include "soup.h" #include "soup-requester.h" -#include "soup-request-http.h" /** * SECTION:soup-request @@ -404,32 +403,3 @@ soup_request_get_content_type (SoupRequest *request) { return SOUP_REQUEST_GET_CLASS (request)->get_content_type (request); } - -/** - * soup_request_disable_feature: - * @request: a #SoupRequest - * @feature_type: the #GType of a #SoupSessionFeature - * - * This disables the actions of #SoupSessionFeatures with the - * given @feature_type (or a subclass of that type) on @request, so - * that @request is processed as though the feature(s) hadn't been - * added to the session. Eg, passing #SOUP_TYPE_PROXY_URI_RESOLVER for - * @feature_type will disable proxy handling and cause @request to be - * sent directly to the indicated origin server, regardless of system - * proxy configuration. - * - * Since: 2.42 - */ -void -soup_request_disable_feature (SoupRequest *request, - GType feature_type) -{ - SoupMessage *msg; - - /* For now, features only affect SoupMessages, so... */ - if (SOUP_IS_REQUEST_HTTP (request)) { - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); - soup_message_disable_feature (msg, feature_type); - g_object_unref (msg); - } -} diff --git a/libsoup/soup-request.h b/libsoup/soup-request.h index e44a7f24..84ad6d6b 100644 --- a/libsoup/soup-request.h +++ b/libsoup/soup-request.h @@ -98,10 +98,6 @@ goffset soup_request_get_content_length (SoupRequest *request); SOUP_AVAILABLE_IN_2_34 const char *soup_request_get_content_type (SoupRequest *request); -SOUP_AVAILABLE_IN_2_42 -void soup_request_disable_feature (SoupRequest *request, - GType feature_type); - G_END_DECLS #endif /* SOUP_REQUEST_H */ diff --git a/tests/cache-test.c b/tests/cache-test.c index 8f8d2b04..ac19bfe5 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -122,6 +122,7 @@ do_request (SoupSession *session, ...) { SoupRequestHTTP *req; + SoupMessage *msg; GInputStream *stream; SoupURI *uri; va_list ap; @@ -135,13 +136,15 @@ do_request (SoupSession *session, uri = soup_uri_new_with_base (base_uri, path); req = soup_session_request_http_uri (session, method, uri, NULL); soup_uri_free (uri); + msg = soup_request_http_get_message (req); va_start (ap, path); while ((header = va_arg (ap, const char *))) { value = va_arg (ap, const char *); - soup_message_headers_append (req->request_headers, + soup_message_headers_append (msg->request_headers, header, value); } + g_object_unref (msg); stream = soup_test_request_send (SOUP_REQUEST (req), NULL, &error); if (!stream) { diff --git a/tests/coding-test.c b/tests/coding-test.c index 7723c19d..5d4f0e32 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -397,6 +397,7 @@ do_coding_req_test (void) { SoupSession *session; SoupRequestHTTP *reqh; + SoupMessage *msg; SoupURI *uri; GByteArray *plain, *cmp; @@ -425,8 +426,10 @@ do_coding_req_test (void) /* Plain text data, claim gzip w/ junk */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n"); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - soup_message_headers_append (reqh->request_headers, + msg = soup_request_http_get_message (reqh); + soup_message_headers_append (msg->request_headers, "X-Test-Options", "trailing-junk"); + g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed w/ junk"); g_byte_array_free (cmp, TRUE); @@ -435,8 +438,10 @@ do_coding_req_test (void) /* Plain text data, claim gzip with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n"); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - soup_message_headers_append (reqh->request_headers, + msg = soup_request_http_get_message (reqh); + soup_message_headers_append (msg->request_headers, "X-Test-Options", "force-encode"); + g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_NOT_DECODED); /* Failed content-decoding should have left the body untouched @@ -450,8 +455,10 @@ do_coding_req_test (void) /* Plain text data, claim deflate */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n"); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - soup_message_headers_append (reqh->request_headers, + msg = soup_request_http_get_message (reqh); + soup_message_headers_append (msg->request_headers, "X-Test-Options", "prefer-deflate-zlib"); + g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed"); g_byte_array_free (cmp, TRUE); @@ -460,8 +467,10 @@ do_coding_req_test (void) /* Plain text data, claim deflate w/ junk */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n"); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - soup_message_headers_append (reqh->request_headers, + msg = soup_request_http_get_message (reqh); + soup_message_headers_append (msg->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); + g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed w/ junk"); g_byte_array_free (cmp, TRUE); @@ -470,8 +479,10 @@ do_coding_req_test (void) /* Plain text data, claim deflate with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n"); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - soup_message_headers_append (reqh->request_headers, + msg = soup_request_http_get_message (reqh); + soup_message_headers_append (msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); + g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED); check_req_bodies (plain, cmp, "plain", "mis-encoded"); g_byte_array_free (cmp, TRUE); @@ -480,8 +491,10 @@ do_coding_req_test (void) /* Plain text data, claim deflate (no zlib headers)*/ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n"); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - soup_message_headers_append (reqh->request_headers, + msg = soup_request_http_get_message (reqh); + soup_message_headers_append (msg->request_headers, "X-Test-Options", "prefer-deflate-raw"); + g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); check_req_bodies (plain, cmp, "plain", "compressed"); g_byte_array_free (cmp, TRUE); @@ -490,8 +503,10 @@ do_coding_req_test (void) /* Plain text data, claim deflate with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n"); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - soup_message_headers_append (reqh->request_headers, + msg = soup_request_http_get_message (reqh); + soup_message_headers_append (msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-raw"); + g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED); check_req_bodies (plain, cmp, "plain", "mis-encoded"); g_byte_array_free (cmp, TRUE); @@ -530,8 +545,10 @@ do_coding_empty_test (void) debug_printf (1, " SoupRequest\n"); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - soup_message_headers_append (reqh->request_headers, + msg = soup_request_http_get_message (reqh); + soup_message_headers_append (msg->request_headers, "X-Test-Options", "empty"); + g_object_unref (msg); body = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_NOT_DECODED); g_byte_array_free (body, TRUE); g_object_unref (reqh); diff --git a/tests/connection-test.c b/tests/connection-test.c index 938c7deb..6b57f24d 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -300,7 +300,7 @@ static void do_timeout_req_test_for_session (SoupSession *session) { SoupRequest *req; - SoupRequestHTTP *http; + SoupMessage *msg; GInputStream *stream; SoupSocket *sockets[4] = { NULL, NULL, NULL, NULL }; SoupURI *timeout_uri; @@ -360,10 +360,10 @@ do_timeout_req_test_for_session (SoupSession *session) g_object_unref (stream); } - http = SOUP_REQUEST_HTTP (req); - if (http->status_code != SOUP_STATUS_OK) { + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); + if (msg->status_code != SOUP_STATUS_OK) { debug_printf (1, " Unexpected response: %d %s\n", - http->status_code, http->reason_phrase); + msg->status_code, msg->reason_phrase); errors++; } if (sockets[1] != sockets[0]) { @@ -379,6 +379,7 @@ do_timeout_req_test_for_session (SoupSession *session) debug_printf (1, " Message was retried again??\n"); errors++; } + g_object_unref (msg); g_object_unref (req); for (i = 0; sockets[i]; i++) diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 3466c569..048acfa7 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -131,8 +131,8 @@ test_url_new_api (const char *url, int proxy, guint expected, { SoupSession *session; SoupURI *proxy_uri; + SoupMessage *msg; SoupRequest *request; - SoupRequestHTTP *http; GInputStream *stream; GError *error = NULL; @@ -162,6 +162,7 @@ test_url_new_api (const char *url, int proxy, guint expected, } request = soup_session_request (session, url, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); stream = soup_test_request_send (request, NULL, &error); if (!stream) { @@ -182,13 +183,13 @@ test_url_new_api (const char *url, int proxy, guint expected, g_object_unref (stream); } - http = SOUP_REQUEST_HTTP (request); - debug_printf (1, " %d %s\n", http->status_code, http->reason_phrase); - if (http->status_code != expected) { + debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); + if (msg->status_code != expected) { debug_printf (1, " EXPECTED %d!\n", expected); errors++; } + g_object_unref (msg); g_object_unref (request); soup_test_session_abort_unref (session); diff --git a/tests/requester-test.c b/tests/requester-test.c index 0a61815b..a4bb5b62 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -145,10 +145,10 @@ test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data) static void auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data) { - SoupRequestHTTP *http = SOUP_REQUEST_HTTP (source); RequestData *data = user_data; GInputStream *stream; GError *error = NULL; + SoupMessage *msg; const char *content_type; stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error); @@ -160,14 +160,15 @@ auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data) return; } - - if (http->status_code != SOUP_STATUS_UNAUTHORIZED) { - debug_printf (1, " GET failed: %d %s\n", http->status_code, - http->reason_phrase); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (source)); + if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { + debug_printf (1, " GET failed: %d %s\n", msg->status_code, + msg->reason_phrase); errors++; g_main_loop_quit (loop); return; } + g_object_unref (msg); content_type = soup_request_get_content_type (SOUP_REQUEST (source)); if (g_strcmp0 (content_type, "text/html") != 0) { @@ -265,12 +266,11 @@ do_async_test (SoupSession *session, SoupURI *uri, request = soup_requester_request_uri (requester, uri, NULL); else request = soup_session_request_uri (session, uri, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); if (cancel) { - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); g_signal_connect (msg, "got-headers", G_CALLBACK (cancel_message), session); - g_object_unref (msg); } started_id = g_signal_connect (session, "request-started", @@ -278,6 +278,7 @@ do_async_test (SoupSession *session, SoupURI *uri, &socket); soup_request_send_async (request, NULL, callback, &data); + g_object_unref (request); loop = g_main_loop_new (soup_session_get_async_context (session), TRUE); g_main_loop_run (loop); @@ -285,16 +286,16 @@ do_async_test (SoupSession *session, SoupURI *uri, g_signal_handler_disconnect (session, started_id); - if (SOUP_REQUEST_HTTP (request)->status_code != expected_status) { + if (msg->status_code != expected_status) { debug_printf (1, " GET failed: %d %s (expected %d)\n", msg->status_code, msg->reason_phrase, expected_status); + g_object_unref (msg); g_object_unref (socket); - g_object_unref (request); errors++; return; } - g_object_unref (request); + g_object_unref (msg); if (!expected_response) { if (data.body->len) { @@ -470,11 +471,10 @@ do_sync_request (SoupSession *session, SoupRequest *request, guint started_id; SoupSocket *socket = NULL; + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); if (cancel) { - msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); g_signal_connect (msg, "got-headers", G_CALLBACK (cancel_message), session); - g_object_unref (msg); } started_id = g_signal_connect (session, "request-started", @@ -494,25 +494,29 @@ do_sync_request (SoupSession *session, SoupRequest *request, errors++; } g_clear_error (&error); + g_object_unref (msg); g_object_unref (socket); return; } else if (!in) { debug_printf (1, " soup_request_send failed: %s\n", error->message); + g_object_unref (msg); g_clear_error (&error); g_object_unref (socket); errors++; return; } - if (SOUP_REQUEST_HTTP (request)->status_code != expected_status) { + if (msg->status_code != expected_status) { debug_printf (1, " GET failed: %d %s\n", msg->status_code, msg->reason_phrase); + g_object_unref (msg); g_object_unref (in); g_object_unref (socket); errors++; return; } + g_object_unref (msg); body = g_string_new (NULL); do { diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index ab8099da..f28ddaf8 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -436,7 +436,9 @@ test_disabled (const char *path) g_object_unref (msg); req = soup_session_request_uri (session, uri, NULL); - soup_request_disable_feature (req, SOUP_TYPE_CONTENT_SNIFFER); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); + soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER); + g_object_unref (msg); stream = soup_test_request_send (req, NULL, &error); if (stream) { soup_test_request_close_stream (req, stream, NULL, &error); -- cgit v1.2.1 From 967dcc28f43cd47a75b7ff2c069807edb9929400 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 14 Dec 2012 09:54:36 -0500 Subject: SoupSession: update docs (and some semantics) for plain SoupSession Update the docs to reflect the changes in plain SoupSessions vs its traditional subclasses. And while we're there, add a few new ones (including making soup_session_queue_message() and soup_session_send_message() work on plain SoupSession. --- docs/reference/Makefile.am | 3 +- docs/reference/libsoup-2.4-docs.sgml | 1 + docs/reference/libsoup-2.4-sections.txt | 3 + docs/reference/session-porting.xml | 163 +++++++++++++++++ libsoup/libsoup-2.4.sym | 2 + libsoup/soup-content-decoder.c | 23 ++- libsoup/soup-proxy-resolver-default.c | 9 + libsoup/soup-session-async.c | 32 ++-- libsoup/soup-session-async.h | 2 + libsoup/soup-session-sync.c | 46 ++--- libsoup/soup-session-sync.h | 2 + libsoup/soup-session.c | 310 +++++++++++++++++++++++--------- libsoup/soup-session.h | 9 +- 13 files changed, 463 insertions(+), 142 deletions(-) create mode 100644 docs/reference/session-porting.xml diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 7e6c180b..74a6d925 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -52,7 +52,8 @@ HTML_IMAGES = content_files = \ build-howto.xml \ client-howto.xml \ - server-howto.xml + server-howto.xml \ + session-porting.xml # Other files to distribute. extra_files = diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index 95ff9c98..f19848f5 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -11,6 +11,7 @@ + diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index f3595973..963cbce1 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -388,6 +388,9 @@ SoupAddressClass SoupSession SoupSession +soup_session_new +soup_session_new_with_options + soup_session_request soup_session_request_uri soup_session_request_http diff --git a/docs/reference/session-porting.xml b/docs/reference/session-porting.xml new file mode 100644 index 00000000..680f75aa --- /dev/null +++ b/docs/reference/session-porting.xml @@ -0,0 +1,163 @@ + + + + +Porting to the new SoupSession +3 +LIBSOUP Library + + + +Porting to the new SoupSessionNotes on +porting from SoupSessionAsync and SoupSessionSync to SoupSession + + + +Introduction + + +As of libsoup 2.42, SoupSession is no longer an +abstract class, and the base SoupSession class is now +preferred over its traditional subclasses, SoupSessionAsync and +SoupSessionSync. + + + +There are several changes in behavior between the old and new sessions +to be aware of. + + + + + +Different defaults + + +The new SoupSession +has different (and hopefully better) defaults than SoupSessionAsync and +SoupSessionSync: + + + + + + The system TLS/SSL certificate database is used by default to + validate https certificates, and sites with invalid certificates + will refuse to load with a + SOUP_STATUS_SSL_FAILED + error. + + + You can still override the CA database as before, by setting the + "ssl-ca-file" + property, although the + "tls-database" + property is preferred, since it allows you to do proper error + handling. + + + If you want to accept all certificates, set + "ssl-strict" to + FALSE. Note that libsoup will still check + certificates, it will just continue with the HTTP request even + if the certificate fails to validate. You can use + soup_message_get_https_status() + to look at the certificate after the fact. + + + + + The + "timeout" + and + "idle-timeout" + properties both default to 60 seconds. + + + + + The + "http-aliases" + property defaults to NULL, meaning that URI + schemes like "webcal" and + "dav" (and "ftp") are not + considered to be aliases for "http", and so + libsoup will not accept requests for such URIs, and will not + follow redirects to such URIs. + + + + + Every session gets a + SoupProxyResolverDefault + and a + SoupContentDecoder + attached to it by default, meaning that it will automatically + use the user's system proxy configuration, and will handle (and + request) "gzip"- and "deflate"-encoded response bodies. + + + + + + + +Differences in SoupMessage-sending APIs + + +SoupSessionAsync always uses asynchronous I/O, and +SoupSessionSync always uses blocking I/O, regardless of +the operation. In the new SoupSession, soup_session_queue_message() +uses asynchronous I/O (like SoupSessionAsync), and soup_session_send_message() +uses blocking I/O (like SoupSessionSync). There is no API +on the plain SoupSession that simulates the effect of +calling soup_session_send_message() on a +SoupSessionAsync (ie, running the main loop internally), +or of calling soup_session_queue_message() on a +SoupSessionSync (ie, automatically sending the request in +another thread). + + + + + +Differences in Asynchronous I/O + + +As compared to SoupSessionAsync, SoupSession behaves more +like gio with respect to asynchronous I/O. + + + +In particular, the "async-context" +and "use-thread-context" +properties are now effectively unused, and the session always queues +asynchronous requests in the GMainContext that was is +the thread default when the asynchronous operation is started. Session +bookkeeping tasks (like closing idle connections) happen in the +context that was thread default when the session was created. + + + +Additionally, soup_session_cancel_message() +now acts asynchronously when you cancel an asynchronous request; +rather than having the request's callback be called from inside +soup_session_cancel_message(), it just gets called +when you need return to the main loop. + + + + + diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 7080ac5b..8ec30b14 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -368,6 +368,8 @@ soup_session_get_feature_for_message soup_session_get_features soup_session_get_type soup_session_has_feature +soup_session_new +soup_session_new_with_options soup_session_pause_message soup_session_prefetch_dns soup_session_prepare_for_uri diff --git a/libsoup/soup-content-decoder.c b/libsoup/soup-content-decoder.c index 8aac8a8a..bce78c01 100644 --- a/libsoup/soup-content-decoder.c +++ b/libsoup/soup-content-decoder.c @@ -18,15 +18,18 @@ * SECTION:soup-content-decoder * @short_description: Content-Encoding handler * - * #SoupContentDecoder handles the "Accept-Encoding" header on - * outgoing messages, and the "Content-Encoding" header on incoming - * ones. If you add it to a session with soup_session_add_feature() or - * soup_session_add_feature_by_type(), the session will automatically - * use Content-Encoding as appropriate. + * #SoupContentDecoder handles adding the "Accept-Encoding" header on + * outgoing messages, and processing the "Content-Encoding" header on + * incoming ones. Currently it supports the "gzip" and "deflate" + * content codings. * - * (Note that currently there is no way to (automatically) use - * Content-Encoding when sending a request body, or to pick specific - * encoding types to support.) + * If you are using a plain #SoupSession (ie, not #SoupSessionAsync or + * #SoupSessionSync), then a #SoupContentDecoder will automatically be + * added to the session by default. (You can use + * %SOUP_SESSION_REMOVE_FEATURE_BY_TYPE at construct time if you don't + * want this.) If you are using one of the deprecated #SoupSession + * subclasses, you can add a #SoupContentDecoder to your session with + * soup_session_add_feature() or soup_session_add_feature_by_type(). * * If #SoupContentDecoder successfully decodes the Content-Encoding, * it will set the %SOUP_MESSAGE_CONTENT_DECODED flag on the message, @@ -40,6 +43,10 @@ * will be decoded (and the %SOUP_MESSAGE_CONTENT_DECODED flag will * not be set). * + * (Note that currently there is no way to (automatically) use + * Content-Encoding when sending a request body, or to pick specific + * encoding types to support.) + * * Since: 2.30 **/ diff --git a/libsoup/soup-proxy-resolver-default.c b/libsoup/soup-proxy-resolver-default.c index 0fc8780c..ee3b102b 100644 --- a/libsoup/soup-proxy-resolver-default.c +++ b/libsoup/soup-proxy-resolver-default.c @@ -19,6 +19,15 @@ * #SoupProxyResolverDefault is a #SoupProxyURIResolver implementation * that uses the default gio GProxyResolver to resolve proxies. * + * If you are using a plain #SoupSession (ie, not #SoupSessionAsync or + * #SoupSessionSync), then a #SoupProxyResolverDefault will + * automatically be added to the session. (You can use + * %SOUP_SESSION_REMOVE_FEATURE_BY_TYPE at construct time if you don't + * want this.) If you are using one of the deprecated #SoupSession + * subclasses, you can add a #SoupProxyResolverDefault to your session + * with soup_session_add_feature() or + * soup_session_add_feature_by_type(). + * * Since: 2.34 */ diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index c416646d..b9353480 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -18,11 +18,16 @@ /** * SECTION:soup-session-async - * @short_description: Soup session for asynchronous (main-loop-based) I/O. + * @short_description: (Deprecated) SoupSession for asynchronous + * (main-loop-based) I/O. * * #SoupSessionAsync is an implementation of #SoupSession that uses - * non-blocking I/O via the glib main loop. It is intended for use in - * single-threaded programs. + * non-blocking I/O via the glib main loop for all I/O. + * + * As of libsoup 2.42, this is deprecated in favor of the plain + * #SoupSession class (which uses both asynchronous and synchronous + * I/O, depending on the API used). See the porting guide. **/ G_DEFINE_TYPE (SoupSessionAsync, soup_session_async, SOUP_TYPE_SESSION) @@ -38,6 +43,10 @@ soup_session_async_init (SoupSessionAsync *sa) * Creates an asynchronous #SoupSession with the default options. * * Return value: the new session. + * + * Deprecated: #SoupSessionAsync is deprecated; use a plain + * #SoupSession, created with soup_session_new(). See the porting guide. **/ SoupSession * soup_session_async_new (void) @@ -53,6 +62,10 @@ soup_session_async_new (void) * Creates an asynchronous #SoupSession with the specified options. * * Return value: the new session. + * + * Deprecated: #SoupSessionAsync is deprecated; use a plain + * #SoupSession, created with soup_session_new_with_options(). See the + * porting guide. **/ SoupSession * soup_session_async_new_with_options (const char *optname1, ...) @@ -68,18 +81,6 @@ soup_session_async_new_with_options (const char *optname1, ...) return session; } -static void -soup_session_async_queue_message (SoupSession *session, SoupMessage *msg, - SoupSessionCallback callback, gpointer user_data) -{ - SoupMessageQueueItem *item; - - item = soup_session_append_queue_item (session, msg, TRUE, FALSE, - callback, user_data); - soup_session_kick_queue (session); - soup_message_queue_item_unref (item); -} - static guint soup_session_async_send_message (SoupSession *session, SoupMessage *msg) { @@ -137,7 +138,6 @@ soup_session_async_class_init (SoupSessionAsyncClass *soup_session_async_class) SoupSessionClass *session_class = SOUP_SESSION_CLASS (soup_session_async_class); /* virtual method override */ - session_class->queue_message = soup_session_async_queue_message; session_class->send_message = soup_session_async_send_message; session_class->cancel_message = soup_session_async_cancel_message; } diff --git a/libsoup/soup-session-async.h b/libsoup/soup-session-async.h index 9fb9cfe0..15b0ebfd 100644 --- a/libsoup/soup-session-async.h +++ b/libsoup/soup-session-async.h @@ -35,9 +35,11 @@ typedef struct { GType soup_session_async_get_type (void); +#ifndef LIBSOUP_DISABLE_DEPRECATED SoupSession *soup_session_async_new (void); SoupSession *soup_session_async_new_with_options (const char *optname1, ...) G_GNUC_NULL_TERMINATED; +#endif G_END_DECLS diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index f6ae9682..374f22bd 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -17,27 +17,16 @@ /** * SECTION:soup-session-sync - * @short_description: Soup session for blocking I/O in multithreaded - * programs. + * @short_description: (Deprecated) SoupSession for blocking I/O in + * multithreaded programs. * * #SoupSessionSync is an implementation of #SoupSession that uses * synchronous I/O, intended for use in multi-threaded programs. * - * You can use #SoupSessionSync from multiple threads concurrently. - * Eg, you can send a #SoupMessage in one thread, and then while - * waiting for the response, send another #SoupMessage from another - * thread. You can also send a message from one thread and then call - * soup_session_cancel_message() on it from any other thread (although - * you need to be careful to avoid race conditions, where the message - * finishes and is then unreffed by the sending thread just before you - * cancel it). - * - * However, the majority of other types and methods in libsoup are not - * MT-safe. In particular, you cannot modify or - * examine a #SoupMessage while it is being transmitted by - * #SoupSessionSync in another thread. Once a message has been handed - * off to #SoupSessionSync, it can only be manipulated from its signal - * handler callbacks, until I/O is complete. + * As of libsoup 2.42, this is deprecated in favor of the plain + * #SoupSession class (which uses both asynchronous and synchronous + * I/O, depending on the API used). See the porting guide. **/ G_DEFINE_TYPE (SoupSessionSync, soup_session_sync, SOUP_TYPE_SESSION) @@ -53,6 +42,10 @@ soup_session_sync_init (SoupSessionSync *ss) * Creates an synchronous #SoupSession with the default options. * * Return value: the new session. + * + * Deprecated: #SoupSessionSync is deprecated; use a plain + * #SoupSession, created with soup_session_new(). See the porting guide. **/ SoupSession * soup_session_sync_new (void) @@ -68,6 +61,10 @@ soup_session_sync_new (void) * Creates an synchronous #SoupSession with the specified options. * * Return value: the new session. + * + * Deprecated: #SoupSessionSync is deprecated; use a plain + * #SoupSession, created with soup_session_new_with_options(). See the + * porting guide. **/ SoupSession * soup_session_sync_new_with_options (const char *optname1, ...) @@ -122,20 +119,6 @@ soup_session_sync_queue_message (SoupSession *session, SoupMessage *msg, g_thread_unref (thread); } -static guint -soup_session_sync_send_message (SoupSession *session, SoupMessage *msg) -{ - SoupMessageQueueItem *item; - guint status; - - item = soup_session_append_queue_item (session, msg, FALSE, FALSE, - NULL, NULL); - soup_session_process_queue_item (session, item, NULL, TRUE); - status = msg->status_code; - soup_message_queue_item_unref (item); - return status; -} - static void soup_session_sync_class_init (SoupSessionSyncClass *session_sync_class) { @@ -143,5 +126,4 @@ soup_session_sync_class_init (SoupSessionSyncClass *session_sync_class) /* virtual method override */ session_class->queue_message = soup_session_sync_queue_message; - session_class->send_message = soup_session_sync_send_message; } diff --git a/libsoup/soup-session-sync.h b/libsoup/soup-session-sync.h index 845e01c3..0ddda226 100644 --- a/libsoup/soup-session-sync.h +++ b/libsoup/soup-session-sync.h @@ -35,9 +35,11 @@ typedef struct { GType soup_session_sync_get_type (void); +#ifndef LIBSOUP_DISABLE_DEPRECATED SoupSession *soup_session_sync_new (void); SoupSession *soup_session_sync_new_with_options (const char *optname1, ...) G_GNUC_NULL_TERMINATED; +#endif G_END_DECLS diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 43e5f6be..0a866300 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -32,7 +32,8 @@ * #SoupSession is the object that controls client-side HTTP. A * #SoupSession encapsulates all of the state that libsoup is keeping * on behalf of your program; cached HTTP connections, authentication - * information, etc. + * information, etc. It also keeps track of various global options + * and features that you are using. * * Most applications will only need a single #SoupSession; the primary * reason you might need multiple sessions is if you need to have @@ -43,12 +44,16 @@ * one session for the first user, and a second session for the other * user.) * - * #SoupSession itself is an abstract class, with two subclasses. If - * you are using the glib main loop, you will generally want to use - * #SoupSessionAsync, which uses non-blocking I/O and callbacks. On - * the other hand, if your application is threaded and you want to do - * synchronous I/O in a separate thread from the UI, use - * #SoupSessionSync. + * In the past, #SoupSession was an abstract class, and users needed + * to choose between #SoupSessionAsync (which always uses + * #GMainLoop-based I/O), or #SoupSessionSync (which always uses + * blocking I/O and can be used from multiple threads simultaneously). + * This is no longer necessary; you can (and should) use a plain + * #SoupSession, which supports both synchronous and asynchronous use. + * (When using a plain #SoupSession, soup_session_queue_message() + * behaves like it traditionally did on a #SoupSessionAsync, and + * soup_session_send_message() behaves like it traditionally did on a + * #SoupSessionSync.) **/ static void @@ -746,6 +751,47 @@ soup_session_get_property (GObject *object, guint prop_id, } } +/** + * soup_session_new: + * + * Creates a #SoupSession with the default options. + * + * Return value: the new session. + * + * Since: 2.42 + */ +SoupSession * +soup_session_new (void) +{ + return g_object_new (SOUP_TYPE_SESSION, NULL); +} + +/** + * soup_session_new_with_options: + * @optname1: name of first property to set + * @...: value of @optname1, followed by additional property/value pairs + * + * Creates a #SoupSession with the specified options. + * + * Return value: the new session. + * + * Since: 2.42 + */ +SoupSession * +soup_session_new_with_options (const char *optname1, + ...) +{ + SoupSession *session; + va_list ap; + + va_start (ap, optname1); + session = (SoupSession *)g_object_new_valist (SOUP_TYPE_SESSION, + optname1, ap); + va_end (ap); + + return session; +} + static gboolean uri_is_http (SoupSessionPrivate *priv, SoupURI *uri) { @@ -793,12 +839,12 @@ uri_is_https (SoupSessionPrivate *priv, SoupURI *uri) * soup_session_get_async_context: * @session: a #SoupSession * - * Gets @session's async_context. This does not add a ref to the - * context, so you will need to ref it yourself if you want it to - * outlive its session. + * Gets @session's #SoupSession:async-context. This does not add a ref + * to the context, so you will need to ref it yourself if you want it + * to outlive its session. * - * If #SoupSession:use-thread-context is true, this will return the - * current thread-default main context. + * For a modern #SoupSession, this will always just return the + * thread-default #GMainContext, and so is not especially useful. * * Return value: (transfer none): @session's #GMainContext, which may * be %NULL @@ -1623,7 +1669,7 @@ get_connection_for_host (SoupSession *session, SOUP_CONNECTION_PROXY_RESOLVER, soup_session_get_feature (session, SOUP_TYPE_PROXY_URI_RESOLVER), SOUP_CONNECTION_SSL, uri_is_https (priv, soup_message_get_uri (item->msg)), SOUP_CONNECTION_SSL_CREDENTIALS, priv->tlsdb, - SOUP_CONNECTION_SSL_STRICT, (priv->tlsdb != NULL) && priv->ssl_strict, + SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (priv->tlsdb != NULL || SOUP_IS_PLAIN_SESSION (session)), SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context, SOUP_CONNECTION_USE_THREAD_CONTEXT, priv->use_thread_context, SOUP_CONNECTION_TIMEOUT, priv->io_timeout, @@ -1887,6 +1933,18 @@ idle_run_queue (gpointer user_data) * qv. **/ +static void +soup_session_real_queue_message (SoupSession *session, SoupMessage *msg, + SoupSessionCallback callback, gpointer user_data) +{ + SoupMessageQueueItem *item; + + item = soup_session_append_queue_item (session, msg, TRUE, FALSE, + callback, user_data); + soup_session_kick_queue (session); + soup_message_queue_item_unref (item); +} + /** * soup_session_queue_message: * @session: a #SoupSession @@ -1895,20 +1953,27 @@ idle_run_queue (gpointer user_data) * be called after the message completes or when an unrecoverable error occurs. * @user_data: (allow-none): a pointer passed to @callback. * - * Queues the message @msg for sending. All messages are processed - * while the glib main loop runs. If @msg has been processed before, - * any resources related to the time it was last sent are freed. + * Queues the message @msg for asynchronously sending the request and + * receiving a response in the current thread-default #GMainContext. + * If @msg has been processed before, any resources related to the + * time it was last sent are freed. * * Upon message completion, the callback specified in @callback will - * be invoked (in the thread associated with @session's async - * context). If after returning from this callback the message has not + * be invoked. If after returning from this callback the message has not * been requeued, @msg will be unreffed. + * + * (The behavior above applies to a plain #SoupSession; if you are + * using #SoupSessionAsync or #SoupSessionSync, then the #GMainContext + * that is used depends on the settings of #SoupSession:async-context + * and #SoupSession:use-thread-context, and for #SoupSessionSync, the + * message will actually be sent and processed in another thread, with + * only the final callback occurring in the indicated #GMainContext.) */ void soup_session_queue_message (SoupSession *session, SoupMessage *msg, SoupSessionCallback callback, gpointer user_data) { - g_return_if_fail (SOUP_IS_SESSION_ASYNC (session) || SOUP_IS_SESSION_SYNC (session)); + g_return_if_fail (SOUP_IS_SESSION (session)); g_return_if_fail (SOUP_IS_MESSAGE (msg)); SOUP_SESSION_GET_CLASS (session)->queue_message (session, msg, @@ -1948,6 +2013,20 @@ soup_session_requeue_message (SoupSession *session, SoupMessage *msg) SOUP_SESSION_GET_CLASS (session)->requeue_message (session, msg); } +static guint +soup_session_real_send_message (SoupSession *session, SoupMessage *msg) +{ + SoupMessageQueueItem *item; + guint status; + + item = soup_session_append_queue_item (session, msg, FALSE, FALSE, + NULL, NULL); + soup_session_process_queue_item (session, item, NULL, TRUE); + status = msg->status_code; + soup_message_queue_item_unref (item); + return status; +} + /** * soup_session_send_message: * @session: a #SoupSession @@ -1957,14 +2036,20 @@ soup_session_requeue_message (SoupSession *session, SoupMessage *msg) * transfer is finished successfully or there is an unrecoverable * error. * - * @msg is not freed upon return. + * Unlike with soup_session_queue_message(), @msg is not freed upon + * return. + * + * (Note that if you call this method on a #SoupSessionAsync, it will + * still use asynchronous I/O internally, running the glib main loop + * to process the message, which may also cause other events to be + * processed.) * * Return value: the HTTP status code of the response */ guint soup_session_send_message (SoupSession *session, SoupMessage *msg) { - g_return_val_if_fail (SOUP_IS_SESSION_ASYNC (session) || SOUP_IS_SESSION_SYNC (session), SOUP_STATUS_MALFORMED); + g_return_val_if_fail (SOUP_IS_SESSION (session), SOUP_STATUS_MALFORMED); g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_STATUS_MALFORMED); return SOUP_SESSION_GET_CLASS (session)->send_message (session, msg); @@ -2105,7 +2190,7 @@ soup_session_real_cancel_message (SoupSession *session, SoupMessage *msg, guint * may call this at any time after handing @msg off to @session; if * @session has started sending the request but has not yet received * the complete response, then it will close the request's connection. - * Note that with non-idempotent requests (eg, + * Note that with requests that have side effects (eg, * POST, PUT, * DELETE) it is possible that you might cancel the * request after the server acts on it, but before it returns a @@ -2116,9 +2201,12 @@ soup_session_real_cancel_message (SoupSession *session, SoupMessage *msg, guint * The response headers, on the other hand, will always be either * empty or complete. * - * For messages queued with soup_session_queue_message() (and - * cancelled from the same thread), the callback will be invoked - * before soup_session_cancel_message() returns. + * Beware that with the deprecated #SoupSessionAsync, messages queued + * with soup_session_queue_message() will have their callbacks invoked + * before soup_session_cancel_message() returns. The plain + * #SoupSession does not have this behavior; cancelling an + * asynchronous message will merely queue its callback to be run after + * returning to the main loop. **/ void soup_session_cancel_message (SoupSession *session, SoupMessage *msg, @@ -2203,6 +2291,12 @@ soup_session_real_flush_queue (SoupSession *session) * * Cancels all pending requests in @session and closes all idle * persistent connections. + * + * The message cancellation has the same semantics as with + * soup_session_cancel_message(); asynchronous requests on a + * #SoupSessionAsync will have their callback called before + * soup_session_abort() returns. Requests on a plain #SoupSession will + * not. **/ void soup_session_abort (SoupSession *session) @@ -2268,10 +2362,6 @@ prefetch_uri (SoupSession *session, SoupURI *uri, * proxy address, etc.) in order to work more quickly once the URI is * actually requested. * - * This method acts asynchronously, in @session's - * #SoupSession:async_context. If you are using #SoupSessionSync and do - * not have a main loop running, then you can't use this method. - * * Since: 2.30 * * Deprecated: 2.38: use soup_session_prefetch_dns() instead @@ -2306,10 +2396,6 @@ soup_session_prepare_for_uri (SoupSession *session, SoupURI *uri) * resolution. @callback will still be invoked in this case, with a * status of %SOUP_STATUS_CANCELLED. * -* This method acts asynchronously, in @session's -* #SoupSession:async_context. If you are using #SoupSessionSync and do -* not have a main loop running, then you can't use this method. -* * Since: 2.38 **/ void @@ -2341,6 +2427,10 @@ soup_session_prefetch_dns (SoupSession *session, const char *hostname, * feature to the session at construct time by using the * %SOUP_SESSION_ADD_FEATURE property. * + * Note that a #SoupProxyResolverDefault and a #SoupContentDecoder are + * added to the session by default (unless you are using one of the + * deprecated session subclasses). + * * Since: 2.24 **/ void @@ -2375,6 +2465,10 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature) * You can also add a feature to the session at construct time by * using the %SOUP_SESSION_ADD_FEATURE_BY_TYPE property. * + * Note that a #SoupProxyResolverDefault and a #SoupContentDecoder are + * added to the session by default (unless you are using one of the + * deprecated session subclasses). + * * Since: 2.24 **/ void @@ -2642,6 +2736,8 @@ soup_session_class_init (SoupSessionClass *session_class) g_type_class_add_private (session_class, sizeof (SoupSessionPrivate)); /* virtual method definition */ + session_class->queue_message = soup_session_real_queue_message; + session_class->send_message = soup_session_real_send_message; session_class->requeue_message = soup_session_real_requeue_message; session_class->cancel_message = soup_session_real_cancel_message; session_class->flush_queue = soup_session_real_flush_queue; @@ -2837,11 +2933,23 @@ soup_session_class_init (SoupSessionClass *session_class) /* properties */ + /** + * SoupSession:proxy-uri: + * + * An http proxy to use for all http and https requests in + * this session. Setting this will remove any + * #SoupProxyURIResolver features that have been added to the + * session. + * + * Note that #SoupProxyResolverDefault will handle looking up + * the user's proxy settings for you; you should only use + * #SoupSession:proxy-uri if you need to override the user's + * normal proxy settings. + */ /** * SOUP_SESSION_PROXY_URI: * - * Alias for the #SoupSession:proxy-uri property. (The HTTP - * proxy to use for this session.) + * Alias for the #SoupSession:proxy-uri property, qv. **/ g_object_class_install_property ( object_class, PROP_PROXY_URI, @@ -2853,8 +2961,7 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SOUP_SESSION_MAX_CONNS: * - * Alias for the #SoupSession:max-conns property. (The maximum - * number of connections that the session can open at once.) + * Alias for the #SoupSession:max-conns property, qv. **/ g_object_class_install_property ( object_class, PROP_MAX_CONNS, @@ -2868,9 +2975,7 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SOUP_SESSION_MAX_CONNS_PER_HOST: * - * Alias for the #SoupSession:max-conns-per-host property. - * (The maximum number of connections that the session can - * open at once to a given host.) + * Alias for the #SoupSession:max-conns-per-host property, qv. **/ g_object_class_install_property ( object_class, PROP_MAX_CONNS_PER_HOST, @@ -2893,13 +2998,17 @@ soup_session_class_init (SoupSessionClass *session_class) * if you want to ensure that all future connections will have * this timeout value. * + * Note that the default value of 60 seconds only applies to + * plain #SoupSessions. If you are using #SoupSessionAsync or + * #SoupSessionSync, the default value is 0 (meaning idle + * connections will never time out). + * * Since: 2.24 **/ /** * SOUP_SESSION_IDLE_TIMEOUT: * - * Alias for the #SoupSession:idle-timeout property. (The idle - * connection lifetime.) + * Alias for the #SoupSession:idle-timeout property, qv. * * Since: 2.24 **/ @@ -2908,7 +3017,7 @@ soup_session_class_init (SoupSessionClass *session_class) g_param_spec_uint (SOUP_SESSION_IDLE_TIMEOUT, "Idle Timeout", "Connection lifetime when idle", - 0, G_MAXUINT, 0, + 0, G_MAXUINT, 60, G_PARAM_READWRITE)); /** * SoupSession:use-ntlm: @@ -2921,8 +3030,7 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SOUP_SESSION_USE_NTLM: * - * Alias for the #SoupSession:use-ntlm property. (Whether or - * not to use NTLM authentication.) + * Alias for the #SoupSession:use-ntlm property, qv. **/ g_object_class_install_property ( object_class, PROP_USE_NTLM, @@ -2936,17 +3044,19 @@ soup_session_class_init (SoupSessionClass *session_class) * * File containing SSL CA certificates. * - * Deprecated: use #SoupSession:ssl-use-system-ca-file or - * #SoupSession:tls-database instead + * If the specified file does not exist or cannot be read, + * then libsoup will print a warning, and then behave as + * though it had read in a empty CA file, meaning that all SSL + * certificates will be considered invalid. + * + * Deprecated: use #SoupSession:ssl-use-system-ca-file, or + * else #SoupSession:tls-database with a #GTlsFileDatabase + * (which allows you to do explicit error handling). **/ /** * SOUP_SESSION_SSL_CA_FILE: * - * Alias for the #SoupSession:ssl-ca-file property. (File - * containing SSL CA certificates.). - * - * Deprecated: use #SoupSession:ssl-use-system-ca-file or - * #SoupSession:tls-database instead + * Alias for the #SoupSession:ssl-ca-file property, qv. **/ g_object_class_install_property ( object_class, PROP_SSL_CA_FILE, @@ -2978,6 +3088,11 @@ soup_session_class_init (SoupSessionClass *session_class) * See #SoupSession:ssl-strict for more information on how * https certificate validation is handled. * + * Note that the default value of %TRUE only applies to plain + * #SoupSessions. If you are using #SoupSessionAsync or + * #SoupSessionSync, the default value is %FALSE, for backward + * compatibility. + * * Since: 2.38 **/ g_object_class_install_property ( @@ -2985,7 +3100,7 @@ soup_session_class_init (SoupSessionClass *session_class) g_param_spec_boolean (SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, "Use system CA file", "Use the system certificate database", - FALSE, + TRUE, G_PARAM_READWRITE)); /** * SOUP_SESSION_TLS_DATABASE: @@ -3008,6 +3123,12 @@ soup_session_class_init (SoupSessionClass *session_class) * See #SoupSession:ssl-strict for more information on how * https certificate validation is handled. * + * If you are using a plain #SoupSession then + * #SoupSession:ssl-use-system-ca-file will be %TRUE by + * default, and so this property will be a copy of the system + * CA database. If you are using #SoupSessionAsync or + * #SoupSessionSync, this property will be %NULL by default. + * * Since: 2.38 **/ g_object_class_install_property ( @@ -3042,9 +3163,13 @@ soup_session_class_init (SoupSessionClass *session_class) * accept invalid certificates after giving some sort of * warning.) * - * If the session has no CA file or TLS database, then all - * certificates are always accepted, and this property has no - * effect. + * For a plain #SoupSession, if the session has no CA file or + * TLS database, and this property is %TRUE, then all + * certificates will be rejected. However, beware that the + * deprecated #SoupSession subclasses (#SoupSessionAsync and + * #SoupSessionSync) have the opposite behavior: if there is + * no CA file or TLS database, then all certificates are always + * accepted, and this property has no effect. * * Since: 2.30 */ @@ -3055,11 +3180,27 @@ soup_session_class_init (SoupSessionClass *session_class) "Whether certificate errors should be considered a connection error", TRUE, G_PARAM_READWRITE)); + /** + * SoupSession:async-context: + * + * The #GMainContext that miscellaneous session-related + * asynchronous callbacks are invoked on. (Eg, setting + * #SoupSession:idle-timeout will add a timeout source on this + * context.) + * + * For a plain #SoupSession, this property is always set to + * the #GMainContext that is the thread-default at the time + * the session was created, and cannot be overridden. For the + * deprecated #SoupSession subclasses, the default value is + * %NULL, meaning to use the global default #GMainContext. + * + * If #SoupSession:use-thread-context is %FALSE, this context + * will also be used for asynchronous HTTP I/O. + */ /** * SOUP_SESSION_ASYNC_CONTEXT: * - * Alias for the #SoupSession:async-context property. (The - * session's #GMainContext.) + * Alias for the #SoupSession:async-context property, qv. */ g_object_class_install_property ( object_class, PROP_ASYNC_CONTEXT, @@ -3077,13 +3218,11 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SoupSession:use-thread-context: * - * If set, asynchronous operations in this session will run in + * If %TRUE (which it always is on a plain #SoupSession), + * asynchronous HTTP requests in this session will run in * whatever the thread-default #GMainContext is at the time - * they are started, rather than always occurring in a context - * fixed at the session's construction time. "Bookkeeping" - * tasks (like expiring idle connections) will happen in the - * context that was thread-default at the time the session was - * created. + * they are started, rather than always occurring in + * #SoupSession:async-context. * * Since: 2.38 */ @@ -3106,12 +3245,20 @@ soup_session_class_init (SoupSessionClass *session_class) * ones. You can call soup_session_abort() after setting this * if you want to ensure that all future connections will have * this timeout value. + * + * Note that the default value of 60 seconds only applies to + * plain #SoupSessions. If you are using #SoupSessionAsync or + * #SoupSessionSync, the default value is 0 (meaning socket I/O + * will not time out). + * + * Not to be confused with #SoupSession:idle-timeout (which is + * the length of time that idle persistent connections will be + * kept open). */ /** * SOUP_SESSION_TIMEOUT: * - * Alias for the #SoupSession:timeout property. (The timeout - * in seconds for socket I/O operations.) + * Alias for the #SoupSession:timeout property, qv. **/ g_object_class_install_property ( object_class, PROP_TIMEOUT, @@ -3225,8 +3372,7 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SOUP_SESSION_ADD_FEATURE: (skip) * - * Alias for the #SoupSession:add-feature property. (Shortcut - * for calling soup_session_add_feature(). + * Alias for the #SoupSession:add-feature property, qv. * * Since: 2.24 **/ @@ -3248,8 +3394,7 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SOUP_SESSION_ADD_FEATURE_BY_TYPE: (skip) * - * Alias for the #SoupSession:add-feature-by-type property. - * (Shortcut for calling soup_session_add_feature_by_type(). + * Alias for the #SoupSession:add-feature-by-type property, qv. * * Since: 2.24 **/ @@ -3271,9 +3416,8 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SOUP_SESSION_REMOVE_FEATURE_BY_TYPE: (skip) * - * Alias for the #SoupSession:remove-feature-by-type - * property. (Shortcut for calling - * soup_session_remove_feature_by_type(). + * Alias for the #SoupSession:remove-feature-by-type property, + * qv. * * Since: 2.24 **/ @@ -3292,14 +3436,14 @@ soup_session_class_init (SoupSessionClass *session_class) * "dav", than a URI of * dav://example.com/path would be treated * identically to http://example.com/path. - * If the value is %NULL, then only "http" is recognized as - * meaning "http". * - * For backward-compatibility reasons, the default value for - * this property is an array containing the single element - * "*", a special value which means that - * any scheme except "https" is considered to be an alias for - * "http". + * In a plain #SoupSession, the default value is %NULL, + * meaning that only "http" is recognized as meaning "http". + * In #SoupSessionAsync and #SoupSessionSync, for backward + * compatibility, the default value is an array containing the + * single element "*", a special value + * which means that any scheme except "https" is considered to + * be an alias for "http". * * See also #SoupSession:https-aliases. * @@ -3308,8 +3452,7 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SOUP_SESSION_HTTP_ALIASES: * - * Alias for the #SoupSession:http-aliases property. (URI - * schemes that will be considered aliases for "http".) + * Alias for the #SoupSession:http-aliases property, qv. * * Since: 2.38 */ @@ -3335,8 +3478,7 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SOUP_SESSION_HTTPS_ALIASES: * - * Alias for the #SoupSession:https-aliases property. (URI - * schemes that will be considered aliases for "https".) + * Alias for the #SoupSession:https-aliases property, qv. * * Since: 2.38 **/ diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index 40f1a8d5..a69c0717 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -81,7 +81,12 @@ GType soup_session_get_type (void); #define SOUP_SESSION_HTTP_ALIASES "http-aliases" #define SOUP_SESSION_HTTPS_ALIASES "https-aliases" -GMainContext *soup_session_get_async_context(SoupSession *session); +SOUP_AVAILABLE_IN_2_42 +SoupSession *soup_session_new (void); + +SOUP_AVAILABLE_IN_2_42 +SoupSession *soup_session_new_with_options (const char *optname1, + ...) G_GNUC_NULL_TERMINATED; void soup_session_queue_message (SoupSession *session, SoupMessage *msg, @@ -103,6 +108,8 @@ void soup_session_cancel_message (SoupSession *session, guint status_code); void soup_session_abort (SoupSession *session); +GMainContext *soup_session_get_async_context(SoupSession *session); + #ifndef LIBSOUP_DISABLE_DEPRECATED /* SOUP_AVAILABLE_IN_2_30 -- this trips up gtkdoc-scan */ SOUP_DEPRECATED_IN_2_38_FOR (soup_session_prefetch_dns) -- cgit v1.2.1 From 6aa0c81d5785f0553418030edf2758c3ef5f0b09 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 14 Dec 2012 15:50:59 -0500 Subject: tests: add session-test Add a test that each of the 3 SoupSession types (plain, async, sync) behaves as expected with soup_session_queue_message(), soup_session_send_message(), and soup_session_cancel_message(). --- tests/Makefile.am | 3 + tests/session-test.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 tests/session-test.c diff --git a/tests/Makefile.am b/tests/Makefile.am index cd132bd6..fdd2c3d1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -29,6 +29,7 @@ noinst_PROGRAMS = \ redirect-test \ requester-test \ resource-test \ + session-test \ simple-httpd \ simple-proxy \ sniffing-test \ @@ -72,6 +73,7 @@ redirect_test_SOURCES = redirect-test.c $(TEST_SRCS) requester_test_SOURCES = requester-test.c $(TEST_SRCS) resource_test_SOURCES = resource-test.c $(TEST_SRCS) server_auth_test_SOURCES = server-auth-test.c $(TEST_SRCS) +session_test_SOURCES = session-test.c $(TEST_SRCS) simple_httpd_SOURCES = simple-httpd.c simple_proxy_SOURCES = simple-proxy.c sniffing_test_SOURCES = sniffing-test.c $(TEST_SRCS) @@ -132,6 +134,7 @@ TESTS = \ redirect-test \ requester-test \ resource-test \ + session-test \ sniffing-test \ socket-test \ ssl-test \ diff --git a/tests/session-test.c b/tests/session-test.c new file mode 100644 index 00000000..3207797e --- /dev/null +++ b/tests/session-test.c @@ -0,0 +1,234 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +static gboolean server_processed_message; +static gboolean timeout; +static GMainLoop *loop; + +static gboolean +timeout_cb (gpointer user_data) +{ + gboolean *timeout = user_data; + + *timeout = TRUE; + return FALSE; +} + +static void +server_handler (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + if (!strcmp (path, "/request-timeout")) { + GMainContext *context = soup_server_get_async_context (server); + GSource *timer; + + timer = g_timeout_source_new (100); + g_source_set_callback (timer, timeout_cb, &timeout, NULL); + g_source_attach (timer, context); + g_source_unref (timer); + } else + server_processed_message = TRUE; + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "ok\r\n", 4); +} + +static void +finished_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + gboolean *finished = user_data; + + *finished = TRUE; +} + +static void +cancel_message_cb (SoupMessage *msg, gpointer session) +{ + soup_session_cancel_message (session, msg, SOUP_STATUS_CANCELLED); + g_main_loop_quit (loop); +} + +static void +do_test_for_session (SoupSession *session, + const char *uri, const char *timeout_uri, + gboolean queue_is_async, + gboolean send_is_blocking, + gboolean cancel_is_immediate) +{ + SoupMessage *msg; + gboolean finished, local_timeout; + guint timeout_id; + + debug_printf (1, " queue_message\n"); + debug_printf (2, " requesting timeout\n"); + msg = soup_message_new ("GET", timeout_uri); + soup_session_send_message (session, msg); + g_object_unref (msg); + + msg = soup_message_new ("GET", uri); + server_processed_message = timeout = finished = FALSE; + soup_session_queue_message (session, msg, finished_cb, &finished); + while (!timeout) + g_usleep (100); + debug_printf (2, " got timeout\n"); + + if (queue_is_async) { + if (server_processed_message) { + debug_printf (1, " message processed without running main loop!\n"); + errors++; + } + debug_printf (2, " waiting for finished\n"); + while (!finished) + g_main_context_iteration (NULL, TRUE); + if (!server_processed_message) { + debug_printf (1, " message finished without server seeing it???\n"); + errors++; + } + } else { + if (!server_processed_message) { + debug_printf (1, " server failed to immediately receive message!\n"); + errors++; + } + debug_printf (2, " waiting for finished\n"); + if (finished) { + debug_printf (1, " message finished without main loop running???\n"); + errors++; + } + while (!finished) + g_main_context_iteration (NULL, TRUE); + } + + debug_printf (1, " send_message\n"); + msg = soup_message_new ("GET", uri); + server_processed_message = local_timeout = FALSE; + timeout_id = g_idle_add_full (G_PRIORITY_HIGH, timeout_cb, &local_timeout, NULL); + soup_session_send_message (session, msg); + + if (!server_processed_message) { + debug_printf (1, " message finished without server seeing it???\n"); + errors++; + } + + if (send_is_blocking) { + if (local_timeout) { + debug_printf (1, " send_message ran main loop!\n"); + errors++; + } + } else { + if (!local_timeout) { + debug_printf (1, " send_message didn't run main loop!\n"); + errors++; + } + } + + if (!local_timeout) + g_source_remove (timeout_id); + + if (!queue_is_async) + return; + + debug_printf (1, " cancel_message\n"); + msg = soup_message_new ("GET", uri); + g_object_ref (msg); + finished = FALSE; + soup_session_queue_message (session, msg, finished_cb, &finished); + g_signal_connect (msg, "wrote-headers", + G_CALLBACK (cancel_message_cb), session); + + loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (loop); + + if (cancel_is_immediate) { + if (!finished) { + debug_printf (1, " cancel did not finish message!\n"); + errors++; + debug_printf (2, " waiting for finished\n"); + while (!finished) + g_main_context_iteration (NULL, TRUE); + } + } else { + if (finished) { + debug_printf (1, " cancel finished message!\n"); + errors++; + } else { + while (!finished) + g_main_context_iteration (NULL, TRUE); + } + } + + if (msg->status_code != SOUP_STATUS_CANCELLED) { + debug_printf (1, " message finished with status %d %s!\n", + msg->status_code, msg->reason_phrase); + errors++; + } + g_object_unref (msg); +} + +static void +do_plain_tests (char *uri, char *timeout_uri) +{ + SoupSession *session; + + debug_printf (1, "SoupSession\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_test_for_session (session, uri, timeout_uri, TRUE, TRUE, FALSE); + soup_test_session_abort_unref (session); +} + +static void +do_async_tests (char *uri, char *timeout_uri) +{ + SoupSession *session; + + debug_printf (1, "\nSoupSessionAsync\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_test_for_session (session, uri, timeout_uri, TRUE, FALSE, TRUE); + soup_test_session_abort_unref (session); +} + +static void +do_sync_tests (char *uri, char *timeout_uri) +{ + SoupSession *session; + + debug_printf (1, "\nSoupSessionSync\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_test_for_session (session, uri, timeout_uri, FALSE, TRUE, FALSE); + soup_test_session_abort_unref (session); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + char *uri, *timeout_uri; + + test_init (argc, argv, NULL); + + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = g_strdup_printf ("http://127.0.0.1:%u", + soup_server_get_port (server)); + timeout_uri = g_strdup_printf ("%s/request-timeout", uri); + + do_plain_tests (uri, timeout_uri); + do_async_tests (uri, timeout_uri); + do_sync_tests (uri, timeout_uri); + + g_free (uri); + g_free (timeout_uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return errors != 0; +} -- cgit v1.2.1 From 9e90b875f77b58c3851d9c6ad5d0cdc052e22c17 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 11 Dec 2012 11:10:45 +0100 Subject: Reorganize NTLM authentication, fix ntlm_auth support Move the auth-managery parts of SoupAuthManagerNTLM down into SoupAuthManager, and the NTLMy parts into SoupAuthNTLM (in preparation for supporting other kinds of connection-based auth such as Negotiate). The reorganization also makes it possible to use SoupAuthNTLM to implement a mock version of /usr/bin/ntlm_auth, so we can extend ntlm-test to test both the built-in-NTLM and external-NTLM codepaths. Doing this reveals that, AFAICT, the external codepath did not previously actually work, because it mis-used G_SPAWN_FILE_AND_ARGV_ZERO and so ended up passing incorrect arguments to /usr/bin/ntlm_auth. --- .gitignore | 1 + libsoup/Makefile.am | 2 - libsoup/soup-auth-manager-ntlm.c | 1359 -------------------------------------- libsoup/soup-auth-manager-ntlm.h | 36 - libsoup/soup-auth-manager.c | 142 +++- libsoup/soup-auth-manager.h | 8 - libsoup/soup-auth-ntlm.c | 1077 +++++++++++++++++++++++++++++- libsoup/soup-auth-ntlm.h | 5 - libsoup/soup-auth.c | 29 +- libsoup/soup-message.c | 10 +- libsoup/soup-session.c | 8 +- tests/Makefile.am | 2 + tests/ntlm-test-helper.c | 103 +++ tests/ntlm-test.c | 60 +- 14 files changed, 1352 insertions(+), 1490 deletions(-) delete mode 100644 libsoup/soup-auth-manager-ntlm.c delete mode 100644 libsoup/soup-auth-manager-ntlm.h create mode 100644 tests/ntlm-test-helper.c diff --git a/.gitignore b/.gitignore index e02235bd..9fbae76f 100644 --- a/.gitignore +++ b/.gitignore @@ -70,6 +70,7 @@ tests/get tests/getbug tests/header-parsing tests/httpd.conf +tests/ntlm-test-helper tests/pull-api tests/simple-httpd tests/simple-proxy diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 59553f04..7a9d6fca 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -107,8 +107,6 @@ libsoup_2_4_la_SOURCES = \ soup-auth-domain-digest.c \ soup-auth-manager.h \ soup-auth-manager.c \ - soup-auth-manager-ntlm.h \ - soup-auth-manager-ntlm.c \ soup-body-input-stream.h \ soup-body-input-stream.c \ soup-body-output-stream.h \ diff --git a/libsoup/soup-auth-manager-ntlm.c b/libsoup/soup-auth-manager-ntlm.c deleted file mode 100644 index ecb9c7c0..00000000 --- a/libsoup/soup-auth-manager-ntlm.c +++ /dev/null @@ -1,1359 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * soup-auth-manager-ntlm.c: NTLM auth manager - * - * Copyright (C) 2001-2007 Novell, Inc. - * Copyright (C) 2008 Red Hat, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include "soup-auth-manager-ntlm.h" -#include "soup.h" -#include "soup-auth-ntlm.h" -#include "soup-message-private.h" - -static void soup_auth_manager_ntlm_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); -static SoupSessionFeatureInterface *soup_auth_manager_parent_feature_interface; - -G_DEFINE_TYPE_WITH_CODE (SoupAuthManagerNTLM, soup_auth_manager_ntlm, SOUP_TYPE_AUTH_MANAGER, - G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, - soup_auth_manager_ntlm_session_feature_init)) - -typedef enum { - SOUP_NTLM_NEW, -#ifdef USE_NTLM_AUTH - SOUP_NTLM_SENT_SSO_REQUEST, - SOUP_NTLM_RECEIVED_SSO_CHALLENGE, - SOUP_NTLM_SENT_SSO_RESPONSE, - SOUP_NTLM_SSO_UNAVAILABLE, - SOUP_NTLM_SSO_FAILED, -#endif - SOUP_NTLM_SENT_REQUEST, - SOUP_NTLM_RECEIVED_CHALLENGE, - SOUP_NTLM_SENT_RESPONSE, - SOUP_NTLM_FAILED -} SoupNTLMState; - -typedef struct { - SoupSocket *socket; - SoupNTLMState state; - char *response_header; - - char *nonce, *domain; - SoupAuth *auth; -#ifdef USE_NTLM_AUTH - char *challenge_header; - int fd_in; - int fd_out; -#endif -} SoupNTLMConnection; - -static void free_ntlm_connection (SoupNTLMConnection *conn); - -typedef struct { - gboolean use_ntlm; - - SoupSession *session; - GHashTable *connections_by_msg; - GHashTable *connections_by_id; -#ifdef USE_NTLM_AUTH - gboolean ntlm_auth_accessible; -#endif -} SoupAuthManagerNTLMPrivate; -#define SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_MANAGER_NTLM, SoupAuthManagerNTLMPrivate)) - -static char *soup_ntlm_request (void); -static gboolean soup_ntlm_parse_challenge (const char *challenge, - char **nonce, - char **default_domain); -static char *soup_ntlm_response (const char *nonce, - const char *user, - const char *password, - const char *host, - const char *domain); -#ifdef USE_NTLM_AUTH -static void sso_ntlm_close (SoupNTLMConnection *conn); -#endif - -static void -soup_auth_manager_ntlm_init (SoupAuthManagerNTLM *ntlm) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm); - - priv->connections_by_id = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify)free_ntlm_connection); - priv->connections_by_msg = g_hash_table_new (NULL, NULL); -#ifdef USE_NTLM_AUTH - priv->ntlm_auth_accessible = (access (NTLM_AUTH, X_OK) == 0); -#endif -} - -static void -free_ntlm_connection (SoupNTLMConnection *conn) -{ - g_free (conn->response_header); - g_free (conn->nonce); - g_free (conn->domain); - g_clear_object (&conn->auth); -#ifdef USE_NTLM_AUTH - g_free (conn->challenge_header); - sso_ntlm_close (conn); -#endif - g_slice_free (SoupNTLMConnection, conn); -} - -static void -soup_auth_manager_ntlm_finalize (GObject *object) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (object); - - g_hash_table_destroy (priv->connections_by_id); - g_hash_table_destroy (priv->connections_by_msg); - - G_OBJECT_CLASS (soup_auth_manager_ntlm_parent_class)->finalize (object); -} - -static void -soup_auth_manager_ntlm_class_init (SoupAuthManagerNTLMClass *auth_manager_ntlm_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (auth_manager_ntlm_class); - - g_type_class_add_private (auth_manager_ntlm_class, sizeof (SoupAuthManagerNTLMPrivate)); - - object_class->finalize = soup_auth_manager_ntlm_finalize; -} - -static void -soup_auth_manager_ntlm_attach (SoupSessionFeature *manager, SoupSession *session) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (manager); - - /* FIXME: should support multiple sessions */ - priv->session = session; - - soup_auth_manager_parent_feature_interface->attach (manager, session); -} - -static void -delete_conn (SoupSocket *socket, gpointer user_data) -{ - SoupAuthManagerNTLMPrivate *priv = user_data; - - g_hash_table_remove (priv->connections_by_id, socket); - g_signal_handlers_disconnect_by_func (socket, delete_conn, priv); -} - -static SoupNTLMConnection * -get_connection (SoupAuthManagerNTLMPrivate *priv, SoupSocket *socket) -{ - SoupNTLMConnection *conn; - - conn = g_hash_table_lookup (priv->connections_by_id, socket); - if (conn) - return conn; - - conn = g_slice_new0 (SoupNTLMConnection); - conn->socket = socket; - conn->state = SOUP_NTLM_NEW; -#ifdef USE_NTLM_AUTH - conn->fd_in = -1; - conn->fd_out = -1; -#endif - g_hash_table_insert (priv->connections_by_id, socket, conn); - - g_signal_connect (socket, "disconnected", - G_CALLBACK (delete_conn), priv); - return conn; -} - -static void -unset_conn (SoupMessage *msg, gpointer user_data) -{ - SoupAuthManagerNTLMPrivate *priv = user_data; - - g_hash_table_remove (priv->connections_by_msg, msg); - g_signal_handlers_disconnect_by_func (msg, unset_conn, priv); -} - -static SoupNTLMConnection * -set_connection_for_msg (SoupAuthManagerNTLMPrivate *priv, SoupMessage *msg, - SoupNTLMConnection *conn) -{ - if (!g_hash_table_lookup (priv->connections_by_msg, msg)) { - g_signal_connect (msg, "finished", - G_CALLBACK (unset_conn), priv); - g_signal_connect (msg, "restarted", - G_CALLBACK (unset_conn), priv); - } - g_hash_table_insert (priv->connections_by_msg, msg, conn); - - return conn; -} - -static SoupNTLMConnection * -get_connection_for_msg (SoupAuthManagerNTLMPrivate *priv, SoupMessage *msg) -{ - return g_hash_table_lookup (priv->connections_by_msg, msg); -} - -#ifdef USE_NTLM_AUTH -static void -sso_ntlm_close (SoupNTLMConnection *conn) -{ - if (conn->fd_in != -1) { - close (conn->fd_in); - conn->fd_in = -1; - } - - if (conn->fd_out != -1) { - close (conn->fd_out); - conn->fd_out = -1; - } -} - -static gboolean -sso_ntlm_initiate (SoupNTLMConnection *conn, SoupAuthManagerNTLMPrivate *priv) -{ - char *username = NULL, *slash, *domain = NULL; - char *argv[9]; - gboolean ret; - - /* Return if ntlm_auth execution process exist already */ - if (conn->fd_in != -1 && conn->fd_out != -1) - return TRUE; - else - /* Clean all sso data before re-initiate */ - sso_ntlm_close (conn); - - if (!priv->ntlm_auth_accessible) - goto done; - - username = getenv ("NTLMUSER"); - if (!username) - username = getenv ("USER"); - if (!username) - goto done; - - slash = strpbrk (username, "\\/"); - if (slash) { - domain = g_strdup (username); - slash = domain + (slash - username); - *slash = '\0'; - username = slash + 1; - } - - argv[0] = NTLM_AUTH; - argv[1] = "--helper-protocol"; - argv[2] = "ntlmssp-client-1"; - argv[3] = "--use-cached-creds"; - argv[4] = "--username"; - argv[5] = username; - argv[6] = domain ? "--domain" : NULL; - argv[7] = domain; - argv[8] = NULL; - /* Spawn child process */ - ret = g_spawn_async_with_pipes (NULL, argv, NULL, - G_SPAWN_FILE_AND_ARGV_ZERO | - G_SPAWN_STDERR_TO_DEV_NULL, - NULL, NULL, - NULL, &conn->fd_in, &conn->fd_out, - NULL, NULL); - if (!ret) - goto done; - g_free (domain); - return TRUE; -done: - g_free (domain); - return FALSE; -} - -static char * -sso_ntlm_response (SoupNTLMConnection *conn, const char *input, SoupNTLMState conn_state) -{ - ssize_t size; - char buf[1024], *response = NULL; - char *tmpbuf = buf; - size_t len_in = strlen (input), len_out = sizeof (buf); - - while (len_in > 0) { - int written = write (conn->fd_in, input, len_in); - if (written == -1) { - /* Interrupted by a signal, retry it */ - if (errno == EINTR) - continue; - /* write failed if other errors happen */ - goto done; - } - input += written; - len_in -= written; - } - /* Read one line */ - while (len_out > 0) { - size = read (conn->fd_out, tmpbuf, len_out); - if (size == -1) { - if (errno == EINTR) - continue; - goto done; - } else if (size == 0) - goto done; - else if (tmpbuf[size - 1] == '\n') { - tmpbuf[size - 1] = '\0'; - goto wrfinish; - } - tmpbuf += size; - len_out -= size; - } - goto done; -wrfinish: - if (g_ascii_strcasecmp (buf, "PW") == 0) { - /* Samba/winbind installed but not configured */ - response = g_strdup ("PW"); - goto done; - } - if (conn_state == SOUP_NTLM_NEW && - g_ascii_strncasecmp (buf, "YR ", 3) != 0) - /* invalid response for type 1 message */ - goto done; - if (conn_state == SOUP_NTLM_RECEIVED_SSO_CHALLENGE && - g_ascii_strncasecmp (buf, "KK ", 3) != 0 && - g_ascii_strncasecmp (buf, "AF ", 3) != 0) - /* invalid response for type 3 message */ - goto done; - - response = g_strdup_printf ("NTLM %.*s", (int)(size - 4), buf + 3); - goto done; -done: - return response; -} -#endif /* USE_NTLM_AUTH */ - -static void -ntlm_authorize_pre (SoupMessage *msg, gpointer ntlm) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm); - SoupNTLMConnection *conn; - const char *val; - char *challenge = NULL; - SoupURI *uri; - - conn = get_connection_for_msg (priv, msg); - if (!conn) - return; - - val = soup_message_headers_get_list (msg->response_headers, - "WWW-Authenticate"); - if (!val) - return; - challenge = soup_auth_manager_extract_challenge (val, "NTLM"); - if (!challenge) - return; - - if (conn->state > SOUP_NTLM_SENT_REQUEST) { - /* We already authenticated, but then got another 401. - * That means "permission denied", so don't try to - * authenticate again. - */ - conn->state = SOUP_NTLM_FAILED; - goto done; - } - - if (!soup_ntlm_parse_challenge (challenge, &conn->nonce, &conn->domain)) { - conn->state = SOUP_NTLM_FAILED; - goto done; - } - - conn->auth = soup_auth_ntlm_new (conn->domain, - soup_message_get_uri (msg)->host); -#ifdef USE_NTLM_AUTH - conn->challenge_header = g_strdup (challenge + 5); - if (conn->state == SOUP_NTLM_SENT_SSO_REQUEST) { - conn->state = SOUP_NTLM_RECEIVED_SSO_CHALLENGE; - goto done; - } -#endif - conn->state = SOUP_NTLM_RECEIVED_CHALLENGE; - - uri = soup_message_get_uri (msg); - if (uri->password) - soup_auth_authenticate (conn->auth, uri->user, uri->password); - else { - soup_auth_manager_emit_authenticate (SOUP_AUTH_MANAGER (ntlm), - msg, conn->auth, FALSE); - } - - done: - g_free (challenge); - - /* Remove the WWW-Authenticate headers so the session won't try - * to do Basic auth too. - */ - soup_message_headers_remove (msg->response_headers, "WWW-Authenticate"); -} - -static void -ntlm_authorize_post (SoupMessage *msg, gpointer ntlm) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm); - SoupNTLMConnection *conn; - const char *username = NULL, *password = NULL; - char *slash, *domain = NULL; - SoupMessageFlags flags; - - conn = get_connection_for_msg (priv, msg); - if (!conn || !conn->auth) - return; - -#ifdef USE_NTLM_AUTH - if (conn->state == SOUP_NTLM_RECEIVED_SSO_CHALLENGE) { - char *input, *header; - input = g_strdup_printf ("TT %s\n", conn->challenge_header); - /* Re-Initiate ntlm_auth process in case it was closed/killed abnormally */ - if (sso_ntlm_initiate (conn, priv)) { - header = sso_ntlm_response (conn, input, conn->state); - g_free (input); - /* Close ntlm_auth as it is no longer needed for current connection */ - sso_ntlm_close (conn); - if (!header) { - conn->state = SOUP_NTLM_SSO_FAILED; - g_free (header); - goto ssofailure; - } - if (!g_ascii_strcasecmp (header, "PW")) { - conn->state = SOUP_NTLM_SSO_UNAVAILABLE; - g_free (header); - goto ssofailure; - } - - conn->response_header = header; - soup_session_requeue_message (priv->session, msg); - goto done; - } - conn->state = SOUP_NTLM_SSO_FAILED; -ssofailure: - soup_session_requeue_message (priv->session, msg); - goto done; - } -#endif - username = soup_auth_ntlm_get_username (conn->auth); - password = soup_auth_ntlm_get_password (conn->auth); - if (!username || !password) - goto done; - - slash = strpbrk (username, "\\/"); - if (slash) { - domain = g_strdup (username); - slash = domain + (slash - username); - *slash = '\0'; - username = slash + 1; - } else - domain = g_strdup (""); - - conn->response_header = soup_ntlm_response (conn->nonce, - username, password, - NULL, domain); - - flags = soup_message_get_flags (msg); - soup_message_set_flags (msg, flags & ~SOUP_MESSAGE_NEW_CONNECTION); - soup_session_requeue_message (priv->session, msg); - -done: - g_free (domain); - g_free (conn->domain); - conn->domain = NULL; - g_free (conn->nonce); - conn->nonce = NULL; - g_object_unref (conn->auth); - conn->auth = NULL; -} - -static void -soup_auth_manager_ntlm_request_queued (SoupSessionFeature *ntlm, - SoupSession *session, - SoupMessage *msg) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm); - - if (priv->use_ntlm) { - soup_message_add_status_code_handler ( - msg, "got_headers", SOUP_STATUS_UNAUTHORIZED, - G_CALLBACK (ntlm_authorize_pre), ntlm); - soup_message_add_status_code_handler ( - msg, "got_body", SOUP_STATUS_UNAUTHORIZED, - G_CALLBACK (ntlm_authorize_post), ntlm); - } - - soup_auth_manager_parent_feature_interface->request_queued (ntlm, session, msg); -} - -static void -soup_auth_manager_ntlm_request_started (SoupSessionFeature *ntlm, - SoupSession *session, - SoupMessage *msg, - SoupSocket *socket) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (ntlm); - SoupNTLMConnection *conn; - char *header = NULL; - - if (!priv->use_ntlm) - goto super; - - conn = get_connection (priv, socket); - set_connection_for_msg (priv, msg, conn); - - switch (conn->state) { - case SOUP_NTLM_NEW: -#ifdef USE_NTLM_AUTH - /* Use Samba's 'winbind' daemon to support NTLM single-sign-on, - * by delegating the NTLM challenge/response protocal to a helper - * in ntlm_auth. - * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html - * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html - * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html - * The preprocessor variable 'USE_NTLM_AUTH' indicates whether - * this feature is enabled. Another one 'NTLM_AUTH' contains absolute - * path of it. - * If NTLM single-sign-on fails, go back to original request handling process. - */ - if (sso_ntlm_initiate (conn, priv)) { - header = sso_ntlm_response (conn, "YR\n", conn->state); - if (header) { - if (g_ascii_strcasecmp (header, "PW") != 0) { - conn->state = SOUP_NTLM_SENT_SSO_REQUEST; - break; - } else { - g_free (header); - header = NULL; - goto ssounavailable; - } - } else { - g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH); - goto ssounavailable; - } - } - case SOUP_NTLM_SSO_UNAVAILABLE: - ssounavailable: -#endif - header = soup_ntlm_request (); - conn->state = SOUP_NTLM_SENT_REQUEST; - break; -#ifdef USE_NTLM_AUTH - case SOUP_NTLM_RECEIVED_SSO_CHALLENGE: - header = conn->response_header; - conn->response_header = NULL; - conn->state = SOUP_NTLM_SENT_SSO_RESPONSE; - break; - case SOUP_NTLM_SSO_FAILED: - /* Restart request without SSO */ - g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH); - header = soup_ntlm_request (); - conn->state = SOUP_NTLM_SENT_REQUEST; - break; -#endif - case SOUP_NTLM_RECEIVED_CHALLENGE: - header = conn->response_header; - conn->response_header = NULL; - conn->state = SOUP_NTLM_SENT_RESPONSE; - break; - default: - break; - } - - if (header && !soup_message_get_auth (msg)) { - soup_message_headers_replace (msg->request_headers, - "Authorization", header); - g_free (header); - } - -super: - soup_auth_manager_parent_feature_interface->request_started (ntlm, session, msg, socket); -} - -static void -soup_auth_manager_ntlm_request_unqueued (SoupSessionFeature *ntlm, - SoupSession *session, - SoupMessage *msg) -{ - g_signal_handlers_disconnect_by_func (msg, ntlm_authorize_pre, ntlm); - g_signal_handlers_disconnect_by_func (msg, ntlm_authorize_post, ntlm); - - soup_auth_manager_parent_feature_interface->request_unqueued (ntlm, session, msg); -} - -static gboolean -soup_auth_manager_ntlm_add_feature (SoupSessionFeature *feature, GType type) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (feature); - - if (type == SOUP_TYPE_AUTH_NTLM) { - priv->use_ntlm = TRUE; - return TRUE; - } - - return soup_auth_manager_parent_feature_interface->add_feature (feature, type); -} - -static gboolean -soup_auth_manager_ntlm_remove_feature (SoupSessionFeature *feature, GType type) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (feature); - - if (type == SOUP_TYPE_AUTH_NTLM) { - priv->use_ntlm = FALSE; - return TRUE; - } - - return soup_auth_manager_parent_feature_interface->remove_feature (feature, type); -} - -static gboolean -soup_auth_manager_ntlm_has_feature (SoupSessionFeature *feature, GType type) -{ - SoupAuthManagerNTLMPrivate *priv = - SOUP_AUTH_MANAGER_NTLM_GET_PRIVATE (feature); - - if (type == SOUP_TYPE_AUTH_NTLM) - return priv->use_ntlm; - - return soup_auth_manager_parent_feature_interface->has_feature (feature, type); -} - -static void -soup_auth_manager_ntlm_session_feature_init (SoupSessionFeatureInterface *feature_interface, - gpointer interface_data) -{ - soup_auth_manager_parent_feature_interface = - g_type_interface_peek_parent (feature_interface); - - feature_interface->attach = soup_auth_manager_ntlm_attach; - feature_interface->request_queued = soup_auth_manager_ntlm_request_queued; - feature_interface->request_started = soup_auth_manager_ntlm_request_started; - feature_interface->request_unqueued = soup_auth_manager_ntlm_request_unqueued; - feature_interface->add_feature = soup_auth_manager_ntlm_add_feature; - feature_interface->remove_feature = soup_auth_manager_ntlm_remove_feature; - feature_interface->has_feature = soup_auth_manager_ntlm_has_feature; -} - -/* NTLM code */ - -static void md4sum (const unsigned char *in, - int nbytes, - unsigned char digest[16]); - -typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */ - -static void deskey (DES_KS, unsigned char *, int); - -static void des (DES_KS, unsigned char *); - -static void setup_schedule (const guchar *key_56, DES_KS ks); - -static void calc_response (const guchar *key, - const guchar *plaintext, - guchar *results); - -#define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \ - "\x4B\x47\x53\x21\x40\x23\x24\x25" \ - "\x00\x00\x00\x00\x00" - -static void -lanmanager_hash (const char *password, guchar hash[21]) -{ - guchar lm_password [15]; - DES_KS ks; - int i; - - for (i = 0; i < 14 && password [i]; i++) - lm_password [i] = toupper ((unsigned char) password [i]); - - for (; i < 15; i++) - lm_password [i] = '\0'; - - memcpy (hash, LM_PASSWORD_MAGIC, 21); - - setup_schedule (lm_password, ks); - des (ks, hash); - - setup_schedule (lm_password + 7, ks); - des (ks, hash + 8); -} - -static void -nt_hash (const char *password, guchar hash[21]) -{ - unsigned char *buf, *p; - - p = buf = g_malloc (strlen (password) * 2); - - while (*password) { - *p++ = *password++; - *p++ = '\0'; - } - - md4sum (buf, p - buf, hash); - memset (hash + 16, 0, 5); - - g_free (buf); -} - -typedef struct { - guint16 length; - guint16 length2; - guint16 offset; - guchar zero_pad[2]; -} NTLMString; - -#define NTLM_CHALLENGE_NONCE_OFFSET 24 -#define NTLM_CHALLENGE_NONCE_LENGTH 8 -#define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12 - -#define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00" -#define NTLM_RESPONSE_FLAGS 0x8201 - -typedef struct { - guchar header[12]; - - NTLMString lm_resp; - NTLMString nt_resp; - NTLMString domain; - NTLMString user; - NTLMString host; - NTLMString session_key; - - guint32 flags; -} NTLMResponse; - -static void -ntlm_set_string (NTLMString *string, int *offset, int len) -{ - string->offset = GUINT16_TO_LE (*offset); - string->length = string->length2 = GUINT16_TO_LE (len); - *offset += len; -} - -static char * -soup_ntlm_request (void) -{ - return g_strdup ("NTLM TlRMTVNTUAABAAAABYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA"); -} - -static gboolean -soup_ntlm_parse_challenge (const char *challenge, - char **nonce, - char **default_domain) -{ - gsize clen; - NTLMString domain; - guchar *chall; - - if (strncmp (challenge, "NTLM ", 5) != 0) - return FALSE; - - chall = g_base64_decode (challenge + 5, &clen); - if (clen < NTLM_CHALLENGE_DOMAIN_STRING_OFFSET || - clen < NTLM_CHALLENGE_NONCE_OFFSET + NTLM_CHALLENGE_NONCE_LENGTH) { - g_free (chall); - return FALSE; - } - - if (default_domain) { - memcpy (&domain, chall + NTLM_CHALLENGE_DOMAIN_STRING_OFFSET, sizeof (domain)); - domain.length = GUINT16_FROM_LE (domain.length); - domain.offset = GUINT16_FROM_LE (domain.offset); - - if (clen < domain.length + domain.offset) { - g_free (chall); - return FALSE; - } - - *default_domain = g_convert ((char *)chall + domain.offset, - domain.length, "UTF-8", "UCS-2LE", - NULL, NULL, NULL); - } - - if (nonce) { - *nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_OFFSET, - NTLM_CHALLENGE_NONCE_LENGTH); - } - - g_free (chall); - return TRUE; -} - -static char * -soup_ntlm_response (const char *nonce, - const char *user, - const char *password, - const char *host, - const char *domain) -{ - int offset; - gsize hlen, dlen, ulen; - guchar hash[21], lm_resp[24], nt_resp[24]; - char *user_conv, *host_conv, *domain_conv; - NTLMResponse resp; - char *out, *p; - int state, save; - - nt_hash (password, hash); - calc_response (hash, (guchar *)nonce, nt_resp); - lanmanager_hash (password, hash); - calc_response (hash, (guchar *)nonce, lm_resp); - - memset (&resp, 0, sizeof (resp)); - memcpy (resp.header, NTLM_RESPONSE_HEADER, sizeof (resp.header)); - resp.flags = GUINT32_TO_LE (NTLM_RESPONSE_FLAGS); - - offset = sizeof (resp); - - if (!host) - host = "UNKNOWN"; - - domain_conv = g_convert (domain, -1, "UCS-2LE", "UTF-8", NULL, &dlen, NULL); - user_conv = g_convert (user, -1, "UCS-2LE", "UTF-8", NULL, &ulen, NULL); - host_conv = g_convert (host, -1, "UCS-2LE", "UTF-8", NULL, &hlen, NULL); - - ntlm_set_string (&resp.domain, &offset, dlen); - ntlm_set_string (&resp.user, &offset, ulen); - ntlm_set_string (&resp.host, &offset, hlen); - ntlm_set_string (&resp.lm_resp, &offset, sizeof (lm_resp)); - ntlm_set_string (&resp.nt_resp, &offset, sizeof (nt_resp)); - - out = g_malloc (((offset + 3) * 4) / 3 + 6); - strncpy (out, "NTLM ", 5); - p = out + 5; - - state = save = 0; - - p += g_base64_encode_step ((const guchar *) &resp, sizeof (resp), - FALSE, p, &state, &save); - p += g_base64_encode_step ((const guchar *) domain_conv, dlen, - FALSE, p, &state, &save); - p += g_base64_encode_step ((const guchar *) user_conv, ulen, - FALSE, p, &state, &save); - p += g_base64_encode_step ((const guchar *) host_conv, hlen, - FALSE, p, &state, &save); - p += g_base64_encode_step (lm_resp, sizeof (lm_resp), - FALSE, p, &state, &save); - p += g_base64_encode_step (nt_resp, sizeof (nt_resp), - FALSE, p, &state, &save); - p += g_base64_encode_close (FALSE, p, &state, &save); - *p = '\0'; - - g_free (domain_conv); - g_free (user_conv); - g_free (host_conv); - - return out; -} - -/* DES utils */ -/* Set up a key schedule based on a 56bit key */ -static void -setup_schedule (const guchar *key_56, DES_KS ks) -{ - guchar key[8]; - int i, c, bit; - - key[0] = (key_56[0]) ; - key[1] = (key_56[1] >> 1) | ((key_56[0] << 7) & 0xFF); - key[2] = (key_56[2] >> 2) | ((key_56[1] << 6) & 0xFF); - key[3] = (key_56[3] >> 3) | ((key_56[2] << 5) & 0xFF); - key[4] = (key_56[4] >> 4) | ((key_56[3] << 4) & 0xFF); - key[5] = (key_56[5] >> 5) | ((key_56[4] << 3) & 0xFF); - key[6] = (key_56[6] >> 6) | ((key_56[5] << 2) & 0xFF); - key[7] = ((key_56[6] << 1) & 0xFF); - - /* Fix parity */ - for (i = 0; i < 8; i++) { - for (c = bit = 0; bit < 8; bit++) - if (key[i] & (1 << bit)) - c++; - if (!(c & 1)) - key[i] ^= 0x01; - } - - deskey (ks, key, 0); -} - -static void -calc_response (const guchar *key, const guchar *plaintext, guchar *results) -{ - DES_KS ks; - - memcpy (results, plaintext, 8); - memcpy (results + 8, plaintext, 8); - memcpy (results + 16, plaintext, 8); - - setup_schedule (key, ks); - des (ks, results); - - setup_schedule (key + 7, ks); - des (ks, results + 8); - - setup_schedule (key + 14, ks); - des (ks, results + 16); -} - - -/* - * MD4 encoder. (The one everyone else uses is not GPL-compatible; - * this is a reimplementation from spec.) This doesn't need to be - * efficient for our purposes, although it would be nice to fix - * it to not malloc()... - */ - -#define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) ) -#define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) ) -#define H(X,Y,Z) ( (X)^(Y)^(Z) ) -#define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) ) - -static void -md4sum (const unsigned char *in, int nbytes, unsigned char digest[16]) -{ - unsigned char *M; - guint32 A, B, C, D, AA, BB, CC, DD, X[16]; - int pbytes, nbits = nbytes * 8, i, j; - - pbytes = (120 - (nbytes % 64)) % 64; - M = alloca (nbytes + pbytes + 8); - memcpy (M, in, nbytes); - memset (M + nbytes, 0, pbytes + 8); - M[nbytes] = 0x80; - M[nbytes + pbytes] = nbits & 0xFF; - M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF; - M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF; - M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF; - - A = 0x67452301; - B = 0xEFCDAB89; - C = 0x98BADCFE; - D = 0x10325476; - - for (i = 0; i < nbytes + pbytes + 8; i += 64) { - for (j = 0; j < 16; j++) { - X[j] = (M[i + j*4]) | - (M[i + j*4 + 1] << 8) | - (M[i + j*4 + 2] << 16) | - (M[i + j*4 + 3] << 24); - } - - AA = A; - BB = B; - CC = C; - DD = D; - - A = ROT (A + F(B, C, D) + X[0], 3); - D = ROT (D + F(A, B, C) + X[1], 7); - C = ROT (C + F(D, A, B) + X[2], 11); - B = ROT (B + F(C, D, A) + X[3], 19); - A = ROT (A + F(B, C, D) + X[4], 3); - D = ROT (D + F(A, B, C) + X[5], 7); - C = ROT (C + F(D, A, B) + X[6], 11); - B = ROT (B + F(C, D, A) + X[7], 19); - A = ROT (A + F(B, C, D) + X[8], 3); - D = ROT (D + F(A, B, C) + X[9], 7); - C = ROT (C + F(D, A, B) + X[10], 11); - B = ROT (B + F(C, D, A) + X[11], 19); - A = ROT (A + F(B, C, D) + X[12], 3); - D = ROT (D + F(A, B, C) + X[13], 7); - C = ROT (C + F(D, A, B) + X[14], 11); - B = ROT (B + F(C, D, A) + X[15], 19); - - A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3); - D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5); - C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9); - B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13); - A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3); - D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5); - C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9); - B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13); - A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3); - D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5); - C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9); - B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13); - A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3); - D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5); - C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9); - B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13); - - A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3); - D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9); - C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11); - B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15); - A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3); - D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9); - C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11); - B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15); - A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3); - D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9); - C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11); - B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15); - A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3); - D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9); - C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11); - B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15); - - A += AA; - B += BB; - C += CC; - D += DD; - } - - digest[0] = A & 0xFF; - digest[1] = (A >> 8) & 0xFF; - digest[2] = (A >> 16) & 0xFF; - digest[3] = (A >> 24) & 0xFF; - digest[4] = B & 0xFF; - digest[5] = (B >> 8) & 0xFF; - digest[6] = (B >> 16) & 0xFF; - digest[7] = (B >> 24) & 0xFF; - digest[8] = C & 0xFF; - digest[9] = (C >> 8) & 0xFF; - digest[10] = (C >> 16) & 0xFF; - digest[11] = (C >> 24) & 0xFF; - digest[12] = D & 0xFF; - digest[13] = (D >> 8) & 0xFF; - digest[14] = (D >> 16) & 0xFF; - digest[15] = (D >> 24) & 0xFF; -} - - -/* Public domain DES implementation from Phil Karn */ -static const guint32 Spbox[8][64] = { - { 0x01010400,0x00000000,0x00010000,0x01010404, - 0x01010004,0x00010404,0x00000004,0x00010000, - 0x00000400,0x01010400,0x01010404,0x00000400, - 0x01000404,0x01010004,0x01000000,0x00000004, - 0x00000404,0x01000400,0x01000400,0x00010400, - 0x00010400,0x01010000,0x01010000,0x01000404, - 0x00010004,0x01000004,0x01000004,0x00010004, - 0x00000000,0x00000404,0x00010404,0x01000000, - 0x00010000,0x01010404,0x00000004,0x01010000, - 0x01010400,0x01000000,0x01000000,0x00000400, - 0x01010004,0x00010000,0x00010400,0x01000004, - 0x00000400,0x00000004,0x01000404,0x00010404, - 0x01010404,0x00010004,0x01010000,0x01000404, - 0x01000004,0x00000404,0x00010404,0x01010400, - 0x00000404,0x01000400,0x01000400,0x00000000, - 0x00010004,0x00010400,0x00000000,0x01010004 }, - { 0x80108020,0x80008000,0x00008000,0x00108020, - 0x00100000,0x00000020,0x80100020,0x80008020, - 0x80000020,0x80108020,0x80108000,0x80000000, - 0x80008000,0x00100000,0x00000020,0x80100020, - 0x00108000,0x00100020,0x80008020,0x00000000, - 0x80000000,0x00008000,0x00108020,0x80100000, - 0x00100020,0x80000020,0x00000000,0x00108000, - 0x00008020,0x80108000,0x80100000,0x00008020, - 0x00000000,0x00108020,0x80100020,0x00100000, - 0x80008020,0x80100000,0x80108000,0x00008000, - 0x80100000,0x80008000,0x00000020,0x80108020, - 0x00108020,0x00000020,0x00008000,0x80000000, - 0x00008020,0x80108000,0x00100000,0x80000020, - 0x00100020,0x80008020,0x80000020,0x00100020, - 0x00108000,0x00000000,0x80008000,0x00008020, - 0x80000000,0x80100020,0x80108020,0x00108000 }, - { 0x00000208,0x08020200,0x00000000,0x08020008, - 0x08000200,0x00000000,0x00020208,0x08000200, - 0x00020008,0x08000008,0x08000008,0x00020000, - 0x08020208,0x00020008,0x08020000,0x00000208, - 0x08000000,0x00000008,0x08020200,0x00000200, - 0x00020200,0x08020000,0x08020008,0x00020208, - 0x08000208,0x00020200,0x00020000,0x08000208, - 0x00000008,0x08020208,0x00000200,0x08000000, - 0x08020200,0x08000000,0x00020008,0x00000208, - 0x00020000,0x08020200,0x08000200,0x00000000, - 0x00000200,0x00020008,0x08020208,0x08000200, - 0x08000008,0x00000200,0x00000000,0x08020008, - 0x08000208,0x00020000,0x08000000,0x08020208, - 0x00000008,0x00020208,0x00020200,0x08000008, - 0x08020000,0x08000208,0x00000208,0x08020000, - 0x00020208,0x00000008,0x08020008,0x00020200 }, - { 0x00802001,0x00002081,0x00002081,0x00000080, - 0x00802080,0x00800081,0x00800001,0x00002001, - 0x00000000,0x00802000,0x00802000,0x00802081, - 0x00000081,0x00000000,0x00800080,0x00800001, - 0x00000001,0x00002000,0x00800000,0x00802001, - 0x00000080,0x00800000,0x00002001,0x00002080, - 0x00800081,0x00000001,0x00002080,0x00800080, - 0x00002000,0x00802080,0x00802081,0x00000081, - 0x00800080,0x00800001,0x00802000,0x00802081, - 0x00000081,0x00000000,0x00000000,0x00802000, - 0x00002080,0x00800080,0x00800081,0x00000001, - 0x00802001,0x00002081,0x00002081,0x00000080, - 0x00802081,0x00000081,0x00000001,0x00002000, - 0x00800001,0x00002001,0x00802080,0x00800081, - 0x00002001,0x00002080,0x00800000,0x00802001, - 0x00000080,0x00800000,0x00002000,0x00802080 }, - { 0x00000100,0x02080100,0x02080000,0x42000100, - 0x00080000,0x00000100,0x40000000,0x02080000, - 0x40080100,0x00080000,0x02000100,0x40080100, - 0x42000100,0x42080000,0x00080100,0x40000000, - 0x02000000,0x40080000,0x40080000,0x00000000, - 0x40000100,0x42080100,0x42080100,0x02000100, - 0x42080000,0x40000100,0x00000000,0x42000000, - 0x02080100,0x02000000,0x42000000,0x00080100, - 0x00080000,0x42000100,0x00000100,0x02000000, - 0x40000000,0x02080000,0x42000100,0x40080100, - 0x02000100,0x40000000,0x42080000,0x02080100, - 0x40080100,0x00000100,0x02000000,0x42080000, - 0x42080100,0x00080100,0x42000000,0x42080100, - 0x02080000,0x00000000,0x40080000,0x42000000, - 0x00080100,0x02000100,0x40000100,0x00080000, - 0x00000000,0x40080000,0x02080100,0x40000100 }, - { 0x20000010,0x20400000,0x00004000,0x20404010, - 0x20400000,0x00000010,0x20404010,0x00400000, - 0x20004000,0x00404010,0x00400000,0x20000010, - 0x00400010,0x20004000,0x20000000,0x00004010, - 0x00000000,0x00400010,0x20004010,0x00004000, - 0x00404000,0x20004010,0x00000010,0x20400010, - 0x20400010,0x00000000,0x00404010,0x20404000, - 0x00004010,0x00404000,0x20404000,0x20000000, - 0x20004000,0x00000010,0x20400010,0x00404000, - 0x20404010,0x00400000,0x00004010,0x20000010, - 0x00400000,0x20004000,0x20000000,0x00004010, - 0x20000010,0x20404010,0x00404000,0x20400000, - 0x00404010,0x20404000,0x00000000,0x20400010, - 0x00000010,0x00004000,0x20400000,0x00404010, - 0x00004000,0x00400010,0x20004010,0x00000000, - 0x20404000,0x20000000,0x00400010,0x20004010 }, - { 0x00200000,0x04200002,0x04000802,0x00000000, - 0x00000800,0x04000802,0x00200802,0x04200800, - 0x04200802,0x00200000,0x00000000,0x04000002, - 0x00000002,0x04000000,0x04200002,0x00000802, - 0x04000800,0x00200802,0x00200002,0x04000800, - 0x04000002,0x04200000,0x04200800,0x00200002, - 0x04200000,0x00000800,0x00000802,0x04200802, - 0x00200800,0x00000002,0x04000000,0x00200800, - 0x04000000,0x00200800,0x00200000,0x04000802, - 0x04000802,0x04200002,0x04200002,0x00000002, - 0x00200002,0x04000000,0x04000800,0x00200000, - 0x04200800,0x00000802,0x00200802,0x04200800, - 0x00000802,0x04000002,0x04200802,0x04200000, - 0x00200800,0x00000000,0x00000002,0x04200802, - 0x00000000,0x00200802,0x04200000,0x00000800, - 0x04000002,0x04000800,0x00000800,0x00200002 }, - { 0x10001040,0x00001000,0x00040000,0x10041040, - 0x10000000,0x10001040,0x00000040,0x10000000, - 0x00040040,0x10040000,0x10041040,0x00041000, - 0x10041000,0x00041040,0x00001000,0x00000040, - 0x10040000,0x10000040,0x10001000,0x00001040, - 0x00041000,0x00040040,0x10040040,0x10041000, - 0x00001040,0x00000000,0x00000000,0x10040040, - 0x10000040,0x10001000,0x00041040,0x00040000, - 0x00041040,0x00040000,0x10041000,0x00001000, - 0x00000040,0x10040040,0x00001000,0x00041040, - 0x10001000,0x00000040,0x10000040,0x10040000, - 0x10040040,0x10000000,0x00040000,0x10001040, - 0x00000000,0x10041040,0x00040040,0x10000040, - 0x10040000,0x10001000,0x10001040,0x00000000, - 0x10041040,0x00041000,0x00041000,0x00001040, - 0x00001040,0x00040040,0x10000000,0x10041000 } -}; - -#undef F -#define F(l,r,key){\ - work = ((r >> 4) | (r << 28)) ^ key[0];\ - l ^= Spbox[6][work & 0x3f];\ - l ^= Spbox[4][(work >> 8) & 0x3f];\ - l ^= Spbox[2][(work >> 16) & 0x3f];\ - l ^= Spbox[0][(work >> 24) & 0x3f];\ - work = r ^ key[1];\ - l ^= Spbox[7][work & 0x3f];\ - l ^= Spbox[5][(work >> 8) & 0x3f];\ - l ^= Spbox[3][(work >> 16) & 0x3f];\ - l ^= Spbox[1][(work >> 24) & 0x3f];\ -} -/* Encrypt or decrypt a block of data in ECB mode */ -static void -des (guint32 ks[16][2], unsigned char block[8]) -{ - guint32 left,right,work; - - /* Read input block and place in left/right in big-endian order */ - left = ((guint32)block[0] << 24) - | ((guint32)block[1] << 16) - | ((guint32)block[2] << 8) - | (guint32)block[3]; - right = ((guint32)block[4] << 24) - | ((guint32)block[5] << 16) - | ((guint32)block[6] << 8) - | (guint32)block[7]; - - /* Hoey's clever initial permutation algorithm, from Outerbridge - * (see Schneier p 478) - * - * The convention here is the same as Outerbridge: rotate each - * register left by 1 bit, i.e., so that "left" contains permuted - * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32 - * (using origin-1 numbering as in the FIPS). This allows us to avoid - * one of the two rotates that would otherwise be required in each of - * the 16 rounds. - */ - work = ((left >> 4) ^ right) & 0x0f0f0f0f; - right ^= work; - left ^= work << 4; - work = ((left >> 16) ^ right) & 0xffff; - right ^= work; - left ^= work << 16; - work = ((right >> 2) ^ left) & 0x33333333; - left ^= work; - right ^= (work << 2); - work = ((right >> 8) ^ left) & 0xff00ff; - left ^= work; - right ^= (work << 8); - right = (right << 1) | (right >> 31); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left << 1) | (left >> 31); - - /* Now do the 16 rounds */ - F(left,right,ks[0]); - F(right,left,ks[1]); - F(left,right,ks[2]); - F(right,left,ks[3]); - F(left,right,ks[4]); - F(right,left,ks[5]); - F(left,right,ks[6]); - F(right,left,ks[7]); - F(left,right,ks[8]); - F(right,left,ks[9]); - F(left,right,ks[10]); - F(right,left,ks[11]); - F(left,right,ks[12]); - F(right,left,ks[13]); - F(left,right,ks[14]); - F(right,left,ks[15]); - - /* Inverse permutation, also from Hoey via Outerbridge and Schneier */ - right = (right << 31) | (right >> 1); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left >> 1) | (left << 31); - work = ((left >> 8) ^ right) & 0xff00ff; - right ^= work; - left ^= work << 8; - work = ((left >> 2) ^ right) & 0x33333333; - right ^= work; - left ^= work << 2; - work = ((right >> 16) ^ left) & 0xffff; - left ^= work; - right ^= work << 16; - work = ((right >> 4) ^ left) & 0x0f0f0f0f; - left ^= work; - right ^= work << 4; - - /* Put the block back into the user's buffer with final swap */ - block[0] = right >> 24; - block[1] = right >> 16; - block[2] = right >> 8; - block[3] = right; - block[4] = left >> 24; - block[5] = left >> 16; - block[6] = left >> 8; - block[7] = left; -} - -/* Key schedule-related tables from FIPS-46 */ - -/* permuted choice table (key) */ -static const unsigned char pc1[] = { - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 -}; - -/* number left rotations of pc1 */ -static const unsigned char totrot[] = { - 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 -}; - -/* permuted choice key (table) */ -static const unsigned char pc2[] = { - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 -}; - -/* End of DES-defined tables */ - - -/* bit 0 is left-most in byte */ -static const int bytebit[] = { - 0200,0100,040,020,010,04,02,01 -}; - - -/* Generate key schedule for encryption or decryption - * depending on the value of "decrypt" - */ -static void -deskey (DES_KS k, unsigned char *key, int decrypt) -{ - unsigned char pc1m[56]; /* place to modify pc1 into */ - unsigned char pcr[56]; /* place to rotate pc1 into */ - register int i,j,l; - int m; - unsigned char ks[8]; - - for (j=0; j<56; j++) { /* convert pc1 to bits of key */ - l=pc1[j]-1; /* integer bit location */ - m = l & 07; /* find bit */ - pc1m[j]=(key[l>>3] & /* find which key byte l is in */ - bytebit[m]) /* and which bit of that byte */ - ? 1 : 0; /* and store 1-bit result */ - } - for (i=0; i<16; i++) { /* key chunk for each iteration */ - memset(ks,0,sizeof(ks)); /* Clear key schedule */ - for (j=0; j<56; j++) /* rotate pc1 the right amount */ - pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28]; - /* rotate left and right halves independently */ - for (j=0; j<48; j++){ /* select bits individually */ - /* check bit that goes to ks[j] */ - if (pcr[pc2[j]-1]){ - /* mask it in if it's there */ - l= j % 6; - ks[j/6] |= bytebit[l] >> 2; - } - } - /* Now convert to packed odd/even interleaved form */ - k[i][0] = ((guint32)ks[0] << 24) - | ((guint32)ks[2] << 16) - | ((guint32)ks[4] << 8) - | ((guint32)ks[6]); - k[i][1] = ((guint32)ks[1] << 24) - | ((guint32)ks[3] << 16) - | ((guint32)ks[5] << 8) - | ((guint32)ks[7]); - } -} diff --git a/libsoup/soup-auth-manager-ntlm.h b/libsoup/soup-auth-manager-ntlm.h deleted file mode 100644 index f0b4f575..00000000 --- a/libsoup/soup-auth-manager-ntlm.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2008 Red Hat, Inc. - */ - -#ifndef SOUP_AUTH_MANAGER_NTLM_H -#define SOUP_AUTH_MANAGER_NTLM_H 1 - -#include "soup-auth-manager.h" - -G_BEGIN_DECLS - -#define SOUP_TYPE_AUTH_MANAGER_NTLM (soup_auth_manager_ntlm_get_type ()) -#define SOUP_AUTH_MANAGER_NTLM(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_MANAGER_NTLM, SoupAuthManagerNTLM)) -#define SOUP_AUTH_MANAGER_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_MANAGER_NTLM, SoupAuthManagerNTLMClass)) -#define SOUP_IS_AUTH_MANAGER_NTLM(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_AUTH_MANAGER_NTLM)) -#define SOUP_IS_AUTH_MANAGER_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_MANAGER_NTLM)) -#define SOUP_AUTH_MANAGER_NTLM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_MANAGER_NTLM, SoupAuthManagerNTLMClass)) - -typedef struct { - SoupAuthManager parent; - -} SoupAuthManagerNTLM; - -typedef struct { - SoupAuthManagerClass parent_class; - -} SoupAuthManagerNTLMClass; - -#define SOUP_AUTH_MANAGER_NTLM_USE_NTLM "use-ntlm" - -GType soup_auth_manager_ntlm_get_type (void); - -G_END_DECLS - -#endif /* SOUP_AUTH_MANAGER_NTLM_NTLM_H */ diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index 2a2030cb..d284826e 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -36,9 +36,13 @@ G_DEFINE_TYPE_WITH_CODE (SoupAuthManager, soup_auth_manager, G_TYPE_OBJECT, typedef struct { SoupSession *session; GPtrArray *auth_types; + gboolean has_ntlm; SoupAuth *proxy_auth; GHashTable *auth_hosts; + + GHashTable *connauths; + GHashTable *sockets_by_msg; } SoupAuthManagerPrivate; #define SOUP_AUTH_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerPrivate)) @@ -60,6 +64,10 @@ soup_auth_manager_init (SoupAuthManager *manager) soup_uri_host_equal, NULL, (GDestroyNotify)soup_auth_host_free); + + priv->connauths = g_hash_table_new_full (NULL, NULL, + NULL, g_object_unref); + priv->sockets_by_msg = g_hash_table_new (NULL, NULL); } static void @@ -73,6 +81,9 @@ soup_auth_manager_finalize (GObject *object) g_clear_object (&priv->proxy_auth); + g_hash_table_destroy (priv->connauths); + g_hash_table_destroy (priv->sockets_by_msg); + G_OBJECT_CLASS (soup_auth_manager_parent_class)->finalize (object); } @@ -120,6 +131,10 @@ soup_auth_manager_add_feature (SoupSessionFeature *feature, GType type) auth_class = g_type_class_ref (type); g_ptr_array_add (priv->auth_types, auth_class); g_ptr_array_sort (priv->auth_types, auth_type_compare_func); + + if (type == SOUP_TYPE_AUTH_NTLM) + priv->has_ntlm = TRUE; + return TRUE; } @@ -134,8 +149,12 @@ soup_auth_manager_remove_feature (SoupSessionFeature *feature, GType type) return FALSE; auth_class = g_type_class_peek (type); + for (i = 0; i < priv->auth_types->len; i++) { if (priv->auth_types->pdata[i] == (gpointer)auth_class) { + if (type == SOUP_TYPE_AUTH_NTLM) + priv->has_ntlm = FALSE; + g_ptr_array_remove_index (priv->auth_types, i); return TRUE; } @@ -162,13 +181,6 @@ soup_auth_manager_has_feature (SoupSessionFeature *feature, GType type) return FALSE; } -void -soup_auth_manager_emit_authenticate (SoupAuthManager *manager, SoupMessage *msg, - SoupAuth *auth, gboolean retrying) -{ - g_signal_emit (manager, signals[AUTHENTICATE], 0, msg, auth, retrying); -} - static void soup_auth_manager_attach (SoupSessionFeature *manager, SoupSession *session) { @@ -252,7 +264,7 @@ next_challenge_start (GSList *items) return NULL; } -char * +static char * soup_auth_manager_extract_challenge (const char *challenges, const char *scheme) { GSList *items, *i, *next; @@ -416,15 +428,77 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, soup_uri_set_password (uri, NULL); soup_uri_set_user (uri, NULL); } else if (!soup_auth_is_authenticated (auth) && can_interact) { - soup_auth_manager_emit_authenticate (manager, msg, auth, - prior_auth_failed); + g_signal_emit (manager, signals[AUTHENTICATE], 0, + msg, auth, prior_auth_failed); } return soup_auth_is_authenticated (auth); } static void -update_auth (SoupMessage *msg, gpointer manager) +delete_connauth (SoupSocket *socket, gpointer user_data) +{ + SoupAuthManagerPrivate *priv = user_data; + + g_hash_table_remove (priv->connauths, socket); + g_signal_handlers_disconnect_by_func (socket, delete_connauth, priv); +} + +static SoupAuth * +get_connauth (SoupAuthManagerPrivate *priv, SoupSocket *socket) +{ + SoupAuth *auth; + + if (!priv->has_ntlm) + return NULL; + + auth = g_hash_table_lookup (priv->connauths, socket); + if (!auth) { + auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL); + g_hash_table_insert (priv->connauths, socket, auth); + g_signal_connect (socket, "disconnected", + G_CALLBACK (delete_connauth), priv); + } + + return auth; +} + +static void +unset_socket (SoupMessage *msg, gpointer user_data) +{ + SoupAuthManagerPrivate *priv = user_data; + + g_hash_table_remove (priv->sockets_by_msg, msg); + g_signal_handlers_disconnect_by_func (msg, unset_socket, priv); +} + +static void +set_socket_for_msg (SoupAuthManagerPrivate *priv, + SoupMessage *msg, SoupSocket *sock) +{ + if (!g_hash_table_lookup (priv->sockets_by_msg, msg)) { + g_signal_connect (msg, "finished", + G_CALLBACK (unset_socket), priv); + g_signal_connect (msg, "restarted", + G_CALLBACK (unset_socket), priv); + } + g_hash_table_insert (priv->sockets_by_msg, msg, sock); +} + +static SoupAuth * +get_connauth_for_msg (SoupAuthManagerPrivate *priv, SoupMessage *msg) +{ + SoupSocket *sock; + + sock = g_hash_table_lookup (priv->sockets_by_msg, msg); + if (sock) + return g_hash_table_lookup (priv->connauths, sock); + else + return NULL; +} + +static void +auth_got_headers (SoupMessage *msg, gpointer manager) { SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); SoupAuthHost *host; @@ -434,6 +508,20 @@ update_auth (SoupMessage *msg, gpointer manager) GSList *pspace, *p; gboolean prior_auth_failed = FALSE; + auth = get_connauth_for_msg (priv, msg); + if (auth) { + const char *header; + + header = auth_header_for_message (msg); + if (header && soup_auth_update (auth, msg, header)) { + if (!soup_auth_is_authenticated (auth)) { + g_signal_emit (manager, signals[AUTHENTICATE], 0, + msg, auth, FALSE); + } + return; + } + } + host = get_auth_host_for_message (priv, msg); /* See if we used auth last time */ @@ -492,17 +580,25 @@ update_auth (SoupMessage *msg, gpointer manager) } static void -requeue_if_authenticated (SoupMessage *msg, gpointer manager) +auth_got_body (SoupMessage *msg, gpointer manager) { SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); - SoupAuth *auth = lookup_auth (priv, msg); + SoupAuth *auth; + + auth = get_connauth_for_msg (priv, msg); + if (auth && soup_auth_is_authenticated (auth)) { + SoupMessageFlags flags; + flags = soup_message_get_flags (msg); + soup_message_set_flags (msg, flags & ~SOUP_MESSAGE_NEW_CONNECTION); + } else + auth = lookup_auth (priv, msg); if (auth && soup_auth_is_authenticated (auth)) soup_session_requeue_message (priv->session, msg); } static void -update_proxy_auth (SoupMessage *msg, gpointer manager) +proxy_auth_got_headers (SoupMessage *msg, gpointer manager) { SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); SoupAuth *prior_auth; @@ -527,7 +623,7 @@ update_proxy_auth (SoupMessage *msg, gpointer manager) } static void -requeue_if_proxy_authenticated (SoupMessage *msg, gpointer manager) +proxy_auth_got_body (SoupMessage *msg, gpointer manager) { SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); SoupAuth *auth = priv->proxy_auth; @@ -543,17 +639,17 @@ soup_auth_manager_request_queued (SoupSessionFeature *manager, { soup_message_add_status_code_handler ( msg, "got_headers", SOUP_STATUS_UNAUTHORIZED, - G_CALLBACK (update_auth), manager); + G_CALLBACK (auth_got_headers), manager); soup_message_add_status_code_handler ( msg, "got_body", SOUP_STATUS_UNAUTHORIZED, - G_CALLBACK (requeue_if_authenticated), manager); + G_CALLBACK (auth_got_body), manager); soup_message_add_status_code_handler ( msg, "got_headers", SOUP_STATUS_PROXY_UNAUTHORIZED, - G_CALLBACK (update_proxy_auth), manager); + G_CALLBACK (proxy_auth_got_headers), manager); soup_message_add_status_code_handler ( msg, "got_body", SOUP_STATUS_PROXY_UNAUTHORIZED, - G_CALLBACK (requeue_if_proxy_authenticated), manager); + G_CALLBACK (proxy_auth_got_body), manager); } static void @@ -566,9 +662,13 @@ soup_auth_manager_request_started (SoupSessionFeature *feature, SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); SoupAuth *auth; + set_socket_for_msg (priv, msg, socket); auth = lookup_auth (priv, msg); - if (!auth || !authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE)) - auth = NULL; + if (auth) { + if (!authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE)) + auth = NULL; + } else + auth = get_connauth (priv, socket); soup_message_set_auth (msg, auth); auth = priv->proxy_auth; diff --git a/libsoup/soup-auth-manager.h b/libsoup/soup-auth-manager.h index d82fbb1d..a4ee3165 100644 --- a/libsoup/soup-auth-manager.h +++ b/libsoup/soup-auth-manager.h @@ -32,14 +32,6 @@ typedef struct { GType soup_auth_manager_get_type (void); -void soup_auth_manager_emit_authenticate (SoupAuthManager *manager, - SoupMessage *msg, - SoupAuth *auth, - gboolean retrying); - -char *soup_auth_manager_extract_challenge (const char *challenges, - const char *scheme); - G_END_DECLS #endif /* SOUP_AUTH_MANAGER_H */ diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index dc24d51f..11b75681 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -9,16 +9,71 @@ #include #endif +#include +#include #include +#include #include "soup-auth-ntlm.h" #include "soup.h" +#include "soup-message-private.h" + +static void soup_ntlm_lanmanager_hash (const char *password, + guchar hash[21]); +static void soup_ntlm_nt_hash (const char *password, + guchar hash[21]); +static char *soup_ntlm_request (void); +static gboolean soup_ntlm_parse_challenge (const char *challenge, + char **nonce, + char **default_domain); +static char *soup_ntlm_response (const char *nonce, + const char *user, + guchar nt_hash[21], + guchar lm_hash[21], + const char *host, + const char *domain); + +typedef enum { + SOUP_NTLM_NEW, +#ifdef USE_NTLM_AUTH + SOUP_NTLM_SENT_SSO_REQUEST, + SOUP_NTLM_RECEIVED_SSO_CHALLENGE, + SOUP_NTLM_SENT_SSO_RESPONSE, + SOUP_NTLM_SSO_UNAVAILABLE, + SOUP_NTLM_SSO_FAILED, +#endif + SOUP_NTLM_SENT_REQUEST, + SOUP_NTLM_RECEIVED_CHALLENGE, + SOUP_NTLM_SENT_RESPONSE, + SOUP_NTLM_FAILED +} SoupNTLMState; typedef struct { - char *username, *password; + SoupNTLMState state; + char *username; + guchar nt_hash[21], lm_hash[21]; + char *nonce, *domain; + char *response_header; + +#ifdef USE_NTLM_AUTH + /* Use Samba's 'winbind' daemon to support NTLM single-sign-on, + * by delegating the NTLM challenge/response protocal to a helper + * in ntlm_auth. + * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html + * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html + * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html + */ + int fd_in; + int fd_out; +#endif } SoupAuthNTLMPrivate; #define SOUP_AUTH_NTLM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMPrivate)) +#ifdef USE_NTLM_AUTH +static gboolean ntlm_auth_available, ntlm_auth_debug; +static void sso_ntlm_close (SoupAuthNTLMPrivate *priv); +#endif + /** * SOUP_TYPE_AUTH_NTLM: * @@ -35,6 +90,30 @@ G_DEFINE_TYPE (SoupAuthNTLM, soup_auth_ntlm, SOUP_TYPE_AUTH) static void soup_auth_ntlm_init (SoupAuthNTLM *ntlm) { + SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (ntlm); +#ifdef USE_NTLM_AUTH + const char *username = NULL, *slash; +#endif + + priv->state = SOUP_NTLM_NEW; + +#ifdef USE_NTLM_AUTH + priv->fd_in = -1; + priv->fd_out = -1; + + username = getenv ("NTLMUSER"); + if (!username) + username = g_get_user_name (); + + slash = strpbrk (username, "\\/"); + if (slash) { + priv->username = g_strdup (slash + 1); + priv->domain = g_strndup (username, slash - username); + } else { + priv->username = g_strdup (username); + priv->domain = NULL; + } +#endif } static void @@ -43,31 +122,212 @@ soup_auth_ntlm_finalize (GObject *object) SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (object); g_free (priv->username); - if (priv->password) { - memset (priv->password, 0, strlen (priv->password)); - g_free (priv->password); - } + g_free (priv->domain); + + memset (priv->nt_hash, 0, sizeof (priv->nt_hash)); + memset (priv->lm_hash, 0, sizeof (priv->lm_hash)); + + g_free (priv->nonce); + g_free (priv->response_header); + +#ifdef USE_NTLM_AUTH + sso_ntlm_close (priv); +#endif G_OBJECT_CLASS (soup_auth_ntlm_parent_class)->finalize (object); } -SoupAuth * -soup_auth_ntlm_new (const char *realm, const char *host) +#ifdef USE_NTLM_AUTH +static void +sso_ntlm_close (SoupAuthNTLMPrivate *priv) { - SoupAuth *auth; + if (priv->fd_in != -1) { + close (priv->fd_in); + priv->fd_in = -1; + } - auth = g_object_new (SOUP_TYPE_AUTH_NTLM, - SOUP_AUTH_REALM, realm, - SOUP_AUTH_HOST, host, - NULL); - return auth; + if (priv->fd_out != -1) { + close (priv->fd_out); + priv->fd_out = -1; + } } +static gboolean +sso_ntlm_initiate (SoupAuthNTLMPrivate *priv) +{ + char *argv[9]; + gboolean ret; + + if (!ntlm_auth_available && !ntlm_auth_debug) + return FALSE; + + /* Return if ntlm_auth execution process exist already */ + if (priv->fd_in != -1 && priv->fd_out != -1) + return TRUE; + else { + /* Clean all sso data before re-initiate */ + sso_ntlm_close (priv); + } + + if (ntlm_auth_debug) { + argv[0] = (char *) g_getenv ("SOUP_NTLM_AUTH_DEBUG"); + if (!*argv[0]) + return FALSE; + } else + argv[0] = NTLM_AUTH; + argv[1] = "--helper-protocol"; + argv[2] = "ntlmssp-client-1"; + argv[3] = "--use-cached-creds"; + argv[4] = "--username"; + argv[5] = priv->username; + argv[6] = priv->domain ? "--domain" : NULL; + argv[7] = priv->domain; + argv[8] = NULL; + + ret = g_spawn_async_with_pipes (NULL, argv, NULL, + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + NULL, &priv->fd_in, &priv->fd_out, + NULL, NULL); + return ret; +} + +static char * +sso_ntlm_response (SoupAuthNTLMPrivate *priv, const char *input, SoupNTLMState conn_state) +{ + ssize_t size; + char buf[1024]; + char *tmpbuf = buf; + size_t len_in = strlen (input), len_out = sizeof (buf); + + while (len_in > 0) { + int written = write (priv->fd_in, input, len_in); + if (written == -1) { + if (errno == EINTR) + continue; + /* write failed if other errors happen */ + return NULL; + } + input += written; + len_in -= written; + } + /* Read one line */ + while (len_out > 0) { + size = read (priv->fd_out, tmpbuf, len_out); + if (size == -1) { + if (errno == EINTR) + continue; + return NULL; + } else if (size == 0) + return NULL; + else if (tmpbuf[size - 1] == '\n') { + tmpbuf[size - 1] = '\0'; + goto wrfinish; + } + tmpbuf += size; + len_out -= size; + } + return NULL; + +wrfinish: + if (g_ascii_strcasecmp (buf, "PW") == 0) { + /* Samba/winbind installed but not configured */ + return g_strdup ("PW"); + } + if (conn_state == SOUP_NTLM_NEW && + g_ascii_strncasecmp (buf, "YR ", 3) != 0) { + /* invalid response for type 1 message */ + return NULL; + } + if (conn_state == SOUP_NTLM_RECEIVED_SSO_CHALLENGE && + g_ascii_strncasecmp (buf, "KK ", 3) != 0 && + g_ascii_strncasecmp (buf, "AF ", 3) != 0) { + /* invalid response for type 3 message */ + return NULL; + } + + return g_strdup_printf ("NTLM %.*s", (int)(size - 4), buf + 3); +} +#endif /* USE_NTLM_AUTH */ + static gboolean soup_auth_ntlm_update (SoupAuth *auth, SoupMessage *msg, GHashTable *auth_params) { - g_return_val_if_reached (FALSE); + SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); + GHashTableIter iter; + gpointer key, value; + char *header; + gboolean success = TRUE; + + if (priv->state > SOUP_NTLM_SENT_REQUEST) { + /* We already authenticated, but then got another 401. + * That means "permission denied", so don't try to + * authenticate again. + */ + priv->state = SOUP_NTLM_FAILED; + return FALSE; + } + + /* The header will be something like "NTLM blahblahblah===", + * which soup_auth_update() will parse as + * "blahblahblah" = "==". Undo that. + */ + g_hash_table_iter_init (&iter, auth_params); + if (!g_hash_table_iter_next (&iter, &key, &value)) + return FALSE; + if (value) + header = g_strdup_printf ("%s=%s", (char *)key, (char *)value); + else + header = g_strdup (key); + + if (!soup_ntlm_parse_challenge (header, &priv->nonce, &priv->domain)) { + g_free (header); + priv->state = SOUP_NTLM_FAILED; + return FALSE; + } + +#ifdef USE_NTLM_AUTH + if (priv->state == SOUP_NTLM_SENT_SSO_REQUEST) { + char *input, *response; + + /* Re-Initiate ntlm_auth process in case it was closed/killed abnormally */ + if (!sso_ntlm_initiate (priv)) { + priv->state = SOUP_NTLM_SSO_FAILED; + success = FALSE; + goto out; + } + + input = g_strdup_printf ("TT %s\n", header); + response = sso_ntlm_response (priv, input, priv->state); + sso_ntlm_close (priv); + g_free (input); + + if (!response) { + priv->state = SOUP_NTLM_SSO_FAILED; + success = FALSE; + } else if (!g_ascii_strcasecmp (header, "PW")) { + priv->state = SOUP_NTLM_SSO_UNAVAILABLE; + g_free (response); + success = FALSE; + } else { + priv->state = SOUP_NTLM_RECEIVED_SSO_CHALLENGE; + priv->response_header = response; + } + } + out: +#endif + + g_free (header); + + if (priv->state == SOUP_NTLM_SENT_REQUEST) + priv->state = SOUP_NTLM_RECEIVED_CHALLENGE; + + g_object_set (G_OBJECT (auth), + SOUP_AUTH_REALM, priv->domain, + SOUP_AUTH_HOST, soup_message_get_uri (msg)->host, + NULL); + return success; } static GSList * @@ -81,24 +341,99 @@ soup_auth_ntlm_authenticate (SoupAuth *auth, const char *username, const char *password) { SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); + const char *slash, *domain; g_return_if_fail (username != NULL); g_return_if_fail (password != NULL); + g_return_if_fail (priv->nonce != NULL); + + slash = strpbrk (username, "\\/"); + if (slash) { + if (priv->domain) + g_free (priv->domain); + domain = priv->domain = g_strndup (username, slash - username); + priv->username = g_strdup (slash + 1); + } else { + domain = ""; + priv->username = g_strdup (username); + } + + soup_ntlm_nt_hash (password, priv->nt_hash); + soup_ntlm_lanmanager_hash (password, priv->lm_hash); + + priv->response_header = soup_ntlm_response (priv->nonce, + priv->username, + priv->nt_hash, + priv->lm_hash, + NULL, + domain); - priv->username = g_strdup (username); - priv->password = g_strdup (password); + g_free (priv->nonce); + priv->nonce = NULL; } static gboolean soup_auth_ntlm_is_authenticated (SoupAuth *auth) { - return SOUP_AUTH_NTLM_GET_PRIVATE (auth)->password != NULL; + return SOUP_AUTH_NTLM_GET_PRIVATE (auth)->username != NULL && + SOUP_AUTH_NTLM_GET_PRIVATE (auth)->response_header != NULL; } static char * soup_auth_ntlm_get_authorization (SoupAuth *auth, SoupMessage *msg) { - g_return_val_if_reached (NULL); + SoupAuthNTLMPrivate *priv = + SOUP_AUTH_NTLM_GET_PRIVATE (auth); + char *header = NULL; + + switch (priv->state) { + case SOUP_NTLM_NEW: +#ifdef USE_NTLM_AUTH + if (sso_ntlm_initiate (priv)) { + header = sso_ntlm_response (priv, "YR\n", priv->state); + if (header) { + if (g_ascii_strcasecmp (header, "PW") != 0) { + priv->state = SOUP_NTLM_SENT_SSO_REQUEST; + break; + } else { + g_free (header); + header = NULL; + } + } else { + g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH); + } + } + /* If NTLM single-sign-on fails, go back to original + * request handling process. + */ + case SOUP_NTLM_SSO_UNAVAILABLE: +#endif + header = soup_ntlm_request (); + priv->state = SOUP_NTLM_SENT_REQUEST; + break; +#ifdef USE_NTLM_AUTH + case SOUP_NTLM_RECEIVED_SSO_CHALLENGE: + header = priv->response_header; + priv->response_header = NULL; + priv->state = SOUP_NTLM_SENT_SSO_RESPONSE; + break; + case SOUP_NTLM_SSO_FAILED: + /* Restart request without SSO */ + g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH); + header = soup_ntlm_request (); + priv->state = SOUP_NTLM_SENT_REQUEST; + break; +#endif + case SOUP_NTLM_RECEIVED_CHALLENGE: + header = priv->response_header; + priv->response_header = NULL; + priv->state = SOUP_NTLM_SENT_RESPONSE; + break; + default: + break; + } + + return header; } static void @@ -119,20 +454,710 @@ soup_auth_ntlm_class_init (SoupAuthNTLMClass *auth_ntlm_class) auth_class->get_authorization = soup_auth_ntlm_get_authorization; object_class->finalize = soup_auth_ntlm_finalize; + +#ifdef USE_NTLM_AUTH + ntlm_auth_available = g_file_test (NTLM_AUTH, G_FILE_TEST_IS_EXECUTABLE); + ntlm_auth_debug = (g_getenv ("SOUP_NTLM_AUTH_DEBUG") != NULL); +#endif } -const char * -soup_auth_ntlm_get_username (SoupAuth *auth) +static void md4sum (const unsigned char *in, + int nbytes, + unsigned char digest[16]); + +typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */ + +static void deskey (DES_KS, unsigned char *, int); + +static void des (DES_KS, unsigned char *); + +static void setup_schedule (const guchar *key_56, DES_KS ks); + +static void calc_response (const guchar *key, + const guchar *plaintext, + guchar *results); + +#define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \ + "\x4B\x47\x53\x21\x40\x23\x24\x25" \ + "\x00\x00\x00\x00\x00" + +static void +soup_ntlm_lanmanager_hash (const char *password, guchar hash[21]) { - SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); + guchar lm_password [15]; + DES_KS ks; + int i; + + for (i = 0; i < 14 && password [i]; i++) + lm_password [i] = g_ascii_toupper ((unsigned char) password [i]); - return priv->username; + for (; i < 15; i++) + lm_password [i] = '\0'; + + memcpy (hash, LM_PASSWORD_MAGIC, 21); + + setup_schedule (lm_password, ks); + des (ks, hash); + + setup_schedule (lm_password + 7, ks); + des (ks, hash + 8); } -const char * -soup_auth_ntlm_get_password (SoupAuth *auth) +static void +soup_ntlm_nt_hash (const char *password, guchar hash[21]) { - SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); + unsigned char *buf, *p; + + p = buf = g_malloc (strlen (password) * 2); + + while (*password) { + *p++ = *password++; + *p++ = '\0'; + } + + md4sum (buf, p - buf, hash); + memset (hash + 16, 0, 5); + + g_free (buf); +} + +typedef struct { + guint16 length; + guint16 length2; + guint16 offset; + guchar zero_pad[2]; +} NTLMString; + +#define NTLM_CHALLENGE_NONCE_OFFSET 24 +#define NTLM_CHALLENGE_NONCE_LENGTH 8 +#define NTLM_CHALLENGE_DOMAIN_STRING_OFFSET 12 + +#define NTLM_RESPONSE_HEADER "NTLMSSP\x00\x03\x00\x00\x00" +#define NTLM_RESPONSE_FLAGS 0x8201 + +typedef struct { + guchar header[12]; + + NTLMString lm_resp; + NTLMString nt_resp; + NTLMString domain; + NTLMString user; + NTLMString host; + NTLMString session_key; - return priv->password; + guint32 flags; +} NTLMResponse; + +static void +ntlm_set_string (NTLMString *string, int *offset, int len) +{ + string->offset = GUINT16_TO_LE (*offset); + string->length = string->length2 = GUINT16_TO_LE (len); + *offset += len; +} + +static char * +soup_ntlm_request (void) +{ + return g_strdup ("NTLM TlRMTVNTUAABAAAABYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA"); +} + +static gboolean +soup_ntlm_parse_challenge (const char *challenge, + char **nonce, + char **default_domain) +{ + gsize clen; + NTLMString domain; + guchar *chall; + + chall = g_base64_decode (challenge, &clen); + if (clen < NTLM_CHALLENGE_DOMAIN_STRING_OFFSET || + clen < NTLM_CHALLENGE_NONCE_OFFSET + NTLM_CHALLENGE_NONCE_LENGTH) { + g_free (chall); + return FALSE; + } + + if (default_domain) { + memcpy (&domain, chall + NTLM_CHALLENGE_DOMAIN_STRING_OFFSET, sizeof (domain)); + domain.length = GUINT16_FROM_LE (domain.length); + domain.offset = GUINT16_FROM_LE (domain.offset); + + if (clen < domain.length + domain.offset) { + g_free (chall); + return FALSE; + } + + *default_domain = g_convert ((char *)chall + domain.offset, + domain.length, "UTF-8", "UCS-2LE", + NULL, NULL, NULL); + } + + if (nonce) { + *nonce = g_memdup (chall + NTLM_CHALLENGE_NONCE_OFFSET, + NTLM_CHALLENGE_NONCE_LENGTH); + } + + g_free (chall); + return TRUE; +} + +static char * +soup_ntlm_response (const char *nonce, + const char *user, + guchar nt_hash[21], + guchar lm_hash[21], + const char *host, + const char *domain) +{ + int offset; + gsize hlen, dlen, ulen; + guchar lm_resp[24], nt_resp[24]; + char *user_conv, *host_conv, *domain_conv; + NTLMResponse resp; + char *out, *p; + int state, save; + + calc_response (nt_hash, (guchar *)nonce, nt_resp); + calc_response (lm_hash, (guchar *)nonce, lm_resp); + + memset (&resp, 0, sizeof (resp)); + memcpy (resp.header, NTLM_RESPONSE_HEADER, sizeof (resp.header)); + resp.flags = GUINT32_TO_LE (NTLM_RESPONSE_FLAGS); + + offset = sizeof (resp); + + if (!host) + host = "UNKNOWN"; + + domain_conv = g_convert (domain, -1, "UCS-2LE", "UTF-8", NULL, &dlen, NULL); + user_conv = g_convert (user, -1, "UCS-2LE", "UTF-8", NULL, &ulen, NULL); + host_conv = g_convert (host, -1, "UCS-2LE", "UTF-8", NULL, &hlen, NULL); + + ntlm_set_string (&resp.domain, &offset, dlen); + ntlm_set_string (&resp.user, &offset, ulen); + ntlm_set_string (&resp.host, &offset, hlen); + ntlm_set_string (&resp.lm_resp, &offset, sizeof (lm_resp)); + ntlm_set_string (&resp.nt_resp, &offset, sizeof (nt_resp)); + + out = g_malloc (((offset + 3) * 4) / 3 + 6); + strncpy (out, "NTLM ", 5); + p = out + 5; + + state = save = 0; + + p += g_base64_encode_step ((const guchar *) &resp, sizeof (resp), + FALSE, p, &state, &save); + p += g_base64_encode_step ((const guchar *) domain_conv, dlen, + FALSE, p, &state, &save); + p += g_base64_encode_step ((const guchar *) user_conv, ulen, + FALSE, p, &state, &save); + p += g_base64_encode_step ((const guchar *) host_conv, hlen, + FALSE, p, &state, &save); + p += g_base64_encode_step (lm_resp, sizeof (lm_resp), + FALSE, p, &state, &save); + p += g_base64_encode_step (nt_resp, sizeof (nt_resp), + FALSE, p, &state, &save); + p += g_base64_encode_close (FALSE, p, &state, &save); + *p = '\0'; + + g_free (domain_conv); + g_free (user_conv); + g_free (host_conv); + + return out; +} + +/* DES utils */ +/* Set up a key schedule based on a 56bit key */ +static void +setup_schedule (const guchar *key_56, DES_KS ks) +{ + guchar key[8]; + int i, c, bit; + + key[0] = (key_56[0]) ; + key[1] = (key_56[1] >> 1) | ((key_56[0] << 7) & 0xFF); + key[2] = (key_56[2] >> 2) | ((key_56[1] << 6) & 0xFF); + key[3] = (key_56[3] >> 3) | ((key_56[2] << 5) & 0xFF); + key[4] = (key_56[4] >> 4) | ((key_56[3] << 4) & 0xFF); + key[5] = (key_56[5] >> 5) | ((key_56[4] << 3) & 0xFF); + key[6] = (key_56[6] >> 6) | ((key_56[5] << 2) & 0xFF); + key[7] = ((key_56[6] << 1) & 0xFF); + + /* Fix parity */ + for (i = 0; i < 8; i++) { + for (c = bit = 0; bit < 8; bit++) + if (key[i] & (1 << bit)) + c++; + if (!(c & 1)) + key[i] ^= 0x01; + } + + deskey (ks, key, 0); +} + +static void +calc_response (const guchar *key, const guchar *plaintext, guchar *results) +{ + DES_KS ks; + + memcpy (results, plaintext, 8); + memcpy (results + 8, plaintext, 8); + memcpy (results + 16, plaintext, 8); + + setup_schedule (key, ks); + des (ks, results); + + setup_schedule (key + 7, ks); + des (ks, results + 8); + + setup_schedule (key + 14, ks); + des (ks, results + 16); +} + + +/* + * MD4 encoder. (The one everyone else uses is not GPL-compatible; + * this is a reimplementation from spec.) This doesn't need to be + * efficient for our purposes, although it would be nice to fix + * it to not malloc()... + */ + +#define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) ) +#define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) ) +#define H(X,Y,Z) ( (X)^(Y)^(Z) ) +#define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) ) + +static void +md4sum (const unsigned char *in, int nbytes, unsigned char digest[16]) +{ + unsigned char *M; + guint32 A, B, C, D, AA, BB, CC, DD, X[16]; + int pbytes, nbits = nbytes * 8, i, j; + + pbytes = (120 - (nbytes % 64)) % 64; + M = alloca (nbytes + pbytes + 8); + memcpy (M, in, nbytes); + memset (M + nbytes, 0, pbytes + 8); + M[nbytes] = 0x80; + M[nbytes + pbytes] = nbits & 0xFF; + M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF; + M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF; + M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF; + + A = 0x67452301; + B = 0xEFCDAB89; + C = 0x98BADCFE; + D = 0x10325476; + + for (i = 0; i < nbytes + pbytes + 8; i += 64) { + for (j = 0; j < 16; j++) { + X[j] = (M[i + j*4]) | + (M[i + j*4 + 1] << 8) | + (M[i + j*4 + 2] << 16) | + (M[i + j*4 + 3] << 24); + } + + AA = A; + BB = B; + CC = C; + DD = D; + + A = ROT (A + F(B, C, D) + X[0], 3); + D = ROT (D + F(A, B, C) + X[1], 7); + C = ROT (C + F(D, A, B) + X[2], 11); + B = ROT (B + F(C, D, A) + X[3], 19); + A = ROT (A + F(B, C, D) + X[4], 3); + D = ROT (D + F(A, B, C) + X[5], 7); + C = ROT (C + F(D, A, B) + X[6], 11); + B = ROT (B + F(C, D, A) + X[7], 19); + A = ROT (A + F(B, C, D) + X[8], 3); + D = ROT (D + F(A, B, C) + X[9], 7); + C = ROT (C + F(D, A, B) + X[10], 11); + B = ROT (B + F(C, D, A) + X[11], 19); + A = ROT (A + F(B, C, D) + X[12], 3); + D = ROT (D + F(A, B, C) + X[13], 7); + C = ROT (C + F(D, A, B) + X[14], 11); + B = ROT (B + F(C, D, A) + X[15], 19); + + A = ROT (A + G(B, C, D) + X[0] + 0x5A827999, 3); + D = ROT (D + G(A, B, C) + X[4] + 0x5A827999, 5); + C = ROT (C + G(D, A, B) + X[8] + 0x5A827999, 9); + B = ROT (B + G(C, D, A) + X[12] + 0x5A827999, 13); + A = ROT (A + G(B, C, D) + X[1] + 0x5A827999, 3); + D = ROT (D + G(A, B, C) + X[5] + 0x5A827999, 5); + C = ROT (C + G(D, A, B) + X[9] + 0x5A827999, 9); + B = ROT (B + G(C, D, A) + X[13] + 0x5A827999, 13); + A = ROT (A + G(B, C, D) + X[2] + 0x5A827999, 3); + D = ROT (D + G(A, B, C) + X[6] + 0x5A827999, 5); + C = ROT (C + G(D, A, B) + X[10] + 0x5A827999, 9); + B = ROT (B + G(C, D, A) + X[14] + 0x5A827999, 13); + A = ROT (A + G(B, C, D) + X[3] + 0x5A827999, 3); + D = ROT (D + G(A, B, C) + X[7] + 0x5A827999, 5); + C = ROT (C + G(D, A, B) + X[11] + 0x5A827999, 9); + B = ROT (B + G(C, D, A) + X[15] + 0x5A827999, 13); + + A = ROT (A + H(B, C, D) + X[0] + 0x6ED9EBA1, 3); + D = ROT (D + H(A, B, C) + X[8] + 0x6ED9EBA1, 9); + C = ROT (C + H(D, A, B) + X[4] + 0x6ED9EBA1, 11); + B = ROT (B + H(C, D, A) + X[12] + 0x6ED9EBA1, 15); + A = ROT (A + H(B, C, D) + X[2] + 0x6ED9EBA1, 3); + D = ROT (D + H(A, B, C) + X[10] + 0x6ED9EBA1, 9); + C = ROT (C + H(D, A, B) + X[6] + 0x6ED9EBA1, 11); + B = ROT (B + H(C, D, A) + X[14] + 0x6ED9EBA1, 15); + A = ROT (A + H(B, C, D) + X[1] + 0x6ED9EBA1, 3); + D = ROT (D + H(A, B, C) + X[9] + 0x6ED9EBA1, 9); + C = ROT (C + H(D, A, B) + X[5] + 0x6ED9EBA1, 11); + B = ROT (B + H(C, D, A) + X[13] + 0x6ED9EBA1, 15); + A = ROT (A + H(B, C, D) + X[3] + 0x6ED9EBA1, 3); + D = ROT (D + H(A, B, C) + X[11] + 0x6ED9EBA1, 9); + C = ROT (C + H(D, A, B) + X[7] + 0x6ED9EBA1, 11); + B = ROT (B + H(C, D, A) + X[15] + 0x6ED9EBA1, 15); + + A += AA; + B += BB; + C += CC; + D += DD; + } + + digest[0] = A & 0xFF; + digest[1] = (A >> 8) & 0xFF; + digest[2] = (A >> 16) & 0xFF; + digest[3] = (A >> 24) & 0xFF; + digest[4] = B & 0xFF; + digest[5] = (B >> 8) & 0xFF; + digest[6] = (B >> 16) & 0xFF; + digest[7] = (B >> 24) & 0xFF; + digest[8] = C & 0xFF; + digest[9] = (C >> 8) & 0xFF; + digest[10] = (C >> 16) & 0xFF; + digest[11] = (C >> 24) & 0xFF; + digest[12] = D & 0xFF; + digest[13] = (D >> 8) & 0xFF; + digest[14] = (D >> 16) & 0xFF; + digest[15] = (D >> 24) & 0xFF; +} + + +/* Public domain DES implementation from Phil Karn */ +static const guint32 Spbox[8][64] = { + { 0x01010400,0x00000000,0x00010000,0x01010404, + 0x01010004,0x00010404,0x00000004,0x00010000, + 0x00000400,0x01010400,0x01010404,0x00000400, + 0x01000404,0x01010004,0x01000000,0x00000004, + 0x00000404,0x01000400,0x01000400,0x00010400, + 0x00010400,0x01010000,0x01010000,0x01000404, + 0x00010004,0x01000004,0x01000004,0x00010004, + 0x00000000,0x00000404,0x00010404,0x01000000, + 0x00010000,0x01010404,0x00000004,0x01010000, + 0x01010400,0x01000000,0x01000000,0x00000400, + 0x01010004,0x00010000,0x00010400,0x01000004, + 0x00000400,0x00000004,0x01000404,0x00010404, + 0x01010404,0x00010004,0x01010000,0x01000404, + 0x01000004,0x00000404,0x00010404,0x01010400, + 0x00000404,0x01000400,0x01000400,0x00000000, + 0x00010004,0x00010400,0x00000000,0x01010004 }, + { 0x80108020,0x80008000,0x00008000,0x00108020, + 0x00100000,0x00000020,0x80100020,0x80008020, + 0x80000020,0x80108020,0x80108000,0x80000000, + 0x80008000,0x00100000,0x00000020,0x80100020, + 0x00108000,0x00100020,0x80008020,0x00000000, + 0x80000000,0x00008000,0x00108020,0x80100000, + 0x00100020,0x80000020,0x00000000,0x00108000, + 0x00008020,0x80108000,0x80100000,0x00008020, + 0x00000000,0x00108020,0x80100020,0x00100000, + 0x80008020,0x80100000,0x80108000,0x00008000, + 0x80100000,0x80008000,0x00000020,0x80108020, + 0x00108020,0x00000020,0x00008000,0x80000000, + 0x00008020,0x80108000,0x00100000,0x80000020, + 0x00100020,0x80008020,0x80000020,0x00100020, + 0x00108000,0x00000000,0x80008000,0x00008020, + 0x80000000,0x80100020,0x80108020,0x00108000 }, + { 0x00000208,0x08020200,0x00000000,0x08020008, + 0x08000200,0x00000000,0x00020208,0x08000200, + 0x00020008,0x08000008,0x08000008,0x00020000, + 0x08020208,0x00020008,0x08020000,0x00000208, + 0x08000000,0x00000008,0x08020200,0x00000200, + 0x00020200,0x08020000,0x08020008,0x00020208, + 0x08000208,0x00020200,0x00020000,0x08000208, + 0x00000008,0x08020208,0x00000200,0x08000000, + 0x08020200,0x08000000,0x00020008,0x00000208, + 0x00020000,0x08020200,0x08000200,0x00000000, + 0x00000200,0x00020008,0x08020208,0x08000200, + 0x08000008,0x00000200,0x00000000,0x08020008, + 0x08000208,0x00020000,0x08000000,0x08020208, + 0x00000008,0x00020208,0x00020200,0x08000008, + 0x08020000,0x08000208,0x00000208,0x08020000, + 0x00020208,0x00000008,0x08020008,0x00020200 }, + { 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802080,0x00800081,0x00800001,0x00002001, + 0x00000000,0x00802000,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00800080,0x00800001, + 0x00000001,0x00002000,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002001,0x00002080, + 0x00800081,0x00000001,0x00002080,0x00800080, + 0x00002000,0x00802080,0x00802081,0x00000081, + 0x00800080,0x00800001,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00000000,0x00802000, + 0x00002080,0x00800080,0x00800081,0x00000001, + 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802081,0x00000081,0x00000001,0x00002000, + 0x00800001,0x00002001,0x00802080,0x00800081, + 0x00002001,0x00002080,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002000,0x00802080 }, + { 0x00000100,0x02080100,0x02080000,0x42000100, + 0x00080000,0x00000100,0x40000000,0x02080000, + 0x40080100,0x00080000,0x02000100,0x40080100, + 0x42000100,0x42080000,0x00080100,0x40000000, + 0x02000000,0x40080000,0x40080000,0x00000000, + 0x40000100,0x42080100,0x42080100,0x02000100, + 0x42080000,0x40000100,0x00000000,0x42000000, + 0x02080100,0x02000000,0x42000000,0x00080100, + 0x00080000,0x42000100,0x00000100,0x02000000, + 0x40000000,0x02080000,0x42000100,0x40080100, + 0x02000100,0x40000000,0x42080000,0x02080100, + 0x40080100,0x00000100,0x02000000,0x42080000, + 0x42080100,0x00080100,0x42000000,0x42080100, + 0x02080000,0x00000000,0x40080000,0x42000000, + 0x00080100,0x02000100,0x40000100,0x00080000, + 0x00000000,0x40080000,0x02080100,0x40000100 }, + { 0x20000010,0x20400000,0x00004000,0x20404010, + 0x20400000,0x00000010,0x20404010,0x00400000, + 0x20004000,0x00404010,0x00400000,0x20000010, + 0x00400010,0x20004000,0x20000000,0x00004010, + 0x00000000,0x00400010,0x20004010,0x00004000, + 0x00404000,0x20004010,0x00000010,0x20400010, + 0x20400010,0x00000000,0x00404010,0x20404000, + 0x00004010,0x00404000,0x20404000,0x20000000, + 0x20004000,0x00000010,0x20400010,0x00404000, + 0x20404010,0x00400000,0x00004010,0x20000010, + 0x00400000,0x20004000,0x20000000,0x00004010, + 0x20000010,0x20404010,0x00404000,0x20400000, + 0x00404010,0x20404000,0x00000000,0x20400010, + 0x00000010,0x00004000,0x20400000,0x00404010, + 0x00004000,0x00400010,0x20004010,0x00000000, + 0x20404000,0x20000000,0x00400010,0x20004010 }, + { 0x00200000,0x04200002,0x04000802,0x00000000, + 0x00000800,0x04000802,0x00200802,0x04200800, + 0x04200802,0x00200000,0x00000000,0x04000002, + 0x00000002,0x04000000,0x04200002,0x00000802, + 0x04000800,0x00200802,0x00200002,0x04000800, + 0x04000002,0x04200000,0x04200800,0x00200002, + 0x04200000,0x00000800,0x00000802,0x04200802, + 0x00200800,0x00000002,0x04000000,0x00200800, + 0x04000000,0x00200800,0x00200000,0x04000802, + 0x04000802,0x04200002,0x04200002,0x00000002, + 0x00200002,0x04000000,0x04000800,0x00200000, + 0x04200800,0x00000802,0x00200802,0x04200800, + 0x00000802,0x04000002,0x04200802,0x04200000, + 0x00200800,0x00000000,0x00000002,0x04200802, + 0x00000000,0x00200802,0x04200000,0x00000800, + 0x04000002,0x04000800,0x00000800,0x00200002 }, + { 0x10001040,0x00001000,0x00040000,0x10041040, + 0x10000000,0x10001040,0x00000040,0x10000000, + 0x00040040,0x10040000,0x10041040,0x00041000, + 0x10041000,0x00041040,0x00001000,0x00000040, + 0x10040000,0x10000040,0x10001000,0x00001040, + 0x00041000,0x00040040,0x10040040,0x10041000, + 0x00001040,0x00000000,0x00000000,0x10040040, + 0x10000040,0x10001000,0x00041040,0x00040000, + 0x00041040,0x00040000,0x10041000,0x00001000, + 0x00000040,0x10040040,0x00001000,0x00041040, + 0x10001000,0x00000040,0x10000040,0x10040000, + 0x10040040,0x10000000,0x00040000,0x10001040, + 0x00000000,0x10041040,0x00040040,0x10000040, + 0x10040000,0x10001000,0x10001040,0x00000000, + 0x10041040,0x00041000,0x00041000,0x00001040, + 0x00001040,0x00040040,0x10000000,0x10041000 } +}; + +#undef F +#define F(l,r,key){\ + work = ((r >> 4) | (r << 28)) ^ key[0];\ + l ^= Spbox[6][work & 0x3f];\ + l ^= Spbox[4][(work >> 8) & 0x3f];\ + l ^= Spbox[2][(work >> 16) & 0x3f];\ + l ^= Spbox[0][(work >> 24) & 0x3f];\ + work = r ^ key[1];\ + l ^= Spbox[7][work & 0x3f];\ + l ^= Spbox[5][(work >> 8) & 0x3f];\ + l ^= Spbox[3][(work >> 16) & 0x3f];\ + l ^= Spbox[1][(work >> 24) & 0x3f];\ +} +/* Encrypt or decrypt a block of data in ECB mode */ +static void +des (guint32 ks[16][2], unsigned char block[8]) +{ + guint32 left,right,work; + + /* Read input block and place in left/right in big-endian order */ + left = ((guint32)block[0] << 24) + | ((guint32)block[1] << 16) + | ((guint32)block[2] << 8) + | (guint32)block[3]; + right = ((guint32)block[4] << 24) + | ((guint32)block[5] << 16) + | ((guint32)block[6] << 8) + | (guint32)block[7]; + + /* Hoey's clever initial permutation algorithm, from Outerbridge + * (see Schneier p 478) + * + * The convention here is the same as Outerbridge: rotate each + * register left by 1 bit, i.e., so that "left" contains permuted + * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32 + * (using origin-1 numbering as in the FIPS). This allows us to avoid + * one of the two rotates that would otherwise be required in each of + * the 16 rounds. + */ + work = ((left >> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= work << 4; + work = ((left >> 16) ^ right) & 0xffff; + right ^= work; + left ^= work << 16; + work = ((right >> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ left) & 0xff00ff; + left ^= work; + right ^= (work << 8); + right = (right << 1) | (right >> 31); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left << 1) | (left >> 31); + + /* Now do the 16 rounds */ + F(left,right,ks[0]); + F(right,left,ks[1]); + F(left,right,ks[2]); + F(right,left,ks[3]); + F(left,right,ks[4]); + F(right,left,ks[5]); + F(left,right,ks[6]); + F(right,left,ks[7]); + F(left,right,ks[8]); + F(right,left,ks[9]); + F(left,right,ks[10]); + F(right,left,ks[11]); + F(left,right,ks[12]); + F(right,left,ks[13]); + F(left,right,ks[14]); + F(right,left,ks[15]); + + /* Inverse permutation, also from Hoey via Outerbridge and Schneier */ + right = (right << 31) | (right >> 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left >> 1) | (left << 31); + work = ((left >> 8) ^ right) & 0xff00ff; + right ^= work; + left ^= work << 8; + work = ((left >> 2) ^ right) & 0x33333333; + right ^= work; + left ^= work << 2; + work = ((right >> 16) ^ left) & 0xffff; + left ^= work; + right ^= work << 16; + work = ((right >> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= work << 4; + + /* Put the block back into the user's buffer with final swap */ + block[0] = right >> 24; + block[1] = right >> 16; + block[2] = right >> 8; + block[3] = right; + block[4] = left >> 24; + block[5] = left >> 16; + block[6] = left >> 8; + block[7] = left; +} + +/* Key schedule-related tables from FIPS-46 */ + +/* permuted choice table (key) */ +static const unsigned char pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +/* number left rotations of pc1 */ +static const unsigned char totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 +}; + +/* permuted choice key (table) */ +static const unsigned char pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +/* End of DES-defined tables */ + + +/* bit 0 is left-most in byte */ +static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 +}; + + +/* Generate key schedule for encryption or decryption + * depending on the value of "decrypt" + */ +static void +deskey (DES_KS k, unsigned char *key, int decrypt) +{ + unsigned char pc1m[56]; /* place to modify pc1 into */ + unsigned char pcr[56]; /* place to rotate pc1 into */ + register int i,j,l; + int m; + unsigned char ks[8]; + + for (j=0; j<56; j++) { /* convert pc1 to bits of key */ + l=pc1[j]-1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j]=(key[l>>3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + for (i=0; i<16; i++) { /* key chunk for each iteration */ + memset(ks,0,sizeof(ks)); /* Clear key schedule */ + for (j=0; j<56; j++) /* rotate pc1 the right amount */ + pcr[j] = pc1m[(l=j+totrot[decrypt? 15-i : i])<(j<28? 28 : 56) ? l: l-28]; + /* rotate left and right halves independently */ + for (j=0; j<48; j++){ /* select bits individually */ + /* check bit that goes to ks[j] */ + if (pcr[pc2[j]-1]){ + /* mask it in if it's there */ + l= j % 6; + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to packed odd/even interleaved form */ + k[i][0] = ((guint32)ks[0] << 24) + | ((guint32)ks[2] << 16) + | ((guint32)ks[4] << 8) + | ((guint32)ks[6]); + k[i][1] = ((guint32)ks[1] << 24) + | ((guint32)ks[3] << 16) + | ((guint32)ks[5] << 8) + | ((guint32)ks[7]); + } } diff --git a/libsoup/soup-auth-ntlm.h b/libsoup/soup-auth-ntlm.h index 1f56976b..7ed9bd3e 100644 --- a/libsoup/soup-auth-ntlm.h +++ b/libsoup/soup-auth-ntlm.h @@ -24,9 +24,4 @@ typedef struct { } SoupAuthNTLMClass; -SoupAuth *soup_auth_ntlm_new (const char *realm, - const char *host); -const char *soup_auth_ntlm_get_username (SoupAuth *auth); -const char *soup_auth_ntlm_get_password (SoupAuth *auth); - #endif /* SOUP_AUTH_NTLM_H */ diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c index bb6f3b45..77fb45e9 100644 --- a/libsoup/soup-auth.c +++ b/libsoup/soup-auth.c @@ -107,9 +107,13 @@ soup_auth_get_property (GObject *object, guint prop_id, g_value_set_string (value, soup_auth_get_scheme_name (auth)); break; case PROP_REALM: + if (auth->realm) + g_free (auth->realm); g_value_set_string (value, soup_auth_get_realm (auth)); break; case PROP_HOST: + if (priv->host) + g_free (priv->host); g_value_set_string (value, soup_auth_get_host (auth)); break; case PROP_IS_FOR_PROXY: @@ -162,7 +166,7 @@ soup_auth_class_init (SoupAuthClass *auth_class) "Realm", "Authentication realm", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); /** * SOUP_AUTH_HOST: * @@ -175,7 +179,7 @@ soup_auth_class_init (SoupAuthClass *auth_class) "Host", "Authentication host", NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); /** * SOUP_AUTH_IS_FOR_PROXY: * @@ -188,7 +192,7 @@ soup_auth_class_init (SoupAuthClass *auth_class) "For Proxy", "Whether or not the auth is for a proxy server", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); /** * SOUP_AUTH_IS_AUTHENTICATED: * @@ -242,19 +246,12 @@ soup_auth_new (GType type, SoupMessage *msg, const char *auth_header) } params = soup_header_parse_param_list (auth_header + strlen (scheme)); - if (!params) { - g_object_unref (auth); - return NULL; - } + if (!params) + params = g_hash_table_new (NULL, NULL); realm = g_hash_table_lookup (params, "realm"); - if (!realm) { - soup_header_free_param_list (params); - g_object_unref (auth); - return NULL; - } - - auth->realm = g_strdup (realm); + if (realm) + auth->realm = g_strdup (realm); if (!SOUP_AUTH_GET_CLASS (auth)->update (auth, msg, params)) { g_object_unref (auth); @@ -295,10 +292,10 @@ soup_auth_update (SoupAuth *auth, SoupMessage *msg, const char *auth_header) params = soup_header_parse_param_list (auth_header + strlen (scheme)); if (!params) - return FALSE; + params = g_hash_table_new (NULL, NULL); realm = g_hash_table_lookup (params, "realm"); - if (!realm || strcmp (realm, auth->realm) != 0) { + if (realm && auth->realm && strcmp (realm, auth->realm) != 0) { soup_header_free_param_list (params); return FALSE; } diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index badcd166..7fe6db84 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1196,7 +1196,6 @@ soup_message_set_auth (SoupMessage *msg, SoupAuth *auth) g_return_if_fail (SOUP_IS_MESSAGE (msg)); g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth)); - g_return_if_fail (auth == NULL || soup_auth_is_authenticated (auth)); priv = SOUP_MESSAGE_GET_PRIVATE (msg); @@ -1211,9 +1210,11 @@ soup_message_set_auth (SoupMessage *msg, SoupAuth *auth) g_object_ref (priv->auth); token = soup_auth_get_authorization (auth, msg); - soup_message_headers_replace (msg->request_headers, - "Authorization", token); - g_free (token); + if (token) { + soup_message_headers_replace (msg->request_headers, + "Authorization", token); + g_free (token); + } } SoupAuth * @@ -1232,7 +1233,6 @@ soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth) g_return_if_fail (SOUP_IS_MESSAGE (msg)); g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth)); - g_return_if_fail (auth == NULL || soup_auth_is_authenticated (auth)); priv = SOUP_MESSAGE_GET_PRIVATE (msg); diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 0a866300..63e90b3d 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -13,7 +13,7 @@ #include "soup-session.h" #include "soup.h" -#include "soup-auth-manager-ntlm.h" +#include "soup-auth-manager.h" #include "soup-cache-private.h" #include "soup-connection.h" #include "soup-marshal.h" @@ -219,7 +219,7 @@ soup_session_init (SoupSession *session) priv->features_cache = g_hash_table_new (NULL, NULL); - auth_manager = g_object_new (SOUP_TYPE_AUTH_MANAGER_NTLM, NULL); + auth_manager = g_object_new (SOUP_TYPE_AUTH_MANAGER, NULL); g_signal_connect (auth_manager, "authenticate", G_CALLBACK (auth_manager_authenticate), session); soup_session_feature_add_feature (SOUP_SESSION_FEATURE (auth_manager), @@ -573,7 +573,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS break; case PROP_USE_NTLM: g_return_if_fail (!SOUP_IS_PLAIN_SESSION (session)); - feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER_NTLM); + feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER); if (feature) { if (g_value_get_boolean (value)) soup_session_feature_add_feature (feature, SOUP_TYPE_AUTH_NTLM); @@ -698,7 +698,7 @@ soup_session_get_property (GObject *object, guint prop_id, g_value_set_int (value, priv->max_conns_per_host); break; case PROP_USE_NTLM: - feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER_NTLM); + feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER); if (feature) g_value_set_boolean (value, soup_session_feature_has_feature (feature, SOUP_TYPE_AUTH_NTLM)); else diff --git a/tests/Makefile.am b/tests/Makefile.am index fdd2c3d1..7af39755 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,7 @@ INCLUDES = \ -I$(top_srcdir) \ -DSRCDIR=\""$(abs_srcdir)"\" \ + -DBUILDDIR=\""$(builddir)"\" \ $(SOUP_MAINTAINER_FLAGS) \ $(XML_CFLAGS) \ $(GLIB_CFLAGS) @@ -25,6 +26,7 @@ noinst_PROGRAMS = \ header-parsing \ misc-test \ multipart-test \ + ntlm-test-helper \ ntlm-test \ redirect-test \ requester-test \ diff --git a/tests/ntlm-test-helper.c b/tests/ntlm-test-helper.c new file mode 100644 index 00000000..60dd0490 --- /dev/null +++ b/tests/ntlm-test-helper.c @@ -0,0 +1,103 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2012 Red Hat, Inc. + */ + +#include +#include +#include +#include + +#include +#include "libsoup/soup.h" + +const char *helper_protocol, *username, *domain; +gboolean use_cached_creds; + +static GOptionEntry entries[] = { + { "helper-protocol", 0, 0, + G_OPTION_ARG_STRING, &helper_protocol, + NULL, NULL }, + { "use-cached-creds", 0, 0, + G_OPTION_ARG_NONE, &use_cached_creds, + NULL, NULL }, + { "username", 0, 0, + G_OPTION_ARG_STRING, &username, + NULL, NULL }, + { "domain", 0, 0, + G_OPTION_ARG_STRING, &domain, + NULL, NULL }, + { NULL } +}; + +int +main (int argc, char **argv) +{ + GOptionContext *opts; + char buf[256], *header; + SoupMessage *msg; + SoupAuth *auth; + + /* Don't recurse */ + g_unsetenv ("SOUP_NTLM_AUTH_DEBUG"); + + setlocale (LC_ALL, ""); + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, entries, NULL); + if (!g_option_context_parse (opts, &argc, &argv, NULL)) { + g_printerr ("Bad arguments\n"); + exit (1); + } + g_option_context_free (opts); + + if (!username || !use_cached_creds || !helper_protocol || + !g_str_equal (helper_protocol, "ntlmssp-client-1")) { + g_printerr ("Wrong arguments; this program is only intended for use by ntlm-test\n"); + exit (1); + } + + msg = soup_message_new ("GET", "http://localhost/"); + auth = NULL; + + while (fgets (buf, sizeof (buf), stdin)) { + if (strchr (buf, '\n')) + *strchr (buf, '\n') = '\0'; + if (!strcmp (buf, "YR")) { + if (g_getenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS")) { + g_print ("PW\n"); + continue; + } + + g_clear_object (&auth); + auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL); + header = soup_auth_get_authorization (auth, msg); + g_print ("YR %s\n", header + 5); + g_free (header); + } else if (g_str_has_prefix (buf, "TT ")) { + header = g_strdup_printf ("NTLM %s\n", buf + 3); + if (!soup_auth_update (auth, msg, header)) { + g_printerr ("Bad challenge\n"); + exit (1); + } + g_free (header); + + soup_auth_authenticate (auth, username, "password"); + header = soup_auth_get_authorization (auth, msg); + if (!header) { + g_printerr ("Internal authentication failure\n"); + exit (1); + } + g_print ("KK %s\n", header + 5); + g_free (header); + } else { + g_printerr ("Unexpected command\n"); + exit (1); + } + } + + g_object_unref (msg); + g_clear_object (&auth); + + return 0; +} diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index e473ba67..ce08f996 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -19,6 +19,10 @@ typedef enum { NTLM_AUTHENTICATED_BOB } NTLMServerState; +static const char *state_name[] = { + "unauth", "recv", "sent", "alice", "bob" +}; + #define NTLM_REQUEST_START "TlRMTVNTUAABAAAA" #define NTLM_RESPONSE_START "TlRMTVNTUAADAAAA" @@ -134,16 +138,22 @@ server_callback (SoupServer *server, SoupMessage *msg, } } + debug_printf (2, " (S:%s)", state_name[state]); g_hash_table_insert (connections, socket, GINT_TO_POINTER (state)); g_object_weak_ref (G_OBJECT (socket), clear_state, connections); } +static gboolean authenticated_ntlm = FALSE; + static void authenticate (SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer user) { - if (!retrying) + if (!retrying) { soup_auth_authenticate (auth, user, "password"); + if (g_str_equal (soup_auth_get_scheme_name (auth), "NTLM")) + authenticated_ntlm = TRUE; + } } typedef struct { @@ -313,7 +323,8 @@ do_message (SoupSession *session, SoupURI *base_uri, const char *path, } static void -do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, const char *user) +do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, + const char *user, gboolean use_builtin_ntlm) { SoupSession *session; gboolean alice = !g_strcmp0 (user, "alice"); @@ -329,6 +340,8 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, const char *user) if (user) { g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), (char *)user); + if (use_ntlm && !use_builtin_ntlm) + g_setenv ("NTLMUSER", user, TRUE); } /* 1. Server doesn't request auth, so both get_ntlm_prompt and @@ -336,11 +349,19 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, const char *user) * if we're using NTLM we'll try that even without the server * asking. */ + authenticated_ntlm = FALSE; do_message (session, base_uri, "/noauth", FALSE, use_ntlm, FALSE, FALSE, SOUP_STATUS_OK); + if (authenticated_ntlm != (use_ntlm && use_builtin_ntlm)) { + debug_printf (1, " ERROR: %s built-in NTLM support, but authenticate signal %s emitted\n", + use_builtin_ntlm ? "Using" : "Not using", + authenticated_ntlm ? "was" : "wasn't"); + errors++; + } + /* 2. Server requires auth as Alice, so it will request that * if we didn't already authenticate the connection to her in * the previous step. If we authenticated as Bob in the @@ -422,16 +443,16 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, const char *user) } static void -do_ntlm_tests (SoupURI *base_uri) +do_ntlm_tests (SoupURI *base_uri, gboolean use_builtin_ntlm) { debug_printf (1, "Round 1: Non-NTLM Connection, no auth\n"); - do_ntlm_round (base_uri, FALSE, NULL); + do_ntlm_round (base_uri, FALSE, NULL, use_builtin_ntlm); debug_printf (1, "Round 2: NTLM Connection, user=alice\n"); - do_ntlm_round (base_uri, TRUE, "alice"); + do_ntlm_round (base_uri, TRUE, "alice", use_builtin_ntlm); debug_printf (1, "Round 3: NTLM Connection, user=bob\n"); - do_ntlm_round (base_uri, TRUE, "bob"); + do_ntlm_round (base_uri, TRUE, "bob", use_builtin_ntlm); debug_printf (1, "Round 4: Non-NTLM Connection, user=alice\n"); - do_ntlm_round (base_uri, FALSE, "alice"); + do_ntlm_round (base_uri, FALSE, "alice", use_builtin_ntlm); } int @@ -453,7 +474,30 @@ main (int argc, char **argv) uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (uri, soup_server_get_port (server)); - do_ntlm_tests (uri); + + /* Built-in NTLM auth support. (We set SOUP_NTLM_AUTH_DEBUG to + * an empty string to ensure that the built-in support is + * being used, even if /usr/bin/ntlm_auth is available.) + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); + debug_printf (1, "Built-in NTLM support\n"); + do_ntlm_tests (uri, TRUE); + + /* Samba winbind /usr/bin/ntlm_auth helper support (via a + * helper program that emulate's its interface). + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", BUILDDIR "/ntlm-test-helper", TRUE); + debug_printf (1, "\nExternal helper support\n"); + do_ntlm_tests (uri, FALSE); + + /* Support for when ntlm_auth is installed, but the user has + * no cached credentials (and thus we have to fall back to + * libsoup's built-in NTLM support). + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); + debug_printf (1, "\nExternal -> fallback support\n"); + do_ntlm_tests (uri, TRUE); + soup_uri_free (uri); g_main_loop_unref (loop); -- cgit v1.2.1 From 886741a1eb01103952617be3fe0f1cabb0bf5806 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 29 Dec 2012 19:33:21 -0500 Subject: soup-auth-ntlm: small fix --- libsoup/soup-auth-ntlm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index 11b75681..bbd04954 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -306,7 +306,7 @@ soup_auth_ntlm_update (SoupAuth *auth, SoupMessage *msg, if (!response) { priv->state = SOUP_NTLM_SSO_FAILED; success = FALSE; - } else if (!g_ascii_strcasecmp (header, "PW")) { + } else if (!g_ascii_strcasecmp (response, "PW")) { priv->state = SOUP_NTLM_SSO_UNAVAILABLE; g_free (response); success = FALSE; -- cgit v1.2.1 From ad5c6e4700e3c5e95274a9b4832fccb8c430c97d Mon Sep 17 00:00:00 2001 From: TmTFx Date: Fri, 28 Dec 2012 23:58:21 -0200 Subject: Updated Friulian translation --- po/LINGUAS | 1 + po/fur.po | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 po/fur.po diff --git a/po/LINGUAS b/po/LINGUAS index 35c4f992..637036f6 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -14,6 +14,7 @@ es et fa fr +fur gl gu he diff --git a/po/fur.po b/po/fur.po new file mode 100644 index 00000000..04579ca1 --- /dev/null +++ b/po/fur.po @@ -0,0 +1,81 @@ +# Friulian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# TmTFx , 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup gnome-3-6\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-12-10 10:22+0000\n" +"PO-Revision-Date: 2012-12-28 13:53+0100\n" +"Last-Translator: TmTFx \n" +"Language-Team: Friulian \n" +"Language: fur\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "No si spietave il termin de conession" + +#: ../libsoup/soup-body-input-stream.c:461 +msgid "Invalid seek request" +msgstr "Domande di ricerche no valide" + +#: ../libsoup/soup-body-input-stream.c:489 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No puès cjonçâ SoupBodyInputStream" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Il buffer di jessude al è masse piçul" + +#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +msgid "Operation was cancelled" +msgstr "L'operazion a je stade scancelade" + +#: ../libsoup/soup-message-io.c:865 +msgid "Operation would block" +msgstr "L'operazion a sarà blocade" + +#: ../libsoup/soup-request.c:142 +#, c-format +msgid "No URI provided" +msgstr "No'l è stât furnît un URI" + +#: ../libsoup/soup-request.c:152 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI '%s' no valit: %s" + +#: ../libsoup/soup-requester.c:219 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "No puès analizâ l'URI '%s'" + +#: ../libsoup/soup-requester.c:253 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Scheme URI '%s' no supuartât" + +#: ../libsoup/soup-tld.c:154 +msgid "Hostname is an IP address" +msgstr "Il non host al è un indiriz IP" + +#: ../libsoup/soup-tld.c:175 +msgid "Invalid hostname" +msgstr "Il non host a no'l è valit" + +#: ../libsoup/soup-tld.c:204 +msgid "Hostname has no base domain" +msgstr "Il non host a no'l a un domini di base" + +#: ../libsoup/soup-tld.c:226 +msgid "Not enough domains" +msgstr "No vonde dominis" -- cgit v1.2.1 From 289f435ad21b9facab5c8a6a9f11ca055c54930b Mon Sep 17 00:00:00 2001 From: Guenther Wutz Date: Mon, 31 Dec 2012 20:28:37 +0100 Subject: soup-auth-domain-digest: minor documentation correction --- libsoup/soup-auth-domain-digest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-auth-domain-digest.c b/libsoup/soup-auth-domain-digest.c index 985919f4..6f48ce56 100644 --- a/libsoup/soup-auth-domain-digest.c +++ b/libsoup/soup-auth-domain-digest.c @@ -21,7 +21,7 @@ * SECTION:soup-auth-domain-digest * @short_description: Server-side "Digest" authentication * - * #SoupAuthDomainBasic handles the server side of HTTP "Digest" + * #SoupAuthDomainDigest handles the server side of HTTP "Digest" * authentication. **/ -- cgit v1.2.1 From 066ecf70733166c2318ec32238e4cb8b8b79e1cd Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 30 Dec 2012 18:12:59 -0500 Subject: ntlm-test-helper: fix We need to set SOUP_NTLM_AUTH_DEBUG to an empty string (to tell SoupAuthNTLM to always use built-in NTLM), not leave it unset, which will let SoupAuthNTLM use the real ntlm_auth binary. (The effect of this bug was that instead of always using built-in NTLM, ntlm-test-helper would first try to use ntlm_auth, and fail because there were no cached credentials, and then fall back to built-in NTLM, which meant that we were testing the fallback codepath even in the supposed-to-be-non-fallback case. Unless your username was "alice" or "bob" and you had a working winbind configuration, in which case the tests would just fail.) Also, fix up ntlm-test a bit, so that if ntlm-test-helper for some reason tries to authenticate as someone other than alice or bob, it recognizes this, rather than considering everyone who isn't alice to be bob. --- tests/ntlm-test-helper.c | 2 +- tests/ntlm-test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ntlm-test-helper.c b/tests/ntlm-test-helper.c index 60dd0490..f2450cae 100644 --- a/tests/ntlm-test-helper.c +++ b/tests/ntlm-test-helper.c @@ -39,7 +39,7 @@ main (int argc, char **argv) SoupAuth *auth; /* Don't recurse */ - g_unsetenv ("SOUP_NTLM_AUTH_DEBUG"); + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); setlocale (LC_ALL, ""); diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index ce08f996..e2dc23ad 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -28,7 +28,7 @@ static const char *state_name[] = { #define NTLM_CHALLENGE "TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=" -#define NTLM_RESPONSE_USER(response) ((response)[86] == 'E' ? NTLM_AUTHENTICATED_ALICE : NTLM_AUTHENTICATED_BOB) +#define NTLM_RESPONSE_USER(response) ((response)[86] == 'E' ? NTLM_AUTHENTICATED_ALICE : ((response)[86] == 'I' ? NTLM_AUTHENTICATED_BOB : NTLM_UNAUTHENTICATED)) static void clear_state (gpointer connections, GObject *ex_connection) -- cgit v1.2.1 From 169483bab63dc505c7d6c304d05c5ad8a7278452 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 1 Jan 2013 21:30:05 -0500 Subject: ntlm-test: kill some dead code --- tests/ntlm-test.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index e2dc23ad..3184ffcf 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -458,7 +458,6 @@ do_ntlm_tests (SoupURI *base_uri, gboolean use_builtin_ntlm) int main (int argc, char **argv) { - GMainLoop *loop; SoupServer *server; GHashTable *connections; SoupURI *uri; @@ -470,8 +469,6 @@ main (int argc, char **argv) soup_server_add_handler (server, NULL, server_callback, connections, NULL); - loop = g_main_loop_new (NULL, TRUE); - uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (uri, soup_server_get_port (server)); @@ -500,8 +497,6 @@ main (int argc, char **argv) soup_uri_free (uri); - g_main_loop_unref (loop); - soup_test_server_quit_unref (server); test_cleanup (); g_hash_table_destroy (connections); -- cgit v1.2.1 From b24b8324b15250865f7f44178cb5c5fba80074e8 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 30 Dec 2012 10:42:29 -0500 Subject: soup-auth-ntlm: get rid of separate SSO states Use a single boolean to track whether we're using single-sign-on (/usr/bin/ntlm_auth) rather than having two parallel sets of SoupNTLMStates. --- libsoup/soup-auth-ntlm.c | 50 +++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index bbd04954..63f8c8b2 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -35,13 +35,7 @@ static char *soup_ntlm_response (const char *nonce, typedef enum { SOUP_NTLM_NEW, -#ifdef USE_NTLM_AUTH - SOUP_NTLM_SENT_SSO_REQUEST, - SOUP_NTLM_RECEIVED_SSO_CHALLENGE, - SOUP_NTLM_SENT_SSO_RESPONSE, - SOUP_NTLM_SSO_UNAVAILABLE, SOUP_NTLM_SSO_FAILED, -#endif SOUP_NTLM_SENT_REQUEST, SOUP_NTLM_RECEIVED_CHALLENGE, SOUP_NTLM_SENT_RESPONSE, @@ -63,6 +57,7 @@ typedef struct { * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html */ + gboolean sso_available; int fd_in; int fd_out; #endif @@ -98,6 +93,7 @@ soup_auth_ntlm_init (SoupAuthNTLM *ntlm) priv->state = SOUP_NTLM_NEW; #ifdef USE_NTLM_AUTH + priv->sso_available = TRUE; priv->fd_in = -1; priv->fd_out = -1; @@ -158,9 +154,14 @@ sso_ntlm_initiate (SoupAuthNTLMPrivate *priv) char *argv[9]; gboolean ret; - if (!ntlm_auth_available && !ntlm_auth_debug) + if (!priv->sso_available) return FALSE; + if (!ntlm_auth_available && !ntlm_auth_debug) { + priv->sso_available = FALSE; + return FALSE; + } + /* Return if ntlm_auth execution process exist already */ if (priv->fd_in != -1 && priv->fd_out != -1) return TRUE; @@ -171,8 +172,10 @@ sso_ntlm_initiate (SoupAuthNTLMPrivate *priv) if (ntlm_auth_debug) { argv[0] = (char *) g_getenv ("SOUP_NTLM_AUTH_DEBUG"); - if (!*argv[0]) + if (!*argv[0]) { + priv->sso_available = FALSE; return FALSE; + } } else argv[0] = NTLM_AUTH; argv[1] = "--helper-protocol"; @@ -189,6 +192,8 @@ sso_ntlm_initiate (SoupAuthNTLMPrivate *priv) NULL, NULL, NULL, &priv->fd_in, &priv->fd_out, NULL, NULL); + if (!ret) + priv->sso_available = FALSE; return ret; } @@ -239,7 +244,7 @@ wrfinish: /* invalid response for type 1 message */ return NULL; } - if (conn_state == SOUP_NTLM_RECEIVED_SSO_CHALLENGE && + if (conn_state == SOUP_NTLM_RECEIVED_CHALLENGE && g_ascii_strncasecmp (buf, "KK ", 3) != 0 && g_ascii_strncasecmp (buf, "AF ", 3) != 0) { /* invalid response for type 3 message */ @@ -288,7 +293,7 @@ soup_auth_ntlm_update (SoupAuth *auth, SoupMessage *msg, } #ifdef USE_NTLM_AUTH - if (priv->state == SOUP_NTLM_SENT_SSO_REQUEST) { + if (priv->sso_available && priv->state == SOUP_NTLM_SENT_REQUEST) { char *input, *response; /* Re-Initiate ntlm_auth process in case it was closed/killed abnormally */ @@ -307,13 +312,10 @@ soup_auth_ntlm_update (SoupAuth *auth, SoupMessage *msg, priv->state = SOUP_NTLM_SSO_FAILED; success = FALSE; } else if (!g_ascii_strcasecmp (response, "PW")) { - priv->state = SOUP_NTLM_SSO_UNAVAILABLE; + priv->sso_available = FALSE; g_free (response); - success = FALSE; - } else { - priv->state = SOUP_NTLM_RECEIVED_SSO_CHALLENGE; + } else priv->response_header = response; - } } out: #endif @@ -393,42 +395,38 @@ soup_auth_ntlm_get_authorization (SoupAuth *auth, SoupMessage *msg) header = sso_ntlm_response (priv, "YR\n", priv->state); if (header) { if (g_ascii_strcasecmp (header, "PW") != 0) { - priv->state = SOUP_NTLM_SENT_SSO_REQUEST; + priv->state = SOUP_NTLM_SENT_REQUEST; break; } else { g_free (header); header = NULL; + priv->sso_available = FALSE; } } else { - g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH); + g_warning ("NTLM single-sign-on using %s failed", NTLM_AUTH); } } /* If NTLM single-sign-on fails, go back to original * request handling process. */ - case SOUP_NTLM_SSO_UNAVAILABLE: #endif header = soup_ntlm_request (); priv->state = SOUP_NTLM_SENT_REQUEST; break; -#ifdef USE_NTLM_AUTH - case SOUP_NTLM_RECEIVED_SSO_CHALLENGE: + case SOUP_NTLM_RECEIVED_CHALLENGE: header = priv->response_header; priv->response_header = NULL; - priv->state = SOUP_NTLM_SENT_SSO_RESPONSE; + priv->state = SOUP_NTLM_SENT_RESPONSE; break; +#ifdef USE_NTLM_AUTH case SOUP_NTLM_SSO_FAILED: /* Restart request without SSO */ g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH); + priv->sso_available = FALSE; header = soup_ntlm_request (); priv->state = SOUP_NTLM_SENT_REQUEST; break; #endif - case SOUP_NTLM_RECEIVED_CHALLENGE: - header = priv->response_header; - priv->response_header = NULL; - priv->state = SOUP_NTLM_SENT_RESPONSE; - break; default: break; } -- cgit v1.2.1 From 586aef885f64352bbd3c1b9e68ae2020f33d5833 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 12 Dec 2012 10:19:00 +0100 Subject: soup-auth-manager: split out connection handling Add a new SoupConnectionAuth class to help with connection tracking, and make SoupAuthNTLM a subclass of it. Allow a single SoupAuthNTLM to carry state information about multiple connections. Make SoupSession store the SoupConnection a SoupMessage is associated with on the message, and use that from SoupConnectionAuth rather than tracking sockets by hand like SoupAuthManager had previously done. Remove the connection tracking in SoupAuthManager, since it is no longer needed. --- docs/reference/Makefile.am | 2 +- docs/reference/libsoup-2.4-sections.txt | 1 + libsoup/Makefile.am | 2 + libsoup/libsoup-2.4.sym | 1 + libsoup/soup-auth-manager.c | 217 ++++++++++++-------------------- libsoup/soup-auth-ntlm.c | 192 +++++++++++++++++----------- libsoup/soup-auth-ntlm.h | 6 +- libsoup/soup-auth.c | 27 ++++ libsoup/soup-auth.h | 8 +- libsoup/soup-connection-auth.c | 173 +++++++++++++++++++++++++ libsoup/soup-connection-auth.h | 52 ++++++++ libsoup/soup-message-private.h | 5 + libsoup/soup-message.c | 13 ++ libsoup/soup-session.c | 1 + 14 files changed, 483 insertions(+), 217 deletions(-) create mode 100644 libsoup/soup-connection-auth.c create mode 100644 libsoup/soup-connection-auth.h diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 74a6d925..17ae6caf 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -32,7 +32,7 @@ CFILE_GLOB= IGNORE_HFILES= soup.h soup-marshal.h soup-enum-types.h \ soup-message-private.h soup-session-private.h \ soup-auth-basic.h soup-auth-digest.h soup-auth-ntlm.h \ - soup-connection.h soup-auth-manager.h soup-auth-manager-ntlm.h \ + soup-connection.h soup-auth-manager.h soup-connection-auth.h \ soup-message-queue.h soup-path-map.h soup-gnome-features.h \ soup-proxy-resolver.h soup-proxy-resolver-gnome.h \ soup-proxy-resolver-static.h soup-directory-input-stream.h \ diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 963cbce1..e1bbbffb 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -536,6 +536,7 @@ soup_auth_get_info soup_auth_authenticate soup_auth_is_authenticated +soup_auth_is_ready soup_auth_get_authorization soup_auth_get_protection_space diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 7a9d6fca..59747441 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -119,6 +119,8 @@ libsoup_2_4_la_SOURCES = \ soup-client-input-stream.c \ soup-connection.h \ soup-connection.c \ + soup-connection-auth.h \ + soup-connection-auth.c \ soup-content-decoder.c \ soup-content-processor.h \ soup-content-processor.c \ diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 8ec30b14..521a5f71 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -53,6 +53,7 @@ soup_auth_get_type soup_auth_has_saved_password soup_auth_is_authenticated soup_auth_is_for_proxy +soup_auth_is_ready soup_auth_new soup_auth_ntlm_get_type soup_auth_save_password diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index d284826e..773291b6 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -13,6 +13,7 @@ #include "soup-auth-manager.h" #include "soup.h" +#include "soup-connection-auth.h" #include "soup-marshal.h" #include "soup-message-private.h" #include "soup-message-queue.h" @@ -36,13 +37,10 @@ G_DEFINE_TYPE_WITH_CODE (SoupAuthManager, soup_auth_manager, G_TYPE_OBJECT, typedef struct { SoupSession *session; GPtrArray *auth_types; - gboolean has_ntlm; + gboolean auto_ntlm; SoupAuth *proxy_auth; GHashTable *auth_hosts; - - GHashTable *connauths; - GHashTable *sockets_by_msg; } SoupAuthManagerPrivate; #define SOUP_AUTH_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerPrivate)) @@ -53,6 +51,8 @@ typedef struct { } SoupAuthHost; static void soup_auth_host_free (SoupAuthHost *host); +static SoupAuth *record_auth_for_uri (SoupAuthManagerPrivate *priv, + SoupURI *uri, SoupAuth *auth); static void soup_auth_manager_init (SoupAuthManager *manager) @@ -64,10 +64,6 @@ soup_auth_manager_init (SoupAuthManager *manager) soup_uri_host_equal, NULL, (GDestroyNotify)soup_auth_host_free); - - priv->connauths = g_hash_table_new_full (NULL, NULL, - NULL, g_object_unref); - priv->sockets_by_msg = g_hash_table_new (NULL, NULL); } static void @@ -81,9 +77,6 @@ soup_auth_manager_finalize (GObject *object) g_clear_object (&priv->proxy_auth); - g_hash_table_destroy (priv->connauths); - g_hash_table_destroy (priv->sockets_by_msg); - G_OBJECT_CLASS (soup_auth_manager_parent_class)->finalize (object); } @@ -133,7 +126,7 @@ soup_auth_manager_add_feature (SoupSessionFeature *feature, GType type) g_ptr_array_sort (priv->auth_types, auth_type_compare_func); if (type == SOUP_TYPE_AUTH_NTLM) - priv->has_ntlm = TRUE; + priv->auto_ntlm = TRUE; return TRUE; } @@ -153,7 +146,7 @@ soup_auth_manager_remove_feature (SoupSessionFeature *feature, GType type) for (i = 0; i < priv->auth_types->len; i++) { if (priv->auth_types->pdata[i] == (gpointer)auth_class) { if (type == SOUP_TYPE_AUTH_NTLM) - priv->has_ntlm = FALSE; + priv->auto_ntlm = FALSE; g_ptr_array_remove_index (priv->auth_types, i); return TRUE; @@ -349,10 +342,9 @@ check_auth (SoupMessage *msg, SoupAuth *auth) } static SoupAuthHost * -get_auth_host_for_message (SoupAuthManagerPrivate *priv, SoupMessage *msg) +get_auth_host_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri) { SoupAuthHost *host; - SoupURI *uri = soup_message_get_uri (msg); host = g_hash_table_lookup (priv->auth_hosts, uri); if (host) @@ -375,14 +367,30 @@ soup_auth_host_free (SoupAuthHost *host) g_slice_free (SoupAuthHost, host); } +static gboolean +make_auto_ntlm_auth (SoupAuthManagerPrivate *priv, SoupAuthHost *host) +{ + SoupAuth *auth; + + if (!priv->auto_ntlm) + return FALSE; + + auth = g_object_new (SOUP_TYPE_AUTH_NTLM, + SOUP_AUTH_HOST, host->uri->host, + NULL); + record_auth_for_uri (priv, host->uri, auth); + g_object_unref (auth); + return TRUE; +} + static SoupAuth * lookup_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg) { SoupAuthHost *host; const char *path, *realm; - host = get_auth_host_for_message (priv, msg); - if (!host->auth_realms) + host = get_auth_host_for_uri (priv, soup_message_get_uri (msg)); + if (!host->auth_realms && !make_auto_ntlm_auth (priv, host)) return NULL; path = soup_message_get_uri (msg)->path; @@ -395,7 +403,7 @@ lookup_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg) return NULL; } -static gboolean +static void authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, SoupMessage *msg, gboolean prior_auth_failed, gboolean proxy, gboolean can_interact) @@ -416,7 +424,7 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, uri = NULL; if (!uri) - return FALSE; + return; } else uri = soup_message_get_uri (msg); @@ -431,110 +439,19 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, g_signal_emit (manager, signals[AUTHENTICATE], 0, msg, auth, prior_auth_failed); } - - return soup_auth_is_authenticated (auth); -} - -static void -delete_connauth (SoupSocket *socket, gpointer user_data) -{ - SoupAuthManagerPrivate *priv = user_data; - - g_hash_table_remove (priv->connauths, socket); - g_signal_handlers_disconnect_by_func (socket, delete_connauth, priv); -} - -static SoupAuth * -get_connauth (SoupAuthManagerPrivate *priv, SoupSocket *socket) -{ - SoupAuth *auth; - - if (!priv->has_ntlm) - return NULL; - - auth = g_hash_table_lookup (priv->connauths, socket); - if (!auth) { - auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL); - g_hash_table_insert (priv->connauths, socket, auth); - g_signal_connect (socket, "disconnected", - G_CALLBACK (delete_connauth), priv); - } - - return auth; -} - -static void -unset_socket (SoupMessage *msg, gpointer user_data) -{ - SoupAuthManagerPrivate *priv = user_data; - - g_hash_table_remove (priv->sockets_by_msg, msg); - g_signal_handlers_disconnect_by_func (msg, unset_socket, priv); -} - -static void -set_socket_for_msg (SoupAuthManagerPrivate *priv, - SoupMessage *msg, SoupSocket *sock) -{ - if (!g_hash_table_lookup (priv->sockets_by_msg, msg)) { - g_signal_connect (msg, "finished", - G_CALLBACK (unset_socket), priv); - g_signal_connect (msg, "restarted", - G_CALLBACK (unset_socket), priv); - } - g_hash_table_insert (priv->sockets_by_msg, msg, sock); } static SoupAuth * -get_connauth_for_msg (SoupAuthManagerPrivate *priv, SoupMessage *msg) -{ - SoupSocket *sock; - - sock = g_hash_table_lookup (priv->sockets_by_msg, msg); - if (sock) - return g_hash_table_lookup (priv->connauths, sock); - else - return NULL; -} - -static void -auth_got_headers (SoupMessage *msg, gpointer manager) +record_auth_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri, + SoupAuth *auth) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); SoupAuthHost *host; - SoupAuth *auth, *prior_auth, *old_auth; + SoupAuth *old_auth; const char *path; char *auth_info, *old_auth_info; GSList *pspace, *p; - gboolean prior_auth_failed = FALSE; - - auth = get_connauth_for_msg (priv, msg); - if (auth) { - const char *header; - - header = auth_header_for_message (msg); - if (header && soup_auth_update (auth, msg, header)) { - if (!soup_auth_is_authenticated (auth)) { - g_signal_emit (manager, signals[AUTHENTICATE], 0, - msg, auth, FALSE); - } - return; - } - } - host = get_auth_host_for_message (priv, msg); - - /* See if we used auth last time */ - prior_auth = soup_message_get_auth (msg); - if (prior_auth && check_auth (msg, prior_auth)) { - auth = prior_auth; - if (!soup_auth_is_authenticated (auth)) - prior_auth_failed = TRUE; - } else { - auth = create_auth (priv, msg); - if (!auth) - return; - } + host = get_auth_host_for_uri (priv, uri); auth_info = soup_auth_get_info (auth); if (!host->auth_realms) { @@ -544,7 +461,7 @@ auth_got_headers (SoupMessage *msg, gpointer manager) } /* Record where this auth realm is used. */ - pspace = soup_auth_get_protection_space (auth, soup_message_get_uri (msg)); + pspace = soup_auth_get_protection_space (auth, uri); for (p = pspace; p; p = p->next) { path = p->data; old_auth_info = soup_path_map_lookup (host->auth_realms, path); @@ -566,16 +483,39 @@ auth_got_headers (SoupMessage *msg, gpointer manager) old_auth = g_hash_table_lookup (host->auths, auth_info); if (old_auth) { g_free (auth_info); - if (auth != old_auth && auth != prior_auth) { - g_object_unref (auth); - auth = old_auth; - } + return old_auth; + } else { + g_hash_table_insert (host->auths, auth_info, + g_object_ref (auth)); + return auth; + } +} + +static void +auth_got_headers (SoupMessage *msg, gpointer manager) +{ + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuth *auth, *prior_auth, *new_auth; + gboolean prior_auth_failed = FALSE; + + /* See if we used auth last time */ + prior_auth = soup_message_get_auth (msg); + if (prior_auth && check_auth (msg, prior_auth)) { + auth = g_object_ref (prior_auth); + if (!soup_auth_is_ready (auth, msg)) + prior_auth_failed = TRUE; } else { - g_hash_table_insert (host->auths, auth_info, auth); + auth = create_auth (priv, msg); + if (!auth) + return; } + new_auth = record_auth_for_uri (priv, soup_message_get_uri (msg), + auth); + g_object_unref (auth); + /* If we need to authenticate, try to do it. */ - authenticate_auth (manager, auth, msg, + authenticate_auth (manager, new_auth, msg, prior_auth_failed, FALSE, TRUE); } @@ -585,16 +525,17 @@ auth_got_body (SoupMessage *msg, gpointer manager) SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); SoupAuth *auth; - auth = get_connauth_for_msg (priv, msg); - if (auth && soup_auth_is_authenticated (auth)) { - SoupMessageFlags flags; + auth = lookup_auth (priv, msg); + if (auth && soup_auth_is_ready (auth, msg)) { + if (SOUP_IS_CONNECTION_AUTH (auth)) { + SoupMessageFlags flags; + + flags = soup_message_get_flags (msg); + soup_message_set_flags (msg, flags & ~SOUP_MESSAGE_NEW_CONNECTION); + } - flags = soup_message_get_flags (msg); - soup_message_set_flags (msg, flags & ~SOUP_MESSAGE_NEW_CONNECTION); - } else - auth = lookup_auth (priv, msg); - if (auth && soup_auth_is_authenticated (auth)) soup_session_requeue_message (priv->session, msg); + } } static void @@ -607,7 +548,7 @@ proxy_auth_got_headers (SoupMessage *msg, gpointer manager) /* See if we used auth last time */ prior_auth = soup_message_get_proxy_auth (msg); if (prior_auth && check_auth (msg, prior_auth)) { - if (!soup_auth_is_authenticated (prior_auth)) + if (!soup_auth_is_ready (prior_auth, msg)) prior_auth_failed = TRUE; } @@ -628,7 +569,7 @@ proxy_auth_got_body (SoupMessage *msg, gpointer manager) SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); SoupAuth *auth = priv->proxy_auth; - if (auth && soup_auth_is_authenticated (auth)) + if (auth && soup_auth_is_ready (auth, msg)) soup_session_requeue_message (priv->session, msg); } @@ -662,18 +603,20 @@ soup_auth_manager_request_started (SoupSessionFeature *feature, SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); SoupAuth *auth; - set_socket_for_msg (priv, msg, socket); auth = lookup_auth (priv, msg); if (auth) { - if (!authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE)) + authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE); + if (!soup_auth_is_ready (auth, msg)) auth = NULL; - } else - auth = get_connauth (priv, socket); + } soup_message_set_auth (msg, auth); auth = priv->proxy_auth; - if (!auth || !authenticate_auth (manager, auth, msg, FALSE, TRUE, FALSE)) - auth = NULL; + if (auth) { + authenticate_auth (manager, auth, msg, FALSE, TRUE, FALSE); + if (!soup_auth_is_ready (auth, msg)) + auth = NULL; + } soup_message_set_proxy_auth (msg, auth); } diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index 63f8c8b2..367a3cac 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -44,10 +44,14 @@ typedef enum { typedef struct { SoupNTLMState state; - char *username; - guchar nt_hash[21], lm_hash[21]; - char *nonce, *domain; + char *nonce; char *response_header; +} SoupNTLMConnectionState; + +typedef struct { + char *username, *domain; + guchar nt_hash[21], lm_hash[21]; + gboolean authenticated; #ifdef USE_NTLM_AUTH /* Use Samba's 'winbind' daemon to support NTLM single-sign-on, @@ -80,19 +84,15 @@ static void sso_ntlm_close (SoupAuthNTLMPrivate *priv); * Since: 2.34 */ -G_DEFINE_TYPE (SoupAuthNTLM, soup_auth_ntlm, SOUP_TYPE_AUTH) +G_DEFINE_TYPE (SoupAuthNTLM, soup_auth_ntlm, SOUP_TYPE_CONNECTION_AUTH) static void soup_auth_ntlm_init (SoupAuthNTLM *ntlm) { - SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (ntlm); #ifdef USE_NTLM_AUTH + SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (ntlm); const char *username = NULL, *slash; -#endif - - priv->state = SOUP_NTLM_NEW; -#ifdef USE_NTLM_AUTH priv->sso_available = TRUE; priv->fd_in = -1; priv->fd_out = -1; @@ -123,9 +123,6 @@ soup_auth_ntlm_finalize (GObject *object) memset (priv->nt_hash, 0, sizeof (priv->nt_hash)); memset (priv->lm_hash, 0, sizeof (priv->lm_hash)); - g_free (priv->nonce); - g_free (priv->response_header); - #ifdef USE_NTLM_AUTH sso_ntlm_close (priv); #endif @@ -255,75 +252,89 @@ wrfinish: } #endif /* USE_NTLM_AUTH */ +static gpointer +soup_auth_ntlm_create_connection_state (SoupConnectionAuth *auth) +{ + SoupNTLMConnectionState *conn; + + conn = g_slice_new0 (SoupNTLMConnectionState); + conn->state = SOUP_NTLM_NEW; + + return conn; +} + +static void +soup_auth_ntlm_free_connection_state (SoupConnectionAuth *auth, + gpointer state) +{ + SoupNTLMConnectionState *conn = state; + + g_free (conn->nonce); + g_free (conn->response_header); + g_slice_free (SoupNTLMConnectionState, conn); +} + static gboolean -soup_auth_ntlm_update (SoupAuth *auth, SoupMessage *msg, - GHashTable *auth_params) +soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg, + const char *auth_header, gpointer state) { SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); - GHashTableIter iter; - gpointer key, value; - char *header; + SoupNTLMConnectionState *conn = state; gboolean success = TRUE; - if (priv->state > SOUP_NTLM_SENT_REQUEST) { + if (conn->state > SOUP_NTLM_SENT_REQUEST) { /* We already authenticated, but then got another 401. * That means "permission denied", so don't try to * authenticate again. */ - priv->state = SOUP_NTLM_FAILED; + conn->state = SOUP_NTLM_FAILED; + + /* FIXME: we should only do this if the password never worked */ + priv->authenticated = FALSE; + return FALSE; } - /* The header will be something like "NTLM blahblahblah===", - * which soup_auth_update() will parse as - * "blahblahblah" = "==". Undo that. - */ - g_hash_table_iter_init (&iter, auth_params); - if (!g_hash_table_iter_next (&iter, &key, &value)) + if (!g_str_has_prefix (auth_header, "NTLM ")) return FALSE; - if (value) - header = g_strdup_printf ("%s=%s", (char *)key, (char *)value); - else - header = g_strdup (key); - - if (!soup_ntlm_parse_challenge (header, &priv->nonce, &priv->domain)) { - g_free (header); - priv->state = SOUP_NTLM_FAILED; + + if (!soup_ntlm_parse_challenge (auth_header + 5, &conn->nonce, &priv->domain)) { + conn->state = SOUP_NTLM_FAILED; return FALSE; } #ifdef USE_NTLM_AUTH - if (priv->sso_available && priv->state == SOUP_NTLM_SENT_REQUEST) { + if (priv->sso_available && conn->state == SOUP_NTLM_SENT_REQUEST) { char *input, *response; /* Re-Initiate ntlm_auth process in case it was closed/killed abnormally */ if (!sso_ntlm_initiate (priv)) { - priv->state = SOUP_NTLM_SSO_FAILED; + conn->state = SOUP_NTLM_SSO_FAILED; success = FALSE; goto out; } - input = g_strdup_printf ("TT %s\n", header); - response = sso_ntlm_response (priv, input, priv->state); + input = g_strdup_printf ("TT %s\n", auth_header + 5); + response = sso_ntlm_response (priv, input, conn->state); sso_ntlm_close (priv); g_free (input); if (!response) { - priv->state = SOUP_NTLM_SSO_FAILED; + conn->state = SOUP_NTLM_SSO_FAILED; success = FALSE; } else if (!g_ascii_strcasecmp (response, "PW")) { priv->sso_available = FALSE; g_free (response); - } else - priv->response_header = response; + } else { + conn->response_header = response; + priv->authenticated = TRUE; + } } out: #endif - g_free (header); - - if (priv->state == SOUP_NTLM_SENT_REQUEST) - priv->state = SOUP_NTLM_RECEIVED_CHALLENGE; + if (conn->state == SOUP_NTLM_SENT_REQUEST) + conn->state = SOUP_NTLM_RECEIVED_CHALLENGE; g_object_set (G_OBJECT (auth), SOUP_AUTH_REALM, priv->domain, @@ -335,7 +346,16 @@ soup_auth_ntlm_update (SoupAuth *auth, SoupMessage *msg, static GSList * soup_auth_ntlm_get_protection_space (SoupAuth *auth, SoupURI *source_uri) { - g_return_val_if_reached (NULL); + char *space, *p; + + space = g_strdup (source_uri->path); + + /* Strip query and filename component */ + p = strrchr (space, '/'); + if (p && p != space && p[1]) + *p = '\0'; + + return g_slist_prepend (NULL, space); } static void @@ -343,59 +363,66 @@ soup_auth_ntlm_authenticate (SoupAuth *auth, const char *username, const char *password) { SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); - const char *slash, *domain; + const char *slash; g_return_if_fail (username != NULL); g_return_if_fail (password != NULL); - g_return_if_fail (priv->nonce != NULL); + + if (priv->username) + g_free (priv->username); + if (priv->domain) + g_free (priv->domain); slash = strpbrk (username, "\\/"); if (slash) { - if (priv->domain) - g_free (priv->domain); - domain = priv->domain = g_strndup (username, slash - username); + priv->domain = g_strndup (username, slash - username); priv->username = g_strdup (slash + 1); } else { - domain = ""; + priv->domain = g_strdup (""); priv->username = g_strdup (username); } soup_ntlm_nt_hash (password, priv->nt_hash); soup_ntlm_lanmanager_hash (password, priv->lm_hash); - priv->response_header = soup_ntlm_response (priv->nonce, - priv->username, - priv->nt_hash, - priv->lm_hash, - NULL, - domain); - - g_free (priv->nonce); - priv->nonce = NULL; + priv->authenticated = TRUE; } static gboolean soup_auth_ntlm_is_authenticated (SoupAuth *auth) { - return SOUP_AUTH_NTLM_GET_PRIVATE (auth)->username != NULL && - SOUP_AUTH_NTLM_GET_PRIVATE (auth)->response_header != NULL; + SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); + + return priv->authenticated; +} + +static gboolean +soup_auth_ntlm_is_connection_ready (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer state) +{ + SoupNTLMConnectionState *conn = state; + + return conn->state != SOUP_NTLM_FAILED && conn->state != SOUP_NTLM_SSO_FAILED; } static char * -soup_auth_ntlm_get_authorization (SoupAuth *auth, SoupMessage *msg) +soup_auth_ntlm_get_connection_authorization (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer state) { - SoupAuthNTLMPrivate *priv = - SOUP_AUTH_NTLM_GET_PRIVATE (auth); + SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); + SoupNTLMConnectionState *conn = state; char *header = NULL; - switch (priv->state) { + switch (conn->state) { case SOUP_NTLM_NEW: #ifdef USE_NTLM_AUTH if (sso_ntlm_initiate (priv)) { - header = sso_ntlm_response (priv, "YR\n", priv->state); + header = sso_ntlm_response (priv, "YR\n", conn->state); if (header) { if (g_ascii_strcasecmp (header, "PW") != 0) { - priv->state = SOUP_NTLM_SENT_REQUEST; + conn->state = SOUP_NTLM_SENT_REQUEST; break; } else { g_free (header); @@ -411,12 +438,22 @@ soup_auth_ntlm_get_authorization (SoupAuth *auth, SoupMessage *msg) */ #endif header = soup_ntlm_request (); - priv->state = SOUP_NTLM_SENT_REQUEST; + conn->state = SOUP_NTLM_SENT_REQUEST; break; case SOUP_NTLM_RECEIVED_CHALLENGE: - header = priv->response_header; - priv->response_header = NULL; - priv->state = SOUP_NTLM_SENT_RESPONSE; + if (conn->response_header) { + header = conn->response_header; + conn->response_header = NULL; + } else { + header = soup_ntlm_response (conn->nonce, + priv->username, + priv->nt_hash, + priv->lm_hash, + NULL, + priv->domain); + } + g_clear_pointer (&conn->nonce, g_free); + conn->state = SOUP_NTLM_SENT_RESPONSE; break; #ifdef USE_NTLM_AUTH case SOUP_NTLM_SSO_FAILED: @@ -424,7 +461,7 @@ soup_auth_ntlm_get_authorization (SoupAuth *auth, SoupMessage *msg) g_warning ("NTLM single-sign-on by using %s failed", NTLM_AUTH); priv->sso_available = FALSE; header = soup_ntlm_request (); - priv->state = SOUP_NTLM_SENT_REQUEST; + conn->state = SOUP_NTLM_SENT_REQUEST; break; #endif default: @@ -438,6 +475,7 @@ static void soup_auth_ntlm_class_init (SoupAuthNTLMClass *auth_ntlm_class) { SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_ntlm_class); + SoupConnectionAuthClass *connauth_class = SOUP_CONNECTION_AUTH_CLASS (auth_ntlm_class); GObjectClass *object_class = G_OBJECT_CLASS (auth_ntlm_class); g_type_class_add_private (auth_ntlm_class, sizeof (SoupAuthNTLMPrivate)); @@ -445,11 +483,15 @@ soup_auth_ntlm_class_init (SoupAuthNTLMClass *auth_ntlm_class) auth_class->scheme_name = "NTLM"; auth_class->strength = 3; - auth_class->update = soup_auth_ntlm_update; auth_class->get_protection_space = soup_auth_ntlm_get_protection_space; auth_class->authenticate = soup_auth_ntlm_authenticate; auth_class->is_authenticated = soup_auth_ntlm_is_authenticated; - auth_class->get_authorization = soup_auth_ntlm_get_authorization; + + connauth_class->create_connection_state = soup_auth_ntlm_create_connection_state; + connauth_class->free_connection_state = soup_auth_ntlm_free_connection_state; + connauth_class->update_connection = soup_auth_ntlm_update_connection; + connauth_class->get_connection_authorization = soup_auth_ntlm_get_connection_authorization; + connauth_class->is_connection_ready = soup_auth_ntlm_is_connection_ready; object_class->finalize = soup_auth_ntlm_finalize; diff --git a/libsoup/soup-auth-ntlm.h b/libsoup/soup-auth-ntlm.h index 7ed9bd3e..43c40856 100644 --- a/libsoup/soup-auth-ntlm.h +++ b/libsoup/soup-auth-ntlm.h @@ -6,7 +6,7 @@ #ifndef SOUP_AUTH_NTLM_H #define SOUP_AUTH_NTLM_H 1 -#include "soup-auth.h" +#include "soup-connection-auth.h" #define SOUP_AUTH_NTLM(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLM)) #define SOUP_AUTH_NTLM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMClass)) @@ -15,12 +15,12 @@ #define SOUP_AUTH_NTLM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_NTLM, SoupAuthNTLMClass)) typedef struct { - SoupAuth parent; + SoupConnectionAuth parent; } SoupAuthNTLM; typedef struct { - SoupAuthClass parent_class; + SoupConnectionAuthClass parent_class; } SoupAuthNTLMClass; diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c index 77fb45e9..5ce92d55 100644 --- a/libsoup/soup-auth.c +++ b/libsoup/soup-auth.c @@ -458,6 +458,33 @@ soup_auth_get_authorization (SoupAuth *auth, SoupMessage *msg) return SOUP_AUTH_GET_CLASS (auth)->get_authorization (auth, msg); } +/** + * soup_auth_is_ready: + * @auth: a #SoupAuth + * @msg: a #SoupMessage + * + * Tests if @auth is ready to make a request for @msg with. For most + * auths, this is equivalent to soup_auth_is_authenticated(), but for + * some auth types (eg, NTLM), the auth may be sendable (eg, as an + * authentication request) even before it is authenticated. + * + * Return value: %TRUE if @auth is ready to make a request with. + * + * Since: 2.42 + **/ +gboolean +soup_auth_is_ready (SoupAuth *auth, + SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_AUTH (auth), TRUE); + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), TRUE); + + if (SOUP_AUTH_GET_CLASS (auth)->is_ready) + return SOUP_AUTH_GET_CLASS (auth)->is_ready (auth, msg); + else + return SOUP_AUTH_GET_CLASS (auth)->is_authenticated (auth); +} + /** * soup_auth_get_protection_space: * @auth: a #SoupAuth diff --git a/libsoup/soup-auth.h b/libsoup/soup-auth.h index 8abda8e0..824857e2 100644 --- a/libsoup/soup-auth.h +++ b/libsoup/soup-auth.h @@ -44,8 +44,11 @@ typedef struct { char * (*get_authorization) (SoupAuth *auth, SoupMessage *msg); + + gboolean (*is_ready) (SoupAuth *auth, + SoupMessage *msg); + /* Padding for future expansion */ - void (*_libsoup_reserved1) (void); void (*_libsoup_reserved2) (void); void (*_libsoup_reserved3) (void); void (*_libsoup_reserved4) (void); @@ -76,6 +79,9 @@ void soup_auth_authenticate (SoupAuth *auth, const char *username, const char *password); gboolean soup_auth_is_authenticated (SoupAuth *auth); +SOUP_AVAILABLE_IN_2_42 +gboolean soup_auth_is_ready (SoupAuth *auth, + SoupMessage *msg); char *soup_auth_get_authorization (SoupAuth *auth, SoupMessage *msg); diff --git a/libsoup/soup-connection-auth.c b/libsoup/soup-connection-auth.c new file mode 100644 index 00000000..fc327335 --- /dev/null +++ b/libsoup/soup-connection-auth.c @@ -0,0 +1,173 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-connection-auth.c: Abstract base class for hacky Microsoft + * connection-based auth mechanisms (NTLM and Negotiate) + * + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "soup-connection-auth.h" +#include "soup.h" +#include "soup-connection.h" +#include "soup-message-private.h" + +G_DEFINE_ABSTRACT_TYPE (SoupConnectionAuth, soup_connection_auth, SOUP_TYPE_AUTH) + +struct SoupConnectionAuthPrivate { + GHashTable *conns; +}; + +static void +soup_connection_auth_init (SoupConnectionAuth *auth) +{ + auth->priv = G_TYPE_INSTANCE_GET_PRIVATE (auth, SOUP_TYPE_CONNECTION_AUTH, SoupConnectionAuthPrivate); + + auth->priv->conns = g_hash_table_new (NULL, NULL); +} + +static void connection_disconnected (SoupConnection *conn, gpointer user_data); + +static void +soup_connection_auth_free_connection_state (SoupConnectionAuth *auth, + SoupConnection *conn, + gpointer state) +{ + g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (connection_disconnected), auth); + SOUP_CONNECTION_AUTH_GET_CLASS (auth)->free_connection_state (auth, state); +} + +static void +connection_disconnected (SoupConnection *conn, gpointer user_data) +{ + SoupConnectionAuth *auth = user_data; + gpointer state; + + state = g_hash_table_lookup (auth->priv->conns, conn); + g_hash_table_remove (auth->priv->conns, conn); + soup_connection_auth_free_connection_state (auth, conn, state); +} + +static void +soup_connection_auth_finalize (GObject *object) +{ + SoupConnectionAuth *auth = SOUP_CONNECTION_AUTH (object); + GHashTableIter iter; + gpointer conn, state; + + g_hash_table_iter_init (&iter, auth->priv->conns); + while (g_hash_table_iter_next (&iter, &conn, &state)) { + soup_connection_auth_free_connection_state (auth, conn, state); + g_hash_table_iter_remove (&iter); + } + g_hash_table_destroy (auth->priv->conns); + + G_OBJECT_CLASS (soup_connection_auth_parent_class)->finalize (object); +} + +static gpointer +get_connection_state_for_message (SoupConnectionAuth *auth, SoupMessage *msg) +{ + SoupConnection *conn; + gpointer state; + + conn = soup_message_get_connection (msg); + state = g_hash_table_lookup (auth->priv->conns, conn); + if (state) + return state; + + state = SOUP_CONNECTION_AUTH_GET_CLASS (auth)->create_connection_state (auth); + if (conn) { + g_signal_connect (conn, "disconnected", + G_CALLBACK (connection_disconnected), auth); + } + + g_hash_table_insert (auth->priv->conns, conn, state); + return state; +} + +static gboolean +soup_connection_auth_update (SoupAuth *auth, + SoupMessage *msg, + GHashTable *auth_params) +{ + SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); + gpointer conn = get_connection_state_for_message (cauth, msg); + GHashTableIter iter; + GString *auth_header; + gpointer key, value; + gboolean result; + + /* Recreate @auth_header out of @auth_params. If the + * base64 data ended with 1 or more "="s, then it + * will have been parsed as key=value. Otherwise + * it will all have been parsed as key, and value + * will be %NULL. + */ + auth_header = g_string_new (soup_auth_get_scheme_name (auth)); + g_hash_table_iter_init (&iter, auth_params); + if (g_hash_table_iter_next (&iter, &key, &value)) { + if (value) { + g_string_append_printf (auth_header, " %s=%s", + (char *)key, + (char *)value); + } else { + g_string_append_printf (auth_header, " %s", + (char *)key); + } + + if (g_hash_table_iter_next (&iter, &key, &value)) { + g_string_free (auth_header, TRUE); + return FALSE; + } + } + + result = SOUP_CONNECTION_AUTH_GET_CLASS (auth)-> + update_connection (cauth, msg, auth_header->str, conn); + + g_string_free (auth_header, TRUE); + return result; +} + +static char * +soup_connection_auth_get_authorization (SoupAuth *auth, + SoupMessage *msg) +{ + SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); + gpointer conn = get_connection_state_for_message (cauth, msg); + + return SOUP_CONNECTION_AUTH_GET_CLASS (auth)-> + get_connection_authorization (cauth, msg, conn); +} + +static gboolean +soup_connection_auth_is_ready (SoupAuth *auth, + SoupMessage *msg) +{ + SoupConnectionAuth *cauth = SOUP_CONNECTION_AUTH (auth); + gpointer conn = get_connection_state_for_message (cauth, msg); + + return SOUP_CONNECTION_AUTH_GET_CLASS (auth)-> + is_connection_ready (SOUP_CONNECTION_AUTH (auth), msg, conn); +} + +static void +soup_connection_auth_class_init (SoupConnectionAuthClass *connauth_class) +{ + SoupAuthClass *auth_class = SOUP_AUTH_CLASS (connauth_class); + GObjectClass *object_class = G_OBJECT_CLASS (connauth_class); + + g_type_class_add_private (connauth_class, sizeof (SoupConnectionAuthPrivate)); + + auth_class->update = soup_connection_auth_update; + auth_class->get_authorization = soup_connection_auth_get_authorization; + auth_class->is_ready = soup_connection_auth_is_ready; + + object_class->finalize = soup_connection_auth_finalize; +} diff --git a/libsoup/soup-connection-auth.h b/libsoup/soup-connection-auth.h new file mode 100644 index 00000000..251ca359 --- /dev/null +++ b/libsoup/soup-connection-auth.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2010 Red Hat, Inc. + */ + +#ifndef SOUP_CONNECTION_AUTH_H +#define SOUP_CONNECTION_AUTH_H 1 + +#include + +G_BEGIN_DECLS + +#define SOUP_TYPE_CONNECTION_AUTH (soup_connection_auth_get_type ()) +#define SOUP_CONNECTION_AUTH(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_CONNECTION_AUTH, SoupConnectionAuth)) +#define SOUP_CONNECTION_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_CONNECTION_AUTH, SoupConnectionAuthClass)) +#define SOUP_IS_CONNECTION_AUTH(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_CONNECTION_AUTH)) +#define SOUP_IS_CONNECTION_AUTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_CONNECTION_AUTH)) +#define SOUP_CONNECTION_AUTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CONNECTION_AUTH, SoupConnectionAuthClass)) + +typedef struct SoupConnectionAuthPrivate SoupConnectionAuthPrivate; + +typedef struct { + SoupAuth parent; + + SoupConnectionAuthPrivate *priv; +} SoupConnectionAuth; + +typedef struct { + SoupAuthClass parent_class; + + gpointer (*create_connection_state) (SoupConnectionAuth *auth); + void (*free_connection_state) (SoupConnectionAuth *auth, + gpointer conn); + + gboolean (*update_connection) (SoupConnectionAuth *auth, + SoupMessage *msg, + const char *auth_header, + gpointer conn); + char *(*get_connection_authorization) (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer conn); + gboolean (*is_connection_ready) (SoupConnectionAuth *auth, + SoupMessage *msg, + gpointer conn); +} SoupConnectionAuthClass; + +SOUP_AVAILABLE_IN_2_42 +GType soup_connection_auth_get_type (void); + +G_END_DECLS + +#endif /* SOUP_CONNECTION_AUTH_H */ diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index 74b6e0d7..de7cb7d0 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -31,6 +31,7 @@ typedef struct { SoupAddress *addr; SoupAuth *auth, *proxy_auth; + SoupConnection *connection; GSList *disabled_features; @@ -138,4 +139,8 @@ GInputStream *soup_message_setup_body_istream (GInputStream *body_stream, void soup_message_set_soup_request (SoupMessage *msg, SoupRequest *req); +SoupConnection *soup_message_get_connection (SoupMessage *msg); +void soup_message_set_connection (SoupMessage *msg, + SoupConnection *conn); + #endif /* SOUP_MESSAGE_PRIVATE_H */ diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 7fe6db84..67b6e6f5 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1260,6 +1260,19 @@ soup_message_get_proxy_auth (SoupMessage *msg) return SOUP_MESSAGE_GET_PRIVATE (msg)->proxy_auth; } +SoupConnection * +soup_message_get_connection (SoupMessage *msg) +{ + return SOUP_MESSAGE_GET_PRIVATE (msg)->connection; +} + +void +soup_message_set_connection (SoupMessage *msg, + SoupConnection *conn) +{ + SOUP_MESSAGE_GET_PRIVATE (msg)->connection = conn; +} + /** * soup_message_cleanup_response: * @msg: a #SoupMessage diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 63e90b3d..20e92329 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1162,6 +1162,7 @@ soup_session_set_item_connection (SoupSession *session, } item->conn = conn; + soup_message_set_connection (item->msg, conn); if (item->conn) { g_object_ref (item->conn); -- cgit v1.2.1 From 2a6100c60c0cde68cbb37ff11075525df222b5da Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 1 Jan 2013 11:43:28 -0500 Subject: SoupAuthManager: make this public --- docs/reference/Makefile.am | 2 +- docs/reference/libsoup-2.4-docs.sgml | 1 + docs/reference/libsoup-2.4-sections.txt | 16 +++++++ libsoup/Makefile.am | 2 +- libsoup/libsoup-2.4.sym | 1 + libsoup/soup-auth-manager.c | 80 ++++++++++++++++++++++++++------- libsoup/soup-auth-manager.h | 3 ++ libsoup/soup.h | 1 + 8 files changed, 87 insertions(+), 19 deletions(-) diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 17ae6caf..adb475de 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -32,7 +32,7 @@ CFILE_GLOB= IGNORE_HFILES= soup.h soup-marshal.h soup-enum-types.h \ soup-message-private.h soup-session-private.h \ soup-auth-basic.h soup-auth-digest.h soup-auth-ntlm.h \ - soup-connection.h soup-auth-manager.h soup-connection-auth.h \ + soup-connection.h soup-connection-auth.h \ soup-message-queue.h soup-path-map.h soup-gnome-features.h \ soup-proxy-resolver.h soup-proxy-resolver-gnome.h \ soup-proxy-resolver-static.h soup-directory-input-stream.h \ diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index f19848f5..f28c6059 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -46,6 +46,7 @@ Additional Features + diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index e1bbbffb..fc56dc50 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -566,6 +566,22 @@ soup_auth_has_saved_password soup_auth_save_password +
+soup-auth-manager +SoupAuthManager +SoupAuthManager +SOUP_TYPE_AUTH_MANAGER + +SoupAuthManagerPrivate +SoupAuthManagerClass +SOUP_AUTH_MANAGER +SOUP_IS_AUTH_MANAGER +SOUP_AUTH_MANAGER_CLASS +SOUP_IS_AUTH_MANAGER_CLASS +SOUP_AUTH_MANAGER_GET_CLASS +soup_auth_manager_get_type +
+
soup-socket SoupSocket diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index 59747441..d2e2cde3 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -29,6 +29,7 @@ soup_headers = \ soup-auth-domain.h \ soup-auth-domain-basic.h \ soup-auth-domain-digest.h \ + soup-auth-manager.h \ soup-cache.h \ soup-content-decoder.h \ soup-content-sniffer.h \ @@ -105,7 +106,6 @@ libsoup_2_4_la_SOURCES = \ soup-auth-domain.c \ soup-auth-domain-basic.c \ soup-auth-domain-digest.c \ - soup-auth-manager.h \ soup-auth-manager.c \ soup-body-input-stream.h \ soup-body-input-stream.c \ diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 521a5f71..d3631b22 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -54,6 +54,7 @@ soup_auth_has_saved_password soup_auth_is_authenticated soup_auth_is_for_proxy soup_auth_is_ready +soup_auth_manager_get_type soup_auth_new soup_auth_ntlm_get_type soup_auth_save_password diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index 773291b6..c4cf783a 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -20,6 +20,37 @@ #include "soup-path-map.h" #include "soup-session-private.h" +/** + * SECTION:soup-auth-manager + * @short_description: HTTP client-side authentication handler + * @see_also: #SoupSession, #SoupAuth + * + * #SoupAuthManager is the #SoupSessionFeature that handles HTTP + * authentication for a #SoupSession. + * + * A #SoupAuthManager is added to the session by default, and normally + * you don't need to worry about it at all. However, if you want to + * disable HTTP authentication, you can remove the feature from the + * session with soup_session_remove_feature_by_type(), or disable it on + * individual requests with soup_message_disable_feature(). + * + * Since: 2.42 + **/ + +/** + * SOUP_TYPE_AUTH_MANAGER: + * + * The #GType of #SoupAuthManager; you can use this with + * soup_session_remove_feature_by_type() or + * soup_message_disable_feature(). + * + * (Although this type has only been publicly visible since libsoup + * 2.42, it has always existed in the background, and you can use + * g_type_from_name ("SoupAuthManager") + * to get its #GType in earlier releases.) + * + * Since: 2.42 + */ static void soup_auth_manager_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); static SoupSessionFeatureInterface *soup_session_feature_default_interface; @@ -34,15 +65,14 @@ G_DEFINE_TYPE_WITH_CODE (SoupAuthManager, soup_auth_manager, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, soup_auth_manager_session_feature_init)) -typedef struct { +struct SoupAuthManagerPrivate { SoupSession *session; GPtrArray *auth_types; gboolean auto_ntlm; SoupAuth *proxy_auth; GHashTable *auth_hosts; -} SoupAuthManagerPrivate; -#define SOUP_AUTH_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerPrivate)) +}; typedef struct { SoupURI *uri; @@ -57,7 +87,9 @@ static SoupAuth *record_auth_for_uri (SoupAuthManagerPrivate *priv, static void soup_auth_manager_init (SoupAuthManager *manager) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuthManagerPrivate *priv; + + priv = manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerPrivate); priv->auth_types = g_ptr_array_new_with_free_func ((GDestroyNotify)g_type_class_unref); priv->auth_hosts = g_hash_table_new_full (soup_uri_host_hash, @@ -69,7 +101,7 @@ soup_auth_manager_init (SoupAuthManager *manager) static void soup_auth_manager_finalize (GObject *object) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (object); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (object)->priv; g_ptr_array_free (priv->auth_types, TRUE); @@ -89,6 +121,20 @@ soup_auth_manager_class_init (SoupAuthManagerClass *auth_manager_class) object_class->finalize = soup_auth_manager_finalize; + /** + * SoupAuthManager::authenticate: + * @manager: the #SoupAuthManager + * @msg: the #SoupMessage being sent + * @auth: the #SoupAuth to authenticate + * @retrying: %TRUE if this is the second (or later) attempt + * + * Emitted when the manager requires the application to + * provide authentication credentials. + * + * #SoupSession connects to this signal and emits its own + * #SoupSession::authenticate signal when it is emitted, so + * you shouldn't need to use this signal directly. + */ signals[AUTHENTICATE] = g_signal_new ("authenticate", G_OBJECT_CLASS_TYPE (object_class), @@ -115,7 +161,7 @@ auth_type_compare_func (gconstpointer a, gconstpointer b) static gboolean soup_auth_manager_add_feature (SoupSessionFeature *feature, GType type) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (feature); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv; SoupAuthClass *auth_class; if (!g_type_is_a (type, SOUP_TYPE_AUTH)) @@ -134,7 +180,7 @@ soup_auth_manager_add_feature (SoupSessionFeature *feature, GType type) static gboolean soup_auth_manager_remove_feature (SoupSessionFeature *feature, GType type) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (feature); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv; SoupAuthClass *auth_class; int i; @@ -159,7 +205,7 @@ soup_auth_manager_remove_feature (SoupSessionFeature *feature, GType type) static gboolean soup_auth_manager_has_feature (SoupSessionFeature *feature, GType type) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (feature); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv; SoupAuthClass *auth_class; int i; @@ -175,14 +221,14 @@ soup_auth_manager_has_feature (SoupSessionFeature *feature, GType type) } static void -soup_auth_manager_attach (SoupSessionFeature *manager, SoupSession *session) +soup_auth_manager_attach (SoupSessionFeature *feature, SoupSession *session) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (feature)->priv; /* FIXME: should support multiple sessions */ priv->session = session; - soup_session_feature_default_interface->attach (manager, session); + soup_session_feature_default_interface->attach (feature, session); } static inline const char * @@ -408,7 +454,7 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, SoupMessage *msg, gboolean prior_auth_failed, gboolean proxy, gboolean can_interact) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuthManagerPrivate *priv = manager->priv; SoupURI *uri; if (proxy) { @@ -494,7 +540,7 @@ record_auth_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri, static void auth_got_headers (SoupMessage *msg, gpointer manager) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; SoupAuth *auth, *prior_auth, *new_auth; gboolean prior_auth_failed = FALSE; @@ -522,7 +568,7 @@ auth_got_headers (SoupMessage *msg, gpointer manager) static void auth_got_body (SoupMessage *msg, gpointer manager) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; SoupAuth *auth; auth = lookup_auth (priv, msg); @@ -541,7 +587,7 @@ auth_got_body (SoupMessage *msg, gpointer manager) static void proxy_auth_got_headers (SoupMessage *msg, gpointer manager) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; SoupAuth *prior_auth; gboolean prior_auth_failed = FALSE; @@ -566,7 +612,7 @@ proxy_auth_got_headers (SoupMessage *msg, gpointer manager) static void proxy_auth_got_body (SoupMessage *msg, gpointer manager) { - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; SoupAuth *auth = priv->proxy_auth; if (auth && soup_auth_is_ready (auth, msg)) @@ -600,7 +646,7 @@ soup_auth_manager_request_started (SoupSessionFeature *feature, SoupSocket *socket) { SoupAuthManager *manager = SOUP_AUTH_MANAGER (feature); - SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER_GET_PRIVATE (manager); + SoupAuthManagerPrivate *priv = manager->priv; SoupAuth *auth; auth = lookup_auth (priv, msg); diff --git a/libsoup/soup-auth-manager.h b/libsoup/soup-auth-manager.h index a4ee3165..a9436bde 100644 --- a/libsoup/soup-auth-manager.h +++ b/libsoup/soup-auth-manager.h @@ -18,9 +18,12 @@ G_BEGIN_DECLS #define SOUP_IS_AUTH_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_AUTH_MANAGER)) #define SOUP_AUTH_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_AUTH_MANAGER, SoupAuthManagerClass)) +typedef struct SoupAuthManagerPrivate SoupAuthManagerPrivate; + typedef struct { GObject parent; + SoupAuthManagerPrivate *priv; } SoupAuthManager; typedef struct { diff --git a/libsoup/soup.h b/libsoup/soup.h index fd836feb..0a7944ee 100644 --- a/libsoup/soup.h +++ b/libsoup/soup.h @@ -15,6 +15,7 @@ extern "C" { #include #include #include +#include #include #include #include -- cgit v1.2.1 From b99acd6fcc30ea537d8a758ff8ce5e2f84848781 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 1 Jan 2013 11:46:18 -0500 Subject: soup-auth-manager: add soup_auth_manager_use_auth() Add soup_auth_manager_use_auth(), for "preloading" authentication, and make the old automatically-request-NTLM behavior happen only for the legacy SoupSession subclasses. --- docs/reference/libsoup-2.4-sections.txt | 1 + docs/reference/session-porting.xml | 45 +++++++++++++++++++++++++++++++++ libsoup/libsoup-2.4.sym | 1 + libsoup/soup-auth-manager.c | 34 ++++++++++++++++++++++++- libsoup/soup-auth-manager.h | 4 +++ libsoup/soup-auth.c | 14 ++++++---- tests/ntlm-test.c | 16 +++++++++--- 7 files changed, 105 insertions(+), 10 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index fc56dc50..52e505d3 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -571,6 +571,7 @@ soup_auth_save_password SoupAuthManager SoupAuthManager SOUP_TYPE_AUTH_MANAGER +soup_auth_manager_use_auth SoupAuthManagerPrivate SoupAuthManagerClass diff --git a/docs/reference/session-porting.xml b/docs/reference/session-porting.xml index 680f75aa..bf1aa411 100644 --- a/docs/reference/session-porting.xml +++ b/docs/reference/session-porting.xml @@ -105,6 +105,51 @@ linkend="SoupSessionAsync">SoupSessionAsync and + +Differences in feature behavior + + +If you are using NTLM authentication, the new SoupSession +behaves slightly differently from the old session types. + + + +First, the deprecated SOUP_SESSION_USE_NTLM +property is no longer supported. If you want to add support for NTLM +to a session, call soup_session_add_feature_by_type(), +passing SOUP_TYPE_AUTH_NTLM. + + + +Second, with the old session types, enabling NTLM would cause all +(otherwise-unauthenticated) requests to be sent with an NTLM request +in the Authorization header. That is, libsoup would +assume that all servers supported NTLM, and would attempt to begin +negotiating NTLM authentication before the server ever returned a 401 +response. With the plain SoupSession, this no longer +happens. If you want the old behavior, you need to call soup_auth_manager_use_auth() +for each host to "preload" the NTLM authentication: + + + + SoupAuthManager *auth_manager; + SoupAuth *auth; + SoupURI *uri; + + auth_manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER)); + auth = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL); + uri = soup_uri_new ("http://ntlm-using-host.example.com/"); + soup_auth_manager_use_auth (auth_manager, uri, auth); + g_object_unref (auth); + soup_uri_free (auth); + + + + Differences in SoupMessage-sending APIs diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index d3631b22..6b82f5a4 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -55,6 +55,7 @@ soup_auth_is_authenticated soup_auth_is_for_proxy soup_auth_is_ready soup_auth_manager_get_type +soup_auth_manager_use_auth soup_auth_new soup_auth_ntlm_get_type soup_auth_save_password diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index c4cf783a..3483a32c 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -171,7 +171,11 @@ soup_auth_manager_add_feature (SoupSessionFeature *feature, GType type) g_ptr_array_add (priv->auth_types, auth_class); g_ptr_array_sort (priv->auth_types, auth_type_compare_func); - if (type == SOUP_TYPE_AUTH_NTLM) + /* Plain SoupSession does not get the backward-compat + * auto-NTLM behavior; SoupSession subclasses do. + */ + if (type == SOUP_TYPE_AUTH_NTLM && + G_TYPE_FROM_INSTANCE (priv->session) != SOUP_TYPE_SESSION) priv->auto_ntlm = TRUE; return TRUE; @@ -675,6 +679,34 @@ soup_auth_manager_request_unqueued (SoupSessionFeature *manager, 0, 0, NULL, NULL, manager); } +/** + * soup_auth_manager_use_auth: + * @manager: a #SoupAuthManager + * @uri: the #SoupURI under which @auth is to be used + * @auth: the #SoupAuth to use + * + * Records that @auth is to be used under @uri, as though a + * WWW-Authenticate header had been received at that URI. This can be + * used to "preload" @manager's auth cache, to avoid an extra HTTP + * round trip in the case where you know ahead of time that a 401 + * response will be returned. + * + * This is only useful for authentication types where the initial + * Authorization header does not depend on any additional information + * from the server. (Eg, Basic or NTLM, but not Digest.) + * + * Since: 2.42 + */ +void +soup_auth_manager_use_auth (SoupAuthManager *manager, + SoupURI *uri, + SoupAuth *auth) +{ + SoupAuthManagerPrivate *priv = manager->priv; + + record_auth_for_uri (priv, uri, auth); +} + static void soup_auth_manager_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data) diff --git a/libsoup/soup-auth-manager.h b/libsoup/soup-auth-manager.h index a9436bde..c1fcc6e6 100644 --- a/libsoup/soup-auth-manager.h +++ b/libsoup/soup-auth-manager.h @@ -35,6 +35,10 @@ typedef struct { GType soup_auth_manager_get_type (void); +void soup_auth_manager_use_auth (SoupAuthManager *manager, + SoupURI *uri, + SoupAuth *auth); + G_END_DECLS #endif /* SOUP_AUTH_MANAGER_H */ diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c index 5ce92d55..8f1e2182 100644 --- a/libsoup/soup-auth.c +++ b/libsoup/soup-auth.c @@ -12,9 +12,9 @@ #include #include "soup-auth.h" -#include "soup-headers.h" +#include "soup.h" +#include "soup-connection-auth.h" #include "soup-marshal.h" -#include "soup-uri.h" /** * SECTION:soup-auth @@ -417,9 +417,13 @@ soup_auth_get_info (SoupAuth *auth) { g_return_val_if_fail (SOUP_IS_AUTH (auth), NULL); - return g_strdup_printf ("%s:%s", - SOUP_AUTH_GET_CLASS (auth)->scheme_name, - auth->realm); + if (SOUP_IS_CONNECTION_AUTH (auth)) + return g_strdup (SOUP_AUTH_GET_CLASS (auth)->scheme_name); + else { + return g_strdup_printf ("%s:%s", + SOUP_AUTH_GET_CLASS (auth)->scheme_name, + auth->realm); + } } /** diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index 3184ffcf..fa31280e 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -333,9 +333,7 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, gboolean bob_via_ntlm = use_ntlm && bob; gboolean alice_via_basic = !use_ntlm && alice; - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - if (use_ntlm) - soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); if (user) { g_signal_connect (session, "authenticate", @@ -343,6 +341,16 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, if (use_ntlm && !use_builtin_ntlm) g_setenv ("NTLMUSER", user, TRUE); } + if (use_ntlm) { + SoupAuthManager *auth_manager; + SoupAuth *ntlm; + + soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); + auth_manager = SOUP_AUTH_MANAGER (soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER)); + ntlm = g_object_new (SOUP_TYPE_AUTH_NTLM, NULL); + soup_auth_manager_use_auth (auth_manager, base_uri, ntlm); + g_object_unref (ntlm); + } /* 1. Server doesn't request auth, so both get_ntlm_prompt and * get_basic_prompt are both FALSE, and likewise do_basic. But @@ -464,7 +472,7 @@ main (int argc, char **argv) test_init (argc, argv, NULL); - server = soup_test_server_new (FALSE); + server = soup_test_server_new (TRUE); connections = g_hash_table_new (NULL, NULL); soup_server_add_handler (server, NULL, server_callback, connections, NULL); -- cgit v1.2.1 From c435fd0695ad927921b83d93295d0e79ae4cfe0e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 1 Jan 2013 14:18:46 -0500 Subject: soup-auth-manager: make this thread-safe Very belatedly, make SoupAuthManager thread-safe. It also ensures that any SoupAuth that it manages is only manipulated from one thread at a time. --- libsoup/soup-auth-manager.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index 3483a32c..e945dd7c 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -70,6 +70,7 @@ struct SoupAuthManagerPrivate { GPtrArray *auth_types; gboolean auto_ntlm; + GMutex lock; SoupAuth *proxy_auth; GHashTable *auth_hosts; }; @@ -96,6 +97,7 @@ soup_auth_manager_init (SoupAuthManager *manager) soup_uri_host_equal, NULL, (GDestroyNotify)soup_auth_host_free); + g_mutex_init (&priv->lock); } static void @@ -109,6 +111,8 @@ soup_auth_manager_finalize (GObject *object) g_clear_object (&priv->proxy_auth); + g_mutex_clear (&priv->lock); + G_OBJECT_CLASS (soup_auth_manager_parent_class)->finalize (object); } @@ -548,6 +552,8 @@ auth_got_headers (SoupMessage *msg, gpointer manager) SoupAuth *auth, *prior_auth, *new_auth; gboolean prior_auth_failed = FALSE; + g_mutex_lock (&priv->lock); + /* See if we used auth last time */ prior_auth = soup_message_get_auth (msg); if (prior_auth && check_auth (msg, prior_auth)) { @@ -556,8 +562,10 @@ auth_got_headers (SoupMessage *msg, gpointer manager) prior_auth_failed = TRUE; } else { auth = create_auth (priv, msg); - if (!auth) + if (!auth) { + g_mutex_unlock (&priv->lock); return; + } } new_auth = record_auth_for_uri (priv, soup_message_get_uri (msg), @@ -567,6 +575,7 @@ auth_got_headers (SoupMessage *msg, gpointer manager) /* If we need to authenticate, try to do it. */ authenticate_auth (manager, new_auth, msg, prior_auth_failed, FALSE, TRUE); + g_mutex_unlock (&priv->lock); } static void @@ -575,6 +584,7 @@ auth_got_body (SoupMessage *msg, gpointer manager) SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; SoupAuth *auth; + g_mutex_lock (&priv->lock); auth = lookup_auth (priv, msg); if (auth && soup_auth_is_ready (auth, msg)) { if (SOUP_IS_CONNECTION_AUTH (auth)) { @@ -586,6 +596,7 @@ auth_got_body (SoupMessage *msg, gpointer manager) soup_session_requeue_message (priv->session, msg); } + g_mutex_unlock (&priv->lock); } static void @@ -595,6 +606,8 @@ proxy_auth_got_headers (SoupMessage *msg, gpointer manager) SoupAuth *prior_auth; gboolean prior_auth_failed = FALSE; + g_mutex_lock (&priv->lock); + /* See if we used auth last time */ prior_auth = soup_message_get_proxy_auth (msg); if (prior_auth && check_auth (msg, prior_auth)) { @@ -604,23 +617,30 @@ proxy_auth_got_headers (SoupMessage *msg, gpointer manager) if (!priv->proxy_auth) { priv->proxy_auth = create_auth (priv, msg); - if (!priv->proxy_auth) + if (!priv->proxy_auth) { + g_mutex_unlock (&priv->lock); return; + } } /* If we need to authenticate, try to do it. */ authenticate_auth (manager, priv->proxy_auth, msg, prior_auth_failed, TRUE, TRUE); + g_mutex_unlock (&priv->lock); } static void proxy_auth_got_body (SoupMessage *msg, gpointer manager) { SoupAuthManagerPrivate *priv = SOUP_AUTH_MANAGER (manager)->priv; - SoupAuth *auth = priv->proxy_auth; + SoupAuth *auth; + + g_mutex_lock (&priv->lock); + auth = priv->proxy_auth; if (auth && soup_auth_is_ready (auth, msg)) soup_session_requeue_message (priv->session, msg); + g_mutex_unlock (&priv->lock); } static void @@ -653,6 +673,8 @@ soup_auth_manager_request_started (SoupSessionFeature *feature, SoupAuthManagerPrivate *priv = manager->priv; SoupAuth *auth; + g_mutex_lock (&priv->lock); + auth = lookup_auth (priv, msg); if (auth) { authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE); @@ -668,6 +690,8 @@ soup_auth_manager_request_started (SoupSessionFeature *feature, auth = NULL; } soup_message_set_proxy_auth (msg, auth); + + g_mutex_unlock (&priv->lock); } static void @@ -704,7 +728,9 @@ soup_auth_manager_use_auth (SoupAuthManager *manager, { SoupAuthManagerPrivate *priv = manager->priv; + g_mutex_lock (&priv->lock); record_auth_for_uri (priv, uri, auth); + g_mutex_unlock (&priv->lock); } static void -- cgit v1.2.1 From 54978fa43f27107870d0c417bacd4dd9a6740479 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 4 Jan 2013 10:36:21 -0500 Subject: Rename LIBSOUP_DISABLE_DEPRECATED to SOUP_DISABLE_DEPRECATED GNOME_MAINTAINER_MODE_DEFINES apparently sets LIBSOUP_DISABLE_DEPRECATED, which is now causing various jhbuild modules to break. "Fix" this by renaming the define (which is only still there because gtk-doc complains if it's not). The *right* way to get deprecation warnings/errors now is to define SOUP_VERSION_MIN_REQUIRED. --- docs/reference/Makefile.am | 2 +- libsoup/soup-cookie-jar.h | 2 +- libsoup/soup-form.h | 2 +- libsoup/soup-logger.h | 2 +- libsoup/soup-message-headers.h | 2 +- libsoup/soup-message.h | 4 ++-- libsoup/soup-proxy-resolver.h | 2 +- libsoup/soup-session-async.h | 2 +- libsoup/soup-session-sync.h | 2 +- libsoup/soup-session.h | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index adb475de..d36977ec 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -13,7 +13,7 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml DOC_SOURCE_DIR=../../libsoup # Extra options to supply to gtkdoc-scan. -SCAN_OPTIONS=--deprecated-guards=LIBSOUP_DISABLE_DEPRECATED --rebuild-types --ignore-decorators='SOUP_DEPRECATED\w*\s*\([^)]*\)|SOUP_DEPRECATED\w*|SOUP_AVAILABLE\w*' +SCAN_OPTIONS=--deprecated-guards=SOUP_DISABLE_DEPRECATED --rebuild-types --ignore-decorators='SOUP_DEPRECATED\w*\s*\([^)]*\)|SOUP_DEPRECATED\w*|SOUP_AVAILABLE\w*' # Extra options to supply to gtkdoc-scangobj. SCANGOBJ_OPTIONS= diff --git a/libsoup/soup-cookie-jar.h b/libsoup/soup-cookie-jar.h index 80497368..e77f8ab3 100644 --- a/libsoup/soup-cookie-jar.h +++ b/libsoup/soup-cookie-jar.h @@ -88,7 +88,7 @@ SoupCookieJarAcceptPolicy soup_cookie_jar_get_accept_policy (SoupCooki SOUP_AVAILABLE_IN_2_40 gboolean soup_cookie_jar_is_persistent (SoupCookieJar *jar); -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED SOUP_AVAILABLE_IN_2_24 SOUP_DEPRECATED_IN_2_26 void soup_cookie_jar_save (SoupCookieJar *jar); diff --git a/libsoup/soup-form.h b/libsoup/soup-form.h index fa080c48..21b8db1e 100644 --- a/libsoup/soup-form.h +++ b/libsoup/soup-form.h @@ -29,7 +29,7 @@ char *soup_form_encode_datalist (GData **form_data_set); char *soup_form_encode_valist (const char *first_field, va_list args); -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED /* Compatibility with libsoup 2.3.0 */ #define soup_form_decode_urlencoded soup_form_decode #define soup_form_encode_urlencoded soup_form_encode_hash diff --git a/libsoup/soup-logger.h b/libsoup/soup-logger.h index 7cf95c4c..d84c765e 100644 --- a/libsoup/soup-logger.h +++ b/libsoup/soup-logger.h @@ -54,7 +54,7 @@ GType soup_logger_get_type (void); SoupLogger *soup_logger_new (SoupLoggerLogLevel level, int max_body_size); -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED SOUP_DEPRECATED_IN_2_24_FOR(soup_session_add_feature) void soup_logger_attach (SoupLogger *logger, SoupSession *session); diff --git a/libsoup/soup-message-headers.h b/libsoup/soup-message-headers.h index 388d75b1..46e5c7c0 100644 --- a/libsoup/soup-message-headers.h +++ b/libsoup/soup-message-headers.h @@ -36,7 +36,7 @@ void soup_message_headers_clear (SoupMessageHeaders *hdrs); SOUP_AVAILABLE_IN_2_36 void soup_message_headers_clean_connection_headers (SoupMessageHeaders *hdrs); -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED SOUP_DEPRECATED_IN_2_28_FOR ("soup_message_headers_get_one or soup_message_headers_get_list") const char *soup_message_headers_get (SoupMessageHeaders *hdrs, const char *name); diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index efcb923a..23ec024a 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -117,7 +117,7 @@ void soup_message_set_first_party (SoupMessage *msg, typedef enum { SOUP_MESSAGE_NO_REDIRECT = (1 << 1), SOUP_MESSAGE_CAN_REBUILD = (1 << 2), -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED SOUP_MESSAGE_OVERWRITE_CHUNKS = (1 << 3), #endif SOUP_MESSAGE_CONTENT_DECODED = (1 << 4), @@ -167,7 +167,7 @@ void soup_message_set_redirect (SoupMessage *msg, const char *redirect_uri); /* I/O */ -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED typedef SoupBuffer * (*SoupChunkAllocator) (SoupMessage *msg, gsize max_len, gpointer user_data); diff --git a/libsoup/soup-proxy-resolver.h b/libsoup/soup-proxy-resolver.h index f5933d9e..87989569 100644 --- a/libsoup/soup-proxy-resolver.h +++ b/libsoup/soup-proxy-resolver.h @@ -10,7 +10,7 @@ G_BEGIN_DECLS -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED #define SOUP_TYPE_PROXY_RESOLVER (soup_proxy_resolver_get_type ()) #define SOUP_PROXY_RESOLVER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER, SoupProxyResolver)) diff --git a/libsoup/soup-session-async.h b/libsoup/soup-session-async.h index 15b0ebfd..96217638 100644 --- a/libsoup/soup-session-async.h +++ b/libsoup/soup-session-async.h @@ -35,7 +35,7 @@ typedef struct { GType soup_session_async_get_type (void); -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED SoupSession *soup_session_async_new (void); SoupSession *soup_session_async_new_with_options (const char *optname1, ...) G_GNUC_NULL_TERMINATED; diff --git a/libsoup/soup-session-sync.h b/libsoup/soup-session-sync.h index 0ddda226..cf81f6b0 100644 --- a/libsoup/soup-session-sync.h +++ b/libsoup/soup-session-sync.h @@ -35,7 +35,7 @@ typedef struct { GType soup_session_sync_get_type (void); -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED SoupSession *soup_session_sync_new (void); SoupSession *soup_session_sync_new_with_options (const char *optname1, ...) G_GNUC_NULL_TERMINATED; diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index a69c0717..5d62667c 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -110,7 +110,7 @@ void soup_session_abort (SoupSession *session); GMainContext *soup_session_get_async_context(SoupSession *session); -#ifndef LIBSOUP_DISABLE_DEPRECATED +#ifndef SOUP_DISABLE_DEPRECATED /* SOUP_AVAILABLE_IN_2_30 -- this trips up gtkdoc-scan */ SOUP_DEPRECATED_IN_2_38_FOR (soup_session_prefetch_dns) void soup_session_prepare_for_uri (SoupSession *session, -- cgit v1.2.1 From 08ff6d1d2124565b10c0b22b17769bf91fc6d5c2 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 5 Jan 2013 18:25:12 -0500 Subject: soup-session: fix up the SoupRequest requeuing logic Split the "this message is likely to be requeued" logic into a single function that the sync and async codepaths can share, and fix it to not think that SOUP_MESSAGE_NO_REDIRECT messages will be redirected, or that messages that disable SOUP_TYPE_AUTH_MANAGER will be authenticated. --- libsoup/soup-session.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 20e92329..ef8983fb 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3493,6 +3493,19 @@ soup_session_class_init (SoupSessionClass *session_class) } +static gboolean +expected_to_be_requeued (SoupSession *session, SoupMessage *msg) +{ + if (msg->status_code == SOUP_STATUS_UNAUTHORIZED || + msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) + return !soup_message_disables_feature (msg, SOUP_TYPE_AUTH_MANAGER); + + if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_NO_REDIRECT)) + return soup_session_would_redirect (session, msg); + + return FALSE; +} + /* send_request_async */ static void @@ -3615,12 +3628,10 @@ static void send_async_maybe_complete (SoupMessageQueueItem *item, GInputStream *stream) { - if (item->msg->status_code == SOUP_STATUS_UNAUTHORIZED || - item->msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED || - soup_session_would_redirect (item->session, item->msg)) { + if (expected_to_be_requeued (item->session, item->msg)) { GOutputStream *ostream; - /* Message may be requeued, so gather the current message body... */ + /* Gather the current message body... */ ostream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free); g_object_set_data_full (G_OBJECT (item->task), "SoupSession:ostream", ostream, g_object_unref); @@ -3927,10 +3938,7 @@ soup_session_send_request (SoupSession *session, if (!stream) break; - /* Break if the message doesn't look likely-to-be-requeued */ - if (msg->status_code != SOUP_STATUS_UNAUTHORIZED && - msg->status_code != SOUP_STATUS_PROXY_UNAUTHORIZED && - !soup_session_would_redirect (session, msg)) + if (!expected_to_be_requeued (session, msg)) break; /* Gather the current message body... */ -- cgit v1.2.1 From 0cb3c8293b37ade115118096298b002a7a9f7c9c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 6 Jan 2013 16:38:30 -0500 Subject: Fix previous commit --- libsoup/soup-session.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index ef8983fb..1132479d 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3497,8 +3497,11 @@ static gboolean expected_to_be_requeued (SoupSession *session, SoupMessage *msg) { if (msg->status_code == SOUP_STATUS_UNAUTHORIZED || - msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) - return !soup_message_disables_feature (msg, SOUP_TYPE_AUTH_MANAGER); + msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) { + SoupSessionFeature *feature = + soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER); + return !feature || !soup_message_disables_feature (msg, feature); + } if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_NO_REDIRECT)) return soup_session_would_redirect (session, msg); -- cgit v1.2.1 From c2ce0f99c1551161fdf6e13a9f83bf8cb656b6d6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 7 Jan 2013 15:50:36 -0500 Subject: Revert "SoupConnection: disconnect on failed connections/tunnels" Disconnecting clears priv->sock, and in some cases, the caller may want to look at that after the failed connection. So switch this back to having the session do the disconnecting itself (which is simpler now due to various SoupSession rewrites), and remove one inconsistent case where the connection was disconnecting itself before. This reverts commit 21d707d66460233596a04f6dc99c945d2dbc3085. --- libsoup/soup-connection.c | 22 +++------------------- libsoup/soup-session.c | 2 ++ 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 21613946..a6ed5243 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -474,8 +474,6 @@ socket_connect_finished (SoupSocket *socket, guint status, gpointer user_data) status = soup_status_proxify (status); data->callback (data->conn, status, data->callback_data); } - if (!SOUP_STATUS_IS_SUCCESSFUL (status) && status != SOUP_STATUS_TRY_AGAIN) - soup_connection_disconnect (data->conn); g_object_unref (data->conn); if (data->cancellable) g_object_unref (data->cancellable); @@ -641,6 +639,7 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) SOUP_SOCKET_CLEAN_DISPOSE, TRUE, NULL); g_object_unref (remote_addr); + event_id = g_signal_connect (priv->socket, "event", G_CALLBACK (proxy_socket_event), conn); status = soup_socket_connect_sync (priv->socket, cancellable); @@ -679,17 +678,9 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; start_idle_timer (conn); - } else if (status != SOUP_STATUS_TRY_AGAIN) { - fail: - if (priv->socket) { - soup_socket_disconnect (priv->socket); - g_object_unref (priv->socket); - priv->socket = NULL; - } - - soup_connection_disconnect (conn); } + fail: if (priv->socket && event_id) g_signal_handler_disconnect (priv->socket, event_id); @@ -721,10 +712,8 @@ soup_connection_start_ssl_sync (SoupConnection *conn, if (!soup_socket_start_proxy_ssl (priv->socket, priv->remote_uri->host, - cancellable)) { - soup_connection_disconnect (conn); + cancellable)) return SOUP_STATUS_SSL_FAILED; - } soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); status = soup_socket_handshake_sync (priv->socket, cancellable); @@ -736,9 +725,6 @@ soup_connection_start_ssl_sync (SoupConnection *conn, status = SOUP_STATUS_TRY_AGAIN; } - if (!SOUP_STATUS_IS_SUCCESSFUL (status) && status != SOUP_STATUS_TRY_AGAIN) - soup_connection_disconnect (conn); - return status; } @@ -757,8 +743,6 @@ start_ssl_completed (SoupSocket *socket, guint status, gpointer user_data) } data->callback (data->conn, status, data->callback_data); - if (!SOUP_STATUS_IS_SUCCESSFUL (status) && status != SOUP_STATUS_TRY_AGAIN) - soup_connection_disconnect (data->conn); g_object_unref (data->conn); g_slice_free (SoupConnectionAsyncConnectData, data); } diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 1132479d..e37a71d5 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1513,6 +1513,7 @@ tunnel_complete (SoupConnection *conn, guint status, gpointer user_data) soup_message_set_https_status (item->msg, item->conn); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + soup_connection_disconnect (conn); soup_session_set_item_connection (session, item, NULL); soup_session_set_item_status (session, item, status); } @@ -1597,6 +1598,7 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) SoupSession *session = item->session; if (status != SOUP_STATUS_OK) { + soup_connection_disconnect (conn); if (item->state == SOUP_MESSAGE_CONNECTING) { soup_session_set_item_status (session, item, status); soup_session_set_item_connection (session, item, NULL); -- cgit v1.2.1 From 645d0943d61885d714e39652b2af65cee4741d17 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 7 Jan 2013 16:30:55 -0500 Subject: soup_message_get_https_status: provide info for failed attempts too SoupMessage:tls-certificate and SoupMessage:tls-errors were only getting set for successful https connections. It is useful to have them be set on failed ones as well. Fix that, and make ssl-test test it. https://bugzilla.gnome.org/show_bug.cgi?id=690176 --- libsoup/soup-message.c | 10 ++++++---- libsoup/soup-session.c | 8 ++++---- tests/ssl-test.c | 4 ++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 67b6e6f5..750b9925 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1826,11 +1826,13 @@ soup_message_set_https_status (SoupMessage *msg, SoupConnection *conn) * @certificate: (out) (transfer none): @msg's TLS certificate * @errors: (out): the verification status of @certificate * - * If @msg is using https, this retrieves the #GTlsCertificate - * associated with its connection, and the #GTlsCertificateFlags showing - * what problems, if any, have been found with that certificate. + * If @msg is using https (or attempted to use https but got + * %SOUP_STATUS_SSL_FAILED), this retrieves the #GTlsCertificate + * associated with its connection, and the #GTlsCertificateFlags + * showing what problems, if any, have been found with that + * certificate. * - * Return value: %TRUE if @msg uses https, %FALSE if not + * Return value: %TRUE if @msg used/attempted https, %FALSE if not * * Since: 2.34 */ diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index e37a71d5..3b23846c 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1509,8 +1509,7 @@ tunnel_complete (SoupConnection *conn, guint status, gpointer user_data) if (item->msg->status_code) item->state = SOUP_MESSAGE_FINISHING; - else - soup_message_set_https_status (item->msg, item->conn); + soup_message_set_https_status (item->msg, item->conn); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { soup_connection_disconnect (conn); @@ -1597,6 +1596,8 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) SoupMessageQueueItem *item = user_data; SoupSession *session = item->session; + soup_message_set_https_status (item->msg, item->conn); + if (status != SOUP_STATUS_OK) { soup_connection_disconnect (conn); if (item->state == SOUP_MESSAGE_CONNECTING) { @@ -1751,10 +1752,10 @@ get_connection (SoupMessageQueueItem *item, gboolean *should_cleanup) } soup_session_set_item_connection (session, item, conn); - soup_message_set_https_status (item->msg, item->conn); if (soup_connection_get_state (item->conn) != SOUP_CONNECTION_NEW) { item->state = SOUP_MESSAGE_READY; + soup_message_set_https_status (item->msg, item->conn); return TRUE; } @@ -1801,7 +1802,6 @@ soup_session_process_queue_item (SoupSession *session, break; case SOUP_MESSAGE_READY: - soup_message_set_https_status (item->msg, item->conn); if (item->msg->status_code) { if (item->msg->status_code == SOUP_STATUS_TRY_AGAIN) { soup_message_cleanup_response (item->msg); diff --git a/tests/ssl-test.c b/tests/ssl-test.c index 6d96bc79..7716f302 100644 --- a/tests/ssl-test.c +++ b/tests/ssl-test.c @@ -109,6 +109,10 @@ do_one_strict_test (SoupSession *session, char *uri, errors++; } } + if (!soup_message_get_https_status (msg, NULL, NULL)) { + debug_printf (1, " get_https_status returns FALSE?\n"); + errors++; + } g_object_unref (msg); } -- cgit v1.2.1 From 42a60d2006047114273fb09a5e3b6fe2b08fae6f Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 8 Jan 2013 16:40:48 +0000 Subject: autogen.sh: Use autoreconf instead gnome-autogen --- autogen.sh | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/autogen.sh b/autogen.sh index e748f3a1..77b8a9d9 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,21 +1,33 @@ #!/bin/sh # Run this to generate all the initial makefiles, etc. -srcdir=`dirname $0` -test -z "$srcdir" && srcdir=. +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. -PKG_NAME="libsoup" +olddir=`pwd` +cd $srcdir -(test -f $srcdir/configure.ac \ - && test -f $srcdir/libsoup.doap \ - && test -d $srcdir/libsoup) || { - echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" - echo " top-level $PKG_NAME directory" - exit 1 -} +AUTORECONF=`which autoreconf` +if test -z $AUTORECONF; then + echo "*** No autoreconf found, please intall it ***" + exit 1 +fi -which gnome-autogen.sh || { - echo "You need to install gnome-common" - exit 1 -} -. gnome-autogen.sh +INTLTOOLIZE=`which intltoolize` +if test -z $INTLTOOLIZE; then + echo "*** No intltoolize found, please install the intltool package ***" + exit 1 +fi + +GTKDOCIZE=`which gtkdocize` +if test -z $GTKDOCIZE; then + echo "*** No GTK-Doc found, please install it ***" + exit 1 +fi + +gtkdocize || exit $? +autopoint --force +AUTOPOINT='intltoolize --automake --copy' autoreconf --force --install --verbose + +cd $olddir +test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" -- cgit v1.2.1 From 1ac2f9dedf63334386988f7e16b4e3fcbef83461 Mon Sep 17 00:00:00 2001 From: Javier Date: Tue, 8 Jan 2013 17:48:41 +0000 Subject: build: Do not use AM_GLIB_GNU_GETTEXT The po/Makefile.in.inis generated by intltoolize --- autogen.sh | 4 ++-- configure.ac | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/autogen.sh b/autogen.sh index 77b8a9d9..cb3e9bdb 100755 --- a/autogen.sh +++ b/autogen.sh @@ -26,8 +26,8 @@ if test -z $GTKDOCIZE; then fi gtkdocize || exit $? -autopoint --force -AUTOPOINT='intltoolize --automake --copy' autoreconf --force --install --verbose +intltoolize --automake --copy +autoreconf --force --install --verbose cd $olddir test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" diff --git a/configure.ac b/configure.ac index 43874110..f307f041 100644 --- a/configure.ac +++ b/configure.ac @@ -125,7 +125,6 @@ IT_PROG_INTLTOOL([0.35.0]) GETTEXT_PACKAGE=libsoup AC_SUBST([GETTEXT_PACKAGE]) AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[The gettext domain name]) -AM_GLIB_GNU_GETTEXT dnl ******************* dnl *** Misc checks *** -- cgit v1.2.1 From 67fb3730a1f5ded95e1a51dd6b3e00cb41dfbdbc Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Wed, 9 Jan 2013 19:20:01 +0100 Subject: Add explicit soup-version.h include into soup.h --- libsoup/soup.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libsoup/soup.h b/libsoup/soup.h index 0a7944ee..82a26329 100644 --- a/libsoup/soup.h +++ b/libsoup/soup.h @@ -49,6 +49,7 @@ extern "C" { #include #include #include +#include #include #ifdef __cplusplus -- cgit v1.2.1 From 7afbc9dc94e36ede35f06a9269e2853c002f8f6f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 9 Jan 2013 17:21:13 -0500 Subject: soup-session: fix a deadlock when aborting a SoupSessionSync We need to signal conn_cond when removing an item from the queue, since flush_queue() expects that... (and also, since in some cases, removing a message from the queue will allow another one to start). https://bugzilla.gnome.org/show_bug.cgi?id=691399 --- libsoup/soup-session.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 3b23846c..c4abe1d9 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1422,6 +1422,7 @@ soup_session_unqueue_item (SoupSession *session, g_mutex_lock (&priv->conn_lock); host = get_host_for_message (session, item->msg); host->num_messages--; + g_cond_broadcast (&priv->conn_cond); g_mutex_unlock (&priv->conn_lock); /* g_signal_handlers_disconnect_by_func doesn't work if you -- cgit v1.2.1 From c63e1392ac6dd3f9e5d32faff1bba8c10b261225 Mon Sep 17 00:00:00 2001 From: Alexander Shopov Date: Sat, 12 Jan 2013 06:56:29 +0200 Subject: Updated Bulgarian translation --- po/bg.po | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/po/bg.po b/po/bg.po index 2d9305ef..42ae49e2 100644 --- a/po/bg.po +++ b/po/bg.po @@ -1,14 +1,14 @@ # Bulgarian translation of libsoup po-file. -# Copyright (C) 2012 Free Software Foundation, Inc. +# Copyright (C) 2012, 2013 Free Software Foundation, Inc. # This file is distributed under the same license as the libsoup package. -# Alexander Shopov , 2012. +# Alexander Shopov , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-19 21:08+0300\n" -"PO-Revision-Date: 2012-09-19 21:08+0300\n" +"POT-Creation-Date: 2013-01-12 06:56+0200\n" +"PO-Revision-Date: 2013-01-12 06:56+0200\n" "Last-Translator: Alexander Shopov \n" "Language-Team: Bulgarian \n" "Language: \n" @@ -31,51 +31,72 @@ msgstr "Неправилна заявка за търсене" msgid "Cannot truncate SoupBodyInputStream" msgstr "Потокът SoupBodyInputStream не може да бъде прекъснат" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Потокът от мрежата неочаквано прекъсна" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Прекалено малък изходен буфер" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Отговорът от HTTP не може да бъде анализиран" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Непознато кодиране на отговора от HTTP" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Операцията е отменена" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Операцията ще блокира" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Заявката към HTTP не може да бъде анализирана" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Не е даден адрес" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Неправилен адрес на „%s“: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4032 #, c-format msgid "Could not parse URI '%s'" msgstr "Адресът „%s“ е неправилен" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4069 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Схемата на адреса не се поддържа „%s“" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4091 +#, c-format +msgid "Not an HTTP URI" +msgstr "Не е адрес URI за HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Името на машината е адрес по IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Неправилно име на машина" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Името на машината не съдържа домейн" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Няма достатъчно домейни" -- cgit v1.2.1 From 00170d90c72d0cd2e6fea434e88c03f8e09f7631 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 12 Jan 2013 09:42:50 -0500 Subject: soup-auth-digest: fix a leak on re-auth Calling soup_auth_authenticate() on an already-authenticated SoupAuthDigest would leak the old username and hashed password. https://bugzilla.gnome.org/show_bug.cgi?id=690142 --- libsoup/soup-auth-digest.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsoup/soup-auth-digest.c b/libsoup/soup-auth-digest.c index b95a996f..1fbb639d 100644 --- a/libsoup/soup-auth-digest.c +++ b/libsoup/soup-auth-digest.c @@ -293,6 +293,9 @@ soup_auth_digest_authenticate (SoupAuth *auth, const char *username, SoupAuthDigestPrivate *priv = SOUP_AUTH_DIGEST_GET_PRIVATE (auth); char *bgen; + g_clear_pointer (&priv->cnonce, g_free); + g_clear_pointer (&priv->user, g_free); + /* Create client nonce */ bgen = g_strdup_printf ("%p:%lu:%lu", auth, -- cgit v1.2.1 From 38901ca5e684a8fac75e6ff740d45c82dd44181a Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 9 Dec 2012 13:23:25 +0100 Subject: SoupURI: replace NULL password with "" on http All supported HTTP auth methods use both username and password, so assume a password of "" if none is given --- libsoup/soup-uri.c | 2 ++ tests/uri-parsing.c | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 28b3025c..fdb43785 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -434,6 +434,8 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) uri->scheme == SOUP_URI_SCHEME_HTTPS) { if (!uri->path) uri->path = g_strdup ("/"); + if (uri->user && !uri->password) + uri->password = g_strdup (""); if (!SOUP_URI_VALID_FOR_HTTP (uri)) { soup_uri_free (uri); return NULL; diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index 892ee2b9..7992d70b 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -23,15 +23,15 @@ static struct { { "ftp://user:password@host", "ftp://user@host", { "ftp", "user", "password", "host", 21, "", NULL, NULL } }, { "http://us%65r@host", "http://user@host/", - { "http", "user", NULL, "host", 80, "/", NULL, NULL } }, + { "http", "user", "", "host", 80, "/", NULL, NULL } }, { "http://us%40r@host", "http://us%40r@host/", - { "http", "us\x40r", NULL, "host", 80, "/", NULL, NULL } }, + { "http", "us\x40r", "", "host", 80, "/", NULL, NULL } }, { "http://us%3ar@host", "http://us%3Ar@host/", - { "http", "us\x3ar", NULL, "host", 80, "/", NULL, NULL } }, + { "http", "us\x3ar", "", "host", 80, "/", NULL, NULL } }, { "http://us%2fr@host", "http://us%2Fr@host/", - { "http", "us\x2fr", NULL, "host", 80, "/", NULL, NULL } }, + { "http", "us\x2fr", "", "host", 80, "/", NULL, NULL } }, { "http://us%3fr@host", "http://us%3Fr@host/", - { "http", "us\x3fr", NULL, "host", 80, "/", NULL, NULL } }, + { "http", "us\x3fr", "", "host", 80, "/", NULL, NULL } }, { "http://host?query", "http://host/?query", { "http", NULL, NULL, "host", 80, "/", "query", NULL } }, { "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", @@ -122,7 +122,7 @@ static struct { { "http", NULL, NULL, "", 80, "//////////////", NULL, NULL } }, { "http://@host", "http://@host/", - { "http", "", NULL, "host", 80, "/", NULL, NULL } }, + { "http", "", "", "host", 80, "/", NULL, NULL } }, { "http://:@host", "http://@host/", { "http", "", "", "host", 80, "/", NULL, NULL } }, -- cgit v1.2.1 From f704e294870a148536b712f4138e5c504d662041 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 12 Jan 2013 09:55:26 -0500 Subject: soup-message: belated #include cleanup Remove some includes that I had commented out to see if they were still needed, but then forgot to actually remove when it turned out they weren't. --- libsoup/soup-message.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 750b9925..d30fd372 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -5,9 +5,6 @@ * Copyright (C) 2000-2003, Ximian, Inc. */ -//#include -//#include - #include "soup-message.h" #include "soup.h" #include "soup-connection.h" -- cgit v1.2.1 From 944a5bfaa3a71d3e58ab00fac55978df51d03bd7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 28 Dec 2012 21:53:02 -0500 Subject: soup-session: add SoupMessage-based streaming APIs SoupRequestHTTP is now implemented in terms of SoupSession SoupMessage operations, so we might as well just expose those directly, for people who want streaming APIs, but not SoupRequest. --- docs/reference/libsoup-2.4-sections.txt | 4 ++ libsoup/libsoup-2.4.sym | 3 + libsoup/soup-request-http.c | 10 +-- libsoup/soup-session.c | 114 ++++++++++++++++++++++++++++---- libsoup/soup-session.h | 16 +++++ 5 files changed, 130 insertions(+), 17 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 52e505d3..1b06804a 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -404,6 +404,10 @@ soup_session_requeue_message soup_session_send_message soup_session_cancel_message +soup_session_send +soup_session_send_async +soup_session_send_finish + soup_session_prefetch_dns soup_session_prepare_for_uri soup_session_abort diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 6b82f5a4..22af1601 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -385,6 +385,9 @@ soup_session_request_http soup_session_request_http_uri soup_session_request_uri soup_session_requeue_message +soup_session_send +soup_session_send_async +soup_session_send_finish soup_session_send_message soup_session_sync_get_type soup_session_sync_new diff --git a/libsoup/soup-request-http.c b/libsoup/soup-request-http.c index 4e527ccd..9ae2c2a7 100644 --- a/libsoup/soup-request-http.c +++ b/libsoup/soup-request-http.c @@ -107,8 +107,8 @@ soup_request_http_send (SoupRequest *request, g_return_val_if_fail (!SOUP_IS_SESSION_ASYNC (session), NULL); - return soup_session_send_request (session, http->priv->msg, - cancellable, error); + return soup_session_send (session, http->priv->msg, + cancellable, error); } @@ -119,7 +119,7 @@ http_input_stream_ready_cb (GObject *source, GAsyncResult *result, gpointer user GError *error = NULL; GInputStream *stream; - stream = soup_session_send_request_finish (SOUP_SESSION (source), result, &error); + stream = soup_session_send_finish (SOUP_SESSION (source), result, &error); if (stream) g_task_return_pointer (task, stream, g_object_unref); else @@ -140,8 +140,8 @@ soup_request_http_send_async (SoupRequest *request, g_return_if_fail (!SOUP_IS_SESSION_SYNC (session)); task = g_task_new (request, cancellable, callback, user_data); - soup_session_send_request_async (session, http->priv->msg, cancellable, - http_input_stream_ready_cb, task); + soup_session_send_async (session, http->priv->msg, cancellable, + http_input_stream_ready_cb, task); } static GInputStream * diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index c4abe1d9..bfc71fc9 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1972,6 +1972,11 @@ soup_session_real_queue_message (SoupSession *session, SoupMessage *msg, * and #SoupSession:use-thread-context, and for #SoupSessionSync, the * message will actually be sent and processed in another thread, with * only the final callback occurring in the indicated #GMainContext.) + * + * Contrast this method with soup_session_send_async(), which also + * asynchronously sends a message, but returns before reading the + * response body, and allows you to read the response via a + * #GInputStream. */ void soup_session_queue_message (SoupSession *session, SoupMessage *msg, @@ -2048,6 +2053,11 @@ soup_session_real_send_message (SoupSession *session, SoupMessage *msg) * to process the message, which may also cause other events to be * processed.) * + * Contrast this method with soup_session_send(), which also + * synchronously sends a message, but returns before reading the + * response body, and allows you to read the response via a + * #GInputStream. + * * Return value: the HTTP status code of the response */ guint @@ -3831,12 +3841,39 @@ async_respond_from_cache (SoupSession *session, return FALSE; } +/** + * soup_session_send_async: + * @session: a #SoupSession + * @msg: a #SoupMessage + * @cancellable: a #GCancellable + * @callback: the callback to invoke + * @user_data: data for @callback + * + * Asynchronously sends @msg and waits for the beginning of a + * response. When @callback is called, then either @msg has been sent, + * and its response headers received, or else an error has occurred. + * Call soup_session_send_finish() to get a #GInputStream for reading + * the response body. + * + * See soup_session_send() for more details on the general semantics. + * + * Contrast this method with soup_session_queue_message(), which also + * asynchronously sends a #SoupMessage, but doesn't invoke its + * callback until the response has been completely read. + * + * (Note that this method cannot be called on the deprecated + * #SoupSessionSync subclass, and can only be called on + * #SoupSessionAsync if you have set the + * #SoupSession:use-thread-context property.) + * + * Since: 2.42 + */ void -soup_session_send_request_async (SoupSession *session, - SoupMessage *msg, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +soup_session_send_async (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { SoupMessageQueueItem *item; gboolean use_thread_context; @@ -3871,10 +3908,25 @@ soup_session_send_request_async (SoupSession *session, soup_session_kick_queue (session); } +/** + * soup_session_send_finish: + * @session: a #SoupSession + * @result: the #GAsyncResult passed to your callback + * @error: return location for a #GError, or %NULL + * + * Gets the response to a soup_session_send_async() call and (if + * successful), returns a #GInputStream that can be used to read the + * response body. + * + * Return value: a #GInputStream for reading the response body, or + * %NULL on error. + * + * Since: 2.42 + */ GInputStream * -soup_session_send_request_finish (SoupSession *session, - GAsyncResult *result, - GError **error) +soup_session_send_finish (SoupSession *session, + GAsyncResult *result, + GError **error) { GTask *task; @@ -3898,11 +3950,49 @@ soup_session_send_request_finish (SoupSession *session, return g_task_propagate_pointer (task, error); } +/** + * soup_session_send: + * @session: a #SoupSession + * @msg: a #SoupMessage + * @cancellable: a #GCancellable + * @error: return location for a #GError, or %NULL + * + * Synchronously sends @msg and waits for the beginning of a response. + * On success, a #GInputStream will be returned which you can use to + * read the response body. ("Success" here means only that an HTTP + * response was received and understood; it does not necessarily mean + * that a 2xx class status code was received.) + * + * If non-%NULL, @cancellable can be used to cancel the request; + * soup_session_send() will return a %G_IO_ERROR_CANCELLED error. Note + * that with requests that have side effects (eg, + * POST, PUT, + * DELETE) it is possible that you might cancel the + * request after the server acts on it, but before it returns a + * response, leaving the remote resource in an unknown state. + * + * If @msg is requeued due to a redirect or authentication, the + * initial (3xx/401/407) response body will be suppressed, and + * soup_session_send() will only return once a final response has been + * received. + * + * Contrast this method with soup_session_send_message(), which also + * synchronously sends a #SoupMessage, but doesn't return until the + * response has been completely read. + * + * (Note that this method cannot be called on the deprecated + * #SoupSessionAsync subclass.) + * + * Return value: a #GInputStream for reading the response body, or + * %NULL on error. + * + * Since: 2.42 + */ GInputStream * -soup_session_send_request (SoupSession *session, - SoupMessage *msg, - GCancellable *cancellable, - GError **error) +soup_session_send (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GError **error) { SoupMessageQueueItem *item; GInputStream *stream = NULL; diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index 5d62667c..90cf12c7 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -110,6 +110,22 @@ void soup_session_abort (SoupSession *session); GMainContext *soup_session_get_async_context(SoupSession *session); +SOUP_AVAILABLE_IN_2_42 +void soup_session_send_async (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +SOUP_AVAILABLE_IN_2_42 +GInputStream *soup_session_send_finish (SoupSession *session, + GAsyncResult *result, + GError **error); +SOUP_AVAILABLE_IN_2_42 +GInputStream *soup_session_send (SoupSession *session, + SoupMessage *msg, + GCancellable *cancellable, + GError **error); + #ifndef SOUP_DISABLE_DEPRECATED /* SOUP_AVAILABLE_IN_2_30 -- this trips up gtkdoc-scan */ SOUP_DEPRECATED_IN_2_38_FOR (soup_session_prefetch_dns) -- cgit v1.2.1 From 0299023543dd4dcfc829ba1aa32c9c2099680da3 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 14 Jan 2013 17:25:14 -0500 Subject: 2.41.4 --- NEWS | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 27459a5b..c1eafdc1 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,63 @@ +Changes in libsoup from 2.41.3 to 2.41.4: + + * Lots of docs fixes, including catching up with some (but not + all!) of the API additions and deprecations, and a new + chapter with hints on porting from + SoupSessionAsync/SoupSessionSync to the new-and-improved + plain SoupSession. + + * The plain SoupSession type now supports + soup_session_queue_message() (with SoupSessionAsync + semantics) and soup_session_send_message() (with + SoupSessionSync semantics), and there are now + soup_session_new() and soup_session_new_with_options(). + + * The mirroring of the SoupMessage API onto SoupRequestHTTP, + added in 2.41.3, has been reverted. However, new APIs + soup_session_send() and soup_session_send_async() have been + added that let you use the GInputStream-based API with + SoupMessages rather than SoupRequest, so if you're doing + HTTP-specific stuff, you can just use that instead. + + * soup_message_get_https_status() now returns the certificate + and flags for unsuccessful https connections as well as + successful ones. [#690176] + + * Fixed a deadlock when calling soup_session_abort() on a + SoupSessionSync in some cases. [#691399] + + * Internal SoupCache rewrites/improvements [#682112, Sergio] + + * Plugged a memory leak in SoupCache [#690382, Sudarsana + Nagineni] and one in SoupAuthDigest [#690142] + + * LIBSOUP_DISABLE_DEPRECATED has been renamed to + SOUP_DISABLE_DEPRECATED, but that's just to keep gtk-doc + happy, and you shouldn't use it. You should use + SOUP_VERSION_MIN_REQUIRED instead. + + * Fixed the samba-windbind-based NTLM support, which appears + to have been broken before. + + * SoupAuthManager is now a public class (so you can remove it + as a feature from a session, or disable it for a particular + message). It also has a new method + soup_auto_manager_use_auth(), which can be used to "preload" + authentication for a host so that libsoup will use + authentication on the very first request. + + * SoupURI now treats "http://user@example.com" as having a + password of "" rather than NULL, since a NULL password would + not be valid for any known HTTP auth type. + + * build: libsoup now uses autoreconf instead of + gnome-autogen.sh, and no longer uses AM_GLIB_GNU_GETTEXT + [Javier Jardon]. + + * Updated translations: + Assamese, Bulgarian, Estonian, Friulian, Galician, Hebrew, + Polish, Slovenian, Spanish + Changes in libsoup from 2.41.2 to 2.41.3 (codename: "I Left My Deprecated APIs in A Coruña"): diff --git a/configure.ac b/configure.ac index f307f041..cc857017 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [3]) +m4_define([soup_micro_version], [4]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 10cbbb00c060a3011af1c6ec882bd7b2a575d427 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Tue, 15 Jan 2013 19:01:22 +0300 Subject: Updated Belarusian translation. --- po/be.po | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/po/be.po b/po/be.po index 18c17f93..12f12d96 100644 --- a/po/be.po +++ b/po/be.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" +"POT-Creation-Date: 2012-12-18 15:49+0000\n" "PO-Revision-Date: 2012-09-14 13:29+0300\n" "Last-Translator: Ihar Hrachyshka \n" "Language-Team: Belarusian \n" @@ -28,39 +28,60 @@ msgstr "Хібны запыт пракручвання змесціва" msgid "Cannot truncate SoupBodyInputStream" msgstr "Немагчыма абрэзаць SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Сеткавы струмень нечакана закрыўся" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Выхадны буфер надта малы" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Не ўдалося разабраць HTTP-адказ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Невядомае кадаванне HTTP-адказу" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Аперацыя была скасавана" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Аперацыя заблакіруе працэс" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Не ўдалося разабраць HTTP-запыт" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "URI-адрас не пададзены" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Хібны URI-адрас \"%s\": %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "Не ўдалося разабраць URI-адрас \"%s\"" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "URI-схема \"%s\" не падтрымліваецца" +#: ../libsoup/soup-session.c:3811 +#, c-format +msgid "Not an HTTP URI" +msgstr "Гэта не HTTP URI-адрас" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Назва хоста з'яўляецца IP-адрасам" -- cgit v1.2.1 From fd9566988e2fd19b8b48b74e5ec856cbe0ac4303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B8=D1=80=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=9D?= =?UTF-8?q?=D0=B8=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Thu, 17 Jan 2013 09:48:28 +0100 Subject: Updated Serbian translation --- po/sr.po | 41 ++++++++++++++++++++++++++++++++--------- po/sr@latin.po | 41 ++++++++++++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/po/sr.po b/po/sr.po index 8be2ed46..c5765c36 100644 --- a/po/sr.po +++ b/po/sr.po @@ -1,14 +1,14 @@ # Serbian translation of libsoup. # Courtesy of Prevod.org team (http://prevod.org/) -- 2012. # This file is distributed under the same license as the libsoup package. -# Мирослав Николић , 2011, 2012. +# Мирослав Николић , 2011, 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" "p&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-14 05:49+0200\n" +"POT-Creation-Date: 2012-12-18 15:49+0000\n" +"PO-Revision-Date: 2013-01-17 09:46+0200\n" "Last-Translator: Мирослав Николић \n" "Language-Team: Serbian \n" "Language: sr\n" @@ -33,39 +33,62 @@ msgstr "Неисправан захтев претраге" msgid "Cannot truncate SoupBodyInputStream" msgstr "Не могу да скратим улазни ток тела Супе" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Мрежни ток је изненадно затворен" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Међумеморија излаза је премала" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Не могу да обрадим ХТТП одговор" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Непознато кодирање ХТТП одговора" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Радња је отказана" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Поступак би блокирао" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Не могу да обрадим ХТТП захтев" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "Није наведена адреса" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Неисправна „%s“ адреса: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "Не могу да обрадим адресу „%s“" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Неподржана „%s“ шема адресе" +#: ../libsoup/soup-session.c:3811 +#, c-format +msgid "Not an HTTP URI" +msgstr "Није ХТТП путања" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Назив домаћина је ИП адреса" diff --git a/po/sr@latin.po b/po/sr@latin.po index 0c191a23..6e83f358 100644 --- a/po/sr@latin.po +++ b/po/sr@latin.po @@ -1,14 +1,14 @@ # Serbian translation of libsoup. # Courtesy of Prevod.org team (http://prevod.org/) -- 2012. # This file is distributed under the same license as the libsoup package. -# Miroslav Nikolić , 2011, 2012. +# Miroslav Nikolić , 2011, 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" "p&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-14 05:49+0200\n" +"POT-Creation-Date: 2012-12-18 15:49+0000\n" +"PO-Revision-Date: 2013-01-17 09:46+0200\n" "Last-Translator: Miroslav Nikolić \n" "Language-Team: Serbian \n" "Language: sr\n" @@ -33,39 +33,62 @@ msgstr "Neispravan zahtev pretrage" msgid "Cannot truncate SoupBodyInputStream" msgstr "Ne mogu da skratim ulazni tok tela Supe" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Mrežni tok je iznenadno zatvoren" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Međumemorija izlaza je premala" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Ne mogu da obradim HTTP odgovor" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nepoznato kodiranje HTTP odgovora" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Radnja je otkazana" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Postupak bi blokirao" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Ne mogu da obradim HTTP zahtev" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "Nije navedena adresa" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Neispravna „%s“ adresa: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "Ne mogu da obradim adresu „%s“" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nepodržana „%s“ šema adrese" +#: ../libsoup/soup-session.c:3811 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nije HTTP putanja" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "Naziv domaćina je IP adresa" -- cgit v1.2.1 From 91f1eea16dac133609a9a083f7e34d5d4ce44003 Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Thu, 17 Jan 2013 10:59:13 +0100 Subject: set_ssl_ca_file: don't try unreffing tlsdb if it's NULL If g_tls_file_database_new() failed for any reason but G_TLS_ERROR_UNAVAILABLE, we don't create a fallback DB and so tlsdb stays NULL. https://bugzilla.gnome.org/show_bug.cgi?id=691930 --- libsoup/soup-session.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index bfc71fc9..ab9e2cd8 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -503,7 +503,8 @@ set_ssl_ca_file (SoupSession *session, const char *ssl_ca_file) } set_tlsdb (session, tlsdb); - g_object_unref (tlsdb); + if (tlsdb) + g_object_unref (tlsdb); priv->ssl_ca_file = g_strdup (ssl_ca_file); g_object_notify (G_OBJECT (session), "ssl-ca-file"); -- cgit v1.2.1 From 1d94ff8543c372c13220971e65e5508f7efeebb7 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Fri, 18 Jan 2013 19:06:48 +0100 Subject: soup-body-input-stream: update priv->eof when skipping We must update the priv->eof field in the skip() operation as we do in read(). This bug was causing redirects not to finish because the SoupBodyInputStream was creating a pollable source that will never issue anything instead of a plain timeout source. https://bugzilla.gnome.org/show_bug.cgi?id=692026 --- libsoup/soup-body-input-stream.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-body-input-stream.c b/libsoup/soup-body-input-stream.c index fff07803..939753a9 100644 --- a/libsoup/soup-body-input-stream.c +++ b/libsoup/soup-body-input-stream.c @@ -286,7 +286,9 @@ soup_body_input_stream_skip (GInputStream *stream, MIN (count, priv->read_length), cancellable, error); - if (skipped != -1) + if (skipped == 0) + priv->eof = TRUE; + else if (skipped > 0) priv->pos += skipped; return skipped; -- cgit v1.2.1 From a146e63c358cf519e6e34f6123d5855e606ed393 Mon Sep 17 00:00:00 2001 From: Gheyret Kenji Date: Sun, 20 Jan 2013 09:27:21 +0900 Subject: Updated Uyghur translation Signed-off-by: Gheyret Kenji --- po/ug.po | 55 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/po/ug.po b/po/ug.po index c10bbc5c..33608e3a 100644 --- a/po/ug.po +++ b/po/ug.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-11-04 20:02+0000\n" +"POT-Creation-Date: 2013-01-14 22:43+0000\n" "PO-Revision-Date: 2011-11-09 16:10+0900\n" "Last-Translator: Gheyret Kenji \n" "Language-Team: Uyghur Computer Science Association \n" @@ -20,7 +20,7 @@ msgstr "" #: ../libsoup/soup-body-input-stream.c:172 #: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" -msgstr "" +msgstr "باغلىنىش تۇيۇقسىز توختاپ قالدى" #: ../libsoup/soup-body-input-stream.c:461 msgid "Invalid seek request" @@ -28,53 +28,76 @@ msgstr "ئىناۋەتسىز ئىزدەش ئىلتىماسى" #: ../libsoup/soup-body-input-stream.c:489 msgid "Cannot truncate SoupBodyInputStream" -msgstr "" +msgstr "ئېقىم SoupBodyInputStream نى قىسقارتقىلى بولمىدى" + +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "تور ئېقىمى تۇيۇقسىز يېپىلدى" #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "چىقىرىش يىغلەكى بەك كىچىك" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP ئىنكاسىنى يېشەلمىدى" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP ئىنكاسىنىڭ كودلىنىشىنى بىلگىلى بولمىدى" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "مەشغۇلات بىكار قىلىندى" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "مەشغۇلات توسۇلىدۇ" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP ئىلتىماسىنى يېشەلمىدى" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "URI تەمىنلەنمىدى" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "ئىناۋەتسىز ‹%s› URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4122 #, c-format msgid "Could not parse URI '%s'" msgstr "URI «%s» نى تەھلىل قىلالمىدى" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4159 #, c-format msgid "Unsupported URI scheme '%s'" -msgstr "" +msgstr "قوللىمايدىغان URI لايىھە ‹%s›" + +#: ../libsoup/soup-session.c:4181 +#, c-format +msgid "Not an HTTP URI" +msgstr "بۇ HTTP URI ئەمەس" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "كومپيۇتېر ئاتى دېگەن بىر دانە IP ئادرېستۇر" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "باش ماشىنا ئاتى ئىناۋەتسىز" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" -msgstr "" +msgstr "كومپيۇتېر ئاتىدا ئاساسىي دائىرە يوق" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" -msgstr "" +msgstr "يېتەرلىك دائىرە يوق" -- cgit v1.2.1 From 341f51afe386de78c780855961bc7e010e9b0b13 Mon Sep 17 00:00:00 2001 From: Kjartan Maraas Date: Mon, 21 Jan 2013 12:32:31 +0100 Subject: =?UTF-8?q?Updated=20Norwegian=20bokm=C3=A5l=20translation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- po/nb.po | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/po/nb.po b/po/nb.po index a8c2d0b9..3f72f036 100644 --- a/po/nb.po +++ b/po/nb.po @@ -1,14 +1,14 @@ # Norwegian bokmål translation of libsoup. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# Kjartan Maraas , 2012. +# Kjartan Maraas , 2012-2013. # msgid "" msgstr "" -"Project-Id-Version: libsoup 3.6.x\n" +"Project-Id-Version: libsoup 3.7.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-10-13 12:50+0200\n" -"PO-Revision-Date: 2012-10-13 12:50+0200\n" +"POT-Creation-Date: 2013-01-21 12:31+0100\n" +"PO-Revision-Date: 2013-01-21 12:32+0100\n" "Last-Translator: Kjartan Maraas \n" "Language-Team: Norwegian bokmål \n" "Language: \n" @@ -22,59 +22,80 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Tilkoblingen ble brutt uventet" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Ugyldig søkeforespørsel" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Kan ikke avkorte SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Nettverksstrømmen ble lukket på uventet vis" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Buffer for utdata er for liten" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Kunne ikke tolke HTTP-svar" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Ikke gjenkjent koding av HTTP-svar" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Operasjonen ble avbrutt" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Operasjonen ville blokkere" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Kunne ikke tolke HTTP-forespørsel" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Ingen URI ble oppgitt" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Ugyldig «%s» URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4123 #, c-format msgid "Could not parse URI '%s'" msgstr "Kunne ikke tolke URI «%s»" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4160 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "URI-skjema «%s» er ikke støttet" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4182 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ikke en HTTP URI" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Vertsnavnet er en IP-adresse" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Ugyldig vertsnavn" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Vertsnavnet har ikke noe grunndomene" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Ikke mange nok domener" -- cgit v1.2.1 From e38317b878708d67ba3a67d3ec2972ab8355fb83 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 21 Jan 2013 10:50:16 -0500 Subject: Revert "SoupURI: replace NULL password with "" on http" This broke CalDAV in evolution. I'm not sure exactly why, but if it broke that, it might break other things too, so let's just revert this. This reverts commit 38901ca5e684a8fac75e6ff740d45c82dd44181a. https://bugzilla.gnome.org/show_bug.cgi?id=692149 --- libsoup/soup-uri.c | 2 -- tests/uri-parsing.c | 12 ++++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index fdb43785..28b3025c 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -434,8 +434,6 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) uri->scheme == SOUP_URI_SCHEME_HTTPS) { if (!uri->path) uri->path = g_strdup ("/"); - if (uri->user && !uri->password) - uri->password = g_strdup (""); if (!SOUP_URI_VALID_FOR_HTTP (uri)) { soup_uri_free (uri); return NULL; diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index 7992d70b..892ee2b9 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -23,15 +23,15 @@ static struct { { "ftp://user:password@host", "ftp://user@host", { "ftp", "user", "password", "host", 21, "", NULL, NULL } }, { "http://us%65r@host", "http://user@host/", - { "http", "user", "", "host", 80, "/", NULL, NULL } }, + { "http", "user", NULL, "host", 80, "/", NULL, NULL } }, { "http://us%40r@host", "http://us%40r@host/", - { "http", "us\x40r", "", "host", 80, "/", NULL, NULL } }, + { "http", "us\x40r", NULL, "host", 80, "/", NULL, NULL } }, { "http://us%3ar@host", "http://us%3Ar@host/", - { "http", "us\x3ar", "", "host", 80, "/", NULL, NULL } }, + { "http", "us\x3ar", NULL, "host", 80, "/", NULL, NULL } }, { "http://us%2fr@host", "http://us%2Fr@host/", - { "http", "us\x2fr", "", "host", 80, "/", NULL, NULL } }, + { "http", "us\x2fr", NULL, "host", 80, "/", NULL, NULL } }, { "http://us%3fr@host", "http://us%3Fr@host/", - { "http", "us\x3fr", "", "host", 80, "/", NULL, NULL } }, + { "http", "us\x3fr", NULL, "host", 80, "/", NULL, NULL } }, { "http://host?query", "http://host/?query", { "http", NULL, NULL, "host", 80, "/", "query", NULL } }, { "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", @@ -122,7 +122,7 @@ static struct { { "http", NULL, NULL, "", 80, "//////////////", NULL, NULL } }, { "http://@host", "http://@host/", - { "http", "", "", "host", 80, "/", NULL, NULL } }, + { "http", "", NULL, "host", 80, "/", NULL, NULL } }, { "http://:@host", "http://@host/", { "http", "", "", "host", 80, "/", NULL, NULL } }, -- cgit v1.2.1 From 8a07df5bd57e48bcb37ac7999e0d985bf9935363 Mon Sep 17 00:00:00 2001 From: Milo Casagrande Date: Thu, 24 Jan 2013 21:48:32 +0100 Subject: [l10n] Updated Italian translation. --- po/it.po | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/po/it.po b/po/it.po index 3d66d3cc..04cddbef 100644 --- a/po/it.po +++ b/po/it.po @@ -1,14 +1,14 @@ # Italian translations for libsoup package -# Copyright (C) 2012 the Free Software Foundation, Inc. +# Copyright (C) 2012, 2013 the Free Software Foundation, Inc. # This file is distributed under the same license as the libsoup package. -# Milo Casagrande , 2012. +# Milo Casagrande , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-10 21:08+0200\n" -"PO-Revision-Date: 2012-09-10 21:09+0200\n" +"POT-Creation-Date: 2013-01-24 21:45+0100\n" +"PO-Revision-Date: 2013-01-24 21:47+0100\n" "Last-Translator: Milo Casagrande \n" "Language-Team: Italian \n" "Language: it\n" @@ -23,59 +23,80 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Connessione terminata inaspettatamente" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Richiesta di posizionamento non valida" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Impossibile troncare SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Flusso di rete chiuso inaspettatamente" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Il buffer di uscita è troppo piccolo" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Impossibile analizzare la risposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codifica risposta HTTP non riconosciuta" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "L'operazione è stata annullata" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "L'operazione potrebbe bloccarsi" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Impossibile analizzare la richiesta HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Nessun URI fornito" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI «%s» non valido: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4123 #, c-format msgid "Could not parse URI '%s'" msgstr "Impossibile analizzare l'URI «%s»" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4160 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Schema URI «%s» non supportato" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4182 +#, c-format +msgid "Not an HTTP URI" +msgstr "Non è uno URI HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Il nome host è un indirizzo IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Nome host non valido" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Il nome host non ha un dominio di base" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Domini insufficienti" -- cgit v1.2.1 From 48b065832cbcbdab96db46864c9f5ac7152b5556 Mon Sep 17 00:00:00 2001 From: Andre Jonas Date: Sun, 3 Feb 2013 19:58:29 +0100 Subject: [l10n] Updated German translation --- po/de.po | 56 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/po/de.po b/po/de.po index a3555c5a..62d77b06 100644 --- a/po/de.po +++ b/po/de.po @@ -3,22 +3,23 @@ # This file is distributed under the same license as the libsoup package. # Tobias Endrigkeit , 2012. # Mario Blättermann , 2012. +# Andre Jonas , 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-20 13:29+0100\n" -"Last-Translator: Mario Blättermann \n" -"Language-Team: Deutsch \n" +"POT-Creation-Date: 2013-01-21 15:55+0000\n" +"PO-Revision-Date: 2013-01-23 12:26+0100\n" +"Last-Translator: Andre Jonas \n" +"Language-Team: Deutsch >\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Gtranslator 2.91.5\n" +"X-Generator: Gtranslator 2.91.6\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -26,59 +27,80 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Die Verbindung wurde unerwartet beendet" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Ungültige Suchanfrage" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream konnte nicht abgeschnitten werden" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Netzwerk-Stream wurde unerwartet geschlossen" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Der Ausgabe-Zwischenspeicher ist zu klein" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP-Antwort konnte nicht verarbeitet werden" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Unbekannte Kodierung der HTTP-Antwort" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Der Vorgang wurde abgebrochen" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Der Vorgang würde gestoppt werden" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "HTTP-Anfrage konnte nicht verarbeitet werden" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Keine Adresse wurde bereitgestellt" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Ungültige »%s« Adresse: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4123 #, c-format msgid "Could not parse URI '%s'" msgstr "Die Adresse »%s« konnte nicht verarbeitet werden" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4160 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nicht unterstütztes Adressenschema »%s«" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4182 +#, c-format +msgid "Not an HTTP URI" +msgstr "Keine HTTP-Adresse" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Der Rechnername ist eine IP-Adresse" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Ungültiger Rechnername" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Der Rechnername hat keine Hauptdomäne" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Nicht genug Domänen" -- cgit v1.2.1 From e91d1962451116a8d7ce1a7b0031095482bfe4a9 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Wed, 30 Jan 2013 19:25:12 +0100 Subject: soup-session: use SoupMessageQueueItem's cancellable for the GTask Even if the caller does not specify a GCancellable the GTask must use the one that comes with the item by default. This also sets check_cancellable() to FALSE in the session's GTask in order not to override error messages previously set on the GTask in case of cancellations. https://bugzilla.gnome.org/show_bug.cgi?id=692310 --- libsoup/soup-session.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index ab9e2cd8..bc23e888 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3894,15 +3894,23 @@ soup_session_send_async (SoupSession *session, g_signal_connect (msg, "finished", G_CALLBACK (async_send_request_finished), item); - item->new_api = TRUE; - item->task = g_task_new (session, cancellable, callback, user_data); - g_task_set_task_data (item->task, item, (GDestroyNotify) soup_message_queue_item_unref); - if (cancellable) { g_object_unref (item->cancellable); item->cancellable = g_object_ref (cancellable); } + item->new_api = TRUE; + item->task = g_task_new (session, item->cancellable, callback, user_data); + g_task_set_task_data (item->task, item, (GDestroyNotify) soup_message_queue_item_unref); + + /* Do not check for cancellations as we do not want to + * overwrite custom error messages set during cancellations + * (for example SOUP_HTTP_ERROR is set for cancelled messages + * in async_send_request_return_result() (status_code==1 + * means CANCEL and is considered a TRANSPORT_ERROR)). + */ + g_task_set_check_cancellable (item->task, FALSE); + if (async_respond_from_cache (session, item)) item->state = SOUP_MESSAGE_CACHED; else -- cgit v1.2.1 From 33e7fe6e6f57ba39ad2b50f9efa73ac97683cb79 Mon Sep 17 00:00:00 2001 From: Chao-Hsiung Liao Date: Mon, 4 Feb 2013 20:34:27 +0800 Subject: Updated Traditional Chinese translation(Hong Kong and Taiwan) --- po/zh_HK.po | 43 ++++++++++++++++++++++++++++++++++--------- po/zh_TW.po | 43 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/po/zh_HK.po b/po/zh_HK.po index ae21d89f..fbd82c47 100644 --- a/po/zh_HK.po +++ b/po/zh_HK.po @@ -6,15 +6,17 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-15 12:53+0800\n" -"PO-Revision-Date: 2012-09-15 12:53+0800\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-12-18 15:49+0000\n" +"PO-Revision-Date: 2013-02-04 20:34+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: Chinese (Hong Kong) \n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -30,39 +32,62 @@ msgstr "無效的搜尋要求" msgid "Cannot truncate SoupBodyInputStream" msgstr "不能截短 SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "網絡串流無預警的關閉了" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "輸出緩衝區太小" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "無法解析 HTTP 回應" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "未辨識的 HTTP 回應編碼" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "操作已被取消" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "操作會阻擋" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "無法解析 HTTP 要求" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "未提供 URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "無效的「%s」URI:%s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "無法解析 URI「%s」" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "不支援的 URI scheme「%s」" +#: ../libsoup/soup-session.c:3811 +#, c-format +msgid "Not an HTTP URI" +msgstr "並非 HTTP URI" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "主機名稱是 IP 位址" diff --git a/po/zh_TW.po b/po/zh_TW.po index 7ece68cc..2f319b71 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -6,15 +6,17 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-15 12:53+0800\n" -"PO-Revision-Date: 2012-09-12 20:11+0800\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2012-12-18 15:49+0000\n" +"PO-Revision-Date: 2013-02-04 18:54+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: Chinese (Taiwan) \n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -30,39 +32,62 @@ msgstr "無效的搜尋要求" msgid "Cannot truncate SoupBodyInputStream" msgstr "不能截短 SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "網路串流無預警的關閉了" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "輸出緩衝區太小" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "無法解析 HTTP 回應" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "未辨識的 HTTP 回應編碼" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "操作已被取消" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "操作會阻擋" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "無法解析 HTTP 要求" + +#: ../libsoup/soup-request.c:141 #, c-format msgid "No URI provided" msgstr "未提供 URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:151 #, c-format msgid "Invalid '%s' URI: %s" msgstr "無效的「%s」URI:%s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:3752 #, c-format msgid "Could not parse URI '%s'" msgstr "無法解析 URI「%s」" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:3789 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "不支援的 URI scheme「%s」" +#: ../libsoup/soup-session.c:3811 +#, c-format +msgid "Not an HTTP URI" +msgstr "並非 HTTP URI" + #: ../libsoup/soup-tld.c:154 msgid "Hostname is an IP address" msgstr "主機名稱是 IP 位址" -- cgit v1.2.1 From fe6d744b68dc118271ca95f7c6a9f989726881e1 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 5 Feb 2013 10:14:44 -0500 Subject: 2.41.5 --- NEWS | 17 +++++++++++++++++ configure.ac | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c1eafdc1..9d19e375 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,20 @@ +Changes in libsoup from 2.41.4 to 2.41.5: + + * Reverted the change to SoupURI's password handling from + 2.41.4, since it turns out to have broken some things. + [#692149, Dan] + + * Avoid a g_return_if_fail() when loading + SoupSession:ssl-ca-file fails. [#691930, Guillaume + Desmottes] + + * Fixed a bug in SoupBodyInputStream that caused redirects in + WebKitGTK to hang. [#692026, Sergio] + + * Updated translations: + Belarusian, Chinese (traditional), German, Italian, + Norwegian bokmål, Serbian, Uyghur + Changes in libsoup from 2.41.3 to 2.41.4: * Lots of docs fixes, including catching up with some (but not diff --git a/configure.ac b/configure.ac index cc857017..fc49a2bd 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [4]) +m4_define([soup_micro_version], [5]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 326f5d45d7dd6bf72c07b0c37ffdbc509a9c5a91 Mon Sep 17 00:00:00 2001 From: Jonh Wendell Date: Mon, 4 Feb 2013 21:52:26 -0200 Subject: SoupSocket: Move the creation of socket clients to a single place Thus avoiding duplication of code in sync and async functions. --- libsoup/soup-socket.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 6b485bab..fd70dc8f 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -697,6 +697,24 @@ socket_connected (SoupSocket *sock, GSocketConnection *conn, GError *error) return SOUP_STATUS_OK; } +static GSocketClient * +new_socket_client (SoupSocket *sock) +{ + SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); + GSocketClient *client = g_socket_client_new (); + + g_signal_connect (client, "event", + G_CALLBACK (proxy_socket_client_event), sock); + if (priv->use_proxy) + g_socket_client_add_application_proxy (client, "http"); + else + g_socket_client_set_enable_proxy (client, FALSE); + if (priv->timeout) + g_socket_client_set_timeout (client, priv->timeout); + + return client; +} + /** * SoupSocketCallback: * @sock: the #SoupSocket @@ -770,15 +788,7 @@ soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable, if (priv->async_context && !priv->use_thread_context) g_main_context_push_thread_default (priv->async_context); - client = g_socket_client_new (); - g_signal_connect (client, "event", - G_CALLBACK (proxy_socket_client_event), sock); - if (priv->use_proxy) - g_socket_client_add_application_proxy (client, "http"); - else - g_socket_client_set_enable_proxy (client, FALSE); - if (priv->timeout) - g_socket_client_set_timeout (client, priv->timeout); + client = new_socket_client (sock); g_socket_client_connect_async (client, G_SOCKET_CONNECTABLE (priv->remote_addr), priv->connect_cancel, @@ -819,15 +829,7 @@ soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable) cancellable = g_cancellable_new (); priv->connect_cancel = cancellable; - client = g_socket_client_new (); - g_signal_connect (client, "event", - G_CALLBACK (proxy_socket_client_event), sock); - if (priv->use_proxy) - g_socket_client_add_application_proxy (client, "http"); - else - g_socket_client_set_enable_proxy (client, FALSE); - if (priv->timeout) - g_socket_client_set_timeout (client, priv->timeout); + client = new_socket_client (sock); conn = g_socket_client_connect (client, G_SOCKET_CONNECTABLE (priv->remote_addr), priv->connect_cancel, &error); -- cgit v1.2.1 From 19aeb978add0f64f348e46909ec5c3bafc02e806 Mon Sep 17 00:00:00 2001 From: Jonh Wendell Date: Mon, 4 Feb 2013 22:21:12 -0200 Subject: SoupSocket: Use the local socket, when available, even on client side. This allows binding the client connection to a specific local address. --- libsoup/soup-socket.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index fd70dc8f..df9a2109 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -712,6 +712,9 @@ new_socket_client (SoupSocket *sock) if (priv->timeout) g_socket_client_set_timeout (client, priv->timeout); + if (priv->local_addr) + g_socket_client_set_local_address (client, soup_address_get_gsockaddr (priv->local_addr)); + return client; } -- cgit v1.2.1 From 50cb7bdd1232316c74fc5b019bf235910f732e59 Mon Sep 17 00:00:00 2001 From: Jonh Wendell Date: Tue, 5 Feb 2013 13:38:09 -0200 Subject: SoupConnection: added a new construction-time property "local-address" It will be proxied to the SoupSocket upon its creation. --- libsoup/soup-connection.c | 18 ++++++++++++++++++ libsoup/soup-connection.h | 1 + 2 files changed, 19 insertions(+) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index a6ed5243..3dff7eca 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -18,6 +18,7 @@ typedef struct { SoupSocket *socket; + SoupAddress *local_addr; SoupURI *remote_uri, *proxy_uri; SoupProxyURIResolver *proxy_resolver; gboolean use_gproxyresolver; @@ -49,6 +50,7 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0, + PROP_LOCAL_ADDRESS, PROP_REMOTE_URI, PROP_PROXY_RESOLVER, PROP_SSL, @@ -85,6 +87,7 @@ soup_connection_finalize (GObject *object) g_clear_pointer (&priv->proxy_uri, soup_uri_free); g_clear_object (&priv->tlsdb); g_clear_object (&priv->proxy_resolver); + g_clear_object (&priv->local_addr); g_clear_pointer (&priv->async_context, g_main_context_unref); G_OBJECT_CLASS (soup_connection_parent_class)->finalize (object); @@ -114,6 +117,9 @@ soup_connection_set_property (GObject *object, guint prop_id, SoupProxyURIResolver *proxy_resolver; switch (prop_id) { + case PROP_LOCAL_ADDRESS: + priv->local_addr = g_value_dup_object (value); + break; case PROP_REMOTE_URI: priv->remote_uri = g_value_dup_boxed (value); break; @@ -168,6 +174,9 @@ soup_connection_get_property (GObject *object, guint prop_id, SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object); switch (prop_id) { + case PROP_LOCAL_ADDRESS: + g_value_set_object (value, priv->local_addr); + break; case PROP_REMOTE_URI: g_value_set_boxed (value, priv->remote_uri); break; @@ -238,6 +247,13 @@ soup_connection_class_init (SoupConnectionClass *connection_class) G_TYPE_NONE, 0); /* properties */ + g_object_class_install_property ( + object_class, PROP_LOCAL_ADDRESS, + g_param_spec_object (SOUP_CONNECTION_LOCAL_ADDRESS, + "Local address", + "Address of local end of socket", + SOUP_TYPE_ADDRESS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( object_class, PROP_REMOTE_URI, g_param_spec_boxed (SOUP_CONNECTION_REMOTE_URI, @@ -527,6 +543,7 @@ connect_async_to_uri (SoupConnectionAsyncConnectData *data, SoupURI *uri) SOUP_SOCKET_USE_PROXY, priv->use_gproxyresolver, SOUP_SOCKET_TIMEOUT, priv->io_timeout, SOUP_SOCKET_CLEAN_DISPOSE, TRUE, + SOUP_SOCKET_LOCAL_ADDRESS, priv->local_addr, NULL); g_object_unref (remote_addr); @@ -637,6 +654,7 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) SOUP_SOCKET_FLAG_NONBLOCKING, FALSE, SOUP_SOCKET_TIMEOUT, priv->io_timeout, SOUP_SOCKET_CLEAN_DISPOSE, TRUE, + SOUP_SOCKET_LOCAL_ADDRESS, priv->local_addr, NULL); g_object_unref (remote_addr); diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h index 52e638f5..50fb7018 100644 --- a/libsoup/soup-connection.h +++ b/libsoup/soup-connection.h @@ -39,6 +39,7 @@ typedef void (*SoupConnectionCallback) (SoupConnection *conn, guint status, gpointer data); +#define SOUP_CONNECTION_LOCAL_ADDRESS "local-address" #define SOUP_CONNECTION_REMOTE_URI "remote-uri" #define SOUP_CONNECTION_PROXY_RESOLVER "proxy-resolver" #define SOUP_CONNECTION_SSL "ssl" -- cgit v1.2.1 From 7ac58e8dacd7609ecf3fd551f26034ad974d56b0 Mon Sep 17 00:00:00 2001 From: Jonh Wendell Date: Tue, 5 Feb 2013 13:57:44 -0200 Subject: SoupSession: added a new construction-time property "local-address" It will be proxied to the SoupConnection and then to SoupSocket, allowing the user to specify a local address to bind the local socket. --- libsoup/soup-session.c | 37 +++++++++++++++++++++++++++++++++++++ libsoup/soup-session.h | 1 + 2 files changed, 38 insertions(+) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index bc23e888..b2f76142 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -105,6 +105,8 @@ typedef struct { guint max_conns, max_conns_per_host; guint io_timeout, idle_timeout; + SoupAddress *local_addr; + /* Must hold the conn_lock before potentially creating a new * SoupSessionHost, adding/removing a connection, * disconnecting a connection, or moving a connection from @@ -190,6 +192,7 @@ enum { PROP_REMOVE_FEATURE_BY_TYPE, PROP_HTTP_ALIASES, PROP_HTTPS_ALIASES, + PROP_LOCAL_ADDRESS, LAST_PROP }; @@ -327,6 +330,7 @@ soup_session_finalize (GObject *object) g_free (priv->ssl_ca_file); g_clear_pointer (&priv->async_context, g_main_context_unref); + g_clear_object (&priv->local_addr); g_hash_table_destroy (priv->features_cache); @@ -547,6 +551,9 @@ soup_session_set_property (GObject *object, guint prop_id, GMainContext *async_context; switch (prop_id) { + case PROP_LOCAL_ADDRESS: + priv->local_addr = g_value_dup_object (value); + break; case PROP_PROXY_URI: uri = g_value_get_boxed (value); @@ -683,6 +690,9 @@ soup_session_get_property (GObject *object, guint prop_id, GTlsDatabase *tlsdb; switch (prop_id) { + case PROP_LOCAL_ADDRESS: + g_value_set_object (value, priv->local_addr); + break; case PROP_PROXY_URI: feature = soup_session_get_feature (session, SOUP_TYPE_PROXY_RESOLVER_STATIC); if (feature) { @@ -1681,6 +1691,7 @@ get_connection_for_host (SoupSession *session, SOUP_CONNECTION_TIMEOUT, priv->io_timeout, SOUP_CONNECTION_IDLE_TIMEOUT, priv->idle_timeout, SOUP_CONNECTION_SSL_FALLBACK, host->ssl_fallback, + SOUP_CONNECTION_LOCAL_ADDRESS, priv->local_addr, NULL); g_signal_connect (conn, "disconnected", G_CALLBACK (connection_disconnected), @@ -3504,6 +3515,32 @@ soup_session_class_init (SoupSessionClass *session_class) "URI schemes that are considered aliases for 'https'", G_TYPE_STRV, G_PARAM_READWRITE)); + + /** + * SOUP_SESSION_LOCAL_ADDRESS: + * + * Alias for the #SoupSession:local-address property, qv. + * + * Since: 2.42 + **/ + /** + * SoupSession:local-address: + * + * Sets the #SoupAddress to use for the client side of + * the connection. + * + * Use this property if you want for instance to bind the + * local socket to a specific IP address. + * + * Since: 2.42 + **/ + g_object_class_install_property ( + object_class, PROP_LOCAL_ADDRESS, + g_param_spec_object (SOUP_SESSION_LOCAL_ADDRESS, + "Local address", + "Address of local end of socket", + SOUP_TYPE_ADDRESS, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index 90cf12c7..9d0f232d 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -60,6 +60,7 @@ typedef struct { GType soup_session_get_type (void); +#define SOUP_SESSION_LOCAL_ADDRESS "local-address" #define SOUP_SESSION_PROXY_URI "proxy-uri" #define SOUP_SESSION_MAX_CONNS "max-conns" #define SOUP_SESSION_MAX_CONNS_PER_HOST "max-conns-per-host" -- cgit v1.2.1 From 4f27350d0f6daf8719cdf5a2b6e71cf1771ff656 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 7 Feb 2013 09:23:31 -0500 Subject: tests: fix non-php apache tests to still work without php Setting "IF_HAVE_PHP" to "#" actually sets it to "", because the "#" is treated as the start of a comment. We have to set it to "\#" if we want to cause the "#" to actually get substituted into httpd.conf https://bugzilla.gnome.org/show_bug.cgi?id=693311 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index fc49a2bd..79026a57 100644 --- a/configure.ac +++ b/configure.ac @@ -284,7 +284,7 @@ if test "$have_apache" = 1; then IF_HAVE_PHP="" else have_php=no - IF_HAVE_PHP="#" + IF_HAVE_PHP="\#" MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES php5" fi AC_MSG_RESULT($have_php) -- cgit v1.2.1 From d2c32e501165544b4afda9813c714b3a7a55cb33 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 7 Feb 2013 14:14:47 -0500 Subject: SoupSession: fix a bug with the add-feature-by-type property The add-feature-by-type and remove-feature-by-type properties were only accepting SoupSessionFeature types, so you couldn't use it for things like request types, auth types, etc. --- libsoup/soup-session.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index b2f76142..c50faa22 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3429,7 +3429,7 @@ soup_session_class_init (SoupSessionClass *session_class) g_param_spec_gtype (SOUP_SESSION_ADD_FEATURE_BY_TYPE, "Add Feature By Type", "Add a feature object of the given type to the session", - SOUP_TYPE_SESSION_FEATURE, + G_TYPE_OBJECT, G_PARAM_READWRITE)); /** * SoupSession:remove-feature-by-type: (skip) @@ -3452,7 +3452,7 @@ soup_session_class_init (SoupSessionClass *session_class) g_param_spec_gtype (SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, "Remove Feature By Type", "Remove features of the given type from the session", - SOUP_TYPE_SESSION_FEATURE, + G_TYPE_OBJECT, G_PARAM_READWRITE)); /** * SoupSession:http-aliases: -- cgit v1.2.1 From 080103de0bc8c70d37125fe60a8886371ca35cfc Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 7 Feb 2013 15:03:41 -0500 Subject: SoupAuthNTLM: fix to do a "retrying" authenticate If the first attempt at NTLM auth fails, let the auth manager emit a "retrying" authenticate as well, just like normal auths do. https://bugzilla.gnome.org/show_bug.cgi?id=693222 --- libsoup/soup-auth-ntlm.c | 79 +++++++++++++++++++++++++++++++++++-------- tests/ntlm-test.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 14 deletions(-) diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index 367a3cac..7b11a436 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -48,10 +48,17 @@ typedef struct { char *response_header; } SoupNTLMConnectionState; +typedef enum { + SOUP_NTLM_PASSWORD_NONE, + SOUP_NTLM_PASSWORD_PROVIDED, + SOUP_NTLM_PASSWORD_ACCEPTED, + SOUP_NTLM_PASSWORD_REJECTED +} SoupNTLMPasswordState; + typedef struct { char *username, *domain; guchar nt_hash[21], lm_hash[21]; - gboolean authenticated; + SoupNTLMPasswordState password_state; #ifdef USE_NTLM_AUTH /* Use Samba's 'winbind' daemon to support NTLM single-sign-on, @@ -282,23 +289,37 @@ soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg, SoupNTLMConnectionState *conn = state; gboolean success = TRUE; + /* Note that we only return FALSE if some sort of parsing error + * occurs. Otherwise, the SoupAuth is still reusable (though it may + * no longer be _ready or _authenticated). + */ + + if (!g_str_has_prefix (auth_header, "NTLM")) + return FALSE; + if (conn->state > SOUP_NTLM_SENT_REQUEST) { - /* We already authenticated, but then got another 401. - * That means "permission denied", so don't try to - * authenticate again. - */ conn->state = SOUP_NTLM_FAILED; - /* FIXME: we should only do this if the password never worked */ - priv->authenticated = FALSE; + if (priv->password_state == SOUP_NTLM_PASSWORD_ACCEPTED) { + /* We know our password is correct, so a 401 + * means "permission denied". Since the conn + * state is now FAILED, the auth is no longer + * is_ready() for this message, so this will + * cause a "retrying" authenticate signal. + */ + return TRUE; + } - return FALSE; + /* Otherwise, we just have a bad password. */ + priv->password_state = SOUP_NTLM_PASSWORD_REJECTED; + return TRUE; } - if (!g_str_has_prefix (auth_header, "NTLM ")) - return FALSE; + if (conn->state == SOUP_NTLM_NEW && !auth_header[4]) + return TRUE; - if (!soup_ntlm_parse_challenge (auth_header + 5, &conn->nonce, &priv->domain)) { + if (!soup_ntlm_parse_challenge (auth_header + 5, &conn->nonce, + priv->domain ? NULL : &priv->domain)) { conn->state = SOUP_NTLM_FAILED; return FALSE; } @@ -327,7 +348,8 @@ soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg, g_free (response); } else { conn->response_header = response; - priv->authenticated = TRUE; + if (priv->password_state != SOUP_NTLM_PASSWORD_ACCEPTED) + priv->password_state = SOUP_NTLM_PASSWORD_PROVIDED; } } out: @@ -385,7 +407,7 @@ soup_auth_ntlm_authenticate (SoupAuth *auth, const char *username, soup_ntlm_nt_hash (password, priv->nt_hash); soup_ntlm_lanmanager_hash (password, priv->lm_hash); - priv->authenticated = TRUE; + priv->password_state = SOUP_NTLM_PASSWORD_PROVIDED; } static gboolean @@ -393,7 +415,8 @@ soup_auth_ntlm_is_authenticated (SoupAuth *auth) { SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); - return priv->authenticated; + return (priv->password_state != SOUP_NTLM_PASSWORD_NONE && + priv->password_state != SOUP_NTLM_PASSWORD_REJECTED); } static gboolean @@ -401,11 +424,32 @@ soup_auth_ntlm_is_connection_ready (SoupConnectionAuth *auth, SoupMessage *msg, gpointer state) { + SoupAuthNTLMPrivate *priv = SOUP_AUTH_NTLM_GET_PRIVATE (auth); SoupNTLMConnectionState *conn = state; + if (priv->password_state == SOUP_NTLM_PASSWORD_REJECTED) + return FALSE; + + if (priv->password_state == SOUP_NTLM_PASSWORD_PROVIDED) + return TRUE; + return conn->state != SOUP_NTLM_FAILED && conn->state != SOUP_NTLM_SSO_FAILED; } +static void +got_final_auth_result (SoupMessage *msg, gpointer data) +{ + SoupAuth *auth = data; + + g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (got_final_auth_result), auth); + + if (auth != soup_message_get_auth (msg)) + return; + + if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) + SOUP_AUTH_NTLM_GET_PRIVATE (auth)->password_state = SOUP_NTLM_PASSWORD_ACCEPTED; +} + static char * soup_auth_ntlm_get_connection_authorization (SoupConnectionAuth *auth, SoupMessage *msg, @@ -454,6 +498,13 @@ soup_auth_ntlm_get_connection_authorization (SoupConnectionAuth *auth, } g_clear_pointer (&conn->nonce, g_free); conn->state = SOUP_NTLM_SENT_RESPONSE; + + if (priv->password_state != SOUP_NTLM_PASSWORD_ACCEPTED) { + /* We need to know if this worked */ + g_signal_connect (msg, "got-headers", + G_CALLBACK (got_final_auth_result), + auth); + } break; #ifdef USE_NTLM_AUTH case SOUP_NTLM_SSO_FAILED: diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index fa31280e..3588c555 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -463,6 +463,89 @@ do_ntlm_tests (SoupURI *base_uri, gboolean use_builtin_ntlm) do_ntlm_round (base_uri, FALSE, "alice", use_builtin_ntlm); } +static void +retry_test_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, + gpointer user_data) +{ + gboolean *retried = user_data; + + if (!retrying) { + /* server_callback doesn't actually verify the password, + * only the username. So we pass an incorrect username + * rather than an incorrect password. + */ + soup_auth_authenticate (auth, "wrong", "password"); + } else if (!*retried) { + soup_auth_authenticate (auth, "alice", "password"); + *retried = TRUE; + } +} + +static void +do_retrying_test (SoupURI *base_uri) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *uri; + gboolean retried = FALSE; + + debug_printf (1, " /alice\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_NTLM, + NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (retry_test_authenticate), &retried); + + uri = soup_uri_new_with_base (base_uri, "/alice"); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + soup_session_send_message (session, msg); + + if (!retried) { + debug_printf (1, " Didn't retry!\n"); + errors++; + } + if (msg->status_code != SOUP_STATUS_OK) { + debug_printf (1, " Unexpected final status %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + g_object_unref (msg); + + soup_test_session_abort_unref (session); + + debug_printf (1, " /bob\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_AUTH_NTLM, + NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (retry_test_authenticate), &retried); + retried = FALSE; + + uri = soup_uri_new_with_base (base_uri, "/bob"); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + soup_session_send_message (session, msg); + + if (!retried) { + debug_printf (1, " Didn't retry!\n"); + errors++; + } + if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { + debug_printf (1, " Unexpected final status %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + g_object_unref (msg); + + soup_test_session_abort_unref (session); +} + int main (int argc, char **argv) { @@ -503,6 +586,11 @@ main (int argc, char **argv) debug_printf (1, "\nExternal -> fallback support\n"); do_ntlm_tests (uri, TRUE); + /* Other tests */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); + debug_printf (1, "\nRetrying on failed password\n"); + do_retrying_test (uri); + soup_uri_free (uri); soup_test_server_quit_unref (server); -- cgit v1.2.1 From dca68a229e60f76191f9ab4f1d01ca87b842180c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavol=20Kla=C4=8Dansk=C3=BD?= Date: Sat, 9 Feb 2013 22:41:00 +0100 Subject: Updated slovak translation --- po/sk.po | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/po/sk.po b/po/sk.po index 0081c92b..92436167 100644 --- a/po/sk.po +++ b/po/sk.po @@ -1,15 +1,15 @@ # Slovak translation for libsoup. -# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# Copyright (C) 2012-2013 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# Pavol Klačanský , 2012. +# Pavol Klačanský , 2012-2013. # msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-11-04 19:36+0000\n" -"PO-Revision-Date: 2012-11-04 20:20+0000\n" +"POT-Creation-Date: 2013-02-07 14:25+0000\n" +"PO-Revision-Date: 2013-02-06 18:11+0000\n" "Last-Translator: Dušan Kazik \n" "Language-Team: Slovak \n" "Language: sk\n" @@ -25,15 +25,19 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Pripojenie bolo neočakávane ukončené" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Neplatná požiadavka na posunutie" # struct -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream sa nedá skrátiť" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "Sieťový prúd bol neočakávane uzavretý" + # PM: buffer by som preložil ako schránka # PK: schranka je clipboard, buffer je jednoznacne vyrovnavacia pamet #: ../libsoup/soup-converter-wrapper.c:192 @@ -41,6 +45,14 @@ msgstr "SoupBodyInputStream sa nedá skrátiť" msgid "Output buffer is too small" msgstr "Výstupná vyrovnávacia pamäť je príliš malá" +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Nepodarilo sa analyzovať odpoveď HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nerozpoznané kódovanie odpovede HTTP" + #: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Operácia bola zrušená" @@ -50,40 +62,49 @@ msgstr "Operácia bola zrušená" msgid "Operation would block" msgstr "Operácia by blokovala spracovanie" +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Nepodarilo sa analyzovať požiadavku HTTP" + # error -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" -msgstr "Nebol poskytnutý identifikáror URI" +msgstr "Nebol poskytnutý identifikátor URI" # first %s - scheme (http, ftp, ...) -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Neplatná schéma „%s“ identifikátora URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4168 #, c-format msgid "Could not parse URI '%s'" msgstr "Nepodarilo sa analyzovať identifikátor URI „%s“" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4205 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nepodporovaná schéma „%s“ pre identifikátor URI" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4227 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nie je HTTP URI" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Názov hostiteľa je adresa IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Neplatný názov hostiteľa" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Názov hostiteľa neobsahuje základnú doménu" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Nedostatočný počet domén" -- cgit v1.2.1 From 52b4df4b2b6d2c70fa333ce712041fd85a65d7c9 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Wed, 30 Jan 2013 20:05:29 +0100 Subject: soup-session: handle cancellation of SoupCache resources SoupSession will now properly handle cancellations (either with soup_session_cancel_message or g_cancellable_cancel) of resources returned by the cache whether they're fresh or need a revalidation. http://bugzilla.gnome.org/show_bug.cgi?id=692310 --- libsoup/soup-cache-private.h | 2 + libsoup/soup-cache.c | 13 ++++++ libsoup/soup-session.c | 94 +++++++++++++++++++++++++++++++++----------- 3 files changed, 85 insertions(+), 24 deletions(-) diff --git a/libsoup/soup-cache-private.h b/libsoup/soup-cache-private.h index 3843e8e9..65ad8689 100644 --- a/libsoup/soup-cache-private.h +++ b/libsoup/soup-cache-private.h @@ -36,6 +36,8 @@ SoupCacheability soup_cache_get_cacheability (SoupCache *cache, SoupMessage *msg); SoupMessage *soup_cache_generate_conditional_request (SoupCache *cache, SoupMessage *original); +void soup_cache_cancel_conditional_request (SoupCache *cache, + SoupMessage *msg); G_END_DECLS diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 5569d6b6..839cdc10 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -1377,6 +1377,19 @@ soup_cache_generate_conditional_request (SoupCache *cache, SoupMessage *original return msg; } +void +soup_cache_cancel_conditional_request (SoupCache *cache, + SoupMessage *msg) +{ + SoupCacheEntry *entry; + + entry = soup_cache_entry_lookup (cache, msg); + if (entry) + entry->being_validated = FALSE; + + soup_session_cancel_message (cache->priv->session, msg, SOUP_STATUS_CANCELLED); +} + static void pack_entry (gpointer data, gpointer user_data) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index c50faa22..ea0a16b9 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3781,12 +3781,49 @@ async_return_from_cache (SoupMessageQueueItem *item, async_send_request_return_result (item, g_object_ref (stream), NULL); } +typedef struct { + SoupCache *cache; + SoupMessage *conditional_msg; +} AsyncCacheCancelData; + + +static void +free_async_cache_cancel_data (AsyncCacheCancelData *data) +{ + g_object_unref (data->conditional_msg); + g_object_unref (data->cache); + g_slice_free (AsyncCacheCancelData, data); +} + +static void +cancel_cache_response (SoupMessageQueueItem *item) +{ + item->paused = FALSE; + item->state = SOUP_MESSAGE_FINISHING; + soup_message_set_status (item->msg, SOUP_STATUS_CANCELLED); + soup_session_kick_queue (item->session); +} + +static void +conditional_request_cancelled_cb (GCancellable *cancellable, AsyncCacheCancelData *data) +{ + soup_cache_cancel_conditional_request (data->cache, data->conditional_msg); +} + static void conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) { SoupMessageQueueItem *item = user_data; GInputStream *stream; + if (g_cancellable_is_cancelled (item->cancellable)) { + cancel_cache_response (item); + return; + } else { + gulong handler_id = GPOINTER_TO_SIZE (g_object_get_data (G_OBJECT (msg), "SoupSession:handler-id")); + g_cancellable_disconnect (item->cancellable, handler_id); + } + if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { SoupCache *cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); @@ -3805,29 +3842,32 @@ conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_ soup_session_kick_queue (session); } -typedef struct { - SoupMessageQueueItem *item; - GInputStream *stream; -} SendAsyncCacheData; - -static void -free_send_async_cache_data (SendAsyncCacheData *sacd) -{ - soup_message_queue_item_unref (sacd->item); - g_object_unref (sacd->stream); - g_slice_free (SendAsyncCacheData, sacd); -} - static gboolean idle_return_from_cache_cb (gpointer data) { GTask *task = data; - SendAsyncCacheData *sacd = g_task_get_task_data (task); + SoupMessageQueueItem *item = g_task_get_task_data (task); + GInputStream *istream; + + if (item->state == SOUP_MESSAGE_FINISHED) { + /* The original request was cancelled using + * soup_session_cancel_message () so it has been + * already handled by the cancellation code path. + */ + return FALSE; + } else if (g_cancellable_is_cancelled (item->cancellable)) { + /* Cancel original msg after g_cancellable_cancel(). */ + cancel_cache_response (item); + return FALSE; + } + + istream = g_object_steal_data (G_OBJECT (task), "SoupSession:istream"); + async_return_from_cache (item, istream); - async_return_from_cache (sacd->item, sacd->stream); return FALSE; } + static gboolean async_respond_from_cache (SoupSession *session, SoupMessageQueueItem *item) @@ -3842,7 +3882,6 @@ async_respond_from_cache (SoupSession *session, response = soup_cache_has_response (cache, item->msg); if (response == SOUP_CACHE_RESPONSE_FRESH) { GInputStream *stream; - SendAsyncCacheData *sacd; GSource *source; stream = soup_cache_send_response (cache, item->msg); @@ -3850,14 +3889,8 @@ async_respond_from_cache (SoupSession *session, /* Cached file was deleted? */ return FALSE; } - - sacd = g_slice_new (SendAsyncCacheData); - sacd->item = item; - soup_message_queue_item_ref (item); - sacd->stream = stream; - - g_task_set_task_data (item->task, sacd, - (GDestroyNotify) free_send_async_cache_data); + g_object_set_data_full (G_OBJECT (item->task), "SoupSession:istream", + stream, g_object_unref); source = g_timeout_source_new (0); g_task_attach_source (item->task, source, @@ -3866,14 +3899,27 @@ async_respond_from_cache (SoupSession *session, return TRUE; } else if (response == SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) { SoupMessage *conditional_msg; + AsyncCacheCancelData *data; + gulong handler_id; conditional_msg = soup_cache_generate_conditional_request (cache, item->msg); if (!conditional_msg) return FALSE; + /* Detect any quick cancellation before the cache is able to return data. */ + data = g_slice_new0 (AsyncCacheCancelData); + data->cache = g_object_ref (cache); + data->conditional_msg = g_object_ref (conditional_msg); + handler_id = g_cancellable_connect (item->cancellable, G_CALLBACK (conditional_request_cancelled_cb), + data, (GDestroyNotify) free_async_cache_cancel_data); + + g_object_set_data (G_OBJECT (conditional_msg), "SoupSession:handler-id", + GSIZE_TO_POINTER (handler_id)); soup_session_queue_message (session, conditional_msg, conditional_get_ready_cb, item); + + return TRUE; } else return FALSE; -- cgit v1.2.1 From b980d54cb2b77b6b9c54168e9c7ff772734caaac Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Wed, 30 Jan 2013 17:56:38 +0100 Subject: test-utils: add cancellation support to soup_test_request_send The function gets a new parametter used to enable request cancellation for both sync and async sessions. The cancellation could be performed by either using the GCancellable or by directly cancelling the SoupMessage. Also the GMainContext used to simulate sync operations with async ones will now try to execute all its pending events before quiting the main loop. https://bugzilla.gnome.org/show_bug.cgi?id=692310 --- tests/cache-test.c | 2 +- tests/coding-test.c | 2 +- tests/connection-test.c | 4 +-- tests/misc-test.c | 56 +++++++++++++++------------------- tests/proxy-test.c | 2 +- tests/redirect-test.c | 2 +- tests/sniffing-test.c | 4 +-- tests/test-utils.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-- tests/test-utils.h | 12 ++++++-- tests/timeout-test.c | 2 +- 10 files changed, 120 insertions(+), 46 deletions(-) diff --git a/tests/cache-test.c b/tests/cache-test.c index ac19bfe5..22ca6f86 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -146,7 +146,7 @@ do_request (SoupSession *session, } g_object_unref (msg); - stream = soup_test_request_send (SOUP_REQUEST (req), NULL, &error); + stream = soup_test_request_send (SOUP_REQUEST (req), NULL, 0, &error); if (!stream) { debug_printf (1, " could not send request: %s\n", error->message); diff --git a/tests/coding-test.c b/tests/coding-test.c index 5d4f0e32..30417b47 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -337,7 +337,7 @@ do_single_coding_req_test (SoupRequestHTTP *reqh, data = g_byte_array_new (); - stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, &error); + stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error); if (error) { debug_printf (1, " Error sending request: %s\n", error->message); diff --git a/tests/connection-test.c b/tests/connection-test.c index 6b57f24d..b7211363 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -316,7 +316,7 @@ do_timeout_req_test_for_session (SoupSession *session) req = soup_session_request_uri (session, timeout_uri, NULL); soup_uri_free (timeout_uri); - stream = soup_test_request_send (req, NULL, &error); + stream = soup_test_request_send (req, NULL, 0, &error); if (!stream) { debug_printf (1, " Unexpected error on send: %s\n", error->message); @@ -343,7 +343,7 @@ do_timeout_req_test_for_session (SoupSession *session) debug_printf (1, " Second request\n"); req = soup_session_request_uri (session, base_uri, NULL); - stream = soup_test_request_send (req, NULL, &error); + stream = soup_test_request_send (req, NULL, 0, &error); if (!stream) { debug_printf (1, " Unexpected error on send: %s\n", error->message); diff --git a/tests/misc-test.c b/tests/misc-test.c index b243ce46..d434e9bd 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -905,24 +905,9 @@ do_cancel_while_reading_test (void) soup_test_session_abort_unref (session); } -static gboolean -cancel_request_timeout (gpointer cancellable) -{ - g_cancellable_cancel (cancellable); - return FALSE; -} - -static gpointer -cancel_request_thread (gpointer cancellable) -{ - g_usleep (100000); /* .1s */ - g_cancellable_cancel (cancellable); - g_object_unref (cancellable); - return NULL; -} - static void -do_cancel_while_reading_req_test_for_session (SoupSession *session) +do_cancel_while_reading_req_test_for_session (SoupSession *session, + guint flags) { SoupRequest *req; SoupURI *uri; @@ -934,18 +919,7 @@ do_cancel_while_reading_req_test_for_session (SoupSession *session) soup_uri_free (uri); cancellable = g_cancellable_new (); - - if (SOUP_IS_SESSION_ASYNC (soup_request_get_session (req))) { - g_timeout_add (100, cancel_request_timeout, cancellable); - soup_test_request_send (req, cancellable, &error); - } else { - GThread *thread; - - thread = g_thread_new ("cancel_request_thread", cancel_request_thread, g_object_ref (cancellable)); - soup_test_request_send (req, cancellable, &error); - g_thread_unref (thread); - } - + soup_test_request_send (req, cancellable, flags, &error); if (!error) { debug_printf (1, " Request succeeded?\n"); errors++; @@ -964,20 +938,38 @@ static void do_cancel_while_reading_req_test (void) { SoupSession *session; + guint flags; + + debug_printf (1, "\nCancelling (immediately) message while reading response (request api)\n"); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); - debug_printf (1, "\nCancelling message while reading response (request api)\n"); + debug_printf (1, "\nCancelling (after 100ms) message while reading response (request api)\n"); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_SOON; debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); - do_cancel_while_reading_req_test_for_session (session); + do_cancel_while_reading_req_test_for_session (session, flags); soup_test_session_abort_unref (session); debug_printf (1, " Sync session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - do_cancel_while_reading_req_test_for_session (session); + do_cancel_while_reading_req_test_for_session (session, flags); soup_test_session_abort_unref (session); } diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 048acfa7..1ac38557 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -164,7 +164,7 @@ test_url_new_api (const char *url, int proxy, guint expected, request = soup_session_request (session, url, NULL); msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); - stream = soup_test_request_send (request, NULL, &error); + stream = soup_test_request_send (request, NULL, 0, &error); if (!stream) { debug_printf (1, " Unexpected error on Request: %s\n", error->message); diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 3307ce63..9bc4621d 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -252,7 +252,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) g_signal_connect (msg, "restarted", G_CALLBACK (restarted), &treq); - stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, &error); + stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error); if (SOUP_STATUS_IS_TRANSPORT_ERROR (final_status)) { if (stream) { diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index f28ddaf8..cbebaba0 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -383,7 +383,7 @@ test_sniffing (const char *path, const char *expected_type) g_object_unref (msg); req = soup_session_request_uri (session, uri, NULL); - stream = soup_test_request_send (req, NULL, &error); + stream = soup_test_request_send (req, NULL, 0, &error); if (stream) { soup_test_request_close_stream (req, stream, NULL, &error); g_object_unref (stream); @@ -439,7 +439,7 @@ test_disabled (const char *path) msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); soup_message_disable_feature (msg, SOUP_TYPE_CONTENT_SNIFFER); g_object_unref (msg); - stream = soup_test_request_send (req, NULL, &error); + stream = soup_test_request_send (req, NULL, 0, &error); if (stream) { soup_test_request_close_stream (req, stream, NULL, &error); g_object_unref (stream); diff --git a/tests/test-utils.c b/tests/test-utils.c index fc5b18d3..cc9aa8e1 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -371,24 +371,98 @@ async_as_sync_callback (GObject *object, gpointer user_data) { AsyncAsSyncData *data = user_data; + GMainContext *context; data->result = g_object_ref (result); + context = g_main_loop_get_context (data->loop); + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); g_main_loop_quit (data->loop); } +typedef struct { + SoupRequest *req; + GCancellable *cancellable; + SoupTestRequestFlags flags; +} CancelData; + +static CancelData * +create_cancel_data (SoupRequest *req, + GCancellable *cancellable, + SoupTestRequestFlags flags) +{ + CancelData *cancel_data; + + if (!flags) + return NULL; + + cancel_data = g_slice_new0 (CancelData); + cancel_data->flags = flags; + if (flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE && SOUP_IS_REQUEST_HTTP (req)) + cancel_data->req = g_object_ref (req); + else if (flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE) + cancel_data->cancellable = g_object_ref (cancellable); + return cancel_data; +} + +static void inline +cancel_message_or_cancellable (CancelData *cancel_data) +{ + if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE) { + SoupRequest *req = cancel_data->req; + soup_session_cancel_message (soup_request_get_session (req), + soup_request_http_get_message (SOUP_REQUEST_HTTP (req)), + SOUP_STATUS_CANCELLED); + g_object_unref (req); + } else if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE) { + g_cancellable_cancel (cancel_data->cancellable); + g_object_unref (cancel_data->cancellable); + } + g_slice_free (CancelData, cancel_data); +} + +static gboolean +cancel_request_timeout (gpointer data) +{ + cancel_message_or_cancellable ((CancelData *) data); + return FALSE; +} + +static gpointer +cancel_request_thread (gpointer data) +{ + g_usleep (100000); /* .1s */ + cancel_message_or_cancellable ((CancelData *) data); + return NULL; +} + GInputStream * soup_test_request_send (SoupRequest *req, GCancellable *cancellable, + guint flags, GError **error) { AsyncAsSyncData data; GInputStream *stream; + CancelData *cancel_data = create_cancel_data (req, cancellable, flags); - if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) - return soup_request_send (req, cancellable, error); + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) { + GThread *thread; - data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + if (cancel_data) + thread = g_thread_new ("cancel_request_thread", cancel_request_thread, + cancel_data); + stream = soup_request_send (req, cancellable, error); + if (cancel_data) + g_thread_unref (thread); + return stream; + } + data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + if (cancel_data) { + guint interval = flags & SOUP_TEST_REQUEST_CANCEL_SOON ? 100 : 0; + g_timeout_add_full (G_PRIORITY_HIGH, interval, cancel_request_timeout, cancel_data, NULL); + } soup_request_send_async (req, cancellable, async_as_sync_callback, &data); g_main_loop_run (data.loop); diff --git a/tests/test-utils.h b/tests/test-utils.h index ca1003f4..22a4a163 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -23,6 +23,13 @@ void apache_init (void); void apache_cleanup (void); #endif +typedef enum { + SOUP_TEST_REQUEST_NONE = 0, + SOUP_TEST_REQUEST_CANCEL_MESSAGE = (1 << 0), + SOUP_TEST_REQUEST_CANCEL_CANCELLABLE = (1 << 1), + SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2) +} SoupTestRequestFlags; + SoupSession *soup_test_session_new (GType type, ...); void soup_test_session_abort_unref (SoupSession *session); @@ -30,8 +37,9 @@ SoupServer *soup_test_server_new (gboolean in_own_thread); SoupServer *soup_test_server_new_ssl (gboolean in_own_thread); void soup_test_server_quit_unref (SoupServer *server); -GInputStream *soup_test_request_send (SoupRequest *req, - GCancellable *cancellable, +GInputStream *soup_test_request_send (SoupRequest *req, + GCancellable *cancellable, + guint flags, GError **error); gboolean soup_test_request_close_stream (SoupRequest *req, GInputStream *stream, diff --git a/tests/timeout-test.c b/tests/timeout-test.c index e523f2db..27bcbff1 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -127,7 +127,7 @@ do_request_to_session (SoupSession *session, const char *uri, g_signal_connect (msg, "finished", G_CALLBACK (message_finished), &finished); - stream = soup_test_request_send (req, NULL, &error); + stream = soup_test_request_send (req, NULL, 0, &error); if (expect_timeout && !error) { debug_printf (1, " FAILED: request did not time out\n"); -- cgit v1.2.1 From 8e7cb1cc11fff189c5d69940d9e714d5b84c2fed Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Wed, 30 Jan 2013 18:16:32 +0100 Subject: cache-test: added cancellation tests Added cancellation tests for both fresh and under revalidation resources. These tests ensure that cancellations happen flawlessly and that any potential revalidation process is also cancelled. https://bugzilla.gnome.org/show_bug.cgi?id=692310 --- tests/cache-test.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/tests/cache-test.c b/tests/cache-test.c index 22ca6f86..ed8ca453 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -113,6 +113,7 @@ static char *do_request (SoupSession *session, static gboolean last_request_hit_network; static gboolean last_request_validated; +static guint cancelled_requests; static char * do_request (SoupSession *session, @@ -180,6 +181,41 @@ do_request (SoupSession *session, return nread ? g_memdup (buf, nread) : g_strdup (""); } +static void +do_request_with_cancel (SoupSession *session, + SoupURI *base_uri, + const char *method, + const char *path, + SoupTestRequestFlags flags) +{ + SoupRequestHTTP *req; + GInputStream *stream; + SoupURI *uri; + GError *error = NULL; + GCancellable *cancellable; + + last_request_validated = last_request_hit_network = FALSE; + cancelled_requests = 0; + + uri = soup_uri_new_with_base (base_uri, path); + req = soup_session_request_http_uri (session, method, uri, NULL); + soup_uri_free (uri); + cancellable = flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE ? g_cancellable_new () : NULL; + stream = soup_test_request_send (SOUP_REQUEST (req), cancellable, flags, &error); + if (stream) { + debug_printf (1, " could not cancel the request\n"); + g_object_unref (stream); + g_object_unref (req); + return; + } + + g_clear_object (&cancellable); + g_clear_object (&stream); + g_clear_object (&req); + + soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE)); +} + static void request_started (SoupSession *session, SoupMessage *msg, SoupSocket *socket) @@ -194,6 +230,14 @@ request_started (SoupSession *session, SoupMessage *msg, } } +static void +request_unqueued (SoupSession *session, SoupMessage *msg, + gpointer data) +{ + if (msg->status_code == SOUP_STATUS_CANCELLED) + cancelled_requests++; +} + static void do_basics_test (SoupURI *base_uri) { @@ -421,6 +465,86 @@ do_basics_test (SoupURI *base_uri) g_free (body5); } +static void +do_cancel_test (SoupURI *base_uri) +{ + SoupSession *session; + SoupCache *cache; + char *cache_dir; + char *body1, *body2; + + debug_printf (1, "Cache cancel tests\n"); + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + g_signal_connect (session, "request-unqueued", + G_CALLBACK (request_unqueued), NULL); + + debug_printf (2, " Initial requests\n"); + body1 = do_request (session, base_uri, "GET", "/1", + "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", + NULL); + body2 = do_request (session, base_uri, "GET", "/2", + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-Cache-Control", "must-revalidate", + NULL); + + /* Check that messages are correctly processed on cancellations. */ + debug_printf (1, " Cancel fresh resource with soup_session_message_cancel()\n"); + do_request_with_cancel (session, base_uri, "GET", "/1", SOUP_TEST_REQUEST_CANCEL_MESSAGE); + if (cancelled_requests != 1) { + debug_printf (1, " invalid number of cancelled requests: %d (1 expected)\n", + cancelled_requests); + errors++; + } + + debug_printf (1, " Cancel fresh resource with g_cancellable_cancel()\n"); + do_request_with_cancel (session, base_uri, "GET", "/1", SOUP_TEST_REQUEST_CANCEL_CANCELLABLE); + if (cancelled_requests != 1) { + debug_printf (1, " invalid number of cancelled requests: %d (1 expected)\n", + cancelled_requests); + errors++; + } + + soup_test_session_abort_unref (session); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + g_signal_connect (session, "request-unqueued", + G_CALLBACK (request_unqueued), NULL); + + /* Check that messages are correctly processed on cancellations. */ + debug_printf (1, " Cancel a revalidating resource with soup_session_message_cancel()\n"); + do_request_with_cancel (session, base_uri, "GET", "/2", SOUP_TEST_REQUEST_CANCEL_MESSAGE); + if (cancelled_requests != 2) { + debug_printf (1, " invalid number of cancelled requests: %d (2 expected)\n", + cancelled_requests); + errors++; + } + + debug_printf (1, " Cancel a revalidating resource with g_cancellable_cancel()\n"); + do_request_with_cancel (session, base_uri, "GET", "/2", SOUP_TEST_REQUEST_CANCEL_CANCELLABLE); + if (cancelled_requests != 2) { + debug_printf (1, " invalid number of cancelled requests: %d (2 expected)\n", + cancelled_requests); + errors++; + } + + soup_test_session_abort_unref (session); + + g_object_unref (cache); + g_free (cache_dir); + g_free (body1); + g_free (body2); +} + int main (int argc, char **argv) { @@ -435,6 +559,7 @@ main (int argc, char **argv) soup_uri_set_port (base_uri, soup_server_get_port (server)); do_basics_test (base_uri); + do_cancel_test (base_uri); soup_uri_free (base_uri); soup_test_server_quit_unref (server); -- cgit v1.2.1 From f0edc19af684c2073bdbfb59ae62c6812d6e5ee8 Mon Sep 17 00:00:00 2001 From: Anish A Date: Fri, 15 Feb 2013 10:30:05 +0400 Subject: Updated Malayalam Localization --- po/ml.po | 67 ++++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/po/ml.po b/po/ml.po index 4e38a46f..e698e1dc 100644 --- a/po/ml.po +++ b/po/ml.po @@ -1,22 +1,23 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# # Ani Peter , 2012. +# Anish A , 2013. msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." -"cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-15 21:43+0000\n" -"PO-Revision-Date: 2012-09-18 23:00+0000\n" -"Last-Translator: Ani Peter \n" -"Language-Team: Malayalam \n" -"Language: \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-12 09:33+0000\n" +"PO-Revision-Date: 2013-02-15 11:47+0530\n" +"Last-Translator: Anish A \n" +"Language-Team: Swatantra Malayalam Computing\n" +"Language: ml\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Lokalize 1.0\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -24,60 +25,80 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "കണക്ഷന്‍ അപ്രതീക്ഷതമായി അവസാനിയ്ക്കുന്നു" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "തെറ്റായ തെരച്ചില്‍ ആവശ്യം" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream ട്രക്കേറ്റ് ചെയ്യുവാന്‍ സാധ്യമല്ല" +#: ../libsoup/soup-cache-input-stream.c:77 +msgid "Network stream unexpectedly closed" +msgstr "ശൃംഖല സ്ട്രീം വിചാരിക്കാതെ അടച്ചു" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "ഔട്ട്പുട്ട് ബഫര്‍ വളരെ ചെറുതാണു്" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP മറുപടി പാഴ്സ് ചെയ്യുവാന്‍ സാധ്യമായില്ല" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP മറുപടിയുടെ രൂപം തിരിച്ചറിയാനായില്ല" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "പ്രക്രിയ റദ്ദാക്കിയിരിയ്ക്കുന്നു" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "പ്രക്രിയ തടസ്സപ്പെടുത്തുന്നു" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "HTTP മറുപടി പാഴ്സ് ചെയ്യുവാനായില്ല" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "യുആര്‍ഐ ലഭ്യമാക്കിയിട്ടില്ല" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "തെറ്റായ '%s' യുആര്‍ഐ: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4214 #, c-format msgid "Could not parse URI '%s'" msgstr "യുആര്‍ഐ '%s' പാഴ്സ് ചെയ്യുവാനായില്ല" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4251 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "പിന്തുണയില്ലാത്ത യുആര്‍ഐ സ്കീം '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4273 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI അല്ല" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "ഹോസ്റ്റ്നാമം ഒരു ഐപി വിലാസമാകുന്നു" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "തെറ്റായ ഹോസ്റ്റ്നാമം" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "ഹോസ്റ്റ്നാമത്തിനു് ബെയിസ് ഡൊമെയില്‍ ലഭ്യമല്ല" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "ആവശ്യമായ ഡൊമെയിനുകള്‍ ലഭ്യമല്ല" - -- cgit v1.2.1 From cf558c8514686851b8eea544a0b110c7d705ea9e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 26 Jan 2013 19:44:56 -0500 Subject: Internal renamings for clarity The GSocketClient::event signal gets proxied from GSocketClient to SoupSocket to SoupConnection to SoupSession to SoupMessage (!) via signal handlers that used to have "proxy" in their names. But that made it sound like they had something to do with network proxies. So rename them all (to "re_emit"). https://bugzilla.gnome.org/show_bug.cgi?id=680273 --- libsoup/soup-connection.c | 12 ++++++------ libsoup/soup-session.c | 12 ++++++------ libsoup/soup-socket.c | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 3dff7eca..a3322e39 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -437,10 +437,10 @@ set_current_msg (SoupConnection *conn, SoupMessage *msg) } static void -proxy_socket_event (SoupSocket *socket, - GSocketClientEvent event, - GIOStream *connection, - gpointer user_data) +re_emit_socket_event (SoupSocket *socket, + GSocketClientEvent event, + GIOStream *connection, + gpointer user_data) { SoupConnection *conn = user_data; @@ -548,7 +548,7 @@ connect_async_to_uri (SoupConnectionAsyncConnectData *data, SoupURI *uri) g_object_unref (remote_addr); data->event_id = g_signal_connect (priv->socket, "event", - G_CALLBACK (proxy_socket_event), + G_CALLBACK (re_emit_socket_event), data->conn); soup_socket_connect_async (priv->socket, data->cancellable, @@ -659,7 +659,7 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) g_object_unref (remote_addr); event_id = g_signal_connect (priv->socket, "event", - G_CALLBACK (proxy_socket_event), conn); + G_CALLBACK (re_emit_socket_event), conn); status = soup_socket_connect_sync (priv->socket, cancellable); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index ea0a16b9..009b6bed 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1152,10 +1152,10 @@ redirect_handler (SoupMessage *msg, gpointer user_data) } static void -proxy_connection_event (SoupConnection *conn, - GSocketClientEvent event, - GIOStream *connection, - gpointer user_data) +re_emit_connection_event (SoupConnection *conn, + GSocketClientEvent event, + GIOStream *connection, + gpointer user_data) { SoupMessageQueueItem *item = user_data; @@ -1168,7 +1168,7 @@ soup_session_set_item_connection (SoupSession *session, SoupConnection *conn) { if (item->conn) { - g_signal_handlers_disconnect_by_func (item->conn, proxy_connection_event, item); + g_signal_handlers_disconnect_by_func (item->conn, re_emit_connection_event, item); g_object_unref (item->conn); } @@ -1178,7 +1178,7 @@ soup_session_set_item_connection (SoupSession *session, if (item->conn) { g_object_ref (item->conn); g_signal_connect (item->conn, "event", - G_CALLBACK (proxy_connection_event), item); + G_CALLBACK (re_emit_connection_event), item); } } diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index df9a2109..885d5318 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -651,11 +651,11 @@ soup_socket_new (const char *optname1, ...) } static void -proxy_socket_client_event (GSocketClient *client, - GSocketClientEvent event, - GSocketConnectable *connectable, - GIOStream *connection, - gpointer user_data) +re_emit_socket_client_event (GSocketClient *client, + GSocketClientEvent event, + GSocketConnectable *connectable, + GIOStream *connection, + gpointer user_data) { SoupSocket *sock = user_data; @@ -704,7 +704,7 @@ new_socket_client (SoupSocket *sock) GSocketClient *client = g_socket_client_new (); g_signal_connect (client, "event", - G_CALLBACK (proxy_socket_client_event), sock); + G_CALLBACK (re_emit_socket_client_event), sock); if (priv->use_proxy) g_socket_client_add_application_proxy (client, "http"); else -- cgit v1.2.1 From ed6f1cdcd72e6e3e9076f5440977e45ed1911811 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 26 Jan 2013 20:06:50 -0500 Subject: SoupSession: remove some dead code, fix proxy error messages SoupMessageQueueItem's proxy_addr and proxy_uri fields were no longer being used, but they were still there, and SoupSession was trying to use item->proxy_uri to provide clarifying information on SOUP_STATUS_CANT_RESOLVE_PROXY / SOUP_STATUS_CANT_CONNECT_PROXY. Remove the unused fields, and fix SoupSession to get the proxy name from the SoupConnection instead. https://bugzilla.gnome.org/show_bug.cgi?id=680273 --- libsoup/soup-message-queue.c | 11 ----------- libsoup/soup-message-queue.h | 2 -- libsoup/soup-session.c | 33 ++++++++++++++------------------- 3 files changed, 14 insertions(+), 32 deletions(-) diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index ac00f163..c7661d8c 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -58,15 +58,6 @@ queue_message_restarted (SoupMessage *msg, gpointer user_data) { SoupMessageQueueItem *item = user_data; - if (item->proxy_addr) { - g_object_unref (item->proxy_addr); - item->proxy_addr = NULL; - } - if (item->proxy_uri) { - soup_uri_free (item->proxy_uri); - item->proxy_uri = NULL; - } - g_cancellable_reset (item->cancellable); } @@ -171,8 +162,6 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) g_object_unref (item->session); g_object_unref (item->msg); g_object_unref (item->cancellable); - g_clear_object (&item->proxy_addr); - g_clear_pointer (&item->proxy_uri, soup_uri_free); g_clear_object (&item->task); if (item->io_source) { g_source_destroy (item->io_source); diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index 490f9a29..848ecd02 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -38,8 +38,6 @@ struct _SoupMessageQueueItem { GMainContext *async_context; GCancellable *cancellable; - SoupAddress *proxy_addr; - SoupURI *proxy_uri; SoupConnection *conn; GTask *task; GSource *io_source; diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 009b6bed..ab13ca9e 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1451,45 +1451,40 @@ soup_session_set_item_status (SoupSession *session, SoupMessageQueueItem *item, guint status_code) { - SoupURI *uri; - char *msg; + SoupURI *uri = NULL; switch (status_code) { case SOUP_STATUS_CANT_RESOLVE: case SOUP_STATUS_CANT_CONNECT: uri = soup_message_get_uri (item->msg); - msg = g_strdup_printf ("%s (%s)", - soup_status_get_phrase (status_code), - uri->host); - soup_message_set_status_full (item->msg, status_code, msg); - g_free (msg); break; case SOUP_STATUS_CANT_RESOLVE_PROXY: case SOUP_STATUS_CANT_CONNECT_PROXY: - if (item->proxy_uri && item->proxy_uri->host) { - msg = g_strdup_printf ("%s (%s)", - soup_status_get_phrase (status_code), - item->proxy_uri->host); - soup_message_set_status_full (item->msg, status_code, msg); - g_free (msg); - break; - } - soup_message_set_status (item->msg, status_code); + if (item->conn) + uri = soup_connection_get_proxy_uri (item->conn); break; case SOUP_STATUS_SSL_FAILED: if (!g_tls_backend_supports_tls (g_tls_backend_get_default ())) { soup_message_set_status_full (item->msg, status_code, "TLS/SSL support not available; install glib-networking"); - } else - soup_message_set_status (item->msg, status_code); + return; + } break; default: - soup_message_set_status (item->msg, status_code); break; } + + if (uri && uri->host) { + char *msg = g_strdup_printf ("%s (%s)", + soup_status_get_phrase (status_code), + uri->host); + soup_message_set_status_full (item->msg, status_code, msg); + g_free (msg); + } else + soup_message_set_status (item->msg, status_code); } -- cgit v1.2.1 From f8f7454fc4b561cb896e6234e69da0102906089d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 16 Feb 2013 18:26:54 -0500 Subject: tests: simplify and improve "make check" Remove rules that automake can figure out itself. Run the tests in alphabetical order. Run "make kill-httpd" at the end of "make check", in case the last httpd-using test crashed. --- tests/Makefile.am | 120 ++++++++++++++---------------------------------------- 1 file changed, 31 insertions(+), 89 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 7af39755..6f0c5aee 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,93 +11,59 @@ LIBS = \ $(LIBGNUTLS_LIBS) \ $(GLIB_LIBS) -noinst_PROGRAMS = \ +tests = \ cache-test \ chunk-test \ coding-test \ connection-test \ context-test \ continue-test \ - cookies-test \ + cookies-test \ date \ - dns \ - forms-test \ - get \ - header-parsing \ + header-parsing \ misc-test \ multipart-test \ - ntlm-test-helper \ ntlm-test \ redirect-test \ requester-test \ resource-test \ session-test \ - simple-httpd \ - simple-proxy \ - sniffing-test \ + sniffing-test \ socket-test \ ssl-test \ streaming-test \ timeout-test \ tld-test \ - uri-parsing \ - $(CURL_TESTS) \ - $(APACHE_TESTS) \ - $(XMLRPC_TESTS) - -noinst_DATA = soup-tests.gresource - -TEST_SRCS = test-utils.c test-utils.h - -auth_test_SOURCES = auth-test.c $(TEST_SRCS) -cache_test_SOURCES = cache-test.c $(TEST_SRCS) -chunk_test_SOURCES = chunk-test.c $(TEST_SRCS) -coding_test_SOURCES = coding-test.c $(TEST_SRCS) -connection_test_SOURCES = connection-test.c $(TEST_SRCS) -context_test_SOURCES = context-test.c $(TEST_SRCS) -continue_test_SOURCES = continue-test.c $(TEST_SRCS) -cookies_test_SOURCES = cookies-test.c $(TEST_SRCS) -date_SOURCES = date.c $(TEST_SRCS) -dns_SOURCES = dns.c -forms_test_SOURCES = forms-test.c $(TEST_SRCS) -get_SOURCES = get.c -if BUILD_LIBSOUP_GNOME -get_LDADD = $(top_builddir)/libsoup/libsoup-gnome-2.4.la -endif -header_parsing_SOURCES = header-parsing.c $(TEST_SRCS) -multipart_test_SOURCES = multipart-test.c $(TEST_SRCS) -misc_test_SOURCES = misc-test.c $(TEST_SRCS) -ntlm_test_SOURCES = ntlm-test.c $(TEST_SRCS) -proxy_test_SOURCES = proxy-test.c $(TEST_SRCS) -pull_api_SOURCES = pull-api.c $(TEST_SRCS) -range_test_SOURCES = range-test.c $(TEST_SRCS) -redirect_test_SOURCES = redirect-test.c $(TEST_SRCS) -requester_test_SOURCES = requester-test.c $(TEST_SRCS) -resource_test_SOURCES = resource-test.c $(TEST_SRCS) -server_auth_test_SOURCES = server-auth-test.c $(TEST_SRCS) -session_test_SOURCES = session-test.c $(TEST_SRCS) -simple_httpd_SOURCES = simple-httpd.c -simple_proxy_SOURCES = simple-proxy.c -sniffing_test_SOURCES = sniffing-test.c $(TEST_SRCS) -socket_test_SOURCES = socket-test.c $(TEST_SRCS) -ssl_test_SOURCES = ssl-test.c $(TEST_SRCS) -streaming_test_SOURCES = streaming-test.c $(TEST_SRCS) -timeout_test_SOURCES = timeout-test.c $(TEST_SRCS) -tld_test_SOURCES = tld-test.c $(TEST_SRCS) -uri_parsing_SOURCES = uri-parsing.c $(TEST_SRCS) -xmlrpc_test_SOURCES = xmlrpc-test.c $(TEST_SRCS) -xmlrpc_server_test_SOURCES = xmlrpc-server-test.c $(TEST_SRCS) + uri-parsing if HAVE_APACHE -APACHE_TESTS = auth-test proxy-test pull-api range-test +tests += auth-test proxy-test pull-api range-test endif if HAVE_CURL -CURL_TESTS = forms-test server-auth-test +tests += forms-test server-auth-test endif if HAVE_XMLRPC_PHP -XMLRPC_TESTS = xmlrpc-test xmlrpc-server-test +tests += xmlrpc-test xmlrpc-server-test endif +noinst_PROGRAMS = \ + $(tests) \ + dns \ + get \ + ntlm-test-helper \ + simple-httpd \ + simple-proxy + +noinst_DATA = soup-tests.gresource + +noinst_LTLIBRARIES = libtest.la + +libtest_la_SOURCES = \ + test-utils.c \ + test-utils.h + +LDADD = libtest.la + if HAVE_APACHE if HAVE_APACHE_2_2 httpd_conf_in = httpd.conf.22.in @@ -120,33 +86,7 @@ endif soup-tests.gresource: soup-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< -TESTS = \ - cache-test \ - chunk-test \ - coding-test \ - connection-test \ - context-test \ - continue-test \ - cookies-test \ - date \ - header-parsing \ - misc-test \ - multipart-test \ - ntlm-test \ - redirect-test \ - requester-test \ - resource-test \ - session-test \ - sniffing-test \ - socket-test \ - ssl-test \ - streaming-test \ - timeout-test \ - tld-test \ - uri-parsing \ - $(APACHE_TESTS) \ - $(CURL_TESTS) \ - $(XMLRPC_TESTS) +TESTS = $(sort $(tests)) RESOURCES = \ resources/atom.xml \ @@ -176,12 +116,14 @@ EXTRA_DIST = \ DISTCLEANFILES = soup-tests.gresource httpd.conf +check-local: check-TESTS kill-httpd if MISSING_REGRESSION_TEST_PACKAGES -check-local: check-TESTS @echo "" @echo "NOTE: some tests were not run due to missing packages:" $(MISSING_REGRESSION_TEST_PACKAGES) @echo "" endif kill-httpd: - $(APACHE_HTTPD) -d `pwd` -f httpd.conf -k stop + @if [ -f httpd.pid ]; then \ + $(APACHE_HTTPD) -d `pwd` -f httpd.conf -k stop; \ + fi -- cgit v1.2.1 From 89a3db7081798ffe0cab1a8c3a173a6c0a61297c Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Fri, 15 Feb 2013 21:40:28 +0100 Subject: soup-cache-input-stream: fixed a reference cycle Fixed a reference cycle between SoupCacheInputStream and a GTask. This reference cycle was preventing the input stream from being freed when the SoupMessage was cancelled before the stream was completely read. Furthermore the SoupCache was not able to complete the pending request because the SoupCacheInputStream was not aware of the message cancellation and remained waiting forever. In order to remove the cycle soup_cache_input_stream_cache(_finish) were removed and the caching operation finalization is now reported via a signal. SoupCacheInputStream also implements close_fn which properly finalizes any pending caching operation. https://bugzilla.gnome.org/show_bug.cgi?id=682527 --- libsoup/soup-cache-input-stream.c | 121 ++++++++++++++++++++++---------------- libsoup/soup-cache-input-stream.h | 16 ++--- libsoup/soup-cache.c | 28 ++++----- 3 files changed, 87 insertions(+), 78 deletions(-) diff --git a/libsoup/soup-cache-input-stream.c b/libsoup/soup-cache-input-stream.c index a44652a8..7815cecc 100644 --- a/libsoup/soup-cache-input-stream.c +++ b/libsoup/soup-cache-input-stream.c @@ -9,6 +9,7 @@ #include #include "soup-cache-input-stream.h" +#include "soup-marshal.h" #include "soup-message-body.h" static void soup_cache_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); @@ -26,16 +27,23 @@ enum { LAST_PROP }; +enum { + CACHING_FINISHED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + struct _SoupCacheInputStreamPrivate { GOutputStream *output_stream; + GCancellable *cancellable; gsize bytes_written; gboolean read_finished; SoupBuffer *current_writing_buffer; GQueue *buffer_queue; - - GTask *task; }; static void soup_cache_input_stream_write_next_buffer (SoupCacheInputStream *istream); @@ -45,21 +53,10 @@ notify_and_clear (SoupCacheInputStream *istream, GError *error) { SoupCacheInputStreamPrivate *priv = istream->priv; - if (error) - g_task_return_error (priv->task, error); - else - g_task_return_int (priv->task, priv->bytes_written); + g_signal_emit (istream, signals[CACHING_FINISHED], 0, priv->bytes_written, error); + g_clear_object (&priv->cancellable); g_clear_object (&priv->output_stream); - g_clear_object (&priv->task); -} - -gsize -soup_cache_input_stream_cache_finish (SoupCacheInputStream *istream, - GAsyncResult *result, - GError **error) -{ - return g_task_propagate_int (G_TASK (result), error); } static inline void @@ -91,25 +88,11 @@ file_replaced_cb (GObject *source, priv->output_stream = (GOutputStream *) g_file_replace_finish (G_FILE (source), res, &error); if (error) - g_task_return_error (priv->task, error); + notify_and_clear (istream, error); else try_write_next_buffer (istream); -} - -void -soup_cache_input_stream_cache (SoupCacheInputStream *istream, - GFile *file, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - SoupCacheInputStreamPrivate *priv = istream->priv; - priv->task = g_task_new (istream, cancellable, callback, user_data); - - g_file_replace_async (file, NULL, FALSE, - G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, - G_PRIORITY_LOW, cancellable, file_replaced_cb, istream); + g_object_unref (istream); } static void @@ -157,23 +140,14 @@ soup_cache_input_stream_set_property (GObject *object, } } -static void -soup_cache_input_stream_dispose (GObject *object) -{ - SoupCacheInputStreamPrivate *priv = SOUP_CACHE_INPUT_STREAM (object)->priv; - - g_clear_object (&priv->output_stream); - g_clear_object (&priv->task); - - G_OBJECT_CLASS (soup_cache_input_stream_parent_class)->dispose (object); -} - static void soup_cache_input_stream_finalize (GObject *object) { SoupCacheInputStream *self = (SoupCacheInputStream *)object; SoupCacheInputStreamPrivate *priv = self->priv; + g_clear_object (&priv->cancellable); + g_clear_object (&priv->output_stream); g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); g_queue_free_full (priv->buffer_queue, (GDestroyNotify) soup_buffer_free); @@ -219,7 +193,6 @@ soup_cache_input_stream_write_next_buffer (SoupCacheInputStream *istream) int priority; g_assert (priv->output_stream && !g_output_stream_is_closed (priv->output_stream)); - g_assert (priv->task); g_clear_pointer (&priv->current_writing_buffer, soup_buffer_free); priv->current_writing_buffer = buffer; @@ -230,7 +203,7 @@ soup_cache_input_stream_write_next_buffer (SoupCacheInputStream *istream) priority = G_PRIORITY_LOW; g_output_stream_write_async (priv->output_stream, buffer->data, buffer->length, - priority, g_task_get_cancellable (priv->task), + priority, priv->cancellable, (GAsyncReadyCallback) write_ready_cb, g_object_ref (istream)); } @@ -252,7 +225,7 @@ read_internal (GInputStream *stream, nread = g_pollable_stream_read (base_stream, buffer, count, blocking, cancellable, error); - if (G_UNLIKELY (nread == -1 || priv->read_finished || !priv->task)) + if (G_UNLIKELY (nread == -1 || priv->read_finished)) return nread; if (nread == 0) { @@ -299,6 +272,33 @@ soup_cache_input_stream_pollable_init (GPollableInputStreamInterface *pollable_i pollable_interface->read_nonblocking = soup_cache_input_stream_read_nonblocking; } +static gboolean +soup_cache_input_stream_close_fn (GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (stream); + SoupCacheInputStreamPrivate *priv = istream->priv; + + if (!priv->read_finished) { + if (priv->output_stream) { + /* Cancel any pending write operation or return an error if none. */ + if (g_output_stream_has_pending (priv->output_stream)) + g_cancellable_cancel (priv->cancellable); + else { + GError *error = NULL; + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, + _("Failed to completely cache the resource")); + notify_and_clear (istream, error); + } + } else if (priv->cancellable) + /* The file_replace_async() hasn't finished yet */ + g_cancellable_cancel (priv->cancellable); + } + + return G_INPUT_STREAM_CLASS (soup_cache_input_stream_parent_class)->close_fn (stream, cancellable, error); +} + static void soup_cache_input_stream_class_init (SoupCacheInputStreamClass *klass) { @@ -309,10 +309,10 @@ soup_cache_input_stream_class_init (SoupCacheInputStreamClass *klass) gobject_class->get_property = soup_cache_input_stream_get_property; gobject_class->set_property = soup_cache_input_stream_set_property; - gobject_class->dispose = soup_cache_input_stream_dispose; gobject_class->finalize = soup_cache_input_stream_finalize; istream_class->read_fn = soup_cache_input_stream_read_fn; + istream_class->close_fn = soup_cache_input_stream_close_fn; g_object_class_install_property (gobject_class, PROP_OUTPUT_STREAM, g_param_spec_object ("output-stream", "Output stream", @@ -321,13 +321,32 @@ soup_cache_input_stream_class_init (SoupCacheInputStreamClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + signals[CACHING_FINISHED] = + g_signal_new ("caching-finished", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (SoupCacheInputStreamClass, caching_finished), + NULL, NULL, + _soup_marshal_NONE__INT_BOXED, + G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_ERROR); } GInputStream * -soup_cache_input_stream_new (GInputStream *base_stream) +soup_cache_input_stream_new (GInputStream *base_stream, + GFile *file) { - return g_object_new (SOUP_TYPE_CACHE_INPUT_STREAM, - "base-stream", base_stream, - "close-base-stream", FALSE, - NULL); + SoupCacheInputStream *istream = g_object_new (SOUP_TYPE_CACHE_INPUT_STREAM, + "base-stream", base_stream, + "close-base-stream", FALSE, + NULL); + + istream->priv->cancellable = g_cancellable_new (); + g_file_replace_async (file, NULL, FALSE, + G_FILE_CREATE_PRIVATE | G_FILE_CREATE_REPLACE_DESTINATION, + G_PRIORITY_DEFAULT, istream->priv->cancellable, + file_replaced_cb, g_object_ref (istream)); + + return (GInputStream *) istream; } diff --git a/libsoup/soup-cache-input-stream.h b/libsoup/soup-cache-input-stream.h index c999d102..92b1d7b6 100644 --- a/libsoup/soup-cache-input-stream.h +++ b/libsoup/soup-cache-input-stream.h @@ -24,6 +24,9 @@ typedef struct _SoupCacheInputStreamPrivate SoupCacheInputStreamPrivate; struct _SoupCacheInputStreamClass { SoupFilterInputStreamClass parent_class; + + /* signals */ + void (*caching_finished) (SoupCacheInputStream *istream, gsize bytes_written, GError *error); }; struct _SoupCacheInputStream @@ -35,17 +38,8 @@ struct _SoupCacheInputStream GType soup_cache_input_stream_get_type (void) G_GNUC_CONST; -GInputStream *soup_cache_input_stream_new (GInputStream *base_stream); - -void soup_cache_input_stream_cache (SoupCacheInputStream *istream, - GFile *file, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gsize soup_cache_input_stream_cache_finish (SoupCacheInputStream *istream, - GAsyncResult *result, - GError **error); +GInputStream *soup_cache_input_stream_new (GInputStream *base_stream, + GFile *file); G_END_DECLS diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 839cdc10..db74831b 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -749,21 +749,20 @@ typedef struct { } StreamHelper; static void -istream_cache_cb (GObject *source, - GAsyncResult *res, - gpointer user_data) +istream_caching_finished (SoupCacheInputStream *istream, + gsize bytes_written, + GError *error, + gpointer user_data) { - SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (source); StreamHelper *helper = (StreamHelper *) user_data; SoupCache *cache = helper->cache; SoupCacheEntry *entry = helper->entry; - GError *error = NULL; - entry->dirty = FALSE; - g_clear_object (&entry->cancellable); --cache->priv->n_pending; - entry->length = soup_cache_input_stream_cache_finish (istream, res, &error); + entry->dirty = FALSE; + entry->length = bytes_written; + g_clear_object (&entry->cancellable); if (error) { /* Update cache size */ @@ -791,7 +790,6 @@ istream_cache_cb (GObject *source, g_slice_free (StreamHelper, helper); } - static GInputStream* soup_cache_content_processor_wrap_input (SoupContentProcessor *processor, GInputStream *base_stream, @@ -853,21 +851,19 @@ soup_cache_content_processor_wrap_input (SoupContentProcessor *processor, return NULL; } - ++cache->priv->n_pending; - - istream = soup_cache_input_stream_new (base_stream); - - file = get_file_from_entry (cache, entry); entry->cancellable = g_cancellable_new (); + ++cache->priv->n_pending; helper = g_slice_new (StreamHelper); helper->cache = g_object_ref (cache); helper->entry = entry; - soup_cache_input_stream_cache (SOUP_CACHE_INPUT_STREAM (istream), file, entry->cancellable, - (GAsyncReadyCallback) istream_cache_cb, helper); + file = get_file_from_entry (cache, entry); + istream = soup_cache_input_stream_new (base_stream, file); g_object_unref (file); + g_signal_connect (istream, "caching-finished", G_CALLBACK (istream_caching_finished), helper); + return istream; } -- cgit v1.2.1 From 3f294a7b6661df7d8dfad3dff175f8807b257c44 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Fri, 15 Feb 2013 21:15:08 +0100 Subject: test-utils: Added SOUP_TEST_REQUEST_CANCEL_IMMEDIATE flag We were assuming that if the SOUP_TEST_REQUEST_CANCEL_SOON flag was not present then we wanted an immediate cancelation. That worked but now we need to add it to support more cancellation types. https://bugzilla.gnome.org/show_bug.cgi?id=682527 --- tests/cache-test.c | 13 +++++++++---- tests/misc-test.c | 2 +- tests/test-utils.c | 3 ++- tests/test-utils.h | 3 ++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/cache-test.c b/tests/cache-test.c index ed8ca453..9469dc12 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -472,6 +472,7 @@ do_cancel_test (SoupURI *base_uri) SoupCache *cache; char *cache_dir; char *body1, *body2; + guint flags; debug_printf (1, "Cache cancel tests\n"); @@ -496,7 +497,8 @@ do_cancel_test (SoupURI *base_uri) /* Check that messages are correctly processed on cancellations. */ debug_printf (1, " Cancel fresh resource with soup_session_message_cancel()\n"); - do_request_with_cancel (session, base_uri, "GET", "/1", SOUP_TEST_REQUEST_CANCEL_MESSAGE); + flags = SOUP_TEST_REQUEST_CANCEL_MESSAGE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + do_request_with_cancel (session, base_uri, "GET", "/1", flags); if (cancelled_requests != 1) { debug_printf (1, " invalid number of cancelled requests: %d (1 expected)\n", cancelled_requests); @@ -504,7 +506,8 @@ do_cancel_test (SoupURI *base_uri) } debug_printf (1, " Cancel fresh resource with g_cancellable_cancel()\n"); - do_request_with_cancel (session, base_uri, "GET", "/1", SOUP_TEST_REQUEST_CANCEL_CANCELLABLE); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + do_request_with_cancel (session, base_uri, "GET", "/1", flags); if (cancelled_requests != 1) { debug_printf (1, " invalid number of cancelled requests: %d (1 expected)\n", cancelled_requests); @@ -522,7 +525,8 @@ do_cancel_test (SoupURI *base_uri) /* Check that messages are correctly processed on cancellations. */ debug_printf (1, " Cancel a revalidating resource with soup_session_message_cancel()\n"); - do_request_with_cancel (session, base_uri, "GET", "/2", SOUP_TEST_REQUEST_CANCEL_MESSAGE); + flags = SOUP_TEST_REQUEST_CANCEL_MESSAGE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + do_request_with_cancel (session, base_uri, "GET", "/2", flags); if (cancelled_requests != 2) { debug_printf (1, " invalid number of cancelled requests: %d (2 expected)\n", cancelled_requests); @@ -530,7 +534,8 @@ do_cancel_test (SoupURI *base_uri) } debug_printf (1, " Cancel a revalidating resource with g_cancellable_cancel()\n"); - do_request_with_cancel (session, base_uri, "GET", "/2", SOUP_TEST_REQUEST_CANCEL_CANCELLABLE); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; + do_request_with_cancel (session, base_uri, "GET", "/2", flags); if (cancelled_requests != 2) { debug_printf (1, " invalid number of cancelled requests: %d (2 expected)\n", cancelled_requests); diff --git a/tests/misc-test.c b/tests/misc-test.c index d434e9bd..c0701f3d 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -941,7 +941,7 @@ do_cancel_while_reading_req_test (void) guint flags; debug_printf (1, "\nCancelling (immediately) message while reading response (request api)\n"); - flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE; + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, diff --git a/tests/test-utils.c b/tests/test-utils.c index cc9aa8e1..754b84a9 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -459,7 +459,8 @@ soup_test_request_send (SoupRequest *req, } data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); - if (cancel_data) { + if (cancel_data && + (flags & SOUP_TEST_REQUEST_CANCEL_SOON || flags & SOUP_TEST_REQUEST_CANCEL_IMMEDIATE)) { guint interval = flags & SOUP_TEST_REQUEST_CANCEL_SOON ? 100 : 0; g_timeout_add_full (G_PRIORITY_HIGH, interval, cancel_request_timeout, cancel_data, NULL); } diff --git a/tests/test-utils.h b/tests/test-utils.h index 22a4a163..e7782ee4 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -27,7 +27,8 @@ typedef enum { SOUP_TEST_REQUEST_NONE = 0, SOUP_TEST_REQUEST_CANCEL_MESSAGE = (1 << 0), SOUP_TEST_REQUEST_CANCEL_CANCELLABLE = (1 << 1), - SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2) + SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2), + SOUP_TEST_REQUEST_CANCEL_IMMEDIATE = (1 << 3) } SoupTestRequestFlags; SoupSession *soup_test_session_new (GType type, ...); -- cgit v1.2.1 From 054b1e3059f5b9b677d2117ecc3130fa6cd79f1a Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Fri, 15 Feb 2013 21:40:37 +0100 Subject: cache-test: added a new cancellation test Added do_refcounting_test that checks that streams do not leak any reference when a message is cancelled just before starting to read. This test also need a new cancel flag called SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH. https://bugzilla.gnome.org/show_bug.cgi?id=682527 --- tests/cache-test.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/test-utils.c | 10 +++++++++ tests/test-utils.h | 3 ++- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/tests/cache-test.c b/tests/cache-test.c index 9469dc12..d9400fe5 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -550,6 +550,66 @@ do_cancel_test (SoupURI *base_uri) g_free (body2); } +static void +do_refcounting_test (SoupURI *base_uri) +{ + SoupSession *session; + SoupCache *cache; + char *cache_dir; + SoupRequestHTTP *req; + GInputStream *stream, *base_stream; + SoupURI *uri; + GError *error = NULL; + guint flags; + + debug_printf (1, "Cache refcounting tests\n"); + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + + last_request_validated = last_request_hit_network = FALSE; + cancelled_requests = 0; + + uri = soup_uri_new_with_base (base_uri, "/1"); + req = soup_session_request_http_uri (session, "GET", uri, NULL); + soup_uri_free (uri); + + flags = SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH | SOUP_TEST_REQUEST_CANCEL_MESSAGE; + stream = soup_test_request_send (SOUP_REQUEST (req), NULL, flags, &error); + if (!stream) { + debug_printf (1, " could not send request: %s\n", + error->message); + g_error_free (error); + g_object_unref (req); + return; + } + + base_stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream)); + g_object_add_weak_pointer (G_OBJECT (base_stream), (gpointer *)&base_stream); + + g_clear_object (&req); + g_object_unref (stream); + + debug_printf (1, " Checking that the base stream is properly unref'ed\n"); + if (base_stream) { + errors++; + debug_printf (1, "leaked GInputStream!\n"); + g_object_remove_weak_pointer (G_OBJECT (base_stream), (gpointer *)&base_stream); + } + + soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE)); + + soup_test_session_abort_unref (session); + + g_object_unref (cache); + g_free (cache_dir); +} + int main (int argc, char **argv) { @@ -565,6 +625,7 @@ main (int argc, char **argv) do_basics_test (base_uri); do_cancel_test (base_uri); + do_refcounting_test (base_uri); soup_uri_free (base_uri); soup_test_server_quit_unref (server); diff --git a/tests/test-utils.c b/tests/test-utils.c index 754b84a9..a2c24cfc 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -469,6 +469,16 @@ soup_test_request_send (SoupRequest *req, stream = soup_request_send_finish (req, data.result, error); + if (cancel_data && (flags & SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH)) { + GMainContext *context; + + cancel_message_or_cancellable (cancel_data); + + context = g_main_loop_get_context (data.loop); + while (g_main_context_pending (context)) + g_main_context_iteration (context, FALSE); + } + g_main_loop_unref (data.loop); g_object_unref (data.result); diff --git a/tests/test-utils.h b/tests/test-utils.h index e7782ee4..b7b21951 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -28,7 +28,8 @@ typedef enum { SOUP_TEST_REQUEST_CANCEL_MESSAGE = (1 << 0), SOUP_TEST_REQUEST_CANCEL_CANCELLABLE = (1 << 1), SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2), - SOUP_TEST_REQUEST_CANCEL_IMMEDIATE = (1 << 3) + SOUP_TEST_REQUEST_CANCEL_IMMEDIATE = (1 << 3), + SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH = (1 << 4), } SoupTestRequestFlags; SoupSession *soup_test_session_new (GType type, ...); -- cgit v1.2.1 From e97979210822acdb900e2f3bc5ece1f8294e8f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Dr=C4=85g?= Date: Mon, 18 Feb 2013 16:17:37 +0100 Subject: Updated Polish translation --- po/pl.po | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/po/pl.po b/po/pl.po index 15e5701a..be2b5bfe 100644 --- a/po/pl.po +++ b/po/pl.po @@ -4,14 +4,14 @@ # pomóc w jego rozwijaniu i pielęgnowaniu, napisz do nas: # gnomepl@aviary.pl # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -# Piotr Drąg , 2012. -# Aviary.pl , 2012. +# Piotr Drąg , 2012-2013. +# Aviary.pl , 2012-2013. msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-12-23 04:28+0100\n" -"PO-Revision-Date: 2012-12-23 04:29+0100\n" +"POT-Creation-Date: 2013-02-18 16:13+0100\n" +"PO-Revision-Date: 2013-02-18 16:14+0100\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" "Language: pl\n" @@ -29,18 +29,22 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Połączenie zostało nieoczekiwanie zakończone" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Nieprawidłowe żądanie przewinięcia" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Nie można skrócić SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Strumień sieciowy został nieoczekiwanie zamknięty" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Całkowite umieszczenie zasobu w pamięci podręcznej się nie powiodło" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -66,43 +70,43 @@ msgstr "Działanie spowodowałoby zablokowanie" msgid "Could not parse HTTP request" msgstr "Nie można przetworzyć żądania HTTP" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Nie podano adresu URI" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Nieprawidłowy adres URI \"%s\": %s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Nie można przetworzyć adresu URI \"%s\"" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nieobsługiwany schemat adresu URI \"%s\"" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" msgstr "Nie jest adresem URI protokołu HTTP" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Nazwa komputera jest adresem IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Nieprawidłowa nazwa komputera" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Nazwa komputera nie posiada podstawowej domeny" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Brak wystarczającej liczby domen" -- cgit v1.2.1 From 2c327266a6ccf1417a1b723562a4850756545870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B8=D1=80=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=9D?= =?UTF-8?q?=D0=B8=D0=BA=D0=BE=D0=BB=D0=B8=D1=9B?= Date: Mon, 18 Feb 2013 20:14:22 +0100 Subject: Updated Serbian translation --- po/sr.po | 34 ++++++++++++++++++---------------- po/sr@latin.po | 34 ++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/po/sr.po b/po/sr.po index c5765c36..885af1d3 100644 --- a/po/sr.po +++ b/po/sr.po @@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" "p&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-18 15:49+0000\n" -"PO-Revision-Date: 2013-01-17 09:46+0200\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-02-18 20:11+0200\n" "Last-Translator: Мирослав Николић \n" "Language-Team: Serbian \n" "Language: sr\n" @@ -25,25 +25,28 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Веза је неочекивано затворена" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Неисправан захтев претраге" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Не могу да скратим улазни ток тела Супе" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Мрежни ток је изненадно затворен" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Нисам успео у потпуности да сместим извориште у оставу " + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Међумеморија излаза је премала" #: ../libsoup/soup-message-client-io.c:41 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" msgstr "Не могу да обрадим ХТТП одговор" @@ -60,47 +63,46 @@ msgid "Operation would block" msgstr "Поступак би блокирао" #: ../libsoup/soup-message-server-io.c:40 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" msgstr "Не могу да обрадим ХТТП захтев" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Није наведена адреса" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Неисправна „%s“ адреса: %s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Не могу да обрадим адресу „%s“" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Неподржана „%s“ шема адресе" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" msgstr "Није ХТТП путања" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Назив домаћина је ИП адреса" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Неисправан назив домаћина" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Назив домаћина нема основни домен" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Нема довољно домена" diff --git a/po/sr@latin.po b/po/sr@latin.po index 6e83f358..04d8dc0b 100644 --- a/po/sr@latin.po +++ b/po/sr@latin.po @@ -7,8 +7,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" "p&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-18 15:49+0000\n" -"PO-Revision-Date: 2013-01-17 09:46+0200\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-02-18 20:11+0200\n" "Last-Translator: Miroslav Nikolić \n" "Language-Team: Serbian \n" "Language: sr\n" @@ -25,25 +25,28 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Veza je neočekivano zatvorena" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Neispravan zahtev pretrage" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Ne mogu da skratim ulazni tok tela Supe" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Mrežni tok je iznenadno zatvoren" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Nisam uspeo u potpunosti da smestim izvorište u ostavu " + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Međumemorija izlaza je premala" #: ../libsoup/soup-message-client-io.c:41 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" msgstr "Ne mogu da obradim HTTP odgovor" @@ -60,47 +63,46 @@ msgid "Operation would block" msgstr "Postupak bi blokirao" #: ../libsoup/soup-message-server-io.c:40 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" msgstr "Ne mogu da obradim HTTP zahtev" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Nije navedena adresa" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Neispravna „%s“ adresa: %s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Ne mogu da obradim adresu „%s“" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nepodržana „%s“ šema adrese" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" msgstr "Nije HTTP putanja" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Naziv domaćina je IP adresa" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Neispravan naziv domaćina" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Naziv domaćina nema osnovni domen" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Nema dovoljno domena" -- cgit v1.2.1 From 351cbb0cfc773d371fd667183317d6041089dcc9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 18 Feb 2013 18:25:25 -0500 Subject: 2.41.90 --- NEWS | 30 ++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 9d19e375..5b0e5e50 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,33 @@ +Changes in libsoup from 2.41.5 to 2.41.90: + + * Added SoupSession:local-address property, which allows you + to force connections to bind to a particular local address + (eg, to control the interface that is used). [#693215, Jonh + Wendell] + + * Fixed SoupCache to properly handle messages that get + cancelled, and added tests for this. [#692310, Sergio] + + * Fixed a reference leak in SoupCache that resulted in + epiphany hanging for several seconds on exit and then + eventually printing "Cache flush finished despite X pending + requests". And added more tests. [#682527, Sergio] + + * Fixed SoupAuthNTLM so that SoupSession:authenticate gets + emitted with retrying=TRUE if the first attempt fails (ie, + make it work the same way as SoupAuthBasic and + SoupAuthDigest). [#693222, Dan] + + * Fixed the SoupSession:add-feature-by-type property to accept + non-SoupSessionFeature features as well (eg, auth types) + [Dan] + + * Fixed a build bug that would break all the apache-based + tests if you didn't have PHP installed. [#693311, Dan] + + * Updated translations: + Malayalam, Polish, Serbian, Slovak + Changes in libsoup from 2.41.4 to 2.41.5: * Reverted the change to SoupURI's password handling from diff --git a/configure.ac b/configure.ac index 79026a57..1b120812 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [5]) +m4_define([soup_micro_version], [90]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 85e9739bea1fd3b66f28866a690def2f062a7f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20=C4=8Cernock=C3=BD?= Date: Tue, 19 Feb 2013 11:23:40 +0100 Subject: Updated Czech translation --- po/cs.po | 61 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 17 deletions(-) diff --git a/po/cs.po b/po/cs.po index ff495e02..3deeec02 100644 --- a/po/cs.po +++ b/po/cs.po @@ -1,16 +1,15 @@ # Czech translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# -# Marek Černocký , 2012. +# Marek Černocký , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-09 00:53+0000\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-02-19 11:21+0100\n" "Last-Translator: Marek Černocký \n" "Language-Team: Czech \n" "Language: cs\n" @@ -18,6 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Gtranslator 2.91.6\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -25,59 +25,86 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Připojení bylo neočekávaně ukončeno" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Neplatný požadavek na posun" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Nelze zkrátit SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Síťový proud byl neočekávaně uzavřen" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Selhalo úplné uložení prostředku do mezipaměti" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Výstupní vyrovnávací paměť je příliš malá" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Nelze zpracovat odpověď HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Nerozpoznáno kódování odpovědi HTTP" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Operace byla zrušena" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Operace by blokovala" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Nelze zpracovat požadavek HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Není poskytnuta žádná adresa URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Neplatná adresa URI „%s“: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" -msgstr "Nelze analyzovat adresu URI „%s“" +msgstr "Nelze zpracovat adresu URI „%s“" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nepodporované schéma URI „%s“" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nejedná se o adresu HTTP URI" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Název počítače je adresa IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Neplatný název počítače" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Název počítače nemá základní doménu" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Nedostatek domén" -- cgit v1.2.1 From 1421b1a2364787b493734618abebe45f4f4bc55d Mon Sep 17 00:00:00 2001 From: Daniel Mustieles Date: Tue, 19 Feb 2013 12:43:10 +0100 Subject: Updated Spanish translation --- po/es.po | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/po/es.po b/po/es.po index c505a424..8cac889c 100644 --- a/po/es.po +++ b/po/es.po @@ -2,15 +2,15 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# Daniel Mustieles , 2012. +# Daniel Mustieles , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-18 15:49+0000\n" -"PO-Revision-Date: 2012-12-20 11:07+0100\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-02-19 12:33+0100\n" "Last-Translator: Daniel Mustieles \n" "Language-Team: Español \n" "Language: \n" @@ -26,18 +26,22 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "La conexión terminó inesperadamente" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Petición de búsqueda no válida" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "No se puede truncar SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "El flujo de red se cerró inesperadamente" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Falló al cachear completamente el recurso" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -63,43 +67,43 @@ msgstr "La operación se bloqueará" msgid "Could not parse HTTP request" msgstr "No se pudo analizar la solicitud HTTP" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "No se ha proporcionado un URI" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI «%s» no válida: %s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "No se pudo analizar el URI «%s»" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Esquema %s de URI no soportado" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" msgstr "No es un URI HTTP" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "El nombre del equipo es una dirección IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "El nombre del equipo no es válido" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "El nombre del equipo no tiene un dominio base" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "No hay suficientes dominios" -- cgit v1.2.1 From 118062681c732e57fc2851cd21c34cab2579c9f4 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Tue, 19 Feb 2013 15:44:17 +0100 Subject: soup-session.c: do not emit content-sniffed if it isn't cached The SoupCache does not get any information from sniffed content types as it works at a lower level. That's why sometimes we might not have any Content-Type information for a cached resource (if the server does not specify it). --- libsoup/soup-session.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index ab13ca9e..b0fc1d50 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3764,13 +3764,15 @@ async_return_from_cache (SoupMessageQueueItem *item, GInputStream *stream) { const char *content_type; - GHashTable *params; + GHashTable *params = NULL; soup_message_got_headers (item->msg); content_type = soup_message_headers_get_content_type (item->msg->response_headers, ¶ms); - soup_message_content_sniffed (item->msg, content_type, params); - g_hash_table_unref (params); + if (content_type) { + soup_message_content_sniffed (item->msg, content_type, params); + g_hash_table_unref (params); + } item->state = SOUP_MESSAGE_FINISHING; async_send_request_return_result (item, g_object_ref (stream), NULL); -- cgit v1.2.1 From 3fd71aca10bddab2da282737e4a26ee0c53e4dec Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 19 Feb 2013 10:34:22 -0500 Subject: tests: fix under automake 1.13 The parallel test harness (which is the default as of automake 1.13) doesn't let you use make functions in the definition of TESTS. (It generates an invalid Makefile in this case.) Since the tests as currently written won't work with the parallel harness anyway (since each apache-based test stops apache when it's done), just force the serial harness for now. https://bugzilla.gnome.org/show_bug.cgi?id=694135 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1b120812..781361a5 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[ht AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz -Wno-portability]) +AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz -Wno-portability serial-tests]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) AC_PROG_MAKE_SET -- cgit v1.2.1 From af5cf439d3f08f969f1b3211b5da93bf377bf00f Mon Sep 17 00:00:00 2001 From: Daniel Martinez Date: Tue, 19 Feb 2013 23:17:42 +0100 Subject: Added Aragonese translation --- po/LINGUAS | 1 + po/an.po | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 po/an.po diff --git a/po/LINGUAS b/po/LINGUAS index 637036f6..f0333dae 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1,3 +1,4 @@ +an as be bg diff --git a/po/an.po b/po/an.po new file mode 100644 index 00000000..5d207a9a --- /dev/null +++ b/po/an.po @@ -0,0 +1,108 @@ +# Aragonese translation for libsoup. +# Copyright (C) 2013 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-19 15:37+0000\n" +"PO-Revision-Date: 2013-02-19 23:17+0100\n" +"Last-Translator: Daniel Martinez \n" +"Language-Team: Aragonese \n" +"Language: an\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 +#: ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "A connexión remató inasperadament" + +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "Petición de búsqueda no válida" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "No se puede truncar SoupBodyInputStream" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "O fluxo de ret se zarró inasperadament" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Falló en cachear completament o recurso" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "O búfer de salida ye masiau chicot" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "No se podió analisar a respuesta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificación d'a respuesta HTTP no reconoixida" + +#: ../libsoup/soup-message-io.c:846 +#: ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "Se canceló a operación" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "A operación se blocará" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "No se podió analisar a solicitut HTTP" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "No s'ha proporcionau un URI" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "URI '%s' no válida: %s" + +#: ../libsoup/soup-session.c:4211 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "No se podió analisar l'URI «%s»" + +#: ../libsoup/soup-session.c:4248 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Esquema %s d'URI no suportau" + +#: ../libsoup/soup-session.c:4270 +#, c-format +msgid "Not an HTTP URI" +msgstr "No ye un URI HTTP" + +#: ../libsoup/soup-tld.c:185 +msgid "Hostname is an IP address" +msgstr "O nombre de l'equipo ye una adreza IP" + +#: ../libsoup/soup-tld.c:206 +msgid "Invalid hostname" +msgstr "O nombre de l'equipo no ye válido" + +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "O nombre de l'equipo no tiene un dominio base" + +#: ../libsoup/soup-tld.c:257 +msgid "Not enough domains" +msgstr "No i hai suficients dominios" + -- cgit v1.2.1 From 98144c40bd5614237d23a95d068b8036af7af9ef Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 19 Feb 2013 19:02:59 -0500 Subject: tests: [CENSORED] [CENSORED] automake [CENSORED] Specifying serial-tests in AM_INIT_AUTOMAKE breaks the build with automake 1.11, so the only way to support both 1.11 and 1.13 is to make the tests work under the parallel harness. Fortunately this wasn't that hard. --- .gitignore | 3 +++ configure.ac | 2 +- tests/Makefile.am | 29 +++++++++++++++++++++-------- tests/test-utils.c | 3 +++ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 9fbae76f..19686f4d 100644 --- a/.gitignore +++ b/.gitignore @@ -63,6 +63,9 @@ po/Makefile.in.in po/POTFILES po/stamp-it stamp-h1 +test-driver +tests/*.log +tests/*.trs tests/*-test tests/date tests/dns diff --git a/configure.ac b/configure.ac index 781361a5..1b120812 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[ht AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz -Wno-portability serial-tests]) +AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz -Wno-portability]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) AC_PROG_MAKE_SET diff --git a/tests/Makefile.am b/tests/Makefile.am index 6f0c5aee..57ec0f4b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,7 +11,7 @@ LIBS = \ $(LIBGNUTLS_LIBS) \ $(GLIB_LIBS) -tests = \ +TESTS = \ cache-test \ chunk-test \ coding-test \ @@ -37,17 +37,17 @@ tests = \ uri-parsing if HAVE_APACHE -tests += auth-test proxy-test pull-api range-test +TESTS += auth-test proxy-test pull-api range-test endif if HAVE_CURL -tests += forms-test server-auth-test +TESTS += forms-test server-auth-test endif if HAVE_XMLRPC_PHP -tests += xmlrpc-test xmlrpc-server-test +TESTS += xmlrpc-test xmlrpc-server-test endif noinst_PROGRAMS = \ - $(tests) \ + $(TESTS) \ dns \ get \ ntlm-test-helper \ @@ -86,8 +86,6 @@ endif soup-tests.gresource: soup-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< -TESTS = $(sort $(tests)) - RESOURCES = \ resources/atom.xml \ resources/home.gif \ @@ -116,14 +114,29 @@ EXTRA_DIST = \ DISTCLEANFILES = soup-tests.gresource httpd.conf -check-local: check-TESTS kill-httpd +TESTS_ENVIRONMENT = \ + SOUP_TESTS_IN_MAKE_CHECK=1 + +check: start-httpd + +check-local: check-TESTS + @$(MAKE) kill-httpd if MISSING_REGRESSION_TEST_PACKAGES @echo "" @echo "NOTE: some tests were not run due to missing packages:" $(MISSING_REGRESSION_TEST_PACKAGES) @echo "" endif +.PHONY: start-httpd kill-httpd + +start-httpd: +if HAVE_APACHE + @$(APACHE_HTTPD) -d `pwd` -f httpd.conf -k start; +endif + kill-httpd: +if HAVE_APACHE @if [ -f httpd.pid ]; then \ $(APACHE_HTTPD) -d `pwd` -f httpd.conf -k stop; \ fi +endif diff --git a/tests/test-utils.c b/tests/test-utils.c index a2c24cfc..8e0fb257 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -187,6 +187,9 @@ apache_cmd (const char *cmd) void apache_init (void) { + if (g_getenv ("SOUP_TESTS_IN_MAKE_CHECK")) + return; + if (!apache_cmd ("start")) { g_printerr ("Could not start apache\n"); exit (1); -- cgit v1.2.1 From 3af28bc8e78a7f281b68c36ffe515b5c8a17e507 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 19 Feb 2013 19:21:35 -0500 Subject: tests: do skipped tests properly automake interprets exit code 77 as meaning "skipped", so have the various apache-dependent, php-dependent, and curl-dependent tests do that, and compile them unconditionally. (Although, to avoid "unused" warnings, we end up #ifdeffing out the whole file.) --- configure.ac | 14 +++++----- tests/Makefile.am | 66 ++++++++++++++++++++++------------------------ tests/auth-test.c | 12 +++++++++ tests/forms-test.c | 12 +++++++++ tests/proxy-test.c | 12 +++++++++ tests/pull-api.c | 12 +++++++++ tests/range-test.c | 12 +++++++++ tests/server-auth-test.c | 12 +++++++++ tests/xmlrpc-server-test.c | 12 +++++++++ tests/xmlrpc-test.c | 12 +++++++++ 10 files changed, 134 insertions(+), 42 deletions(-) diff --git a/configure.ac b/configure.ac index 1b120812..d6c97ee4 100644 --- a/configure.ac +++ b/configure.ac @@ -288,29 +288,27 @@ if test "$have_apache" = 1; then MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES php5" fi AC_MSG_RESULT($have_php) + AC_SUBST(IF_HAVE_PHP) if test "$have_php" = yes; then - AC_MSG_CHECKING([for xmlrpc-php]) + AC_MSG_CHECKING([for php-xmlrpc]) if $PHP --rf xmlrpc_server_create | grep -q "does not exist"; then - have_xmlrpc_php=no + have_php_xmlrpc=no MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES php-xmlrpc" else - have_xmlrpc_php=yes + have_php_xmlrpc=yes + AC_DEFINE(HAVE_PHP_XMLRPC, 1, [Have php-xmlrpc]) fi - AC_MSG_RESULT($have_xmlrpc_php) + AC_MSG_RESULT($have_php_xmlrpc) fi fi -AC_SUBST(IF_HAVE_PHP) -AM_CONDITIONAL(HAVE_XMLRPC_PHP, test "$have_xmlrpc_php" = yes) - AC_PATH_PROG(CURL, curl, no) if test "$CURL" != no; then AC_DEFINE(HAVE_CURL, 1, [Whether or not curl can be used for tests]) else MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES curl" fi -AM_CONDITIONAL(HAVE_CURL, test "$CURL" != no) GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0` AC_SUBST(GLIB_COMPILE_RESOURCES) diff --git a/tests/Makefile.am b/tests/Makefile.am index 57ec0f4b..55dd3273 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,40 +11,38 @@ LIBS = \ $(LIBGNUTLS_LIBS) \ $(GLIB_LIBS) -TESTS = \ - cache-test \ - chunk-test \ - coding-test \ - connection-test \ - context-test \ - continue-test \ - cookies-test \ - date \ - header-parsing \ - misc-test \ - multipart-test \ - ntlm-test \ - redirect-test \ - requester-test \ - resource-test \ - session-test \ - sniffing-test \ - socket-test \ - ssl-test \ - streaming-test \ - timeout-test \ - tld-test \ - uri-parsing - -if HAVE_APACHE -TESTS += auth-test proxy-test pull-api range-test -endif -if HAVE_CURL -TESTS += forms-test server-auth-test -endif -if HAVE_XMLRPC_PHP -TESTS += xmlrpc-test xmlrpc-server-test -endif +TESTS = \ + auth-test \ + cache-test \ + chunk-test \ + coding-test \ + connection-test \ + context-test \ + continue-test \ + cookies-test \ + date \ + forms-test \ + header-parsing \ + misc-test \ + multipart-test \ + ntlm-test \ + proxy-test \ + pull-api \ + range-test \ + redirect-test \ + requester-test \ + resource-test \ + session-test \ + server-auth-test \ + sniffing-test \ + socket-test \ + ssl-test \ + streaming-test \ + timeout-test \ + tld-test \ + uri-parsing \ + xmlrpc-server-test \ + xmlrpc-test noinst_PROGRAMS = \ $(TESTS) \ diff --git a/tests/auth-test.c b/tests/auth-test.c index 334033b3..2c443d63 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -2,6 +2,8 @@ #include "test-utils.h" +#ifdef HAVE_APACHE + static GMainLoop *loop; typedef struct { @@ -1201,3 +1203,13 @@ main (int argc, char **argv) test_cleanup (); return errors != 0; } + +#else /* HAVE_APACHE */ + +int +main (int argc, char **argv) +{ + return 77; /* SKIP */ +} + +#endif diff --git a/tests/forms-test.c b/tests/forms-test.c index 1d254b12..3b6e5c16 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -5,6 +5,8 @@ #include "test-utils.h" +#ifdef HAVE_CURL + static struct { const char *title, *name; const char *result; @@ -451,3 +453,13 @@ main (int argc, char **argv) test_cleanup (); return errors != 0; } + +#else /* HAVE_CURL */ + +int +main (int argc, char **argv) +{ + return 77; /* SKIP */ +} + +#endif diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 1ac38557..075289dc 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -2,6 +2,8 @@ #include "test-utils.h" +#ifdef HAVE_APACHE + typedef struct { const char *explanation; const char *url; @@ -394,3 +396,13 @@ main (int argc, char **argv) test_cleanup (); return errors != 0; } + +#else /* HAVE_APACHE */ + +int +main (int argc, char **argv) +{ + return 77; /* SKIP */ +} + +#endif diff --git a/tests/pull-api.c b/tests/pull-api.c index 512d1768..070c2099 100644 --- a/tests/pull-api.c +++ b/tests/pull-api.c @@ -2,6 +2,8 @@ #include "test-utils.h" +#ifdef HAVE_APACHE + static SoupBuffer *correct_response; static void @@ -527,3 +529,13 @@ main (int argc, char **argv) test_cleanup (); return errors != 0; } + +#else /* HAVE_APACHE */ + +int +main (int argc, char **argv) +{ + return 77; /* SKIP */ +} + +#endif diff --git a/tests/range-test.c b/tests/range-test.c index 09e95f12..e7d01d21 100644 --- a/tests/range-test.c +++ b/tests/range-test.c @@ -2,6 +2,8 @@ #include "test-utils.h" +#ifdef HAVE_APACHE + SoupBuffer *full_response; int total_length; char *test_response; @@ -370,3 +372,13 @@ main (int argc, char **argv) test_cleanup (); return errors != 0; } + +#else /* HAVE_APACHE */ + +int +main (int argc, char **argv) +{ + return 77; /* SKIP */ +} + +#endif diff --git a/tests/server-auth-test.c b/tests/server-auth-test.c index 757e065a..33cff45a 100644 --- a/tests/server-auth-test.c +++ b/tests/server-auth-test.c @@ -5,6 +5,8 @@ #include "test-utils.h" +#ifdef HAVE_CURL + static struct { gboolean client_sent_basic, client_sent_digest; gboolean server_requested_basic, server_requested_digest; @@ -361,3 +363,13 @@ main (int argc, char **argv) test_cleanup (); return errors != 0; } + +#else /* HAVE_CURL */ + +int +main (int argc, char **argv) +{ + return 77; /* SKIP */ +} + +#endif diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c index 75f6c911..421348b1 100644 --- a/tests/xmlrpc-server-test.c +++ b/tests/xmlrpc-server-test.c @@ -5,6 +5,8 @@ #include "test-utils.h" +#ifdef HAVE_PHP_XMLRPC + #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS #endif @@ -345,3 +347,13 @@ main (int argc, char **argv) test_cleanup (); return errors != 0; } + +#else /* HAVE_PHP_XMLRPC */ + +int +main (int argc, char **argv) +{ + return 77; /* SKIP */ +} + +#endif diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c index 7a29d0e9..3c3f76fe 100644 --- a/tests/xmlrpc-test.c +++ b/tests/xmlrpc-test.c @@ -5,6 +5,8 @@ #include "test-utils.h" +#ifdef HAVE_PHP_XMLRPC + #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS #endif @@ -552,3 +554,13 @@ main (int argc, char **argv) test_cleanup (); return errors != 0; } + +#else /* HAVE_PHP_XMLRPC */ + +int +main (int argc, char **argv) +{ + return 77; /* SKIP */ +} + +#endif -- cgit v1.2.1 From 5bcbe3c8bbf5ae394c0be76f0b14bb841733dbf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Di=C3=A9guez?= Date: Wed, 20 Feb 2013 10:40:04 +0100 Subject: Updated Galician translations --- po/gl.po | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/po/gl.po b/po/gl.po index 412d5d11..b2cfc9bb 100644 --- a/po/gl.po +++ b/po/gl.po @@ -1,13 +1,13 @@ # Galician translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# Fran Dieguez , 2012. +# Fran Dieguez , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-12-23 04:03+0100\n" -"PO-Revision-Date: 2012-12-23 04:04+0200\n" +"POT-Creation-Date: 2013-02-20 10:39+0100\n" +"PO-Revision-Date: 2013-02-20 10:40+0200\n" "Last-Translator: Fran Dieguez \n" "Language-Team: gnome-l10n-gl@gnome.org\n" "Language: gl\n" @@ -23,18 +23,22 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "A conexión rematou de forma non esperada" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Petición de busca non válida" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Non é posíbel truncar SoupbodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Fluxo de rede pechado de forma non esperada" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Produciuse un fallo ao cachear completamente o recurso" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -60,43 +64,43 @@ msgstr "A operación bloquearase" msgid "Could not parse HTTP request" msgstr "Non é posíbel analizar a consulta HTTP" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Non se forneceu un URI" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI «%s» non válida: %s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4211 #, c-format msgid "Could not parse URI '%s'" msgstr "Non é posíbel analizar o URI «%s»" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4248 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Esquema de URI «%s» non admitido" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4270 #, c-format msgid "Not an HTTP URI" msgstr "Non é unha URI de HTTP" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "O nome do computador é un enderezo IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "O nome do computador non é válido" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "O nome do computador non ten un dominio base" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Non hai dominios dabondo" -- cgit v1.2.1 From 51e044f3e238f24b004ec1af39c2b40ea4e14635 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Thu, 21 Feb 2013 19:55:39 +0200 Subject: Updated Hebrew translation. --- po/he.po | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/po/he.po b/po/he.po index 72bac9e4..7658eed8 100644 --- a/po/he.po +++ b/po/he.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup gnome\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-12-27 00:49+0200\n" -"PO-Revision-Date: 2012-12-27 00:50+0200\n" +"POT-Creation-Date: 2013-02-21 19:54+0200\n" +"PO-Revision-Date: 2013-02-21 19:55+0200\n" "Last-Translator: Yaron Shahrabani \n" "Language-Team: Hebrew \n" "Language: \n" @@ -27,18 +27,22 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "החיבור הופסק באופן בלתי צפוי" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "בקשת חיפוש שגויה" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "לא ניתן לקצץ את SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "תזרים הרשת נסגר בפתאומיות" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "שמירת המשאב במלואו במטמון נכשלה" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -65,44 +69,44 @@ msgstr "הפעולה תיחסם" msgid "Could not parse HTTP request" msgstr "לא ניתן לנתח את תגובת ה־HTTP" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "לא סופקה כתובת" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "כתובת '%s' שגויה: %s" -#: ../libsoup/soup-session.c:3875 +#: ../libsoup/soup-session.c:4211 #, c-format msgid "Could not parse URI '%s'" msgstr "לא ניתן לנתח את הכתובת '%s'" -#: ../libsoup/soup-session.c:3912 +#: ../libsoup/soup-session.c:4248 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "תבנית הכתובת אינה נתמכת '%s'" -#: ../libsoup/soup-session.c:3934 +#: ../libsoup/soup-session.c:4270 #, c-format msgid "Not an HTTP URI" msgstr "כתובת שאינה HTTP" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "שם המארח הוא כתובת IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "שם מארח שגוי" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "לשם המארח אין שם מתחם בסיסי" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "אין מספיק שמות מתחם" -- cgit v1.2.1 From 926105bc58f373726baeb7567a264a53903b2836 Mon Sep 17 00:00:00 2001 From: Gheyret Kenji Date: Fri, 22 Feb 2013 22:20:48 +0900 Subject: Updated Uyghur translation Signed-off-by: Gheyret Kenji --- po/ug.po | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/po/ug.po b/po/ug.po index 33608e3a..c5c366a6 100644 --- a/po/ug.po +++ b/po/ug.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2013-01-14 22:43+0000\n" -"PO-Revision-Date: 2011-11-09 16:10+0900\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-02-22 21:51+0900\n" "Last-Translator: Gheyret Kenji \n" "Language-Team: Uyghur Computer Science Association \n" "Language: \n" @@ -22,25 +22,28 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "باغلىنىش تۇيۇقسىز توختاپ قالدى" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "ئىناۋەتسىز ئىزدەش ئىلتىماسى" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "ئېقىم SoupBodyInputStream نى قىسقارتقىلى بولمىدى" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "تور ئېقىمى تۇيۇقسىز يېپىلدى" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "مەنبەنى تولۇق غەملىۋېلىش مەغلۇپ بولدى" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "چىقىرىش يىغلەكى بەك كىچىك" #: ../libsoup/soup-message-client-io.c:41 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" msgstr "HTTP ئىنكاسىنى يېشەلمىدى" @@ -57,7 +60,6 @@ msgid "Operation would block" msgstr "مەشغۇلات توسۇلىدۇ" #: ../libsoup/soup-message-server-io.c:40 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" msgstr "HTTP ئىلتىماسىنى يېشەلمىدى" @@ -71,17 +73,17 @@ msgstr "URI تەمىنلەنمىدى" msgid "Invalid '%s' URI: %s" msgstr "ئىناۋەتسىز ‹%s› URI: %s" -#: ../libsoup/soup-session.c:4122 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "URI «%s» نى تەھلىل قىلالمىدى" -#: ../libsoup/soup-session.c:4159 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "قوللىمايدىغان URI لايىھە ‹%s›" -#: ../libsoup/soup-session.c:4181 +#: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" msgstr "بۇ HTTP URI ئەمەس" -- cgit v1.2.1 From 4e9713343934fc2aba5d81ab12fccd64cc24a99f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 22 Feb 2013 22:13:33 +0100 Subject: build: remove some cruft Remove accumulated cruft, mostly from things we used to depend on but don't any more. Also a few minor drive-by configure cleanups --- configure.ac | 18 +++++++----------- libsoup/Makefile.am | 12 ++---------- tests/Makefile.am | 3 --- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index d6c97ee4..68293d39 100644 --- a/configure.ac +++ b/configure.ac @@ -63,12 +63,6 @@ fi AC_SUBST(SOUP_DEBUG_FLAGS) -# Set the maintainer flags -#if test -d .git; then -# SOUP_MAINTAINER_FLAGS="-DG_DISABLE_DEPRECATED" -#fi -AC_SUBST(SOUP_MAINTAINER_FLAGS) - dnl *************************** dnl *** Checks for programs *** dnl *************************** @@ -130,7 +124,6 @@ dnl ******************* dnl *** Misc checks *** dnl ******************* AC_CHECK_FUNCS(gmtime_r) -AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket)) dnl ********************* dnl *** GNOME support *** @@ -165,7 +158,7 @@ save_LIBS="$LIBS" CFLAGS="$CFLAGS $GLIB_CFLAGS" LIBS="$LIBS $GLIB_LIBS" AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], - [g_type_init (); return !g_tls_backend_supports_tls (g_tls_backend_get_default ());])], + [return !g_tls_backend_supports_tls (g_tls_backend_get_default ());])], [have_glib_networking=yes], [have_glib_networking=no], [have_glib_networking="unknown (cross-compiling)"]) @@ -310,12 +303,15 @@ else MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES curl" fi -GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0` -AC_SUBST(GLIB_COMPILE_RESOURCES) - AC_SUBST(MISSING_REGRESSION_TEST_PACKAGES) AM_CONDITIONAL(MISSING_REGRESSION_TEST_PACKAGES, test -n "$MISSING_REGRESSION_TEST_PACKAGES") +dnl ********************* +dnl *** resource compiler +dnl ********************* +GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0` +AC_SUBST(GLIB_COMPILE_RESOURCES) + dnl ********************************************************** dnl *** path of NTLM single-sign-on helper ntlm_auth dnl ********************************************************** diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index d2e2cde3..e99c8e6c 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -4,21 +4,15 @@ EXTRA_DIST = include $(GLIB_MAKEFILE) -if OS_WIN32 -LIBWS2_32 = -lws2_32 -endif - INCLUDES = \ -DG_LOG_DOMAIN=\"libsoup\" \ -DLOCALEDIR=\"$(localedir)\" \ -I$(top_srcdir) \ -I$(top_builddir) \ $(SOUP_DEBUG_FLAGS) \ - $(SOUP_MAINTAINER_FLAGS) \ $(GLIB_CFLAGS) \ $(XML_CFLAGS) \ - $(SQLITE_CFLAGS) \ - $(GNOME_KEYRING_CFLAGS) + $(SQLITE_CFLAGS) libsoupincludedir = $(includedir)/libsoup-2.4/libsoup @@ -90,9 +84,7 @@ EXTRA_DIST += libsoup-2.4.sym libsoup_2_4_la_LIBADD = \ $(GLIB_LIBS) \ $(XML_LIBS) \ - $(SQLITE_LIBS) \ - -lz \ - $(LIBWS2_32) + $(SQLITE_LIBS) libsoup_2_4_la_SOURCES = \ soup-address.c \ diff --git a/tests/Makefile.am b/tests/Makefile.am index 55dd3273..5bbcba8e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,13 +2,10 @@ INCLUDES = \ -I$(top_srcdir) \ -DSRCDIR=\""$(abs_srcdir)"\" \ -DBUILDDIR=\""$(builddir)"\" \ - $(SOUP_MAINTAINER_FLAGS) \ - $(XML_CFLAGS) \ $(GLIB_CFLAGS) LIBS = \ $(top_builddir)/libsoup/libsoup-2.4.la \ - $(LIBGNUTLS_LIBS) \ $(GLIB_LIBS) TESTS = \ -- cgit v1.2.1 From 4c7d4c4cd46f64538ca0b3e186b52bdfcaa97e29 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 23 Feb 2013 02:13:26 +0100 Subject: examples: move examples from tests/ to examples/ get, simple-httpd, and simple-proxy are more example code than test programs, so move them into a separate directory. Also, remove "dns", which was once a sort-of test of SoupAddress, but is now just a redundant sort-of test of GResolver. --- .gitignore | 7 +- Makefile.am | 2 +- configure.ac | 1 + examples/Makefile.am | 14 +++ examples/get.c | 193 ++++++++++++++++++++++++++++++++ examples/simple-httpd.c | 291 ++++++++++++++++++++++++++++++++++++++++++++++++ examples/simple-proxy.c | 185 ++++++++++++++++++++++++++++++ tests/Makefile.am | 6 +- tests/dns.c | 60 ---------- tests/get.c | 191 ------------------------------- tests/simple-httpd.c | 289 ----------------------------------------------- tests/simple-proxy.c | 182 ------------------------------ 12 files changed, 689 insertions(+), 732 deletions(-) create mode 100644 examples/Makefile.am create mode 100644 examples/get.c create mode 100644 examples/simple-httpd.c create mode 100644 examples/simple-proxy.c delete mode 100644 tests/dns.c delete mode 100644 tests/get.c delete mode 100644 tests/simple-httpd.c delete mode 100644 tests/simple-proxy.c diff --git a/.gitignore b/.gitignore index 19686f4d..b3a877b9 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,9 @@ docs/reference/libsoup-2.4.signals docs/reference/libsoup-2.4.types docs/reference/tmpl docs/reference/xml +examples/get +examples/simple-httpd +examples/simple-proxy gtk-doc.make install-sh libsoup-zip @@ -68,14 +71,10 @@ tests/*.log tests/*.trs tests/*-test tests/date -tests/dns -tests/get tests/getbug tests/header-parsing tests/httpd.conf tests/ntlm-test-helper tests/pull-api -tests/simple-httpd -tests/simple-proxy tests/soup-tests.gresource tests/uri-parsing diff --git a/Makefile.am b/Makefile.am index 18bf80af..66992d93 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} -SUBDIRS = libsoup po tests docs +SUBDIRS = libsoup po tests examples docs EXTRA_DIST = \ data/effective_tld_names.dat \ diff --git a/configure.ac b/configure.ac index 68293d39..36a16878 100644 --- a/configure.ac +++ b/configure.ac @@ -361,6 +361,7 @@ AC_CONFIG_FILES([ po/Makefile.in po/Makefile tests/Makefile + examples/Makefile docs/Makefile docs/reference/Makefile libsoup/soup-version.h diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 00000000..69e5b550 --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES = \ + -I$(top_srcdir) \ + -DSRCDIR=\""$(abs_srcdir)"\" \ + -DBUILDDIR=\""$(builddir)"\" \ + $(GLIB_CFLAGS) + +LIBS = \ + $(top_builddir)/libsoup/libsoup-2.4.la \ + $(GLIB_LIBS) + +noinst_PROGRAMS = \ + get \ + simple-httpd \ + simple-proxy diff --git a/examples/get.c b/examples/get.c new file mode 100644 index 00000000..f28e5357 --- /dev/null +++ b/examples/get.c @@ -0,0 +1,193 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#include +#include + +#ifdef G_OS_WIN32 +#include +#endif + +#include + +static SoupSession *session; +static GMainLoop *loop; +static gboolean debug = FALSE, quiet = FALSE; +static const char *method; + +static void +get_url (const char *url) +{ + const char *name; + SoupMessage *msg; + const char *header; + + msg = soup_message_new (method, url); + soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); + + soup_session_send_message (session, msg); + + name = soup_message_get_uri (msg)->path; + + if (debug) { + SoupMessageHeadersIter iter; + const char *hname, *value; + char *path = soup_uri_to_string (soup_message_get_uri (msg), TRUE); + + g_print ("%s %s HTTP/1.%d\n", method, path, + soup_message_get_http_version (msg)); + soup_message_headers_iter_init (&iter, msg->request_headers); + while (soup_message_headers_iter_next (&iter, &hname, &value)) + g_print ("%s: %s\r\n", hname, value); + g_print ("\n"); + + g_print ("HTTP/1.%d %d %s\n", + soup_message_get_http_version (msg), + msg->status_code, msg->reason_phrase); + + soup_message_headers_iter_init (&iter, msg->response_headers); + while (soup_message_headers_iter_next (&iter, &hname, &value)) + g_print ("%s: %s\r\n", hname, value); + g_print ("\n"); + } else if (msg->status_code == SOUP_STATUS_SSL_FAILED) { + GTlsCertificateFlags flags; + + if (soup_message_get_https_status (msg, NULL, &flags)) + g_print ("%s: %d %s (0x%x)\n", name, msg->status_code, msg->reason_phrase, flags); + else + g_print ("%s: %d %s (no handshake status)\n", name, msg->status_code, msg->reason_phrase); + } else if (!quiet || SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) + g_print ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase); + + if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) { + header = soup_message_headers_get_one (msg->response_headers, + "Location"); + if (header) { + SoupURI *uri; + char *uri_string; + + if (!debug && !quiet) + g_print (" -> %s\n", header); + + uri = soup_uri_new_with_base (soup_message_get_uri (msg), header); + uri_string = soup_uri_to_string (uri, FALSE); + get_url (uri_string); + g_free (uri_string); + soup_uri_free (uri); + } + } else if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + fwrite (msg->response_body->data, 1, + msg->response_body->length, stdout); + } +} + +static void +usage (void) +{ + g_printerr ("Usage: get [-c CAfile] [-p proxy URL] [-h] [-d] URL\n"); + exit (1); +} + +int +main (int argc, char **argv) +{ + const char *cafile = NULL, *url; + SoupURI *proxy = NULL, *parsed; + gboolean synchronous = FALSE, ntlm = FALSE; + int opt; + + method = SOUP_METHOD_GET; + + while ((opt = getopt (argc, argv, "c:dhnp:qs")) != -1) { + switch (opt) { + case 'c': + cafile = optarg; + break; + + case 'd': + debug = TRUE; + break; + + case 'h': + method = SOUP_METHOD_HEAD; + debug = TRUE; + break; + + case 'n': + ntlm = TRUE; + break; + + case 'p': + proxy = soup_uri_new (optarg); + if (!proxy) { + g_printerr ("Could not parse %s as URI\n", + optarg); + exit (1); + } + break; + + case 'q': + quiet = TRUE; + break; + + case 's': + synchronous = TRUE; + break; + + case '?': + usage (); + break; + } + } + argc -= optind; + argv += optind; + + if (argc != 1) + usage (); + url = argv[0]; + parsed = soup_uri_new (url); + if (!parsed) { + g_printerr ("Could not parse '%s' as a URL\n", url); + exit (1); + } + soup_uri_free (parsed); + + if (synchronous) { + session = soup_session_sync_new_with_options ( + SOUP_SESSION_SSL_CA_FILE, cafile, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, + SOUP_SESSION_USER_AGENT, "get ", + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, + SOUP_SESSION_USE_NTLM, ntlm, + NULL); + } else { + session = soup_session_async_new_with_options ( + SOUP_SESSION_SSL_CA_FILE, cafile, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, + SOUP_SESSION_USER_AGENT, "get ", + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, + SOUP_SESSION_USE_NTLM, ntlm, + NULL); + } + + if (proxy) { + g_object_set (G_OBJECT (session), + SOUP_SESSION_PROXY_URI, proxy, + NULL); + } else + soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_DEFAULT); + + if (!synchronous) + loop = g_main_loop_new (NULL, TRUE); + + get_url (url); + + if (!synchronous) + g_main_loop_unref (loop); + + return 0; +} diff --git a/examples/simple-httpd.c b/examples/simple-httpd.c new file mode 100644 index 00000000..3d05c2a1 --- /dev/null +++ b/examples/simple-httpd.c @@ -0,0 +1,291 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef G_OS_WIN32 +#include +#endif + +#include + +static int +compare_strings (gconstpointer a, gconstpointer b) +{ + const char **sa = (const char **)a; + const char **sb = (const char **)b; + + return strcmp (*sa, *sb); +} + +static GString * +get_directory_listing (const char *path) +{ + GPtrArray *entries; + GString *listing; + char *escaped; + DIR *dir; + struct dirent *dent; + int i; + + entries = g_ptr_array_new (); + dir = opendir (path); + if (dir) { + while ((dent = readdir (dir))) { + if (!strcmp (dent->d_name, ".") || + (!strcmp (dent->d_name, "..") && + !strcmp (path, "./"))) + continue; + escaped = g_markup_escape_text (dent->d_name, -1); + g_ptr_array_add (entries, escaped); + } + closedir (dir); + } + + g_ptr_array_sort (entries, (GCompareFunc)compare_strings); + + listing = g_string_new ("\r\n"); + escaped = g_markup_escape_text (strchr (path, '/'), -1); + g_string_append_printf (listing, "Index of %s\r\n", escaped); + g_string_append_printf (listing, "

Index of %s

\r\n

\r\n", escaped); + g_free (escaped); + for (i = 0; i < entries->len; i++) { + g_string_append_printf (listing, "%s
\r\n", + (char *)entries->pdata[i], + (char *)entries->pdata[i]); + g_free (entries->pdata[i]); + } + g_string_append (listing, "\r\n\r\n"); + + g_ptr_array_free (entries, TRUE); + return listing; +} + +static void +do_get (SoupServer *server, SoupMessage *msg, const char *path) +{ + char *slash; + struct stat st; + + if (stat (path, &st) == -1) { + if (errno == EPERM) + soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN); + else if (errno == ENOENT) + soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); + else + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + if (S_ISDIR (st.st_mode)) { + GString *listing; + char *index_path; + + slash = strrchr (path, '/'); + if (!slash || slash[1]) { + char *redir_uri; + + redir_uri = g_strdup_printf ("%s/", soup_message_get_uri (msg)->path); + soup_message_set_redirect (msg, SOUP_STATUS_MOVED_PERMANENTLY, + redir_uri); + g_free (redir_uri); + return; + } + + index_path = g_strdup_printf ("%s/index.html", path); + if (stat (index_path, &st) != -1) { + do_get (server, msg, index_path); + g_free (index_path); + return; + } + g_free (index_path); + + listing = get_directory_listing (path); + soup_message_set_response (msg, "text/html", + SOUP_MEMORY_TAKE, + listing->str, listing->len); + g_string_free (listing, FALSE); + return; + } + + if (msg->method == SOUP_METHOD_GET) { + GMappedFile *mapping; + SoupBuffer *buffer; + + mapping = g_mapped_file_new (path, FALSE, NULL); + if (!mapping) { + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + buffer = soup_buffer_new_with_owner (g_mapped_file_get_contents (mapping), + g_mapped_file_get_length (mapping), + mapping, (GDestroyNotify)g_mapped_file_unref); + soup_message_body_append_buffer (msg->response_body, buffer); + soup_buffer_free (buffer); + } else /* msg->method == SOUP_METHOD_HEAD */ { + char *length; + + /* We could just use the same code for both GET and + * HEAD (soup-message-server-io.c will fix things up). + * But we'll optimize and avoid the extra I/O. + */ + length = g_strdup_printf ("%lu", (gulong)st.st_size); + soup_message_headers_append (msg->response_headers, + "Content-Length", length); + g_free (length); + } + + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +static void +do_put (SoupServer *server, SoupMessage *msg, const char *path) +{ + struct stat st; + FILE *f; + gboolean created = TRUE; + + if (stat (path, &st) != -1) { + const char *match = soup_message_headers_get_one (msg->request_headers, "If-None-Match"); + if (match && !strcmp (match, "*")) { + soup_message_set_status (msg, SOUP_STATUS_CONFLICT); + return; + } + + if (!S_ISREG (st.st_mode)) { + soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN); + return; + } + + created = FALSE; + } + + f = fopen (path, "w"); + if (!f) { + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + fwrite (msg->request_body->data, 1, msg->request_body->length, f); + fclose (f); + + soup_message_set_status (msg, created ? SOUP_STATUS_CREATED : SOUP_STATUS_OK); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + char *file_path; + SoupMessageHeadersIter iter; + const char *name, *value; + + g_print ("%s %s HTTP/1.%d\n", msg->method, path, + soup_message_get_http_version (msg)); + soup_message_headers_iter_init (&iter, msg->request_headers); + while (soup_message_headers_iter_next (&iter, &name, &value)) + g_print ("%s: %s\n", name, value); + if (msg->request_body->length) + g_print ("%s\n", msg->request_body->data); + + file_path = g_strdup_printf (".%s", path); + + if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD) + do_get (server, msg, file_path); + else if (msg->method == SOUP_METHOD_PUT) + do_put (server, msg, file_path); + else + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + + g_free (file_path); + g_print (" -> %d %s\n\n", msg->status_code, msg->reason_phrase); +} + +static void +quit (int sig) +{ + /* Exit cleanly on ^C in case we're valgrinding. */ + exit (0); +} + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + SoupServer *server, *ssl_server; + int opt; + int port = SOUP_ADDRESS_ANY_PORT; + int ssl_port = SOUP_ADDRESS_ANY_PORT; + const char *ssl_cert_file = NULL, *ssl_key_file = NULL; + + signal (SIGINT, quit); + + while ((opt = getopt (argc, argv, "p:k:c:s:")) != -1) { + switch (opt) { + case 'p': + port = atoi (optarg); + break; + case 'k': + ssl_key_file = optarg; + break; + case 'c': + ssl_cert_file = optarg; + break; + case 's': + ssl_port = atoi (optarg); + break; + default: + g_printerr ("Usage: %s [-p port] [-c ssl-cert-file -k ssl-key-file [-s ssl-port]]\n", + argv[0]); + exit (1); + } + } + + server = soup_server_new (SOUP_SERVER_PORT, port, + SOUP_SERVER_SERVER_HEADER, "simple-httpd ", + NULL); + if (!server) { + g_printerr ("Unable to bind to server port %d\n", port); + exit (1); + } + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + g_print ("\nStarting Server on port %d\n", + soup_server_get_port (server)); + soup_server_run_async (server); + + if (ssl_cert_file && ssl_key_file) { + ssl_server = soup_server_new ( + SOUP_SERVER_PORT, ssl_port, + SOUP_SERVER_SSL_CERT_FILE, ssl_cert_file, + SOUP_SERVER_SSL_KEY_FILE, ssl_key_file, + NULL); + + if (!ssl_server) { + g_printerr ("Unable to bind to SSL server port %d\n", ssl_port); + exit (1); + } + soup_server_add_handler (ssl_server, NULL, + server_callback, NULL, NULL); + g_print ("Starting SSL Server on port %d\n", + soup_server_get_port (ssl_server)); + soup_server_run_async (ssl_server); + } + + g_print ("\nWaiting for requests...\n"); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + + return 0; +} diff --git a/examples/simple-proxy.c b/examples/simple-proxy.c new file mode 100644 index 00000000..1a9e0ed3 --- /dev/null +++ b/examples/simple-proxy.c @@ -0,0 +1,185 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2001-2003, Ximian, Inc. + */ + +#include +#include + +#ifdef G_OS_WIN32 +#include +#endif + +#include + +/* WARNING: this is really really really not especially compliant with + * RFC 2616. But it does work for basic stuff. + */ + +static SoupSession *session; +static SoupServer *server; + +static void +copy_header (const char *name, const char *value, gpointer dest_headers) +{ + soup_message_headers_append (dest_headers, name, value); +} + +static void +send_headers (SoupMessage *from, SoupMessage *to) +{ + g_print ("[%p] HTTP/1.%d %d %s\n", to, + soup_message_get_http_version (from), + from->status_code, from->reason_phrase); + + soup_message_set_status_full (to, from->status_code, + from->reason_phrase); + soup_message_headers_foreach (from->response_headers, copy_header, + to->response_headers); + soup_message_headers_remove (to->response_headers, "Content-Length"); + soup_server_unpause_message (server, to); +} + +static void +send_chunk (SoupMessage *from, SoupBuffer *chunk, SoupMessage *to) +{ + g_print ("[%p] writing chunk of %lu bytes\n", to, + (unsigned long)chunk->length); + + soup_message_body_append_buffer (to->response_body, chunk); + soup_server_unpause_message (server, to); +} + +static void +client_msg_failed (SoupMessage *msg, gpointer msg2) +{ + soup_session_cancel_message (session, msg2, SOUP_STATUS_IO_ERROR); +} + +static void +finish_msg (SoupSession *session, SoupMessage *msg2, gpointer data) +{ + SoupMessage *msg = data; + + g_print ("[%p] done\n\n", msg); + g_signal_handlers_disconnect_by_func (msg, client_msg_failed, msg2); + + soup_message_body_complete (msg->response_body); + soup_server_unpause_message (server, msg); + g_object_unref (msg); +} + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + SoupMessage *msg2; + char *uristr; + + uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE); + g_print ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr, + soup_message_get_http_version (msg)); + + if (msg->method == SOUP_METHOD_CONNECT) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + msg2 = soup_message_new (msg->method, uristr); + soup_message_headers_foreach (msg->request_headers, copy_header, + msg2->request_headers); + soup_message_headers_remove (msg2->request_headers, "Host"); + soup_message_headers_remove (msg2->request_headers, "Connection"); + + if (msg->request_body->length) { + SoupBuffer *request = soup_message_body_flatten (msg->request_body); + soup_message_body_append_buffer (msg2->request_body, request); + soup_buffer_free (request); + } + soup_message_headers_set_encoding (msg->response_headers, + SOUP_ENCODING_CHUNKED); + + g_signal_connect (msg2, "got_headers", + G_CALLBACK (send_headers), msg); + g_signal_connect (msg2, "got_chunk", + G_CALLBACK (send_chunk), msg); + + g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2); + + soup_session_queue_message (session, msg2, finish_msg, msg); + + g_object_ref (msg); + soup_server_pause_message (server, msg); +} + +static gboolean +auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, + const char *username, const char *password, gpointer data) +{ + return !strcmp (username, "user") && !strcmp (password, "password"); +} + +static void +quit (int sig) +{ + /* Exit cleanly on ^C in case we're valgrinding. */ + exit (0); +} + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + int opt; + int port = SOUP_ADDRESS_ANY_PORT; + SoupAuthDomain *auth_domain = NULL; + + signal (SIGINT, quit); + + while ((opt = getopt (argc, argv, "ap:")) != -1) { + switch (opt) { + case 'a': + auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "simple-proxy", + SOUP_AUTH_DOMAIN_PROXY, TRUE, + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback, + NULL); + break; + case 'p': + port = atoi (optarg); + break; + default: + g_printerr ("Usage: %s [-p port] [-n]\n", + argv[0]); + exit (1); + } + } + + server = soup_server_new (SOUP_SERVER_PORT, port, + NULL); + if (!server) { + g_printerr ("Unable to bind to server port %d\n", port); + exit (1); + } + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + if (auth_domain) { + soup_server_add_auth_domain (server, auth_domain); + g_object_unref (auth_domain); + } + + g_print ("\nStarting proxy on port %d\n", + soup_server_get_port (server)); + soup_server_run_async (server); + + session = soup_session_async_new (); + + g_print ("\nWaiting for requests...\n"); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + return 0; +} diff --git a/tests/Makefile.am b/tests/Makefile.am index 5bbcba8e..417b04c7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,12 +42,8 @@ TESTS = \ xmlrpc-test noinst_PROGRAMS = \ - $(TESTS) \ - dns \ - get \ ntlm-test-helper \ - simple-httpd \ - simple-proxy + $(TESTS) noinst_DATA = soup-tests.gresource diff --git a/tests/dns.c b/tests/dns.c deleted file mode 100644 index ee9108e6..00000000 --- a/tests/dns.c +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ - -#include "test-utils.h" - -static GMainLoop *loop; -static int nlookups = 0; - -static void -resolve_callback (SoupAddress *addr, guint status, gpointer data) -{ - if (status == SOUP_STATUS_OK) { - g_print ("Name: %s\n", soup_address_get_name (addr)); - g_print ("Address: %s\n", soup_address_get_physical (addr)); - } else { - g_print ("Name: %s\n", soup_address_get_name (addr)); - g_print ("Error: %s\n", soup_status_get_phrase (status)); - } - g_print ("\n"); - - g_object_unref (addr); - - nlookups--; - if (nlookups == 0) - g_main_loop_quit (loop); -} - -static void -usage (void) -{ - g_printerr ("Usage: dns hostname ...\n"); - exit (1); -} - -int -main (int argc, char **argv) -{ - SoupAddress *addr; - int i; - - if (argc < 2) - usage (); - - for (i = 1; i < argc; i++) { - addr = soup_address_new (argv[i], 0); - if (!addr) { - g_printerr ("Could not parse address %s\n", argv[1]); - exit (1); - } - - soup_address_resolve_async (addr, NULL, NULL, - resolve_callback, NULL); - nlookups++; - } - - loop = g_main_loop_new (NULL, TRUE); - g_main_loop_run (loop); - g_main_loop_unref (loop); - - return 0; -} diff --git a/tests/get.c b/tests/get.c deleted file mode 100644 index 15d69033..00000000 --- a/tests/get.c +++ /dev/null @@ -1,191 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2001-2003, Ximian, Inc. - */ - -#include "test-utils.h" -#include - -#ifdef G_OS_WIN32 -#include -#endif - -static SoupSession *session; -static GMainLoop *loop; -static gboolean debug = FALSE, quiet = FALSE; -static const char *method; - -static void -get_url (const char *url) -{ - const char *name; - SoupMessage *msg; - const char *header; - - msg = soup_message_new (method, url); - soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); - - soup_session_send_message (session, msg); - - name = soup_message_get_uri (msg)->path; - - if (debug) { - SoupMessageHeadersIter iter; - const char *hname, *value; - char *path = soup_uri_to_string (soup_message_get_uri (msg), TRUE); - - g_print ("%s %s HTTP/1.%d\n", method, path, - soup_message_get_http_version (msg)); - soup_message_headers_iter_init (&iter, msg->request_headers); - while (soup_message_headers_iter_next (&iter, &hname, &value)) - g_print ("%s: %s\r\n", hname, value); - g_print ("\n"); - - g_print ("HTTP/1.%d %d %s\n", - soup_message_get_http_version (msg), - msg->status_code, msg->reason_phrase); - - soup_message_headers_iter_init (&iter, msg->response_headers); - while (soup_message_headers_iter_next (&iter, &hname, &value)) - g_print ("%s: %s\r\n", hname, value); - g_print ("\n"); - } else if (msg->status_code == SOUP_STATUS_SSL_FAILED) { - GTlsCertificateFlags flags; - - if (soup_message_get_https_status (msg, NULL, &flags)) - g_print ("%s: %d %s (0x%x)\n", name, msg->status_code, msg->reason_phrase, flags); - else - g_print ("%s: %d %s (no handshake status)\n", name, msg->status_code, msg->reason_phrase); - } else if (!quiet || SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) - g_print ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase); - - if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) { - header = soup_message_headers_get_one (msg->response_headers, - "Location"); - if (header) { - SoupURI *uri; - char *uri_string; - - if (!debug && !quiet) - g_print (" -> %s\n", header); - - uri = soup_uri_new_with_base (soup_message_get_uri (msg), header); - uri_string = soup_uri_to_string (uri, FALSE); - get_url (uri_string); - g_free (uri_string); - soup_uri_free (uri); - } - } else if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - fwrite (msg->response_body->data, 1, - msg->response_body->length, stdout); - } -} - -static void -usage (void) -{ - g_printerr ("Usage: get [-c CAfile] [-p proxy URL] [-h] [-d] URL\n"); - exit (1); -} - -int -main (int argc, char **argv) -{ - const char *cafile = NULL, *url; - SoupURI *proxy = NULL, *parsed; - gboolean synchronous = FALSE, ntlm = FALSE; - int opt; - - method = SOUP_METHOD_GET; - - while ((opt = getopt (argc, argv, "c:dhnp:qs")) != -1) { - switch (opt) { - case 'c': - cafile = optarg; - break; - - case 'd': - debug = TRUE; - break; - - case 'h': - method = SOUP_METHOD_HEAD; - debug = TRUE; - break; - - case 'n': - ntlm = TRUE; - break; - - case 'p': - proxy = soup_uri_new (optarg); - if (!proxy) { - g_printerr ("Could not parse %s as URI\n", - optarg); - exit (1); - } - break; - - case 'q': - quiet = TRUE; - break; - - case 's': - synchronous = TRUE; - break; - - case '?': - usage (); - break; - } - } - argc -= optind; - argv += optind; - - if (argc != 1) - usage (); - url = argv[0]; - parsed = soup_uri_new (url); - if (!parsed) { - g_printerr ("Could not parse '%s' as a URL\n", url); - exit (1); - } - soup_uri_free (parsed); - - if (synchronous) { - session = soup_session_sync_new_with_options ( - SOUP_SESSION_SSL_CA_FILE, cafile, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, - SOUP_SESSION_USER_AGENT, "get ", - SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, - SOUP_SESSION_USE_NTLM, ntlm, - NULL); - } else { - session = soup_session_async_new_with_options ( - SOUP_SESSION_SSL_CA_FILE, cafile, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, - SOUP_SESSION_USER_AGENT, "get ", - SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, - SOUP_SESSION_USE_NTLM, ntlm, - NULL); - } - - if (proxy) { - g_object_set (G_OBJECT (session), - SOUP_SESSION_PROXY_URI, proxy, - NULL); - } else - soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_DEFAULT); - - if (!synchronous) - loop = g_main_loop_new (NULL, TRUE); - - get_url (url); - - if (!synchronous) - g_main_loop_unref (loop); - - return 0; -} diff --git a/tests/simple-httpd.c b/tests/simple-httpd.c deleted file mode 100644 index 75b7cd4a..00000000 --- a/tests/simple-httpd.c +++ /dev/null @@ -1,289 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2001-2003, Ximian, Inc. - */ - -#include "test-utils.h" - -#include -#include -#include -#include -#include - -#ifdef G_OS_WIN32 -#include -#endif - -static int -compare_strings (gconstpointer a, gconstpointer b) -{ - const char **sa = (const char **)a; - const char **sb = (const char **)b; - - return strcmp (*sa, *sb); -} - -static GString * -get_directory_listing (const char *path) -{ - GPtrArray *entries; - GString *listing; - char *escaped; - DIR *dir; - struct dirent *dent; - int i; - - entries = g_ptr_array_new (); - dir = opendir (path); - if (dir) { - while ((dent = readdir (dir))) { - if (!strcmp (dent->d_name, ".") || - (!strcmp (dent->d_name, "..") && - !strcmp (path, "./"))) - continue; - escaped = g_markup_escape_text (dent->d_name, -1); - g_ptr_array_add (entries, escaped); - } - closedir (dir); - } - - g_ptr_array_sort (entries, (GCompareFunc)compare_strings); - - listing = g_string_new ("\r\n"); - escaped = g_markup_escape_text (strchr (path, '/'), -1); - g_string_append_printf (listing, "Index of %s\r\n", escaped); - g_string_append_printf (listing, "

Index of %s

\r\n

\r\n", escaped); - g_free (escaped); - for (i = 0; i < entries->len; i++) { - g_string_append_printf (listing, "%s
\r\n", - (char *)entries->pdata[i], - (char *)entries->pdata[i]); - g_free (entries->pdata[i]); - } - g_string_append (listing, "\r\n\r\n"); - - g_ptr_array_free (entries, TRUE); - return listing; -} - -static void -do_get (SoupServer *server, SoupMessage *msg, const char *path) -{ - char *slash; - struct stat st; - - if (stat (path, &st) == -1) { - if (errno == EPERM) - soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN); - else if (errno == ENOENT) - soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); - else - soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - - if (S_ISDIR (st.st_mode)) { - GString *listing; - char *index_path; - - slash = strrchr (path, '/'); - if (!slash || slash[1]) { - char *redir_uri; - - redir_uri = g_strdup_printf ("%s/", soup_message_get_uri (msg)->path); - soup_message_set_redirect (msg, SOUP_STATUS_MOVED_PERMANENTLY, - redir_uri); - g_free (redir_uri); - return; - } - - index_path = g_strdup_printf ("%s/index.html", path); - if (stat (index_path, &st) != -1) { - do_get (server, msg, index_path); - g_free (index_path); - return; - } - g_free (index_path); - - listing = get_directory_listing (path); - soup_message_set_response (msg, "text/html", - SOUP_MEMORY_TAKE, - listing->str, listing->len); - g_string_free (listing, FALSE); - return; - } - - if (msg->method == SOUP_METHOD_GET) { - GMappedFile *mapping; - SoupBuffer *buffer; - - mapping = g_mapped_file_new (path, FALSE, NULL); - if (!mapping) { - soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - - buffer = soup_buffer_new_with_owner (g_mapped_file_get_contents (mapping), - g_mapped_file_get_length (mapping), - mapping, (GDestroyNotify)g_mapped_file_unref); - soup_message_body_append_buffer (msg->response_body, buffer); - soup_buffer_free (buffer); - } else /* msg->method == SOUP_METHOD_HEAD */ { - char *length; - - /* We could just use the same code for both GET and - * HEAD (soup-message-server-io.c will fix things up). - * But we'll optimize and avoid the extra I/O. - */ - length = g_strdup_printf ("%lu", (gulong)st.st_size); - soup_message_headers_append (msg->response_headers, - "Content-Length", length); - g_free (length); - } - - soup_message_set_status (msg, SOUP_STATUS_OK); -} - -static void -do_put (SoupServer *server, SoupMessage *msg, const char *path) -{ - struct stat st; - FILE *f; - gboolean created = TRUE; - - if (stat (path, &st) != -1) { - const char *match = soup_message_headers_get_one (msg->request_headers, "If-None-Match"); - if (match && !strcmp (match, "*")) { - soup_message_set_status (msg, SOUP_STATUS_CONFLICT); - return; - } - - if (!S_ISREG (st.st_mode)) { - soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN); - return; - } - - created = FALSE; - } - - f = fopen (path, "w"); - if (!f) { - soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - - fwrite (msg->request_body->data, 1, msg->request_body->length, f); - fclose (f); - - soup_message_set_status (msg, created ? SOUP_STATUS_CREATED : SOUP_STATUS_OK); -} - -static void -server_callback (SoupServer *server, SoupMessage *msg, - const char *path, GHashTable *query, - SoupClientContext *context, gpointer data) -{ - char *file_path; - SoupMessageHeadersIter iter; - const char *name, *value; - - g_print ("%s %s HTTP/1.%d\n", msg->method, path, - soup_message_get_http_version (msg)); - soup_message_headers_iter_init (&iter, msg->request_headers); - while (soup_message_headers_iter_next (&iter, &name, &value)) - g_print ("%s: %s\n", name, value); - if (msg->request_body->length) - g_print ("%s\n", msg->request_body->data); - - file_path = g_strdup_printf (".%s", path); - - if (msg->method == SOUP_METHOD_GET || msg->method == SOUP_METHOD_HEAD) - do_get (server, msg, file_path); - else if (msg->method == SOUP_METHOD_PUT) - do_put (server, msg, file_path); - else - soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); - - g_free (file_path); - g_print (" -> %d %s\n\n", msg->status_code, msg->reason_phrase); -} - -static void -quit (int sig) -{ - /* Exit cleanly on ^C in case we're valgrinding. */ - exit (0); -} - -int -main (int argc, char **argv) -{ - GMainLoop *loop; - SoupServer *server, *ssl_server; - int opt; - int port = SOUP_ADDRESS_ANY_PORT; - int ssl_port = SOUP_ADDRESS_ANY_PORT; - const char *ssl_cert_file = NULL, *ssl_key_file = NULL; - - signal (SIGINT, quit); - - while ((opt = getopt (argc, argv, "p:k:c:s:")) != -1) { - switch (opt) { - case 'p': - port = atoi (optarg); - break; - case 'k': - ssl_key_file = optarg; - break; - case 'c': - ssl_cert_file = optarg; - break; - case 's': - ssl_port = atoi (optarg); - break; - default: - g_printerr ("Usage: %s [-p port] [-c ssl-cert-file -k ssl-key-file [-s ssl-port]]\n", - argv[0]); - exit (1); - } - } - - server = soup_server_new (SOUP_SERVER_PORT, port, - SOUP_SERVER_SERVER_HEADER, "simple-httpd ", - NULL); - if (!server) { - g_printerr ("Unable to bind to server port %d\n", port); - exit (1); - } - soup_server_add_handler (server, NULL, - server_callback, NULL, NULL); - g_print ("\nStarting Server on port %d\n", - soup_server_get_port (server)); - soup_server_run_async (server); - - if (ssl_cert_file && ssl_key_file) { - ssl_server = soup_server_new ( - SOUP_SERVER_PORT, ssl_port, - SOUP_SERVER_SSL_CERT_FILE, ssl_cert_file, - SOUP_SERVER_SSL_KEY_FILE, ssl_key_file, - NULL); - - if (!ssl_server) { - g_printerr ("Unable to bind to SSL server port %d\n", ssl_port); - exit (1); - } - soup_server_add_handler (ssl_server, NULL, - server_callback, NULL, NULL); - g_print ("Starting SSL Server on port %d\n", - soup_server_get_port (ssl_server)); - soup_server_run_async (ssl_server); - } - - g_print ("\nWaiting for requests...\n"); - - loop = g_main_loop_new (NULL, TRUE); - g_main_loop_run (loop); - - return 0; -} diff --git a/tests/simple-proxy.c b/tests/simple-proxy.c deleted file mode 100644 index 765fa5e7..00000000 --- a/tests/simple-proxy.c +++ /dev/null @@ -1,182 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2001-2003, Ximian, Inc. - */ - -#include "test-utils.h" - -#ifdef G_OS_WIN32 -#include -#endif - -/* WARNING: this is really really really not especially compliant with - * RFC 2616. But it does work for basic stuff. - */ - -static SoupSession *session; -static SoupServer *server; - -static void -copy_header (const char *name, const char *value, gpointer dest_headers) -{ - soup_message_headers_append (dest_headers, name, value); -} - -static void -send_headers (SoupMessage *from, SoupMessage *to) -{ - g_print ("[%p] HTTP/1.%d %d %s\n", to, - soup_message_get_http_version (from), - from->status_code, from->reason_phrase); - - soup_message_set_status_full (to, from->status_code, - from->reason_phrase); - soup_message_headers_foreach (from->response_headers, copy_header, - to->response_headers); - soup_message_headers_remove (to->response_headers, "Content-Length"); - soup_server_unpause_message (server, to); -} - -static void -send_chunk (SoupMessage *from, SoupBuffer *chunk, SoupMessage *to) -{ - g_print ("[%p] writing chunk of %lu bytes\n", to, - (unsigned long)chunk->length); - - soup_message_body_append_buffer (to->response_body, chunk); - soup_server_unpause_message (server, to); -} - -static void -client_msg_failed (SoupMessage *msg, gpointer msg2) -{ - soup_session_cancel_message (session, msg2, SOUP_STATUS_IO_ERROR); -} - -static void -finish_msg (SoupSession *session, SoupMessage *msg2, gpointer data) -{ - SoupMessage *msg = data; - - g_print ("[%p] done\n\n", msg); - g_signal_handlers_disconnect_by_func (msg, client_msg_failed, msg2); - - soup_message_body_complete (msg->response_body); - soup_server_unpause_message (server, msg); - g_object_unref (msg); -} - -static void -server_callback (SoupServer *server, SoupMessage *msg, - const char *path, GHashTable *query, - SoupClientContext *context, gpointer data) -{ - SoupMessage *msg2; - char *uristr; - - uristr = soup_uri_to_string (soup_message_get_uri (msg), FALSE); - g_print ("[%p] %s %s HTTP/1.%d\n", msg, msg->method, uristr, - soup_message_get_http_version (msg)); - - if (msg->method == SOUP_METHOD_CONNECT) { - soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); - return; - } - - msg2 = soup_message_new (msg->method, uristr); - soup_message_headers_foreach (msg->request_headers, copy_header, - msg2->request_headers); - soup_message_headers_remove (msg2->request_headers, "Host"); - soup_message_headers_remove (msg2->request_headers, "Connection"); - - if (msg->request_body->length) { - SoupBuffer *request = soup_message_body_flatten (msg->request_body); - soup_message_body_append_buffer (msg2->request_body, request); - soup_buffer_free (request); - } - soup_message_headers_set_encoding (msg->response_headers, - SOUP_ENCODING_CHUNKED); - - g_signal_connect (msg2, "got_headers", - G_CALLBACK (send_headers), msg); - g_signal_connect (msg2, "got_chunk", - G_CALLBACK (send_chunk), msg); - - g_signal_connect (msg, "finished", G_CALLBACK (client_msg_failed), msg2); - - soup_session_queue_message (session, msg2, finish_msg, msg); - - g_object_ref (msg); - soup_server_pause_message (server, msg); -} - -static gboolean -auth_callback (SoupAuthDomain *auth_domain, SoupMessage *msg, - const char *username, const char *password, gpointer data) -{ - return !strcmp (username, "user") && !strcmp (password, "password"); -} - -static void -quit (int sig) -{ - /* Exit cleanly on ^C in case we're valgrinding. */ - exit (0); -} - -int -main (int argc, char **argv) -{ - GMainLoop *loop; - int opt; - int port = SOUP_ADDRESS_ANY_PORT; - SoupAuthDomain *auth_domain = NULL; - - signal (SIGINT, quit); - - while ((opt = getopt (argc, argv, "ap:")) != -1) { - switch (opt) { - case 'a': - auth_domain = soup_auth_domain_basic_new ( - SOUP_AUTH_DOMAIN_REALM, "simple-proxy", - SOUP_AUTH_DOMAIN_PROXY, TRUE, - SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback, - NULL); - break; - case 'p': - port = atoi (optarg); - break; - default: - g_printerr ("Usage: %s [-p port] [-n]\n", - argv[0]); - exit (1); - } - } - - server = soup_server_new (SOUP_SERVER_PORT, port, - NULL); - if (!server) { - g_printerr ("Unable to bind to server port %d\n", port); - exit (1); - } - soup_server_add_handler (server, NULL, - server_callback, NULL, NULL); - if (auth_domain) { - soup_server_add_auth_domain (server, auth_domain); - g_object_unref (auth_domain); - } - - g_print ("\nStarting proxy on port %d\n", - soup_server_get_port (server)); - soup_server_run_async (server); - - session = soup_session_async_new (); - - g_print ("\nWaiting for requests...\n"); - - loop = g_main_loop_new (NULL, TRUE); - g_main_loop_run (loop); - g_main_loop_unref (loop); - - return 0; -} -- cgit v1.2.1 From 342e1b6f371d5852ead85131d72643160fa66522 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 23 Feb 2013 02:43:33 +0100 Subject: examples: use GOptionContext (finally) --- examples/get.c | 156 +++++++++++++++++++++--------------------------- examples/simple-httpd.c | 67 +++++++++++---------- examples/simple-proxy.c | 67 ++++++++++++--------- 3 files changed, 146 insertions(+), 144 deletions(-) diff --git a/examples/get.c b/examples/get.c index f28e5357..3540b724 100644 --- a/examples/get.c +++ b/examples/get.c @@ -6,16 +6,11 @@ #include #include -#ifdef G_OS_WIN32 -#include -#endif - #include static SoupSession *session; static GMainLoop *loop; -static gboolean debug = FALSE, quiet = FALSE; -static const char *method; +static gboolean debug, head, quiet; static void get_url (const char *url) @@ -24,19 +19,19 @@ get_url (const char *url) SoupMessage *msg; const char *header; - msg = soup_message_new (method, url); + msg = soup_message_new (head ? "HEAD" : "GET", url); soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); soup_session_send_message (session, msg); name = soup_message_get_uri (msg)->path; - if (debug) { + if (debug || head) { SoupMessageHeadersIter iter; const char *hname, *value; char *path = soup_uri_to_string (soup_message_get_uri (msg), TRUE); - g_print ("%s %s HTTP/1.%d\n", method, path, + g_print ("%s %s HTTP/1.%d\n", msg->method, path, soup_message_get_http_version (msg)); soup_message_headers_iter_init (&iter, msg->request_headers); while (soup_message_headers_iter_next (&iter, &hname, &value)) @@ -83,70 +78,60 @@ get_url (const char *url) } } -static void -usage (void) -{ - g_printerr ("Usage: get [-c CAfile] [-p proxy URL] [-h] [-d] URL\n"); - exit (1); -} +static const char *ca_file, *proxy; +static gboolean synchronous, ntlm; + +static GOptionEntry entries[] = { + { "ca-file", 'c', 0, + G_OPTION_ARG_STRING, &ca_file, + "Use FILE as the TLS CA file", "FILE" }, + { "debug", 'd', 0, + G_OPTION_ARG_NONE, &debug, + "Show HTTP headers", NULL }, + { "head", 'h', 0, + G_OPTION_ARG_NONE, &head, + "Do HEAD rather than GET", NULL }, + { "ntlm", 'n', 0, + G_OPTION_ARG_NONE, &ntlm, + "Use NTLM authentication", NULL }, + { "proxy", 'p', 0, + G_OPTION_ARG_STRING, &proxy, + "Use URL as an HTTP proxy", "URL" }, + { "quiet", 'q', 0, + G_OPTION_ARG_NONE, &quiet, + "Don't show HTTP status code", NULL }, + { "sync", 's', 0, + G_OPTION_ARG_NONE, &synchronous, + "Use SoupSessionSync rather than SoupSessionAsync", NULL }, + { NULL } +}; int main (int argc, char **argv) { - const char *cafile = NULL, *url; - SoupURI *proxy = NULL, *parsed; - gboolean synchronous = FALSE, ntlm = FALSE; - int opt; - - method = SOUP_METHOD_GET; - - while ((opt = getopt (argc, argv, "c:dhnp:qs")) != -1) { - switch (opt) { - case 'c': - cafile = optarg; - break; - - case 'd': - debug = TRUE; - break; - - case 'h': - method = SOUP_METHOD_HEAD; - debug = TRUE; - break; - - case 'n': - ntlm = TRUE; - break; - - case 'p': - proxy = soup_uri_new (optarg); - if (!proxy) { - g_printerr ("Could not parse %s as URI\n", - optarg); - exit (1); - } - break; - - case 'q': - quiet = TRUE; - break; - - case 's': - synchronous = TRUE; - break; - - case '?': - usage (); - break; - } + GOptionContext *opts; + const char *url; + SoupURI *proxy_uri, *parsed; + GError *error = NULL; + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, entries, NULL); + if (!g_option_context_parse (opts, &argc, &argv, &error)) { + g_printerr ("Could not parse arguments: %s\n", + error->message); + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); } - argc -= optind; - argv += optind; - if (argc != 1) - usage (); - url = argv[0]; + if (argc != 2) { + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + g_option_context_free (opts); + + url = argv[1]; parsed = soup_uri_new (url); if (!parsed) { g_printerr ("Could not parse '%s' as a URL\n", url); @@ -154,30 +139,27 @@ main (int argc, char **argv) } soup_uri_free (parsed); - if (synchronous) { - session = soup_session_sync_new_with_options ( - SOUP_SESSION_SSL_CA_FILE, cafile, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, - SOUP_SESSION_USER_AGENT, "get ", - SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, - SOUP_SESSION_USE_NTLM, ntlm, - NULL); - } else { - session = soup_session_async_new_with_options ( - SOUP_SESSION_SSL_CA_FILE, cafile, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, - SOUP_SESSION_USER_AGENT, "get ", - SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, - SOUP_SESSION_USE_NTLM, ntlm, - NULL); - } + session = g_object_new (synchronous ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_SSL_CA_FILE, ca_file, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, + SOUP_SESSION_USER_AGENT, "get ", + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, + SOUP_SESSION_USE_NTLM, ntlm, + NULL); if (proxy) { + proxy_uri = soup_uri_new (proxy); + if (!proxy_uri) { + g_printerr ("Could not parse '%s' as URI\n", + proxy); + exit (1); + } + g_object_set (G_OBJECT (session), - SOUP_SESSION_PROXY_URI, proxy, + SOUP_SESSION_PROXY_URI, proxy_uri, NULL); + soup_uri_free (proxy_uri); } else soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_DEFAULT); diff --git a/examples/simple-httpd.c b/examples/simple-httpd.c index 3d05c2a1..71ff874c 100644 --- a/examples/simple-httpd.c +++ b/examples/simple-httpd.c @@ -5,16 +5,11 @@ #include #include -#include #include #include #include #include -#ifdef G_OS_WIN32 -#include -#endif - #include static int @@ -218,39 +213,51 @@ quit (int sig) exit (0); } +static int port, ssl_port; +static const char *ssl_cert_file, *ssl_key_file; + +static GOptionEntry entries[] = { + { "cert-file", 'c', 0, + G_OPTION_ARG_STRING, &ssl_cert_file, + "Use FILE as the TLS certificate file", "FILE" }, + { "key-file", 'k', 0, + G_OPTION_ARG_STRING, &ssl_key_file, + "Use FILE as the TLS private key file", "FILE" }, + { "port", 'p', 0, + G_OPTION_ARG_INT, &port, + "Port to listen on", NULL }, + { "ssl-port", 's', 0, + G_OPTION_ARG_INT, &port, + "Port to listen on for TLS traffic", NULL }, + { NULL } +}; + int main (int argc, char **argv) { + GOptionContext *opts; GMainLoop *loop; SoupServer *server, *ssl_server; - int opt; - int port = SOUP_ADDRESS_ANY_PORT; - int ssl_port = SOUP_ADDRESS_ANY_PORT; - const char *ssl_cert_file = NULL, *ssl_key_file = NULL; + GError *error = NULL; + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, entries, NULL); + if (!g_option_context_parse (opts, &argc, &argv, &error)) { + g_printerr ("Could not parse arguments: %s\n", + error->message); + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + if (argc != 1) { + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } + g_option_context_free (opts); signal (SIGINT, quit); - while ((opt = getopt (argc, argv, "p:k:c:s:")) != -1) { - switch (opt) { - case 'p': - port = atoi (optarg); - break; - case 'k': - ssl_key_file = optarg; - break; - case 'c': - ssl_cert_file = optarg; - break; - case 's': - ssl_port = atoi (optarg); - break; - default: - g_printerr ("Usage: %s [-p port] [-c ssl-cert-file -k ssl-key-file [-s ssl-port]]\n", - argv[0]); - exit (1); - } - } - server = soup_server_new (SOUP_SERVER_PORT, port, SOUP_SERVER_SERVER_HEADER, "simple-httpd ", NULL); diff --git a/examples/simple-proxy.c b/examples/simple-proxy.c index 1a9e0ed3..6623166c 100644 --- a/examples/simple-proxy.c +++ b/examples/simple-proxy.c @@ -6,10 +6,6 @@ #include #include -#ifdef G_OS_WIN32 -#include -#endif - #include /* WARNING: this is really really really not especially compliant with @@ -127,34 +123,44 @@ quit (int sig) exit (0); } +static int port; +static gboolean require_auth; + +static GOptionEntry entries[] = { + { "auth-domain", 'a', 0, + G_OPTION_ARG_NONE, &require_auth, + "Require authentication", NULL }, + { "port", 'p', 0, + G_OPTION_ARG_INT, &port, + "Port to listen on", NULL }, + { NULL } +}; + int main (int argc, char **argv) { + GOptionContext *opts; GMainLoop *loop; - int opt; - int port = SOUP_ADDRESS_ANY_PORT; - SoupAuthDomain *auth_domain = NULL; - - signal (SIGINT, quit); + GError *error = NULL; + + opts = g_option_context_new (NULL); + g_option_context_add_main_entries (opts, entries, NULL); + if (!g_option_context_parse (opts, &argc, &argv, &error)) { + g_printerr ("Could not parse arguments: %s\n", + error->message); + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); + } - while ((opt = getopt (argc, argv, "ap:")) != -1) { - switch (opt) { - case 'a': - auth_domain = soup_auth_domain_basic_new ( - SOUP_AUTH_DOMAIN_REALM, "simple-proxy", - SOUP_AUTH_DOMAIN_PROXY, TRUE, - SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback, - NULL); - break; - case 'p': - port = atoi (optarg); - break; - default: - g_printerr ("Usage: %s [-p port] [-n]\n", - argv[0]); - exit (1); - } + if (argc != 2) { + g_printerr ("%s", + g_option_context_get_help (opts, TRUE, NULL)); + exit (1); } + g_option_context_free (opts); + + signal (SIGINT, quit); server = soup_server_new (SOUP_SERVER_PORT, port, NULL); @@ -164,7 +170,14 @@ main (int argc, char **argv) } soup_server_add_handler (server, NULL, server_callback, NULL, NULL); - if (auth_domain) { + if (require_auth) { + SoupAuthDomain *auth_domain; + + auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "simple-proxy", + SOUP_AUTH_DOMAIN_PROXY, TRUE, + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, auth_callback, + NULL); soup_server_add_auth_domain (server, auth_domain); g_object_unref (auth_domain); } -- cgit v1.2.1 From 345d739b6e97f0318d83a4eaf55321718d6cd14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aurimas=20=C4=8Cernius?= Date: Sun, 24 Feb 2013 21:55:55 +0200 Subject: Updated Lithuanian translation --- po/lt.po | 71 ++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/po/lt.po b/po/lt.po index 5775351b..ae9183e4 100644 --- a/po/lt.po +++ b/po/lt.po @@ -1,84 +1,111 @@ # Lithuanian translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# Aurimas Černius , 2012. +# Aurimas Černius , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-13 22:40+0300\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-02-24 21:55+0200\n" "Last-Translator: Aurimas Černius \n" -"Language-Team: Lithuanian \n" +"Language-Team: Lietuvių \n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Gtranslator 2.91.6\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 -#: ../libsoup/soup-body-input-stream.c:205 -#: ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Ryšys netikėtai nutrūko" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Netinkama paieškos užklausa" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Negalima trumpinti SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Tinklo srautas netikėtai užsivėrė" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Nepavyko visiškai patalpinti resurso į podėlį" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Išvesties buferis yra per mažas" -#: ../libsoup/soup-message-io.c:818 -#: ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Nepavyko perskaityti URI „%s“Nepavyko perskaityti HTTP atsako" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Neatpažinta HTTP atsako koduotė" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Veiksmas buvo nutrauktas" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Veiksmas blokuosis" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Nepavyko perskaityti HTTP užklausos" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Nepateiktas URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Netinkamas „%s“ URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Nepavyko perskaityti URI „%s“" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nepalaikoma URI schema „%s“" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ne HTTP URI" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Serverio vardas arba IP adresas" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Netinkamas serverio vardas" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Serverio vardas neturi bazinio domeno" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Nepakanka domenų" - -- cgit v1.2.1 From e0d89ccc26f045b6c7837d3aab1bf4e8aa93b048 Mon Sep 17 00:00:00 2001 From: Kjartan Maraas Date: Mon, 25 Feb 2013 17:07:20 +0100 Subject: =?UTF-8?q?Updated=20Norwegian=20bokm=C3=A5l=20translation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- po/nb.po | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/po/nb.po b/po/nb.po index 3f72f036..b2293d90 100644 --- a/po/nb.po +++ b/po/nb.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: libsoup 3.7.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-21 12:31+0100\n" -"PO-Revision-Date: 2013-01-21 12:32+0100\n" +"POT-Creation-Date: 2013-02-25 17:06+0100\n" +"PO-Revision-Date: 2013-02-25 17:07+0100\n" "Last-Translator: Kjartan Maraas \n" "Language-Team: Norwegian bokmål \n" "Language: \n" @@ -30,10 +30,14 @@ msgstr "Ugyldig søkeforespørsel" msgid "Cannot truncate SoupBodyInputStream" msgstr "Kan ikke avkorte SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Nettverksstrømmen ble lukket på uventet vis" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Klarte ikke å mellomlagre ressursen fullt ut" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -69,17 +73,17 @@ msgstr "Ingen URI ble oppgitt" msgid "Invalid '%s' URI: %s" msgstr "Ugyldig «%s» URI: %s" -#: ../libsoup/soup-session.c:4123 +#: ../libsoup/soup-session.c:4211 #, c-format msgid "Could not parse URI '%s'" msgstr "Kunne ikke tolke URI «%s»" -#: ../libsoup/soup-session.c:4160 +#: ../libsoup/soup-session.c:4248 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "URI-skjema «%s» er ikke støttet" -#: ../libsoup/soup-session.c:4182 +#: ../libsoup/soup-session.c:4270 #, c-format msgid "Not an HTTP URI" msgstr "Ikke en HTTP URI" -- cgit v1.2.1 From 9140a5edc0cf8cb19aa40c422d3bea20dde91cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavol=20Kla=C4=8Dansk=C3=BD?= Date: Mon, 25 Feb 2013 20:30:40 +0100 Subject: Updated slovak translation --- po/sk.po | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/po/sk.po b/po/sk.po index 92436167..cb442ca0 100644 --- a/po/sk.po +++ b/po/sk.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2013-02-07 14:25+0000\n" -"PO-Revision-Date: 2013-02-06 18:11+0000\n" +"POT-Creation-Date: 2013-02-20 09:40+0000\n" +"PO-Revision-Date: 2013-02-20 20:57+0000\n" "Last-Translator: Dušan Kazik \n" "Language-Team: Slovak \n" "Language: sk\n" @@ -34,10 +34,14 @@ msgstr "Neplatná požiadavka na posunutie" msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream sa nedá skrátiť" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Sieťový prúd bol neočakávane uzavretý" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Úplné načítanie zdroja do dočasnej pamäte zlyhalo" + # PM: buffer by som preložil ako schránka # PK: schranka je clipboard, buffer je jednoznacne vyrovnavacia pamet #: ../libsoup/soup-converter-wrapper.c:192 @@ -78,17 +82,17 @@ msgstr "Nebol poskytnutý identifikátor URI" msgid "Invalid '%s' URI: %s" msgstr "Neplatná schéma „%s“ identifikátora URI: %s" -#: ../libsoup/soup-session.c:4168 +#: ../libsoup/soup-session.c:4211 #, c-format msgid "Could not parse URI '%s'" msgstr "Nepodarilo sa analyzovať identifikátor URI „%s“" -#: ../libsoup/soup-session.c:4205 +#: ../libsoup/soup-session.c:4248 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nepodporovaná schéma „%s“ pre identifikátor URI" -#: ../libsoup/soup-session.c:4227 +#: ../libsoup/soup-session.c:4270 #, c-format msgid "Not an HTTP URI" msgstr "Nie je HTTP URI" -- cgit v1.2.1 From d0b058ddaaee9916e963cc3dcf01bbcaa3d5cff0 Mon Sep 17 00:00:00 2001 From: A S Alam Date: Tue, 26 Feb 2013 07:37:04 +0530 Subject: Punjabi: Translation updated (aalam) --- po/pa.po | 59 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/po/pa.po b/po/pa.po index eefaffaf..3edbf498 100644 --- a/po/pa.po +++ b/po/pa.po @@ -2,14 +2,14 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # -# A S Alam , 2012. +# A S Alam , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-19 20:51+0530\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-02-26 07:36+0530\n" "Last-Translator: A S Alam \n" "Language-Team: Punjabi/Panjabi \n" "Language: pa\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Lokalize 1.4\n" +"X-Generator: Lokalize 1.5\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -25,60 +25,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "ਕੁਨੈਕਸ਼ਨ ਅਚਾਨਕ ਬੰਦ ਹੋ ਗਿਆ" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "ਸੀਕ ਮੰਗ ਗਲਤ ਹੈ" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream ਨੂੰ ਛੋਟਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "ਨੈੱਟਵਰਕ ਸਟਰੀਮ ਅਚਾਨਕ ਬੰਦ ਹੋਈ" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "ਸਰੋਤ ਨੂੰ ਪੂਰੀ ਕੈਸ਼ ਕਰਨ ਲਈ ਫੇਲ੍ਹ ਹੈ" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "ਆਉਟਪੁੱਟ ਬਫ਼ਰ ਬਹੁਤ ਛੋਟਾ ਹੈ" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "ਬੇਪਛਾਣ HTTP ਜਵਾਬ ਇੰਕੋਡਿੰਗ" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "ਕਾਰਵਾਈ ਰੱਦ ਕੀਤੀ ਗਈ" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "ਕਾਰਵਾਈ ਉੱਤੇ ਪਾਬੰਦੀ ਹੋਵੇਗੀ" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP ਮੰਗ ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "ਕੋਈ URI ਨਹੀਂ ਦਿੱਤਾ" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "ਗਲਤ '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' ਨੂੰ ਪਾਰਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "ਗ਼ੈਰ-ਸਹਾਇਕ URI ਸਕੀਮ '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI ਨਹੀਂ ਹੈ" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "ਹੋਸਟ ਨਾਂ IP ਐਡਰੈਸ ਹੈ" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "ਗਲਤ ਹੋਸਟ-ਨਾਂ" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "ਹੋਸਟ-ਨਾਂ ਲਈ ਬੇਸ ਡੋਮੇਮ ਨਹੀਂ ਹੈ" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "ਲੋੜੀਦੀਆਂ ਡੋਮੇਨ ਨਹੀਂ ਹੈ" -- cgit v1.2.1 From 41c0d9b3a5b195f30bc7d72973b500186d88065b Mon Sep 17 00:00:00 2001 From: Chao-Hsiung Liao Date: Fri, 1 Mar 2013 22:41:18 +0800 Subject: Updated Traditional Chinese translation(Hong Kong and Taiwan) --- po/zh_HK.po | 37 +++++++++++++++++++------------------ po/zh_TW.po | 37 +++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/po/zh_HK.po b/po/zh_HK.po index fbd82c47..f9e17ba7 100644 --- a/po/zh_HK.po +++ b/po/zh_HK.po @@ -6,10 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-18 15:49+0000\n" -"PO-Revision-Date: 2013-02-04 20:34+0800\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-03-01 22:41+0800\n" +"PO-Revision-Date: 2013-03-01 22:41+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: Chinese (Hong Kong) \n" "Language: zh_TW\n" @@ -24,25 +23,28 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "連線無預警的關閉了" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "無效的搜尋要求" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "不能截短 SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "網絡串流無預警的關閉了" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "無法完整快取資源" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "輸出緩衝區太小" #: ../libsoup/soup-message-client-io.c:41 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" msgstr "無法解析 HTTP 回應" @@ -59,47 +61,46 @@ msgid "Operation would block" msgstr "操作會阻擋" #: ../libsoup/soup-message-server-io.c:40 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" msgstr "無法解析 HTTP 要求" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "未提供 URI" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "無效的「%s」URI:%s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4211 #, c-format msgid "Could not parse URI '%s'" msgstr "無法解析 URI「%s」" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4248 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "不支援的 URI scheme「%s」" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4270 #, c-format msgid "Not an HTTP URI" msgstr "並非 HTTP URI" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "主機名稱是 IP 位址" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "主機名稱無效" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "主機名稱沒有基礎網域" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "沒有足夠的網域" diff --git a/po/zh_TW.po b/po/zh_TW.po index 2f319b71..d59a81ca 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -6,10 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-18 15:49+0000\n" -"PO-Revision-Date: 2013-02-04 18:54+0800\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-03-01 22:41+0800\n" +"PO-Revision-Date: 2013-02-28 09:48+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: Chinese (Taiwan) \n" "Language: zh_TW\n" @@ -24,25 +23,28 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "連線無預警的關閉了" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "無效的搜尋要求" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "不能截短 SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "網路串流無預警的關閉了" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "無法完整快取資源" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "輸出緩衝區太小" #: ../libsoup/soup-message-client-io.c:41 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" msgstr "無法解析 HTTP 回應" @@ -59,47 +61,46 @@ msgid "Operation would block" msgstr "操作會阻擋" #: ../libsoup/soup-message-server-io.c:40 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" msgstr "無法解析 HTTP 要求" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "未提供 URI" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "無效的「%s」URI:%s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4211 #, c-format msgid "Could not parse URI '%s'" msgstr "無法解析 URI「%s」" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4248 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "不支援的 URI scheme「%s」" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4270 #, c-format msgid "Not an HTTP URI" msgstr "並非 HTTP URI" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "主機名稱是 IP 位址" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "主機名稱無效" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "主機名稱沒有基礎網域" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "沒有足夠的網域" -- cgit v1.2.1 From 1ac14817cd68b4f4dae82021c9e4535fe4c7763d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sat, 2 Mar 2013 20:42:54 +0700 Subject: po/vi: import from Damned Lies --- po/vi.po | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 15 deletions(-) diff --git a/po/vi.po b/po/vi.po index 5fc62da4..f095706e 100644 --- a/po/vi.po +++ b/po/vi.po @@ -8,62 +8,104 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-06-28 03:27+0000\n" -"PO-Revision-Date: 2012-06-30 10:15+0700\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-02 20:42+0700\n" "Last-Translator: Nguyễn Thái Ngọc Duy \n" "Language-Team: Vietnamese \n" +"Language: vi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../libsoup/soup-body-input-stream.c:139 -#: ../libsoup/soup-body-input-stream.c:170 -#: ../libsoup/soup-body-input-stream.c:203 ../libsoup/soup-message-io.c:231 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Kết nối ngắt bất ngờ" -#: ../libsoup/soup-converter-wrapper.c:190 +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Vùng đệm xuất quá nhỏ" -#: ../libsoup/soup-message-io.c:836 ../libsoup/soup-message-io.c:863 +#: ../libsoup/soup-message-client-io.c:41 +#, fuzzy +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Không thể phân tích URI '%s'" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Thao tác bị huỷ" -#: ../libsoup/soup-message-io.c:874 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Thao tác có thể treo" -#: ../libsoup/soup-request.c:145 +#: ../libsoup/soup-message-server-io.c:40 +#, fuzzy +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Không thể phân tích URI '%s'" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Chưa có URI" -#: ../libsoup/soup-request.c:155 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI '%s' không hợp lệ: %s" -#: ../libsoup/soup-requester.c:220 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Không thể phân tích URI '%s'" -#: ../libsoup/soup-requester.c:254 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Không hỗ trợ kiểu URI '%s'" -#: ../libsoup/soup-tld.c:145 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Tên máy là địa chỉ IP" -#: ../libsoup/soup-tld.c:166 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Tên máy không hợp lệ" -#: ../libsoup/soup-tld.c:181 ../libsoup/soup-tld.c:219 +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "" + +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Không đủ miền" -- cgit v1.2.1 From 0e0fcd0397272031a5c1f57d293681920400bc20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20Th=C3=A1i=20Ng=E1=BB=8Dc=20Duy?= Date: Sat, 2 Mar 2013 20:44:41 +0700 Subject: Updated Vietnamese translation --- po/vi.po | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/po/vi.po b/po/vi.po index f095706e..f10402e2 100644 --- a/po/vi.po +++ b/po/vi.po @@ -1,7 +1,7 @@ # Vietnamese translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# Nguyễn Thái Ngọc Duy , 2012. +# Nguyễn Thái Ngọc Duy , 2012-2013. # msgid "" msgstr "" @@ -9,7 +9,7 @@ msgstr "" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" "POT-Creation-Date: 2013-02-18 10:20+0000\n" -"PO-Revision-Date: 2013-03-02 20:42+0700\n" +"PO-Revision-Date: 2013-03-02 20:44+0700\n" "Last-Translator: Nguyễn Thái Ngọc Duy \n" "Language-Team: Vietnamese \n" "Language: vi\n" @@ -26,19 +26,19 @@ msgstr "Kết nối ngắt bất ngờ" #: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" -msgstr "" +msgstr "Yêu cầu di chuyển (seek) không hợp lệ" #: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" -msgstr "" +msgstr "Không thể cắt SoupBodyInputStream" #: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" -msgstr "" +msgstr "Luồng mạng đóng bất ngờ" #: ../libsoup/soup-cache-input-stream.c:291 msgid "Failed to completely cache the resource" -msgstr "" +msgstr "Lỗi lưu tạm (cache) toàn bộ tài nguyên" #: ../libsoup/soup-converter-wrapper.c:192 #, c-format @@ -46,14 +46,12 @@ msgid "Output buffer is too small" msgstr "Vùng đệm xuất quá nhỏ" #: ../libsoup/soup-message-client-io.c:41 -#, fuzzy -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" -msgstr "Không thể phân tích URI '%s'" +msgstr "Không thể phân tích phản hồi HTTP" #: ../libsoup/soup-message-client-io.c:66 msgid "Unrecognized HTTP response encoding" -msgstr "" +msgstr "Không nhận ra bảng mã phản hồi HTTP" #: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" @@ -64,10 +62,8 @@ msgid "Operation would block" msgstr "Thao tác có thể treo" #: ../libsoup/soup-message-server-io.c:40 -#, fuzzy -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" -msgstr "Không thể phân tích URI '%s'" +msgstr "Không thể phân tích phản hồi HTTP" #: ../libsoup/soup-request.c:140 #, c-format @@ -92,7 +88,7 @@ msgstr "Không hỗ trợ kiểu URI '%s'" #: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" -msgstr "" +msgstr "Không phải HTTP URI" #: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" @@ -104,7 +100,7 @@ msgstr "Tên máy không hợp lệ" #: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" -msgstr "" +msgstr "Tên máy không có miền cơ bản" #: ../libsoup/soup-tld.c:257 msgid "Not enough domains" -- cgit v1.2.1 From 5057f867f1e58fff45383f4a07ec1b6df3475342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20Bl=C3=A4ttermann?= Date: Sun, 3 Mar 2013 21:11:04 +0100 Subject: [l10n] Updated German translation --- po/de.po | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/po/de.po b/po/de.po index 62d77b06..cdb26022 100644 --- a/po/de.po +++ b/po/de.po @@ -2,7 +2,7 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # Tobias Endrigkeit , 2012. -# Mario Blättermann , 2012. +# Mario Blättermann , 2012, 2013. # Andre Jonas , 2013. # msgid "" @@ -10,9 +10,9 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2013-01-21 15:55+0000\n" -"PO-Revision-Date: 2013-01-23 12:26+0100\n" -"Last-Translator: Andre Jonas \n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-03 21:07+0100\n" +"Last-Translator: Mario Blättermann \n" "Language-Team: Deutsch >\n" "Language: de\n" "MIME-Version: 1.0\n" @@ -35,10 +35,14 @@ msgstr "Ungültige Suchanfrage" msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream konnte nicht abgeschnitten werden" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Netzwerk-Stream wurde unerwartet geschlossen" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Das vollständige Zwischenspeichern der Ressource ist fehlgeschlagen" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -74,17 +78,17 @@ msgstr "Keine Adresse wurde bereitgestellt" msgid "Invalid '%s' URI: %s" msgstr "Ungültige »%s« Adresse: %s" -#: ../libsoup/soup-session.c:4123 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Die Adresse »%s« konnte nicht verarbeitet werden" -#: ../libsoup/soup-session.c:4160 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nicht unterstütztes Adressenschema »%s«" -#: ../libsoup/soup-session.c:4182 +#: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" msgstr "Keine HTTP-Adresse" -- cgit v1.2.1 From 6c24fd0e6d3d6a1b18829e72e2508ad6fcf6f9e7 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 4 Mar 2013 11:26:17 +0100 Subject: soup-message-queue: hold a reference to the async context This will ensure that the GMainContext is not freed at least until we get rid of the queue item. This was causing crashes when synchronously retrieving resources in WebKit as it uses a different GMainContext for each of those synchronous requests. https://bugzilla.gnome.org/show_bug.cgi?id=694920 --- libsoup/soup-message-queue.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index c7661d8c..8b1ebaf9 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -82,6 +82,8 @@ soup_message_queue_append (SoupMessageQueue *queue, SoupMessage *msg, item = g_slice_new0 (SoupMessageQueueItem); item->session = g_object_ref (queue->session); item->async_context = soup_session_get_async_context (item->session); + if (item->async_context) + g_main_context_ref (item->async_context); item->queue = queue; item->msg = g_object_ref (msg); item->callback = callback; @@ -163,6 +165,7 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) g_object_unref (item->msg); g_object_unref (item->cancellable); g_clear_object (&item->task); + g_clear_pointer (&item->async_context, g_main_context_unref); if (item->io_source) { g_source_destroy (item->io_source); g_source_unref (item->io_source); -- cgit v1.2.1 From 1b995688933a32a79146bb72f43676d01f817765 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Fri, 1 Mar 2013 14:18:39 +0100 Subject: build: Remove gio resource compiler definition from configure.ac MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variable GLIB_COMPILE_RESOURCES is already set by AM_PATH_GLIB_2_0 macro. Spotted by Csaba Osztrogonác. https://bugzilla.gnome.org/show_bug.cgi?id=694942 --- configure.ac | 6 ------ 1 file changed, 6 deletions(-) diff --git a/configure.ac b/configure.ac index 36a16878..e62b4d4e 100644 --- a/configure.ac +++ b/configure.ac @@ -306,12 +306,6 @@ fi AC_SUBST(MISSING_REGRESSION_TEST_PACKAGES) AM_CONDITIONAL(MISSING_REGRESSION_TEST_PACKAGES, test -n "$MISSING_REGRESSION_TEST_PACKAGES") -dnl ********************* -dnl *** resource compiler -dnl ********************* -GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0` -AC_SUBST(GLIB_COMPILE_RESOURCES) - dnl ********************************************************** dnl *** path of NTLM single-sign-on helper ntlm_auth dnl ********************************************************** -- cgit v1.2.1 From 74f914e293a112ee53ec4c87c925c5e56199f4b3 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Mon, 4 Mar 2013 17:58:41 +0100 Subject: soup-cache: update cached headers on revalidations SoupCache was not updating the cached headers on conditional requests. We were only doing it for revalidations started by libsoup clients. This also properly reset the values of freshness_lifetime and must_revalidate on revalidations. These two fields were keeping their original values even if the server wasn't providing such information. Finally this adds a new cache test (do_header_test) and fixes the one disabled with #ifdefs (second revalidations). https://bugzilla.gnome.org/show_bug.cgi?id=695121 --- libsoup/soup-cache-private.h | 22 +++--- libsoup/soup-cache.c | 39 +++++++++-- libsoup/soup-session.c | 6 +- tests/cache-test.c | 161 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 180 insertions(+), 48 deletions(-) diff --git a/libsoup/soup-cache-private.h b/libsoup/soup-cache-private.h index 65ad8689..e17fc0de 100644 --- a/libsoup/soup-cache-private.h +++ b/libsoup/soup-cache-private.h @@ -28,16 +28,18 @@ G_BEGIN_DECLS -SoupCacheResponse soup_cache_has_response (SoupCache *cache, - SoupMessage *msg); -GInputStream *soup_cache_send_response (SoupCache *cache, - SoupMessage *msg); -SoupCacheability soup_cache_get_cacheability (SoupCache *cache, - SoupMessage *msg); -SoupMessage *soup_cache_generate_conditional_request (SoupCache *cache, - SoupMessage *original); -void soup_cache_cancel_conditional_request (SoupCache *cache, - SoupMessage *msg); +SoupCacheResponse soup_cache_has_response (SoupCache *cache, + SoupMessage *msg); +GInputStream *soup_cache_send_response (SoupCache *cache, + SoupMessage *msg); +SoupCacheability soup_cache_get_cacheability (SoupCache *cache, + SoupMessage *msg); +SoupMessage *soup_cache_generate_conditional_request (SoupCache *cache, + SoupMessage *original); +void soup_cache_cancel_conditional_request (SoupCache *cache, + SoupMessage *msg); +void soup_cache_update_from_conditional_request (SoupCache *cache, + SoupMessage *msg); G_END_DECLS diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index db74831b..815d2f71 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -286,6 +286,12 @@ copy_headers (const char *name, const char *value, SoupMessageHeaders *headers) soup_message_headers_append (headers, name, value); } +static void +remove_headers (const char *name, const char *value, SoupMessageHeaders *headers) +{ + soup_message_headers_remove (headers, name); +} + static char *hop_by_hop_headers[] = {"Connection", "Keep-Alive", "Proxy-Authenticate", "Proxy-Authorization", "TE", "Trailer", "Transfer-Encoding", "Upgrade"}; static void @@ -328,6 +334,12 @@ soup_cache_entry_set_freshness (SoupCacheEntry *entry, SoupMessage *msg, SoupCac const char *cache_control; const char *expires, *date, *last_modified; + /* Reset these values. We have to do this to ensure that + * revalidations overwrite previous values for the headers. + */ + entry->must_revalidate = FALSE; + entry->freshness_lifetime = 0; + cache_control = soup_message_headers_get_list (entry->headers, "Cache-Control"); if (cache_control && *cache_control) { const char *max_age, *s_maxage; @@ -820,11 +832,8 @@ soup_cache_content_processor_wrap_input (SoupContentProcessor *processor, * example the soup client is the one creating the * conditional request. */ - if (entry) { - entry->being_validated = FALSE; - copy_end_to_end_headers (msg->response_headers, entry->headers); - soup_cache_entry_set_freshness (entry, msg, cache); - } + if (entry) + soup_cache_update_from_conditional_request (cache, msg); return NULL; } @@ -1386,6 +1395,26 @@ soup_cache_cancel_conditional_request (SoupCache *cache, soup_session_cancel_message (cache->priv->session, msg, SOUP_STATUS_CANCELLED); } +void +soup_cache_update_from_conditional_request (SoupCache *cache, + SoupMessage *msg) +{ + SoupCacheEntry *entry = soup_cache_entry_lookup (cache, msg); + if (!entry) + return; + + entry->being_validated = FALSE; + + if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { + soup_message_headers_foreach (msg->response_headers, + (SoupMessageHeadersForeachFunc) remove_headers, + entry->headers); + copy_end_to_end_headers (msg->response_headers, entry->headers); + + soup_cache_entry_set_freshness (entry, msg, cache); + } +} + static void pack_entry (gpointer data, gpointer user_data) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index b0fc1d50..ee470019 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3812,6 +3812,7 @@ conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_ { SoupMessageQueueItem *item = user_data; GInputStream *stream; + SoupCache *cache; if (g_cancellable_is_cancelled (item->cancellable)) { cancel_cache_response (item); @@ -3821,9 +3822,10 @@ conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_ g_cancellable_disconnect (item->cancellable, handler_id); } - if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { - SoupCache *cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); + cache = (SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE); + soup_cache_update_from_conditional_request (cache, msg); + if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) { stream = soup_cache_send_response (cache, item->msg); if (stream) { async_return_from_cache (item, stream); diff --git a/tests/cache-test.c b/tests/cache-test.c index d9400fe5..34389f8e 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -77,6 +77,14 @@ server_callback (SoupServer *server, SoupMessage *msg, status = SOUP_STATUS_NOT_MODIFIED; } + header = soup_message_headers_get_one (msg->request_headers, + "Test-Set-My-Header"); + if (header) { + soup_message_headers_append (msg->response_headers, + "My-Header", + header); + } + if (status == SOUP_STATUS_OK) { GChecksum *sum; const char *body; @@ -105,21 +113,32 @@ is_network_stream (GInputStream *stream) return !G_IS_FILE_INPUT_STREAM (stream); } -static char *do_request (SoupSession *session, - SoupURI *base_uri, - const char *method, - const char *path, +static char *do_request (SoupSession *session, + SoupURI *base_uri, + const char *method, + const char *path, + SoupMessageHeaders *response_headers, ...) G_GNUC_NULL_TERMINATED; static gboolean last_request_hit_network; static gboolean last_request_validated; static guint cancelled_requests; +static void +copy_headers (const char *name, + const char *value, + gpointer user_data) +{ + SoupMessageHeaders *headers = (SoupMessageHeaders *) user_data; + soup_message_headers_append (headers, name, value); +} + static char * -do_request (SoupSession *session, - SoupURI *base_uri, - const char *method, - const char *path, +do_request (SoupSession *session, + SoupURI *base_uri, + const char *method, + const char *path, + SoupMessageHeaders *response_headers, ...) { SoupRequestHTTP *req; @@ -139,13 +158,12 @@ do_request (SoupSession *session, soup_uri_free (uri); msg = soup_request_http_get_message (req); - va_start (ap, path); + va_start (ap, response_headers); while ((header = va_arg (ap, const char *))) { value = va_arg (ap, const char *); soup_message_headers_append (msg->request_headers, header, value); } - g_object_unref (msg); stream = soup_test_request_send (SOUP_REQUEST (req), NULL, 0, &error); if (!stream) { @@ -153,9 +171,15 @@ do_request (SoupSession *session, error->message); g_error_free (error); g_object_unref (req); + g_object_unref (msg); return NULL; } + if (response_headers) + soup_message_headers_foreach (msg->response_headers, copy_headers, response_headers); + + g_object_unref (msg); + last_request_hit_network = is_network_stream (stream); g_input_stream_read_all (stream, buf, sizeof (buf), &nread, @@ -259,28 +283,28 @@ do_basics_test (SoupURI *base_uri) G_CALLBACK (request_started), NULL); debug_printf (2, " Initial requests\n"); - body1 = do_request (session, base_uri, "GET", "/1", + body1 = do_request (session, base_uri, "GET", "/1", NULL, "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", NULL); - body2 = do_request (session, base_uri, "GET", "/2", + body2 = do_request (session, base_uri, "GET", "/2", NULL, "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", NULL); - body3 = do_request (session, base_uri, "GET", "/3", + body3 = do_request (session, base_uri, "GET", "/3", NULL, "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", "Test-Set-Cache-Control", "must-revalidate", NULL); - body4 = do_request (session, base_uri, "GET", "/4", + body4 = do_request (session, base_uri, "GET", "/4", NULL, "Test-Set-ETag", "\"abcdefg\"", "Test-Set-Cache-Control", "must-revalidate", NULL); - body5 = do_request (session, base_uri, "GET", "/5", + body5 = do_request (session, base_uri, "GET", "/5", NULL, "Test-Set-Cache-Control", "no-cache", NULL); /* Resource with future Expires should have been cached */ debug_printf (1, " Fresh cached resource\n"); - cmp = do_request (session, base_uri, "GET", "/1", + cmp = do_request (session, base_uri, "GET", "/1", NULL, NULL); if (last_request_hit_network) { debug_printf (1, " Request for /1 not filled from cache!\n"); @@ -296,7 +320,7 @@ do_basics_test (SoupURI *base_uri) /* Resource with long-ago Last-Modified should have been cached */ debug_printf (1, " Heuristically-fresh cached resource\n"); - cmp = do_request (session, base_uri, "GET", "/2", + cmp = do_request (session, base_uri, "GET", "/2", NULL, NULL); if (last_request_hit_network) { debug_printf (1, " Request for /2 not filled from cache!\n"); @@ -312,7 +336,7 @@ do_basics_test (SoupURI *base_uri) /* Adding a query string should bypass the cache but not invalidate it */ debug_printf (1, " Fresh cached resource with a query\n"); - cmp = do_request (session, base_uri, "GET", "/1?attr=value", + cmp = do_request (session, base_uri, "GET", "/1?attr=value", NULL, NULL); if (!last_request_hit_network) { debug_printf (1, " Request for /1?attr=value filled from cache!\n"); @@ -320,7 +344,7 @@ do_basics_test (SoupURI *base_uri) } g_free (cmp); debug_printf (2, " Second request\n"); - cmp = do_request (session, base_uri, "GET", "/1", + cmp = do_request (session, base_uri, "GET", "/1", NULL, NULL); if (last_request_hit_network) { debug_printf (1, " Second request for /1 not filled from cache!\n"); @@ -336,7 +360,7 @@ do_basics_test (SoupURI *base_uri) /* Last-Modified + must-revalidate causes a conditional request */ debug_printf (1, " Unchanged must-revalidate resource w/ Last-Modified\n"); - cmp = do_request (session, base_uri, "GET", "/3", + cmp = do_request (session, base_uri, "GET", "/3", NULL, "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", "Test-Set-Cache-Control", "must-revalidate", NULL); @@ -358,7 +382,7 @@ do_basics_test (SoupURI *base_uri) /* Validation failure should update cache */ debug_printf (1, " Changed must-revalidate resource w/ Last-Modified\n"); - cmp = do_request (session, base_uri, "GET", "/3", + cmp = do_request (session, base_uri, "GET", "/3", NULL, "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT", "Test-Set-Cache-Control", "must-revalidate", NULL); @@ -376,9 +400,8 @@ do_basics_test (SoupURI *base_uri) } g_free (cmp); -#if 0 /* This doesn't work... is the test wrong or is SoupCache? */ debug_printf (2, " Second request\n"); - cmp = do_request (session, base_uri, "GET", "/3", + cmp = do_request (session, base_uri, "GET", "/3", NULL, "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT", "Test-Set-Cache-Control", "must-revalidate", NULL); @@ -395,12 +418,10 @@ do_basics_test (SoupURI *base_uri) errors++; } g_free (cmp); -#endif - /* ETag + must-revalidate causes a conditional request */ debug_printf (1, " Unchanged must-revalidate resource w/ ETag\n"); - cmp = do_request (session, base_uri, "GET", "/4", + cmp = do_request (session, base_uri, "GET", "/4", NULL, "Test-Set-ETag", "\"abcdefg\"", NULL); if (!last_request_validated) { @@ -421,7 +442,7 @@ do_basics_test (SoupURI *base_uri) /* Cache-Control: no-cache prevents caching */ debug_printf (1, " Uncacheable resource\n"); - cmp = do_request (session, base_uri, "GET", "/5", + cmp = do_request (session, base_uri, "GET", "/5", NULL, "Test-Set-Cache-Control", "no-cache", NULL); if (!last_request_hit_network) { @@ -438,14 +459,14 @@ do_basics_test (SoupURI *base_uri) /* PUT to a URI invalidates the cache entry */ debug_printf (1, " Invalidating and re-requesting a cached resource\n"); - cmp = do_request (session, base_uri, "PUT", "/1", + cmp = do_request (session, base_uri, "PUT", "/1", NULL, NULL); if (!last_request_hit_network) { debug_printf (1, " PUT filled from cache!\n"); errors++; } g_free (cmp); - cmp = do_request (session, base_uri, "GET", "/1", + cmp = do_request (session, base_uri, "GET", "/1", NULL, NULL); if (!last_request_hit_network) { debug_printf (1, " PUT failed to invalidate cache entry!\n"); @@ -487,10 +508,10 @@ do_cancel_test (SoupURI *base_uri) G_CALLBACK (request_unqueued), NULL); debug_printf (2, " Initial requests\n"); - body1 = do_request (session, base_uri, "GET", "/1", + body1 = do_request (session, base_uri, "GET", "/1", NULL, "Test-Set-Expires", "Fri, 01 Jan 2100 00:00:00 GMT", NULL); - body2 = do_request (session, base_uri, "GET", "/2", + body2 = do_request (session, base_uri, "GET", "/2", NULL, "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", "Test-Set-Cache-Control", "must-revalidate", NULL); @@ -610,6 +631,83 @@ do_refcounting_test (SoupURI *base_uri) g_free (cache_dir); } +static void +do_headers_test (SoupURI *base_uri) +{ + SoupSession *session; + SoupMessageHeaders *headers; + SoupCache *cache; + char *cache_dir; + char *body1, *cmp; + const char *header_value; + + debug_printf (1, "Cache basics\n"); + + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); + debug_printf (2, " Caching to %s\n", cache_dir); + cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_ADD_FEATURE, cache, + NULL); + + g_signal_connect (session, "request-started", + G_CALLBACK (request_started), NULL); + + debug_printf (2, " Initial requests\n"); + body1 = do_request (session, base_uri, "GET", "/1", NULL, + "Test-Set-Last-Modified", "Fri, 01 Jan 2100 00:00:00 GMT", + "Test-Set-My-Header", "My header value", + NULL); + + /* My-Header new value should be updated in cache */ + debug_printf (2, " Fresh cached resource which updates My-Header\n"); + cmp = do_request (session, base_uri, "GET", "/1", NULL, + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + "Test-Set-My-Header", "My header NEW value", + NULL); + if (!last_request_validated) { + debug_printf (1, " Request for /1 not validated!\n"); + errors++; + } + if (last_request_hit_network) { + debug_printf (1, " Request for /1 not filled from cache!\n"); + errors++; + } + g_free (cmp); + + /* Check that cache returns the updated header */ + debug_printf (2, " Fresh cached resource with new value for My-Header\n"); + headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE); + cmp = do_request (session, base_uri, "GET", "/1", headers, + "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", + NULL); + if (last_request_hit_network) { + debug_printf (1, " Request for /1 not filled from cache!\n"); + errors++; + } + g_free (cmp); + + header_value = soup_message_headers_get_list (headers, "My-Header"); + if (!header_value) { + debug_printf (1, " Header \"My-Header\" not present!\n"); + errors++; + } + if (strcmp (header_value, "My header NEW value") != 0) { + debug_printf (1, " \"My-Header = %s\" and should be \"%s\"\n", + header_value, + "My header NEW value"); + errors++; + } + soup_message_headers_free (headers); + + soup_test_session_abort_unref (session); + g_object_unref (cache); + + g_free (cache_dir); + g_free (body1); +} + int main (int argc, char **argv) { @@ -626,6 +724,7 @@ main (int argc, char **argv) do_basics_test (base_uri); do_cancel_test (base_uri); do_refcounting_test (base_uri); + do_headers_test (base_uri); soup_uri_free (base_uri); soup_test_server_quit_unref (server); -- cgit v1.2.1 From 230a42c9e53380e2fb82306bed174618ef5a41e0 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 5 Mar 2013 10:48:24 -0500 Subject: 2.41.91 --- NEWS | 22 ++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 5b0e5e50..9224b5bd 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,25 @@ +Changes in libsoup from 2.41.90 to 2.41.91: + + * Fixed a crash that showed up with XMLRPC requests in + WebKitGTK. [#694920, Sergio] + + * Fixed SoupCache to update the cached headers when it + receives a 304 Not Modified response, and added a test for + this. [#695121, Sergio] + + * libsoup now builds under automake 1.13 (and "make check" + works under the parallel test harness which is the default + in 1.13) [#694135] + + * The tests/ directory now contains only actual test programs + that are run by "make check", and the programs that are + intended more as example code are under examples/. + + * New/updated translations: + Aragonese, Chinese (traditional), Czech, Galician, Hebrew, + Lithuanian, Norwegian bokmål, Punjabi, Spanish, Uyghur, + Vietnamese + Changes in libsoup from 2.41.5 to 2.41.90: * Added SoupSession:local-address property, which allows you diff --git a/configure.ac b/configure.ac index e62b4d4e..34db3676 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [90]) +m4_define([soup_micro_version], [91]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From ef359ad7565e3b46691582358fd07f1148c933f7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 6 Mar 2013 12:58:29 -0500 Subject: SoupSession: break infinite loops Every year or two some bug comes up that makes libsoup retry a request infinitely. (Also, apps can do this on their own by not paying attention to the "retrying" flag in SoupSession::authenticate.) Move the "too many redirects" code and rework it to handle all possible cases of "message gets resent a suspicious number of times". --- libsoup/soup-message-queue.h | 2 +- libsoup/soup-session.c | 29 +++++++++++-------------- tests/auth-test.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index 848ecd02..135a6aac 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -46,7 +46,7 @@ struct _SoupMessageQueueItem { guint new_api : 1; guint io_started : 1; guint async : 1; - guint redirection_count : 28; + guint resend_count : 28; SoupMessageQueueItemState state; diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index ee470019..a153cde5 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -149,7 +149,7 @@ static void async_send_request_running (SoupSession *session, SoupMessageQueueIt #define SOUP_SESSION_MAX_CONNS_DEFAULT 10 #define SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT 2 -#define SOUP_SESSION_MAX_REDIRECTION_COUNT 20 +#define SOUP_SESSION_MAX_RESEND_COUNT 20 #define SOUP_SESSION_USER_AGENT_BASE "libsoup/" PACKAGE_VERSION @@ -1088,27 +1088,12 @@ soup_session_would_redirect (SoupSession *session, SoupMessage *msg) gboolean soup_session_redirect_message (SoupSession *session, SoupMessage *msg) { - SoupMessageQueueItem *item; SoupURI *new_uri; new_uri = redirection_uri (msg); if (!new_uri) return FALSE; - item = soup_message_queue_lookup (soup_session_get_queue (session), msg); - if (!item) { - soup_uri_free (new_uri); - return FALSE; - } - if (item->redirection_count >= SOUP_SESSION_MAX_REDIRECTION_COUNT) { - soup_uri_free (new_uri); - soup_session_cancel_message (session, msg, SOUP_STATUS_TOO_MANY_REDIRECTS); - soup_message_queue_item_unref (item); - return FALSE; - } - item->redirection_count++; - soup_message_queue_item_unref (item); - if (SOUP_SESSION_WOULD_REDIRECT_AS_GET (session, msg)) { if (msg->method != SOUP_METHOD_HEAD) { g_object_set (msg, @@ -2008,7 +1993,17 @@ soup_session_real_requeue_message (SoupSession *session, SoupMessage *msg) item = soup_message_queue_lookup (priv->queue, msg); g_return_if_fail (item != NULL); - item->state = SOUP_MESSAGE_RESTARTING; + + if (item->resend_count >= SOUP_SESSION_MAX_RESEND_COUNT) { + if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) + soup_message_set_status (msg, SOUP_STATUS_TOO_MANY_REDIRECTS); + else + g_warning ("SoupMessage %p stuck in infinite loop?", msg); + } else { + item->resend_count++; + item->state = SOUP_MESSAGE_RESTARTING; + } + soup_message_queue_item_unref (item); } diff --git a/tests/auth-test.c b/tests/auth-test.c index 2c443d63..fba6f1e1 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -1074,6 +1074,56 @@ do_auth_close_test (void) soup_test_server_quit_unref (server); } +static gboolean +infinite_cancel (gpointer session) +{ + soup_session_abort (session); + return FALSE; +} + +static void +infinite_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + soup_auth_authenticate (auth, "user", "bad"); +} + +static void +do_infinite_auth_test (const char *base_uri) +{ + SoupSession *session; + SoupMessage *msg; + char *uri; + int timeout; + + debug_printf (1, "\nTesting broken infinite-loop auth:\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (infinite_authenticate), NULL); + + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + msg = soup_message_new ("GET", uri); + g_free (uri); + + timeout = g_timeout_add (500, infinite_cancel, session); + expect_warning = TRUE; + soup_session_send_message (session, msg); + + if (msg->status_code == SOUP_STATUS_CANCELLED) { + debug_printf (1, " FAILED: Got stuck in loop"); + errors++; + } else if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { + debug_printf (1, " Final status wrong: expected 401, got %u\n", + msg->status_code); + errors++; + } + + g_source_remove (timeout); + soup_test_session_abort_unref (session); + g_object_unref (msg); +} + static SoupAuthTest relogin_tests[] = { { "Auth provided via URL, should succeed", "Basic/realm12/", "1", TRUE, "01", SOUP_STATUS_OK }, @@ -1199,6 +1249,7 @@ main (int argc, char **argv) do_async_auth_test (base_uri); do_select_auth_test (); do_auth_close_test (); + do_infinite_auth_test (base_uri); test_cleanup (); return errors != 0; -- cgit v1.2.1 From 162abf754b75238ed0f772563d602a964e8dc149 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 6 Mar 2013 12:17:19 -0500 Subject: SoupAuthManager: deal with "disappearing" auth headers Normally when sending a 401 response, a server re-sends the initial WWW-Authenticate challenge. However, it doesn't actually have to, and libsoup was getting confused if it didn't. Fix that. https://bugzilla.redhat.com/show_bug.cgi?id=916224 --- libsoup/soup-auth-manager.c | 38 ++++++++++++---------- tests/auth-test.c | 78 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 18 deletions(-) diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index e945dd7c..b1647915 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -83,7 +83,8 @@ typedef struct { static void soup_auth_host_free (SoupAuthHost *host); static SoupAuth *record_auth_for_uri (SoupAuthManagerPrivate *priv, - SoupURI *uri, SoupAuth *auth); + SoupURI *uri, SoupAuth *auth, + gboolean prior_auth_failed); static void soup_auth_manager_init (SoupAuthManager *manager) @@ -378,19 +379,22 @@ create_auth (SoupAuthManagerPrivate *priv, SoupMessage *msg) static gboolean check_auth (SoupMessage *msg, SoupAuth *auth) { - const char *header; - char *challenge; - gboolean ok; + const char *header, *scheme; + char *challenge = NULL; + gboolean ok = TRUE; - header = auth_header_for_message (msg); - if (!header) - return FALSE; + scheme = soup_auth_get_scheme_name (auth); - challenge = soup_auth_manager_extract_challenge (header, soup_auth_get_scheme_name (auth)); - if (!challenge) - return FALSE; + header = auth_header_for_message (msg); + if (header) + challenge = soup_auth_manager_extract_challenge (header, scheme); + if (!challenge) { + ok = FALSE; + challenge = g_strdup (scheme); + } - ok = soup_auth_update (auth, msg, challenge); + if (!soup_auth_update (auth, msg, challenge)) + ok = FALSE; g_free (challenge); return ok; } @@ -432,7 +436,7 @@ make_auto_ntlm_auth (SoupAuthManagerPrivate *priv, SoupAuthHost *host) auth = g_object_new (SOUP_TYPE_AUTH_NTLM, SOUP_AUTH_HOST, host->uri->host, NULL); - record_auth_for_uri (priv, host->uri, auth); + record_auth_for_uri (priv, host->uri, auth, FALSE); g_object_unref (auth); return TRUE; } @@ -497,7 +501,7 @@ authenticate_auth (SoupAuthManager *manager, SoupAuth *auth, static SoupAuth * record_auth_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri, - SoupAuth *auth) + SoupAuth *auth, gboolean prior_auth_failed) { SoupAuthHost *host; SoupAuth *old_auth; @@ -531,11 +535,11 @@ record_auth_for_uri (SoupAuthManagerPrivate *priv, SoupURI *uri, soup_auth_free_protection_space (auth, pspace); /* Now, make sure the auth is recorded. (If there's a - * pre-existing auth, we keep that rather than the new one, + * pre-existing good auth, we keep that rather than the new one, * since the old one might already be authenticated.) */ old_auth = g_hash_table_lookup (host->auths, auth_info); - if (old_auth) { + if (old_auth && (old_auth != auth || !prior_auth_failed)) { g_free (auth_info); return old_auth; } else { @@ -569,7 +573,7 @@ auth_got_headers (SoupMessage *msg, gpointer manager) } new_auth = record_auth_for_uri (priv, soup_message_get_uri (msg), - auth); + auth, prior_auth_failed); g_object_unref (auth); /* If we need to authenticate, try to do it. */ @@ -729,7 +733,7 @@ soup_auth_manager_use_auth (SoupAuthManager *manager, SoupAuthManagerPrivate *priv = manager->priv; g_mutex_lock (&priv->lock); - record_auth_for_uri (priv, uri, auth); + record_auth_for_uri (priv, uri, auth, FALSE); g_mutex_unlock (&priv->lock); } diff --git a/tests/auth-test.c b/tests/auth-test.c index fba6f1e1..992e3d5e 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -817,7 +817,7 @@ select_auth_test_one (SoupURI *uri, } else if (!second_headers && sad.round[1].headers) { debug_printf (1, " Didn't expect a second round!\n"); errors++; - } else if (second_headers) { + } else if (second_headers && second_response) { if (strcmp (sad.round[1].headers, second_headers) != 0) { debug_printf (1, " Second round header order wrong: expected %s, got %s\n", second_headers, sad.round[1].headers); @@ -1124,6 +1124,81 @@ do_infinite_auth_test (const char *base_uri) g_object_unref (msg); } +static void +disappear_request_read (SoupServer *server, SoupMessage *msg, + SoupClientContext *context, gpointer user_data) +{ + /* Remove the WWW-Authenticate header if this was a failed attempt */ + if (soup_message_headers_get_one (msg->request_headers, "Authorization") && + msg->status_code == SOUP_STATUS_UNAUTHORIZED) + soup_message_headers_remove (msg->response_headers, "WWW-Authenticate"); +} + +static void +disappear_authenticate (SoupSession *session, SoupMessage *msg, + SoupAuth *auth, gboolean retrying, gpointer data) +{ + int *counter = data; + + (*counter)++; + if (!retrying) + soup_auth_authenticate (auth, "user", "bad"); +} + +static void +do_disappearing_auth_test (void) +{ + SoupServer *server; + SoupAuthDomain *auth_domain; + SoupURI *uri; + SoupMessage *msg; + SoupSession *session; + int counter; + + debug_printf (1, "\nTesting auth when server does not repeat challenge on failure:\n"); + + server = soup_test_server_new (FALSE); + soup_server_add_handler (server, NULL, + server_callback, NULL, NULL); + + uri = soup_uri_new ("http://127.0.0.1/"); + soup_uri_set_port (uri, soup_server_get_port (server)); + + auth_domain = soup_auth_domain_basic_new ( + SOUP_AUTH_DOMAIN_REALM, "auth-test", + SOUP_AUTH_DOMAIN_ADD_PATH, "/", + SOUP_AUTH_DOMAIN_BASIC_AUTH_CALLBACK, server_basic_auth_callback, + NULL); + soup_server_add_auth_domain (server, auth_domain); + g_signal_connect (server, "request-read", + G_CALLBACK (disappear_request_read), NULL); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + counter = 0; + g_signal_connect (session, "authenticate", + G_CALLBACK (disappear_authenticate), &counter); + + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (session, msg); + + if (counter > 2) { + debug_printf (1, " FAILED: Got stuck in loop"); + errors++; + } else if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { + debug_printf (1, " Final status wrong: expected 401, got %u\n", + msg->status_code); + errors++; + } + + g_object_unref (msg); + soup_test_session_abort_unref (session); + + g_object_unref (auth_domain); + soup_uri_free (uri); + soup_test_server_quit_unref (server); +} + static SoupAuthTest relogin_tests[] = { { "Auth provided via URL, should succeed", "Basic/realm12/", "1", TRUE, "01", SOUP_STATUS_OK }, @@ -1250,6 +1325,7 @@ main (int argc, char **argv) do_select_auth_test (); do_auth_close_test (); do_infinite_auth_test (base_uri); + do_disappearing_auth_test (); test_cleanup (); return errors != 0; -- cgit v1.2.1 From 69a9eefbca3b3b75eea7445fc6d1f7dce5df52c5 Mon Sep 17 00:00:00 2001 From: Enrico Nicoletto Date: Wed, 6 Mar 2013 23:57:19 -0300 Subject: Updated Brazilian Portuguese translation --- po/pt_BR.po | 60 +++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/po/pt_BR.po b/po/pt_BR.po index 3a213e15..c567838b 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -1,22 +1,23 @@ # Brazilian Portuguese translation for libsoup. -# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# Copyright (C) 2013 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # Gabriel F. Vilar , 2012. -# +# Enrico Nicoletto , 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-12 12:36+0000\n" -"PO-Revision-Date: 2012-09-12 09:48-0300\n" -"Last-Translator: Rafael Ferreira \n" +"POT-Creation-Date: 2013-03-06 19:50+0000\n" +"PO-Revision-Date: 2013-02-28 10:19-0300\n" +"Last-Translator: Enrico Nicoletto \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 1.5.4\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -24,59 +25,84 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "A conexão terminou inesperadamente" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Requisição de busca inválida" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Não foi possível truncar SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "O fluxo de rede fechou de forma inesperada" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Falha ao armazenar completamente em cache o recurso" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "O buffer de saída é muito pequeno" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Não foi possível analisar a resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificação de resposta HTTP não reconhecível" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "A operação foi cancelada" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "A operação será bloqueada" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Não foi possível analisar a solicitação HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Nenhuma URI foi fornecida" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI: %s inválida '%s'" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4208 #, c-format msgid "Could not parse URI '%s'" msgstr "Não foi possível analisar URI '%s'" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4245 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Esquema de URI não suportado '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4267 +#, c-format +msgid "Not an HTTP URI" +msgstr "Não é um URI do tipo HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "O nome da máquina é um endereço de IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "O nome da máquina é inválido" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Nome da máquina não está na base do domínio" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Não há domínios suficientes" -- cgit v1.2.1 From 4ea885c0e036c6978d1af26ba44434f7796738f5 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Thu, 7 Mar 2013 18:06:46 +0300 Subject: Updated Belarusian translation. --- po/be.po | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/po/be.po b/po/be.po index 12f12d96..e2b35341 100644 --- a/po/be.po +++ b/po/be.po @@ -5,7 +5,7 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-18 15:49+0000\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" "PO-Revision-Date: 2012-09-14 13:29+0300\n" "Last-Translator: Ihar Hrachyshka \n" "Language-Team: Belarusian \n" @@ -20,18 +20,22 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Злучэнне нечакана перарвана" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Хібны запыт пракручвання змесціва" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Немагчыма абрэзаць SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Сеткавы струмень нечакана закрыўся" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Не ўдалося цалкам змясціць рэсурс у кэш-памяці" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -57,43 +61,43 @@ msgstr "Аперацыя заблакіруе працэс" msgid "Could not parse HTTP request" msgstr "Не ўдалося разабраць HTTP-запыт" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "URI-адрас не пададзены" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Хібны URI-адрас \"%s\": %s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Не ўдалося разабраць URI-адрас \"%s\"" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "URI-схема \"%s\" не падтрымліваецца" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" msgstr "Гэта не HTTP URI-адрас" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Назва хоста з'яўляецца IP-адрасам" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Хібная назва хоста" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Назва хоста не мае базавага дамена" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Не хапае даменаў" -- cgit v1.2.1 From 24aaa6d7566eacc8f848f22d213a09a44a061121 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 16 Feb 2013 19:20:18 -0500 Subject: Add SoupSession:proxy-resolver Now that GSocketClient lets you override its proxy resolver, allow setting a GProxyResolver on a SoupSession, to eventually pass on to the GSocketClient. (In the interest of not breaking things this late in the release cycle, all of the old SoupProxyURIResolver code still exists as well, in parallel, but in 2.43 it will be removed and replaced with GProxyResolver-based backward-compat stuff.) https://bugzilla.gnome.org/show_bug.cgi?id=680273 --- libsoup/soup-connection.c | 48 +++++++++++++++++++++------------- libsoup/soup-connection.h | 3 ++- libsoup/soup-misc-private.h | 2 +- libsoup/soup-session.c | 64 ++++++++++++++++++++++++++++++++++++++------- libsoup/soup-session.h | 1 + libsoup/soup-socket.c | 31 ++++++++++++---------- 6 files changed, 105 insertions(+), 44 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index a3322e39..bcc5af48 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -20,8 +20,8 @@ typedef struct { SoupAddress *local_addr; SoupURI *remote_uri, *proxy_uri; - SoupProxyURIResolver *proxy_resolver; - gboolean use_gproxyresolver; + SoupProxyURIResolver *soup_proxy_resolver; + GProxyResolver *g_proxy_resolver; GTlsDatabase *tlsdb; gboolean ssl, ssl_strict, ssl_fallback; @@ -52,7 +52,8 @@ enum { PROP_LOCAL_ADDRESS, PROP_REMOTE_URI, - PROP_PROXY_RESOLVER, + PROP_SOUP_PROXY_RESOLVER, + PROP_G_PROXY_RESOLVER, PROP_SSL, PROP_SSL_CREDS, PROP_SSL_STRICT, @@ -86,7 +87,8 @@ soup_connection_finalize (GObject *object) g_clear_pointer (&priv->remote_uri, soup_uri_free); g_clear_pointer (&priv->proxy_uri, soup_uri_free); g_clear_object (&priv->tlsdb); - g_clear_object (&priv->proxy_resolver); + g_clear_object (&priv->soup_proxy_resolver); + g_clear_object (&priv->g_proxy_resolver); g_clear_object (&priv->local_addr); g_clear_pointer (&priv->async_context, g_main_context_unref); @@ -123,12 +125,15 @@ soup_connection_set_property (GObject *object, guint prop_id, case PROP_REMOTE_URI: priv->remote_uri = g_value_dup_boxed (value); break; - case PROP_PROXY_RESOLVER: + case PROP_SOUP_PROXY_RESOLVER: proxy_resolver = g_value_get_object (value); if (proxy_resolver && SOUP_IS_PROXY_RESOLVER_DEFAULT (proxy_resolver)) - priv->use_gproxyresolver = TRUE; + priv->g_proxy_resolver = g_object_ref (g_proxy_resolver_get_default ()); else if (proxy_resolver) - priv->proxy_resolver = g_object_ref (proxy_resolver); + priv->soup_proxy_resolver = g_object_ref (proxy_resolver); + break; + case PROP_G_PROXY_RESOLVER: + priv->g_proxy_resolver = g_value_dup_object (value); break; case PROP_SSL: priv->ssl = g_value_get_boolean (value); @@ -262,12 +267,19 @@ soup_connection_class_init (SoupConnectionClass *connection_class) SOUP_TYPE_URI, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( - object_class, PROP_PROXY_RESOLVER, - g_param_spec_object (SOUP_CONNECTION_PROXY_RESOLVER, + object_class, PROP_SOUP_PROXY_RESOLVER, + g_param_spec_object (SOUP_CONNECTION_SOUP_PROXY_RESOLVER, "Proxy resolver", - "SoupProxyURIResolver to use", + "SoupProxyResolver to use", SOUP_TYPE_PROXY_URI_RESOLVER, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property ( + object_class, PROP_G_PROXY_RESOLVER, + g_param_spec_object (SOUP_CONNECTION_G_PROXY_RESOLVER, + "Proxy resolver", + "GProxyResolver to use", + G_TYPE_PROXY_RESOLVER, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( object_class, PROP_SSL, g_param_spec_boolean (SOUP_CONNECTION_SSL, @@ -507,7 +519,7 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data) return; } - if (priv->use_gproxyresolver) + if (priv->g_proxy_resolver) priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); if (priv->ssl && !priv->proxy_uri) { @@ -540,7 +552,7 @@ connect_async_to_uri (SoupConnectionAsyncConnectData *data, SoupURI *uri) SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback, SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context, SOUP_SOCKET_USE_THREAD_CONTEXT, priv->use_thread_context, - SOUP_SOCKET_USE_PROXY, priv->use_gproxyresolver, + SOUP_SOCKET_PROXY_RESOLVER, priv->g_proxy_resolver, SOUP_SOCKET_TIMEOUT, priv->io_timeout, SOUP_SOCKET_CLEAN_DISPOSE, TRUE, SOUP_SOCKET_LOCAL_ADDRESS, priv->local_addr, @@ -597,7 +609,7 @@ soup_connection_connect_async (SoupConnection *conn, data->callback_data = user_data; data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - if (!priv->proxy_resolver) { + if (!priv->soup_proxy_resolver) { connect_async_to_uri (data, priv->remote_uri); return; } @@ -607,7 +619,7 @@ soup_connection_connect_async (SoupConnection *conn, else async_context = priv->async_context; - soup_proxy_uri_resolver_get_proxy_uri_async (priv->proxy_resolver, + soup_proxy_uri_resolver_get_proxy_uri_async (priv->soup_proxy_resolver, priv->remote_uri, async_context, cancellable, @@ -629,8 +641,8 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); - if (priv->proxy_resolver) { - status = soup_proxy_uri_resolver_get_proxy_uri_sync (priv->proxy_resolver, + if (priv->soup_proxy_resolver) { + status = soup_proxy_uri_resolver_get_proxy_uri_sync (priv->soup_proxy_resolver, priv->remote_uri, cancellable, &priv->proxy_uri); @@ -647,7 +659,7 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) remote_addr = soup_address_new (connect_uri->host, connect_uri->port); priv->socket = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, - SOUP_SOCKET_USE_PROXY, priv->use_gproxyresolver, + SOUP_SOCKET_PROXY_RESOLVER, priv->g_proxy_resolver, SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb, SOUP_SOCKET_SSL_STRICT, priv->ssl_strict, SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback, @@ -665,7 +677,7 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) if (!SOUP_STATUS_IS_SUCCESSFUL (status)) goto fail; - if (priv->use_gproxyresolver) + if (priv->g_proxy_resolver) priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); if (priv->ssl && !priv->proxy_uri) { diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h index 50fb7018..dcfb56ac 100644 --- a/libsoup/soup-connection.h +++ b/libsoup/soup-connection.h @@ -41,7 +41,8 @@ typedef void (*SoupConnectionCallback) (SoupConnection *conn, #define SOUP_CONNECTION_LOCAL_ADDRESS "local-address" #define SOUP_CONNECTION_REMOTE_URI "remote-uri" -#define SOUP_CONNECTION_PROXY_RESOLVER "proxy-resolver" +#define SOUP_CONNECTION_SOUP_PROXY_RESOLVER "soup-proxy-resolver" +#define SOUP_CONNECTION_G_PROXY_RESOLVER "g-proxy-resolver" #define SOUP_CONNECTION_SSL "ssl" #define SOUP_CONNECTION_SSL_CREDENTIALS "ssl-creds" #define SOUP_CONNECTION_SSL_STRICT "ssl-strict" diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index 79e73bc6..b9f0724f 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -23,7 +23,7 @@ GIOStream *soup_socket_get_connection (SoupSocket *sock); GIOStream *soup_socket_get_iostream (SoupSocket *sock); #define SOUP_SOCKET_CLEAN_DISPOSE "clean-dispose" -#define SOUP_SOCKET_USE_PROXY "use-proxy" +#define SOUP_SOCKET_PROXY_RESOLVER "proxy-resolver" SoupURI *soup_socket_get_http_proxy_uri (SoupSocket *sock); /* At some point it might be possible to mark additional methods diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index a153cde5..14e2be47 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -122,6 +122,7 @@ typedef struct { GSList *run_queue_sources; GResolver *resolver; + GProxyResolver *g_proxy_resolver; char **http_aliases, **https_aliases; @@ -173,6 +174,7 @@ enum { PROP_0, PROP_PROXY_URI, + PROP_PROXY_RESOLVER, PROP_MAX_CONNS, PROP_MAX_CONNS_PER_HOST, PROP_USE_NTLM, @@ -335,6 +337,7 @@ soup_session_finalize (GObject *object) g_hash_table_destroy (priv->features_cache); g_object_unref (priv->resolver); + g_clear_object (&priv->g_proxy_resolver); g_free (priv->http_aliases); g_free (priv->https_aliases); @@ -556,23 +559,26 @@ soup_session_set_property (GObject *object, guint prop_id, break; case PROP_PROXY_URI: uri = g_value_get_boxed (value); - if (uri) { -#ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS -G_GNUC_BEGIN_IGNORE_DEPRECATIONS -#endif + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER); -#ifdef G_GNUC_END_IGNORE_DEPRECATIONS -G_GNUC_END_IGNORE_DEPRECATIONS -#endif + G_GNUC_END_IGNORE_DEPRECATIONS; feature = SOUP_SESSION_FEATURE (soup_proxy_resolver_static_new (uri)); soup_session_add_feature (session, feature); g_object_unref (feature); } else soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_STATIC); - + g_clear_object (&priv->g_proxy_resolver); soup_session_abort (session); break; + case PROP_PROXY_RESOLVER: + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER); + G_GNUC_END_IGNORE_DEPRECATIONS; + if (priv->g_proxy_resolver) + g_object_unref (priv->g_proxy_resolver); + priv->g_proxy_resolver = g_value_dup_object (value); + break; case PROP_MAX_CONNS: priv->max_conns = g_value_get_int (value); break; @@ -702,6 +708,9 @@ soup_session_get_property (GObject *object, guint prop_id, } else g_value_set_boxed (value, NULL); break; + case PROP_PROXY_RESOLVER: + g_value_set_object (value, priv->g_proxy_resolver); + break; case PROP_MAX_CONNS: g_value_set_int (value, priv->max_conns); break; @@ -1662,7 +1671,8 @@ get_connection_for_host (SoupSession *session, conn = g_object_new ( SOUP_TYPE_CONNECTION, SOUP_CONNECTION_REMOTE_URI, host->uri, - SOUP_CONNECTION_PROXY_RESOLVER, soup_session_get_feature (session, SOUP_TYPE_PROXY_URI_RESOLVER), + SOUP_CONNECTION_SOUP_PROXY_RESOLVER, soup_session_get_feature (session, SOUP_TYPE_PROXY_URI_RESOLVER), + SOUP_CONNECTION_G_PROXY_RESOLVER, priv->g_proxy_resolver, SOUP_CONNECTION_SSL, uri_is_https (priv, soup_message_get_uri (item->msg)), SOUP_CONNECTION_SSL_CREDENTIALS, priv->tlsdb, SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (priv->tlsdb != NULL || SOUP_IS_PLAIN_SESSION (session)), @@ -2458,6 +2468,10 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature) g_return_if_fail (SOUP_IS_SESSION_FEATURE (feature)); priv = SOUP_SESSION_GET_PRIVATE (session); + + if (SOUP_IS_PROXY_URI_RESOLVER (feature)) + g_clear_object (&priv->g_proxy_resolver); + priv->features = g_slist_prepend (priv->features, g_object_ref (feature)); g_hash_table_remove_all (priv->features_cache); soup_session_feature_attach (feature, session); @@ -2955,7 +2969,8 @@ soup_session_class_init (SoupSessionClass *session_class) * An http proxy to use for all http and https requests in * this session. Setting this will remove any * #SoupProxyURIResolver features that have been added to the - * session. + * session. Setting this property will also cancel all + * currently pending messages. * * Note that #SoupProxyResolverDefault will handle looking up * the user's proxy settings for you; you should only use @@ -2974,6 +2989,35 @@ soup_session_class_init (SoupSessionClass *session_class) "The HTTP Proxy to use for this session", SOUP_TYPE_URI, G_PARAM_READWRITE)); + /** + * SoupSession:proxy-resolver: + * + * A #GProxyResolver to use with this session. Setting this + * will clear the #SoupSession:proxy-uri property, and remove + * any #SoupProxyURIResolver features that have been added to + * the session. + * + * You only need to set this if you want to manually control + * proxy resolution (and need to do something more complicated than + * #SoupSession:proxy-uri allows). If you just want to use the + * system proxy settings, #SoupProxyResolverDefault will do that + * for you, and that is automatically part of the session if you + * are using a plain #SoupSession. + * + * Since: 2.42 + */ + /** + * SOUP_SESSION_PROXY_RESOLVER: + * + * Alias for the #SoupSession:proxy-resolver property, qv. + **/ + g_object_class_install_property ( + object_class, PROP_PROXY_RESOLVER, + g_param_spec_object (SOUP_SESSION_PROXY_RESOLVER, + "Proxy Resolver", + "The GProxyResolver to use for this session", + G_TYPE_PROXY_RESOLVER, + G_PARAM_READWRITE)); /** * SOUP_SESSION_MAX_CONNS: * diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index 9d0f232d..67a59eaa 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -62,6 +62,7 @@ GType soup_session_get_type (void); #define SOUP_SESSION_LOCAL_ADDRESS "local-address" #define SOUP_SESSION_PROXY_URI "proxy-uri" +#define SOUP_SESSION_PROXY_RESOLVER "proxy-resolver" #define SOUP_SESSION_MAX_CONNS "max-conns" #define SOUP_SESSION_MAX_CONNS_PER_HOST "max-conns-per-host" #define SOUP_SESSION_USE_NTLM "use-ntlm" diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 885d5318..4268429b 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -58,7 +58,7 @@ enum { PROP_CLEAN_DISPOSE, PROP_TLS_CERTIFICATE, PROP_TLS_ERRORS, - PROP_USE_PROXY, + PROP_PROXY_RESOLVER, LAST_PROP }; @@ -70,6 +70,7 @@ typedef struct { GInputStream *istream; GOutputStream *ostream; GTlsCertificateFlags tls_errors; + GProxyResolver *proxy_resolver; guint non_blocking:1; guint is_server:1; @@ -78,7 +79,6 @@ typedef struct { guint ssl_fallback:1; guint clean_dispose:1; guint use_thread_context:1; - guint use_proxy:1; gpointer ssl_creds; GMainContext *async_context; @@ -149,6 +149,8 @@ soup_socket_finalize (GObject *object) g_clear_object (&priv->local_addr); g_clear_object (&priv->remote_addr); + g_clear_object (&priv->proxy_resolver); + if (priv->watch_src) { if (priv->clean_dispose && !priv->is_server) g_warning ("Disposing socket %p during async op", object); @@ -219,8 +221,8 @@ soup_socket_set_property (GObject *object, guint prop_id, if (priv->conn) g_socket_set_timeout (priv->gsock, priv->timeout); break; - case PROP_USE_PROXY: - priv->use_proxy = g_value_get_boolean (value); + case PROP_PROXY_RESOLVER: + priv->proxy_resolver = g_value_dup_object (value); break; case PROP_CLEAN_DISPOSE: priv->clean_dispose = g_value_get_boolean (value); @@ -280,8 +282,8 @@ soup_socket_get_property (GObject *object, guint prop_id, case PROP_TLS_ERRORS: g_value_set_flags (value, priv->tls_errors); break; - case PROP_USE_PROXY: - g_value_set_boolean (value, priv->use_proxy); + case PROP_PROXY_RESOLVER: + g_value_set_object (value, priv->proxy_resolver); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -618,12 +620,12 @@ soup_socket_class_init (SoupSocketClass *socket_class) G_PARAM_READABLE)); g_object_class_install_property ( - object_class, PROP_USE_PROXY, - g_param_spec_boolean (SOUP_SOCKET_USE_PROXY, - "Use proxy", - "Use #GProxyResolver", - FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + object_class, PROP_PROXY_RESOLVER, + g_param_spec_object (SOUP_SOCKET_PROXY_RESOLVER, + "Proxy resolver", + "GProxyResolver to use", + G_TYPE_PROXY_RESOLVER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } @@ -705,9 +707,10 @@ new_socket_client (SoupSocket *sock) g_signal_connect (client, "event", G_CALLBACK (re_emit_socket_client_event), sock); - if (priv->use_proxy) + if (priv->proxy_resolver) { + g_socket_client_set_proxy_resolver (client, priv->proxy_resolver); g_socket_client_add_application_proxy (client, "http"); - else + } else g_socket_client_set_enable_proxy (client, FALSE); if (priv->timeout) g_socket_client_set_timeout (client, priv->timeout); -- cgit v1.2.1 From f2cc0847347cca8b85abdc7c4d6814195d440d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Urban=C4=8Di=C4=8D?= Date: Thu, 7 Mar 2013 17:02:43 +0100 Subject: Updated Slovenian translation --- po/sl.po | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/po/sl.po b/po/sl.po index 2573f87e..483f0337 100644 --- a/po/sl.po +++ b/po/sl.po @@ -9,8 +9,8 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-20 10:15+0000\n" -"PO-Revision-Date: 2012-12-22 15:17+0100\n" +"POT-Creation-Date: 2013-03-07 15:08+0000\n" +"PO-Revision-Date: 2013-03-07 17:00+0100\n" "Last-Translator: Matej Urbančič \n" "Language-Team: Slovenian \n" "Language: sl\n" @@ -28,18 +28,22 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Povezava je nepričakovano končana" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Neveljavna zahteva iskanja" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Ni mogoče porezati SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Omrežni pretok se je nepričakovano zaprl" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Ustvarjanje predpomnilnika vira je spodletelo" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -65,43 +69,43 @@ msgstr "Opravilo bi zaustavilo delovanje" msgid "Could not parse HTTP request" msgstr "Zahteve HTTP ni mogoče razčleniti" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Ni podanega naslova URI" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Neveljaven naslov URI '%s': %s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "Ni mogoče razčleniti naslova URI '%s'" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nepodprta shema URI '%s'" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4311 #, c-format msgid "Not an HTTP URI" msgstr "Naslov ni v obliki HTTP URI" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Ime gostitelja je naslov IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Neveljavno ime gostitelja" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Ime gostitelja je brez osnovne domene" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Ni dovolj domen" -- cgit v1.2.1 From b21b3b3b6a7555db2e3d9418c62c52305a5127c8 Mon Sep 17 00:00:00 2001 From: Theppitak Karoonboonyanan Date: Sat, 9 Mar 2013 11:38:55 +0700 Subject: Updated Thai translation --- po/th.po | 60 +++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/po/th.po b/po/th.po index 11639625..b2c806a0 100644 --- a/po/th.po +++ b/po/th.po @@ -1,16 +1,17 @@ # Thai translation for libsoup. -# Copyright (C) 2012 Free Software Foundation, Inc. +# Copyright (C) 2012-2013 Free Software Foundation, Inc. # This file is distributed under the same license as the libsoup package. -# knight2000 , 2012. +# Akom Chotiphantawanon , 2012. +# Theppitak Karoonboonyanan , 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-21 07:06+0000\n" -"PO-Revision-Date: 2012-09-21 18:49+0700\n" -"Last-Translator: Akom Chotiphantawanon \n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-09 11:38+0700\n" +"Last-Translator: Theppitak Karoonboonyanan \n" "Language-Team: Thai \n" "Language: th\n" "MIME-Version: 1.0\n" @@ -23,59 +24,84 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "การเชื่อมต่อยุติกะทันหัน" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "การร้องขอการเลื่อนตำแหน่งไม่ถูกต้อง" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "ไม่สามารถตัดท้าย SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "สตรีมเครือข่ายปิดกะทันหัน" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "ทำแคชทรัพยากรไม่เสร็จสมบูรณ์" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "บัฟเฟอร์ข้อมูลออกเล็กเกินไป" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "ไม่สามารถแจงคำตอบ HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "ไม่รู้จักรหัสอักขระของคำตอบ HTTP" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "การทำงานถูกยกเลิก" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "การทำงานถูกบล็อค" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "ไม่สามารถแจงคำร้อง HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "ไม่ได้ระบุ URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI '%s' ไม่ถูกต้อง: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "ไม่สามารถแจง URI '%s'" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "ไม่รองรับ URI แบบ '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "ไม่ใช่ URI ของ HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "ชื่อโฮสต์เป็นหมายเลขไอพี" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "ชื่อโฮสต์ผิดรูปแบบ" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "ชื่อโฮสต์ไม่มีโดเมนฐาน" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "มีโดเมนน้อยเกินไป" -- cgit v1.2.1 From a7a9a8eaa34a340884228e2085ffea377b848da0 Mon Sep 17 00:00:00 2001 From: Dimitris Spingos Date: Sat, 9 Mar 2013 11:44:56 +0200 Subject: Updated Greek translation --- po/el.po | 67 ++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/po/el.po b/po/el.po index 60cb80b7..d71f863d 100644 --- a/po/el.po +++ b/po/el.po @@ -2,21 +2,23 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # Tom Tryfonidis , 2012. -# +# Dimitris Spingos (Δημήτρης Σπίγγος) , 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-10 21:43+0200\n" -"Last-Translator: Tom Tryfonidis \n" -"Language-Team: Greek \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-09 11:44+0300\n" +"Last-Translator: Dimitris Spingos (Δημήτρης Σπίγγος) \n" +"Language-Team: team@gnome.gr\n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -24,59 +26,86 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Η σύνδεση τερματίστηκε απρόσμενα" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Άκυρη αίτηση αναζήτησης" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Αδυναμία περικοπής του SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Η ροή του δικτύου έκλεισε αναπάντεχα" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Αποτυχία πλήρους απόκρυψης του πόρου" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Η ενδιάμεση μνήμη εξόδου είναι πολύ μικρή" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Αδυναμία ανάλυσης της απάντησης HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Μη αναγνωρίσιμη κωδικοποίηση απάντησης HTTP" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Η λειτουργία ακυρώθηκε" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Η λειτουργία θα μπλοκαριστεί" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Αδυναμία ανάλυσης αιτήματος HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Δεν έχει δοθεί URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Μη έγκυρο '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Αδυναμία ανάλυσης URI '%s'" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Μη υποστηριζόμενο URI σχήμα '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "Δεν είναι URI HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Το όνομα συστήματος είναι μια διεύθυνση IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Μη έγκυρο όνομα συστήματος" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Το όνομα συστήματος δεν έχει βασικό τομέα" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Δεν υπάρχουν αρκετοί τομείς" -- cgit v1.2.1 From 61d321fa2cfb1ffb34a7c9fc151287c271b4cca4 Mon Sep 17 00:00:00 2001 From: Milo Casagrande Date: Mon, 11 Mar 2013 17:00:46 +0100 Subject: [l10n] Updated Italian translation. --- po/it.po | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/po/it.po b/po/it.po index 04cddbef..ba800dba 100644 --- a/po/it.po +++ b/po/it.po @@ -1,15 +1,15 @@ # Italian translations for libsoup package # Copyright (C) 2012, 2013 the Free Software Foundation, Inc. # This file is distributed under the same license as the libsoup package. -# Milo Casagrande , 2012, 2013. +# Milo Casagrande , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-24 21:45+0100\n" -"PO-Revision-Date: 2013-01-24 21:47+0100\n" -"Last-Translator: Milo Casagrande \n" +"POT-Creation-Date: 2013-03-11 16:59+0100\n" +"PO-Revision-Date: 2013-03-11 17:00+0100\n" +"Last-Translator: Milo Casagrande \n" "Language-Team: Italian \n" "Language: it\n" "MIME-Version: 1.0\n" @@ -31,10 +31,14 @@ msgstr "Richiesta di posizionamento non valida" msgid "Cannot truncate SoupBodyInputStream" msgstr "Impossibile troncare SoupBodyInputStream" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "Flusso di rete chiuso inaspettatamente" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Salvataggio in memoria della risorsa non riuscito" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -70,17 +74,17 @@ msgstr "Nessun URI fornito" msgid "Invalid '%s' URI: %s" msgstr "URI «%s» non valido: %s" -#: ../libsoup/soup-session.c:4123 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "Impossibile analizzare l'URI «%s»" -#: ../libsoup/soup-session.c:4160 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Schema URI «%s» non supportato" -#: ../libsoup/soup-session.c:4182 +#: ../libsoup/soup-session.c:4311 #, c-format msgid "Not an HTTP URI" msgstr "Non è uno URI HTTP" -- cgit v1.2.1 From c1c58c9fc79562b0da4ceeeb3fc378407f8b9c85 Mon Sep 17 00:00:00 2001 From: Zan Dobersek Date: Thu, 7 Mar 2013 21:23:15 +0100 Subject: data: URL requests should serve the whole decoded URL Address the possibility of data: URLs containing null characters when the data request is being performed. The uri_decoded_copy method is enhanced with a third argument, a pointer to an integer that should be set to the length of decoded data when provided. This length is then set as the request's content length. A test checking the correct behavior is added in requester-test. Calls to uri_decoded_copy where the length of the decoded output is not required are adjusted to provide NULL as the third argument. --- libsoup/soup-misc-private.h | 2 +- libsoup/soup-request-data.c | 7 ++-- libsoup/soup-uri.c | 13 ++++--- tests/requester-test.c | 86 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index b9f0724f..cd836189 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -9,7 +9,7 @@ #include "soup-socket.h" -char *uri_decoded_copy (const char *str, int length); +char *uri_decoded_copy (const char *str, int length, int *decoded_length); guint soup_socket_handshake_sync (SoupSocket *sock, GCancellable *cancellable); diff --git a/libsoup/soup-request-data.c b/libsoup/soup-request-data.c index 66836a5b..246854a7 100644 --- a/libsoup/soup-request-data.c +++ b/libsoup/soup-request-data.c @@ -96,7 +96,7 @@ soup_request_data_send (SoupRequest *request, end = comma; if (end != start) - data->priv->content_type = uri_decoded_copy (start, end - start); + data->priv->content_type = uri_decoded_copy (start, end - start, NULL); } memstream = g_memory_input_stream_new (); @@ -105,12 +105,13 @@ soup_request_data_send (SoupRequest *request, start = comma + 1; if (*start) { - guchar *buf = (guchar *) soup_uri_decode (start); + int decoded_length = 0; + guchar *buf = (guchar *) uri_decoded_copy (start, strlen (start), &decoded_length); if (base64) buf = g_base64_decode_inplace ((gchar*) buf, &data->priv->content_length); else - data->priv->content_length = strlen ((const char *) buf); + data->priv->content_length = decoded_length; g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (memstream), buf, data->priv->content_length, diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 28b3025c..723e3610 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -291,14 +291,14 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) colon = strchr (uri_string, ':'); if (colon && colon < at) { uri->password = uri_decoded_copy (colon + 1, - at - colon - 1); + at - colon - 1, NULL); } else { uri->password = NULL; colon = at; } uri->user = uri_decoded_copy (uri_string, - colon - uri_string); + colon - uri_string, NULL); uri_string = at + 1; } else uri->user = uri->password = NULL; @@ -320,7 +320,7 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) hostend = colon ? colon : path; } - uri->host = uri_decoded_copy (uri_string, hostend - uri_string); + uri->host = uri_decoded_copy (uri_string, hostend - uri_string, NULL); if (colon && colon != path - 1) { char *portend; @@ -694,7 +694,7 @@ soup_uri_encode (const char *part, const char *escape_extra) #define HEXCHAR(s) ((XDIGIT (s[1]) << 4) + XDIGIT (s[2])) char * -uri_decoded_copy (const char *part, int length) +uri_decoded_copy (const char *part, int length, int *decoded_length) { unsigned char *s, *d; char *decoded = g_strndup (part, length); @@ -715,6 +715,9 @@ uri_decoded_copy (const char *part, int length) *d++ = *s; } while (*s++); + if (decoded_length) + *decoded_length = d - (unsigned char *)decoded - 1; + return decoded; } @@ -735,7 +738,7 @@ soup_uri_decode (const char *part) { g_return_val_if_fail (part != NULL, NULL); - return uri_decoded_copy (part, strlen (part)); + return uri_decoded_copy (part, strlen (part), NULL); } static char * diff --git a/tests/requester-test.c b/tests/requester-test.c index a4bb5b62..147ba4c3 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -649,6 +649,90 @@ do_sync_test (const char *uri_string, gboolean plain_session) soup_uri_free (uri); } + +static void +do_null_char_request (SoupSession *session, const char *encoded_data, + const char *expected_data, int expected_len) +{ + GError *error = NULL; + GInputStream *stream; + SoupRequest *request; + SoupURI *uri; + char *uri_string, buf[256]; + gsize nread; + + uri_string = g_strdup_printf ("data:text/html,%s", encoded_data); + uri = soup_uri_new (uri_string); + g_free (uri_string); + + request = soup_session_request_uri (session, uri, NULL); + stream = soup_test_request_send (request, NULL, 0, &error); + + if (error) { + debug_printf (1, " could not send request: %s\n", error->message); + g_error_free (error); + g_object_unref (request); + soup_uri_free (uri); + return; + } + + g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error); + if (error) { + debug_printf (1, " could not read response: %s\n", error->message); + errors++; + g_clear_error (&error); + } + + soup_test_request_close_stream (request, stream, NULL, &error); + if (error) { + debug_printf (1, " could not close stream: %s\n", error->message); + errors++; + g_clear_error (&error); + } + + if (nread != expected_len) { + debug_printf (1, " response length mismatch: expected %d, got %lu\n", expected_len, nread); + errors++; + } else if (memcmp (buf, expected_data, nread) != 0) { + debug_printf (1, " response data mismatch\n"); + errors++; + } + + g_object_unref (stream); + g_object_unref (request); + soup_uri_free (uri); +} + +static void +do_null_char_test (gboolean plain_session) +{ + SoupSession *session; + int i; + static struct { + const char *encoded_data; + const char *expected_data; + int expected_len; + } test_cases[] = { + { "%3Cscript%3Ea%3D'%00'%3C%2Fscript%3E", "", 22 }, + { "%00%3Cscript%3Ea%3D42%3C%2Fscript%3E", "\0", 22 }, + { "%3Cscript%3E%00%3Cbr%2F%3E%3C%2Fscript%3E%00", "\0", 24 }, + }; + static int num_test_cases = G_N_ELEMENTS(test_cases); + + debug_printf (1, "Streaming data URLs containing null chars with %s\n", + plain_session ? "SoupSession" : "SoupSessionSync"); + + session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + + for (i = 0; i < num_test_cases; i++) + do_null_char_request (session, test_cases[i].encoded_data, + test_cases[i].expected_data, test_cases[i].expected_len); + + soup_test_session_abort_unref (session); +} + int main (int argc, char **argv) { @@ -666,11 +750,13 @@ main (int argc, char **argv) do_thread_test (uri, FALSE); do_context_test (uri, FALSE); do_sync_test (uri, FALSE); + do_null_char_test (FALSE); do_simple_test (uri, TRUE); do_thread_test (uri, TRUE); do_context_test (uri, TRUE); do_sync_test (uri, TRUE); + do_null_char_test (TRUE); g_free (uri); soup_buffer_free (response); -- cgit v1.2.1 From fe685d999f49785a22cbd99fcf92f345cdfaaf4a Mon Sep 17 00:00:00 2001 From: Duarte Loreto Date: Mon, 11 Mar 2013 22:55:08 +0000 Subject: Updated Portuguese translation and converted to New Spelling (Novo AO) --- po/pt.po | 65 ++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/po/pt.po b/po/pt.po index 39bcbcb3..7db149fb 100644 --- a/po/pt.po +++ b/po/pt.po @@ -1,14 +1,14 @@ -# libsoup's Portuguese translation. -# Copyright © 2012 libsoup -# This file is distributed under the same license as the libsoup package. -# Duarte Loreto , 2012. -# +# libsoup's Portuguese translation. +# Copyright © 2012, 2013 libsoup +# This file is distributed under the same license as the libsoup package. +# Duarte Loreto , 2012, 2013. +# msgid "" msgstr "" -"Project-Id-Version: 3.6\n" +"Project-Id-Version: 3.8\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-12 23:36+0100\n" -"PO-Revision-Date: 2012-09-12 23:37+0100\n" +"POT-Creation-Date: 2013-03-11 22:54+0000\n" +"PO-Revision-Date: 2013-03-11 23:00+0100\n" "Last-Translator: Duarte Loreto \n" "Language-Team: Portuguese \n" "Language: pt\n" @@ -22,59 +22,84 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Ligação terminou inesperadamente" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Pedido de procura inválido" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Incapaz de truncar SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Fluxo de rede terminado inesperadamente" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Falha ao colocar o recurso totalmente em cache" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Buffer de resultado é demasiado pequeno" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Incapaz de processar a resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codificação de resposta HTTP desconhecida" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "A operação foi cancelada" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "A operação iria bloquear" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Incapaz de processar o pedido HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Nenhum URI especificado" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI '%s' inválido: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "Incapaz de processar o URI '%s'" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Esquema de URI '%s' não suportado" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "Não é um URI HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Nome da máquina é um endereço IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Nome de máquina inválido" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Nome de máquina não possui domínio base" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Domínios insuficientes" -- cgit v1.2.1 From a66b97fdc0231cd1bc1ee56bc9376bcad121e038 Mon Sep 17 00:00:00 2001 From: Sweta Kothari Date: Tue, 12 Mar 2013 16:22:06 +0530 Subject: Updated gujarati file --- po/gu.po | 59 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/po/gu.po b/po/gu.po index 4fc981a4..19d46368 100644 --- a/po/gu.po +++ b/po/gu.po @@ -2,16 +2,16 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # -# , 2012. +# , 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." "cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-14 15:54+0530\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-12 16:21+0530\n" "Last-Translator: \n" -"Language-Team: gu_IN \n" +"Language-Team: American English \n" "Language: gu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -25,60 +25,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "જોડાણ અનિચ્છનીય રીતે તૂટી ગયુ" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "અયોગ્ય સીક માંગણી" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream કાઢી શકાતુ નથી" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "નેટવર્ક સ્ટ્રીમ અનિચ્છનીય રીતે બંધ થઇ ગઇ" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "સ્ત્રોતને સંપૂર્ણપણે કેશ કરવામાં નિષ્ફળતા" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "આઉટપુટ બફર ઘણુ નાનું છે" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP જવાબનું પદચ્છેદન કરી શક્યા નહિં" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "બિનઓળખાયેલ HTTP જવાબ એનકોડીંગ" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "ક્રિયા રદ થયેલ હતી" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "ક્રિયા રોકી રખાશે" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP માંગણીનુ પદચ્છેદન કરી શક્યા નહિં" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "URI પૂરુ પાડેલ નથી" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "અમાન્ય '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' ને પદચ્છેદન કરી શક્યા નહિં" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "બિનઆધારભૂત URI યોજના '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI નથી" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "યજમાનનામ એ IP સરનામું છે" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "અમાન્ય યજમાનનામ" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "યજમાન પાસે મૂળ ડોમેઇન નથી" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "પૂરતુ ડોમેઇન નથી" -- cgit v1.2.1 From 6be6cf86db1a40daea699734436fcc92137c4bce Mon Sep 17 00:00:00 2001 From: Nilamdyuti Goswami Date: Tue, 12 Mar 2013 18:37:32 +0530 Subject: Assamese translation updated for gnome 3.8 --- po/as.po | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/po/as.po b/po/as.po index 734724ed..b87688a1 100644 --- a/po/as.po +++ b/po/as.po @@ -2,14 +2,14 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # -# Nilamdyuti Goswami , 2012. +# Nilamdyuti Goswami , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-18 15:49+0000\n" -"PO-Revision-Date: 2012-12-19 12:56+0530\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-12 18:37+0530\n" "Last-Translator: Nilamdyuti Goswami \n" "Language-Team: Assamese \n" "Language: as\n" @@ -25,18 +25,22 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "সংযোগ অপ্ৰত্যাশিতভাৱে অন্ত হল" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "অবৈধ সন্ধান অনুৰোধ" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream চুটি কৰিব নোৱাৰি" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "নেটৱাৰ্ক স্ট্ৰিম অপ্ৰত্যাশিতভাৱে বন্ধ হল" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "সম্পদক সম্পূৰ্ণভাৱে ক্যাশ কৰিবলে ব্যৰ্থ" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -62,44 +66,44 @@ msgstr "কাৰ্য্য প্ৰতিৰোধ কৰিব" msgid "Could not parse HTTP request" msgstr "HTTP অনুৰোধ বিশ্লেষণ কৰিব পৰা নগল" -#: ../libsoup/soup-request.c:141 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "কোনো URl প্ৰদান কৰা হোৱা নাই" -#: ../libsoup/soup-request.c:151 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "অবৈধ '%s' URI: %s" -#: ../libsoup/soup-session.c:3752 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' বিশ্লেষণ কৰিব পৰা নগল" -#: ../libsoup/soup-session.c:3789 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "অসমৰ্থিত URl আঁচনি '%s'" -#: ../libsoup/soup-session.c:3811 +#: ../libsoup/soup-session.c:4268 #, c-format msgid "Not an HTTP URI" msgstr "এটা HTTP URI নহয়" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "হস্টনাম এটা IP ঠিকনা" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "অবৈধ হস্টনাম" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "হস্টনামৰ কোনো ভিত্তি ডমেইন নাই" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "পৰ্যাপ্ত ডমেইন নাই" -- cgit v1.2.1 From fe4f6d1e2b5b60dd82239c4a140d3bf7db96fb27 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Tue, 12 Mar 2013 17:10:05 +0100 Subject: Add G_BEGIN_DECLS/G_END_DECLS guards to soup-message-headers.h --- libsoup/soup-message-headers.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsoup/soup-message-headers.h b/libsoup/soup-message-headers.h index 46e5c7c0..02e752bc 100644 --- a/libsoup/soup-message-headers.h +++ b/libsoup/soup-message-headers.h @@ -8,6 +8,8 @@ #include +G_BEGIN_DECLS + typedef struct SoupMessageHeaders SoupMessageHeaders; GType soup_message_headers_get_type (void); #define SOUP_TYPE_MESSAGE_HEADERS (soup_message_headers_get_type ()) @@ -146,4 +148,6 @@ void soup_message_headers_set_content_disposition (SoupMessageHeaders *hdrs const char *disposition, GHashTable *params); +G_END_DECLS + #endif /* SOUP_MESSAGE_HEADERS_H */ -- cgit v1.2.1 From 2e91a09f623dd32bcd0568796c660c7a74ee8804 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Tue, 12 Mar 2013 17:51:25 +0100 Subject: Updated French translation --- po/fr.po | 58 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/po/fr.po b/po/fr.po index 9d11d823..a92665e9 100644 --- a/po/fr.po +++ b/po/fr.po @@ -11,10 +11,10 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-12 12:36+0000\n" -"PO-Revision-Date: 2012-09-13 20:44+0200\n" -"Last-Translator: Mickael Albertus \n" -"Language-Team: français \n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-12 17:51+0100\n" +"Last-Translator: Claude Paroz \n" +"Language-Team: GNOME French Team \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -27,59 +27,83 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "La connexion a été interrompue de manière inattendue" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Requête de recherche invalide" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Impossible de tronquer le SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Le flux réseau s'est arrêté inopinément" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Impossible de mettre la ressource totalement en cache" + #: ../libsoup/soup-converter-wrapper.c:192 -#, c-format msgid "Output buffer is too small" msgstr "La mémoire tampon de sortie est trop petite" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Impossible d'analyser la réponse HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Codage de réponse HTTP inconnu" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "L'opération a été annulée" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "L'opération aurait bloqué" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Impossible d'analyser la requête HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Aucun URI fourni" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI « %s » non valide : %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Impossible d'analyser l'URI « %s »" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Le schéma d'URI « %s » n'est pas pris en charge" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ce n'est pas un URI HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Le nom d'hôte est une adresse IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Nom d'hôte non valide" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Le nom d'hôte n'a pas de domaine de base" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Pas assez de domaines" -- cgit v1.2.1 From 5e32b6dbc30cc413e4387794cd6128877eed9dd4 Mon Sep 17 00:00:00 2001 From: Gil Forcada Date: Tue, 12 Mar 2013 23:07:12 +0100 Subject: [l10n] Updated Catalan translation --- po/ca.po | 55 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/po/ca.po b/po/ca.po index 9b14dd1a..60d22f79 100644 --- a/po/ca.po +++ b/po/ca.po @@ -1,14 +1,14 @@ # Catalan translation for libsoup. # Copyright (C) 2012 Free Software Foundation, Inc. # This file is distributed under the same license as the libsoup package. -# Gil Forcada , 2012. +# Gil Forcada , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-23 13:00+0000\n" +"POT-Creation-Date: 2013-03-09 09:45+0000\n" "PO-Revision-Date: 2012-09-23 17:22+0200\n" "Last-Translator: Gil Forcada \n" "Language-Team: Catalan \n" @@ -25,59 +25,84 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "S'ha finalitzat la connexió inesperadament" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "La petició de cerca no és vàlida" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "No es pot truncar el SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "S'ha tancat inesperadament el flux de xarxa" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "No s'ha pogut carregar completament el recurs a la memòria cau" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "La memòria intermèdia de sortida és massa petita" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "No s'ha pogut analitzar la resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "No es reconeix la codificació de la resposta HTTP" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" -msgstr "S'ha canceŀlat l'operació" +msgstr "S'ha cancel·lat l'operació" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "L'operació bloquejaria" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "No s'ha pogut analitzar la petició HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "No s'ha proporcionat cap URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "L'URI «%s» no és vàlid: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "No s'ha pogut analitzar l'URI «%s»" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "No es sap gestionar l'esquema d'URI «%s»" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "No és un URI HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "El nom d'ordinador és una adreça IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "El nom d'ordinador no és vàlid" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "El nom d'ordinador no té cap domini base" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "No hi ha prou dominis" -- cgit v1.2.1 From 8fb4376a174eebb10b1948451c7ef2dd0f4388f1 Mon Sep 17 00:00:00 2001 From: Carles Ferrando Date: Tue, 12 Mar 2013 23:07:17 +0100 Subject: [l10n] Updated Catalan (Valencian) translation --- po/ca@valencia.po | 55 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/po/ca@valencia.po b/po/ca@valencia.po index 6b447f21..04aee98f 100644 --- a/po/ca@valencia.po +++ b/po/ca@valencia.po @@ -1,13 +1,13 @@ # Catalan translation for libsoup. # Copyright (C) 2012 Free Software Foundation, Inc. # This file is distributed under the same license as the libsoup package. -# Gil Forcada , 2012. +# Gil Forcada , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-26 01:23+0200\n" +"POT-Creation-Date: 2013-03-12 23:07+0100\n" "PO-Revision-Date: 2012-09-23 17:22+0200\n" "Last-Translator: Gil Forcada \n" "Language-Team: Catalan \n" @@ -24,59 +24,84 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "S'ha finalitzat la connexió inesperadament" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "La petició de cerca no és vàlida" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "No es pot truncar el SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "S'ha tancat inesperadament el flux de xarxa" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "No s'ha pogut carregar completament el recurs a la memòria cau" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "La memòria intermèdia d'eixida és massa petita" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "No s'ha pogut analitzar la resposta HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "No es reconeix la codificació de la resposta HTTP" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" -msgstr "S'ha canceŀlat l'operació" +msgstr "S'ha cancel·lat l'operació" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "L'operació bloquejaria" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "No s'ha pogut analitzar la petició HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "No s'ha proporcionat cap URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "L'URI «%s» no és vàlid: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "No s'ha pogut analitzar l'URI «%s»" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "No es sap gestionar l'esquema d'URI «%s»" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "No és un URI HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "El nom d'ordinador és una adreça IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "El nom d'ordinador no és vàlid" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "El nom d'ordinador no té cap domini base" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "No hi ha prou dominis" -- cgit v1.2.1 From 7d63c4180e80aa8e41492b34edd46ba867bb5821 Mon Sep 17 00:00:00 2001 From: Joe Hansen Date: Tue, 12 Mar 2013 23:14:56 +0100 Subject: Updated Danish translation --- po/da.po | 59 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/po/da.po b/po/da.po index 566a3ef2..fc187292 100644 --- a/po/da.po +++ b/po/da.po @@ -1,15 +1,16 @@ # Danish translation for libsoup. -# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# Copyright (C) 2013 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # Ask Hjorth Larsen , 2012. +# Joe Hansen (joedalton2@yahoo.dk), 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-15 23:42+0200\n" -"PO-Revision-Date: 2012-09-15 18:15+0200\n" -"Last-Translator: FULL NAME \n" +"POT-Creation-Date: 2013-03-12 23:14+0100\n" +"PO-Revision-Date: 2013-03-12 18:15+0200\n" +"Last-Translator: Joe Hansen \n" "Language-Team: Danish \n" "Language: da\n" "MIME-Version: 1.0\n" @@ -23,59 +24,85 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Forbindelsen blev uventet afbrudt" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Ugyldig søgeforespørgsel" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Kan ikke afkorte SoupBodyInputStream" +# evt. Netværksstrømmen +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Netværksudsendelsen blev uventet lukket ned" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Kunne ikke lave fuldt mellemlager for ressourcen" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Outputbuffer er for lille" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Kunne ikke fortolke HTTP-svar" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Ej genkendt HTTP-svarkodning" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Operationen blev annulleret" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Operationen ville blokere" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Kunne ikke fortolke HTTP-forespørgsel" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Ingen URI givet" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Ugyldig \"%s\"-URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "Kunne ikke fortolke URI \"%s\"" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Uunderstøttet URI-skema \"%s\"" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ikke en HTTP URI" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Værtsnavn er en IP-adresse" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Ugyldigt værtsnavn" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Værtsnavnet har intet basisdomæne" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Ikke nok domæner" -- cgit v1.2.1 From 9020b719c325b08b0124752a196e29ed22b220a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20P=C3=B5ldaru?= Date: Wed, 13 Mar 2013 12:56:07 +0200 Subject: [l10n] Updated Estonian translation --- po/et.po | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/po/et.po b/po/et.po index 7f23ec4a..b57ce405 100644 --- a/po/et.po +++ b/po/et.po @@ -1,15 +1,15 @@ # Estonian translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# Mattias Põldaru , 2012. +# Mattias Põldaru , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-19 09:41+0000\n" -"PO-Revision-Date: 2012-12-19 17:55+0300\n" +"POT-Creation-Date: 2013-03-12 16:51+0000\n" +"PO-Revision-Date: 2013-03-12 22:43+0300\n" "Last-Translator: Mattias Põldaru \n" "Language-Team: Estonian \n" "Language: et\n" @@ -30,6 +30,9 @@ msgstr "SoupBodyInputStream-i pole võimalik lühendada" msgid "Network stream unexpectedly closed" msgstr "Võrguvoog sulgus ootamatult" +msgid "Failed to completely cache the resource" +msgstr "Ressursi täielik puhverdamine nurjus" + #, c-format msgid "Output buffer is too small" msgstr "Väljundpuhver on liiga väike" -- cgit v1.2.1 From 0fd5e1350206dbcfb64df8e5bb4ed43e49c532db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20=C3=9Ar?= Date: Fri, 15 Mar 2013 12:35:44 +0100 Subject: Updated Hungarian translation --- po/hu.po | 63 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/po/hu.po b/po/hu.po index 3765f0f9..dc3311ea 100644 --- a/po/hu.po +++ b/po/hu.po @@ -3,20 +3,22 @@ # This file is distributed under the same license as the libsoup package. # # Gabor Kelemen , 2012. +# Balázs Úr , 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-17 23:23+0200\n" -"PO-Revision-Date: 2012-09-17 23:23+0200\n" -"Last-Translator: Gabor Kelemen \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-15 12:35+0100\n" +"Last-Translator: Balázs Úr \n" "Language-Team: Hungarian \n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: KBabel 1.11.4\n" +"X-Generator: Lokalize 1.2\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -24,60 +26,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Kapcsolat váratlanul megszakítva" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Érvénytelen pozicionálási kérés" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "A SoupBodyInputStream nem csonkítható" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Az hálózati adatfolyam váratlanul lezárult" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Nem sikerült teljesen gyorsítótárazni az erőforrást" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "A kimeneti puffer túl kicsi" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Nem dolgozható fel a HTTP válasz" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Ismeretlen HTTP válasz kódolás" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "A művelet megszakítva" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "A művelet blokkoló lenne" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Nem dolgozható fel a HTTP kérés" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Nincs megadva URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Érvénytelen „%s” URI: „%s”" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Nem dolgozható fel a(z) „%s” URI" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Nem támogatott URI séma: „%s”" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ez nem HTTP URI" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "A gépnév egy IP-cím" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Érvénytelen gépnév" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "A gépnévnek nincs alap tartománya" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Nincs elég tartomány" -- cgit v1.2.1 From a24d9e392d7385295d5771335d7601bc16eab1cb Mon Sep 17 00:00:00 2001 From: Yuri Myasoedov Date: Sat, 16 Mar 2013 22:48:24 +0400 Subject: Updated Russian translation --- po/ru.po | 62 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/po/ru.po b/po/ru.po index 35c7d55e..375b8bc0 100644 --- a/po/ru.po +++ b/po/ru.po @@ -1,15 +1,16 @@ -# Russian translation for libsoup. -# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER -# This file is distributed under the same license as the libsoup package. -# Yuri Myasoedov , 2012. +# Russian translation for libsoup. +# Copyright (C) 2012 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# +# Yuri Myasoedov , 2012, 2013. , 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-17 16:46+0400\n" +"POT-Creation-Date: 2013-03-15 11:36+0000\n" +"PO-Revision-Date: 2013-03-16 22:47+0400\n" "Last-Translator: Yuri Myasoedov \n" "Language-Team: русский \n" "Language: ru\n" @@ -25,59 +26,84 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Соединение было неожиданно разорвано" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Неверный запрос поиска" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Не удалось отсечь SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Сетевой поток неожиданно закрылся" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Не удалось полностью закэшировать ресурс" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Слишком маленький буфер вывода" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Не удалось разобрать HTTP-ответ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Нераспознанная кодировка HTTP-ответа" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Действие отменено" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Действие заблокировано" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Не удалось разобрать HTTP-запрос" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Не указан URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Недопустимый URI «%s»: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "Не удалось разобрать URI «%s»" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Неподдерживаемая схема URI «%s»" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "Формат URI отличается от HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Имя компьютера является IP-адресом" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Неверное имя компьютера" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Имя компьютера не содержит доменной части" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Недостаточно доменных имён в адресе" -- cgit v1.2.1 From c9d2a55622b8d7064d508b0594fb8c623e4db8d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20Mazurs?= Date: Sun, 17 Mar 2013 20:11:48 +0200 Subject: Updated Latvian translation --- po/lv.po | 60 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/po/lv.po b/po/lv.po index f92e647a..c22e57a4 100644 --- a/po/lv.po +++ b/po/lv.po @@ -3,13 +3,14 @@ # This file is distributed under the same license as the libsoup package. # # Tranzistors , 2012. -# Rūdolfs Mazurs , 2012. +# Rūdolfs Mazurs , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-24 16:54+0300\n" -"PO-Revision-Date: 2012-09-24 16:54+0300\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-17 20:11+0200\n" "Last-Translator: Rūdolfs Mazurs \n" "Language-Team: Latvian \n" "Language: lv\n" @@ -26,60 +27,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "Savienojums tika negaidīti pārtraukts" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "Nederīgs meklēšanas pieprasījums" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "Nevar apraut SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Tīkla straume negaidīti aizvērās" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Neizdevās resursu pilnībā noglabāt kešatmiņā" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Izvades buferis ir pārāk mazs" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "Nevarēja parsēt HTTP atbildi" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Neatpazīts HTTP atbildes kodējums" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Darbība tika atcelta" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Darbība bloķētu" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "Nevarēja parsēt HTTP pieprasījumu" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "Nav sniegts URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Nederīgs “%s” URI — %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "Nevarēja parsēt URI “%s”" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Neatbalstīta URI shēma “%s”" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "Nav HTTP URI" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Datora nosaukums ir IP adrese" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Nederīgs datora nosaukums" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Datora nosaukumam nav bāzes domēna" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Nepietiekami daudz domēnu" -- cgit v1.2.1 From eea361366594ff21a03db9f87a4fe943bfc5a264 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 18 Mar 2013 13:48:40 -0400 Subject: 2.41.92 --- NEWS | 29 +++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 9224b5bd..5713ec4f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,32 @@ +Changes in libsoup from 2.41.91 to 2.41.92: + + * Fixed a bug that caused libsoup to retry an incorrect + password repeatedly, forever, in a certain case that + affected Google calendars in evolution in particuar. + [Red Hat bug #916224, Dan] + + * Also added code to make such infinite retry loops impossible + in the future. [Dan] + + * Fixed SoupRequestData's handling of URIs with "%00" in them. + [#695246, Žan Doberšek] + + * Added the SoupSession:proxy-resolver property, to override + the GProxyResolver used by a session. (This means there are + now three different ways of controlling proxy resolution in + SoupSession... this will be cleaned up a bit after 2.42.) + [#680273, Dan] + + * Added missing G_BEGIN_DECLS/G_END_DECLS to + soup-message-headers.h, so that its functions can be called + from C++. [Carlos Garcia Campos] + + * Updated translations: + Assamese, Belarusian, Brazilian Portuguese, Catalan + (Valencian), Catalan, Danish, Estonian, French, Greek, + Gujarati, Hungarian, Italian, Latvian, Portuguese, Russian, + Slovenian, Thai + Changes in libsoup from 2.41.90 to 2.41.91: * Fixed a crash that showed up with XMLRPC requests in diff --git a/configure.ac b/configure.ac index 34db3676..b9e25013 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [91]) +m4_define([soup_micro_version], [92]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 3af7390fd6aba17f4eedc35f83ed3ce515bf3363 Mon Sep 17 00:00:00 2001 From: Victor Ibragimov Date: Tue, 19 Mar 2013 22:31:49 +0100 Subject: [l10n] Added Tadjik translation --- po/LINGUAS | 1 + po/tg.po | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 po/tg.po diff --git a/po/LINGUAS b/po/LINGUAS index f0333dae..1c3a73d4 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -45,6 +45,7 @@ sr@latin sv ta te +tg th tr ug diff --git a/po/tg.po b/po/tg.po new file mode 100644 index 00000000..c0ece901 --- /dev/null +++ b/po/tg.po @@ -0,0 +1,107 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Victor Ibragimov , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: Tajik Gnome\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" +"product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-03-07 15:08+0000\n" +"PO-Revision-Date: 2013-01-19 17:43+0500\n" +"Last-Translator: Victor Ibragimov \n" +"Language-Team: \n" +"Language: Tajik\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "" + +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "Амалиёт бекор шудааст" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "" + +#: ../libsoup/soup-session.c:4252 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "" + +#: ../libsoup/soup-session.c:4289 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "" + +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "" + +#: ../libsoup/soup-tld.c:185 +msgid "Hostname is an IP address" +msgstr "" + +#: ../libsoup/soup-tld.c:206 +msgid "Invalid hostname" +msgstr "" + +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "" + +#: ../libsoup/soup-tld.c:257 +msgid "Not enough domains" +msgstr "" -- cgit v1.2.1 From b681ec9223ba845ac0a3e433923ed7d89326371a Mon Sep 17 00:00:00 2001 From: Sandeep Sheshrao Shedmake Date: Wed, 20 Mar 2013 06:57:13 +0530 Subject: Updated Marathi Translations --- po/mr.po | 59 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/po/mr.po b/po/mr.po index eeb427f7..e2ca1630 100644 --- a/po/mr.po +++ b/po/mr.po @@ -2,14 +2,14 @@ # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. # -# Sandeep Shedmake , 2012. +# Sandeep Shedmake , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-12 18:04+0530\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-20 06:56+0530\n" "Last-Translator: Sandeep Shedmake \n" "Language-Team: Marathi \n" "Language: mr\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Lokalize 1.4\n" +"X-Generator: Lokalize 1.5\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -25,60 +25,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "जोडणी अनपेक्षितपणे बंद झाली" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "अवैध सीक विनंती" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream ट्रंकेट करणे अशक्य" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "नेटवर्क स्ट्रिम अनपेक्षितरित्या बंद झाले" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "रिसोअर्स संपूर्णपणे कॅशे करण्यास अपयशी" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "आउटपुट बफर खूपच लहान आहे" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP प्रतिसाद वाचणे अशक्य" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "अपरिचीत HTTP प्रतिसाद एंकोडिंग" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "कार्य रद्द केले" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "कार्य बंधिस्त करू शकते" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP विनंती वाचणे अशक्य" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "URI पुरवले नाही" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "अवैध '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' वाचणे अशक्य" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "असमर्थीत URI सुत्रयोजना '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI नाही" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "यजमाननाव IP पत्ता आहे" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "अवैध यजमाननाव" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "यजमाननावात बेस डोमैन नाही" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "अतिरिक्त डोमैन्स् आढळले नाही" -- cgit v1.2.1 From 50f4c17eeaae428182055e8087a502ae3dce529b Mon Sep 17 00:00:00 2001 From: Rajesh Ranjan Date: Wed, 20 Mar 2013 16:52:29 +0530 Subject: hindi translation --- po/hi.po | 63 +++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/po/hi.po b/po/hi.po index f43ab73d..de85b345 100644 --- a/po/hi.po +++ b/po/hi.po @@ -3,22 +3,22 @@ # This file is distributed under the same license as the libsoup package. # 1 <1>, 2012. # 1 Pratibha kumari <1pratibharoshan1526@gmail.com>, 2012. - +# raj , 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-15 21:43+0000\n" -"PO-Revision-Date: 2012-09-20 14:12+0530\n" -"Last-Translator: 1 Pratibha kumari <1pratibharoshan1526@gmail.com>\n" -"Language-Team: Hindi \n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-20 16:47+0530\n" +"Last-Translator: raj \n" +"Language-Team: Hindi \n" "Language: hi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Lokalize 1.2\n" +"X-Generator: Lokalize 1.5\n" "X-Project-Style: gnome\n" #: ../libsoup/soup-body-input-stream.c:141 @@ -27,60 +27,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "मिलाप अनपेक्षित रुप से खतम हो गया " -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "अमान्य खोज अनुरोध" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream का नहीं कर सकता" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "संजाल स्ट्रीम अप्रत्याशित रूप से बंद हो गया" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "संसाधन को पूरी तरह कैश करने में विफल" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "निर्गम बफर बहुत छोटा है" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP अनुक्रिया विश्लेषित नहीं कर सका" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "अपरिचित HTTP अनुक्रिया एन्कोडिंग" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "आपरेशन रद्द कर दिया गया" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "आपरेशन बंद हो जाएगा" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP आग्रह विश्लेषित नहीं कर सका" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "यूआरआई नहीं प्रदान किया गया" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "यूआरआई '%s' अमान्य: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' पद व्याख्या नहीं हो सका" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "URI योजना '%s' को सहारा नहीं" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "कोई HTTP URI नहीं" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "मेजबाननाम एक आईपी पता है" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "मेजबाननाम मान्य नहीं" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "मेजबाननाम को आधार डोमेन नहीं है" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "डोमेन पर्याप्त नहीं" -- cgit v1.2.1 From 096eed1a810f8c09c6e646adaeee248ed914595a Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Wed, 20 Mar 2013 17:33:35 +0100 Subject: requester-test: fix a printf format compiler warning Could use G_GSIZE_FORMAT here, but casting to gulong is simpler. --- tests/requester-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/requester-test.c b/tests/requester-test.c index 147ba4c3..6e169ad0 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -691,7 +691,8 @@ do_null_char_request (SoupSession *session, const char *encoded_data, } if (nread != expected_len) { - debug_printf (1, " response length mismatch: expected %d, got %lu\n", expected_len, nread); + debug_printf (1, " response length mismatch: expected %d, got %lu\n", + expected_len, (gulong)nread); errors++; } else if (memcmp (buf, expected_data, nread) != 0) { debug_printf (1, " response data mismatch\n"); -- cgit v1.2.1 From 3f7cd4bafe3d19082ba1ad389457ee04844e5ad2 Mon Sep 17 00:00:00 2001 From: Changwoo Ryu Date: Fri, 22 Mar 2013 04:46:53 +0900 Subject: Updated Korean translation --- po/ko.po | 87 +++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/po/ko.po b/po/ko.po index 3d83be9e..c07240e5 100644 --- a/po/ko.po +++ b/po/ko.po @@ -3,13 +3,15 @@ # This file is distributed under the same license as the libsoup package. # # eukim , 2012. +# Changwoo Ryu , 2013. +# msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-12 00:04+0000\n" -"PO-Revision-Date: 2012-08-26 14:57+0900\n" -"Last-Translator: eukim \n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-22 04:46+0900\n" +"Last-Translator: Changwoo Ryu \n" "Language-Team: Korean \n" "Language: ko\n" "MIME-Version: 1.0\n" @@ -18,57 +20,90 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Lokalize 1.0\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "예상치 않게 연결이 중지됨" +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "탐색 요청이 잘못되었습니다" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream을 자를 수 없습니다" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "네트워크 스트림이 예상치 못하게 닫혔습니다" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "리소스를 완전히 캐시에 저장하는데 실패했습니다" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -msgstr "출력 버퍼가 너무 작음" +msgstr "출력 버퍼가 너무 작습니다" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP 응답을 구문 분석할 수 없습니다" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP 응답 인코딩을 알 수 없습니다" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" -msgstr "작업이 취소됨" +msgstr "작업이 취소되었습니다" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" -msgstr "작업이 차단됨" +msgstr "작업이 블럭되었습니다" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "HTTP 요청을 구문 분석할 수 없습니다" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" -msgstr "URI이 제공되지 않음" +msgstr "URI가 없습니다" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "잘못된 '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" -msgstr "URI '%s'을(를) 구문 분석할 수 없음" +msgstr "'%s' URI를 구문 분석할 수 없습니다" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" -msgstr "지원하지 않는 URI 스킴 '%s'" +msgstr "'%s' URI 스킴을 지원하지 않습니다" + +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI가 아닙니다" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" -msgstr "호스트 이름은 IP 주소임" +msgstr "호스트 이름은 IP 주소입니다" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" -msgstr "잘못된 호스트 이름" +msgstr "잘못된 호스트 이름입니다" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" -msgstr "호스트 이름에 기본 도메인이 없음" +msgstr "호스트 이름에 기본 도메인이 없습니다" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" -msgstr "도메인이 충분하지 않음" +msgstr "도메인이 충분하지 않습니다" -- cgit v1.2.1 From 08c5acaee4e6187e57c6f9ff71190bcee9e246e1 Mon Sep 17 00:00:00 2001 From: ManojKumar Giri Date: Fri, 22 Mar 2013 18:32:00 +0530 Subject: Updated Odia Language along with FUEL implementation --- po/or.po | 57 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/po/or.po b/po/or.po index e8e13d65..f6be296d 100644 --- a/po/or.po +++ b/po/or.po @@ -1,14 +1,14 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # -# Manoj Kumar Giri , 2012. +# Manoj Kumar Giri , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-11-12 21:50+0000\n" -"PO-Revision-Date: 2012-12-03 14:43+0530\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-22 18:02+0530\n" "Last-Translator: Manoj Kumar Giri \n" "Language-Team: Oriya \n" "Language: or\n" @@ -24,60 +24,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "ସଂଯୋଗଟି ଅପ୍ରତ୍ୟାଶିତ ଭାବରେ ବନ୍ଦ ହୋଇଛି" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "ଅବୈଧ ଅନୁସନ୍ଧାନ ଅନୁରୋଧ" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr " SoupBodyInputStream କୁ ବିଚ୍ଛିନ୍ନ କରିହେବ ନାହିଁ " +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "ନେଟୱର୍କ୍‌ ଧାରା ଅପ୍ରତ୍ୟାଶିତ ଭାବରେ ବନ୍ଦ ହୋଇଛି" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "ଉତ୍ସକୁ ସମ୍ପୂର୍ଣ୍ଣ ଭାବରେ କ୍ୟାଶେ କରିବାରେ ବିଫଳ" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "ଫଳାଫଳ ବଫରଟି ଅତି ଛୋଟ ଅଟେ" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP ଉତ୍ତର ବିଶ୍ଳେଷଣ କରିପାରିଲା ନାହିଁ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "ଅଚିହ୍ନା HTTP ଉତ୍ତର ସାଙ୍କେତିକରଣ" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "ପ୍ରୟୋଗକୁ ବାତିଲ କରାଯାଇଛି" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "ପ୍ରୟୋଗଟି ବନ୍ଦ ହୋଇପାରେ" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP ଅନୁରୋଧକୁ ବିଶ୍ଳେଷଣ କରିପାରିଲା ନାହିଁ" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "କୌଣସି URI ଦିଆଯାଇ ନାହିଁ" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "ଅବୈଧ '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s'କୁ ବିଶ୍ଳେଷଣ କରିପାରିଲା ନାହିଁ" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "ଅସମର୍ଥିତ URI ଯୋଜନା '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "ଏହା ଏକ HTTP URI ନୁହଁ" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "ହୋଷ୍ଟନାମଟି ଏକ IP ଠିକଣା ଅଟେ" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "ଅବୈଧ ହୋଷ୍ଟ ନାମ" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "ହୋଷ୍ଟ ନାମରେ କୌଣସି ମୂଳ ଡମେନ ନଥାଏ" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "ଯଥେଷ୍ଟ ଡମେନ ନାହିଁ" -- cgit v1.2.1 From d96de2d3348499960d18ddaa67216358c8e880d6 Mon Sep 17 00:00:00 2001 From: Arash Mousavi Date: Sat, 23 Mar 2013 18:08:26 +0430 Subject: L10N: Updated Persian Translation --- po/fa.po | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/po/fa.po b/po/fa.po index ed9d6af9..74ee1e77 100644 --- a/po/fa.po +++ b/po/fa.po @@ -1,73 +1,109 @@ # Persian translation for libsoup. # Copyright (C) 2012 libsoup's COPYRIGHT HOLDER # This file is distributed under the same license as the libsoup package. -# Arash Mousavi , 2012. +# Arash Mousavi , 2012, 2013. # msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-07 16:15+0000\n" -"PO-Revision-Date: 2012-09-08 00:58+0330\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-23 18:07+0330\n" "Last-Translator: Arash Mousavi \n" "Language-Team: Persian\n" "Language: fa\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "اتصال به شکل غیرمنتظره‌ای بسته شد" +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "درخواست جستجو نامعتبر" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "نمی‌توان SoupBodyInputStream را کوتاه کرد" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "جریان شبکه به‌طور غیرمنتظره‌ای بسته شد" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "به‌طور کامل حافظه‌ی نهان کردن منبع شکست خورد" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "میانگیر خروجی خیلی کوتاه است" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "نمی‌توان پاسخ HTTP را تجزیه کرد" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "کدگذاری پاسخ HTTP شناخته نشد" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "عملیات لغو شده بود" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "عملیات می‌توانست بسته شود" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "نمی‌توان درخواست HTTP را تجزیه کرد" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "هیچ URIای داده نشده است" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "«%s» نامعتبر URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "نمی‌توان URI را تجزیه کرد «%s»" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "شِما URI پشتیبانی نشده «%s»" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "آدرس HTTP نیست" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "نام میزبان یک آدرس آی‌پی است" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "نام‌میزبان نامعتبر" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "نام‌میزبان دامنه‌ی پایه ندارد" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "دامنه‌های کافی موجود نیست" -- cgit v1.2.1 From 56ee3252834694b958a6e28ae0034de451464bc6 Mon Sep 17 00:00:00 2001 From: Shankar Prasad Date: Sun, 24 Mar 2013 18:00:45 +0530 Subject: Updated kn translations --- po/kn.po | 57 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/po/kn.po b/po/kn.po index 8d2e7118..2cc9ce59 100644 --- a/po/kn.po +++ b/po/kn.po @@ -1,14 +1,14 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # -# Shankar Prasad , 2012. +# Shankar Prasad , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-12-03 11:35+0000\n" -"PO-Revision-Date: 2012-12-10 15:49+0530\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-24 18:00+0530\n" "Last-Translator: Shankar Prasad \n" "Language-Team: Kannada \n" "Language: kn\n" @@ -24,60 +24,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "ಸಂಪರ್ಕವು ಅನಿರೀಕ್ಷಿತವಾಗಿ ಕೊನೆಗೊಂಡಿದೆ" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "ಅಮಾನ್ಯವಾದ ಕೋರಿಕೆಯ ಮನವಿ" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream ಅನ್ನು ತುಂಡರಿಸಲಾಗಿಲ್ಲ" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "ಜಾಲಬಂಧ ಸ್ಟ್ರೀಮ್ ಅನ್ನು ಅನಿರೀಕ್ಷಿತವಾಗಿ ಮುಚ್ಚಲಾಗಿದೆ" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "ಸಂಪನ್ಮೂಲವನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಕ್ಯಾಶ್ ಮಾಡುವಲ್ಲಿ ವಿಫಲಗೊಂಡಿದೆ" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "ಔಟ್‌ಪುಟ್ ಬಫರ್ ಬಹಳ ಚಿಕ್ಕದಾಗಿದೆ" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP ಪ್ರತ್ಯುತ್ತರವನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "ಗುರುತಿಸಲಾಗದ HTTP ಪ್ರತಿಕ್ರಿಯೆ ಎನ್ಕೋಡಿಂಗ್" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "ಕಾರ್ಯಾಚರಣೆ ತಡೆಯಲ್ಪಡಬಹುದು" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP ಮನವಿಯನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "ಯಾವುದೆ URI ಅನ್ನು ಒದಗಿಸಲಾಗಿಲ್ಲ." -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "ಅಮಾನ್ಯವಾದ '%s' URI:'%s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "'%s' URL ಅನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "ಬೆಂಬಲವಿಲ್ಲದ ಯುಆರ್ಐ ಮಾದರಿ '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "ಒಂದು HTTP URI ಅಲ್ಲ" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "ಆತಿಥೇಯವು ಒಂದು IP ವಿಳಾಸವಾಗಿದೆ" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "ಅಮಾನ್ಯವಾದ ಅತಿಥೇಯದ ಹೆಸರು" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "ಆತಿಥೇಯದ ಹೆಸರಿನಲ್ಲಿ ಯಾವುದೆ ಮೂಲ ಡೊಮೈನ್ ಇಲ್ಲ" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "ಬೇಕಾದಷ್ಟು ಡೊಮೈನ್‌ಗಳಿಲ್ಲ" -- cgit v1.2.1 From 9bb3868be6019a828c8a09905dbc907e19fa23d2 Mon Sep 17 00:00:00 2001 From: Ani Peter Date: Mon, 25 Mar 2013 11:43:52 +0530 Subject: Completed for Malayalam --- po/ml.po | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/po/ml.po b/po/ml.po index e698e1dc..4b515208 100644 --- a/po/ml.po +++ b/po/ml.po @@ -1,22 +1,22 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# Ani Peter , 2012. +# Ani Peter , 2012, 2013. # Anish A , 2013. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2013-02-12 09:33+0000\n" -"PO-Revision-Date: 2013-02-15 11:47+0530\n" -"Last-Translator: Anish A \n" -"Language-Team: Swatantra Malayalam Computing\n" +"POT-Creation-Date: 2013-03-24 12:31+0000\n" +"PO-Revision-Date: 2013-03-25 11:40+0530\n" +"Last-Translator: Ani Peter \n" +"Language-Team: American English \n" "Language: ml\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Virtaal 0.7.1\n" +"X-Generator: Lokalize 1.5\n" "X-Project-Style: gnome\n" #: ../libsoup/soup-body-input-stream.c:141 @@ -33,10 +33,14 @@ msgstr "തെറ്റായ തെരച്ചില്‍ ആവശ്യം" msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream ട്രക്കേറ്റ് ചെയ്യുവാന്‍ സാധ്യമല്ല" -#: ../libsoup/soup-cache-input-stream.c:77 +#: ../libsoup/soup-cache-input-stream.c:74 msgid "Network stream unexpectedly closed" msgstr "ശൃംഖല സ്ട്രീം വിചാരിക്കാതെ അടച്ചു" +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "ശ്രോതസ്സ് കാഷ് ചെയ്യുന്നതു് പൂര്‍ണ്ണമായി പരാജയപ്പെട്ടു" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" @@ -72,17 +76,17 @@ msgstr "യുആര്‍ഐ ലഭ്യമാക്കിയിട്ടി msgid "Invalid '%s' URI: %s" msgstr "തെറ്റായ '%s' യുആര്‍ഐ: %s" -#: ../libsoup/soup-session.c:4214 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "യുആര്‍ഐ '%s' പാഴ്സ് ചെയ്യുവാനായില്ല" -#: ../libsoup/soup-session.c:4251 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "പിന്തുണയില്ലാത്ത യുആര്‍ഐ സ്കീം '%s'" -#: ../libsoup/soup-session.c:4273 +#: ../libsoup/soup-session.c:4311 #, c-format msgid "Not an HTTP URI" msgstr "HTTP URI അല്ല" @@ -102,3 +106,4 @@ msgstr "ഹോസ്റ്റ്നാമത്തിനു് ബെയിസ #: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "ആവശ്യമായ ഡൊമെയിനുകള്‍ ലഭ്യമല്ല" + -- cgit v1.2.1 From 2a6bdf7745c74486d9aadf5aabcec23bb53f890d Mon Sep 17 00:00:00 2001 From: Shantha kumar Date: Mon, 25 Mar 2013 12:11:48 +0530 Subject: Tamil Translations Updated --- po/ta.po | 65 ++++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/po/ta.po b/po/ta.po index c0606120..96b82ab4 100644 --- a/po/ta.po +++ b/po/ta.po @@ -3,19 +3,21 @@ # This file is distributed under the same license as the libsoup package. # # Dr.T.Vasudevan , 2012. +# Shantha kumar , 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-19 20:16+0530\n" -"PO-Revision-Date: 2012-09-19 20:26+0530\n" -"Last-Translator: Dr.T.Vasudevan \n" -"Language-Team: Tamil \n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug." +"cgi?product=libsoup&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-25 10:44+0530\n" +"Last-Translator: Shantha kumar \n" +"Language-Team: Tamil <>\n" "Language: ta\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Lokalize 1.1\n" +"X-Generator: Lokalize 1.0\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" #: ../libsoup/soup-body-input-stream.c:141 @@ -24,60 +26,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "இணைப்பு எதிர்பாராமல் துண்டிக்கப்பட்டது" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "செல்லுபடியாகாத தேடல் கோரிக்கை" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream ஐ பிரிக்க இயலாது" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "பிணைய ஸ்ட்ரீம் எதிர்பாராமல் முடிந்துவிட்டது" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "வளத்தை முழுவதுமாக தேக்ககப்படுத்துவதில் தோல்வியடைந்தது" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "வெளியீட்டு இடைநினைவு மிகச்சிறியது" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP பதிலை பாகுபடுத்த முடியவில்லை" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "அடையாளம் காண முடியாத HTTP பதிலளிப்பு குறியீடாக்கம்" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "செயல்பாடு ரத்து செய்யப்பட்டது" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "செயல்பாடு தடை செய்யும்" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP கோரிக்கையை பாகுபடுத்த முடியவில்லை" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "யூஆர்ஐ ஏதும் தரப்படவில்லை" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "செல்லுபடியாகாத '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "'%s' யூஆர்ஐ ஐ அலகிட முடியவில்லை" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "ஆதரவு இல்லாத யூஆர்ஐ திட்டம் '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI அல்ல" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "புரவலன் பெயர் ஒரு ஐபி முகவரி" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "செல்லுபடியாகாத கணிணிப்பெயர்" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "புரவலன் பெயருக்கு ஒரு செயற்களம் இல்லை" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "போதிய செயற்களம் இல்லை" -- cgit v1.2.1 From bce11d1c051d1763f5b17b61a18754a03d52ad2a Mon Sep 17 00:00:00 2001 From: Krishnababu Krothapalli Date: Mon, 25 Mar 2013 16:11:00 +0530 Subject: Updated Telugu Translations --- po/te.po | 59 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/po/te.po b/po/te.po index bd9713df..4b2fed78 100644 --- a/po/te.po +++ b/po/te.po @@ -3,14 +3,14 @@ # This file is distributed under the same license as the libsoup package. # # Sasi Bhushan Boddepalli , 2012. -# Krishnababu Krothapalli , 2012. +# Krishnababu Krothapalli , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-21 21:25+0530\n" +"POT-Creation-Date: 2013-02-18 10:20+0000\n" +"PO-Revision-Date: 2013-03-25 14:39+0530\n" "Last-Translator: Krishnababu Krothapalli \n" "Language-Team: Telugu \n" "Language: te\n" @@ -18,7 +18,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Lokalize 1.4\n" +"X-Generator: Lokalize 1.5\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 @@ -26,60 +26,87 @@ msgstr "" msgid "Connection terminated unexpectedly" msgstr "కనెక్షను అనుకోకుండా అంతమైంది" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:463 msgid "Invalid seek request" msgstr "చెల్లని సీక్ అభ్యర్ధన" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:491 msgid "Cannot truncate SoupBodyInputStream" msgstr "SoupBodyInputStream ట్రంకేట్ చేయలేదు" +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "నెట్వర్కు స్ట్రీమ్ అనుకోకుండా మూయబడింది" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "వనరును సంపూర్ణంగా క్యాచీ చేయుటకు విఫలమైంది" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "అవుట్పుట్ బఫర్ మరీ చిన్నది" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP response" +msgstr "HTTP స్పందనను పార్శ్ చేయలేక పోయింది" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "గుర్తించని HTTP స్పందన యెన్కోడింగ్" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "ఆపరేషన్ రద్దు చేయబడింది" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "ఆపరేషన్ బ్లాక్ చేస్తుంది" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +#| msgid "Could not parse URI '%s'" +msgid "Could not parse HTTP request" +msgstr "HTTP అభ్యర్ధనను పార్స్ చేయలేదు" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "URl అందించబడలేదు" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "చెల్లని '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4209 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' అన్వయించడం సాధ్యం కాదు" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4246 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "మద్దతు లేని URI స్కీమ్ '%s'" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4268 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI కాదు" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "హోస్ట్ పేరు ఒక IP చిరునామా" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "చెల్లని హోస్ట్ పేరు" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "అతిధేయిపేరు అధార డొమైన్ కలిగిలేదు" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "సరిపోనన్ని డొమైన్ లు" -- cgit v1.2.1 From 092915ebcb32859ae0b74aa6defa72bae0476c96 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 25 Mar 2013 08:40:19 -0400 Subject: 2.42.0 --- NEWS | 9 +++++++++ configure.ac | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 5713ec4f..c697ff3d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +Changes in libsoup from 2.41.92 to 2.42.0: + + * Fixed a compiler warning on 32bit in a test program. [Kalev + Lember] + + * New/updated translations: + Hindi, Kannada, Korean, Malayalam, Marathi, Odia, Persian, + Tadjik, Tamil, Telugu + Changes in libsoup from 2.41.91 to 2.41.92: * Fixed a bug that caused libsoup to retry an incorrect diff --git a/configure.ac b/configure.ac index b9e25013..c5645b4d 100644 --- a/configure.ac +++ b/configure.ac @@ -3,8 +3,8 @@ dnl *** Initialize automake and set version *** dnl ******************************************* m4_define([soup_major_version], [2]) -m4_define([soup_minor_version], [41]) -m4_define([soup_micro_version], [92]) +m4_define([soup_minor_version], [42]) +m4_define([soup_micro_version], [0]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) @@ -27,10 +27,10 @@ SOUP_API_VERSION=2.4 AC_SUBST(SOUP_API_VERSION) # Increment on interface addition. Reset on removal. -SOUP_AGE=5 +SOUP_AGE=6 # Increment on interface add, remove, or change. -SOUP_CURRENT=6 +SOUP_CURRENT=7 # Increment on source change. Reset when CURRENT changes. SOUP_REVISION=0 -- cgit v1.2.1 From fff0baf87a3950d1f8e096cfc71b0bb6e180a452 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Thu, 21 Mar 2013 23:54:36 +0100 Subject: win32: link with ws2_32 for htons https://bugzilla.gnome.org/show_bug.cgi?id=696354 --- libsoup/Makefile.am | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index e99c8e6c..d54a06a9 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -4,6 +4,10 @@ EXTRA_DIST = include $(GLIB_MAKEFILE) +if OS_WIN32 +LIBWS2_32 = -lws2_32 +endif + INCLUDES = \ -DG_LOG_DOMAIN=\"libsoup\" \ -DLOCALEDIR=\"$(localedir)\" \ @@ -83,6 +87,7 @@ EXTRA_DIST += libsoup-2.4.sym libsoup_2_4_la_LIBADD = \ $(GLIB_LIBS) \ + $(LIBWS2_32) \ $(XML_LIBS) \ $(SQLITE_LIBS) -- cgit v1.2.1 From 71589c70b7af17b3f1dc10fbf4c1bf05588fb351 Mon Sep 17 00:00:00 2001 From: Inaki Larranaga Murgoitio Date: Tue, 26 Mar 2013 11:26:19 +0100 Subject: Added Basque language\nAdded 'eu' (Basque) to LINGUAS --- po/LINGUAS | 1 + po/eu.po | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 po/eu.po diff --git a/po/LINGUAS b/po/LINGUAS index 1c3a73d4..6afda913 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -13,6 +13,7 @@ en_GB eo es et +eu fa fr fur diff --git a/po/eu.po b/po/eu.po new file mode 100644 index 00000000..28bbd393 --- /dev/null +++ b/po/eu.po @@ -0,0 +1,106 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Iñaki Larrañaga Murgoitio , 2013. +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-03-26 11:25+0100\n" +"PO-Revision-Date: 2013-03-24 16:37+0100\n" +"Last-Translator: Iñaki Larrañaga Murgoitio \n" +"Language-Team: Basque \n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Lokalize 1.4\n" + +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Konexioa ustekabean amaitu da" + +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "Bilaketa-eskaera baliogabea" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Ezin da SoupBodyInputStream trunkatu" + +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Sarearen korrontea ustekabean itxi da" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Huts egin du baliabidea erabat cachean gordetzean" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Irteeraren bufferra txikiegia da" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Ezin izan da HTTP erantzuna analizatu" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP erantzunaren kodeketa ezezaguna" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "Eragiketa bertan behera utzi da" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "Eragiketak blokea dezake" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Ezin izan da HTTP eskaera analizatu" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Ez da URIrik eman" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Baliogabeko '%s' URIa: %s" + +#: ../libsoup/soup-session.c:4252 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Ezin izan da '%s' URIa analizatu" + +#: ../libsoup/soup-session.c:4289 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Onartu gabeko '%s' URI eskema" + +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "Ez da HTTP URIa" + +#: ../libsoup/soup-tld.c:185 +msgid "Hostname is an IP address" +msgstr "Ostalari-izena IP helbide bat da" + +#: ../libsoup/soup-tld.c:206 +msgid "Invalid hostname" +msgstr "Baliogabeko ostalari-izena" + +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "Ostalari-izenak ez dauka oinarrizko domeinurik" + +#: ../libsoup/soup-tld.c:257 +msgid "Not enough domains" +msgstr "Ez dago nahikoa domeinurik" -- cgit v1.2.1 From 6666b3cd99a4931bd28b622918c121f92cf33b52 Mon Sep 17 00:00:00 2001 From: Xan Lopez Date: Tue, 26 Mar 2013 16:20:38 +0100 Subject: soup-session: fix memory leak Do not steal the stream from the GTask, otherwise its destruction method will never run and it will be leaked. https://bugzilla.gnome.org/show_bug.cgi?id=696594 --- libsoup/soup-session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 14e2be47..186d57ad 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3899,7 +3899,7 @@ idle_return_from_cache_cb (gpointer data) return FALSE; } - istream = g_object_steal_data (G_OBJECT (task), "SoupSession:istream"); + istream = g_object_get_data (G_OBJECT (task), "SoupSession:istream"); async_return_from_cache (item, istream); return FALSE; -- cgit v1.2.1 From b376dd82ad9beba54e85911a39f41ba8cea08498 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 3 Apr 2013 11:27:59 -0400 Subject: soup-connection: fix SoupProxyResolverDefault breakage It got broken at the last minute when adding SoupSession:proxy-resolver support. https://bugzilla.gnome.org/show_bug.cgi?id=697028 --- libsoup/soup-connection.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index bcc5af48..fbddfea3 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -133,7 +133,8 @@ soup_connection_set_property (GObject *object, guint prop_id, priv->soup_proxy_resolver = g_object_ref (proxy_resolver); break; case PROP_G_PROXY_RESOLVER: - priv->g_proxy_resolver = g_value_dup_object (value); + if (g_value_get_object (value)) + priv->g_proxy_resolver = g_value_dup_object (value); break; case PROP_SSL: priv->ssl = g_value_get_boolean (value); -- cgit v1.2.1 From 258c7a45528251f40614f597e275fca7ab8c9258 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 8 Apr 2013 15:34:11 -0400 Subject: configure: require glib 2.36 (not just 2.35.x) --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index c5645b4d..80b96498 100644 --- a/configure.ac +++ b/configure.ac @@ -77,7 +77,7 @@ dnl *********************** dnl *** Checks for glib *** dnl *********************** -GLIB_REQUIRED=2.35.0 +GLIB_REQUIRED=2.36.0 AM_PATH_GLIB_2_0($GLIB_REQUIRED,,,gobject gio) if test "$GLIB_LIBS" = ""; then AC_MSG_ERROR(GLIB $GLIB_REQUIRED or later is required to build libsoup) -- cgit v1.2.1 From df03c80e44ff2efe15dcca40b214fb2050fbe6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ozan=20=C3=87a=C4=9Flayan?= Date: Wed, 10 Apr 2013 00:54:56 +0300 Subject: [l10n] Updated Turkish translation --- po/tr.po | 83 +++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 25 deletions(-) diff --git a/po/tr.po b/po/tr.po index 1c8813a7..809ebf54 100644 --- a/po/tr.po +++ b/po/tr.po @@ -3,75 +3,108 @@ # This file is distributed under the same license as the libsoup package. # # Muhammet Kara , 2012. +# Ozan Çağlayan , 2013. +# msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-08-07 13:39+0000\n" -"PO-Revision-Date: 2012-08-08 20:04+0000\n" -"Last-Translator: Muhammet Kara \n" -"Language-Team: Turkish \n" +"POT-Creation-Date: 2013-04-03 16:00+0000\n" +"PO-Revision-Date: 2013-04-07 22:53+0300\n" +"Last-Translator: Ozan Çağlayan \n" +"Language-Team: Türkçe <>\n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Lokalize 1.4\n" +"X-Generator: Gtranslator 2.91.6\n" -#: ../libsoup/soup-body-input-stream.c:136 -#: ../libsoup/soup-body-input-stream.c:167 -#: ../libsoup/soup-body-input-stream.c:200 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:141 +#: ../libsoup/soup-body-input-stream.c:172 +#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" -msgstr "Bağlantı beklenmedik şekilde sonlandırıldı" +msgstr "Bağlantı beklenmeyen bir şekilde sonlandı" + +#: ../libsoup/soup-body-input-stream.c:463 +msgid "Invalid seek request" +msgstr "Geçersiz arama talebi" + +#: ../libsoup/soup-body-input-stream.c:491 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "SoupBodyInputStream kesilemiyor" -#: ../libsoup/soup-converter-wrapper.c:191 +#: ../libsoup/soup-cache-input-stream.c:74 +msgid "Network stream unexpectedly closed" +msgstr "Ağ akışı beklenmeyen bir şekilde sonlandı" + +#: ../libsoup/soup-cache-input-stream.c:291 +msgid "Failed to completely cache the resource" +msgstr "Özkaynak tamamen önbelleğe alınamadı" + +#: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -msgstr "Çıktı arabelleği çok küçük" +msgstr "Çıkış arabelleği çok küçük" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "HTTP cevabı ayrıştırılamadı" -#: ../libsoup/soup-message-io.c:817 ../libsoup/soup-message-io.c:853 +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "HTTP cevabı tanınmayan bir şekilde kodlanmış" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "İşlem iptal edildi" -#: ../libsoup/soup-message-io.c:864 -#, fuzzy +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" -msgstr "İşlem bloklanabilir" +msgstr "İşlem bloke edebilir" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "HTTP talebi ayrıştırılamadı" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "URI verilmedi" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "Geçersiz '%s' URI: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "URI '%s' ayrıştırılamadı" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Desteklenmeyen URI şeması '%s'" -#: ../libsoup/soup-tld.c:152 +#: ../libsoup/soup-session.c:4311 +#, c-format +msgid "Not an HTTP URI" +msgstr "HTTP URI değil" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" -msgstr "Makine adı bir ip adresi" +msgstr "Makine adı bir IP adresi" -#: ../libsoup/soup-tld.c:173 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Geçersiz makine adı" -#: ../libsoup/soup-tld.c:202 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Ana makinenin temel etki alanı yok" -#: ../libsoup/soup-tld.c:224 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Yeterli etki alanı yok" - -- cgit v1.2.1 From 727cae4b26d528887e8cc0e7fd503df5b78bc3ac Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 10 Apr 2013 09:11:45 -0400 Subject: tests: fix ntlm-test when built without ntlm_auth support Don't try to use external NTLM auth if built without support for that. https://bugzilla.gnome.org/show_bug.cgi?id=697510 --- configure.ac | 2 ++ tests/ntlm-test.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 80b96498..983bf501 100644 --- a/configure.ac +++ b/configure.ac @@ -319,6 +319,8 @@ if test "$ntlm_auth" != "no"; then dnl --with-ntlm-auth (without path) used, use default path ntlm_auth="/usr/bin/ntlm_auth" fi +else + MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES ntlm_auth" fi AC_SUBST(ntlm_auth) AC_DEFINE_UNQUOTED(NTLM_AUTH, "$ntlm_auth", [Samba's 'winbind' daemon helper 'ntlm_auth' which can be used for NTLM single-sign-on]) diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index 3588c555..f67a3d14 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -571,8 +571,9 @@ main (int argc, char **argv) debug_printf (1, "Built-in NTLM support\n"); do_ntlm_tests (uri, TRUE); +#ifdef USE_NTLM_AUTH /* Samba winbind /usr/bin/ntlm_auth helper support (via a - * helper program that emulate's its interface). + * helper program that emulates its interface). */ g_setenv ("SOUP_NTLM_AUTH_DEBUG", BUILDDIR "/ntlm-test-helper", TRUE); debug_printf (1, "\nExternal helper support\n"); @@ -585,6 +586,7 @@ main (int argc, char **argv) g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); debug_printf (1, "\nExternal -> fallback support\n"); do_ntlm_tests (uri, TRUE); +#endif /* Other tests */ g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); -- cgit v1.2.1 From 2a28ddf6b34546b0f5ca82ce5152612a44a6cd50 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 16 Apr 2013 09:09:10 -0400 Subject: 2.42.1 --- NEWS | 16 ++++++++++++++++ configure.ac | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c697ff3d..ea5a2194 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,19 @@ +Changes in libsoup from 2.42.0 to 2.42.1: + + * Fixed SoupProxyResolverDefault, which got broken in 2.42.92. + [#697028, Dan] + + * Fixed a gigantic memory leak when using SoupCache. [#696594, + Xan] + + * Fixed a build problem on Windows. [#696354, Kalev Lember] + + * Fixed ntlm-test to pass whether or not Samba ntlm_auth + support was compiled in. [#697510, Dan] + + * New/updated translations: + Basque, Turkish + Changes in libsoup from 2.41.92 to 2.42.0: * Fixed a compiler warning on 32bit in a test program. [Kalev diff --git a/configure.ac b/configure.ac index 983bf501..99cb2412 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [42]) -m4_define([soup_micro_version], [0]) +m4_define([soup_micro_version], [1]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 59e85ac49acc693c61cb120d670e76fb19d0c917 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 16 Apr 2013 09:09:54 -0400 Subject: bump version to 2.43.0 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 99cb2412..8d717cc4 100644 --- a/configure.ac +++ b/configure.ac @@ -3,8 +3,8 @@ dnl *** Initialize automake and set version *** dnl ******************************************* m4_define([soup_major_version], [2]) -m4_define([soup_minor_version], [42]) -m4_define([soup_micro_version], [1]) +m4_define([soup_minor_version], [43]) +m4_define([soup_micro_version], [0]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From d61e68e5187224f5b6e0ad4a0060b22d07ba0b64 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Wed, 17 Apr 2013 09:44:29 +0200 Subject: Added version 2.44 defines --- docs/reference/libsoup-2.4-sections.txt | 4 ++++ libsoup/soup-version.h.in | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 1b06804a..9a856429 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -1227,6 +1227,7 @@ SOUP_VERSION_2_36 SOUP_VERSION_2_38 SOUP_VERSION_2_40 SOUP_VERSION_2_42 +SOUP_VERSION_2_44 SOUP_AVAILABLE_IN_2_24 SOUP_AVAILABLE_IN_2_26 @@ -1238,6 +1239,7 @@ SOUP_AVAILABLE_IN_2_36 SOUP_AVAILABLE_IN_2_38 SOUP_AVAILABLE_IN_2_40 SOUP_AVAILABLE_IN_2_42 +SOUP_AVAILABLE_IN_2_44 SOUP_DEPRECATED_IN_2_24 SOUP_DEPRECATED_IN_2_24_FOR SOUP_DEPRECATED_IN_2_26 @@ -1258,6 +1260,8 @@ SOUP_DEPRECATED_IN_2_40 SOUP_DEPRECATED_IN_2_40_FOR SOUP_DEPRECATED_IN_2_42 SOUP_DEPRECATED_IN_2_42_FOR +SOUP_DEPRECATED_IN_2_44 +SOUP_DEPRECATED_IN_2_44_FOR SOUP_ENCODE_VERSION SOUP_VERSION_CUR_STABLE SOUP_VERSION_PREV_STABLE diff --git a/libsoup/soup-version.h.in b/libsoup/soup-version.h.in index 4466a481..c3ad8c67 100644 --- a/libsoup/soup-version.h.in +++ b/libsoup/soup-version.h.in @@ -46,6 +46,7 @@ gboolean soup_check_version (guint major, #define SOUP_VERSION_2_38 (SOUP_ENCODE_VERSION (2, 38)) #define SOUP_VERSION_2_40 (SOUP_ENCODE_VERSION (2, 40)) #define SOUP_VERSION_2_42 (SOUP_ENCODE_VERSION (2, 42)) +#define SOUP_VERSION_2_44 (SOUP_ENCODE_VERSION (2, 44)) /* evaluates to the current stable version; for development cycles, * this means the next stable target @@ -226,6 +227,20 @@ gboolean soup_check_version (guint major, # define SOUP_AVAILABLE_IN_2_42 #endif +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_44 +# define SOUP_DEPRECATED_IN_2_44 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_44_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_44 +# define SOUP_DEPRECATED_IN_2_44_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_44 +# define SOUP_AVAILABLE_IN_2_44 GLIB_UNAVAILABLE(2, 44) +#else +# define SOUP_AVAILABLE_IN_2_44 +#endif + G_END_DECLS #endif /* SOUP_VERSION_H */ -- cgit v1.2.1 From c146806dc176f81be0c7554d67f9e981ee07a3b9 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Wed, 17 Apr 2013 10:15:59 +0200 Subject: soup-message-queue: add a priority system to the message queue Clients can specify a priority for each message added to the SoupSession, which will determine the order in which it is processed by the session's message processing queue. https://bugzilla.gnome.org/show_bug.cgi?id=696277 --- docs/reference/libsoup-2.4-sections.txt | 5 ++ libsoup/libsoup-2.4.sym | 3 ++ libsoup/soup-message-private.h | 2 + libsoup/soup-message-queue.c | 25 +++++++-- libsoup/soup-message-queue.h | 3 +- libsoup/soup-message.c | 91 +++++++++++++++++++++++++++++++++ libsoup/soup-message.h | 18 +++++++ tests/session-test.c | 57 +++++++++++++++++++++ 8 files changed, 200 insertions(+), 4 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 9a856429..4b6ebfd9 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -37,6 +37,10 @@ soup_message_set_chunk_allocator soup_message_disable_feature soup_message_get_soup_request +SoupMessagePriority +soup_message_get_priority +soup_message_set_priority + SOUP_MESSAGE_METHOD SOUP_MESSAGE_URI SOUP_MESSAGE_HTTP_VERSION @@ -45,6 +49,7 @@ SOUP_MESSAGE_STATUS_CODE SOUP_MESSAGE_REASON_PHRASE SOUP_MESSAGE_SERVER_SIDE SOUP_MESSAGE_FIRST_PARTY +SOUP_MESSAGE_PRIORITY SOUP_MESSAGE_REQUEST_BODY SOUP_MESSAGE_REQUEST_HEADERS SOUP_MESSAGE_RESPONSE_BODY diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index 22af1601..d0f22f6e 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -231,6 +231,7 @@ soup_message_get_first_party soup_message_get_flags soup_message_get_https_status soup_message_get_http_version +soup_message_get_priority soup_message_get_soup_request soup_message_get_type soup_message_get_uri @@ -273,11 +274,13 @@ soup_message_io_cleanup soup_message_is_keepalive soup_message_new soup_message_new_from_uri +soup_message_priority_get_type soup_message_restarted soup_message_set_chunk_allocator soup_message_set_first_party soup_message_set_flags soup_message_set_http_version +soup_message_set_priority soup_message_set_redirect soup_message_set_request soup_message_set_response diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index de7cb7d0..356b96db 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -41,6 +41,8 @@ typedef struct { GTlsCertificateFlags tls_errors; SoupRequest *request; + + SoupMessagePriority priority; } SoupMessagePrivate; #define SOUP_MESSAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_MESSAGE, SoupMessagePrivate)) diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index 8b1ebaf9..3dced0e4 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -89,6 +89,7 @@ soup_message_queue_append (SoupMessageQueue *queue, SoupMessage *msg, item->callback = callback; item->callback_data = user_data; item->cancellable = g_cancellable_new (); + item->priority = soup_message_get_priority (msg); g_signal_connect (msg, "restarted", G_CALLBACK (queue_message_restarted), item); @@ -101,9 +102,27 @@ soup_message_queue_append (SoupMessageQueue *queue, SoupMessage *msg, g_mutex_lock (&queue->mutex); if (queue->head) { - queue->tail->next = item; - item->prev = queue->tail; - queue->tail = item; + SoupMessageQueueItem *it = queue->head; + + while (it && it->priority >= item->priority) + it = it->next; + + if (!it) { + if (queue->tail) { + queue->tail->next = item; + item->prev = queue->tail; + } else + queue->head = item; + queue->tail = item; + } else { + if (it != queue->head) + it->prev->next = item; + else + queue->head = item; + item->prev = it->prev; + it->prev = item; + item->next = it; + } } else queue->head = queue->tail = item; diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index 135a6aac..d965e513 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -52,7 +52,8 @@ struct _SoupMessageQueueItem { /*< private >*/ guint removed : 1; - guint ref_count : 31; + guint priority : 3; + guint ref_count : 28; SoupMessageQueueItem *prev, *next; SoupMessageQueueItem *related; }; diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index d30fd372..b65dd76b 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -135,6 +135,7 @@ enum { PROP_RESPONSE_HEADERS, PROP_TLS_CERTIFICATE, PROP_TLS_ERRORS, + PROP_PRIORITY, LAST_PROP }; @@ -145,6 +146,7 @@ soup_message_init (SoupMessage *msg) SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); priv->http_version = priv->orig_http_version = SOUP_HTTP_1_1; + priv->priority = SOUP_MESSAGE_PRIORITY_NORMAL; msg->request_body = soup_message_body_new (); msg->request_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST); @@ -236,6 +238,9 @@ soup_message_set_property (GObject *object, guint prop_id, else if (priv->tls_certificate) priv->msg_flags |= SOUP_MESSAGE_CERTIFICATE_TRUSTED; break; + case PROP_PRIORITY: + priv->priority = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -292,6 +297,9 @@ soup_message_get_property (GObject *object, guint prop_id, case PROP_TLS_ERRORS: g_value_set_flags (value, priv->tls_errors); break; + case PROP_PRIORITY: + g_value_set_enum (value, priv->priority); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -857,6 +865,22 @@ soup_message_class_init (SoupMessageClass *message_class) "The verification errors on the message's TLS certificate", G_TYPE_TLS_CERTIFICATE_FLAGS, 0, G_PARAM_READWRITE)); + /** + * SOUP_MESSAGE_PRIORITY: + * + * Sets the priority of the #SoupMessage. See + * soup_message_set_priority() for further details. + * + * Since: 2.44 + **/ + g_object_class_install_property ( + object_class, PROP_PRIORITY, + g_param_spec_enum (SOUP_MESSAGE_PRIORITY, + "Priority", + "The priority of the message", + SOUP_TYPE_MESSAGE_PRIORITY, + SOUP_MESSAGE_PRIORITY_NORMAL, + G_PARAM_READWRITE)); } @@ -1917,3 +1941,70 @@ soup_message_get_soup_request (SoupMessage *msg) return priv->request; } +/** + * SoupMessagePriority: + * @SOUP_MESSAGE_PRIORITY_VERY_LOW: The lowest priority, the messages + * with this priority will be the last ones to be attended. + * @SOUP_MESSAGE_PRIORITY_LOW: Use this for low priority messages, a + * #SoupMessage with the default priority will be processed first. + * @SOUP_MESSAGE_PRIORITY_NORMAL: The default priotity, this is the + * priority assigned to the #SoupMessage by default. + * @SOUP_MESSAGE_PRIORITY_HIGH: High priority, a #SoupMessage with + * this priority will be processed before the ones with the default + * priority. + * @SOUP_MESSAGE_PRIORITY_VERY_HIGH: The highest priority, use this + * for very urgent #SoupMessage as they will be the first ones to be + * attended. + * + * Priorities that can be set on a #SoupMessage to instruct the + * message queue to process it before any other message with lower + * priority. + **/ + +/** + * soup_message_set_priority: + * @msg: a #SoupMessage + * @priority: the #SoupMessagePriority + * + * Sets the priority of a message. Note that this won't have any + * effect unless used before the message is added to the session's + * message processing queue. + * + * The message will be placed just before any other previously added + * message with lower priority (messages with the same priority are + * processed on a FIFO basis). + * + * Setting priorities does not currently work with #SoupSessionSync + * (or with synchronous messages on a plain #SoupSession) because in + * the synchronous/blocking case, priority ends up being determined + * semi-randomly by thread scheduling. + * + * Since: 2.44 + */ +void +soup_message_set_priority (SoupMessage *msg, + SoupMessagePriority priority) +{ + g_return_if_fail (SOUP_IS_MESSAGE (msg)); + + g_object_set (msg, SOUP_MESSAGE_PRIORITY, priority, NULL); +} + +/** + * soup_message_get_priority: + * @msg: a #SoupMessage + * + * Retrieves the #SoupMessagePriority. If not set this value defaults + * to #SOUP_MESSAGE_PRIORITY_NORMAL. + * + * Return value: the priority of the message. + * + * Since: 2.44 + */ +SoupMessagePriority +soup_message_get_priority (SoupMessage *msg) +{ + g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_MESSAGE_PRIORITY_NORMAL); + + return SOUP_MESSAGE_GET_PRIVATE (msg)->priority; +} diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index 23ec024a..22c2b1ed 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -74,6 +74,7 @@ GType soup_message_get_type (void); #define SOUP_MESSAGE_RESPONSE_HEADERS "response-headers" #define SOUP_MESSAGE_TLS_CERTIFICATE "tls-certificate" #define SOUP_MESSAGE_TLS_ERRORS "tls-errors" +#define SOUP_MESSAGE_PRIORITY "priority" SoupMessage *soup_message_new (const char *method, const char *uri_string); @@ -186,6 +187,23 @@ void soup_message_disable_feature (SoupMessage *msg, SOUP_AVAILABLE_IN_2_42 SoupRequest *soup_message_get_soup_request (SoupMessage *msg); + +typedef enum { + SOUP_MESSAGE_PRIORITY_VERY_LOW = 0, + SOUP_MESSAGE_PRIORITY_LOW, + SOUP_MESSAGE_PRIORITY_NORMAL, + SOUP_MESSAGE_PRIORITY_HIGH, + SOUP_MESSAGE_PRIORITY_VERY_HIGH +} SoupMessagePriority; + +SOUP_AVAILABLE_IN_2_44 +void soup_message_set_priority (SoupMessage *msg, + SoupMessagePriority priority); + + +SOUP_AVAILABLE_IN_2_44 +SoupMessagePriority soup_message_get_priority (SoupMessage *msg); + void soup_message_wrote_informational (SoupMessage *msg); void soup_message_wrote_headers (SoupMessage *msg); void soup_message_wrote_chunk (SoupMessage *msg); diff --git a/tests/session-test.c b/tests/session-test.c index 3207797e..b8e224ea 100644 --- a/tests/session-test.c +++ b/tests/session-test.c @@ -5,6 +5,7 @@ static gboolean server_processed_message; static gboolean timeout; static GMainLoop *loop; +static SoupMessagePriority expected_priorities[3]; static gboolean timeout_cb (gpointer user_data) @@ -207,6 +208,61 @@ do_sync_tests (char *uri, char *timeout_uri) soup_test_session_abort_unref (session); } +static void +priority_test_finished_cb (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + guint *finished_count = user_data; + SoupMessagePriority priority = soup_message_get_priority (msg); + + if (priority != expected_priorities[*finished_count]) { + debug_printf (1, " message %d should have priority %d (%d found)\n", + *finished_count, expected_priorities[*finished_count], priority); + errors++; + } else + debug_printf (1, " received message %d with priority %d\n", + *finished_count, priority); + + (*finished_count)++; +} + +static void +do_priority_tests (char *uri) +{ + SoupSession *session; + int i, finished_count = 0; + SoupMessagePriority priorities[] = + { SOUP_MESSAGE_PRIORITY_LOW, + SOUP_MESSAGE_PRIORITY_HIGH, + SOUP_MESSAGE_PRIORITY_NORMAL }; + + debug_printf (1, "\nSoupSessionAsync\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_object_set (session, "max-conns", 1, NULL); + + expected_priorities[0] = SOUP_MESSAGE_PRIORITY_HIGH; + expected_priorities[1] = SOUP_MESSAGE_PRIORITY_NORMAL; + expected_priorities[2] = SOUP_MESSAGE_PRIORITY_LOW; + + for (i = 0; i < 3; i++) { + char *msg_uri; + SoupMessage *msg; + + msg_uri = g_strdup_printf ("%s/%d", uri, i); + msg = soup_message_new ("GET", uri); + g_free (msg_uri); + + soup_message_set_priority (msg, priorities[i]); + soup_session_queue_message (session, msg, priority_test_finished_cb, &finished_count); + } + + debug_printf (2, " waiting for finished\n"); + while (finished_count != 3) + g_main_context_iteration (NULL, TRUE); + + soup_test_session_abort_unref (session); +} + int main (int argc, char **argv) { @@ -224,6 +280,7 @@ main (int argc, char **argv) do_plain_tests (uri, timeout_uri); do_async_tests (uri, timeout_uri); do_sync_tests (uri, timeout_uri); + do_priority_tests (uri); g_free (uri); g_free (timeout_uri); -- cgit v1.2.1 From 1498c1a6dcb7f6b9aab93838bc9dfd55fd2a5c59 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 17 Apr 2013 17:38:37 -0400 Subject: tests: fix to pass when glib-networking TLS isn't available --- tests/connection-test.c | 28 ++++++++++++++++++++-------- tests/misc-test.c | 32 ++++++++++++++++++++------------ tests/proxy-test.c | 3 +++ 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/tests/connection-test.c b/tests/connection-test.c index b7211363..1a8c51a4 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -769,8 +769,11 @@ do_connection_state_test_for_session (SoupSession *session) debug_printf (1, " http\n"); do_one_connection_state_test (session, HTTP_SERVER); - debug_printf (1, " https\n"); - do_one_connection_state_test (session, HTTPS_SERVER); + if (tls_available) { + debug_printf (1, " https\n"); + do_one_connection_state_test (session, HTTPS_SERVER); + } else + debug_printf (1, " https -- SKIPPING\n"); proxy_uri = soup_uri_new (HTTP_PROXY); g_object_set (G_OBJECT (session), @@ -781,8 +784,11 @@ do_connection_state_test_for_session (SoupSession *session) debug_printf (1, " http with proxy\n"); do_one_connection_state_test (session, HTTP_SERVER); - debug_printf (1, " https with proxy\n"); - do_one_connection_state_test (session, HTTPS_SERVER); + if (tls_available) { + debug_printf (1, " https with proxy\n"); + do_one_connection_state_test (session, HTTPS_SERVER); + } else + debug_printf (1, " https with proxy -- SKIPPING\n"); } static void @@ -884,8 +890,11 @@ do_connection_event_test_for_session (SoupSession *session) debug_printf (1, " http\n"); do_one_connection_event_test (session, HTTP_SERVER, "rRcCx"); - debug_printf (1, " https\n"); - do_one_connection_event_test (session, HTTPS_SERVER, "rRcCtTx"); + if (tls_available) { + debug_printf (1, " https\n"); + do_one_connection_event_test (session, HTTPS_SERVER, "rRcCtTx"); + } else + debug_printf (1, " https -- SKIPPING\n"); proxy_uri = soup_uri_new (HTTP_PROXY); g_object_set (G_OBJECT (session), @@ -896,8 +905,11 @@ do_connection_event_test_for_session (SoupSession *session) debug_printf (1, " http with proxy\n"); do_one_connection_event_test (session, HTTP_SERVER, "rRcCx"); - debug_printf (1, " https with proxy\n"); - do_one_connection_event_test (session, HTTPS_SERVER, "rRcCpPtTx"); + if (tls_available) { + debug_printf (1, " https with proxy\n"); + do_one_connection_event_test (session, HTTPS_SERVER, "rRcCpPtTx"); + } else + debug_printf (1, " https with proxy -- SKIPPING\n"); } static void diff --git a/tests/misc-test.c b/tests/misc-test.c index c0701f3d..a9150a11 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -1021,12 +1021,15 @@ do_aliases_test (void) do_aliases_test_for_session (session, "http"); soup_test_session_abort_unref (session); - debug_printf (1, " foo-means-https\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_HTTPS_ALIASES, aliases, - NULL); - do_aliases_test_for_session (session, "https"); - soup_test_session_abort_unref (session); + if (tls_available) { + debug_printf (1, " foo-means-https\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_HTTPS_ALIASES, aliases, + NULL); + do_aliases_test_for_session (session, "https"); + soup_test_session_abort_unref (session); + } else + debug_printf (1, " foo-means-https -- SKIPPING\n"); debug_printf (1, " foo-means-nothing\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, @@ -1217,10 +1220,12 @@ main (int argc, char **argv) soup_server_add_auth_domain (server, auth_domain); g_object_unref (auth_domain); - ssl_server = soup_test_server_new_ssl (TRUE); - soup_server_add_handler (ssl_server, NULL, server_callback, "https", NULL); - ssl_base_uri = soup_uri_new ("https://127.0.0.1/"); - soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server)); + if (tls_available) { + ssl_server = soup_test_server_new_ssl (TRUE); + soup_server_add_handler (ssl_server, NULL, server_callback, "https", NULL); + ssl_base_uri = soup_uri_new ("https://127.0.0.1/"); + soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server)); + } do_host_test (); do_callback_unref_test (); @@ -1239,9 +1244,12 @@ main (int argc, char **argv) do_pause_abort_test (); soup_uri_free (base_uri); - soup_uri_free (ssl_base_uri); soup_test_server_quit_unref (server); - soup_test_server_quit_unref (ssl_server); + + if (tls_available) { + soup_uri_free (ssl_base_uri); + soup_test_server_quit_unref (ssl_server); + } test_cleanup (); return errors != 0; diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 075289dc..44d125d0 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -340,6 +340,9 @@ do_proxy_redirect_test (void) SoupURI *proxy_uri, *req_uri, *new_uri; SoupMessage *msg; + if (!tls_available) + return; + debug_printf (1, "\nTesting redirection through proxy\n"); proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]); -- cgit v1.2.1 From 8c5ae3c24c95381b52530ac76a80598bb750c1ef Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 18 Apr 2013 10:30:32 -0400 Subject: soup-address: fix proxy enumerator implementation When creating a GProxyAddressEnumerator, the destination URI passed to it must include the port number, or the proxy may end up trying to connect to port 0. libsoup was omitting the port number when it was the default for the protocol. https://bugzilla.gnome.org/show_bug.cgi?id=698163 --- libsoup/soup-address.c | 3 ++- libsoup/soup-misc-private.h | 2 ++ libsoup/soup-uri.c | 39 +++++++++++++++++++++++---------------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index e1696fb0..286be8c7 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -14,6 +14,7 @@ #include "soup-address.h" #include "soup.h" #include "soup-marshal.h" +#include "soup-misc-private.h" /** * SECTION:soup-address @@ -1209,7 +1210,7 @@ soup_address_connectable_proxy_enumerate (GSocketConnectable *connectable) soup_uri_set_host (uri, priv->name ? priv->name : soup_address_get_physical (addr)); soup_uri_set_port (uri, priv->port); soup_uri_set_path (uri, ""); - uri_string = soup_uri_to_string (uri, FALSE); + uri_string = soup_uri_to_string_internal (uri, FALSE, TRUE); proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, "connectable", connectable, diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index cd836189..d03bc77f 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -10,6 +10,8 @@ #include "soup-socket.h" char *uri_decoded_copy (const char *str, int length, int *decoded_length); +char *soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, + gboolean force_port); guint soup_socket_handshake_sync (SoupSocket *sock, GCancellable *cancellable); diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 723e3610..26ec24a0 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -489,21 +489,9 @@ soup_uri_new (const char *uri_string) } -/** - * soup_uri_to_string: - * @uri: a #SoupURI - * @just_path_and_query: if %TRUE, output just the path and query portions - * - * Returns a string representing @uri. - * - * If @just_path_and_query is %TRUE, this concatenates the path and query - * together. That is, it constructs the string that would be needed in - * the Request-Line of an HTTP request for @uri. - * - * Return value: a string representing @uri, which the caller must free. - **/ char * -soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query) +soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, + gboolean force_port) { GString *str; char *return_result; @@ -511,7 +499,7 @@ soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query) g_return_val_if_fail (uri != NULL, NULL); g_warn_if_fail (SOUP_URI_IS_VALID (uri)); - str = g_string_sized_new (20); + str = g_string_sized_new (40); if (uri->scheme && !just_path_and_query) g_string_append_printf (str, "%s:", uri->scheme); @@ -527,7 +515,7 @@ soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query) g_string_append_c (str, ']'); } else append_uri_encoded (str, uri->host, ":/"); - if (uri->port && uri->port != soup_scheme_default_port (uri->scheme)) + if (uri->port && (force_port || uri->port != soup_scheme_default_port (uri->scheme))) g_string_append_printf (str, ":%u", uri->port); if (!uri->path && (uri->query || uri->fragment)) g_string_append_c (str, '/'); @@ -557,6 +545,25 @@ soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query) return return_result; } +/** + * soup_uri_to_string: + * @uri: a #SoupURI + * @just_path_and_query: if %TRUE, output just the path and query portions + * + * Returns a string representing @uri. + * + * If @just_path_and_query is %TRUE, this concatenates the path and query + * together. That is, it constructs the string that would be needed in + * the Request-Line of an HTTP request for @uri. + * + * Return value: a string representing @uri, which the caller must free. + **/ +char * +soup_uri_to_string (SoupURI *uri, gboolean just_path_and_query) +{ + return soup_uri_to_string_internal (uri, just_path_and_query, FALSE); +} + /** * soup_uri_copy: * @uri: a #SoupURI -- cgit v1.2.1 From ce2043a7a81d2d8c9fba3b87a03df52df99e4115 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 18 Apr 2013 15:40:55 -0400 Subject: misc-test: skip the IPv6 server test if there's no IPv6 support https://bugzilla.gnome.org/show_bug.cgi?id=698220 --- tests/misc-test.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/misc-test.c b/tests/misc-test.c index a9150a11..39ee960b 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -1110,6 +1110,11 @@ do_ipv6_test (void) ipv6_server = soup_server_new (SOUP_SERVER_INTERFACE, ipv6_addr, NULL); g_object_unref (ipv6_addr); + if (!ipv6_server) { + debug_printf (1, " skipping due to lack of IPv6 support\n"); + return; + } + soup_server_add_handler (ipv6_server, NULL, ipv6_server_callback, NULL, NULL); soup_server_run_async (ipv6_server); -- cgit v1.2.1 From 9b00583aabca2c7200189c8e40f34dda819c3e80 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 19 Apr 2013 09:57:34 -0400 Subject: Fix build on Windows, deprecate soup-portability.h soup-portability.h created portability problems (ha!) because the windows headers do "#define interface struct", conflicting with variable names elsewhere. The only thing that needed soup-portability.h in the public headers was soup-address.h, which uses struct sockaddr. But we can just do a forward declaration of that type rather than actually pulling in the headers. Then soup-address.h can stop including soup-portability.h, and we can use gio/gnetworking.h in the handful of other places that need networking-related includes. This may possibly break some other modules that depended on implicitly getting network includes as a side effect of including soup.h... https://bugzilla.gnome.org/show_bug.cgi?id=692134 --- libsoup/soup-address.c | 2 ++ libsoup/soup-address.h | 3 ++- libsoup/soup-socket.c | 2 ++ tests/connection-test.c | 2 ++ tests/socket-test.c | 6 ++---- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index 286be8c7..da4da948 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -11,6 +11,8 @@ #include +#include + #include "soup-address.h" #include "soup.h" #include "soup-marshal.h" diff --git a/libsoup/soup-address.h b/libsoup/soup-address.h index dd4c275d..797a5506 100644 --- a/libsoup/soup-address.h +++ b/libsoup/soup-address.h @@ -8,7 +8,6 @@ #include -#include #include G_BEGIN_DECLS @@ -51,6 +50,8 @@ typedef enum { #define SOUP_ADDRESS_ANY_PORT 0 +struct sockaddr; + typedef void (*SoupAddressCallback) (SoupAddress *addr, guint status, gpointer user_data); diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 4268429b..9e4de132 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -11,6 +11,8 @@ #include +#include + #include "soup-socket.h" #include "soup.h" #include "soup-filter-input-stream.h" diff --git a/tests/connection-test.c b/tests/connection-test.c index 1a8c51a4..cdc4cced 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -5,6 +5,8 @@ #include "test-utils.h" +#include + SoupServer *server; SoupURI *base_uri; GMutex server_mutex; diff --git a/tests/socket-test.c b/tests/socket-test.c index 60c3e86c..42ab6c8b 100644 --- a/tests/socket-test.c +++ b/tests/socket-test.c @@ -4,12 +4,10 @@ * Copyright 2012 Nokia Corporation */ -#include - -#include - #include "test-utils.h" +#include + static void do_unconnected_socket_test (void) { -- cgit v1.2.1 From 39e527cdc1af04afdf13207f5503afa7b772043e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 19 Apr 2013 10:54:05 -0400 Subject: build: update Makefile.glib If a SOURCES variable changes, we need to recheck the generated files, since a file may have been removed from SOURCES, but still be referenced in a previously-generated -enum-types.c file, etc. So make these generated files depend on Makefile. Also, update spacing of silent rules to match current automake. --- Makefile.glib | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Makefile.glib b/Makefile.glib index 8713f9a8..c28c983b 100644 --- a/Makefile.glib +++ b/Makefile.glib @@ -128,7 +128,7 @@ _GLIB_DISTCLEANFILES = _GLIB_V_GEN = $(_glib_v_gen_$(V)) _glib_v_gen_ = $(_glib_v_gen_$(AM_DEFAULT_VERBOSITY)) -_glib_v_gen_0 = @echo " GEN " $(subst .stamp,,$@); +_glib_v_gen_0 = @echo " GEN " $(subst .stamp,,$@); ### glib-genmarshal @@ -154,8 +154,8 @@ _glib_marshal_sources = $(filter-out %.h,$(filter-out $(GLIB_GENERATED),$($(_gli define _glib_make_genmarshal_rules $(if $(_glib_marshal_sources),,$(error Need to define $(_glib_marshal_sources_var) for $(1).[ch])) -$(1).list.stamp: $(_glib_marshal_sources) - $$(_GLIB_V_GEN) LC_ALL=C sed -ne 's/.*_$(_glib_marshal_prefix)_\([_A-Z0-9]*\).*/\1/p' $$^ | sort -u | sed -e 's/__/:/' -e 's/_/,/g' > $(1).list.tmp && \ +$(1).list.stamp: $(_glib_marshal_sources) Makefile + $$(_GLIB_V_GEN) LC_ALL=C sed -ne 's/.*_$(_glib_marshal_prefix)_\([_A-Z]*\).*/\1/p' $$(filter-out Makefile, $$^) | sort -u | sed -e 's/__/:/' -e 's/_/,/g' > $(1).list.tmp && \ (cmp -s $(1).list.tmp $(1).list || cp $(1).list.tmp $(1).list) && \ rm -f $(1).list.tmp && \ echo timestamp > $$@ @@ -200,7 +200,7 @@ _glib_enum_types_h_sources = $(filter %.h,$(_glib_enum_types_sources)) define _glib_make_mkenums_rules $(if $(_glib_enum_types_sources),,$(error Need to define $(_glib_enum_types_sources_var) for $(1).[ch])) -$(1).h.stamp: $(_glib_enum_types_h_sources) +$(1).h.stamp: $(_glib_enum_types_h_sources) Makefile $$(_GLIB_V_GEN) $$(GLIB_MKENUMS) \ --fhead "/* Generated by glib-mkenums. Do not edit */\n\n#ifndef $(_glib_enum_types_guard)\n#define $(_glib_enum_types_guard)\n\n" \ $$(GLIB_MKENUMS_H_FLAGS) \ @@ -208,7 +208,7 @@ $(1).h.stamp: $(_glib_enum_types_h_sources) --fhead "#include \n\nG_BEGIN_DECLS\n" \ --vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())\n" \ --ftail "G_END_DECLS\n\n#endif /* $(_glib_enum_types_guard) */" \ - $$^ > $(1).h.tmp && \ + $$(filter-out Makefile, $$^) > $(1).h.tmp && \ (cmp -s $(1).h.tmp $(1).h || cp $(1).h.tmp $(1).h) && \ rm -f $(1).h.tmp && \ echo timestamp > $$@ @@ -216,16 +216,16 @@ $(1).h.stamp: $(_glib_enum_types_h_sources) $(1).h: $(1).h.stamp @true -$(1).c.stamp: $(_glib_enum_types_h_sources) +$(1).c.stamp: $(_glib_enum_types_h_sources) Makefile $$(_GLIB_V_GEN) $$(GLIB_MKENUMS) \ --fhead "/* Generated by glib-mkenums. Do not edit */\n\n#include \"$(notdir $(1)).h\"\n" \ $$(GLIB_MKENUMS_C_FLAGS) \ $$($(_glib_enum_types_prefix)_MKENUMS_C_FLAGS) \ - --fhead "$$(foreach f,$$(^F),\n#include \"$$(f)\")\n\n" \ + --fhead "$$(foreach f,$$(filter-out Makefile,$$(^F)),\n#include \"$$(f)\")\n\n" \ --vhead "GType\n@enum_name@_get_type (void)\n{\n static volatile gsize g_define_type_id__volatile = 0;\n\n if (g_once_init_enter (&g_define_type_id__volatile))\n {\n static const G@Type@Value values[] = {\n" \ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" },\n" \ --vtail " { 0, NULL, NULL }\n };\n GType g_define_type_id =\n g_@type@_register_static (g_intern_static_string (\"@EnumName@\"), values);\n g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);\n }\n\n return g_define_type_id__volatile;\n}\n" \ - $$^ > $(1).c.tmp && \ + $$(filter-out Makefile, $$^) > $(1).c.tmp && \ (cmp -s $(1).c.tmp $(1).c || cp $(1).c.tmp $(1).c) && \ rm -f $(1).c.tmp && \ echo timestamp > $$@ @@ -254,13 +254,13 @@ _glib_enums_xml_namespace = $(subst .enums.xml,,$(notdir $(1))) define _glib_make_enums_xml_rule $(if $(_glib_enums_xml_sources),,$(error Need to define $(_glib_enums_xml_sources_var) for $(1))) -$(1): $(_glib_enums_xml_sources) - $$(_GLIB_V_GEN) $$(GLIB_MKENUMS) --comments '' --fhead "" --vhead " <@type@ id='$(_glib_enums_xml_namespace).@EnumName@'>" --vprod " " --vtail " " --ftail "" $$^ > $$@.tmp && mv $$@.tmp $$@ +$(1): $(_glib_enums_xml_sources) Makefile + $$(_GLIB_V_GEN) $$(GLIB_MKENUMS) --comments '' --fhead "" --vhead " <@type@ id='$(_glib_enums_xml_namespace).@EnumName@'>" --vprod " " --vtail " " --ftail "" $$(filter-out Makefile, $$^) > $$@.tmp && mv $$@.tmp $$@ endef _GLIB_V_CHECK = $(_glib_v_check_$(V)) _glib_v_check_ = $(_glib_v_check_$(AM_DEFAULT_VERBOSITY)) -_glib_v_check_0 = @echo " CHECK " $(subst .valid,.xml,$@); +_glib_v_check_0 = @echo " CHECK " $(subst .valid,.xml,$@); define _glib_make_schema_validate_rule $(subst .xml,.valid,$(1)): $(_GLIB_ENUMS_XML_GENERATED) $(1) -- cgit v1.2.1 From 816cdc96f30087cb9427312b86e6bdc807349628 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 30 Apr 2013 16:51:51 -0400 Subject: 2.43.1 --- NEWS | 19 +++++++++++++++++++ configure.ac | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ea5a2194..808ba000 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,22 @@ +Changes in libsoup from 2.42.1 to 2.43.1: + + * Including no longer pulls in the system + networking headers. This may cause some packages to no + longer compile, if they were accidentally depending on this. + Adding "#include " will fix them on both + unix and Windows. (This was done as part of fixing the build + on Windows.) [#692134, Dan] + + * Fixed SoupSession:proxy-resolver [#698163, Dan] + + * Added soup_message_set_priority(), to mark messages as being + high, low, or normal priority, and update the message queue + to prioritize them accordingly. [#696277, Sergio] + + * Fixed several test programs to still work if glib-networking + isn't installed [Dan], and fixed another to still work if + the kernel has no IPv6 support. [#698220, Dan] + Changes in libsoup from 2.42.0 to 2.42.1: * Fixed SoupProxyResolverDefault, which got broken in 2.42.92. diff --git a/configure.ac b/configure.ac index 8d717cc4..8bbf9613 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [43]) -m4_define([soup_micro_version], [0]) +m4_define([soup_micro_version], [1]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 663995a495a2e7906787c6452a3053fab5d267d4 Mon Sep 17 00:00:00 2001 From: Erik van Pienbroek Date: Thu, 9 May 2013 13:46:45 +0200 Subject: Include string.h in soup-request-file.c Resolves implicit declaration failures of functions like 'strchr' https://bugzilla.gnome.org/show_bug.cgi?id=700003 --- libsoup/soup-request-file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c index 49b741d0..5a56b28b 100644 --- a/libsoup/soup-request-file.c +++ b/libsoup/soup-request-file.c @@ -25,6 +25,8 @@ #include #endif +#include + #include "soup-request-file.h" #include "soup.h" #include "soup-directory-input-stream.h" -- cgit v1.2.1 From 53da10780a2728cdd77bbae47ec5755efd929ff5 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 15 May 2013 08:32:44 -0400 Subject: tests: fix a memory leak --- tests/test-utils.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test-utils.c b/tests/test-utils.c index 8e0fb257..b528b786 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -413,9 +413,10 @@ cancel_message_or_cancellable (CancelData *cancel_data) { if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_MESSAGE) { SoupRequest *req = cancel_data->req; - soup_session_cancel_message (soup_request_get_session (req), - soup_request_http_get_message (SOUP_REQUEST_HTTP (req)), + SoupMessage *msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); + soup_session_cancel_message (soup_request_get_session (req), msg, SOUP_STATUS_CANCELLED); + g_object_unref (msg); g_object_unref (req); } else if (cancel_data->flags & SOUP_TEST_REQUEST_CANCEL_CANCELLABLE) { g_cancellable_cancel (cancel_data->cancellable); -- cgit v1.2.1 From a51cd9ea7aa32444ff48b3f29f15c410581b6540 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 15 May 2013 11:27:44 -0400 Subject: soup-auth-manager: don't send host auth to proxy servers When sending a CONNECT request, don't include auth headers intended for the origin server. (And in particular, when doing NTLM through a proxy, don't assume that the NTLM auth succeeded because the proxy returned 200 to the CONNECT request.) Part of https://bugzilla.gnome.org/show_bug.cgi?id=698728 --- libsoup/soup-auth-manager.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index b1647915..3f230b1a 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -679,13 +679,15 @@ soup_auth_manager_request_started (SoupSessionFeature *feature, g_mutex_lock (&priv->lock); - auth = lookup_auth (priv, msg); - if (auth) { - authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE); - if (!soup_auth_is_ready (auth, msg)) - auth = NULL; + if (msg->method != SOUP_METHOD_CONNECT) { + auth = lookup_auth (priv, msg); + if (auth) { + authenticate_auth (manager, auth, msg, FALSE, FALSE, FALSE); + if (!soup_auth_is_ready (auth, msg)) + auth = NULL; + } + soup_message_set_auth (msg, auth); } - soup_message_set_auth (msg, auth); auth = priv->proxy_auth; if (auth) { -- cgit v1.2.1 From 562f2b86f8070c3fe6b21c22fdb8bda76acf6e6b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 20 May 2013 14:54:02 -0300 Subject: soup-session: cope with the dummy TLS backend better Make SoupSession handle GDummyTlsBackend a little better (and add a test for it). https://bugzilla.gnome.org/show_bug.cgi?id=700518 --- libsoup/soup-session.c | 22 ++++-- tests/Makefile.am | 1 + tests/no-ssl-test.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+), 8 deletions(-) create mode 100644 tests/no-ssl-test.c diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 186d57ad..066cfde9 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -439,10 +439,12 @@ set_tlsdb (SoupSession *session, GTlsDatabase *tlsdb) g_object_freeze_notify (G_OBJECT (session)); system_default = g_tls_backend_get_default_database (g_tls_backend_get_default ()); - if (priv->tlsdb == system_default || tlsdb == system_default) { - g_object_notify (G_OBJECT (session), "ssl-use-system-ca-file"); + if (system_default) { + if (priv->tlsdb == system_default || tlsdb == system_default) { + g_object_notify (G_OBJECT (session), "ssl-use-system-ca-file"); + } + g_object_unref (system_default); } - g_object_unref (system_default); if (priv->ssl_ca_file) { g_free (priv->ssl_ca_file); @@ -473,7 +475,7 @@ set_use_system_ca_file (SoupSession *session, gboolean use_system_ca_file) else if (priv->tlsdb == system_default) set_tlsdb (session, NULL); - g_object_unref (system_default); + g_clear_object (&system_default); } static void @@ -510,11 +512,15 @@ set_ssl_ca_file (SoupSession *session, const char *ssl_ca_file) } set_tlsdb (session, tlsdb); - if (tlsdb) + if (tlsdb) { g_object_unref (tlsdb); - priv->ssl_ca_file = g_strdup (ssl_ca_file); - g_object_notify (G_OBJECT (session), "ssl-ca-file"); + priv->ssl_ca_file = g_strdup (ssl_ca_file); + g_object_notify (G_OBJECT (session), "ssl-ca-file"); + } else if (priv->ssl_ca_file) { + g_clear_pointer (&priv->ssl_ca_file, g_free); + g_object_notify (G_OBJECT (session), "ssl-ca-file"); + } g_object_thaw_notify (G_OBJECT (session)); } @@ -730,7 +736,7 @@ soup_session_get_property (GObject *object, guint prop_id, case PROP_SSL_USE_SYSTEM_CA_FILE: tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); g_value_set_boolean (value, priv->tlsdb == tlsdb); - g_object_unref (tlsdb); + g_clear_object (&tlsdb); break; case PROP_TLS_DATABASE: g_value_set_object (value, priv->tlsdb); diff --git a/tests/Makefile.am b/tests/Makefile.am index 417b04c7..6fa6d1c3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -22,6 +22,7 @@ TESTS = \ header-parsing \ misc-test \ multipart-test \ + no-ssl-test \ ntlm-test \ proxy-test \ pull-api \ diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c new file mode 100644 index 00000000..89a75206 --- /dev/null +++ b/tests/no-ssl-test.c @@ -0,0 +1,199 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +#include "test-utils.h" + +static void +do_ssl_test_for_session (SoupSession *session, char *uri) +{ + SoupMessage *msg; + GTlsCertificate *cert; + GTlsCertificateFlags flags; + + msg = soup_message_new ("GET", uri); + soup_session_send_message (session, msg); + if (msg->status_code != SOUP_STATUS_SSL_FAILED) { + debug_printf (1, " Unexpected status: %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + + if (soup_message_get_https_status (msg, &cert, &flags)) { + debug_printf (1, " get_http_status() returned TRUE? (flags %x)\n", flags); + errors++; + if (cert) { + debug_printf (1, " Got GTlsCertificate?\n"); + errors++; + } + } + if (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) { + debug_printf (1, " CERTIFICATE_TRUSTED set?\n"); + errors++; + } + + g_object_unref (msg); +} + +static void +do_ssl_tests (char *uri) +{ + SoupSession *session; + + debug_printf (1, "\nSoupSession without SSL support\n"); + + debug_printf (1, " plain\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); + + debug_printf (1, " async\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); + + debug_printf (1, " sync\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); +} + +static void +do_session_property_tests (void) +{ + gboolean use_system; + GTlsDatabase *tlsdb; + char *ca_file; + SoupSession *session; + + debug_printf (1, "session properties\n"); + + session = soup_session_async_new (); + + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + if (use_system) { + debug_printf (1, " ssl-use-system-ca-file defaults to TRUE?\n"); + errors++; + } + if (tlsdb) { + debug_printf (1, " tls-database set by default?\n"); + errors++; + g_object_unref (tlsdb); + } + if (ca_file) { + debug_printf (1, " ca-file set by default?\n"); + errors++; + g_free (ca_file); + } + + g_object_set (G_OBJECT (session), + "ssl-use-system-ca-file", TRUE, + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "ssl-ca-file", &ca_file, + NULL); + if (use_system) { + debug_printf (1, " setting ssl-use-system-ca-file did not fail\n"); + errors++; + } + if (ca_file) { + debug_printf (1, " setting ssl-use-system-ca-file set ssl-ca-file\n"); + errors++; + g_free (ca_file); + } + + g_object_set (G_OBJECT (session), + "ssl-ca-file", SRCDIR "/test-cert.pem", + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + if (ca_file) { + debug_printf (1, " setting ssl-ca-file did not fail\n"); + errors++; + g_free (ca_file); + } + if (use_system) { + debug_printf (1, " setting ssl-ca-file set ssl-use-system-ca-file\n"); + errors++; + } + if (tlsdb) { + debug_printf (1, " setting ssl-ca-file set tls-database\n"); + errors++; + g_object_unref (tlsdb); + } + + g_object_set (G_OBJECT (session), + "tls-database", NULL, + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + if (tlsdb) { + debug_printf (1, " setting tls-database NULL failed\n"); + errors++; + g_object_unref (tlsdb); + } + if (use_system) { + debug_printf (1, " setting tls-database NULL set ssl-use-system-ca-file\n"); + errors++; + } + if (ca_file) { + debug_printf (1, " setting tls-database NULL set ssl-ca-file\n"); + errors++; + g_free (ca_file); + } + + soup_test_session_abort_unref (session); +} + +static void +server_handler (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) +{ + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "ok\r\n", 4); +} + +int +main (int argc, char **argv) +{ + SoupServer *server; + char *uri; + + /* Force this test to use the dummy TLS backend */ + g_setenv ("GIO_USE_TLS", "dummy", TRUE); + + test_init (argc, argv, NULL); + + /* Make a non-SSL server and pretend that it's ssl, which is fine + * since we won't ever actually talk to it anyway. We don't + * currently test that failing to construct an SSL server works. + */ + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = g_strdup_printf ("https://127.0.0.1:%u/", + soup_server_get_port (server)); + + do_session_property_tests (); + do_ssl_tests (uri); + + g_free (uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return errors != 0; +} -- cgit v1.2.1 From b038f13190b59c27b96a5f82501b838df058940c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Tue, 21 May 2013 09:51:17 -0300 Subject: soup-socket: fix a memory leak https://bugzilla.gnome.org/show_bug.cgi?id=700472 --- libsoup/soup-socket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 9e4de132..fdec66dd 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -1404,8 +1404,11 @@ soup_socket_get_http_proxy_uri (SoupSocket *sock) if (!priv->gsock) return NULL; addr = g_socket_get_remote_address (priv->gsock, NULL); - if (!addr || !G_IS_PROXY_ADDRESS (addr)) + if (!addr || !G_IS_PROXY_ADDRESS (addr)) { + if (addr) + g_object_unref (addr); return NULL; + } paddr = G_PROXY_ADDRESS (addr); if (strcmp (g_proxy_address_get_protocol (paddr), "http") != 0) -- cgit v1.2.1 From a58dc77fb50d67c05d0f695d1a7173ac6241649e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 21 May 2013 11:41:55 -0300 Subject: multipart-test: fix quotes in messages --- tests/multipart-test.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/multipart-test.c b/tests/multipart-test.c index a9b3425d..bfe4f5b2 100644 --- a/tests/multipart-test.c +++ b/tests/multipart-test.c @@ -113,12 +113,12 @@ got_headers (SoupMessage *msg, int *headers_count) } if (!g_str_equal (name, "Content-Type")) { - debug_printf (1, " expected `Content-Type' got %s\n", name); + debug_printf (1, " expected 'Content-Type' got %s\n", name); errors++; } if (!g_str_equal (value, "multipart/x-mixed-replace; boundary=cut-here")) { - debug_printf (1, " expected `multipart/x-mixed-replace; boundary=cut-here' got %s\n", value); + debug_printf (1, " expected 'multipart/x-mixed-replace; boundary=cut-here' got %s\n", value); errors++; } } @@ -293,12 +293,12 @@ check_headers (SoupMultipartInputStream* multipart, unsigned passes) check_is_next (is_next); if (!g_str_equal (name, "Content-Type")) { - debug_printf (1, " [0] expected `Content-Type' got %s\n", name); + debug_printf (1, " [0] expected 'Content-Type' got %s\n", name); errors++; } if (!g_str_equal (value, "text/html")) { - debug_printf (1, " [0] expected `text/html' got %s\n", value); + debug_printf (1, " [0] expected 'text/html' got %s\n", value); errors++; } @@ -306,12 +306,12 @@ check_headers (SoupMultipartInputStream* multipart, unsigned passes) check_is_next (is_next); if (!g_str_equal (name, "Content-Length")) { - debug_printf (1, " [0] expected `Content-Length' got %s\n", name); + debug_printf (1, " [0] expected 'Content-Length' got %s\n", name); errors++; } if (!g_str_equal (value, "30")) { - debug_printf (1, " [0] expected `30' got %s\n", value); + debug_printf (1, " [0] expected '30' got %s\n", value); errors++; } @@ -321,12 +321,12 @@ check_headers (SoupMultipartInputStream* multipart, unsigned passes) check_is_next (is_next); if (!g_str_equal (name, "Content-Length")) { - debug_printf (1, " [1] expected `Content-Length' got %s\n", name); + debug_printf (1, " [1] expected 'Content-Length' got %s\n", name); errors++; } if (!g_str_equal (value, "10")) { - debug_printf (1, " [1] expected `10' got %s\n", value); + debug_printf (1, " [1] expected '10' got %s\n", value); errors++; } @@ -337,12 +337,12 @@ check_headers (SoupMultipartInputStream* multipart, unsigned passes) check_is_next (is_next); if (!g_str_equal (name, "Content-Type")) { - debug_printf (1, " [%d] expected `Content-Type' got %s\n", passes, name); + debug_printf (1, " [%d] expected 'Content-Type' got %s\n", passes, name); errors++; } if (!g_str_equal (value, "text/css")) { - debug_printf (1, " [%d] expected `text/html' got %s\n", passes, value); + debug_printf (1, " [%d] expected 'text/html' got %s\n", passes, value); errors++; } -- cgit v1.2.1 From 1e48dc8f9a8a90e8e644ce78882c9468ca1d298b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 22 May 2013 10:52:50 -0300 Subject: Fix a slightly-erroneous comment in soup-auth-basic/soup-auth-ntlm. --- libsoup/soup-auth-basic.c | 2 +- libsoup/soup-auth-ntlm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-auth-basic.c b/libsoup/soup-auth-basic.c index fefe1c7e..f298e36c 100644 --- a/libsoup/soup-auth-basic.c +++ b/libsoup/soup-auth-basic.c @@ -73,7 +73,7 @@ soup_auth_basic_get_protection_space (SoupAuth *auth, SoupURI *source_uri) space = g_strdup (source_uri->path); - /* Strip query and filename component */ + /* Strip filename component */ p = strrchr (space, '/'); if (p && p != space && p[1]) *p = '\0'; diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index 7b11a436..cff469f7 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -372,7 +372,7 @@ soup_auth_ntlm_get_protection_space (SoupAuth *auth, SoupURI *source_uri) space = g_strdup (source_uri->path); - /* Strip query and filename component */ + /* Strip filename component */ p = strrchr (space, '/'); if (p && p != space && p[1]) *p = '\0'; -- cgit v1.2.1 From 8b1763d8429872e216f25d6a72c6f898226ae0fd Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 28 May 2013 14:05:35 -0300 Subject: 2.43.2 --- NEWS | 17 +++++++++++++++++ configure.ac | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 808ba000..06ba7b74 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,20 @@ +Changes in libsoup from 2.43.1 to 2.43.2: + + * Fixed an authentication error when using NTLM when + connecting to an https site over a proxy; the code was + getting confused and thinking that the 200 OK response to + the CONNECT meant that NTLM auth had succeeded. [#698728, + Dan] + + * Fixed a memory leak in SoupSocket. [#700472, Richard + Röjfors] + + * Fixed a missing include error on some platforms [#700003, + Erik van Pienbroek] + + * Fixed warnings when running against the "dummy" TLS backend. + [#700518, Dan] + Changes in libsoup from 2.42.1 to 2.43.1: * Including no longer pulls in the system diff --git a/configure.ac b/configure.ac index 8bbf9613..ccdf5b08 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [43]) -m4_define([soup_micro_version], [1]) +m4_define([soup_micro_version], [2]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From bd39b5703f5c58a9097a2c409bf83c222d42fbcb Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 31 May 2013 15:25:56 -0300 Subject: soup-session: fix a concurrency bug soup_session_kick_queue() should have been locking conn_mutex around signalling conn_cond, since otherwise there's a race condition where it could signal just before someone else starts waiting. (In reality, this is unlikely to cause problems, since we tend to signal conn_cond more than is actually necessary. But maybe we'll get better about not doing that in the future.) --- libsoup/soup-session.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 066cfde9..2ae7249a 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -2148,8 +2148,11 @@ soup_session_real_kick_queue (SoupSession *session) have_sync_items = TRUE; } - if (have_sync_items) + if (have_sync_items) { + g_mutex_lock (&priv->conn_lock); g_cond_broadcast (&priv->conn_cond); + g_mutex_unlock (&priv->conn_lock); + } } void -- cgit v1.2.1 From 961dc48ae20f970026f87d0e74f31cc7094ea654 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 8 Jun 2013 20:31:03 -0300 Subject: soup-socket: fix another leak in soup_socket_get_http_proxy_uri() Add a test for the leak in bug 700472, which also turned up another leak. https://bugzilla.gnome.org/show_bug.cgi?id=700472 --- libsoup/soup-socket.c | 5 ++++- tests/proxy-test.c | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index fdec66dd..ee1aac99 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -1400,6 +1400,7 @@ soup_socket_get_http_proxy_uri (SoupSocket *sock) SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); GSocketAddress *addr; GProxyAddress *paddr; + SoupURI *uri; if (!priv->gsock) return NULL; @@ -1414,7 +1415,9 @@ soup_socket_get_http_proxy_uri (SoupSocket *sock) if (strcmp (g_proxy_address_get_protocol (paddr), "http") != 0) return NULL; - return soup_uri_new (g_proxy_address_get_uri (paddr)); + uri = soup_uri_new (g_proxy_address_get_uri (paddr)); + g_object_unref (addr); + return uri; } static gboolean diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 44d125d0..682b5375 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -16,6 +16,7 @@ static SoupProxyTest tests[] = { { "GET -> 401 -> 200", "/Basic/realm1/", SOUP_STATUS_OK }, { "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED }, { "GET -> 403", "http://no-such-hostname.xx/", SOUP_STATUS_FORBIDDEN }, + { "GET -> 200 (unproxied)", "http://localhost:47524/", SOUP_STATUS_OK }, }; static const int ntests = sizeof (tests) / sizeof (tests[0]); @@ -37,6 +38,8 @@ static const char *proxy_names[] = { "authenticated proxy", "unauthenticatable-to proxy" }; +static GProxyResolver *proxy_resolvers[3]; +static const char *ignore_hosts[] = { "localhost", NULL }; static void authenticate (SoupSession *session, SoupMessage *msg, @@ -82,26 +85,25 @@ test_url (const char *url, int proxy, guint expected, gboolean sync, gboolean close) { SoupSession *session; - SoupURI *proxy_uri; SoupMessage *msg; + gboolean noproxy = !!strstr (url, "localhost"); if (!tls_available && g_str_has_prefix (url, "https:")) return; debug_printf (1, " GET %s via %s%s\n", url, proxy_names[proxy], close ? " (with Connection: close)" : ""); - if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN) + if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN && !noproxy) expected = SOUP_STATUS_PROXY_UNAUTHORIZED; /* We create a new session for each request to ensure that * connections/auth aren't cached between tests. */ - proxy_uri = soup_uri_new (proxies[proxy]); session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_PROXY_URI, proxy_uri, + SOUP_SESSION_PROXY_RESOLVER, proxy_resolvers[proxy], SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + SOUP_SESSION_SSL_STRICT, FALSE, NULL); - soup_uri_free (proxy_uri); g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), NULL); if (close) { @@ -132,29 +134,28 @@ test_url_new_api (const char *url, int proxy, guint expected, gboolean sync, gboolean close) { SoupSession *session; - SoupURI *proxy_uri; SoupMessage *msg; SoupRequest *request; GInputStream *stream; GError *error = NULL; + gboolean noproxy = !!strstr (url, "localhost"); if (!tls_available && g_str_has_prefix (url, "https:")) return; debug_printf (1, " GET (request API) %s via %s%s\n", url, proxy_names[proxy], close ? " (with Connection: close)" : ""); - if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN) + if (proxy == UNAUTH_PROXY && expected != SOUP_STATUS_FORBIDDEN && !noproxy) expected = SOUP_STATUS_PROXY_UNAUTHORIZED; /* We create a new session for each request to ensure that * connections/auth aren't cached between tests. */ - proxy_uri = soup_uri_new (proxies[proxy]); session = soup_test_session_new (sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - SOUP_SESSION_PROXY_URI, proxy_uri, + SOUP_SESSION_PROXY_RESOLVER, proxy_resolvers[proxy], + SOUP_SESSION_SSL_STRICT, FALSE, NULL); - soup_uri_free (proxy_uri); g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), NULL); @@ -206,8 +207,18 @@ run_test (int i, gboolean sync) sync ? "sync" : "async"); if (!strncmp (tests[i].url, "http", 4)) { + SoupURI *uri; + guint port; + http_url = g_strdup (tests[i].url); - https_url = g_strdup_printf ("https%s", tests[i].url + 4); + + uri = soup_uri_new (tests[i].url); + port = uri->port; + soup_uri_set_scheme (uri, "https"); + if (port) + soup_uri_set_port (uri, port + 1); + https_url = soup_uri_to_string (uri, FALSE); + soup_uri_free (uri); } else { http_url = g_strconcat (HTTP_SERVER, tests[i].url, NULL); https_url = g_strconcat (HTTPS_SERVER, tests[i].url, NULL); @@ -380,10 +391,16 @@ main (int argc, char **argv) { SoupServer *server; SoupURI *base_uri; + int i; test_init (argc, argv, NULL); apache_init (); + for (i = 0; i < 3; i++) { + proxy_resolvers[i] = + g_simple_proxy_resolver_new (proxies[i], (char **) ignore_hosts); + } + server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); base_uri = soup_uri_new ("http://127.0.0.1/"); -- cgit v1.2.1 From 7539b3c15ece007f0d1894f2e0cbb4d32898f4cf Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Fri, 12 Oct 2012 17:41:58 +0200 Subject: use libfffi-based generic marshaller instead of glib-genmarshal g_cclosure_marshal_generic() is the default signal handler starting from glib 2.29.12. libsoup already requires glib 2.33.1. https://bugzilla.gnome.org/show_bug.cgi?id=686042 --- .gitignore | 1 - docs/reference/Makefile.am | 2 +- libsoup/Makefile.am | 8 ++------ libsoup/soup-address.c | 1 - libsoup/soup-auth-domain-basic.c | 1 - libsoup/soup-auth-domain-digest.c | 1 - libsoup/soup-auth-manager.c | 3 +-- libsoup/soup-auth.c | 1 - libsoup/soup-body-input-stream.c | 3 +-- libsoup/soup-client-input-stream.c | 3 +-- libsoup/soup-connection.c | 3 +-- libsoup/soup-cookie-jar.c | 3 +-- libsoup/soup-message.c | 25 ++++++++++++------------- libsoup/soup-server.c | 9 ++++----- libsoup/soup-session.c | 13 ++++++------- libsoup/soup-socket.c | 9 ++++----- 16 files changed, 34 insertions(+), 52 deletions(-) diff --git a/.gitignore b/.gitignore index b3a877b9..d7c22fba 100644 --- a/.gitignore +++ b/.gitignore @@ -45,7 +45,6 @@ libsoup-zip libsoup-2.4.pc libsoup-gnome-2.4.pc libsoup/soup-enum-types.* -libsoup/soup-marshal.* libsoup/Soup-2.4.gir libsoup/Soup-2.4.typelib libsoup/SoupGNOME-2.4.gir diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index d36977ec..29ff97e0 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -29,7 +29,7 @@ HFILE_GLOB= CFILE_GLOB= # Header files to ignore when scanning. -IGNORE_HFILES= soup.h soup-marshal.h soup-enum-types.h \ +IGNORE_HFILES= soup.h soup-enum-types.h \ soup-message-private.h soup-session-private.h \ soup-auth-basic.h soup-auth-digest.h soup-auth-ntlm.h \ soup-connection.h soup-connection-auth.h \ diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index d54a06a9..c2f69aec 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -142,8 +142,6 @@ libsoup_2_4_la_SOURCES = \ soup-io-stream.h \ soup-io-stream.c \ soup-logger.c \ - soup-marshal.h \ - soup-marshal.c \ soup-message.c \ soup-message-body.c \ soup-message-client-io.c \ @@ -226,13 +224,11 @@ libsoup_gnome_2_4_la_SOURCES = \ endif -GLIB_GENERATED = soup-marshal.c soup-marshal.h -GLIB_GENERATED += soup-enum-types.c soup-enum-types.h +GLIB_GENERATED = soup-enum-types.c soup-enum-types.h BUILT_SOURCES = \ $(GLIB_GENERATED) \ tld_data.inc -soup_marshal_sources = $(libsoup_2_4_la_SOURCES) $(libsoup_gnome_2_4_la_SOURCES) soup_enum_types_sources = $(libsoupinclude_HEADERS) $(libsoupgnomeinclude_HEADERS) soup_enum_types_MKENUMS_C_FLAGS = --fhead "\#define LIBSOUP_USE_UNSTABLE_REQUEST_API" @@ -248,7 +244,7 @@ if HAVE_INTROSPECTION # Core library gi_soup_files = \ - $(filter-out soup.h soup-enum-types.% soup-marshal.% soup-proxy-resolver.h,\ + $(filter-out soup.h soup-enum-types.% soup-proxy-resolver.h,\ $(soup_headers) $(filter-out %.h, $(libsoup_2_4_la_SOURCES))) gi_built_soup_files = soup-enum-types.h diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index da4da948..e2a06912 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -15,7 +15,6 @@ #include "soup-address.h" #include "soup.h" -#include "soup-marshal.h" #include "soup-misc-private.h" /** diff --git a/libsoup/soup-auth-domain-basic.c b/libsoup/soup-auth-domain-basic.c index 9e8afe8f..b843ad72 100644 --- a/libsoup/soup-auth-domain-basic.c +++ b/libsoup/soup-auth-domain-basic.c @@ -13,7 +13,6 @@ #include "soup-auth-domain-basic.h" #include "soup.h" -#include "soup-marshal.h" /** * SECTION:soup-auth-domain-basic diff --git a/libsoup/soup-auth-domain-digest.c b/libsoup/soup-auth-domain-digest.c index 6f48ce56..ebf3ddb6 100644 --- a/libsoup/soup-auth-domain-digest.c +++ b/libsoup/soup-auth-domain-digest.c @@ -15,7 +15,6 @@ #include "soup-auth-domain-digest.h" #include "soup.h" #include "soup-auth-digest.h" -#include "soup-marshal.h" /** * SECTION:soup-auth-domain-digest diff --git a/libsoup/soup-auth-manager.c b/libsoup/soup-auth-manager.c index 3f230b1a..f40a9282 100644 --- a/libsoup/soup-auth-manager.c +++ b/libsoup/soup-auth-manager.c @@ -14,7 +14,6 @@ #include "soup-auth-manager.h" #include "soup.h" #include "soup-connection-auth.h" -#include "soup-marshal.h" #include "soup-message-private.h" #include "soup-message-queue.h" #include "soup-path-map.h" @@ -146,7 +145,7 @@ soup_auth_manager_class_init (SoupAuthManagerClass *auth_manager_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupAuthManagerClass, authenticate), NULL, NULL, - _soup_marshal_NONE__OBJECT_OBJECT_BOOLEAN, + NULL, G_TYPE_NONE, 3, SOUP_TYPE_MESSAGE, SOUP_TYPE_AUTH, diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c index 8f1e2182..0c348ad4 100644 --- a/libsoup/soup-auth.c +++ b/libsoup/soup-auth.c @@ -14,7 +14,6 @@ #include "soup-auth.h" #include "soup.h" #include "soup-connection-auth.h" -#include "soup-marshal.h" /** * SECTION:soup-auth diff --git a/libsoup/soup-body-input-stream.c b/libsoup/soup-body-input-stream.c index 939753a9..62747446 100644 --- a/libsoup/soup-body-input-stream.c +++ b/libsoup/soup-body-input-stream.c @@ -16,7 +16,6 @@ #include "soup-body-input-stream.h" #include "soup.h" #include "soup-filter-input-stream.h" -#include "soup-marshal.h" typedef enum { SOUP_BODY_INPUT_STREAM_STATE_CHUNK_SIZE, @@ -385,7 +384,7 @@ soup_body_input_stream_class_init (SoupBodyInputStreamClass *stream_class) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); g_object_class_install_property ( diff --git a/libsoup/soup-client-input-stream.c b/libsoup/soup-client-input-stream.c index 78bc15f1..3e533ca8 100644 --- a/libsoup/soup-client-input-stream.c +++ b/libsoup/soup-client-input-stream.c @@ -11,7 +11,6 @@ #include "soup-client-input-stream.h" #include "soup.h" -#include "soup-marshal.h" #include "soup-message-private.h" struct _SoupClientInputStreamPrivate { @@ -226,7 +225,7 @@ soup_client_input_stream_class_init (SoupClientInputStreamClass *stream_class) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); g_object_class_install_property ( diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index fbddfea3..7657fc9c 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -11,7 +11,6 @@ #include "soup-connection.h" #include "soup.h" -#include "soup-marshal.h" #include "soup-message-queue.h" #include "soup-misc-private.h" @@ -249,7 +248,7 @@ soup_connection_class_init (SoupConnectionClass *connection_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupConnectionClass, disconnected), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /* properties */ diff --git a/libsoup/soup-cookie-jar.c b/libsoup/soup-cookie-jar.c index 38ddf923..93fd157b 100644 --- a/libsoup/soup-cookie-jar.c +++ b/libsoup/soup-cookie-jar.c @@ -13,7 +13,6 @@ #include "soup-cookie-jar.h" #include "soup.h" -#include "soup-marshal.h" /** * SECTION:soup-cookie-jar @@ -175,7 +174,7 @@ soup_cookie_jar_class_init (SoupCookieJarClass *jar_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupCookieJarClass, changed), NULL, NULL, - _soup_marshal_NONE__BOXED_BOXED, + NULL, G_TYPE_NONE, 2, SOUP_TYPE_COOKIE | G_SIGNAL_TYPE_STATIC_SCOPE, SOUP_TYPE_COOKIE | G_SIGNAL_TYPE_STATIC_SCOPE); diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index b65dd76b..cd206a2f 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -8,7 +8,6 @@ #include "soup-message.h" #include "soup.h" #include "soup-connection.h" -#include "soup-marshal.h" #include "soup-message-private.h" /** @@ -351,7 +350,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, wrote_informational), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -369,7 +368,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, wrote_headers), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -391,7 +390,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, wrote_chunk), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -414,7 +413,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, 0, /* FIXME after next ABI break */ NULL, NULL, - _soup_marshal_NONE__BOXED, + NULL, G_TYPE_NONE, 1, SOUP_TYPE_BUFFER); @@ -435,7 +434,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, wrote_body), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -458,7 +457,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, got_informational), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -490,7 +489,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, got_headers), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -513,7 +512,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, got_chunk), NULL, NULL, - _soup_marshal_NONE__BOXED, + NULL, G_TYPE_NONE, 1, /* Use %G_SIGNAL_TYPE_STATIC_SCOPE so that * the %SOUP_MEMORY_TEMPORARY buffers used @@ -542,7 +541,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, got_body), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -579,7 +578,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, 0, NULL, NULL, - _soup_marshal_NONE__STRING_BOXED, + NULL, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_HASH_TABLE); @@ -599,7 +598,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, restarted), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -616,7 +615,7 @@ soup_message_class_init (SoupMessageClass *message_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupMessageClass, finished), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index cea950db..acf8fa14 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -14,7 +14,6 @@ #include "soup-server.h" #include "soup.h" #include "soup-message-private.h" -#include "soup-marshal.h" #include "soup-path-map.h" /** @@ -387,7 +386,7 @@ soup_server_class_init (SoupServerClass *server_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupServerClass, request_started), NULL, NULL, - _soup_marshal_NONE__OBJECT_POINTER, + NULL, G_TYPE_NONE, 2, SOUP_TYPE_MESSAGE, SOUP_TYPE_CLIENT_CONTEXT); @@ -412,7 +411,7 @@ soup_server_class_init (SoupServerClass *server_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupServerClass, request_read), NULL, NULL, - _soup_marshal_NONE__OBJECT_POINTER, + NULL, G_TYPE_NONE, 2, SOUP_TYPE_MESSAGE, SOUP_TYPE_CLIENT_CONTEXT); @@ -432,7 +431,7 @@ soup_server_class_init (SoupServerClass *server_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupServerClass, request_finished), NULL, NULL, - _soup_marshal_NONE__OBJECT_POINTER, + NULL, G_TYPE_NONE, 2, SOUP_TYPE_MESSAGE, SOUP_TYPE_CLIENT_CONTEXT); @@ -461,7 +460,7 @@ soup_server_class_init (SoupServerClass *server_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupServerClass, request_aborted), NULL, NULL, - _soup_marshal_NONE__OBJECT_POINTER, + NULL, G_TYPE_NONE, 2, SOUP_TYPE_MESSAGE, SOUP_TYPE_CLIENT_CONTEXT); diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 2ae7249a..7ffd8f76 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -16,7 +16,6 @@ #include "soup-auth-manager.h" #include "soup-cache-private.h" #include "soup-connection.h" -#include "soup-marshal.h" #include "soup-message-private.h" #include "soup-misc-private.h" #include "soup-message-queue.h" @@ -2840,7 +2839,7 @@ soup_session_class_init (SoupSessionClass *session_class) G_SIGNAL_RUN_FIRST, 0, /* FIXME? */ NULL, NULL, - _soup_marshal_NONE__OBJECT, + NULL, G_TYPE_NONE, 1, SOUP_TYPE_MESSAGE); @@ -2860,7 +2859,7 @@ soup_session_class_init (SoupSessionClass *session_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupSessionClass, request_started), NULL, NULL, - _soup_marshal_NONE__OBJECT_OBJECT, + NULL, G_TYPE_NONE, 2, SOUP_TYPE_MESSAGE, SOUP_TYPE_SOCKET); @@ -2883,7 +2882,7 @@ soup_session_class_init (SoupSessionClass *session_class) G_SIGNAL_RUN_FIRST, 0, /* FIXME? */ NULL, NULL, - _soup_marshal_NONE__OBJECT, + NULL, G_TYPE_NONE, 1, SOUP_TYPE_MESSAGE); @@ -2916,7 +2915,7 @@ soup_session_class_init (SoupSessionClass *session_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupSessionClass, authenticate), NULL, NULL, - _soup_marshal_NONE__OBJECT_OBJECT_BOOLEAN, + NULL, G_TYPE_NONE, 3, SOUP_TYPE_MESSAGE, SOUP_TYPE_AUTH, @@ -2939,7 +2938,7 @@ soup_session_class_init (SoupSessionClass *session_class) G_SIGNAL_RUN_FIRST, 0, NULL, NULL, - _soup_marshal_NONE__OBJECT, + NULL, G_TYPE_NONE, 1, /* SoupConnection is private, so we can't use * SOUP_TYPE_CONNECTION here. @@ -2963,7 +2962,7 @@ soup_session_class_init (SoupSessionClass *session_class) G_SIGNAL_RUN_FIRST, 0, NULL, NULL, - _soup_marshal_NONE__OBJECT, + NULL, G_TYPE_NONE, 1, /* SoupConnection is private, so we can't use * SOUP_TYPE_CONNECTION here. diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index ee1aac99..baa9290c 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -17,7 +17,6 @@ #include "soup.h" #include "soup-filter-input-stream.h" #include "soup-io-stream.h" -#include "soup-marshal.h" #include "soup-misc-private.h" /** @@ -321,7 +320,7 @@ soup_socket_class_init (SoupSocketClass *socket_class) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SoupSocketClass, readable), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -337,7 +336,7 @@ soup_socket_class_init (SoupSocketClass *socket_class) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SoupSocketClass, writable), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -353,7 +352,7 @@ soup_socket_class_init (SoupSocketClass *socket_class) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (SoupSocketClass, disconnected), NULL, NULL, - _soup_marshal_NONE__NONE, + NULL, G_TYPE_NONE, 0); /** @@ -373,7 +372,7 @@ soup_socket_class_init (SoupSocketClass *socket_class) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupSocketClass, new_connection), NULL, NULL, - _soup_marshal_NONE__OBJECT, + NULL, G_TYPE_NONE, 1, SOUP_TYPE_SOCKET); /** -- cgit v1.2.1 From 38c79e2389855828a6505b635fec688ef1f30116 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 8 Jun 2013 20:44:35 -0300 Subject: oops, addendum to previous commit --- libsoup/soup-cache-input-stream.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libsoup/soup-cache-input-stream.c b/libsoup/soup-cache-input-stream.c index 7815cecc..679531d0 100644 --- a/libsoup/soup-cache-input-stream.c +++ b/libsoup/soup-cache-input-stream.c @@ -9,7 +9,6 @@ #include #include "soup-cache-input-stream.h" -#include "soup-marshal.h" #include "soup-message-body.h" static void soup_cache_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); @@ -328,7 +327,7 @@ soup_cache_input_stream_class_init (SoupCacheInputStreamClass *klass) G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SoupCacheInputStreamClass, caching_finished), NULL, NULL, - _soup_marshal_NONE__INT_BOXED, + NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_ERROR); } -- cgit v1.2.1 From adcf9a68f56030dcbf3eab5b0717209392f45240 Mon Sep 17 00:00:00 2001 From: Bernhard Schuster Date: Fri, 21 Jun 2013 09:42:46 +0200 Subject: replace g_hash_table_destroy with _unref for server query This is necessary to allow passing the query on to another thread, given that the developer adds another reference. With the current destroy thing this will not work. https://bugzilla.gnome.org/show_bug.cgi?id=702793 --- libsoup/soup-server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index acf8fa14..ff51e5bd 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -907,7 +907,7 @@ call_handler (SoupMessage *msg, SoupClientContext *client) client, hand->user_data); if (form_data_set) - g_hash_table_destroy (form_data_set); + g_hash_table_unref (form_data_set); } } -- cgit v1.2.1 From e06d243fadb351b63ba6e7734fd1a9b9fccf4d50 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 29 Jun 2013 13:10:23 -0400 Subject: Add/fix some annotations --- libsoup/soup-auth.c | 5 +++++ libsoup/soup-message.c | 2 +- libsoup/soup-password-manager.c | 4 ++++ libsoup/soup-password-manager.h | 20 ++++++++++++-------- libsoup/soup-requester.c | 10 ++++++++++ libsoup/soup-session.c | 8 ++++---- libsoup/soup-socket.h | 8 ++++---- libsoup/soup-uri.c | 23 ----------------------- 8 files changed, 40 insertions(+), 40 deletions(-) diff --git a/libsoup/soup-auth.c b/libsoup/soup-auth.c index 0c348ad4..7c34dcfa 100644 --- a/libsoup/soup-auth.c +++ b/libsoup/soup-auth.c @@ -524,6 +524,11 @@ soup_auth_free_protection_space (SoupAuth *auth, GSList *space) g_slist_free_full (space, g_free); } +/** + * soup_auth_get_saved_users: + * + * Return value: (transfer full) (element-type utf8): + */ GSList * soup_auth_get_saved_users (SoupAuth *auth) { diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index cd206a2f..d18eab12 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1925,7 +1925,7 @@ soup_message_set_soup_request (SoupMessage *msg, * If @msg is associated with a #SoupRequest, this returns that * request. Otherwise it returns %NULL. * - * Return value: @msg's associated #SoupRequest + * Return value: (transfer none): @msg's associated #SoupRequest * * Since: 2.42 */ diff --git a/libsoup/soup-password-manager.c b/libsoup/soup-password-manager.c index d9cf81c3..532ff7eb 100644 --- a/libsoup/soup-password-manager.c +++ b/libsoup/soup-password-manager.c @@ -21,6 +21,10 @@ soup_password_manager_default_init (SoupPasswordManagerInterface *iface) { } +/** + * soup_password_manager_get_passwords_async: + * @callback: (scope async) + */ void soup_password_manager_get_passwords_async (SoupPasswordManager *password_manager, SoupMessage *msg, diff --git a/libsoup/soup-password-manager.h b/libsoup/soup-password-manager.h index d4e60ac7..aa5faf55 100644 --- a/libsoup/soup-password-manager.h +++ b/libsoup/soup-password-manager.h @@ -17,8 +17,8 @@ typedef struct _SoupPasswordManager SoupPasswordManager; -typedef void (*SoupPasswordManagerCallback) (SoupPasswordManager *, - SoupMessage *, SoupAuth *, +typedef void (*SoupPasswordManagerCallback) (SoupPasswordManager *password_manager, + SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer user_data); @@ -26,12 +26,16 @@ typedef struct { GTypeInterface base; /* virtual methods */ - void (*get_passwords_async) (SoupPasswordManager *, SoupMessage *, - SoupAuth *, gboolean, - GMainContext *, GCancellable *, - SoupPasswordManagerCallback, gpointer); - void (*get_passwords_sync) (SoupPasswordManager *, SoupMessage *, - SoupAuth *, GCancellable *); + void (*get_passwords_async) (SoupPasswordManager *password_manager, + SoupMessage *msg, SoupAuth *auth, + gboolean retrying, + GMainContext *async_context, + GCancellable *cancellable, + SoupPasswordManagerCallback callback, + gpointer user_data); + void (*get_passwords_sync) (SoupPasswordManager *password_manager, + SoupMessage *msg, SoupAuth *auth, + GCancellable *cancellable); } SoupPasswordManagerInterface; diff --git a/libsoup/soup-requester.c b/libsoup/soup-requester.c index 60648e11..c67bfe31 100644 --- a/libsoup/soup-requester.c +++ b/libsoup/soup-requester.c @@ -144,6 +144,11 @@ translate_error (GError *error) g_warn_if_reached (); } +/** + * soup_requester_request: + * + * Return value: (transfer full): + */ SoupRequest * soup_requester_request (SoupRequester *requester, const char *uri_string, GError **error) @@ -161,6 +166,11 @@ soup_requester_request (SoupRequester *requester, const char *uri_string, return NULL; } +/** + * soup_requester_request_uri: + * + * Return value: (transfer full): + */ SoupRequest * soup_requester_request_uri (SoupRequester *requester, SoupURI *uri, GError **error) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 7ffd8f76..abdebef8 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -4056,8 +4056,8 @@ soup_session_send_async (SoupSession *session, * successful), returns a #GInputStream that can be used to read the * response body. * - * Return value: a #GInputStream for reading the response body, or - * %NULL on error. + * Return value: (transfer full): a #GInputStream for reading the + * response body, or %NULL on error. * * Since: 2.42 */ @@ -4121,8 +4121,8 @@ soup_session_send_finish (SoupSession *session, * (Note that this method cannot be called on the deprecated * #SoupSessionAsync subclass.) * - * Return value: a #GInputStream for reading the response body, or - * %NULL on error. + * Return value: (transfer full): a #GInputStream for reading the + * response body, or %NULL on error. * * Since: 2.42 */ diff --git a/libsoup/soup-socket.h b/libsoup/soup-socket.h index ed405bdc..5c1264f9 100644 --- a/libsoup/soup-socket.h +++ b/libsoup/soup-socket.h @@ -26,11 +26,11 @@ typedef struct { GObjectClass parent_class; /* signals */ - void (*readable) (SoupSocket *); - void (*writable) (SoupSocket *); - void (*disconnected) (SoupSocket *); + void (*readable) (SoupSocket *sock); + void (*writable) (SoupSocket *sock); + void (*disconnected) (SoupSocket *sock); - void (*new_connection) (SoupSocket *, SoupSocket *); + void (*new_connection) (SoupSocket *listener, SoupSocket *new_sock); /* Padding for future expansion */ void (*_libsoup_reserved1) (void); diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 26ec24a0..b9ff93fe 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -863,29 +863,6 @@ soup_uri_uses_default_port (SoupURI *uri) return uri->port == soup_scheme_default_port (uri->scheme); } -/** - * SOUP_URI_SCHEME_HTTP: - * - * "http" as an interned string. This can be compared directly against - * the value of a #SoupURI's scheme - **/ - -/** - * SOUP_URI_SCHEME_HTTPS: - * - * "https" as an interned string. This can be compared directly - * against the value of a #SoupURI's scheme - **/ - -/** - * SOUP_URI_SCHEME_RESOURCE: - * - * "resource" as an interned string. This can be compared directly - * against the value of a #SoupURI's scheme - * - * Since: 2.42 - **/ - /** * soup_uri_get_scheme: * @uri: a #SoupURI -- cgit v1.2.1 From 037c1f92678735c24e337ad568463141710d5679 Mon Sep 17 00:00:00 2001 From: Andres Gomez Date: Thu, 27 Jun 2013 18:37:25 +0300 Subject: [examples] Added SoupLogger to get example Now, instead of printing the debug information manually we use SoupLogger for this with the "-d" flag. https://bugzilla.gnome.org/show_bug.cgi?id=703231 --- examples/get.c | 48 +++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/examples/get.c b/examples/get.c index 3540b724..a2307bfd 100644 --- a/examples/get.c +++ b/examples/get.c @@ -1,6 +1,7 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2001-2003, Ximian, Inc. + * Copyright (C) 2013 Igalia, S.L. */ #include @@ -26,35 +27,17 @@ get_url (const char *url) name = soup_message_get_uri (msg)->path; - if (debug || head) { - SoupMessageHeadersIter iter; - const char *hname, *value; - char *path = soup_uri_to_string (soup_message_get_uri (msg), TRUE); - - g_print ("%s %s HTTP/1.%d\n", msg->method, path, - soup_message_get_http_version (msg)); - soup_message_headers_iter_init (&iter, msg->request_headers); - while (soup_message_headers_iter_next (&iter, &hname, &value)) - g_print ("%s: %s\r\n", hname, value); - g_print ("\n"); - - g_print ("HTTP/1.%d %d %s\n", - soup_message_get_http_version (msg), - msg->status_code, msg->reason_phrase); - - soup_message_headers_iter_init (&iter, msg->response_headers); - while (soup_message_headers_iter_next (&iter, &hname, &value)) - g_print ("%s: %s\r\n", hname, value); - g_print ("\n"); - } else if (msg->status_code == SOUP_STATUS_SSL_FAILED) { - GTlsCertificateFlags flags; - - if (soup_message_get_https_status (msg, NULL, &flags)) - g_print ("%s: %d %s (0x%x)\n", name, msg->status_code, msg->reason_phrase, flags); - else - g_print ("%s: %d %s (no handshake status)\n", name, msg->status_code, msg->reason_phrase); - } else if (!quiet || SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) - g_print ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase); + if (!debug) { + if (msg->status_code == SOUP_STATUS_SSL_FAILED) { + GTlsCertificateFlags flags; + + if (soup_message_get_https_status (msg, NULL, &flags)) + g_print ("%s: %d %s (0x%x)\n", name, msg->status_code, msg->reason_phrase, flags); + else + g_print ("%s: %d %s (no handshake status)\n", name, msg->status_code, msg->reason_phrase); + } else if (!quiet || SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) + g_print ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase); + } if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) { header = soup_message_headers_get_one (msg->response_headers, @@ -113,6 +96,7 @@ main (int argc, char **argv) const char *url; SoupURI *proxy_uri, *parsed; GError *error = NULL; + SoupLogger *logger = NULL; opts = g_option_context_new (NULL); g_option_context_add_main_entries (opts, entries, NULL); @@ -148,6 +132,12 @@ main (int argc, char **argv) SOUP_SESSION_USE_NTLM, ntlm, NULL); + if (debug) { + logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger)); + g_object_unref (logger); + } + if (proxy) { proxy_uri = soup_uri_new (proxy); if (!proxy_uri) { -- cgit v1.2.1 From 09727545304e22b3c31df344ca58ef979e43f8e5 Mon Sep 17 00:00:00 2001 From: Andres Gomez Date: Thu, 27 Jun 2013 17:53:45 +0300 Subject: [examples] "get" uses -o to save to a file The "get" example is now able to handle a new "-o" parameter specifying the path of a file in which to write the received body of a "GET" operation. If the file exists, it will be overwritten. https://bugzilla.gnome.org/show_bug.cgi?id=703229 --- examples/get.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/examples/get.c b/examples/get.c index a2307bfd..ad1446e3 100644 --- a/examples/get.c +++ b/examples/get.c @@ -12,6 +12,7 @@ static SoupSession *session; static GMainLoop *loop; static gboolean debug, head, quiet; +static const gchar *output_file_path = NULL; static void get_url (const char *url) @@ -19,6 +20,7 @@ get_url (const char *url) const char *name; SoupMessage *msg; const char *header; + FILE *output_file = NULL; msg = soup_message_new (head ? "HEAD" : "GET", url); soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); @@ -55,9 +57,23 @@ get_url (const char *url) g_free (uri_string); soup_uri_free (uri); } - } else if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - fwrite (msg->response_body->data, 1, - msg->response_body->length, stdout); + } else if (!head && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + if (output_file_path) { + output_file = fopen (output_file_path, "w"); + if (!output_file) + g_printerr ("Error trying to create file %s.\n", output_file_path); + } else if (!quiet) + output_file = stdout; + + if (output_file) { + fwrite (msg->response_body->data, + 1, + msg->response_body->length, + output_file); + + if (output_file_path) + fclose (output_file); + } } } @@ -77,6 +93,9 @@ static GOptionEntry entries[] = { { "ntlm", 'n', 0, G_OPTION_ARG_NONE, &ntlm, "Use NTLM authentication", NULL }, + { "output", 'o', 0, + G_OPTION_ARG_STRING, &output_file_path, + "Write the received data to FILE instead of stdout", "FILE" }, { "proxy", 'p', 0, G_OPTION_ARG_STRING, &proxy, "Use URL as an HTTP proxy", "URL" }, @@ -146,7 +165,7 @@ main (int argc, char **argv) exit (1); } - g_object_set (G_OBJECT (session), + g_object_set (G_OBJECT (session), SOUP_SESSION_PROXY_URI, proxy_uri, NULL); soup_uri_free (proxy_uri); -- cgit v1.2.1 From 085f4e28907e91c5e5d6517c0205d4288167fd05 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 2 Jul 2013 15:00:47 +0100 Subject: soup-session: Fix a crash when destroying a NULL unpause source Closes: https://bugzilla.gnome.org/show_bug.cgi?id=703461 --- libsoup/soup-message-io.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 928b73ef..497fd063 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -1149,8 +1149,7 @@ io_unpause_internal (gpointer msg) g_return_val_if_fail (io != NULL, FALSE); - g_source_unref (io->unpause_source); - io->unpause_source = NULL; + g_clear_pointer (&io->unpause_source, g_source_unref); io->paused = FALSE; if (io->io_source) -- cgit v1.2.1 From 2081c31235e7c2b3a15fa0a819631106cf4c3efa Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 2 Jul 2013 15:04:18 +0100 Subject: soup-session: Force cleanup of REMOTE_DISCONNECTED conns for sync sessions get_connection() assumed that REMOTE_DISCONNECTED connections would get implicitly cleaned up elsewhere in the code, which is true for async sessions, but not sync ones. This could lead to connection exhaustion and hence hangs. Closes: https://bugzilla.gnome.org/show_bug.cgi?id=703463 --- libsoup/soup-session.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index abdebef8..627a6843 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1726,6 +1726,8 @@ get_connection (SoupMessageQueueItem *item, gboolean *should_cleanup) gboolean my_should_cleanup = FALSE; gboolean need_new_connection; + soup_session_cleanup_connections (session, FALSE); + need_new_connection = (soup_message_get_flags (item->msg) & SOUP_MESSAGE_NEW_CONNECTION) || (!(soup_message_get_flags (item->msg) & SOUP_MESSAGE_IDEMPOTENT) && -- cgit v1.2.1 From e6ed20e9832dbc7290b3cfde39b1e029689e1ace Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 9 Jul 2013 09:57:02 -0400 Subject: 2.43.4 --- NEWS | 23 +++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 06ba7b74..ecd19a61 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,26 @@ +Changes in libsoup from 2.43.2 to 2.43.4: + + * Fixed a bug that could cause synchronous sessions to get + stuck in a state where no new messages would ever get + processed. [#703463, Philip Withnall] + + * Fixed another memory leak in SoupSocket (found while + added a test case for #700472) + + * Switched to using g_cclosure_marshal_generic() rather than + using glib-genmarshal. [#686042, Olivier Blin] + + * Changed SoupServer to call unref() on the query hash table + after calling the handler, rather than destroy(), so that + the handler can keep a copy of the query data if it wants. + [#702793, Bernhard Schuster] + + * Fixed a few introspection annotations + + * Updated examples/get to use SoupLogger and to allow + redirecting the output to a file [#703231, #703229, Andres + Gomez] + Changes in libsoup from 2.43.1 to 2.43.2: * Fixed an authentication error when using NTLM when diff --git a/configure.ac b/configure.ac index ccdf5b08..92d52f83 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [43]) -m4_define([soup_micro_version], [2]) +m4_define([soup_micro_version], [4]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 312dbe87cc452c2f55f53068d1c5ac59ab2be94b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 10 Jul 2013 09:08:35 -0400 Subject: build: use AM_CPPFLAGS rather than INCLUDES to make automake 1.13 happy --- examples/Makefile.am | 2 +- libsoup/Makefile.am | 6 +++--- tests/Makefile.am | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/Makefile.am b/examples/Makefile.am index 69e5b550..1609ff24 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = \ +AM_CPPFLAGS = \ -I$(top_srcdir) \ -DSRCDIR=\""$(abs_srcdir)"\" \ -DBUILDDIR=\""$(builddir)"\" \ diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index c2f69aec..be35fc77 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -8,7 +8,7 @@ if OS_WIN32 LIBWS2_32 = -lws2_32 endif -INCLUDES = \ +AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\"libsoup\" \ -DLOCALEDIR=\"$(localedir)\" \ -I$(top_srcdir) \ @@ -250,7 +250,7 @@ gi_built_soup_files = soup-enum-types.h Soup-2.4.gir: libsoup-2.4.la Soup_2_4_gir_INCLUDES = Gio-2.0 -Soup_2_4_gir_CFLAGS = $(INCLUDES) -DLIBSOUP_USE_UNSTABLE_REQUEST_API +Soup_2_4_gir_CFLAGS = $(AM_CPPFLAGS) -DLIBSOUP_USE_UNSTABLE_REQUEST_API Soup_2_4_gir_LIBS = libsoup-2.4.la Soup_2_4_gir_EXPORT_PACKAGES = libsoup-2.4 Soup_2_4_gir_SCANNERFLAGS = --c-include "libsoup/soup.h" @@ -275,7 +275,7 @@ SoupGNOME_2_4_gir_SCANNERFLAGS = \ --symbol-prefix=soup \ --c-include "libsoup/soup-gnome.h" \ --include-uninstalled=$(builddir)/Soup-2.4.gir -SoupGNOME_2_4_gir_CFLAGS = $(INCLUDES) +SoupGNOME_2_4_gir_CFLAGS = $(AM_CPPFLAGS) SoupGNOME_2_4_gir_LIBS = libsoup-gnome-2.4.la libsoup-2.4.la SoupGNOME_2_4_gir_FILES = $(addprefix $(srcdir)/,$(gi_soup_gnome_files)) SoupGNOME_2_4_gir_EXPORT_PACKAGES = libsoup-gnome-2.4 diff --git a/tests/Makefile.am b/tests/Makefile.am index 6fa6d1c3..22c4a851 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = \ +AM_CPPFLAGS = \ -I$(top_srcdir) \ -DSRCDIR=\""$(abs_srcdir)"\" \ -DBUILDDIR=\""$(builddir)"\" \ -- cgit v1.2.1 From 75af66a37dcf564bcc9e73080e1e93f51925a7d3 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 13 Jul 2013 10:17:26 -0400 Subject: build: use AC_CONFIG_AUX_DIR and update .gitignore (Primarily to move automake 1.13's test-driver out of the top level so that the tests/ subdir autocompletes correctly again.) --- .gitignore | 17 +++-------------- configure.ac | 1 + 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index d7c22fba..713357b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ -*~ *.o *.lo *.la -*.stamp -*.bak .deps .libs INSTALL @@ -11,16 +8,14 @@ Makefile Makefile.in aclocal.m4 autom4te.cache -config.guess +build-aux config.h config.h.in +config.h.in~ config.log config.status -config.sub configure -depcomp -docs/reference/html-build.stamp -docs/reference/html.stamp +docs/reference/*.stamp docs/reference/html docs/reference/libsoup-2.4-decl-list.txt docs/reference/libsoup-2.4-decl.txt @@ -40,7 +35,6 @@ examples/get examples/simple-httpd examples/simple-proxy gtk-doc.make -install-sh libsoup-zip libsoup-2.4.pc libsoup-gnome-2.4.pc @@ -52,25 +46,20 @@ libsoup/SoupGNOME-2.4.typelib libsoup/tld_data.inc libsoup/soup-version.h libtool -ltmain.sh m4/gtk-doc.m4 m4/intltool.m4 m4/libtool.m4 m4/lt*.m4 -missing -mkinstalldirs po/*.gmo po/libsoup.pot po/Makefile.in.in po/POTFILES po/stamp-it stamp-h1 -test-driver tests/*.log tests/*.trs tests/*-test tests/date -tests/getbug tests/header-parsing tests/httpd.conf tests/ntlm-test-helper diff --git a/configure.ac b/configure.ac index 92d52f83..a5461687 100644 --- a/configure.ac +++ b/configure.ac @@ -10,6 +10,7 @@ AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) AC_CONFIG_SRCDIR([libsoup-2.4.pc.in]) AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz -Wno-portability]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) -- cgit v1.2.1 From 11811349f8a10ce419d980c01a518c774fe8a5e5 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 13 Jul 2013 10:22:14 -0400 Subject: misc-test: add a test that preemptively cancelling a SoupRequest works https://bugzilla.gnome.org/show_bug.cgi?id=637039 --- tests/misc-test.c | 16 ++++++++++++++++ tests/test-utils.c | 2 ++ tests/test-utils.h | 3 ++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/misc-test.c b/tests/misc-test.c index 39ee960b..18f0e615 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -971,6 +971,22 @@ do_cancel_while_reading_req_test (void) NULL); do_cancel_while_reading_req_test_for_session (session, flags); soup_test_session_abort_unref (session); + + debug_printf (1, "\nCancelling (preemptively) message while reading response (request api)\n"); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE; + + debug_printf (1, " Async session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); + + debug_printf (1, " Sync session\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + NULL); + do_cancel_while_reading_req_test_for_session (session, flags); + soup_test_session_abort_unref (session); } static void diff --git a/tests/test-utils.c b/tests/test-utils.c index b528b786..248f2fe8 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -468,6 +468,8 @@ soup_test_request_send (SoupRequest *req, guint interval = flags & SOUP_TEST_REQUEST_CANCEL_SOON ? 100 : 0; g_timeout_add_full (G_PRIORITY_HIGH, interval, cancel_request_timeout, cancel_data, NULL); } + if (cancel_data && (flags & SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE)) + g_cancellable_cancel (cancellable); soup_request_send_async (req, cancellable, async_as_sync_callback, &data); g_main_loop_run (data.loop); diff --git a/tests/test-utils.h b/tests/test-utils.h index b7b21951..98d93393 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -29,7 +29,8 @@ typedef enum { SOUP_TEST_REQUEST_CANCEL_CANCELLABLE = (1 << 1), SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2), SOUP_TEST_REQUEST_CANCEL_IMMEDIATE = (1 << 3), - SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH = (1 << 4), + SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE = (1 << 4), + SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH = (1 << 5), } SoupTestRequestFlags; SoupSession *soup_test_session_new (GType type, ...); -- cgit v1.2.1 From 7f9c7c8731821149ff42971fad18e2a9abbb4c10 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 13 Jul 2013 11:06:29 -0400 Subject: Rename SoupKnownStatusCode to SoupStatus Rename SoupKnownStatusCode to SoupStatus (so that the type name matches the enum values), and then, for backward-compatibility, add a new SoupKnownStatusCode enum with equivalent values so that introspection-using code that was doing "SoupKnownStatusCode.OK", etc, will still work. https://bugzilla.gnome.org/show_bug.cgi?id=684409 --- docs/reference/libsoup-2.4-sections.txt | 3 +- libsoup/libsoup-2.4.sym | 1 + libsoup/soup-message.c | 2 +- libsoup/soup-proxy-uri-resolver.c | 2 +- libsoup/soup-status.c | 15 +++++-- libsoup/soup-status.h | 80 ++++++++++++++++++++++++++++++++- 6 files changed, 95 insertions(+), 8 deletions(-) diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 4b6ebfd9..2fb91342 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -199,13 +199,14 @@ SOUP_STATUS_IS_SUCCESSFUL SOUP_STATUS_IS_REDIRECTION SOUP_STATUS_IS_CLIENT_ERROR SOUP_STATUS_IS_SERVER_ERROR -SoupKnownStatusCode +SoupStatus soup_status_get_phrase soup_status_proxify SOUP_HTTP_ERROR soup_http_error_quark +SoupKnownStatusCode

diff --git a/libsoup/libsoup-2.4.sym b/libsoup/libsoup-2.4.sym index d0f22f6e..be4cd7f4 100644 --- a/libsoup/libsoup-2.4.sym +++ b/libsoup/libsoup-2.4.sym @@ -416,6 +416,7 @@ soup_socket_start_ssl soup_socket_write soup_ssl_supported soup_status_get_phrase +soup_status_get_type soup_status_proxify soup_str_case_equal soup_str_case_hash diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index d18eab12..76130436 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -52,7 +52,7 @@ * * Represents an HTTP message being sent or received. * - * @status_code will normally be a #SoupKnownStatusCode, eg, + * @status_code will normally be a #SoupStatus value, eg, * %SOUP_STATUS_OK, though of course it might actually be an unknown * status code. @reason_phrase is the actual text returned from the * server, which may or may not correspond to the "standard" diff --git a/libsoup/soup-proxy-uri-resolver.c b/libsoup/soup-proxy-uri-resolver.c index 65f65d4b..ca49b90f 100644 --- a/libsoup/soup-proxy-uri-resolver.c +++ b/libsoup/soup-proxy-uri-resolver.c @@ -34,7 +34,7 @@ soup_proxy_uri_resolver_default_init (SoupProxyURIResolverInterface *iface) /** * SoupProxyURIResolverCallback: * @resolver: the #SoupProxyURIResolver - * @status: a #SoupKnownStatusCode + * @status: a #SoupStatus * @proxy_uri: the resolved proxy URI, or %NULL * @user_data: data passed to soup_proxy_uri_resolver_get_proxy_uri_async() * diff --git a/libsoup/soup-status.c b/libsoup/soup-status.c index 7b048a80..6dbb9edb 100644 --- a/libsoup/soup-status.c +++ b/libsoup/soup-status.c @@ -68,7 +68,7 @@ **/ /** - * SoupKnownStatusCode: + * SoupStatus: * @SOUP_STATUS_NONE: No status available. (Eg, the message has not * been sent yet) * @SOUP_STATUS_CANCELLED: Message was cancelled locally @@ -150,14 +150,21 @@ * * These represent the known HTTP status code values, plus various * network and internal errors. + * + * Note that no libsoup functions take or return this type directly; + * any function that works with status codes will accept unrecognized + * status codes as well. + * + * Prior to 2.44 this type was called + * SoupKnownStatusCode, but the individual values + * have always had the names they have now. **/ /** * SOUP_HTTP_ERROR: * - * A #GError domain representing an HTTP status. Use a - * #SoupKnownStatusCode for the code - * value. + * A #GError domain representing an HTTP status. Use a #SoupStatus for + * the code value. **/ diff --git a/libsoup/soup-status.h b/libsoup/soup-status.h index 669c1224..fb4147c6 100644 --- a/libsoup/soup-status.h +++ b/libsoup/soup-status.h @@ -91,7 +91,7 @@ typedef enum { SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505, SOUP_STATUS_INSUFFICIENT_STORAGE = 507, /* WebDAV search */ SOUP_STATUS_NOT_EXTENDED = 510 /* RFC 2774 */ -} SoupKnownStatusCode; +} SoupStatus; const char *soup_status_get_phrase (guint status_code); SOUP_AVAILABLE_IN_2_26 @@ -100,6 +100,84 @@ guint soup_status_proxify (guint status_code); #define SOUP_HTTP_ERROR soup_http_error_quark() GQuark soup_http_error_quark (void); +#ifndef SOUP_DISABLE_DEPRECATED +/* For introspection purposes, we create a duplicate enum type under + * the deprecated type name, since some (all?) bindings don't handle + * enum type typedefs the way we want. + */ +typedef enum { + SOUP_KNOWN_STATUS_CODE_NONE, + + SOUP_KNOWN_STATUS_CODE_CANCELLED = 1, + SOUP_KNOWN_STATUS_CODE_CANT_RESOLVE, + SOUP_KNOWN_STATUS_CODE_CANT_RESOLVE_PROXY, + SOUP_KNOWN_STATUS_CODE_CANT_CONNECT, + SOUP_KNOWN_STATUS_CODE_CANT_CONNECT_PROXY, + SOUP_KNOWN_STATUS_CODE_SSL_FAILED, + SOUP_KNOWN_STATUS_CODE_IO_ERROR, + SOUP_KNOWN_STATUS_CODE_MALFORMED, + SOUP_KNOWN_STATUS_CODE_TRY_AGAIN, + SOUP_KNOWN_STATUS_CODE_TOO_MANY_REDIRECTS, + SOUP_KNOWN_STATUS_CODE_TLS_FAILED, + + SOUP_KNOWN_STATUS_CODE_CONTINUE = 100, + SOUP_KNOWN_STATUS_CODE_SWITCHING_PROTOCOLS = 101, + SOUP_KNOWN_STATUS_CODE_PROCESSING = 102, + + SOUP_KNOWN_STATUS_CODE_OK = 200, + SOUP_KNOWN_STATUS_CODE_CREATED = 201, + SOUP_KNOWN_STATUS_CODE_ACCEPTED = 202, + SOUP_KNOWN_STATUS_CODE_NON_AUTHORITATIVE = 203, + SOUP_KNOWN_STATUS_CODE_NO_CONTENT = 204, + SOUP_KNOWN_STATUS_CODE_RESET_CONTENT = 205, + SOUP_KNOWN_STATUS_CODE_PARTIAL_CONTENT = 206, + SOUP_KNOWN_STATUS_CODE_MULTI_STATUS = 207, + + SOUP_KNOWN_STATUS_CODE_MULTIPLE_CHOICES = 300, + SOUP_KNOWN_STATUS_CODE_MOVED_PERMANENTLY = 301, + SOUP_KNOWN_STATUS_CODE_FOUND = 302, + SOUP_KNOWN_STATUS_CODE_MOVED_TEMPORARILY = 302, + SOUP_KNOWN_STATUS_CODE_SEE_OTHER = 303, + SOUP_KNOWN_STATUS_CODE_NOT_MODIFIED = 304, + SOUP_KNOWN_STATUS_CODE_USE_PROXY = 305, + SOUP_KNOWN_STATUS_CODE_NOT_APPEARING_IN_THIS_PROTOCOL = 306, + SOUP_KNOWN_STATUS_CODE_TEMPORARY_REDIRECT = 307, + + SOUP_KNOWN_STATUS_CODE_BAD_REQUEST = 400, + SOUP_KNOWN_STATUS_CODE_UNAUTHORIZED = 401, + SOUP_KNOWN_STATUS_CODE_PAYMENT_REQUIRED = 402, + SOUP_KNOWN_STATUS_CODE_FORBIDDEN = 403, + SOUP_KNOWN_STATUS_CODE_NOT_FOUND = 404, + SOUP_KNOWN_STATUS_CODE_METHOD_NOT_ALLOWED = 405, + SOUP_KNOWN_STATUS_CODE_NOT_ACCEPTABLE = 406, + SOUP_KNOWN_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED = 407, + SOUP_KNOWN_STATUS_CODE_PROXY_UNAUTHORIZED = SOUP_KNOWN_STATUS_CODE_PROXY_AUTHENTICATION_REQUIRED, + SOUP_KNOWN_STATUS_CODE_REQUEST_TIMEOUT = 408, + SOUP_KNOWN_STATUS_CODE_CONFLICT = 409, + SOUP_KNOWN_STATUS_CODE_GONE = 410, + SOUP_KNOWN_STATUS_CODE_LENGTH_REQUIRED = 411, + SOUP_KNOWN_STATUS_CODE_PRECONDITION_FAILED = 412, + SOUP_KNOWN_STATUS_CODE_REQUEST_ENTITY_TOO_LARGE = 413, + SOUP_KNOWN_STATUS_CODE_REQUEST_URI_TOO_LONG = 414, + SOUP_KNOWN_STATUS_CODE_UNSUPPORTED_MEDIA_TYPE = 415, + SOUP_KNOWN_STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416, + SOUP_KNOWN_STATUS_CODE_INVALID_RANGE = SOUP_KNOWN_STATUS_CODE_REQUESTED_RANGE_NOT_SATISFIABLE, + SOUP_KNOWN_STATUS_CODE_EXPECTATION_FAILED = 417, + SOUP_KNOWN_STATUS_CODE_UNPROCESSABLE_ENTITY = 422, + SOUP_KNOWN_STATUS_CODE_LOCKED = 423, + SOUP_KNOWN_STATUS_CODE_FAILED_DEPENDENCY = 424, + + SOUP_KNOWN_STATUS_CODE_INTERNAL_SERVER_ERROR = 500, + SOUP_KNOWN_STATUS_CODE_NOT_IMPLEMENTED = 501, + SOUP_KNOWN_STATUS_CODE_BAD_GATEWAY = 502, + SOUP_KNOWN_STATUS_CODE_SERVICE_UNAVAILABLE = 503, + SOUP_KNOWN_STATUS_CODE_GATEWAY_TIMEOUT = 504, + SOUP_KNOWN_STATUS_CODE_HTTP_VERSION_NOT_SUPPORTED = 505, + SOUP_KNOWN_STATUS_CODE_INSUFFICIENT_STORAGE = 507, + SOUP_KNOWN_STATUS_CODE_NOT_EXTENDED = 510 +} SoupKnownStatusCode; +#endif + G_END_DECLS #endif /* SOUP_STATUS_H */ -- cgit v1.2.1 From e7f1e5ae3e1b218bac1f1aa70c17847aa32a7151 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 8 Jun 2013 20:56:00 -0300 Subject: examples: port get to plain SoupSession --- examples/get.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/examples/get.c b/examples/get.c index ad1446e3..a74991dc 100644 --- a/examples/get.c +++ b/examples/get.c @@ -14,6 +14,12 @@ static GMainLoop *loop; static gboolean debug, head, quiet; static const gchar *output_file_path = NULL; +static void +finished (SoupSession *session, SoupMessage *msg, gpointer loop) +{ + g_main_loop_quit (loop); +} + static void get_url (const char *url) { @@ -25,6 +31,12 @@ get_url (const char *url) msg = soup_message_new (head ? "HEAD" : "GET", url); soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); + if (loop) { + g_object_ref (msg); + soup_session_queue_message (session, msg, finished, loop); + g_main_loop_run (loop); + } + soup_session_send_message (session, msg); name = soup_message_get_uri (msg)->path; @@ -142,14 +154,15 @@ main (int argc, char **argv) } soup_uri_free (parsed); - session = g_object_new (synchronous ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, + session = g_object_new (SOUP_TYPE_SESSION, SOUP_SESSION_SSL_CA_FILE, ca_file, SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_COOKIE_JAR, SOUP_SESSION_USER_AGENT, "get ", SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE, - SOUP_SESSION_USE_NTLM, ntlm, NULL); + if (ntlm) + soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); if (debug) { logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, -1); @@ -169,8 +182,7 @@ main (int argc, char **argv) SOUP_SESSION_PROXY_URI, proxy_uri, NULL); soup_uri_free (proxy_uri); - } else - soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_DEFAULT); + } if (!synchronous) loop = g_main_loop_new (NULL, TRUE); -- cgit v1.2.1 From fb09bf930c5e0e79b67fbbd323b46284591b8624 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 16 Feb 2013 19:20:18 -0500 Subject: Use GProxyResolver for all proxy resolving Finish up the GProxyResolver porting started in 2.42 by removing all the non-GProxyResolver proxy code from SoupSocket and SoupConnection and implementing SoupSession:proxy-uri in terms of GSimpleProxyResolver. If the user adds a SoupProxyResolverDefault to the session, just use its GProxyResolver directly instead. If the user adds any other kind of SoupProxyURIResolver to the session, use the new SoupProxyResolverWrapper, which is a GProxyResolver that translates from SoupProxyURIResolver. https://bugzilla.gnome.org/show_bug.cgi?id=680273 --- docs/reference/Makefile.am | 3 +- docs/reference/libsoup-2.4-docs.sgml | 1 - docs/reference/libsoup-2.4-sections.txt | 18 ---- docs/reference/session-porting.xml | 21 +++- libsoup/Makefile.am | 4 +- libsoup/soup-connection.c | 144 ++++++-------------------- libsoup/soup-connection.h | 3 +- libsoup/soup-gnome-features.h | 2 +- libsoup/soup-proxy-resolver-default.c | 16 +-- libsoup/soup-proxy-resolver-gnome.c | 3 + libsoup/soup-proxy-resolver-static.c | 177 -------------------------------- libsoup/soup-proxy-resolver-static.h | 35 ------- libsoup/soup-proxy-resolver-wrapper.c | 167 ++++++++++++++++++++++++++++++ libsoup/soup-proxy-resolver-wrapper.h | 34 ++++++ libsoup/soup-proxy-resolver.h | 2 +- libsoup/soup-proxy-uri-resolver.c | 23 ++++- libsoup/soup-proxy-uri-resolver.h | 3 + libsoup/soup-session.c | 131 ++++++++++++++--------- 18 files changed, 371 insertions(+), 416 deletions(-) delete mode 100644 libsoup/soup-proxy-resolver-static.c delete mode 100644 libsoup/soup-proxy-resolver-static.h create mode 100644 libsoup/soup-proxy-resolver-wrapper.c create mode 100644 libsoup/soup-proxy-resolver-wrapper.h diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 29ff97e0..36e77006 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -43,7 +43,8 @@ IGNORE_HFILES= soup.h soup-enum-types.h \ soup-content-sniffer-stream.h soup-io-stream.h \ soup-cache-input-stream.h soup-filter-input-stream.h \ soup-cookie-jar-sqlite.h soup-requester.h soup-tld-private.h \ - soup-misc-private.h + soup-misc-private.h soup-proxy-uri-resolver.h \ + soup-proxy-resolver-wrapper.h # Images to copy into HTML directory. HTML_IMAGES = diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index f28c6059..ca92b864 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -53,7 +53,6 @@ - diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 2fb91342..6b193101 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -1019,24 +1019,6 @@ SOUP_IS_COOKIE_JAR_DB_CLASS soup_cookie_jar_db_get_type
-
-soup-proxy-uri-resolver -SoupProxyURIResolver -SoupProxyURIResolver -SoupProxyURIResolverCallback -soup_proxy_uri_resolver_get_proxy_uri_async -soup_proxy_uri_resolver_get_proxy_uri_sync - -SoupProxyURIResolverInterface -SOUP_IS_PROXY_URI_RESOLVER -SOUP_IS_PROXY_URI_RESOLVER_CLASS -SOUP_PROXY_URI_RESOLVER -SOUP_PROXY_URI_RESOLVER_CLASS -SOUP_PROXY_URI_RESOLVER_GET_CLASS -SOUP_TYPE_PROXY_URI_RESOLVER -soup_proxy_uri_resolver_get_type -
-
soup-content-sniffer SoupContentSniffer diff --git a/docs/reference/session-porting.xml b/docs/reference/session-porting.xml index bf1aa411..67a433a1 100644 --- a/docs/reference/session-porting.xml +++ b/docs/reference/session-porting.xml @@ -90,15 +90,28 @@ linkend="SoupSessionAsync">SoupSessionAsync and follow redirects to such URIs. + + + The new + "proxy-resolver" + property is now initialized to the default + GProxyResolver, + meaning that it will automatically use the user's system proxy + configuration. This replaces the use of the + SoupProxyResolverDefault, + session feature in earlier releases. You can set this property to + NULL if you don't want to use proxies, and the + "proxy-uri" + property still works if you want to use a single proxy for all requests. + + Every session gets a - SoupProxyResolverDefault - and a SoupContentDecoder attached to it by default, meaning that it will automatically - use the user's system proxy configuration, and will handle (and - request) "gzip"- and "deflate"-encoded response bodies. + handle (and request) "gzip"- and "deflate"-encoded response + bodies. diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am index be35fc77..60920bdc 100644 --- a/libsoup/Makefile.am +++ b/libsoup/Makefile.am @@ -161,8 +161,8 @@ libsoup_2_4_la_SOURCES = \ soup-path-map.c \ soup-proxy-resolver.c \ soup-proxy-resolver-default.c \ - soup-proxy-resolver-static.h \ - soup-proxy-resolver-static.c \ + soup-proxy-resolver-wrapper.h \ + soup-proxy-resolver-wrapper.c \ soup-proxy-uri-resolver.c \ soup-request.c \ soup-request-data.c \ diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 7657fc9c..c1184104 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -19,8 +19,7 @@ typedef struct { SoupAddress *local_addr; SoupURI *remote_uri, *proxy_uri; - SoupProxyURIResolver *soup_proxy_resolver; - GProxyResolver *g_proxy_resolver; + GProxyResolver *proxy_resolver; GTlsDatabase *tlsdb; gboolean ssl, ssl_strict, ssl_fallback; @@ -51,8 +50,7 @@ enum { PROP_LOCAL_ADDRESS, PROP_REMOTE_URI, - PROP_SOUP_PROXY_RESOLVER, - PROP_G_PROXY_RESOLVER, + PROP_PROXY_RESOLVER, PROP_SSL, PROP_SSL_CREDS, PROP_SSL_STRICT, @@ -86,8 +84,7 @@ soup_connection_finalize (GObject *object) g_clear_pointer (&priv->remote_uri, soup_uri_free); g_clear_pointer (&priv->proxy_uri, soup_uri_free); g_clear_object (&priv->tlsdb); - g_clear_object (&priv->soup_proxy_resolver); - g_clear_object (&priv->g_proxy_resolver); + g_clear_object (&priv->proxy_resolver); g_clear_object (&priv->local_addr); g_clear_pointer (&priv->async_context, g_main_context_unref); @@ -115,7 +112,6 @@ soup_connection_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object); - SoupProxyURIResolver *proxy_resolver; switch (prop_id) { case PROP_LOCAL_ADDRESS: @@ -124,16 +120,8 @@ soup_connection_set_property (GObject *object, guint prop_id, case PROP_REMOTE_URI: priv->remote_uri = g_value_dup_boxed (value); break; - case PROP_SOUP_PROXY_RESOLVER: - proxy_resolver = g_value_get_object (value); - if (proxy_resolver && SOUP_IS_PROXY_RESOLVER_DEFAULT (proxy_resolver)) - priv->g_proxy_resolver = g_object_ref (g_proxy_resolver_get_default ()); - else if (proxy_resolver) - priv->soup_proxy_resolver = g_object_ref (proxy_resolver); - break; - case PROP_G_PROXY_RESOLVER: - if (g_value_get_object (value)) - priv->g_proxy_resolver = g_value_dup_object (value); + case PROP_PROXY_RESOLVER: + priv->proxy_resolver = g_value_dup_object (value); break; case PROP_SSL: priv->ssl = g_value_get_boolean (value); @@ -267,15 +255,8 @@ soup_connection_class_init (SoupConnectionClass *connection_class) SOUP_TYPE_URI, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( - object_class, PROP_SOUP_PROXY_RESOLVER, - g_param_spec_object (SOUP_CONNECTION_SOUP_PROXY_RESOLVER, - "Proxy resolver", - "SoupProxyResolver to use", - SOUP_TYPE_PROXY_URI_RESOLVER, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property ( - object_class, PROP_G_PROXY_RESOLVER, - g_param_spec_object (SOUP_CONNECTION_G_PROXY_RESOLVER, + object_class, PROP_PROXY_RESOLVER, + g_param_spec_object (SOUP_CONNECTION_PROXY_RESOLVER, "Proxy resolver", "GProxyResolver to use", G_TYPE_PROXY_RESOLVER, @@ -519,8 +500,7 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data) return; } - if (priv->g_proxy_resolver) - priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); + priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); if (priv->ssl && !priv->proxy_uri) { if (soup_socket_start_ssl (sock, data->cancellable)) { @@ -538,55 +518,6 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data) socket_connect_finished (sock, status, data); } -static void -connect_async_to_uri (SoupConnectionAsyncConnectData *data, SoupURI *uri) -{ - SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); - SoupAddress *remote_addr; - - remote_addr = soup_address_new (uri->host, uri->port); - priv->socket = - soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, - SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb, - SOUP_SOCKET_SSL_STRICT, priv->ssl_strict, - SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback, - SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context, - SOUP_SOCKET_USE_THREAD_CONTEXT, priv->use_thread_context, - SOUP_SOCKET_PROXY_RESOLVER, priv->g_proxy_resolver, - SOUP_SOCKET_TIMEOUT, priv->io_timeout, - SOUP_SOCKET_CLEAN_DISPOSE, TRUE, - SOUP_SOCKET_LOCAL_ADDRESS, priv->local_addr, - NULL); - g_object_unref (remote_addr); - - data->event_id = g_signal_connect (priv->socket, "event", - G_CALLBACK (re_emit_socket_event), - data->conn); - - soup_socket_connect_async (priv->socket, data->cancellable, - socket_connect_result, data); -} - -static void -proxy_resolver_result (SoupProxyURIResolver *resolver, - guint status, SoupURI *proxy_uri, - gpointer user_data) -{ - SoupConnectionAsyncConnectData *data = user_data; - SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); - - if (status != SOUP_STATUS_OK) { - socket_connect_finished (NULL, status, data); - return; - } - - if (proxy_uri) { - priv->proxy_uri = soup_uri_copy (proxy_uri); - connect_async_to_uri (data, proxy_uri); - } else - connect_async_to_uri (data, priv->remote_uri); -} - void soup_connection_connect_async (SoupConnection *conn, GCancellable *cancellable, @@ -595,7 +526,7 @@ soup_connection_connect_async (SoupConnection *conn, { SoupConnectionAsyncConnectData *data; SoupConnectionPrivate *priv; - GMainContext *async_context; + SoupAddress *remote_addr; g_return_if_fail (SOUP_IS_CONNECTION (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); @@ -609,22 +540,28 @@ soup_connection_connect_async (SoupConnection *conn, data->callback_data = user_data; data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - if (!priv->soup_proxy_resolver) { - connect_async_to_uri (data, priv->remote_uri); - return; - } + remote_addr = soup_address_new (priv->remote_uri->host, + priv->remote_uri->port); + priv->socket = + soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, + SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb, + SOUP_SOCKET_SSL_STRICT, priv->ssl_strict, + SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback, + SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context, + SOUP_SOCKET_USE_THREAD_CONTEXT, priv->use_thread_context, + SOUP_SOCKET_PROXY_RESOLVER, priv->proxy_resolver, + SOUP_SOCKET_TIMEOUT, priv->io_timeout, + SOUP_SOCKET_CLEAN_DISPOSE, TRUE, + SOUP_SOCKET_LOCAL_ADDRESS, priv->local_addr, + NULL); + g_object_unref (remote_addr); - if (priv->use_thread_context) - async_context = g_main_context_get_thread_default (); - else - async_context = priv->async_context; + data->event_id = g_signal_connect (priv->socket, "event", + G_CALLBACK (re_emit_socket_event), + data->conn); - soup_proxy_uri_resolver_get_proxy_uri_async (priv->soup_proxy_resolver, - priv->remote_uri, - async_context, - cancellable, - proxy_resolver_result, - data); + soup_socket_connect_async (priv->socket, data->cancellable, + socket_connect_result, data); } guint @@ -632,7 +569,6 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) { SoupConnectionPrivate *priv; guint status, event_id = 0; - SoupURI *connect_uri; SoupAddress *remote_addr; g_return_val_if_fail (SOUP_IS_CONNECTION (conn), SOUP_STATUS_MALFORMED); @@ -641,25 +577,10 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); - if (priv->soup_proxy_resolver) { - status = soup_proxy_uri_resolver_get_proxy_uri_sync (priv->soup_proxy_resolver, - priv->remote_uri, - cancellable, - &priv->proxy_uri); - if (status != SOUP_STATUS_OK) - goto fail; - - if (priv->proxy_uri) - connect_uri = priv->proxy_uri; - else - connect_uri = priv->remote_uri; - } else - connect_uri = priv->remote_uri; - - remote_addr = soup_address_new (connect_uri->host, connect_uri->port); + remote_addr = soup_address_new (priv->remote_uri->host, priv->remote_uri->port); priv->socket = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, - SOUP_SOCKET_PROXY_RESOLVER, priv->g_proxy_resolver, + SOUP_SOCKET_PROXY_RESOLVER, priv->proxy_resolver, SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb, SOUP_SOCKET_SSL_STRICT, priv->ssl_strict, SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback, @@ -677,8 +598,7 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) if (!SOUP_STATUS_IS_SUCCESSFUL (status)) goto fail; - if (priv->g_proxy_resolver) - priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); + priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); if (priv->ssl && !priv->proxy_uri) { if (!soup_socket_start_ssl (priv->socket, cancellable)) diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h index dcfb56ac..50fb7018 100644 --- a/libsoup/soup-connection.h +++ b/libsoup/soup-connection.h @@ -41,8 +41,7 @@ typedef void (*SoupConnectionCallback) (SoupConnection *conn, #define SOUP_CONNECTION_LOCAL_ADDRESS "local-address" #define SOUP_CONNECTION_REMOTE_URI "remote-uri" -#define SOUP_CONNECTION_SOUP_PROXY_RESOLVER "soup-proxy-resolver" -#define SOUP_CONNECTION_G_PROXY_RESOLVER "g-proxy-resolver" +#define SOUP_CONNECTION_PROXY_RESOLVER "proxy-resolver" #define SOUP_CONNECTION_SSL "ssl" #define SOUP_CONNECTION_SSL_CREDENTIALS "ssl-creds" #define SOUP_CONNECTION_SSL_STRICT "ssl-strict" diff --git a/libsoup/soup-gnome-features.h b/libsoup/soup-gnome-features.h index 648d5043..18f37dea 100644 --- a/libsoup/soup-gnome-features.h +++ b/libsoup/soup-gnome-features.h @@ -11,7 +11,7 @@ G_BEGIN_DECLS SOUP_AVAILABLE_IN_2_26 -SOUP_DEPRECATED_IN_2_42_FOR(SOUP_TYPE_PROXY_RESOLVER_DEFAULT) +SOUP_DEPRECATED_IN_2_42_FOR(SoupSession:proxy-resolver) GType soup_proxy_resolver_gnome_get_type (void); #define SOUP_TYPE_PROXY_RESOLVER_GNOME (soup_proxy_resolver_gnome_get_type ()) diff --git a/libsoup/soup-proxy-resolver-default.c b/libsoup/soup-proxy-resolver-default.c index ee3b102b..9149feef 100644 --- a/libsoup/soup-proxy-resolver-default.c +++ b/libsoup/soup-proxy-resolver-default.c @@ -9,6 +9,9 @@ #include #endif +#undef SOUP_VERSION_MIN_REQUIRED +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_42 + #include "soup-proxy-resolver-default.h" #include "soup.h" @@ -19,14 +22,11 @@ * #SoupProxyResolverDefault is a #SoupProxyURIResolver implementation * that uses the default gio GProxyResolver to resolve proxies. * - * If you are using a plain #SoupSession (ie, not #SoupSessionAsync or - * #SoupSessionSync), then a #SoupProxyResolverDefault will - * automatically be added to the session. (You can use - * %SOUP_SESSION_REMOVE_FEATURE_BY_TYPE at construct time if you don't - * want this.) If you are using one of the deprecated #SoupSession - * subclasses, you can add a #SoupProxyResolverDefault to your session - * with soup_session_add_feature() or - * soup_session_add_feature_by_type(). + * Deprecated: In libsoup 2.44 and later, you can set the + * #SoupSession:proxy-resolver property to the resolver returned by + * g_proxy_resolver_get_default() to get the same effect. Note that + * for "plain" #SoupSessions (ie, not #SoupSessionAsync or + * #SoupSessionSync), this is done for you automatically. * * Since: 2.34 */ diff --git a/libsoup/soup-proxy-resolver-gnome.c b/libsoup/soup-proxy-resolver-gnome.c index bc423370..16a34680 100644 --- a/libsoup/soup-proxy-resolver-gnome.c +++ b/libsoup/soup-proxy-resolver-gnome.c @@ -9,6 +9,9 @@ #include #endif +#undef SOUP_VERSION_MIN_REQUIRED +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_40 + #include #include "soup-proxy-resolver-gnome.h" diff --git a/libsoup/soup-proxy-resolver-static.c b/libsoup/soup-proxy-resolver-static.c deleted file mode 100644 index 94327671..00000000 --- a/libsoup/soup-proxy-resolver-static.c +++ /dev/null @@ -1,177 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * soup-proxy-resolver-static.c: Static proxy "resolution" - * - * Copyright (C) 2008 Red Hat, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "soup-proxy-resolver-static.h" -#include "soup.h" - -typedef struct { - SoupURI *proxy_uri; - -} SoupProxyResolverStaticPrivate; -#define SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_PROXY_RESOLVER_STATIC, SoupProxyResolverStaticPrivate)) - -static void soup_proxy_resolver_static_interface_init (SoupProxyURIResolverInterface *proxy_resolver_interface); - -G_DEFINE_TYPE_EXTENDED (SoupProxyResolverStatic, soup_proxy_resolver_static, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL) - G_IMPLEMENT_INTERFACE (SOUP_TYPE_PROXY_URI_RESOLVER, soup_proxy_resolver_static_interface_init)) - -enum { - PROP_0, - - PROP_PROXY_URI, - - LAST_PROP -}; - -static void -soup_proxy_resolver_static_init (SoupProxyResolverStatic *resolver_static) -{ -} - -static void -soup_proxy_resolver_static_finalize (GObject *object) -{ - SoupProxyResolverStaticPrivate *priv = - SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (object); - - g_clear_pointer (&priv->proxy_uri, soup_uri_free); - - G_OBJECT_CLASS (soup_proxy_resolver_static_parent_class)->finalize (object); -} - -static void -soup_proxy_resolver_static_set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - SoupProxyResolverStaticPrivate *priv = - SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (object); - SoupURI *uri; - - switch (prop_id) { - case PROP_PROXY_URI: - uri = g_value_get_boxed (value); - if (priv->proxy_uri) - soup_uri_free (priv->proxy_uri); - - priv->proxy_uri = uri ? soup_uri_copy (uri) : NULL; - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -soup_proxy_resolver_static_get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - SoupProxyResolverStaticPrivate *priv = - SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_PROXY_URI: - g_value_set_boxed (value, priv->proxy_uri); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -typedef struct { - SoupProxyURIResolver *proxy_resolver; - SoupProxyURIResolverCallback callback; - gpointer user_data; -} SoupStaticAsyncData; - -static gboolean -idle_return_proxy_uri (gpointer data) -{ - SoupStaticAsyncData *ssad = data; - SoupProxyResolverStaticPrivate *priv = - SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (ssad->proxy_resolver); - - ssad->callback (ssad->proxy_resolver, - SOUP_STATUS_OK, priv->proxy_uri, - ssad->user_data); - g_object_unref (ssad->proxy_resolver); - g_slice_free (SoupStaticAsyncData, ssad); - - return FALSE; -} - -static void -soup_proxy_resolver_static_get_proxy_uri_async (SoupProxyURIResolver *proxy_resolver, - SoupURI *uri, - GMainContext *async_context, - GCancellable *cancellable, - SoupProxyURIResolverCallback callback, - gpointer user_data) -{ - SoupStaticAsyncData *ssad; - - ssad = g_slice_new0 (SoupStaticAsyncData); - ssad->proxy_resolver = g_object_ref (proxy_resolver); - ssad->callback = callback; - ssad->user_data = user_data; - soup_add_completion (async_context, idle_return_proxy_uri, ssad); -} - -static guint -soup_proxy_resolver_static_get_proxy_uri_sync (SoupProxyURIResolver *proxy_resolver, - SoupURI *uri, - GCancellable *cancellable, - SoupURI **proxy_uri) -{ - SoupProxyResolverStaticPrivate *priv = - SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (proxy_resolver); - - *proxy_uri = soup_uri_copy (priv->proxy_uri); - return SOUP_STATUS_OK; -} - -static void -soup_proxy_resolver_static_class_init (SoupProxyResolverStaticClass *static_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (static_class); - - g_type_class_add_private (static_class, sizeof (SoupProxyResolverStaticPrivate)); - - object_class->set_property = soup_proxy_resolver_static_set_property; - object_class->get_property = soup_proxy_resolver_static_get_property; - object_class->finalize = soup_proxy_resolver_static_finalize; - - g_object_class_install_property ( - object_class, PROP_PROXY_URI, - g_param_spec_boxed (SOUP_PROXY_RESOLVER_STATIC_PROXY_URI, - "Proxy URI", - "The HTTP Proxy to use", - SOUP_TYPE_URI, - G_PARAM_READWRITE)); -} - -static void -soup_proxy_resolver_static_interface_init (SoupProxyURIResolverInterface *proxy_uri_resolver_interface) -{ - proxy_uri_resolver_interface->get_proxy_uri_async = - soup_proxy_resolver_static_get_proxy_uri_async; - proxy_uri_resolver_interface->get_proxy_uri_sync = - soup_proxy_resolver_static_get_proxy_uri_sync; -} - -SoupProxyURIResolver * -soup_proxy_resolver_static_new (SoupURI *proxy_uri) -{ - return g_object_new (SOUP_TYPE_PROXY_RESOLVER_STATIC, - SOUP_PROXY_RESOLVER_STATIC_PROXY_URI, proxy_uri, - NULL); -} diff --git a/libsoup/soup-proxy-resolver-static.h b/libsoup/soup-proxy-resolver-static.h deleted file mode 100644 index 090b84b9..00000000 --- a/libsoup/soup-proxy-resolver-static.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2008 Red Hat, Inc. - */ - -#ifndef SOUP_PROXY_RESOLVER_STATIC_H -#define SOUP_PROXY_RESOLVER_STATIC_H 1 - -#include "soup-proxy-uri-resolver.h" -#include "soup-uri.h" - -#define SOUP_TYPE_PROXY_RESOLVER_STATIC (soup_proxy_resolver_static_get_type ()) -#define SOUP_PROXY_RESOLVER_STATIC(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER_STATIC, SoupProxyResolverStatic)) -#define SOUP_PROXY_RESOLVER_STATIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER_STATIC, SoupProxyResolverStaticClass)) -#define SOUP_IS_PROXY_RESOLVER_STATIC(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER_STATIC)) -#define SOUP_IS_PROXY_RESOLVER_STATIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER_STATIC)) -#define SOUP_PROXY_RESOLVER_STATIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_PROXY_RESOLVER_STATIC, SoupProxyResolverStaticClass)) - -typedef struct { - GObject parent; - -} SoupProxyResolverStatic; - -typedef struct { - GObjectClass parent_class; - -} SoupProxyResolverStaticClass; - -GType soup_proxy_resolver_static_get_type (void); - -#define SOUP_PROXY_RESOLVER_STATIC_PROXY_URI "proxy-uri" - -SoupProxyURIResolver *soup_proxy_resolver_static_new (SoupURI *proxy_uri); - -#endif /* SOUP_PROXY_RESOLVER_STATIC_H */ diff --git a/libsoup/soup-proxy-resolver-wrapper.c b/libsoup/soup-proxy-resolver-wrapper.c new file mode 100644 index 00000000..e07664ca --- /dev/null +++ b/libsoup/soup-proxy-resolver-wrapper.c @@ -0,0 +1,167 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * soup-proxy-resolver-wrapper.c: SoupProxyURIResolver -> GProxyResolver wrapper + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "soup-proxy-resolver-wrapper.h" +#include "soup.h" + +static void soup_proxy_resolver_wrapper_interface_init (GProxyResolverInterface *proxy_resolver_interface); + +G_DEFINE_TYPE_WITH_CODE (SoupProxyResolverWrapper, soup_proxy_resolver_wrapper, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER, soup_proxy_resolver_wrapper_interface_init); + ) + +static void +soup_proxy_resolver_wrapper_init (SoupProxyResolverWrapper *resolver_wrapper) +{ +} + +static void +soup_proxy_resolver_wrapper_finalize (GObject *object) +{ + SoupProxyResolverWrapper *wrapper = + SOUP_PROXY_RESOLVER_WRAPPER (object); + + g_clear_object (&wrapper->soup_resolver); + + G_OBJECT_CLASS (soup_proxy_resolver_wrapper_parent_class)->finalize (object); +} + +static char ** +convert_response (SoupURI *source_uri, guint status, + SoupURI *proxy_uri, GError **error) +{ + char **proxies = NULL; + + if (status == SOUP_STATUS_CANT_RESOLVE_PROXY) { + g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND, + "%s (%s)", soup_status_get_phrase (status), + source_uri->host); + } else if (status == SOUP_STATUS_CANT_CONNECT_PROXY) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED, + "%s (%s)", soup_status_get_phrase (status), + source_uri->host); + } else { + g_return_val_if_fail (status == SOUP_STATUS_OK, NULL); + + proxies = g_new (char *, 2); + proxies[0] = soup_uri_to_string (proxy_uri, FALSE); + proxies[1] = NULL; + + soup_uri_free (proxy_uri); + } + + return proxies; +} + +static void +wrapper_lookup_async_complete (SoupProxyURIResolver *resolver, + guint status, SoupURI *proxy_uri, + gpointer user_data) +{ + GTask *task = user_data; + SoupURI *source_uri = g_task_get_task_data (task); + char **proxies; + GError *error = NULL; + + proxies = convert_response (source_uri, status, proxy_uri, &error); + if (error) + g_task_return_error (task, error); + else + g_task_return_pointer (task, proxies, (GDestroyNotify) g_strfreev); + g_object_unref (task); +} + +static void +soup_proxy_resolver_wrapper_lookup_async (GProxyResolver *resolver, + const gchar *uri, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupProxyResolverWrapper *wrapper = + SOUP_PROXY_RESOLVER_WRAPPER (resolver); + GTask *task; + SoupURI *source_uri; + + task = g_task_new (resolver, cancellable, callback, user_data); + source_uri = soup_uri_new (uri); + g_task_set_task_data (task, source_uri, (GDestroyNotify) soup_uri_free); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + soup_proxy_uri_resolver_get_proxy_uri_async (wrapper->soup_resolver, + source_uri, + g_main_context_get_thread_default (), + cancellable, + wrapper_lookup_async_complete, + task); + G_GNUC_END_IGNORE_DEPRECATIONS; +} + +static char ** +soup_proxy_resolver_wrapper_lookup_finish (GProxyResolver *resolver, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (result), error); +} + +static gchar ** +soup_proxy_resolver_wrapper_lookup (GProxyResolver *resolver, + const gchar *uri, + GCancellable *cancellable, + GError **error) +{ + SoupProxyResolverWrapper *wrapper = + SOUP_PROXY_RESOLVER_WRAPPER (resolver); + SoupURI *source_uri, *proxy_uri; + guint status; + gchar **proxies; + + source_uri = soup_uri_new (uri); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + status = soup_proxy_uri_resolver_get_proxy_uri_sync (wrapper->soup_resolver, + source_uri, + cancellable, + &proxy_uri); + G_GNUC_END_IGNORE_DEPRECATIONS; + proxies = convert_response (source_uri, status, proxy_uri, error); + soup_uri_free (source_uri); + return proxies; +} + +static void +soup_proxy_resolver_wrapper_class_init (SoupProxyResolverWrapperClass *static_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (static_class); + + object_class->finalize = soup_proxy_resolver_wrapper_finalize; +} + +static void +soup_proxy_resolver_wrapper_interface_init (GProxyResolverInterface *proxy_resolver_interface) +{ + proxy_resolver_interface->lookup = + soup_proxy_resolver_wrapper_lookup; + proxy_resolver_interface->lookup_async = + soup_proxy_resolver_wrapper_lookup_async; + proxy_resolver_interface->lookup_finish = + soup_proxy_resolver_wrapper_lookup_finish; +} + +GProxyResolver * +soup_proxy_resolver_wrapper_new (SoupProxyURIResolver *soup_resolver) +{ + SoupProxyResolverWrapper *wrapper; + + wrapper = g_object_new (SOUP_TYPE_PROXY_RESOLVER_WRAPPER, NULL); + wrapper->soup_resolver = g_object_ref (soup_resolver); + return (GProxyResolver *)wrapper; +} diff --git a/libsoup/soup-proxy-resolver-wrapper.h b/libsoup/soup-proxy-resolver-wrapper.h new file mode 100644 index 00000000..d16b57c9 --- /dev/null +++ b/libsoup/soup-proxy-resolver-wrapper.h @@ -0,0 +1,34 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2008 Red Hat, Inc. + */ + +#ifndef SOUP_PROXY_RESOLVER_WRAPPER_H +#define SOUP_PROXY_RESOLVER_WRAPPER_H 1 + +#include "soup-proxy-uri-resolver.h" +#include "soup-uri.h" + +#define SOUP_TYPE_PROXY_RESOLVER_WRAPPER (soup_proxy_resolver_wrapper_get_type ()) +#define SOUP_PROXY_RESOLVER_WRAPPER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER_WRAPPER, SoupProxyResolverWrapper)) +#define SOUP_PROXY_RESOLVER_WRAPPER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER_WRAPPER, SoupProxyResolverWrapperClass)) +#define SOUP_IS_PROXY_RESOLVER_WRAPPER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER_WRAPPER)) +#define SOUP_IS_PROXY_RESOLVER_WRAPPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER_WRAPPER)) +#define SOUP_PROXY_RESOLVER_WRAPPER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_PROXY_RESOLVER_WRAPPER, SoupProxyResolverWrapperClass)) + +typedef struct { + GObject parent; + + SoupProxyURIResolver *soup_resolver; +} SoupProxyResolverWrapper; + +typedef struct { + GObjectClass parent_class; + +} SoupProxyResolverWrapperClass; + +GType soup_proxy_resolver_wrapper_get_type (void); + +GProxyResolver *soup_proxy_resolver_wrapper_new (SoupProxyURIResolver *soup_resolver); + +#endif /* SOUP_PROXY_RESOLVER_WRAPPER_H */ diff --git a/libsoup/soup-proxy-resolver.h b/libsoup/soup-proxy-resolver.h index 87989569..72e48852 100644 --- a/libsoup/soup-proxy-resolver.h +++ b/libsoup/soup-proxy-resolver.h @@ -39,7 +39,7 @@ typedef struct { } SoupProxyResolverInterface; -SOUP_DEPRECATED_IN_2_28_FOR(SoupProxyURIResolver) +SOUP_DEPRECATED_IN_2_28 GType soup_proxy_resolver_get_type (void); SOUP_DEPRECATED_IN_2_28 diff --git a/libsoup/soup-proxy-uri-resolver.c b/libsoup/soup-proxy-uri-resolver.c index ca49b90f..f075a0f7 100644 --- a/libsoup/soup-proxy-uri-resolver.c +++ b/libsoup/soup-proxy-uri-resolver.c @@ -9,6 +9,9 @@ #include #endif +#undef SOUP_VERSION_MIN_REQUIRED +#define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_42 + #include "soup-proxy-uri-resolver.h" #include "soup.h" @@ -19,12 +22,18 @@ * #SoupProxyURIResolver is an interface for finding appropriate HTTP * proxies to use. * - * You are not likely to have to implement this interface on your own; - * instead, you should usually just be able to use - * #SoupProxyResolverDefault. + * Deprecated: #SoupSession now has a #SoupSession:proxy-resolver + * property that takes a #GProxyResolver (which is semantically + * identical to #SoupProxyURIResolver). + * + * Even in older releases of libsoup, you are not likely to have to + * implement this interface on your own; instead, you should usually + * just be able to use #SoupProxyResolverDefault. */ -G_DEFINE_INTERFACE (SoupProxyURIResolver, soup_proxy_uri_resolver, G_TYPE_OBJECT) +G_DEFINE_INTERFACE_WITH_CODE (SoupProxyURIResolver, soup_proxy_uri_resolver, G_TYPE_OBJECT, + g_type_interface_add_prerequisite (g_define_type_id, SOUP_TYPE_SESSION_FEATURE); + ) static void soup_proxy_uri_resolver_default_init (SoupProxyURIResolverInterface *iface) @@ -54,6 +63,9 @@ soup_proxy_uri_resolver_default_init (SoupProxyURIResolverInterface *iface) * @callback. * * Since: 2.26.3 + * + * Deprecated: #SoupProxyURIResolver is deprecated in favor of + * #GProxyResolver **/ void soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_resolver, @@ -84,6 +96,9 @@ soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_re * error. * * Since: 2.26.3 + * + * Deprecated: #SoupProxyURIResolver is deprecated in favor of + * #GProxyResolver **/ guint soup_proxy_uri_resolver_get_proxy_uri_sync (SoupProxyURIResolver *proxy_uri_resolver, diff --git a/libsoup/soup-proxy-uri-resolver.h b/libsoup/soup-proxy-uri-resolver.h index 95c118fe..e203125b 100644 --- a/libsoup/soup-proxy-uri-resolver.h +++ b/libsoup/soup-proxy-uri-resolver.h @@ -44,9 +44,11 @@ typedef struct { } SoupProxyURIResolverInterface; SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_44 GType soup_proxy_uri_resolver_get_type (void); SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_44 void soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_resolver, SoupURI *uri, GMainContext *async_context, @@ -54,6 +56,7 @@ void soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_ SoupProxyURIResolverCallback callback, gpointer user_data); SOUP_AVAILABLE_IN_2_28 +SOUP_DEPRECATED_IN_2_44 guint soup_proxy_uri_resolver_get_proxy_uri_sync (SoupProxyURIResolver *proxy_uri_resolver, SoupURI *uri, GCancellable *cancellable, diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 627a6843..95436f30 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -19,7 +19,7 @@ #include "soup-message-private.h" #include "soup-misc-private.h" #include "soup-message-queue.h" -#include "soup-proxy-resolver-static.h" +#include "soup-proxy-resolver-wrapper.h" #include "soup-session-private.h" #define HOST_KEEP_ALIVE 5 * 60 * 1000 /* 5 min in msecs */ @@ -121,7 +121,8 @@ typedef struct { GSList *run_queue_sources; GResolver *resolver; - GProxyResolver *g_proxy_resolver; + GProxyResolver *proxy_resolver; + SoupURI *proxy_uri; char **http_aliases, **https_aliases; @@ -278,8 +279,9 @@ soup_session_constructor (GType type, priv->http_aliases[0] = NULL; + priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ()); + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); - soup_session_add_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_DEFAULT); } return object; @@ -336,7 +338,8 @@ soup_session_finalize (GObject *object) g_hash_table_destroy (priv->features_cache); g_object_unref (priv->resolver); - g_clear_object (&priv->g_proxy_resolver); + g_clear_object (&priv->proxy_resolver); + g_clear_pointer (&priv->proxy_uri, soup_uri_free); g_free (priv->http_aliases); g_free (priv->https_aliases); @@ -547,13 +550,43 @@ set_aliases (char ***variable, char **value) (*variable)[i] = NULL; } +static void +set_proxy_resolver (SoupSession *session, SoupURI *uri, + SoupProxyURIResolver *soup_resolver, + GProxyResolver *g_resolver) +{ + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_URI_RESOLVER); + G_GNUC_END_IGNORE_DEPRECATIONS; + g_clear_object (&priv->proxy_resolver); + g_clear_pointer (&priv->proxy_uri, soup_uri_free); + + if (uri) { + char *uri_string; + + priv->proxy_uri = soup_uri_copy (uri); + uri_string = soup_uri_to_string (uri, FALSE); + priv->proxy_resolver = g_simple_proxy_resolver_new (uri_string, NULL); + g_free (uri_string); + } else if (soup_resolver) { + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + if (SOUP_IS_PROXY_RESOLVER_DEFAULT (soup_resolver)) + priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ()); + else + priv->proxy_resolver = soup_proxy_resolver_wrapper_new (soup_resolver); + G_GNUC_END_IGNORE_DEPRECATIONS; + } else if (g_resolver) + priv->proxy_resolver = g_object_ref (g_resolver); +} + static void soup_session_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SoupSession *session = SOUP_SESSION (object); SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - SoupURI *uri; const char *user_agent; SoupSessionFeature *feature; GMainContext *async_context; @@ -563,26 +596,13 @@ soup_session_set_property (GObject *object, guint prop_id, priv->local_addr = g_value_dup_object (value); break; case PROP_PROXY_URI: - uri = g_value_get_boxed (value); - if (uri) { - G_GNUC_BEGIN_IGNORE_DEPRECATIONS; - soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER); - G_GNUC_END_IGNORE_DEPRECATIONS; - feature = SOUP_SESSION_FEATURE (soup_proxy_resolver_static_new (uri)); - soup_session_add_feature (session, feature); - g_object_unref (feature); - } else - soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER_STATIC); - g_clear_object (&priv->g_proxy_resolver); + set_proxy_resolver (session, g_value_get_boxed (value), + NULL, NULL); soup_session_abort (session); break; case PROP_PROXY_RESOLVER: - G_GNUC_BEGIN_IGNORE_DEPRECATIONS; - soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER); - G_GNUC_END_IGNORE_DEPRECATIONS; - if (priv->g_proxy_resolver) - g_object_unref (priv->g_proxy_resolver); - priv->g_proxy_resolver = g_value_dup_object (value); + set_proxy_resolver (session, NULL, NULL, + g_value_get_object (value)); break; case PROP_MAX_CONNS: priv->max_conns = g_value_get_int (value); @@ -705,16 +725,10 @@ soup_session_get_property (GObject *object, guint prop_id, g_value_set_object (value, priv->local_addr); break; case PROP_PROXY_URI: - feature = soup_session_get_feature (session, SOUP_TYPE_PROXY_RESOLVER_STATIC); - if (feature) { - g_object_get_property (G_OBJECT (feature), - SOUP_PROXY_RESOLVER_STATIC_PROXY_URI, - value); - } else - g_value_set_boxed (value, NULL); + g_value_set_boxed (value, priv->proxy_uri); break; case PROP_PROXY_RESOLVER: - g_value_set_object (value, priv->g_proxy_resolver); + g_value_set_object (value, priv->proxy_resolver); break; case PROP_MAX_CONNS: g_value_set_int (value, priv->max_conns); @@ -1676,8 +1690,7 @@ get_connection_for_host (SoupSession *session, conn = g_object_new ( SOUP_TYPE_CONNECTION, SOUP_CONNECTION_REMOTE_URI, host->uri, - SOUP_CONNECTION_SOUP_PROXY_RESOLVER, soup_session_get_feature (session, SOUP_TYPE_PROXY_URI_RESOLVER), - SOUP_CONNECTION_G_PROXY_RESOLVER, priv->g_proxy_resolver, + SOUP_CONNECTION_PROXY_RESOLVER, priv->proxy_resolver, SOUP_CONNECTION_SSL, uri_is_https (priv, soup_message_get_uri (item->msg)), SOUP_CONNECTION_SSL_CREDENTIALS, priv->tlsdb, SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (priv->tlsdb != NULL || SOUP_IS_PLAIN_SESSION (session)), @@ -2463,9 +2476,8 @@ soup_session_prefetch_dns (SoupSession *session, const char *hostname, * feature to the session at construct time by using the * %SOUP_SESSION_ADD_FEATURE property. * - * Note that a #SoupProxyResolverDefault and a #SoupContentDecoder are - * added to the session by default (unless you are using one of the - * deprecated session subclasses). + * Note that a #SoupContentDecoder is added to the session by default + * (unless you are using one of the deprecated session subclasses). * * Since: 2.24 **/ @@ -2479,8 +2491,13 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature) priv = SOUP_SESSION_GET_PRIVATE (session); - if (SOUP_IS_PROXY_URI_RESOLVER (feature)) - g_clear_object (&priv->g_proxy_resolver); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + if (SOUP_IS_PROXY_URI_RESOLVER (feature)) { + set_proxy_resolver (session, NULL, + SOUP_PROXY_URI_RESOLVER (feature), + NULL); + } + G_GNUC_END_IGNORE_DEPRECATIONS; priv->features = g_slist_prepend (priv->features, g_object_ref (feature)); g_hash_table_remove_all (priv->features_cache); @@ -2505,9 +2522,8 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature) * You can also add a feature to the session at construct time by * using the %SOUP_SESSION_ADD_FEATURE_BY_TYPE property. * - * Note that a #SoupProxyResolverDefault and a #SoupContentDecoder are - * added to the session by default (unless you are using one of the - * deprecated session subclasses). + * Note that a #SoupContentDecoder is added to the session by default + * (unless you are using one of the deprecated session subclasses). * * Since: 2.24 **/ @@ -2568,6 +2584,15 @@ soup_session_remove_feature (SoupSession *session, SoupSessionFeature *feature) priv->features = g_slist_remove (priv->features, feature); g_hash_table_remove_all (priv->features_cache); soup_session_feature_detach (feature, session); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + if (SOUP_IS_PROXY_URI_RESOLVER (feature)) { + if (SOUP_IS_PROXY_RESOLVER_WRAPPER (priv->proxy_resolver) && + SOUP_PROXY_RESOLVER_WRAPPER (priv->proxy_resolver)->soup_resolver == SOUP_PROXY_URI_RESOLVER (feature)) + g_clear_object (&priv->proxy_resolver); + } + G_GNUC_END_IGNORE_DEPRECATIONS; + g_object_unref (feature); } } @@ -2976,16 +3001,23 @@ soup_session_class_init (SoupSessionClass *session_class) /** * SoupSession:proxy-uri: * - * An http proxy to use for all http and https requests in - * this session. Setting this will remove any + * A proxy to use for all http and https requests in this + * session. Setting this will clear the + * #SoupSession:proxy-resolver property, and remove any * #SoupProxyURIResolver features that have been added to the * session. Setting this property will also cancel all * currently pending messages. * - * Note that #SoupProxyResolverDefault will handle looking up - * the user's proxy settings for you; you should only use + * Note that #SoupSession will normally handle looking up the + * user's proxy settings for you; you should only use * #SoupSession:proxy-uri if you need to override the user's * normal proxy settings. + * + * Also note that this proxy will be used for + * all requests; even requests to + * localhost. If you need more control over + * proxies, you can create a #GSimpleProxyResolver and set the + * #SoupSession:proxy-resolver property. */ /** * SOUP_SESSION_PROXY_URI: @@ -3007,12 +3039,11 @@ soup_session_class_init (SoupSessionClass *session_class) * any #SoupProxyURIResolver features that have been added to * the session. * - * You only need to set this if you want to manually control - * proxy resolution (and need to do something more complicated than - * #SoupSession:proxy-uri allows). If you just want to use the - * system proxy settings, #SoupProxyResolverDefault will do that - * for you, and that is automatically part of the session if you - * are using a plain #SoupSession. + * By default, in a plain #SoupSession, this is set to the + * default #GProxyResolver, but you can set it to %NULL if you + * don't want to use proxies, or set it to your own + * #GProxyResolver if you want to control what proxies get + * used. * * Since: 2.42 */ -- cgit v1.2.1 From 74f27b8305cfbcf9324a07bea93829237c86e687 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Tue, 18 Jun 2013 08:48:44 +0100 Subject: tld-parser.py: Force file io to use utf-8 This fixes an issue where the build would fail with a UnicodeDecodeError when run in a non-utf8 locale (which is typical in build environments) using Python 3. https://bugzilla.gnome.org/show_bug.cgi?id=702534 --- libsoup/tld-parser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsoup/tld-parser.py b/libsoup/tld-parser.py index c1a0346f..5d9d2ba5 100755 --- a/libsoup/tld-parser.py +++ b/libsoup/tld-parser.py @@ -5,13 +5,14 @@ # Based on tld-parser.c Copyright (C) 2012 Igalia S.L. import sys +import codecs SOUP_TLD_RULE_NORMAL = 0 SOUP_TLD_RULE_MATCH_ALL = 1 << 0 SOUP_TLD_RULE_EXCEPTION = 1 << 1 -tlds_file = open(sys.argv[1]) -inc_file = open(sys.argv[2], 'w') +tlds_file = codecs.open(sys.argv[1], encoding='utf-8') +inc_file = codecs.open(sys.argv[2], 'w', encoding='utf-8') first = True for rule in tlds_file: -- cgit v1.2.1 From 2e436f5c75fcff49518a33eee6429a23f556ec6d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 13 Jul 2013 11:55:00 -0400 Subject: soup-uri: fix URI scheme parsing The URI grammar allows a scheme to have digits in it after the first character, and doesn't allow [.+-] in the first character. https://bugzilla.gnome.org/show_bug.cgi?id=703776 --- libsoup/soup-uri.c | 7 +++++-- tests/uri-parsing.c | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index b9ff93fe..16098f69 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -263,10 +263,13 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) end = hash; } - /* Find scheme: initial [a-z+.-]* substring until ":" */ + /* Find scheme */ p = uri_string; while (p < end && (g_ascii_isalpha (*p) || - *p == '.' || *p == '+' || *p == '-')) + (p > uri_string && (g_ascii_isdigit (*p) || + *p == '.' || + *p == '+' || + *p == '-')))) p++; if (p > uri_string && *p == ':') { diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index 892ee2b9..d1bba4e1 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -128,6 +128,22 @@ static struct { { "http://host/keep%00nuls", "http://host/keep%00nuls", { "http", NULL, NULL, "host", 80, "/keep%00nuls", NULL, NULL } }, + + /* Bug 703776; scheme parsing */ + { "foo0://host/path", "foo0://host/path", + { "foo0", NULL, NULL, "host", 0, "/path", NULL, NULL } }, + { "f0.o://host/path", "f0.o://host/path", + { "f0.o", NULL, NULL, "host", 0, "/path", NULL, NULL } }, + { "http++://host/path", "http++://host/path", + { "http++", NULL, NULL, "host", 0, "/path", NULL, NULL } }, + { "http-ish://host/path", "http-ish://host/path", + { "http-ish", NULL, NULL, "host", 0, "/path", NULL, NULL } }, + { "99http://host/path", NULL, + { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, + { ".http://host/path", NULL, + { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, + { "+http://host/path", NULL, + { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, }; static int num_abs_tests = G_N_ELEMENTS(abs_tests); -- cgit v1.2.1 From 47615947cf5b135c00f39ce919ef7da9067c2cb0 Mon Sep 17 00:00:00 2001 From: Andres Gomez Date: Wed, 3 Jul 2013 13:06:37 +0300 Subject: [soup-logger] On response, always print headers SoupLogger won't print any information upon response until the "got-body" or "got-informational" signals are received. If the response message has been cancelled or requeued first, we miss the headers information, even when we would have been already able to print it. Now, upon response, if the logging has not yet happened when the "finished" signal is triggered, we do perform the logging then. https://bugzilla.gnome.org/show_bug.cgi?id=703200 --- libsoup/soup-logger.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/libsoup/soup-logger.c b/libsoup/soup-logger.c index 52d74cda..a441f211 100644 --- a/libsoup/soup-logger.c +++ b/libsoup/soup-logger.c @@ -4,6 +4,7 @@ * * Copyright (C) 2001-2004 Novell, Inc. * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2013 Igalia, S.L. */ #ifdef HAVE_CONFIG_H @@ -68,13 +69,21 @@ * the first byte of the request gets written to the network (from the * #SoupSession::request_started signal), which means that if you have * not made the complete request body available at that point, it will - * not be logged. The response is logged just after the last byte of - * the response body is read from the network (from the - * #SoupMessage::got_body or #SoupMessage::got_informational signal), - * which means that the #SoupMessage::got_headers signal, and anything - * triggered off it (such as #SoupSession::authenticate) will be - * emitted before the response headers are - * actually logged. + * not be logged. + * + * The response is logged just after the last byte of the response + * body is read from the network (from the #SoupMessage::got_body or + * #SoupMessage::got_informational signal), which means that the + * #SoupMessage::got_headers signal, and anything triggered off it + * (such as #SoupSession::authenticate) will be emitted + * before the response headers are actually + * logged. + * + * If the response doesn't happen to trigger the + * #SoupMessage::got_body nor #SoupMessage::got_informational signals + * due to, for example, a cancellation before receiving the last byte + * of the response body, the response will still be logged on the + * event of the #SoupMessage::finished signal. **/ static void soup_logger_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data); @@ -573,6 +582,20 @@ print_response (SoupLogger *logger, SoupMessage *msg) } } +static void +finished (SoupMessage *msg, gpointer user_data) +{ + SoupLogger *logger = user_data; + SoupLoggerPrivate *priv = SOUP_LOGGER_GET_PRIVATE (logger); + + g_mutex_lock (&priv->lock); + + print_response (logger, msg); + soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', ""); + + g_mutex_unlock (&priv->lock); +} + static void got_informational (SoupMessage *msg, gpointer user_data) { @@ -581,6 +604,7 @@ got_informational (SoupMessage *msg, gpointer user_data) g_mutex_lock (&priv->lock); + g_signal_handlers_disconnect_by_func (msg, finished, logger); print_response (logger, msg); soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', ""); @@ -615,6 +639,7 @@ got_body (SoupMessage *msg, gpointer user_data) g_mutex_lock (&priv->lock); + g_signal_handlers_disconnect_by_func (msg, finished, logger); print_response (logger, msg); soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, ' ', ""); @@ -634,6 +659,9 @@ soup_logger_request_queued (SoupSessionFeature *logger, g_signal_connect (msg, "got-body", G_CALLBACK (got_body), logger); + g_signal_connect (msg, "finished", + G_CALLBACK (finished), + logger); } static void @@ -677,6 +705,7 @@ soup_logger_request_unqueued (SoupSessionFeature *logger, g_signal_handlers_disconnect_by_func (msg, got_informational, logger); g_signal_handlers_disconnect_by_func (msg, got_body, logger); + g_signal_handlers_disconnect_by_func (msg, finished, logger); } static void -- cgit v1.2.1 From 5afc190b6c968a7f06ed5dcb0310384b9840f0fd Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 5 Jul 2013 19:14:17 +0100 Subject: soup-session: Warn if [un]pausing messages from a sync session It was never meant to work, and can lead to weird behaviour and crashes. Also mention this more explicitly in the documentation for soup_session_[un]pause_message(). Helps: https://bugzilla.gnome.org/show_bug.cgi?id=703461 --- libsoup/soup-session.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 95436f30..10851b3e 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -2109,6 +2109,9 @@ soup_session_send_message (SoupSession *session, SoupMessage *msg) * * Pauses HTTP I/O on @msg. Call soup_session_unpause_message() to * resume I/O. + * + * This may only be called for asynchronous messages (those sent on a + * #SoupSessionAsync or using soup_session_queue_message()). **/ void soup_session_pause_message (SoupSession *session, @@ -2123,6 +2126,7 @@ soup_session_pause_message (SoupSession *session, priv = SOUP_SESSION_GET_PRIVATE (session); item = soup_message_queue_lookup (priv->queue, msg); g_return_if_fail (item != NULL); + g_return_if_fail (item->async); item->paused = TRUE; if (item->state == SOUP_MESSAGE_RUNNING) @@ -2186,6 +2190,9 @@ soup_session_kick_queue (SoupSession *session) * If @msg is being sent via blocking I/O, this will resume reading or * writing immediately. If @msg is using non-blocking I/O, then * reading or writing won't resume until you return to the main loop. + * + * This may only be called for asynchronous messages (those sent on a + * #SoupSessionAsync or using soup_session_queue_message()). **/ void soup_session_unpause_message (SoupSession *session, @@ -2200,6 +2207,7 @@ soup_session_unpause_message (SoupSession *session, priv = SOUP_SESSION_GET_PRIVATE (session); item = soup_message_queue_lookup (priv->queue, msg); g_return_if_fail (item != NULL); + g_return_if_fail (item->async); item->paused = FALSE; if (item->state == SOUP_MESSAGE_RUNNING) -- cgit v1.2.1 From 78aaee682f7650d4687cbf0d62509d8b52629564 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 29 Jul 2013 17:40:22 -0400 Subject: 2.43.5 --- NEWS | 29 +++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ecd19a61..a9f337e0 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,32 @@ +Changes in libsoup from 2.43.4 to 2.43.5: + + * SoupProxyURIResolver is now deprecated in favor of the + SoupSession:proxy-resolver property (which takes a + GProxyResolver). [#680273, Dan] + + * The SoupKnownStatusCode enum is now called SoupStatus. The + old name continues to exist as an alias, but is deprecated. + (This change has no visible effect in C; it is primarily to + help language bindings, so that, eg, SOUP_STATUS_NOT_FOUND + maps to "Soup.Status.NOT_FOUND" rather than + "Soup.KnownStatusCode.NOT_FOUND".) [#684409, Dan] + + * Fixed the parsing of URI schemes in SoupURI (in particular, + to allow scheme names with digits in them). [#703776, Dan] + + * Fixed SoupLogger to print a message's response headers even + if the message gets cancelled before the complete response + body is received. [#703200, Andres Gomez] + + * Fixed a build problem in non-UTF-8 locales [#702534, Ross + Lagerwall] + + * SoupSession now warns if you use + soup_session_pause_message() or + soup_session_unpause_message() on a synchronous message + (which has never worked, though that fact wasn't + documented). [#703461, Philip Withnall] + Changes in libsoup from 2.43.2 to 2.43.4: * Fixed a bug that could cause synchronous sessions to get diff --git a/configure.ac b/configure.ac index a5461687..570b3b55 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [43]) -m4_define([soup_micro_version], [4]) +m4_define([soup_micro_version], [5]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 8524d46134bce62ee6d8a534a56c24da90651b9c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 4 Aug 2013 13:08:29 -0400 Subject: soup-message-server-io: handle unsatisfiable Range requests correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit soup_message_headers_get_ranges() doesn't check satisfiability (and can't without changing its API) so add a new soup_message_headers_get_ranges_internal(), and use that from soup-message-server-io so we can handle this properly. Test that it works from range-test. Pointed out on the mailing list by Kai Lüke. --- libsoup/soup-message-headers.c | 114 +++++++++++++++++++++++++-------------- libsoup/soup-message-server-io.c | 13 +++-- libsoup/soup-misc-private.h | 7 +++ tests/range-test.c | 85 ++++++++++++++++++++++++----- 4 files changed, 165 insertions(+), 54 deletions(-) diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c index 876db61c..f488c1c0 100644 --- a/libsoup/soup-message-headers.c +++ b/libsoup/soup-message-headers.c @@ -9,6 +9,7 @@ #include "soup-message-headers.h" #include "soup.h" +#include "soup-misc-private.h" /** * SECTION:soup-message-headers @@ -858,56 +859,40 @@ sort_ranges (gconstpointer a, gconstpointer b) return ra->start - rb->start; } -/** - * soup_message_headers_get_ranges: - * @hdrs: a #SoupMessageHeaders - * @total_length: the total_length of the response body - * @ranges: (out): return location for an array of #SoupRange - * @length: the length of the returned array - * - * Parses @hdrs's Range header and returns an array of the requested - * byte ranges. The returned array must be freed with - * soup_message_headers_free_ranges(). - * - * If @total_length is non-0, its value will be used to adjust the - * returned ranges to have explicit start and end values, and the - * returned ranges will be sorted and non-overlapping. If - * @total_length is 0, then some ranges may have an end value of -1, - * as described under #SoupRange, and some of the ranges may be - * redundant. - * - * Return value: %TRUE if @hdrs contained a "Range" header containing - * byte ranges which could be parsed, %FALSE otherwise (in which case - * @range and @length will not be set). - * - * Since: 2.26 - **/ -gboolean -soup_message_headers_get_ranges (SoupMessageHeaders *hdrs, - goffset total_length, - SoupRange **ranges, - int *length) +/* like soup_message_headers_get_ranges(), except it returns: + * SOUP_STATUS_OK if there is no Range or it should be ignored. + * SOUP_STATUS_PARTIAL_CONTENT if there is at least one satisfiable range. + * SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE if @check_satisfiable + * is %TRUE and the request is not satisfiable given @total_length. + */ +guint +soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + goffset total_length, + gboolean check_satisfiable, + SoupRange **ranges, + int *length) { const char *range = soup_message_headers_get_one (hdrs, "Range"); GSList *range_list, *r; GArray *array; char *spec, *end; int i; + guint status = SOUP_STATUS_OK; if (!range || strncmp (range, "bytes", 5) != 0) - return FALSE; + return status; range += 5; while (g_ascii_isspace (*range)) range++; if (*range++ != '=') - return FALSE; + return status; while (g_ascii_isspace (*range)) range++; range_list = soup_header_parse_list (range); if (!range_list) - return FALSE; + return status; array = g_array_new (FALSE, FALSE, sizeof (SoupRange)); for (r = range_list; r; r = r->next) { @@ -921,22 +906,34 @@ soup_message_headers_get_ranges (SoupMessageHeaders *hdrs, cur.start = g_ascii_strtoull (spec, &end, 10); if (*end == '-') end++; - if (*end) + if (*end) { cur.end = g_ascii_strtoull (end, &end, 10); - else + if (cur.end < cur.start) { + status = SOUP_STATUS_OK; + break; + } + } else cur.end = total_length - 1; } if (*end) { - g_array_free (array, TRUE); - soup_header_free_list (range_list); - return FALSE; + status = SOUP_STATUS_OK; + break; + } else if (check_satisfiable && cur.start >= total_length) { + if (status == SOUP_STATUS_OK) + status = SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE; + continue; } g_array_append_val (array, cur); + status = SOUP_STATUS_PARTIAL_CONTENT; } - soup_header_free_list (range_list); + if (status != SOUP_STATUS_PARTIAL_CONTENT) { + g_array_free (array, TRUE); + return status; + } + if (total_length) { g_array_sort (array, sort_ranges); for (i = 1; i < array->len; i++) { @@ -954,7 +951,46 @@ soup_message_headers_get_ranges (SoupMessageHeaders *hdrs, *length = array->len; g_array_free (array, FALSE); - return TRUE; + return SOUP_STATUS_PARTIAL_CONTENT; +} + +/** + * soup_message_headers_get_ranges: + * @hdrs: a #SoupMessageHeaders + * @total_length: the total_length of the response body + * @ranges: (out): return location for an array of #SoupRange + * @length: the length of the returned array + * + * Parses @hdrs's Range header and returns an array of the requested + * byte ranges. The returned array must be freed with + * soup_message_headers_free_ranges(). + * + * If @total_length is non-0, its value will be used to adjust the + * returned ranges to have explicit start and end values, and the + * returned ranges will be sorted and non-overlapping. If + * @total_length is 0, then some ranges may have an end value of -1, + * as described under #SoupRange, and some of the ranges may be + * redundant. + * + * Beware that even if given a @total_length, this function does not + * check that the ranges are satisfiable. + * + * Return value: %TRUE if @hdrs contained a syntactically-valid + * "Range" header, %FALSE otherwise (in which case @range and @length + * will not be set). + * + * Since: 2.26 + **/ +gboolean +soup_message_headers_get_ranges (SoupMessageHeaders *hdrs, + goffset total_length, + SoupRange **ranges, + int *length) +{ + guint status; + + status = soup_message_headers_get_ranges_internal (hdrs, total_length, FALSE, ranges, length); + return status == SOUP_STATUS_PARTIAL_CONTENT; } /** diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c index e85896b3..814ae7e5 100644 --- a/libsoup/soup-message-server-io.c +++ b/libsoup/soup-message-server-io.c @@ -119,6 +119,7 @@ handle_partial_get (SoupMessage *msg) SoupRange *ranges; int nranges; SoupBuffer *full_response; + guint status; /* Make sure the message is set up right for us to return a * partial response; it has to be a GET, the status must be @@ -137,9 +138,15 @@ handle_partial_get (SoupMessage *msg) /* Oh, and there has to have been a valid Range header on the * request, of course. */ - if (!soup_message_headers_get_ranges (msg->request_headers, - msg->response_body->length, - &ranges, &nranges)) + status = soup_message_headers_get_ranges_internal (msg->request_headers, + msg->response_body->length, + TRUE, + &ranges, &nranges); + if (status == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { + soup_message_set_status (msg, status); + soup_message_body_truncate (msg->response_body); + return; + } else if (status != SOUP_STATUS_PARTIAL_CONTENT) return; full_response = soup_message_body_flatten (msg->response_body); diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index d03bc77f..02768706 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -8,6 +8,7 @@ #define SOUP_MISC_PRIVATE_H 1 #include "soup-socket.h" +#include "soup-message-headers.h" char *uri_decoded_copy (const char *str, int length, int *decoded_length); char *soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, @@ -47,4 +48,10 @@ GSource *soup_add_completion_reffed (GMainContext *async_context, GSourceFunc function, gpointer data); +guint soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, + goffset total_length, + gboolean check_satisfiable, + SoupRange **ranges, + int *length); + #endif /* SOUP_MISC_PRIVATE_H */ diff --git a/tests/range-test.c b/tests/range-test.c index e7d01d21..00b8567d 100644 --- a/tests/range-test.c +++ b/tests/range-test.c @@ -78,7 +78,7 @@ check_part (SoupMessageHeaders *headers, const char *body, gsize body_len, static void do_single_range (SoupSession *session, SoupMessage *msg, - int start, int end) + int start, int end, gboolean succeed) { const char *content_type; @@ -87,11 +87,31 @@ do_single_range (SoupSession *session, SoupMessage *msg, soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) { - debug_printf (1, " Unexpected status %d %s\n", - msg->status_code, msg->reason_phrase); + if (succeed) { + if (msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) { + debug_printf (1, " Unexpected status %d %s\n", + msg->status_code, msg->reason_phrase); + g_object_unref (msg); + errors++; + return; + } + } else { + if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { + debug_printf (1, " Got expected %d %s\n", + msg->status_code, msg->reason_phrase); + } else { + const char *content_range; + + debug_printf (1, " Unexpected status %d %s\n", + msg->status_code, msg->reason_phrase); + content_range = soup_message_headers_get_one (msg->response_headers, + "Content-Range"); + if (content_range) + debug_printf (1, " Content-Range: %s\n", content_range); + errors++; + } + g_object_unref (msg); - errors++; return; } @@ -111,13 +131,13 @@ do_single_range (SoupSession *session, SoupMessage *msg, static void request_single_range (SoupSession *session, const char *uri, - int start, int end) + int start, int end, gboolean succeed) { SoupMessage *msg; msg = soup_message_new ("GET", uri); soup_message_headers_set_range (msg->request_headers, start, end); - do_single_range (session, msg, start, end); + do_single_range (session, msg, start, end, succeed); } static void @@ -198,7 +218,8 @@ request_double_range (SoupSession *session, const char *uri, if (expected_return_ranges == 1) { do_single_range (session, msg, MIN (first_start, second_start), - MAX (first_end, second_end)); + MAX (first_end, second_end), + TRUE); } else do_multi_range (session, msg, expected_return_ranges); } @@ -225,11 +246,33 @@ request_triple_range (SoupSession *session, const char *uri, if (expected_return_ranges == 1) { do_single_range (session, msg, MIN (first_start, MIN (second_start, third_start)), - MAX (first_end, MAX (second_end, third_end))); + MAX (first_end, MAX (second_end, third_end)), + TRUE); } else do_multi_range (session, msg, expected_return_ranges); } +static void +request_semi_invalid_range (SoupSession *session, const char *uri, + int first_good_start, int first_good_end, + int bad_start, int bad_end, + int second_good_start, int second_good_end) +{ + SoupMessage *msg; + SoupRange ranges[3]; + + msg = soup_message_new ("GET", uri); + ranges[0].start = first_good_start; + ranges[0].end = first_good_end; + ranges[1].start = bad_start; + ranges[1].end = bad_end; + ranges[2].start = second_good_start; + ranges[2].end = second_good_end; + soup_message_headers_set_ranges (msg->request_headers, ranges, 3); + + do_multi_range (session, msg, 2); +} + static void do_range_test (SoupSession *session, const char *uri, gboolean expect_coalesce, gboolean expect_partial_coalesce) @@ -258,7 +301,8 @@ do_range_test (SoupSession *session, const char *uri, /* A: 0, simple request */ debug_printf (1, "Requesting %d-%d\n", 0 * twelfths, 1 * twelfths); request_single_range (session, uri, - 0 * twelfths, 1 * twelfths); + 0 * twelfths, 1 * twelfths, + TRUE); /* B: 11, end-relative request. These two are mostly redundant * in terms of data coverage, but they may still catch @@ -266,10 +310,12 @@ do_range_test (SoupSession *session, const char *uri, */ debug_printf (1, "Requesting %d-\n", 11 * twelfths); request_single_range (session, uri, - 11 * twelfths, -1); + 11 * twelfths, -1, + TRUE); debug_printf (1, "Requesting -%d\n", 1 * twelfths); request_single_range (session, uri, - -1 * twelfths, -1); + -1 * twelfths, -1, + TRUE); /* C: 2 and 5 */ debug_printf (1, "Requesting %d-%d,%d-%d\n", @@ -318,6 +364,21 @@ do_range_test (SoupSession *session, const char *uri, debug_printf (1, "\nfull_response and test_response don't match\n"); errors++; } + + debug_printf (1, "Requesting (invalid) %d-%d\n", + (int) full_response->length + 1, + (int) full_response->length + 100); + request_single_range (session, uri, + full_response->length + 1, full_response->length + 100, + FALSE); + + debug_printf (1, "Requesting (semi-invalid) 1-10,%d-%d,20-30\n", + (int) full_response->length + 1, + (int) full_response->length + 100); + request_semi_invalid_range (session, uri, + 1, 10, + full_response->length + 1, full_response->length + 100, + 20, 30); } static void -- cgit v1.2.1 From 761ab8aac93e85cadc1c32e1abbd9b87060a65f7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 18 Aug 2013 11:23:26 -0400 Subject: get: fix to not send the request twice --- examples/get.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/get.c b/examples/get.c index a74991dc..a8888d49 100644 --- a/examples/get.c +++ b/examples/get.c @@ -35,9 +35,8 @@ get_url (const char *url) g_object_ref (msg); soup_session_queue_message (session, msg, finished, loop); g_main_loop_run (loop); - } - - soup_session_send_message (session, msg); + } else + soup_session_send_message (session, msg); name = soup_message_get_uri (msg)->path; -- cgit v1.2.1 From e3705dc057a0deb80a58f93351f145c267349c4d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 19 Aug 2013 11:05:19 -0400 Subject: soup-message-headers: clarify that SoupServer has built-in Range handling --- libsoup/soup-message-headers.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c index f488c1c0..28ecaeda 100644 --- a/libsoup/soup-message-headers.c +++ b/libsoup/soup-message-headers.c @@ -975,6 +975,22 @@ soup_message_headers_get_ranges_internal (SoupMessageHeaders *hdrs, * Beware that even if given a @total_length, this function does not * check that the ranges are satisfiable. * + * + * #SoupServer has built-in handling for range requests. If your + * server handler returns a %SOUP_STATUS_OK response containing the + * complete response body (rather than pausing the message and + * returning some of the response body later), and there is a Range + * header in the request, then libsoup will automatically convert the + * response to a %SOUP_STATUS_PARTIAL_CONTENT response containing only + * the range(s) requested by the client. + * + * The only time you need to process the Range header yourself is if + * either you need to stream the response body rather than returning + * it all at once, or you do not already have the complete response + * body available, and only want to generate the parts that were + * actually requested by the client. + * + * * Return value: %TRUE if @hdrs contained a syntactically-valid * "Range" header, %FALSE otherwise (in which case @range and @length * will not be set). @@ -1140,6 +1156,12 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs, * (Note that @total_length is the total length of the entire resource * that this is a range of, not simply @end - @start + 1.) * + * + * #SoupServer has built-in handling for range requests, and you do + * not normally need to call this function youself. See + * soup_message_headers_get_range() for more details. + * + * * Since: 2.26 **/ void -- cgit v1.2.1 From fbc47c33a98e5b3ff4d38daab348d70c7aafa042 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 19 Aug 2013 13:26:19 -0400 Subject: soup-address: handle IPv6 literals with scope IDs Use GNetworkAddress to try to parse IPv6 addresses with scope IDs, rather than just letting the scope ID get dropped. Part of https://bugzilla.gnome.org/show_bug.cgi?id=669724 --- libsoup/soup-address.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index e2a06912..d698234e 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -561,6 +561,59 @@ soup_address_get_port (SoupAddress *addr) } +/* Tries to resolve priv->name as an IP address, possibly including an + * IPv6 scope id. + */ +static void +maybe_resolve_ip (SoupAddress *addr) +{ + SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr); + const char *pct, *ip; + char *tmp = NULL; + GSocketConnectable *gaddr; + GSocketAddressEnumerator *sa_enum; + GSocketAddress *saddr; + + if (priv->sockaddr || !priv->name) + return; + + pct = strchr (priv->name, '%'); + if (pct) + ip = tmp = g_strndup (priv->name, pct - priv->name); + else + ip = priv->name; + + if (!g_hostname_is_ip_address (ip)) { + g_free (tmp); + return; + } + g_free (tmp); + + gaddr = g_network_address_new (priv->name, priv->port); + if (!gaddr) + return; + + sa_enum = g_socket_connectable_enumerate (gaddr); + saddr = g_socket_address_enumerator_next (sa_enum, NULL, NULL); + if (saddr) { + priv->n_addrs = 1; + priv->sockaddr = g_new (struct sockaddr_storage, 1); + if (!g_socket_address_to_native (saddr, priv->sockaddr, + sizeof (struct sockaddr_storage), + NULL)) { + /* can't happen: We know the address format is supported + * and the buffer is large enough + */ + g_warn_if_reached (); + } + g_object_unref (saddr); + } + + g_object_unref (sa_enum); + g_object_unref (gaddr); +} + + static guint update_addrs (SoupAddress *addr, GList *addrs, GError *error) { @@ -762,6 +815,8 @@ soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context, * not intended to be thread-safe. */ + if (priv->name && !priv->sockaddr) + maybe_resolve_ip (addr); if (priv->name && priv->sockaddr && !callback) return; @@ -822,6 +877,10 @@ resolve_sync_internal (SoupAddress *addr, GCancellable *cancellable, GError **er * blocking op, and then re-lock it to modify @addr. */ g_mutex_lock (&priv->lock); + + if (priv->name && !priv->sockaddr) + maybe_resolve_ip (addr); + if (!priv->sockaddr) { GList *addrs; @@ -847,6 +906,7 @@ resolve_sync_internal (SoupAddress *addr, GCancellable *cancellable, GError **er g_free (name); } else status = SOUP_STATUS_OK; + g_mutex_unlock (&priv->lock); if (my_err) -- cgit v1.2.1 From fe3735f81a8e1bfa5242904a94c30217a5101cbc Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 19 Aug 2013 13:39:51 -0400 Subject: soup-address: fix a GMainContext bug SoupAddress's GSocketAddressEnumerator implementation was passing the wrong GMainContext to soup_address_resolve_async(), although it only ended up affecting the address-is-already-resolved case. Fix this. Also, remove the async_lookups list from SoupAddressPrivate, and just make multiple calls to the resolver if there are multiple calls to soup_address_resolve_async() at once, since that code didn't handle different GMainContexts correctly. --- libsoup/soup-address.c | 111 +++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 63 deletions(-) diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index d698234e..b2d1647a 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -52,7 +52,6 @@ typedef struct { const char *protocol; GMutex lock; - GSList *async_lookups; } SoupAddressPrivate; #define SOUP_ADDRESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_ADDRESS, SoupAddressPrivate)) @@ -674,55 +673,47 @@ update_name (SoupAddress *addr, const char *name, GError *error) } typedef struct { + SoupAddress *addr; SoupAddressCallback callback; gpointer callback_data; } SoupAddressResolveAsyncData; static void -complete_resolve_async (SoupAddress *addr, guint status) +complete_resolve_async (SoupAddressResolveAsyncData *res_data, guint status) { - SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr); - SoupAddressResolveAsyncData *res_data; - GSList *lookups, *l; GSource *current_source; GMainContext *current_context; - lookups = priv->async_lookups; - priv->async_lookups = NULL; - - /* Awful hack; to make soup_socket_connect_async() with an - * non-default async_context work correctly, we need to ensure - * that the non-default context (which we're now running in) - * is the thread-default when the callbacks are run... - */ - current_source = g_main_current_source (); - if (current_source && !g_source_is_destroyed (current_source)) - current_context = g_source_get_context (current_source); - else - current_context = NULL; - g_main_context_push_thread_default (current_context); + if (res_data->callback) { + /* Awful hack; to make soup_socket_connect_async() + * with an non-default async_context work correctly, + * we need to ensure that the non-default context + * (which we're now running in) is the thread-default + * when the callbacks are run... + */ + current_source = g_main_current_source (); + if (current_source && !g_source_is_destroyed (current_source)) + current_context = g_source_get_context (current_source); + else + current_context = NULL; + g_main_context_push_thread_default (current_context); - for (l = lookups; l; l = l->next) { - res_data = l->data; + res_data->callback (res_data->addr, status, + res_data->callback_data); - if (res_data->callback) { - res_data->callback (addr, status, - res_data->callback_data); - } - g_slice_free (SoupAddressResolveAsyncData, res_data); + g_main_context_pop_thread_default (current_context); } - g_slist_free (lookups); - g_main_context_pop_thread_default (current_context); - - g_object_unref (addr); + g_object_unref (res_data->addr); + g_slice_free (SoupAddressResolveAsyncData, res_data); } static void lookup_resolved (GObject *source, GAsyncResult *result, gpointer user_data) { GResolver *resolver = G_RESOLVER (source); - SoupAddress *addr = user_data; + SoupAddressResolveAsyncData *res_data = user_data; + SoupAddress *addr = res_data->addr; SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr); GError *error = NULL; guint status; @@ -748,7 +739,7 @@ lookup_resolved (GObject *source, GAsyncResult *result, gpointer user_data) g_object_ref (addr); g_object_set_data (G_OBJECT (addr), "async-resolved-error", error); - complete_resolve_async (addr, status); + complete_resolve_async (res_data, status); g_object_set_data (G_OBJECT (addr), "async-resolved-error", NULL); g_object_unref (addr); @@ -757,9 +748,9 @@ lookup_resolved (GObject *source, GAsyncResult *result, gpointer user_data) } static gboolean -idle_complete_resolve (gpointer addr) +idle_complete_resolve (gpointer res_data) { - complete_resolve_async (addr, SOUP_STATUS_OK); + complete_resolve_async (res_data, SOUP_STATUS_OK); return FALSE; } @@ -805,7 +796,6 @@ soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context, SoupAddressPrivate *priv; SoupAddressResolveAsyncData *res_data; GResolver *resolver; - gboolean already_started; g_return_if_fail (SOUP_IS_ADDRESS (addr)); priv = SOUP_ADDRESS_GET_PRIVATE (addr); @@ -821,43 +811,37 @@ soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context, return; res_data = g_slice_new0 (SoupAddressResolveAsyncData); + res_data->addr = g_object_ref (addr); res_data->callback = callback; res_data->callback_data = user_data; - already_started = priv->async_lookups != NULL; - priv->async_lookups = g_slist_prepend (priv->async_lookups, res_data); - - if (already_started) - return; - - g_object_ref (addr); - - if (priv->name && priv->sockaddr) { - soup_add_completion (async_context, idle_complete_resolve, addr); - return; - } - - resolver = g_resolver_get_default (); if (async_context) g_main_context_push_thread_default (async_context); - if (priv->name) { - g_resolver_lookup_by_name_async (resolver, priv->name, - cancellable, - lookup_resolved, addr); - } else { - GInetAddress *gia; + if (priv->name && priv->sockaddr) + soup_add_completion (async_context, idle_complete_resolve, res_data); + else { + resolver = g_resolver_get_default (); + + if (priv->name) { + g_resolver_lookup_by_name_async (resolver, priv->name, + cancellable, + lookup_resolved, res_data); + } else { + GInetAddress *gia; + + gia = soup_address_make_inet_address (addr); + g_resolver_lookup_by_address_async (resolver, gia, + cancellable, + lookup_resolved, res_data); + g_object_unref (gia); + } - gia = soup_address_make_inet_address (addr); - g_resolver_lookup_by_address_async (resolver, gia, - cancellable, - lookup_resolved, addr); - g_object_unref (gia); + g_object_unref (resolver); } if (async_context) g_main_context_pop_thread_default (async_context); - g_object_unref (resolver); } static guint @@ -1205,8 +1189,9 @@ soup_address_address_enumerator_next_async (GSocketAddressEnumerator *enumerato task = g_task_new (enumerator, cancellable, callback, user_data); if (!priv->sockaddr) { - soup_address_resolve_async (addr_enum->addr, NULL, cancellable, - got_addresses, task); + soup_address_resolve_async (addr_enum->addr, + g_main_context_get_thread_default (), + cancellable, got_addresses, task); } else { g_task_return_pointer (task, next_address (addr_enum), g_object_unref); g_object_unref (task); -- cgit v1.2.1 From e43eef9705634317a7af7d1217793925b1b13ab9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 19 Aug 2013 15:44:12 -0400 Subject: More IPv6 scope ID fixes Don't include the scope ID in the "Host" header. Make SoupURI correctly parse both correct and incorrect scope IDs, and add checks for that in tests/uri-parsing. --- libsoup/soup-message-client-io.c | 2 +- libsoup/soup-uri.c | 21 ++++++++++++++++++--- tests/uri-parsing.c | 8 ++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c index 0d3df282..1d96729d 100644 --- a/libsoup/soup-message-client-io.c +++ b/libsoup/soup-message-client-io.c @@ -83,7 +83,7 @@ get_request_headers (SoupMessage *msg, GString *header, const char *name, *value; if (strchr (uri->host, ':')) - uri_host = g_strdup_printf ("[%s]", uri->host); + uri_host = g_strdup_printf ("[%.*s]", (int) strcspn (uri->host, "%"), uri->host); else if (g_hostname_is_non_ascii (uri->host)) uri_host = g_hostname_to_ascii (uri->host); else diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 16098f69..6e3d220b 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -308,6 +308,8 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) /* Find host and port. */ if (*uri_string == '[') { + const char *pct; + uri_string++; hostend = strchr (uri_string, ']'); if (!hostend || hostend > path) { @@ -318,13 +320,18 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) colon = hostend + 1; else colon = NULL; + + pct = memchr (uri_string, '%', hostend - uri_string); + if (!pct || (pct[1] == '2' && pct[2] == '5')) + uri->host = uri_decoded_copy (uri_string, hostend - uri_string, NULL); + else + uri->host = g_strndup (uri_string, hostend - uri_string); } else { colon = memchr (uri_string, ':', path - uri_string); hostend = colon ? colon : path; + uri->host = uri_decoded_copy (uri_string, hostend - uri_string, NULL); } - uri->host = uri_decoded_copy (uri_string, hostend - uri_string, NULL); - if (colon && colon != path - 1) { char *portend; uri->port = strtoul (colon + 1, &portend, 10); @@ -513,8 +520,16 @@ soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, g_string_append_c (str, '@'); } if (strchr (uri->host, ':')) { + const char *pct; + g_string_append_c (str, '['); - g_string_append (str, uri->host); + pct = strchr (uri->host, '%'); + if (pct) { + g_string_append_printf (str, "%.*s%%25%s", + (int) (pct - uri->host), + uri->host, pct + 1); + } else + g_string_append (str, uri->host); g_string_append_c (str, ']'); } else append_uri_encoded (str, uri->host, ":/"); diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index d1bba4e1..b4f495b6 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -144,6 +144,14 @@ static struct { { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, { "+http://host/path", NULL, { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, + + /* IPv6 scope ID parsing (both correct and incorrect) */ + { "http://[fe80::dead:beef%em1]/", "http://[fe80::dead:beef%25em1]/", + { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } }, + { "http://[fe80::dead:beef%25em1]/", "http://[fe80::dead:beef%25em1]/", + { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } }, + { "http://[fe80::dead:beef%10]/", "http://[fe80::dead:beef%2510]/", + { "http", NULL, NULL, "fe80::dead:beef%10", 80, "/", NULL, NULL } } }; static int num_abs_tests = G_N_ELEMENTS(abs_tests); -- cgit v1.2.1 From 9eb7ad6ab119d17020e56e6606d6720ccaf1ba1f Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 19 Aug 2013 16:51:55 -0400 Subject: 2.43.90 --- NEWS | 11 +++++++++++ configure.ac | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a9f337e0..befc5fc8 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,14 @@ +Changes in libsoup from 2.43.5 to 2.43.90: + + * Fixed the handling of unsatisfiable range requests in + SoupServer [pointed out on mailing list, Dan]. Also, added + more documentation clarifying that you don't need to handle + range requests yourself in many cases. + + * Fixed the handling of IPv6 address literals with scope IDs. + (Requires the latest glib as well for the complete fix.) + [#669724, Dan] + Changes in libsoup from 2.43.4 to 2.43.5: * SoupProxyURIResolver is now deprecated in favor of the diff --git a/configure.ac b/configure.ac index 570b3b55..742e5435 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [43]) -m4_define([soup_micro_version], [5]) +m4_define([soup_micro_version], [90]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 164e49a27eeeedca800f466b0b14a4e61a162007 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 23 Aug 2013 13:34:37 -0400 Subject: cache-test: fix race condition The refcounting test had a race condition. Fix it by just waiting for the stream to be destroyed, rather than asserting it already has been. https://bugzilla.gnome.org/show_bug.cgi?id=698305 --- tests/cache-test.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/tests/cache-test.c b/tests/cache-test.c index 34389f8e..a8d01ebf 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -571,6 +571,19 @@ do_cancel_test (SoupURI *base_uri) g_free (body2); } +static gboolean +unref_stream (gpointer stream) +{ + g_object_unref (stream); + return FALSE; +} + +static void +base_stream_unreffed (gpointer loop, GObject *ex_base_stream) +{ + g_main_loop_quit (loop); +} + static void do_refcounting_test (SoupURI *base_uri) { @@ -582,6 +595,7 @@ do_refcounting_test (SoupURI *base_uri) SoupURI *uri; GError *error = NULL; guint flags; + GMainLoop *loop; debug_printf (1, "Cache refcounting tests\n"); @@ -609,19 +623,16 @@ do_refcounting_test (SoupURI *base_uri) g_object_unref (req); return; } + g_object_unref (req); base_stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream)); - g_object_add_weak_pointer (G_OBJECT (base_stream), (gpointer *)&base_stream); - - g_clear_object (&req); - g_object_unref (stream); debug_printf (1, " Checking that the base stream is properly unref'ed\n"); - if (base_stream) { - errors++; - debug_printf (1, "leaked GInputStream!\n"); - g_object_remove_weak_pointer (G_OBJECT (base_stream), (gpointer *)&base_stream); - } + loop = g_main_loop_new (NULL, FALSE); + g_object_weak_ref (G_OBJECT (base_stream), base_stream_unreffed, loop); + g_idle_add (unref_stream, stream); + g_main_loop_run (loop); + g_main_loop_unref (loop); soup_cache_flush ((SoupCache *)soup_session_get_feature (session, SOUP_TYPE_CACHE)); -- cgit v1.2.1 From 0ea86f566b7d526c8328c7c602ae1be8cda8dd68 Mon Sep 17 00:00:00 2001 From: "Andre Moreira Magalhaes (andrunko)" Date: Mon, 19 Aug 2013 18:29:33 -0300 Subject: Also copy disabled features when copying messages. https://bugzilla.gnome.org/show_bug.cgi?id=706338 --- libsoup/soup-cache.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c index 815d2f71..c17e537c 100644 --- a/libsoup/soup-cache.c +++ b/libsoup/soup-cache.c @@ -38,6 +38,7 @@ #include "soup-content-processor.h" #include "soup-message-private.h" #include "soup.h" +#include "soup-message-private.h" /** * SECTION:soup-cache @@ -1345,6 +1346,8 @@ soup_cache_generate_conditional_request (SoupCache *cache, SoupMessage *original SoupURI *uri; SoupCacheEntry *entry; const char *last_modified, *etag; + SoupMessagePrivate *origpriv; + GSList *f; g_return_val_if_fail (SOUP_IS_CACHE (cache), NULL); g_return_val_if_fail (SOUP_IS_MESSAGE (original), NULL); @@ -1370,6 +1373,10 @@ soup_cache_generate_conditional_request (SoupCache *cache, SoupMessage *original (SoupMessageHeadersForeachFunc)copy_headers, msg->request_headers); + origpriv = SOUP_MESSAGE_GET_PRIVATE (original); + for (f = origpriv->disabled_features; f; f = f->next) + soup_message_disable_feature (msg, (GType) GPOINTER_TO_SIZE (f->data)); + if (last_modified) soup_message_headers_append (msg->request_headers, "If-Modified-Since", -- cgit v1.2.1 From 74b6fc3525a04432495cb2db5d6ce62c5a90c5a6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 25 Aug 2013 09:40:05 -0400 Subject: soup_cookie_new: clarify the interpretation of @domain https://bugzilla.gnome.org/show_bug.cgi?id=691840 --- libsoup/soup-cookie.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsoup/soup-cookie.c b/libsoup/soup-cookie.c index 731a4a5a..3f7dcc38 100755 --- a/libsoup/soup-cookie.c +++ b/libsoup/soup-cookie.c @@ -358,6 +358,10 @@ cookie_new_internal (const char *name, const char *value, * soup_cookie_set_secure() and soup_cookie_set_http_only() if you * need to set those attributes on the returned cookie.) * + * If @domain starts with ".", that indicates a domain (which matches + * the string after the ".", or any hostname that has @domain as a + * suffix). Otherwise, it is a hostname and must match exactly. + * * @max_age is used to set the "expires" attribute on the cookie; pass * -1 to not include the attribute (indicating that the cookie expires * with the current session), 0 for an already-expired cookie, or a -- cgit v1.2.1 From a7ce33ef264e0794fa1e406a879607018cfc6597 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 25 Aug 2013 10:29:41 -0400 Subject: soup-body-output-stream: fix closing of chunked stream When closing a chunked stream, we need to write the final 0-length chunk. However, we can only do that if we successfully wrote the previous chunk. https://bugzilla.gnome.org/show_bug.cgi?id=703297 --- libsoup/soup-body-output-stream.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-body-output-stream.c b/libsoup/soup-body-output-stream.c index a1419754..03353ef5 100644 --- a/libsoup/soup-body-output-stream.c +++ b/libsoup/soup-body-output-stream.c @@ -231,7 +231,8 @@ soup_body_output_stream_close_fn (GOutputStream *stream, { SoupBodyOutputStream *bostream = SOUP_BODY_OUTPUT_STREAM (stream); - if (bostream->priv->encoding == SOUP_ENCODING_CHUNKED) { + if (bostream->priv->encoding == SOUP_ENCODING_CHUNKED && + bostream->priv->chunked_state == SOUP_BODY_OUTPUT_STREAM_STATE_CHUNK_SIZE) { if (soup_body_output_stream_write_chunked (bostream, NULL, 0, TRUE, cancellable, error) == -1) return FALSE; } -- cgit v1.2.1 From 6d149d8595d93c706c816a22acaffef37ea34ca5 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 25 Aug 2013 16:45:21 -0400 Subject: soup-filter-input-stream: fix read_until() with subclasses If doing a read_line()/read_until() in a subclass, we need to use the subclass's read implementation rather than just going directly to the base stream. --- libsoup/soup-filter-input-stream.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/libsoup/soup-filter-input-stream.c b/libsoup/soup-filter-input-stream.c index 3b76386b..8067b882 100644 --- a/libsoup/soup-filter-input-stream.c +++ b/libsoup/soup-filter-input-stream.c @@ -23,6 +23,7 @@ struct _SoupFilterInputStreamPrivate { GByteArray *buf; gboolean need_more; + gboolean in_read_until; }; static void soup_filter_input_stream_pollable_init (GPollableInputStreamInterface *pollable_interface, gpointer interface_data); @@ -79,8 +80,10 @@ soup_filter_input_stream_read_fn (GInputStream *stream, { SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); - fstream->priv->need_more = FALSE; - if (fstream->priv->buf) { + if (!fstream->priv->in_read_until) + fstream->priv->need_more = FALSE; + + if (fstream->priv->buf && !fstream->priv->in_read_until) { return read_from_buf (fstream, buffer, count); } else { return g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, @@ -108,8 +111,10 @@ soup_filter_input_stream_read_nonblocking (GPollableInputStream *stream, { SoupFilterInputStream *fstream = SOUP_FILTER_INPUT_STREAM (stream); - fstream->priv->need_more = FALSE; - if (fstream->priv->buf) { + if (!fstream->priv->in_read_until) + fstream->priv->need_more = FALSE; + + if (fstream->priv->buf && !fstream->priv->in_read_until) { return read_from_buf (fstream, buffer, count); } else { return g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, @@ -217,10 +222,12 @@ soup_filter_input_stream_read_until (SoupFilterInputStream *fstream, g_byte_array_set_size (fstream->priv->buf, length); buf = fstream->priv->buf->data; - nread = g_pollable_stream_read (G_FILTER_INPUT_STREAM (fstream)->base_stream, + fstream->priv->in_read_until = TRUE; + nread = g_pollable_stream_read (G_INPUT_STREAM (fstream), buf + prev_len, length - prev_len, blocking, cancellable, &my_error); + fstream->priv->in_read_until = FALSE; if (nread <= 0) { if (prev_len) fstream->priv->buf->len = prev_len; -- cgit v1.2.1 From bc11dd3f7399faa09a6b149ccc4afccd1b5445b6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 25 Aug 2013 16:46:23 -0400 Subject: chunk-io-test: new test of the chunked I/O read/write streams --- tests/Makefile.am | 1 + tests/chunk-io-test.c | 654 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 655 insertions(+) create mode 100644 tests/chunk-io-test.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 22c4a851..43347fe2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -12,6 +12,7 @@ TESTS = \ auth-test \ cache-test \ chunk-test \ + chunk-io-test \ coding-test \ connection-test \ context-test \ diff --git a/tests/chunk-io-test.c b/tests/chunk-io-test.c new file mode 100644 index 00000000..7606d41b --- /dev/null +++ b/tests/chunk-io-test.c @@ -0,0 +1,654 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2013 Red Hat, Inc. + */ + +#include "test-utils.h" + +static void +force_io_streams_init (void) +{ + SoupServer *server; + SoupSession *session; + guint port; + SoupURI *base_uri; + SoupMessage *msg; + + /* Poke libsoup enough to cause SoupBodyInputStream and + * SoupBodyOutputStream to get defined, so we can find them + * via g_type_from_name() later. + */ + + server = soup_test_server_new (TRUE); + port = soup_server_get_port (server); + + base_uri = soup_uri_new ("http://127.0.0.1"); + soup_uri_set_port (base_uri, port); + + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + msg = soup_message_new_from_uri ("POST", base_uri); + soup_session_send_message (session, msg); + g_object_unref (msg); + soup_test_session_abort_unref (session); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); +} + +typedef struct { + GFilterInputStream grandparent; + + gpointer *soup_filter_input_stream_private; + + gboolean is_readable; +} SlowInputStream; + +typedef struct { + GFilterInputStreamClass grandparent; +} SlowInputStreamClass; + +GType slow_input_stream_get_type (void); +static void slow_pollable_input_stream_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SlowInputStream, slow_input_stream, + g_type_from_name ("SoupFilterInputStream"), + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM, slow_pollable_input_stream_init); + ) + +static void +slow_input_stream_init (SlowInputStream *sis) +{ +} + +static gssize +slow_input_stream_read (GInputStream *stream, + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return g_input_stream_read (G_FILTER_INPUT_STREAM (stream)->base_stream, + buffer, 1, cancellable, error); +} + +static void +slow_input_stream_class_init (SlowInputStreamClass *sisclass) +{ + GInputStreamClass *input_stream_class = G_INPUT_STREAM_CLASS (sisclass); + + input_stream_class->read_fn = slow_input_stream_read; +} + +static gboolean +slow_input_stream_is_readable (GPollableInputStream *stream) +{ + return ((SlowInputStream *)stream)->is_readable; +} + +static gssize +slow_input_stream_read_nonblocking (GPollableInputStream *stream, + void *buffer, + gsize count, + GError **error) +{ + if (((SlowInputStream *)stream)->is_readable) { + ((SlowInputStream *)stream)->is_readable = FALSE; + return slow_input_stream_read (G_INPUT_STREAM (stream), buffer, count, + NULL, error); + } else { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, + "would block"); + return -1; + } +} + +static GSource * +slow_input_stream_create_source (GPollableInputStream *stream, + GCancellable *cancellable) +{ + GSource *base_source, *pollable_source; + + ((SlowInputStream *)stream)->is_readable = TRUE; + base_source = g_timeout_source_new (0); + g_source_set_dummy_callback (base_source); + + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +slow_pollable_input_stream_init (GPollableInputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_readable = slow_input_stream_is_readable; + pollable_interface->read_nonblocking = slow_input_stream_read_nonblocking; + pollable_interface->create_source = slow_input_stream_create_source; +} + +typedef struct { + GFilterOutputStream parent; + + gboolean is_writable; +} SlowOutputStream; + +typedef struct { + GFilterOutputStreamClass parent; +} SlowOutputStreamClass; + +GType slow_output_stream_get_type (void); + +static void slow_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (SlowOutputStream, slow_output_stream, + g_type_from_name ("GFilterOutputStream"), + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, slow_pollable_output_stream_init); + ) + +static void +slow_output_stream_init (SlowOutputStream *sis) +{ +} + +static gssize +slow_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return g_output_stream_write (G_FILTER_OUTPUT_STREAM (stream)->base_stream, + buffer, 1, cancellable, error); +} + +static void +slow_output_stream_class_init (SlowOutputStreamClass *sisclass) +{ + GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (sisclass); + + output_stream_class->write_fn = slow_output_stream_write; +} + +static gboolean +slow_output_stream_is_writable (GPollableOutputStream *stream) +{ + return ((SlowOutputStream *)stream)->is_writable; +} + +static gssize +slow_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize count, + GError **error) +{ + if (((SlowOutputStream *)stream)->is_writable) { + ((SlowOutputStream *)stream)->is_writable = FALSE; + return slow_output_stream_write (G_OUTPUT_STREAM (stream), buffer, count, + NULL, error); + } else { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, + "would block"); + return -1; + } +} + +static GSource * +slow_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable) +{ + GSource *base_source, *pollable_source; + + ((SlowOutputStream *)stream)->is_writable = TRUE; + base_source = g_timeout_source_new (0); + g_source_set_dummy_callback (base_source); + + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +slow_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_writable = slow_output_stream_is_writable; + pollable_interface->write_nonblocking = slow_output_stream_write_nonblocking; + pollable_interface->create_source = slow_output_stream_create_source; +} + +typedef struct { + GFilterOutputStream parent; + + gboolean is_broken; +} BreakingOutputStream; + +typedef struct { + GFilterOutputStreamClass parent; +} BreakingOutputStreamClass; + +GType breaking_output_stream_get_type (void); + +static void breaking_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data); + +G_DEFINE_TYPE_WITH_CODE (BreakingOutputStream, breaking_output_stream, + g_type_from_name ("GFilterOutputStream"), + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, breaking_pollable_output_stream_init); + ) + +static void +breaking_output_stream_init (BreakingOutputStream *sis) +{ +} + +static gssize +breaking_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + if (((BreakingOutputStream *)stream)->is_broken) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "failed"); + return -1; + } + + if (count > 128) { + ((BreakingOutputStream *)stream)->is_broken = TRUE; + count /= 2; + } + return g_output_stream_write (G_FILTER_OUTPUT_STREAM (stream)->base_stream, + buffer, count, cancellable, error); +} + +static void +breaking_output_stream_class_init (BreakingOutputStreamClass *sisclass) +{ + GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (sisclass); + + output_stream_class->write_fn = breaking_output_stream_write; +} + +static gboolean +breaking_output_stream_is_writable (GPollableOutputStream *stream) +{ + return TRUE; +} + +static gssize +breaking_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize count, + GError **error) +{ + if (((BreakingOutputStream *)stream)->is_broken) { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "failed"); + return -1; + } + + if (count > 128) { + ((BreakingOutputStream *)stream)->is_broken = TRUE; + count /= 2; + } + return g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (G_FILTER_OUTPUT_STREAM (stream)->base_stream), + buffer, count, NULL, error); +} + +static GSource * +breaking_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable) +{ + GSource *base_source, *pollable_source; + + base_source = g_timeout_source_new (0); + g_source_set_dummy_callback (base_source); + + pollable_source = g_pollable_source_new (G_OBJECT (stream)); + g_source_add_child_source (pollable_source, base_source); + g_source_unref (base_source); + + return pollable_source; +} + +static void +breaking_pollable_output_stream_init (GPollableOutputStreamInterface *pollable_interface, + gpointer interface_data) +{ + pollable_interface->is_writable = breaking_output_stream_is_writable; + pollable_interface->write_nonblocking = breaking_output_stream_write_nonblocking; + pollable_interface->create_source = breaking_output_stream_create_source; +} + +#define CHUNK_SIZE 1024 + +static GString * +chunkify (const char *str, gsize length) +{ + GString *gstr; + int i, size; + + gstr = g_string_new (NULL); + for (i = 0; i < length; i += CHUNK_SIZE) { + size = MIN (CHUNK_SIZE, length - i); + g_string_append_printf (gstr, "%x\r\n", size); + g_string_append_len (gstr, str + i, size); + g_string_append (gstr, "\r\n"); + } + g_string_append (gstr, "0\r\n\r\n"); + + return gstr; +} + +static void +do_io_tests (void) +{ + GInputStream *imem, *islow, *in; + GOutputStream *omem, *oslow, *out; + char *raw_contents, *buf; + gsize raw_length; + GString *chunkified; + GError *error = NULL; + gssize nread, nwrote, total; + gssize chunk_length, chunk_total; + + debug_printf (1, "\nI/O tests\n"); + + if (!g_file_get_contents (SRCDIR "/index.txt", &raw_contents, &raw_length, &error)) { + g_printerr ("Could not read index.txt: %s\n", + error->message); + exit (1); + } + + chunkified = chunkify (raw_contents, raw_length); + + debug_printf (1, " sync read\n"); + + imem = g_memory_input_stream_new_from_data (chunkified->str, chunkified->len, NULL); + islow = g_object_new (slow_input_stream_get_type (), + "base-stream", imem, + "close-base-stream", TRUE, + NULL); + in = g_object_new (g_type_from_name ("SoupBodyInputStream"), + "base-stream", islow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (imem); + g_object_unref (islow); + + buf = g_malloc (raw_length); + total = 0; + while (TRUE) { + nread = g_input_stream_read (in, buf + total, raw_length - total, + NULL, &error); + if (nread == -1) { + debug_printf (1, " Error reading stream: %s\n", error->message); + g_clear_error (&error); + errors++; + break; + } else if (nread == 0) + break; + else + total += nread; + } + + g_input_stream_close (in, NULL, &error); + if (error) { + debug_printf (1, " Error closing input stream: %s\n", error->message); + g_clear_error (&error); + errors++; + } + g_object_unref (in); + + if (total == raw_length) { + if (memcmp (buf, raw_contents, raw_length) != 0) { + debug_printf (1, " mismatch when reading\n"); + errors++; + } + } else { + debug_printf (1, " incorrect read length: %d vs %d\n", + (int) total, (int) raw_length); + errors++; + } + g_free (buf); + + debug_printf (1, " async read\n"); + + imem = g_memory_input_stream_new_from_data (chunkified->str, chunkified->len, NULL); + islow = g_object_new (slow_input_stream_get_type (), + "base-stream", imem, + "close-base-stream", TRUE, + NULL); + in = g_object_new (g_type_from_name ("SoupBodyInputStream"), + "base-stream", islow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (imem); + g_object_unref (islow); + + buf = g_malloc (raw_length); + total = 0; + while (TRUE) { + nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (in), + buf + total, raw_length - total, + NULL, &error); + if (nread == -1 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + GSource *source; + + g_clear_error (&error); + source = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (in), NULL); + g_source_set_dummy_callback (source); + g_source_attach (source, NULL); + while (!g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (in))) + g_main_context_iteration (NULL, TRUE); + g_source_destroy (source); + g_source_unref (source); + continue; + } else if (nread == -1) { + debug_printf (1, " Error reading stream: %s\n", error->message); + g_clear_error (&error); + errors++; + break; + } else if (nread == 0) + break; + else + total += nread; + } + + g_input_stream_close (in, NULL, &error); + if (error) { + debug_printf (1, " Error closing input stream: %s\n", error->message); + g_clear_error (&error); + errors++; + } + g_object_unref (in); + + if (total == raw_length) { + if (memcmp (buf, raw_contents, raw_length) != 0) { + debug_printf (1, " mismatch when reading\n"); + errors++; + } + } else { + debug_printf (1, " incorrect read length: %d vs %d\n", + (int) total, (int) raw_length); + errors++; + } + g_free (buf); + + debug_printf (1, " sync write\n"); + + buf = g_malloc (chunkified->len); + omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL); + oslow = g_object_new (slow_output_stream_get_type (), + "base-stream", omem, + "close-base-stream", TRUE, + NULL); + out = g_object_new (g_type_from_name ("SoupBodyOutputStream"), + "base-stream", oslow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (omem); + g_object_unref (oslow); + + total = chunk_length = chunk_total = 0; + while (total < raw_length) { + if (chunk_total == chunk_length) { + chunk_length = MIN (CHUNK_SIZE, raw_length - total); + chunk_total = 0; + } + nwrote = g_output_stream_write (out, raw_contents + total, + chunk_length - chunk_total, NULL, &error); + if (nwrote == -1) { + debug_printf (1, " Error writing stream: %s\n", error->message); + g_clear_error (&error); + errors++; + break; + } else { + total += nwrote; + chunk_total += nwrote; + } + } + + g_output_stream_close (out, NULL, &error); + if (error) { + debug_printf (1, " Error closing output stream: %s\n", error->message); + g_clear_error (&error); + errors++; + } + g_object_unref (out); + + if (total == raw_length) { + if (memcmp (buf, chunkified->str, chunkified->len) != 0) { + debug_printf (1, " mismatch when writing\n"); + g_print ("%.*s\n", (int)chunkified->len, buf); + errors++; + } + } + g_free (buf); + + debug_printf (1, " async write\n"); + + buf = g_malloc (chunkified->len); + omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL); + oslow = g_object_new (slow_output_stream_get_type (), + "base-stream", omem, + "close-base-stream", TRUE, + NULL); + out = g_object_new (g_type_from_name ("SoupBodyOutputStream"), + "base-stream", oslow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (omem); + g_object_unref (oslow); + + total = chunk_length = chunk_total = 0; + while (total < raw_length) { + if (chunk_total == chunk_length) { + chunk_length = MIN (CHUNK_SIZE, raw_length - total); + chunk_total = 0; + } + nwrote = g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (out), + raw_contents + total, + chunk_length - chunk_total, + NULL, &error); + if (nwrote == -1 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + GSource *source; + + g_clear_error (&error); + source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (out), NULL); + g_source_set_dummy_callback (source); + g_source_attach (source, NULL); + while (!g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (out))) + g_main_context_iteration (NULL, TRUE); + g_source_destroy (source); + g_source_unref (source); + continue; + } else if (nwrote == -1) { + debug_printf (1, " Error writing stream: %s\n", error->message); + g_clear_error (&error); + errors++; + break; + } else { + total += nwrote; + chunk_total += nwrote; + } + } + + g_output_stream_close (out, NULL, &error); + if (error) { + debug_printf (1, " Error closing output stream: %s\n", error->message); + g_clear_error (&error); + errors++; + } + g_object_unref (out); + + if (total == raw_length) { + if (memcmp (buf, chunkified->str, chunkified->len) != 0) { + debug_printf (1, " mismatch when writing\n"); + errors++; + } + } + g_free (buf); + + debug_printf (1, " failed write\n"); + /* this succeeds if it doesn't critical */ + + buf = g_malloc (chunkified->len); + omem = g_memory_output_stream_new (buf, chunkified->len, NULL, NULL); + oslow = g_object_new (breaking_output_stream_get_type (), + "base-stream", omem, + "close-base-stream", TRUE, + NULL); + out = g_object_new (g_type_from_name ("SoupBodyOutputStream"), + "base-stream", oslow, + "close-base-stream", TRUE, + "encoding", SOUP_ENCODING_CHUNKED, + NULL); + g_object_unref (omem); + g_object_unref (oslow); + + total = 0; + while (total < nwrote) { + nwrote = g_output_stream_write (out, raw_contents + total, + raw_length - total, NULL, NULL); + if (nwrote == -1) + break; + else + total += nwrote; + } + + if (total == raw_length) { + debug_printf (1, " breaking stream didn't break?\n"); + errors++; + } + + g_output_stream_close (out, NULL, NULL); + g_object_unref (out); + + g_free (buf); + + g_string_free (chunkified, TRUE); + g_free (raw_contents); +} + +int +main (int argc, char **argv) +{ + test_init (argc, argv, NULL); + + force_io_streams_init (); + + do_io_tests (); + + test_cleanup (); + return errors != 0; +} -- cgit v1.2.1 From 3935e102d8195ec12349e688b87e200df4f33649 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 26 Aug 2013 10:54:03 -0400 Subject: server-test: split SoupServer-specific tests out of misc-test --- tests/Makefile.am | 1 + tests/misc-test.c | 209 ------------------------------------------- tests/server-test.c | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 252 insertions(+), 209 deletions(-) create mode 100644 tests/server-test.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 43347fe2..76a87fa7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -33,6 +33,7 @@ TESTS = \ resource-test \ session-test \ server-auth-test \ + server-test \ sniffing-test \ socket-test \ ssl-test \ diff --git a/tests/misc-test.c b/tests/misc-test.c index 18f0e615..73cc6333 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -32,16 +32,6 @@ server_callback (SoupServer *server, SoupMessage *msg, SoupURI *uri = soup_message_get_uri (msg); const char *server_protocol = data; - soup_message_headers_append (msg->response_headers, - "X-Handled-By", "server_callback"); - - if (!strcmp (path, "*")) { - debug_printf (1, " default server_callback got request for '*'!\n"); - errors++; - soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); return; @@ -99,29 +89,6 @@ server_callback (SoupServer *server, SoupMessage *msg, } } -static void -server_star_callback (SoupServer *server, SoupMessage *msg, - const char *path, GHashTable *query, - SoupClientContext *context, gpointer data) -{ - soup_message_headers_append (msg->response_headers, - "X-Handled-By", "star_callback"); - - if (strcmp (path, "*") != 0) { - debug_printf (1, " server_star_callback got request for '%s'!\n", path); - errors++; - soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); - return; - } - - if (msg->method != SOUP_METHOD_OPTIONS) { - soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED); - return; - } - - soup_message_set_status (msg, SOUP_STATUS_OK); -} - /* Host header handling: client must be able to override the default * value, server must be able to recognize different Host values. * #539803. @@ -462,69 +429,6 @@ do_msg_reuse_test (void) g_free (signal_ids); } -/* Server handlers for "*" work but are separate from handlers for - * all other URIs. #590751 - */ -static void -do_star_test (void) -{ - SoupSession *session; - SoupMessage *msg; - SoupURI *star_uri; - const char *handled_by; - - debug_printf (1, "\nOPTIONS *\n"); - - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - star_uri = soup_uri_copy (base_uri); - soup_uri_set_path (star_uri, "*"); - - debug_printf (1, " Testing with no handler\n"); - msg = soup_message_new_from_uri ("OPTIONS", star_uri); - soup_session_send_message (session, msg); - - if (msg->status_code != SOUP_STATUS_NOT_FOUND) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - handled_by = soup_message_headers_get_one (msg->response_headers, - "X-Handled-By"); - if (handled_by) { - /* Should have been rejected by SoupServer directly */ - debug_printf (1, " Message reached handler '%s'\n", - handled_by); - errors++; - } - g_object_unref (msg); - - soup_server_add_handler (server, "*", server_star_callback, NULL, NULL); - - debug_printf (1, " Testing with handler\n"); - msg = soup_message_new_from_uri ("OPTIONS", star_uri); - soup_session_send_message (session, msg); - - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - handled_by = soup_message_headers_get_one (msg->response_headers, - "X-Handled-By"); - if (!handled_by) { - debug_printf (1, " Message did not reach handler!\n"); - errors++; - } else if (strcmp (handled_by, "star_callback") != 0) { - debug_printf (1, " Message reached incorrect handler '%s'\n", - handled_by); - errors++; - } - g_object_unref (msg); - - soup_test_session_abort_unref (session); - soup_uri_free (star_uri); -} - /* Handle unexpectedly-early aborts. #596074, #618641 */ static void ea_msg_completed_one (SoupSession *session, SoupMessage *msg, gpointer loop) @@ -1055,116 +959,6 @@ do_aliases_test (void) soup_test_session_abort_unref (session); } -static void -do_dot_dot_test (void) -{ - SoupSession *session; - SoupMessage *msg; - SoupURI *uri; - - debug_printf (1, "\n'..' smuggling test\n"); - - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - - uri = soup_uri_new_with_base (base_uri, "/..%2ftest"); - msg = soup_message_new_from_uri ("GET", uri); - soup_uri_free (uri); - - soup_session_send_message (session, msg); - - if (msg->status_code != SOUP_STATUS_BAD_REQUEST) { - debug_printf (1, " FAILED: %d %s (expected Bad Request)\n", - msg->status_code, msg->reason_phrase); - errors++; - } - g_object_unref (msg); - - soup_test_session_abort_unref (session); -} - -static void -ipv6_server_callback (SoupServer *server, SoupMessage *msg, - const char *path, GHashTable *query, - SoupClientContext *context, gpointer data) -{ - const char *host; - char expected_host[128]; - - host = soup_message_headers_get_one (msg->request_headers, "Host"); - if (!host) { - debug_printf (1, " request has no Host header!\n"); - errors++; - soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); - return; - } - - g_snprintf (expected_host, sizeof (expected_host), - "[::1]:%d", soup_server_get_port (server)); - - if (strcmp (host, expected_host) == 0) - soup_message_set_status (msg, SOUP_STATUS_OK); - else { - debug_printf (1, " request has incorrect Host header '%s'\n", host); - errors++; - soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); - } -} - -static void -do_ipv6_test (void) -{ - SoupServer *ipv6_server; - SoupURI *ipv6_uri; - SoupAddress *ipv6_addr; - SoupSession *session; - SoupMessage *msg; - - debug_printf (1, "\nIPv6 server test\n"); - - ipv6_addr = soup_address_new ("::1", SOUP_ADDRESS_ANY_PORT); - soup_address_resolve_sync (ipv6_addr, NULL); - ipv6_server = soup_server_new (SOUP_SERVER_INTERFACE, ipv6_addr, - NULL); - g_object_unref (ipv6_addr); - if (!ipv6_server) { - debug_printf (1, " skipping due to lack of IPv6 support\n"); - return; - } - - soup_server_add_handler (ipv6_server, NULL, ipv6_server_callback, NULL, NULL); - soup_server_run_async (ipv6_server); - - ipv6_uri = soup_uri_new ("http://[::1]/"); - soup_uri_set_port (ipv6_uri, soup_server_get_port (ipv6_server)); - - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - - debug_printf (1, " HTTP/1.1\n"); - msg = soup_message_new_from_uri ("GET", ipv6_uri); - soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " request failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - g_object_unref (msg); - - debug_printf (1, " HTTP/1.0\n"); - msg = soup_message_new_from_uri ("GET", ipv6_uri); - soup_message_set_http_version (msg, SOUP_HTTP_1_0); - soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " request failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - g_object_unref (msg); - - soup_uri_free (ipv6_uri); - soup_test_session_abort_unref (session); - soup_test_server_quit_unref (ipv6_server); -} - static void do_idle_on_dispose_test (void) { @@ -1252,15 +1046,12 @@ main (int argc, char **argv) do_callback_unref_test (); do_callback_unref_req_test (); do_msg_reuse_test (); - do_star_test (); do_early_abort_test (); do_early_abort_req_test (); do_accept_language_test (); do_cancel_while_reading_test (); do_cancel_while_reading_req_test (); do_aliases_test (); - do_dot_dot_test (); - do_ipv6_test (); do_idle_on_dispose_test (); do_pause_abort_test (); diff --git a/tests/server-test.c b/tests/server-test.c new file mode 100644 index 00000000..3cad5c52 --- /dev/null +++ b/tests/server-test.c @@ -0,0 +1,251 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright 2007-2012 Red Hat, Inc. + */ + +#include "test-utils.h" + +SoupServer *server; +SoupURI *base_uri; + +static void +server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + soup_message_headers_append (msg->response_headers, + "X-Handled-By", "server_callback"); + + if (!strcmp (path, "*")) { + debug_printf (1, " default server_callback got request for '*'!\n"); + errors++; + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + if (msg->method != SOUP_METHOD_GET && msg->method != SOUP_METHOD_POST) { + soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, "index", 5); +} + +static void +server_star_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + soup_message_headers_append (msg->response_headers, + "X-Handled-By", "star_callback"); + + if (strcmp (path, "*") != 0) { + debug_printf (1, " server_star_callback got request for '%s'!\n", path); + errors++; + soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); + return; + } + + if (msg->method != SOUP_METHOD_OPTIONS) { + soup_message_set_status (msg, SOUP_STATUS_METHOD_NOT_ALLOWED); + return; + } + + soup_message_set_status (msg, SOUP_STATUS_OK); +} + +/* Server handlers for "*" work but are separate from handlers for + * all other URIs. #590751 + */ +static void +do_star_test (void) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *star_uri; + const char *handled_by; + + debug_printf (1, "\nOPTIONS *\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + star_uri = soup_uri_copy (base_uri); + soup_uri_set_path (star_uri, "*"); + + debug_printf (1, " Testing with no handler\n"); + msg = soup_message_new_from_uri ("OPTIONS", star_uri); + soup_session_send_message (session, msg); + + if (msg->status_code != SOUP_STATUS_NOT_FOUND) { + debug_printf (1, " Unexpected response: %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + handled_by = soup_message_headers_get_one (msg->response_headers, + "X-Handled-By"); + if (handled_by) { + /* Should have been rejected by SoupServer directly */ + debug_printf (1, " Message reached handler '%s'\n", + handled_by); + errors++; + } + g_object_unref (msg); + + soup_server_add_handler (server, "*", server_star_callback, NULL, NULL); + + debug_printf (1, " Testing with handler\n"); + msg = soup_message_new_from_uri ("OPTIONS", star_uri); + soup_session_send_message (session, msg); + + if (msg->status_code != SOUP_STATUS_OK) { + debug_printf (1, " Unexpected response: %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + handled_by = soup_message_headers_get_one (msg->response_headers, + "X-Handled-By"); + if (!handled_by) { + debug_printf (1, " Message did not reach handler!\n"); + errors++; + } else if (strcmp (handled_by, "star_callback") != 0) { + debug_printf (1, " Message reached incorrect handler '%s'\n", + handled_by); + errors++; + } + g_object_unref (msg); + + soup_test_session_abort_unref (session); + soup_uri_free (star_uri); +} + +static void +do_dot_dot_test (void) +{ + SoupSession *session; + SoupMessage *msg; + SoupURI *uri; + + debug_printf (1, "\n'..' smuggling test\n"); + + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + uri = soup_uri_new_with_base (base_uri, "/..%2ftest"); + msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + soup_session_send_message (session, msg); + + if (msg->status_code != SOUP_STATUS_BAD_REQUEST) { + debug_printf (1, " FAILED: %d %s (expected Bad Request)\n", + msg->status_code, msg->reason_phrase); + errors++; + } + g_object_unref (msg); + + soup_test_session_abort_unref (session); +} + +static void +ipv6_server_callback (SoupServer *server, SoupMessage *msg, + const char *path, GHashTable *query, + SoupClientContext *context, gpointer data) +{ + const char *host; + char expected_host[128]; + + host = soup_message_headers_get_one (msg->request_headers, "Host"); + if (!host) { + debug_printf (1, " request has no Host header!\n"); + errors++; + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + + g_snprintf (expected_host, sizeof (expected_host), + "[::1]:%d", soup_server_get_port (server)); + + if (strcmp (host, expected_host) == 0) + soup_message_set_status (msg, SOUP_STATUS_OK); + else { + debug_printf (1, " request has incorrect Host header '%s'\n", host); + errors++; + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + } +} + +static void +do_ipv6_test (void) +{ + SoupServer *ipv6_server; + SoupURI *ipv6_uri; + SoupAddress *ipv6_addr; + SoupSession *session; + SoupMessage *msg; + + debug_printf (1, "\nIPv6 server test\n"); + + ipv6_addr = soup_address_new ("::1", SOUP_ADDRESS_ANY_PORT); + soup_address_resolve_sync (ipv6_addr, NULL); + ipv6_server = soup_server_new (SOUP_SERVER_INTERFACE, ipv6_addr, + NULL); + g_object_unref (ipv6_addr); + if (!ipv6_server) { + debug_printf (1, " skipping due to lack of IPv6 support\n"); + return; + } + + soup_server_add_handler (ipv6_server, NULL, ipv6_server_callback, NULL, NULL); + soup_server_run_async (ipv6_server); + + ipv6_uri = soup_uri_new ("http://[::1]/"); + soup_uri_set_port (ipv6_uri, soup_server_get_port (ipv6_server)); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + debug_printf (1, " HTTP/1.1\n"); + msg = soup_message_new_from_uri ("GET", ipv6_uri); + soup_session_send_message (session, msg); + if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + debug_printf (1, " request failed: %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + g_object_unref (msg); + + debug_printf (1, " HTTP/1.0\n"); + msg = soup_message_new_from_uri ("GET", ipv6_uri); + soup_message_set_http_version (msg, SOUP_HTTP_1_0); + soup_session_send_message (session, msg); + if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + debug_printf (1, " request failed: %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + g_object_unref (msg); + + soup_uri_free (ipv6_uri); + soup_test_session_abort_unref (session); + soup_test_server_quit_unref (ipv6_server); +} + +int +main (int argc, char **argv) +{ + test_init (argc, argv, NULL); + + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + base_uri = soup_uri_new ("http://127.0.0.1/"); + soup_uri_set_port (base_uri, soup_server_get_port (server)); + + do_star_test (); + do_dot_dot_test (); + do_ipv6_test (); + + soup_uri_free (base_uri); + soup_test_server_quit_unref (server); + + test_cleanup (); + return errors != 0; +} -- cgit v1.2.1 From 4a8b1c0544b168b25cbd3b016b7aedee263515ba Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 25 Aug 2013 10:51:22 -0400 Subject: SoupServer: add :http-aliases and :https-aliases properties Add :http-aliases and :https-aliases properties to SoupServer, to allow it to handle requests like: GET daap://host:port/path HTTP/1.1 https://bugzilla.gnome.org/show_bug.cgi?id=703694 --- libsoup/soup-message-server-io.c | 5 +- libsoup/soup-misc-private.h | 2 + libsoup/soup-server.c | 117 ++++++++++++++++++++++++++++++++++- libsoup/soup-server.h | 2 + libsoup/soup-session.c | 54 ++-------------- libsoup/soup-uri.c | 43 +++++++++++++ tests/server-test.c | 130 ++++++++++++++++++++++++++++++++++++++- 7 files changed, 298 insertions(+), 55 deletions(-) diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c index 814ae7e5..2647b811 100644 --- a/libsoup/soup-message-server-io.c +++ b/libsoup/soup-message-server-io.c @@ -98,10 +98,7 @@ parse_request_headers (SoupMessage *msg, char *headers, guint headers_len, g_free (req_path); - if (!SOUP_URI_VALID_FOR_HTTP (uri)) { - /* certainly not "a valid host on the server" (RFC2616 5.2.3) - * SOUP_URI_VALID_FOR_HTTP also guards against uri == NULL - */ + if (!uri || !uri->host) { if (uri) soup_uri_free (uri); return SOUP_STATUS_BAD_REQUEST; diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index 02768706..e9c83f61 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -13,6 +13,8 @@ char *uri_decoded_copy (const char *str, int length, int *decoded_length); char *soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, gboolean force_port); +gboolean soup_uri_is_http (SoupURI *uri, char **aliases); +gboolean soup_uri_is_https (SoupURI *uri, char **aliases); guint soup_socket_handshake_sync (SoupSocket *sock, GCancellable *cancellable); diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index ff51e5bd..abda60ba 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -14,6 +14,7 @@ #include "soup-server.h" #include "soup.h" #include "soup-message-private.h" +#include "soup-misc-private.h" #include "soup-path-map.h" /** @@ -105,6 +106,8 @@ typedef struct { GSList *auth_domains; GMainContext *async_context; + + char **http_aliases, **https_aliases; } SoupServerPrivate; #define SOUP_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SERVER, SoupServerPrivate)) @@ -121,6 +124,8 @@ enum { PROP_ASYNC_CONTEXT, PROP_RAW_PATHS, PROP_SERVER_HEADER, + PROP_HTTP_ALIASES, + PROP_HTTPS_ALIASES, LAST_PROP }; @@ -141,6 +146,10 @@ soup_server_init (SoupServer *server) SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server); priv->handlers = soup_path_map_new ((GDestroyNotify)free_handler); + + priv->http_aliases = g_new (char *, 2); + priv->http_aliases[0] = (char *)g_intern_string ("*"); + priv->http_aliases[1] = NULL; } static void @@ -191,6 +200,9 @@ soup_server_finalize (GObject *object) g_clear_pointer (&priv->loop, g_main_loop_unref); g_clear_pointer (&priv->async_context, g_main_context_unref); + g_free (priv->http_aliases); + g_free (priv->https_aliases); + G_OBJECT_CLASS (soup_server_parent_class)->finalize (object); } @@ -250,6 +262,29 @@ soup_server_constructor (GType type, return server; } +/* priv->http_aliases and priv->https_aliases are stored as arrays of + * *interned* strings, so we can't just use g_strdupv() to set them. + */ +static void +set_aliases (char ***variable, char **value) +{ + int len, i; + + if (*variable) + g_free (*variable); + + if (!value) { + *variable = NULL; + return; + } + + len = g_strv_length (value); + *variable = g_new (char *, len + 1); + for (i = 0; i < len; i++) + (*variable)[i] = (char *)g_intern_string (value[i]); + (*variable)[i] = NULL; +} + static void soup_server_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) @@ -304,6 +339,12 @@ soup_server_set_property (GObject *object, guint prop_id, } else priv->server_header = g_strdup (header); break; + case PROP_HTTP_ALIASES: + set_aliases (&priv->http_aliases, g_value_get_boxed (value)); + break; + case PROP_HTTPS_ALIASES: + set_aliases (&priv->https_aliases, g_value_get_boxed (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -341,6 +382,12 @@ soup_server_get_property (GObject *object, guint prop_id, case PROP_SERVER_HEADER: g_value_set_string (value, priv->server_header); break; + case PROP_HTTP_ALIASES: + g_value_set_boxed (value, priv->http_aliases); + break; + case PROP_HTTPS_ALIASES: + g_value_set_boxed (value, priv->https_aliases); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -628,6 +675,68 @@ soup_server_class_init (SoupServerClass *server_class) "Server header", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + /** + * SoupServer:http-aliases: + * + * A %NULL-terminated array of URI schemes that should be + * considered to be aliases for "http". Eg, if this included + * "dav", than a URI of + * dav://example.com/path would be treated + * identically to http://example.com/path. + * In particular, this is needed in cases where a client + * sends requests with absolute URIs, where those URIs do + * not use "http:". + * + * The default value is an array containing the single element + * "*", a special value which means that + * any scheme except "https" is considered to be an alias for + * "http". + * + * See also #SoupServer:https-aliases. + * + * Since: 2.44 + */ + /** + * SOUP_SERVERI_HTTP_ALIASES: + * + * Alias for the #SoupServer:http-aliases property, qv. + * + * Since: 2.44 + */ + g_object_class_install_property ( + object_class, PROP_HTTP_ALIASES, + g_param_spec_boxed (SOUP_SERVER_HTTP_ALIASES, + "http aliases", + "URI schemes that are considered aliases for 'http'", + G_TYPE_STRV, + G_PARAM_READWRITE)); + /** + * SoupServer:https-aliases: + * + * A comma-delimited list of URI schemes that should be + * considered to be aliases for "https". See + * #SoupServer:http-aliases for more information. + * + * The default value is %NULL, meaning that no URI schemes + * are considered aliases for "https". + * + * Since: 2.44 + */ + /** + * SOUP_SERVER_HTTPS_ALIASES: + * + * Alias for the #SoupServer:https-aliases property, qv. + * + * Since: 2.44 + **/ + g_object_class_install_property ( + object_class, PROP_HTTPS_ALIASES, + g_param_spec_boxed (SOUP_SERVER_HTTPS_ALIASES, + "https aliases", + "URI schemes that are considered aliases for 'https'", + G_TYPE_STRV, + G_PARAM_READWRITE)); } /** @@ -816,10 +925,16 @@ got_headers (SoupMessage *msg, SoupClientContext *client) gboolean rejected = FALSE; char *auth_user; + uri = soup_message_get_uri (msg); + if ((soup_server_is_https (server) && !soup_uri_is_https (uri, priv->https_aliases)) || + (!soup_server_is_https (server) && !soup_uri_is_http (uri, priv->http_aliases))) { + soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); + return; + } + if (!priv->raw_paths) { char *decoded_path; - uri = soup_message_get_uri (msg); decoded_path = soup_uri_decode (uri->path); if (strstr (decoded_path, "/../") || diff --git a/libsoup/soup-server.h b/libsoup/soup-server.h index e1c9bbfb..0d09322e 100644 --- a/libsoup/soup-server.h +++ b/libsoup/soup-server.h @@ -64,6 +64,8 @@ typedef void (*SoupServerCallback) (SoupServer *server, #define SOUP_SERVER_ASYNC_CONTEXT "async-context" #define SOUP_SERVER_RAW_PATHS "raw-paths" #define SOUP_SERVER_SERVER_HEADER "server-header" +#define SOUP_SERVER_HTTP_ALIASES "http-aliases" +#define SOUP_SERVER_HTTPS_ALIASES "https-aliases" SoupServer *soup_server_new (const char *optname1, ...) G_GNUC_NULL_TERMINATED; diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 10851b3e..85ef1b25 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -831,49 +831,6 @@ soup_session_new_with_options (const char *optname1, return session; } -static gboolean -uri_is_http (SoupSessionPrivate *priv, SoupURI *uri) -{ - int i; - - if (uri->scheme == SOUP_URI_SCHEME_HTTP) - return TRUE; - else if (uri->scheme == SOUP_URI_SCHEME_HTTPS) - return FALSE; - else if (!priv->http_aliases) - return FALSE; - - for (i = 0; priv->http_aliases[i]; i++) { - if (uri->scheme == priv->http_aliases[i]) - return TRUE; - } - - if (!priv->http_aliases[1] && !strcmp (priv->http_aliases[0], "*")) - return TRUE; - else - return FALSE; -} - -static gboolean -uri_is_https (SoupSessionPrivate *priv, SoupURI *uri) -{ - int i; - - if (uri->scheme == SOUP_URI_SCHEME_HTTPS) - return TRUE; - else if (uri->scheme == SOUP_URI_SCHEME_HTTP) - return FALSE; - else if (!priv->https_aliases) - return FALSE; - - for (i = 0; priv->https_aliases[i]; i++) { - if (uri->scheme == priv->https_aliases[i]) - return TRUE; - } - - return FALSE; -} - /** * soup_session_get_async_context: * @session: a #SoupSession @@ -945,7 +902,7 @@ soup_session_host_new (SoupSession *session, SoupURI *uri) host->uri->scheme != SOUP_URI_SCHEME_HTTPS) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - if (uri_is_https (priv, host->uri)) + if (soup_uri_is_https (host->uri, priv->https_aliases)) host->uri->scheme = SOUP_URI_SCHEME_HTTPS; else host->uri->scheme = SOUP_URI_SCHEME_HTTP; @@ -969,7 +926,7 @@ get_host_for_uri (SoupSession *session, SoupURI *uri) SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupSessionHost *host; - if (uri_is_https (priv, uri)) + if (soup_uri_is_https (uri, priv->https_aliases)) host = g_hash_table_lookup (priv->https_hosts, uri); else host = g_hash_table_lookup (priv->http_hosts, uri); @@ -978,7 +935,7 @@ get_host_for_uri (SoupSession *session, SoupURI *uri) host = soup_session_host_new (session, uri); - if (uri_is_https (priv, uri)) + if (soup_uri_is_https (uri, priv->https_aliases)) g_hash_table_insert (priv->https_hosts, host->uri, host); else g_hash_table_insert (priv->http_hosts, host->uri, host); @@ -1080,7 +1037,8 @@ soup_session_would_redirect (SoupSession *session, SoupMessage *msg) if (!new_uri) return FALSE; if (!new_uri->host || !*new_uri->host || - (!uri_is_http (priv, new_uri) && !uri_is_https (priv, new_uri))) { + (!soup_uri_is_http (new_uri, priv->http_aliases) && + !soup_uri_is_https (new_uri, priv->https_aliases))) { soup_uri_free (new_uri); return FALSE; } @@ -1691,7 +1649,7 @@ get_connection_for_host (SoupSession *session, SOUP_TYPE_CONNECTION, SOUP_CONNECTION_REMOTE_URI, host->uri, SOUP_CONNECTION_PROXY_RESOLVER, priv->proxy_resolver, - SOUP_CONNECTION_SSL, uri_is_https (priv, soup_message_get_uri (item->msg)), + SOUP_CONNECTION_SSL, soup_uri_is_https (soup_message_get_uri (item->msg), priv->https_aliases), SOUP_CONNECTION_SSL_CREDENTIALS, priv->tlsdb, SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (priv->tlsdb != NULL || SOUP_IS_PLAIN_SESSION (session)), SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context, diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 6e3d220b..808d2ccc 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -1291,4 +1291,47 @@ soup_uri_host_equal (gconstpointer v1, gconstpointer v2) return g_ascii_strcasecmp (one->host, two->host) == 0; } +gboolean +soup_uri_is_http (SoupURI *uri, char **aliases) +{ + int i; + + if (uri->scheme == SOUP_URI_SCHEME_HTTP) + return TRUE; + else if (uri->scheme == SOUP_URI_SCHEME_HTTPS) + return FALSE; + else if (!aliases) + return FALSE; + + for (i = 0; aliases[i]; i++) { + if (uri->scheme == aliases[i]) + return TRUE; + } + + if (!aliases[1] && !strcmp (aliases[0], "*")) + return TRUE; + else + return FALSE; +} + +gboolean +soup_uri_is_https (SoupURI *uri, char **aliases) +{ + int i; + + if (uri->scheme == SOUP_URI_SCHEME_HTTPS) + return TRUE; + else if (uri->scheme == SOUP_URI_SCHEME_HTTP) + return FALSE; + else if (!aliases) + return FALSE; + + for (i = 0; aliases[i]; i++) { + if (uri->scheme == aliases[i]) + return TRUE; + } + + return FALSE; +} + G_DEFINE_BOXED_TYPE (SoupURI, soup_uri, soup_uri_copy, soup_uri_free) diff --git a/tests/server-test.c b/tests/server-test.c index 3cad5c52..3ff7cadd 100644 --- a/tests/server-test.c +++ b/tests/server-test.c @@ -5,8 +5,8 @@ #include "test-utils.h" -SoupServer *server; -SoupURI *base_uri; +SoupServer *server, *ssl_server; +SoupURI *base_uri, *ssl_base_uri; static void server_callback (SoupServer *server, SoupMessage *msg, @@ -119,6 +119,109 @@ do_star_test (void) soup_uri_free (star_uri); } +static void +do_one_server_aliases_test (SoupURI *uri, + const char *alias, + gboolean succeed) +{ + GSocketClient *client; + GSocketConnectable *addr; + GSocketConnection *conn; + GInputStream *in; + GOutputStream *out; + GError *error = NULL; + GString *req; + static char buf[1024]; + + debug_printf (1, " %s via %s\n", alias, uri->scheme); + + /* There's no way to make libsoup's client side send an absolute + * URI (to a non-proxy server), so we have to fake this. + */ + + client = g_socket_client_new (); + if (uri->scheme == SOUP_URI_SCHEME_HTTPS) { + g_socket_client_set_tls (client, TRUE); + g_socket_client_set_tls_validation_flags (client, 0); + } + addr = g_network_address_new (uri->host, uri->port); + + conn = g_socket_client_connect (client, addr, NULL, &error); + g_object_unref (addr); + g_object_unref (client); + if (!conn) { + debug_printf (1, " error connecting to server: %s\n", + error->message); + g_error_free (error); + errors++; + return; + } + + in = g_io_stream_get_input_stream (G_IO_STREAM (conn)); + out = g_io_stream_get_output_stream (G_IO_STREAM (conn)); + + req = g_string_new (NULL); + g_string_append_printf (req, "GET %s://%s:%d HTTP/1.1\r\n", + alias, uri->host, uri->port); + g_string_append_printf (req, "Host: %s:%d\r\n", + uri->host, uri->port); + g_string_append (req, "Connection: close\r\n\r\n"); + + if (!g_output_stream_write_all (out, req->str, req->len, NULL, NULL, &error)) { + debug_printf (1, " error sending request: %s\n", + error->message); + g_error_free (error); + errors++; + g_object_unref (conn); + g_string_free (req, TRUE); + return; + } + g_string_free (req, TRUE); + + if (!g_input_stream_read_all (in, buf, sizeof (buf), NULL, NULL, &error)) { + debug_printf (1, " error reading response: %s\n", + error->message); + g_error_free (error); + errors++; + g_object_unref (conn); + return; + } + + if ((succeed && !g_str_has_prefix (buf, "HTTP/1.1 200 ")) || + (!succeed && !g_str_has_prefix (buf, "HTTP/1.1 400 "))) { + debug_printf (1, " unexpected response: %.*s\n", + (int) strcspn (buf, "\r\n"), buf); + errors++; + } + + g_io_stream_close (G_IO_STREAM (conn), NULL, NULL); + g_object_unref (conn); +} + +static void +do_server_aliases_test (void) +{ + char *http_good[] = { "http", "dav", NULL }; + char *http_bad[] = { "https", "davs", "fred", NULL }; + char *https_good[] = { "https", "davs", NULL }; + char *https_bad[] = { "http", "dav", "fred", NULL }; + int i; + + debug_printf (1, "\nserver aliases test\n"); + + for (i = 0; http_good[i]; i++) + do_one_server_aliases_test (base_uri, http_good[i], TRUE); + for (i = 0; http_bad[i]; i++) + do_one_server_aliases_test (base_uri, http_bad[i], FALSE); + + if (tls_available) { + for (i = 0; https_good[i]; i++) + do_one_server_aliases_test (ssl_base_uri, https_good[i], TRUE); + for (i = 0; https_bad[i]; i++) + do_one_server_aliases_test (ssl_base_uri, https_bad[i], FALSE); + } +} + static void do_dot_dot_test (void) { @@ -232,6 +335,9 @@ do_ipv6_test (void) int main (int argc, char **argv) { + char *http_aliases[] = { "dav", NULL }; + char *https_aliases[] = { "davs", NULL }; + test_init (argc, argv, NULL); server = soup_test_server_new (TRUE); @@ -239,13 +345,33 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); + g_object_set (G_OBJECT (server), + SOUP_SERVER_HTTP_ALIASES, http_aliases, + NULL); + + if (tls_available) { + ssl_server = soup_test_server_new_ssl (TRUE); + soup_server_add_handler (ssl_server, NULL, server_callback, NULL, NULL); + ssl_base_uri = soup_uri_new ("https://127.0.0.1/"); + soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server)); + g_object_set (G_OBJECT (ssl_server), + SOUP_SERVER_HTTPS_ALIASES, https_aliases, + NULL); + } + do_star_test (); + do_server_aliases_test (); do_dot_dot_test (); do_ipv6_test (); soup_uri_free (base_uri); soup_test_server_quit_unref (server); + if (tls_available) { + soup_uri_free (ssl_base_uri); + soup_test_server_quit_unref (ssl_server); + } + test_cleanup (); return errors != 0; } -- cgit v1.2.1 From 825e817118a3e046e3b11443b518cc552a168aee Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 27 Aug 2013 11:22:59 -0400 Subject: chunk-io-test: fix a bug --- tests/chunk-io-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/chunk-io-test.c b/tests/chunk-io-test.c index 7606d41b..f1f96b0f 100644 --- a/tests/chunk-io-test.c +++ b/tests/chunk-io-test.c @@ -617,7 +617,7 @@ do_io_tests (void) g_object_unref (oslow); total = 0; - while (total < nwrote) { + while (total < raw_length) { nwrote = g_output_stream_write (out, raw_contents + total, raw_length - total, NULL, NULL); if (nwrote == -1) -- cgit v1.2.1 From c3cc4a9d3d033c9a53ca83fa8b903d7be5dddeb5 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 30 Aug 2013 09:12:05 -0400 Subject: timeout-test: fix on very slow machines On slow old machines, the TLS handshake when making an https request can take longer than 1 second, which meant that even the "fast" https requests were hitting the 1-second timeout and failing. Fix this by making the timeouts longer. However, we don't want to do that unless absolutely necessary, since the test has to hit this timeout multiple times, and the test already takes 10 seconds to run with the 1-second timeout. So check how long it takes to make a single https request, and only slow down the rest of the tests if it looks like it will be needed. Also fix an unrelated bug, where the "session did/didn't close connection" check could fail if the same memory location got used for the first and second sockets. https://bugzilla.gnome.org/show_bug.cgi?id=660581 --- tests/timeout-test.c | 53 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/tests/timeout-test.c b/tests/timeout-test.c index 27bcbff1..405ec3c1 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -26,7 +26,8 @@ do_message_to_session (SoupSession *session, const char *uri, SoupMessage *msg; gboolean finished = FALSE; - debug_printf (1, " msg %s\n", comment); + if (comment) + debug_printf (1, " msg %s\n", comment); msg = soup_message_new ("GET", uri); g_signal_connect (msg, "finished", @@ -71,14 +72,14 @@ do_msg_tests_for_session (SoupSession *timeout_session, g_signal_connect (idle_session, "request-started", G_CALLBACK (request_started_cb), &ret); do_message_to_session (idle_session, fast_uri, "fast to idle", SOUP_STATUS_OK); - idle_first = ret; + idle_first = g_object_ref (ret); } if (plain_session) { g_signal_connect (plain_session, "request-started", G_CALLBACK (request_started_cb), &ret); do_message_to_session (plain_session, fast_uri, "fast to plain", SOUP_STATUS_OK); - plain_first = ret; + plain_first = g_object_ref (ret); } do_message_to_session (timeout_session, fast_uri, "fast to timeout", SOUP_STATUS_OK); @@ -95,6 +96,7 @@ do_msg_tests_for_session (SoupSession *timeout_session, debug_printf (1, " ERROR: idle_session did not close first connection\n"); errors++; } + g_object_unref (idle_first); } if (plain_session) { @@ -108,6 +110,7 @@ do_msg_tests_for_session (SoupSession *timeout_session, debug_printf (1, " ERROR: plain_session closed connection\n"); errors++; } + g_object_unref (plain_first); } } @@ -148,7 +151,7 @@ do_request_to_session (SoupSession *session, const char *uri, soup_test_request_close_stream (req, stream, NULL, &error); if (error) { - debug_printf (1, " ERROR closing string: %s", + debug_printf (1, " ERROR closing stream: %s\n", error->message); errors++; } @@ -188,14 +191,14 @@ do_req_tests_for_session (SoupSession *timeout_session, g_signal_connect (idle_session, "request-started", G_CALLBACK (request_started_cb), &ret); do_request_to_session (idle_session, fast_uri, "fast to idle", FALSE); - idle_first = ret; + idle_first = g_object_ref (ret); } if (plain_session) { g_signal_connect (plain_session, "request-started", G_CALLBACK (request_started_cb), &ret); do_request_to_session (plain_session, fast_uri, "fast to plain", FALSE); - plain_first = ret; + plain_first = g_object_ref (ret); } do_request_to_session (timeout_session, fast_uri, "fast to timeout", FALSE); @@ -212,6 +215,7 @@ do_req_tests_for_session (SoupSession *timeout_session, debug_printf (1, " ERROR: idle_session did not close first connection\n"); errors++; } + g_object_unref (idle_first); } if (plain_session) { @@ -225,21 +229,22 @@ do_req_tests_for_session (SoupSession *timeout_session, debug_printf (1, " ERROR: plain_session closed connection\n"); errors++; } + g_object_unref (plain_first); } } static void -do_timeout_tests (char *fast_uri, char *slow_uri) +do_timeout_tests (char *fast_uri, char *slow_uri, gboolean extra_slow) { SoupSession *timeout_session, *idle_session, *plain_session; debug_printf (1, " async\n"); timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_TIMEOUT, 1, + SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); idle_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_IDLE_TIMEOUT, 1, + SOUP_SESSION_IDLE_TIMEOUT, extra_slow ? 2 : 1, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); /* The "plain" session also has an idle timeout, but it's longer @@ -247,7 +252,7 @@ do_timeout_tests (char *fast_uri, char *slow_uri) * it has no timeout. */ plain_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_IDLE_TIMEOUT, 2, + SOUP_SESSION_IDLE_TIMEOUT, 20, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -261,7 +266,7 @@ do_timeout_tests (char *fast_uri, char *slow_uri) debug_printf (1, "\n sync\n"); timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, - SOUP_SESSION_TIMEOUT, 1, + SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1, NULL); /* SOUP_SESSION_TIMEOUT doesn't work with sync sessions */ plain_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, @@ -298,7 +303,7 @@ server_handler (SoupServer *server, soup_server_pause_message (server, msg); g_object_set_data (G_OBJECT (msg), "server", server); soup_add_timeout (soup_server_get_async_context (server), - 1100, timeout_finish_message, msg); + 4000, timeout_finish_message, msg); } } @@ -317,12 +322,16 @@ main (int argc, char **argv) soup_server_get_port (server)); slow_uri = g_strdup_printf ("http://127.0.0.1:%u/slow", soup_server_get_port (server)); - do_timeout_tests (fast_uri, slow_uri); + do_timeout_tests (fast_uri, slow_uri, FALSE); g_free (fast_uri); g_free (slow_uri); soup_test_server_quit_unref (server); if (tls_available) { + SoupSession *test_session; + gboolean extra_slow; + gint64 start, end; + debug_printf (1, "\nhttps\n"); server = soup_test_server_new_ssl (TRUE); soup_server_add_handler (server, NULL, server_handler, NULL, NULL); @@ -330,7 +339,23 @@ main (int argc, char **argv) soup_server_get_port (server)); slow_uri = g_strdup_printf ("https://127.0.0.1:%u/slow", soup_server_get_port (server)); - do_timeout_tests (fast_uri, slow_uri); + + /* The 1-second timeouts are too fast for some machines... */ + test_session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + start = g_get_monotonic_time (); + do_message_to_session (test_session, fast_uri, NULL, SOUP_STATUS_OK); + end = g_get_monotonic_time (); + soup_test_session_abort_unref (test_session); + debug_printf (2, " (https request took %0.3fs)\n", (end - start) / 1000000.0); + if (end - start > 750000) { + debug_printf (1, " (using extra-slow mode)\n\n"); + extra_slow = TRUE; + } else { + debug_printf (2, "\n"); + extra_slow = FALSE; + } + + do_timeout_tests (fast_uri, slow_uri, extra_slow); g_free (fast_uri); g_free (slow_uri); soup_test_server_quit_unref (server); -- cgit v1.2.1 From 03fd6fdc23e0652dda8cb11a16d3fe9b41e16ba9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 11 Sep 2013 15:33:04 -0400 Subject: cache-test: fix some minor things pointed out by coverity --- tests/cache-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/cache-test.c b/tests/cache-test.c index a8d01ebf..a19e9747 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -164,6 +164,7 @@ do_request (SoupSession *session, soup_message_headers_append (msg->request_headers, header, value); } + va_end (ap); stream = soup_test_request_send (SOUP_REQUEST (req), NULL, 0, &error); if (!stream) { @@ -703,8 +704,7 @@ do_headers_test (SoupURI *base_uri) if (!header_value) { debug_printf (1, " Header \"My-Header\" not present!\n"); errors++; - } - if (strcmp (header_value, "My header NEW value") != 0) { + } else if (strcmp (header_value, "My header NEW value") != 0) { debug_printf (1, " \"My-Header = %s\" and should be \"%s\"\n", header_value, "My header NEW value"); -- cgit v1.2.1 From b63d08471391c35b7c67d414f24fecf0d1810c74 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 13 Sep 2013 14:32:44 +0100 Subject: Bug 708006 - libsoup fails to close connection when message cancelled We need to clear priv->reusable when we send a request, *even* if we're only resending a request that was already tried once (as with NTLM authentication). Otherwise, cancellation of the pending, restarted, request will not properly close the connection as it should. --- libsoup/soup-connection.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index c1184104..00fe72b9 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -890,5 +890,8 @@ soup_connection_send_request (SoupConnection *conn, if (item->msg != priv->current_msg) set_current_msg (conn, item->msg); + else + priv->reusable = FALSE; + soup_message_send_request (item, completion_cb, user_data); } -- cgit v1.2.1 From 2b9345730cd95ea9efb4e1b78d40574f6c316f96 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 27 Jun 2013 22:57:09 +0100 Subject: Bug 703186 - fallback from automatic NTLM auth not working There were two issues. Firstly, when the automatic NTLM authentication failed we were setting conn->state to SOUP_NTLM_FAILED. So although we would emit the 'authenticate' signal and obtain a password, we'd never actually *try* it. We have the SOUP_NTLM_SSO_FAILED state for this, which makes it work. Secondly, the resulting 'authenticate' signal we being emitted with the 'retrying' property set, even when it was the first time we actually asked for a password. This was confusing Evolution (bug 703181 comments 1-3). Fix the latter problem by making soup_auth_ntlm_is_connection_ready() return TRUE when the state is SOUP_NTLM_SSO_FAILED. That makes auth_got_headers() do the right thing, and Evolution is happy again. With this fixed, Evolution will now automatically try to connect to an Exchange server using automatic NTLM authentication, and will fall back to asking for a password only if it actually needs to. --- libsoup/soup-auth-ntlm.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index cff469f7..19be6928 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -298,8 +298,6 @@ soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg, return FALSE; if (conn->state > SOUP_NTLM_SENT_REQUEST) { - conn->state = SOUP_NTLM_FAILED; - if (priv->password_state == SOUP_NTLM_PASSWORD_ACCEPTED) { /* We know our password is correct, so a 401 * means "permission denied". Since the conn @@ -307,11 +305,17 @@ soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg, * is_ready() for this message, so this will * cause a "retrying" authenticate signal. */ + conn->state = SOUP_NTLM_FAILED; return TRUE; } - /* Otherwise, we just have a bad password. */ - priv->password_state = SOUP_NTLM_PASSWORD_REJECTED; + if (priv->sso_available) { + conn->state = SOUP_NTLM_SSO_FAILED; + priv->password_state = SOUP_NTLM_PASSWORD_NONE; + } else { + conn->state = SOUP_NTLM_FAILED; + priv->password_state = SOUP_NTLM_PASSWORD_REJECTED; + } return TRUE; } @@ -433,7 +437,7 @@ soup_auth_ntlm_is_connection_ready (SoupConnectionAuth *auth, if (priv->password_state == SOUP_NTLM_PASSWORD_PROVIDED) return TRUE; - return conn->state != SOUP_NTLM_FAILED && conn->state != SOUP_NTLM_SSO_FAILED; + return conn->state != SOUP_NTLM_FAILED; } static void -- cgit v1.2.1 From 70b0173962cfd4252a01e7d849a6b0f24dbcb927 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 16 Sep 2013 18:18:20 -0400 Subject: 2.43.92 --- NEWS | 30 ++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index befc5fc8..fd8b680f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,33 @@ +Changes in libsoup from 2.43.90 to 2.43.92: + + * Fixed a bug in the connection-pool code, which would in + certain cases accidentally keep using a connection after a + message was cancelled while in progress, causing the next + request on that connection to get the response to the + previous request, etc. [#708006, David Woodhouse] + + * Fixed some problems when falling back from samba + single-sign-on-based NTLM to ordinary ask-for-a-password + NTLM. [#703186, David Woodhouse] + + * When sending a conditional GET request, SoupCache now + preserves the original message's list of disabled features, + ensure that it gets back the same kind of response the + original message would have. [#706338, Andre Moreira + Magalhaes] + + * Fixed a warning when the remote host closes the connection + while we are writing something using chunked encoding. + [#703297, Dan] + + * Added SoupServer:http-aliases and :https-aliases properties, + to specify URI schemes that should be treated as though they + were http (just like SoupSession:http-aliases and + :https-aliases, but on the server side). [#703694, Dan] + + * Fixed race conditions in cache-test and timeout-test that + could case spurious failures. [#698305, #660581, Dan] + Changes in libsoup from 2.43.5 to 2.43.90: * Fixed the handling of unsatisfiable range requests in diff --git a/configure.ac b/configure.ac index 742e5435..7dcc2983 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [43]) -m4_define([soup_micro_version], [90]) +m4_define([soup_micro_version], [92]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 90b0d787af98fefd5d0ecabaa5cdfa81ce137798 Mon Sep 17 00:00:00 2001 From: Reinout van Schouwen Date: Wed, 18 Sep 2013 23:22:38 +0200 Subject: Initial Dutch translation --- po/LINGUAS | 1 + po/nl.po | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 po/nl.po diff --git a/po/LINGUAS b/po/LINGUAS index 6afda913..a1d98a9e 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -32,6 +32,7 @@ lv ml mr nb +nl or pa pl diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 00000000..77fc8526 --- /dev/null +++ b/po/nl.po @@ -0,0 +1,109 @@ +# Dutch translation for libsoup. +# Copyright (C) 2013 libsoup's COPYRIGHT HOLDER +# This file is distributed under the same license as the libsoup package. +# Reinout van Schouwen , 2013. +# Reinout van Schouwen , 2013. +msgid "" +msgstr "" +"Project-Id-Version: libsoup master\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=libsou" +"p&keywords=I18N+L10N&component=general\n" +"POT-Creation-Date: 2013-09-16 22:19+0000\n" +"PO-Revision-Date: 2013-09-18 23:22+0200\n" +"Last-Translator: Reinout van Schouwen \n" +"Language-Team: Dutch \n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Virtaal 0.7.1\n" +"X-Project-Style: gnome\n" + +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:191 +msgid "Connection terminated unexpectedly" +msgstr "Verbinding werd onverwacht verbroken" + +#: ../libsoup/soup-body-input-stream.c:462 +msgid "Invalid seek request" +msgstr "Ongeldige zoekaanvraag" + +#: ../libsoup/soup-body-input-stream.c:490 +msgid "Cannot truncate SoupBodyInputStream" +msgstr "Kan SoupBodyInputStream niet afkappen" + +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "Netwerkstroom onverwacht gesloten" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "Volledig bufferen van de bron is mislukt" + +#: ../libsoup/soup-converter-wrapper.c:192 +#, c-format +msgid "Output buffer is too small" +msgstr "Uitvoerbuffer is te klein" + +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Kan HTTP-antwoord niet verwerken" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Niet-herkende HTTP-antwoordcodering" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +msgid "Operation was cancelled" +msgstr "Bewerking is geannuleerd" + +#: ../libsoup/soup-message-io.c:893 +msgid "Operation would block" +msgstr "Bewerking zou blokkeren" + +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Kan HTTP-aanvraag niet verwerken" + +#: ../libsoup/soup-request.c:140 +#, c-format +msgid "No URI provided" +msgstr "Geen URI aangeleverd" + +#: ../libsoup/soup-request.c:150 +#, c-format +msgid "Invalid '%s' URI: %s" +msgstr "Ongeldige ‘%s’-URI: %s" + +#: ../libsoup/soup-session.c:4259 +#, c-format +msgid "Could not parse URI '%s'" +msgstr "Kon URI ‘%s’ niet verwerken" + +#: ../libsoup/soup-session.c:4296 +#, c-format +msgid "Unsupported URI scheme '%s'" +msgstr "Niet-ondersteund URI-schema ‘%s’." + +#: ../libsoup/soup-session.c:4318 +#, c-format +msgid "Not an HTTP URI" +msgstr "Geen HTTP-URI" + +#: ../libsoup/soup-tld.c:185 +msgid "Hostname is an IP address" +msgstr "Hostnaam is een IP-adres" + +#: ../libsoup/soup-tld.c:206 +msgid "Invalid hostname" +msgstr "Ongeldige hostnaam" + +#: ../libsoup/soup-tld.c:235 +msgid "Hostname has no base domain" +msgstr "Hostnaam heeft geen basisdomein" + +#: ../libsoup/soup-tld.c:257 +msgid "Not enough domains" +msgstr "Niet genoeg domeinen" -- cgit v1.2.1 From db71813b860a6339d4db6edd4d7734812057176b Mon Sep 17 00:00:00 2001 From: Dirgita Date: Thu, 19 Sep 2013 10:39:52 +0700 Subject: Updated Indonesian translation --- po/id.po | 65 ++++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/po/id.po b/po/id.po index 0cefc660..96307099 100644 --- a/po/id.po +++ b/po/id.po @@ -3,82 +3,107 @@ # This file is distributed under the same license as the libsoup package. # # Andika Triwidada , 2012. -# Dirgita , 2012. +# Dirgita , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-11 23:45+0700\n" -"Last-Translator: Andika Triwidada \n" +"POT-Creation-Date: 2013-09-16 22:19+0000\n" +"PO-Revision-Date: 2013-09-18 20:55+0700\n" +"Last-Translator: Dirgita \n" "Language-Team: Indonesian \n" "Language: id\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Lokalize 1.2\n" +"X-Generator: Lokalize 1.5\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../libsoup/soup-body-input-stream.c:141 -#: ../libsoup/soup-body-input-stream.c:172 -#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "Sambungan terputus secara tak diharapkan" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:462 msgid "Invalid seek request" msgstr "Permintaan seek yang tak valid" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:490 msgid "Cannot truncate SoupBodyInputStream" msgstr "Tak bisa memenggal SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "Lalu lintas jaringan putus tak terduga" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "Gagal melengkapi tembolok sumber" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "Penyangga keluaran terlalu kecil" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "Tak dapat mengurai tanggapan HTTP" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "Enkode tanggapan HTTP tak dikenal" + +#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "Operasi dibatalkan" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:893 msgid "Operation would block" msgstr "Operasi akan memblokir" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "Tak dapat mengurai permintaan HTTP" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "URI tak diberikan" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "URI '%s' tak valid: %s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4259 #, c-format msgid "Could not parse URI '%s'" msgstr "Tak bisa mengurai URI '%s'" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4296 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "Skema URI '%s' tak didukung" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4318 +#, c-format +msgid "Not an HTTP URI" +msgstr "Bukan URI HTTP" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "Nama host adalah suatu alamat IP" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "Nama host tak valid" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "Nama host tidak memiliki domain dasar" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "Tak cukup domain" -- cgit v1.2.1 From 9c09d4592df0073dbf5e52e6f5c4e1460067b967 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 23 Sep 2013 18:22:51 -0400 Subject: 2.44.0 --- NEWS | 5 +++++ configure.ac | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index fd8b680f..a339bebc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +Changes in libsoup from 2.43.92 to 2.44.0: + + * New/updated translations: + Dutch, Indonesian + Changes in libsoup from 2.43.90 to 2.43.92: * Fixed a bug in the connection-pool code, which would in diff --git a/configure.ac b/configure.ac index 7dcc2983..9eee7a8e 100644 --- a/configure.ac +++ b/configure.ac @@ -3,8 +3,8 @@ dnl *** Initialize automake and set version *** dnl ******************************************* m4_define([soup_major_version], [2]) -m4_define([soup_minor_version], [43]) -m4_define([soup_micro_version], [92]) +m4_define([soup_minor_version], [44]) +m4_define([soup_micro_version], [0]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) @@ -28,10 +28,10 @@ SOUP_API_VERSION=2.4 AC_SUBST(SOUP_API_VERSION) # Increment on interface addition. Reset on removal. -SOUP_AGE=6 +SOUP_AGE=7 # Increment on interface add, remove, or change. -SOUP_CURRENT=7 +SOUP_CURRENT=8 # Increment on source change. Reset when CURRENT changes. SOUP_REVISION=0 -- cgit v1.2.1 From 3acda7636ad2e116397aab913f6d8bb8f609715a Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Mon, 23 Sep 2013 15:12:25 +0200 Subject: append_form_encoded: sync urlencode with php RFC1738 implementation. From php_url_encode: /* Allow only alphanumeric chars and '_', '-', '.'; escape the rest */ https://bugzilla.gnome.org/show_bug.cgi?id=708621 --- libsoup/soup-form.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-form.c b/libsoup/soup-form.c index 5946daeb..4dee5647 100644 --- a/libsoup/soup-form.c +++ b/libsoup/soup-form.c @@ -218,7 +218,8 @@ append_form_encoded (GString *str, const char *in) if (*s == ' ') { g_string_append_c (str, '+'); s++; - } else if (!g_ascii_isalnum (*s)) + } else if (!g_ascii_isalnum (*s) && (*s != '-') && (*s != '_') + && (*s != '.')) g_string_append_printf (str, "%%%02X", (int)*s++); else g_string_append_c (str, *s++); -- cgit v1.2.1 From 3a308914423d4aa16e5546c1484c983c69fd2780 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 28 Sep 2013 16:09:06 -0400 Subject: Fix asynchronicity of soup_session_queue_message() on plain SoupSession Messages sent via soup_session_queue_message() on a plain SoupSession accidentally ended up using blocking I/O. Fix this (and also make switching between sync and async ops during a streaming operation work better). https://bugzilla.gnome.org/show_bug.cgi?id=707711 --- libsoup/soup-client-input-stream.c | 4 +- libsoup/soup-message-client-io.c | 2 +- libsoup/soup-message-io.c | 88 +++++++++++++++++++++----------------- libsoup/soup-message-private.h | 3 ++ libsoup/soup-session.c | 4 +- 5 files changed, 57 insertions(+), 44 deletions(-) diff --git a/libsoup/soup-client-input-stream.c b/libsoup/soup-client-input-stream.c index 3e533ca8..d73fb007 100644 --- a/libsoup/soup-client-input-stream.c +++ b/libsoup/soup-client-input-stream.c @@ -129,7 +129,7 @@ soup_client_input_stream_close_fn (GInputStream *stream, { SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (stream); - return soup_message_io_run_until_finish (cistream->priv->msg, + return soup_message_io_run_until_finish (cistream->priv->msg, TRUE, cancellable, error); } @@ -150,7 +150,7 @@ close_async_ready (SoupMessage *msg, gpointer user_data) SoupClientInputStream *cistream = g_task_get_source_object (task); GError *error = NULL; - if (!soup_message_io_run_until_finish (cistream->priv->msg, + if (!soup_message_io_run_until_finish (cistream->priv->msg, FALSE, g_task_get_cancellable (task), &error) && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c index 1d96729d..b145bbaf 100644 --- a/libsoup/soup-message-client-io.c +++ b/libsoup/soup-message-client-io.c @@ -150,7 +150,7 @@ soup_message_send_request (SoupMessageQueueItem *item, GMainContext *async_context; GIOStream *iostream; - if (SOUP_IS_SESSION_ASYNC (item->session)) { + if (!SOUP_IS_SESSION_SYNC (item->session)) { async_context = soup_session_get_async_context (item->session); if (!async_context) async_context = g_main_context_default (); diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 497fd063..f5f4c514 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -60,7 +60,6 @@ typedef struct { GOutputStream *ostream; GOutputStream *body_ostream; GMainContext *async_context; - gboolean blocking; SoupMessageIOState read_state; SoupEncoding read_encoding; @@ -167,7 +166,8 @@ soup_message_io_finished (SoupMessage *msg) } static gboolean -read_headers (SoupMessage *msg, GCancellable *cancellable, GError **error) +read_headers (SoupMessage *msg, gboolean blocking, + GCancellable *cancellable, GError **error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; @@ -180,7 +180,7 @@ read_headers (SoupMessage *msg, GCancellable *cancellable, GError **error) nread = soup_filter_input_stream_read_line (io->istream, io->read_header_buf->data + old_len, RESPONSE_BLOCK_SIZE, - io->blocking, + blocking, &got_lf, cancellable, error); io->read_header_buf->len = old_len + MAX (nread, 0); @@ -303,7 +303,8 @@ soup_message_setup_body_istream (GInputStream *body_stream, * socket not writable, write is complete, etc). */ static gboolean -io_write (SoupMessage *msg, GCancellable *cancellable, GError **error) +io_write (SoupMessage *msg, gboolean blocking, + GCancellable *cancellable, GError **error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; @@ -322,7 +323,7 @@ io_write (SoupMessage *msg, GCancellable *cancellable, GError **error) nwrote = g_pollable_stream_write (io->ostream, io->write_buf->str + io->written, io->write_buf->len - io->written, - io->blocking, + blocking, cancellable, error); if (nwrote == -1) return FALSE; @@ -414,7 +415,7 @@ io_write (SoupMessage *msg, GCancellable *cancellable, GError **error) nwrote = g_pollable_stream_write (io->body_ostream, io->write_chunk->data + io->written, io->write_chunk->length - io->written, - io->blocking, + blocking, cancellable, error); if (nwrote == -1) return FALSE; @@ -486,7 +487,8 @@ io_write (SoupMessage *msg, GCancellable *cancellable, GError **error) * socket not readable, read is complete, etc). */ static gboolean -io_read (SoupMessage *msg, GCancellable *cancellable, GError **error) +io_read (SoupMessage *msg, gboolean blocking, + GCancellable *cancellable, GError **error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; @@ -497,7 +499,7 @@ io_read (SoupMessage *msg, GCancellable *cancellable, GError **error) switch (io->read_state) { case SOUP_MESSAGE_IO_STATE_HEADERS: - if (!read_headers (msg, cancellable, error)) + if (!read_headers (msg, blocking, cancellable, error)) return FALSE; status = io->parse_headers_cb (msg, (char *)io->read_header_buf->data, @@ -608,7 +610,8 @@ io_read (SoupMessage *msg, GCancellable *cancellable, GError **error) const char *content_type; GHashTable *params; - if (!soup_content_sniffer_stream_is_ready (sniffer_stream, io->blocking, cancellable, error)) + if (!soup_content_sniffer_stream_is_ready (sniffer_stream, blocking, + cancellable, error)) return FALSE; content_type = soup_content_sniffer_stream_sniff (sniffer_stream, ¶ms); @@ -638,7 +641,7 @@ io_read (SoupMessage *msg, GCancellable *cancellable, GError **error) nread = g_pollable_stream_read (io->body_istream, (guchar *)buffer->data, buffer->length, - io->blocking, + blocking, cancellable, error); if (nread > 0) { buffer->length = nread; @@ -829,7 +832,7 @@ request_is_restartable (SoupMessage *msg, GError *error) } static gboolean -io_run_until (SoupMessage *msg, +io_run_until (SoupMessage *msg, gboolean blocking, SoupMessageIOState read_state, SoupMessageIOState write_state, GCancellable *cancellable, GError **error) { @@ -853,9 +856,9 @@ io_run_until (SoupMessage *msg, (io->read_state < read_state || io->write_state < write_state)) { if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state)) - progress = io_read (msg, cancellable, &my_error); + progress = io_read (msg, blocking, cancellable, &my_error); else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state)) - progress = io_write (msg, cancellable, &my_error); + progress = io_write (msg, blocking, cancellable, &my_error); else progress = FALSE; } @@ -887,7 +890,7 @@ io_run_until (SoupMessage *msg, done = (io->read_state >= read_state && io->write_state >= write_state); - if (io->paused && !done) { + if (!blocking && !done) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, _("Operation would block")); @@ -899,8 +902,17 @@ io_run_until (SoupMessage *msg, return done; } +static void io_run (SoupMessage *msg, gboolean blocking); + static gboolean -io_run (SoupMessage *msg, gpointer user_data) +io_run_ready (SoupMessage *msg, gpointer user_data) +{ + io_run (msg, FALSE); + return FALSE; +} + +static void +io_run (SoupMessage *msg, gboolean blocking) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; @@ -916,14 +928,14 @@ io_run (SoupMessage *msg, gpointer user_data) g_object_ref (msg); cancellable = io->cancellable ? g_object_ref (io->cancellable) : NULL; - if (io_run_until (msg, + if (io_run_until (msg, blocking, SOUP_MESSAGE_IO_STATE_DONE, SOUP_MESSAGE_IO_STATE_DONE, cancellable, &error)) { soup_message_io_finished (msg); } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_clear_error (&error); - io->io_source = soup_message_io_get_source (msg, NULL, io_run, msg); + io->io_source = soup_message_io_get_source (msg, NULL, io_run_ready, msg); g_source_attach (io->io_source, io->async_context); } else if (error && priv->io_data == io) { if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) @@ -942,25 +954,23 @@ io_run (SoupMessage *msg, gpointer user_data) g_object_unref (msg); g_clear_object (&cancellable); - - return FALSE; } gboolean -soup_message_io_run_until_write (SoupMessage *msg, +soup_message_io_run_until_write (SoupMessage *msg, gboolean blocking, GCancellable *cancellable, GError **error) { - return io_run_until (msg, + return io_run_until (msg, blocking, SOUP_MESSAGE_IO_STATE_ANY, SOUP_MESSAGE_IO_STATE_BODY, cancellable, error); } gboolean -soup_message_io_run_until_read (SoupMessage *msg, +soup_message_io_run_until_read (SoupMessage *msg, gboolean blocking, GCancellable *cancellable, GError **error) { - return io_run_until (msg, + return io_run_until (msg, blocking, SOUP_MESSAGE_IO_STATE_BODY, SOUP_MESSAGE_IO_STATE_ANY, cancellable, error); @@ -968,12 +978,13 @@ soup_message_io_run_until_read (SoupMessage *msg, gboolean soup_message_io_run_until_finish (SoupMessage *msg, + gboolean blocking, GCancellable *cancellable, GError **error) { g_object_ref (msg); - if (!io_run_until (msg, + if (!io_run_until (msg, blocking, SOUP_MESSAGE_IO_STATE_DONE, SOUP_MESSAGE_IO_STATE_DONE, cancellable, error)) { @@ -1045,11 +1056,8 @@ new_iostate (SoupMessage *msg, GIOStream *iostream, io->istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (iostream)); io->ostream = g_io_stream_get_output_stream (iostream); - if (async_context) { + if (async_context) io->async_context = g_main_context_ref (async_context); - io->blocking = FALSE; - } else - io->blocking = TRUE; io->read_header_buf = g_byte_array_new (); io->write_buf = g_string_new (NULL); @@ -1088,8 +1096,13 @@ soup_message_io_client (SoupMessageQueueItem *item, io->write_body = item->msg->request_body; io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS; - if (!item->new_api) - io_run (item->msg, NULL); + + if (!item->new_api) { + gboolean blocking = + SOUP_IS_SESSION_SYNC (item->session) || + (!SOUP_IS_SESSION_ASYNC (item->session) && !item->async); + io_run (item->msg, blocking); + } } void @@ -1112,7 +1125,7 @@ soup_message_io_server (SoupMessage *msg, io->write_body = msg->response_body; io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS; - io_run (msg, NULL); + io_run (msg, FALSE); } void @@ -1155,7 +1168,7 @@ io_unpause_internal (gpointer msg) if (io->io_source) return FALSE; - io_run (msg, NULL); + io_run (msg, FALSE); return FALSE; } @@ -1173,13 +1186,10 @@ soup_message_io_unpause (SoupMessage *msg) return; } - if (!io->blocking) { - if (!io->unpause_source) { - io->unpause_source = soup_add_completion_reffed ( - io->async_context, io_unpause_internal, msg); - } - } else - io_unpause_internal (msg); + if (!io->unpause_source) { + io->unpause_source = soup_add_completion_reffed (io->async_context, + io_unpause_internal, msg); + } } /** diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index 356b96db..35cc9887 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -105,12 +105,15 @@ void soup_message_io_unpause (SoupMessage *msg); gboolean soup_message_io_in_progress (SoupMessage *msg); gboolean soup_message_io_run_until_write (SoupMessage *msg, + gboolean blocking, GCancellable *cancellable, GError **error); gboolean soup_message_io_run_until_read (SoupMessage *msg, + gboolean blocking, GCancellable *cancellable, GError **error); gboolean soup_message_io_run_until_finish (SoupMessage *msg, + gboolean blocking, GCancellable *cancellable, GError **error); diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 85ef1b25..a9258ef7 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3767,7 +3767,7 @@ try_run_until_read (SoupMessageQueueItem *item) GError *error = NULL; GInputStream *stream = NULL; - if (soup_message_io_run_until_read (item->msg, item->cancellable, &error)) + if (soup_message_io_run_until_read (item->msg, FALSE, item->cancellable, &error)) stream = soup_message_io_get_response_istream (item->msg, &error); if (stream) { send_async_maybe_complete (item, stream); @@ -4157,7 +4157,7 @@ soup_session_send (SoupSession *session, break; /* Send request, read headers */ - if (!soup_message_io_run_until_read (msg, item->cancellable, &my_error)) { + if (!soup_message_io_run_until_read (msg, TRUE, item->cancellable, &my_error)) { if (g_error_matches (my_error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) { item->state = SOUP_MESSAGE_RESTARTING; soup_message_io_finished (item->msg); -- cgit v1.2.1 From a5d3351caf88824db7de968f312565851d47840a Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 29 Sep 2013 09:04:11 -0400 Subject: test-utils: set GSETTINGS_BACKEND=memory To ensure we don't get unwanted proxy settings, and so we don't get warnings if the memory backend is the only one available. --- tests/test-utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test-utils.c b/tests/test-utils.c index 248f2fe8..0b739393 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -82,6 +82,7 @@ test_init (int argc, char **argv, GOptionEntry *entries) GTlsBackend *tls_backend; setlocale (LC_ALL, ""); + g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); name = strrchr (argv[0], '/'); if (!name++) -- cgit v1.2.1 From 96da2df64c9dd8cc52e97ce73e54615d6b520664 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 29 Sep 2013 09:06:37 -0400 Subject: Fix soup_client_input_stream_close to not block Closing a SoupClientInputStream for a message that hadn't been completely read was trying to read to the end of the message first. Fix it to just cancel the read instead. Also fix a few tests that were implicitly assuming the old behavior. https://bugzilla.gnome.org/show_bug.cgi?id=695652 --- libsoup/soup-client-input-stream.c | 12 +++-- libsoup/soup-message-io.c | 10 ++++ tests/redirect-test.c | 8 ++++ tests/requester-test.c | 94 +++++++++++++++++++++++++++++++++++++- tests/test-utils.c | 33 +++++++++++++ tests/test-utils.h | 4 ++ tests/timeout-test.c | 9 ++++ 7 files changed, 163 insertions(+), 7 deletions(-) diff --git a/libsoup/soup-client-input-stream.c b/libsoup/soup-client-input-stream.c index d73fb007..87fa49d6 100644 --- a/libsoup/soup-client-input-stream.c +++ b/libsoup/soup-client-input-stream.c @@ -187,11 +187,13 @@ soup_client_input_stream_close_async (GInputStream *stream, task = g_task_new (stream, cancellable, callback, user_data); g_task_set_priority (task, priority); - source = soup_message_io_get_source (cistream->priv->msg, - cancellable, NULL, NULL); - - g_task_attach_source (task, source, (GSourceFunc) close_async_ready); - g_source_unref (source); + if (close_async_ready (cistream->priv->msg, task) == G_SOURCE_CONTINUE) { + source = soup_message_io_get_source (cistream->priv->msg, + cancellable, NULL, NULL); + + g_task_attach_source (task, source, (GSourceFunc) close_async_ready); + g_source_unref (source); + } } static gboolean diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index f5f4c514..16a74e11 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -982,8 +982,18 @@ soup_message_io_run_until_finish (SoupMessage *msg, GCancellable *cancellable, GError **error) { + SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupMessageIOData *io = priv->io_data; + g_object_ref (msg); + if (io) { + g_return_if_fail (io->mode == SOUP_MESSAGE_IO_CLIENT); + + if (io->read_state < SOUP_MESSAGE_IO_STATE_BODY_DONE) + io->read_state = SOUP_MESSAGE_IO_STATE_BODY_DONE; + } + if (!io_run_until (msg, blocking, SOUP_MESSAGE_IO_STATE_DONE, SOUP_MESSAGE_IO_STATE_DONE, diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 9bc4621d..2b4fb5ea 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -285,6 +285,14 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) return; } + soup_test_request_read_all (SOUP_REQUEST (reqh), stream, NULL, &error); + if (error) { + debug_printf (1, " could not read from stream: %s\n", + error->message); + g_error_free (error); + errors++; + } + soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error); if (error) { debug_printf (1, " could not close stream: %s\n", diff --git a/tests/requester-test.c b/tests/requester-test.c index 6e169ad0..cfa9fcd6 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -37,6 +37,23 @@ get_index (void) strlen (AUTH_HTML_BODY)); } +static gboolean +slow_finish_message (gpointer msg) +{ + SoupServer *server = g_object_get_data (G_OBJECT (msg), "server"); + + soup_server_unpause_message (server, msg); + return FALSE; +} + +static void +slow_pause_message (SoupMessage *msg, gpointer server) +{ + soup_server_pause_message (server, msg); + soup_add_timeout (soup_server_get_async_context (server), + 1000, slow_finish_message, msg); +} + static void server_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, @@ -70,6 +87,10 @@ server_callback (SoupServer *server, SoupMessage *msg, } else if (strcmp (path, "/non-persistent") == 0) { soup_message_headers_append (msg->response_headers, "Connection", "close"); + } else if (!strcmp (path, "/slow")) { + g_object_set_data (G_OBJECT (msg), "server", server); + g_signal_connect (msg, "wrote-headers", + G_CALLBACK (slow_pause_message), server); } soup_message_set_status (msg, SOUP_STATUS_OK); @@ -670,6 +691,7 @@ do_null_char_request (SoupSession *session, const char *encoded_data, if (error) { debug_printf (1, " could not send request: %s\n", error->message); + errors++; g_error_free (error); g_object_unref (request); soup_uri_free (uri); @@ -720,8 +742,8 @@ do_null_char_test (gboolean plain_session) }; static int num_test_cases = G_N_ELEMENTS(test_cases); - debug_printf (1, "Streaming data URLs containing null chars with %s\n", - plain_session ? "SoupSession" : "SoupSessionSync"); + debug_printf (1, "\nStreaming data URLs containing null chars with %s\n", + plain_session ? "SoupSession" : "SoupSessionAsync"); session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, @@ -734,6 +756,72 @@ do_null_char_test (gboolean plain_session) soup_test_session_abort_unref (session); } +static void +do_close_test_for_session (SoupSession *session, + SoupURI *uri) +{ + GError *error = NULL; + GInputStream *stream; + SoupRequest *request; + guint64 start, end; + + request = soup_session_request_uri (session, uri, NULL); + stream = soup_test_request_send (request, NULL, 0, &error); + + if (error) { + debug_printf (1, " could not send request: %s\n", error->message); + errors++; + g_error_free (error); + g_object_unref (request); + return; + } + + start = g_get_monotonic_time (); + soup_test_request_close_stream (request, stream, NULL, &error); + if (error) { + debug_printf (1, " could not close stream: %s\n", error->message); + errors++; + g_clear_error (&error); + } + end = g_get_monotonic_time (); + + if (end - start > 500000) { + debug_printf (1, " close() waited for response to complete!\n"); + errors++; + } + + g_object_unref (stream); + g_object_unref (request); +} + +static void +do_close_tests (const char *uri) +{ + SoupSession *session; + SoupURI *slow_uri; + + debug_printf (1, "\nClosing stream before end should cancel\n"); + + slow_uri = soup_uri_new (uri); + soup_uri_set_path (slow_uri, "/slow"); + + debug_printf (1, " async\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_close_test_for_session (session, slow_uri); + soup_test_session_abort_unref (session); + + debug_printf (1, " sync\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_close_test_for_session (session, slow_uri); + soup_test_session_abort_unref (session); + + soup_uri_free (slow_uri); +} + int main (int argc, char **argv) { @@ -759,6 +847,8 @@ main (int argc, char **argv) do_sync_test (uri, TRUE); do_null_char_test (TRUE); + do_close_tests (uri); + g_free (uri); soup_buffer_free (response); soup_buffer_free (auth_response); diff --git a/tests/test-utils.c b/tests/test-utils.c index 0b739393..9848d9ba 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -492,6 +492,39 @@ soup_test_request_send (SoupRequest *req, return stream; } +gboolean +soup_test_request_read_all (SoupRequest *req, + GInputStream *stream, + GCancellable *cancellable, + GError **error) +{ + char buf[8192]; + AsyncAsSyncData data; + gsize nread; + + if (!SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + data.loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + + do { + if (SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) { + nread = g_input_stream_read (stream, buf, sizeof (buf), + cancellable, error); + } else { + g_input_stream_read_async (stream, buf, sizeof (buf), + G_PRIORITY_DEFAULT, cancellable, + async_as_sync_callback, &data); + g_main_loop_run (data.loop); + nread = g_input_stream_read_finish (stream, data.result, error); + g_object_unref (data.result); + } + } while (nread > 0); + + if (!SOUP_IS_SESSION_SYNC (soup_request_get_session (req))) + g_main_loop_unref (data.loop); + + return nread == 0; +} + gboolean soup_test_request_close_stream (SoupRequest *req, GInputStream *stream, diff --git a/tests/test-utils.h b/tests/test-utils.h index 98d93393..c85103d8 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -44,6 +44,10 @@ GInputStream *soup_test_request_send (SoupRequest *req, GCancellable *cancellable, guint flags, GError **error); +gboolean soup_test_request_read_all (SoupRequest *req, + GInputStream *stream, + GCancellable *cancellable, + GError **error); gboolean soup_test_request_close_stream (SoupRequest *req, GInputStream *stream, GCancellable *cancellable, diff --git a/tests/timeout-test.c b/tests/timeout-test.c index 405ec3c1..5903069b 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -147,6 +147,15 @@ do_request_to_session (SoupSession *session, const char *uri, } g_clear_error (&error); + if (stream) { + soup_test_request_read_all (req, stream, NULL, &error); + if (error) { + debug_printf (1, " ERROR reading stream: %s\n", + error->message); + errors++; + } + } + if (stream) { soup_test_request_close_stream (req, stream, NULL, &error); -- cgit v1.2.1 From d1cb3455a7278a7a5d8ac770852ae489a54e6452 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 29 Sep 2013 16:23:53 -0400 Subject: soup-session: don't resolve default proxy-resolver/tlsdb if not needed If the user overrides the proxy or TLS configuration of a session at construct time, we should avoid ever trying to resolve the default extensions. https://bugzilla.gnome.org/show_bug.cgi?id=708696 --- libsoup/soup-session.c | 62 +++++++++++++++++++---- tests/session-test.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 10 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index a9258ef7..bd586cd3 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -88,6 +88,7 @@ typedef struct { GTlsDatabase *tlsdb; char *ssl_ca_file; gboolean ssl_strict; + gboolean tlsdb_use_default; SoupMessageQueue *queue; @@ -122,6 +123,7 @@ typedef struct { GResolver *resolver; GProxyResolver *proxy_resolver; + gboolean proxy_use_default; SoupURI *proxy_uri; char **http_aliases, **https_aliases; @@ -268,9 +270,6 @@ soup_session_constructor (GType type, SoupSession *session = SOUP_SESSION (object); SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - g_clear_object (&priv->tlsdb); - priv->tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); - g_clear_pointer (&priv->async_context, g_main_context_unref); priv->async_context = g_main_context_ref_thread_default (); priv->use_thread_context = TRUE; @@ -279,7 +278,12 @@ soup_session_constructor (GType type, priv->http_aliases[0] = NULL; - priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ()); + /* If the user overrides the proxy or tlsdb during construction, + * we don't want to needlessly resolve the extension point. So + * we just set flags saying to do it later. + */ + priv->proxy_use_default = TRUE; + priv->tlsdb_use_default = TRUE; soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); } @@ -435,6 +439,7 @@ set_tlsdb (SoupSession *session, GTlsDatabase *tlsdb) SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); GTlsDatabase *system_default; + priv->tlsdb_use_default = FALSE; if (tlsdb == priv->tlsdb) return; @@ -470,6 +475,8 @@ set_use_system_ca_file (SoupSession *session, gboolean use_system_ca_file) SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); GTlsDatabase *system_default; + priv->tlsdb_use_default = FALSE; + system_default = g_tls_backend_get_default_database (g_tls_backend_get_default ()); if (use_system_ca_file) @@ -487,6 +494,7 @@ set_ssl_ca_file (SoupSession *session, const char *ssl_ca_file) GTlsDatabase *tlsdb; GError *error = NULL; + priv->tlsdb_use_default = FALSE; if (!g_strcmp0 (priv->ssl_ca_file, ssl_ca_file)) return; @@ -562,6 +570,7 @@ set_proxy_resolver (SoupSession *session, SoupURI *uri, G_GNUC_END_IGNORE_DEPRECATIONS; g_clear_object (&priv->proxy_resolver); g_clear_pointer (&priv->proxy_uri, soup_uri_free); + priv->proxy_use_default = FALSE; if (uri) { char *uri_string; @@ -711,6 +720,30 @@ soup_session_set_property (GObject *object, guint prop_id, } } +static GProxyResolver * +get_proxy_resolver (SoupSession *session) +{ + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + + if (priv->proxy_use_default) { + priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ()); + priv->proxy_use_default = FALSE; + } + return priv->proxy_resolver; +} + +static GTlsDatabase * +get_tls_database (SoupSession *session) +{ + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + + if (priv->tlsdb_use_default) { + priv->tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); + priv->tlsdb_use_default = FALSE; + } + return priv->tlsdb; +} + static void soup_session_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) @@ -728,7 +761,7 @@ soup_session_get_property (GObject *object, guint prop_id, g_value_set_boxed (value, priv->proxy_uri); break; case PROP_PROXY_RESOLVER: - g_value_set_object (value, priv->proxy_resolver); + g_value_set_object (value, get_proxy_resolver (session)); break; case PROP_MAX_CONNS: g_value_set_int (value, priv->max_conns); @@ -748,11 +781,11 @@ soup_session_get_property (GObject *object, guint prop_id, break; case PROP_SSL_USE_SYSTEM_CA_FILE: tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); - g_value_set_boolean (value, priv->tlsdb == tlsdb); + g_value_set_boolean (value, get_tls_database (session) == tlsdb); g_clear_object (&tlsdb); break; case PROP_TLS_DATABASE: - g_value_set_object (value, priv->tlsdb); + g_value_set_object (value, get_tls_database (session)); break; case PROP_SSL_STRICT: g_value_set_boolean (value, priv->ssl_strict); @@ -1609,6 +1642,8 @@ get_connection_for_host (SoupSession *session, SoupConnection *conn; GSList *conns; int num_pending = 0; + GProxyResolver *proxy_resolver; + GTlsDatabase *tlsdb; if (priv->disposed) return FALSE; @@ -1645,13 +1680,16 @@ get_connection_for_host (SoupSession *session, return NULL; } + proxy_resolver = get_proxy_resolver (session); + tlsdb = get_tls_database (session); + conn = g_object_new ( SOUP_TYPE_CONNECTION, SOUP_CONNECTION_REMOTE_URI, host->uri, - SOUP_CONNECTION_PROXY_RESOLVER, priv->proxy_resolver, + SOUP_CONNECTION_PROXY_RESOLVER, proxy_resolver, SOUP_CONNECTION_SSL, soup_uri_is_https (soup_message_get_uri (item->msg), priv->https_aliases), - SOUP_CONNECTION_SSL_CREDENTIALS, priv->tlsdb, - SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (priv->tlsdb != NULL || SOUP_IS_PLAIN_SESSION (session)), + SOUP_CONNECTION_SSL_CREDENTIALS, tlsdb, + SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (tlsdb != NULL || SOUP_IS_PLAIN_SESSION (session)), SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context, SOUP_CONNECTION_USE_THREAD_CONTEXT, priv->use_thread_context, SOUP_CONNECTION_TIMEOUT, priv->io_timeout, @@ -2593,6 +2631,10 @@ soup_session_remove_feature_by_type (SoupSession *session, GType feature_type) goto restart; } } + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + if (g_type_is_a (feature_type, SOUP_TYPE_PROXY_URI_RESOLVER)) + priv->proxy_use_default = FALSE; + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; } else if (g_type_is_a (feature_type, SOUP_TYPE_REQUEST)) { SoupRequestClass *request_class; int i; diff --git a/tests/session-test.c b/tests/session-test.c index b8e224ea..d40e7766 100644 --- a/tests/session-test.c +++ b/tests/session-test.c @@ -263,6 +263,135 @@ do_priority_tests (char *uri) soup_test_session_abort_unref (session); } +static void +test_session_properties (const char *name, + SoupSession *session, + GProxyResolver *expected_proxy_resolver, + GTlsDatabase *expected_tls_database) +{ + GProxyResolver *proxy_resolver = NULL; + GTlsDatabase *tlsdb = NULL; + + g_object_get (G_OBJECT (session), + SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver, + SOUP_SESSION_TLS_DATABASE, &tlsdb, + NULL); + if (proxy_resolver != expected_proxy_resolver) { + debug_printf (1, " %s has %s proxy resolver!\n", + name, proxy_resolver ? (expected_proxy_resolver ? "wrong" : "a") : "no"); + errors++; + } + if (tlsdb != expected_tls_database) { + debug_printf (1, " %s has %s TLS database!\n", + name, tlsdb ? (expected_tls_database ? "wrong" : "a") : "no"); + errors++; + } + g_clear_object (&proxy_resolver); + g_clear_object (&tlsdb); +} + +static void +do_property_tests (void) +{ + SoupSession *session; + GProxyResolver *proxy_resolver, *default_proxy_resolver; + GTlsDatabase *tlsdb, *default_tlsdb; + SoupURI *uri; + + debug_printf (1, "\nTesting session init properties\n"); + + default_proxy_resolver = g_proxy_resolver_get_default (); + default_tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); + + /* NOTE: We intentionally do not use soup_test_session_new() here */ + + session = g_object_new (SOUP_TYPE_SESSION, + NULL); + test_session_properties ("Base plain session", session, + default_proxy_resolver, default_tlsdb); + g_object_unref (session); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_RESOLVER, NULL, + NULL); + test_session_properties ("Session with NULL :proxy-resolver", session, + NULL, default_tlsdb); + g_object_unref (session); + + proxy_resolver = g_simple_proxy_resolver_new (NULL, NULL); + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_RESOLVER, proxy_resolver, + NULL); + test_session_properties ("Session with non-NULL :proxy-resolver", session, + proxy_resolver, default_tlsdb); + g_object_unref (proxy_resolver); + g_object_unref (session); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_URI, NULL, + NULL); + test_session_properties ("Session with NULL :proxy-uri", session, + NULL, default_tlsdb); + g_object_unref (session); + + uri = soup_uri_new ("http://example.com/"); + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_PROXY_URI, uri, + NULL); + g_object_get (G_OBJECT (session), + SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver, + NULL); + test_session_properties ("Session with non-NULL :proxy-uri", session, + proxy_resolver, default_tlsdb); + if (!G_IS_SIMPLE_PROXY_RESOLVER (proxy_resolver)) { + debug_printf (1, " proxy resolver had wrong type (%s)\n", + G_OBJECT_TYPE_NAME (proxy_resolver)); + errors++; + } + g_object_unref (proxy_resolver); + g_object_unref (session); + soup_uri_free (uri); + + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_REMOVE_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_URI_RESOLVER, + NULL); + test_session_properties ("Session with removed proxy resolver feature", session, + NULL, default_tlsdb); + g_object_unref (session); + G_GNUC_END_IGNORE_DEPRECATIONS; + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_TLS_DATABASE, NULL, + NULL); + test_session_properties ("Session with NULL :tls-database", session, + default_proxy_resolver, NULL); + g_object_unref (session); + + tlsdb = g_tls_file_database_new (SRCDIR "/test-cert.pem", NULL); + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_TLS_DATABASE, tlsdb, + NULL); + test_session_properties ("Session with non-NULL :tls-database", session, + default_proxy_resolver, tlsdb); + g_object_unref (tlsdb); + g_object_unref (session); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE, + NULL); + test_session_properties ("Session with :ssl-use-system-ca-file FALSE", session, + default_proxy_resolver, NULL); + g_object_unref (session); + + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE, + NULL); + test_session_properties ("Session with :ssl-use-system-ca-file TRUE", session, + default_proxy_resolver, default_tlsdb); + g_object_unref (session); +} + int main (int argc, char **argv) { @@ -281,6 +410,7 @@ main (int argc, char **argv) do_async_tests (uri, timeout_uri); do_sync_tests (uri, timeout_uri); do_priority_tests (uri); + do_property_tests (); g_free (uri); g_free (timeout_uri); -- cgit v1.2.1 From fb2fddb3ed7e5a8c51d928bfe8be6f3e198d4a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Tue, 8 Oct 2013 15:57:54 +0200 Subject: SoupServer: check only for tls-certificate to know if a server is running plain http or https We can check only for "tls-certificate", once it's set whether "ssl-cert-file" and "ssl-key-file" are set. https://bugzilla.gnome.org/show_bug.cgi?id=709647 --- libsoup/soup-server.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index abda60ba..3d3070a2 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -788,7 +788,8 @@ soup_server_get_port (SoupServer *server) * * In order for a server to run https, you must set the * %SOUP_SERVER_SSL_CERT_FILE and %SOUP_SERVER_SSL_KEY_FILE properties - * to provide it with an SSL certificate to use. + * or %SOUP_SERVER_TLS_CERTIFICATE property to provide it with an SSL + * certificate to use. * * Return value: %TRUE if @server is serving https. **/ @@ -800,7 +801,7 @@ soup_server_is_https (SoupServer *server) g_return_val_if_fail (SOUP_IS_SERVER (server), 0); priv = SOUP_SERVER_GET_PRIVATE (server); - return (priv->ssl_cert_file && priv->ssl_key_file); + return priv->ssl_cert != NULL; } /** -- cgit v1.2.1 From bf4afcdaa5443cb9bc8829817b3a510010a99325 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 8 Oct 2013 13:12:56 -0400 Subject: tests: fix another test broken by the SoupClientInputStream close change One of connection-test's tests was failing (but only sporadically) because it closed the stream without reading it, causing the stream to be disconnected, while it was expecting the connection to stay open. --- tests/connection-test.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/connection-test.c b/tests/connection-test.c index cdc4cced..3d517539 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -325,6 +325,14 @@ do_timeout_req_test_for_session (SoupSession *session) errors++; g_clear_error (&error); } else { + soup_test_request_read_all (req, stream, NULL, &error); + if (error) { + debug_printf (1, " Unexpected error on read: %s\n", + error->message); + errors++; + g_clear_error (&error); + } + soup_test_request_close_stream (req, stream, NULL, &error); if (error) { debug_printf (1, " Unexpected error on close: %s\n", @@ -400,6 +408,7 @@ do_persistent_connection_timeout_test (void) do_timeout_test_for_session (session); soup_test_session_abort_unref (session); + debug_printf (1, " Async session, request API\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -411,6 +420,7 @@ do_persistent_connection_timeout_test (void) do_timeout_test_for_session (session); soup_test_session_abort_unref (session); + debug_printf (1, " Sync session, request API\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); do_timeout_req_test_for_session (session); soup_test_session_abort_unref (session); -- cgit v1.2.1 From 1e0656f8ceb6fb1eb019f3b083d3dfe610032b68 Mon Sep 17 00:00:00 2001 From: Victor Ibragimov Date: Thu, 10 Oct 2013 16:34:56 +0500 Subject: Tajik translation updated --- po/tg.po | 64 ++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/po/tg.po b/po/tg.po index c0ece901..c8332dd7 100644 --- a/po/tg.po +++ b/po/tg.po @@ -8,50 +8,50 @@ msgstr "" "Project-Id-Version: Tajik Gnome\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2013-03-07 15:08+0000\n" -"PO-Revision-Date: 2013-01-19 17:43+0500\n" +"POT-Creation-Date: 2013-07-28 11:48+0000\n" +"PO-Revision-Date: 2013-10-10 16:30+0500\n" "Last-Translator: Victor Ibragimov \n" "Language-Team: \n" "Language: Tajik\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.4\n" +"X-Generator: Poedit 1.5.7\n" -#: ../libsoup/soup-body-input-stream.c:141 -#: ../libsoup/soup-body-input-stream.c:172 -#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" -msgstr "" +msgstr "Пайвастшавӣ ногаҳон қатъ шудааст" -#: ../libsoup/soup-body-input-stream.c:463 +#: ../libsoup/soup-body-input-stream.c:462 msgid "Invalid seek request" -msgstr "" +msgstr "Дархости ҷустуҷӯи нодуруст" -#: ../libsoup/soup-body-input-stream.c:491 +#: ../libsoup/soup-body-input-stream.c:490 msgid "Cannot truncate SoupBodyInputStream" -msgstr "" +msgstr "SoupBodyInputStream кӯтоҳ карда намешавад" -#: ../libsoup/soup-cache-input-stream.c:74 +#: ../libsoup/soup-cache-input-stream.c:73 msgid "Network stream unexpectedly closed" -msgstr "" +msgstr "Ҷараёни шабака ногаҳон манъ карда шудааст" -#: ../libsoup/soup-cache-input-stream.c:291 +#: ../libsoup/soup-cache-input-stream.c:290 msgid "Failed to completely cache the resource" -msgstr "" +msgstr "Зерҳофизаи манбаъ комилан захира карда нашуд" #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" -msgstr "" +msgstr "Миёнҷии барориш хеле хурд аст" #: ../libsoup/soup-message-client-io.c:41 msgid "Could not parse HTTP response" -msgstr "" +msgstr "Ҷавоби HTTP таҷзия карда намешавад" #: ../libsoup/soup-message-client-io.c:66 msgid "Unrecognized HTTP response encoding" -msgstr "" +msgstr "Рамзгузории ҷавоби HTTP шинохта нашудааст" #: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" @@ -59,49 +59,49 @@ msgstr "Амалиёт бекор шудааст" #: ../libsoup/soup-message-io.c:893 msgid "Operation would block" -msgstr "" +msgstr "Амалиёт қатъ карда мешавад" #: ../libsoup/soup-message-server-io.c:40 msgid "Could not parse HTTP request" -msgstr "" +msgstr "Дархости HTTP таҷзия карда намешавад" #: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" -msgstr "" +msgstr "Ягон URI таъмин нашудааст" #: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" -msgstr "" +msgstr "Суроғаи '%s' URI нодуруст аст: %s" -#: ../libsoup/soup-session.c:4252 +#: ../libsoup/soup-session.c:4301 #, c-format msgid "Could not parse URI '%s'" -msgstr "" +msgstr "Суроғаи URI '%s' таҷзия карда нашуд" -#: ../libsoup/soup-session.c:4289 +#: ../libsoup/soup-session.c:4338 #, c-format msgid "Unsupported URI scheme '%s'" -msgstr "" +msgstr "Нақшаи суроғаи URI '%s' дастгирӣ намешавад" -#: ../libsoup/soup-session.c:4311 +#: ../libsoup/soup-session.c:4360 #, c-format msgid "Not an HTTP URI" -msgstr "" +msgstr "Суроғаи HTTP URI намебошад" #: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" -msgstr "" +msgstr "Номи мизбон суроғаи IP мебошад" #: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" -msgstr "" +msgstr "Номи мизбони нодуруст" #: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" -msgstr "" +msgstr "Номи мизбон домени асосӣ надорад" #: ../libsoup/soup-tld.c:257 msgid "Not enough domains" -msgstr "" +msgstr "Доменҳои кофӣ надорад" -- cgit v1.2.1 From e5fbda83f6045a610054b179ae60fc062bded101 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 10 Oct 2013 09:31:23 -0400 Subject: soup-uri: minor code reorg/renaming Change uri_decoded_copy() to strdup the input string *after* doing its g_return_val_if_fail(), to avoid pointlessly confusing code analyzers. Also, rename the function to soup_uri_decoded_copy(), since it's used from soup-request-data.c too and it's been annoying me that it was non-namespaced. https://bugzilla.gnome.org/show_bug.cgi?id=709793 --- libsoup/soup-misc-private.h | 2 +- libsoup/soup-request-data.c | 5 +++-- libsoup/soup-uri.c | 25 ++++++++++++++----------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index e9c83f61..7ea2cdea 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -10,7 +10,7 @@ #include "soup-socket.h" #include "soup-message-headers.h" -char *uri_decoded_copy (const char *str, int length, int *decoded_length); +char *soup_uri_decoded_copy (const char *str, int length, int *decoded_length); char *soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, gboolean force_port); gboolean soup_uri_is_http (SoupURI *uri, char **aliases); diff --git a/libsoup/soup-request-data.c b/libsoup/soup-request-data.c index 246854a7..678e84da 100644 --- a/libsoup/soup-request-data.c +++ b/libsoup/soup-request-data.c @@ -96,7 +96,7 @@ soup_request_data_send (SoupRequest *request, end = comma; if (end != start) - data->priv->content_type = uri_decoded_copy (start, end - start, NULL); + data->priv->content_type = soup_uri_decoded_copy (start, end - start, NULL); } memstream = g_memory_input_stream_new (); @@ -106,7 +106,8 @@ soup_request_data_send (SoupRequest *request, if (*start) { int decoded_length = 0; - guchar *buf = (guchar *) uri_decoded_copy (start, strlen (start), &decoded_length); + guchar *buf = (guchar *) soup_uri_decoded_copy (start, strlen (start), + &decoded_length); if (base64) buf = g_base64_decode_inplace ((gchar*) buf, &data->priv->content_length); diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index 808d2ccc..e3092dcf 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -293,15 +293,15 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) if (at && at < path) { colon = strchr (uri_string, ':'); if (colon && colon < at) { - uri->password = uri_decoded_copy (colon + 1, - at - colon - 1, NULL); + uri->password = soup_uri_decoded_copy (colon + 1, + at - colon - 1, NULL); } else { uri->password = NULL; colon = at; } - uri->user = uri_decoded_copy (uri_string, - colon - uri_string, NULL); + uri->user = soup_uri_decoded_copy (uri_string, + colon - uri_string, NULL); uri_string = at + 1; } else uri->user = uri->password = NULL; @@ -322,14 +322,16 @@ soup_uri_new_with_base (SoupURI *base, const char *uri_string) colon = NULL; pct = memchr (uri_string, '%', hostend - uri_string); - if (!pct || (pct[1] == '2' && pct[2] == '5')) - uri->host = uri_decoded_copy (uri_string, hostend - uri_string, NULL); - else + if (!pct || (pct[1] == '2' && pct[2] == '5')) { + uri->host = soup_uri_decoded_copy (uri_string, + hostend - uri_string, NULL); + } else uri->host = g_strndup (uri_string, hostend - uri_string); } else { colon = memchr (uri_string, ':', path - uri_string); hostend = colon ? colon : path; - uri->host = uri_decoded_copy (uri_string, hostend - uri_string, NULL); + uri->host = soup_uri_decoded_copy (uri_string, + hostend - uri_string, NULL); } if (colon && colon != path - 1) { @@ -719,13 +721,14 @@ soup_uri_encode (const char *part, const char *escape_extra) #define HEXCHAR(s) ((XDIGIT (s[1]) << 4) + XDIGIT (s[2])) char * -uri_decoded_copy (const char *part, int length, int *decoded_length) +soup_uri_decoded_copy (const char *part, int length, int *decoded_length) { unsigned char *s, *d; - char *decoded = g_strndup (part, length); + char *decoded; g_return_val_if_fail (part != NULL, NULL); + decoded = g_strndup (part, length); s = d = (unsigned char *)decoded; do { if (*s == '%') { @@ -763,7 +766,7 @@ soup_uri_decode (const char *part) { g_return_val_if_fail (part != NULL, NULL); - return uri_decoded_copy (part, strlen (part), NULL); + return soup_uri_decoded_copy (part, strlen (part), NULL); } static char * -- cgit v1.2.1 From 5acf257bb82d25cc821417aefda506e581117232 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 15 Oct 2013 09:57:44 -0400 Subject: 2.44.1 --- NEWS | 42 ++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a339bebc..aa7606e7 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,45 @@ +Changes in libsoup from 2.44.0 to 2.44.1: + + * If you called g_input_stream_close() on SoupMessage or + SoupRequests's GInputStream before you finished reading it, + it would block until the rest of the response had been read + (which in the case of, eg, an infinite audio stream, meant + that it would block forever). This was an unintended change + from 2.42 and is now fixed. [#695652, Dan] + + * soup_session_queue_message() on a plain SoupSession (not + SoupSessionAsync) was operating synchronously rather than + asynchronously as it should have. [#707711, Dan] + + * soup-form methods now use the HTML5 x-www-form-urlencoded + rules rather than the HTML4 ones. (In particular, they leave + "-", "_", and "." unencoded.) [#708621, Alban Browaeys] + + * The test programs now explicitly request the "memory" + GSettings backend, meaning they won't print a warning if + they get it accidentally, and they won't accidentally use + the dconf proxy settings if the dconf backend is available. + [Dan] + + * Fix SoupSession so that if you override the proxy + configuration at construct time, it doesn't try to resolve + the default GProxyResolver. (This is important in particular + for programs that expect to run outside a user session, + which would otherwise spew errors from the dconf GSettings + backend about not being able to connect to dconf.) Likewise + with TLS settings and the TLS backend. [#708696, Dan] + + * Fix the SoupServer:tls-certificate property; + soup_server_is_https() had not been updated to recognize it, + and so would return FALSE, which in turn meant that the + server would return 400 Bad Request in response to https + requests. [#709647, Fabiano Fidêncio] + + * Fixed a sporadic failure in tests/connection-test. [Dan] + + * Updated translations: + Tajik + Changes in libsoup from 2.43.92 to 2.44.0: * New/updated translations: diff --git a/configure.ac b/configure.ac index 9eee7a8e..5dd28f48 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [44]) -m4_define([soup_micro_version], [0]) +m4_define([soup_micro_version], [1]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 40e6a48ea7f2d1fb949d2843100e3f30cd2a73d5 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 15 Oct 2013 10:27:10 -0400 Subject: Post-branch release bump to 2.45.0 --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 5dd28f48..f498b963 100644 --- a/configure.ac +++ b/configure.ac @@ -3,8 +3,8 @@ dnl *** Initialize automake and set version *** dnl ******************************************* m4_define([soup_major_version], [2]) -m4_define([soup_minor_version], [44]) -m4_define([soup_micro_version], [1]) +m4_define([soup_minor_version], [45]) +m4_define([soup_micro_version], [0]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 3c96f1977a556b76bc768edeb78497a2e92dd898 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 17 Oct 2013 17:56:29 -0400 Subject: soup-logger: fix -Wformat-nonliteral warnings in clang --- configure.ac | 1 + libsoup/soup-logger.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f498b963..3759baba 100644 --- a/configure.ac +++ b/configure.ac @@ -340,6 +340,7 @@ if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then -Wall -Wstrict-prototypes -Werror=missing-prototypes \ -Werror=implicit-function-declaration \ -Werror=pointer-arith -Werror=init-self -Werror=format=2 \ + -Wno-format-zero-length \ -Werror=missing-include-dirs -Werror=aggregate-return \ -Werror=declaration-after-statement" fi diff --git a/libsoup/soup-logger.c b/libsoup/soup-logger.c index a441f211..34a55764 100644 --- a/libsoup/soup-logger.c +++ b/libsoup/soup-logger.c @@ -374,6 +374,9 @@ soup_logger_detach (SoupLogger *logger, soup_session_remove_feature (session, SOUP_SESSION_FEATURE (logger)); } +static void soup_logger_print (SoupLogger *logger, SoupLoggerLogLevel level, + char direction, const char *format, ...) G_GNUC_PRINTF (4, 5); + static void soup_logger_print (SoupLogger *logger, SoupLoggerLogLevel level, char direction, const char *format, ...) @@ -434,7 +437,7 @@ soup_logger_print_basic_auth (SoupLogger *logger, const char *value) *p = '*'; } soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>', - "Authorization: Basic [%.*s]", len, decoded); + "Authorization: Basic [%.*s]", (int)len, decoded); g_free (decoded); } -- cgit v1.2.1 From 38cbd9905ea3f87bab16663a90375dbd48b75b49 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 17 Oct 2013 18:03:05 -0400 Subject: soup-auth-ntlm: fix build with --without-ntlm-auth https://bugzilla.gnome.org/show_bug.cgi?id=710267 --- libsoup/soup-auth-ntlm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsoup/soup-auth-ntlm.c b/libsoup/soup-auth-ntlm.c index 19be6928..05541973 100644 --- a/libsoup/soup-auth-ntlm.c +++ b/libsoup/soup-auth-ntlm.c @@ -309,13 +309,17 @@ soup_auth_ntlm_update_connection (SoupConnectionAuth *auth, SoupMessage *msg, return TRUE; } +#ifdef USE_NTLM_AUTH if (priv->sso_available) { conn->state = SOUP_NTLM_SSO_FAILED; priv->password_state = SOUP_NTLM_PASSWORD_NONE; } else { +#endif conn->state = SOUP_NTLM_FAILED; priv->password_state = SOUP_NTLM_PASSWORD_REJECTED; +#ifdef USE_NTLM_AUTH } +#endif return TRUE; } -- cgit v1.2.1 From caa68752e295d48a3d1d9c6e5334f6c17a576000 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 19 Oct 2013 12:11:34 -0400 Subject: soup-message-io: fix early SoupClientInputStream close case When closing the stream early, we should be skipping the read state ahead to FINISHING, rather than BODY_DONE, so that got_body doesn't get emitted (thus causing the connection to mark itself reusable). https://bugzilla.gnome.org/show_bug.cgi?id=710494 --- libsoup/soup-message-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 16a74e11..03dc4333 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -991,7 +991,7 @@ soup_message_io_run_until_finish (SoupMessage *msg, g_return_if_fail (io->mode == SOUP_MESSAGE_IO_CLIENT); if (io->read_state < SOUP_MESSAGE_IO_STATE_BODY_DONE) - io->read_state = SOUP_MESSAGE_IO_STATE_BODY_DONE; + io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; } if (!io_run_until (msg, blocking, -- cgit v1.2.1 From 88103312ffac176b8ffeb159bd75fc3bbe2c452e Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 4 Jul 2013 11:35:29 -0400 Subject: SoupSocket: make handshaking methods gio-like and update SoupConnection to use them --- libsoup/soup-connection.c | 150 ++++++++++++++++++++++-------------------- libsoup/soup-misc-private.h | 18 +++-- libsoup/soup-socket.c | 155 ++++++++++++++++++++++---------------------- 3 files changed, 170 insertions(+), 153 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 00fe72b9..f8b6cef7 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -451,12 +451,12 @@ typedef struct { } SoupConnectionAsyncConnectData; static void -socket_connect_finished (SoupSocket *socket, guint status, gpointer user_data) +socket_connect_finished (SoupConnectionAsyncConnectData *data, guint status) { - SoupConnectionAsyncConnectData *data = user_data; SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); - g_signal_handler_disconnect (socket, data->event_id); + if (priv->socket) + g_signal_handler_disconnect (priv->socket, data->event_id); if (SOUP_STATUS_IS_SUCCESSFUL (status)) { if (priv->ssl && !priv->proxy_uri) { @@ -473,9 +473,6 @@ socket_connect_finished (SoupSocket *socket, guint status, gpointer user_data) soup_connection_set_state (data->conn, SOUP_CONNECTION_IN_USE); priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; start_idle_timer (data->conn); - } else if (status == SOUP_STATUS_TLS_FAILED) { - priv->ssl_fallback = TRUE; - status = SOUP_STATUS_TRY_AGAIN; } if (data->callback) { @@ -489,6 +486,31 @@ socket_connect_finished (SoupSocket *socket, guint status, gpointer user_data) g_slice_free (SoupConnectionAsyncConnectData, data); } + +static void +socket_handshake_complete (GObject *object, GAsyncResult *result, gpointer user_data) +{ + SoupConnectionAsyncConnectData *data = user_data; + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); + GError *error = NULL; + guint status; + + if (priv->async_context && !priv->use_thread_context) + g_main_context_pop_thread_default (priv->async_context); + + if (soup_socket_handshake_finish (priv->socket, result, &error)) + status = SOUP_STATUS_OK; + else if (!priv->ssl_fallback && + g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { + priv->ssl_fallback = TRUE; + status = SOUP_STATUS_TRY_AGAIN; + } else + status = SOUP_STATUS_SSL_FAILED; + g_clear_error (&error); + + socket_connect_finished (data, status); +} + static void socket_connect_result (SoupSocket *sock, guint status, gpointer user_data) { @@ -496,26 +518,26 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data) SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - socket_connect_finished (sock, status, data); + socket_connect_finished (data, status); return; } priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); if (priv->ssl && !priv->proxy_uri) { - if (soup_socket_start_ssl (sock, data->cancellable)) { - soup_connection_event (data->conn, - G_SOCKET_CLIENT_TLS_HANDSHAKING, - NULL); - soup_socket_handshake_async (sock, data->cancellable, - socket_connect_finished, data); - return; - } - - status = SOUP_STATUS_SSL_FAILED; + soup_connection_event (data->conn, + G_SOCKET_CLIENT_TLS_HANDSHAKING, + NULL); + + if (priv->async_context && !priv->use_thread_context) + g_main_context_push_thread_default (priv->async_context); + soup_socket_handshake_async (sock, priv->remote_uri->host, + data->cancellable, + socket_handshake_complete, data); + return; } - socket_connect_finished (sock, status, data); + socket_connect_finished (data, status); } void @@ -601,22 +623,25 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); if (priv->ssl && !priv->proxy_uri) { - if (!soup_socket_start_ssl (priv->socket, cancellable)) - status = SOUP_STATUS_SSL_FAILED; - else { + GError *error = NULL; + + soup_connection_event (conn, + G_SOCKET_CLIENT_TLS_HANDSHAKING, + NULL); + if (soup_socket_handshake_sync (priv->socket, + priv->remote_uri->host, + cancellable, &error)) { soup_connection_event (conn, - G_SOCKET_CLIENT_TLS_HANDSHAKING, + G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); - status = soup_socket_handshake_sync (priv->socket, cancellable); - if (status == SOUP_STATUS_OK) { - soup_connection_event (conn, - G_SOCKET_CLIENT_TLS_HANDSHAKED, - NULL); - } else if (status == SOUP_STATUS_TLS_FAILED) { - priv->ssl_fallback = TRUE; - status = SOUP_STATUS_TRY_AGAIN; - } - } + status = SOUP_STATUS_OK; + } else if (!priv->ssl_fallback && + g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { + priv->ssl_fallback = TRUE; + status = SOUP_STATUS_TRY_AGAIN; + } else + status = SOUP_STATUS_SSL_FAILED; + g_clear_error (&error); } if (SOUP_STATUS_IS_SUCCESSFUL (status)) { @@ -656,21 +681,19 @@ soup_connection_start_ssl_sync (SoupConnection *conn, { SoupConnectionPrivate *priv; guint status; + GError *error = NULL; g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - if (!soup_socket_start_proxy_ssl (priv->socket, - priv->remote_uri->host, - cancellable)) - return SOUP_STATUS_SSL_FAILED; - soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); - status = soup_socket_handshake_sync (priv->socket, cancellable); - if (status == SOUP_STATUS_OK) { + if (soup_socket_handshake_sync (priv->socket, priv->remote_uri->host, + cancellable, &error)) { soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); - } else if (status == SOUP_STATUS_TLS_FAILED) { + status = SOUP_STATUS_OK; + } else if (!priv->ssl_fallback && + g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { priv->ssl_fallback = TRUE; status = SOUP_STATUS_TRY_AGAIN; } @@ -679,33 +702,33 @@ soup_connection_start_ssl_sync (SoupConnection *conn, } static void -start_ssl_completed (SoupSocket *socket, guint status, gpointer user_data) +start_ssl_completed (GObject *object, GAsyncResult *result, gpointer user_data) { SoupConnectionAsyncConnectData *data = user_data; SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); + guint status; + GError *error = NULL; - if (status == SOUP_STATUS_OK) { + if (priv->async_context && !priv->use_thread_context) + g_main_context_pop_thread_default (priv->async_context); + + if (soup_socket_handshake_finish (priv->socket, result, &error)) { soup_connection_event (data->conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); soup_connection_event (data->conn, G_SOCKET_CLIENT_COMPLETE, NULL); - } else if (status == SOUP_STATUS_TLS_FAILED) { + status = SOUP_STATUS_OK; + } else if (!priv->ssl_fallback && + g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { priv->ssl_fallback = TRUE; status = SOUP_STATUS_TRY_AGAIN; - } + } else + status = SOUP_STATUS_SSL_FAILED; + g_clear_error (&error); data->callback (data->conn, status, data->callback_data); g_object_unref (data->conn); g_slice_free (SoupConnectionAsyncConnectData, data); } -static gboolean -idle_start_ssl_completed (gpointer user_data) -{ - SoupConnectionAsyncConnectData *data = user_data; - - start_ssl_completed (NULL, SOUP_STATUS_SSL_FAILED, data); - return FALSE; -} - void soup_connection_start_ssl_async (SoupConnection *conn, GCancellable *cancellable, @@ -714,7 +737,6 @@ soup_connection_start_ssl_async (SoupConnection *conn, { SoupConnectionPrivate *priv; SoupConnectionAsyncConnectData *data; - GMainContext *async_context; g_return_if_fail (SOUP_IS_CONNECTION (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); @@ -724,22 +746,12 @@ soup_connection_start_ssl_async (SoupConnection *conn, data->callback = callback; data->callback_data = user_data; - if (priv->use_thread_context) - async_context = g_main_context_get_thread_default (); - else - async_context = priv->async_context; - - if (!soup_socket_start_proxy_ssl (priv->socket, - priv->remote_uri->host, - cancellable)) { - soup_add_completion (async_context, - idle_start_ssl_completed, data); - return; - } - soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); - soup_socket_handshake_async (priv->socket, cancellable, - start_ssl_completed, data); + + if (priv->async_context && !priv->use_thread_context) + g_main_context_push_thread_default (priv->async_context); + soup_socket_handshake_async (priv->socket, priv->remote_uri->host, + cancellable, start_ssl_completed, data); } /** diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index 7ea2cdea..948470ff 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -16,12 +16,18 @@ char *soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, gboolean soup_uri_is_http (SoupURI *uri, char **aliases); gboolean soup_uri_is_https (SoupURI *uri, char **aliases); -guint soup_socket_handshake_sync (SoupSocket *sock, - GCancellable *cancellable); -void soup_socket_handshake_async (SoupSocket *sock, - GCancellable *cancellable, - SoupSocketCallback callback, - gpointer user_data); +gboolean soup_socket_handshake_sync (SoupSocket *sock, + const char *host, + GCancellable *cancellable, + GError **error); +void soup_socket_handshake_async (SoupSocket *sock, + const char *host, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean soup_socket_handshake_finish (SoupSocket *sock, + GAsyncResult *result, + GError **error); GSocket *soup_socket_get_gsocket (SoupSocket *sock); GIOStream *soup_socket_get_connection (SoupSocket *sock); diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index baa9290c..9caf0d2c 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -1035,37 +1035,11 @@ soup_socket_accept_certificate (GTlsConnection *conn, GTlsCertificate *cert, return TRUE; } -/** - * soup_socket_start_ssl: - * @sock: the socket - * @cancellable: a #GCancellable - * - * Starts using SSL on @socket. - * - * Return value: success or failure - **/ -gboolean -soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable) -{ - SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); - - return soup_socket_start_proxy_ssl (sock, soup_address_get_name (priv->remote_addr), cancellable); -} - -/** - * soup_socket_start_proxy_ssl: - * @sock: the socket - * @ssl_host: hostname of the SSL server - * @cancellable: a #GCancellable - * - * Starts using SSL on @socket, expecting to find a host named - * @ssl_host. - * - * Return value: success or failure - **/ -gboolean -soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host, - GCancellable *cancellable) +static gboolean +soup_socket_setup_ssl (SoupSocket *sock, + const char *ssl_host, + GCancellable *cancellable, + GError **error) { SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); GTlsBackend *backend = g_tls_backend_get_default (); @@ -1073,7 +1047,7 @@ soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host, if (G_IS_TLS_CONNECTION (priv->conn)) return TRUE; - if (g_cancellable_is_cancelled (cancellable)) + if (g_cancellable_set_error_if_cancelled (cancellable, error)) return FALSE; priv->ssl = TRUE; @@ -1084,7 +1058,7 @@ soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host, identity = g_network_address_new (ssl_host, 0); conn = g_initable_new (g_tls_backend_get_client_connection_type (backend), - NULL, NULL, + cancellable, error, "base-io-stream", priv->conn, "server-identity", identity, "database", priv->ssl_creds, @@ -1108,7 +1082,7 @@ soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host, GTlsServerConnection *conn; conn = g_initable_new (g_tls_backend_get_server_connection_type (backend), - NULL, NULL, + cancellable, error, "base-io-stream", priv->conn, "certificate", priv->ssl_creds, "use-system-certdb", FALSE, @@ -1133,76 +1107,101 @@ soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host, return TRUE; } + +/** + * soup_socket_start_ssl: + * @sock: the socket + * @cancellable: a #GCancellable + * + * Starts using SSL on @socket. + * + * Return value: success or failure + **/ +gboolean +soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable) +{ + SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); + + return soup_socket_setup_ssl (sock, soup_address_get_name (priv->remote_addr), + cancellable, NULL); +} -guint +/** + * soup_socket_start_proxy_ssl: + * @sock: the socket + * @ssl_host: hostname of the SSL server + * @cancellable: a #GCancellable + * + * Starts using SSL on @socket, expecting to find a host named + * @ssl_host. + * + * Return value: success or failure + **/ +gboolean +soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host, + GCancellable *cancellable) +{ + return soup_socket_setup_ssl (sock, ssl_host, cancellable, NULL); +} + +gboolean soup_socket_handshake_sync (SoupSocket *sock, - GCancellable *cancellable) + const char *ssl_host, + GCancellable *cancellable, + GError **error) { SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); - GError *error = NULL; - priv->ssl = TRUE; - if (g_tls_connection_handshake (G_TLS_CONNECTION (priv->conn), - cancellable, &error)) - return SOUP_STATUS_OK; - else if (!priv->ssl_fallback && - g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { - g_error_free (error); - return SOUP_STATUS_TLS_FAILED; - } else { - g_error_free (error); - return SOUP_STATUS_SSL_FAILED; - } + if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, error)) + return FALSE; + + return g_tls_connection_handshake (G_TLS_CONNECTION (priv->conn), + cancellable, error); } static void handshake_async_ready (GObject *source, GAsyncResult *result, gpointer user_data) { - SoupSocketAsyncConnectData *data = user_data; - SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (data->sock); + GTask *task = user_data; GError *error = NULL; - guint status; - - if (priv->async_context && !priv->use_thread_context) - g_main_context_pop_thread_default (priv->async_context); if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (source), result, &error)) - status = SOUP_STATUS_OK; - else if (!priv->ssl_fallback && - g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) - status = SOUP_STATUS_TLS_FAILED; + g_task_return_boolean (task, TRUE); else - status = SOUP_STATUS_SSL_FAILED; - g_clear_error (&error); - - data->callback (data->sock, status, data->user_data); - g_object_unref (data->sock); - g_slice_free (SoupSocketAsyncConnectData, data); + g_task_return_error (task, error); } void -soup_socket_handshake_async (SoupSocket *sock, - GCancellable *cancellable, - SoupSocketCallback callback, - gpointer user_data) +soup_socket_handshake_async (SoupSocket *sock, + const char *ssl_host, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); - SoupSocketAsyncConnectData *data; + GTask *task; + GError *error = NULL; - priv->ssl = TRUE; + task = g_task_new (sock, cancellable, callback, user_data); - data = g_slice_new (SoupSocketAsyncConnectData); - data->sock = g_object_ref (sock); - data->callback = callback; - data->user_data = user_data; + if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, &error)) { + g_task_return_error (task, error); + return; + } - if (priv->async_context && !priv->use_thread_context) - g_main_context_push_thread_default (priv->async_context); g_tls_connection_handshake_async (G_TLS_CONNECTION (priv->conn), G_PRIORITY_DEFAULT, cancellable, handshake_async_ready, - data); + task); +} + +gboolean +soup_socket_handshake_finish (SoupSocket *sock, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); } /** -- cgit v1.2.1 From 665a6e44005b4a0d5e4911b81e89d9984695e40b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 3 Jul 2013 17:28:23 -0400 Subject: SoupConnection: make methods gio-like Port the SoupConnection methods to be gio-like, using GAsyncReadyCallback for the async ones, and returning GErrors rather than libsoup status codes. Add internal-gio-like SoupSocket connect methods for the SoupConnection methods to use. --- libsoup/soup-connection.c | 268 +++++++++++++++++++------------------------- libsoup/soup-connection.h | 36 +++--- libsoup/soup-misc-private.h | 11 ++ libsoup/soup-session.c | 139 ++++++++++++++++++----- libsoup/soup-socket.c | 171 +++++++++++++++++++--------- 5 files changed, 374 insertions(+), 251 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index f8b6cef7..2b5dc49e 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -442,113 +442,89 @@ re_emit_socket_event (SoupSocket *socket, soup_connection_event (conn, event, connection); } -typedef struct { - SoupConnection *conn; - SoupConnectionCallback callback; - gpointer callback_data; - GCancellable *cancellable; - guint event_id; -} SoupConnectionAsyncConnectData; - static void -socket_connect_finished (SoupConnectionAsyncConnectData *data, guint status) +socket_connect_finished (GTask *task, SoupSocket *sock, GError *error) { - SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); + SoupConnection *conn = g_task_get_source_object (task); + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); - if (priv->socket) - g_signal_handler_disconnect (priv->socket, data->event_id); + if (priv->async_context && !priv->use_thread_context) + g_main_context_pop_thread_default (priv->async_context); - if (SOUP_STATUS_IS_SUCCESSFUL (status)) { + g_signal_handlers_disconnect_by_func (sock, G_CALLBACK (re_emit_socket_event), conn); + + if (!error) { if (priv->ssl && !priv->proxy_uri) { - soup_connection_event (data->conn, + soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); } if (!priv->ssl || !priv->proxy_uri) { - soup_connection_event (data->conn, + soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); } - soup_connection_set_state (data->conn, SOUP_CONNECTION_IN_USE); + soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; - start_idle_timer (data->conn); - } + start_idle_timer (conn); - if (data->callback) { - if (priv->proxy_uri != NULL) - status = soup_status_proxify (status); - data->callback (data->conn, status, data->callback_data); - } - g_object_unref (data->conn); - if (data->cancellable) - g_object_unref (data->cancellable); - g_slice_free (SoupConnectionAsyncConnectData, data); + g_task_return_boolean (task, TRUE); + } else + g_task_return_error (task, error); + g_object_unref (task); } - static void socket_handshake_complete (GObject *object, GAsyncResult *result, gpointer user_data) { - SoupConnectionAsyncConnectData *data = user_data; - SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); + SoupSocket *sock = SOUP_SOCKET (object); + GTask *task = user_data; GError *error = NULL; - guint status; - - if (priv->async_context && !priv->use_thread_context) - g_main_context_pop_thread_default (priv->async_context); - if (soup_socket_handshake_finish (priv->socket, result, &error)) - status = SOUP_STATUS_OK; - else if (!priv->ssl_fallback && - g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { - priv->ssl_fallback = TRUE; - status = SOUP_STATUS_TRY_AGAIN; - } else - status = SOUP_STATUS_SSL_FAILED; - g_clear_error (&error); - - socket_connect_finished (data, status); + soup_socket_handshake_finish (sock, result, &error); + socket_connect_finished (task, sock, error); } static void -socket_connect_result (SoupSocket *sock, guint status, gpointer user_data) +socket_connect_complete (GObject *object, GAsyncResult *result, gpointer user_data) { - SoupConnectionAsyncConnectData *data = user_data; - SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); + SoupSocket *sock = SOUP_SOCKET (object); + GTask *task = user_data; + SoupConnection *conn = g_task_get_source_object (task); + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); + GError *error = NULL; - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - socket_connect_finished (data, status); + if (!soup_socket_connect_finish_internal (sock, result, &error)) { + socket_connect_finished (task, sock, error); return; } - priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); + priv->proxy_uri = soup_socket_get_http_proxy_uri (sock); if (priv->ssl && !priv->proxy_uri) { - soup_connection_event (data->conn, + soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); - if (priv->async_context && !priv->use_thread_context) - g_main_context_push_thread_default (priv->async_context); soup_socket_handshake_async (sock, priv->remote_uri->host, - data->cancellable, - socket_handshake_complete, data); + g_task_get_cancellable (task), + socket_handshake_complete, task); return; } - socket_connect_finished (data, status); + socket_connect_finished (task, sock, NULL); } void -soup_connection_connect_async (SoupConnection *conn, - GCancellable *cancellable, - SoupConnectionCallback callback, - gpointer user_data) +soup_connection_connect_async (SoupConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { - SoupConnectionAsyncConnectData *data; SoupConnectionPrivate *priv; SoupAddress *remote_addr; + GTask *task; g_return_if_fail (SOUP_IS_CONNECTION (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); @@ -556,12 +532,6 @@ soup_connection_connect_async (SoupConnection *conn, soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); - data = g_slice_new (SoupConnectionAsyncConnectData); - data->conn = g_object_ref (conn); - data->callback = callback; - data->callback_data = user_data; - data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - remote_addr = soup_address_new (priv->remote_uri->host, priv->remote_uri->port); priv->socket = @@ -578,24 +548,38 @@ soup_connection_connect_async (SoupConnection *conn, NULL); g_object_unref (remote_addr); - data->event_id = g_signal_connect (priv->socket, "event", - G_CALLBACK (re_emit_socket_event), - data->conn); + g_signal_connect (priv->socket, "event", + G_CALLBACK (re_emit_socket_event), conn); - soup_socket_connect_async (priv->socket, data->cancellable, - socket_connect_result, data); + if (priv->async_context && !priv->use_thread_context) + g_main_context_push_thread_default (priv->async_context); + task = g_task_new (conn, cancellable, callback, user_data); + + soup_socket_connect_async_internal (priv->socket, cancellable, + socket_connect_complete, task); +} + +gboolean +soup_connection_connect_finish (SoupConnection *conn, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); } -guint -soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) +gboolean +soup_connection_connect_sync (SoupConnection *conn, + GCancellable *cancellable, + GError **error) { SoupConnectionPrivate *priv; - guint status, event_id = 0; + guint event_id = 0; SoupAddress *remote_addr; + gboolean success = TRUE; - g_return_val_if_fail (SOUP_IS_CONNECTION (conn), SOUP_STATUS_MALFORMED); + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - g_return_val_if_fail (priv->socket == NULL, SOUP_STATUS_MALFORMED); + g_return_val_if_fail (priv->socket == NULL, FALSE); soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); @@ -615,53 +599,42 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) event_id = g_signal_connect (priv->socket, "event", G_CALLBACK (re_emit_socket_event), conn); - status = soup_socket_connect_sync (priv->socket, cancellable); - - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) - goto fail; + if (!soup_socket_connect_sync_internal (priv->socket, cancellable, error)) { + success = FALSE; + goto done; + } priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); if (priv->ssl && !priv->proxy_uri) { - GError *error = NULL; - soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); - if (soup_socket_handshake_sync (priv->socket, - priv->remote_uri->host, - cancellable, &error)) { - soup_connection_event (conn, - G_SOCKET_CLIENT_TLS_HANDSHAKED, - NULL); - status = SOUP_STATUS_OK; - } else if (!priv->ssl_fallback && - g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { - priv->ssl_fallback = TRUE; - status = SOUP_STATUS_TRY_AGAIN; - } else - status = SOUP_STATUS_SSL_FAILED; - g_clear_error (&error); + if (!soup_socket_handshake_sync (priv->socket, + priv->remote_uri->host, + cancellable, error)) { + success = FALSE; + goto done; + } + soup_connection_event (conn, + G_SOCKET_CLIENT_TLS_HANDSHAKED, + NULL); } - if (SOUP_STATUS_IS_SUCCESSFUL (status)) { - if (!priv->ssl || !priv->proxy_uri) { - soup_connection_event (conn, - G_SOCKET_CLIENT_COMPLETE, - NULL); - } - soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); - priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; - start_idle_timer (conn); + if (!priv->ssl || !priv->proxy_uri) { + soup_connection_event (conn, + G_SOCKET_CLIENT_COMPLETE, + NULL); } + soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE); + priv->unused_timeout = time (NULL) + SOUP_CONNECTION_UNUSED_TIMEOUT; + start_idle_timer (conn); - fail: + done: if (priv->socket && event_id) g_signal_handler_disconnect (priv->socket, event_id); - if (priv->proxy_uri != NULL) - status = soup_status_proxify (status); - return status; + return success; } gboolean @@ -675,83 +648,74 @@ soup_connection_is_tunnelled (SoupConnection *conn) return priv->ssl && priv->proxy_uri != NULL; } -guint -soup_connection_start_ssl_sync (SoupConnection *conn, - GCancellable *cancellable) +gboolean +soup_connection_start_ssl_sync (SoupConnection *conn, + GCancellable *cancellable, + GError **error) { SoupConnectionPrivate *priv; - guint status; - GError *error = NULL; g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); priv = SOUP_CONNECTION_GET_PRIVATE (conn); soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); if (soup_socket_handshake_sync (priv->socket, priv->remote_uri->host, - cancellable, &error)) { + cancellable, error)) { soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); - status = SOUP_STATUS_OK; - } else if (!priv->ssl_fallback && - g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { - priv->ssl_fallback = TRUE; - status = SOUP_STATUS_TRY_AGAIN; - } - - return status; + return TRUE; + } else + return FALSE; } static void start_ssl_completed (GObject *object, GAsyncResult *result, gpointer user_data) { - SoupConnectionAsyncConnectData *data = user_data; - SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); - guint status; + GTask *task = user_data; + SoupConnection *conn = g_task_get_source_object (task); + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn); GError *error = NULL; if (priv->async_context && !priv->use_thread_context) g_main_context_pop_thread_default (priv->async_context); if (soup_socket_handshake_finish (priv->socket, result, &error)) { - soup_connection_event (data->conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); - soup_connection_event (data->conn, G_SOCKET_CLIENT_COMPLETE, NULL); - status = SOUP_STATUS_OK; - } else if (!priv->ssl_fallback && - g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { - priv->ssl_fallback = TRUE; - status = SOUP_STATUS_TRY_AGAIN; + soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); + soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); + g_task_return_boolean (task, TRUE); } else - status = SOUP_STATUS_SSL_FAILED; - g_clear_error (&error); - - data->callback (data->conn, status, data->callback_data); - g_object_unref (data->conn); - g_slice_free (SoupConnectionAsyncConnectData, data); + g_task_return_error (task, error); + g_object_unref (task); } void -soup_connection_start_ssl_async (SoupConnection *conn, - GCancellable *cancellable, - SoupConnectionCallback callback, - gpointer user_data) +soup_connection_start_ssl_async (SoupConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { SoupConnectionPrivate *priv; - SoupConnectionAsyncConnectData *data; + GTask *task; g_return_if_fail (SOUP_IS_CONNECTION (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - data = g_slice_new (SoupConnectionAsyncConnectData); - data->conn = g_object_ref (conn); - data->callback = callback; - data->callback_data = user_data; - soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL); if (priv->async_context && !priv->use_thread_context) g_main_context_push_thread_default (priv->async_context); + task = g_task_new (conn, cancellable, callback, user_data); + soup_socket_handshake_async (priv->socket, priv->remote_uri->host, - cancellable, start_ssl_completed, data); + cancellable, start_ssl_completed, task); +} + +gboolean +soup_connection_start_ssl_finish (SoupConnection *conn, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); } /** diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h index 50fb7018..b70a8a36 100644 --- a/libsoup/soup-connection.h +++ b/libsoup/soup-connection.h @@ -35,10 +35,6 @@ typedef struct { GType soup_connection_get_type (void); -typedef void (*SoupConnectionCallback) (SoupConnection *conn, - guint status, - gpointer data); - #define SOUP_CONNECTION_LOCAL_ADDRESS "local-address" #define SOUP_CONNECTION_REMOTE_URI "remote-uri" #define SOUP_CONNECTION_PROXY_RESOLVER "proxy-resolver" @@ -53,18 +49,26 @@ typedef void (*SoupConnectionCallback) (SoupConnection *conn, #define SOUP_CONNECTION_STATE "state" #define SOUP_CONNECTION_MESSAGE "message" -void soup_connection_connect_async (SoupConnection *conn, - GCancellable *cancellable, - SoupConnectionCallback callback, - gpointer user_data); -guint soup_connection_connect_sync (SoupConnection *conn, - GCancellable *cancellable); -guint soup_connection_start_ssl_sync (SoupConnection *conn, - GCancellable *cancellable); -void soup_connection_start_ssl_async (SoupConnection *conn, - GCancellable *cancellable, - SoupConnectionCallback callback, - gpointer user_data); +void soup_connection_connect_async (SoupConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean soup_connection_connect_finish (SoupConnection *conn, + GAsyncResult *result, + GError **error); +gboolean soup_connection_connect_sync (SoupConnection *conn, + GCancellable *cancellable, + GError **error); +gboolean soup_connection_start_ssl_sync (SoupConnection *conn, + GCancellable *cancellable, + GError **error); +void soup_connection_start_ssl_async (SoupConnection *conn, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean soup_connection_start_ssl_finish (SoupConnection *conn, + GAsyncResult *result, + GError **error); void soup_connection_disconnect (SoupConnection *conn); diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index 948470ff..50a3b988 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -16,6 +16,17 @@ char *soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, gboolean soup_uri_is_http (SoupURI *uri, char **aliases); gboolean soup_uri_is_https (SoupURI *uri, char **aliases); +gboolean soup_socket_connect_sync_internal (SoupSocket *sock, + GCancellable *cancellable, + GError **error); +void soup_socket_connect_async_internal (SoupSocket *sock, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean soup_socket_connect_finish_internal (SoupSocket *sock, + GAsyncResult *result, + GError **error); + gboolean soup_socket_handshake_sync (SoupSocket *sock, const char *host, GCancellable *cancellable, diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index bd586cd3..0fa65cda 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1508,10 +1508,59 @@ message_completed (SoupMessage *msg, gpointer user_data) } } +static guint +status_from_connect_error (SoupMessageQueueItem *item, GError *error) +{ + guint status; + + if (!error) + return SOUP_STATUS_OK; + + if (g_error_matches (error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS)) { + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (item->session); + SoupSessionHost *host; + + g_mutex_lock (&priv->conn_lock); + host = get_host_for_message (item->session, item->msg); + if (!host->ssl_fallback) { + host->ssl_fallback = TRUE; + status = SOUP_STATUS_TRY_AGAIN; + } else + status = SOUP_STATUS_SSL_FAILED; + g_mutex_unlock (&priv->conn_lock); + } else if (error->domain == G_TLS_ERROR) + status = SOUP_STATUS_SSL_FAILED; + else if (error->domain == G_RESOLVER_ERROR) + status = SOUP_STATUS_CANT_RESOLVE; + else if (error->domain == G_IO_ERROR) { + if (error->code == G_IO_ERROR_CANCELLED) + status = SOUP_STATUS_CANCELLED; + else if (error->code == G_IO_ERROR_HOST_UNREACHABLE || + error->code == G_IO_ERROR_NETWORK_UNREACHABLE || + error->code == G_IO_ERROR_CONNECTION_REFUSED) + status = SOUP_STATUS_CANT_CONNECT; + else if (error->code == G_IO_ERROR_PROXY_FAILED || + error->code == G_IO_ERROR_PROXY_AUTH_FAILED || + error->code == G_IO_ERROR_PROXY_NEED_AUTH || + error->code == G_IO_ERROR_PROXY_NOT_ALLOWED) + status = SOUP_STATUS_CANT_CONNECT_PROXY; + else + status = SOUP_STATUS_IO_ERROR; + } else + status = SOUP_STATUS_IO_ERROR; + + g_error_free (error); + + if (item->conn && soup_connection_is_via_proxy (item->conn)) + return soup_status_proxify (status); + else + return status; +} + static void -tunnel_complete (SoupConnection *conn, guint status, gpointer user_data) +tunnel_complete (SoupMessageQueueItem *tunnel_item, + guint status, GError *error) { - SoupMessageQueueItem *tunnel_item = user_data; SoupMessageQueueItem *item = tunnel_item->related; SoupSession *session = tunnel_item->session; @@ -1522,8 +1571,10 @@ tunnel_complete (SoupConnection *conn, guint status, gpointer user_data) item->state = SOUP_MESSAGE_FINISHING; soup_message_set_https_status (item->msg, item->conn); + if (!status) + status = status_from_connect_error (item, error); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - soup_connection_disconnect (conn); + soup_connection_disconnect (item->conn); soup_session_set_item_connection (session, item, NULL); soup_session_set_item_status (session, item, status); } @@ -1534,6 +1585,19 @@ tunnel_complete (SoupConnection *conn, guint status, gpointer user_data) soup_message_queue_item_unref (item); } +static void +tunnel_handshake_complete (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + SoupConnection *conn = SOUP_CONNECTION (object); + SoupMessageQueueItem *tunnel_item = user_data; + GError *error = NULL; + + soup_connection_start_ssl_finish (conn, result, &error); + tunnel_complete (tunnel_item, 0, error); +} + static void tunnel_message_completed (SoupMessage *msg, gpointer user_data) { @@ -1559,16 +1623,19 @@ tunnel_message_completed (SoupMessage *msg, gpointer user_data) status = tunnel_item->msg->status_code; if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - tunnel_complete (item->conn, status, tunnel_item); + tunnel_complete (tunnel_item, status, NULL); return; } if (tunnel_item->async) { soup_connection_start_ssl_async (item->conn, item->cancellable, - tunnel_complete, tunnel_item); + tunnel_handshake_complete, + tunnel_item); } else { - status = soup_connection_start_ssl_sync (item->conn, item->cancellable); - tunnel_complete (item->conn, status, tunnel_item); + GError *error = NULL; + + soup_connection_start_ssl_sync (item->conn, item->cancellable, &error); + tunnel_complete (tunnel_item, 0, error); } } @@ -1602,34 +1669,48 @@ tunnel_connect (SoupMessageQueueItem *item) } static void -got_connection (SoupConnection *conn, guint status, gpointer user_data) +connect_complete (SoupMessageQueueItem *item, SoupConnection *conn, GError *error) { - SoupMessageQueueItem *item = user_data; SoupSession *session = item->session; + guint status; soup_message_set_https_status (item->msg, item->conn); - if (status != SOUP_STATUS_OK) { - soup_connection_disconnect (conn); - if (item->state == SOUP_MESSAGE_CONNECTING) { - soup_session_set_item_status (session, item, status); - soup_session_set_item_connection (session, item, NULL); - item->state = SOUP_MESSAGE_READY; - } - } else + if (!error) { item->state = SOUP_MESSAGE_CONNECTED; + return; + } - if (item->async) { - if (item->state == SOUP_MESSAGE_CONNECTED || - item->state == SOUP_MESSAGE_READY) - async_run_queue (item->session); - else - soup_session_kick_queue (item->session); - - soup_message_queue_item_unref (item); + status = status_from_connect_error (item, error); + soup_connection_disconnect (conn); + if (item->state == SOUP_MESSAGE_CONNECTING) { + soup_session_set_item_status (session, item, status); + soup_session_set_item_connection (session, item, NULL); + item->state = SOUP_MESSAGE_READY; } } +static void +connect_async_complete (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + SoupConnection *conn = SOUP_CONNECTION (object); + SoupMessageQueueItem *item = user_data; + GError *error = NULL; + + soup_connection_connect_finish (conn, result, &error); + connect_complete (item, conn, error); + + if (item->state == SOUP_MESSAGE_CONNECTED || + item->state == SOUP_MESSAGE_READY) + async_run_queue (item->session); + else + soup_session_kick_queue (item->session); + + soup_message_queue_item_unref (item); +} + /* requires conn_lock */ static SoupConnection * get_connection_for_host (SoupSession *session, @@ -1783,13 +1864,13 @@ get_connection (SoupMessageQueueItem *item, gboolean *should_cleanup) if (item->async) { soup_message_queue_item_ref (item); soup_connection_connect_async (item->conn, item->cancellable, - got_connection, item); + connect_async_complete, item); return FALSE; } else { - guint status; + GError *error = NULL; - status = soup_connection_connect_sync (item->conn, item->cancellable); - got_connection (item->conn, status, item); + soup_connection_connect_sync (item->conn, item->cancellable, &error); + connect_complete (item, conn, error); return TRUE; } diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 9caf0d2c..d4046ec2 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -666,38 +666,36 @@ re_emit_socket_client_event (GSocketClient *client, event, connection); } -static guint -socket_connected (SoupSocket *sock, GSocketConnection *conn, GError *error) +static gboolean +socket_connect_finish (SoupSocket *sock, GSocketConnection *conn) { SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); - if (priv->connect_cancel) { - GCancellable *cancellable = priv->connect_cancel; - gboolean cancelled = g_cancellable_is_cancelled (cancellable); + g_clear_object (&priv->connect_cancel); - g_object_unref (priv->connect_cancel); - priv->connect_cancel = NULL; - if (cancelled) { - g_clear_error (&error); - return SOUP_STATUS_CANCELLED; - } - } + if (conn) { + priv->conn = (GIOStream *)conn; + priv->gsock = g_object_ref (g_socket_connection_get_socket (conn)); + finish_socket_setup (priv); + return TRUE; + } else + return FALSE; +} - if (error) { - if (error->domain == G_RESOLVER_ERROR) { - g_error_free (error); - return SOUP_STATUS_CANT_RESOLVE; - } else { - g_error_free (error); - return SOUP_STATUS_CANT_CONNECT; - } - } +static guint +socket_legacy_error (SoupSocket *sock, GError *error) +{ + guint status; - priv->conn = (GIOStream *)conn; - priv->gsock = g_object_ref (g_socket_connection_get_socket (conn)); - finish_socket_setup (priv); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + status = SOUP_STATUS_CANCELLED; + else if (error->domain == G_RESOLVER_ERROR) + status = SOUP_STATUS_CANT_RESOLVE; + else + status = SOUP_STATUS_CANT_CONNECT; - return SOUP_STATUS_OK; + g_error_free (error); + return status; } static GSocketClient * @@ -722,6 +720,57 @@ new_socket_client (SoupSocket *sock) return client; } +static void +async_connected (GObject *client, GAsyncResult *result, gpointer data) +{ + GTask *task = data; + SoupSocket *sock = g_task_get_source_object (task); + GSocketConnection *conn; + GError *error = NULL; + + conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), + result, &error); + if (socket_connect_finish (sock, conn)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); +} + +gboolean +soup_socket_connect_finish_internal (SoupSocket *sock, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + +void +soup_socket_connect_async_internal (SoupSocket *sock, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + SoupSocketPrivate *priv; + GSocketClient *client; + GTask *task; + + g_return_if_fail (SOUP_IS_SOCKET (sock)); + priv = SOUP_SOCKET_GET_PRIVATE (sock); + g_return_if_fail (!priv->is_server); + g_return_if_fail (priv->gsock == NULL); + g_return_if_fail (priv->remote_addr != NULL); + + priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new (); + task = g_task_new (sock, priv->connect_cancel, callback, user_data); + + client = new_socket_client (sock); + g_socket_client_connect_async (client, + G_SOCKET_CONNECTABLE (priv->remote_addr), + priv->connect_cancel, + async_connected, task); + g_object_unref (client); +} + /** * SoupSocketCallback: * @sock: the #SoupSocket @@ -738,22 +787,25 @@ typedef struct { } SoupSocketAsyncConnectData; static void -async_connected (GObject *client, GAsyncResult *result, gpointer data) +legacy_connect_async_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) { - SoupSocketAsyncConnectData *sacd = data; - SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock); + SoupSocket *sock = SOUP_SOCKET (object); + SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); + SoupSocketAsyncConnectData *sacd = user_data; GError *error = NULL; - GSocketConnection *conn; guint status; if (priv->async_context && !priv->use_thread_context) g_main_context_pop_thread_default (priv->async_context); - conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), - result, &error); - status = socket_connected (sacd->sock, conn, error); + if (soup_socket_connect_finish_internal (sock, result, &error)) + status = SOUP_STATUS_OK; + else + status = socket_legacy_error (sock, error); - sacd->callback (sacd->sock, status, sacd->user_data); + sacd->callback (sock, status, sacd->user_data); g_object_unref (sacd->sock); g_slice_free (SoupSocketAsyncConnectData, sacd); } @@ -779,10 +831,11 @@ soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable, { SoupSocketPrivate *priv; SoupSocketAsyncConnectData *sacd; - GSocketClient *client; g_return_if_fail (SOUP_IS_SOCKET (sock)); priv = SOUP_SOCKET_GET_PRIVATE (sock); + g_return_if_fail (!priv->is_server); + g_return_if_fail (priv->gsock == NULL); g_return_if_fail (priv->remote_addr != NULL); sacd = g_slice_new0 (SoupSocketAsyncConnectData); @@ -790,17 +843,38 @@ soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable, sacd->callback = callback; sacd->user_data = user_data; - priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new (); - if (priv->async_context && !priv->use_thread_context) g_main_context_push_thread_default (priv->async_context); + soup_socket_connect_async_internal (sock, cancellable, + legacy_connect_async_cb, + sacd); +} + +gboolean +soup_socket_connect_sync_internal (SoupSocket *sock, + GCancellable *cancellable, + GError **error) +{ + SoupSocketPrivate *priv; + GSocketClient *client; + GSocketConnection *conn; + + g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED); + priv = SOUP_SOCKET_GET_PRIVATE (sock); + g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED); + g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED); + g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED); + + priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new (); + client = new_socket_client (sock); - g_socket_client_connect_async (client, - G_SOCKET_CONNECTABLE (priv->remote_addr), - priv->connect_cancel, - async_connected, sacd); + conn = g_socket_client_connect (client, + G_SOCKET_CONNECTABLE (priv->remote_addr), + priv->connect_cancel, error); g_object_unref (client); + + return socket_connect_finish (sock, conn); } /** @@ -820,8 +894,6 @@ guint soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable) { SoupSocketPrivate *priv; - GSocketClient *client; - GSocketConnection *conn; GError *error = NULL; g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED); @@ -830,19 +902,10 @@ soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable) g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED); g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED); - if (cancellable) - g_object_ref (cancellable); + if (soup_socket_connect_sync_internal (sock, cancellable, &error)) + return SOUP_STATUS_OK; else - cancellable = g_cancellable_new (); - priv->connect_cancel = cancellable; - - client = new_socket_client (sock); - conn = g_socket_client_connect (client, - G_SOCKET_CONNECTABLE (priv->remote_addr), - priv->connect_cancel, &error); - g_object_unref (client); - - return socket_connected (sock, conn, error); + return socket_legacy_error (sock, error); } /** -- cgit v1.2.1 From 65bd4b98e2e5ed8518beb94fac05c9d9967cadb7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 9 Jul 2013 12:27:37 -0400 Subject: SoupSession: propagate GErrors to callers When using soup_session_send() or soup_session_send_async(), propagate underlying GErrors to the caller, rather than constructing fake SOUP_HTTP_ERROR errors. --- libsoup/soup-message-queue.c | 1 + libsoup/soup-message-queue.h | 2 ++ libsoup/soup-session.c | 34 ++++++++++++++++++++++------------ tests/misc-test.c | 4 ++-- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c index 3dced0e4..4bc37267 100644 --- a/libsoup/soup-message-queue.c +++ b/libsoup/soup-message-queue.c @@ -183,6 +183,7 @@ soup_message_queue_item_unref (SoupMessageQueueItem *item) g_object_unref (item->session); g_object_unref (item->msg); g_object_unref (item->cancellable); + g_clear_error (&item->error); g_clear_object (&item->task); g_clear_pointer (&item->async_context, g_main_context_unref); if (item->io_source) { diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index d965e513..f86a1296 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -38,6 +38,8 @@ struct _SoupMessageQueueItem { GMainContext *async_context; GCancellable *cancellable; + GError *error; + SoupConnection *conn; GTask *task; GSource *io_source; diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 0fa65cda..6f44935f 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1453,7 +1453,8 @@ soup_session_unqueue_item (SoupSession *session, static void soup_session_set_item_status (SoupSession *session, SoupMessageQueueItem *item, - guint status_code) + guint status_code, + GError *error) { SoupURI *uri = NULL; @@ -1481,7 +1482,9 @@ soup_session_set_item_status (SoupSession *session, break; } - if (uri && uri->host) { + if (error) + soup_message_set_status_full (item->msg, status_code, error->message); + else if (uri && uri->host) { char *msg = g_strdup_printf ("%s (%s)", soup_status_get_phrase (status_code), uri->host); @@ -1549,8 +1552,6 @@ status_from_connect_error (SoupMessageQueueItem *item, GError *error) } else status = SOUP_STATUS_IO_ERROR; - g_error_free (error); - if (item->conn && soup_connection_is_via_proxy (item->conn)) return soup_status_proxify (status); else @@ -1571,12 +1572,14 @@ tunnel_complete (SoupMessageQueueItem *tunnel_item, item->state = SOUP_MESSAGE_FINISHING; soup_message_set_https_status (item->msg, item->conn); + item->error = error; if (!status) status = status_from_connect_error (item, error); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { soup_connection_disconnect (item->conn); soup_session_set_item_connection (session, item, NULL); - soup_session_set_item_status (session, item, status); + if (!item->new_api || item->msg->status_code == 0) + soup_session_set_item_status (session, item, status, error); } item->state = SOUP_MESSAGE_READY; @@ -1681,10 +1684,12 @@ connect_complete (SoupMessageQueueItem *item, SoupConnection *conn, GError *erro return; } + item->error = error; status = status_from_connect_error (item, error); soup_connection_disconnect (conn); if (item->state == SOUP_MESSAGE_CONNECTING) { - soup_session_set_item_status (session, item, status); + if (!item->new_api || item->msg->status_code == 0) + soup_session_set_item_status (session, item, status, error); soup_session_set_item_connection (session, item, NULL); item->state = SOUP_MESSAGE_READY; } @@ -3747,7 +3752,11 @@ async_send_request_return_result (SoupMessageQueueItem *item, if (error) g_task_return_error (task, error); - else if (SOUP_STATUS_IS_TRANSPORT_ERROR (item->msg->status_code)) { + else if (item->error) { + if (stream) + g_object_unref (stream); + g_task_return_error (task, g_error_copy (item->error)); + } else if (SOUP_STATUS_IS_TRANSPORT_ERROR (item->msg->status_code)) { if (stream) g_object_unref (stream); g_task_return_new_error (task, SOUP_HTTP_ERROR, @@ -4331,11 +4340,12 @@ soup_session_send (SoupSession *session, if (my_error) g_propagate_error (error, my_error); - else if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { - if (stream) { - g_object_unref (stream); - stream = NULL; - } + else if (item->error) { + g_clear_object (&stream); + if (error) + *error = g_error_copy (item->error); + } else if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { + g_clear_object (&stream); g_set_error_literal (error, SOUP_HTTP_ERROR, msg->status_code, msg->reason_phrase); } else if (!stream) diff --git a/tests/misc-test.c b/tests/misc-test.c index 73cc6333..2aaa2cd4 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -242,7 +242,7 @@ cur_one_completed (GObject *source, GAsyncResult *result, gpointer session) if (soup_request_send_finish (one, result, &error)) { debug_printf (1, " Request 1 succeeded?\n"); errors++; - } else if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_CONNECT)) { + } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED)) { debug_printf (1, " Unexpected error on Request 1: %s\n", error->message); errors++; @@ -269,7 +269,7 @@ cur_two_completed (GObject *source, GAsyncResult *result, gpointer loop) if (soup_request_send_finish (two, result, &error)) { debug_printf (1, " Request 2 succeeded?\n"); errors++; - } else if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANT_CONNECT)) { + } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED)) { debug_printf (1, " Unexpected error on Request 2: %s\n", error->message); errors++; -- cgit v1.2.1 From 819298693dba366cde307adcdc541c8d6039403d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= Date: Tue, 22 Oct 2013 15:49:22 +0200 Subject: Fix 'return with no value' warning --- libsoup/soup-message-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 03dc4333..6ba29607 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -988,7 +988,7 @@ soup_message_io_run_until_finish (SoupMessage *msg, g_object_ref (msg); if (io) { - g_return_if_fail (io->mode == SOUP_MESSAGE_IO_CLIENT); + g_return_val_if_fail (io->mode == SOUP_MESSAGE_IO_CLIENT, FALSE); if (io->read_state < SOUP_MESSAGE_IO_STATE_BODY_DONE) io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; -- cgit v1.2.1 From 45d84ff3a03f547819fa53731df5d7b2b72150d0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sun, 3 Nov 2013 17:06:22 -0500 Subject: tests/connection-test: Ensure quit source id is reset to 0 between runs Otherwise we may attempt to remove a nonexistent quit loop from the previous one. The second hunk here is the real fix, the first is just being more defensive/consistent. Reported-By: Kjartan Maraas Tested-By: Kjartan Maraas https://bugzilla.gnome.org/show_bug.cgi?id=711361 --- tests/connection-test.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/connection-test.c b/tests/connection-test.c index 3d517539..fd7179f2 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -495,6 +495,8 @@ do_max_conns_test_for_session (SoupSession *session) msgs_done = 0; g_idle_add (idle_start_server, NULL); + if (quit_loop_timeout) + g_source_remove (quit_loop_timeout); quit_loop_timeout = g_timeout_add (1000, quit_loop, NULL); g_main_loop_run (max_conns_loop); @@ -517,8 +519,10 @@ do_max_conns_test_for_session (SoupSession *session) } g_main_loop_unref (max_conns_loop); - if (quit_loop_timeout) + if (quit_loop_timeout) { g_source_remove (quit_loop_timeout); + quit_loop_timeout = 0; + } for (i = 0; i < TEST_CONNS; i++) g_object_unref (msgs[i]); -- cgit v1.2.1 From 51cd4fb8e7ec0a589d321de5312160ee99523b5f Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Tue, 29 Oct 2013 17:12:18 +0100 Subject: Don't leak g_get_current_dir() result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glib API documentation indicates: « The returned string should be freed when no longer needed. » https://bugzilla.gnome.org/show_bug.cgi?id=711085 --- libsoup/soup-session.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 6f44935f..3a29f4f8 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -509,6 +509,7 @@ set_ssl_ca_file (SoupSession *session, const char *ssl_ca_file) path = g_build_filename (cwd, ssl_ca_file, NULL); tlsdb = g_tls_file_database_new (path, &error); g_free (path); + g_free (cwd); } if (error) { -- cgit v1.2.1 From 1ad6f7e90eb68522e6be6feee1c7462b24af737d Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Tue, 29 Oct 2013 17:26:34 +0100 Subject: socket: Don't leak GTasks GTask needs to be unreffed after calling g_task_return_* when we don't use async methods which take ownership of it (as g_task_run_in_thread() does). https://bugzilla.gnome.org/show_bug.cgi?id=711085 --- libsoup/soup-socket.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index d4046ec2..c101fa52 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -734,6 +734,7 @@ async_connected (GObject *client, GAsyncResult *result, gpointer data) g_task_return_boolean (task, TRUE); else g_task_return_error (task, error); + g_object_unref (task); } gboolean @@ -1233,6 +1234,7 @@ handshake_async_ready (GObject *source, GAsyncResult *result, gpointer user_data g_task_return_boolean (task, TRUE); else g_task_return_error (task, error); + g_object_unref (task); } void @@ -1250,6 +1252,7 @@ soup_socket_handshake_async (SoupSocket *sock, if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, &error)) { g_task_return_error (task, error); + g_object_unref (task); return; } -- cgit v1.2.1 From 8ca8bf9550e92f45efab590ee7ff53b83bae8e75 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 2 Nov 2013 18:44:56 -0400 Subject: requester-test: reorganize to be more like other tests --- tests/requester-test.c | 192 +++++++++++++++++++++++++++---------------------- 1 file changed, 108 insertions(+), 84 deletions(-) diff --git a/tests/requester-test.c b/tests/requester-test.c index cfa9fcd6..461f1934 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -363,14 +363,14 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri) } soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); - debug_printf (1, " basic test\n"); + debug_printf (1, " basic test\n"); uri = soup_uri_new (base_uri); do_async_test (session, uri, test_sent, SOUP_STATUS_OK, response, TRUE, FALSE); soup_uri_free (uri); - debug_printf (1, " chunked test\n"); + debug_printf (1, " chunked test\n"); uri = soup_uri_new (base_uri); soup_uri_set_path (uri, "/chunked"); do_async_test (session, uri, test_sent, @@ -378,7 +378,7 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri) TRUE, FALSE); soup_uri_free (uri); - debug_printf (1, " auth test\n"); + debug_printf (1, " auth test\n"); uri = soup_uri_new (base_uri); soup_uri_set_path (uri, "/auth"); do_async_test (session, uri, auth_test_sent, @@ -386,7 +386,7 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri) TRUE, FALSE); soup_uri_free (uri); - debug_printf (1, " non-persistent test\n"); + debug_printf (1, " non-persistent test\n"); uri = soup_uri_new (base_uri); soup_uri_set_path (uri, "/non-persistent"); do_async_test (session, uri, test_sent, @@ -394,7 +394,7 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri) FALSE, FALSE); soup_uri_free (uri); - debug_printf (1, " cancellation test\n"); + debug_printf (1, " cancellation test\n"); uri = soup_uri_new (base_uri); soup_uri_set_path (uri, "/"); do_async_test (session, uri, test_sent, @@ -404,14 +404,19 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri) } static void -do_simple_test (const char *uri, gboolean plain_session) +do_simple_tests (const char *uri) { SoupSession *session; - debug_printf (1, "Simple streaming test with %s\n", - plain_session ? "SoupSession" : "SoupSessionAsync"); + debug_printf (1, "Simple streaming test\n"); - session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC, + debug_printf (1, " SoupSession\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_test_for_thread_and_context (session, uri); + soup_test_session_abort_unref (session); + + debug_printf (1, " SoupSessionAsync\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); do_test_for_thread_and_context (session, uri); @@ -442,6 +447,7 @@ do_test_with_context_and_type (const char *uri, gboolean plain_session) static gpointer do_test_with_context (gpointer uri) { + debug_printf (1, " SoupSessionAsync\n"); do_test_with_context_and_type (uri, FALSE); return NULL; } @@ -449,31 +455,34 @@ do_test_with_context (gpointer uri) static gpointer do_plain_test_with_context (gpointer uri) { + debug_printf (1, " SoupSession\n"); do_test_with_context_and_type (uri, TRUE); return NULL; } static void -do_context_test (const char *uri, gboolean plain_session) +do_context_tests (const char *uri) { - debug_printf (1, "Streaming with a non-default-context with %s\n", - plain_session ? "SoupSession" : "SoupSessionAsync"); - if (plain_session) - do_plain_test_with_context ((gpointer)uri); - else - do_test_with_context ((gpointer)uri); + debug_printf (1, "\nStreaming with a non-default-context\n"); + + do_plain_test_with_context ((gpointer)uri); + do_test_with_context ((gpointer)uri); } static void -do_thread_test (const char *uri, gboolean plain_session) +do_thread_tests (const char *uri) { GThread *thread; - debug_printf (1, "Streaming in another thread with %s\n", - plain_session ? "SoupSession" : "SoupSessionAsync"); + debug_printf (1, "\nStreaming in another thread\n"); thread = g_thread_new ("do_test_with_context", - plain_session ? do_plain_test_with_context : do_test_with_context, + do_plain_test_with_context, + (gpointer)uri); + g_thread_join (thread); + + thread = g_thread_new ("do_test_with_context", + do_test_with_context, (gpointer)uri); g_thread_join (thread); } @@ -593,87 +602,98 @@ do_sync_request (SoupSession *session, SoupRequest *request, } static void -do_sync_test (const char *uri_string, gboolean plain_session) +do_sync_tests_for_session (SoupSession *session, const char *uri_string) { - SoupSession *session; SoupRequester *requester; SoupRequest *request; SoupURI *uri; - debug_printf (1, "Sync streaming with %s\n", - plain_session ? "SoupSession" : "SoupSessionSync"); - - session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_SYNC, NULL); - if (!plain_session) { - requester = soup_requester_new (); - soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); - g_object_unref (requester); - } + requester = SOUP_REQUESTER (soup_session_get_feature (session, SOUP_TYPE_REQUESTER)); uri = soup_uri_new (uri_string); - debug_printf (1, " basic test\n"); - if (plain_session) - request = soup_session_request_uri (session, uri, NULL); - else + debug_printf (1, " basic test\n"); + if (requester) request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); do_sync_request (session, request, SOUP_STATUS_OK, response, TRUE, FALSE); g_object_unref (request); - debug_printf (1, " chunked test\n"); + debug_printf (1, " chunked test\n"); soup_uri_set_path (uri, "/chunked"); - if (plain_session) - request = soup_session_request_uri (session, uri, NULL); - else + if (requester) request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); do_sync_request (session, request, SOUP_STATUS_OK, response, TRUE, FALSE); g_object_unref (request); - debug_printf (1, " auth test\n"); + debug_printf (1, " auth test\n"); soup_uri_set_path (uri, "/auth"); - if (plain_session) - request = soup_session_request_uri (session, uri, NULL); - else + if (requester) request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); do_sync_request (session, request, SOUP_STATUS_UNAUTHORIZED, auth_response, TRUE, FALSE); g_object_unref (request); - debug_printf (1, " non-persistent test\n"); + debug_printf (1, " non-persistent test\n"); soup_uri_set_path (uri, "/non-persistent"); - if (plain_session) - request = soup_session_request_uri (session, uri, NULL); - else + if (requester) request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); do_sync_request (session, request, SOUP_STATUS_OK, response, FALSE, FALSE); g_object_unref (request); - debug_printf (1, " cancel test\n"); + debug_printf (1, " cancel test\n"); soup_uri_set_path (uri, "/"); - if (plain_session) - request = soup_session_request_uri (session, uri, NULL); - else + if (requester) request = soup_requester_request_uri (requester, uri, NULL); + else + request = soup_session_request_uri (session, uri, NULL); do_sync_request (session, request, SOUP_STATUS_FORBIDDEN, NULL, TRUE, TRUE); g_object_unref (request); - soup_test_session_abort_unref (session); soup_uri_free (uri); } +static void +do_sync_tests (const char *uri_string) +{ + SoupSession *session; + SoupRequester *requester; + + debug_printf (1, "\nSync streaming\n"); + + debug_printf (1, " SoupSession\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_sync_tests_for_session (session, uri_string); + soup_test_session_abort_unref (session); + + debug_printf (1, " SoupSessionSync\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + requester = soup_requester_new (); + soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); + g_object_unref (requester); + do_sync_tests_for_session (session, uri_string); + soup_test_session_abort_unref (session); +} static void do_null_char_request (SoupSession *session, const char *encoded_data, - const char *expected_data, int expected_len) + const char *expected_data, int expected_len) { GError *error = NULL; GInputStream *stream; @@ -690,7 +710,7 @@ do_null_char_request (SoupSession *session, const char *encoded_data, stream = soup_test_request_send (request, NULL, 0, &error); if (error) { - debug_printf (1, " could not send request: %s\n", error->message); + debug_printf (1, " could not send request: %s\n", error->message); errors++; g_error_free (error); g_object_unref (request); @@ -700,24 +720,24 @@ do_null_char_request (SoupSession *session, const char *encoded_data, g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error); if (error) { - debug_printf (1, " could not read response: %s\n", error->message); + debug_printf (1, " could not read response: %s\n", error->message); errors++; g_clear_error (&error); } soup_test_request_close_stream (request, stream, NULL, &error); if (error) { - debug_printf (1, " could not close stream: %s\n", error->message); + debug_printf (1, " could not close stream: %s\n", error->message); errors++; g_clear_error (&error); } if (nread != expected_len) { - debug_printf (1, " response length mismatch: expected %d, got %lu\n", + debug_printf (1, " response length mismatch: expected %d, got %lu\n", expected_len, (gulong)nread); errors++; } else if (memcmp (buf, expected_data, nread) != 0) { - debug_printf (1, " response data mismatch\n"); + debug_printf (1, " response data mismatch\n"); errors++; } @@ -727,10 +747,8 @@ do_null_char_request (SoupSession *session, const char *encoded_data, } static void -do_null_char_test (gboolean plain_session) +do_null_char_test_for_session (SoupSession *session) { - SoupSession *session; - int i; static struct { const char *encoded_data; const char *expected_data; @@ -741,18 +759,31 @@ do_null_char_test (gboolean plain_session) { "%3Cscript%3E%00%3Cbr%2F%3E%3C%2Fscript%3E%00", "\0", 24 }, }; static int num_test_cases = G_N_ELEMENTS(test_cases); + int i; - debug_printf (1, "\nStreaming data URLs containing null chars with %s\n", - plain_session ? "SoupSession" : "SoupSessionAsync"); - - session = soup_test_session_new (plain_session ? SOUP_TYPE_SESSION : SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - NULL); - - for (i = 0; i < num_test_cases; i++) + for (i = 0; i < num_test_cases; i++) { do_null_char_request (session, test_cases[i].encoded_data, test_cases[i].expected_data, test_cases[i].expected_len); + } +} +static void +do_null_char_tests (void) +{ + SoupSession *session; + + debug_printf (1, "\nStreaming data URLs containing null chars\n"); + + debug_printf (1, " SoupSession\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_null_char_test_for_session (session); + soup_test_session_abort_unref (session); + + debug_printf (1, " SoupSessionAsync\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + do_null_char_test_for_session (session); soup_test_session_abort_unref (session); } @@ -769,7 +800,7 @@ do_close_test_for_session (SoupSession *session, stream = soup_test_request_send (request, NULL, 0, &error); if (error) { - debug_printf (1, " could not send request: %s\n", error->message); + debug_printf (1, " could not send request: %s\n", error->message); errors++; g_error_free (error); g_object_unref (request); @@ -805,14 +836,14 @@ do_close_tests (const char *uri) slow_uri = soup_uri_new (uri); soup_uri_set_path (slow_uri, "/slow"); - debug_printf (1, " async\n"); + debug_printf (1, " SoupSessionAsync\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); do_close_test_for_session (session, slow_uri); soup_test_session_abort_unref (session); - debug_printf (1, " sync\n"); + debug_printf (1, " SoupSessionSync\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -835,18 +866,11 @@ main (int argc, char **argv) uri = g_strdup_printf ("http://127.0.0.1:%u/foo", soup_server_get_port (server)); - do_simple_test (uri, FALSE); - do_thread_test (uri, FALSE); - do_context_test (uri, FALSE); - do_sync_test (uri, FALSE); - do_null_char_test (FALSE); - - do_simple_test (uri, TRUE); - do_thread_test (uri, TRUE); - do_context_test (uri, TRUE); - do_sync_test (uri, TRUE); - do_null_char_test (TRUE); - + do_simple_tests (uri); + do_thread_tests (uri); + do_context_tests (uri); + do_sync_tests (uri); + do_null_char_tests (); do_close_tests (uri); g_free (uri); -- cgit v1.2.1 From da167aad39438d4df33df189c97bd07e989d38d0 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 3 Nov 2013 18:31:59 -0500 Subject: soup-session: update a comment for current reality --- libsoup/soup-session.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 3a29f4f8..f2e643f3 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3868,10 +3868,10 @@ send_async_maybe_complete (SoupMessageQueueItem *item, /* Give the splice op its own ref on item */ soup_message_queue_item_ref (item); + /* We don't use CLOSE_SOURCE because we need to control when the + * side effects of closing the SoupClientInputStream happen. + */ g_output_stream_splice_async (ostream, stream, - /* We can't use CLOSE_SOURCE because it - * might get closed in the wrong thread. - */ G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, G_PRIORITY_DEFAULT, item->cancellable, -- cgit v1.2.1 From 4e755ba87e2937ce32c53c2983d4efe8b9121541 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 4 Nov 2013 16:41:10 -0500 Subject: Fix SoupClientInputStream close on error g_input/output_stream_close() always mark their stream closed, even on error, even if their cancellable is pre-cancelled. That means we have to guarantee that soup_message_io_finished() gets called when a SoupClientInputStream is closed, even if an error occurs while closing. https://bugzilla.gnome.org/show_bug.cgi?id=711260 --- libsoup/soup-client-input-stream.c | 9 +++++-- libsoup/soup-message-io.c | 25 ++++++++++-------- tests/requester-test.c | 54 +++++++++++++++++++++++++++++++++++--- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/libsoup/soup-client-input-stream.c b/libsoup/soup-client-input-stream.c index 87fa49d6..0264cb79 100644 --- a/libsoup/soup-client-input-stream.c +++ b/libsoup/soup-client-input-stream.c @@ -128,9 +128,12 @@ soup_client_input_stream_close_fn (GInputStream *stream, GError **error) { SoupClientInputStream *cistream = SOUP_CLIENT_INPUT_STREAM (stream); + gboolean success; - return soup_message_io_run_until_finish (cistream->priv->msg, TRUE, - cancellable, error); + success = soup_message_io_run_until_finish (cistream->priv->msg, TRUE, + NULL, error); + soup_message_io_finished (cistream->priv->msg); + return success; } static gboolean @@ -158,6 +161,8 @@ close_async_ready (SoupMessage *msg, gpointer user_data) return TRUE; } + soup_message_io_finished (cistream->priv->msg); + if (error) { g_task_return_error (task, error); g_object_unref (task); diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 6ba29607..be5cb2d2 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -155,8 +155,14 @@ soup_message_io_finished (SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; - SoupMessageCompletionFn completion_cb = io->completion_cb; - gpointer completion_data = io->completion_data; + SoupMessageCompletionFn completion_cb; + gpointer completion_data; + + if (!io) + return; + + completion_cb = io->completion_cb; + completion_data = io->completion_data; g_object_ref (msg); soup_message_io_cleanup (msg); @@ -984,6 +990,7 @@ soup_message_io_run_until_finish (SoupMessage *msg, { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; + gboolean success; g_object_ref (msg); @@ -994,17 +1001,13 @@ soup_message_io_run_until_finish (SoupMessage *msg, io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; } - if (!io_run_until (msg, blocking, - SOUP_MESSAGE_IO_STATE_DONE, - SOUP_MESSAGE_IO_STATE_DONE, - cancellable, error)) { - g_object_unref (msg); - return FALSE; - } + success = io_run_until (msg, blocking, + SOUP_MESSAGE_IO_STATE_DONE, + SOUP_MESSAGE_IO_STATE_DONE, + cancellable, error); - soup_message_io_finished (msg); g_object_unref (msg); - return TRUE; + return success; } static void diff --git a/tests/requester-test.c b/tests/requester-test.c index 461f1934..a202c164 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -787,6 +787,15 @@ do_null_char_tests (void) soup_test_session_abort_unref (session); } +static void +close_test_msg_finished (SoupMessage *msg, + gpointer user_data) +{ + gboolean *finished = user_data; + + *finished = TRUE; +} + static void do_close_test_for_session (SoupSession *session, SoupURI *uri) @@ -795,12 +804,17 @@ do_close_test_for_session (SoupSession *session, GInputStream *stream; SoupRequest *request; guint64 start, end; + GCancellable *cancellable; + SoupMessage *msg; + gboolean finished = FALSE; + + debug_printf (1, " normal close\n"); request = soup_session_request_uri (session, uri, NULL); stream = soup_test_request_send (request, NULL, 0, &error); if (error) { - debug_printf (1, " could not send request: %s\n", error->message); + debug_printf (1, " could not send request: %s\n", error->message); errors++; g_error_free (error); g_object_unref (request); @@ -810,14 +824,48 @@ do_close_test_for_session (SoupSession *session, start = g_get_monotonic_time (); soup_test_request_close_stream (request, stream, NULL, &error); if (error) { - debug_printf (1, " could not close stream: %s\n", error->message); + debug_printf (1, " could not close stream: %s\n", error->message); errors++; g_clear_error (&error); } end = g_get_monotonic_time (); if (end - start > 500000) { - debug_printf (1, " close() waited for response to complete!\n"); + debug_printf (1, " close() waited for response to complete!\n"); + errors++; + } + + g_object_unref (stream); + g_object_unref (request); + + + debug_printf (1, " error close\n"); + + request = soup_session_request_uri (session, uri, NULL); + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + g_signal_connect (msg, "finished", G_CALLBACK (close_test_msg_finished), &finished); + g_object_unref (msg); + + stream = soup_test_request_send (request, NULL, 0, &error); + if (error) { + debug_printf (1, " could not send request: %s\n", error->message); + errors++; + g_error_free (error); + g_object_unref (request); + return; + } + + cancellable = g_cancellable_new (); + g_cancellable_cancel (cancellable); + soup_test_request_close_stream (request, stream, cancellable, &error); + if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + debug_printf (1, " did not get expected error: %s\n", error->message); + errors++; + g_clear_error (&error); + } + + if (!finished) { + debug_printf (1, " message did not finish!\n"); errors++; } -- cgit v1.2.1 From 0152dca6d87b6e737c730e842ba226dbe4de1d86 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 10 Nov 2013 11:38:09 -0500 Subject: test-utils: bump up debug_level when running under "make check" Since automake's "make check" rule now logs the output of tests to a log file, we might as well use maximum debugging, so that if something fails, we have plenty of explanation why. (We still parallelize parallelizable tests by default though, meaning the output is not especially useful for those ones.) --- tests/test-utils.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test-utils.c b/tests/test-utils.c index 9848d9ba..f4632a9b 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -108,6 +108,9 @@ test_init (int argc, char **argv, GOptionEntry *entries) if (debug_level > 0 || http_debug_level > 0) parallelize = !parallelize; + if (g_getenv ("SOUP_TESTS_IN_MAKE_CHECK")) + debug_level = G_MAXINT; + /* Exit cleanly on ^C in case we're valgrinding. */ signal (SIGINT, quit); -- cgit v1.2.1 From a241493298bc87748a79fdfaa7e7f1d657906065 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 23 Oct 2013 08:57:45 +0100 Subject: soup-server: clarify soup_server_[un]pause_message() documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a SoupMessage which hasn’t yet started to be received is passed into soup_server_[un]pause_message(), an assertion will fail in soup-message-io.c because the message doesn’t yet have any I/O data. Document that passing such SoupMessages into those methods is naughty and shouldn’t be done. https://bugzilla.gnome.org/show_bug.cgi?id=710602 --- libsoup/soup-server.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index 3d3070a2..07d801d1 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -1551,6 +1551,10 @@ soup_server_remove_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain) * Pauses I/O on @msg. This can be used when you need to return from * the server handler without having the full response ready yet. Use * soup_server_unpause_message() to resume I/O. + * + * This must only be called on #SoupMessages which were created by the + * #SoupServer and are currently doing I/O, such as those passed into a + * #SoupServerCallback or emitted in a #SoupServer::request-read signal. **/ void soup_server_pause_message (SoupServer *server, @@ -1572,6 +1576,10 @@ soup_server_pause_message (SoupServer *server, * chunked response. * * I/O won't actually resume until you return to the main loop. + * + * This must only be called on #SoupMessages which were created by the + * #SoupServer and are currently doing I/O, such as those passed into a + * #SoupServerCallback or emitted in a #SoupServer::request-read signal. **/ void soup_server_unpause_message (SoupServer *server, -- cgit v1.2.1 From 0f22a7505ae2e41e2a9e17854d9bd362f5a72945 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 17 Nov 2013 09:23:08 -0500 Subject: soup-message: minor fixups to soup_message_set_request/response_body() g_warn_if_fail() if the Content-Type is invalid, and impove the annotations. https://bugzilla.gnome.org/show_bug.cgi?id=686766 --- libsoup/soup-message.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 76130436..b51f234e 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -5,6 +5,8 @@ * Copyright (C) 2000-2003, Ximian, Inc. */ +#include + #include "soup-message.h" #include "soup.h" #include "soup-connection.h" @@ -936,9 +938,10 @@ soup_message_new_from_uri (const char *method, SoupURI *uri) /** * soup_message_set_request: * @msg: the message - * @content_type: MIME Content-Type of the body + * @content_type: (allow-none): MIME Content-Type of the body * @req_use: a #SoupMemoryUse describing how to handle @req_body - * @req_body: a data buffer containing the body of the message request. + * @req_body: (allow-none) (array length=req_length) (element-type guint8): + * a data buffer containing the body of the message request. * @req_length: the byte length of @req_body. * * Convenience function to set the request body of a #SoupMessage. If @@ -955,6 +958,8 @@ soup_message_set_request (SoupMessage *msg, g_return_if_fail (content_type != NULL || req_length == 0); if (content_type) { + g_warn_if_fail (strchr (content_type, '/') != NULL); + soup_message_headers_replace (msg->request_headers, "Content-Type", content_type); soup_message_body_append (msg->request_body, req_use, @@ -971,8 +976,8 @@ soup_message_set_request (SoupMessage *msg, * @msg: the message * @content_type: (allow-none): MIME Content-Type of the body * @resp_use: a #SoupMemoryUse describing how to handle @resp_body - * @resp_body: (array length=resp_length) (element-type guint8): a data buffer - * containing the body of the message response. + * @resp_body: (allow-none) (array length=resp_length) (element-type guint8): + * a data buffer containing the body of the message response. * @resp_length: the byte length of @resp_body. * * Convenience function to set the response body of a #SoupMessage. If @@ -989,6 +994,8 @@ soup_message_set_response (SoupMessage *msg, g_return_if_fail (content_type != NULL || resp_length == 0); if (content_type) { + g_warn_if_fail (strchr (content_type, '/') != NULL); + soup_message_headers_replace (msg->response_headers, "Content-Type", content_type); soup_message_body_append (msg->response_body, resp_use, -- cgit v1.2.1 From 16fa40768078ed676b6ffe6ad0f5334a273ed428 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 17 Nov 2013 09:47:02 -0500 Subject: session-test: fix to work with the dummy TLS backend do_property_tests() apparently didn't work with the dummy TLS backend, half because of a glib bug, and half because of a session-test bug. This fixes the session-test bug; the glib bug is fixed in glib master. --- tests/session-test.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/session-test.c b/tests/session-test.c index d40e7766..205885d7 100644 --- a/tests/session-test.c +++ b/tests/session-test.c @@ -368,14 +368,19 @@ do_property_tests (void) default_proxy_resolver, NULL); g_object_unref (session); - tlsdb = g_tls_file_database_new (SRCDIR "/test-cert.pem", NULL); - session = g_object_new (SOUP_TYPE_SESSION, - SOUP_SESSION_TLS_DATABASE, tlsdb, - NULL); - test_session_properties ("Session with non-NULL :tls-database", session, - default_proxy_resolver, tlsdb); - g_object_unref (tlsdb); - g_object_unref (session); + /* g_tls_file_database_new() will fail with the dummy backend, + * so we can only do this test if we have a real TLS backend. + */ + if (tls_available) { + tlsdb = g_tls_file_database_new (SRCDIR "/test-cert.pem", NULL); + session = g_object_new (SOUP_TYPE_SESSION, + SOUP_SESSION_TLS_DATABASE, tlsdb, + NULL); + test_session_properties ("Session with non-NULL :tls-database", session, + default_proxy_resolver, tlsdb); + g_object_unref (tlsdb); + g_object_unref (session); + } session = g_object_new (SOUP_TYPE_SESSION, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, FALSE, -- cgit v1.2.1 From d24e469c9a4e11a6ca05dab8b4c95d4d14186c75 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 25 Aug 2013 11:05:44 -0400 Subject: SoupMessage: add :request-body-data and :response-body-data properties Make it easier to use the request and response bodies from introspection by providing accessors to get them as GBytes. https://bugzilla.gnome.org/show_bug.cgi?id=704105 --- libsoup/soup-message.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ libsoup/soup-message.h | 32 +++++++++++++++------------- 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index b51f234e..07967fc2 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -131,8 +131,10 @@ enum { PROP_REASON_PHRASE, PROP_FIRST_PARTY, PROP_REQUEST_BODY, + PROP_REQUEST_BODY_DATA, PROP_REQUEST_HEADERS, PROP_RESPONSE_BODY, + PROP_RESPONSE_BODY_DATA, PROP_RESPONSE_HEADERS, PROP_TLS_CERTIFICATE, PROP_TLS_ERRORS, @@ -254,6 +256,7 @@ soup_message_get_property (GObject *object, guint prop_id, { SoupMessage *msg = SOUP_MESSAGE (object); SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); + SoupBuffer *buf; switch (prop_id) { case PROP_METHOD: @@ -283,12 +286,22 @@ soup_message_get_property (GObject *object, guint prop_id, case PROP_REQUEST_BODY: g_value_set_boxed (value, msg->request_body); break; + case PROP_REQUEST_BODY_DATA: + buf = soup_message_body_flatten (msg->request_body); + g_value_take_boxed (value, soup_buffer_get_as_bytes (buf)); + soup_buffer_free (buf); + break; case PROP_REQUEST_HEADERS: g_value_set_boxed (value, msg->request_headers); break; case PROP_RESPONSE_BODY: g_value_set_boxed (value, msg->response_body); break; + case PROP_RESPONSE_BODY_DATA: + buf = soup_message_body_flatten (msg->response_body); + g_value_take_boxed (value, soup_buffer_get_as_bytes (buf)); + soup_buffer_free (buf); + break; case PROP_RESPONSE_HEADERS: g_value_set_boxed (value, msg->response_headers); break; @@ -783,6 +796,28 @@ soup_message_class_init (SoupMessageClass *message_class) "The HTTP request content", SOUP_TYPE_MESSAGE_BODY, G_PARAM_READABLE)); + /** + * SOUP_MESSAGE_REQUEST_BODY_DATA: + * + * Alias for the #SoupMessage:request-body-data property. (The + * message's HTTP request body, as a #GBytes.) + * + * Since: 2.46 + **/ + /** + * SoupMessage:request-body-data: + * + * The message's HTTP request body, as a #GBytes. + * + * Since: 2.46 + **/ + g_object_class_install_property ( + object_class, PROP_REQUEST_BODY_DATA, + g_param_spec_boxed (SOUP_MESSAGE_REQUEST_BODY_DATA, + "Request Body Data", + "The HTTP request body", + G_TYPE_BYTES, + G_PARAM_READABLE)); /** * SOUP_MESSAGE_REQUEST_HEADERS: * @@ -809,6 +844,28 @@ soup_message_class_init (SoupMessageClass *message_class) "The HTTP response content", SOUP_TYPE_MESSAGE_BODY, G_PARAM_READABLE)); + /** + * SOUP_MESSAGE_RESPONSE_BODY_DATA: + * + * Alias for the #SoupMessage:response-body-data property. (The + * message's HTTP response body, as a #GBytes.) + * + * Since: 2.46 + **/ + /** + * SoupMessage:response-body-data: + * + * The message's HTTP response body, as a #GBytes. + * + * Since: 2.46 + **/ + g_object_class_install_property ( + object_class, PROP_RESPONSE_BODY_DATA, + g_param_spec_boxed (SOUP_MESSAGE_RESPONSE_BODY_DATA, + "Response Body Data", + "The HTTP response body", + G_TYPE_BYTES, + G_PARAM_READABLE)); /** * SOUP_MESSAGE_RESPONSE_HEADERS: * diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index 22c2b1ed..b02d293b 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -60,21 +60,23 @@ typedef struct { GType soup_message_get_type (void); -#define SOUP_MESSAGE_METHOD "method" -#define SOUP_MESSAGE_URI "uri" -#define SOUP_MESSAGE_HTTP_VERSION "http-version" -#define SOUP_MESSAGE_FLAGS "flags" -#define SOUP_MESSAGE_SERVER_SIDE "server-side" -#define SOUP_MESSAGE_STATUS_CODE "status-code" -#define SOUP_MESSAGE_REASON_PHRASE "reason-phrase" -#define SOUP_MESSAGE_FIRST_PARTY "first-party" -#define SOUP_MESSAGE_REQUEST_BODY "request-body" -#define SOUP_MESSAGE_REQUEST_HEADERS "request-headers" -#define SOUP_MESSAGE_RESPONSE_BODY "response-body" -#define SOUP_MESSAGE_RESPONSE_HEADERS "response-headers" -#define SOUP_MESSAGE_TLS_CERTIFICATE "tls-certificate" -#define SOUP_MESSAGE_TLS_ERRORS "tls-errors" -#define SOUP_MESSAGE_PRIORITY "priority" +#define SOUP_MESSAGE_METHOD "method" +#define SOUP_MESSAGE_URI "uri" +#define SOUP_MESSAGE_HTTP_VERSION "http-version" +#define SOUP_MESSAGE_FLAGS "flags" +#define SOUP_MESSAGE_SERVER_SIDE "server-side" +#define SOUP_MESSAGE_STATUS_CODE "status-code" +#define SOUP_MESSAGE_REASON_PHRASE "reason-phrase" +#define SOUP_MESSAGE_FIRST_PARTY "first-party" +#define SOUP_MESSAGE_REQUEST_BODY "request-body" +#define SOUP_MESSAGE_REQUEST_BODY_DATA "request-body-data" +#define SOUP_MESSAGE_REQUEST_HEADERS "request-headers" +#define SOUP_MESSAGE_RESPONSE_BODY "response-body" +#define SOUP_MESSAGE_RESPONSE_BODY_DATA "response-body-data" +#define SOUP_MESSAGE_RESPONSE_HEADERS "response-headers" +#define SOUP_MESSAGE_TLS_CERTIFICATE "tls-certificate" +#define SOUP_MESSAGE_TLS_ERRORS "tls-errors" +#define SOUP_MESSAGE_PRIORITY "priority" SoupMessage *soup_message_new (const char *method, const char *uri_string); -- cgit v1.2.1 From b16b45344b10d6dc3abcca10ed477c5ea45787c8 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 20 Nov 2013 17:18:57 -0500 Subject: no-ssl-test: fix for GDummyTlsBackend changes This was assuming that setting "ssl-use-system-ca-file" would fail when using the dummy TLS backend, but the fact that it failed was just a side effect of the fact that GDummyTlsBackend returned a different GTlsDatabase every time you called g_tls_backend_get_default_database(). Now that that's fixed, setting "ssl-use-system-ca-file" does appear to work. Of course, SSL won't work at all with the dummy backend, so it doesn't really matter whether setting this property works or not, so just remove that part of the test, so this will pass with either old or new glib. --- tests/no-ssl-test.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c index 89a75206..f442ea0e 100644 --- a/tests/no-ssl-test.c +++ b/tests/no-ssl-test.c @@ -92,13 +92,8 @@ do_session_property_tests (void) "ssl-use-system-ca-file", TRUE, NULL); g_object_get (G_OBJECT (session), - "ssl-use-system-ca-file", &use_system, "ssl-ca-file", &ca_file, NULL); - if (use_system) { - debug_printf (1, " setting ssl-use-system-ca-file did not fail\n"); - errors++; - } if (ca_file) { debug_printf (1, " setting ssl-use-system-ca-file set ssl-ca-file\n"); errors++; -- cgit v1.2.1 From 86acc457ab068ff71c5afc5007263d5ac0aadfa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=98=E9=9C=B2=28Gan=20=20Lu=29?= Date: Sat, 7 Dec 2013 14:17:56 +0800 Subject: Update Chinese simplified translation --- po/zh_CN.po | 67 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/po/zh_CN.po b/po/zh_CN.po index 964bdae4..c1ea76fc 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -11,76 +11,101 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2012-09-10 15:07+0000\n" -"PO-Revision-Date: 2012-09-23 05:00+0800\n" -"Last-Translator: YunQiang Su \n" +"POT-Creation-Date: 2013-11-04 21:49+0000\n" +"PO-Revision-Date: 2013-09-07 14:07+0700\n" +"Last-Translator: 甘露(Gan Lu) \n" "Language-Team: Chinese (simplified) \n" -"Language: \n" +"Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bits\n" +"Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Gtranslator 2.91.5\n" +"X-Generator: Poedit 1.5.4\n" -#: ../libsoup/soup-body-input-stream.c:141 -#: ../libsoup/soup-body-input-stream.c:172 -#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:140 +#: ../libsoup/soup-body-input-stream.c:171 +#: ../libsoup/soup-body-input-stream.c:204 ../libsoup/soup-message-io.c:197 msgid "Connection terminated unexpectedly" msgstr "连接异常终止" -#: ../libsoup/soup-body-input-stream.c:461 +#: ../libsoup/soup-body-input-stream.c:462 msgid "Invalid seek request" msgstr "无效的 seek 请求" -#: ../libsoup/soup-body-input-stream.c:489 +#: ../libsoup/soup-body-input-stream.c:490 msgid "Cannot truncate SoupBodyInputStream" msgstr "不能截断(truncate) SoupBodyInputStream" +#: ../libsoup/soup-cache-input-stream.c:73 +msgid "Network stream unexpectedly closed" +msgstr "网络流意外关闭" + +#: ../libsoup/soup-cache-input-stream.c:290 +msgid "Failed to completely cache the resource" +msgstr "无法完全缓存该资源" + #: ../libsoup/soup-converter-wrapper.c:192 #, c-format msgid "Output buffer is too small" msgstr "输出缓冲区太小" -#: ../libsoup/soup-message-io.c:818 ../libsoup/soup-message-io.c:854 +#: ../libsoup/soup-message-client-io.c:41 +msgid "Could not parse HTTP response" +msgstr "无法解析 HTTP 响应" + +#: ../libsoup/soup-message-client-io.c:66 +msgid "Unrecognized HTTP response encoding" +msgstr "未识别的 HTTP 响应编码" + +#: ../libsoup/soup-message-io.c:855 ../libsoup/soup-message-io.c:891 msgid "Operation was cancelled" msgstr "操作被取消" -#: ../libsoup/soup-message-io.c:865 +#: ../libsoup/soup-message-io.c:902 msgid "Operation would block" msgstr "操作将阻塞" -#: ../libsoup/soup-request.c:142 +#: ../libsoup/soup-message-server-io.c:40 +msgid "Could not parse HTTP request" +msgstr "无法解析 HTTP 请求" + +#: ../libsoup/soup-request.c:140 #, c-format msgid "No URI provided" msgstr "未提供 URI" -#: ../libsoup/soup-request.c:152 +#: ../libsoup/soup-request.c:150 #, c-format msgid "Invalid '%s' URI: %s" msgstr "无效的“%s”URI:%s" -#: ../libsoup/soup-requester.c:219 +#: ../libsoup/soup-session.c:4393 #, c-format msgid "Could not parse URI '%s'" msgstr "无法解析 URI:“%s”" -#: ../libsoup/soup-requester.c:253 +#: ../libsoup/soup-session.c:4430 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "不支持的 URI 方案:“%s”" -#: ../libsoup/soup-tld.c:154 +#: ../libsoup/soup-session.c:4452 +#, c-format +msgid "Not an HTTP URI" +msgstr "不是一个 HTTP URI" + +#: ../libsoup/soup-tld.c:185 msgid "Hostname is an IP address" msgstr "主机名是一个 IP 地址" -#: ../libsoup/soup-tld.c:175 +#: ../libsoup/soup-tld.c:206 msgid "Invalid hostname" msgstr "主机名无效" -#: ../libsoup/soup-tld.c:204 +#: ../libsoup/soup-tld.c:235 msgid "Hostname has no base domain" msgstr "主机名没有基域" -#: ../libsoup/soup-tld.c:226 +#: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "没有足够的域" -- cgit v1.2.1 From d867737856aba6d5ad49ddbad0316e987bdae90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=98=E9=9C=B2=28Gan=20=20Lu=29?= Date: Sat, 7 Dec 2013 14:19:37 +0800 Subject: Update Chinese simplified translation --- po/zh_CN.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/po/zh_CN.po b/po/zh_CN.po index c1ea76fc..3f746aa0 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -11,7 +11,7 @@ msgstr "" "Project-Id-Version: libsoup master\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=libsoup&keywords=I18N+L10N&component=general\n" -"POT-Creation-Date: 2013-11-04 21:49+0000\n" +"POT-Creation-Date: 2013-11-11 22:47+0000\n" "PO-Revision-Date: 2013-09-07 14:07+0700\n" "Last-Translator: 甘露(Gan Lu) \n" "Language-Team: Chinese (simplified) \n" @@ -79,17 +79,17 @@ msgstr "未提供 URI" msgid "Invalid '%s' URI: %s" msgstr "无效的“%s”URI:%s" -#: ../libsoup/soup-session.c:4393 +#: ../libsoup/soup-session.c:4302 #, c-format msgid "Could not parse URI '%s'" msgstr "无法解析 URI:“%s”" -#: ../libsoup/soup-session.c:4430 +#: ../libsoup/soup-session.c:4339 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "不支持的 URI 方案:“%s”" -#: ../libsoup/soup-session.c:4452 +#: ../libsoup/soup-session.c:4361 #, c-format msgid "Not an HTTP URI" msgstr "不是一个 HTTP URI" -- cgit v1.2.1 From 7effd70bbe2e2a1a1e72279539f27250af9e37ea Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 30 Nov 2013 20:00:50 -0500 Subject: soup-version: add 2.46 --- libsoup/soup-version.h.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libsoup/soup-version.h.in b/libsoup/soup-version.h.in index c3ad8c67..000b9456 100644 --- a/libsoup/soup-version.h.in +++ b/libsoup/soup-version.h.in @@ -47,6 +47,7 @@ gboolean soup_check_version (guint major, #define SOUP_VERSION_2_40 (SOUP_ENCODE_VERSION (2, 40)) #define SOUP_VERSION_2_42 (SOUP_ENCODE_VERSION (2, 42)) #define SOUP_VERSION_2_44 (SOUP_ENCODE_VERSION (2, 44)) +#define SOUP_VERSION_2_46 (SOUP_ENCODE_VERSION (2, 46)) /* evaluates to the current stable version; for development cycles, * this means the next stable target @@ -241,6 +242,20 @@ gboolean soup_check_version (guint major, # define SOUP_AVAILABLE_IN_2_44 #endif +#if SOUP_VERSION_MIN_REQUIRED >= SOUP_VERSION_2_46 +# define SOUP_DEPRECATED_IN_2_46 GLIB_DEPRECATED +# define SOUP_DEPRECATED_IN_2_46_FOR(f) GLIB_DEPRECATED_FOR(f) +#else +# define SOUP_DEPRECATED_IN_2_46 +# define SOUP_DEPRECATED_IN_2_46_FOR(f) +#endif + +#if SOUP_VERSION_MAX_ALLOWED < SOUP_VERSION_2_46 +# define SOUP_AVAILABLE_IN_2_46 GLIB_UNAVAILABLE(2, 46) +#else +# define SOUP_AVAILABLE_IN_2_46 +#endif + G_END_DECLS #endif /* SOUP_VERSION_H */ -- cgit v1.2.1 From 48419347e7682a242ee94afbdb35001ccd02aaec Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 30 Nov 2013 20:28:17 -0500 Subject: no-ssl-test: fix indentation --- tests/no-ssl-test.c | 302 ++++++++++++++++++++++++++-------------------------- 1 file changed, 151 insertions(+), 151 deletions(-) diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c index f442ea0e..ab1bdc3a 100644 --- a/tests/no-ssl-test.c +++ b/tests/no-ssl-test.c @@ -5,148 +5,148 @@ static void do_ssl_test_for_session (SoupSession *session, char *uri) { - SoupMessage *msg; - GTlsCertificate *cert; - GTlsCertificateFlags flags; - - msg = soup_message_new ("GET", uri); - soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_SSL_FAILED) { - debug_printf (1, " Unexpected status: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - - if (soup_message_get_https_status (msg, &cert, &flags)) { - debug_printf (1, " get_http_status() returned TRUE? (flags %x)\n", flags); - errors++; - if (cert) { - debug_printf (1, " Got GTlsCertificate?\n"); - errors++; - } - } - if (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) { - debug_printf (1, " CERTIFICATE_TRUSTED set?\n"); - errors++; - } - - g_object_unref (msg); + SoupMessage *msg; + GTlsCertificate *cert; + GTlsCertificateFlags flags; + + msg = soup_message_new ("GET", uri); + soup_session_send_message (session, msg); + if (msg->status_code != SOUP_STATUS_SSL_FAILED) { + debug_printf (1, " Unexpected status: %d %s\n", + msg->status_code, msg->reason_phrase); + errors++; + } + + if (soup_message_get_https_status (msg, &cert, &flags)) { + debug_printf (1, " get_http_status() returned TRUE? (flags %x)\n", flags); + errors++; + if (cert) { + debug_printf (1, " Got GTlsCertificate?\n"); + errors++; + } + } + if (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) { + debug_printf (1, " CERTIFICATE_TRUSTED set?\n"); + errors++; + } + + g_object_unref (msg); } static void do_ssl_tests (char *uri) { - SoupSession *session; + SoupSession *session; - debug_printf (1, "\nSoupSession without SSL support\n"); + debug_printf (1, "\nSoupSession without SSL support\n"); - debug_printf (1, " plain\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); - do_ssl_test_for_session (session, uri); - soup_test_session_abort_unref (session); + debug_printf (1, " plain\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); - debug_printf (1, " async\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - do_ssl_test_for_session (session, uri); - soup_test_session_abort_unref (session); + debug_printf (1, " async\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); - debug_printf (1, " sync\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - do_ssl_test_for_session (session, uri); - soup_test_session_abort_unref (session); + debug_printf (1, " sync\n"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + do_ssl_test_for_session (session, uri); + soup_test_session_abort_unref (session); } static void do_session_property_tests (void) { - gboolean use_system; - GTlsDatabase *tlsdb; - char *ca_file; - SoupSession *session; - - debug_printf (1, "session properties\n"); - - session = soup_session_async_new (); - - g_object_get (G_OBJECT (session), - "ssl-use-system-ca-file", &use_system, - "tls-database", &tlsdb, - "ssl-ca-file", &ca_file, - NULL); - if (use_system) { - debug_printf (1, " ssl-use-system-ca-file defaults to TRUE?\n"); - errors++; - } - if (tlsdb) { - debug_printf (1, " tls-database set by default?\n"); - errors++; - g_object_unref (tlsdb); - } - if (ca_file) { - debug_printf (1, " ca-file set by default?\n"); - errors++; - g_free (ca_file); - } - - g_object_set (G_OBJECT (session), - "ssl-use-system-ca-file", TRUE, - NULL); - g_object_get (G_OBJECT (session), - "ssl-ca-file", &ca_file, - NULL); - if (ca_file) { - debug_printf (1, " setting ssl-use-system-ca-file set ssl-ca-file\n"); - errors++; - g_free (ca_file); - } - - g_object_set (G_OBJECT (session), - "ssl-ca-file", SRCDIR "/test-cert.pem", - NULL); - g_object_get (G_OBJECT (session), - "ssl-use-system-ca-file", &use_system, - "tls-database", &tlsdb, - "ssl-ca-file", &ca_file, - NULL); - if (ca_file) { - debug_printf (1, " setting ssl-ca-file did not fail\n"); - errors++; - g_free (ca_file); - } - if (use_system) { - debug_printf (1, " setting ssl-ca-file set ssl-use-system-ca-file\n"); - errors++; - } - if (tlsdb) { - debug_printf (1, " setting ssl-ca-file set tls-database\n"); - errors++; - g_object_unref (tlsdb); - } - - g_object_set (G_OBJECT (session), - "tls-database", NULL, - NULL); - g_object_get (G_OBJECT (session), - "ssl-use-system-ca-file", &use_system, - "tls-database", &tlsdb, - "ssl-ca-file", &ca_file, - NULL); - if (tlsdb) { - debug_printf (1, " setting tls-database NULL failed\n"); - errors++; - g_object_unref (tlsdb); - } - if (use_system) { - debug_printf (1, " setting tls-database NULL set ssl-use-system-ca-file\n"); - errors++; - } - if (ca_file) { - debug_printf (1, " setting tls-database NULL set ssl-ca-file\n"); - errors++; - g_free (ca_file); - } - - soup_test_session_abort_unref (session); + gboolean use_system; + GTlsDatabase *tlsdb; + char *ca_file; + SoupSession *session; + + debug_printf (1, "session properties\n"); + + session = soup_session_async_new (); + + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + if (use_system) { + debug_printf (1, " ssl-use-system-ca-file defaults to TRUE?\n"); + errors++; + } + if (tlsdb) { + debug_printf (1, " tls-database set by default?\n"); + errors++; + g_object_unref (tlsdb); + } + if (ca_file) { + debug_printf (1, " ca-file set by default?\n"); + errors++; + g_free (ca_file); + } + + g_object_set (G_OBJECT (session), + "ssl-use-system-ca-file", TRUE, + NULL); + g_object_get (G_OBJECT (session), + "ssl-ca-file", &ca_file, + NULL); + if (ca_file) { + debug_printf (1, " setting ssl-use-system-ca-file set ssl-ca-file\n"); + errors++; + g_free (ca_file); + } + + g_object_set (G_OBJECT (session), + "ssl-ca-file", SRCDIR "/test-cert.pem", + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + if (ca_file) { + debug_printf (1, " setting ssl-ca-file did not fail\n"); + errors++; + g_free (ca_file); + } + if (use_system) { + debug_printf (1, " setting ssl-ca-file set ssl-use-system-ca-file\n"); + errors++; + } + if (tlsdb) { + debug_printf (1, " setting ssl-ca-file set tls-database\n"); + errors++; + g_object_unref (tlsdb); + } + + g_object_set (G_OBJECT (session), + "tls-database", NULL, + NULL); + g_object_get (G_OBJECT (session), + "ssl-use-system-ca-file", &use_system, + "tls-database", &tlsdb, + "ssl-ca-file", &ca_file, + NULL); + if (tlsdb) { + debug_printf (1, " setting tls-database NULL failed\n"); + errors++; + g_object_unref (tlsdb); + } + if (use_system) { + debug_printf (1, " setting tls-database NULL set ssl-use-system-ca-file\n"); + errors++; + } + if (ca_file) { + debug_printf (1, " setting tls-database NULL set ssl-ca-file\n"); + errors++; + g_free (ca_file); + } + + soup_test_session_abort_unref (session); } static void @@ -157,38 +157,38 @@ server_handler (SoupServer *server, SoupClientContext *client, gpointer user_data) { - soup_message_set_status (msg, SOUP_STATUS_OK); - soup_message_set_response (msg, "text/plain", - SOUP_MEMORY_STATIC, - "ok\r\n", 4); + soup_message_set_status (msg, SOUP_STATUS_OK); + soup_message_set_response (msg, "text/plain", + SOUP_MEMORY_STATIC, + "ok\r\n", 4); } int main (int argc, char **argv) { - SoupServer *server; - char *uri; + SoupServer *server; + char *uri; - /* Force this test to use the dummy TLS backend */ - g_setenv ("GIO_USE_TLS", "dummy", TRUE); + /* Force this test to use the dummy TLS backend */ + g_setenv ("GIO_USE_TLS", "dummy", TRUE); - test_init (argc, argv, NULL); + test_init (argc, argv, NULL); - /* Make a non-SSL server and pretend that it's ssl, which is fine - * since we won't ever actually talk to it anyway. We don't - * currently test that failing to construct an SSL server works. - */ - server = soup_test_server_new (TRUE); - soup_server_add_handler (server, NULL, server_handler, NULL, NULL); - uri = g_strdup_printf ("https://127.0.0.1:%u/", - soup_server_get_port (server)); + /* Make a non-SSL server and pretend that it's ssl, which is fine + * since we won't ever actually talk to it anyway. We don't + * currently test that failing to construct an SSL server works. + */ + server = soup_test_server_new (TRUE); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = g_strdup_printf ("https://127.0.0.1:%u/", + soup_server_get_port (server)); - do_session_property_tests (); - do_ssl_tests (uri); + do_session_property_tests (); + do_ssl_tests (uri); - g_free (uri); - soup_test_server_quit_unref (server); + g_free (uri); + soup_test_server_quit_unref (server); - test_cleanup (); - return errors != 0; + test_cleanup (); + return errors != 0; } -- cgit v1.2.1 From c2c2ecbf7d021bb5445a205ec8c66286afaf1008 Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Sun, 8 Dec 2013 15:41:56 -0500 Subject: fix up non-literal format string issues Fix up a couple of errors picked up by -Werror=format-nonliteral on clang. https://bugzilla.gnome.org/show_bug.cgi?id=720082 --- libsoup/soup-xmlrpc.c | 5 +++++ tests/coding-test.c | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libsoup/soup-xmlrpc.c b/libsoup/soup-xmlrpc.c index 8d711d3b..e2890100 100644 --- a/libsoup/soup-xmlrpc.c +++ b/libsoup/soup-xmlrpc.c @@ -289,6 +289,11 @@ soup_xmlrpc_build_method_response (GValue *value) return body; } +static char * +soup_xmlrpc_build_faultv (int fault_code, + const char *fault_format, + va_list args) G_GNUC_PRINTF (2, 0); + static char * soup_xmlrpc_build_faultv (int fault_code, const char *fault_format, va_list args) { diff --git a/tests/coding-test.c b/tests/coding-test.c index 30417b47..1bffbc43 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -33,7 +33,7 @@ server_callback (SoupServer *server, SoupMessage *msg, if (codings) { gboolean claim_deflate, claim_gzip; - const char *file_path = NULL, *encoding = NULL; + const char *extension = NULL, *encoding = NULL; claim_deflate = g_slist_find_custom (codings, "deflate", (GCompareFunc)g_ascii_strcasecmp) != NULL; claim_gzip = g_slist_find_custom (codings, "gzip", (GCompareFunc)g_ascii_strcasecmp) != NULL; @@ -41,19 +41,19 @@ server_callback (SoupServer *server, SoupMessage *msg, if (claim_gzip && (!claim_deflate || (!soup_header_contains (options, "prefer-deflate-zlib") && !soup_header_contains (options, "prefer-deflate-raw")))) { - file_path = SRCDIR "/resources%s.gz"; + extension = "gz"; encoding = "gzip"; } else if (claim_deflate) { if (soup_header_contains (options, "prefer-deflate-raw")) { - file_path = SRCDIR "/resources%s.raw"; + extension = "raw"; encoding = "deflate"; } else { - file_path = SRCDIR "/resources%s.zlib"; + extension = "zlib"; encoding = "deflate"; } } - if (file_path && encoding) { - file = g_strdup_printf (file_path, path); + if (extension && encoding) { + file = g_strdup_printf (SRCDIR "/resources%s.%s", path, extension); if (g_file_test (file, G_FILE_TEST_EXISTS)) { soup_message_headers_append (msg->response_headers, "Content-Encoding", -- cgit v1.2.1 From dd3e2f4d9be661a5fae96c81618fb25c438916da Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 10 Dec 2013 10:34:08 +0100 Subject: SoupSocket: set TCP_NODELAY on sockets The old SoupSocket did this but it accidentally got removed in the GSocket port because I thought it didn't matter. It does. Noticed by Andy Wingo. --- libsoup/soup-socket.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index c101fa52..e0748fd1 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -182,6 +182,7 @@ finish_socket_setup (SoupSocketPrivate *priv) priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream)); g_socket_set_timeout (priv->gsock, priv->timeout); + g_socket_set_option (priv->gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL); } static void -- cgit v1.2.1 From c2d0f8d19eb25f21838a1ddfd4baab1c0218ac9c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 11 Dec 2013 11:44:31 +0100 Subject: docs: Update client-side tutorial for 2.42, document request APIs --- docs/reference/Makefile.am | 1 + docs/reference/client-howto.xml | 406 ++++++++++++++++---------------- docs/reference/libsoup-2.4-docs.sgml | 1 + docs/reference/libsoup-2.4-sections.txt | 1 + docs/reference/request-howto.xml | 184 +++++++++++++++ 5 files changed, 391 insertions(+), 202 deletions(-) create mode 100644 docs/reference/request-howto.xml diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 36e77006..a11ce395 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -53,6 +53,7 @@ HTML_IMAGES = content_files = \ build-howto.xml \ client-howto.xml \ + request-howto.xml \ server-howto.xml \ session-porting.xml diff --git a/docs/reference/client-howto.xml b/docs/reference/client-howto.xml index 3cf5a4e1..d4d0f37b 100644 --- a/docs/reference/client-howto.xml +++ b/docs/reference/client-howto.xml @@ -3,15 +3,25 @@ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"> -Soup Client Basics +libsoup Client Basics 3 LIBSOUP Library -Soup Client BasicsClient-side tutorial +libsoup Client BasicsClient-side tutorial + + +This section explains how to use libsoup as +an HTTP client using several new APIs introduced in version 2.42. If +you want to be compatible with older versions of +libsoup, consult the documentation for that +version. + + + Creating a <type>SoupSession</type> @@ -24,35 +34,8 @@ authentication information, etc. -There are two subclasses of SoupSession that you can use, with -slightly different behavior: - - - - - SoupSessionAsync, - which uses callbacks and the glib main loop to provide - asynchronous I/O. - - - - SoupSessionSync, - which uses blocking I/O rather than callbacks, making it more - suitable for threaded applications. - - - - -If you want to do a mix of mainloop-based and blocking I/O, you will -need to create two different session objects. - - - -When you create the session (with soup_session_async_new_with_options -or soup_session_sync_new_with_options), +When you create the session with soup_session_new_with_options, you can specify various additional options: @@ -64,7 +47,7 @@ you can specify various additional options: the session will have open at one time. (Once it reaches this limit, it will either close idle connections, or wait for existing connections to free up before starting - new requests.) + new requests.) The default value is 10. @@ -72,43 +55,60 @@ you can specify various additional options: Allows you to set the maximum total number of connections the session will have open to a single - host at one time. + host at one time. The default value is 2. - SOUP_SESSION_USE_NTLM + SOUP_SESSION_USER_AGENT - If TRUE, then Microsoft NTLM - authentication will be used if available (and will be - preferred to HTTP Basic or Digest authentication). - If FALSE, NTLM authentication won't be - used, even if it's the only authentication type available. - (NTLM works differently from the standard HTTP - authentication types, so it needs to be handled - specially.) + Allows you to set a User-Agent string that will be sent + on all outgoing requests. - SOUP_SESSION_SSL_CA_FILE + SOUP_SESSION_ACCEPT_LANGUAGE + and SOUP_SESSION_ACCEPT_LANGUAGE_AUTO - Points to a file containing certificates for recognized - SSL Certificate Authorities. If this is set, then HTTPS - connections will be checked against these authorities, and - rejected if they can't be verified. (Otherwise all SSL - certificates will be accepted automatically.) + Allow you to set an Accept-Language header on all outgoing + requests. SOUP_SESSION_ACCEPT_LANGUAGE + takes a list of language tags to use, while + SOUP_SESSION_ACCEPT_LANGUAGE_AUTO + automatically generates the list from the user's locale + settings. - SOUP_SESSION_ASYNC_CONTEXT + SOUP_SESSION_HTTP_ALIASES + and SOUP_SESSION_HTTPS_ALIASES - A GMainContext - which the session will use for asynchronous operations. - This can be set if you want to use a - SoupSessionAsync in a thread other than the - main thread. + Allow you to tell the session to recognize additional URI + schemes as aliases for "http" or + https. You can set this if you are + using URIs with schemes like "dav" or + "webcal" (and in particular, you need + to set this if the server you are talking to might return + redirects with such a scheme). + + SOUP_SESSION_PROXY_RESOLVER and SOUP_SESSION_PROXY_URI + + + SOUP_SESSION_PROXY_RESOLVER + specifies a GProxyResolver + to use to determine the HTTP proxies to use. By default, + this is set to the resolver returned by g_proxy_resolver_get_default, + so you do not need to set it yourself. + + + Alternatively, if you want all requests to go through a + single proxy, you can set SOUP_SESSION_PROXY_URI. + + + SOUP_SESSION_ADD_FEATURE and SOUP_SESSION_ADD_FEATURE_BY_TYPE @@ -120,11 +120,16 @@ you can specify various additional options: + +Other properties are also available; see the SoupSession documentation for +more details. + + If you don't need to specify any options, you can just use soup_session_async_new or -soup_session_sync_new, -which take no arguments. +linkend="soup-session-new">soup_session_new, +which takes no arguments. @@ -143,8 +148,19 @@ options at session-construction-time, or afterward via the soup_session_add_feature and soup_session_add_feature_by_type -functions. Some of the features available in -libsoup are: +functions. + + + +A SoupContentDecoder is +added for you automatically. This advertises to servers that the +client supports compression, and automatically decompresses compressed +responses. + + + +Some other available features that you can add include: @@ -156,26 +172,27 @@ functions. Some of the features available in - SoupCookieJar and SoupCookieJarText + + SoupCookieJar, + SoupCookieJarText, + and SoupCookieJarDB + Support for HTTP cookies. SoupCookieJar provides non-persistent cookie storage, while SoupCookieJarText uses a text file to keep - track of cookies between sessions. - - - - SoupProxyResolverDefault - - A feature that automatically determines the correct HTTP - proxy to use for requests. + track of cookies between sessions, and + SoupCookieJarDB uses a + SQLite database. - SoupCookieJarDB + SoupContentSniffer - Support for HTTP cookies stored in an - SQLite database. + Uses the HTML5 sniffing rules to attempt to + determine the Content-Type of a response when the + server does not identify the Content-Type, or appears to + have provided an incorrect one. @@ -183,7 +200,7 @@ functions. Some of the features available in Use the "add_feature_by_type" property/function to add features that don't require any configuration (such as SoupProxyResolverDefault), +linkend="SoupContentSniffer">SoupContentSniffer), and the "add_feature" property/function to add features that must be constructed first (such as SoupLogger). For example, an @@ -191,11 +208,10 @@ application might do something like the following: - session = soup_session_async_new_with_options ( -#ifdef HAVE_LIBSOUP_GNOME - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT, -#endif + session = soup_session_new_with_options ( + SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER, NULL); + if (debug_level) { SoupLogger *logger; @@ -211,7 +227,7 @@ application might do something like the following: Creating and Sending SoupMessages -Once you have a session, you do HTTP traffic using SoupMessage. In the simplest case, you only need to create the message and it's ready to send: @@ -235,7 +251,7 @@ request headers and body of the message: msg = soup_message_new ("POST", "http://example.com/form.cgi"); soup_message_set_request (msg, "application/x-www-form-urlencoded", - SOUP_MEMORY_COPY, formdata, strlen (formdata)); + SOUP_MEMORY_COPY, formdata, strlen (formdata)); soup_message_headers_append (msg->request_headers, "Referer", referring_url); @@ -262,28 +278,56 @@ flag. To send a message and wait for the response, use soup_session_send_message: +linkend="soup-session-send">soup_session_send: - guint status; + GInputStream *stream; + GError *error = NULL; - status = soup_session_send_message (session, msg); + stream = soup_session_send (session, msg, cancellable, &error); -(If you use soup_session_send_message with a -SoupSessionAsync, -it will run the main loop itself until the message is complete.) +At the point when soup_session_send returns, the +request will have been sent, and the response headers read back in; +you can examine the message's status_code, +reason_phrase, and +response_headers fields to see the response +metadata. To get the response body, read from the returned GInputStream, and close it +when you are done. -The return value from soup_session_send_message -is a libsoup status code, -indicating either a transport error that prevented the message from -being sent, or the HTTP status that was returned by the server in -response to the message. (The status is also available as -msg->status_code.) +Note that soup_session_send only returns an error +if a transport-level problem occurs (eg, it could not connect to the +host, or the request was cancelled). Use the message's +status_code field to determine whether the +request was successful or not at the HTTP level (ie, "200 +OK" vs "401 Bad Request"). + + + +If you would prefer to have libsoup gather +the response body for you and then return it all at once, you can use +the older +soup_session_send_message +API: + + + + guint status; + + status = soup_session_send_message (session, msg); + + + +In this case, the response body will be available in the message's +response_body field, and transport-level +errors will be indicated in the status_code +field via special pseudo-HTTP-status codes like SOUP_STATUS_CANT_CONNECT. @@ -293,51 +337,63 @@ response to the message. (The status is also available as To send a message asynchronously, use soup_session_queue_message: +linkend="soup-session-send-async">soup_session_send_async: +{ ... - soup_session_queue_message (session, msg, my_callback, my_callback_data); + soup_session_send_async (session, msg, cancellable, my_callback, my_callback_data); ... } static void -my_callback (SoupSession *session, SoupMessage *msg, gpointer user_data) +my_callback (GObject *object, GAsyncResult *result, gpointer user_data) { - /* Handle the response here */ + GInputStream *stream; + GError *error = NULL; + + stream = soup_session_send_finish (SOUP_SESSION (object), result, &error); + ... } The message will be added to the session's queue, and eventually (when control is returned back to the main loop), it will be sent and the -response be will be read. When the message is complete, -callback will be invoked, along with the data you -passed to soup_session_queue_message. +response be will be read. When the message has been sent, and its +headers received, the callback will be invoked, in the standard +GAsyncReadyCallback +style. -soup_session_queue_message -steals a reference to the message object, and unrefs it after the last -callback is invoked on it. So in the usual case, messages sent -asynchronously will be automatically freed for you without you needing -to do anything. (Of course, this wouldn't work when using the synchronous -API, since you will usually need continue working with the message -after calling soup_session_send_message, -so in that case, you must unref it explicitly when you are done with -it.) +As with synchronous sending, there is also an alternate API, soup_session_queue_message, +in which your callback is not invoked until the response has been +completely read: + +{ + ... + soup_session_queue_message (session, msg, my_callback, my_callback_data); + ... +} + +static void +my_callback (SoupSession *session, SoupMessage *msg, gpointer user_data) +{ + /* msg->response_body contains the response */ +} + + -(If you use soup_session_queue_message -with a SoupSessionSync, the -message will be sent in another thread, with the callback eventually -being invoked in the session's SOUP_SESSION_ASYNC_CONTEXT.) +is slightly unusual in that it steals a reference to the message +object, and unrefs it after the last callback is invoked on it. So +when using this API, you should not unref the message yourself. @@ -348,19 +404,17 @@ being invoked in the session's < Processing the Response -Once you have received the response from the server, synchronously or -asynchronously, you can look at the response fields in the -SoupMessage to decide what to do next. The -status_code and +Once you have received the initial response from the server, +synchronously or asynchronously, streaming or not, you can look at the +response fields in the SoupMessage to decide what +to do next. The status_code and reason_phrase fields contain the numeric status and textual status response from the server. response_headers contains the response headers, which you can investigate using soup_message_headers_get and -soup_message_headers_foreach. -The response body (if any) is in the -response_body field. +linkend="soup-message-headers-get">soup_message_headers_get +and soup_message_headers_foreach. @@ -382,41 +436,6 @@ headers much better than functions like - -Intermediate/Automatic Processing - - -You can also connect to various SoupMessage signals to do -processing at intermediate stages of HTTP I/O. Eg, the got-chunk -signal is emitted as each piece of the response body is read (allowing -you to provide progress information when receiving a large response, -for example). SoupMessage also provides two convenience -methods, soup_message_add_header_handler, -and soup_message_add_status_code_handler, -which allow you to set up a signal handler that will only be invoked -for messages with certain response headers or status codes. -SoupSession uses this internally to handle authentication -and redirection. - - - -When using the synchronous API, the callbacks and signal handlers will -be invoked during the call to soup_session_send_message. - - - -To automatically set up handlers on all messages sent via a session, -you can connect to the session's request_started -signal, and add handlers to each message from there. - - - - Handling Authentication @@ -467,38 +486,39 @@ linkend="soup-session-unpause-message">soup_session_unpause_message + +By default, NTLM authentication is not enabled. To add NTLM support to +a session, call: + + + + soup_session_add_feature_by_type (session, SOUP_TYPE_AUTH_NTLM); + + + +(You can also disable Basic or Digest authentication by calling soup_session_remove_feature_by_type +on SOUP_TYPE_AUTH_BASIC +or SOUP_TYPE_AUTH_DIGEST.) + + Multi-threaded usage -The only explicitly thread-safe operations in -libsoup are SoupSessionSync's -implementations of the SoupSession methods. So -after creating a SoupSessionSync, you can call soup_session_send_message -and soup_session_cancel_message -on it from any thread. But, eg, while the session is processing a -message, you should not call any SoupMessage methods on it -from any thread other than the one in which it is being sent. (That -is, you should not call any SoupMessage methods on it -except from a message or session callback or signal handler.) +A SoupSession can be +used from multiple threads. However, if you are using the async APIs, +then each thread you use the session from must have its own +thread-default GMainContext. -All other objects (including SoupSessionAsync) -should only be used from a single thread, with objects that are also -only be used from that thread. (And in particular, if you set a -non-default GMainContext on a session, -socket, etc, then you can only use that object from the thread in -which that GMainContext is running.) +SoupMessage is +not thread-safe, so once you send a message on +the session, you must not interact with it from any thread other than +the one where it was sent. @@ -508,7 +528,8 @@ which that GMainContext is running.) A few sample programs are available in the -libsoup sources: +libsoup sources, in the +examples directory: @@ -517,21 +538,6 @@ A few sample programs are available in the HTTP GET utility using the asynchronous API. - - getbug is a trivial - demonstration of the XMLRPC interface. - (xmlrpc-test provides - a slightly more complicated example.) - - - - auth-test shows how to use - authentication handlers and status-code handlers, although in - a fairly unusual way. - - simple-proxy uses both the client and server APIs to create a simple (and not very @@ -544,11 +550,7 @@ A few sample programs are available in the -More complicated examples are available in GNOME CVS. The libsoup -pages on the GNOME wiki include a list of applications using -libsoup. +More complicated examples are available in GNOME git. diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml index ca92b864..c0c8a05c 100644 --- a/docs/reference/libsoup-2.4-docs.sgml +++ b/docs/reference/libsoup-2.4-docs.sgml @@ -10,6 +10,7 @@ Tutorial + diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index 6b193101..ca423328 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -436,6 +436,7 @@ soup_session_get_feature_for_message soup_session_has_feature SOUP_SESSION_PROXY_URI +SOUP_SESSION_PROXY_RESOLVER SOUP_SESSION_MAX_CONNS SOUP_SESSION_MAX_CONNS_PER_HOST SOUP_SESSION_USE_NTLM diff --git a/docs/reference/request-howto.xml b/docs/reference/request-howto.xml new file mode 100644 index 00000000..55a46431 --- /dev/null +++ b/docs/reference/request-howto.xml @@ -0,0 +1,184 @@ + + + + +libsoup Client SoupRequest API +3 +LIBSOUP Library + + + +libsoup Client SoupRequest APIUsing +libsoup with a mix of http and non-http URIs. + + + +<type>SoupRequest</type> + + +SoupRequest is an +abstract type representing a request for a particular URI. The +SoupRequest API is an alternative to the SoupMessage-based SoupSession APIs which may be +useful to programs that want to deal with multiple kinds of URIs. + + + +SoupRequest officially became part of the +libsoup API in 2.42 with the addition of +soup_session_request +and the related functions. However, parts of it are also available as +far back as libsoup 2.34 via the +(now-deprecated) SoupRequester session feature, if you +define LIBSOUP_USE_UNSTABLE_REQUEST_API before +including the libsoup headers. + + + +Additionally, before libsoup 2.42, the +SoupRequest API was the only way to stream an HTTP +response body via GInputStream. As of 2.42, +there are streaming APIs based on SoupMessage (soup_session_send +and soup_session_send_async), +so applications that are using SoupRequest with only +http and https URIs can be +ported to those APIs now. + + + + + +Creating a SoupRequest + + +There are four SoupSession methods for creating +SoupRequests: + + + + + + soup_session_request + takes an arbitrary URI as a string, and returns a SoupRequest. + + + + + soup_session_request_uri + takes an arbitrary URI as a SoupURI, + and returns a SoupRequest. + + + + + soup_session_request_http + takes an HTTP method and an http or https URI as a string, and returns a SoupRequestHTTP. + + + + + soup_session_request_http_uri + takes an HTTP method and an http or https URI as a SoupURI, + and returns a SoupRequestHTTP. + + + + + + + +Sending a SoupRequest + + +Once you have created a SoupRequest, you can send it with +either soup_request_send +or soup_request_send_async. +This will provide you with a GInputStream which you can +read to get the response body. + + + +After sending, you can use soup_request_get_content_length +and soup_request_get_content_type +to get information about the response body. + + + +As with the streaming SoupMessage-based APIs, +soup_request_send and +soup_request_send_async only return errors if a +transport-level problem occurs (eg, it could not connect to the host, +or the request was cancelled). In the case of an HTTP request, use the +message's status_code field to determine +whether the request was successful or not at the HTTP level (ie, "200 +OK" vs "401 Bad Request"). (You can call soup_request_http_get_message +to get the request's corresponding SoupMessage, to look at the +status code or other HTTP metadata.) + + + + + +Supported URI types, and adding your own + + +Different URI types are implemented by different subclasses of +SoupRequest. libsoup currently +implements three SoupRequest classes: + + + + + SoupRequestHTTP + + Handles http and + https URI. + + + + SoupRequestData + + Handles data URIs containing inline data. + + + + SoupRequestFile + + Handles file and + resource URIs. + If you request a URI corresponding to a directory, this + will generate an HTML listing of the directory. + + + + + +You can add additional URI types by implementing your own +SoupRequest subclass; set the +SoupRequestClass's schemes +field to point to a NULL-terminated array of scheme +names, implement the various SoupRequest methods, and +then register the type with your SoupSession by calling +soup_session_add_feature_by_type +and passing the GType of +your request class. + + + + + -- cgit v1.2.1 From f0f3d6aeeba584fd795168f93c30de474585da1d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 11 Dec 2013 12:13:52 +0100 Subject: Misc docs updates --- .gitignore | 1 + docs/reference/Makefile.am | 3 ++- docs/reference/client-howto.xml | 2 +- docs/reference/libsoup-2.4-sections.txt | 23 +++++++++++++--------- docs/reference/server-howto.xml | 34 ++++++++++++++++----------------- libsoup/soup-content-sniffer.c | 2 +- libsoup/soup-cookie-jar.c | 2 +- libsoup/soup-cookie.c | 22 +++++++-------------- libsoup/soup-message-headers.c | 2 +- libsoup/soup-message.c | 6 ++---- libsoup/soup-proxy-resolver-default.c | 9 ++++++--- libsoup/soup-proxy-uri-resolver.c | 14 +++++++------- libsoup/soup-session.c | 10 +++++----- libsoup/soup-version.c | 19 ++++++++++++++++++ 14 files changed, 84 insertions(+), 65 deletions(-) diff --git a/.gitignore b/.gitignore index 713357b9..293106cf 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ config.log config.status configure docs/reference/*.stamp +docs/reference/*.bak docs/reference/html docs/reference/libsoup-2.4-decl-list.txt docs/reference/libsoup-2.4-decl.txt diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index a11ce395..d47693a1 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -44,7 +44,8 @@ IGNORE_HFILES= soup.h soup-enum-types.h \ soup-cache-input-stream.h soup-filter-input-stream.h \ soup-cookie-jar-sqlite.h soup-requester.h soup-tld-private.h \ soup-misc-private.h soup-proxy-uri-resolver.h \ - soup-proxy-resolver-wrapper.h + soup-proxy-resolver-wrapper.h soup-proxy-uri-resolver.h \ + soup-cache-private.h # Images to copy into HTML directory. HTML_IMAGES = diff --git a/docs/reference/client-howto.xml b/docs/reference/client-howto.xml index d4d0f37b..e694cb72 100644 --- a/docs/reference/client-howto.xml +++ b/docs/reference/client-howto.xml @@ -122,7 +122,7 @@ you can specify various additional options: Other properties are also available; see the SoupSession documentation for +linkend="SoupSession">SoupSession documentation for more details. diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt index ca423328..03d35d4b 100644 --- a/docs/reference/libsoup-2.4-sections.txt +++ b/docs/reference/libsoup-2.4-sections.txt @@ -51,8 +51,10 @@ SOUP_MESSAGE_SERVER_SIDE SOUP_MESSAGE_FIRST_PARTY SOUP_MESSAGE_PRIORITY SOUP_MESSAGE_REQUEST_BODY +SOUP_MESSAGE_REQUEST_BODY_DATA SOUP_MESSAGE_REQUEST_HEADERS SOUP_MESSAGE_RESPONSE_BODY +SOUP_MESSAGE_RESPONSE_BODY_DATA SOUP_MESSAGE_RESPONSE_HEADERS SOUP_MESSAGE_TLS_CERTIFICATE SOUP_MESSAGE_TLS_ERRORS @@ -248,6 +250,8 @@ SOUP_SERVER_TLS_CERTIFICATE SOUP_SERVER_ASYNC_CONTEXT SOUP_SERVER_RAW_PATHS SOUP_SERVER_SERVER_HEADER +SOUP_SERVER_HTTP_ALIASES +SOUP_SERVER_HTTPS_ALIASES SOUP_SERVER SOUP_IS_SERVER @@ -439,11 +443,12 @@ SOUP_SESSION_PROXY_URI SOUP_SESSION_PROXY_RESOLVER SOUP_SESSION_MAX_CONNS SOUP_SESSION_MAX_CONNS_PER_HOST -SOUP_SESSION_USE_NTLM -SOUP_SESSION_SSL_CA_FILE -SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE SOUP_SESSION_TLS_DATABASE +SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE +SOUP_SESSION_SSL_CA_FILE +SOUP_SESSION_SSL_STRICT SOUP_SESSION_ASYNC_CONTEXT +SOUP_SESSION_USE_THREAD_CONTEXT SOUP_SESSION_TIMEOUT SOUP_SESSION_IDLE_TIMEOUT SOUP_SESSION_USER_AGENT @@ -452,10 +457,9 @@ SOUP_SESSION_ADD_FEATURE_BY_TYPE SOUP_SESSION_REMOVE_FEATURE_BY_TYPE SOUP_SESSION_ACCEPT_LANGUAGE SOUP_SESSION_ACCEPT_LANGUAGE_AUTO -SOUP_SESSION_SSL_STRICT SOUP_SESSION_HTTP_ALIASES SOUP_SESSION_HTTPS_ALIASES -SOUP_SESSION_USE_THREAD_CONTEXT +SOUP_SESSION_LOCAL_ADDRESS SOUP_IS_SESSION SOUP_IS_SESSION_CLASS @@ -471,6 +475,7 @@ SoupConnection SoupConnectionState SoupMessageQueue SoupMessageQueueItem +SOUP_SESSION_USE_NTLM
@@ -1061,11 +1066,7 @@ SOUP_CACHE_GET_CLASS SoupCacheClass SoupCachePrivate -soup_cache_generate_conditional_request -soup_cache_get_cacheability soup_cache_get_type -soup_cache_has_response -soup_cache_send_response SoupCacheResponse SoupCacheability
@@ -1217,6 +1218,7 @@ SOUP_VERSION_2_38 SOUP_VERSION_2_40 SOUP_VERSION_2_42 SOUP_VERSION_2_44 +SOUP_VERSION_2_46 SOUP_AVAILABLE_IN_2_24 SOUP_AVAILABLE_IN_2_26 @@ -1229,6 +1231,7 @@ SOUP_AVAILABLE_IN_2_38 SOUP_AVAILABLE_IN_2_40 SOUP_AVAILABLE_IN_2_42 SOUP_AVAILABLE_IN_2_44 +SOUP_AVAILABLE_IN_2_46 SOUP_DEPRECATED_IN_2_24 SOUP_DEPRECATED_IN_2_24_FOR SOUP_DEPRECATED_IN_2_26 @@ -1251,6 +1254,8 @@ SOUP_DEPRECATED_IN_2_42 SOUP_DEPRECATED_IN_2_42_FOR SOUP_DEPRECATED_IN_2_44 SOUP_DEPRECATED_IN_2_44_FOR +SOUP_DEPRECATED_IN_2_46 +SOUP_DEPRECATED_IN_2_46_FOR SOUP_ENCODE_VERSION SOUP_VERSION_CUR_STABLE SOUP_VERSION_PREV_STABLE diff --git a/docs/reference/server-howto.xml b/docs/reference/server-howto.xml index 76c19182..05fb0c05 100644 --- a/docs/reference/server-howto.xml +++ b/docs/reference/server-howto.xml @@ -100,7 +100,7 @@ to set a callback to handle certain URI paths. soup_server_add_handler (server, "/foo", server_callback, - data, destroy_notify); + data, destroy_notify); @@ -131,11 +131,11 @@ A handler callback looks something like this: static void server_callback (SoupServer *server, - SoupMessage *msg, - const char *path, - GHashTable *query, - SoupClientContext *client, - gpointer user_data) + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) { ... } @@ -192,11 +192,11 @@ data available at once. static void server_callback (SoupServer *server, - SoupMessage *msg, - const char *path, - GHashTable *query, - SoupClientContext *client, - gpointer user_data) + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *client, + gpointer user_data) { MyServerData *server_data = user_data; const char *mime_type; @@ -219,7 +219,7 @@ server_callback (SoupServer *server, soup_message_set_status (msg, SOUP_STATUS_OK); soup_message_set_response (msg, mime_type, SOUP_MEMORY_COPY, - body->data, body->len); + body->data, body->len); } @@ -264,7 +264,7 @@ is emitted indicating that the previous one was written successfully.) The simple-proxy -example in the tests/ directory gives an example of +example in the examples/ directory gives an example of using chunked encoding. @@ -308,8 +308,8 @@ passed to the server_callback: static gboolean auth_callback (SoupAuthDomain *domain, SoupMessage *msg, - const char *username, const char *password, - gpointer user_data) + const char *username, const char *password, + gpointer user_data) { MyServerData *server_data = user_data; MyUserData *user; @@ -360,8 +360,8 @@ domains. If you want to require authentication for some requests under a certain path, but not all of them (eg, you want to authenticate -PUTs, but not GETs), use a -PUT requests, but not GET +requests), use a SoupAuthDomainFilter. diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index e8f69d47..fb2aa090 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -19,7 +19,7 @@ /** * SECTION:soup-content-sniffer - * @short_description: Content sniffing for #SoupSession + * @short_description: Content sniffing for SoupSession * * A #SoupContentSniffer tries to detect the actual content type of * the files that are being downloaded by looking at some of the data diff --git a/libsoup/soup-cookie-jar.c b/libsoup/soup-cookie-jar.c index 93fd157b..83229705 100644 --- a/libsoup/soup-cookie-jar.c +++ b/libsoup/soup-cookie-jar.c @@ -16,7 +16,7 @@ /** * SECTION:soup-cookie-jar - * @short_description: Automatic cookie handling for #SoupSession + * @short_description: Automatic cookie handling for SoupSession * * A #SoupCookieJar stores #SoupCookies and arrange for them * to be sent with the appropriate #SoupMessages. diff --git a/libsoup/soup-cookie.c b/libsoup/soup-cookie.c index 3f7dcc38..de5efa13 100755 --- a/libsoup/soup-cookie.c +++ b/libsoup/soup-cookie.c @@ -18,17 +18,10 @@ /** * SECTION:soup-cookie * @short_description: HTTP Cookies - * @see_also: #SoupMessage - * - * #SoupCookie implements HTTP cookies, primarily as described by - * the - * original Netscape cookie specification, but with slight - * modifications based on RFC 2109, Microsoft's - * HttpOnly extension attribute, and observed real-world usage - * (and, in particular, based on what Firefox does). + * @see_also: #SoupMessage, #SoupCookieJar + * + * #SoupCookie implements HTTP cookies, as described by RFC 6265. * * To have a #SoupSession handle cookies for your appliction * automatically, use a #SoupCookieJar. @@ -58,10 +51,9 @@ * is a hostname and must match exactly. * * @expires will be non-%NULL if the cookie uses either the original - * "expires" attribute, or the "max-age" attribute specified in RFC - * 2109. If @expires is %NULL, it indicates that neither "expires" nor - * "max-age" was specified, and the cookie expires at the end of the - * session. + * "expires" attribute, or the newer "max-age" attribute. If @expires + * is %NULL, it indicates that neither "expires" nor "max-age" was + * specified, and the cookie expires at the end of the session. * * If @http_only is set, the cookie should not be exposed to untrusted * code (eg, javascript), so as to minimize the danger posed by diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c index 28ecaeda..9c704b49 100644 --- a/libsoup/soup-message-headers.c +++ b/libsoup/soup-message-headers.c @@ -1159,7 +1159,7 @@ soup_message_headers_get_content_range (SoupMessageHeaders *hdrs, * * #SoupServer has built-in handling for range requests, and you do * not normally need to call this function youself. See - * soup_message_headers_get_range() for more details. + * soup_message_headers_get_ranges() for more details. * * * Since: 2.26 diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 07967fc2..23fd8b08 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -1780,10 +1780,8 @@ soup_message_set_chunk_allocator (SoupMessage *msg, * This disables the actions of #SoupSessionFeatures with the * given @feature_type (or a subclass of that type) on @msg, so that * @msg is processed as though the feature(s) hadn't been added to the - * session. Eg, passing #SOUP_TYPE_PROXY_URI_RESOLVER for @feature_type - * will disable proxy handling and cause @msg to be sent directly to - * the indicated origin server, regardless of system proxy - * configuration. + * session. Eg, passing #SOUP_TYPE_CONTENT_SNIFFER for @feature_type + * will disable Content-Type sniffing on the message. * * You must call this before queueing @msg on a session; calling it on * a message that has already been queued is undefined. In particular, diff --git a/libsoup/soup-proxy-resolver-default.c b/libsoup/soup-proxy-resolver-default.c index 9149feef..7fd09349 100644 --- a/libsoup/soup-proxy-resolver-default.c +++ b/libsoup/soup-proxy-resolver-default.c @@ -19,16 +19,19 @@ * SECTION:soup-proxy-resolver-default * @short_description: System proxy configuration integration * - * #SoupProxyResolverDefault is a #SoupProxyURIResolver implementation - * that uses the default gio GProxyResolver to resolve proxies. + * #SoupProxyResolverDefault is a SoupProxyURIResolver + * implementation that uses the default gio #GProxyResolver to resolve + * proxies. * - * Deprecated: In libsoup 2.44 and later, you can set the + * In libsoup 2.44 and later, you can set the session's * #SoupSession:proxy-resolver property to the resolver returned by * g_proxy_resolver_get_default() to get the same effect. Note that * for "plain" #SoupSessions (ie, not #SoupSessionAsync or * #SoupSessionSync), this is done for you automatically. * * Since: 2.34 + * + * Deprecated: Use #SoupSession:proxy-resolver */ static void soup_proxy_resolver_default_interface_init (SoupProxyURIResolverInterface *proxy_resolver_interface); diff --git a/libsoup/soup-proxy-uri-resolver.c b/libsoup/soup-proxy-uri-resolver.c index f075a0f7..7971fcb7 100644 --- a/libsoup/soup-proxy-uri-resolver.c +++ b/libsoup/soup-proxy-uri-resolver.c @@ -15,7 +15,7 @@ #include "soup-proxy-uri-resolver.h" #include "soup.h" -/** +/* * SECTION:soup-proxy-uri-resolver * @short_description: Interface for locating HTTP proxies * @@ -40,7 +40,7 @@ soup_proxy_uri_resolver_default_init (SoupProxyURIResolverInterface *iface) { } -/** +/* * SoupProxyURIResolverCallback: * @resolver: the #SoupProxyURIResolver * @status: a #SoupStatus @@ -48,9 +48,9 @@ soup_proxy_uri_resolver_default_init (SoupProxyURIResolverInterface *iface) * @user_data: data passed to soup_proxy_uri_resolver_get_proxy_uri_async() * * Callback for soup_proxy_uri_resolver_get_proxy_uri_async() - **/ + */ -/** +/* * soup_proxy_uri_resolver_get_proxy_uri_async: * @proxy_uri_resolver: the #SoupProxyURIResolver * @uri: the #SoupURI you want a proxy for @@ -66,7 +66,7 @@ soup_proxy_uri_resolver_default_init (SoupProxyURIResolverInterface *iface) * * Deprecated: #SoupProxyURIResolver is deprecated in favor of * #GProxyResolver - **/ + */ void soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_resolver, SoupURI *uri, @@ -81,7 +81,7 @@ soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_re callback, user_data); } -/** +/* * soup_proxy_uri_resolver_get_proxy_uri_sync: * @proxy_uri_resolver: the #SoupProxyURIResolver * @uri: the #SoupURI you want a proxy for @@ -99,7 +99,7 @@ soup_proxy_uri_resolver_get_proxy_uri_async (SoupProxyURIResolver *proxy_uri_re * * Deprecated: #SoupProxyURIResolver is deprecated in favor of * #GProxyResolver - **/ + */ guint soup_proxy_uri_resolver_get_proxy_uri_sync (SoupProxyURIResolver *proxy_uri_resolver, SoupURI *uri, diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index f2e643f3..b3081f14 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -3099,9 +3099,9 @@ soup_session_class_init (SoupSessionClass *session_class) * A proxy to use for all http and https requests in this * session. Setting this will clear the * #SoupSession:proxy-resolver property, and remove any - * #SoupProxyURIResolver features that have been added to the - * session. Setting this property will also cancel all - * currently pending messages. + * SoupProxyURIResolver features that have been + * added to the session. Setting this property will also + * cancel all currently pending messages. * * Note that #SoupSession will normally handle looking up the * user's proxy settings for you; you should only use @@ -3131,8 +3131,8 @@ soup_session_class_init (SoupSessionClass *session_class) * * A #GProxyResolver to use with this session. Setting this * will clear the #SoupSession:proxy-uri property, and remove - * any #SoupProxyURIResolver features that have been added to - * the session. + * any SoupProxyURIResolver features that have + * been added to the session. * * By default, in a plain #SoupSession, this is set to the * default #GProxyResolver, but you can set it to %NULL if you diff --git a/libsoup/soup-version.c b/libsoup/soup-version.c index 8a0fa929..31e7262d 100644 --- a/libsoup/soup-version.c +++ b/libsoup/soup-version.c @@ -286,3 +286,22 @@ soup_check_version (guint major, * Since: 2.42 */ +/** + * SOUP_VERSION_2_44: + * + * A macro that evaluates to the 2.44 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.44 + */ + +/** + * SOUP_VERSION_2_46: + * + * A macro that evaluates to the 2.46 version of libsoup, in a format + * that can be used by %SOUP_VERSION_MIN_REQUIRED and + * %SOUP_VERSION_MAX_ALLOWED. + * + * Since: 2.46 + */ -- cgit v1.2.1 From 28bec1b4fc48dca58f347ec51916269a90218f65 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 11 Dec 2013 20:30:31 +0100 Subject: Update the public suffix list (and its test) --- data/effective_tld_names.dat | 897 ++++++++++++++++++++++++++++++++++++------- tests/tld-test.c | 25 +- 2 files changed, 770 insertions(+), 152 deletions(-) diff --git a/data/effective_tld_names.dat b/data/effective_tld_names.dat index 1738ab3e..95a555aa 100644 --- a/data/effective_tld_names.dat +++ b/data/effective_tld_names.dat @@ -175,17 +175,16 @@ it.ao // aq : http://en.wikipedia.org/wiki/.aq aq -// ar : http://en.wikipedia.org/wiki/.ar -*.ar -!congresodelalengua3.ar -!educ.ar -!gobiernoelectronico.ar -!mecon.ar -!nacion.ar -!nic.ar -!promocion.ar -!retina.ar -!uba.ar +// ar : https://nic.ar/normativa-vigente.xhtml +ar +com.ar +edu.ar +gob.ar +int.ar +mil.ar +net.ar +org.ar +tur.ar // arpa : http://en.wikipedia.org/wiki/.arpa // Confirmed by registry 2008-06-18 @@ -219,9 +218,9 @@ net.au org.au edu.au gov.au -csiro.au asn.au id.au +csiro.au // Historic 2LDs (closed to new registration, but sites still exist) info.au conf.au @@ -245,9 +244,8 @@ tas.edu.au vic.edu.au wa.edu.au act.gov.au -// Removed at request of Shae.Donelan@services.nsw.gov.au, 2010-03-04 -// nsw.gov.au -nt.gov.au +// nsw.gov.au Bug 547985 - Removed at request of +// nt.gov.au Bug 940478 - Removed at request of Greg Connors qld.gov.au sa.gov.au tas.gov.au @@ -350,7 +348,7 @@ z.bg 6.bg 7.bg 8.bg -9.bg +9.bg // bh : http://en.wikipedia.org/wiki/.bh bh @@ -402,7 +400,7 @@ mil.bo tv.bo // br : http://registro.br/dominio/dpn.html -// Updated by registry 2011-03-01 +// Submitted by registry 2011-03-01 br adm.br adv.br @@ -415,13 +413,13 @@ b.br bio.br blog.br bmd.br -can.br cim.br cng.br cnt.br com.br coop.br ecn.br +eco.br edu.br emp.br eng.br @@ -442,6 +440,7 @@ ind.br inf.br jor.br jus.br +leg.br lel.br mat.br med.br @@ -691,6 +690,14 @@ inf.cu // cv : http://en.wikipedia.org/wiki/.cv cv +// cw : http://www.una.cw/cw_registry/ +// Confirmed by registry 2013-03-26 +cw +com.cw +edu.cw +net.cw +org.cw + // cx : http://en.wikipedia.org/wiki/.cx // list of other 2nd level tlds ? cx @@ -779,7 +786,7 @@ org.ee fie.ee // eg : http://en.wikipedia.org/wiki/.eg -eg +eg com.eg edu.eg eun.eg @@ -878,13 +885,12 @@ pvt.ge // gf : http://en.wikipedia.org/wiki/.gf gf -// gg : http://www.channelisles.net/applic/avextn.shtml +// gg : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 gg co.gg -org.gg net.gg -sch.gg -gov.gg +org.gg // gh : http://en.wikipedia.org/wiki/.gh // see also: http://www.nic.gh/reg_now.php @@ -949,9 +955,15 @@ gov.gr // gs : http://en.wikipedia.org/wiki/.gs gs -// gt : http://www.gt/politicas.html -*.gt -!www.gt +// gt : http://www.gt/politicas_de_registro.html +gt +com.gt +edu.gt +gob.gt +ind.gt +mil.gt +net.gt +org.gt // gu : http://gadao.gov.gu/registration.txt *.gu @@ -989,7 +1001,7 @@ org.hk 网絡.hk 组织.hk 組織.hk -組织.hk +組织.hk // hm : http://en.wikipedia.org/wiki/.hm hm @@ -1065,13 +1077,14 @@ tozsde.hu utazas.hu video.hu -// id : http://en.wikipedia.org/wiki/.id -// see also: https://register.pandi.or.id/ +// id : https://register.pandi.or.id/ id ac.id +biz.id co.id go.id mil.id +my.id net.id or.id sch.id @@ -1084,16 +1097,18 @@ gov.ie // il : http://en.wikipedia.org/wiki/.il *.il -// im : https://www.nic.im/pdfs/imfaqs.pdf +// im : https://www.nic.im/ +// Submitted by registry 2013-11-15 im +ac.im co.im +com.im ltd.co.im -plc.co.im net.im -gov.im org.im -nic.im -ac.im +plc.co.im +tt.im +tv.im // in : http://en.wikipedia.org/wiki/.in // see also: http://www.inregistry.in/policies/ @@ -1165,9 +1180,9 @@ int.is it gov.it edu.it -// list of reserved geo-names : +// list of reserved geo-names : // http://www.nic.it/documenti/regolamenti-e-linee-guida/regolamento-assegnazione-versione-6.0.pdf -// (There is also a list of reserved geo-names corresponding to Italian +// (There is also a list of reserved geo-names corresponding to Italian // municipalities : http://www.nic.it/documenti/appendice-c.pdf , but it is // not included here.) agrigento.it @@ -1446,13 +1461,12 @@ vi.it viterbo.it vt.it -// je : http://www.channelisles.net/applic/avextn.shtml +// je : http://www.channelisles.net/register-domains/ +// Confirmed by registry 2013-11-28 je co.je -org.je net.je -sch.je -gov.je +org.je // jm : http://www.com.jm/register.html *.jm @@ -1473,7 +1487,7 @@ jobs // jp : http://en.wikipedia.org/wiki/.jp // http://jprs.co.jp/en/jpdomain.html -// Updated by registry 2012-05-28 +// Submitted by registry 2012-05-28 jp // jp organizational type names ac.jp @@ -3547,8 +3561,13 @@ gov.mr // ms : http://en.wikipedia.org/wiki/.ms ms -// mt : https://www.nic.org.mt/dotmt/ -*.mt +// mt : https://www.nic.org.mt/go/policy +// Submitted by registry 2013-11-19 +mt +com.mt +edu.mt +net.mt +org.mt // mu : http://en.wikipedia.org/wiki/.mu mu @@ -4165,6 +4184,7 @@ name.my // mz : http://www.gobin.info/domainname/mz-template.doc *.mz +!teledata.mz // na : http://www.na-nic.com.na/ // http://www.info.na/domain/ @@ -4214,13 +4234,16 @@ other.nf store.nf // ng : http://psg.com/dns/ng/ -// Submitted by registry 2008-06-17 -ac.ng +ng com.ng edu.ng -gov.ng +name.ng net.ng org.ng +sch.ng +gov.ng +mil.ng +mobi.ng // ni : http://www.nic.ni/dominios.htm *.ni @@ -4236,7 +4259,7 @@ bv.nl // no : http://www.norid.no/regelverk/index.en.html // The Norwegian registry has declined to notify us of updates. The web pages // referenced below are the official source of the data. There is also an -// announce mailing list: +// announce mailing list: // https://postlister.uninett.no/sympa/info/norid-diskusjon no // Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html @@ -5021,17 +5044,16 @@ nu *.nz // om : http://en.wikipedia.org/wiki/.om -*.om -!mediaphone.om -!nawrastelecom.om -!nawras.om -!omanmobile.om -!omanpost.om -!omantel.om -!rakpetroleum.om -!siemens.om -!songfest.om -!statecouncil.om +om +co.om +com.om +edu.om +gov.om +med.om +museum.om +net.om +org.om +pro.om // org : http://en.wikipedia.org/wiki/.org org @@ -5300,6 +5322,9 @@ org.pn edu.pn net.pn +// post : http://en.wikipedia.org/wiki/.post +post + // pr : http://www.nic.pr/index.asp?f=1 pr com.pr @@ -5358,8 +5383,16 @@ ed.pw go.pw belau.pw -// py : http://www.nic.py/faq_a.html#faq_b -*.py +// py : http://www.nic.py/pautas.html#seccion_9 +// Confirmed by registry 2012-10-03 +py +com.py +coop.py +edu.py +gov.py +mil.py +net.py +org.py // qa : http://domains.qa/en/ qa @@ -5714,8 +5747,13 @@ store.st // su : http://en.wikipedia.org/wiki/.su su -// sv : http://www.svnet.org.sv/svpolicy.html -*.sv +// sv : http://www.svnet.org.sv/niveldos.pdf +sv +com.sv +edu.sv +gob.sv +org.sv +red.sv // sx : http://en.wikipedia.org/wiki/.sx // Confirmed by registry 2012-05-31 @@ -5888,71 +5926,102 @@ club.tw 組織.tw 商業.tw -// tz : http://en.wikipedia.org/wiki/.tz -// Submitted by registry 2008-06-17 -// Updated from http://www.tznic.or.tz/index.php/domains.html 2010-10-25 +// tz : http://www.tznic.or.tz/index.php/domains +// Confirmed by registry 2013-01-22 ac.tz co.tz go.tz +hotel.tz +info.tz +me.tz mil.tz +mobi.tz ne.tz or.tz sc.tz +tv.tz -// ua : http://www.nic.net.ua/ +// ua : https://hostmaster.ua/policy/?ua +// Submitted by registry 2012-04-27 ua +// ua 2LD com.ua edu.ua gov.ua in.ua net.ua org.ua -// ua geo-names +// ua geographic names +// https://hostmaster.ua/2ld/ cherkassy.ua +cherkasy.ua chernigov.ua +chernihiv.ua +chernivtsi.ua chernovtsy.ua ck.ua cn.ua +cr.ua crimea.ua cv.ua dn.ua dnepropetrovsk.ua +dnipropetrovsk.ua +dominic.ua donetsk.ua dp.ua if.ua ivano-frankivsk.ua kh.ua +kharkiv.ua kharkov.ua kherson.ua khmelnitskiy.ua +khmelnytskyi.ua kiev.ua kirovograd.ua km.ua kr.ua +krym.ua ks.ua kv.ua +kyiv.ua lg.ua +lt.ua lugansk.ua lutsk.ua +lv.ua lviv.ua mk.ua +mykolaiv.ua nikolaev.ua od.ua +odesa.ua odessa.ua pl.ua poltava.ua +rivne.ua rovno.ua rv.ua +sb.ua sebastopol.ua +sevastopol.ua +sm.ua sumy.ua te.ua ternopil.ua +uz.ua uzhgorod.ua vinnica.ua +vinnytsia.ua vn.ua +volyn.ua +yalta.ua zaporizhzhe.ua -zp.ua +zaporizhzhia.ua zhitomir.ua +zhytomyr.ua +zp.ua zt.ua // Private registries in .ua @@ -5971,20 +6040,19 @@ com.ug org.ug // uk : http://en.wikipedia.org/wiki/.uk +// Submitted by registry 2012-10-02 +// and tweaked by us pending further consultation. *.uk *.sch.uk !bl.uk !british-library.uk -!icnet.uk !jet.uk !mod.uk +!national-library-scotland.uk !nel.uk -!nhs.uk !nic.uk !nls.uk -!national-library-scotland.uk !parliament.uk -!police.uk // us : http://en.wikipedia.org/wiki/.us us @@ -6068,7 +6136,7 @@ k12.de.us k12.fl.us k12.ga.us k12.gu.us -// k12.hi.us Hawaii has a state-wide DOE login: bug 614565 +// k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login k12.ia.us k12.id.us k12.il.us @@ -6099,7 +6167,7 @@ k12.pa.us k12.pr.us k12.ri.us k12.sc.us -k12.sd.us +// k12.sd.us Bug 934131 - Removed at request of James Booze k12.tn.us k12.tx.us k12.ut.us @@ -6220,19 +6288,25 @@ lib.vt.us lib.va.us lib.wa.us lib.wi.us -lib.wv.us +// lib.wv.us Bug 941670 - Removed at request of Larry W Arnold lib.wy.us -// k12.ma.us contains school districts in Massachusetts. The 4LDs are +// k12.ma.us contains school districts in Massachusetts. The 4LDs are // managed indepedently except for private (PVT), charter (CHTR) and -// parochial (PAROCH) schools. Those are delegated dorectly to the +// parochial (PAROCH) schools. Those are delegated dorectly to the // 5LD operators. pvt.k12.ma.us chtr.k12.ma.us paroch.k12.ma.us -// uy : http://www.antel.com.uy/ -*.uy +// uy : http://www.nic.org.uy/ +uy +com.uy +edu.uy +gub.uy +mil.uy +net.uy +org.uy // uz : http://www.reg.uz/ uz @@ -6254,8 +6328,19 @@ gov.vc mil.vc edu.vc -// ve : http://registro.nic.ve/nicve/registro/index.html -*.ve +// ve : https://registro.nic.ve/ +// Confirmed by registry 2012-10-04 +ve +co.ve +com.ve +e12.ve +edu.ve +gov.ve +info.ve +mil.ve +net.ve +org.ve +web.ve // vg : http://en.wikipedia.org/wiki/.vg vg @@ -6316,10 +6401,10 @@ yt // http://nic.ae/english/arabicdomain/rules.jsp امارات -// xn--54b7fta0cc ("Bangla" Bangla) : BD +// xn--54b7fta0cc ("Bangla" Bangla) : BD বাংলা -// xn--fiqs8s ("China" Chinese-Han-Simplified <.Zhonggou>) : CN +// xn--fiqs8s ("China" Chinese-Han-Simplified <.Zhonggou>) : CN // CNNIC // http://cnnic.cn/html/Dir/2005/10/11/3218.htm 中国 @@ -6329,60 +6414,60 @@ yt // http://cnnic.cn/html/Dir/2005/10/11/3218.htm 中國 -// xn--lgbbat1ad8j ("Algeria / Al Jazair" Arabic) : DZ +// xn--lgbbat1ad8j ("Algeria / Al Jazair" Arabic) : DZ الجزائر // xn--wgbh1c ("Egypt" Arabic .masr) : EG // http://www.dotmasr.eg/ مصر -// xn--node ("ge" Georgian (Mkhedruli)) : GE +// xn--node ("ge" Georgian (Mkhedruli)) : GE გე // xn--j6w193g ("Hong Kong" Chinese-Han) : HK // https://www2.hkirc.hk/register/rules.jsp 香港 -// xn--h2brj9c ("Bharat" Devanagari) : IN +// xn--h2brj9c ("Bharat" Devanagari) : IN // India भारत -// xn--mgbbh1a71e ("Bharat" Arabic) : IN +// xn--mgbbh1a71e ("Bharat" Arabic) : IN // India بھارت -// xn--fpcrj9c3d ("Bharat" Telugu) : IN +// xn--fpcrj9c3d ("Bharat" Telugu) : IN // India భారత్ -// xn--gecrj9c ("Bharat" Gujarati) : IN +// xn--gecrj9c ("Bharat" Gujarati) : IN // India ભારત -// xn--s9brj9c ("Bharat" Gurmukhi) : IN +// xn--s9brj9c ("Bharat" Gurmukhi) : IN // India ਭਾਰਤ -// xn--45brj9c ("Bharat" Bengali) : IN +// xn--45brj9c ("Bharat" Bengali) : IN // India ভারত -// xn--xkc2dl3a5ee0h ("India" Tamil) : IN +// xn--xkc2dl3a5ee0h ("India" Tamil) : IN // India இந்தியா -// xn--mgba3a4f16a ("Iran" Persian) : IR +// xn--mgba3a4f16a ("Iran" Persian) : IR ایران -// xn--mgba3a4fra ("Iran" Arabic) : IR +// xn--mgba3a4fra ("Iran" Arabic) : IR ايران // xn--mgbayh7gpa ("al-Ordon" Arabic) : JO -// National Information Technology Center (NITC) +// National Information Technology Center (NITC) // Royal Scientific Society, Al-Jubeiha الاردن -// xn--3e0b707e ("Republic of Korea" Hangul) : KR +// xn--3e0b707e ("Republic of Korea" Hangul) : KR 한국 // xn--fzc2c9e2c ("Lanka" Sinhalese-Sinhala) : LK @@ -6393,10 +6478,10 @@ yt // http://nic.lk இலங்கை -// xn--mgbc0a9azcg ("Morocco / al-Maghrib" Arabic) : MA +// xn--mgbc0a9azcg ("Morocco / al-Maghrib" Arabic) : MA المغرب -// xn--mgb9awbf ("Oman" Arabic) : OM +// xn--mgb9awbf ("Oman" Arabic) : OM عمان // xn--ygbi2ammx ("Falasteen" Arabic) : PS @@ -6404,7 +6489,7 @@ yt // http://www.pnina.ps فلسطين -// xn--90a3ac ("srb" Cyrillic) : RS +// xn--90a3ac ("srb" Cyrillic) : RS срб // xn--p1ai ("rf" Russian-Cyrillic) : RU @@ -6419,19 +6504,19 @@ yt // http://www.nic.net.sa/ السعودية -// xn--mgberp4a5d4a87g ("AlSaudiah" Arabic) variant : SA +// xn--mgberp4a5d4a87g ("AlSaudiah" Arabic) variant : SA السعودیة -// xn--mgbqly7c0a67fbc ("AlSaudiah" Arabic) variant : SA +// xn--mgbqly7c0a67fbc ("AlSaudiah" Arabic) variant : SA السعودیۃ -// xn--mgbqly7cvafr ("AlSaudiah" Arabic) variant : SA +// xn--mgbqly7cvafr ("AlSaudiah" Arabic) variant : SA السعوديه -// xn--ogbpf8fl ("Syria" Arabic) : SY +// xn--ogbpf8fl ("Syria" Arabic) : SY سورية -// xn--mgbtf8fl ("Syria" Arabic) variant : SY +// xn--mgbtf8fl ("Syria" Arabic) variant : SY سوريا // xn--yfro4i67o Singapore ("Singapore" Chinese-Han) : SG @@ -6456,13 +6541,13 @@ yt // http://www.twnic.net/english/dn/dn_07a.htm 台湾 -// xn--nnx388a ("Taiwan") variant : TW +// xn--nnx388a ("Taiwan") variant : TW 臺灣 -// xn--j1amh ("ukr" Cyrillic) : UA +// xn--j1amh ("ukr" Cyrillic) : UA укр -// xn--mgb2ddes ("AlYemen" Arabic) : YE +// xn--mgb2ddes ("AlYemen" Arabic) : YE اليمن // xxx : http://icmregistry.com @@ -6480,30 +6565,464 @@ xxx // zw : http://en.wikipedia.org/wiki/.zw *.zw -// ===END ICANN DOMAINS=== -// ===BEGIN PRIVATE DOMAINS=== -// info.at : http://www.info.at/ -biz.at -info.at +// xn--80asehdb : 2013-07-14 CORE Association +онлайн -// priv.at : http://www.nic.priv.at/ -// Submitted by registry 2008-06-09 -priv.at +// xn--80aswg : 2013-07-14 CORE Association +сайт -// co.ca : http://registry.co.ca -co.ca +// xn--ngbc5azd : 2013-07-14 International Domain Registry Pty. Ltd. +شبكة + +// xn--unup4y : 2013-07-14 Spring Fields, LLC +游戏 + +// xn--vhquv : 2013-08-28 Dash McCook, LLC +企业 + +// camera : 2013-08-28 Atomic Maple, LLC +camera + +// clothing : 2013-08-28 Steel Lake, LLC +clothing + +// lighting : 2013-08-28 John McCook, LLC +lighting + +// singles : 2013-08-28 Fern Madison, LLC +singles + +// ventures : 2013-08-28 Binky Lake, LLC +ventures + +// voyage : 2013-08-28 Ruby House, LLC +voyage + +// guru : 2013-08-28 Pioneer Cypress, LLC +guru + +// holdings : 2013-08-28 John Madison, LLC +holdings + +// equipment : 2013-08-28 Corn Station, LLC +equipment + +// bike : 2013-08-28 Grand Hollow, LLC +bike + +// estate : 2013-08-28 Trixy Park, LLC +estate + +// tattoo : 2013-08-30 Uniregistry,Corp. +tattoo + +// xn--3ds443g : 2013-09-09 TLD Registry Limited +在线 + +// xn--fiq228c5hs : 2013-09-09 TLD Registry Limited +中文网 + +// land : 2013-09-10 Pine Moon, LLC +land + +// plumbing : 2013-09-10 Spring Tigers, LLC +plumbing + +// contractors : 2013-09-10 Magic Woods, LLC +contractors + +// sexy : 2013-09-11 Uniregistry,Corp. +sexy + +// menu : 2013-09-11 Wedding TLD2, LLC +menu + +// xn--rhqv96g : 2013-09-11 Stable Tone Limited +世界 + +// uno : 2013-09-11 Dot Latin, LLC +uno + +// gallery : 2013-09-13 Sugar House, LLC +gallery + +// technology : 2013-09-13 Auburn Falls +technology + +// xn--3bst00m : 2013-09-13 Eagle Horizon Limited +集团 + +// reviews : 2013-09-13 Extra Cover, LLC +reviews + +// guide : 2013-09-13 Snow Moon, LLC +guide + +// xn--6qq986b3x1 : 2013-09-13 Tycoon Treasure Limited +我爱你 + +// graphics : 2013-09-13 Over Madison, LLC +graphics + +// construction : 2013-09-13 Fox Dynamite, LLC +construction + +// onl : 2013-09-16 I-Registry Ltd. +onl + +// xn--q9jyb4c : 2013-09-17 Charleston Road Registry +みんな + +// diamonds : 2013-09-23 John Edge, LLC +diamonds + +// kiwi : 2013-09-23 Dot Kiwi Limited +kiwi + +// enterprises : 2013-09-23 Snow Oaks LLC +enterprises + +// today : 2013-09-23 Pearl Woods, LLC +today + +// futbol : 2013-09-23 Atomic Falls, LLC +futbol + +// photography : 2013-09-23 Sugar Glen, LLC +photography + +// tips : 2013-09-23 Corn Willow, LLC +tips + +// directory : 2013-09-23 Extra Madison, LLC +directory + +// kitchen : 2013-09-23 Just Goodbye, LLC +kitchen + +// xn--6frz82g : 2013-09-24 Afilias Limited +移动 + +// kim : 2013-09-24 Afilias Limited +kim + +// xn--cg4bki : 2013-09-27 Samsung SDS Co., LTD +삼성 + +// monash : 2013-10-01 Monash University +monash + +// wed : 2013-10-02 Atgron, Inc. +wed + +// pink : 2013-10-02 Afilias Limited +pink + +// ruhr : 2013-10-02 regiodot GmbH & Co. KG +ruhr + +// buzz : 2013-10-03 DOTSTRATEGY CO. +buzz + +// careers : 2013-10-03 Wild Corner, LLC +careers + +// shoes : 2013-10-03 Binky Galley, LLC +shoes + +// xn--4gbrim : 2013-10-07 Suhub Electronic Establishment +موقع + +// career : 2013-10-09 dotCareer, LLC +career + +// otsuka : 2013-10-11 Otsuka Holdings Co. Ltd. +otsuka + +// xn--fiQ64b : 2013-10-14 CITIC Group Corporation +中信 + +// wed : 2013-10-02 Atgron, Inc. +wed + +// pink : 2013-10-02 Afilias Limited +pink + +// ruhr : 2013-10-02 regiodot GmbH & Co. KG +ruhr + +// buzz : 2013-10-03 DOTSTRATEGY CO. +buzz + +// careers : 2013-10-03 Wild Corner, LLC +careers + +// shoes : 2013-10-03 Binky Galley, LLC +shoes + +// xn--4gbrim : 2013-10-07 Suhub Electronic Establishment +موقع + +// career : 2013-10-09 dotCareer, LLC +career + +// otsuka : 2013-10-11 Otsuka Holdings Co. Ltd. +otsuka + +// xn--fiQ64b : 2013-10-14 CITIC Group Corporation +中信 + +// gift : 2013-10-18 Uniregistry Corp. +gift + +// recipes : 2013-10-18 Grand Island, LLC +recipes + +// coffee : 2013-10-18 Trixy Cover, LLC +coffee + +// luxury : 2013-10-18 Luxury Partners, LLC +luxury + +// domains : 2013-10-18 Sugar Cross, LLC +domains + +// photos : 2013-10-18 Sea Corner, LLC +photos + +// limo : 2013-10-18 Hidden Frostbite, LLC +limo + +// viajes : 2013-10-18 Black Madison, LLC +viajes + +// wang : 2013-10-24 Zodiac Leo Limited +wang + +// democrat : 2013-10-24 United TLD Holdco Ltd. +democrat + +// mango : 2013-10-25 PUNTO FA S.L. +mango + +// cab : 2013-10-25 Half Sunset, LLC +cab + +// support : 2013-10-25 Grand Orchard, LLC +support + +// dance : 2013-10-25 United TLD Holdco Ltd. +dance + +// nagoya : 2013-10-25 GMO Registry, Inc. +nagoya + +// computer : 2013-10-25 Pine Mill, LLC +computer + +// wien : 2013-10-28 punkt.wien GmbH +wien + +// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG +berlin + +// codes : 2013-10-31 Puff Willow, LLC +codes + +// email : 2013-10-31 Spring Madison, LLC +email + +// xn--mgbab2bd : 2013-10-31 CORE Association +بازار + +// repair : 2013-11-07 Lone Sunset, LLC +repair + +// holiday : 2013-11-07 Goose Woods, LLC +holiday + +// center : 2013-11-07 Tin Mill, LLC +center + +// systems : 2013-11-07 Dash Cypress, LLC +systems + +// wiki : 2013-11-07 Top Level Design, LLC +wiki + +// ceo : 2013-11-07 CEOTLD Pty Ltd +ceo + +// international : 2013-11-07 Wild Way, LLC +international + +// solar : 2013-11-07 Ruby Town, LLC +solar + +// company : 2013-11-07 Silver Avenue, LLC +company + +// education : 2013-11-07 Brice Way, LLC +education + +// training : 2013-11-07 Wild Willow, LLC +training + +// academy : 2013-11-07 Half Oaks, LLC +academy + +// marketing : 2013-11-07 Fern Pass, LLC +marketing + +// florist : 2013-11-08 Half Cypress, LLC +florist + +// solutions : 2013-11-07 Silver Cover, LLC +solutions + +// build : 2013-11-07 Plan Bee LLC +build + +// institute : 2013-11-07 Outer Maple, LLC +institute + +// builders : 2013-11-07 Atomic Madison, LLC +builders + +// red : 2013-11-07 Afilias Limited +red + +// blue : 2013-11-07 Afilias Limited +blue + +// ninja : 2013-11-07 United TLD Holdco Ltd. +ninja + +// business : 2013-11-07 Spring Cross, LLC +business + +// gal : 2013-11-07 Asociación puntoGAL +gal + +// social : 2013-11-07 United TLD Holdco Ltd. +social + +// house : 2013-11-07 Sugar Park, LLC +house + +// camp : 2013-11-07 Delta Dynamite, LLC +camp + +// immobilien : 2013-11-07 United TLD Holdco Ltd. +immobilien + +// moda : 2013-11-07 United TLD Holdco Ltd. +moda + +// glass : 2013-11-07 Black Cover, LLC +glass + +// management : 2013-11-07 John Goodbye, LLC +management + +// kaufen : 2013-11-07 United TLD Holdco Ltd. +kaufen + +// farm : 2013-11-07 Just Maple, LLC +farm + +// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center +公益 + +// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center +政务 + +// club : 2013-11-08 .CLUB DOMAINS, LLC +club + +// voting : 2013-11-13 Valuetainment Corp. +voting + +// TOKYO : 2013-11-13 GMO Registry, Inc. +TOKYO + +// moe : 2013-11-13 Interlink Co., Ltd. +moe + + +// ===END ICANN DOMAINS=== +// ===BEGIN PRIVATE DOMAINS=== + +// Amazon CloudFront : https://aws.amazon.com/cloudfront/ +// Submitted by Donavan Miller 2013-03-22 +cloudfront.net + +// Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/ +// Submitted by Osman Surkatty 2013-04-02 +compute.amazonaws.com +us-east-1.amazonaws.com +compute-1.amazonaws.com +z-1.compute-1.amazonaws.com +z-2.compute-1.amazonaws.com +ap-northeast-1.compute.amazonaws.com +ap-southeast-1.compute.amazonaws.com +ap-southeast-2.compute.amazonaws.com +eu-west-1.compute.amazonaws.com +sa-east-1.compute.amazonaws.com +us-gov-west-1.compute.amazonaws.com +us-west-1.compute.amazonaws.com +us-west-2.compute.amazonaws.com + +// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ +// Submitted by Adam Stein 2013-04-02 +elasticbeanstalk.com + +// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/ +// Submitted by Scott Vidmar 2013-03-27 +elb.amazonaws.com + +// Amazon S3 : https://aws.amazon.com/s3/ +// Submitted by Courtney Eckhardt 2013-03-22 +s3.amazonaws.com +s3-us-west-2.amazonaws.com +s3-us-west-1.amazonaws.com +s3-eu-west-1.amazonaws.com +s3-ap-southeast-1.amazonaws.com +s3-ap-southeast-2.amazonaws.com +s3-ap-northeast-1.amazonaws.com +s3-sa-east-1.amazonaws.com +s3-us-gov-west-1.amazonaws.com +s3-fips-us-gov-west-1.amazonaws.com +s3-website-us-east-1.amazonaws.com +s3-website-us-west-2.amazonaws.com +s3-website-us-west-1.amazonaws.com +s3-website-eu-west-1.amazonaws.com +s3-website-ap-southeast-1.amazonaws.com +s3-website-ap-southeast-2.amazonaws.com +s3-website-ap-northeast-1.amazonaws.com +s3-website-sa-east-1.amazonaws.com +s3-website-us-gov-west-1.amazonaws.com + +// BetaInABox +// Submitted by adrian@betainabox.com 2012-09-13 +betainabox.com // CentralNic : http://www.centralnic.com/names/domains -// Confirmed by registry 2008-06-09 +// Submitted by registry 2012-09-27 +ae.org ar.com br.com cn.com +com.de de.com eu.com gb.com +gb.net gr.com hu.com +hu.net +jp.net jpn.com kr.com no.com @@ -6511,44 +7030,36 @@ qc.com ru.com sa.com se.com +se.net uk.com +uk.net us.com +us.org uy.com za.com -gb.net -jp.net -se.net -uk.net -ae.org -us.org -com.de - -// Opera Software, A.S.A. -// Requested by Yngve Pettersen 2009-11-26 -operaunite.com - -// Google, Inc. -// Requested by Eduardo Vela 2010-09-06 -appspot.com - -// iki.fi : Submitted by Hannu Aronsson 2009-11-05 -iki.fi // c.la : http://www.c.la/ c.la -// ZaNiC : http://www.za.net/ -// Confirmed by registry 2009-10-03 -za.net -za.org +// cloudControl : https://www.cloudcontrol.com/ +// Submitted by Tobias Wilken 2013-07-23 +cloudcontrolled.com +cloudcontrolapp.com + +// co.ca : http://registry.co.ca/ +co.ca // CoDNS B.V. -// Added 2010-05-23. co.nl co.no -// Mainseek Sp. z o.o. : http://www.co.pl/ -co.pl +// Cupcake : https://cupcake.io/ +// Submitted by Jonathan Rudenberg 2013-10-08 +cupcake.is + +// DreamHost : http://www.dreamhost.com/ +// Submitted by Andrew Farmer 2012-10-02 +dreamhosters.com // DynDNS.com : http://www.dyndns.com/services/dns/dyndns/ dyndns-at-home.com @@ -6831,4 +7342,104 @@ webhop.org worse-than.tv writesthisblog.com +// Fastly Inc. http://www.fastly.com/ +// Submitted by Vladimir Vuksan 2013-05-31 +a.ssl.fastly.net +b.ssl.fastly.net +global.ssl.fastly.net +a.prod.fastly.net +global.prod.fastly.net + +// GitHub, Inc. +// Submitted by Ben Toews 2013-04-18 +github.io + +// GlobeHosting, Inc. +// Submitted by Zoltan Egresi 2013-07-12 +ro.com + +// Google, Inc. +// Submitted by Eduardo Vela 2012-10-24 +appspot.com +blogspot.be +blogspot.bj +blogspot.ca +blogspot.cf +blogspot.ch +blogspot.co.at +blogspot.co.il +blogspot.co.nz +blogspot.co.uk +blogspot.com +blogspot.com.ar +blogspot.com.au +blogspot.com.br +blogspot.com.es +blogspot.cv +blogspot.cz +blogspot.de +blogspot.dk +blogspot.fi +blogspot.fr +blogspot.gr +blogspot.hk +blogspot.hu +blogspot.ie +blogspot.in +blogspot.it +blogspot.jp +blogspot.kr +blogspot.mr +blogspot.mx +blogspot.nl +blogspot.no +blogspot.pt +blogspot.re +blogspot.ro +blogspot.se +blogspot.sg +blogspot.sk +blogspot.td +blogspot.tw +codespot.com +googleapis.com +googlecode.com + +// Heroku : https://www.heroku.com/ +// Submitted by Tom Maher 2013-05-02 +herokuapp.com +herokussl.com + +// iki.fi +// Submitted by Hannu Aronsson 2009-11-05 +iki.fi + +// info.at : http://www.info.at/ +biz.at +info.at + +// Michau Enterprises Limited : http://www.co.pl/ +co.pl + +// NYC.mn : http://www.information.nyc.mn +// Submitted by Matthew Brown 2013-03-11 +nyc.mn + +// Opera Software, A.S.A. +// Submitted by Yngve Pettersen 2009-11-26 +operaunite.com + +// Red Hat, Inc. OpenShift : https://openshift.redhat.com/ +// Submitted by Tim Kramer 2012-10-24 +rhcloud.com + +// priv.at : http://www.nic.priv.at/ +// Submitted by registry 2008-06-09 +priv.at + +// ZaNiC : http://www.za.net/ +// Submitted by registry 2009-10-03 +za.net +za.org + // ===END PRIVATE DOMAINS=== diff --git a/tests/tld-test.c b/tests/tld-test.c index d0c73a8e..2b6b5dd9 100644 --- a/tests/tld-test.c +++ b/tests/tld-test.c @@ -57,12 +57,12 @@ static struct { { "city.kyoto.jp", "city.kyoto.jp" }, { "www.city.kyoto.jp", "city.kyoto.jp" }, /* TLD with a wildcard rule and exceptions. */ - { "om", NULL }, - { "test.om", NULL }, - { "b.test.om", "b.test.om" }, - { "a.b.test.om", "b.test.om" }, - { "songfest.om", "songfest.om" }, - { "www.songfest.om", "songfest.om" }, + { "ck", NULL }, + { "test.ck", NULL }, + { "b.test.ck", "b.test.ck" }, + { "a.b.test.ck", "b.test.ck" }, + { "www.ck", "www.ck" }, + { "www.www.ck", "www.ck" }, /* US K12. */ { "us", NULL }, { "test.us", "test.us" }, @@ -73,11 +73,18 @@ static struct { { "k12.ak.us", NULL }, { "test.k12.ak.us", "test.k12.ak.us" }, { "www.test.k12.ak.us", "test.k12.ak.us" }, + /* IDN labels. */ + { "食狮.com.cn", "食狮.com.cn" }, + { "食狮.公司.cn", "食狮.公司.cn" }, + { "www.食狮.公司.cn", "食狮.公司.cn" }, + { "shishi.公司.cn", "shishi.公司.cn" }, + { "公司.cn", NULL }, + { "食狮.中国", "食狮.中国" }, + { "www.食狮.中国", "食狮.中国" }, + { "shishi.中国", "shishi.中国" }, + { "中国", NULL }, /* This is not in http://publicsuffix.org/list/test.txt but we want to check it anyway. */ { "co.uk", NULL }, - /* The original list does not include non-ASCII tests. Let's add a couple. */ - { "公司.cn", NULL }, - { "a.b.åfjord.no", "b.åfjord.no" } }, /* Non Internet TLDs have NULL as expected result */ -- cgit v1.2.1 From 501bd45cee95b35d097471db2896a36747048b9a Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 16 Dec 2013 16:42:02 -0500 Subject: 2.45.3 --- NEWS | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index aa7606e7..dab58d61 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,60 @@ +Changes in libsoup from 2.44.1 to 2.45.3: + + * The documentation has finally been updated to reflect the + new APIs added in 2.42. + + * Added GBytes-valued :request-body-data and + :response-body-data properties to SoupMessage, which should + help some bindings. + + * We now set TCP_NODELAY on sockets, improving throughput a + bit. In particular, this avoids an unnecessary extra round + trip in the TLS handshake. + + * The SoupSession APIs that return GErrors now return the + actual underlying gio errors in the event of connection + failures and the like. + + * Updated the copy of the Public Suffix list used by soup-tld. + + * Fixed a hang with internet radio streams in Rhythmbox (and + some other places). [#710494, Dan] + + * Fixed a connection leak when cancelling the close of + a message GInputStream. [#711260, Dan] + + * Updated the soup_server_pause_message() / + soup_server_unpause_message() documentation to clarify when + you can and can't call them. [#710602, Philip Withnall] + + * soup_message_set_request() and soup_message_set_response() + now g_warn_if_fail() if you pass an invalid Content-Type. + (And they also have better introspection annotations.) + [#686766, Dan] + + * Plugged a few memory leaks [#711085, Christophe Fergeau] + + * Fixed connection-test to pass with current glib [#711361, + Colin Walters] + + * session-test now passes when run against the dummy TLS + backend (ie, if you don't have glib-networking installed), + as long as you have the latest glib. + + * Fixed build with -Werror=format-nonliteral [#720082, Ryan + Lortie] + + * Fix build with --without-ntlm [#710267, Dan] + + * Fixed a few warnings [Dan, Fabiano Fidêncio] + + * Tests are now more verbose by default under "make check", + since current automake just redirects all the output to a + log file anyway. + + * Updated translations: + Chinese + Changes in libsoup from 2.44.0 to 2.44.1: * If you called g_input_stream_close() on SoupMessage or diff --git a/configure.ac b/configure.ac index 3759baba..f60744a5 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [45]) -m4_define([soup_micro_version], [0]) +m4_define([soup_micro_version], [3]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 4c2d1ac3daed3940217da2477546db31fbdb1b43 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 18 Dec 2013 17:06:16 -0500 Subject: soup-tld: accept ASCII-encoded hostnames too It's inconvenient for callers to have to ensure that the hostname they pass in is UTF-8 (since they themselves may not need to care). So accept ASCII-encoded hostnames too, and add the corresponding punycode tests from the publicsuffix.org test list that we were ignoring before. --- libsoup/soup-tld.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-------- tests/tld-test.c | 26 ++++++++++++++++++++- 2 files changed, 82 insertions(+), 11 deletions(-) diff --git a/libsoup/soup-tld.c b/libsoup/soup-tld.c index c6faed13..2e3da62d 100644 --- a/libsoup/soup-tld.c +++ b/libsoup/soup-tld.c @@ -57,7 +57,7 @@ soup_tld_ensure_rules_hash_table (void) /** * soup_tld_get_base_domain: - * @hostname: a UTF-8 hostname in its canonical representation form + * @hostname: a hostname * @error: return location for a #GError, or %NULL to ignore * errors. See #SoupTLDError for the available error codes * @@ -70,9 +70,10 @@ soup_tld_ensure_rules_hash_table (void) * with any well known TLD) because choosing a base domain for them * would be totally arbitrary. * - * This method only works for valid UTF-8 hostnames in their canonical - * representation form, so you should use g_hostname_to_unicode() to - * get the canonical representation if that is not the case. + * Prior to libsoup 2.46, this function required that @hostname be in + * UTF-8 if it was an IDN. From 2.46 on, the name can be in either + * UTF-8 or ASCII format (and the return value will be in the same + * format). * * Returns: a pointer to the start of the base domain in @hostname. If * an error occurs, %NULL will be returned and @error set. @@ -83,21 +84,21 @@ const char * soup_tld_get_base_domain (const char *hostname, GError **error) { g_return_val_if_fail (hostname, NULL); - g_return_val_if_fail (!g_hostname_is_ascii_encoded (hostname), FALSE); return soup_tld_get_base_domain_internal (hostname, 1, error); } /** * soup_tld_domain_is_public_suffix: - * @domain: a UTF-8 domain in its canonical representation form + * @domain: a domain name * * Looks whether the @domain passed as argument is a public domain * suffix (.org, .com, .co.uk, etc) or not. * - * This method only works for valid UTF-8 domains in their canonical - * representation form, so you should use g_hostname_to_unicode() to - * get the canonical representation if that is not the case. + * Prior to libsoup 2.46, this function required that @domain be in + * UTF-8 if it was an IDN. From 2.46 on, the name can be in either + * UTF-8 or ASCII format (and the return value will be in the same + * format). * * Returns: %TRUE if it is a public domain, %FALSE otherwise. * @@ -174,8 +175,10 @@ soup_tld_error_quark (void) static const char * soup_tld_get_base_domain_internal (const char *hostname, guint additional_domains, GError **error) { - char *prev_domain, *cur_domain, *tld, *next_dot; + char *prev_domain, *cur_domain, *next_dot; gint add_domains; + const char *orig_hostname = NULL, *tld; + char *utf8_hostname = NULL; soup_tld_ensure_rules_hash_table (); @@ -186,6 +189,17 @@ soup_tld_get_base_domain_internal (const char *hostname, guint additional_domain return NULL; } + if (g_hostname_is_ascii_encoded (hostname)) { + orig_hostname = hostname; + hostname = utf8_hostname = g_hostname_to_unicode (hostname); + if (!hostname) { + g_set_error_literal (error, SOUP_TLD_ERROR, + SOUP_TLD_ERROR_INVALID_HOSTNAME, + _("Invalid hostname")); + return NULL; + } + } + cur_domain = (char *) hostname; tld = cur_domain; prev_domain = NULL; @@ -204,6 +218,7 @@ soup_tld_get_base_domain_internal (const char *hostname, guint additional_domain g_set_error_literal (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_INVALID_HOSTNAME, _("Invalid hostname")); + g_free (utf8_hostname); return NULL; } @@ -233,6 +248,7 @@ soup_tld_get_base_domain_internal (const char *hostname, guint additional_domain g_set_error_literal (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_NO_BASE_DOMAIN, _("Hostname has no base domain")); + g_free (utf8_hostname); return NULL; } @@ -240,6 +256,37 @@ soup_tld_get_base_domain_internal (const char *hostname, guint additional_domain cur_domain = next_dot + 1; } + if (orig_hostname) { + int dots; + const char *p; + + /* Count the number of dots that appear after tld in + * utf8_hostname, and then find the corresponding spot + * in orig_hostname; + */ + for (p = tld, dots = 0; *p; p++) { + if (*p == '.') + dots++; + } + + for (p = orig_hostname + strlen (orig_hostname); p > orig_hostname; p--) { + if (*(p - 1) == '.') { + if (dots) + dots--; + else + break; + } + } + /* It's not possible for utf8_hostname to have had + * more dots than orig_hostname. + */ + g_assert (dots == 0); + + tld = p; + g_free (utf8_hostname); + hostname = orig_hostname; + } + /* Include the additional number of domains requested. */ add_domains = additional_domains; while (tld != hostname) { diff --git a/tests/tld-test.c b/tests/tld-test.c index 2b6b5dd9..d1f1de1f 100644 --- a/tests/tld-test.c +++ b/tests/tld-test.c @@ -83,8 +83,30 @@ static struct { { "www.食狮.中国", "食狮.中国" }, { "shishi.中国", "shishi.中国" }, { "中国", NULL }, - /* This is not in http://publicsuffix.org/list/test.txt but we want to check it anyway. */ + /* Same as above, but punycoded. */ + { "xn--85x722f.com.cn", "xn--85x722f.com.cn" }, + { "xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn" }, + { "www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn" }, + { "shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn" }, + { "xn--55qx5d.cn", NULL }, + { "xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s" }, + { "www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s" }, + { "shishi.xn--fiqs8s", "shishi.xn--fiqs8s" }, + { "xn--fiqs8s", NULL }, + /* End of publicsuffix.org tests */ + + /* Let's just double-check this one... */ { "co.uk", NULL }, + { "test.co.uk", "test.co.uk" }, + { "www.test.co.uk", "test.co.uk" }, + + /* Two levels of non-ASCII */ + { "våler.østfold.no", NULL }, + { "test.våler.østfold.no", "test.våler.østfold.no" }, + { "www.test.våler.østfold.no", "test.våler.østfold.no" }, + { "xn--vler-qoa.xn--stfold-9xa.no", NULL }, + { "test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no" }, + { "www.test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no" }, }, /* Non Internet TLDs have NULL as expected result */ @@ -135,6 +157,8 @@ main (int argc, char **argv) g_clear_error(&error); } + debug_printf (1, "\n"); + for (i = 0; i < G_N_ELEMENTS (non_inet_tld_tests); ++i) { gboolean is_public = soup_tld_domain_is_public_suffix (non_inet_tld_tests[i].hostname); const char *base_domain = soup_tld_get_base_domain (non_inet_tld_tests[i].hostname, NULL); -- cgit v1.2.1 From c6ca559e4e29bf00b6f61387b2e24fe53e463312 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 7 Jan 2014 13:19:09 -0500 Subject: examples: fix simple-proxy startup error checking was busted, making this not even work --- examples/simple-proxy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple-proxy.c b/examples/simple-proxy.c index 6623166c..db8c9f96 100644 --- a/examples/simple-proxy.c +++ b/examples/simple-proxy.c @@ -153,7 +153,7 @@ main (int argc, char **argv) exit (1); } - if (argc != 2) { + if (argc != 1) { g_printerr ("%s", g_option_context_get_help (opts, TRUE, NULL)); exit (1); -- cgit v1.2.1 From 4684b8c77f65db28a39bbd2c88d861d41931498c Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 7 Jan 2014 13:25:42 -0500 Subject: tests: ignore proxy settings Some of the tests depend in various ways on the fact that they are not going through a proxy, so make sure they really aren't (by forcing the use of the dummy GProxyResolver). Likewise, pass "--noproxy *" to curl in the tests that use it, to make sure it doesn't pick up $http_proxy, etc. Pointed out by Dirkjan Ochtman on IRC. --- tests/forms-test.c | 4 ++++ tests/server-auth-test.c | 2 ++ tests/test-utils.c | 1 + 3 files changed, 7 insertions(+) diff --git a/tests/forms-test.c b/tests/forms-test.c index 3b6e5c16..cf8963c3 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -51,6 +51,8 @@ do_hello_test (int n, gboolean extra, const char *uri) args = g_ptr_array_new (); g_ptr_array_add (args, "curl"); + g_ptr_array_add (args, "--noproxy"); + g_ptr_array_add (args, "*"); g_ptr_array_add (args, "-G"); if (tests[n].title) { title_arg = soup_form_encode ("title", tests[n].title, NULL); @@ -114,6 +116,8 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5) args = g_ptr_array_new (); g_ptr_array_add (args, "curl"); + g_ptr_array_add (args, "--noproxy"); + g_ptr_array_add (args, "*"); g_ptr_array_add (args, "-L"); g_ptr_array_add (args, "-F"); file_arg = g_strdup_printf ("file=@%s", file); diff --git a/tests/server-auth-test.c b/tests/server-auth-test.c index 33cff45a..78cd0686 100644 --- a/tests/server-auth-test.c +++ b/tests/server-auth-test.c @@ -48,6 +48,8 @@ do_test (int n, SoupURI *base_uri, const char *path, args = g_ptr_array_new (); g_ptr_array_add (args, "curl"); + g_ptr_array_add (args, "--noproxy"); + g_ptr_array_add (args, "*"); g_ptr_array_add (args, "-f"); g_ptr_array_add (args, "-s"); if (offer_basic || offer_digest) { diff --git a/tests/test-utils.c b/tests/test-utils.c index f4632a9b..36b0ee5d 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -83,6 +83,7 @@ test_init (int argc, char **argv, GOptionEntry *entries) setlocale (LC_ALL, ""); g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); + g_setenv ("GIO_USE_PROXY_RESOLVER", "dummy", TRUE); name = strrchr (argv[0], '/'); if (!name++) -- cgit v1.2.1 From 3c9849e3251534ff1dc0a24e5b9ba9561a2d6404 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 18 Jan 2014 21:47:37 -0500 Subject: soup_uri_to_string: document that passwords are never output --- libsoup/soup-uri.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libsoup/soup-uri.c b/libsoup/soup-uri.c index e3092dcf..42c2f680 100644 --- a/libsoup/soup-uri.c +++ b/libsoup/soup-uri.c @@ -576,6 +576,9 @@ soup_uri_to_string_internal (SoupURI *uri, gboolean just_path_and_query, * together. That is, it constructs the string that would be needed in * the Request-Line of an HTTP request for @uri. * + * Note that the output will never contain a password, even if @uri + * does. + * * Return value: a string representing @uri, which the caller must free. **/ char * -- cgit v1.2.1 From aea9575bf50ff3899ddb4d9763db0313a6377710 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 16 Jan 2014 10:50:10 +0000 Subject: tests: headers-parsing: allow checks with case insensitive headers fields https://bugzilla.gnome.org/show_bug.cgi?id=722341 --- tests/header-parsing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/header-parsing.c b/tests/header-parsing.c index 5b2950fc..52b2279b 100644 --- a/tests/header-parsing.c +++ b/tests/header-parsing.c @@ -727,7 +727,7 @@ check_headers (Header *headers, SoupMessageHeaders *hdrs) } for (i = 0, h = header_names; headers[i].name && h; i++, h = h->next) { - if (strcmp (h->data, headers[i].name) != 0) { + if (g_ascii_strcasecmp (h->data, headers[i].name) != 0) { ok = FALSE; break; } -- cgit v1.2.1 From 1b2a752663896bec558049fc050504517b0d1743 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 16 Jan 2014 10:52:43 +0000 Subject: tests: headers: allow checks on non present headers fields https://bugzilla.gnome.org/show_bug.cgi?id=722341 --- tests/header-parsing.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/header-parsing.c b/tests/header-parsing.c index 52b2279b..b02bc980 100644 --- a/tests/header-parsing.c +++ b/tests/header-parsing.c @@ -455,7 +455,7 @@ static struct ResponseTest { SoupHTTPVersion version; guint status_code; const char *reason_phrase; - Header headers[4]; + Header headers[10]; } resptests[] = { /***********************/ /*** VALID RESPONSES ***/ @@ -521,6 +521,19 @@ static struct ResponseTest { } }, + /* Tests from Cockpit */ + + { "Response w/ 3 headers, check case-insensitivity", + "HTTP/1.0 200 ok\r\nHeader1: value3\r\nHeader2: field\r\nHead3: Another \r\n", -1, + SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok", + { { "header1", "value3" }, + { "Header2", "field" }, + { "hEAD3", "Another" }, + { "Something else", NULL }, + { NULL } + } + }, + /*****************************/ /*** RECOVERABLE RESPONSES ***/ /*****************************/ @@ -732,7 +745,15 @@ check_headers (Header *headers, SoupMessageHeaders *hdrs) break; } value = soup_message_headers_get_list (hdrs, headers[i].name); - if (!value || strcmp (value, headers[i].value) != 0) { + if (g_strcmp0 (value, headers[i].value) != 0) { + ok = FALSE; + break; + } + } + /* If we have remaining fields to check, they should return NULL */ + for (; headers[i].name; i++) { + value = soup_message_headers_get_list (hdrs, headers[i].name); + if (value) { ok = FALSE; break; } -- cgit v1.2.1 From 3e417e71bba7c96a40d0e45e91d88513b060d176 Mon Sep 17 00:00:00 2001 From: Shankar Prasad Date: Wed, 5 Feb 2014 17:04:53 +0530 Subject: updated kn.po --- po/kn.po | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/po/kn.po b/po/kn.po index 2cc9ce59..98bd11e4 100644 --- a/po/kn.po +++ b/po/kn.po @@ -1,26 +1,27 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# +# # Shankar Prasad , 2012, 2013. msgid "" msgstr "" "Project-Id-Version: \n" -"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" -"product=libsoup&keywords=I18N+L10N&component=general\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=" +"libsoup&keywords=I18N+L10N&component=general\n" "POT-Creation-Date: 2013-02-18 10:20+0000\n" -"PO-Revision-Date: 2013-03-24 18:00+0530\n" +"PO-Revision-Date: 2013-03-24 08:30-0400\n" "Last-Translator: Shankar Prasad \n" "Language-Team: Kannada \n" -"Language: kn\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Language: kn\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Lokalize 1.5\n" +"X-Generator: Zanata 3.2.3\n" #: ../libsoup/soup-body-input-stream.c:141 #: ../libsoup/soup-body-input-stream.c:172 -#: ../libsoup/soup-body-input-stream.c:205 ../libsoup/soup-message-io.c:191 +#: ../libsoup/soup-body-input-stream.c:205 +#: ../libsoup/soup-message-io.c:191 msgid "Connection terminated unexpectedly" msgstr "ಸಂಪರ್ಕವು ಅನಿರೀಕ್ಷಿತವಾಗಿ ಕೊನೆಗೊಂಡಿದೆ" @@ -46,7 +47,6 @@ msgid "Output buffer is too small" msgstr "ಔಟ್‌ಪುಟ್ ಬಫರ್ ಬಹಳ ಚಿಕ್ಕದಾಗಿದೆ" #: ../libsoup/soup-message-client-io.c:41 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP response" msgstr "HTTP ಪ್ರತ್ಯುತ್ತರವನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" @@ -54,7 +54,8 @@ msgstr "HTTP ಪ್ರತ್ಯುತ್ತರವನ್ನು ಪಾರ್ಸ್ msgid "Unrecognized HTTP response encoding" msgstr "ಗುರುತಿಸಲಾಗದ HTTP ಪ್ರತಿಕ್ರಿಯೆ ಎನ್ಕೋಡಿಂಗ್" -#: ../libsoup/soup-message-io.c:846 ../libsoup/soup-message-io.c:882 +#: ../libsoup/soup-message-io.c:846 +#: ../libsoup/soup-message-io.c:882 msgid "Operation was cancelled" msgstr "ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ" @@ -63,7 +64,6 @@ msgid "Operation would block" msgstr "ಕಾರ್ಯಾಚರಣೆ ತಡೆಯಲ್ಪಡಬಹುದು" #: ../libsoup/soup-message-server-io.c:40 -#| msgid "Could not parse URI '%s'" msgid "Could not parse HTTP request" msgstr "HTTP ಮನವಿಯನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" @@ -77,17 +77,17 @@ msgstr "ಯಾವುದೆ URI ಅನ್ನು ಒದಗಿಸಲಾಗಿಲ್ msgid "Invalid '%s' URI: %s" msgstr "ಅಮಾನ್ಯವಾದ '%s' URI:'%s" -#: ../libsoup/soup-session.c:4209 +#: ../libsoup/soup-session.c:4252 #, c-format msgid "Could not parse URI '%s'" msgstr "'%s' URL ಅನ್ನು ಪಾರ್ಸ್ ಮಾಡಲಾಗಿಲ್ಲ" -#: ../libsoup/soup-session.c:4246 +#: ../libsoup/soup-session.c:4289 #, c-format msgid "Unsupported URI scheme '%s'" msgstr "ಬೆಂಬಲವಿಲ್ಲದ ಯುಆರ್ಐ ಮಾದರಿ '%s'" -#: ../libsoup/soup-session.c:4268 +#: ../libsoup/soup-session.c:4311 #, c-format msgid "Not an HTTP URI" msgstr "ಒಂದು HTTP URI ಅಲ್ಲ" @@ -107,4 +107,3 @@ msgstr "ಆತಿಥೇಯದ ಹೆಸರಿನಲ್ಲಿ ಯಾವುದೆ #: ../libsoup/soup-tld.c:257 msgid "Not enough domains" msgstr "ಬೇಕಾದಷ್ಟು ಡೊಮೈನ್‌ಗಳಿಲ್ಲ" - -- cgit v1.2.1 From 64e667bda5009c8f1acd03659c457e26b16457a6 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 10 Dec 2013 15:47:34 +0100 Subject: tests: initial port to the gtestutils framework Some programs need to be split up into more tests, and the debug output is mostly not updated for the new format. --- tests/auth-test.c | 288 +++++++++++++---------------------- tests/cache-test.c | 214 ++++++++------------------ tests/chunk-io-test.c | 122 ++++++--------- tests/chunk-test.c | 162 +++++++------------- tests/coding-test.c | 179 +++++++++------------- tests/connection-test.c | 283 ++++++++++++----------------------- tests/context-test.c | 84 ++++------- tests/continue-test.c | 32 ++-- tests/cookies-test.c | 69 +++------ tests/date.c | 194 ++++++++++++------------ tests/forms-test.c | 69 +++------ tests/header-parsing.c | 276 +++++++--------------------------- tests/misc-test.c | 232 ++++++++-------------------- tests/multipart-test.c | 226 +++++++++------------------- tests/no-ssl-test.c | 98 ++++-------- tests/ntlm-test.c | 175 +++++++++++----------- tests/proxy-test.c | 190 ++++++++--------------- tests/pull-api.c | 170 ++++++++++----------- tests/range-test.c | 140 ++++++++--------- tests/redirect-test.c | 267 +++++++++++++++------------------ tests/requester-test.c | 349 ++++++++++++++++--------------------------- tests/resource-test.c | 163 ++++++++------------ tests/server-auth-test.c | 55 +++---- tests/server-test.c | 108 ++++---------- tests/session-test.c | 146 +++++++----------- tests/sniffing-test.c | 324 +++++++++++++++++++--------------------- tests/socket-test.c | 71 +++++---- tests/ssl-test.c | 229 ++++++++++------------------ tests/streaming-test.c | 61 ++++---- tests/test-utils.c | 77 ++++------ tests/test-utils.h | 68 +++++++-- tests/timeout-test.c | 187 +++++++++++------------ tests/tld-test.c | 311 +++++++++++++++++++------------------- tests/uri-parsing.c | 365 ++++++++++++++------------------------------- tests/xmlrpc-server-test.c | 43 ++++-- tests/xmlrpc-test.c | 214 ++++++++++---------------- 36 files changed, 2392 insertions(+), 3849 deletions(-) diff --git a/tests/auth-test.c b/tests/auth-test.c index 992e3d5e..c1825205 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -4,6 +4,7 @@ #ifdef HAVE_APACHE +static const char *base_uri; static GMainLoop *loop; typedef struct { @@ -37,10 +38,6 @@ typedef struct { guint final_status; } SoupAuthTest; -/* Will either point to main_tests or relogin_tests - */ -static SoupAuthTest *current_tests; - static SoupAuthTest main_tests[] = { { "No auth available, should fail", "Basic/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }, @@ -151,7 +148,9 @@ static SoupAuthTest main_tests[] = { "Digest/realm1/", "", FALSE, "0", SOUP_STATUS_UNAUTHORIZED }, { "Fail with URI-embedded password, then use right password in the authenticate signal", - "Basic/realm3/", "43", TRUE, "43", SOUP_STATUS_OK } + "Basic/realm3/", "43", TRUE, "43", SOUP_STATUS_OK }, + + { NULL } }; static const char *auths[] = { @@ -207,14 +206,12 @@ handler (SoupMessage *msg, gpointer data) if (*expected) { exp = *expected - '0'; - if (auth != exp) { - debug_printf (1, " expected %s!\n", auths[exp]); - errors++; - } + soup_test_assert (auth == exp, + "expected %s", auths[exp]); memmove (expected, expected + 1, strlen (expected)); } else { - debug_printf (1, " expected to be finished\n"); - errors++; + soup_test_assert (*expected, + "expected to be finished"); } } @@ -222,18 +219,18 @@ static void authenticate (SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer data) { - int *i = data; + SoupAuthTest *test = data; char *username, *password; char num; - if (!current_tests[*i].provided[0]) + if (!test->provided[0]) return; if (retrying) { - if (!current_tests[*i].provided[1]) + if (!test->provided[1]) return; - num = current_tests[*i].provided[1]; + num = test->provided[1]; } else - num = current_tests[*i].provided[0]; + num = test->provided[0]; username = g_strdup_printf ("user%c", num); password = g_strdup_printf ("realm%c", num); @@ -249,13 +246,10 @@ bug271540_sent (SoupMessage *msg, gpointer data) gboolean *authenticated = data; int auth = identify_auth (msg); - if (!*authenticated && auth) { - debug_printf (1, " using auth on message %d before authenticating!!??\n", n); - errors++; - } else if (*authenticated && !auth) { - debug_printf (1, " sent unauthenticated message %d after authenticating!\n", n); - errors++; - } + soup_test_assert (*authenticated || !auth, + "using auth on message %d before authenticating", n); + soup_test_assert (!*authenticated || auth, + "sent unauthenticated message %d after authenticating", n); } static void @@ -274,8 +268,8 @@ bug271540_authenticate (SoupSession *session, SoupMessage *msg, soup_auth_authenticate (auth, "user1", "realm1"); *authenticated = TRUE; } else { - debug_printf (1, " asked to authenticate message %d after authenticating!\n", n); - errors++; + soup_test_assert (!*authenticated, + "asked to authenticate message %d after authenticating", n); } } @@ -283,13 +277,8 @@ static void bug271540_finished (SoupSession *session, SoupMessage *msg, gpointer data) { int *left = data; - int n = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (msg), "#")); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " got status '%d %s' on message %d!\n", - msg->status_code, msg->reason_phrase, n); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); (*left)--; if (!*left) @@ -297,7 +286,7 @@ bug271540_finished (SoupSession *session, SoupMessage *msg, gpointer data) } static void -do_pipelined_auth_test (const char *base_uri) +do_pipelined_auth_test (void) { SoupSession *session; SoupMessage *msg; @@ -442,23 +431,16 @@ do_digest_nonce_test (SoupSession *session, &got_401); got_401 = FALSE; soup_session_send_message (session, msg); - if (got_401 != expect_401) { - debug_printf (1, " %s request %s a 401 Unauthorized!\n", nth, - got_401 ? "got" : "did not get"); - errors++; - } - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " %s request got status %d %s!\n", nth, - msg->status_code, msg->reason_phrase); - errors++; - } - if (errors == 0) - debug_printf (1, " %s request succeeded\n", nth); + soup_test_assert (got_401 == expect_401, + "%s request %s a 401 Unauthorized!\n", nth, + got_401 ? "got" : "did not get"); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); } static void -do_digest_expiration_test (const char *base_uri) +do_digest_expiration_test (void) { SoupSession *session; char *uri; @@ -535,10 +517,8 @@ async_authenticate_assert_once (SoupSession *session, SoupMessage *msg, debug_printf (2, " async_authenticate_assert_once\n"); - if (*been_here) { - debug_printf (1, " ERROR: async_authenticate_assert_once called twice\n"); - errors++; - } + soup_test_assert (!*been_here, + "async_authenticate_assert_once called twice"); *been_here = TRUE; } @@ -550,10 +530,8 @@ async_authenticate_assert_once_and_stop (SoupSession *session, SoupMessage *msg, debug_printf (2, " async_authenticate_assert_once_and_stop\n"); - if (*been_here) { - debug_printf (1, " ERROR: async_authenticate_assert_once called twice\n"); - errors++; - } + soup_test_assert (!*been_here, + "async_authenticate_assert_once called twice"); *been_here = TRUE; soup_session_pause_message (session, msg); @@ -561,7 +539,7 @@ async_authenticate_assert_once_and_stop (SoupSession *session, SoupMessage *msg, } static void -do_async_auth_test (const char *base_uri) +do_async_auth_test (void) { SoupSession *session; SoupMessage *msg1, *msg2, *msg3, msg2_bak; @@ -595,13 +573,7 @@ do_async_auth_test (const char *base_uri) g_object_set_data (G_OBJECT (msg2), "id", GINT_TO_POINTER (2)); soup_session_send_message (session, msg2); - if (msg2->status_code == SOUP_STATUS_UNAUTHORIZED) - debug_printf (1, " msg2 failed as expected\n"); - else { - debug_printf (1, " msg2 got wrong status! (%u)\n", - msg2->status_code); - errors++; - } + soup_test_assert_message_status (msg2, SOUP_STATUS_UNAUTHORIZED); /* msg2 should be done at this point; assuming everything is * working correctly, the session won't look at it again; we @@ -632,25 +604,11 @@ do_async_auth_test (const char *base_uri) g_main_loop_run (loop); /* async_finished will quit the loop */ - } else { - debug_printf (1, " msg1 didn't get authenticate signal!\n"); - errors++; - } + } else + soup_test_assert (auth, "msg1 didn't get authenticate signal"); - if (msg1->status_code == SOUP_STATUS_OK) - debug_printf (1, " msg1 succeeded\n"); - else { - debug_printf (1, " msg1 FAILED! (%u %s)\n", - msg1->status_code, msg1->reason_phrase); - errors++; - } - if (msg3->status_code == SOUP_STATUS_OK) - debug_printf (1, " msg3 succeeded\n"); - else { - debug_printf (1, " msg3 FAILED! (%u %s)\n", - msg3->status_code, msg3->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg1, SOUP_STATUS_OK); + soup_test_assert_message_status (msg3, SOUP_STATUS_OK); soup_test_session_abort_unref (session); @@ -688,10 +646,8 @@ do_async_auth_test (const char *base_uri) g_main_loop_run (loop); g_signal_handler_disconnect (session, auth_id); - if (!been_there) { - debug_printf (1, " authenticate not emitted?\n"); - errors++; - } + soup_test_assert (been_there, + "authenticate not emitted"); soup_test_session_abort_unref (session); g_object_unref (msg1); @@ -800,41 +756,27 @@ select_auth_test_one (SoupURI *uri, msg = soup_message_new_from_uri ("GET", uri); soup_session_send_message (session, msg); - if (strcmp (sad.round[0].headers, first_headers) != 0) { - debug_printf (1, " Header order wrong: expected %s, got %s\n", - first_headers, sad.round[0].headers); - errors++; - } - if (strcmp (sad.round[0].response, first_response) != 0) { - debug_printf (1, " Selected auth type wrong: expected %s, got %s\n", - first_response, sad.round[0].response); - errors++; - } - - if (second_headers && !sad.round[1].headers) { - debug_printf (1, " Expected a second round!\n"); - errors++; - } else if (!second_headers && sad.round[1].headers) { - debug_printf (1, " Didn't expect a second round!\n"); - errors++; - } else if (second_headers && second_response) { - if (strcmp (sad.round[1].headers, second_headers) != 0) { - debug_printf (1, " Second round header order wrong: expected %s, got %s\n", - second_headers, sad.round[1].headers); - errors++; - } - if (strcmp (sad.round[1].response, second_response) != 0) { - debug_printf (1, " Second round selected auth type wrong: expected %s, got %s\n", - second_response, sad.round[1].response); - errors++; - } + soup_test_assert (strcmp (sad.round[0].headers, first_headers) == 0, + "Header order wrong: expected %s, got %s", + first_headers, sad.round[0].headers); + soup_test_assert (strcmp (sad.round[0].response, first_response) == 0, + "Selected auth type wrong: expected %s, got %s", + first_response, sad.round[0].response); + + soup_test_assert (sad.round[1].headers || !second_headers, + "Expected a second round"); + soup_test_assert (!sad.round[1].headers || second_headers, + "Didn't expect a second round"); + if (second_headers && second_response) { + soup_test_assert (strcmp (sad.round[1].headers, second_headers) == 0, + "Second round header order wrong: expected %s, got %s\n", + second_headers, sad.round[1].headers); + soup_test_assert (strcmp (sad.round[1].response, second_response) == 0, + "Second round selected auth type wrong: expected %s, got %s\n", + second_response, sad.round[1].response); } - if (msg->status_code != final_status) { - debug_printf (1, " Final status wrong: expected %u, got %u\n", - final_status, msg->status_code); - errors++; - } + soup_test_assert_message_status (msg, final_status); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -1062,12 +1004,7 @@ do_auth_close_test (void) soup_uri_free (uri); soup_session_send_message (acd.session, acd.msg); - if (acd.msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Final status wrong: expected %u, got %u %s\n", - SOUP_STATUS_OK, acd.msg->status_code, - acd.msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (acd.msg, SOUP_STATUS_OK); g_object_unref (acd.msg); soup_test_session_abort_unref (acd.session); @@ -1089,7 +1026,7 @@ infinite_authenticate (SoupSession *session, SoupMessage *msg, } static void -do_infinite_auth_test (const char *base_uri) +do_infinite_auth_test (void) { SoupSession *session; SoupMessage *msg; @@ -1107,17 +1044,14 @@ do_infinite_auth_test (const char *base_uri) g_free (uri); timeout = g_timeout_add (500, infinite_cancel, session); - expect_warning = TRUE; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*stuck in infinite loop*"); soup_session_send_message (session, msg); + g_test_assert_expected_messages (); - if (msg->status_code == SOUP_STATUS_CANCELLED) { - debug_printf (1, " FAILED: Got stuck in loop"); - errors++; - } else if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { - debug_printf (1, " Final status wrong: expected 401, got %u\n", - msg->status_code); - errors++; - } + soup_test_assert (msg->status_code != SOUP_STATUS_CANCELLED, + "Got stuck in loop"); + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); g_source_remove (timeout); soup_test_session_abort_unref (session); @@ -1182,14 +1116,9 @@ do_disappearing_auth_test (void) msg = soup_message_new_from_uri ("GET", uri); soup_session_send_message (session, msg); - if (counter > 2) { - debug_printf (1, " FAILED: Got stuck in loop"); - errors++; - } else if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { - debug_printf (1, " Final status wrong: expected 401, got %u\n", - msg->status_code); - errors++; - } + soup_test_assert (counter <= 2, + "Got stuck in loop"); + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -1220,25 +1149,26 @@ static SoupAuthTest relogin_tests[] = { { "Should fail with no auth, fail again with bad password, and give up", "Basic/realm12/", "3", FALSE, "03", SOUP_STATUS_UNAUTHORIZED }, + + { NULL } }; static void -do_batch_tests (const gchar *base_uri_str, gint ntests) +do_batch_tests (gconstpointer data) { + const SoupAuthTest *current_tests = data; SoupSession *session; SoupMessage *msg; char *expected, *uristr; - SoupURI *base_uri; + SoupURI *base; + guint signal; int i; session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - g_signal_connect (session, "authenticate", - G_CALLBACK (authenticate), &i); - - base_uri = soup_uri_new (base_uri_str); + base = soup_uri_new (base_uri); - for (i = 0; i < ntests; i++) { - SoupURI *soup_uri = soup_uri_new_with_base (base_uri, current_tests[i].url); + for (i = 0; current_tests[i].url; i++) { + SoupURI *soup_uri = soup_uri_new_with_base (base, current_tests[i].url); debug_printf (1, "Test %d: %s\n", i + 1, current_tests[i].explanation); @@ -1269,30 +1199,24 @@ do_batch_tests (const gchar *base_uri_str, gint ntests) soup_message_add_status_code_handler ( msg, "got_headers", SOUP_STATUS_OK, G_CALLBACK (handler), expected); + + signal = g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), + (gpointer)¤t_tests[i]); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_UNAUTHORIZED && - msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " %d %s !\n", msg->status_code, - msg->reason_phrase); - errors++; - } - if (*expected) { - debug_printf (1, " expected %d more round(s)\n", - (int)strlen (expected)); - errors++; - } - g_free (expected); + g_signal_handler_disconnect (session, signal); - if (msg->status_code != current_tests[i].final_status) { - debug_printf (1, " expected %d\n", - current_tests[i].final_status); - } + soup_test_assert_message_status (msg, current_tests[i].final_status); + soup_test_assert (!*expected, + "expected %d more round(s)\n", + (int)strlen (expected)); + g_free (expected); debug_printf (1, "\n"); g_object_unref (msg); } - soup_uri_free (base_uri); + soup_uri_free (base); soup_test_session_abort_unref (session); } @@ -1300,35 +1224,27 @@ do_batch_tests (const gchar *base_uri_str, gint ntests) int main (int argc, char **argv) { - const char *base_uri; - int ntests; + int ret; test_init (argc, argv, NULL); apache_init (); base_uri = "http://127.0.0.1:47524/"; - /* Main tests */ - current_tests = main_tests; - ntests = G_N_ELEMENTS (main_tests); - do_batch_tests (base_uri, ntests); - - /* Re-login tests */ - current_tests = relogin_tests; - ntests = G_N_ELEMENTS (relogin_tests); - do_batch_tests (base_uri, ntests); - - /* Other regression tests */ - do_pipelined_auth_test (base_uri); - do_digest_expiration_test (base_uri); - do_async_auth_test (base_uri); - do_select_auth_test (); - do_auth_close_test (); - do_infinite_auth_test (base_uri); - do_disappearing_auth_test (); + g_test_add_data_func ("/auth/main-tests", main_tests, do_batch_tests); + g_test_add_data_func ("/auth/relogin-tests", relogin_tests, do_batch_tests); + g_test_add_func ("/auth/pipelined-auth", do_pipelined_auth_test); + g_test_add_func ("/auth/digest-expiration", do_digest_expiration_test); + g_test_add_func ("/auth/async-auth", do_async_auth_test); + g_test_add_func ("/auth/select-auth", do_select_auth_test); + g_test_add_func ("/auth/auth-close", do_auth_close_test); + g_test_add_func ("/auth/infinite-auth", do_infinite_auth_test); + g_test_add_func ("/auth/disappearing-auth", do_disappearing_auth_test); + + ret = g_test_run (); test_cleanup (); - return errors != 0; + return ret; } #else /* HAVE_APACHE */ diff --git a/tests/cache-test.c b/tests/cache-test.c index a19e9747..b60fb9c1 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -264,8 +264,9 @@ request_unqueued (SoupSession *session, SoupMessage *msg, } static void -do_basics_test (SoupURI *base_uri) +do_basics_test (gconstpointer data) { + SoupURI *base_uri = (SoupURI *)data; SoupSession *session; SoupCache *cache; char *cache_dir; @@ -307,15 +308,9 @@ do_basics_test (SoupURI *base_uri) debug_printf (1, " Fresh cached resource\n"); cmp = do_request (session, base_uri, "GET", "/1", NULL, NULL); - if (last_request_hit_network) { - debug_printf (1, " Request for /1 not filled from cache!\n"); - errors++; - } - if (strcmp (body1, cmp) != 0) { - debug_printf (1, " Cached response (%s) did not match original (%s)\n", - cmp, body1); - errors++; - } + soup_test_assert (!last_request_hit_network, + "Request for /1 not filled from cache"); + g_assert_cmpstr (body1, ==, cmp); g_free (cmp); @@ -323,15 +318,9 @@ do_basics_test (SoupURI *base_uri) debug_printf (1, " Heuristically-fresh cached resource\n"); cmp = do_request (session, base_uri, "GET", "/2", NULL, NULL); - if (last_request_hit_network) { - debug_printf (1, " Request for /2 not filled from cache!\n"); - errors++; - } - if (strcmp (body2, cmp) != 0) { - debug_printf (1, " Cached response (%s) did not match original (%s)\n", - cmp, body2); - errors++; - } + soup_test_assert (!last_request_hit_network, + "Request for /2 not filled from cache"); + g_assert_cmpstr (body2, ==, cmp); g_free (cmp); @@ -339,23 +328,15 @@ do_basics_test (SoupURI *base_uri) debug_printf (1, " Fresh cached resource with a query\n"); cmp = do_request (session, base_uri, "GET", "/1?attr=value", NULL, NULL); - if (!last_request_hit_network) { - debug_printf (1, " Request for /1?attr=value filled from cache!\n"); - errors++; - } + soup_test_assert (last_request_hit_network, + "Request for /1?attr=value filled from cache"); g_free (cmp); debug_printf (2, " Second request\n"); cmp = do_request (session, base_uri, "GET", "/1", NULL, NULL); - if (last_request_hit_network) { - debug_printf (1, " Second request for /1 not filled from cache!\n"); - errors++; - } - if (strcmp (body1, cmp) != 0) { - debug_printf (1, " Cached response (%s) did not match original (%s)\n", - cmp, body1); - errors++; - } + soup_test_assert (!last_request_hit_network, + "Second request for /1 not filled from cache"); + g_assert_cmpstr (body1, ==, cmp); g_free (cmp); @@ -365,19 +346,11 @@ do_basics_test (SoupURI *base_uri) "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", "Test-Set-Cache-Control", "must-revalidate", NULL); - if (!last_request_validated) { - debug_printf (1, " Request for /3 not validated!\n"); - errors++; - } - if (last_request_hit_network) { - debug_printf (1, " Request for /3 not filled from cache!\n"); - errors++; - } - if (strcmp (body3, cmp) != 0) { - debug_printf (1, " Cached response (%s) did not match original (%s)\n", - cmp, body3); - errors++; - } + soup_test_assert (last_request_validated, + "Request for /3 not validated"); + soup_test_assert (!last_request_hit_network, + "Request for /3 not filled from cache"); + g_assert_cmpstr (body3, ==, cmp); g_free (cmp); @@ -387,18 +360,11 @@ do_basics_test (SoupURI *base_uri) "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT", "Test-Set-Cache-Control", "must-revalidate", NULL); - if (!last_request_validated) { - debug_printf (1, " Request for /3 not validated!\n"); - errors++; - } - if (!last_request_hit_network) { - debug_printf (1, " Request for /3 filled from cache!\n"); - errors++; - } - if (strcmp (body3, cmp) == 0) { - debug_printf (1, " Request for /3 returned cached response\n"); - errors++; - } + soup_test_assert (last_request_validated, + "Request for /3 not validated"); + soup_test_assert (last_request_hit_network, + "Request for /3 filled from cache"); + g_assert_cmpstr (body3, !=, cmp); g_free (cmp); debug_printf (2, " Second request\n"); @@ -406,18 +372,11 @@ do_basics_test (SoupURI *base_uri) "Test-Set-Last-Modified", "Sat, 02 Jan 2010 00:00:00 GMT", "Test-Set-Cache-Control", "must-revalidate", NULL); - if (!last_request_validated) { - debug_printf (1, " Second request for /3 not validated!\n"); - errors++; - } - if (last_request_hit_network) { - debug_printf (1, " Second request for /3 not filled from cache!\n"); - errors++; - } - if (strcmp (body3, cmp) == 0) { - debug_printf (1, " Replacement body for /3 not cached!\n"); - errors++; - } + soup_test_assert (last_request_validated, + "Second request for /3 not validated"); + soup_test_assert (!last_request_hit_network, + "Second request for /3 not filled from cache"); + g_assert_cmpstr (body3, !=, cmp); g_free (cmp); /* ETag + must-revalidate causes a conditional request */ @@ -425,19 +384,11 @@ do_basics_test (SoupURI *base_uri) cmp = do_request (session, base_uri, "GET", "/4", NULL, "Test-Set-ETag", "\"abcdefg\"", NULL); - if (!last_request_validated) { - debug_printf (1, " Request for /4 not validated!\n"); - errors++; - } - if (last_request_hit_network) { - debug_printf (1, " Request for /4 not filled from cache!\n"); - errors++; - } - if (strcmp (body4, cmp) != 0) { - debug_printf (1, " Cached response (%s) did not match original (%s)\n", - cmp, body4); - errors++; - } + soup_test_assert (last_request_validated, + "Request for /4 not validated"); + soup_test_assert (!last_request_hit_network, + "Request for /4 not filled from cache"); + g_assert_cmpstr (body4, ==, cmp); g_free (cmp); @@ -446,15 +397,9 @@ do_basics_test (SoupURI *base_uri) cmp = do_request (session, base_uri, "GET", "/5", NULL, "Test-Set-Cache-Control", "no-cache", NULL); - if (!last_request_hit_network) { - debug_printf (1, " Request for /5 filled from cache!\n"); - errors++; - } - if (strcmp (body5, cmp) != 0) { - debug_printf (1, " Re-retrieved response (%s) did not match original (%s)\n", - cmp, body5); - errors++; - } + soup_test_assert (last_request_hit_network, + "Request for /5 filled from cache"); + g_assert_cmpstr (body5, ==, cmp); g_free (cmp); @@ -462,17 +407,14 @@ do_basics_test (SoupURI *base_uri) debug_printf (1, " Invalidating and re-requesting a cached resource\n"); cmp = do_request (session, base_uri, "PUT", "/1", NULL, NULL); - if (!last_request_hit_network) { - debug_printf (1, " PUT filled from cache!\n"); - errors++; - } + soup_test_assert (last_request_hit_network, + "PUT filled from cache"); g_free (cmp); cmp = do_request (session, base_uri, "GET", "/1", NULL, NULL); - if (!last_request_hit_network) { - debug_printf (1, " PUT failed to invalidate cache entry!\n"); - errors++; - } + soup_test_assert (last_request_hit_network, + "PUT failed to invalidate cache entry"); + g_assert_true (last_request_hit_network); g_free (cmp); @@ -488,8 +430,9 @@ do_basics_test (SoupURI *base_uri) } static void -do_cancel_test (SoupURI *base_uri) +do_cancel_test (gconstpointer data) { + SoupURI *base_uri = (SoupURI *)data; SoupSession *session; SoupCache *cache; char *cache_dir; @@ -521,20 +464,12 @@ do_cancel_test (SoupURI *base_uri) debug_printf (1, " Cancel fresh resource with soup_session_message_cancel()\n"); flags = SOUP_TEST_REQUEST_CANCEL_MESSAGE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; do_request_with_cancel (session, base_uri, "GET", "/1", flags); - if (cancelled_requests != 1) { - debug_printf (1, " invalid number of cancelled requests: %d (1 expected)\n", - cancelled_requests); - errors++; - } + g_assert_cmpint (cancelled_requests, ==, 1); debug_printf (1, " Cancel fresh resource with g_cancellable_cancel()\n"); flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; do_request_with_cancel (session, base_uri, "GET", "/1", flags); - if (cancelled_requests != 1) { - debug_printf (1, " invalid number of cancelled requests: %d (1 expected)\n", - cancelled_requests); - errors++; - } + g_assert_cmpint (cancelled_requests, ==, 1); soup_test_session_abort_unref (session); @@ -549,20 +484,12 @@ do_cancel_test (SoupURI *base_uri) debug_printf (1, " Cancel a revalidating resource with soup_session_message_cancel()\n"); flags = SOUP_TEST_REQUEST_CANCEL_MESSAGE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; do_request_with_cancel (session, base_uri, "GET", "/2", flags); - if (cancelled_requests != 2) { - debug_printf (1, " invalid number of cancelled requests: %d (2 expected)\n", - cancelled_requests); - errors++; - } + g_assert_cmpint (cancelled_requests, ==, 2); debug_printf (1, " Cancel a revalidating resource with g_cancellable_cancel()\n"); flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; do_request_with_cancel (session, base_uri, "GET", "/2", flags); - if (cancelled_requests != 2) { - debug_printf (1, " invalid number of cancelled requests: %d (2 expected)\n", - cancelled_requests); - errors++; - } + g_assert_cmpint (cancelled_requests, ==, 2); soup_test_session_abort_unref (session); @@ -586,8 +513,9 @@ base_stream_unreffed (gpointer loop, GObject *ex_base_stream) } static void -do_refcounting_test (SoupURI *base_uri) +do_refcounting_test (gconstpointer data) { + SoupURI *base_uri = (SoupURI *)data; SoupSession *session; SoupCache *cache; char *cache_dir; @@ -644,8 +572,9 @@ do_refcounting_test (SoupURI *base_uri) } static void -do_headers_test (SoupURI *base_uri) +do_headers_test (gconstpointer data) { + SoupURI *base_uri = (SoupURI *)data; SoupSession *session; SoupMessageHeaders *headers; SoupCache *cache; @@ -678,14 +607,10 @@ do_headers_test (SoupURI *base_uri) "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", "Test-Set-My-Header", "My header NEW value", NULL); - if (!last_request_validated) { - debug_printf (1, " Request for /1 not validated!\n"); - errors++; - } - if (last_request_hit_network) { - debug_printf (1, " Request for /1 not filled from cache!\n"); - errors++; - } + soup_test_assert (last_request_validated, + "Request for /1 not validated"); + soup_test_assert (!last_request_hit_network, + "Request for /1 not filled from cache"); g_free (cmp); /* Check that cache returns the updated header */ @@ -694,22 +619,12 @@ do_headers_test (SoupURI *base_uri) cmp = do_request (session, base_uri, "GET", "/1", headers, "Test-Set-Last-Modified", "Fri, 01 Jan 2010 00:00:00 GMT", NULL); - if (last_request_hit_network) { - debug_printf (1, " Request for /1 not filled from cache!\n"); - errors++; - } + soup_test_assert (!last_request_hit_network, + "Request for /1 not filled from cache"); g_free (cmp); header_value = soup_message_headers_get_list (headers, "My-Header"); - if (!header_value) { - debug_printf (1, " Header \"My-Header\" not present!\n"); - errors++; - } else if (strcmp (header_value, "My header NEW value") != 0) { - debug_printf (1, " \"My-Header = %s\" and should be \"%s\"\n", - header_value, - "My header NEW value"); - errors++; - } + g_assert_cmpstr (header_value, ==, "My header NEW value"); soup_message_headers_free (headers); soup_test_session_abort_unref (session); @@ -724,6 +639,7 @@ main (int argc, char **argv) { SoupServer *server; SoupURI *base_uri; + int ret; test_init (argc, argv, NULL); @@ -732,14 +648,16 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); - do_basics_test (base_uri); - do_cancel_test (base_uri); - do_refcounting_test (base_uri); - do_headers_test (base_uri); + g_test_add_data_func ("/cache/basics", base_uri, do_basics_test); + g_test_add_data_func ("/cache/cancellation", base_uri, do_cancel_test); + g_test_add_data_func ("/cache/refcounting", base_uri, do_refcounting_test); + g_test_add_data_func ("/cache/headers", base_uri, do_headers_test); + + ret = g_test_run (); soup_uri_free (base_uri); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/chunk-io-test.c b/tests/chunk-io-test.c index f1f96b0f..4003e341 100644 --- a/tests/chunk-io-test.c +++ b/tests/chunk-io-test.c @@ -350,6 +350,7 @@ do_io_tests (void) { GInputStream *imem, *islow, *in; GOutputStream *omem, *oslow, *out; + GMemoryOutputStream *mem; char *raw_contents, *buf; gsize raw_length; GString *chunkified; @@ -387,35 +388,20 @@ do_io_tests (void) while (TRUE) { nread = g_input_stream_read (in, buf + total, raw_length - total, NULL, &error); - if (nread == -1) { - debug_printf (1, " Error reading stream: %s\n", error->message); - g_clear_error (&error); - errors++; - break; - } else if (nread == 0) - break; - else + g_assert_no_error (error); + g_clear_error (&error); + if (nread > 0) total += nread; + else + break; } g_input_stream_close (in, NULL, &error); - if (error) { - debug_printf (1, " Error closing input stream: %s\n", error->message); - g_clear_error (&error); - errors++; - } + g_assert_no_error (error); + g_clear_error (&error); g_object_unref (in); - if (total == raw_length) { - if (memcmp (buf, raw_contents, raw_length) != 0) { - debug_printf (1, " mismatch when reading\n"); - errors++; - } - } else { - debug_printf (1, " incorrect read length: %d vs %d\n", - (int) total, (int) raw_length); - errors++; - } + soup_assert_cmpmem (buf, total, raw_contents, raw_length); g_free (buf); debug_printf (1, " async read\n"); @@ -452,9 +438,8 @@ do_io_tests (void) g_source_unref (source); continue; } else if (nread == -1) { - debug_printf (1, " Error reading stream: %s\n", error->message); + g_assert_no_error (error); g_clear_error (&error); - errors++; break; } else if (nread == 0) break; @@ -463,23 +448,11 @@ do_io_tests (void) } g_input_stream_close (in, NULL, &error); - if (error) { - debug_printf (1, " Error closing input stream: %s\n", error->message); - g_clear_error (&error); - errors++; - } + g_assert_no_error (error); + g_clear_error (&error); g_object_unref (in); - if (total == raw_length) { - if (memcmp (buf, raw_contents, raw_length) != 0) { - debug_printf (1, " mismatch when reading\n"); - errors++; - } - } else { - debug_printf (1, " incorrect read length: %d vs %d\n", - (int) total, (int) raw_length); - errors++; - } + soup_assert_cmpmem (buf, total, raw_contents, raw_length); g_free (buf); debug_printf (1, " sync write\n"); @@ -506,32 +479,25 @@ do_io_tests (void) } nwrote = g_output_stream_write (out, raw_contents + total, chunk_length - chunk_total, NULL, &error); - if (nwrote == -1) { - debug_printf (1, " Error writing stream: %s\n", error->message); - g_clear_error (&error); - errors++; - break; - } else { + g_assert_no_error (error); + g_clear_error (&error); + if (nwrote > 0) { total += nwrote; chunk_total += nwrote; - } + } else + break; } g_output_stream_close (out, NULL, &error); - if (error) { - debug_printf (1, " Error closing output stream: %s\n", error->message); - g_clear_error (&error); - errors++; - } - g_object_unref (out); + g_assert_no_error (error); + g_clear_error (&error); - if (total == raw_length) { - if (memcmp (buf, chunkified->str, chunkified->len) != 0) { - debug_printf (1, " mismatch when writing\n"); - g_print ("%.*s\n", (int)chunkified->len, buf); - errors++; - } - } + mem = G_MEMORY_OUTPUT_STREAM (omem); + soup_assert_cmpmem (g_memory_output_stream_get_data (mem), + g_memory_output_stream_get_data_size (mem), + chunkified->str, chunkified->len); + + g_object_unref (out); g_free (buf); debug_printf (1, " async write\n"); @@ -573,9 +539,8 @@ do_io_tests (void) g_source_unref (source); continue; } else if (nwrote == -1) { - debug_printf (1, " Error writing stream: %s\n", error->message); + g_assert_no_error (error); g_clear_error (&error); - errors++; break; } else { total += nwrote; @@ -584,19 +549,15 @@ do_io_tests (void) } g_output_stream_close (out, NULL, &error); - if (error) { - debug_printf (1, " Error closing output stream: %s\n", error->message); - g_clear_error (&error); - errors++; - } - g_object_unref (out); + g_assert_no_error (error); + g_clear_error (&error); - if (total == raw_length) { - if (memcmp (buf, chunkified->str, chunkified->len) != 0) { - debug_printf (1, " mismatch when writing\n"); - errors++; - } - } + mem = G_MEMORY_OUTPUT_STREAM (omem); + soup_assert_cmpmem (g_memory_output_stream_get_data (mem), + g_memory_output_stream_get_data_size (mem), + chunkified->str, chunkified->len); + + g_object_unref (out); g_free (buf); debug_printf (1, " failed write\n"); @@ -626,10 +587,7 @@ do_io_tests (void) total += nwrote; } - if (total == raw_length) { - debug_printf (1, " breaking stream didn't break?\n"); - errors++; - } + g_assert_cmpint (total, !=, raw_length); g_output_stream_close (out, NULL, NULL); g_object_unref (out); @@ -643,12 +601,16 @@ do_io_tests (void) int main (int argc, char **argv) { + int ret; + test_init (argc, argv, NULL); force_io_streams_init (); - do_io_tests (); + g_test_add_func ("/chunk-io", do_io_tests); + + ret = g_test_run (); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/chunk-test.c b/tests/chunk-test.c index ce929565..de1007d7 100644 --- a/tests/chunk-test.c +++ b/tests/chunk-test.c @@ -5,6 +5,9 @@ #include "test-utils.h" +static SoupSession *session; +static SoupURI *base_uri; + typedef struct { SoupSession *session; SoupBuffer *chunks[3]; @@ -19,9 +22,9 @@ write_next_chunk (SoupMessage *msg, gpointer user_data) debug_printf (2, " writing chunk %d\n", ptd->next); - if (ptd->streaming && ptd->next > 0 && ptd->chunks[ptd->next - 1]) { - debug_printf (1, " error: next chunk requested before last one freed!\n"); - errors++; + if (ptd->streaming && ptd->next > 0) { + soup_test_assert (ptd->chunks[ptd->next - 1] == NULL, + "next chunk requested before last one freed"); } if (ptd->next < G_N_ELEMENTS (ptd->chunks)) { @@ -50,8 +53,8 @@ write_next_chunk_streaming_hack (SoupMessage *msg, gpointer user_data) soup_message_body_wrote_chunk (msg->request_body, chunk); soup_buffer_free (chunk); } else { - debug_printf (1, " error: written chunk does not exist!\n"); - errors++; + soup_test_assert (chunk, + "written chunk does not exist"); } write_next_chunk (msg, user_data); } @@ -77,8 +80,8 @@ clear_buffer_ptr (gpointer data) g_free ((char *)(*buffer_ptr)->data); *buffer_ptr = NULL; } else { - debug_printf (2, " chunk is already clear!\n"); - errors++; + soup_test_assert (*buffer_ptr, + "chunk is already clear"); } } @@ -136,8 +139,9 @@ typedef enum { } RequestTestFlags; static void -do_request_test (SoupSession *session, SoupURI *base_uri, RequestTestFlags flags) +do_request_test (gconstpointer data) { + RequestTestFlags flags = GPOINTER_TO_UINT (data); SoupURI *uri = base_uri; PutTestData ptd; SoupMessage *msg; @@ -199,29 +203,14 @@ do_request_test (SoupSession *session, SoupURI *base_uri, RequestTestFlags flags G_CALLBACK (wrote_body_data), &ptd); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " message failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - - if (msg->request_body->data) { - debug_printf (1, " msg->request_body set!\n"); - errors++; - } - if (msg->request_body->length != length || length != ptd.nwrote) { - debug_printf (1, " sent length mismatch: %d vs %d vs %d\n", - (int)msg->request_body->length, length, ptd.nwrote); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CREATED); + g_assert_null (msg->request_body->data); + g_assert_cmpint (msg->request_body->length, ==, length); + g_assert_cmpint (length, ==, ptd.nwrote); server_md5 = soup_message_headers_get_one (msg->response_headers, "Content-MD5"); - if (!server_md5 || strcmp (client_md5, server_md5) != 0) { - debug_printf (1, " client/server data mismatch: %s vs %s\n", - client_md5, server_md5 ? server_md5 : "(null)"); - errors++; - } + g_assert_cmpstr (client_md5, ==, server_md5); g_object_unref (msg); g_checksum_free (check); @@ -243,10 +232,8 @@ chunk_allocator (SoupMessage *msg, gsize max_len, gpointer user_data) debug_printf (2, " allocating chunk\n"); - if (gtd->current_chunk) { - debug_printf (1, " error: next chunk allocated before last one freed!\n"); - errors++; - } + soup_test_assert (gtd->current_chunk == NULL, + "error: next chunk allocated before last one freed"); gtd->current_chunk = soup_buffer_new_with_owner (g_malloc (6), 6, >d->current_chunk, clear_buffer_ptr); @@ -270,7 +257,7 @@ got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) } static void -do_response_test (SoupSession *session, SoupURI *base_uri) +do_response_test (void) { GetTestData gtd; SoupMessage *msg; @@ -291,30 +278,14 @@ do_response_test (SoupSession *session, SoupURI *base_uri) G_CALLBACK (got_chunk), >d); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " message failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - - if (msg->response_body->data) { - debug_printf (1, " msg->response_body set!\n"); - errors++; - } - if (soup_message_headers_get_content_length (msg->response_headers) != gtd.length) { - debug_printf (1, " received length mismatch: %d vs %d\n", - (int)soup_message_headers_get_content_length (msg->response_headers), gtd.length); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_null (msg->response_body->data); + g_assert_cmpint (soup_message_headers_get_content_length (msg->response_headers), ==, gtd.length); client_md5 = g_checksum_get_string (gtd.check); server_md5 = soup_message_headers_get_one (msg->response_headers, "Content-MD5"); - if (!server_md5 || strcmp (client_md5, server_md5) != 0) { - debug_printf (1, " client/server data mismatch: %s vs %s\n", - client_md5, server_md5 ? server_md5 : "(null)"); - errors++; - } + g_assert_cmpstr (client_md5, ==, server_md5); g_object_unref (msg); g_checksum_free (gtd.check); @@ -336,18 +307,18 @@ temp_test_wrote_chunk (SoupMessage *msg, gpointer session) * the I/O to stall since soup-message-io will think it's * done, but it hasn't written Content-Length bytes yet. */ - if (!chunk) { - debug_printf (1, " Lost second chunk!\n"); - errors++; - soup_session_abort (session); - } else + if (chunk) soup_buffer_free (chunk); + else { + soup_test_assert (chunk, "Lost second chunk"); + soup_session_abort (session); + } g_signal_handlers_disconnect_by_func (msg, temp_test_wrote_chunk, session); } static void -do_temporary_test (SoupSession *session, SoupURI *base_uri) +do_temporary_test (void) { SoupMessage *msg; char *client_md5; @@ -368,19 +339,11 @@ do_temporary_test (SoupSession *session, SoupURI *base_uri) G_CALLBACK (temp_test_wrote_chunk), session); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " message failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CREATED); server_md5 = soup_message_headers_get_one (msg->response_headers, "Content-MD5"); - if (!server_md5 || strcmp (client_md5, server_md5) != 0) { - debug_printf (1, " client/server data mismatch: %s vs %s\n", - client_md5, server_md5 ? server_md5 : "(null)"); - errors++; - } + g_assert_cmpstr (client_md5, ==, server_md5); g_free (client_md5); g_object_unref (msg); @@ -398,16 +361,14 @@ large_wrote_body_data (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) { LargeChunkData *lcd = user_data; - if (memcmp (chunk->data, lcd->buf->data + lcd->offset, chunk->length) != 0) { - debug_printf (1, " chunk data mismatch at %ld\n", (long)lcd->offset); - errors++; - } else - debug_printf (2, " chunk data match at %ld\n", (long)lcd->offset); + soup_assert_cmpmem (chunk->data, chunk->length, + lcd->buf->data + lcd->offset, + chunk->length); lcd->offset += chunk->length; } static void -do_large_chunk_test (SoupSession *session, SoupURI *base_uri) +do_large_chunk_test (void) { SoupMessage *msg; char *buf_data; @@ -430,40 +391,12 @@ do_large_chunk_test (SoupSession *session, SoupURI *base_uri) G_CALLBACK (large_wrote_body_data), &lcd); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " message failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CREATED); soup_buffer_free (lcd.buf); g_object_unref (msg); } -static void -do_chunk_tests (SoupURI *base_uri) -{ - SoupSession *session; - - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - do_request_test (session, base_uri, 0); - debug_printf (2, "\n\n"); - do_request_test (session, base_uri, PROPER_STREAMING); - debug_printf (2, "\n\n"); - do_request_test (session, base_uri, PROPER_STREAMING | RESTART); - debug_printf (2, "\n\n"); - do_request_test (session, base_uri, HACKY_STREAMING); - debug_printf (2, "\n\n"); - do_request_test (session, base_uri, HACKY_STREAMING | RESTART); - debug_printf (2, "\n\n"); - do_response_test (session, base_uri); - debug_printf (2, "\n\n"); - do_temporary_test (session, base_uri); - debug_printf (2, "\n\n"); - do_large_chunk_test (session, base_uri); - soup_test_session_abort_unref (session); -} - static void server_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, @@ -507,7 +440,7 @@ main (int argc, char **argv) GMainLoop *loop; SoupServer *server; guint port; - SoupURI *base_uri; + int ret; test_init (argc, argv, NULL); @@ -520,12 +453,27 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1"); soup_uri_set_port (base_uri, port); - do_chunk_tests (base_uri); + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + + g_test_add_data_func ("/chunks/request/unstreamed", GINT_TO_POINTER (0), do_request_test); + g_test_add_data_func ("/chunks/request/proper-streaming", GINT_TO_POINTER (PROPER_STREAMING), do_request_test); + g_test_add_data_func ("/chunks/request/proper-streaming/restart", GINT_TO_POINTER (PROPER_STREAMING | RESTART), do_request_test); + g_test_add_data_func ("/chunks/request/hacky-streaming", GINT_TO_POINTER (HACKY_STREAMING), do_request_test); + g_test_add_data_func ("/chunks/request/hacky-streaming/restart", GINT_TO_POINTER (HACKY_STREAMING | RESTART), do_request_test); + g_test_add_func ("/chunks/response", do_response_test); + g_test_add_func ("/chunks/temporary", do_temporary_test); + g_test_add_func ("/chunks/large", do_large_chunk_test); + + ret = g_test_run (); + + soup_test_session_abort_unref (session); + soup_uri_free (base_uri); g_main_loop_unref (loop); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/coding-test.c b/tests/coding-test.c index 1bffbc43..8bc3e5f3 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -133,69 +133,20 @@ check_response (SoupMessage *msg, { const char *coding, *type; - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " Unexpected status %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); coding = soup_message_headers_get_one (msg->response_headers, "Content-Encoding"); - if (expected_encoding) { - if (!coding || g_ascii_strcasecmp (coding, expected_encoding) != 0) { - debug_printf (1, " Unexpected Content-Encoding: %s\n", - coding ? coding : "(none)"); - errors++; - } - } else { - if (coding) { - debug_printf (1, " Unexpected Content-Encoding: %s\n", - coding); - errors++; - } - } + g_assert_cmpstr (coding, ==, expected_encoding); if (status != NO_CHECK) { - if (status == EXPECT_DECODED) { - if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED)) { - debug_printf (1, " SOUP_MESSAGE_CONTENT_DECODED not set!\n"); - errors++; - } - } else { - if (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED) { - debug_printf (1, " SOUP_MESSAGE_CONTENT_DECODED set!\n"); - errors++; - } - } + if (status == EXPECT_DECODED) + g_assert_true (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED); + else + g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED); } type = soup_message_headers_get_one (msg->response_headers, "Content-Type"); - if (!type || g_ascii_strcasecmp (type, expected_content_type) != 0) { - debug_printf (1, " Unexpected Content-Type: %s\n", - type ? type : "(none)"); - errors++; - } -} - -static void -check_msg_bodies (SoupMessage *msg1, - SoupMessage *msg2, - const char *msg1_type, - const char *msg2_type) -{ - if (msg1->response_body->length != msg2->response_body->length) { - debug_printf (1, " Message length mismatch: %lu (%s) vs %lu (%s)\n", - (gulong)msg1->response_body->length, - msg1_type, - (gulong)msg2->response_body->length, - msg2_type); - errors++; - } else if (memcmp (msg1->response_body->data, - msg2->response_body->data, - msg1->response_body->length) != 0) { - debug_printf (1, " Message data mismatch (%s/%s)\n", - msg1_type, msg2_type); - errors++; - } + g_assert_cmpstr (type, ==, expected_content_type); } static void @@ -222,7 +173,10 @@ do_coding_test (void) msgz = soup_message_new_from_uri ("GET", uri); soup_session_send_message (session, msgz); check_response (msgz, "gzip", "text/plain", EXPECT_DECODED); - check_msg_bodies (msg, msgz, "plain", "compressed"); + soup_assert_cmpmem (msg->response_body->data, + msg->response_body->length, + msgz->response_body->data, + msgz->response_body->length); /* Plain text data, claim gzip w/ junk */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n"); @@ -231,7 +185,10 @@ do_coding_test (void) "X-Test-Options", "trailing-junk"); soup_session_send_message (session, msgj); check_response (msgj, "gzip", "text/plain", EXPECT_DECODED); - check_msg_bodies (msg, msgj, "plain", "compressed w/ junk"); + soup_assert_cmpmem (msg->response_body->data, + msg->response_body->length, + msgj->response_body->data, + msgj->response_body->length); /* Plain text data, claim gzip with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n"); @@ -245,7 +202,10 @@ do_coding_test (void) * from what the server sent... which happens to be the * uncompressed data. */ - check_msg_bodies (msg, msge, "plain", "mis-encoded"); + soup_assert_cmpmem (msg->response_body->data, + msg->response_body->length, + msge->response_body->data, + msge->response_body->length); /* Plain text data, claim deflate */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n"); @@ -254,7 +214,10 @@ do_coding_test (void) "X-Test-Options", "prefer-deflate-zlib"); soup_session_send_message (session, msgzl); check_response (msgzl, "deflate", "text/plain", EXPECT_DECODED); - check_msg_bodies (msg, msgzl, "plain", "compressed"); + soup_assert_cmpmem (msg->response_body->data, + msg->response_body->length, + msgzl->response_body->data, + msgzl->response_body->length); /* Plain text data, claim deflate w/ junk */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n"); @@ -263,7 +226,10 @@ do_coding_test (void) "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); soup_session_send_message (session, msgzlj); check_response (msgzlj, "deflate", "text/plain", EXPECT_DECODED); - check_msg_bodies (msg, msgzlj, "plain", "compressed w/ junk"); + soup_assert_cmpmem (msg->response_body->data, + msg->response_body->length, + msgzlj->response_body->data, + msgzlj->response_body->length); /* Plain text data, claim deflate with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n"); @@ -272,7 +238,10 @@ do_coding_test (void) "X-Test-Options", "force-encode, prefer-deflate-zlib"); soup_session_send_message (session, msgzle); check_response (msgzle, "deflate", "text/plain", EXPECT_NOT_DECODED); - check_msg_bodies (msg, msgzle, "plain", "mis-encoded"); + soup_assert_cmpmem (msg->response_body->data, + msg->response_body->length, + msgzle->response_body->data, + msgzle->response_body->length); /* Plain text data, claim deflate (no zlib headers)*/ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n"); @@ -281,7 +250,10 @@ do_coding_test (void) "X-Test-Options", "prefer-deflate-raw"); soup_session_send_message (session, msgzlr); check_response (msgzlr, "deflate", "text/plain", EXPECT_DECODED); - check_msg_bodies (msg, msgzlr, "plain", "compressed"); + soup_assert_cmpmem (msg->response_body->data, + msg->response_body->length, + msgzlr->response_body->data, + msgzlr->response_body->length); /* Plain text data, claim deflate with server error */ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n"); @@ -290,7 +262,10 @@ do_coding_test (void) "X-Test-Options", "force-encode, prefer-deflate-raw"); soup_session_send_message (session, msgzlre); check_response (msgzlre, "deflate", "text/plain", EXPECT_NOT_DECODED); - check_msg_bodies (msg, msgzlre, "plain", "mis-encoded"); + soup_assert_cmpmem (msg->response_body->data, + msg->response_body->length, + msgzlre->response_body->data, + msgzlre->response_body->length); g_object_unref (msg); g_object_unref (msgzlre); @@ -314,12 +289,8 @@ read_finished (GObject *stream, GAsyncResult *result, gpointer user_data) *nread = g_input_stream_read_finish (G_INPUT_STREAM (stream), result, &error); - if (error) { - debug_printf (1, " Error reading: %s\n", - error->message); - g_error_free (error); - errors++; - } + g_assert_no_error (error); + g_clear_error (&error); } static GByteArray * @@ -338,11 +309,9 @@ do_single_coding_req_test (SoupRequestHTTP *reqh, data = g_byte_array_new (); stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error); - if (error) { - debug_printf (1, " Error sending request: %s\n", - error->message); + if (!stream) { + g_assert_no_error (error); g_error_free (error); - errors++; return data; } @@ -359,12 +328,8 @@ do_single_coding_req_test (SoupRequestHTTP *reqh, } while (nread > 0); soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error); - if (error) { - debug_printf (1, " error closing stream: %s\n", - error->message); - g_error_free (error); - errors++; - } + g_assert_no_error (error); + g_clear_error (&error); g_object_unref (stream); msg = soup_request_http_get_message (reqh); @@ -374,24 +339,6 @@ do_single_coding_req_test (SoupRequestHTTP *reqh, return data; } -static void -check_req_bodies (GByteArray *body1, - GByteArray *body2, - const char *msg1_type, - const char *msg2_type) -{ - if (body1->len != body2->len) { - debug_printf (1, " Message length mismatch: %lu (%s) vs %lu (%s)\n", - (gulong)body1->len, msg1_type, - (gulong)body2->len, msg2_type); - errors++; - } else if (memcmp (body1->data, body2->data, body1->len) != 0) { - debug_printf (1, " Message data mismatch (%s/%s)\n", - msg1_type, msg2_type); - errors++; - } -} - static void do_coding_req_test (void) { @@ -419,7 +366,8 @@ do_coding_req_test (void) soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); reqh = soup_session_request_http_uri (session, "GET", uri, NULL); cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED); - check_req_bodies (plain, cmp, "plain", "compressed"); + soup_assert_cmpmem (plain->data, plain->len, + cmp->data, cmp->len); g_byte_array_free (cmp, TRUE); g_object_unref (reqh); @@ -431,7 +379,8 @@ do_coding_req_test (void) "X-Test-Options", "trailing-junk"); g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED); - check_req_bodies (plain, cmp, "plain", "compressed w/ junk"); + soup_assert_cmpmem (plain->data, plain->len, + cmp->data, cmp->len); g_byte_array_free (cmp, TRUE); g_object_unref (reqh); @@ -448,7 +397,8 @@ do_coding_req_test (void) * from what the server sent... which happens to be the * uncompressed data. */ - check_req_bodies (plain, cmp, "plain", "mis-encoded"); + soup_assert_cmpmem (plain->data, plain->len, + cmp->data, cmp->len); g_byte_array_free (cmp, TRUE); g_object_unref (reqh); @@ -460,7 +410,8 @@ do_coding_req_test (void) "X-Test-Options", "prefer-deflate-zlib"); g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); - check_req_bodies (plain, cmp, "plain", "compressed"); + soup_assert_cmpmem (plain->data, plain->len, + cmp->data, cmp->len); g_byte_array_free (cmp, TRUE); g_object_unref (reqh); @@ -472,7 +423,8 @@ do_coding_req_test (void) "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); - check_req_bodies (plain, cmp, "plain", "compressed w/ junk"); + soup_assert_cmpmem (plain->data, plain->len, + cmp->data, cmp->len); g_byte_array_free (cmp, TRUE); g_object_unref (reqh); @@ -484,7 +436,8 @@ do_coding_req_test (void) "X-Test-Options", "force-encode, prefer-deflate-zlib"); g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED); - check_req_bodies (plain, cmp, "plain", "mis-encoded"); + soup_assert_cmpmem (plain->data, plain->len, + cmp->data, cmp->len); g_byte_array_free (cmp, TRUE); g_object_unref (reqh); @@ -496,7 +449,8 @@ do_coding_req_test (void) "X-Test-Options", "prefer-deflate-raw"); g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); - check_req_bodies (plain, cmp, "plain", "compressed"); + soup_assert_cmpmem (plain->data, plain->len, + cmp->data, cmp->len); g_byte_array_free (cmp, TRUE); g_object_unref (reqh); @@ -508,7 +462,8 @@ do_coding_req_test (void) "X-Test-Options", "force-encode, prefer-deflate-raw"); g_object_unref (msg); cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED); - check_req_bodies (plain, cmp, "plain", "mis-encoded"); + soup_assert_cmpmem (plain->data, plain->len, + cmp->data, cmp->len); g_byte_array_free (cmp, TRUE); g_object_unref (reqh); @@ -561,6 +516,8 @@ do_coding_empty_test (void) int main (int argc, char **argv) { + int ret; + test_init (argc, argv, NULL); server = soup_test_server_new (TRUE); @@ -568,13 +525,15 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); - do_coding_test (); - do_coding_req_test (); - do_coding_empty_test (); + g_test_add_func ("/coding/message", do_coding_test); + g_test_add_func ("/coding/request", do_coding_req_test); + g_test_add_func ("/coding/empty", do_coding_empty_test); + + ret = g_test_run (); soup_uri_free (base_uri); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/connection-test.c b/tests/connection-test.c index fd7179f2..3dd2cae5 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -174,21 +174,14 @@ do_content_length_framing_test (void) request_uri = soup_uri_new_with_base (base_uri, "/content-length/long"); msg = soup_message_new_from_uri ("GET", request_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } else { - declared_length = soup_message_headers_get_content_length (msg->response_headers); - debug_printf (2, " Content-Length: %lu, body: %s\n", - (gulong)declared_length, msg->response_body->data); - if (msg->response_body->length >= declared_length) { - debug_printf (1, " Body length %lu >= declared length %lu\n", - (gulong)msg->response_body->length, - (gulong)declared_length); - errors++; - } - } + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + declared_length = soup_message_headers_get_content_length (msg->response_headers); + debug_printf (2, " Content-Length: %lu, body: %s\n", + (gulong)declared_length, msg->response_body->data); + g_assert_cmpint (msg->response_body->length, <, declared_length); + soup_uri_free (request_uri); g_object_unref (msg); @@ -196,21 +189,12 @@ do_content_length_framing_test (void) request_uri = soup_uri_new_with_base (base_uri, "/content-length/noclose"); msg = soup_message_new_from_uri ("GET", request_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } else { - declared_length = soup_message_headers_get_content_length (msg->response_headers); - debug_printf (2, " Content-Length: %lu, body: %s\n", - (gulong)declared_length, msg->response_body->data); - if (msg->response_body->length != declared_length) { - debug_printf (1, " Body length %lu != declared length %lu\n", - (gulong)msg->response_body->length, - (gulong)declared_length); - errors++; - } - } + + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + declared_length = soup_message_headers_get_content_length (msg->response_headers); + g_assert_cmpint (msg->response_body->length, ==, declared_length); + soup_uri_free (request_uri); g_object_unref (msg); @@ -234,12 +218,11 @@ request_started_socket_collector (SoupSession *session, SoupMessage *msg, * two consecutive sockets. */ sockets[i] = g_object_ref (socket); - return; + break; } } - debug_printf (1, " socket queue overflowed!\n"); - errors++; + soup_test_assert (i < 4, "socket queue overflowed"); } static void @@ -259,14 +242,10 @@ do_timeout_test_for_session (SoupSession *session) msg = soup_message_new_from_uri ("GET", timeout_uri); soup_uri_free (timeout_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + if (sockets[1]) { - debug_printf (1, " Message was retried??\n"); - errors++; + soup_test_assert (sockets[1] == NULL, "Message was retried"); sockets[1] = sockets[2] = sockets[3] = NULL; } g_object_unref (msg); @@ -274,24 +253,16 @@ do_timeout_test_for_session (SoupSession *session) debug_printf (1, " Second message\n"); msg = soup_message_new_from_uri ("GET", base_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - if (sockets[1] != sockets[0]) { - debug_printf (1, " Message was not retried on existing connection\n"); - errors++; - } else if (!sockets[2]) { - debug_printf (1, " Message was not retried after disconnect\n"); - errors++; - } else if (sockets[2] == sockets[1]) { - debug_printf (1, " Message was retried on closed connection??\n"); - errors++; - } else if (sockets[3]) { - debug_printf (1, " Message was retried again??\n"); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + soup_test_assert (sockets[1] == sockets[0], + "Message was not retried on existing connection"); + soup_test_assert (sockets[2] != NULL, + "Message was not retried after disconnect"); + soup_test_assert (sockets[2] != sockets[1], + "Message was retried on closed connection"); + soup_test_assert (sockets[3] == NULL, + "Message was retried again"); g_object_unref (msg); for (i = 0; sockets[i]; i++) @@ -319,33 +290,26 @@ do_timeout_req_test_for_session (SoupSession *session) soup_uri_free (timeout_uri); stream = soup_test_request_send (req, NULL, 0, &error); - if (!stream) { - debug_printf (1, " Unexpected error on send: %s\n", - error->message); - errors++; + if (error) { + g_assert_no_error (error); g_clear_error (&error); } else { soup_test_request_read_all (req, stream, NULL, &error); if (error) { - debug_printf (1, " Unexpected error on read: %s\n", - error->message); - errors++; + g_assert_no_error (error); g_clear_error (&error); } soup_test_request_close_stream (req, stream, NULL, &error); if (error) { - debug_printf (1, " Unexpected error on close: %s\n", - error->message); - errors++; + g_assert_no_error (error); g_clear_error (&error); } g_object_unref (stream); } if (sockets[1]) { - debug_printf (1, " Message was retried??\n"); - errors++; + soup_test_assert (sockets[1] == NULL, "Message was retried"); sockets[1] = sockets[2] = sockets[3] = NULL; } g_object_unref (req); @@ -354,41 +318,29 @@ do_timeout_req_test_for_session (SoupSession *session) req = soup_session_request_uri (session, base_uri, NULL); stream = soup_test_request_send (req, NULL, 0, &error); - if (!stream) { - debug_printf (1, " Unexpected error on send: %s\n", - error->message); - errors++; + if (error) { + g_assert_no_error (error); g_clear_error (&error); } else { soup_test_request_close_stream (req, stream, NULL, &error); if (error) { - debug_printf (1, " Unexpected error on close: %s\n", - error->message); - errors++; + g_assert_no_error (error); g_clear_error (&error); } g_object_unref (stream); } msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (req)); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - if (sockets[1] != sockets[0]) { - debug_printf (1, " Message was not retried on existing connection\n"); - errors++; - } else if (!sockets[2]) { - debug_printf (1, " Message was not retried after disconnect\n"); - errors++; - } else if (sockets[2] == sockets[1]) { - debug_printf (1, " Message was retried on closed connection??\n"); - errors++; - } else if (sockets[3]) { - debug_printf (1, " Message was retried again??\n"); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + + soup_test_assert (sockets[1] == sockets[0], + "Message was not retried on existing connection"); + soup_test_assert (sockets[2] != NULL, + "Message was not retried after disconnect"); + soup_test_assert (sockets[2] != sockets[1], + "Message was retried on closed connection"); + soup_test_assert (sockets[3] == NULL, + "Message was retried again"); g_object_unref (msg); g_object_unref (req); @@ -486,11 +438,7 @@ do_max_conns_test_for_session (SoupSession *session) } g_main_loop_run (max_conns_loop); - if (msgs_done != MAX_CONNS) { - debug_printf (1, " Queued %d connections out of max %d?", - msgs_done, MAX_CONNS); - errors++; - } + g_assert_cmpint (msgs_done, ==, MAX_CONNS); g_signal_handlers_disconnect_by_func (session, max_conns_request_started, NULL); msgs_done = 0; @@ -500,14 +448,8 @@ do_max_conns_test_for_session (SoupSession *session) quit_loop_timeout = g_timeout_add (1000, quit_loop, NULL); g_main_loop_run (max_conns_loop); - for (i = 0; i < TEST_CONNS; i++) { - if (!SOUP_STATUS_IS_SUCCESSFUL (msgs[i]->status_code)) { - debug_printf (1, " Message %d failed? %d %s\n", - i, msgs[i]->status_code, - msgs[i]->reason_phrase ? msgs[i]->reason_phrase : "-"); - errors++; - } - } + for (i = 0; i < TEST_CONNS; i++) + soup_test_assert_message_status (msgs[i], SOUP_STATUS_OK); if (msgs_done != TEST_CONNS) { /* Clean up so we don't get a spurious "Leaked @@ -565,10 +507,7 @@ np_request_unqueued (SoupSession *session, SoupMessage *msg, { SoupSocket *socket = *(SoupSocket **)user_data; - if (soup_socket_is_connected (socket)) { - debug_printf (1, " socket is still connected\n"); - errors++; - } + g_assert_false (soup_socket_is_connected (socket)); } static void @@ -604,11 +543,8 @@ do_non_persistent_test_for_session (SoupSession *session) g_main_loop_run (loop); g_main_loop_unref (loop); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); g_object_unref (socket); } @@ -645,14 +581,9 @@ do_non_idempotent_test_for_session (SoupSession *session) debug_printf (2, " GET\n"); msg = soup_message_new_from_uri ("GET", base_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); if (sockets[1]) { - debug_printf (1, " Message was retried??\n"); - errors++; + soup_test_assert (sockets[1] == NULL, "Message was retried"); sockets[1] = sockets[2] = sockets[3] = NULL; } g_object_unref (msg); @@ -660,19 +591,12 @@ do_non_idempotent_test_for_session (SoupSession *session) debug_printf (2, " POST\n"); msg = soup_message_new_from_uri ("POST", base_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - if (sockets[1] == sockets[0]) { - debug_printf (1, " Message was sent on existing connection!\n"); - errors++; - } - if (sockets[2]) { - debug_printf (1, " Too many connections used...\n"); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + soup_test_assert (sockets[1] != sockets[0], + "Message was sent on existing connection"); + soup_test_assert (sockets[2] == NULL, + "Too many connections used"); + g_object_unref (msg); for (i = 0; sockets[i]; i++) @@ -726,15 +650,11 @@ connection_state_changed (GObject *object, GParamSpec *param, SoupConnectionState new_state; g_object_get (object, "state", &new_state, NULL); - if (state_transitions[*state] != new_state) { - debug_printf (1, " Unexpected transition: %s -> %s\n", - state_names[*state], state_names[new_state]); - errors++; - } else { - debug_printf (2, " %s -> %s\n", - state_names[*state], state_names[new_state]); - } - + debug_printf (2, " %s -> %s\n", + state_names[*state], state_names[new_state]); + soup_test_assert (state_transitions[*state] == new_state, + "Unexpected transition: %s -> %s\n", + state_names[*state], state_names[new_state]); *state = new_state; } @@ -745,11 +665,7 @@ connection_created (SoupSession *session, GObject *conn, SoupConnectionState *state = user_data; g_object_get (conn, "state", state, NULL); - if (*state != SOUP_CONNECTION_NEW) { - debug_printf (1, " Unexpected initial state: %d\n", - *state); - errors++; - } + g_assert_cmpint (*state, ==, SOUP_CONNECTION_NEW); g_signal_connect (conn, "notify::state", G_CALLBACK (connection_state_changed), @@ -763,11 +679,7 @@ do_one_connection_state_test (SoupSession *session, const char *uri) msg = soup_message_new ("GET", uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); soup_session_abort (session); } @@ -854,21 +766,12 @@ network_event (SoupMessage *msg, GSocketClientEvent event, { const char **events = user_data; - if (!**events) { - debug_printf (1, " Unexpected event: %s\n", - event_names[event]); - errors++; - } else { - if (**events == event_abbrevs[event]) - debug_printf (2, " %s\n", event_names[event]); - else { - debug_printf (1, " Unexpected event: %s (expected %s)\n", - event_names[event], - event_name_from_abbrev (**events)); - errors++; - } - *events = *events + 1; - } + debug_printf (2, " %s\n", event_name_from_abbrev (**events)); + soup_test_assert (**events == event_abbrevs[event], + "Unexpected event: %s (expected %s)\n", + event_names[event], + event_name_from_abbrev (**events)); + *events = *events + 1; } static void @@ -882,18 +785,14 @@ do_one_connection_event_test (SoupSession *session, const char *uri, G_CALLBACK (network_event), &events); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } else { - while (*events) { - debug_printf (1, " Expected %s\n", - event_name_from_abbrev (*events)); - events++; - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + while (*events) { + soup_test_assert (!*events, + "Expected %s", + event_name_from_abbrev (*events)); + events++; } + g_object_unref (msg); soup_session_abort (session); } @@ -951,6 +850,8 @@ do_connection_event_test (void) int main (int argc, char **argv) { + int ret; + test_init (argc, argv, NULL); #ifdef HAVE_APACHE apache_init (); @@ -961,19 +862,21 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); - do_content_length_framing_test (); - do_persistent_connection_timeout_test (); - do_max_conns_test (); - do_non_persistent_connection_test (); - do_non_idempotent_connection_test (); + g_test_add_func ("/connection/content-length-framing", do_content_length_framing_test); + g_test_add_func ("/connection/persistent-connection-timeout", do_persistent_connection_timeout_test); + g_test_add_func ("/connection/max-conns", do_max_conns_test); + g_test_add_func ("/connection/non-persistent", do_non_persistent_connection_test); + g_test_add_func ("/connection/non-idempotent", do_non_idempotent_connection_test); #ifdef HAVE_APACHE - do_connection_state_test (); - do_connection_event_test (); + g_test_add_func ("/connection/state", do_connection_state_test); + g_test_add_func ("/connection/event", do_connection_event_test); #endif + ret = g_test_run (); + soup_uri_free (base_uri); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/context-test.c b/tests/context-test.c index 97cd2c0c..7fe3d60b 100644 --- a/tests/context-test.c +++ b/tests/context-test.c @@ -84,9 +84,11 @@ static GMutex test1_mutex; static GMainLoop *test1_loop; static void -do_test1 (int n, gboolean use_thread_context) +do_test1 (gconstpointer data) { - debug_printf (1, "\nTest %d: blocking the main thread does not block other thread\n", n); + gboolean use_thread_context = GPOINTER_TO_INT (data); + + debug_printf (1, "\nBlocking the main thread does not block other thread\n"); if (use_thread_context) debug_printf (1, "(Using g_main_context_push_thread_default())\n"); else @@ -111,9 +113,8 @@ idle_start_test1_thread (gpointer use_thread_context) if (g_cond_wait_until (&test1_cond, &test1_mutex, time)) g_thread_join (thread); else { - debug_printf (1, " timeout!\n"); + soup_test_assert (FALSE, "timeout"); g_thread_unref (thread); - errors++; } g_mutex_unlock (&test1_mutex); @@ -158,11 +159,7 @@ test1_thread (gpointer use_thread_context) debug_printf (1, " send_message\n"); msg = soup_message_new ("GET", uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " unexpected status: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); debug_printf (1, " queue_message\n"); @@ -172,11 +169,7 @@ test1_thread (gpointer use_thread_context) soup_session_queue_message (session, msg, test1_finished, loop); g_main_loop_run (loop); g_main_loop_unref (loop); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " unexpected status: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -196,15 +189,16 @@ test1_thread (gpointer use_thread_context) static gboolean idle_test2_fail (gpointer user_data); static void -do_test2 (int n, gboolean use_thread_context) +do_test2 (gconstpointer data) { + gboolean use_thread_context = GPOINTER_TO_INT (data); guint idle; GMainContext *async_context; SoupSession *session; char *uri; SoupMessage *msg; - debug_printf (1, "\nTest %d: a session with its own context is independent of the main loop.\n", n); + debug_printf (1, "\nA session with its own context is independent of the main loop.\n"); if (use_thread_context) debug_printf (1, "(Using g_main_context_push_thread_default())\n"); else @@ -230,11 +224,7 @@ do_test2 (int n, gboolean use_thread_context) debug_printf (1, " send_message\n"); msg = soup_message_new ("GET", uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " unexpected status: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -249,8 +239,7 @@ do_test2 (int n, gboolean use_thread_context) static gboolean idle_test2_fail (gpointer user_data) { - debug_printf (1, " idle ran!\n"); - errors++; + soup_test_assert (FALSE, "idle ran"); return FALSE; } @@ -279,14 +268,14 @@ multi_msg_finished (SoupSession *session, SoupMessage *msg, gpointer user_data) } static void -do_multicontext_test (int n) +do_multicontext_test (void) { SoupSession *session; SoupMessage *msg1, *msg2; GMainContext *context1, *context2; GMainLoop *loop1, *loop2; - debug_printf (1, "\nTest %d: Using multiple async contexts\n", n); + debug_printf (1, "\nUsing multiple async contexts\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, @@ -318,36 +307,26 @@ do_multicontext_test (int n) g_main_loop_run (loop1); g_main_context_pop_thread_default (context1); - if (!g_object_get_data (G_OBJECT (msg1), "started")) { - debug_printf (1, " msg1 not started??\n"); - errors++; - } - if (g_object_get_data (G_OBJECT (msg2), "started")) { - debug_printf (1, " msg2 started while loop1 was running!\n"); - errors++; - } + if (!g_object_get_data (G_OBJECT (msg1), "started")) + soup_test_assert (FALSE, "msg1 not started"); + if (g_object_get_data (G_OBJECT (msg2), "started")) + soup_test_assert (FALSE, "msg2 started while loop1 was running"); g_main_context_push_thread_default (context2); g_main_loop_run (loop2); g_main_context_pop_thread_default (context2); - if (g_object_get_data (G_OBJECT (msg1), "finished")) { - debug_printf (1, " msg1 finished while loop2 was running!\n"); - errors++; - } - if (!g_object_get_data (G_OBJECT (msg2), "finished")) { - debug_printf (1, " msg2 not finished??\n"); - errors++; - } + if (g_object_get_data (G_OBJECT (msg1), "finished")) + soup_test_assert (FALSE, "msg1 finished while loop2 was running"); + if (!g_object_get_data (G_OBJECT (msg2), "finished")) + soup_test_assert (FALSE, "msg2 not finished"); g_main_context_push_thread_default (context1); g_main_loop_run (loop1); g_main_context_pop_thread_default (context1); - if (!g_object_get_data (G_OBJECT (msg1), "finished")) { - debug_printf (1, " msg1 not finished??\n"); - errors++; - } + if (!g_object_get_data (G_OBJECT (msg1), "finished")) + soup_test_assert (FALSE, "msg1 not finished"); g_object_unref (msg1); g_object_unref (msg2); @@ -364,6 +343,7 @@ int main (int argc, char **argv) { SoupServer *server; + int ret; test_init (argc, argv, NULL); @@ -372,15 +352,17 @@ main (int argc, char **argv) base_uri = g_strdup_printf ("http://127.0.0.1:%u/", soup_server_get_port (server)); - do_test1 (1, FALSE); - do_test1 (2, TRUE); - do_test2 (3, FALSE); - do_test2 (4, TRUE); - do_multicontext_test (5); + g_test_add_data_func ("/context/blocking/explicit", GINT_TO_POINTER (FALSE), do_test1); + g_test_add_data_func ("/context/blocking/thread-default", GINT_TO_POINTER (TRUE), do_test1); + g_test_add_data_func ("/context/nested/explicit", GINT_TO_POINTER (FALSE), do_test2); + g_test_add_data_func ("/context/nested/thread-default", GINT_TO_POINTER (TRUE), do_test2); + g_test_add_func ("/context/multiple", do_multicontext_test); + + ret = g_test_run (); g_free (base_uri); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/continue-test.c b/tests/continue-test.c index 7cc9f692..42138ce2 100644 --- a/tests/continue-test.c +++ b/tests/continue-test.c @@ -106,17 +106,13 @@ do_message (const char *path, gboolean long_body, while ((expected_event = va_arg (ap, const char *))) { if (!events) { - debug_printf (1, " Expected '%s', got end of list\n", - expected_event); - errors++; + soup_test_assert (events != NULL, + "Expected '%s', got end of list", + expected_event); continue; } else { actual_event = events->data; - if (strcmp (expected_event, actual_event) != 0) { - debug_printf (1, " Expected '%s', got '%s'\n", - expected_event, actual_event); - errors++; - } + g_assert_cmpstr (expected_event, ==, actual_event); events = g_slist_delete_link (events, events); } @@ -134,10 +130,10 @@ do_message (const char *path, gboolean long_body, if (expected_status != -1 && actual_status != -1 && expected_status != actual_status) { - debug_printf (1, " Expected status '%s', got '%s'\n", - soup_status_get_phrase (expected_status), - soup_status_get_phrase (actual_status)); - errors++; + soup_test_assert (expected_status == actual_status, + "Expected status '%s', got '%s'", + soup_status_get_phrase (expected_status), + soup_status_get_phrase (actual_status)); } g_free (actual_event); @@ -145,8 +141,8 @@ do_message (const char *path, gboolean long_body, va_end (ap); while (events) { actual_event = events->data; - debug_printf (1, " Expected to be done, got '%s'\n", actual_event); - errors++; + soup_test_assert (events == NULL, + "Expected to be done, got '%s'", actual_event); events = g_slist_delete_link (events, events); if (!strcmp (actual_event, "server-wrote_headers") || @@ -434,15 +430,19 @@ int main (int argc, char **argv) { SoupServer *server; + int ret; test_init (argc, argv, NULL); server = setup_server (); port = soup_server_get_port (server); - run_tests (); + g_test_add_func ("/continue", run_tests); + + ret = g_test_run (); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + + return ret; } diff --git a/tests/cookies-test.c b/tests/cookies-test.c index 58f8052e..b36b14af 100644 --- a/tests/cookies-test.c +++ b/tests/cookies-test.c @@ -83,13 +83,7 @@ do_cookies_accept_policy_test (void) g_object_unref (msg); l = soup_cookie_jar_all_cookies (jar); - if (g_slist_length (l) < validResults[i].n_cookies) { - debug_printf (1, " accepted less cookies than it should have\n"); - errors++; - } else if (g_slist_length (l) > validResults[i].n_cookies) { - debug_printf (1, " accepted more cookies than it should have\n"); - errors++; - } + g_assert_cmpint (g_slist_length (l), ==, validResults[i].n_cookies); for (p = l; p; p = p->next) { soup_cookie_jar_delete_cookie (jar, p->data); @@ -146,56 +140,28 @@ do_cookies_parsing_test (void) if (!strcmp (soup_cookie_get_name (cookie), "one")) { got1 = TRUE; - if (!soup_cookie_get_http_only (cookie)) { - debug_printf (1, " cookie 1 is not HttpOnly!\n"); - errors++; - } - if (!soup_cookie_get_expires (cookie)) { - debug_printf (1, " cookie 1 did not fully parse!\n"); - errors++; - } + g_assert_true (soup_cookie_get_http_only (cookie)); + g_assert_true (soup_cookie_get_expires (cookie) != NULL); } else if (!strcmp (soup_cookie_get_name (cookie), "two")) { got2 = TRUE; - if (!soup_cookie_get_http_only (cookie)) { - debug_printf (1, " cookie 2 is not HttpOnly!\n"); - errors++; - } - if (!soup_cookie_get_expires (cookie)) { - debug_printf (1, " cookie 3 did not fully parse!\n"); - errors++; - } + g_assert_true (soup_cookie_get_http_only (cookie)); + g_assert_true (soup_cookie_get_expires (cookie) != NULL); } else if (!strcmp (soup_cookie_get_name (cookie), "three")) { got3 = TRUE; - if (!soup_cookie_get_http_only (cookie)) { - debug_printf (1, " cookie 3 is not HttpOnly!\n"); - errors++; - } - if (!soup_cookie_get_expires (cookie)) { - debug_printf (1, " cookie 3 did not fully parse!\n"); - errors++; - } + g_assert_true (soup_cookie_get_http_only (cookie)); + g_assert_true (soup_cookie_get_expires (cookie) != NULL); } else { - debug_printf (1, " got unexpected cookie '%s'\n", - soup_cookie_get_name (cookie)); - errors++; + soup_test_assert (FALSE, "got unexpected cookie '%s'", + soup_cookie_get_name (cookie)); } soup_cookie_free (cookie); } g_slist_free (cookies); - if (!got1) { - debug_printf (1, " didn't get cookie 1\n"); - errors++; - } - if (!got2) { - debug_printf (1, " didn't get cookie 2\n"); - errors++; - } - if (!got3) { - debug_printf (1, " didn't get cookie 3\n"); - errors++; - } + g_assert_true (got1); + g_assert_true (got2); + g_assert_true (got3); soup_test_session_abort_unref (session); } @@ -203,6 +169,8 @@ do_cookies_parsing_test (void) int main (int argc, char **argv) { + int ret; + test_init (argc, argv, NULL); server = soup_test_server_new (TRUE); @@ -212,14 +180,15 @@ main (int argc, char **argv) soup_uri_set_port (first_party_uri, soup_server_get_port (server)); soup_uri_set_port (third_party_uri, soup_server_get_port (server)); - do_cookies_accept_policy_test (); - do_cookies_parsing_test (); + g_test_add_func ("/cookies/accept-policy", do_cookies_accept_policy_test); + g_test_add_func ("/cookies/parsing", do_cookies_parsing_test); + + ret = g_test_run (); soup_uri_free (first_party_uri); soup_uri_free (third_party_uri); soup_test_server_quit_unref (server); test_cleanup (); - - return errors != 0; + return ret; } diff --git a/tests/date.c b/tests/date.c index 54a59f2b..6b0ff9bb 100644 --- a/tests/date.c +++ b/tests/date.c @@ -5,7 +5,7 @@ #include "test-utils.h" -static gboolean check_ok (const char *strdate, SoupDate *date); +static void check_ok (gconstpointer data); static SoupDate * make_date (const char *strdate) @@ -24,10 +24,12 @@ make_date (const char *strdate) return date; } -static const struct { +typedef struct { SoupDateFormat format; const char *date; -} good_dates[] = { +} GoodDate; + +static const GoodDate good_dates[] = { { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT" }, { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT" }, { SOUP_DATE_RFC2822, "Sat, 6 Nov 2004 08:09:07 -0430" }, @@ -37,22 +39,21 @@ static const struct { }; static void -check_good (SoupDateFormat format, const char *strdate) +check_good (gconstpointer data) { + GoodDate *good = (GoodDate *)data; SoupDate *date; char *strdate2; - date = make_date (strdate); - g_assert (date); - strdate2 = soup_date_to_string (date, format); - if (!check_ok (strdate, date)) - return; + check_ok (good->date); - if (strcmp (strdate, strdate2) != 0) { - debug_printf (1, " restringification failed: '%s' -> '%s'\n", - strdate, strdate2); - errors++; - } + date = make_date (good->date); + strdate2 = soup_date_to_string (date, good->format); + soup_date_free (date); + + soup_test_assert (strcmp (good->date, strdate2) == 0, + "restringification failed: '%s' -> '%s'\n", + good->date, strdate2); g_free (strdate2); } @@ -114,30 +115,42 @@ static const char *ok_dates[] = { "Sat, 06 Nov 2004 08:09:7 GMT" }; +static void +check_ok (gconstpointer data) +{ + const char *strdate = data; + SoupDate *date; + + date = make_date (strdate); + if (!date) { + g_assert_true (date != NULL); + return; + } + + g_assert_cmpint (date->year, ==, 2004); + g_assert_cmpint (date->month, ==, 11); + g_assert_cmpint (date->day, ==, 6); + g_assert_cmpint (date->hour, ==, 8); + g_assert_cmpint (date->minute, ==, 9); + g_assert_cmpint (date->second, ==, 7); +} + #define TIME_T 1099728547L #define TIME_T_STRING "1099728547" -static gboolean -check_ok (const char *strdate, SoupDate *date) +static void +check_ok_time_t (void) { - debug_printf (2, "%s\n", strdate); + SoupDate *date; - if (date && - date->year == 2004 && date->month == 11 && date->day == 6 && - date->hour == 8 && date->minute == 9 && date->second == 7) { - soup_date_free (date); - return TRUE; - } + date = soup_date_new_from_time_t (TIME_T); - debug_printf (1, " date parsing failed for '%s'.\n", strdate); - if (date) { - debug_printf (1, " got: %d %d %d - %d %d %d\n\n", - date->year, date->month, date->day, - date->hour, date->minute, date->second); - soup_date_free (date); - } - errors++; - return FALSE; + g_assert_cmpint (date->year, ==, 2004); + g_assert_cmpint (date->month, ==, 11); + g_assert_cmpint (date->day, ==, 6); + g_assert_cmpint (date->hour, ==, 8); + g_assert_cmpint (date->minute, ==, 9); + g_assert_cmpint (date->second, ==, 7); } static const char *bad_dates[] = { @@ -177,25 +190,26 @@ static const char *bad_dates[] = { }; static void -check_bad (const char *strdate, SoupDate *date) +check_bad (gconstpointer data) { - debug_printf (2, "%s\n", strdate); - - if (!date) - return; - errors++; + const char *strdate = data; + SoupDate *date; - debug_printf (1, " date parsing succeeded for '%s'!\n", strdate); - debug_printf (1, " got: %d %d %d - %d %d %d\n\n", - date->year, date->month, date->day, - date->hour, date->minute, date->second); - soup_date_free (date); + date = make_date (strdate); + soup_test_assert (date == NULL, + "date parsing succeeded for '%s': %d %d %d - %d %d %d", + strdate, + date->year, date->month, date->day, + date->hour, date->minute, date->second); + g_clear_pointer (&date, soup_date_free); } -static const struct conversion { +typedef struct { const char *source; const char *http, *cookie, *rfc2822, *compact, *full, *xmlrpc; -} conversions[] = { +} DateConversion; + +static const DateConversion conversions[] = { /* SOUP_DATE_HTTP */ { "Sat, 06 Nov 2004 08:09:07 GMT", @@ -288,71 +302,40 @@ static const struct conversion { }; static void -check_conversion (const struct conversion *conv) +check_conversion (gconstpointer data) { + const DateConversion *conv = data; SoupDate *date; char *str; - debug_printf (2, "%s\n", conv->source); date = make_date (conv->source); if (!date) { - debug_printf (1, " date parsing failed for '%s'.\n", conv->source); - errors++; + soup_test_assert (FALSE, "date parsing failed for '%s'.", conv->source); return; } str = soup_date_to_string (date, SOUP_DATE_HTTP); - if (!str || strcmp (str, conv->http) != 0) { - debug_printf (1, " conversion of '%s' to HTTP failed:\n" - " wanted: %s\n got: %s\n", - conv->source, conv->http, str ? str : "(null)"); - errors++; - } + g_assert_cmpstr (str, ==, conv->http); g_free (str); str = soup_date_to_string (date, SOUP_DATE_COOKIE); - if (!str || strcmp (str, conv->cookie) != 0) { - debug_printf (1, " conversion of '%s' to COOKIE failed:\n" - " wanted: %s\n got: %s\n", - conv->source, conv->cookie, str ? str : "(null)"); - errors++; - } + g_assert_cmpstr (str, ==, conv->cookie); g_free (str); str = soup_date_to_string (date, SOUP_DATE_RFC2822); - if (!str || strcmp (str, conv->rfc2822) != 0) { - debug_printf (1, " conversion of '%s' to RFC2822 failed:\n" - " wanted: %s\n got: %s\n", - conv->source, conv->rfc2822, str ? str : "(null)"); - errors++; - } + g_assert_cmpstr (str, ==, conv->rfc2822); g_free (str); str = soup_date_to_string (date, SOUP_DATE_ISO8601_COMPACT); - if (!str || strcmp (str, conv->compact) != 0) { - debug_printf (1, " conversion of '%s' to COMPACT failed:\n" - " wanted: %s\n got: %s\n", - conv->source, conv->compact, str ? str : "(null)"); - errors++; - } + g_assert_cmpstr (str, ==, conv->compact); g_free (str); str = soup_date_to_string (date, SOUP_DATE_ISO8601_FULL); - if (!str || strcmp (str, conv->full) != 0) { - debug_printf (1, " conversion of '%s' to FULL failed:\n" - " wanted: %s\n got: %s\n", - conv->source, conv->full, str ? str : "(null)"); - errors++; - } + g_assert_cmpstr (str, ==, conv->full); g_free (str); str = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC); - if (!str || strcmp (str, conv->xmlrpc) != 0) { - debug_printf (1, " conversion of '%s' to XMLRPC failed:\n" - " wanted: %s\n got: %s\n", - conv->source, conv->xmlrpc, str ? str : "(null)"); - errors++; - } + g_assert_cmpstr (str, ==, conv->xmlrpc); g_free (str); soup_date_free (date); @@ -361,27 +344,38 @@ check_conversion (const struct conversion *conv) int main (int argc, char **argv) { - int i; + int i, ret; + char *path; test_init (argc, argv, NULL); - debug_printf (1, "Good dates:\n"); - for (i = 0; i < G_N_ELEMENTS (good_dates); i++) - check_good (good_dates[i].format, good_dates[i].date); + for (i = 0; i < G_N_ELEMENTS (good_dates); i++) { + path = g_strdup_printf ("/date/good/%s", good_dates[i].date); + g_test_add_data_func (path, &good_dates[i], check_good); + g_free (path); + } - debug_printf (1, "\nOK dates:\n"); - for (i = 0; i < G_N_ELEMENTS (ok_dates); i++) - check_ok (ok_dates[i], make_date (ok_dates[i])); - check_ok (TIME_T_STRING, soup_date_new_from_time_t (TIME_T)); + for (i = 0; i < G_N_ELEMENTS (ok_dates); i++) { + path = g_strdup_printf ("/date/ok/%s", ok_dates[i]); + g_test_add_data_func (path, ok_dates[i], check_ok); + g_free (path); + } + g_test_add_func ("/date/ok/" TIME_T_STRING, check_ok_time_t); + + for (i = 0; i < G_N_ELEMENTS (bad_dates); i++) { + path = g_strdup_printf ("/date/bad/%s", bad_dates[i]); + g_test_add_data_func (path, bad_dates[i], check_bad); + g_free (path); + } - debug_printf (1, "\nBad dates:\n"); - for (i = 0; i < G_N_ELEMENTS (bad_dates); i++) - check_bad (bad_dates[i], make_date (bad_dates[i])); + for (i = 0; i < G_N_ELEMENTS (conversions); i++) { + path = g_strdup_printf ("/date/conversions/%s", conversions[i].source); + g_test_add_data_func (path, &conversions[i], check_conversion); + g_free (path); + } - debug_printf (1, "\nConversions:\n"); - for (i = 0; i < G_N_ELEMENTS (conversions); i++) - check_conversion (&conversions[i] ); + ret = g_test_run (); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/forms-test.c b/tests/forms-test.c index cf8963c3..5a5db28b 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -43,6 +43,7 @@ do_hello_test (int n, gboolean extra, const char *uri) GPtrArray *args; char *title_arg = NULL, *name_arg = NULL; char *str_stdout = NULL; + GError *error = NULL; debug_printf (1, "%2d. '%s' '%s'%s: ", n * 2 + (extra ? 2 : 1), tests[n].title ? tests[n].title : "(null)", @@ -74,20 +75,12 @@ do_hello_test (int n, gboolean extra, const char *uri) if (g_spawn_sync (NULL, (char **)args->pdata, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, - &str_stdout, NULL, NULL, NULL)) { - if (str_stdout && !strcmp (str_stdout, tests[n].result)) - debug_printf (1, "OK!\n"); - else { - debug_printf (1, "WRONG!\n"); - debug_printf (1, " expected '%s', got '%s'\n", - tests[n].result, - str_stdout ? str_stdout : "(error)"); - errors++; - } + &str_stdout, NULL, NULL, &error)) { + g_assert_cmpstr (str_stdout, ==, tests[n].result); g_free (str_stdout); } else { - debug_printf (1, "ERROR!\n"); - errors++; + g_assert_no_error (error); + g_error_free (error); } g_ptr_array_free (args, TRUE); g_free (title_arg); @@ -95,7 +88,7 @@ do_hello_test (int n, gboolean extra, const char *uri) } static void -do_hello_tests (const char *uri) +do_hello_tests (gconstpointer uri) { int n; @@ -111,6 +104,7 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5) { GPtrArray *args; char *file_arg, *str_stdout; + GError *error = NULL; debug_printf (1, " via curl: "); @@ -131,18 +125,11 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5) G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &str_stdout, NULL, NULL, NULL)) { - if (str_stdout && !strcmp (str_stdout, md5)) - debug_printf (1, "OK!\n"); - else { - debug_printf (1, "WRONG!\n"); - debug_printf (1, " expected '%s', got '%s'\n", - md5, str_stdout ? str_stdout : "(error)"); - errors++; - } + g_assert_cmpstr (str_stdout, ==, md5); g_free (str_stdout); } else { - debug_printf (1, "ERROR!\n"); - errors++; + g_assert_no_error (error); + g_error_free (error); } g_ptr_array_free (args, TRUE); g_free (file_arg); @@ -178,23 +165,15 @@ do_md5_test_libsoup (const char *uri, const char *contents, session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, "ERROR: Unexpected status %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } else if (strcmp (msg->response_body->data, md5) != 0) { - debug_printf (1, "ERROR: Incorrect response: expected '%s' got '%s'\n", - md5, msg->response_body->data); - errors++; - } else - debug_printf (1, "OK!\n"); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_cmpstr (msg->response_body->data, ==, md5); g_object_unref (msg); soup_test_session_abort_unref (session); } static void -do_md5_tests (const char *uri) +do_md5_tests (gconstpointer uri) { char *contents, *md5; gsize length; @@ -203,9 +182,8 @@ do_md5_tests (const char *uri) debug_printf (1, "\nMD5 tests (POST, multipart/form-data)\n"); if (!g_file_get_contents (MD5_TEST_FILE, &contents, &length, &error)) { - debug_printf (1, " ERROR: Could not read " MD5_TEST_FILE ": %s\n", error->message); + g_assert_no_error (error); g_error_free (error); - errors++; return; } @@ -238,11 +216,7 @@ do_form_decode_test (void) tmp = g_strdup ("other"); value = g_hash_table_lookup (table, "foo"); - if (g_strcmp0 (value, "third") != 0) { - debug_printf (1, " ERROR: expected '%s', got '%s'\n", - "third", value ? value : "(null)"); - errors++; - } + g_assert_cmpstr (value, ==, "third"); g_free (tmp); g_hash_table_destroy (table); @@ -423,6 +397,7 @@ main (int argc, char **argv) SoupServer *server; guint port; char *uri_str; + int ret = 0; test_init (argc, argv, no_test_entry); @@ -437,14 +412,14 @@ main (int argc, char **argv) if (run_tests) { uri_str = g_strdup_printf ("http://127.0.0.1:%u/hello", port); - do_hello_tests (uri_str); - g_free (uri_str); + g_test_add_data_func_full ("/forms/hello", uri_str, do_hello_tests, g_free); uri_str = g_strdup_printf ("http://127.0.0.1:%u/md5", port); - do_md5_tests (uri_str); - g_free (uri_str); + g_test_add_data_func_full ("/forms/md5", uri_str, do_md5_tests, g_free); + + g_test_add_func ("/forms/decode", do_form_decode_test); - do_form_decode_test (); + ret = g_test_run (); } else { g_print ("Listening on port %d\n", port); g_main_loop_run (loop); @@ -455,7 +430,7 @@ main (int argc, char **argv) soup_test_server_quit_unref (server); if (run_tests) test_cleanup (); - return errors != 0; + return ret; } #else /* HAVE_CURL */ diff --git a/tests/header-parsing.c b/tests/header-parsing.c index b02bc980..5f99831f 100644 --- a/tests/header-parsing.c +++ b/tests/header-parsing.c @@ -717,18 +717,11 @@ static struct QValueTest { static const int num_qvaluetests = G_N_ELEMENTS (qvaluetests); static void -print_header (const char *name, const char *value, gpointer data) -{ - debug_printf (1, " '%s': '%s'\n", name, value); -} - -static gboolean check_headers (Header *headers, SoupMessageHeaders *hdrs) { GSList *header_names, *h; SoupMessageHeadersIter iter; const char *name, *value; - gboolean ok = TRUE; int i; header_names = NULL; @@ -740,34 +733,26 @@ check_headers (Header *headers, SoupMessageHeaders *hdrs) } for (i = 0, h = header_names; headers[i].name && h; i++, h = h->next) { - if (g_ascii_strcasecmp (h->data, headers[i].name) != 0) { - ok = FALSE; - break; - } + g_assert (g_ascii_strcasecmp (h->data, headers[i].name) == 0); + value = soup_message_headers_get_list (hdrs, headers[i].name); - if (g_strcmp0 (value, headers[i].value) != 0) { - ok = FALSE; - break; - } + g_assert_cmpstr (value, ==, headers[i].value); } /* If we have remaining fields to check, they should return NULL */ for (; headers[i].name; i++) { value = soup_message_headers_get_list (hdrs, headers[i].name); - if (value) { - ok = FALSE; - break; - } + g_assert_null (value); } - if (headers[i].name || h) - ok = FALSE; + g_assert_null (headers[i].name); + g_assert_null (h); + g_slist_free (header_names); - return ok; } static void do_request_tests (void) { - int i, len, h; + int i, len; char *method, *path; SoupHTTPVersion version; SoupMessageHeaders *headers; @@ -775,8 +760,6 @@ do_request_tests (void) debug_printf (1, "Request tests\n"); for (i = 0; i < num_reqtests; i++) { - gboolean ok = TRUE; - debug_printf (1, "%2d. %s (%s): ", i + 1, reqtests[i].description, soup_status_get_phrase (reqtests[i].status)); @@ -790,48 +773,13 @@ do_request_tests (void) status = soup_headers_parse_request (reqtests[i].request, len, headers, &method, &path, &version); + g_assert_cmpint (status, ==, reqtests[i].status); if (SOUP_STATUS_IS_SUCCESSFUL (status)) { - if ((reqtests[i].method && strcmp (reqtests[i].method, method) != 0) || !reqtests[i].method) - ok = FALSE; - if ((reqtests[i].path && strcmp (reqtests[i].path, path) != 0) || !reqtests[i].path) - ok = FALSE; - if (reqtests[i].version != version) - ok = FALSE; - - if (!check_headers (reqtests[i].headers, headers)) - ok = FALSE; - } else { - if (status != reqtests[i].status) - ok = FALSE; - } + g_assert_cmpstr (method, ==, reqtests[i].method); + g_assert_cmpstr (path, ==, reqtests[i].path); + g_assert_cmpint (version, ==, reqtests[i].version); - if (ok) - debug_printf (1, "OK!\n"); - else { - debug_printf (1, "BAD!\n"); - errors++; - if (reqtests[i].method) { - debug_printf (1, " expected: '%s' '%s' 'HTTP/1.%d'\n", - reqtests[i].method, - reqtests[i].path, - reqtests[i].version); - for (h = 0; reqtests[i].headers[h].name; h++) { - debug_printf (1, " '%s': '%s'\n", - reqtests[i].headers[h].name, - reqtests[i].headers[h].value); - } - } else { - debug_printf (1, " expected: %s\n", - soup_status_get_phrase (reqtests[i].status)); - } - if (method) { - debug_printf (1, " got: '%s' '%s' 'HTTP/1.%d'\n", - method, path, version); - soup_message_headers_foreach (headers, print_header, NULL); - } else { - debug_printf (1, " got: %s\n", - soup_status_get_phrase (status)); - } + check_headers (reqtests[i].headers, headers); } g_free (method); @@ -844,7 +792,7 @@ do_request_tests (void) static void do_response_tests (void) { - int i, len, h; + int i, len; guint status_code; char *reason_phrase; SoupHTTPVersion version; @@ -852,8 +800,6 @@ do_response_tests (void) debug_printf (1, "Response tests\n"); for (i = 0; i < num_resptests; i++) { - gboolean ok = TRUE; - debug_printf (1, "%2d. %s (%s): ", i + 1, resptests[i].description, resptests[i].reason_phrase ? "should parse" : "should NOT parse"); @@ -867,44 +813,13 @@ do_response_tests (void) if (soup_headers_parse_response (resptests[i].response, len, headers, &version, &status_code, &reason_phrase)) { - if (resptests[i].version != version) - ok = FALSE; - if (resptests[i].status_code != status_code) - ok = FALSE; - if ((resptests[i].reason_phrase && strcmp (resptests[i].reason_phrase, reason_phrase) != 0) || !resptests[i].reason_phrase) - ok = FALSE; - - if (!check_headers (resptests[i].headers, headers)) - ok = FALSE; - } else { - if (resptests[i].reason_phrase) - ok = FALSE; - } + g_assert_cmpint (version, ==, resptests[i].version); + g_assert_cmpint (status_code, ==, resptests[i].status_code); + g_assert_cmpstr (reason_phrase, ==, resptests[i].reason_phrase); - if (ok) - debug_printf (1, "OK!\n"); - else { - debug_printf (1, "BAD!\n"); - errors++; - if (resptests[i].reason_phrase) { - debug_printf (1, " expected: 'HTTP/1.%d' '%03d' '%s'\n", - resptests[i].version, - resptests[i].status_code, - resptests[i].reason_phrase); - for (h = 0; resptests[i].headers[h].name; h++) { - debug_printf (1, " '%s': '%s'\n", - resptests[i].headers[h].name, - resptests[i].headers[h].value); - } - } else - debug_printf (1, " expected: parse error\n"); - if (reason_phrase) { - debug_printf (1, " got: 'HTTP/1.%d' '%03d' '%s'\n", - version, status_code, reason_phrase); - soup_message_headers_foreach (headers, print_header, NULL); - } else - debug_printf (1, " got: parse error\n"); - } + check_headers (resptests[i].headers, headers); + } else + g_assert_null (resptests[i].reason_phrase); g_free (reason_phrase); soup_message_headers_free (headers); @@ -917,7 +832,6 @@ do_qvalue_tests (void) { int i, j; GSList *acceptable, *unacceptable, *iter; - gboolean wrong; debug_printf (1, "qvalue tests\n"); for (i = 0; i < num_qvaluetests; i++) { @@ -928,46 +842,26 @@ do_qvalue_tests (void) &unacceptable); debug_printf (1, " acceptable: "); - wrong = FALSE; if (acceptable) { for (iter = acceptable, j = 0; iter; iter = iter->next, j++) { debug_printf (1, "%s ", (char *)iter->data); - if (!qvaluetests[i].acceptable[j] || - strcmp (iter->data, qvaluetests[i].acceptable[j]) != 0) - wrong = TRUE; + g_assert_cmpstr (iter->data, ==, qvaluetests[i].acceptable[j]); } debug_printf (1, "\n"); soup_header_free_list (acceptable); } else debug_printf (1, "(none)\n"); - if (wrong) { - debug_printf (1, " WRONG! expected: "); - for (j = 0; qvaluetests[i].acceptable[j]; j++) - debug_printf (1, "%s ", qvaluetests[i].acceptable[j]); - debug_printf (1, "\n"); - errors++; - } debug_printf (1, " unacceptable: "); - wrong = FALSE; if (unacceptable) { for (iter = unacceptable, j = 0; iter; iter = iter->next, j++) { debug_printf (1, "%s ", (char *)iter->data); - if (!qvaluetests[i].unacceptable[j] || - strcmp (iter->data, qvaluetests[i].unacceptable[j]) != 0) - wrong = TRUE; + g_assert_cmpstr (iter->data, ==, qvaluetests[i].unacceptable[j]); } debug_printf (1, "\n"); soup_header_free_list (unacceptable); } else debug_printf (1, "(none)\n"); - if (wrong) { - debug_printf (1, " WRONG! expected: "); - for (j = 0; qvaluetests[i].unacceptable[j]; j++) - debug_printf (1, "%s ", qvaluetests[i].unacceptable[j]); - debug_printf (1, "\n"); - errors++; - } debug_printf (1, "\n"); } @@ -1002,14 +896,7 @@ do_content_disposition_tests (void) g_hash_table_destroy (params); header = soup_message_headers_get_one (hdrs, "Content-Disposition"); - if (!g_strcmp0 (header, RFC5987_TEST_HEADER_ENCODED)) - debug_printf (1, " encoded OK\n"); - else { - debug_printf (1, " encoding FAILED!\n expected: %s\n got: %s\n", - RFC5987_TEST_HEADER_ENCODED, - header ? header : "(none)"); - errors++; - } + g_assert_cmpstr (header, ==, RFC5987_TEST_HEADER_ENCODED); /* UTF-8 decoding */ soup_message_headers_clear (hdrs); @@ -1018,22 +905,13 @@ do_content_disposition_tests (void) if (!soup_message_headers_get_content_disposition (hdrs, &disposition, ¶ms)) { - debug_printf (1, " UTF-8 decoding FAILED!\n could not parse\n"); - errors++; + soup_test_assert (FALSE, "UTF-8 decoding FAILED"); return; } g_free (disposition); filename = g_hash_table_lookup (params, "filename"); - if (!filename) { - debug_printf (1, " UTF-8 decoding FAILED!\n could not find filename\n"); - errors++; - } else if (strcmp (filename, RFC5987_TEST_FILENAME) != 0) { - debug_printf (1, " UTF-8 decoding FAILED!\n expected: %s\n got: %s\n", - RFC5987_TEST_FILENAME, filename); - errors++; - } else - debug_printf (1, " UTF-8 decoded OK\n"); + g_assert_cmpstr (filename, ==, RFC5987_TEST_FILENAME); g_hash_table_destroy (params); /* ISO-8859-1 decoding */ @@ -1043,22 +921,13 @@ do_content_disposition_tests (void) if (!soup_message_headers_get_content_disposition (hdrs, &disposition, ¶ms)) { - debug_printf (1, " iso-8859-1 decoding FAILED!\n could not parse\n"); - errors++; + soup_test_assert (FALSE, "iso-8859-1 decoding FAILED"); return; } g_free (disposition); filename = g_hash_table_lookup (params, "filename"); - if (!filename) { - debug_printf (1, " iso-8859-1 decoding FAILED!\n could not find filename\n"); - errors++; - } else if (strcmp (filename, RFC5987_TEST_FILENAME) != 0) { - debug_printf (1, " iso-8859-1 decoding FAILED!\n expected: %s\n got: %s\n", - RFC5987_TEST_FILENAME, filename); - errors++; - } else - debug_printf (1, " iso-8859-1 decoded OK\n"); + g_assert_cmpstr (filename, ==, RFC5987_TEST_FILENAME); g_hash_table_destroy (params); /* Fallback */ @@ -1068,22 +937,13 @@ do_content_disposition_tests (void) if (!soup_message_headers_get_content_disposition (hdrs, &disposition, ¶ms)) { - debug_printf (1, " fallback decoding FAILED!\n could not parse\n"); - errors++; + soup_test_assert (FALSE, "fallback decoding FAILED"); return; } g_free (disposition); filename = g_hash_table_lookup (params, "filename"); - if (!filename) { - debug_printf (1, " fallback decoding FAILED!\n could not find filename\n"); - errors++; - } else if (strcmp (filename, RFC5987_TEST_FALLBACK_FILENAME) != 0) { - debug_printf (1, " fallback decoding FAILED!\n expected: %s\n got: %s\n", - RFC5987_TEST_FALLBACK_FILENAME, filename); - errors++; - } else - debug_printf (1, " fallback decoded OK\n"); + g_assert_cmpstr (filename, ==, RFC5987_TEST_FALLBACK_FILENAME); g_hash_table_destroy (params); soup_message_headers_free (hdrs); @@ -1104,12 +964,8 @@ do_content_disposition_tests (void) buffer = soup_message_body_flatten (body); soup_message_body_free (body); - if (strstr (buffer->data, "filename=\"token\"")) - debug_printf (1, " SoupMultipart encoded filename correctly\n"); - else { - debug_printf (1, " SoupMultipart encoded filename incorrectly!\n"); - errors++; - } + g_assert_true (strstr (buffer->data, "filename=\"token\"")); + soup_buffer_free (buffer); debug_printf (1, "\n"); @@ -1139,14 +995,7 @@ do_content_type_tests (void) g_hash_table_destroy (params); header = soup_message_headers_get_one (hdrs, "Content-Type"); - if (!g_strcmp0 (header, CONTENT_TYPE_TEST_HEADER)) - debug_printf (1, " encoded OK\n"); - else { - debug_printf (1, " encoding FAILED!\n expected: %s\n got: %s\n", - CONTENT_TYPE_TEST_HEADER, - header ? header : "(none)"); - errors++; - } + g_assert_cmpstr (header, ==, CONTENT_TYPE_TEST_HEADER); soup_message_headers_clear (hdrs); soup_message_headers_append (hdrs, "Content-Type", @@ -1156,22 +1005,8 @@ do_content_type_tests (void) CONTENT_TYPE_TEST_MIME_TYPE); mime_type = soup_message_headers_get_content_type (hdrs, ¶ms); - if (!mime_type) { - debug_printf (1, " decoding FAILED!\n could not parse\n"); - errors++; - } - - if (mime_type && strcmp (mime_type, CONTENT_TYPE_TEST_MIME_TYPE) != 0) { - debug_printf (1, " decoding FAILED!\n bad returned MIME type: %s\n", - mime_type); - errors++; - } else if (params && g_hash_table_size (params) != 0) { - debug_printf (1, " decoding FAILED!\n params contained %d params (should be 0)\n", - g_hash_table_size (params)); - errors++; - } else - debug_printf (1, " decoded OK\n"); - + g_assert_cmpstr (mime_type, ==, CONTENT_TYPE_TEST_MIME_TYPE); + g_assert_cmpint (g_hash_table_size (params), ==, 0); if (params) g_hash_table_destroy (params); @@ -1179,11 +1014,7 @@ do_content_type_tests (void) soup_message_headers_append (hdrs, "Content-Type", CONTENT_TYPE_BAD_HEADER); mime_type = soup_message_headers_get_content_type (hdrs, ¶ms); - if (mime_type) { - debug_printf (1, " Bad content rejection FAILED!\n"); - errors++; - } else - debug_printf (1, " Bad content rejection OK\n"); + g_assert_null (mime_type); soup_message_headers_free (hdrs); @@ -1218,12 +1049,7 @@ do_append_param_tests (void) test_params[i].name, test_params[i].value); } - if (strcmp (params->str, TEST_PARAMS_RESULT) != 0) { - debug_printf (1, " FAILED!\n expected: %s\n got: %s\n", - TEST_PARAMS_RESULT, params->str); - errors++; - } else - debug_printf (1, " OK\n"); + g_assert_cmpstr (params->str, ==, TEST_PARAMS_RESULT); g_string_free (params, TRUE); debug_printf (1, "\n"); @@ -1254,14 +1080,12 @@ do_bad_header_tests (void) hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); for (i = 0; i < G_N_ELEMENTS (bad_headers); i++) { debug_printf (1, " %s\n", bad_headers[i].description); - expect_warning = TRUE; + + g_test_expect_message ("libsoup", G_LOG_LEVEL_CRITICAL, + "*soup_message_headers_append*assertion*failed*"); soup_message_headers_append (hdrs, bad_headers[i].name, bad_headers[i].value); - if (expect_warning) { - expect_warning = FALSE; - debug_printf (1, " FAILED: soup_message_headers_append() did not reject it\n"); - errors++; - } + g_test_assert_expected_messages (); } soup_message_headers_free (hdrs); } @@ -1269,16 +1093,20 @@ do_bad_header_tests (void) int main (int argc, char **argv) { + int ret; + test_init (argc, argv, NULL); - do_request_tests (); - do_response_tests (); - do_qvalue_tests (); - do_content_disposition_tests (); - do_content_type_tests (); - do_append_param_tests (); - do_bad_header_tests (); + g_test_add_func ("/header-parsing/request", do_request_tests); + g_test_add_func ("/header-parsing/response", do_response_tests); + g_test_add_func ("/header-parsing/qvalue", do_qvalue_tests); + g_test_add_func ("/header-parsing/content-disposition", do_content_disposition_tests); + g_test_add_func ("/header-parsing/content-type", do_content_type_tests); + g_test_add_func ("/header-parsing/append-param", do_append_param_tests); + g_test_add_func ("/header-parsing/bad", do_bad_header_tests); + + ret = g_test_run (); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/misc-test.c b/tests/misc-test.c index 2aaa2cd4..46c9cb10 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -112,26 +112,12 @@ do_host_test (void) soup_test_session_abort_unref (session); - if (!SOUP_STATUS_IS_SUCCESSFUL (one->status_code)) { - debug_printf (1, " Message 1 failed: %d %s\n", - one->status_code, one->reason_phrase); - errors++; - } else if (strcmp (one->response_body->data, "index") != 0) { - debug_printf (1, " Unexpected response to message 1: '%s'\n", - one->response_body->data); - errors++; - } + soup_test_assert_message_status (one, SOUP_STATUS_OK); + g_assert_cmpstr (one->response_body->data, ==, "index"); g_object_unref (one); - if (!SOUP_STATUS_IS_SUCCESSFUL (two->status_code)) { - debug_printf (1, " Message 2 failed: %d %s\n", - two->status_code, two->reason_phrase); - errors++; - } else if (strcmp (two->response_body->data, "foo-index") != 0) { - debug_printf (1, " Unexpected response to message 2: '%s'\n", - two->response_body->data); - errors++; - } + soup_test_assert_message_status (two, SOUP_STATUS_OK); + g_assert_cmpstr (two->response_body->data, ==, "foo-index"); g_object_unref (two); } @@ -143,11 +129,7 @@ static void cu_one_completed (SoupSession *session, SoupMessage *msg, gpointer loop) { debug_printf (2, " Message 1 completed\n"); - if (msg->status_code != SOUP_STATUS_CANT_CONNECT) { - debug_printf (1, " Unexpected status on Message 1: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CANT_CONNECT); g_object_unref (session); } @@ -162,11 +144,7 @@ static void cu_two_completed (SoupSession *session, SoupMessage *msg, gpointer loop) { debug_printf (2, " Message 2 completed\n"); - if (msg->status_code != SOUP_STATUS_CANT_CONNECT) { - debug_printf (1, " Unexpected status on Message 2: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CANT_CONNECT); g_idle_add (cu_idle_quit, loop); } @@ -210,22 +188,19 @@ do_callback_unref_test (void) g_main_loop_run (loop); g_main_loop_unref (loop); + g_assert_null (session); if (session) { g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session); - debug_printf (1, " Session not destroyed?\n"); - errors++; g_object_unref (session); } + g_assert_null (one); if (one) { g_object_remove_weak_pointer (G_OBJECT (one), (gpointer *)&one); - debug_printf (1, " Message 1 not destroyed?\n"); - errors++; g_object_unref (one); } + g_assert_null (two); if (two) { g_object_remove_weak_pointer (G_OBJECT (two), (gpointer *)&two); - debug_printf (1, " Message 2 not destroyed?\n"); - errors++; g_object_unref (two); } @@ -239,14 +214,8 @@ cur_one_completed (GObject *source, GAsyncResult *result, gpointer session) GError *error = NULL; debug_printf (2, " Request 1 completed\n"); - if (soup_request_send_finish (one, result, &error)) { - debug_printf (1, " Request 1 succeeded?\n"); - errors++; - } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED)) { - debug_printf (1, " Unexpected error on Request 1: %s\n", - error->message); - errors++; - } + soup_request_send_finish (one, result, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED); g_clear_error (&error); g_object_unref (session); @@ -266,14 +235,8 @@ cur_two_completed (GObject *source, GAsyncResult *result, gpointer loop) GError *error = NULL; debug_printf (2, " Request 2 completed\n"); - if (soup_request_send_finish (two, result, &error)) { - debug_printf (1, " Request 2 succeeded?\n"); - errors++; - } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED)) { - debug_printf (1, " Unexpected error on Request 2: %s\n", - error->message); - errors++; - } + soup_request_send_finish (two, result, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED); g_clear_error (&error); g_idle_add (cur_idle_quit, loop); @@ -323,22 +286,19 @@ do_callback_unref_req_test (void) g_main_loop_run (loop); g_main_loop_unref (loop); + g_assert_null (session); if (session) { g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session); - debug_printf (1, " Session not destroyed?\n"); - errors++; g_object_unref (session); } + g_assert_null (one); if (one) { g_object_remove_weak_pointer (G_OBJECT (one), (gpointer *)&one); - debug_printf (1, " Request 1 not destroyed?\n"); - errors++; g_object_unref (one); } + g_assert_null (two); if (two) { g_object_remove_weak_pointer (G_OBJECT (two), (gpointer *)&two); - debug_printf (1, " Request 2 not destroyed?\n"); - errors++; g_object_unref (two); } @@ -353,14 +313,14 @@ static void ensure_no_signal_handlers (SoupMessage *msg, guint *signal_ids, guint n_signal_ids) { int i; + guint id; for (i = 0; i < n_signal_ids; i++) { - if (g_signal_handler_find (msg, G_SIGNAL_MATCH_ID, signal_ids[i], - 0, NULL, NULL, NULL)) { - debug_printf (1, " Message has handler for '%s'\n", - g_signal_name (signal_ids[i])); - errors++; - } + id = g_signal_handler_find (msg, G_SIGNAL_MATCH_ID, signal_ids[i], + 0, NULL, NULL, NULL); + soup_test_assert (id == 0, + "message has handler for '%s'", + g_signal_name (signal_ids[i])); } } @@ -401,10 +361,7 @@ do_msg_reuse_test (void) soup_message_set_uri (msg, uri); soup_uri_free (uri); soup_session_send_message (session, msg); - if (!soup_uri_equal (soup_message_get_uri (msg), base_uri)) { - debug_printf (1, " Message did not get redirected!\n"); - errors++; - } + g_assert_true (soup_uri_equal (soup_message_get_uri (msg), base_uri)); ensure_no_signal_handlers (msg, signal_ids, n_signal_ids); debug_printf (1, " Auth message\n"); @@ -412,10 +369,7 @@ do_msg_reuse_test (void) soup_message_set_uri (msg, uri); soup_uri_free (uri); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " Message did not get authenticated!\n"); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); ensure_no_signal_handlers (msg, signal_ids, n_signal_ids); /* One last try to make sure the auth stuff got cleaned up */ @@ -434,11 +388,7 @@ static void ea_msg_completed_one (SoupSession *session, SoupMessage *msg, gpointer loop) { debug_printf (2, " Message 1 completed\n"); - if (msg->status_code != SOUP_STATUS_CANCELLED) { - debug_printf (1, " Unexpected status on Message 1: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); g_main_loop_quit (loop); } @@ -509,11 +459,7 @@ do_early_abort_test (void) soup_session_send_message (session, msg); debug_printf (2, " Message 2 completed\n"); - if (msg->status_code != SOUP_STATUS_CANCELLED) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); g_object_unref (msg); while (g_main_context_pending (context)) @@ -529,11 +475,7 @@ do_early_abort_test (void) soup_session_send_message (session, msg); debug_printf (2, " Message 3 completed\n"); - if (msg->status_code != SOUP_STATUS_CANCELLED) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); g_object_unref (msg); while (g_main_context_pending (context)) @@ -548,14 +490,8 @@ ear_one_completed (GObject *source, GAsyncResult *result, gpointer user_data) GError *error = NULL; debug_printf (2, " Request 1 completed\n"); - if (soup_request_send_finish (SOUP_REQUEST (source), result, &error)) { - debug_printf (1, " Request 1 succeeded?\n"); - errors++; - } else if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED)) { - debug_printf (1, " Unexpected error on Request 1: %s\n", - error->message); - errors++; - } + soup_request_send_finish (SOUP_REQUEST (source), result, &error); + g_assert_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED); g_clear_error (&error); } @@ -565,14 +501,8 @@ ear_two_completed (GObject *source, GAsyncResult *result, gpointer loop) GError *error = NULL; debug_printf (2, " Request 2 completed\n"); - if (soup_request_send_finish (SOUP_REQUEST (source), result, &error)) { - debug_printf (1, " Request 2 succeeded?\n"); - errors++; - } else if (!g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED)) { - debug_printf (1, " Unexpected error on Request 2: %s\n", - error->message); - errors++; - } + soup_request_send_finish (SOUP_REQUEST (source), result, &error); + g_assert_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_CANCELLED); g_clear_error (&error); g_main_loop_quit (loop); @@ -584,14 +514,8 @@ ear_three_completed (GObject *source, GAsyncResult *result, gpointer loop) GError *error = NULL; debug_printf (2, " Request 3 completed\n"); - if (soup_request_send_finish (SOUP_REQUEST (source), result, &error)) { - debug_printf (1, " Request 3 succeeded?\n"); - errors++; - } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - debug_printf (1, " Unexpected error on Request 3: %s\n", - error->message); - errors++; - } + soup_request_send_finish (SOUP_REQUEST (source), result, &error); + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_clear_error (&error); g_main_loop_quit (loop); @@ -683,21 +607,10 @@ do_one_accept_language_test (const char *language, const char *expected_header) soup_session_send_message (session, msg); soup_test_session_abort_unref (session); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " Message failed? %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); val = soup_message_headers_get_list (msg->request_headers, "Accept-Language"); - if (!val) { - debug_printf (1, " No Accept-Language set!\n"); - errors++; - } else if (strcmp (val, expected_header) != 0) { - debug_printf (1, " Wrong Accept-Language: expected '%s', got '%s'\n", - expected_header, val); - errors++; - } + g_assert_cmpstr (val, ==, expected_header); g_object_unref (msg); } @@ -780,11 +693,7 @@ do_cancel_while_reading_test_for_session (SoupSession *session) while (!done) g_main_context_iteration (NULL, TRUE); - if (msg->status_code != SOUP_STATUS_CANCELLED) { - debug_printf (1, " FAILED: %d %s (expected Cancelled)\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); g_object_unref (msg); if (thread) @@ -824,14 +733,7 @@ do_cancel_while_reading_req_test_for_session (SoupSession *session, cancellable = g_cancellable_new (); soup_test_request_send (req, cancellable, flags, &error); - if (!error) { - debug_printf (1, " Request succeeded?\n"); - errors++; - } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - debug_printf (1, " Unexpected error: %s\n", - error->message); - errors++; - } + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_clear_error (&error); g_object_unref (req); @@ -910,20 +812,11 @@ do_aliases_test_for_session (SoupSession *session, redirected_protocol = soup_message_headers_get_one (msg->response_headers, "X-Redirected-Protocol"); - if (g_strcmp0 (redirect_protocol, redirected_protocol)) { - debug_printf (1, " redirect went to %s, should have gone to %s!\n", - redirected_protocol ? redirected_protocol : "(none)", - redirect_protocol ? redirect_protocol : "(none)"); - errors++; - } else if (redirect_protocol && !SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " msg failed? (%d %s)\n", - msg->status_code, msg->reason_phrase); - errors++; - } else if (!redirect_protocol && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " msg succeeded? (%d %s)\n", - msg->status_code, msg->reason_phrase); - errors++; - } + g_assert_cmpstr (redirect_protocol, ==, redirected_protocol); + if (redirect_protocol) + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + else + soup_test_assert_message_status (msg, SOUP_STATUS_FOUND); g_object_unref (msg); } @@ -982,10 +875,8 @@ do_idle_on_dispose_test (void) g_object_run_dispose (G_OBJECT (session)); - if (g_main_context_iteration (async_context, FALSE)) { - debug_printf (1, " idle was queued!\n"); - errors++; - } + if (g_main_context_iteration (async_context, FALSE)) + soup_test_assert (FALSE, "idle was queued"); g_object_unref (session); g_main_context_unref (async_context); @@ -1009,16 +900,14 @@ do_pause_abort_test (void) g_object_add_weak_pointer (G_OBJECT (msg), &ptr); soup_test_session_abort_unref (session); - if (ptr) { - debug_printf (1, " msg was leaked\n"); - errors++; - } + g_assert_null (ptr); } int main (int argc, char **argv) { SoupAuthDomain *auth_domain; + int ret; test_init (argc, argv, NULL); @@ -1042,18 +931,20 @@ main (int argc, char **argv) soup_uri_set_port (ssl_base_uri, soup_server_get_port (ssl_server)); } - do_host_test (); - do_callback_unref_test (); - do_callback_unref_req_test (); - do_msg_reuse_test (); - do_early_abort_test (); - do_early_abort_req_test (); - do_accept_language_test (); - do_cancel_while_reading_test (); - do_cancel_while_reading_req_test (); - do_aliases_test (); - do_idle_on_dispose_test (); - do_pause_abort_test (); + g_test_add_func ("/misc/host", do_host_test); + g_test_add_func ("/misc/callback-unref/msg", do_callback_unref_test); + g_test_add_func ("/misc/callback-unref/req", do_callback_unref_req_test); + g_test_add_func ("/misc/msg-reuse", do_msg_reuse_test); + g_test_add_func ("/misc/early-abort/msg", do_early_abort_test); + g_test_add_func ("/misc/early-abort/req", do_early_abort_req_test); + g_test_add_func ("/misc/accept-language", do_accept_language_test); + g_test_add_func ("/misc/cancel-while-reading/msg", do_cancel_while_reading_test); + g_test_add_func ("/misc/cancel-while-reading/req", do_cancel_while_reading_req_test); + g_test_add_func ("/misc/aliases", do_aliases_test); + g_test_add_func ("/misc/idle-on-dispose", do_idle_on_dispose_test); + g_test_add_func ("/misc/pause-abort", do_pause_abort_test); + + ret = g_test_run (); soup_uri_free (base_uri); soup_test_server_quit_unref (server); @@ -1063,6 +954,5 @@ main (int argc, char **argv) soup_test_server_quit_unref (ssl_server); } - test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/multipart-test.c b/tests/multipart-test.c index bfe4f5b2..b5ab813d 100644 --- a/tests/multipart-test.c +++ b/tests/multipart-test.c @@ -87,10 +87,8 @@ content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, int * static void check_is_next (gboolean is_next) { - if (!is_next) { - debug_printf (1, " expected a header, but there are no more headers\n"); - errors++; - } + soup_test_assert (is_next, + "expected a header, but there are no more headers"); } static void @@ -112,15 +110,8 @@ got_headers (SoupMessage *msg, int *headers_count) check_is_next (is_next); } - if (!g_str_equal (name, "Content-Type")) { - debug_printf (1, " expected 'Content-Type' got %s\n", name); - errors++; - } - - if (!g_str_equal (value, "multipart/x-mixed-replace; boundary=cut-here")) { - debug_printf (1, " expected 'multipart/x-mixed-replace; boundary=cut-here' got %s\n", value); - errors++; - } + g_assert_cmpstr (name, ==, "Content-Type"); + g_assert_cmpstr (value, ==, "multipart/x-mixed-replace; boundary=cut-here"); } static void @@ -129,12 +120,11 @@ read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) GMainLoop *loop = (GMainLoop*)data; GInputStream *stream = G_INPUT_STREAM (source); GError *error = NULL; - gssize bytes_read = g_input_stream_read_finish (stream, asyncResult, &error); + gssize bytes_read; + bytes_read = g_input_stream_read_finish (stream, asyncResult, &error); + g_assert_no_error (error); if (error) { - debug_printf (1, " failed read: %s\n", error->message); - errors++; - g_object_unref (stream); g_main_loop_quit (loop); return; @@ -142,13 +132,8 @@ read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) if (!bytes_read) { g_input_stream_close (stream, NULL, &error); + g_assert_no_error (error); g_object_unref (stream); - - if (error) { - debug_printf (1, " failed close: %s\n", error->message); - errors++; - } - g_main_loop_quit (loop); return; } @@ -167,11 +152,8 @@ no_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) GInputStream* in; in = soup_request_send_finish (request, res, &error); - + g_assert_no_error (error); if (error) { - debug_printf (1, " failed send: %s\n", error->message); - errors++; - g_main_loop_quit (loop); return; } @@ -188,10 +170,7 @@ multipart_close_part_cb (GObject *source, GAsyncResult *res, gpointer data) GError *error = NULL; g_input_stream_close_finish (in, res, &error); - if (error) { - debug_printf (1, " error closing stream: %s\n", error->message); - errors++; - } + g_assert_no_error (error); } static void multipart_next_part_cb (GObject *source, @@ -203,32 +182,20 @@ check_read (gsize nread, unsigned passes) { switch (passes) { case 0: - if (nread != 30) { - debug_printf (1, " expected to read 30 bytes, got: %d\n", (int)nread); - errors++; - } + g_assert_cmpint (nread, ==, 30); break; case 1: - if (nread != 10) { - debug_printf (1, " expected to read 10 bytes, got: %d\n", (int)nread); - errors++; - } + g_assert_cmpint (nread, ==, 10); break; case 2: - if (nread != 24) { - debug_printf (1, " expected to read 24 bytes, got: %d\n", (int)nread); - errors++; - } + g_assert_cmpint (nread, ==, 24); break; case 3: - if (nread != 34) { - debug_printf (1, " expected to read 34 bytes, got: %d\n", (int)nread); - errors++; - } + g_assert_cmpint (nread, ==, 34); break; default: - debug_printf (1, " unexpected read of size: %d\n", (int)nread); - errors++; + soup_test_assert (FALSE, "unexpected read of size: %d", (int)nread); + break; } } @@ -242,11 +209,8 @@ multipart_read_cb (GObject *source, GAsyncResult *asyncResult, gpointer data) gssize bytes_read; bytes_read = g_input_stream_read_finish (in, asyncResult, &error); - + g_assert_no_error (error); if (error) { - debug_printf (1, " failed read: %s\n", error->message); - errors++; - g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, multipart_close_part_cb, NULL); g_object_unref (in); @@ -292,43 +256,22 @@ check_headers (SoupMultipartInputStream* multipart, unsigned passes) is_next = soup_message_headers_iter_next (&iter, &name, &value); check_is_next (is_next); - if (!g_str_equal (name, "Content-Type")) { - debug_printf (1, " [0] expected 'Content-Type' got %s\n", name); - errors++; - } - - if (!g_str_equal (value, "text/html")) { - debug_printf (1, " [0] expected 'text/html' got %s\n", value); - errors++; - } + g_assert_cmpstr (name, ==, "Content-Type"); + g_assert_cmpstr (value, ==, "text/html"); is_next = soup_message_headers_iter_next (&iter, &name, &value); check_is_next (is_next); - if (!g_str_equal (name, "Content-Length")) { - debug_printf (1, " [0] expected 'Content-Length' got %s\n", name); - errors++; - } - - if (!g_str_equal (value, "30")) { - debug_printf (1, " [0] expected '30' got %s\n", value); - errors++; - } + g_assert_cmpstr (name, ==, "Content-Length"); + g_assert_cmpstr (value, ==, "30"); break; case 1: is_next = soup_message_headers_iter_next (&iter, &name, &value); check_is_next (is_next); - if (!g_str_equal (name, "Content-Length")) { - debug_printf (1, " [1] expected 'Content-Length' got %s\n", name); - errors++; - } - - if (!g_str_equal (value, "10")) { - debug_printf (1, " [1] expected '10' got %s\n", value); - errors++; - } + g_assert_cmpstr (name, ==, "Content-Length"); + g_assert_cmpstr (value, ==, "10"); break; case 2: @@ -336,19 +279,12 @@ check_headers (SoupMultipartInputStream* multipart, unsigned passes) is_next = soup_message_headers_iter_next (&iter, &name, &value); check_is_next (is_next); - if (!g_str_equal (name, "Content-Type")) { - debug_printf (1, " [%d] expected 'Content-Type' got %s\n", passes, name); - errors++; - } - - if (!g_str_equal (value, "text/css")) { - debug_printf (1, " [%d] expected 'text/html' got %s\n", passes, value); - errors++; - } + g_assert_cmpstr (name, ==, "Content-Type"); + g_assert_cmpstr (value, ==, "text/css"); break; default: - debug_printf (1, " unexpected part received\n"); + soup_test_assert (FALSE, "unexpected part received"); break; } } @@ -364,23 +300,16 @@ multipart_next_part_cb (GObject *source, GAsyncResult *res, gpointer data) g_assert (SOUP_MULTIPART_INPUT_STREAM (source) == multipart); in = soup_multipart_input_stream_next_part_finish (multipart, res, &error); - + g_assert_no_error (error); if (error) { - debug_printf (1, " failed next part: %s\n", error->message); g_clear_error (&error); - errors++; - g_object_unref (multipart); g_main_loop_quit (loop); return; } if (!in) { - if (passes != 4) { - debug_printf (1, " expected 4 parts, got %u\n", passes); - errors++; - } - + g_assert_cmpint (passes, ==, 4); g_object_unref (multipart); g_main_loop_quit (loop); return; @@ -406,19 +335,17 @@ multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) SoupMessage *message; in = soup_request_send_finish (request, res, &error); - message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); - multipart = soup_multipart_input_stream_new (message, in); - g_object_unref (message); - g_object_unref (in); - + g_assert_no_error (error); if (error) { - debug_printf (1, " failed send: %s\n", error->message); - errors++; - g_main_loop_quit (loop); return; } + message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + multipart = soup_multipart_input_stream_new (message, in); + g_object_unref (message); + g_object_unref (in); + if (g_object_get_data (source, "multipart-small-reads")) g_object_set_data (G_OBJECT (multipart), "multipart-small-reads", GINT_TO_POINTER(1)); @@ -438,25 +365,21 @@ sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) gsize bytes_read; in = soup_request_send_finish (request, res, &error); - message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); - multipart = soup_multipart_input_stream_new (message, in); - g_object_unref (message); - g_object_unref (in); - + g_assert_no_error (error); if (error) { - debug_printf (1, " failed send: %s\n", error->message); - errors++; - g_main_loop_quit (loop); return; } + message = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + multipart = soup_multipart_input_stream_new (message, in); + g_object_unref (message); + g_object_unref (in); + while (TRUE) { in = soup_multipart_input_stream_next_part (multipart, NULL, &error); - + g_assert_no_error (error); if (error) { - debug_printf (1, " failed sync next part: %s\n", error->message); - errors++; g_clear_error (&error); break; } @@ -467,10 +390,8 @@ sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) check_headers (multipart, passes); g_input_stream_read_all (in, (void*)buffer, sizeof (buffer), &bytes_read, NULL, &error); - + g_assert_no_error (error); if (error) { - debug_printf (1, " failed sync read: %s\n", error->message); - errors++; g_clear_error (&error); g_object_unref (in); break; @@ -482,10 +403,7 @@ sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) g_object_unref (in); } - if (passes != 4) { - debug_printf (1, " expected 4 parts, got %u\n", passes); - errors++; - } + g_assert_cmpint (passes, ==, 4); g_main_loop_quit (loop); g_object_unref (multipart); @@ -505,21 +423,29 @@ multipart_mode_to_string (MultipartMode mode) } static void -test_multipart (int headers_expected, int sniffed_expected, MultipartMode multipart_mode) +test_multipart (gconstpointer data) { - GError* error = NULL; - SoupRequest* request = soup_session_request (session, base_uri_string, &error); - - SoupMessage *msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); - GMainLoop *loop = g_main_loop_new (NULL, TRUE); + int headers_expected = 1, sniffed_expected = 1; + MultipartMode multipart_mode = GPOINTER_TO_INT (data); + SoupRequest* request; + SoupMessage *msg; + GMainLoop *loop; int headers_count = 0; int sniffed_count = 0; GHashTable *params; const char *content_type; gboolean message_is_multipart = FALSE; + GError* error = NULL; debug_printf (1, "test_multipart(%s)\n", multipart_mode_to_string (multipart_mode)); + request = soup_session_request (session, base_uri_string, &error); + g_assert_no_error (error); + if (error) + return; + + msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); + /* This is used to track the number of parts. */ passes = 0; @@ -533,6 +459,8 @@ test_multipart (int headers_expected, int sniffed_expected, MultipartMode multip g_signal_connect (msg, "content-sniffed", G_CALLBACK (content_sniffed), &sniffed_count); + loop = g_main_loop_new (NULL, TRUE); + if (multipart_mode == ASYNC_MULTIPART) soup_request_send_async (request, NULL, multipart_handling_cb, loop); else if (multipart_mode == ASYNC_MULTIPART_SMALL_READS) { @@ -554,25 +482,9 @@ test_multipart (int headers_expected, int sniffed_expected, MultipartMode multip } g_clear_pointer (¶ms, g_hash_table_unref); - if (!message_is_multipart) { - debug_printf (1, - " Header does not indicate a multipart message!\n"); - errors++; - } - - if (headers_count != headers_expected) { - debug_printf (1, - " expected got_header %d times, got %d!\n", - headers_expected, headers_count); - errors++; - } - - if (sniffed_count != sniffed_expected) { - debug_printf (1, - " expected content_sniffed %d times, got %d!\n", - sniffed_expected, sniffed_count); - errors++; - } + g_assert_true (message_is_multipart); + g_assert_cmpint (headers_count, ==, headers_expected); + g_assert_cmpint (sniffed_count, ==, sniffed_expected); g_object_unref (msg); g_object_unref (request); @@ -583,6 +495,7 @@ int main (int argc, char **argv) { SoupServer *server; + int ret; test_init (argc, argv, NULL); @@ -604,10 +517,12 @@ main (int argc, char **argv) NULL); soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); - test_multipart (1, 1, NO_MULTIPART); - test_multipart (1, 1, SYNC_MULTIPART); - test_multipart (1, 1, ASYNC_MULTIPART); - test_multipart (1, 1, ASYNC_MULTIPART_SMALL_READS); + g_test_add_data_func ("/multipart/no", GINT_TO_POINTER (NO_MULTIPART), test_multipart); + g_test_add_data_func ("/multipart/sync", GINT_TO_POINTER (SYNC_MULTIPART), test_multipart); + g_test_add_data_func ("/multipart/async", GINT_TO_POINTER (ASYNC_MULTIPART), test_multipart); + g_test_add_data_func ("/multipart/async-small-reads", GINT_TO_POINTER (ASYNC_MULTIPART_SMALL_READS), test_multipart); + + ret = g_test_run (); soup_uri_free (base_uri); g_free (base_uri_string); @@ -615,6 +530,7 @@ main (int argc, char **argv) soup_test_session_abort_unref (session); soup_test_server_quit_unref (server); + test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c index ab1bdc3a..5944b91b 100644 --- a/tests/no-ssl-test.c +++ b/tests/no-ssl-test.c @@ -3,38 +3,28 @@ #include "test-utils.h" static void -do_ssl_test_for_session (SoupSession *session, char *uri) +do_ssl_test_for_session (SoupSession *session, const char *uri) { SoupMessage *msg; - GTlsCertificate *cert; + GTlsCertificate *cert = NULL; GTlsCertificateFlags flags; + gboolean is_https; msg = soup_message_new ("GET", uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_SSL_FAILED) { - debug_printf (1, " Unexpected status: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - - if (soup_message_get_https_status (msg, &cert, &flags)) { - debug_printf (1, " get_http_status() returned TRUE? (flags %x)\n", flags); - errors++; - if (cert) { - debug_printf (1, " Got GTlsCertificate?\n"); - errors++; - } - } - if (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) { - debug_printf (1, " CERTIFICATE_TRUSTED set?\n"); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_SSL_FAILED); + + is_https = soup_message_get_https_status (msg, &cert, &flags); + soup_test_assert (!is_https, "get_http_status() returned TRUE? (flags %x)", flags); + + g_assert_null (cert); + g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); g_object_unref (msg); } static void -do_ssl_tests (char *uri) +do_ssl_tests (gconstpointer uri) { SoupSession *session; @@ -73,20 +63,9 @@ do_session_property_tests (void) "tls-database", &tlsdb, "ssl-ca-file", &ca_file, NULL); - if (use_system) { - debug_printf (1, " ssl-use-system-ca-file defaults to TRUE?\n"); - errors++; - } - if (tlsdb) { - debug_printf (1, " tls-database set by default?\n"); - errors++; - g_object_unref (tlsdb); - } - if (ca_file) { - debug_printf (1, " ca-file set by default?\n"); - errors++; - g_free (ca_file); - } + soup_test_assert (!use_system, "ssl-use-system-ca-file defaults to TRUE"); + soup_test_assert (tlsdb == NULL, "tls-database set by default"); + soup_test_assert (ca_file == NULL, "ca-file set by default"); g_object_set (G_OBJECT (session), "ssl-use-system-ca-file", TRUE, @@ -94,11 +73,7 @@ do_session_property_tests (void) g_object_get (G_OBJECT (session), "ssl-ca-file", &ca_file, NULL); - if (ca_file) { - debug_printf (1, " setting ssl-use-system-ca-file set ssl-ca-file\n"); - errors++; - g_free (ca_file); - } + soup_test_assert (ca_file == NULL, "setting ssl-use-system-ca-file set ssl-ca-file"); g_object_set (G_OBJECT (session), "ssl-ca-file", SRCDIR "/test-cert.pem", @@ -108,20 +83,9 @@ do_session_property_tests (void) "tls-database", &tlsdb, "ssl-ca-file", &ca_file, NULL); - if (ca_file) { - debug_printf (1, " setting ssl-ca-file did not fail\n"); - errors++; - g_free (ca_file); - } - if (use_system) { - debug_printf (1, " setting ssl-ca-file set ssl-use-system-ca-file\n"); - errors++; - } - if (tlsdb) { - debug_printf (1, " setting ssl-ca-file set tls-database\n"); - errors++; - g_object_unref (tlsdb); - } + soup_test_assert (ca_file == NULL, "setting ssl-ca-file did not fail"); + soup_test_assert (!use_system, "setting ssl-ca-file set ssl-use-system-ca-file"); + soup_test_assert (tlsdb == NULL, "setting ssl-ca-file set tls-database"); g_object_set (G_OBJECT (session), "tls-database", NULL, @@ -131,20 +95,9 @@ do_session_property_tests (void) "tls-database", &tlsdb, "ssl-ca-file", &ca_file, NULL); - if (tlsdb) { - debug_printf (1, " setting tls-database NULL failed\n"); - errors++; - g_object_unref (tlsdb); - } - if (use_system) { - debug_printf (1, " setting tls-database NULL set ssl-use-system-ca-file\n"); - errors++; - } - if (ca_file) { - debug_printf (1, " setting tls-database NULL set ssl-ca-file\n"); - errors++; - g_free (ca_file); - } + soup_test_assert (tlsdb == NULL, "setting tls-database NULL failed"); + soup_test_assert (!use_system, "setting tls-database NULL set ssl-use-system-ca-file"); + soup_test_assert (ca_file == NULL, "setting tls-database NULL set ssl-ca-file"); soup_test_session_abort_unref (session); } @@ -168,6 +121,7 @@ main (int argc, char **argv) { SoupServer *server; char *uri; + int ret; /* Force this test to use the dummy TLS backend */ g_setenv ("GIO_USE_TLS", "dummy", TRUE); @@ -183,12 +137,14 @@ main (int argc, char **argv) uri = g_strdup_printf ("https://127.0.0.1:%u/", soup_server_get_port (server)); - do_session_property_tests (); - do_ssl_tests (uri); + g_test_add_func ("/no-ssl/session-properties", do_session_property_tests); + g_test_add_data_func ("/no-ssl/request-error", uri, do_ssl_tests); + + ret = g_test_run (); g_free (uri); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index f67a3d14..39879274 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -248,77 +248,59 @@ do_message (SoupSession *session, SoupURI *base_uri, const char *path, if (state.got_ntlm_prompt) { debug_printf (1, " NTLM_PROMPT"); - if (!get_ntlm_prompt) { + if (!get_ntlm_prompt) debug_printf (1, "???"); - errors++; - } - } else if (get_ntlm_prompt) { + } else if (get_ntlm_prompt) debug_printf (1, " no-ntlm-prompt???"); - errors++; - } if (state.got_basic_prompt) { debug_printf (1, " BASIC_PROMPT"); - if (!get_basic_prompt) { + if (!get_basic_prompt) debug_printf (1, "???"); - errors++; - } - } else if (get_basic_prompt) { + } else if (get_basic_prompt) debug_printf (1, " no-basic-prompt???"); - errors++; - } if (state.sent_ntlm_request) { debug_printf (1, " REQUEST"); - if (!do_ntlm) { + if (!do_ntlm) debug_printf (1, "???"); - errors++; - } - } else if (do_ntlm) { + } else if (do_ntlm) debug_printf (1, " no-request???"); - errors++; - } if (state.got_ntlm_challenge) { debug_printf (1, " CHALLENGE"); - if (!do_ntlm) { + if (!do_ntlm) debug_printf (1, "???"); - errors++; - } - } else if (do_ntlm) { + } else if (do_ntlm) debug_printf (1, " no-challenge???"); - errors++; - } if (state.sent_ntlm_response) { debug_printf (1, " NTLM_RESPONSE"); - if (!do_ntlm) { + if (!do_ntlm) debug_printf (1, "???"); - errors++; - } - } else if (do_ntlm) { + } else if (do_ntlm) debug_printf (1, " no-ntlm-response???"); - errors++; - } if (state.sent_basic_response) { debug_printf (1, " BASIC_RESPONSE"); - if (!do_basic) { + if (!do_basic) debug_printf (1, "???"); - errors++; - } - } else if (do_basic) { + } else if (do_basic) debug_printf (1, " no-basic-response???"); - errors++; - } debug_printf (1, " -> %s", msg->reason_phrase); - if (msg->status_code != status_code) { + if (msg->status_code != status_code) debug_printf (1, "???"); - errors++; - } debug_printf (1, "\n"); + g_assert_true (state.got_ntlm_prompt == get_ntlm_prompt); + g_assert_true (state.got_basic_prompt == get_basic_prompt); + g_assert_true (state.sent_ntlm_request == do_ntlm); + g_assert_true (state.got_ntlm_challenge == do_ntlm); + g_assert_true (state.sent_ntlm_response == do_ntlm); + g_assert_true (state.sent_basic_response == do_basic); + soup_test_assert_message_status (msg, status_code); + g_object_unref (msg); } @@ -363,12 +345,10 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, FALSE, FALSE, SOUP_STATUS_OK); - if (authenticated_ntlm != (use_ntlm && use_builtin_ntlm)) { - debug_printf (1, " ERROR: %s built-in NTLM support, but authenticate signal %s emitted\n", - use_builtin_ntlm ? "Using" : "Not using", - authenticated_ntlm ? "was" : "wasn't"); - errors++; - } + soup_test_assert (authenticated_ntlm == (use_ntlm && use_builtin_ntlm), + "%s built-in NTLM support, but authenticate signal %s emitted\n", + use_builtin_ntlm ? "Using" : "Not using", + authenticated_ntlm ? "was" : "wasn't"); /* 2. Server requires auth as Alice, so it will request that * if we didn't already authenticate the connection to her in @@ -463,6 +443,48 @@ do_ntlm_tests (SoupURI *base_uri, gboolean use_builtin_ntlm) do_ntlm_round (base_uri, FALSE, "alice", use_builtin_ntlm); } +static void +do_builtin_ntlm_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + + /* Built-in NTLM auth support. (We set SOUP_NTLM_AUTH_DEBUG to + * an empty string to ensure that the built-in support is + * being used, even if /usr/bin/ntlm_auth is available.) + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); + do_ntlm_tests (uri, TRUE); +} + +#ifdef USE_NTLM_AUTH +static void +do_winbind_ntlm_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + + /* Samba winbind /usr/bin/ntlm_auth helper support (via a + * helper program that emulates its interface). + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", BUILDDIR "/ntlm-test-helper", TRUE); + g_unsetenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS"); + do_ntlm_tests (uri, FALSE); +} + +static void +do_fallback_ntlm_test (gconstpointer data) +{ + SoupURI *uri = (SoupURI *)data; + + /* Support for when ntlm_auth is installed, but the user has + * no cached credentials (and thus we have to fall back to + * libsoup's built-in NTLM support). + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", BUILDDIR "/ntlm-test-helper", TRUE); + g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); + do_ntlm_tests (uri, TRUE); +} +#endif + static void retry_test_authenticate (SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying, @@ -483,13 +505,16 @@ retry_test_authenticate (SoupSession *session, SoupMessage *msg, } static void -do_retrying_test (SoupURI *base_uri) +do_retrying_test (gconstpointer data) { + SoupURI *base_uri = (SoupURI *)data; SoupSession *session; SoupMessage *msg; SoupURI *uri; gboolean retried = FALSE; + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); + debug_printf (1, " /alice\n"); session = soup_test_session_new (SOUP_TYPE_SESSION, @@ -504,15 +529,9 @@ do_retrying_test (SoupURI *base_uri) soup_session_send_message (session, msg); - if (!retried) { - debug_printf (1, " Didn't retry!\n"); - errors++; - } - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected final status %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + g_assert_true (retried); + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_object_unref (msg); soup_test_session_abort_unref (session); @@ -532,15 +551,9 @@ do_retrying_test (SoupURI *base_uri) soup_session_send_message (session, msg); - if (!retried) { - debug_printf (1, " Didn't retry!\n"); - errors++; - } - if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { - debug_printf (1, " Unexpected final status %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + g_assert_true (retried); + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); + g_object_unref (msg); soup_test_session_abort_unref (session); @@ -552,6 +565,7 @@ main (int argc, char **argv) SoupServer *server; GHashTable *connections; SoupURI *uri; + int ret; test_init (argc, argv, NULL); @@ -563,35 +577,14 @@ main (int argc, char **argv) uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (uri, soup_server_get_port (server)); - /* Built-in NTLM auth support. (We set SOUP_NTLM_AUTH_DEBUG to - * an empty string to ensure that the built-in support is - * being used, even if /usr/bin/ntlm_auth is available.) - */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); - debug_printf (1, "Built-in NTLM support\n"); - do_ntlm_tests (uri, TRUE); - + g_test_add_data_func ("/ntlm/builtin", uri, do_builtin_ntlm_test); #ifdef USE_NTLM_AUTH - /* Samba winbind /usr/bin/ntlm_auth helper support (via a - * helper program that emulates its interface). - */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG", BUILDDIR "/ntlm-test-helper", TRUE); - debug_printf (1, "\nExternal helper support\n"); - do_ntlm_tests (uri, FALSE); - - /* Support for when ntlm_auth is installed, but the user has - * no cached credentials (and thus we have to fall back to - * libsoup's built-in NTLM support). - */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); - debug_printf (1, "\nExternal -> fallback support\n"); - do_ntlm_tests (uri, TRUE); + g_test_add_data_func ("/ntlm/winbind", uri, do_winbind_ntlm_test); + g_test_add_data_func ("/ntlm/fallback", uri, do_fallback_ntlm_test); #endif + g_test_add_data_func ("/ntlm/retry", uri, do_retrying_test); - /* Other tests */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); - debug_printf (1, "\nRetrying on failed password\n"); - do_retrying_test (uri); + ret = g_test_run (); soup_uri_free (uri); @@ -599,5 +592,5 @@ main (int argc, char **argv) test_cleanup (); g_hash_table_destroy (connections); - return errors != 0; + return ret; } diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 682b5375..ceb2ff37 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -46,19 +46,15 @@ authenticate (SoupSession *session, SoupMessage *msg, SoupAuth *auth, gboolean retrying, gpointer data) { if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { - if (soup_auth_is_for_proxy (auth)) { - debug_printf (1, " got proxy auth object for 401!\n"); - errors++; - } + soup_test_assert (!soup_auth_is_for_proxy (auth), + "got proxy auth object for 401"); } else if (msg->status_code == SOUP_STATUS_PROXY_UNAUTHORIZED) { - if (!soup_auth_is_for_proxy (auth)) { - debug_printf (1, " got regular auth object for 407!\n"); - errors++; - } + soup_test_assert (soup_auth_is_for_proxy (auth), + "got regular auth object for 407"); } else { - debug_printf (1, " got authenticate signal with status %d\n", - msg->status_code); - errors++; + soup_test_assert (FALSE, + "got authenticate signal with status %d\n", + msg->status_code); } if (!retrying) @@ -120,10 +116,7 @@ test_url (const char *url, int proxy, guint expected, soup_session_send_message (session, msg); debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); - if (msg->status_code != expected) { - debug_printf (1, " EXPECTED %d!\n", expected); - errors++; - } + soup_test_assert_message_status (msg, expected); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -168,29 +161,18 @@ test_url_new_api (const char *url, int proxy, guint expected, msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (request)); stream = soup_test_request_send (request, NULL, 0, &error); - if (!stream) { - debug_printf (1, " Unexpected error on Request: %s\n", - error->message); - errors++; - g_clear_error (&error); - } + g_assert_no_error (error); + g_clear_error (&error); if (stream) { - soup_test_request_close_stream (request, stream, NULL, NULL); - if (error) { - debug_printf (1, " Unexpected error on close: %s\n", - error->message); - errors++; - g_clear_error (&error); - } + soup_test_request_close_stream (request, stream, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); g_object_unref (stream); } debug_printf (1, " %d %s\n", msg->status_code, msg->reason_phrase); - if (msg->status_code != expected) { - debug_printf (1, " EXPECTED %d!\n", expected); - errors++; - } + soup_test_assert_message_status (msg, expected); g_object_unref (msg); g_object_unref (request); @@ -199,20 +181,17 @@ test_url_new_api (const char *url, int proxy, guint expected, } static void -run_test (int i, gboolean sync) +do_proxy_test (SoupProxyTest *test, gboolean sync) { char *http_url, *https_url; - debug_printf (1, "Test %d: %s (%s)\n", i + 1, tests[i].explanation, - sync ? "sync" : "async"); - - if (!strncmp (tests[i].url, "http", 4)) { + if (!strncmp (test->url, "http", 4)) { SoupURI *uri; guint port; - http_url = g_strdup (tests[i].url); + http_url = g_strdup (test->url); - uri = soup_uri_new (tests[i].url); + uri = soup_uri_new (test->url); port = uri->port; soup_uri_set_scheme (uri, "https"); if (port) @@ -220,26 +199,26 @@ run_test (int i, gboolean sync) https_url = soup_uri_to_string (uri, FALSE); soup_uri_free (uri); } else { - http_url = g_strconcat (HTTP_SERVER, tests[i].url, NULL); - https_url = g_strconcat (HTTPS_SERVER, tests[i].url, NULL); + http_url = g_strconcat (HTTP_SERVER, test->url, NULL); + https_url = g_strconcat (HTTPS_SERVER, test->url, NULL); } - test_url (http_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE); - test_url_new_api (http_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE); - test_url (https_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE); - test_url_new_api (https_url, SIMPLE_PROXY, tests[i].final_status, sync, FALSE); + test_url (http_url, SIMPLE_PROXY, test->final_status, sync, FALSE); + test_url_new_api (http_url, SIMPLE_PROXY, test->final_status, sync, FALSE); + test_url (https_url, SIMPLE_PROXY, test->final_status, sync, FALSE); + test_url_new_api (https_url, SIMPLE_PROXY, test->final_status, sync, FALSE); - test_url (http_url, AUTH_PROXY, tests[i].final_status, sync, FALSE); - test_url_new_api (http_url, AUTH_PROXY, tests[i].final_status, sync, FALSE); - test_url (https_url, AUTH_PROXY, tests[i].final_status, sync, FALSE); - test_url_new_api (https_url, AUTH_PROXY, tests[i].final_status, sync, FALSE); - test_url (https_url, AUTH_PROXY, tests[i].final_status, sync, TRUE); - test_url_new_api (https_url, AUTH_PROXY, tests[i].final_status, sync, TRUE); + test_url (http_url, AUTH_PROXY, test->final_status, sync, FALSE); + test_url_new_api (http_url, AUTH_PROXY, test->final_status, sync, FALSE); + test_url (https_url, AUTH_PROXY, test->final_status, sync, FALSE); + test_url_new_api (https_url, AUTH_PROXY, test->final_status, sync, FALSE); + test_url (https_url, AUTH_PROXY, test->final_status, sync, TRUE); + test_url_new_api (https_url, AUTH_PROXY, test->final_status, sync, TRUE); - test_url (http_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE); - test_url_new_api (http_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE); - test_url (https_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE); - test_url_new_api (https_url, UNAUTH_PROXY, tests[i].final_status, sync, FALSE); + test_url (http_url, UNAUTH_PROXY, test->final_status, sync, FALSE); + test_url_new_api (http_url, UNAUTH_PROXY, test->final_status, sync, FALSE); + test_url (https_url, UNAUTH_PROXY, test->final_status, sync, FALSE); + test_url_new_api (https_url, UNAUTH_PROXY, test->final_status, sync, FALSE); g_free (http_url); g_free (https_url); @@ -247,61 +226,20 @@ run_test (int i, gboolean sync) debug_printf (1, "\n"); } -static gpointer -async_proxy_test_thread (gpointer num) +static void +do_async_proxy_test (gconstpointer data) { - GMainContext *context = g_main_context_new (); - - g_main_context_push_thread_default (context); - run_test (GPOINTER_TO_INT (num), FALSE); - g_main_context_pop_thread_default (context); - g_main_context_unref (context); + SoupProxyTest *test = (SoupProxyTest *)data; - return NULL; -} - -static gpointer -sync_proxy_test_thread (gpointer num) -{ - run_test (GPOINTER_TO_INT (num), TRUE); - return NULL; + do_proxy_test (test, FALSE); } static void -do_proxy_tests (void) +do_sync_proxy_test (gconstpointer data) { - int i; - - debug_printf (1, "Basic proxy tests\n"); - - if (parallelize) { - GThread *threads[ntests]; - - /* Doing the sync and async tests separately is faster - * than doing them both at the same time (hitting - * apache's connection limit maybe?) - */ - for (i = 0; i < ntests; i++) { - threads[i] = g_thread_new ("async_proxy_test", - async_proxy_test_thread, - GINT_TO_POINTER (i)); - } - for (i = 0; i < ntests; i++) - g_thread_join (threads[i]); - - for (i = 0; i < ntests; i++) { - threads[i] = g_thread_new ("sync_proxy_test", - sync_proxy_test_thread, - GINT_TO_POINTER (i)); - } - for (i = 0; i < ntests; i++) - g_thread_join (threads[i]); - } else { - for (i = 0; i < ntests; i++) { - run_test (i, FALSE); - run_test (i, TRUE); - } - } + SoupProxyTest *test = (SoupProxyTest *)data; + + do_proxy_test (test, TRUE); } static void @@ -315,8 +253,9 @@ server_callback (SoupServer *server, SoupMessage *msg, } static void -do_proxy_fragment_test (SoupURI *base_uri) +do_proxy_fragment_test (gconstpointer data) { + SoupURI *base_uri = (SoupURI *)data; SoupSession *session; SoupURI *proxy_uri, *req_uri; SoupMessage *msg; @@ -334,11 +273,7 @@ do_proxy_fragment_test (SoupURI *base_uri) soup_uri_free (req_uri); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " unexpected status %d %s!\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -370,17 +305,11 @@ do_proxy_redirect_test (void) soup_session_send_message (session, msg); new_uri = soup_message_get_uri (msg); - if (!strcmp (req_uri->path, new_uri->path)) { - debug_printf (1, " message was not redirected!\n"); - errors++; - } + soup_test_assert (strcmp (req_uri->path, new_uri->path) != 0, + "message was not redirected"); soup_uri_free (req_uri); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " unexpected status %d %s!\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -391,7 +320,8 @@ main (int argc, char **argv) { SoupServer *server; SoupURI *base_uri; - int i; + char *path; + int i, ret; test_init (argc, argv, NULL); apache_init (); @@ -406,15 +336,27 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); - do_proxy_tests (); - do_proxy_fragment_test (base_uri); - do_proxy_redirect_test (); + for (i = 0; i < ntests; i++) { + path = g_strdup_printf ("/proxy/async/%s", tests[i].explanation); + g_test_add_data_func (path, &tests[i], do_async_proxy_test); + g_free (path); + } + for (i = 0; i < ntests; i++) { + path = g_strdup_printf ("/proxy/sync/%s", tests[i].explanation); + g_test_add_data_func (path, &tests[i], do_sync_proxy_test); + g_free (path); + } + + g_test_add_data_func ("/proxy/fragment", base_uri, do_proxy_fragment_test); + g_test_add_func ("/proxy/redirect", do_proxy_redirect_test); + + ret = g_test_run (); soup_uri_free (base_uri); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } #else /* HAVE_APACHE */ diff --git a/tests/pull-api.c b/tests/pull-api.c index 070c2099..8060646b 100644 --- a/tests/pull-api.c +++ b/tests/pull-api.c @@ -163,9 +163,7 @@ fully_async_got_headers (SoupMessage *msg, gpointer user_data) */ return; } else if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " unexpected status: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; + soup_test_assert_message_status (msg, SOUP_STATUS_OK); return; } @@ -194,18 +192,10 @@ fully_async_got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer user_data) * test program, that means comparing it against * correct_response to make sure that we got the right data. */ - if (ad->read_so_far + chunk->length > correct_response->length) { - debug_printf (1, " read too far! (%lu > %lu)\n", - (unsigned long) (ad->read_so_far + chunk->length), - (unsigned long) correct_response->length); - errors++; - } else if (memcmp (chunk->data, - correct_response->data + ad->read_so_far, - chunk->length) != 0) { - debug_printf (1, " data mismatch in block starting at %lu\n", - (unsigned long) ad->read_so_far); - errors++; - } + g_assert_cmpint (ad->read_so_far + chunk->length, <=, correct_response->length); + soup_assert_cmpmem (chunk->data, chunk->length, + correct_response->data + ad->read_so_far, + chunk->length); ad->read_so_far += chunk->length; /* Now pause I/O, and prepare to read another chunk later. @@ -226,11 +216,7 @@ fully_async_finished (SoupSession *session, SoupMessage *msg, { FullyAsyncData *ad = user_data; - if (msg->status_code != ad->expected_status) { - debug_printf (1, " unexpected final status: %d %s !\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, ad->expected_status); if (ad->timeout != 0) g_source_remove (ad->timeout); @@ -242,6 +228,41 @@ fully_async_finished (SoupSession *session, SoupMessage *msg, g_main_loop_quit (ad->loop); } +static void +do_fast_async_test (gconstpointer data) +{ + const char *base_uri = data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), NULL); + do_fully_async_test (session, base_uri, "/", + TRUE, SOUP_STATUS_OK); + do_fully_async_test (session, base_uri, "/Basic/realm1/", + TRUE, SOUP_STATUS_UNAUTHORIZED); + do_fully_async_test (session, base_uri, "/Basic/realm2/", + TRUE, SOUP_STATUS_OK); + soup_test_session_abort_unref (session); +} + +static void +do_slow_async_test (gconstpointer data) +{ + const char *base_uri = data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + g_signal_connect (session, "authenticate", + G_CALLBACK (authenticate), NULL); + do_fully_async_test (session, base_uri, "/", + FALSE, SOUP_STATUS_OK); + do_fully_async_test (session, base_uri, "/Basic/realm1/", + FALSE, SOUP_STATUS_UNAUTHORIZED); + do_fully_async_test (session, base_uri, "/Basic/realm2/", + FALSE, SOUP_STATUS_OK); + soup_test_session_abort_unref (session); +} /* Pull API version 2: synchronous pull API via async I/O. */ @@ -286,14 +307,12 @@ do_synchronously_async_test (SoupSession *session, /* Send the message, get back headers */ sync_async_send (session, msg); - if (sync_async_is_finished (msg) && - expected_status == SOUP_STATUS_OK) { - debug_printf (1, " finished without reading response!\n"); - errors++; - } else if (!sync_async_is_finished (msg) && - expected_status != SOUP_STATUS_OK) { - debug_printf (1, " request failed to fail!\n"); - errors++; + if (expected_status == SOUP_STATUS_OK) { + soup_test_assert (!sync_async_is_finished (msg), + "finished without reading response"); + } else { + soup_test_assert (sync_async_is_finished (msg), + "request failed to fail"); } /* Now we're ready to read the response body (though we could @@ -305,32 +324,19 @@ do_synchronously_async_test (SoupSession *session, (unsigned long) read_so_far, (unsigned long) read_so_far + chunk->length); - if (read_so_far + chunk->length > correct_response->length) { - debug_printf (1, " read too far! (%lu > %lu)\n", - (unsigned long) read_so_far + chunk->length, - (unsigned long) correct_response->length); - errors++; - } else if (memcmp (chunk->data, - correct_response->data + read_so_far, - chunk->length) != 0) { - debug_printf (1, " data mismatch in block starting at %lu\n", - (unsigned long) read_so_far); - errors++; - } + g_assert_cmpint (read_so_far + chunk->length, <=, correct_response->length); + soup_assert_cmpmem (chunk->data, chunk->length, + correct_response->data + read_so_far, + chunk->length); + read_so_far += chunk->length; soup_buffer_free (chunk); } - if (!sync_async_is_finished (msg) || - (msg->status_code == SOUP_STATUS_OK && - read_so_far != correct_response->length)) { - debug_printf (1, " loop ended before message was fully read!\n"); - errors++; - } else if (msg->status_code != expected_status) { - debug_printf (1, " unexpected final status: %d %s !\n", - msg->status_code, msg->reason_phrase); - errors++; - } + g_assert_true (sync_async_is_finished (msg)); + soup_test_assert_message_status (msg, expected_status); + if (msg->status_code == SOUP_STATUS_OK) + g_assert_cmpint (read_so_far, ==, correct_response->length); sync_async_cleanup (msg); g_object_unref (msg); @@ -395,9 +401,7 @@ sync_async_got_headers (SoupMessage *msg, gpointer user_data) */ return; } else if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " unexpected status: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; + soup_test_assert_message_status (msg, SOUP_STATUS_OK); return; } @@ -475,44 +479,12 @@ sync_async_cleanup (SoupMessage *msg) g_free (ad); } - -int -main (int argc, char **argv) +static void +do_sync_async_test (gconstpointer data) { + const char *base_uri = data; SoupSession *session; - const char *base_uri; - test_init (argc, argv, NULL); - apache_init (); - - base_uri = "http://127.0.0.1:47524/"; - get_correct_response (base_uri); - - debug_printf (1, "\nFully async, fast requests\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - g_signal_connect (session, "authenticate", - G_CALLBACK (authenticate), NULL); - do_fully_async_test (session, base_uri, "/", - TRUE, SOUP_STATUS_OK); - do_fully_async_test (session, base_uri, "/Basic/realm1/", - TRUE, SOUP_STATUS_UNAUTHORIZED); - do_fully_async_test (session, base_uri, "/Basic/realm2/", - TRUE, SOUP_STATUS_OK); - soup_test_session_abort_unref (session); - - debug_printf (1, "\nFully async, slow requests\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - g_signal_connect (session, "authenticate", - G_CALLBACK (authenticate), NULL); - do_fully_async_test (session, base_uri, "/", - FALSE, SOUP_STATUS_OK); - do_fully_async_test (session, base_uri, "/Basic/realm1/", - FALSE, SOUP_STATUS_UNAUTHORIZED); - do_fully_async_test (session, base_uri, "/Basic/realm2/", - FALSE, SOUP_STATUS_OK); - soup_test_session_abort_unref (session); - - debug_printf (1, "\nSynchronously async\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), NULL); @@ -523,11 +495,31 @@ main (int argc, char **argv) do_synchronously_async_test (session, base_uri, "/Basic/realm2/", SOUP_STATUS_OK); soup_test_session_abort_unref (session); +} + + +int +main (int argc, char **argv) +{ + const char *base_uri; + int ret; + + test_init (argc, argv, NULL); + apache_init (); + + base_uri = "http://127.0.0.1:47524/"; + get_correct_response (base_uri); + + g_test_add_data_func ("/pull-api/async/fast", base_uri, do_fast_async_test); + g_test_add_data_func ("/pull-api/async/slow", base_uri, do_slow_async_test); + g_test_add_data_func ("/pull-api/sync-async", base_uri, do_sync_async_test); + + ret = g_test_run (); soup_buffer_free (correct_response); test_cleanup (); - return errors != 0; + return ret; } #else /* HAVE_APACHE */ diff --git a/tests/range-test.c b/tests/range-test.c index 00b8567d..89ae59c4 100644 --- a/tests/range-test.c +++ b/tests/range-test.c @@ -35,41 +35,39 @@ check_part (SoupMessageHeaders *headers, const char *body, gsize body_len, soup_message_headers_get_one (headers, "Content-Range")); if (!soup_message_headers_get_content_range (headers, &start, &end, &total_length)) { - debug_printf (1, " Could not find/parse Content-Range\n"); - errors++; + soup_test_assert (FALSE, "Could not find/parse Content-Range"); return; } if (total_length != full_response->length && total_length != -1) { - debug_printf (1, " Unexpected total length %" G_GINT64_FORMAT " in response\n", - total_length); - errors++; + soup_test_assert (FALSE, + "Unexpected total length %" G_GINT64_FORMAT " in response\n", + total_length); return; } if (check_start_end) { if ((expected_start >= 0 && start != expected_start) || (expected_start < 0 && start != full_response->length + expected_start)) { - debug_printf (1, " Unexpected range start %" G_GINT64_FORMAT " in response\n", - start); - errors++; + soup_test_assert (FALSE, + "Unexpected range start %" G_GINT64_FORMAT " in response\n", + start); return; } if ((expected_end >= 0 && end != expected_end) || (expected_end < 0 && end != full_response->length - 1)) { - debug_printf (1, " Unexpected range end %" G_GINT64_FORMAT " in response\n", - end); - errors++; + soup_test_assert (FALSE, + "Unexpected range end %" G_GINT64_FORMAT " in response\n", + end); return; } } if (end - start + 1 != body_len) { - debug_printf (1, " Range length (%d) does not match body length (%d)\n", - (int)(end - start) + 1, - (int)body_len); - errors++; + soup_test_assert (FALSE, "Range length (%d) does not match body length (%d)\n", + (int)(end - start) + 1, + (int)body_len); return; } @@ -87,42 +85,26 @@ do_single_range (SoupSession *session, SoupMessage *msg, soup_session_send_message (session, msg); - if (succeed) { - if (msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) { - debug_printf (1, " Unexpected status %d %s\n", - msg->status_code, msg->reason_phrase); - g_object_unref (msg); - errors++; - return; - } - } else { - if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { - debug_printf (1, " Got expected %d %s\n", - msg->status_code, msg->reason_phrase); - } else { + if (!succeed) { + soup_test_assert_message_status (msg, SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE); + if (msg->status_code != SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE) { const char *content_range; - debug_printf (1, " Unexpected status %d %s\n", - msg->status_code, msg->reason_phrase); content_range = soup_message_headers_get_one (msg->response_headers, "Content-Range"); if (content_range) debug_printf (1, " Content-Range: %s\n", content_range); - errors++; } g_object_unref (msg); return; } + soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT); + content_type = soup_message_headers_get_content_type ( msg->response_headers, NULL); - if (content_type && !strcmp (content_type, "multipart/byteranges")) { - debug_printf (1, " Response body should not have been multipart/byteranges\n"); - g_object_unref (msg); - errors++; - return; - } + g_assert_cmpstr (content_type, !=, "multipart/byteranges"); check_part (msg->response_headers, msg->response_body->data, msg->response_body->length, TRUE, start, end); @@ -153,38 +135,21 @@ do_multi_range (SoupSession *session, SoupMessage *msg, soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) { - debug_printf (1, " Unexpected status %d %s\n", - msg->status_code, msg->reason_phrase); - g_object_unref (msg); - errors++; - return; - } + soup_test_assert_message_status (msg, SOUP_STATUS_PARTIAL_CONTENT); content_type = soup_message_headers_get_content_type (msg->response_headers, NULL); - if (!content_type || strcmp (content_type, "multipart/byteranges") != 0) { - debug_printf (1, " Response Content-Type (%s) was not multipart/byteranges\n", - content_type); - g_object_unref (msg); - errors++; - return; - } + g_assert_cmpstr (content_type, ==, "multipart/byteranges"); multipart = soup_multipart_new_from_message (msg->response_headers, msg->response_body); if (!multipart) { - debug_printf (1, " Could not parse multipart\n"); + soup_test_assert (FALSE, "Could not parse multipart"); g_object_unref (msg); - errors++; return; } length = soup_multipart_get_length (multipart); - if (length != expected_return_ranges) { - debug_printf (1, " Expected %d ranges, got %d\n", - expected_return_ranges, length); - errors++; - } + g_assert_cmpint (length, ==, expected_return_ranges); for (i = 0; i < length; i++) { SoupMessageHeaders *headers; @@ -360,10 +325,8 @@ do_range_test (SoupSession *session, const char *uri, 10 * twelfths - 5, 11 * twelfths, expect_partial_coalesce ? 2 : 3); - if (memcmp (full_response->data, test_response, full_response->length) != 0) { - debug_printf (1, "\nfull_response and test_response don't match\n"); - errors++; - } + soup_assert_cmpmem (full_response->data, full_response->length, + test_response, full_response->length); debug_printf (1, "Requesting (invalid) %d-%d\n", (int) full_response->length + 1, @@ -381,6 +344,22 @@ do_range_test (SoupSession *session, const char *uri, 20, 30); } +static void +do_apache_range_test (void) +{ + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + +#if HAVE_APACHE_2_2 + do_range_test (session, "http://127.0.0.1:47524/", FALSE, FALSE); +#else + do_range_test (session, "http://127.0.0.1:47524/", TRUE, FALSE); +#endif + + soup_test_session_abort_unref (session); +} + static void server_handler (SoupServer *server, SoupMessage *msg, @@ -394,29 +373,15 @@ server_handler (SoupServer *server, full_response); } -int -main (int argc, char **argv) +static void +do_libsoup_range_test (void) { SoupSession *session; SoupServer *server; char *base_uri; - test_init (argc, argv, NULL); - apache_init (); - - get_full_response (); - test_response = g_malloc0 (full_response->length); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - debug_printf (1, "1. Testing against apache\n"); -#if HAVE_APACHE_2_2 - do_range_test (session, "http://127.0.0.1:47524/", FALSE, FALSE); -#else - do_range_test (session, "http://127.0.0.1:47524/", TRUE, FALSE); -#endif - - debug_printf (1, "\n2. Testing against SoupServer\n"); server = soup_test_server_new (FALSE); soup_server_add_handler (server, NULL, server_handler, NULL, NULL); base_uri = g_strdup_printf ("http://127.0.0.1:%u/", @@ -426,12 +391,29 @@ main (int argc, char **argv) soup_test_server_quit_unref (server); soup_test_session_abort_unref (session); +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + apache_init (); + + get_full_response (); + test_response = g_malloc0 (full_response->length); + + g_test_add_func ("/ranges/apache", do_apache_range_test); + g_test_add_func ("/ranges/libsoup", do_libsoup_range_test); + + ret = g_test_run (); soup_buffer_free (full_response); g_free (test_response); test_cleanup (); - return errors != 0; + return ret; } #else /* HAVE_APACHE */ diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 2b4fb5ea..b20a3187 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -5,7 +5,9 @@ #include "test-utils.h" +SoupURI *base_uri; char *server2_uri; +SoupSession *async_session, *sync_session; typedef struct { const char *method; @@ -14,11 +16,13 @@ typedef struct { gboolean repeat; } TestRequest; -static struct { +typedef struct { TestRequest requests[3]; guint final_status; guint request_api_final_status; -} tests[] = { +} TestCase; + +static TestCase tests[] = { /* A redirecty response to a GET or HEAD should cause a redirect */ { { { "GET", "/301", 301 }, @@ -131,11 +135,7 @@ got_headers (SoupMessage *msg, gpointer user_data) if (!(*treq)->method) return; - if (msg->status_code != (*treq)->status_code) { - debug_printf (1, " - Expected %d !\n", - (*treq)->status_code); - errors++; - } + soup_test_assert_message_status (msg, (*treq)->status_code); } static void @@ -149,35 +149,26 @@ restarted (SoupMessage *msg, gpointer user_data) if ((*treq)->method && !(*treq)->repeat) (*treq)++; - if (!(*treq)->method) { - debug_printf (1, " - Expected to be done!\n"); - errors++; - return; - } + soup_test_assert ((*treq)->method, + "Expected to be done"); - if (strcmp (msg->method, (*treq)->method) != 0) { - debug_printf (1, " - Expected %s !\n", (*treq)->method); - errors++; - } - if (strcmp (uri->path, (*treq)->path) != 0) { - debug_printf (1, " - Expected %s !\n", (*treq)->path); - errors++; - } + g_assert_cmpstr (msg->method, ==, (*treq)->method); + g_assert_cmpstr (uri->path, ==, (*treq)->path); } static void -do_message_api_test (SoupSession *session, SoupURI *base_uri, int n) +do_message_api_test (SoupSession *session, TestCase *test) { SoupURI *uri; SoupMessage *msg; TestRequest *treq; - debug_printf (1, "%2d. %s %s\n", n + 1, - tests[n].requests[0].method, - tests[n].requests[0].path); + debug_printf (1, "%s %s\n", + test->requests[0].method, + test->requests[0].path); - uri = soup_uri_new_with_base (base_uri, tests[n].requests[0].path); - msg = soup_message_new_from_uri (tests[n].requests[0].method, uri); + uri = soup_uri_new_with_base (base_uri, test->requests[0].path); + msg = soup_message_new_from_uri (test->requests[0].method, uri); soup_uri_free (uri); if (msg->method == SOUP_METHOD_POST) { @@ -187,7 +178,7 @@ do_message_api_test (SoupSession *session, SoupURI *base_uri, int n) strlen ("post body")); } - treq = &tests[n].requests[0]; + treq = &test->requests[0]; g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), &treq); g_signal_connect (msg, "restarted", @@ -195,18 +186,14 @@ do_message_api_test (SoupSession *session, SoupURI *base_uri, int n) soup_session_send_message (session, msg); - if (msg->status_code != tests[n].final_status) { - debug_printf (1, " - Expected final status of %d, got %d !\n", - tests[n].final_status, msg->status_code); - errors++; - } + soup_test_assert_message_status (msg, test->final_status); g_object_unref (msg); debug_printf (2, "\n"); } static void -do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) +do_request_api_test (SoupSession *session, TestCase *test) { SoupURI *uri; SoupRequestHTTP *reqh; @@ -216,24 +203,22 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) GError *error = NULL; guint final_status; - debug_printf (1, "%2d. %s %s\n", n + 1, - tests[n].requests[0].method, - tests[n].requests[0].path); + debug_printf (1, "%s %s\n", + test->requests[0].method, + test->requests[0].path); - final_status = tests[n].request_api_final_status; + final_status = test->request_api_final_status; if (!final_status) - final_status = tests[n].final_status; + final_status = test->final_status; - uri = soup_uri_new_with_base (base_uri, tests[n].requests[0].path); + uri = soup_uri_new_with_base (base_uri, test->requests[0].path); reqh = soup_session_request_http_uri (session, - tests[n].requests[0].method, + test->requests[0].method, uri, &error); soup_uri_free (uri); - if (!reqh) { - debug_printf (1, " could not create request: %s\n", - error->message); + g_assert_no_error (error); + if (error) { g_error_free (error); - errors++; debug_printf (2, "\n"); return; } @@ -246,7 +231,7 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) strlen ("post body")); } - treq = &tests[n].requests[0]; + treq = &test->requests[0]; g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), &treq); g_signal_connect (msg, "restarted", @@ -255,58 +240,37 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error); if (SOUP_STATUS_IS_TRANSPORT_ERROR (final_status)) { - if (stream) { - debug_printf (1, " expected failure (%s) but succeeded", - soup_status_get_phrase (final_status)); - errors++; - g_object_unref (stream); - } - if (error->domain != SOUP_HTTP_ERROR || - error->code != final_status) { - debug_printf (1, " expected '%s' but got '%s'", - soup_status_get_phrase (final_status), - error->message); - errors++; - } + g_assert_error (error, SOUP_HTTP_ERROR, final_status); + g_clear_error (&error); + + g_assert_null (stream); + g_clear_object (&stream); - g_error_free (error); g_object_unref (msg); g_object_unref (reqh); debug_printf (2, "\n"); return; - } else if (!stream) { - debug_printf (1, " could not send request: %s\n", - error->message); + } + + g_assert_no_error (error); + if (error) { g_error_free (error); g_object_unref (msg); g_object_unref (reqh); - errors++; debug_printf (2, "\n"); return; } soup_test_request_read_all (SOUP_REQUEST (reqh), stream, NULL, &error); - if (error) { - debug_printf (1, " could not read from stream: %s\n", - error->message); - g_error_free (error); - errors++; - } + g_assert_no_error (error); + g_clear_error (&error); soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error); - if (error) { - debug_printf (1, " could not close stream: %s\n", - error->message); - g_error_free (error); - errors++; - } + g_assert_no_error (error); + g_clear_error (&error); g_object_unref (stream); - if (msg->status_code != final_status) { - debug_printf (1, " - Expected final status of %d, got %d !\n", - final_status, msg->status_code); - errors++; - } + g_assert_cmpint (msg->status_code, ==, final_status); g_object_unref (msg); g_object_unref (reqh); @@ -314,30 +278,27 @@ do_request_api_test (SoupSession *session, SoupURI *base_uri, int n) } static void -do_redirect_tests (SoupURI *base_uri) +do_async_msg_api_test (gconstpointer test) { - SoupSession *session; - int n; - - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - NULL); - debug_printf (1, "Async session, SoupMessage\n"); - for (n = 0; n < n_tests; n++) - do_message_api_test (session, base_uri, n); - debug_printf (1, "\nAsync session, SoupRequest\n"); - for (n = 0; n < n_tests; n++) - do_request_api_test (session, base_uri, n); - soup_test_session_abort_unref (session); - - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - debug_printf (1, "\nSync session, SoupMessage\n"); - for (n = 0; n < n_tests; n++) - do_message_api_test (session, base_uri, n); - debug_printf (1, "\nSync session, SoupRequest\n"); - for (n = 0; n < n_tests; n++) - do_request_api_test (session, base_uri, n); - soup_test_session_abort_unref (session); + do_message_api_test (async_session, (TestCase *)test); +} + +static void +do_async_req_api_test (gconstpointer test) +{ + do_request_api_test (async_session, (TestCase *)test); +} + +static void +do_sync_msg_api_test (gconstpointer test) +{ + do_message_api_test (sync_session, (TestCase *)test); +} + +static void +do_sync_req_api_test (gconstpointer test) +{ + do_request_api_test (sync_session, (TestCase *)test); } typedef struct { @@ -350,11 +311,7 @@ typedef struct { static void msg2_finished (SoupSession *session, SoupMessage *msg2, gpointer user_data) { - if (!SOUP_STATUS_IS_SUCCESSFUL (msg2->status_code)) { - debug_printf (1, " msg2 failed: %d %s\n", - msg2->status_code, msg2->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg2, SOUP_STATUS_OK); } static void @@ -362,16 +319,12 @@ unpause_msg1 (SoupMessage *msg2, gpointer user_data) { ConnectionTestData *data = user_data; - if (!data->sock1) { - debug_printf (1, " msg1 has no connection?\n"); - errors++; - } else if (!data->sock2) { - debug_printf (1, " msg2 has no connection?\n"); - errors++; - } else if (data->sock1 == data->sock2) { - debug_printf (1, " Both messages sharing the same connection\n"); - errors++; - } + soup_test_assert (data->sock1 != NULL, + "msg1 has no connection"); + soup_test_assert (data->sock2 != NULL, + "msg2 has no connection"); + soup_test_assert (data->sock1 != data->sock2, + "Both messages sharing the same connection"); soup_session_unpause_message (data->session, data->msg1); } @@ -422,11 +375,10 @@ request_started (SoupSession *session, SoupMessage *msg, } static void -do_connection_test (SoupURI *base_uri) +do_connection_test (void) { ConnectionTestData data; - debug_printf (1, "\nConnection reuse\n"); memset (&data, 0, sizeof (data)); data.session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -441,11 +393,8 @@ do_connection_test (SoupURI *base_uri) G_CALLBACK (msg1_about_to_restart), &data); soup_session_send_message (data.session, data.msg1); - if (!SOUP_STATUS_IS_SUCCESSFUL (data.msg1->status_code)) { - debug_printf (1, " msg1 failed: %d %s\n", - data.msg1->status_code, data.msg1->reason_phrase); - errors++; - } + soup_test_assert_message_status (data.msg1, SOUP_STATUS_OK); + g_object_unref (data.msg1); soup_uri_free (data.uri1); soup_uri_free (data.uri2); @@ -550,29 +499,23 @@ server2_callback (SoupServer *server, SoupMessage *msg, soup_message_set_status (msg, SOUP_STATUS_OK); } -static gboolean run_tests = TRUE; - -static GOptionEntry no_test_entry[] = { - { "no-tests", 'n', G_OPTION_FLAG_REVERSE, - G_OPTION_ARG_NONE, &run_tests, - "Don't run tests, just run the test server", NULL }, - { NULL } -}; - int main (int argc, char **argv) { GMainLoop *loop; SoupServer *server, *server2; guint port; - SoupURI *base_uri; + char *path; + int n, ret; - test_init (argc, argv, no_test_entry); + test_init (argc, argv, NULL); server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); port = soup_server_get_port (server); + base_uri = soup_uri_new ("http://127.0.0.1"); + soup_uri_set_port (base_uri, port); server2 = soup_test_server_new (TRUE); soup_server_add_handler (server2, NULL, @@ -582,23 +525,49 @@ main (int argc, char **argv) loop = g_main_loop_new (NULL, TRUE); - if (run_tests) { - base_uri = soup_uri_new ("http://127.0.0.1"); - soup_uri_set_port (base_uri, port); - do_redirect_tests (base_uri); - do_connection_test (base_uri); - soup_uri_free (base_uri); - } else { - g_print ("Listening on port %d\n", port); - g_main_loop_run (loop); + async_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); + sync_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); + + for (n = 0; n < n_tests; n++) { + path = g_strdup_printf ("/redirect/async/msg/%d-%s-%d", n + , tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_async_msg_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/async/req/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_async_req_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/sync/msg/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_sync_msg_api_test); + g_free (path); + + path = g_strdup_printf ("/redirect/sync/req/%d-%s-%d", n, + tests[n].requests[0].method, + tests[n].requests[0].status_code); + g_test_add_data_func (path, &tests[n], do_sync_req_api_test); + g_free (path); } + g_test_add_func ("/redirect/reuse", do_connection_test); + + ret = g_test_run (); + g_main_loop_unref (loop); - g_free (server2_uri); + soup_uri_free (base_uri); soup_test_server_quit_unref (server); + g_free (server2_uri); soup_test_server_quit_unref (server2); - if (run_tests) - test_cleanup (); - return errors != 0; + soup_test_session_abort_unref (async_session); + soup_test_session_abort_unref (sync_session); + + return ret; } diff --git a/tests/requester-test.c b/tests/requester-test.c index a202c164..61a69f28 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -123,11 +123,8 @@ stream_closed (GObject *source, GAsyncResult *res, gpointer user_data) GInputStream *stream = G_INPUT_STREAM (source); GError *error = NULL; - if (!g_input_stream_close_finish (stream, res, &error)) { - debug_printf (1, " close failed: %s\n", error->message); - g_error_free (error); - errors++; - } + g_input_stream_close_finish (stream, res, &error); + g_assert_no_error (error); g_main_loop_quit (loop); g_object_unref (stream); } @@ -143,9 +140,8 @@ test_read_ready (GObject *source, GAsyncResult *res, gpointer user_data) nread = g_input_stream_read_finish (stream, res, &error); if (nread == -1) { - debug_printf (1, " read_async failed: %s\n", error->message); + g_assert_no_error (error); g_error_free (error); - errors++; g_input_stream_close (stream, NULL, NULL); g_object_unref (stream); g_main_loop_quit (loop); @@ -174,29 +170,18 @@ auth_test_sent (GObject *source, GAsyncResult *res, gpointer user_data) stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error); if (!stream) { - debug_printf (1, " send_async failed: %s\n", error->message); + g_assert_no_error (error); g_clear_error (&error); - errors++; g_main_loop_quit (loop); return; } msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (source)); - if (msg->status_code != SOUP_STATUS_UNAUTHORIZED) { - debug_printf (1, " GET failed: %d %s\n", msg->status_code, - msg->reason_phrase); - errors++; - g_main_loop_quit (loop); - return; - } + soup_test_assert_message_status (msg, SOUP_STATUS_UNAUTHORIZED); g_object_unref (msg); content_type = soup_request_get_content_type (SOUP_REQUEST (source)); - if (g_strcmp0 (content_type, "text/html") != 0) { - debug_printf (1, " failed to sniff Content-Type: got %s\n", - content_type ? content_type : "(NULL)"); - errors++; - } + g_assert_cmpstr (content_type, ==, "text/html"); g_input_stream_read_async (stream, buf, sizeof (buf), G_PRIORITY_DEFAULT, NULL, @@ -213,22 +198,13 @@ test_sent (GObject *source, GAsyncResult *res, gpointer user_data) stream = soup_request_send_finish (SOUP_REQUEST (source), res, &error); if (data->cancel) { - if (stream) { - debug_printf (1, " send_async succeeded??\n"); - errors++; - g_input_stream_close (stream, NULL, NULL); - g_object_unref (stream); - } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - debug_printf (1, " send_async failed with wrong error: %s\n", error->message); - errors++; - } + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_clear_error (&error); g_main_loop_quit (loop); return; } else { + g_assert_no_error (error); if (!stream) { - debug_printf (1, " send_async failed: %s\n", error->message); - errors++; g_main_loop_quit (loop); g_clear_error (&error); return; @@ -236,11 +212,7 @@ test_sent (GObject *source, GAsyncResult *res, gpointer user_data) } content_type = soup_request_get_content_type (SOUP_REQUEST (source)); - if (g_strcmp0 (content_type, "text/plain") != 0) { - debug_printf (1, " failed to sniff Content-Type: got %s\n", - content_type ? content_type : "(NULL)"); - errors++; - } + g_assert_cmpstr (content_type, ==, "text/plain"); g_input_stream_read_async (stream, buf, sizeof (buf), G_PRIORITY_DEFAULT, NULL, @@ -307,44 +279,20 @@ do_async_test (SoupSession *session, SoupURI *uri, g_signal_handler_disconnect (session, started_id); - if (msg->status_code != expected_status) { - debug_printf (1, " GET failed: %d %s (expected %d)\n", - msg->status_code, msg->reason_phrase, - expected_status); - g_object_unref (msg); - g_object_unref (socket); - errors++; - return; - } + soup_test_assert_message_status (msg, expected_status); g_object_unref (msg); - if (!expected_response) { - if (data.body->len) { - debug_printf (1, " body length mismatch: expected 0, got %d\n", - (int)data.body->len); - errors++; - } - } else if (data.body->len != expected_response->length) { - debug_printf (1, " body length mismatch: expected %d, got %d\n", - (int)expected_response->length, (int)data.body->len); - errors++; - } else if (memcmp (data.body->str, expected_response->data, - expected_response->length) != 0) { - debug_printf (1, " body data mismatch\n"); - errors++; - } + if (expected_response) { + soup_assert_cmpmem (data.body->str, data.body->len, + expected_response->data, expected_response->length); + } else + g_assert_cmpint (data.body->len, ==, 0); + + if (persistent) + g_assert_true (soup_socket_is_connected (socket)); + else + g_assert_false (soup_socket_is_connected (socket)); - if (persistent) { - if (!soup_socket_is_connected (socket)) { - debug_printf (1, " socket not still connected!\n"); - errors++; - } - } else { - if (soup_socket_is_connected (socket)) { - debug_printf (1, " socket still connected!\n"); - errors++; - } - } g_object_unref (socket); g_string_free (data.body, TRUE); @@ -404,18 +352,20 @@ do_test_for_thread_and_context (SoupSession *session, const char *base_uri) } static void -do_simple_tests (const char *uri) +do_simple_plain_test (gconstpointer uri) { SoupSession *session; - debug_printf (1, "Simple streaming test\n"); - - debug_printf (1, " SoupSession\n"); session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); do_test_for_thread_and_context (session, uri); soup_test_session_abort_unref (session); +} + +static void +do_simple_async_test (gconstpointer uri) +{ + SoupSession *session; - debug_printf (1, " SoupSessionAsync\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -444,45 +394,50 @@ do_test_with_context_and_type (const char *uri, gboolean plain_session) g_main_context_unref (async_context); } -static gpointer -do_test_with_context (gpointer uri) +static void +do_async_test_with_context (gconstpointer uri) { - debug_printf (1, " SoupSessionAsync\n"); do_test_with_context_and_type (uri, FALSE); - return NULL; +} + +static void +do_plain_test_with_context (gconstpointer uri) +{ + do_test_with_context_and_type (uri, TRUE); } static gpointer -do_plain_test_with_context (gpointer uri) +async_test_thread (gpointer uri) { - debug_printf (1, " SoupSession\n"); do_test_with_context_and_type (uri, TRUE); return NULL; } -static void -do_context_tests (const char *uri) +static gpointer +plain_test_thread (gpointer uri) { - debug_printf (1, "\nStreaming with a non-default-context\n"); - - do_plain_test_with_context ((gpointer)uri); - do_test_with_context ((gpointer)uri); + do_test_with_context_and_type (uri, FALSE); + return NULL; } static void -do_thread_tests (const char *uri) +do_async_test_in_thread (gconstpointer uri) { GThread *thread; - debug_printf (1, "\nStreaming in another thread\n"); - - thread = g_thread_new ("do_test_with_context", - do_plain_test_with_context, + thread = g_thread_new ("do_async_test_in_thread", + async_test_thread, (gpointer)uri); g_thread_join (thread); +} - thread = g_thread_new ("do_test_with_context", - do_test_with_context, +static void +do_plain_test_in_thread (gconstpointer uri) +{ + GThread *thread; + + thread = g_thread_new ("do_plain_test_in_thread", + plain_test_thread, (gpointer)uri); g_thread_join (thread); } @@ -514,88 +469,49 @@ do_sync_request (SoupSession *session, SoupRequest *request, in = soup_request_send (request, NULL, &error); g_signal_handler_disconnect (session, started_id); if (cancel) { - if (in) { - debug_printf (1, " send succeeded??\n"); - errors++; - g_input_stream_close (in, NULL, NULL); - g_object_unref (in); - } else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - debug_printf (1, " send failed with wrong error: %s\n", error->message); - errors++; - } + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); g_clear_error (&error); g_object_unref (msg); g_object_unref (socket); return; } else if (!in) { - debug_printf (1, " soup_request_send failed: %s\n", - error->message); - g_object_unref (msg); + g_assert_no_error (error); g_clear_error (&error); - g_object_unref (socket); - errors++; - return; - } - - if (msg->status_code != expected_status) { - debug_printf (1, " GET failed: %d %s\n", msg->status_code, - msg->reason_phrase); g_object_unref (msg); - g_object_unref (in); g_object_unref (socket); - errors++; return; } + + soup_test_assert_message_status (msg, expected_status); g_object_unref (msg); body = g_string_new (NULL); do { nread = g_input_stream_read (in, buf, sizeof (buf), NULL, &error); + g_assert_no_error (error); if (nread == -1) { - debug_printf (1, " g_input_stream_read failed: %s\n", - error->message); g_clear_error (&error); - errors++; break; } g_string_append_len (body, buf, nread); } while (nread > 0); - if (!g_input_stream_close (in, NULL, &error)) { - debug_printf (1, " g_input_stream_close failed: %s\n", - error->message); - g_clear_error (&error); - errors++; - } + g_input_stream_close (in, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); g_object_unref (in); - if (!expected_response) { - if (body->len) { - debug_printf (1, " body length mismatch: expected 0, got %d\n", - (int)body->len); - errors++; - } - } else if (body->len != expected_response->length) { - debug_printf (1, " body length mismatch: expected %d, got %d\n", - (int)expected_response->length, (int)body->len); - errors++; - } else if (memcmp (body->str, expected_response->data, body->len) != 0) { - debug_printf (1, " body data mismatch\n"); - errors++; - } + if (expected_response) { + soup_assert_cmpmem (body->str, body->len, + expected_response->data, expected_response->length); + } else + g_assert_cmpint (body->len, ==, 0); - if (persistent) { - if (!soup_socket_is_connected (socket)) { - debug_printf (1, " socket not still connected!\n"); - errors++; - } - } else { - if (soup_socket_is_connected (socket)) { - debug_printf (1, " socket still connected!\n"); - errors++; - } - } + if (persistent) + g_assert_true (soup_socket_is_connected (socket)); + else + g_assert_false (soup_socket_is_connected (socket)); g_object_unref (socket); g_string_free (body, TRUE); @@ -670,24 +586,26 @@ do_sync_tests_for_session (SoupSession *session, const char *uri_string) } static void -do_sync_tests (const char *uri_string) +do_plain_sync_test (gconstpointer uri) { SoupSession *session; - SoupRequester *requester; - debug_printf (1, "\nSync streaming\n"); - - debug_printf (1, " SoupSession\n"); session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); - do_sync_tests_for_session (session, uri_string); + do_sync_tests_for_session (session, uri); soup_test_session_abort_unref (session); +} + +static void +do_sync_sync_test (gconstpointer uri) +{ + SoupSession *session; + SoupRequester *requester; - debug_printf (1, " SoupSessionSync\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); requester = soup_requester_new (); soup_session_add_feature (session, SOUP_SESSION_FEATURE (requester)); g_object_unref (requester); - do_sync_tests_for_session (session, uri_string); + do_sync_tests_for_session (session, uri); soup_test_session_abort_unref (session); } @@ -708,10 +626,8 @@ do_null_char_request (SoupSession *session, const char *encoded_data, request = soup_session_request_uri (session, uri, NULL); stream = soup_test_request_send (request, NULL, 0, &error); - + g_assert_no_error (error); if (error) { - debug_printf (1, " could not send request: %s\n", error->message); - errors++; g_error_free (error); g_object_unref (request); soup_uri_free (uri); @@ -719,27 +635,14 @@ do_null_char_request (SoupSession *session, const char *encoded_data, } g_input_stream_read_all (stream, buf, sizeof (buf), &nread, NULL, &error); - if (error) { - debug_printf (1, " could not read response: %s\n", error->message); - errors++; - g_clear_error (&error); - } + g_assert_no_error (error); + g_clear_error (&error); soup_test_request_close_stream (request, stream, NULL, &error); - if (error) { - debug_printf (1, " could not close stream: %s\n", error->message); - errors++; - g_clear_error (&error); - } + g_assert_no_error (error); + g_clear_error (&error); - if (nread != expected_len) { - debug_printf (1, " response length mismatch: expected %d, got %lu\n", - expected_len, (gulong)nread); - errors++; - } else if (memcmp (buf, expected_data, nread) != 0) { - debug_printf (1, " response data mismatch\n"); - errors++; - } + soup_assert_cmpmem (buf, nread, expected_data, expected_len); g_object_unref (stream); g_object_unref (request); @@ -768,18 +671,20 @@ do_null_char_test_for_session (SoupSession *session) } static void -do_null_char_tests (void) +do_plain_null_char_test (void) { SoupSession *session; - debug_printf (1, "\nStreaming data URLs containing null chars\n"); - - debug_printf (1, " SoupSession\n"); session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); do_null_char_test_for_session (session); soup_test_session_abort_unref (session); +} + +static void +do_async_null_char_test (void) +{ + SoupSession *session; - debug_printf (1, " SoupSessionAsync\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -812,10 +717,8 @@ do_close_test_for_session (SoupSession *session, request = soup_session_request_uri (session, uri, NULL); stream = soup_test_request_send (request, NULL, 0, &error); - + g_assert_no_error (error); if (error) { - debug_printf (1, " could not send request: %s\n", error->message); - errors++; g_error_free (error); g_object_unref (request); return; @@ -823,17 +726,11 @@ do_close_test_for_session (SoupSession *session, start = g_get_monotonic_time (); soup_test_request_close_stream (request, stream, NULL, &error); - if (error) { - debug_printf (1, " could not close stream: %s\n", error->message); - errors++; - g_clear_error (&error); - } + g_assert_no_error (error); + g_clear_error (&error); end = g_get_monotonic_time (); - if (end - start > 500000) { - debug_printf (1, " close() waited for response to complete!\n"); - errors++; - } + g_assert_cmpint (end - start, <=, 500000); g_object_unref (stream); g_object_unref (request); @@ -847,9 +744,8 @@ do_close_test_for_session (SoupSession *session, g_object_unref (msg); stream = soup_test_request_send (request, NULL, 0, &error); + g_assert_no_error (error); if (error) { - debug_printf (1, " could not send request: %s\n", error->message); - errors++; g_error_free (error); g_object_unref (request); return; @@ -858,39 +754,43 @@ do_close_test_for_session (SoupSession *session, cancellable = g_cancellable_new (); g_cancellable_cancel (cancellable); soup_test_request_close_stream (request, stream, cancellable, &error); - if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - debug_printf (1, " did not get expected error: %s\n", error->message); - errors++; - g_clear_error (&error); - } + if (error) + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED); + g_clear_error (&error); - if (!finished) { - debug_printf (1, " message did not finish!\n"); - errors++; - } + g_assert_true (finished); g_object_unref (stream); g_object_unref (request); } static void -do_close_tests (const char *uri) +do_async_close_test (gconstpointer uri) { SoupSession *session; SoupURI *slow_uri; - debug_printf (1, "\nClosing stream before end should cancel\n"); - slow_uri = soup_uri_new (uri); soup_uri_set_path (slow_uri, "/slow"); - debug_printf (1, " SoupSessionAsync\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); do_close_test_for_session (session, slow_uri); soup_test_session_abort_unref (session); + soup_uri_free (slow_uri); +} + +static void +do_sync_close_test (gconstpointer uri) +{ + SoupSession *session; + SoupURI *slow_uri; + + slow_uri = soup_uri_new (uri); + soup_uri_set_path (slow_uri, "/slow"); + debug_printf (1, " SoupSessionSync\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, @@ -905,6 +805,7 @@ int main (int argc, char **argv) { char *uri; + int ret; test_init (argc, argv, NULL); get_index (); @@ -914,12 +815,20 @@ main (int argc, char **argv) uri = g_strdup_printf ("http://127.0.0.1:%u/foo", soup_server_get_port (server)); - do_simple_tests (uri); - do_thread_tests (uri); - do_context_tests (uri); - do_sync_tests (uri); - do_null_char_tests (); - do_close_tests (uri); + g_test_add_data_func ("/requester/simple/SoupSession", uri, do_simple_plain_test); + g_test_add_data_func ("/requester/simple/SoupSessionAsync", uri, do_simple_async_test); + g_test_add_data_func ("/requester/threaded/SoupSession", uri, do_plain_test_in_thread); + g_test_add_data_func ("/requester/threaded/SoupSessionAsync", uri, do_async_test_in_thread); + g_test_add_data_func ("/requester/context/SoupSession", uri, do_plain_test_with_context); + g_test_add_data_func ("/requester/context/SoupSessionAsync", uri, do_async_test_with_context); + g_test_add_data_func ("/requester/sync/SoupSession", uri, do_plain_sync_test); + g_test_add_data_func ("/requester/sync/SoupSessionSync", uri, do_sync_sync_test); + g_test_add_func ("/requester/null-char/SoupSession", do_plain_null_char_test); + g_test_add_func ("/requester/null-char/SoupSessionAsync", do_async_null_char_test); + g_test_add_data_func ("/requester/close/SoupSessionAsync", uri, do_async_close_test); + g_test_add_data_func ("/requester/close/SoupSessionSync", uri, do_sync_close_test); + + ret = g_test_run (); g_free (uri); soup_buffer_free (response); @@ -927,5 +836,5 @@ main (int argc, char **argv) soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/resource-test.c b/tests/resource-test.c index 21e2f98e..e41c6032 100644 --- a/tests/resource-test.c +++ b/tests/resource-test.c @@ -39,19 +39,6 @@ register_gresource (void) g_resource_unref (resource); } -static void -check_results (GString *body) -{ - if (body->len != index_buffer->length) { - debug_printf (1, " body length mismatch: expected %d, got %d\n", - (int)index_buffer->length, (int)body->len); - errors++; - } else if (memcmp (body->str, index_buffer->data, body->len) != 0) { - debug_printf (1, " body data mismatch\n"); - errors++; - } -} - typedef struct { GString *body; char buffer[1024]; @@ -65,11 +52,8 @@ stream_closed (GObject *source, GAsyncResult *result, gpointer user_data) AsyncRequestData *data = user_data; GError *error = NULL; - if (!g_input_stream_close_finish (in, result, &error)) { - debug_printf (1, " close failed: %s\n", error->message); - g_error_free (error); - errors++; - } + g_input_stream_close_finish (in, result, &error); + g_assert_no_error (error); g_main_loop_quit (data->loop); g_object_unref (in); } @@ -84,12 +68,10 @@ test_read_ready (GObject *source, GAsyncResult *result, gpointer user_data) nread = g_input_stream_read_finish (in, result, &error); if (nread == -1) { - debug_printf (1, " g_input_stream_read failed: %s\n", - error->message); + g_assert_no_error (error); g_clear_error (&error); g_input_stream_close (in, NULL, NULL); g_object_unref (in); - errors++; return; } else if (nread == 0) { g_input_stream_close_async (in, G_PRIORITY_DEFAULT, NULL, @@ -112,10 +94,8 @@ async_request_sent (GObject *source, GAsyncResult *result, gpointer user_data) in = soup_request_send_finish (SOUP_REQUEST (source), result, &error); if (!in) { - debug_printf (1, " soup_request_send_async failed: %s\n", - error->message); + g_assert_no_error (error); g_clear_error (&error); - errors++; return; } @@ -136,7 +116,8 @@ do_async_request (SoupRequest *request) g_main_loop_run (data.loop); g_main_loop_unref (data.loop); - check_results (data.body); + soup_assert_cmpmem (data.body->str, data.body->len, + index_buffer->data, index_buffer->length); g_string_free (data.body, TRUE); } @@ -151,10 +132,8 @@ do_sync_request (SoupRequest *request) in = soup_request_send (request, NULL, &error); if (!in) { - debug_printf (1, " soup_request_send failed: %s\n", - error->message); + g_assert_no_error (error); g_clear_error (&error); - errors++; return; } @@ -163,127 +142,111 @@ do_sync_request (SoupRequest *request) nread = g_input_stream_read (in, buffer, sizeof (buffer), NULL, &error); if (nread == -1) { - debug_printf (1, " g_input_stream_read failed: %s\n", - error->message); + g_assert_no_error (error); g_clear_error (&error); - errors++; break; } g_string_append_len (body, buffer, nread); } while (nread > 0); - if (!g_input_stream_close (in, NULL, &error)) { - debug_printf (1, " g_input_stream_close failed: %s\n", - error->message); - g_clear_error (&error); - errors++; - } + g_input_stream_close (in, NULL, &error); + g_assert_no_error (error); + g_clear_error (&error); g_object_unref (in); - check_results (body); + soup_assert_cmpmem (body->str, body->len, index_buffer->data, index_buffer->length); g_string_free (body, TRUE); } static void -do_request_file_test (SoupSession *session, - gboolean async) +do_request (const char *uri_string, gconstpointer type) { + SoupSession *session; SoupRequest *request; - GFile *index; - char *uri_string; - SoupURI *uri; + GError *error = NULL; - index = g_file_new_for_path (SRCDIR "/index.txt"); - uri_string = g_file_get_uri (index); - g_object_unref (index); + session = soup_test_session_new (GPOINTER_TO_SIZE (type), + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); - uri = soup_uri_new (uri_string); - g_free (uri_string); + request = soup_session_request (session, uri_string, &error); + g_assert_no_error (error); - request = soup_session_request_uri (session, uri, NULL); - if (async) + if (SOUP_IS_SESSION_ASYNC (session)) do_async_request (request); else do_sync_request (request); + g_object_unref (request); + soup_test_session_abort_unref (session); +} - soup_uri_free (uri); +static void +do_request_file_test (gconstpointer type) +{ + GFile *index; + char *uri_string; + + index = g_file_new_for_path (SRCDIR "/index.txt"); + uri_string = g_file_get_uri (index); + g_object_unref (index); + + do_request (uri_string, type); + g_free (uri_string); } static void -do_request_data_test (SoupSession *session, - gboolean async) +do_request_data_test (gconstpointer type) { - SoupRequest *request; gchar *base64; char *uri_string; - SoupURI *uri; base64 = g_base64_encode ((const guchar *)index_buffer->data, index_buffer->length); uri_string = g_strdup_printf ("data:text/plain;charset=utf8;base64,%s", base64); g_free (base64); - uri = soup_uri_new (uri_string); + do_request (uri_string, type); g_free (uri_string); - - request = soup_session_request_uri (session, uri, NULL); - if (async) - do_async_request (request); - else - do_sync_request (request); - g_object_unref (request); - - soup_uri_free (uri); } static void -do_request_gresource_test (SoupSession *session, - gboolean async) +do_request_gresource_test (gconstpointer type) { - SoupRequest *request; - SoupURI *uri; - - uri = soup_uri_new ("resource:///org/gnome/libsoup/tests/index.txt"); - request = soup_session_request_uri (session, uri, NULL); - if (async) - do_async_request (request); - else - do_sync_request (request); - g_object_unref (request); - - soup_uri_free (uri); + do_request ("resource:///org/gnome/libsoup/tests/index.txt", type); } int main (int argc, char **argv) { - SoupSession *session; + int ret; test_init (argc, argv, NULL); get_index (); register_gresource (); - /* Sync tests */ - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - - do_request_file_test (session, FALSE); - do_request_data_test (session, FALSE); - do_request_gresource_test (session, FALSE); - - soup_test_session_abort_unref (session); - - /* Async tests */ - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - NULL); - - do_request_file_test (session, TRUE); - do_request_data_test (session, TRUE); - do_request_gresource_test (session, TRUE); - - soup_test_session_abort_unref (session); + g_test_add_data_func ("/resource/sync/file", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC), + do_request_file_test); + g_test_add_data_func ("/resource/sync/data", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC), + do_request_data_test); + g_test_add_data_func ("/resource/sync/gresource", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC), + do_request_gresource_test); + + g_test_add_data_func ("/resource/async/file", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC), + do_request_file_test); + g_test_add_data_func ("/resource/async/data", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC), + do_request_data_test); + g_test_add_data_func ("/resource/async/gresource", + GSIZE_TO_POINTER (SOUP_TYPE_SESSION_ASYNC), + do_request_gresource_test); + + ret = g_test_run (); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/server-auth-test.c b/tests/server-auth-test.c index 78cd0686..77a5dba1 100644 --- a/tests/server-auth-test.c +++ b/tests/server-auth-test.c @@ -90,46 +90,18 @@ do_test (int n, SoupURI *base_uri, const char *path, g_ptr_array_free (args, TRUE); g_free (uri_str); - if (server_requests_basic != test_data.server_requested_basic) { - errors++; - if (test_data.server_requested_basic) - debug_printf (1, " Server sent WWW-Authenticate: Basic, but shouldn't have!\n"); - else - debug_printf (1, " Server didn't send WWW-Authenticate: Basic, but should have!\n"); - } - if (server_requests_digest != test_data.server_requested_digest) { - errors++; - if (test_data.server_requested_digest) - debug_printf (1, " Server sent WWW-Authenticate: Digest, but shouldn't have!\n"); - else - debug_printf (1, " Server didn't send WWW-Authenticate: Digest, but should have!\n"); - } - if (client_sends_basic != test_data.client_sent_basic) { - errors++; - if (test_data.client_sent_basic) - debug_printf (1, " Client sent Authorization: Basic, but shouldn't have!\n"); - else - debug_printf (1, " Client didn't send Authorization: Basic, but should have!\n"); - } - if (client_sends_digest != test_data.client_sent_digest) { - errors++; - if (test_data.client_sent_digest) - debug_printf (1, " Client sent Authorization: Digest, but shouldn't have!\n"); - else - debug_printf (1, " Client didn't send Authorization: Digest, but should have!\n"); - } - if (success && !test_data.succeeded) { - errors++; - debug_printf (1, " Should have succeeded, but didn't!\n"); - } else if (!success && test_data.succeeded) { - errors++; - debug_printf (1, " Should not have succeeded, but did!\n"); - } + g_assert_cmpint (server_requests_basic, ==, test_data.server_requested_basic); + g_assert_cmpint (server_requests_digest, ==, test_data.server_requested_digest); + g_assert_cmpint (client_sends_basic, ==, test_data.client_sent_basic); + g_assert_cmpint (client_sends_digest, ==, test_data.client_sent_digest); + + g_assert_cmpint (success, ==, test_data.succeeded); } static void -do_auth_tests (SoupURI *base_uri) +do_auth_tests (gconstpointer data) { + SoupURI *base_uri = (SoupURI *)data; int i, n = 1; gboolean use_basic, use_digest, good_user, good_password; gboolean preemptive_basic, good_auth; @@ -317,6 +289,7 @@ main (int argc, char **argv) SoupServer *server; SoupURI *uri; SoupAuthDomain *auth_domain; + int ret; test_init (argc, argv, no_test_entry); @@ -351,11 +324,17 @@ main (int argc, char **argv) if (run_tests) { uri = soup_uri_new ("http://127.0.0.1"); soup_uri_set_port (uri, soup_server_get_port (server)); - do_auth_tests (uri); + + /* FIXME: split this up! */ + g_test_add_data_func ("/server-auth", uri, do_auth_tests); + + ret = g_test_run (); + soup_uri_free (uri); } else { g_print ("Listening on port %d\n", soup_server_get_port (server)); g_main_loop_run (loop); + ret = 0; } g_main_loop_unref (loop); @@ -363,7 +342,7 @@ main (int argc, char **argv) if (run_tests) test_cleanup (); - return errors != 0; + return ret; } #else /* HAVE_CURL */ diff --git a/tests/server-test.c b/tests/server-test.c index 3ff7cadd..ec5b6901 100644 --- a/tests/server-test.c +++ b/tests/server-test.c @@ -17,8 +17,7 @@ server_callback (SoupServer *server, SoupMessage *msg, "X-Handled-By", "server_callback"); if (!strcmp (path, "*")) { - debug_printf (1, " default server_callback got request for '*'!\n"); - errors++; + soup_test_assert (FALSE, "default server_callback got request for '*'"); soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; } @@ -42,8 +41,7 @@ server_star_callback (SoupServer *server, SoupMessage *msg, "X-Handled-By", "star_callback"); if (strcmp (path, "*") != 0) { - debug_printf (1, " server_star_callback got request for '%s'!\n", path); - errors++; + soup_test_assert (FALSE, "server_star_callback got request for '%s'", path); soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; } @@ -77,19 +75,10 @@ do_star_test (void) msg = soup_message_new_from_uri ("OPTIONS", star_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_NOT_FOUND) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_NOT_FOUND); handled_by = soup_message_headers_get_one (msg->response_headers, "X-Handled-By"); - if (handled_by) { - /* Should have been rejected by SoupServer directly */ - debug_printf (1, " Message reached handler '%s'\n", - handled_by); - errors++; - } + g_assert_cmpstr (handled_by, ==, NULL); g_object_unref (msg); soup_server_add_handler (server, "*", server_star_callback, NULL, NULL); @@ -98,21 +87,10 @@ do_star_test (void) msg = soup_message_new_from_uri ("OPTIONS", star_uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " Unexpected response: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); handled_by = soup_message_headers_get_one (msg->response_headers, "X-Handled-By"); - if (!handled_by) { - debug_printf (1, " Message did not reach handler!\n"); - errors++; - } else if (strcmp (handled_by, "star_callback") != 0) { - debug_printf (1, " Message reached incorrect handler '%s'\n", - handled_by); - errors++; - } + g_assert_cmpstr (handled_by, ==, "star_callback"); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -150,10 +128,8 @@ do_one_server_aliases_test (SoupURI *uri, g_object_unref (addr); g_object_unref (client); if (!conn) { - debug_printf (1, " error connecting to server: %s\n", - error->message); + g_assert_no_error (error); g_error_free (error); - errors++; return; } @@ -168,10 +144,8 @@ do_one_server_aliases_test (SoupURI *uri, g_string_append (req, "Connection: close\r\n\r\n"); if (!g_output_stream_write_all (out, req->str, req->len, NULL, NULL, &error)) { - debug_printf (1, " error sending request: %s\n", - error->message); + g_assert_no_error (error); g_error_free (error); - errors++; g_object_unref (conn); g_string_free (req, TRUE); return; @@ -179,20 +153,16 @@ do_one_server_aliases_test (SoupURI *uri, g_string_free (req, TRUE); if (!g_input_stream_read_all (in, buf, sizeof (buf), NULL, NULL, &error)) { - debug_printf (1, " error reading response: %s\n", - error->message); + g_assert_no_error (error); g_error_free (error); - errors++; g_object_unref (conn); return; } - if ((succeed && !g_str_has_prefix (buf, "HTTP/1.1 200 ")) || - (!succeed && !g_str_has_prefix (buf, "HTTP/1.1 400 "))) { - debug_printf (1, " unexpected response: %.*s\n", - (int) strcspn (buf, "\r\n"), buf); - errors++; - } + if (succeed) + g_assert_true (g_str_has_prefix (buf, "HTTP/1.1 200 ")); + else + g_assert_true (g_str_has_prefix (buf, "HTTP/1.1 400 ")); g_io_stream_close (G_IO_STREAM (conn), NULL, NULL); g_object_unref (conn); @@ -238,12 +208,7 @@ do_dot_dot_test (void) soup_uri_free (uri); soup_session_send_message (session, msg); - - if (msg->status_code != SOUP_STATUS_BAD_REQUEST) { - debug_printf (1, " FAILED: %d %s (expected Bad Request)\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_BAD_REQUEST); g_object_unref (msg); soup_test_session_abort_unref (session); @@ -257,24 +222,16 @@ ipv6_server_callback (SoupServer *server, SoupMessage *msg, const char *host; char expected_host[128]; - host = soup_message_headers_get_one (msg->request_headers, "Host"); - if (!host) { - debug_printf (1, " request has no Host header!\n"); - errors++; - soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); - return; - } - g_snprintf (expected_host, sizeof (expected_host), "[::1]:%d", soup_server_get_port (server)); - if (strcmp (host, expected_host) == 0) - soup_message_set_status (msg, SOUP_STATUS_OK); - else { - debug_printf (1, " request has incorrect Host header '%s'\n", host); - errors++; + host = soup_message_headers_get_one (msg->request_headers, "Host"); + g_assert_cmpstr (host, ==, expected_host); + + if (g_test_failed ()) soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST); - } + else + soup_message_set_status (msg, SOUP_STATUS_OK); } static void @@ -309,22 +266,14 @@ do_ipv6_test (void) debug_printf (1, " HTTP/1.1\n"); msg = soup_message_new_from_uri ("GET", ipv6_uri); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " request failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); debug_printf (1, " HTTP/1.0\n"); msg = soup_message_new_from_uri ("GET", ipv6_uri); soup_message_set_http_version (msg, SOUP_HTTP_1_0); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " request failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); g_object_unref (msg); soup_uri_free (ipv6_uri); @@ -337,6 +286,7 @@ main (int argc, char **argv) { char *http_aliases[] = { "dav", NULL }; char *https_aliases[] = { "davs", NULL }; + int ret; test_init (argc, argv, NULL); @@ -359,10 +309,12 @@ main (int argc, char **argv) NULL); } - do_star_test (); - do_server_aliases_test (); - do_dot_dot_test (); - do_ipv6_test (); + g_test_add_func ("/server/OPTIONS *", do_star_test); + g_test_add_func ("/server/aliases", do_server_aliases_test); + g_test_add_func ("/server/..-in-path", do_dot_dot_test); + g_test_add_func ("/server/ipv6", do_ipv6_test); + + ret = g_test_run (); soup_uri_free (base_uri); soup_test_server_quit_unref (server); @@ -373,5 +325,5 @@ main (int argc, char **argv) } test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/session-test.c b/tests/session-test.c index 205885d7..a6ce2c45 100644 --- a/tests/session-test.c +++ b/tests/session-test.c @@ -58,7 +58,7 @@ cancel_message_cb (SoupMessage *msg, gpointer session) static void do_test_for_session (SoupSession *session, - const char *uri, const char *timeout_uri, + const char *uri, gboolean queue_is_async, gboolean send_is_blocking, gboolean cancel_is_immediate) @@ -66,10 +66,13 @@ do_test_for_session (SoupSession *session, SoupMessage *msg; gboolean finished, local_timeout; guint timeout_id; + char *timeout_uri; debug_printf (1, " queue_message\n"); debug_printf (2, " requesting timeout\n"); + timeout_uri = g_strdup_printf ("%s/request-timeout", uri); msg = soup_message_new ("GET", timeout_uri); + g_free (timeout_uri); soup_session_send_message (session, msg); g_object_unref (msg); @@ -81,27 +84,15 @@ do_test_for_session (SoupSession *session, debug_printf (2, " got timeout\n"); if (queue_is_async) { - if (server_processed_message) { - debug_printf (1, " message processed without running main loop!\n"); - errors++; - } + g_assert_false (server_processed_message); debug_printf (2, " waiting for finished\n"); while (!finished) g_main_context_iteration (NULL, TRUE); - if (!server_processed_message) { - debug_printf (1, " message finished without server seeing it???\n"); - errors++; - } + g_assert_true (server_processed_message); } else { - if (!server_processed_message) { - debug_printf (1, " server failed to immediately receive message!\n"); - errors++; - } + g_assert_true (server_processed_message); + g_assert_false (finished); debug_printf (2, " waiting for finished\n"); - if (finished) { - debug_printf (1, " message finished without main loop running???\n"); - errors++; - } while (!finished) g_main_context_iteration (NULL, TRUE); } @@ -112,21 +103,14 @@ do_test_for_session (SoupSession *session, timeout_id = g_idle_add_full (G_PRIORITY_HIGH, timeout_cb, &local_timeout, NULL); soup_session_send_message (session, msg); - if (!server_processed_message) { - debug_printf (1, " message finished without server seeing it???\n"); - errors++; - } + g_assert_true (server_processed_message); if (send_is_blocking) { - if (local_timeout) { - debug_printf (1, " send_message ran main loop!\n"); - errors++; - } + soup_test_assert (!local_timeout, + "send_message ran main loop"); } else { - if (!local_timeout) { - debug_printf (1, " send_message didn't run main loop!\n"); - errors++; - } + soup_test_assert (local_timeout, + "send_message didn't run main loop"); } if (!local_timeout) @@ -146,65 +130,48 @@ do_test_for_session (SoupSession *session, loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); - if (cancel_is_immediate) { - if (!finished) { - debug_printf (1, " cancel did not finish message!\n"); - errors++; - debug_printf (2, " waiting for finished\n"); - while (!finished) - g_main_context_iteration (NULL, TRUE); - } - } else { - if (finished) { - debug_printf (1, " cancel finished message!\n"); - errors++; - } else { - while (!finished) - g_main_context_iteration (NULL, TRUE); - } - } + if (cancel_is_immediate) + g_assert_true (finished); + else + g_assert_false (finished); - if (msg->status_code != SOUP_STATUS_CANCELLED) { - debug_printf (1, " message finished with status %d %s!\n", - msg->status_code, msg->reason_phrase); - errors++; + if (!finished) { + debug_printf (2, " waiting for finished\n"); + while (!finished) + g_main_context_iteration (NULL, TRUE); } + + soup_test_assert_message_status (msg, SOUP_STATUS_CANCELLED); g_object_unref (msg); } static void -do_plain_tests (char *uri, char *timeout_uri) +do_plain_tests (gconstpointer uri) { SoupSession *session; - debug_printf (1, "SoupSession\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); - do_test_for_session (session, uri, timeout_uri, TRUE, TRUE, FALSE); + do_test_for_session (session, uri, TRUE, TRUE, FALSE); soup_test_session_abort_unref (session); } static void -do_async_tests (char *uri, char *timeout_uri) +do_async_tests (gconstpointer uri) { SoupSession *session; - debug_printf (1, "\nSoupSessionAsync\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - do_test_for_session (session, uri, timeout_uri, TRUE, FALSE, TRUE); + do_test_for_session (session, uri, TRUE, FALSE, TRUE); soup_test_session_abort_unref (session); } static void -do_sync_tests (char *uri, char *timeout_uri) +do_sync_tests (gconstpointer uri) { SoupSession *session; - debug_printf (1, "\nSoupSessionSync\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - do_test_for_session (session, uri, timeout_uri, FALSE, TRUE, FALSE); + do_test_for_session (session, uri, FALSE, TRUE, FALSE); soup_test_session_abort_unref (session); } @@ -214,20 +181,20 @@ priority_test_finished_cb (SoupSession *session, SoupMessage *msg, gpointer user guint *finished_count = user_data; SoupMessagePriority priority = soup_message_get_priority (msg); - if (priority != expected_priorities[*finished_count]) { - debug_printf (1, " message %d should have priority %d (%d found)\n", - *finished_count, expected_priorities[*finished_count], priority); - errors++; - } else - debug_printf (1, " received message %d with priority %d\n", - *finished_count, priority); + debug_printf (1, " received message %d with priority %d\n", + *finished_count, priority); + + soup_test_assert (priority == expected_priorities[*finished_count], + "message %d should have priority %d (%d found)", + *finished_count, expected_priorities[*finished_count], priority); (*finished_count)++; } static void -do_priority_tests (char *uri) +do_priority_tests (gconstpointer data) { + const char *uri = data; SoupSession *session; int i, finished_count = 0; SoupMessagePriority priorities[] = @@ -276,16 +243,14 @@ test_session_properties (const char *name, SOUP_SESSION_PROXY_RESOLVER, &proxy_resolver, SOUP_SESSION_TLS_DATABASE, &tlsdb, NULL); - if (proxy_resolver != expected_proxy_resolver) { - debug_printf (1, " %s has %s proxy resolver!\n", - name, proxy_resolver ? (expected_proxy_resolver ? "wrong" : "a") : "no"); - errors++; - } - if (tlsdb != expected_tls_database) { - debug_printf (1, " %s has %s TLS database!\n", - name, tlsdb ? (expected_tls_database ? "wrong" : "a") : "no"); - errors++; - } + + soup_test_assert (proxy_resolver == expected_proxy_resolver, + "%s has %s proxy resolver", + name, proxy_resolver ? (expected_proxy_resolver ? "wrong" : "a") : "no"); + soup_test_assert (tlsdb == expected_tls_database, + "%s has %s TLS database", + name, tlsdb ? (expected_tls_database ? "wrong" : "a") : "no"); + g_clear_object (&proxy_resolver); g_clear_object (&tlsdb); } @@ -343,11 +308,7 @@ do_property_tests (void) NULL); test_session_properties ("Session with non-NULL :proxy-uri", session, proxy_resolver, default_tlsdb); - if (!G_IS_SIMPLE_PROXY_RESOLVER (proxy_resolver)) { - debug_printf (1, " proxy resolver had wrong type (%s)\n", - G_OBJECT_TYPE_NAME (proxy_resolver)); - errors++; - } + g_assert_cmpstr (G_OBJECT_TYPE_NAME (proxy_resolver), ==, "GSimpleProxyResolver"); g_object_unref (proxy_resolver); g_object_unref (session); soup_uri_free (uri); @@ -402,6 +363,7 @@ main (int argc, char **argv) { SoupServer *server; char *uri, *timeout_uri; + int ret; test_init (argc, argv, NULL); @@ -411,16 +373,18 @@ main (int argc, char **argv) soup_server_get_port (server)); timeout_uri = g_strdup_printf ("%s/request-timeout", uri); - do_plain_tests (uri, timeout_uri); - do_async_tests (uri, timeout_uri); - do_sync_tests (uri, timeout_uri); - do_priority_tests (uri); - do_property_tests (); + g_test_add_data_func ("/session/SoupSession", uri, do_plain_tests); + g_test_add_data_func ("/session/SoupSessionAsync", uri, do_async_tests); + g_test_add_data_func ("/session/SoupSessionSync", uri, do_sync_tests); + g_test_add_data_func ("/session/priority", uri, do_priority_tests); + g_test_add_func ("/session/property", do_property_tests); + + ret = g_test_run (); g_free (uri); g_free (timeout_uri); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index cbebaba0..b5088d4d 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -47,12 +47,7 @@ server_callback (SoupServer *server, SoupMessage *msg, g_file_get_contents (SRCDIR "/resources/mbox", &contents, &length, &error); - } - - if (error) { - g_error ("%s", error->message); - g_error_free (error); - exit (1); + g_assert_no_error (error); } soup_message_headers_append (msg->response_headers, @@ -66,16 +61,11 @@ server_callback (SoupServer *server, SoupMessage *msg, g_file_get_contents (file_name, &contents, &length, &error); + g_assert_no_error (error); g_free (base_name); g_free (file_name); - if (error) { - g_error ("%s", error->message); - g_error_free (error); - exit (1); - } - soup_message_headers_append (msg->response_headers, "Content-Type", "text/plain"); } @@ -87,16 +77,11 @@ server_callback (SoupServer *server, SoupMessage *msg, g_file_get_contents (file_name, &contents, &length, &error); + g_assert_no_error (error); g_free (base_name); g_free (file_name); - if (error) { - g_error ("%s", error->message); - g_error_free (error); - exit (1); - } - soup_message_headers_append (msg->response_headers, "Content-Type", "UNKNOWN/unknown"); } @@ -111,16 +96,11 @@ server_callback (SoupServer *server, SoupMessage *msg, g_file_get_contents (file_name, &contents, &length, &error); + g_assert_no_error (error); g_free (base_name); g_free (file_name); - if (error) { - g_error ("%s", error->message); - g_error_free (error); - exit (1); - } - /* Hack to allow passing type in the URI */ ptr = g_strrstr (components[2], "_"); *ptr = '/'; @@ -137,16 +117,11 @@ server_callback (SoupServer *server, SoupMessage *msg, g_file_get_contents (file_name, &contents, &length, &error); + g_assert_no_error (error); g_free (base_name); g_free (file_name); - if (error) { - g_error ("%s", error->message); - g_error_free (error); - exit (1); - } - soup_message_headers_append (msg->response_headers, "Content-Type", "text/xml"); soup_message_headers_append (msg->response_headers, @@ -181,10 +156,8 @@ content_sniffed (SoupMessage *msg, char *content_type, GHashTable *params, gpoin debug_printf (2, " content-sniffed -> %s\n", content_type); - if (g_object_get_data (G_OBJECT (msg), "got-chunk")) { - debug_printf (1, " got-chunk got emitted before content-sniffed\n"); - errors++; - } + soup_test_assert (g_object_get_data (G_OBJECT (msg), "got-chunk") == NULL, + "got-chunk got emitted before content-sniffed"); g_object_set_data (G_OBJECT (msg), "content-sniffed", GINT_TO_POINTER (TRUE)); @@ -202,10 +175,8 @@ got_headers (SoupMessage *msg, gpointer data) debug_printf (2, " got-headers\n"); - if (g_object_get_data (G_OBJECT (msg), "content-sniffed")) { - debug_printf (1, " content-sniffed got emitted before got-headers\n"); - errors++; - } + soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL, + "content-sniffed got emitted before got-headers"); g_object_set_data (G_OBJECT (msg), "got-headers", GINT_TO_POINTER (TRUE)); @@ -277,14 +248,12 @@ do_signals_test (gboolean should_content_sniff, soup_session_send_message (session, msg); - if (!should_content_sniff && - g_object_get_data (G_OBJECT (msg), "content-sniffed")) { - debug_printf (1, " content-sniffed got emitted without a sniffer\n"); - errors++; - } else if (should_content_sniff && - !g_object_get_data (G_OBJECT (msg), "content-sniffed")) { - debug_printf (1, " content-sniffed did not get emitted\n"); - errors++; + if (should_content_sniff) { + soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") != NULL, + "content-sniffed did not get emitted"); + } else { + soup_test_assert (g_object_get_data (G_OBJECT (msg), "content-sniffed") == NULL, + "content-sniffed got emitted without a sniffer"); } if (empty_response) { @@ -294,12 +263,7 @@ do_signals_test (gboolean should_content_sniff, g_file_get_contents (SRCDIR "/resources/mbox", &contents, &length, &error); - } - - if (error) { - g_error ("%s", error->message); - g_error_free (error); - exit (1); + g_assert_no_error (error); } if (!should_accumulate && chunk_data) @@ -307,15 +271,8 @@ do_signals_test (gboolean should_content_sniff, else if (msg->response_body) body = soup_message_body_flatten (msg->response_body); - if (body && body->length != length) { - debug_printf (1, " lengths do not match\n"); - errors++; - } - - if (body && memcmp (body->data, contents, length)) { - debug_printf (1, " downloaded data does not match\n"); - errors++; - } + if (body) + soup_assert_cmpmem (body->data, body->length, contents, length); g_free (contents); if (body) @@ -329,6 +286,41 @@ do_signals_test (gboolean should_content_sniff, g_object_unref (msg); } +static void +do_signals_tests (gconstpointer data) +{ + gboolean should_content_sniff = GPOINTER_TO_INT (data); + + if (!should_content_sniff) + soup_session_remove_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); + + do_signals_test (should_content_sniff, + FALSE, FALSE, FALSE, FALSE); + do_signals_test (should_content_sniff, + FALSE, FALSE, TRUE, FALSE); + do_signals_test (should_content_sniff, + FALSE, TRUE, FALSE, FALSE); + do_signals_test (should_content_sniff, + FALSE, TRUE, TRUE, FALSE); + + do_signals_test (should_content_sniff, + TRUE, TRUE, FALSE, FALSE); + do_signals_test (should_content_sniff, + TRUE, TRUE, TRUE, FALSE); + do_signals_test (should_content_sniff, + TRUE, FALSE, FALSE, FALSE); + do_signals_test (should_content_sniff, + TRUE, FALSE, TRUE, FALSE); + + do_signals_test (should_content_sniff, + TRUE, TRUE, FALSE, TRUE); + do_signals_test (should_content_sniff, + TRUE, TRUE, TRUE, TRUE); + + if (!should_content_sniff) + soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); +} + static void sniffing_content_sniffed (SoupMessage *msg, const char *content_type, GHashTable *params, gpointer data) @@ -360,10 +352,9 @@ test_sniffing (const char *path, const char *expected_type) SoupRequest *req; GInputStream *stream; char *sniffed_type = NULL; + const char *req_sniffed_type; GError *error = NULL; - debug_printf (1, "test_sniffing(\"%s\", \"%s\")\n", path, expected_type); - uri = soup_uri_new_with_base (base_uri, path); msg = soup_message_new_from_uri ("GET", uri); @@ -371,14 +362,7 @@ test_sniffing (const char *path, const char *expected_type) G_CALLBACK (sniffing_content_sniffed), &sniffed_type); soup_session_send_message (session, msg); - if (!sniffed_type) { - debug_printf (1, " message was not sniffed!\n"); - errors++; - } else if (strcmp (sniffed_type, expected_type) != 0) { - debug_printf (1, " message sniffing failed! expected %s, got %s\n", - expected_type, sniffed_type); - errors++; - } + g_assert_cmpstr (sniffed_type, ==, expected_type); g_free (sniffed_type); g_object_unref (msg); @@ -388,32 +372,39 @@ test_sniffing (const char *path, const char *expected_type) soup_test_request_close_stream (req, stream, NULL, &error); g_object_unref (stream); } - if (error) { - debug_printf (1, " request failed: %s\n", error->message); - g_clear_error (&error); - } else { - const char *req_sniffed_type; + g_assert_no_error (error); + g_clear_error (&error); - req_sniffed_type = soup_request_get_content_type (req); - if (strcmp (req_sniffed_type, expected_type) != 0) { - debug_printf (1, " request sniffing failed! expected %s, got %s\n", - expected_type, req_sniffed_type); - errors++; - } - } + req_sniffed_type = soup_request_get_content_type (req); + g_assert_cmpstr (req_sniffed_type, ==, expected_type); g_object_unref (req); soup_uri_free (uri); } static void -test_disabled (const char *path) +do_sniffing_test (gconstpointer data) { + const char *path_and_result = data; + char **parts; + + parts = g_strsplit (path_and_result, " => ", -1); + g_assert (parts && parts[0] && parts[1] && !parts[2]); + + test_sniffing (parts[0], parts[1]); + g_strfreev (parts); +} + +static void +test_disabled (gconstpointer data) +{ + const char *path = data; SoupURI *uri; SoupMessage *msg; SoupRequest *req; GInputStream *stream; char *sniffed_type = NULL; + const char *sniffed_content_type; GError *error = NULL; debug_printf (1, "test_disabled(\"%s\")\n", path); @@ -428,11 +419,7 @@ test_disabled (const char *path) soup_session_send_message (session, msg); - if (sniffed_type) { - debug_printf (1, " message was sniffed!\n"); - errors++; - g_free (sniffed_type); - } + g_assert_null (sniffed_type); g_object_unref (msg); req = soup_session_request_uri (session, uri, NULL); @@ -444,18 +431,11 @@ test_disabled (const char *path) soup_test_request_close_stream (req, stream, NULL, &error); g_object_unref (stream); } - if (error) { - debug_printf (1, " request failed: %s\n", error->message); - g_clear_error (&error); - } else { - const char *sniffed_content_type; + g_assert_no_error (error); + + sniffed_content_type = soup_request_get_content_type (req); + g_assert_cmpstr (sniffed_content_type, ==, NULL); - sniffed_content_type = soup_request_get_content_type (req); - if (sniffed_content_type != NULL) { - debug_printf (1, " request was sniffed!\n"); - errors++; - } - } g_object_unref (req); soup_uri_free (uri); @@ -465,6 +445,7 @@ int main (int argc, char **argv) { SoupServer *server; + int ret; test_init (argc, argv, NULL); @@ -476,106 +457,113 @@ main (int argc, char **argv) session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); - - /* No sniffer, no content_sniffed should be emitted */ - do_signals_test (FALSE, FALSE, FALSE, FALSE, FALSE); - do_signals_test (FALSE, FALSE, FALSE, TRUE, FALSE); - do_signals_test (FALSE, FALSE, TRUE, FALSE, FALSE); - do_signals_test (FALSE, FALSE, TRUE, TRUE, FALSE); - - do_signals_test (FALSE, TRUE, TRUE, FALSE, FALSE); - do_signals_test (FALSE, TRUE, TRUE, TRUE, FALSE); - do_signals_test (FALSE, TRUE, FALSE, FALSE, FALSE); - do_signals_test (FALSE, TRUE, FALSE, TRUE, FALSE); - - /* Tests that the signals are correctly emitted for empty - * responses; see - * http://bugzilla.gnome.org/show_bug.cgi?id=587907 */ - - do_signals_test (FALSE, TRUE, TRUE, FALSE, TRUE); - do_signals_test (FALSE, TRUE, TRUE, TRUE, TRUE); - soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_SNIFFER); - /* Now, with a sniffer, content_sniffed must be emitted after - * got-headers, and before got-chunk. - */ - do_signals_test (TRUE, FALSE, FALSE, FALSE, FALSE); - do_signals_test (TRUE, FALSE, FALSE, TRUE, FALSE); - do_signals_test (TRUE, FALSE, TRUE, FALSE, FALSE); - do_signals_test (TRUE, FALSE, TRUE, TRUE, FALSE); - - do_signals_test (TRUE, TRUE, TRUE, FALSE, FALSE); - do_signals_test (TRUE, TRUE, TRUE, TRUE, FALSE); - do_signals_test (TRUE, TRUE, FALSE, FALSE, FALSE); - do_signals_test (TRUE, TRUE, FALSE, TRUE, FALSE); + g_test_add_data_func ("/sniffing/signals/no-sniffer", + GINT_TO_POINTER (FALSE), + do_signals_tests); + g_test_add_data_func ("/sniffing/signals/with-sniffer", + GINT_TO_POINTER (TRUE), + do_signals_tests); - /* Empty response tests */ - do_signals_test (TRUE, TRUE, TRUE, FALSE, TRUE); - do_signals_test (TRUE, TRUE, TRUE, TRUE, TRUE); - - /* Test the text_or_binary sniffing path */ - - /* GIF is a 'safe' type */ - test_sniffing ("/text_or_binary/home.gif", "image/gif"); + g_test_add_data_func ("/sniffing/type/gif", + "text_or_binary/home.gif => image/gif", + do_sniffing_test); /* With our current code, no sniffing is done using GIO, so * the mbox will be identified as text/plain; should we change * this? */ - test_sniffing ("/text_or_binary/mbox", "text/plain"); + g_test_add_data_func ("/sniffing/type/mbox", + "text_or_binary/mbox => text/plain", + do_sniffing_test); /* HTML is considered unsafe for this algorithm, since it is * scriptable, so going from text/plain to text/html is * considered 'privilege escalation' */ - test_sniffing ("/text_or_binary/test.html", "text/plain"); + g_test_add_data_func ("/sniffing/type/html-in-text-context", + "text_or_binary/test.html => text/plain", + do_sniffing_test); /* text/plain with binary content and unknown pattern should be - * application/octet-stream */ - test_sniffing ("/text_or_binary/text_binary.txt", "application/octet-stream"); + * application/octet-stream + */ + g_test_add_data_func ("/sniffing/type/text-binary", + "text_or_binary/text_binary.txt => application/octet-stream", + do_sniffing_test); - /* text/plain with binary content and scriptable pattern should be - * application/octet-stream to avoid 'privilege escalation' */ - test_sniffing ("/text_or_binary/html_binary.html", "application/octet-stream"); + /* text/html with binary content and scriptable pattern should be + * application/octet-stream to avoid 'privilege escalation' + */ + g_test_add_data_func ("/sniffing/type/html-binary", + "text_or_binary/html_binary.html => application/octet-stream", + do_sniffing_test); /* text/plain with binary content and non scriptable known pattern should - * be the given type */ - test_sniffing ("/text_or_binary/ps_binary.ps", "application/postscript"); + * be the given type + */ + g_test_add_data_func ("/sniffing/type/ps", + "text_or_binary/ps_binary.ps => application/postscript", + do_sniffing_test); /* Test the unknown sniffing path */ - - test_sniffing ("/unknown/test.html", "text/html"); - test_sniffing ("/unknown/home.gif", "image/gif"); - test_sniffing ("/unknown/mbox", "text/plain"); - test_sniffing ("/unknown/text_binary.txt", "application/octet-stream"); + g_test_add_data_func ("/sniffing/type/unknown-html", + "unknown/test.html => text/html", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/unknown-gif", + "unknown/home.gif => image/gif", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/unknown-mbox", + "unknown/mbox => text/plain", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/unknown-binary", + "unknown/text_binary.txt => application/octet-stream", + do_sniffing_test); /* Test the XML sniffing path */ - - test_sniffing ("/type/text_xml/home.gif", "text/xml"); - test_sniffing ("/type/anice_type+xml/home.gif", "anice/type+xml"); - test_sniffing ("/type/application_xml/home.gif", "application/xml"); + g_test_add_data_func ("/sniffing/type/xml", + "type/text_xml/home.gif => text/xml", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/xml+xml", + "type/anice_type+xml/home.gif => anice/type+xml", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/application-xml", + "type/application_xml/home.gif => application/xml", + do_sniffing_test); /* Test the image sniffing path */ - - test_sniffing ("/type/image_png/home.gif", "image/gif"); + g_test_add_data_func ("/sniffing/type/image", + "type/image_png/home.gif => image/gif", + do_sniffing_test); /* Test the feed or html path */ - - test_sniffing ("/type/text_html/test.html", "text/html"); - test_sniffing ("/type/text_html/rss20.xml", "application/rss+xml"); - test_sniffing ("/type/text_html/atom.xml", "application/atom+xml"); + g_test_add_data_func ("/sniffing/type/html/html", + "type/text_html/test.html => text/html", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/html/rss", + "type/text_html/rss20.xml => application/rss+xml", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/html/atom", + "type/text_html/atom.xml => application/atom+xml", + do_sniffing_test); /* The spec tells us to only use the last Content-Type header */ - - test_sniffing ("/multiple_headers/home.gif", "image/gif"); + g_test_add_data_func ("/sniffing/multiple-headers", + "multiple_headers/home.gif => image/gif", + do_sniffing_test); /* Test that we keep the parameters when sniffing */ - test_sniffing ("/type/text_html; charset=UTF-8/test.html", "text/html; charset=UTF-8"); + g_test_add_data_func ("/sniffing/parameters", + "type/text_html; charset=UTF-8/test.html => text/html; charset=UTF-8", + do_sniffing_test); /* Test that disabling the sniffer works correctly */ + g_test_add_data_func ("/sniffing/disabled", + "/text_or_binary/home.gif", + test_disabled); - test_disabled ("/text_or_binary/home.gif"); + ret = g_test_run (); soup_uri_free (base_uri); @@ -583,5 +571,5 @@ main (int argc, char **argv) soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/socket-test.c b/tests/socket-test.c index 42ab6c8b..4fb0d35c 100644 --- a/tests/socket-test.c +++ b/tests/socket-test.c @@ -24,75 +24,82 @@ do_unconnected_socket_test (void) localhost = soup_address_new_from_sockaddr ( (struct sockaddr *) &in_localhost, sizeof (in_localhost)); - g_assert (localhost != NULL); + g_assert_true (localhost != NULL); res = soup_address_resolve_sync (localhost, NULL); g_assert_cmpuint (res, ==, SOUP_STATUS_OK); - sock = soup_socket_new ( - SOUP_SOCKET_LOCAL_ADDRESS, localhost, - NULL); - g_assert (sock != NULL); + sock = soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, localhost, + NULL); + g_assert_true (sock != NULL); addr = soup_socket_get_local_address (sock); - g_assert (addr != NULL); + g_assert_true (addr != NULL); g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); g_assert_cmpuint (soup_address_get_port (addr), ==, 0); /* fails with ENOTCONN */ - expect_warning++; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*socket not connected*"); addr = soup_socket_get_remote_address (sock); - g_assert (addr == NULL); + g_test_assert_expected_messages (); + g_assert_null (addr); res = soup_socket_listen (sock); - g_assert_cmpuint (res, ==, TRUE); + g_assert_true (res); addr = soup_socket_get_local_address (sock); - g_assert (addr != NULL); + g_assert_true (addr != NULL); g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); g_assert_cmpuint (soup_address_get_port (addr), >, 0); - client = soup_socket_new ( - SOUP_SOCKET_REMOTE_ADDRESS, - soup_socket_get_local_address (sock), - NULL); + client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, + soup_socket_get_local_address (sock), + NULL); res = soup_socket_connect_sync (client, NULL); g_assert_cmpuint (res, ==, SOUP_STATUS_OK); addr = soup_socket_get_local_address (client); - g_assert (addr != NULL); + g_assert_true (addr != NULL); addr = soup_socket_get_remote_address (client); - g_assert (addr != NULL); + g_assert_true (addr != NULL); g_assert_cmpstr (soup_address_get_physical (addr), ==, "127.0.0.1"); g_assert_cmpuint (soup_address_get_port (addr), >, 0); g_object_unref (client); - client = soup_socket_new ( - SOUP_SOCKET_REMOTE_ADDRESS, - soup_socket_get_local_address (sock), - NULL); + client = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, + soup_socket_get_local_address (sock), + NULL); /* save it for later */ /* listening socket fails with ENOTCONN */ - expect_warning++; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*endpoint is not connected*"); addr = soup_socket_get_remote_address (sock); - g_assert (addr == NULL); + g_test_assert_expected_messages (); + g_assert_null (addr); soup_socket_disconnect (sock); - expect_warning++; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*socket not connected*"); addr = soup_socket_get_remote_address (sock); - g_assert (addr == NULL); + g_test_assert_expected_messages (); + g_assert_null (addr); /* has never been connected */ - expect_warning++; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*socket not connected*"); addr = soup_socket_get_local_address (client); - g_assert (addr == NULL); + g_test_assert_expected_messages (); + g_assert_null (addr); res = soup_socket_connect_sync (client, NULL); g_assert_cmpuint (res, ==, SOUP_STATUS_CANT_CONNECT); - expect_warning++; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*socket not connected*"); addr = soup_socket_get_local_address (client); - g_assert (addr == NULL); + g_test_assert_expected_messages (); + g_assert_null (addr); g_object_unref (localhost); g_object_unref (client); @@ -102,10 +109,14 @@ do_unconnected_socket_test (void) int main (int argc, char **argv) { + int ret; + test_init (argc, argv, NULL); - do_unconnected_socket_test (); + g_test_add_func ("/sockets/unconnected", do_unconnected_socket_test); + + ret = g_test_run (); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/ssl-test.c b/tests/ssl-test.c index 7716f302..5ef41292 100644 --- a/tests/ssl-test.c +++ b/tests/ssl-test.c @@ -3,7 +3,7 @@ #include "test-utils.h" static void -do_properties_test_for_session (SoupSession *session, char *uri) +do_properties_test_for_session (SoupSession *session, const char *uri) { SoupMessage *msg; GTlsCertificate *cert; @@ -11,42 +11,23 @@ do_properties_test_for_session (SoupSession *session, char *uri) msg = soup_message_new ("GET", uri); soup_session_send_message (session, msg); - if (msg->status_code != SOUP_STATUS_OK) { - debug_printf (1, " FAILED: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); if (soup_message_get_https_status (msg, &cert, &flags)) { - if (!G_IS_TLS_CERTIFICATE (cert)) { - debug_printf (1, " No certificate?\n"); - errors++; - } - if (flags != G_TLS_CERTIFICATE_UNKNOWN_CA) { - debug_printf (1, " Wrong cert flags (got %x, wanted %x)\n", - flags, G_TLS_CERTIFICATE_UNKNOWN_CA); - errors++; - } - } else { - debug_printf (1, " Response not https\n"); - errors++; - } - if (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) { - debug_printf (1, " CERTIFICATE_TRUSTED set?\n"); - errors++; - } + g_assert_true (G_IS_TLS_CERTIFICATE (cert)); + g_assert_cmpuint (flags, ==, G_TLS_CERTIFICATE_UNKNOWN_CA); + } else + soup_test_assert (FALSE, "Response not https"); + g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); g_object_unref (msg); } static void -do_properties_tests (char *uri) +do_async_properties_tests (gconstpointer uri) { SoupSession *session; - debug_printf (1, "\nSoupMessage properties\n"); - - debug_printf (1, " async\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_object_set (G_OBJECT (session), SOUP_SESSION_SSL_CA_FILE, "/dev/null", @@ -54,8 +35,13 @@ do_properties_tests (char *uri) NULL); do_properties_test_for_session (session, uri); soup_test_session_abort_unref (session); +} + +static void +do_sync_properties_tests (gconstpointer uri) +{ + SoupSession *session; - debug_printf (1, " sync\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); g_object_set (G_OBJECT (session), SOUP_SESSION_SSL_CA_FILE, "/dev/null", @@ -66,7 +52,7 @@ do_properties_tests (char *uri) } static void -do_one_strict_test (SoupSession *session, char *uri, +do_one_strict_test (SoupSession *session, const char *uri, gboolean strict, gboolean with_ca_list, guint expected_status) { @@ -97,28 +83,18 @@ do_one_strict_test (SoupSession *session, char *uri, soup_message_get_https_status (msg, NULL, &flags); debug_printf (1, " tls error flags: 0x%x\n", flags); } - errors++; - } else if (with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED)) { - debug_printf (1, " CERTIFICATE_TRUSTED not set?\n"); - errors++; - } - } else { - if (with_ca_list && soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) { - debug_printf (1, " CERTIFICATE_TRUSTED set?\n"); - errors++; - } - } - if (!soup_message_get_https_status (msg, NULL, NULL)) { - debug_printf (1, " get_https_status returns FALSE?\n"); - errors++; - } + } else if (with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + g_assert_true (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); + else + g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); + + g_assert_true (soup_message_get_https_status (msg, NULL, NULL)); g_object_unref (msg); } static void -do_strict_tests (char *uri) +do_strict_tests (gconstpointer uri) { SoupSession *session; @@ -179,20 +155,12 @@ do_session_property_tests (void) "tls-database", &tlsdb, "ssl-ca-file", &ca_file, NULL); - if (use_system) { - debug_printf (1, " ssl-use-system-ca-file defaults to TRUE?\n"); - errors++; - } - if (tlsdb) { - debug_printf (1, " tls-database set by default?\n"); - errors++; - g_object_unref (tlsdb); - } - if (ca_file) { - debug_printf (1, " ca-file set by default?\n"); - errors++; - g_free (ca_file); - } + soup_test_assert (!use_system, + "ssl-use-system-ca-file defaults to TRUE"); + soup_test_assert (tlsdb == NULL, + "tls-database set by default"); + soup_test_assert (ca_file == NULL, + "ca-file set by default"); use_system_changed = tlsdb_changed = ca_file_changed = FALSE; g_object_set (G_OBJECT (session), @@ -203,32 +171,16 @@ do_session_property_tests (void) "tls-database", &tlsdb, "ssl-ca-file", &ca_file, NULL); - if (!use_system) { - debug_printf (1, " setting ssl-use-system-ca-file failed\n"); - errors++; - } - if (!tlsdb) { - debug_printf (1, " setting ssl-use-system-ca-file didn't set tls-database\n"); - errors++; - } else - g_object_unref (tlsdb); - if (ca_file) { - debug_printf (1, " setting ssl-use-system-ca-file set ssl-ca-file\n"); - errors++; - g_free (ca_file); - } - if (!use_system_changed) { - debug_printf (1, " setting ssl-use-system-ca-file didn't emit notify::ssl-use-system-ca-file\n"); - errors++; - } - if (!tlsdb_changed) { - debug_printf (1, " setting ssl-use-system-ca-file didn't emit notify::tls-database\n"); - errors++; - } - if (ca_file_changed) { - debug_printf (1, " setting ssl-use-system-ca-file emitted notify::ssl-ca-file\n"); - errors++; - } + soup_test_assert (use_system, + "setting ssl-use-system-ca-file failed"); + g_assert_true (use_system_changed); + soup_test_assert (tlsdb != NULL, + "setting ssl-use-system-ca-file didn't set tls-database"); + g_assert_true (tlsdb_changed); + g_clear_object (&tlsdb); + soup_test_assert (ca_file == NULL, + "setting ssl-use-system-ca-file set ssl-ca-file"); + g_assert_false (ca_file_changed); use_system_changed = tlsdb_changed = ca_file_changed = FALSE; g_object_set (G_OBJECT (session), @@ -239,32 +191,17 @@ do_session_property_tests (void) "tls-database", &tlsdb, "ssl-ca-file", &ca_file, NULL); - if (use_system) { - debug_printf (1, " setting ssl-ca-file left ssl-use-system-ca-file set\n"); - errors++; - } - if (!tlsdb) { - debug_printf (1, " setting ssl-ca-file didn't set tls-database\n"); - errors++; - } else - g_object_unref (tlsdb); - if (!ca_file) { - debug_printf (1, " setting ssl-ca-file failed\n"); - errors++; - } else - g_free (ca_file); - if (!use_system_changed) { - debug_printf (1, " setting ssl-ca-file didn't emit notify::ssl-use-system-ca-file\n"); - errors++; - } - if (!tlsdb_changed) { - debug_printf (1, " setting ssl-ca-file didn't emit notify::tls-database\n"); - errors++; - } - if (!ca_file_changed) { - debug_printf (1, " setting ssl-ca-file didn't emit notify::ssl-ca-file\n"); - errors++; - } + soup_test_assert (!use_system, + "setting ssl-ca-file left ssl-use-system-ca-file set"); + g_assert_true (use_system_changed); + soup_test_assert (tlsdb != NULL, + "setting ssl-ca-file didn't set tls-database"); + g_assert_true (tlsdb_changed); + g_clear_object (&tlsdb); + soup_test_assert (ca_file != NULL, + "setting ssl-ca-file failed"); + g_assert_true (ca_file_changed); + g_free (ca_file); use_system_changed = tlsdb_changed = ca_file_changed = FALSE; g_object_set (G_OBJECT (session), @@ -275,32 +212,15 @@ do_session_property_tests (void) "tls-database", &tlsdb, "ssl-ca-file", &ca_file, NULL); - if (use_system) { - debug_printf (1, " setting tls-database NULL left ssl-use-system-ca-file set\n"); - errors++; - } - if (tlsdb) { - debug_printf (1, " setting tls-database NULL failed\n"); - errors++; - g_object_unref (tlsdb); - } - if (ca_file) { - debug_printf (1, " setting tls-database didn't clear ssl-ca-file\n"); - errors++; - g_free (ca_file); - } - if (use_system_changed) { - debug_printf (1, " setting tls-database emitted notify::ssl-use-system-ca-file\n"); - errors++; - } - if (!tlsdb_changed) { - debug_printf (1, " setting tls-database didn't emit notify::tls-database\n"); - errors++; - } - if (!ca_file_changed) { - debug_printf (1, " setting tls-database didn't emit notify::ssl-ca-file\n"); - errors++; - } + soup_test_assert (!use_system, + "setting tls-database NULL left ssl-use-system-ca-file set"); + g_assert_false (use_system_changed); + soup_test_assert (tlsdb == NULL, + "setting tls-database NULL failed"); + g_assert_true (tlsdb_changed); + soup_test_assert (ca_file == NULL, + "setting tls-database didn't clear ssl-ca-file"); + g_assert_true (ca_file_changed); soup_test_session_abort_unref (session); } @@ -324,23 +244,32 @@ main (int argc, char **argv) { SoupServer *server; char *uri; + int ret; test_init (argc, argv, NULL); - if (tls_available) { - server = soup_test_server_new_ssl (TRUE); - soup_server_add_handler (server, NULL, server_handler, NULL, NULL); - uri = g_strdup_printf ("https://127.0.0.1:%u/", - soup_server_get_port (server)); + if (!tls_available) { + test_cleanup (); + return 77; /* SKIP */ + } - do_session_property_tests (); - do_strict_tests (uri); - do_properties_tests (uri); + server = soup_test_server_new_ssl (TRUE); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = g_strdup_printf ("https://127.0.0.1:%u/", + soup_server_get_port (server)); - g_free (uri); - soup_test_server_quit_unref (server); - } + g_test_add_func ("/ssl/session-properties", do_session_property_tests); + g_test_add_data_func ("/ssl/message-properties/async", uri, do_async_properties_tests); + g_test_add_data_func ("/ssl/message-properties/sync", uri, do_sync_properties_tests); + + /* FIXME: split this up */ + g_test_add_data_func ("/ssl/strict", uri, do_strict_tests); + + ret = g_test_run (); + + g_free (uri); + soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/streaming-test.c b/tests/streaming-test.c index 239e0ce8..9790766a 100644 --- a/tests/streaming-test.c +++ b/tests/streaming-test.c @@ -106,44 +106,47 @@ do_request (SoupSession *session, SoupURI *base_uri, char *path) soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, " message failed: %d %s\n", - msg->status_code, msg->reason_phrase); - errors++; - } - - if (msg->response_body->length != full_response_length) { - debug_printf (1, " received length mismatch: expected %d, got %d\n", - (int)full_response_length, (int)msg->request_body->length); - errors++; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); + g_assert_cmpint (msg->response_body->length, ==, full_response_length); md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, (guchar *)msg->response_body->data, msg->response_body->length); - if (strcmp (md5, full_response_md5) != 0) { - debug_printf (1, " data mismatch: expected %s, got %s\n", - full_response_md5, md5); - errors++; - } + g_assert_cmpstr (md5, ==, full_response_md5); g_free (md5); g_object_unref (msg); } static void -do_tests (SoupURI *base_uri) +do_chunked_test (gconstpointer data) { + SoupURI *base_uri = (SoupURI *)data; SoupSession *session; session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - debug_printf (1, "Chunked encoding\n"); do_request (session, base_uri, "chunked"); - debug_printf (1, "\n"); - debug_printf (1, "Content-Length encoding\n"); + soup_test_session_abort_unref (session); +} + +static void +do_content_length_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_request (session, base_uri, "content-length"); - debug_printf (1, "\n"); - debug_printf (1, "EOF encoding\n"); + soup_test_session_abort_unref (session); +} + +static void +do_eof_test (gconstpointer data) +{ + SoupURI *base_uri = (SoupURI *)data; + SoupSession *session; + + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_request (session, base_uri, "eof"); soup_test_session_abort_unref (session); } @@ -155,8 +158,10 @@ main (int argc, char **argv) SoupServer *server; guint port; SoupURI *base_uri; + int ret; test_init (argc, argv, NULL); + get_full_response (); server = soup_test_server_new (FALSE); @@ -168,14 +173,20 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1"); soup_uri_set_port (base_uri, port); - do_tests (base_uri); - soup_uri_free (base_uri); + g_test_add_data_func ("/streaming/chunked", base_uri, do_chunked_test); + g_test_add_data_func ("/streaming/content-length", base_uri, do_content_length_test); + g_test_add_data_func ("/streaming/eof", base_uri, do_eof_test); + + ret = g_test_run (); + + soup_uri_free (base_uri); g_main_loop_unref (loop); g_free (full_response); g_free (full_response_md5); soup_test_server_quit_unref (server); test_cleanup (); - return errors != 0; + + return ret; } diff --git a/tests/test-utils.c b/tests/test-utils.c index 36b0ee5d..c28994a1 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -13,8 +13,7 @@ static gboolean apache_running; static SoupLogger *logger; -int debug_level, errors; -gboolean parallelize = TRUE; +int debug_level; gboolean expect_warning, tls_available; static int http_debug_level; @@ -38,9 +37,6 @@ static GOptionEntry debug_entry[] = { { "debug", 'd', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, increment_debug_level, "Enable (or increase) test-specific debugging", NULL }, - { "parallel", 'p', G_OPTION_FLAG_REVERSE, - G_OPTION_ARG_NONE, ¶llelize, - "Toggle parallelization (default is on, unless -d or -h)", NULL }, { "http-debug", 'h', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, increment_http_debug_level, "Enable (or increase) HTTP-level debugging", NULL }, @@ -58,21 +54,6 @@ quit (int sig) exit (1); } -static void -test_log_handler (const char *log_domain, GLogLevelFlags log_level, - const char *message, gpointer user_data) -{ - if (log_level & (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL)) { - if (expect_warning) { - expect_warning = FALSE; - debug_printf (2, "Got expected warning: %s\n", message); - return; - } else - errors++; - } - g_log_default_handler (log_domain, log_level, message, user_data); -} - void test_init (int argc, char **argv, GOptionEntry *entries) { @@ -92,6 +73,9 @@ test_init (int argc, char **argv, GOptionEntry *entries) name += 3; g_set_prgname (name); + g_test_init (&argc, &argv, NULL); + g_test_set_nonfatal_assertions (); + opts = g_option_context_new (NULL); g_option_context_add_main_entries (opts, debug_entry, NULL); if (entries) @@ -106,17 +90,12 @@ test_init (int argc, char **argv, GOptionEntry *entries) } g_option_context_free (opts); - if (debug_level > 0 || http_debug_level > 0) - parallelize = !parallelize; - if (g_getenv ("SOUP_TESTS_IN_MAKE_CHECK")) debug_level = G_MAXINT; /* Exit cleanly on ^C in case we're valgrinding. */ signal (SIGINT, quit); - g_log_set_default_handler (test_log_handler, NULL); - tls_backend = g_tls_backend_get_default (); tls_available = g_tls_backend_supports_tls (tls_backend); } @@ -135,12 +114,6 @@ test_cleanup (void) g_main_context_unref (g_main_context_default ()); debug_printf (1, "\n"); - if (errors) { - g_print ("%s: %d error(s).%s\n", - g_get_prgname (), errors, - debug_level == 0 ? " Run with '-d' for details" : ""); - } else - g_print ("%s: OK\n", g_get_prgname ()); } void @@ -257,16 +230,10 @@ soup_test_session_new (GType type, ...) void soup_test_session_abort_unref (SoupSession *session) { - g_object_add_weak_pointer (G_OBJECT (session), (gpointer *)&session); - soup_session_abort (session); - g_object_unref (session); - if (session) { - errors++; - debug_printf (1, "leaked SoupSession!\n"); - g_object_remove_weak_pointer (G_OBJECT (session), (gpointer *)&session); - } + g_assert_cmpint (G_OBJECT (session)->ref_count, ==, 1); + g_object_unref (session); } static gpointer run_server_thread (gpointer user_data); @@ -348,9 +315,6 @@ soup_test_server_quit_unref (SoupServer *server) { GThread *thread; - g_object_add_weak_pointer (G_OBJECT (server), - (gpointer *)&server); - thread = g_object_get_data (G_OBJECT (server), "thread"); if (thread) { soup_add_completion (soup_server_get_async_context (server), @@ -358,14 +322,9 @@ soup_test_server_quit_unref (SoupServer *server) g_thread_join (thread); } else soup_server_quit (server); - g_object_unref (server); - if (server) { - errors++; - debug_printf (1, "leaked SoupServer!\n"); - g_object_remove_weak_pointer (G_OBJECT (server), - (gpointer *)&server); - } + g_assert_cmpint (G_OBJECT (server)->ref_count, ==, 1); + g_object_unref (server); } typedef struct { @@ -554,3 +513,23 @@ soup_test_request_close_stream (SoupRequest *req, return ok; } + +#ifndef G_HAVE_ISO_VARARGS +void +soup_test_assert (gboolean expr, const char *fmt, ...) +{ + char *message; + va_list args; + + if (G_UNLIKELY (!expr)) { + va_start (args, fmt); + message = g_strdup_vprintf (fmt, args); + va_end (args); + + g_assertion_message (G_LOG_DOMAIN, + "???", 0, "???" + message); + g_free (message); + } +} +#endif diff --git a/tests/test-utils.h b/tests/test-utils.h index c85103d8..97741516 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -1,3 +1,5 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -13,9 +15,8 @@ void test_init (int argc, char **argv, GOptionEntry *entries); void test_cleanup (void); -extern int debug_level, errors; -extern gboolean parallelize; -extern gboolean expect_warning, tls_available; +extern int debug_level; +extern gboolean tls_available; void debug_printf (int level, const char *format, ...) G_GNUC_PRINTF (2, 3); #ifdef HAVE_APACHE @@ -24,13 +25,13 @@ void apache_cleanup (void); #endif typedef enum { - SOUP_TEST_REQUEST_NONE = 0, - SOUP_TEST_REQUEST_CANCEL_MESSAGE = (1 << 0), - SOUP_TEST_REQUEST_CANCEL_CANCELLABLE = (1 << 1), - SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2), - SOUP_TEST_REQUEST_CANCEL_IMMEDIATE = (1 << 3), - SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE = (1 << 4), - SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH = (1 << 5), + SOUP_TEST_REQUEST_NONE = 0, + SOUP_TEST_REQUEST_CANCEL_MESSAGE = (1 << 0), + SOUP_TEST_REQUEST_CANCEL_CANCELLABLE = (1 << 1), + SOUP_TEST_REQUEST_CANCEL_SOON = (1 << 2), + SOUP_TEST_REQUEST_CANCEL_IMMEDIATE = (1 << 3), + SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE = (1 << 4), + SOUP_TEST_REQUEST_CANCEL_AFTER_SEND_FINISH = (1 << 5), } SoupTestRequestFlags; SoupSession *soup_test_session_new (GType type, ...); @@ -52,3 +53,50 @@ gboolean soup_test_request_close_stream (SoupRequest *req, GInputStream *stream, GCancellable *cancellable, GError **error); + +#ifdef G_HAVE_ISO_VARARGS +#define soup_test_assert(expr, ...) \ +G_STMT_START { \ + char *_message; \ + if (G_UNLIKELY (!(expr))) { \ + _message = g_strdup_printf (__VA_ARGS__); \ + g_assertion_message (G_LOG_DOMAIN, \ + __FILE__, __LINE__, G_STRFUNC, \ + _message); \ + g_free (_message); \ + } \ +} G_STMT_END +#else +void soup_test_assert (gboolean expr, const char *fmt, ...); +#endif + +#define soup_test_assert_message_status(msg, status) \ +G_STMT_START { \ + SoupMessage *_msg = (msg); \ + guint _status = (status); \ + char *_message; \ + \ + if (G_UNLIKELY (_msg->status_code != _status)) { \ + _message = g_strdup_printf ("Unexpected status %d %s (expected %d %s)", \ + _msg->status_code, _msg->reason_phrase, \ + _status, soup_status_get_phrase (_status)); \ + g_assertion_message (G_LOG_DOMAIN, \ + __FILE__, __LINE__, G_STRFUNC, \ + _message); \ + g_free (_message); \ + } \ +} G_STMT_END + +#define soup_assert_cmpmem(s1, l1, s2, l2) \ +G_STMT_START { \ + int __l1 = l1, __l2 = l2; \ + gconstpointer __s1 = s1, __s2 = s2; \ + if (G_UNLIKELY ((__l1) != (__l2))) { \ + g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + "len(" #s1 ") == len(" #s2 ")", __l1, "==", __l2, \ + 'i'); \ + } else if (G_UNLIKELY (memcmp (__s1, __s2, __l1) != 0)) { \ + g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + "assertion failed (" #s1 " == " #s2 ")"); \ + } \ +} G_STMT_END diff --git a/tests/timeout-test.c b/tests/timeout-test.c index 5903069b..fba515db 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -2,6 +2,8 @@ #include "test-utils.h" +static gboolean slow_https; + static void message_finished (SoupMessage *msg, gpointer user_data) { @@ -34,24 +36,10 @@ do_message_to_session (SoupSession *session, const char *uri, G_CALLBACK (message_finished), &finished); soup_session_send_message (session, msg); - if (msg->status_code != expected_status) { - debug_printf (1, " FAILED: %d %s (expected %d %s)\n", - msg->status_code, msg->reason_phrase, - expected_status, - soup_status_get_phrase (expected_status)); - errors++; - } - - if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code) && - !soup_message_is_keepalive (msg)) { - debug_printf (1, " ERROR: message is not keepalive!\n"); - errors++; - } - - if (!finished) { - debug_printf (1, " ERROR: 'finished' was not emitted\n"); - errors++; - } + soup_test_assert_message_status (msg, expected_status); + if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + g_assert_true (soup_message_is_keepalive (msg)); + g_assert_true (finished); g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (message_finished), @@ -63,7 +51,8 @@ static void do_msg_tests_for_session (SoupSession *timeout_session, SoupSession *idle_session, SoupSession *plain_session, - char *fast_uri, char *slow_uri) + const char *fast_uri, + const char *slow_uri) { SoupSocket *ret, *idle_first, *idle_second; SoupSocket *plain_first, *plain_second; @@ -92,10 +81,8 @@ do_msg_tests_for_session (SoupSession *timeout_session, (gpointer)request_started_cb, &ret); - if (idle_first == idle_second) { - debug_printf (1, " ERROR: idle_session did not close first connection\n"); - errors++; - } + soup_test_assert (idle_first != idle_second, + "idle_session did not close first connection"); g_object_unref (idle_first); } @@ -106,10 +93,8 @@ do_msg_tests_for_session (SoupSession *timeout_session, (gpointer)request_started_cb, &ret); - if (plain_first != plain_second) { - debug_printf (1, " ERROR: plain_session closed connection\n"); - errors++; - } + soup_test_assert (plain_first == plain_second, + "plain_session closed connection"); g_object_unref (plain_first); } } @@ -132,51 +117,26 @@ do_request_to_session (SoupSession *session, const char *uri, G_CALLBACK (message_finished), &finished); stream = soup_test_request_send (req, NULL, 0, &error); - if (expect_timeout && !error) { - debug_printf (1, " FAILED: request did not time out\n"); - errors++; - } else if (expect_timeout && !g_error_matches (error, G_IO_ERROR, - G_IO_ERROR_TIMED_OUT)) { - debug_printf (1, " FAILED: wrong error: %s\n", - error->message); - errors++; - } else if (!expect_timeout && error) { - debug_printf (1, " FAILED: expected success but got error: %s\n", - error->message); - errors++; - } + if (expect_timeout) + g_assert_error (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT); + else + g_assert_no_error (error); g_clear_error (&error); if (stream) { soup_test_request_read_all (req, stream, NULL, &error); - if (error) { - debug_printf (1, " ERROR reading stream: %s\n", - error->message); - errors++; - } + g_assert_no_error (error); } if (stream) { soup_test_request_close_stream (req, stream, NULL, &error); - - if (error) { - debug_printf (1, " ERROR closing stream: %s\n", - error->message); - errors++; - } + g_assert_no_error (error); g_object_unref (stream); } - if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code) && - !soup_message_is_keepalive (msg)) { - debug_printf (1, " ERROR: message is not keepalive!\n"); - errors++; - } - - if (!finished) { - debug_printf (1, " ERROR: 'finished' was not emitted\n"); - errors++; - } + if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + g_assert_true (soup_message_is_keepalive (msg)); + g_assert_true (finished); g_signal_handlers_disconnect_by_func (msg, G_CALLBACK (message_finished), @@ -189,7 +149,8 @@ static void do_req_tests_for_session (SoupSession *timeout_session, SoupSession *idle_session, SoupSession *plain_session, - char *fast_uri, char *slow_uri) + const char *fast_uri, + const char *slow_uri) { SoupSocket *ret, *idle_first, *idle_second; SoupSocket *plain_first, *plain_second; @@ -220,10 +181,8 @@ do_req_tests_for_session (SoupSession *timeout_session, (gpointer)request_started_cb, &ret); - if (idle_first == idle_second) { - debug_printf (1, " ERROR: idle_session did not close first connection\n"); - errors++; - } + soup_test_assert (idle_first != idle_second, + "idle_session did not close first connection"); g_object_unref (idle_first); } @@ -234,20 +193,30 @@ do_req_tests_for_session (SoupSession *timeout_session, (gpointer)request_started_cb, &ret); - if (plain_first != plain_second) { - debug_printf (1, " ERROR: plain_session closed connection\n"); - errors++; - } + soup_test_assert (plain_first == plain_second, + "plain_session closed connection"); g_object_unref (plain_first); } } static void -do_timeout_tests (char *fast_uri, char *slow_uri, gboolean extra_slow) +do_async_timeout_tests (gconstpointer data) { SoupSession *timeout_session, *idle_session, *plain_session; + const char *fast_uri = data; + const char *slow_uri = g_build_path ("/", fast_uri, "slow", NULL); + gboolean extra_slow; + + if (g_str_has_prefix (fast_uri, "https")) { + if (!tls_available) { + g_test_skip ("TLS not available"); + return; + } + + extra_slow = slow_https; + } else + extra_slow = FALSE; - debug_printf (1, " async\n"); timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, @@ -272,8 +241,26 @@ do_timeout_tests (char *fast_uri, char *slow_uri, gboolean extra_slow) soup_test_session_abort_unref (timeout_session); soup_test_session_abort_unref (idle_session); soup_test_session_abort_unref (plain_session); +} + +static void +do_sync_timeout_tests (gconstpointer data) +{ + SoupSession *timeout_session, *plain_session; + const char *fast_uri = data; + const char *slow_uri = g_build_path ("/", fast_uri, "slow", NULL); + gboolean extra_slow; + + if (g_str_has_prefix (fast_uri, "https")) { + if (!tls_available) { + g_test_skip ("TLS not available"); + return; + } + + extra_slow = slow_https; + } else + extra_slow = FALSE; - debug_printf (1, "\n sync\n"); timeout_session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, SOUP_SESSION_TIMEOUT, extra_slow ? 3 : 1, NULL); @@ -319,57 +306,55 @@ server_handler (SoupServer *server, int main (int argc, char **argv) { - SoupServer *server; - char *fast_uri, *slow_uri; + SoupServer *server, *https_server = NULL; + char *uri, *https_uri = NULL; + int ret; test_init (argc, argv, NULL); - debug_printf (1, "http\n"); server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_handler, NULL, NULL); - fast_uri = g_strdup_printf ("http://127.0.0.1:%u/", - soup_server_get_port (server)); - slow_uri = g_strdup_printf ("http://127.0.0.1:%u/slow", - soup_server_get_port (server)); - do_timeout_tests (fast_uri, slow_uri, FALSE); - g_free (fast_uri); - g_free (slow_uri); - soup_test_server_quit_unref (server); + uri = g_strdup_printf ("http://127.0.0.1:%u/", + soup_server_get_port (server)); if (tls_available) { SoupSession *test_session; - gboolean extra_slow; gint64 start, end; - debug_printf (1, "\nhttps\n"); - server = soup_test_server_new_ssl (TRUE); - soup_server_add_handler (server, NULL, server_handler, NULL, NULL); - fast_uri = g_strdup_printf ("https://127.0.0.1:%u/", - soup_server_get_port (server)); - slow_uri = g_strdup_printf ("https://127.0.0.1:%u/slow", - soup_server_get_port (server)); + https_server = soup_test_server_new_ssl (TRUE); + soup_server_add_handler (https_server, NULL, server_handler, NULL, NULL); + https_uri = g_strdup_printf ("https://127.0.0.1:%u/", + soup_server_get_port (https_server)); /* The 1-second timeouts are too fast for some machines... */ test_session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); start = g_get_monotonic_time (); - do_message_to_session (test_session, fast_uri, NULL, SOUP_STATUS_OK); + do_message_to_session (test_session, uri, NULL, SOUP_STATUS_OK); end = g_get_monotonic_time (); soup_test_session_abort_unref (test_session); debug_printf (2, " (https request took %0.3fs)\n", (end - start) / 1000000.0); if (end - start > 750000) { debug_printf (1, " (using extra-slow mode)\n\n"); - extra_slow = TRUE; + slow_https = TRUE; } else { debug_printf (2, "\n"); - extra_slow = FALSE; + slow_https = FALSE; } - - do_timeout_tests (fast_uri, slow_uri, extra_slow); - g_free (fast_uri); - g_free (slow_uri); - soup_test_server_quit_unref (server); } + g_test_add_data_func ("/timeout/http/async", uri, do_async_timeout_tests); + g_test_add_data_func ("/timeout/http/sync", uri, do_sync_timeout_tests); + g_test_add_data_func ("/timeout/https/async", https_uri, do_async_timeout_tests); + g_test_add_data_func ("/timeout/https/sync", https_uri, do_sync_timeout_tests); + + ret = g_test_run (); + + g_free (uri); + g_free (https_uri); + soup_test_server_quit_unref (server); + if (https_server) + soup_test_server_quit_unref (https_server); + test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/tld-test.c b/tests/tld-test.c index d1f1de1f..2e7f8a21 100644 --- a/tests/tld-test.c +++ b/tests/tld-test.c @@ -7,176 +7,183 @@ /* From http://publicsuffix.org/list/test.txt */ static struct { - const char *hostname; - const char *result; + const char *hostname; + const char *result; + SoupTLDError error; } tld_tests[] = { - /* NULL input. Not checked here because the API requires a valid hostname. */ - /* { NULL, NULL }, */ - /* Mixed case. Not checked because the API requires a valid hostname. */ - /* { "COM", NULL }, */ - /* { "example.COM", "example.com" }, */ - /* { "WwW.example.COM", "example.com" }, */ - /* Leading dot. */ - { ".com", NULL }, - { ".example", NULL }, - { ".example.com", NULL }, - { ".example.example", NULL }, - /* TLD with only 1 rule. */ - { "biz", NULL }, - { "domain.biz", "domain.biz" }, - { "b.domain.biz", "domain.biz" }, - { "a.b.domain.biz", "domain.biz" }, - /* TLD with some 2-level rules. */ - { "com", NULL }, - { "example.com", "example.com" }, - { "b.example.com", "example.com" }, - { "a.b.example.com", "example.com" }, - { "uk.com", NULL }, - { "example.uk.com", "example.uk.com" }, - { "b.example.uk.com", "example.uk.com" }, - { "a.b.example.uk.com", "example.uk.com" }, - { "test.ac", "test.ac" }, - /* TLD with only 1 (wildcard) rule. */ - { "cy", NULL }, - { "c.cy", NULL }, - { "b.c.cy", "b.c.cy" }, - { "a.b.c.cy", "b.c.cy" }, - /* More complex TLD. */ - { "jp", NULL }, - { "test.jp", "test.jp" }, - { "www.test.jp", "test.jp" }, - { "ac.jp", NULL }, - { "test.ac.jp", "test.ac.jp" }, - { "www.test.ac.jp", "test.ac.jp" }, - { "kyoto.jp", NULL }, - { "minami.kyoto.jp", NULL }, - { "b.minami.kyoto.jp", "b.minami.kyoto.jp" }, - { "a.b.minami.kyoto.jp", "b.minami.kyoto.jp" }, - { "pref.kyoto.jp", "pref.kyoto.jp" }, - { "www.pref.kyoto.jp", "pref.kyoto.jp" }, - { "city.kyoto.jp", "city.kyoto.jp" }, - { "www.city.kyoto.jp", "city.kyoto.jp" }, - /* TLD with a wildcard rule and exceptions. */ - { "ck", NULL }, - { "test.ck", NULL }, - { "b.test.ck", "b.test.ck" }, - { "a.b.test.ck", "b.test.ck" }, - { "www.ck", "www.ck" }, - { "www.www.ck", "www.ck" }, - /* US K12. */ - { "us", NULL }, - { "test.us", "test.us" }, - { "www.test.us", "test.us" }, - { "ak.us", NULL }, - { "test.ak.us", "test.ak.us" }, - { "www.test.ak.us", "test.ak.us" }, - { "k12.ak.us", NULL }, - { "test.k12.ak.us", "test.k12.ak.us" }, - { "www.test.k12.ak.us", "test.k12.ak.us" }, - /* IDN labels. */ - { "食狮.com.cn", "食狮.com.cn" }, - { "食狮.公司.cn", "食狮.公司.cn" }, - { "www.食狮.公司.cn", "食狮.公司.cn" }, - { "shishi.公司.cn", "shishi.公司.cn" }, - { "公司.cn", NULL }, - { "食狮.中国", "食狮.中国" }, - { "www.食狮.中国", "食狮.中国" }, - { "shishi.中国", "shishi.中国" }, - { "中国", NULL }, - /* Same as above, but punycoded. */ - { "xn--85x722f.com.cn", "xn--85x722f.com.cn" }, - { "xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn" }, - { "www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn" }, - { "shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn" }, - { "xn--55qx5d.cn", NULL }, - { "xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s" }, - { "www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s" }, - { "shishi.xn--fiqs8s", "shishi.xn--fiqs8s" }, - { "xn--fiqs8s", NULL }, - /* End of publicsuffix.org tests */ - - /* Let's just double-check this one... */ - { "co.uk", NULL }, - { "test.co.uk", "test.co.uk" }, - { "www.test.co.uk", "test.co.uk" }, - - /* Two levels of non-ASCII */ - { "våler.østfold.no", NULL }, - { "test.våler.østfold.no", "test.våler.østfold.no" }, - { "www.test.våler.østfold.no", "test.våler.østfold.no" }, - { "xn--vler-qoa.xn--stfold-9xa.no", NULL }, - { "test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no" }, - { "www.test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no" }, + /* NULL input. Not checked here because the API requires a valid hostname. */ + /* { NULL, NULL, -1 }, */ + /* Mixed case. Not checked because the API requires a valid hostname. */ + /* { "COM", NULL, -1 }, */ + /* { "example.COM", "example.com", -1 }, */ + /* { "WwW.example.COM", "example.com", -1 }, */ + /* Leading dot. */ + { ".com", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + { ".example", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + { ".example.com", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + { ".example.example", NULL, SOUP_TLD_ERROR_INVALID_HOSTNAME }, + /* TLD with only 1 rule. */ + { "biz", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "domain.biz", "domain.biz", -1 }, + { "b.domain.biz", "domain.biz", -1 }, + { "a.b.domain.biz", "domain.biz", -1 }, + /* TLD with some 2-level rules. */ + { "com", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "example.com", "example.com", -1 }, + { "b.example.com", "example.com", -1 }, + { "a.b.example.com", "example.com", -1 }, + { "uk.com", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "example.uk.com", "example.uk.com", -1 }, + { "b.example.uk.com", "example.uk.com", -1 }, + { "a.b.example.uk.com", "example.uk.com", -1 }, + { "test.ac", "test.ac", -1 }, + /* TLD with only 1 (wildcard) rule. */ + { "cy", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "c.cy", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "b.c.cy", "b.c.cy", -1 }, + { "a.b.c.cy", "b.c.cy", -1 }, + /* More complex TLD. */ + { "jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.jp", "test.jp", -1 }, + { "www.test.jp", "test.jp", -1 }, + { "ac.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.ac.jp", "test.ac.jp", -1 }, + { "www.test.ac.jp", "test.ac.jp", -1 }, + { "kyoto.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "minami.kyoto.jp", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "b.minami.kyoto.jp", "b.minami.kyoto.jp", -1 }, + { "a.b.minami.kyoto.jp", "b.minami.kyoto.jp", -1 }, + { "pref.kyoto.jp", "pref.kyoto.jp", -1 }, + { "www.pref.kyoto.jp", "pref.kyoto.jp", -1 }, + { "city.kyoto.jp", "city.kyoto.jp", -1 }, + { "www.city.kyoto.jp", "city.kyoto.jp", -1 }, + /* TLD with a wildcard rule and exceptions. */ + { "ck", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.ck", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "b.test.ck", "b.test.ck", -1 }, + { "a.b.test.ck", "b.test.ck", -1 }, + { "www.ck", "www.ck", -1 }, + { "www.www.ck", "www.ck", -1 }, + /* US K12. */ + { "us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.us", "test.us", -1 }, + { "www.test.us", "test.us", -1 }, + { "ak.us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.ak.us", "test.ak.us", -1 }, + { "www.test.ak.us", "test.ak.us", -1 }, + { "k12.ak.us", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.k12.ak.us", "test.k12.ak.us", -1 }, + { "www.test.k12.ak.us", "test.k12.ak.us", -1 }, + /* IDN labels. */ + { "食狮.com.cn", "食狮.com.cn", -1 }, + { "食狮.公司.cn", "食狮.公司.cn", -1 }, + { "www.食狮.公司.cn", "食狮.公司.cn", -1 }, + { "shishi.公司.cn", "shishi.公司.cn", -1 }, + { "公司.cn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "食狮.中国", "食狮.中国", -1 }, + { "www.食狮.中国", "食狮.中国", -1 }, + { "shishi.中国", "shishi.中国", -1 }, + { "中国", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + /* Same as above, but punycoded. */ + { "xn--85x722f.com.cn", "xn--85x722f.com.cn", -1 }, + { "xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn", -1 }, + { "www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn", -1 }, + { "shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn", -1 }, + { "xn--55qx5d.cn", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s", -1 }, + { "www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s", -1 }, + { "shishi.xn--fiqs8s", "shishi.xn--fiqs8s", -1 }, + { "xn--fiqs8s", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + /* End of publicsuffix.org tests */ + + /* Let's just double-check this one... */ + { "co.uk", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.co.uk", "test.co.uk", -1 }, + { "www.test.co.uk", "test.co.uk", -1 }, + + /* Two levels of non-ASCII */ + { "våler.østfold.no", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.våler.østfold.no", "test.våler.østfold.no", -1 }, + { "www.test.våler.østfold.no", "test.våler.østfold.no", -1 }, + { "xn--vler-qoa.xn--stfold-9xa.no", NULL, SOUP_TLD_ERROR_NOT_ENOUGH_DOMAINS }, + { "test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no", -1 }, + { "www.test.xn--vler-qoa.xn--stfold-9xa.no", "test.xn--vler-qoa.xn--stfold-9xa.no", -1 }, }, + /* Non Internet TLDs have NULL as expected result */ non_inet_tld_tests[] = { - /* Unlisted TLD.*/ - { "example", NULL }, - { "example.example", NULL }, - { "b.example.example", NULL }, - { "a.b.example.example", NULL }, - /* Listed, but non-Internet, TLD. */ - { "local", NULL }, - { "example.local", NULL }, - { "b.example.local", NULL }, - { "a.b.example.local", NULL } + /* Unlisted TLD.*/ + { "example", NULL }, + { "example.example", NULL }, + { "b.example.example", NULL }, + { "a.b.example.example", NULL }, + /* Listed, but non-Internet, TLD. */ + { "local", NULL }, + { "example.local", NULL }, + { "b.example.local", NULL }, + { "a.b.example.local", NULL } }; -int -main (int argc, char **argv) +static void +do_inet_tests (void) { int i; - test_init (argc, argv, NULL); - - errors = 0; - for (i = 0; i < G_N_ELEMENTS (tld_tests); ++i) { + for (i = 0; i < G_N_ELEMENTS (tld_tests); i++) { GError *error = NULL; - gboolean is_public = soup_tld_domain_is_public_suffix (tld_tests[i].hostname); - const char *base_domain = soup_tld_get_base_domain (tld_tests[i].hostname, &error); - - debug_printf (1, "Testing %s: ", tld_tests[i].hostname); - - if (is_public && tld_tests[i].result) { - debug_printf (1, "ERROR: domain is public but base_domain is not NULL (%s)\n", - base_domain); - ++errors; - } else if (g_strcmp0 (tld_tests[i].result, base_domain)) { - debug_printf (1, "ERROR: %s expected as base domain but got %s\n", - tld_tests[i].result, base_domain); - ++errors; - - } else if (!tld_tests[i].result && !is_public && - !g_error_matches (error, SOUP_TLD_ERROR, SOUP_TLD_ERROR_INVALID_HOSTNAME)) { - debug_printf (1, "ERROR: not public domain with NULL expected result\n"); - ++errors; - } else - debug_printf (1, "OK\n"); - - g_clear_error(&error); + gboolean is_public; + const char *base_domain; + + debug_printf (1, "Testing %s\n", tld_tests[i].hostname); + + is_public = soup_tld_domain_is_public_suffix (tld_tests[i].hostname); + base_domain = soup_tld_get_base_domain (tld_tests[i].hostname, &error); + + if (base_domain) { + g_assert_no_error (error); + g_assert_false (is_public); + g_assert_cmpstr (base_domain, ==, tld_tests[i].result); + } else { + g_assert_null (tld_tests[i].result); + g_assert_error (error, SOUP_TLD_ERROR, tld_tests[i].error); + g_clear_error (&error); + } } +} + +static void +do_non_inet_tests (void) +{ + int i; - debug_printf (1, "\n"); + for (i = 0; i < G_N_ELEMENTS (non_inet_tld_tests); i++) { + gboolean is_public; + const char *base_domain; - for (i = 0; i < G_N_ELEMENTS (non_inet_tld_tests); ++i) { - gboolean is_public = soup_tld_domain_is_public_suffix (non_inet_tld_tests[i].hostname); - const char *base_domain = soup_tld_get_base_domain (non_inet_tld_tests[i].hostname, NULL); + debug_printf (1, "Testing %s\n", non_inet_tld_tests[i].hostname); - debug_printf (1, "Testing %s: ", non_inet_tld_tests[i].hostname); + is_public = soup_tld_domain_is_public_suffix (non_inet_tld_tests[i].hostname); + base_domain = soup_tld_get_base_domain (non_inet_tld_tests[i].hostname, NULL); - if (is_public) { - debug_printf (1, "ERROR: domain incorrectly clasified as public\n"); - ++errors; - } else if (base_domain) { - debug_printf (1, "ERROR: non NULL base domain (%s) for local url\n", - base_domain); - ++errors; - } else - debug_printf (1, "OK\n"); + g_assert_false (is_public); + g_assert_null (base_domain); } +} + +int +main (int argc, char **argv) +{ + int ret; + + test_init (argc, argv, NULL); + + g_test_add_func ("/tld/inet", do_inet_tests); + g_test_add_func ("/tld/non-inet", do_non_inet_tests); + + ret = g_test_run (); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index b4f495b6..e67253e3 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -266,39 +266,7 @@ static struct { }; static int num_eq_tests = G_N_ELEMENTS(eq_tests); -#define test_cmpstr(a, b) _test_cmpstr (#a, #b, a, b) - -static gboolean -_test_cmpstr (const char *got_desc, - const char *exp_desc, - const char *got, - const char *expected) -{ - if (got == expected) - return TRUE; - - if (got == NULL) { - debug_printf (1, "ERR\n %s = NULL, expected %s = \"%s\"\n", - got_desc, exp_desc, expected); - return FALSE; - } - - if (expected == NULL) { - debug_printf (1, "ERR\n %s = \"%s\", expected %s = NULL\n", - got_desc, got, exp_desc); - return FALSE; - } - - if (strcmp (got, expected) != 0) { - debug_printf (1, "ERR\n %s = \"%s\", expected %s = \"%s\"\n", - got_desc, got, exp_desc, expected); - return FALSE; - } - - return TRUE; -} - -static gboolean +static void do_uri (SoupURI *base_uri, const char *base_str, const char *in_uri, const char *out_uri, const SoupURI *bits) @@ -307,76 +275,89 @@ do_uri (SoupURI *base_uri, const char *base_str, char *uri_string; if (base_uri) { - debug_printf (1, "<%s> + <%s> = <%s>? ", base_str, in_uri, + debug_printf (1, "<%s> + <%s> = <%s>\n", base_str, in_uri, out_uri ? out_uri : "ERR"); uri = soup_uri_new_with_base (base_uri, in_uri); } else { - debug_printf (1, "<%s> => <%s>? ", in_uri, + debug_printf (1, "<%s> => <%s>\n", in_uri, out_uri ? out_uri : "ERR"); uri = soup_uri_new (in_uri); } if (!uri) { - if (out_uri) { - debug_printf (1, "ERR\n Could not parse %s\n", in_uri); - return FALSE; - } else { - debug_printf (1, "OK\n"); - return TRUE; - } + g_assert_null (out_uri); + return; } if (bits != NULL) { - gboolean failed = FALSE; - - if (!test_cmpstr (uri->scheme, bits->scheme)) - failed = TRUE; + g_assert_cmpstr (uri->scheme, ==, bits->scheme); + g_assert_cmpstr (uri->user, ==, bits->user); + g_assert_cmpstr (uri->password, ==, bits->password); + g_assert_cmpstr (uri->host, ==, bits->host); + g_assert_cmpuint (uri->port, ==, bits->port); + g_assert_cmpstr (uri->path, ==, bits->path); + g_assert_cmpstr (uri->query, ==, bits->query); + g_assert_cmpstr (uri->fragment, ==, bits->fragment); + } - if (!test_cmpstr (uri->user, bits->user)) - failed = TRUE; + uri_string = soup_uri_to_string (uri, FALSE); + soup_uri_free (uri); - if (!test_cmpstr (uri->password, bits->password)) - failed = TRUE; + g_assert_cmpstr (uri_string, ==, out_uri); + g_free (uri_string); +} - if (!test_cmpstr (uri->host, bits->host)) - failed = TRUE; +static void +do_absolute_uri_tests (void) +{ + int i; - if (uri->port != bits->port) { - debug_printf (1, "ERR\n port was %u, expected %u\n", - uri->port, bits->port); - failed = TRUE; - } + for (i = 0; i < num_abs_tests; i++) { + do_uri (NULL, NULL, abs_tests[i].uri_string, + abs_tests[i].result, &abs_tests[i].bits); + } +} - if (!test_cmpstr (uri->path, bits->path)) - failed = TRUE; +static void +do_relative_uri_tests (void) +{ + SoupURI *base_uri; + char *uri_string; + int i; - if (!test_cmpstr (uri->query, bits->query)) - failed = TRUE; + base_uri = soup_uri_new (base); + if (!base_uri) { + g_printerr ("Could not parse %s!\n", base); + exit (1); + } - if (!test_cmpstr (uri->fragment, bits->fragment)) - failed = TRUE; + uri_string = soup_uri_to_string (base_uri, FALSE); + g_assert_cmpstr (uri_string, ==, base); + g_free (uri_string); - if (failed) - return FALSE; + for (i = 0; i < num_rel_tests; i++) { + do_uri (base_uri, base, rel_tests[i].uri_string, + rel_tests[i].result, &rel_tests[i].bits); } + soup_uri_free (base_uri); +} - uri_string = soup_uri_to_string (uri, FALSE); - soup_uri_free (uri); +static void +do_equality_tests (void) +{ + SoupURI *uri1, *uri2; + int i; - if (!out_uri) { - debug_printf (1, "ERR\n Got %s\n", uri_string); - return FALSE; - } + for (i = 0; i < num_eq_tests; i++) { + uri1 = soup_uri_new (eq_tests[i].one); + uri2 = soup_uri_new (eq_tests[i].two); - if (strcmp (uri_string, out_uri) != 0) { - debug_printf (1, "NO\n Unparses to <%s>\n", uri_string); - g_free (uri_string); - return FALSE; - } - g_free (uri_string); + debug_printf (1, "<%s> == <%s>\n", eq_tests[i].one, eq_tests[i].two); + g_assert_true (soup_uri_equal (uri1, uri2)); - debug_printf (1, "OK\n"); - return TRUE; + soup_uri_free (uri1); + soup_uri_free (uri2); + } } static void @@ -385,146 +366,80 @@ do_soup_uri_null_tests (void) SoupURI *uri, *uri2; char *uri_string; - debug_printf (1, "\nsoup_uri_new (NULL)\n"); uri = soup_uri_new (NULL); - if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) { - debug_printf (1, " ERROR: soup_uri_new(NULL) returns valid URI?\n"); - errors++; - } + g_assert_false (SOUP_URI_IS_VALID (uri)); + g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri)); /* This implicitly also verifies that none of these methods g_warn */ - if (soup_uri_get_scheme (uri) || - soup_uri_get_user (uri) || - soup_uri_get_password (uri) || - soup_uri_get_host (uri) || - soup_uri_get_port (uri) || - soup_uri_get_path (uri) || - soup_uri_get_query (uri) || - soup_uri_get_fragment (uri)) { - debug_printf (1, " ERROR: soup_uri_new(NULL) returns non-empty URI?\n"); - errors++; - } - - expect_warning = TRUE; + g_assert_null (soup_uri_get_scheme (uri)); + g_assert_null (soup_uri_get_user (uri)); + g_assert_null (soup_uri_get_password (uri)); + g_assert_null (soup_uri_get_host (uri)); + g_assert_cmpint (soup_uri_get_port (uri), ==, 0); + g_assert_null (soup_uri_get_path (uri)); + g_assert_null (soup_uri_get_query (uri)); + g_assert_null (soup_uri_get_fragment (uri)); + + g_test_expect_message ("libsoup", G_LOG_LEVEL_CRITICAL, + "*base == NULL*"); uri2 = soup_uri_new_with_base (uri, "/path"); - if (uri2 || expect_warning) { - debug_printf (1, " ERROR: soup_uri_new_with_base didn't fail on NULL URI?\n"); - errors++; - expect_warning = FALSE; - } + g_test_assert_expected_messages (); + g_assert_null (uri2); - expect_warning = TRUE; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*SOUP_URI_IS_VALID*"); uri_string = soup_uri_to_string (uri, FALSE); - if (expect_warning) { - debug_printf (1, " ERROR: soup_uri_to_string didn't fail on NULL URI?\n"); - errors++; - expect_warning = FALSE; - } else if (*uri_string) { - debug_printf (1, " ERROR: soup_uri_to_string on NULL URI returned '%s'\n", - uri_string); - errors++; - } + g_test_assert_expected_messages (); + g_assert_cmpstr (uri_string, ==, ""); g_free (uri_string); soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP); - if (SOUP_URI_IS_VALID (uri) || SOUP_URI_VALID_FOR_HTTP (uri)) { - debug_printf (1, " ERROR: setting scheme on NULL URI makes it valid?\n"); - errors++; - } + g_assert_false (SOUP_URI_IS_VALID (uri)); + g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri)); - expect_warning = TRUE; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*SOUP_URI_IS_VALID*"); uri_string = soup_uri_to_string (uri, FALSE); - if (expect_warning) { - debug_printf (1, " ERROR: soup_uri_to_string didn't fail on scheme-only URI?\n"); - errors++; - expect_warning = FALSE; - } else if (strcmp (uri_string, "http:") != 0) { - debug_printf (1, " ERROR: soup_uri_to_string returned '%s' instead of 'http:'\n", - uri_string); - errors++; - } + g_test_assert_expected_messages (); + g_assert_cmpstr (uri_string, ==, "http:"); g_free (uri_string); soup_uri_set_host (uri, "localhost"); - if (SOUP_URI_IS_VALID (uri)) { - debug_printf (1, " ERROR: setting scheme+host on NULL URI makes it valid?\n"); - errors++; - } - if (SOUP_URI_VALID_FOR_HTTP (uri)) { - debug_printf (1, " ERROR: setting scheme+host on NULL URI makes it valid for http?\n"); - errors++; - } + g_assert_false (SOUP_URI_IS_VALID (uri)); + g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri)); - expect_warning = TRUE; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*SOUP_URI_IS_VALID*"); uri_string = soup_uri_to_string (uri, FALSE); - if (expect_warning) { - debug_printf (1, " ERROR: soup_uri_to_string didn't fail on scheme+host URI?\n"); - errors++; - expect_warning = FALSE; - } else if (strcmp (uri_string, "http://localhost/") != 0) { - debug_printf (1, " ERROR: soup_uri_to_string with NULL path returned '%s' instead of 'http://localhost/'\n", - uri_string); - errors++; - } + g_test_assert_expected_messages (); + g_assert_cmpstr (uri_string, ==, "http://localhost/"); g_free (uri_string); - expect_warning = TRUE; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*SOUP_URI_IS_VALID*"); uri2 = soup_uri_new_with_base (uri, "/path"); - if (expect_warning) { - debug_printf (1, " ERROR: soup_uri_new_with_base didn't warn on NULL+scheme URI?\n"); - errors++; - expect_warning = FALSE; - } else if (!uri2) { - debug_printf (1, " ERROR: soup_uri_new_with_base didn't fix path on NULL+scheme URI\n"); - errors++; - } + g_test_assert_expected_messages (); + g_assert_true (uri2 != NULL); if (uri2) { uri_string = soup_uri_to_string (uri2, FALSE); - if (!uri_string) { - debug_printf (1, " ERROR: soup_uri_to_string failed on uri2?\n"); - errors++; - } else if (strcmp (uri_string, "http://localhost/path") != 0) { - debug_printf (1, " ERROR: soup_uri_to_string returned '%s' instead of 'http://localhost/path'\n", - uri_string); - errors++; - } + g_assert_cmpstr (uri_string, ==, "http://localhost/path"); g_free (uri_string); soup_uri_free (uri2); } - expect_warning = TRUE; + g_test_expect_message ("libsoup", G_LOG_LEVEL_WARNING, + "*path != NULL*"); soup_uri_set_path (uri, NULL); - if (expect_warning) { - debug_printf (1, " ERROR: setting path to NULL doesn't warn\n"); - errors++; - expect_warning = FALSE; - } - if (!uri->path || *uri->path) { - debug_printf (1, " ERROR: setting path to NULL != \"\"\n"); - errors++; - soup_uri_set_path (uri, ""); - } + g_test_assert_expected_messages (); + g_assert_cmpstr (uri->path, ==, ""); uri_string = soup_uri_to_string (uri, FALSE); - if (!uri_string) { - debug_printf (1, " ERROR: soup_uri_to_string failed on complete URI?\n"); - errors++; - } else if (strcmp (uri_string, "http://localhost/") != 0) { - debug_printf (1, " ERROR: soup_uri_to_string with empty path returned '%s' instead of 'http://localhost/'\n", - uri_string); - errors++; - } + g_assert_cmpstr (uri_string, ==, "http://localhost/"); g_free (uri_string); - if (!SOUP_URI_IS_VALID (uri)) { - debug_printf (1, " ERROR: setting scheme+path on NULL URI doesn't make it valid?\n"); - errors++; - } - if (!SOUP_URI_VALID_FOR_HTTP (uri)) { - debug_printf (1, " ERROR: setting scheme+host+path on NULL URI doesn't make it valid for http?\n"); - errors++; - } + g_assert_true (SOUP_URI_IS_VALID (uri)); + g_assert_true (SOUP_URI_VALID_FOR_HTTP (uri)); soup_uri_free (uri); } @@ -549,29 +464,21 @@ do_normalization_tests (void) char *normalized; int i; - debug_printf (1, "\nsoup_uri_normalize\n"); - for (i = 0; i < num_normalization_tests; i++) { if (normalization_tests[i].unescape_extra) { - debug_printf (1, "<%s> unescaping <%s> => <%s>: ", + debug_printf (1, "<%s> unescaping <%s> => <%s>\n", normalization_tests[i].uri_string, normalization_tests[i].unescape_extra, normalization_tests[i].result); } else { - debug_printf (1, "<%s> => <%s>: ", + debug_printf (1, "<%s> => <%s>\n", normalization_tests[i].uri_string, normalization_tests[i].result); } normalized = soup_uri_normalize (normalization_tests[i].uri_string, normalization_tests[i].unescape_extra); - - if (!strcmp (normalized, normalization_tests[i].result)) - debug_printf (1, "OK\n"); - else { - debug_printf (1, "NO, got <%s>\n", normalized); - errors++; - } + g_assert_cmpstr (normalized, ==, normalization_tests[i].result); g_free (normalized); } } @@ -579,62 +486,18 @@ do_normalization_tests (void) int main (int argc, char **argv) { - SoupURI *base_uri, *uri1, *uri2; - char *uri_string; - int i; + int ret; test_init (argc, argv, NULL); - debug_printf (1, "Absolute URI parsing\n"); - for (i = 0; i < num_abs_tests; i++) { - if (!do_uri (NULL, NULL, abs_tests[i].uri_string, - abs_tests[i].result, &abs_tests[i].bits)) - errors++; - } - - debug_printf (1, "\nRelative URI parsing\n"); - base_uri = soup_uri_new (base); - if (!base_uri) { - g_printerr ("Could not parse %s!\n", base); - exit (1); - } - - uri_string = soup_uri_to_string (base_uri, FALSE); - if (strcmp (uri_string, base) != 0) { - g_printerr ("URI <%s> unparses to <%s>\n", - base, uri_string); - errors++; - } - g_free (uri_string); - - for (i = 0; i < num_rel_tests; i++) { - if (!do_uri (base_uri, base, rel_tests[i].uri_string, - rel_tests[i].result, &rel_tests[i].bits)) - errors++; - } - soup_uri_free (base_uri); - - debug_printf (1, "\nURI equality testing\n"); - for (i = 0; i < num_eq_tests; i++) { - uri1 = soup_uri_new (eq_tests[i].one); - uri2 = soup_uri_new (eq_tests[i].two); - debug_printf (1, "<%s> == <%s>? ", eq_tests[i].one, eq_tests[i].two); - if (soup_uri_equal (uri1, uri2)) - debug_printf (1, "OK\n"); - else { - debug_printf (1, "NO\n"); - debug_printf (1, "%s : %s : %s\n%s : %s : %s\n", - uri1->scheme, uri1->host, uri1->path, - uri2->scheme, uri2->host, uri2->path); - errors++; - } - soup_uri_free (uri1); - soup_uri_free (uri2); - } + g_test_add_func ("/uri/absolute", do_absolute_uri_tests); + g_test_add_func ("/uri/relative", do_relative_uri_tests); + g_test_add_func ("/uri/equality", do_equality_tests); + g_test_add_func ("/uri/null", do_soup_uri_null_tests); + g_test_add_func ("/uri/normalization", do_normalization_tests); - do_soup_uri_null_tests (); - do_normalization_tests (); + ret = g_test_run (); test_cleanup (); - return errors != 0; + return ret; } diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c index 421348b1..a6f2d5f0 100644 --- a/tests/xmlrpc-server-test.c +++ b/tests/xmlrpc-server-test.c @@ -242,7 +242,7 @@ server_callback (SoupServer *server, SoupMessage *msg, static void xmlrpc_test_exited (GPid pid, int status, gpointer data) { - errors = WIFEXITED (status) ? WEXITSTATUS (status) : 1; + g_assert_true (WIFEXITED (status) && WEXITSTATUS (status) == 0); g_main_loop_quit (loop); } @@ -270,9 +270,10 @@ xmlrpc_test_print (GIOChannel *io, GIOCondition cond, gpointer data) } static void -do_xmlrpc_tests (SoupURI *uri) +do_xmlrpc_tests (gconstpointer data) { - char *argv[8]; + SoupURI *uri = (SoupURI *)data; + char *argv[10]; int arg, out; gboolean ok; GPid pid; @@ -280,13 +281,14 @@ do_xmlrpc_tests (SoupURI *uri) GIOChannel *child_out; argv[0] = "./xmlrpc-test"; - argv[1] = "-s"; - argv[2] = "-u"; + argv[1] = "-S"; + argv[2] = "-U"; argv[3] = soup_uri_to_string (uri, FALSE); + argv[4] = "-q"; for (arg = 0; arg < debug_level && arg < 3; arg++) - argv[arg + 4] = "-d"; - argv[arg + 4] = NULL; + argv[arg + 5] = "-d"; + argv[arg + 5] = NULL; ok = g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, @@ -295,17 +297,18 @@ do_xmlrpc_tests (SoupURI *uri) &error); g_free (argv[3]); - if (!ok) { - g_print ("Could not run xmlrpc-test: %s\n", error->message); - errors++; + g_assert_no_error (error); + if (!ok) return; - } g_child_watch_add (pid, xmlrpc_test_exited, NULL); child_out = g_io_channel_unix_new (out); g_io_add_watch (child_out, G_IO_IN | G_IO_ERR | G_IO_HUP, xmlrpc_test_print, NULL); g_io_channel_unref (child_out); + + g_main_loop_run (loop); + g_main_loop_unref (loop); } gboolean run_tests = TRUE; @@ -322,6 +325,7 @@ main (int argc, char **argv) { SoupServer *server; SoupURI *uri; + int ret; test_init (argc, argv, no_test_entry); @@ -334,18 +338,25 @@ main (int argc, char **argv) if (run_tests) { uri = soup_uri_new ("http://127.0.0.1/xmlrpc-server.php"); soup_uri_set_port (uri, soup_server_get_port (server)); - do_xmlrpc_tests (uri); + + g_test_add_data_func ("/xmlrpc/server", uri, do_xmlrpc_tests); + + ret = g_test_run (); + soup_uri_free (uri); - } else + } else { g_print ("Listening on port %d\n", soup_server_get_port (server)); - g_main_loop_run (loop); - g_main_loop_unref (loop); + g_main_loop_run (loop); + g_main_loop_unref (loop); + + ret = 0; + } soup_test_server_quit_unref (server); if (run_tests) test_cleanup (); - return errors != 0; + return ret; } #else /* HAVE_PHP_XMLRPC */ diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c index 3c3f76fe..3a7b20ad 100644 --- a/tests/xmlrpc-test.c +++ b/tests/xmlrpc-test.c @@ -39,21 +39,16 @@ send_xmlrpc (const char *body, GValue *retval) body, strlen (body)); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, "ERROR: %d %s\n", msg->status_code, - msg->reason_phrase); - g_object_unref (msg); - return FALSE; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); if (!soup_xmlrpc_parse_method_response (msg->response_body->data, msg->response_body->length, retval, &err)) { if (err) { - debug_printf (1, "FAULT: %d %s\n", err->code, err->message); + soup_test_assert (FALSE, "FAULT: %d %s\n", err->code, err->message); g_error_free (err); } else - debug_printf (1, "ERROR: could not parse response\n"); + soup_test_assert (FALSE, "ERROR: could not parse response\n"); g_object_unref (msg); return FALSE; } @@ -92,8 +87,7 @@ check_xmlrpc (GValue *value, GType type, ...) va_list args; if (!G_VALUE_HOLDS (value, type)) { - debug_printf (1, "ERROR: could not parse response\n"); - g_value_unset (value); + g_assert_true (G_VALUE_HOLDS (value, type)); return FALSE; } @@ -103,7 +97,7 @@ check_xmlrpc (GValue *value, GType type, ...) return TRUE; } -static gboolean +static void test_sum (void) { GValueArray *ints; @@ -129,14 +123,13 @@ test_sum (void) g_value_array_free (ints); if (!ok) - return FALSE; + return; - debug_printf (2, "%d: ", result); - debug_printf (1, "%s\n", result == sum ? "OK!" : "WRONG!"); - return result == sum; + debug_printf (2, "%d\n", result); + g_assert_cmpint (result, ==, sum); } -static gboolean +static void test_countBools (void) { GValueArray *bools; @@ -166,25 +159,19 @@ test_countBools (void) check_xmlrpc (&retval, G_TYPE_HASH_TABLE, &result)); g_value_array_free (bools); if (!ok) - return FALSE; + return; + + g_assert_true (soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)); + g_assert_true (soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)); - if (!soup_value_hash_lookup (result, "true", G_TYPE_INT, &ret_trues)) { - debug_printf (1, "NO 'true' value in response\n"); - return FALSE; - } - if (!soup_value_hash_lookup (result, "false", G_TYPE_INT, &ret_falses)) { - debug_printf (1, "NO 'false' value in response\n"); - return FALSE; - } g_hash_table_destroy (result); - debug_printf (2, "{ true: %d, false: %d } ", ret_trues, ret_falses); - ok = (trues == ret_trues) && (falses == ret_falses); - debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!"); - return ok; + debug_printf (2, "{ true: %d, false: %d }\n", ret_trues, ret_falses); + g_assert_cmpint (trues, ==, ret_trues); + g_assert_cmpint (falses, ==, ret_falses); } -static gboolean +static void test_md5sum (void) { GByteArray *data, *result; @@ -195,7 +182,7 @@ test_md5sum (void) GValue retval; gboolean ok; - debug_printf (1, "md5sum (base64 -> base64): "); + debug_printf (1, "md5sum (base64 -> base64)\n"); data = g_byte_array_new (); g_byte_array_set_size (data, 256); @@ -213,21 +200,14 @@ test_md5sum (void) check_xmlrpc (&retval, SOUP_TYPE_BYTE_ARRAY, &result)); g_byte_array_free (data, TRUE); if (!ok) - return FALSE; - - if (result->len != digest_len) { - debug_printf (1, "result has WRONG length (%d)\n", result->len); - g_byte_array_free (result, TRUE); - return FALSE; - } + return; - ok = (memcmp (digest, result->data, digest_len) == 0); - debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!"); + soup_assert_cmpmem (result->data, result->len, + digest, digest_len); g_byte_array_free (result, TRUE); - return ok; } -static gboolean +static void test_dateChange (void) { GHashTable *structval; @@ -236,7 +216,7 @@ test_dateChange (void) GValue retval; gboolean ok; - debug_printf (1, "dateChange (date, struct of ints -> time): "); + debug_printf (1, "dateChange (date, struct of ints -> time)\n"); date = soup_date_new (1970 + (g_random_int_range (0, 50)), 1 + g_random_int_range (0, 12), @@ -301,26 +281,24 @@ test_dateChange (void) g_hash_table_destroy (structval); if (!ok) { soup_date_free (date); - return FALSE; + return; } if (debug_level >= 2) { timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC); - debug_printf (2, "%s: ", timestamp); + debug_printf (2, "%s\n", timestamp); g_free (timestamp); } - ok = ((date->year == result->year) && - (date->month == result->month) && - (date->day == result->day) && - (date->hour == result->hour) && - (date->minute == result->minute) && - (date->second == result->second)); + g_assert_cmpint (date->year, ==, result->year); + g_assert_cmpint (date->month, ==, result->month); + g_assert_cmpint (date->day, ==, result->day); + g_assert_cmpint (date->hour, ==, result->hour); + g_assert_cmpint (date->minute, ==, result->minute); + g_assert_cmpint (date->second, ==, result->second); + soup_date_free (date); soup_date_free (result); - - debug_printf (1, "%s\n", ok ? "OK!" : "WRONG!"); - return ok; } static const char *const echo_strings[] = { @@ -338,15 +316,14 @@ static const char *const echo_strings_broken[] = { "amp; so is lt;thisgt;" }; -static gboolean +static void test_echo (void) { GValueArray *originals, *echoes; GValue retval; int i; - gboolean php_bug = FALSE; - debug_printf (1, "echo (array of string -> array of string): "); + debug_printf (1, "echo (array of string -> array of string):\n"); originals = g_value_array_new (N_ECHO_STRINGS); for (i = 0; i < N_ECHO_STRINGS; i++) { @@ -360,7 +337,7 @@ test_echo (void) G_TYPE_INVALID) && check_xmlrpc (&retval, G_TYPE_VALUE_ARRAY, &echoes))) { g_value_array_free (originals); - return FALSE; + return; } g_value_array_free (originals); @@ -369,37 +346,29 @@ test_echo (void) debug_printf (2, "%s\"%s\"", i == 0 ? "[" : ", ", g_value_get_string (&echoes->values[i])); } - debug_printf (2, "] -> "); + debug_printf (2, "]\n"); } - if (echoes->n_values != N_ECHO_STRINGS) { - debug_printf (1, " WRONG! Wrong number of return strings"); - g_value_array_free (echoes); - return FALSE; - } + g_assert_cmpint (echoes->n_values, ==, N_ECHO_STRINGS); for (i = 0; i < echoes->n_values; i++) { - if (strcmp (echo_strings[i], g_value_get_string (&echoes->values[i])) != 0) { - if (!server_test && strcmp (echo_strings_broken[i], g_value_get_string (&echoes->values[i])) == 0) - php_bug = TRUE; - else { - debug_printf (1, " WRONG! Mismatch at %d\n", i + 1); - g_value_array_free (echoes); - return FALSE; - } + if (!server_test && strcmp (echo_strings_broken[i], g_value_get_string (&echoes->values[i])) == 0) { + /* We want to call g_test_skip(), but as of glib 2.38 + * that marks the test as failed rather than succeeded. + */ + // FIXME g_test_skip ("PHP bug"); + g_value_array_free (echoes); + return; } + + g_assert_cmpstr (echo_strings[i], ==, g_value_get_string (&echoes->values[i])); } - if (php_bug) - debug_printf (1, "WRONG, but it's php's fault\n"); - else - debug_printf (1, "OK!\n"); g_value_array_free (echoes); - return TRUE; } -static gboolean -test_ping (gboolean include_params) +static void +test_ping (gconstpointer include_params) { GValueArray *params; GValue retval; @@ -407,7 +376,7 @@ test_ping (gboolean include_params) char *out; gboolean ret; - debug_printf (1, "ping (void (%s) -> string): ", + debug_printf (1, "ping (void (%s) -> string)\n", include_params ? "empty " : "no "); params = soup_value_array_new (); @@ -415,15 +384,15 @@ test_ping (gboolean include_params) params->n_values); g_value_array_free (params); if (!request) - return FALSE; + return; if (!include_params) { char *params, *end; params = strstr (request, ""); if (!params) { - debug_printf (1, "ERROR: XML did not contain !"); - return FALSE; + soup_test_assert (FALSE, "ERROR: XML did not contain !"); + return; } end = params + strlen (""); memmove (params, end, strlen (end) + 1); @@ -433,21 +402,14 @@ test_ping (gboolean include_params) g_free (request); if (!ret || !check_xmlrpc (&retval, G_TYPE_STRING, &out)) - return FALSE; + return; - if (!strcmp (out, "pong")) { - debug_printf (1, "OK!\n"); - ret = TRUE; - } else { - debug_printf (1, "WRONG! Bad response '%s'", out); - ret = FALSE; - } + g_assert_cmpstr (out, ==, "pong"); g_free (out); - return ret; } -static gboolean +static void do_bad_xmlrpc (const char *body) { SoupMessage *msg; @@ -459,12 +421,7 @@ do_bad_xmlrpc (const char *body) body, strlen (body)); soup_session_send_message (session, msg); - if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { - debug_printf (1, "ERROR: %d %s\n", msg->status_code, - msg->reason_phrase); - g_object_unref (msg); - return FALSE; - } + soup_test_assert_message_status (msg, SOUP_STATUS_OK); if (!soup_xmlrpc_parse_method_response (msg->response_body->data, msg->response_body->length, @@ -474,44 +431,43 @@ do_bad_xmlrpc (const char *body) err->code, err->message); g_error_free (err); g_object_unref (msg); - return TRUE; + return; } else - debug_printf (1, "ERROR: could not parse response\n"); + soup_test_assert (FALSE, "ERROR: could not parse response\n"); } else - debug_printf (1, "Unexpectedly got successful response!\n"); + soup_test_assert (FALSE, "Unexpectedly got successful response!\n"); g_object_unref (msg); - return FALSE; } -static gboolean +static void test_fault_malformed (void) { debug_printf (1, "malformed request: "); - return do_bad_xmlrpc (""); + do_bad_xmlrpc (""); } -static gboolean +static void test_fault_method (void) { debug_printf (1, "request to non-existent method: "); - return do_bad_xmlrpc ("no_such_method1"); + do_bad_xmlrpc ("no_such_method1"); } -static gboolean +static void test_fault_args (void) { debug_printf (1, "request with invalid args: "); - return do_bad_xmlrpc ("sum1"); + do_bad_xmlrpc ("sum1"); } static GOptionEntry xmlrpc_entries[] = { - { "uri", 'u', 0, G_OPTION_ARG_STRING, &uri, + { "uri", 'U', 0, G_OPTION_ARG_STRING, &uri, "Alternate URI for server", NULL }, - { "server-test", 's', 0, G_OPTION_ARG_NONE, &server_test, + { "server-test", 'S', 0, G_OPTION_ARG_NONE, &server_test, "If this is being run from xmlrpc-server-test", NULL }, { NULL } }; @@ -519,6 +475,8 @@ static GOptionEntry xmlrpc_entries[] = { int main (int argc, char **argv) { + int ret; + test_init (argc, argv, xmlrpc_entries); if (!uri) { @@ -528,31 +486,23 @@ main (int argc, char **argv) session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - if (!test_sum ()) - errors++; - if (!test_countBools ()) - errors++; - if (!test_md5sum ()) - errors++; - if (!test_dateChange ()) - errors++; - if (!test_echo ()) - errors++; - if (!test_ping (TRUE)) - errors++; - if (!test_ping (FALSE)) - errors++; - if (!test_fault_malformed ()) - errors++; - if (!test_fault_method ()) - errors++; - if (!test_fault_args ()) - errors++; + g_test_add_func ("/xmlrpc/sum", test_sum); + g_test_add_func ("/xmlrpc/countBools", test_countBools); + g_test_add_func ("/xmlrpc/md5sum", test_md5sum); + g_test_add_func ("/xmlrpc/dateChange", test_dateChange); + g_test_add_func ("/xmlrpc/echo", test_echo); + g_test_add_data_func ("/xmlrpc/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping); + g_test_add_data_func ("/xmlrpc/ping/no-params", GINT_TO_POINTER (FALSE), test_ping); + g_test_add_func ("/xmlrpc/fault_malformed", test_fault_malformed); + g_test_add_func ("/xmlrpc/fault_method", test_fault_method); + g_test_add_func ("/xmlrpc/fault_args", test_fault_args); + + ret = g_test_run (); soup_test_session_abort_unref (session); test_cleanup (); - return errors != 0; + return ret; } #else /* HAVE_PHP_XMLRPC */ -- cgit v1.2.1 From 094eee8d1e0ac31e83f45e026ef26688e1468884 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 11 Dec 2013 18:15:13 +0100 Subject: tests: Add resources/* to soup-test.gresource, add utility functions Add the files in resources/ to soup-test.gresource, and add soup_test_load_resource() to get the contents of one of them, and then use this in places that were previously reading them by hand. Except forms-test, which needs to pass a filename to curl, so have it use index.txt instead of one of the resource files. Now none of the tests access the resources/ directory at runtime. Also add soup_test_get_index() to read index.txt rather than reimplementing it in multiple test programs. --- tests/Makefile.am | 19 +++------- tests/chunk-io-test.c | 48 ++++++++++++------------- tests/coding-test.c | 31 ++++++++-------- tests/forms-test.c | 6 ++-- tests/range-test.c | 20 +---------- tests/requester-test.c | 27 +++----------- tests/resource-test.c | 36 ++----------------- tests/sniffing-test.c | 80 +++++++++++++++--------------------------- tests/soup-tests.gresource.xml | 13 ++++++- tests/streaming-test.c | 38 ++++++-------------- tests/test-utils.c | 67 +++++++++++++++++++++++++++++++++++ tests/test-utils.h | 6 ++++ 12 files changed, 174 insertions(+), 217 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 76a87fa7..f7293b12 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -77,21 +77,10 @@ httpd.conf: $(httpd_conf_in) BUILT_SOURCES = httpd.conf endif -soup-tests.gresource: soup-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) - $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< - -RESOURCES = \ - resources/atom.xml \ - resources/home.gif \ - resources/html_binary.html \ - resources/mbox \ - resources/mbox.gz \ - resources/mbox.raw \ - resources/mbox.zlib \ - resources/ps_binary.ps \ - resources/rss20.xml \ - resources/test.html \ - resources/text_binary.txt +RESOURCES = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) + +soup-tests.gresource: soup-tests.gresource.xml $(RESOURCES) + $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< EXTRA_DIST = \ htdigest \ diff --git a/tests/chunk-io-test.c b/tests/chunk-io-test.c index 4003e341..29062a69 100644 --- a/tests/chunk-io-test.c +++ b/tests/chunk-io-test.c @@ -351,8 +351,8 @@ do_io_tests (void) GInputStream *imem, *islow, *in; GOutputStream *omem, *oslow, *out; GMemoryOutputStream *mem; - char *raw_contents, *buf; - gsize raw_length; + SoupBuffer *raw_contents; + char *buf; GString *chunkified; GError *error = NULL; gssize nread, nwrote, total; @@ -360,13 +360,8 @@ do_io_tests (void) debug_printf (1, "\nI/O tests\n"); - if (!g_file_get_contents (SRCDIR "/index.txt", &raw_contents, &raw_length, &error)) { - g_printerr ("Could not read index.txt: %s\n", - error->message); - exit (1); - } - - chunkified = chunkify (raw_contents, raw_length); + raw_contents = soup_test_get_index (); + chunkified = chunkify (raw_contents->data, raw_contents->length); debug_printf (1, " sync read\n"); @@ -383,10 +378,11 @@ do_io_tests (void) g_object_unref (imem); g_object_unref (islow); - buf = g_malloc (raw_length); + buf = g_malloc (raw_contents->length); total = 0; while (TRUE) { - nread = g_input_stream_read (in, buf + total, raw_length - total, + nread = g_input_stream_read (in, buf + total, + raw_contents->length - total, NULL, &error); g_assert_no_error (error); g_clear_error (&error); @@ -401,7 +397,7 @@ do_io_tests (void) g_clear_error (&error); g_object_unref (in); - soup_assert_cmpmem (buf, total, raw_contents, raw_length); + soup_assert_cmpmem (buf, total, raw_contents->data, raw_contents->length); g_free (buf); debug_printf (1, " async read\n"); @@ -419,11 +415,12 @@ do_io_tests (void) g_object_unref (imem); g_object_unref (islow); - buf = g_malloc (raw_length); + buf = g_malloc (raw_contents->length); total = 0; while (TRUE) { nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (in), - buf + total, raw_length - total, + buf + total, + raw_contents->length - total, NULL, &error); if (nread == -1 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { GSource *source; @@ -452,7 +449,7 @@ do_io_tests (void) g_clear_error (&error); g_object_unref (in); - soup_assert_cmpmem (buf, total, raw_contents, raw_length); + soup_assert_cmpmem (buf, total, raw_contents->data, raw_contents->length); g_free (buf); debug_printf (1, " sync write\n"); @@ -472,12 +469,12 @@ do_io_tests (void) g_object_unref (oslow); total = chunk_length = chunk_total = 0; - while (total < raw_length) { + while (total < raw_contents->length) { if (chunk_total == chunk_length) { - chunk_length = MIN (CHUNK_SIZE, raw_length - total); + chunk_length = MIN (CHUNK_SIZE, raw_contents->length - total); chunk_total = 0; } - nwrote = g_output_stream_write (out, raw_contents + total, + nwrote = g_output_stream_write (out, raw_contents->data + total, chunk_length - chunk_total, NULL, &error); g_assert_no_error (error); g_clear_error (&error); @@ -517,13 +514,13 @@ do_io_tests (void) g_object_unref (oslow); total = chunk_length = chunk_total = 0; - while (total < raw_length) { + while (total < raw_contents->length) { if (chunk_total == chunk_length) { - chunk_length = MIN (CHUNK_SIZE, raw_length - total); + chunk_length = MIN (CHUNK_SIZE, raw_contents->length - total); chunk_total = 0; } nwrote = g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (out), - raw_contents + total, + raw_contents->data + total, chunk_length - chunk_total, NULL, &error); if (nwrote == -1 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { @@ -578,16 +575,16 @@ do_io_tests (void) g_object_unref (oslow); total = 0; - while (total < raw_length) { - nwrote = g_output_stream_write (out, raw_contents + total, - raw_length - total, NULL, NULL); + while (total < raw_contents->length) { + nwrote = g_output_stream_write (out, raw_contents->data + total, + raw_contents->length - total, NULL, NULL); if (nwrote == -1) break; else total += nwrote; } - g_assert_cmpint (total, !=, raw_length); + g_assert_cmpint (total, !=, raw_contents->length); g_output_stream_close (out, NULL, NULL); g_object_unref (out); @@ -595,7 +592,6 @@ do_io_tests (void) g_free (buf); g_string_free (chunkified, TRUE); - g_free (raw_contents); } int diff --git a/tests/coding-test.c b/tests/coding-test.c index 8bc3e5f3..d922a19c 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -16,8 +16,7 @@ server_callback (SoupServer *server, SoupMessage *msg, { const char *accept_encoding, *options; GSList *codings; - char *file = NULL, *contents; - gsize length; + SoupBuffer *response = NULL; options = soup_message_headers_get_one (msg->request_headers, "X-Test-Options"); @@ -53,32 +52,32 @@ server_callback (SoupServer *server, SoupMessage *msg, } } if (extension && encoding) { - file = g_strdup_printf (SRCDIR "/resources%s.%s", path, extension); - if (g_file_test (file, G_FILE_TEST_EXISTS)) { + char *resource; + + resource = g_strdup_printf ("%s.%s", path, extension); + response = soup_test_load_resource (resource, NULL); + + if (response) { soup_message_headers_append (msg->response_headers, "Content-Encoding", encoding); - } else { - g_free (file); - file = NULL; } + g_free (resource); } } soup_header_free_list (codings); - if (!file) - file = g_strdup_printf (SRCDIR "/resources%s", path); - if (!g_file_get_contents (file, &contents, &length, NULL)) { + if (!response) + response = soup_test_load_resource (path, NULL); + if (!response) { /* If path.gz exists but can't be read, we'll send back * the error with "Content-Encoding: gzip" but there's * no body, so, eh. */ - g_free (file); soup_message_set_status (msg, SOUP_STATUS_NOT_FOUND); return; } - g_free (file); if (soup_header_contains (options, "force-encode")) { const gchar *encoding = "gzip"; @@ -106,11 +105,9 @@ server_callback (SoupServer *server, SoupMessage *msg, soup_message_set_status (msg, SOUP_STATUS_OK); soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CHUNKED); - if (!soup_header_contains (options, "empty")) { - soup_message_body_append (msg->response_body, - SOUP_MEMORY_TAKE, contents, length); - } else - g_free (contents); + if (!soup_header_contains (options, "empty")) + soup_message_body_append_buffer (msg->response_body, response); + soup_buffer_free (response); if (soup_header_contains (options, "trailing-junk")) { soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY, diff --git a/tests/forms-test.c b/tests/forms-test.c index 5a5db28b..7a843dac 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -135,9 +135,9 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5) g_free (file_arg); } -#define MD5_TEST_FILE SRCDIR "/resources/home.gif" -#define MD5_TEST_FILE_BASENAME "home.gif" -#define MD5_TEST_FILE_MIME_TYPE "image/gif" +#define MD5_TEST_FILE SRCDIR "/index.txt" +#define MD5_TEST_FILE_BASENAME "index.txt" +#define MD5_TEST_FILE_MIME_TYPE "text/plain" static void do_md5_test_libsoup (const char *uri, const char *contents, diff --git a/tests/range-test.c b/tests/range-test.c index 89ae59c4..4d008d46 100644 --- a/tests/range-test.c +++ b/tests/range-test.c @@ -8,23 +8,6 @@ SoupBuffer *full_response; int total_length; char *test_response; -static void -get_full_response (void) -{ - char *contents; - gsize length; - GError *error = NULL; - - if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) { - g_printerr ("Could not read index.txt: %s\n", - error->message); - exit (1); - } - - full_response = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length); - debug_printf (1, "Total response length is %d\n\n", (int)length); -} - static void check_part (SoupMessageHeaders *headers, const char *body, gsize body_len, gboolean check_start_end, int expected_start, int expected_end) @@ -401,7 +384,7 @@ main (int argc, char **argv) test_init (argc, argv, NULL); apache_init (); - get_full_response (); + full_response = soup_test_get_index (); test_response = g_malloc0 (full_response->length); g_test_add_func ("/ranges/apache", do_apache_range_test); @@ -409,7 +392,6 @@ main (int argc, char **argv) ret = g_test_run (); - soup_buffer_free (full_response); g_free (test_response); test_cleanup (); diff --git a/tests/requester-test.c b/tests/requester-test.c index 61a69f28..52c3eac2 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -17,26 +17,6 @@ SoupBuffer *response, *auth_response; #define REDIRECT_HTML_BODY "Try again\r\n" #define AUTH_HTML_BODY "Unauthorized\r\n" -static void -get_index (void) -{ - char *contents; - gsize length; - GError *error = NULL; - - if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) { - g_printerr ("Could not read index.txt: %s\n", - error->message); - exit (1); - } - - response = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length); - - auth_response = soup_buffer_new (SOUP_MEMORY_STATIC, - AUTH_HTML_BODY, - strlen (AUTH_HTML_BODY)); -} - static gboolean slow_finish_message (gpointer msg) { @@ -808,7 +788,11 @@ main (int argc, char **argv) int ret; test_init (argc, argv, NULL); - get_index (); + + response = soup_test_get_index (); + auth_response = soup_buffer_new (SOUP_MEMORY_STATIC, + AUTH_HTML_BODY, + strlen (AUTH_HTML_BODY)); server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); @@ -831,7 +815,6 @@ main (int argc, char **argv) ret = g_test_run (); g_free (uri); - soup_buffer_free (response); soup_buffer_free (auth_response); soup_test_server_quit_unref (server); diff --git a/tests/resource-test.c b/tests/resource-test.c index e41c6032..50d63ab9 100644 --- a/tests/resource-test.c +++ b/tests/resource-test.c @@ -7,38 +7,6 @@ SoupBuffer *index_buffer; -static void -get_index (void) -{ - char *contents; - gsize length; - GError *error = NULL; - - if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) { - g_printerr ("Could not read index.txt: %s\n", - error->message); - exit (1); - } - - index_buffer = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length); -} - -static void -register_gresource (void) -{ - GResource *resource; - GError *error = NULL; - - resource = g_resource_load ("soup-tests.gresource", &error); - if (!resource) { - g_printerr ("Could not load resource soup-tests.gresource: %s\n", - error->message); - exit (1); - } - g_resources_register (resource); - g_resource_unref (resource); -} - typedef struct { GString *body; char buffer[1024]; @@ -222,8 +190,8 @@ main (int argc, char **argv) test_init (argc, argv, NULL); - get_index (); - register_gresource (); + index_buffer = soup_test_get_index (); + soup_test_register_resources (); g_test_add_data_func ("/resource/sync/file", GSIZE_TO_POINTER (SOUP_TYPE_SESSION_SYNC), diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index b5088d4d..532e6ed5 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -16,8 +16,8 @@ server_callback (SoupServer *server, SoupMessage *msg, { GError *error = NULL; char *query_key; - char *contents; - gsize length = 0, offset; + SoupBuffer *response = NULL; + gsize offset; gboolean empty_response = FALSE; if (msg->method != SOUP_METHOD_GET) { @@ -40,13 +40,8 @@ server_callback (SoupServer *server, SoupMessage *msg, } if (!strcmp (path, "/mbox")) { - if (empty_response) { - contents = g_strdup (""); - length = 0; - } else { - g_file_get_contents (SRCDIR "/resources/mbox", - &contents, &length, - &error); + if (!empty_response) { + response = soup_test_load_resource ("mbox", &error); g_assert_no_error (error); } @@ -56,15 +51,10 @@ server_callback (SoupServer *server, SoupMessage *msg, if (g_str_has_prefix (path, "/text_or_binary/")) { char *base_name = g_path_get_basename (path); - char *file_name = g_strdup_printf (SRCDIR "/resources/%s", base_name); - g_file_get_contents (file_name, - &contents, &length, - &error); + response = soup_test_load_resource (base_name, &error); g_assert_no_error (error); - g_free (base_name); - g_free (file_name); soup_message_headers_append (msg->response_headers, "Content-Type", "text/plain"); @@ -72,15 +62,10 @@ server_callback (SoupServer *server, SoupMessage *msg, if (g_str_has_prefix (path, "/unknown/")) { char *base_name = g_path_get_basename (path); - char *file_name = g_strdup_printf (SRCDIR "/resources/%s", base_name); - g_file_get_contents (file_name, - &contents, &length, - &error); + response = soup_test_load_resource (base_name, &error); g_assert_no_error (error); - g_free (base_name); - g_free (file_name); soup_message_headers_append (msg->response_headers, "Content-Type", "UNKNOWN/unknown"); @@ -91,15 +76,10 @@ server_callback (SoupServer *server, SoupMessage *msg, char *ptr; char *base_name = g_path_get_basename (path); - char *file_name = g_strdup_printf (SRCDIR "/resources/%s", base_name); - g_file_get_contents (file_name, - &contents, &length, - &error); + response = soup_test_load_resource (base_name, &error); g_assert_no_error (error); - g_free (base_name); - g_free (file_name); /* Hack to allow passing type in the URI */ ptr = g_strrstr (components[2], "_"); @@ -112,15 +92,10 @@ server_callback (SoupServer *server, SoupMessage *msg, if (g_str_has_prefix (path, "/multiple_headers/")) { char *base_name = g_path_get_basename (path); - char *file_name = g_strdup_printf (SRCDIR "/resources/%s", base_name); - g_file_get_contents (file_name, - &contents, &length, - &error); + response = soup_test_load_resource (base_name, &error); g_assert_no_error (error); - g_free (base_name); - g_free (file_name); soup_message_headers_append (msg->response_headers, "Content-Type", "text/xml"); @@ -128,15 +103,18 @@ server_callback (SoupServer *server, SoupMessage *msg, "Content-Type", "text/plain"); } - for (offset = 0; offset < length; offset += 500) { - soup_message_body_append (msg->response_body, - SOUP_MEMORY_COPY, - contents + offset, - MIN(500, length - offset)); + if (response) { + for (offset = 0; offset < response->length; offset += 500) { + soup_message_body_append (msg->response_body, + SOUP_MEMORY_COPY, + response->data + offset, + MIN (500, response->length - offset)); + } + + soup_buffer_free (response); } - soup_message_body_complete (msg->response_body); - g_free (contents); + soup_message_body_complete (msg->response_body); } static gboolean @@ -212,8 +190,7 @@ do_signals_test (gboolean should_content_sniff, { SoupURI *uri = soup_uri_new_with_base (base_uri, "/mbox"); SoupMessage *msg = soup_message_new_from_uri ("GET", uri); - char *contents; - gsize length; + SoupBuffer *expected; GError *error = NULL; SoupBuffer *body = NULL; @@ -256,13 +233,10 @@ do_signals_test (gboolean should_content_sniff, "content-sniffed got emitted without a sniffer"); } - if (empty_response) { - contents = g_strdup (""); - length = 0; - } else { - g_file_get_contents (SRCDIR "/resources/mbox", - &contents, &length, - &error); + if (empty_response) + expected = soup_buffer_new (SOUP_MEMORY_STATIC, "", 0); + else { + expected = soup_test_load_resource ("mbox", &error); g_assert_no_error (error); } @@ -271,10 +245,12 @@ do_signals_test (gboolean should_content_sniff, else if (msg->response_body) body = soup_message_body_flatten (msg->response_body); - if (body) - soup_assert_cmpmem (body->data, body->length, contents, length); + if (body) { + soup_assert_cmpmem (body->data, body->length, + expected->data, expected->length); + } - g_free (contents); + soup_buffer_free (expected); if (body) soup_buffer_free (body); if (chunk_data) { diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml index 969a6bfe..9b580a35 100644 --- a/tests/soup-tests.gresource.xml +++ b/tests/soup-tests.gresource.xml @@ -2,5 +2,16 @@ index.txt + resources/atom.xml + resources/home.gif + resources/html_binary.html + resources/mbox + resources/mbox.gz + resources/mbox.raw + resources/mbox.zlib + resources/ps_binary.ps + resources/rss20.xml + resources/test.html + resources/text_binary.txt - \ No newline at end of file + diff --git a/tests/streaming-test.c b/tests/streaming-test.c index 9790766a..f15e1890 100644 --- a/tests/streaming-test.c +++ b/tests/streaming-test.c @@ -7,28 +7,8 @@ #define RESPONSE_CHUNK_SIZE 1024 -char *full_response, *full_response_md5; -gsize full_response_length; - -static void -get_full_response (void) -{ - GError *error = NULL; - - if (!g_file_get_contents (SRCDIR "/index.txt", - &full_response, - &full_response_length, - &error)) { - g_printerr ("Could not read index file %s: %s\n", - SRCDIR "/index.txt", error->message); - g_error_free (error); - exit (1); - } - - full_response_md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, - (guchar *)full_response, - full_response_length); -} +SoupBuffer *full_response; +char *full_response_md5; static void write_next_chunk (SoupMessage *msg, gpointer user_data) @@ -36,12 +16,12 @@ write_next_chunk (SoupMessage *msg, gpointer user_data) gsize *offset = user_data; gsize chunk_length; - chunk_length = MIN (RESPONSE_CHUNK_SIZE, full_response_length - *offset); + chunk_length = MIN (RESPONSE_CHUNK_SIZE, full_response->length - *offset); if (chunk_length > 0) { debug_printf (2, " writing chunk\n"); soup_message_body_append (msg->response_body, SOUP_MEMORY_STATIC, - full_response + *offset, + full_response->data + *offset, chunk_length); *offset += chunk_length; } else { @@ -74,7 +54,7 @@ server_callback (SoupServer *server, SoupMessage *msg, soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_CONTENT_LENGTH); soup_message_headers_set_content_length (msg->response_headers, - full_response_length); + full_response->length); } else if (!strcmp (path, "/eof")) { soup_message_headers_set_encoding (msg->response_headers, SOUP_ENCODING_EOF); @@ -107,7 +87,7 @@ do_request (SoupSession *session, SoupURI *base_uri, char *path) soup_session_send_message (session, msg); soup_test_assert_message_status (msg, SOUP_STATUS_OK); - g_assert_cmpint (msg->response_body->length, ==, full_response_length); + g_assert_cmpint (msg->response_body->length, ==, full_response->length); md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, (guchar *)msg->response_body->data, @@ -162,7 +142,10 @@ main (int argc, char **argv) test_init (argc, argv, NULL); - get_full_response (); + full_response = soup_test_get_index (); + full_response_md5 = g_compute_checksum_for_data (G_CHECKSUM_MD5, + (guchar *)full_response->data, + full_response->length); server = soup_test_server_new (FALSE); soup_server_add_handler (server, NULL, @@ -183,7 +166,6 @@ main (int argc, char **argv) soup_uri_free (base_uri); g_main_loop_unref (loop); - g_free (full_response); g_free (full_response_md5); soup_test_server_quit_unref (server); test_cleanup (); diff --git a/tests/test-utils.c b/tests/test-utils.c index c28994a1..3d2546f5 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -12,6 +12,7 @@ static gboolean apache_running; #endif static SoupLogger *logger; +static SoupBuffer *index_buffer; int debug_level; gboolean expect_warning, tls_available; @@ -110,6 +111,8 @@ test_cleanup (void) if (logger) g_object_unref (logger); + if (index_buffer) + soup_buffer_free (index_buffer); g_main_context_unref (g_main_context_default ()); @@ -514,6 +517,70 @@ soup_test_request_close_stream (SoupRequest *req, return ok; } +void +soup_test_register_resources (void) +{ + static gboolean registered = FALSE; + GResource *resource; + GError *error = NULL; + + if (registered) + return; + + resource = g_resource_load ("soup-tests.gresource", &error); + if (!resource) { + g_printerr ("Could not load resource soup-tests.gresource: %s\n", + error->message); + exit (1); + } + g_resources_register (resource); + g_resource_unref (resource); + + registered = TRUE; +} + +SoupBuffer * +soup_test_load_resource (const char *name, + GError **error) +{ + GBytes *bytes; + char *path; + + soup_test_register_resources (); + + path = g_build_path ("/", "/org/gnome/libsoup/tests/resources", name, NULL); + bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, error); + g_free (path); + + if (!bytes) + return NULL; + + return soup_buffer_new_with_owner (g_bytes_get_data (bytes, NULL), + g_bytes_get_size (bytes), + bytes, + (GDestroyNotify) g_bytes_unref); +} + +SoupBuffer * +soup_test_get_index (void) +{ + if (!index_buffer) { + char *contents; + gsize length; + GError *error = NULL; + + if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) { + g_printerr ("Could not read index.txt: %s\n", + error->message); + exit (1); + } + + index_buffer = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length); + } + + return index_buffer; +} + #ifndef G_HAVE_ISO_VARARGS void soup_test_assert (gboolean expr, const char *fmt, ...) diff --git a/tests/test-utils.h b/tests/test-utils.h index 97741516..315d1117 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -54,6 +54,12 @@ gboolean soup_test_request_close_stream (SoupRequest *req, GCancellable *cancellable, GError **error); +void soup_test_register_resources (void); +SoupBuffer *soup_test_load_resource (const char *name, + GError **error); + +SoupBuffer *soup_test_get_index (void); + #ifdef G_HAVE_ISO_VARARGS #define soup_test_assert(expr, ...) \ G_STMT_START { \ -- cgit v1.2.1 From c92ef5cf5fc71d6cd6c29c87a258561b8a525d2b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 11 Dec 2013 19:55:50 +0100 Subject: tests: use TAP, and install the tests Import glib-tap.mk to run the tests in TAP mode, and to provide rules to install the tests. This required some restructuring of httpd.conf-related stuff in order to come up with a configuration that would work for all three cases (srcdir==buildir, srcdir!=builddir, and installed). --- .gitignore | 1 + Makefile.am | 4 +- configure.ac | 2 + glib-tap.mk | 134 ++++++++++ m4/glibtests.m4 | 28 ++ tap-driver.sh | 652 +++++++++++++++++++++++++++++++++++++++++++++ tap-test | 5 + tests/Makefile.am | 46 ++-- tests/forms-test.c | 2 +- tests/httpd.conf.22.in | 81 +++--- tests/httpd.conf.24.in | 82 +++--- tests/no-ssl-test.c | 3 +- tests/ntlm-test.c | 8 +- tests/resource-test.c | 2 +- tests/session-test.c | 8 +- tests/ssl-test.c | 7 +- tests/test-utils.c | 80 ++++-- tests/xmlrpc-server-test.c | 2 +- 18 files changed, 1014 insertions(+), 133 deletions(-) create mode 100644 glib-tap.mk create mode 100644 m4/glibtests.m4 create mode 100755 tap-driver.sh create mode 100755 tap-test diff --git a/.gitignore b/.gitignore index 293106cf..674fad1a 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ stamp-h1 tests/*.log tests/*.trs tests/*-test +tests/*.test tests/date tests/header-parsing tests/httpd.conf diff --git a/Makefile.am b/Makefile.am index 66992d93..c8fa95ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,9 @@ EXTRA_DIST = \ libsoup-gnome-2.4.pc.in \ gtk-doc.make \ libsoup-zip.in \ - m4/introspection.m4 \ + glib-tap.mk \ + tap-driver.sh \ + tap-test \ Makefile.glib DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-introspection diff --git a/configure.ac b/configure.ac index f60744a5..defe54b8 100644 --- a/configure.ac +++ b/configure.ac @@ -88,6 +88,8 @@ GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_36" GLIB_MAKEFILE='$(top_srcdir)/Makefile.glib' AC_SUBST(GLIB_MAKEFILE) +GLIB_TESTS + PKG_CHECK_MODULES(XML, libxml-2.0) AC_SUBST(XML_CFLAGS) AC_SUBST(XML_LIBS) diff --git a/glib-tap.mk b/glib-tap.mk new file mode 100644 index 00000000..c97bf3f2 --- /dev/null +++ b/glib-tap.mk @@ -0,0 +1,134 @@ +# GLIB - Library of useful C routines + +TESTS_ENVIRONMENT= \ + G_TEST_SRCDIR="$(abs_srcdir)" \ + G_TEST_BUILDDIR="$(abs_builddir)" \ + G_DEBUG=gc-friendly \ + MALLOC_CHECK_=2 \ + MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256)) +LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh +LOG_COMPILER = $(top_srcdir)/tap-test + +NULL = + +# initialize variables for unconditional += appending +BUILT_SOURCES = +BUILT_EXTRA_DIST = +CLEANFILES = *.log *.trs +DISTCLEANFILES = +MAINTAINERCLEANFILES = +EXTRA_DIST = +TESTS = + +installed_test_LTLIBRARIES = +installed_test_PROGRAMS = +installed_test_SCRIPTS = +nobase_installed_test_DATA = + +noinst_LTLIBRARIES = +noinst_PROGRAMS = +noinst_SCRIPTS = +noinst_DATA = + +check_LTLIBRARIES = +check_PROGRAMS = +check_SCRIPTS = +check_DATA = + +# We support a fairly large range of possible variables. It is expected that all types of files in a test suite +# will belong in exactly one of the following variables. +# +# First, we support the usual automake suffixes, but in lowercase, with the customary meaning: +# +# test_programs, test_scripts, test_data, test_ltlibraries +# +# The above are used to list files that are involved in both uninstalled and installed testing. The +# test_programs and test_scripts are taken to be actual testcases and will be run as part of the test suite. +# Note that _data is always used with the nobase_ automake variable name to ensure that installed test data is +# installed in the same way as it appears in the package layout. +# +# In order to mark a particular file as being only for one type of testing, use 'installed' or 'uninstalled', +# like so: +# +# installed_test_programs, uninstalled_test_programs +# installed_test_scripts, uninstalled_test_scripts +# installed_test_data, uninstalled_test_data +# installed_test_ltlibraries, uninstalled_test_ltlibraries +# +# Additionally, we support 'extra' infixes for programs and scripts. This is used for support programs/scripts +# that should not themselves be run as testcases (but exist to be used from other testcases): +# +# test_extra_programs, installed_test_extra_programs, uninstalled_test_extra_programs +# test_extra_scripts, installed_test_extra_scripts, uninstalled_test_extra_scripts +# +# Additionally, for _scripts and _data, we support the customary dist_ prefix so that the named script or data +# file automatically end up in the tarball. +# +# dist_test_scripts, dist_test_data, dist_test_extra_scripts +# dist_installed_test_scripts, dist_installed_test_data, dist_installed_test_extra_scripts +# dist_uninstalled_test_scripts, dist_uninstalled_test_data, dist_uninstalled_test_extra_scripts +# +# Note that no file is automatically disted unless it appears in one of the dist_ variables. This follows the +# standard automake convention of not disting programs scripts or data by default. +# +# test_programs, test_scripts, uninstalled_test_programs and uninstalled_test_scripts (as well as their disted +# variants) will be run as part of the in-tree 'make check'. These are all assumed to be runnable under +# gtester. That's a bit strange for scripts, but it's possible. + +TESTS += $(test_programs) $(test_scripts) $(uninstalled_test_programs) $(uninstalled_test_scripts) \ + $(dist_test_scripts) $(dist_uninstalled_test_scripts) + +# Note: build even the installed-only targets during 'make check' to ensure that they still work. +# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to +# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were +# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'. +all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \ + $(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs) +all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) $(installed_test_scripts) \ + $(test_extra_scripts) $(uninstalled_test_extra_scripts) $(installed_test_extra_scripts) +all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \ + $(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts) +all_test_scripts += $(all_dist_test_scripts) +EXTRA_DIST += $(all_dist_test_scripts) +all_test_data = $(test_data) $(uninstalled_test_data) $(installed_test_data) +all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data) +all_test_data += $(all_dist_test_data) +EXTRA_DIST += $(all_dist_test_data) +all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries) + +if ENABLE_ALWAYS_BUILD_TESTS +noinst_LTLIBRARIES += $(all_test_ltlibs) +noinst_PROGRAMS += $(all_test_programs) +noinst_SCRIPTS += $(all_test_scripts) +noinst_DATA += $(all_test_data) +else +check_LTLIBRARIES += $(all_test_ltlibs) +check_PROGRAMS += $(all_test_programs) +check_SCRIPTS += $(all_test_scripts) +check_DATA += $(all_test_data) +endif + +if ENABLE_INSTALLED_TESTS +installed_test_PROGRAMS += $(test_programs) $(installed_test_programs) \ + $(test_extra_programs) $(installed_test_extra_programs) +installed_test_SCRIPTS += $(test_scripts) $(installed_test_scripts) \ + $(test_extra_scripts) $(test_installed_extra_scripts) +installed_test_SCRIPTS += $(dist_test_scripts) $(dist_test_extra_scripts) \ + $(dist_installed_test_scripts) $(dist_installed_test_extra_scripts) +nobase_installed_test_DATA += $(test_data) $(installed_test_data) +nobase_installed_test_DATA += $(dist_test_data) $(dist_installed_test_data) +installed_test_LTLIBRARIES += $(test_ltlibraries) $(installed_test_ltlibraries) +installed_testcases = $(test_programs) $(installed_test_programs) \ + $(test_scripts) $(installed_test_scripts) \ + $(dist_test_scripts) $(dist_installed_test_scripts) + +installed_test_meta_DATA = $(installed_testcases:=.test) + +%.test: %$(EXEEXT) Makefile + $(AM_V_GEN) (echo '[Test]' > $@.tmp; \ + echo 'Type=session' >> $@.tmp; \ + echo 'Exec=$(installed_testdir)/$<' >> $@.tmp; \ + mv $@.tmp $@) + +CLEANFILES += $(installed_test_meta_DATA) +endif diff --git a/m4/glibtests.m4 b/m4/glibtests.m4 new file mode 100644 index 00000000..7d5920a4 --- /dev/null +++ b/m4/glibtests.m4 @@ -0,0 +1,28 @@ +dnl GLIB_TESTS +dnl + +AC_DEFUN([GLIB_TESTS], +[ + AC_ARG_ENABLE(installed-tests, + AS_HELP_STRING([--enable-installed-tests], + [Enable installation of some test cases]), + [case ${enableval} in + yes) ENABLE_INSTALLED_TESTS="1" ;; + no) ENABLE_INSTALLED_TESTS="" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-installed-tests]) ;; + esac]) + AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], test "$ENABLE_INSTALLED_TESTS" = "1") + AC_ARG_ENABLE(always-build-tests, + AS_HELP_STRING([--enable-always-build-tests], + [Enable always building tests during 'make all']), + [case ${enableval} in + yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;; + no) ENABLE_ALWAYS_BUILD_TESTS="" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-always-build-tests]) ;; + esac]) + AM_CONDITIONAL([ENABLE_ALWAYS_BUILD_TESTS], test "$ENABLE_ALWAYS_BUILD_TESTS" = "1") + if test "$ENABLE_INSTALLED_TESTS" = "1"; then + AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME) + AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME) + fi +]) diff --git a/tap-driver.sh b/tap-driver.sh new file mode 100755 index 00000000..19aa531d --- /dev/null +++ b/tap-driver.sh @@ -0,0 +1,652 @@ +#! /bin/sh +# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +scriptversion=2011-12-27.17; # UTC + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +me=tap-driver.sh + +fatal () +{ + echo "$me: fatal: $*" >&2 + exit 1 +} + +usage_error () +{ + echo "$me: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat < + # + trap : 1 3 2 13 15 + if test $merge -gt 0; then + exec 2>&1 + else + exec 2>&3 + fi + "$@" + echo $? + ) | LC_ALL=C ${AM_TAP_AWK-awk} \ + -v me="$me" \ + -v test_script_name="$test_name" \ + -v log_file="$log_file" \ + -v trs_file="$trs_file" \ + -v expect_failure="$expect_failure" \ + -v merge="$merge" \ + -v ignore_exit="$ignore_exit" \ + -v comments="$comments" \ + -v diag_string="$diag_string" \ +' +# FIXME: the usages of "cat >&3" below could be optimized when using +# FIXME: GNU awk, and/on on systems that supports /dev/fd/. + +# Implementation note: in what follows, `result_obj` will be an +# associative array that (partly) simulates a TAP result object +# from the `TAP::Parser` perl module. + +## ----------- ## +## FUNCTIONS ## +## ----------- ## + +function fatal(msg) +{ + print me ": " msg | "cat >&2" + exit 1 +} + +function abort(where) +{ + fatal("internal error " where) +} + +# Convert a boolean to a "yes"/"no" string. +function yn(bool) +{ + return bool ? "yes" : "no"; +} + +function add_test_result(result) +{ + if (!test_results_index) + test_results_index = 0 + test_results_list[test_results_index] = result + test_results_index += 1 + test_results_seen[result] = 1; +} + +# Whether the test script should be re-run by "make recheck". +function must_recheck() +{ + for (k in test_results_seen) + if (k != "XFAIL" && k != "PASS" && k != "SKIP") + return 1 + return 0 +} + +# Whether the content of the log file associated to this test should +# be copied into the "global" test-suite.log. +function copy_in_global_log() +{ + for (k in test_results_seen) + if (k != "PASS") + return 1 + return 0 +} + +# FIXME: this can certainly be improved ... +function get_global_test_result() +{ + if ("ERROR" in test_results_seen) + return "ERROR" + if ("FAIL" in test_results_seen || "XPASS" in test_results_seen) + return "FAIL" + all_skipped = 1 + for (k in test_results_seen) + if (k != "SKIP") + all_skipped = 0 + if (all_skipped) + return "SKIP" + return "PASS"; +} + +function stringify_result_obj(result_obj) +{ + if (result_obj["is_unplanned"] || result_obj["number"] != testno) + return "ERROR" + + if (plan_seen == LATE_PLAN) + return "ERROR" + + if (result_obj["directive"] == "TODO") + return result_obj["is_ok"] ? "XPASS" : "XFAIL" + + if (result_obj["directive"] == "SKIP") + return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL; + + if (length(result_obj["directive"])) + abort("in function stringify_result_obj()") + + return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL +} + +function decorate_result(result) +{ + color_name = color_for_result[result] + if (color_name) + return color_map[color_name] "" result "" color_map["std"] + # If we are not using colorized output, or if we do not know how + # to colorize the given result, we should return it unchanged. + return result +} + +function report(result, details) +{ + if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/) + { + msg = ": " test_script_name + add_test_result(result) + } + else if (result == "#") + { + msg = " " test_script_name ":" + } + else + { + abort("in function report()") + } + if (length(details)) + msg = msg " " details + # Output on console might be colorized. + print decorate_result(result) msg + # Log the result in the log file too, to help debugging (this is + # especially true when said result is a TAP error or "Bail out!"). + print result msg | "cat >&3"; +} + +function testsuite_error(error_message) +{ + report("ERROR", "- " error_message) +} + +function handle_tap_result() +{ + details = result_obj["number"]; + if (length(result_obj["description"])) + details = details " " result_obj["description"] + + if (plan_seen == LATE_PLAN) + { + details = details " # AFTER LATE PLAN"; + } + else if (result_obj["is_unplanned"]) + { + details = details " # UNPLANNED"; + } + else if (result_obj["number"] != testno) + { + details = sprintf("%s # OUT-OF-ORDER (expecting %d)", + details, testno); + } + else if (result_obj["directive"]) + { + details = details " # " result_obj["directive"]; + if (length(result_obj["explanation"])) + details = details " " result_obj["explanation"] + } + + report(stringify_result_obj(result_obj), details) +} + +# `skip_reason` should be empty whenever planned > 0. +function handle_tap_plan(planned, skip_reason) +{ + planned += 0 # Avoid getting confused if, say, `planned` is "00" + if (length(skip_reason) && planned > 0) + abort("in function handle_tap_plan()") + if (plan_seen) + { + # Error, only one plan per stream is acceptable. + testsuite_error("multiple test plans") + return; + } + planned_tests = planned + # The TAP plan can come before or after *all* the TAP results; we speak + # respectively of an "early" or a "late" plan. If we see the plan line + # after at least one TAP result has been seen, assume we have a late + # plan; in this case, any further test result seen after the plan will + # be flagged as an error. + plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN) + # If testno > 0, we have an error ("too many tests run") that will be + # automatically dealt with later, so do not worry about it here. If + # $plan_seen is true, we have an error due to a repeated plan, and that + # has already been dealt with above. Otherwise, we have a valid "plan + # with SKIP" specification, and should report it as a particular kind + # of SKIP result. + if (planned == 0 && testno == 0) + { + if (length(skip_reason)) + skip_reason = "- " skip_reason; + report("SKIP", skip_reason); + } +} + +function extract_tap_comment(line) +{ + if (index(line, diag_string) == 1) + { + # Strip leading `diag_string` from `line`. + line = substr(line, length(diag_string) + 1) + # And strip any leading and trailing whitespace left. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + # Return what is left (if any). + return line; + } + return ""; +} + +# When this function is called, we know that line is a TAP result line, +# so that it matches the (perl) RE "^(not )?ok\b". +function setup_result_obj(line) +{ + # Get the result, and remove it from the line. + result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0) + sub("^(not )?ok[ \t]*", "", line) + + # If the result has an explicit number, get it and strip it; otherwise, + # automatically assing the next progresive number to it. + if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/) + { + match(line, "^[0-9]+") + # The final `+ 0` is to normalize numbers with leading zeros. + result_obj["number"] = substr(line, 1, RLENGTH) + 0 + line = substr(line, RLENGTH + 1) + } + else + { + result_obj["number"] = testno + } + + if (plan_seen == LATE_PLAN) + # No further test results are acceptable after a "late" TAP plan + # has been seen. + result_obj["is_unplanned"] = 1 + else if (plan_seen && testno > planned_tests) + result_obj["is_unplanned"] = 1 + else + result_obj["is_unplanned"] = 0 + + # Strip trailing and leading whitespace. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + + # This will have to be corrected if we have a "TODO"/"SKIP" directive. + result_obj["description"] = line + result_obj["directive"] = "" + result_obj["explanation"] = "" + + if (index(line, "#") == 0) + return # No possible directive, nothing more to do. + + # Directives are case-insensitive. + rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*" + + # See whether we have the directive, and if yes, where. + pos = match(line, rx "$") + if (!pos) + pos = match(line, rx "[^a-zA-Z0-9_]") + + # If there was no TAP directive, we have nothing more to do. + if (!pos) + return + + # Let`s now see if the TAP directive has been escaped. For example: + # escaped: ok \# SKIP + # not escaped: ok \\# SKIP + # escaped: ok \\\\\# SKIP + # not escaped: ok \ # SKIP + if (substr(line, pos, 1) == "#") + { + bslash_count = 0 + for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--) + bslash_count += 1 + if (bslash_count % 2) + return # Directive was escaped. + } + + # Strip the directive and its explanation (if any) from the test + # description. + result_obj["description"] = substr(line, 1, pos - 1) + # Now remove the test description from the line, that has been dealt + # with already. + line = substr(line, pos) + # Strip the directive, and save its value (normalized to upper case). + sub("^[ \t]*#[ \t]*", "", line) + result_obj["directive"] = toupper(substr(line, 1, 4)) + line = substr(line, 5) + # Now get the explanation for the directive (if any), with leading + # and trailing whitespace removed. + sub("^[ \t]*", "", line) + sub("[ \t]*$", "", line) + result_obj["explanation"] = line +} + +function get_test_exit_message(status) +{ + if (status == 0) + return "" + if (status !~ /^[1-9][0-9]*$/) + abort("getting exit status") + if (status < 127) + exit_details = "" + else if (status == 127) + exit_details = " (command not found?)" + else if (status >= 128 && status <= 255) + exit_details = sprintf(" (terminated by signal %d?)", status - 128) + else if (status > 256 && status <= 384) + # We used to report an "abnormal termination" here, but some Korn + # shells, when a child process die due to signal number n, can leave + # in $? an exit status of 256+n instead of the more standard 128+n. + # Apparently, both behaviours are allowed by POSIX (2008), so be + # prepared to handle them both. See also Austing Group report ID + # 0000051 + exit_details = sprintf(" (terminated by signal %d?)", status - 256) + else + # Never seen in practice. + exit_details = " (abnormal termination)" + return sprintf("exited with status %d%s", status, exit_details) +} + +function write_test_results() +{ + print ":global-test-result: " get_global_test_result() > trs_file + print ":recheck: " yn(must_recheck()) > trs_file + print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file + for (i = 0; i < test_results_index; i += 1) + print ":test-result: " test_results_list[i] > trs_file + close(trs_file); +} + +BEGIN { + +## ------- ## +## SETUP ## +## ------- ## + +'"$init_colors"' + +# Properly initialized once the TAP plan is seen. +planned_tests = 0 + +COOKED_PASS = expect_failure ? "XPASS": "PASS"; +COOKED_FAIL = expect_failure ? "XFAIL": "FAIL"; + +# Enumeration-like constants to remember which kind of plan (if any) +# has been seen. It is important that NO_PLAN evaluates "false" as +# a boolean. +NO_PLAN = 0 +EARLY_PLAN = 1 +LATE_PLAN = 2 + +testno = 0 # Number of test results seen so far. +bailed_out = 0 # Whether a "Bail out!" directive has been seen. + +# Whether the TAP plan has been seen or not, and if yes, which kind +# it is ("early" is seen before any test result, "late" otherwise). +plan_seen = NO_PLAN + +## --------- ## +## PARSING ## +## --------- ## + +is_first_read = 1 + +while (1) + { + # Involutions required so that we are able to read the exit status + # from the last input line. + st = getline + if (st < 0) # I/O error. + fatal("I/O error while reading from input stream") + else if (st == 0) # End-of-input + { + if (is_first_read) + abort("in input loop: only one input line") + break + } + if (is_first_read) + { + is_first_read = 0 + nextline = $0 + continue + } + else + { + curline = nextline + nextline = $0 + $0 = curline + } + # Copy any input line verbatim into the log file. + print | "cat >&3" + # Parsing of TAP input should stop after a "Bail out!" directive. + if (bailed_out) + continue + + # TAP test result. + if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/) + { + testno += 1 + setup_result_obj($0) + handle_tap_result() + } + # TAP plan (normal or "SKIP" without explanation). + else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/) + { + # The next two lines will put the number of planned tests in $0. + sub("^1\\.\\.", "") + sub("[^0-9]*$", "") + handle_tap_plan($0, "") + continue + } + # TAP "SKIP" plan, with an explanation. + else if ($0 ~ /^1\.\.0+[ \t]*#/) + { + # The next lines will put the skip explanation in $0, stripping + # any leading and trailing whitespace. This is a little more + # tricky in truth, since we want to also strip a potential leading + # "SKIP" string from the message. + sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "") + sub("[ \t]*$", ""); + handle_tap_plan(0, $0) + } + # "Bail out!" magic. + # Older versions of prove and TAP::Harness (e.g., 3.17) did not + # recognize a "Bail out!" directive when preceded by leading + # whitespace, but more modern versions (e.g., 3.23) do. So we + # emulate the latter, "more modern" behaviour. + else if ($0 ~ /^[ \t]*Bail out!/) + { + bailed_out = 1 + # Get the bailout message (if any), with leading and trailing + # whitespace stripped. The message remains stored in `$0`. + sub("^[ \t]*Bail out![ \t]*", ""); + sub("[ \t]*$", ""); + # Format the error message for the + bailout_message = "Bail out!" + if (length($0)) + bailout_message = bailout_message " " $0 + testsuite_error(bailout_message) + } + # Maybe we have too look for dianogtic comments too. + else if (comments != 0) + { + comment = extract_tap_comment($0); + if (length(comment)) + report("#", comment); + } + } + +## -------- ## +## FINISH ## +## -------- ## + +# A "Bail out!" directive should cause us to ignore any following TAP +# error, as well as a non-zero exit status from the TAP producer. +if (!bailed_out) + { + if (!plan_seen) + { + testsuite_error("missing test plan") + } + else if (planned_tests != testno) + { + bad_amount = testno > planned_tests ? "many" : "few" + testsuite_error(sprintf("too %s tests run (expected %d, got %d)", + bad_amount, planned_tests, testno)) + } + if (!ignore_exit) + { + # Fetch exit status from the last line. + exit_message = get_test_exit_message(nextline) + if (exit_message) + testsuite_error(exit_message) + } + } + +write_test_results() + +exit 0 + +} # End of "BEGIN" block. +' + +# TODO: document that we consume the file descriptor 3 :-( +} 3>"$log_file" + +test $? -eq 0 || fatal "I/O or internal error" + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/tap-test b/tap-test new file mode 100755 index 00000000..481e333e --- /dev/null +++ b/tap-test @@ -0,0 +1,5 @@ +#! /bin/sh + +# run a GTest in tap mode. The test binary is passed as $1 + +$1 -k --tap diff --git a/tests/Makefile.am b/tests/Makefile.am index f7293b12..d9ede804 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,14 +1,14 @@ +include $(top_srcdir)/glib-tap.mk + AM_CPPFLAGS = \ -I$(top_srcdir) \ - -DSRCDIR=\""$(abs_srcdir)"\" \ - -DBUILDDIR=\""$(builddir)"\" \ $(GLIB_CFLAGS) LIBS = \ $(top_builddir)/libsoup/libsoup-2.4.la \ $(GLIB_LIBS) -TESTS = \ +test_programs = \ auth-test \ cache-test \ chunk-test \ @@ -44,13 +44,18 @@ TESTS = \ xmlrpc-server-test \ xmlrpc-test -noinst_PROGRAMS = \ +test_extra_programs = \ ntlm-test-helper \ $(TESTS) -noinst_DATA = soup-tests.gresource +test_data = \ + index.txt \ + soup-tests.gresource \ + test-cert.pem \ + test-key.pem \ + xmlrpc-server.php -noinst_LTLIBRARIES = libtest.la +noinst_LTLIBRARIES += libtest.la libtest_la_SOURCES = \ test-utils.c \ @@ -74,7 +79,11 @@ httpd.conf: $(httpd_conf_in) -e 's,[@]APACHE_SSL_MODULE_DIR@,$(APACHE_SSL_MODULE_DIR),' \ $< > $@ || rm -f $@ -BUILT_SOURCES = httpd.conf +BUILT_SOURCES += httpd.conf +test_data += \ + htdigest \ + htpasswd \ + httpd.conf endif RESOURCES = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/soup-tests.gresource.xml) @@ -82,7 +91,7 @@ RESOURCES = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-d soup-tests.gresource: soup-tests.gresource.xml $(RESOURCES) $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $< -EXTRA_DIST = \ +EXTRA_DIST += \ htdigest \ htpasswd \ httpd.conf.22.in \ @@ -95,10 +104,9 @@ EXTRA_DIST = \ xmlrpc-server.php \ $(RESOURCES) -DISTCLEANFILES = soup-tests.gresource httpd.conf +DISTCLEANFILES += soup-tests.gresource httpd.conf -TESTS_ENVIRONMENT = \ - SOUP_TESTS_IN_MAKE_CHECK=1 +TESTS_ENVIRONMENT += SOUP_TESTS_IN_MAKE_CHECK=1 check: start-httpd @@ -113,13 +121,21 @@ endif .PHONY: start-httpd kill-httpd start-httpd: -if HAVE_APACHE - @$(APACHE_HTTPD) -d `pwd` -f httpd.conf -k start; +if HAVE_APACHE_2_2 + @$(APACHE_HTTPD) -d $(abs_srcdir) -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start; +endif +if HAVE_APACHE_2_4 + @$(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k start; endif kill-httpd: -if HAVE_APACHE +if HAVE_APACHE_2_2 + @if [ -f httpd.pid ]; then \ + $(APACHE_HTTPD) -d $(abs_srcdir) -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k stop; \ + fi +endif +if HAVE_APACHE_2_4 @if [ -f httpd.pid ]; then \ - $(APACHE_HTTPD) -d `pwd` -f httpd.conf -k stop; \ + $(APACHE_HTTPD) -d $(abs_srcdir) -c "DefaultRuntimeDir `pwd`" -c "PidFile `pwd`/httpd.pid" -f `pwd`/httpd.conf -k stop; \ fi endif diff --git a/tests/forms-test.c b/tests/forms-test.c index 7a843dac..da71569b 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -135,7 +135,7 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5) g_free (file_arg); } -#define MD5_TEST_FILE SRCDIR "/index.txt" +#define MD5_TEST_FILE (g_test_get_filename (G_TEST_DIST, "index.txt", NULL)) #define MD5_TEST_FILE_BASENAME "index.txt" #define MD5_TEST_FILE_MIME_TYPE "text/plain" diff --git a/tests/httpd.conf.22.in b/tests/httpd.conf.22.in index de0b75fa..b912ca36 100644 --- a/tests/httpd.conf.22.in +++ b/tests/httpd.conf.22.in @@ -3,8 +3,7 @@ ServerName 127.0.0.1 Listen 127.0.0.1:47524 -PidFile @builddir@/httpd.pid -DocumentRoot @srcdir@ +DocumentRoot . # The tests shut down apache with "graceful-stop", because that makes # it close its listening socket right away. But it seems to sometimes @@ -83,7 +82,7 @@ Listen 127.0.0.1:47527 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require valid-user @@ -94,7 +93,7 @@ Listen 127.0.0.1:47527 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require valid-user @@ -124,7 +123,7 @@ Listen 127.0.0.1:47528 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user no-such-user @@ -135,7 +134,7 @@ Listen 127.0.0.1:47528 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user no-such-user @@ -154,89 +153,89 @@ Listen 127.0.0.1:47528 SSLEngine on - SSLCertificateFile @srcdir@/test-cert.pem - SSLCertificateKeyFile @srcdir@/test-key.pem + SSLCertificateFile ./test-cert.pem + SSLCertificateKeyFile ./test-key.pem # Basic auth tests -Alias /Basic/realm1/realm2/realm1 @srcdir@ -Alias /Basic/realm1/realm2 @srcdir@ -Alias /Basic/realm1/subdir @srcdir@ -Alias /Basic/realm1/not @srcdir@ -Alias /Basic/realm1 @srcdir@ -Alias /Basic/realm12/subdir @srcdir@ -Alias /Basic/realm12 @srcdir@ -Alias /Basic/realm2 @srcdir@ -Alias /Basic/realm3 @srcdir@ -Alias /Basic @srcdir@ +Alias /Basic/realm1/realm2/realm1 . +Alias /Basic/realm1/realm2 . +Alias /Basic/realm1/subdir . +Alias /Basic/realm1/not . +Alias /Basic/realm1 . +Alias /Basic/realm12/subdir . +Alias /Basic/realm12 . +Alias /Basic/realm2 . +Alias /Basic/realm3 . +Alias /Basic . AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user1 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user2 AuthType Basic AuthName realm12 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user1 user2 AuthType Basic AuthName realm2 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user2 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user1 AuthType Basic AuthName realm2 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user2 AuthType Basic AuthName realm3 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user3 # Digest auth tests -Alias /Digest/realm1/realm2/realm1 @srcdir@ -Alias /Digest/realm1/realm2 @srcdir@ -Alias /Digest/realm1/subdir @srcdir@ -Alias /Digest/realm1/expire @srcdir@ -Alias /Digest/realm1/not @srcdir@ -Alias /Digest/realm1 @srcdir@ -Alias /Digest/realm2 @srcdir@ -Alias /Digest/realm3 @srcdir@ -Alias /Digest @srcdir@ +Alias /Digest/realm1/realm2/realm1 . +Alias /Digest/realm1/realm2 . +Alias /Digest/realm1/subdir . +Alias /Digest/realm1/expire . +Alias /Digest/realm1/not . +Alias /Digest/realm1 . +Alias /Digest/realm2 . +Alias /Digest/realm3 . +Alias /Digest . AuthType Digest AuthName realm1 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 Require valid-user @@ -244,7 +243,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm1 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 AuthDigestNonceLifetime 2 Require valid-user @@ -253,7 +252,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm1 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 Require user user2 @@ -261,7 +260,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm2 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 Require valid-user @@ -269,7 +268,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm1 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 Require valid-user @@ -277,7 +276,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm2 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 Require valid-user @@ -285,7 +284,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm3 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm3 Require valid-user # test RFC2069-style Digest diff --git a/tests/httpd.conf.24.in b/tests/httpd.conf.24.in index 2407ad75..850b8393 100644 --- a/tests/httpd.conf.24.in +++ b/tests/httpd.conf.24.in @@ -3,9 +3,7 @@ ServerName 127.0.0.1 Listen 127.0.0.1:47524 -PidFile @builddir@/httpd.pid -DefaultRuntimeDir @builddir@ -DocumentRoot @srcdir@ +DocumentRoot . # The tests shut down apache with "graceful-stop", because that makes # it close its listening socket right away. But it seems to sometimes @@ -80,7 +78,7 @@ Listen 127.0.0.1:47527 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require valid-user @@ -88,7 +86,7 @@ Listen 127.0.0.1:47527 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require valid-user @@ -113,7 +111,7 @@ Listen 127.0.0.1:47528 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user no-such-user @@ -121,7 +119,7 @@ Listen 127.0.0.1:47528 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user no-such-user @@ -139,89 +137,89 @@ Listen 127.0.0.1:47528 SSLEngine on - SSLCertificateFile @srcdir@/test-cert.pem - SSLCertificateKeyFile @srcdir@/test-key.pem + SSLCertificateFile ./test-cert.pem + SSLCertificateKeyFile ./test-key.pem # Basic auth tests -Alias /Basic/realm1/realm2/realm1 @srcdir@ -Alias /Basic/realm1/realm2 @srcdir@ -Alias /Basic/realm1/subdir @srcdir@ -Alias /Basic/realm1/not @srcdir@ -Alias /Basic/realm1 @srcdir@ -Alias /Basic/realm12/subdir @srcdir@ -Alias /Basic/realm12 @srcdir@ -Alias /Basic/realm2 @srcdir@ -Alias /Basic/realm3 @srcdir@ -Alias /Basic @srcdir@ +Alias /Basic/realm1/realm2/realm1 . +Alias /Basic/realm1/realm2 . +Alias /Basic/realm1/subdir . +Alias /Basic/realm1/not . +Alias /Basic/realm1 . +Alias /Basic/realm12/subdir . +Alias /Basic/realm12 . +Alias /Basic/realm2 . +Alias /Basic/realm3 . +Alias /Basic . AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user1 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user2 AuthType Basic AuthName realm12 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user1 user2 AuthType Basic AuthName realm2 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user2 AuthType Basic AuthName realm1 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user1 AuthType Basic AuthName realm2 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user2 AuthType Basic AuthName realm3 - AuthUserFile @srcdir@/htpasswd + AuthUserFile ./htpasswd Require user user3 # Digest auth tests -Alias /Digest/realm1/realm2/realm1 @srcdir@ -Alias /Digest/realm1/realm2 @srcdir@ -Alias /Digest/realm1/subdir @srcdir@ -Alias /Digest/realm1/expire @srcdir@ -Alias /Digest/realm1/not @srcdir@ -Alias /Digest/realm1 @srcdir@ -Alias /Digest/realm2 @srcdir@ -Alias /Digest/realm3 @srcdir@ -Alias /Digest @srcdir@ +Alias /Digest/realm1/realm2/realm1 . +Alias /Digest/realm1/realm2 . +Alias /Digest/realm1/subdir . +Alias /Digest/realm1/expire . +Alias /Digest/realm1/not . +Alias /Digest/realm1 . +Alias /Digest/realm2 . +Alias /Digest/realm3 . +Alias /Digest . AuthType Digest AuthName realm1 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 Require valid-user @@ -229,7 +227,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm1 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 AuthDigestNonceLifetime 2 Require valid-user @@ -238,7 +236,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm1 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 Require user user2 @@ -246,7 +244,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm2 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 Require valid-user @@ -254,7 +252,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm1 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm1 /Digest/realm1/realm2/realm1 Require valid-user @@ -262,7 +260,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm2 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm2 /Digest/realm1/realm2 Require valid-user @@ -270,7 +268,7 @@ Alias /Digest @srcdir@ AuthType Digest AuthName realm3 - AuthUserFile @srcdir@/htdigest + AuthUserFile ./htdigest AuthDigestDomain /Digest/realm3 Require valid-user # test RFC2069-style Digest diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c index 5944b91b..feffa5bd 100644 --- a/tests/no-ssl-test.c +++ b/tests/no-ssl-test.c @@ -76,7 +76,8 @@ do_session_property_tests (void) soup_test_assert (ca_file == NULL, "setting ssl-use-system-ca-file set ssl-ca-file"); g_object_set (G_OBJECT (session), - "ssl-ca-file", SRCDIR "/test-cert.pem", + "ssl-ca-file", + g_test_get_filename (G_TEST_DIST, "test-cert.pem", NULL), NULL); g_object_get (G_OBJECT (session), "ssl-use-system-ca-file", &use_system, diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index 39879274..0fa4b478 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -465,7 +465,9 @@ do_winbind_ntlm_test (gconstpointer data) /* Samba winbind /usr/bin/ntlm_auth helper support (via a * helper program that emulates its interface). */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG", BUILDDIR "/ntlm-test-helper", TRUE); + g_setenv ("SOUP_NTLM_AUTH_DEBUG", + g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL), + TRUE); g_unsetenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS"); do_ntlm_tests (uri, FALSE); } @@ -479,7 +481,9 @@ do_fallback_ntlm_test (gconstpointer data) * no cached credentials (and thus we have to fall back to * libsoup's built-in NTLM support). */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG", BUILDDIR "/ntlm-test-helper", TRUE); + g_setenv ("SOUP_NTLM_AUTH_DEBUG", + g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL), + TRUE); g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); do_ntlm_tests (uri, TRUE); } diff --git a/tests/resource-test.c b/tests/resource-test.c index 50d63ab9..6fcb899e 100644 --- a/tests/resource-test.c +++ b/tests/resource-test.c @@ -155,7 +155,7 @@ do_request_file_test (gconstpointer type) GFile *index; char *uri_string; - index = g_file_new_for_path (SRCDIR "/index.txt"); + index = g_file_new_for_path (g_test_get_filename (G_TEST_DIST, "index.txt", NULL)); uri_string = g_file_get_uri (index); g_object_unref (index); diff --git a/tests/session-test.c b/tests/session-test.c index a6ce2c45..21d97a85 100644 --- a/tests/session-test.c +++ b/tests/session-test.c @@ -333,7 +333,13 @@ do_property_tests (void) * so we can only do this test if we have a real TLS backend. */ if (tls_available) { - tlsdb = g_tls_file_database_new (SRCDIR "/test-cert.pem", NULL); + GError *error = NULL; + + tlsdb = g_tls_file_database_new (g_test_get_filename (G_TEST_DIST, + "test-cert.pem", + NULL), &error); + g_assert_no_error (error); + session = g_object_new (SOUP_TYPE_SESSION, SOUP_SESSION_TLS_DATABASE, tlsdb, NULL); diff --git a/tests/ssl-test.c b/tests/ssl-test.c index 5ef41292..753a980c 100644 --- a/tests/ssl-test.c +++ b/tests/ssl-test.c @@ -65,7 +65,10 @@ do_one_strict_test (SoupSession *session, const char *uri, g_object_set (G_OBJECT (session), SOUP_SESSION_SSL_STRICT, strict, - SOUP_SESSION_SSL_CA_FILE, with_ca_list ? SRCDIR "/test-cert.pem" : "/dev/null", + SOUP_SESSION_SSL_CA_FILE, + (with_ca_list ? + g_test_get_filename (G_TEST_DIST, "/test-cert.pem", NULL) : + "/dev/null"), NULL); /* Close existing connections with old params */ soup_session_abort (session); @@ -184,7 +187,7 @@ do_session_property_tests (void) use_system_changed = tlsdb_changed = ca_file_changed = FALSE; g_object_set (G_OBJECT (session), - "ssl-ca-file", SRCDIR "/test-cert.pem", + "ssl-ca-file", g_test_get_filename (G_TEST_DIST, "/test-cert.pem", NULL), NULL); g_object_get (G_OBJECT (session), "ssl-use-system-ca-file", &use_system, diff --git a/tests/test-utils.c b/tests/test-utils.c index 3d2546f5..1d0d775b 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -91,9 +91,6 @@ test_init (int argc, char **argv, GOptionEntry *entries) } g_option_context_free (opts); - if (g_getenv ("SOUP_TESTS_IN_MAKE_CHECK")) - debug_level = G_MAXINT; - /* Exit cleanly on ^C in case we're valgrinding. */ signal (SIGINT, quit); @@ -137,30 +134,52 @@ debug_printf (int level, const char *format, ...) static gboolean apache_cmd (const char *cmd) { - const char *argv[8]; - char *cwd, *conf; + GPtrArray *argv; + char *server_root, *cwd, *pid_file; +#ifdef HAVE_APACHE_2_4 + char *default_runtime_dir; +#endif int status; gboolean ok; + server_root = g_test_build_filename (G_TEST_BUILT, "", NULL); + cwd = g_get_current_dir (); - conf = g_build_filename (cwd, "httpd.conf", NULL); - - argv[0] = APACHE_HTTPD; - argv[1] = "-d"; - argv[2] = cwd; - argv[3] = "-f"; - argv[4] = conf; - argv[5] = "-k"; - argv[6] = cmd; - argv[7] = NULL; - - ok = g_spawn_sync (cwd, (char **)argv, NULL, 0, NULL, NULL, +#ifdef HAVE_APACHE_2_4 + default_runtime_dir = g_strdup_printf ("DefaultRuntimeDir %s", cwd); +#endif + pid_file = g_strdup_printf ("PidFile %s/httpd.pid", cwd); + + argv = g_ptr_array_new (); + g_ptr_array_add (argv, APACHE_HTTPD); + g_ptr_array_add (argv, "-d"); + g_ptr_array_add (argv, server_root); + g_ptr_array_add (argv, "-f"); + g_ptr_array_add (argv, "httpd.conf"); + +#ifdef HAVE_APACHE_2_4 + g_ptr_array_add (argv, "-c"); + g_ptr_array_add (argv, default_runtime_dir); +#endif + g_ptr_array_add (argv, "-c"); + g_ptr_array_add (argv, pid_file); + + g_ptr_array_add (argv, "-k"); + g_ptr_array_add (argv, (char *)cmd); + g_ptr_array_add (argv, NULL); + + ok = g_spawn_sync (cwd, (char **)argv->pdata, NULL, 0, NULL, NULL, NULL, NULL, &status, NULL); if (ok) ok = (status == 0); + g_free (server_root); g_free (cwd); - g_free (conf); + g_free (pid_file); +#ifdef HAVE_APACHE_2_4 + g_free (default_runtime_dir); +#endif + g_ptr_array_free (argv, TRUE); return ok; } @@ -208,15 +227,18 @@ soup_test_session_new (GType type, ...) va_list args; const char *propname; SoupSession *session; + char *cafile; va_start (args, type); propname = va_arg (args, const char *); session = (SoupSession *)g_object_new_valist (type, propname, args); va_end (args); + cafile = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL); g_object_set (G_OBJECT (session), - SOUP_SESSION_SSL_CA_FILE, SRCDIR "/test-cert.pem", + SOUP_SESSION_SSL_CA_FILE, cafile, NULL); + g_free (cafile); if (http_debug_level && !logger) { SoupLoggerLogLevel level = MIN ((SoupLoggerLogLevel)http_debug_level, SOUP_LOGGER_LOG_BODY); @@ -246,14 +268,14 @@ test_server_new (gboolean in_own_thread, gboolean ssl) { SoupServer *server; GMainContext *async_context; - const char *ssl_cert_file, *ssl_key_file; + char *ssl_cert_file, *ssl_key_file; SoupAddress *addr; async_context = in_own_thread ? g_main_context_new () : NULL; if (ssl) { - ssl_cert_file = SRCDIR "/test-cert.pem"; - ssl_key_file = SRCDIR "/test-key.pem"; + ssl_cert_file = g_test_build_filename (G_TEST_DIST, "test-cert.pem", NULL); + ssl_key_file = g_test_build_filename (G_TEST_DIST, "test-key.pem", NULL); } else ssl_cert_file = ssl_key_file = NULL; @@ -268,6 +290,8 @@ test_server_new (gboolean in_own_thread, gboolean ssl) g_object_unref (addr); if (async_context) g_main_context_unref (async_context); + g_free (ssl_cert_file); + g_free (ssl_key_file); if (!server) { g_printerr ("Unable to create server\n"); @@ -522,17 +546,21 @@ soup_test_register_resources (void) { static gboolean registered = FALSE; GResource *resource; + char *path; GError *error = NULL; if (registered) return; - resource = g_resource_load ("soup-tests.gresource", &error); + path = g_test_build_filename (G_TEST_BUILT, "soup-tests.gresource", NULL); + resource = g_resource_load (path, &error); if (!resource) { g_printerr ("Could not load resource soup-tests.gresource: %s\n", error->message); exit (1); } + g_free (path); + g_resources_register (resource); g_resource_unref (resource); @@ -565,15 +593,17 @@ SoupBuffer * soup_test_get_index (void) { if (!index_buffer) { - char *contents; + char *path, *contents; gsize length; GError *error = NULL; - if (!g_file_get_contents (SRCDIR "/index.txt", &contents, &length, &error)) { + path = g_test_build_filename (G_TEST_DIST, "index.txt", NULL); + if (!g_file_get_contents (path, &contents, &length, &error)) { g_printerr ("Could not read index.txt: %s\n", error->message); exit (1); } + g_free (path); index_buffer = soup_buffer_new (SOUP_MEMORY_TAKE, contents, length); } diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c index a6f2d5f0..89e6e8de 100644 --- a/tests/xmlrpc-server-test.c +++ b/tests/xmlrpc-server-test.c @@ -280,7 +280,7 @@ do_xmlrpc_tests (gconstpointer data) GError *error = NULL; GIOChannel *child_out; - argv[0] = "./xmlrpc-test"; + argv[0] = (char *) g_test_get_filename (G_TEST_BUILT, "xmlrpc-test", NULL); argv[1] = "-S"; argv[2] = "-U"; argv[3] = soup_uri_to_string (uri, FALSE); -- cgit v1.2.1 From 3c4cea7bcc7dd44d61bf1d87a4ec8dce99a875cf Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 17 Feb 2014 10:05:36 -0500 Subject: SoupConnection: Explicitly set SoupAddress protocol. So GProxyResolver can distinguish between "http" and "https" requests, and choose the appropriate proxy settings. Previously the SoupAddress protocol was left unset, so soup_address_connectable_proxy_enumerate() assumed "http". https://bugzilla.gnome.org/show_bug.cgi?id=724316 --- libsoup/soup-connection.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index 2b5dc49e..fce589fa 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -532,8 +532,14 @@ soup_connection_connect_async (SoupConnection *conn, soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); - remote_addr = soup_address_new (priv->remote_uri->host, - priv->remote_uri->port); + /* Set the protocol to ensure correct proxy resolution. */ + remote_addr = + g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_NAME, priv->remote_uri->host, + SOUP_ADDRESS_PORT, priv->remote_uri->port, + SOUP_ADDRESS_PROTOCOL, priv->remote_uri->scheme, + NULL); + priv->socket = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb, @@ -583,7 +589,14 @@ soup_connection_connect_sync (SoupConnection *conn, soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); - remote_addr = soup_address_new (priv->remote_uri->host, priv->remote_uri->port); + /* Set the protocol to ensure correct proxy resolution. */ + remote_addr = + g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_NAME, priv->remote_uri->host, + SOUP_ADDRESS_PORT, priv->remote_uri->port, + SOUP_ADDRESS_PROTOCOL, priv->remote_uri->scheme, + NULL); + priv->socket = soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, SOUP_SOCKET_PROXY_RESOLVER, priv->proxy_resolver, -- cgit v1.2.1 From 7b14d465c87c07d9a9dc6319ee0bfc134e3e975b Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Sun, 8 Dec 2013 19:10:04 +0100 Subject: sniffing: Document the specification we are targeting --- libsoup/soup-content-sniffer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index fb2aa090..d2a0808f 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -3,6 +3,10 @@ * soup-content-sniffer.c * * Copyright (C) 2009 Gustavo Noronha Silva. + * + * This code implements the following specification: + * + * http://mimesniff.spec.whatwg.org/ as of 11 June 2013 */ #ifdef HAVE_CONFIG_H -- cgit v1.2.1 From 6510806d97713450625bbd648d3ce6cd953a4df9 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Sun, 8 Dec 2013 19:11:21 +0100 Subject: sniffing: Implement the check-apache-bug flag Run the text or binary algorithm when some specific text/plain Content-Types are provided, since older versions of apache would send that type for binary files. http://mimesniff.spec.whatwg.org/#dfnReturnLink-0 --- libsoup/soup-content-sniffer.c | 37 ++++++++++++++++++++++++++++--------- tests/resources/text.txt | 1 + tests/sniffing-test.c | 11 ++++++++++- tests/soup-tests.gresource.xml | 1 + 4 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 tests/resources/text.txt diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index d2a0808f..e16658ba 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -2,7 +2,7 @@ /* * soup-content-sniffer.c * - * Copyright (C) 2009 Gustavo Noronha Silva. + * Copyright (C) 2009, 2013 Gustavo Noronha Silva. * * This code implements the following specification: * @@ -297,7 +297,7 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer, return g_strdup ("text/plain"); } -/* HTML5: 2.7.3 Content-Type sniffing: text or binary */ +/* MIMESNIFF: 7.2 Sniffing a mislabeled binary resource */ static char* sniff_text_or_binary (SoupContentSniffer *sniffer, SoupBuffer *buffer) { @@ -306,15 +306,20 @@ sniff_text_or_binary (SoupContentSniffer *sniffer, SoupBuffer *buffer) gboolean looks_binary = FALSE; int i; - /* Detecting UTF-16BE, UTF-16LE, or UTF-8 BOMs means it's text/plain */ - if (resource_length >= 4) { + /* 2. Detecting UTF-16BE, UTF-16LE BOMs means it's text/plain */ + if (resource_length >= 2) { if ((resource[0] == 0xFE && resource[1] == 0xFF) || - (resource[0] == 0xFF && resource[1] == 0xFE) || - (resource[0] == 0xEF && resource[1] == 0xBB && resource[2] == 0xBF)) + (resource[0] == 0xFF && resource[1] == 0xFE)) return g_strdup ("text/plain"); } - /* Look to see if any of the first n bytes looks binary */ + /* 3. UTF-8 BOM. */ + if (resource_length >= 3) { + if (resource[0] == 0xEF && resource[1] == 0xBB && resource[2] == 0xBF) + return g_strdup ("text/plain"); + } + + /* 4. Look to see if any of the first n bytes looks binary */ for (i = 0; i < resource_length; i++) { if (byte_looks_binary[resource[i]]) { looks_binary = TRUE; @@ -325,6 +330,9 @@ sniff_text_or_binary (SoupContentSniffer *sniffer, SoupBuffer *buffer) if (!looks_binary) return g_strdup ("text/plain"); + /* 5. Execute 7.1 Identifying a resource with an unknown MIME type. + * TODO: sniff-scriptable needs to be unset. + */ return sniff_unknown (sniffer, buffer, TRUE); } @@ -472,14 +480,25 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, content_type = soup_message_headers_get_content_type (msg->response_headers, params); - /* These comparisons are done in an ASCII-case-insensitive - * manner because the spec requires it */ + /* MIMESNIFF: 7 Determining the sniffed MIME type of a resource. */ + + /* 1. Unknown/undefined supplied type respecting sniff-scritable. */ if ((content_type == NULL) || !g_ascii_strcasecmp (content_type, "unknown/unknown") || !g_ascii_strcasecmp (content_type, "application/unknown") || !g_ascii_strcasecmp (content_type, "*/*")) return sniff_unknown (sniffer, buffer, FALSE); + /* TODO: 2. no-sniff flag handling. */ + + /* 3. check-for-apache-bug */ + if ((content_type != NULL) && + (g_str_equal (content_type, "text/plain") || + g_str_equal (content_type, "text/plain; charset=ISO-8859-1") || + g_str_equal (content_type, "text/plain; charset=iso-8859-1") || + g_str_equal (content_type, "text/plain; charset=UTF-8"))) + return sniff_text_or_binary (sniffer, buffer); + if (g_str_has_suffix (content_type, "+xml") || !g_ascii_strcasecmp (content_type, "text/xml") || !g_ascii_strcasecmp (content_type, "application/xml")) diff --git a/tests/resources/text.txt b/tests/resources/text.txt new file mode 100644 index 00000000..ff7066f6 --- /dev/null +++ b/tests/resources/text.txt @@ -0,0 +1 @@ +This is just text. diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index 532e6ed5..b668f403 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -49,7 +49,7 @@ server_callback (SoupServer *server, SoupMessage *msg, "Content-Type", "text/plain"); } - if (g_str_has_prefix (path, "/text_or_binary/")) { + if (g_str_has_prefix (path, "/text_or_binary/") || g_str_has_prefix (path, "/apache_bug/")) { char *base_name = g_path_get_basename (path); response = soup_test_load_resource (base_name, &error); @@ -442,6 +442,15 @@ main (int argc, char **argv) GINT_TO_POINTER (TRUE), do_signals_tests); + /* Test the apache bug sniffing path */ + g_test_add_data_func ("/sniffing/apache-bug/binary", + "/apache_bug/text_binary.txt => application/octet-stream", + do_sniffing_test); + g_test_add_data_func ("/sniffing/apache-bug/text", + "/apache_bug/text.txt => text/plain", + do_sniffing_test); + + /* GIF is a 'safe' type */ g_test_add_data_func ("/sniffing/type/gif", "text_or_binary/home.gif => image/gif", do_sniffing_test); diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml index 9b580a35..2fe21ddc 100644 --- a/tests/soup-tests.gresource.xml +++ b/tests/soup-tests.gresource.xml @@ -12,6 +12,7 @@ resources/ps_binary.ps resources/rss20.xml resources/test.html + resources/text.txt resources/text_binary.txt -- cgit v1.2.1 From b766f11049d98f54980f64a6261914610e4e5116 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Sun, 8 Dec 2013 20:04:48 +0100 Subject: sniffing: Implement handling of the X-Content-Type-Options header --- libsoup/soup-content-sniffer.c | 6 +++++- tests/sniffing-test.c | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index e16658ba..6dec3e30 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -477,6 +477,7 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, SoupBuffer *buffer, GHashTable **params) { const char *content_type; + const char *x_content_type_options; content_type = soup_message_headers_get_content_type (msg->response_headers, params); @@ -489,7 +490,10 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, !g_ascii_strcasecmp (content_type, "*/*")) return sniff_unknown (sniffer, buffer, FALSE); - /* TODO: 2. no-sniff flag handling. */ + /* 2. If nosniff is specified in X-Content-Type-Options use the supplied MIME type. */ + x_content_type_options = soup_message_headers_get_one (msg->response_headers, "X-Content-Type-Options"); + if (!g_strcmp0 (x_content_type_options, "nosniff")) + return g_strdup (content_type); /* 3. check-for-apache-bug */ if ((content_type != NULL) && diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index b668f403..a8bc3ffc 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -49,6 +49,20 @@ server_callback (SoupServer *server, SoupMessage *msg, "Content-Type", "text/plain"); } + if (g_str_has_prefix (path, "/nosniff/")) { + char *base_name = g_path_get_basename (path); + + response = soup_test_load_resource (base_name, &error); + g_assert_no_error (error); + g_free (base_name); + + soup_message_headers_append (msg->response_headers, + "X-Content-Type-Options", "nosniff"); + + soup_message_headers_append (msg->response_headers, + "Content-Type", "no/sniffing-allowed"); + } + if (g_str_has_prefix (path, "/text_or_binary/") || g_str_has_prefix (path, "/apache_bug/")) { char *base_name = g_path_get_basename (path); @@ -450,6 +464,11 @@ main (int argc, char **argv) "/apache_bug/text.txt => text/plain", do_sniffing_test); + /* X-Content-Type-Options: nosniff */ + g_test_add_data_func ("/sniffing/nosniff", + "nosniff/home.gif => no/sniffing-allowed", + do_sniffing_test); + /* GIF is a 'safe' type */ g_test_add_data_func ("/sniffing/type/gif", "text_or_binary/home.gif => image/gif", -- cgit v1.2.1 From fa2b82c870277a4b6717c852ea0185442af93014 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Mon, 9 Dec 2013 11:54:29 +0100 Subject: sniffing: Adjust the general unknown MIME type algorithm This change adjusts the pattern matching table to the current form of the MIMESNIFF spec, adding a check for a tag-terminating byte and using the formally defined sniff-scriptable flag. --- libsoup/soup-content-sniffer.c | 240 ++++++++++++++++++++++++++++++--------- tests/resources/html_binary.html | 2 +- 2 files changed, 187 insertions(+), 55 deletions(-) diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index 6dec3e30..39210af6 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -77,12 +77,16 @@ soup_content_sniffer_init (SoupContentSniffer *content_sniffer) { } -/* This table is based on the HTML5 spec; - * See 2.7.4 Content-Type sniffing: unknown type +/* This table is based on the MIMESNIFF spec; + * See 7.1 Identifying a resource with an unknown MIME type */ typedef struct { /* @has_ws is TRUE if @pattern contains "generic" whitespace */ gboolean has_ws; + /* @has_tag_termination is TRUE if we should check for a tag-terminating + * byte (0x20 " " or 0x3E ">") after the pattern match. + */ + gboolean has_tag_termination; const guchar *mask; const guchar *pattern; guint pattern_length; @@ -90,111 +94,234 @@ typedef struct { gboolean scriptable; } SoupContentSnifferPattern; + +/* When has_ws is TRUE, spaces in the pattern will indicate where insignificant space + * is allowed. Those spaces are marked with \x00 on the mask. + */ static SoupContentSnifferPattern types_table[] = { - { FALSE, - (const guchar *)"\xFF\xFF\xDF\xDF\xDF\xDF\xDF\xDF\xDF\xFF\xDF\xDF\xDF\xDF", - (const guchar *)"\x3C\x21\x44\x4F\x43\x54\x59\x50\x45\x20\x48\x54\x4D\x4C", + /* Scriptable types. */ + + { TRUE, TRUE, + (const guchar *)"\x00\xFF\xFF\xDF\xDF\xDF\xDF\xDF\xDF\xDF\xFF\xDF\xDF\xDF\xDF", + (const guchar *)" data; int resource_length = MIN (512, buffer->length); @@ -232,9 +359,7 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer, for (i = 0; i < G_N_ELEMENTS (types_table); i++) { SoupContentSnifferPattern *type_row = &(types_table[i]); - /* The scriptable types should be skiped for the text - * or binary path, but considered for other paths */ - if (for_text_or_binary && type_row->scriptable) + if (!sniff_scriptable && type_row->scriptable) continue; if (type_row->has_ws) { @@ -267,8 +392,14 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer, if (skip_row) continue; - if (index_pattern > type_row->pattern_length) + if (index_pattern > type_row->pattern_length) { + if (type_row->has_tag_termination && + resource[index_stream] != '\x20' && + resource[index_stream] != '\x3E') + continue; + return g_strdup (type_row->sniffed_type); + } } else { int j; @@ -286,9 +417,6 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer, } } - if (for_text_or_binary) - return g_strdup ("application/octet-stream"); - for (i = 0; i < resource_length; i++) { if (byte_looks_binary[resource[i]]) return g_strdup ("application/octet-stream"); @@ -478,21 +606,25 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, { const char *content_type; const char *x_content_type_options; + gboolean no_sniff = FALSE; content_type = soup_message_headers_get_content_type (msg->response_headers, params); /* MIMESNIFF: 7 Determining the sniffed MIME type of a resource. */ - /* 1. Unknown/undefined supplied type respecting sniff-scritable. */ + x_content_type_options = soup_message_headers_get_one (msg->response_headers, "X-Content-Type-Options"); + if (!g_strcmp0 (x_content_type_options, "nosniff")) + no_sniff = TRUE; + + /* 1. Unknown/undefined supplied type with sniff-scritable = !nosniff. */ if ((content_type == NULL) || !g_ascii_strcasecmp (content_type, "unknown/unknown") || !g_ascii_strcasecmp (content_type, "application/unknown") || !g_ascii_strcasecmp (content_type, "*/*")) - return sniff_unknown (sniffer, buffer, FALSE); + return sniff_unknown (sniffer, buffer, !no_sniff); /* 2. If nosniff is specified in X-Content-Type-Options use the supplied MIME type. */ - x_content_type_options = soup_message_headers_get_one (msg->response_headers, "X-Content-Type-Options"); - if (!g_strcmp0 (x_content_type_options, "nosniff")) + if (no_sniff) return g_strdup (content_type); /* 3. check-for-apache-bug */ diff --git a/tests/resources/html_binary.html b/tests/resources/html_binary.html index 9200dd42..d443048c 100644 --- a/tests/resources/html_binary.html +++ b/tests/resources/html_binary.html @@ -1 +1 @@ - Date: Mon, 25 Nov 2013 01:22:19 +0200 Subject: sniffing: test that it allows leading whitespace in doctype headers https://bugzilla.gnome.org/show_bug.cgi?id=715126 --- tests/resources/leading_space.html | 12 ++++++++++++ tests/sniffing-test.c | 3 +++ tests/soup-tests.gresource.xml | 1 + 3 files changed, 16 insertions(+) create mode 100644 tests/resources/leading_space.html diff --git a/tests/resources/leading_space.html b/tests/resources/leading_space.html new file mode 100644 index 00000000..a640d653 --- /dev/null +++ b/tests/resources/leading_space.html @@ -0,0 +1,12 @@ + + + + + + + + + +

GNOME!

+ + diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index a8bc3ffc..2dc9fb2c 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -524,6 +524,9 @@ main (int argc, char **argv) g_test_add_data_func ("/sniffing/type/unknown-binary", "unknown/text_binary.txt => application/octet-stream", do_sniffing_test); + g_test_add_data_func ("/sniffing/type/unknown-leading-space", + "unknown/leading_space.html => text/html", + do_sniffing_test); /* Test the XML sniffing path */ g_test_add_data_func ("/sniffing/type/xml", diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml index 2fe21ddc..d24a04b0 100644 --- a/tests/soup-tests.gresource.xml +++ b/tests/soup-tests.gresource.xml @@ -5,6 +5,7 @@ resources/atom.xml resources/home.gif resources/html_binary.html + resources/leading_space.html resources/mbox resources/mbox.gz resources/mbox.raw -- cgit v1.2.1 From f5498190f9717d1366b4d57a7860899f87f0fc86 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Mon, 9 Dec 2013 15:04:16 +0100 Subject: sniffing: Add comment to the XML types bit --- libsoup/soup-content-sniffer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index 39210af6..154df841 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -635,6 +635,7 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, g_str_equal (content_type, "text/plain; charset=UTF-8"))) return sniff_text_or_binary (sniffer, buffer); + /* 4. XML types sent by the server are always used. */ if (g_str_has_suffix (content_type, "+xml") || !g_ascii_strcasecmp (content_type, "text/xml") || !g_ascii_strcasecmp (content_type, "application/xml")) -- cgit v1.2.1 From cd4f6a94f9275670091326a5aec8a07bce7f8d79 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Mon, 9 Dec 2013 16:20:02 +0100 Subject: sniffing: Bring feed vs HTML up-to-date with the MIMESNIFF spec * decide on that before doing the image sniffing to match the spec * use const char* and g_str_has_prefix for comparisons to make it more legible * deal with rdf:RDF tags --- libsoup/soup-content-sniffer.c | 117 ++++++++++++++++++++++++++++------------- tests/resources/feed.rdf | 32 +++++++++++ tests/sniffing-test.c | 13 +++-- tests/soup-tests.gresource.xml | 1 + 4 files changed, 120 insertions(+), 43 deletions(-) create mode 100644 tests/resources/feed.rdf diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index 154df841..5b768bb2 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -491,10 +491,26 @@ sniff_images (SoupContentSniffer *sniffer, SoupBuffer *buffer, return g_strdup (content_type); } +static gboolean +skip_insignificant_space (const char *resource, int *pos, int resource_length) +{ + while ((resource[*pos] == '\x09') || + (resource[*pos] == '\x20') || + (resource[*pos] == '\x0A') || + (resource[*pos] == '\x0D')) { + *pos = *pos + 1; + + if (*pos > resource_length) + return TRUE; + } + + return FALSE; +} + static char* sniff_feed_or_html (SoupContentSniffer *sniffer, SoupBuffer *buffer) { - const guchar *resource = (const guchar *)buffer->data; + const char *resource = (const char *)buffer->data; int resource_length = MIN (512, buffer->length); int pos = 0; @@ -509,19 +525,10 @@ sniff_feed_or_html (SoupContentSniffer *sniffer, SoupBuffer *buffer) if (pos > resource_length) goto text_html; - /* Skip insignificant white space */ - while ((resource[pos] == '\x09') || - (resource[pos] == '\x20') || - (resource[pos] == '\x0A') || - (resource[pos] == '\x0D')) { - pos++; - - if (pos > resource_length) - goto text_html; - } + if (skip_insignificant_space (resource, &pos, resource_length)) + goto text_html; - /* != < */ - if (resource[pos] != '\x3C') + if (resource[pos] != '<') return g_strdup ("text/html"); pos++; @@ -529,73 +536,106 @@ sniff_feed_or_html (SoupContentSniffer *sniffer, SoupBuffer *buffer) if ((pos + 2) > resource_length) goto text_html; - /* Skipping comments */ - if ((resource[pos] == '\x2D') || - (resource[pos+1] == '\x2D') || - (resource[pos+2] == '\x3E')) { + /* Skip comments. */ + if (g_str_has_prefix (resource + pos, "!--")) { pos = pos + 3; if ((pos + 2) > resource_length) goto text_html; - while ((resource[pos] != '\x2D') && - (resource[pos+1] != '\x2D') && - (resource[pos+2] != '\x3E')) { + while (!g_str_has_prefix (resource + pos, "-->")) { pos++; if ((pos + 2) > resource_length) goto text_html; } + pos = pos + 3; + goto look_for_tag; } if (pos > resource_length) goto text_html; - /* == ! */ - if (resource[pos] == '\x21') { + if (resource[pos] == '!') { do { pos++; if (pos > resource_length) goto text_html; - } while (resource[pos] != '\x3E'); + } while (resource[pos] != '>'); pos++; goto look_for_tag; - } else if (resource[pos] == '\x3F') { /* ? */ + } else if (resource[pos] == '?') { do { pos++; if ((pos + 1) > resource_length) goto text_html; - } while ((resource[pos] != '\x3F') && - (resource[pos+1] != '\x3E')); + } while (!g_str_has_prefix (resource + pos, "?>")); pos = pos + 2; goto look_for_tag; } - if ((pos + 2) > resource_length) + if ((pos + 3) > resource_length) goto text_html; - if ((resource[pos] == '\x72') && - (resource[pos+1] == '\x73') && - (resource[pos+2] == '\x73')) + if (g_str_has_prefix (resource + pos, "rss")) return g_strdup ("application/rss+xml"); - if ((pos + 3) > resource_length) + if ((pos + 4) > resource_length) goto text_html; - if ((resource[pos] == '\x66') && - (resource[pos+1] == '\x65') && - (resource[pos+2] == '\x65') && - (resource[pos+3] == '\x64')) + if (g_str_has_prefix (resource + pos, "feed")) return g_strdup ("application/atom+xml"); + if ((pos + 7) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "rdf:RDF")) { + pos = pos + 7; + + if (skip_insignificant_space (resource, &pos, resource_length)) + goto text_html; + + if ((pos + 32) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "xmlns=\"http://purl.org/rss/1.0/\"")) { + pos = pos + 32; + + if (skip_insignificant_space (resource, &pos, resource_length)) + goto text_html; + + if ((pos + 55) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"")) + return g_strdup ("application/rss+xml"); + } + + if ((pos + 55) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"")) { + pos = pos + 55; + + if (skip_insignificant_space (resource, &pos, resource_length)) + goto text_html; + + if ((pos + 32) > resource_length) + goto text_html; + + if (g_str_has_prefix (resource + pos, "xmlns=\"http://purl.org/rss/1.0/\"")) + return g_strdup ("application/rss+xml"); + } + } + text_html: return g_strdup ("text/html"); } @@ -641,6 +681,10 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, !g_ascii_strcasecmp (content_type, "application/xml")) return g_strdup (content_type); + /* 5. Distinguish feed from HTML. */ + if (!g_ascii_strcasecmp (content_type, "text/html")) + return sniff_feed_or_html (sniffer, buffer); + /* 2.7.5 Content-Type sniffing: image * The spec says: * @@ -659,9 +703,6 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, return sniff_text_or_binary (sniffer, buffer); } - if (!g_ascii_strcasecmp (content_type, "text/html")) - return sniff_feed_or_html (sniffer, buffer); - return g_strdup (content_type); } diff --git a/tests/resources/feed.rdf b/tests/resources/feed.rdf new file mode 100644 index 00000000..f3d9e276 --- /dev/null +++ b/tests/resources/feed.rdf @@ -0,0 +1,32 @@ + + + + + + + + XML.com + http://xml.com/pub + + XML.com features a rich mix of information and services + for the XML community. + + + + + + + + + + + + + + + diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index 2dc9fb2c..498df976 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -539,11 +539,6 @@ main (int argc, char **argv) "type/application_xml/home.gif => application/xml", do_sniffing_test); - /* Test the image sniffing path */ - g_test_add_data_func ("/sniffing/type/image", - "type/image_png/home.gif => image/gif", - do_sniffing_test); - /* Test the feed or html path */ g_test_add_data_func ("/sniffing/type/html/html", "type/text_html/test.html => text/html", @@ -554,6 +549,14 @@ main (int argc, char **argv) g_test_add_data_func ("/sniffing/type/html/atom", "type/text_html/atom.xml => application/atom+xml", do_sniffing_test); + g_test_add_data_func ("/sniffing/type/html/rdf", + "type/text_html/feed.rdf => application/rss+xml", + do_sniffing_test); + + /* Test the image sniffing path */ + g_test_add_data_func ("/sniffing/type/image", + "type/image_png/home.gif => image/gif", + do_sniffing_test); /* The spec tells us to only use the last Content-Type header */ g_test_add_data_func ("/sniffing/multiple-headers", diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml index d24a04b0..320cd63d 100644 --- a/tests/soup-tests.gresource.xml +++ b/tests/soup-tests.gresource.xml @@ -3,6 +3,7 @@ index.txt resources/atom.xml + resources/feed.rdf resources/home.gif resources/html_binary.html resources/leading_space.html -- cgit v1.2.1 From 26a65181db0b1fc3eb97748a5e3d9ceeecdc62e3 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Tue, 10 Dec 2013 17:17:40 +0100 Subject: sniffing: Bring image sniffing up-to-date with the MIMESNIFF spec --- libsoup/soup-content-sniffer.c | 212 ++++++++++++++++++++++------------------- tests/resources/home.jpg | Bin 0 -> 1074 bytes tests/resources/home.png | Bin 0 -> 313 bytes tests/resources/tux.webp | Bin 0 -> 17128 bytes tests/sniffing-test.c | 11 ++- tests/soup-tests.gresource.xml | 3 + 6 files changed, 127 insertions(+), 99 deletions(-) create mode 100644 tests/resources/home.jpg create mode 100644 tests/resources/home.png create mode 100644 tests/resources/tux.webp diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index 5b768bb2..5e0b2a70 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -77,6 +77,105 @@ soup_content_sniffer_init (SoupContentSniffer *content_sniffer) { } +typedef struct { + const guchar *mask; + const guchar *pattern; + guint pattern_length; + const char *sniffed_type; +} SoupContentSnifferMediaPattern; + +static char* +sniff_media (SoupContentSniffer *sniffer, + SoupBuffer *buffer, + SoupContentSnifferMediaPattern table[], + int table_length) +{ + const guchar *resource = (const guchar *)buffer->data; + int resource_length = MIN (512, buffer->length); + int i; + + for (i = 0; i < table_length; i++) { + SoupContentSnifferMediaPattern *type_row = &(table[i]); + int j; + + if (resource_length < type_row->pattern_length) + continue; + + for (j = 0; j < type_row->pattern_length; j++) { + if ((type_row->mask[j] & resource[j]) != type_row->pattern[j]) + break; + } + + /* This means our comparison above matched completely */ + if (j == type_row->pattern_length) + return g_strdup (type_row->sniffed_type); + } + + return NULL; +} + +/* This table is based on the MIMESNIFF spec; + * See 6.1 Matching an image type pattern + */ +static SoupContentSnifferMediaPattern image_types_table[] = { + + /* Windows icon signature. */ + { (const guchar *)"\xFF\xFF\xFF\xFF", + (const guchar *)"\x00\x00\x01\x00", + 4, + "image/x-icon" }, + + /* Windows cursor signature. */ + { (const guchar *)"\xFF\xFF\xFF\xFF", + (const guchar *)"\x00\x00\x02\x00", + 4, + "image/x-icon" }, + + /* BMP. */ + { (const guchar *)"\xFF\xFF", + (const guchar *)"BM", + 2, + "image/bmp" }, + + /* GIFs. */ + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"GIF87a", + 6, + "image/gif" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"GIF89a", + 6, + "image/gif" }, + + /* WEBP. */ + { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"RIFF\x00\x00\x00\x00WEBPVP", + 14, + "image/webp" }, + + /* PNG. */ + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"\x89PNG\x0D\x0A\x1A\x0A", + 8, + "image/png" }, + + /* JPEG. */ + { (const guchar *)"\xFF\xFF\xFF", + (const guchar *)"\xFF\xD8\xFF", + 3, + "image/jpeg" }, +}; + +static char* +sniff_images (SoupContentSniffer *sniffer, SoupBuffer *buffer) +{ + return sniff_media (sniffer, + buffer, + image_types_table, + G_N_ELEMENTS (image_types_table)); +} + /* This table is based on the MIMESNIFF spec; * See 7.1 Identifying a resource with an unknown MIME type */ @@ -262,66 +361,6 @@ static SoupContentSnifferPattern types_table[] = { 4, "text/plain", FALSE }, - - /* Images. */ - - { FALSE, FALSE, /* Windows icon signature. */ - (const guchar *)"\xFF\xFF\xFF\xFF", - (const guchar *)"\x00\x00\x01\x00", - 4, - "image/x-icon", - FALSE }, - - { FALSE, FALSE, /* Windows cursor signature. */ - (const guchar *)"\xFF\xFF\xFF\xFF", - (const guchar *)"\x00\x00\x02\x00", - 4, - "image/x-icon", - FALSE }, - - { FALSE, FALSE, /* BMP. */ - (const guchar *)"\xFF\xFF", - (const guchar *)"BM", - 2, - "image/bmp", - FALSE }, - - { FALSE, FALSE, /* GIF. */ - (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF", - (const guchar *)"GIF87a", - 6, - "image/gif", - FALSE }, - - { FALSE, FALSE, /* GIF. */ - (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF", - (const guchar *)"GIF89a", - 6, - "image/gif", - FALSE }, - - { FALSE, FALSE, /* WEBP. */ - (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF", - (const guchar *)"RIFF\x00\x00\x00\x00WEBPVP", - 14, - "image/webp", - FALSE }, - - { FALSE, FALSE, /* PNG. */ - (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", - (const guchar *)"\x89PNG\x0D\x0A\x1A\x0A", - 8, - "image/png", - FALSE }, - - { FALSE, FALSE, /* JPEG. */ - (const guchar *)"\xFF\xFF\xFF", - (const guchar *)"\xFF\xD8\xFF", - 3, - "image/jpeg", - FALSE }, - - /* TODO: audio/video, archive type. */ }; /* Whether a given byte looks like it might be part of binary content. @@ -352,6 +391,7 @@ static char* sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer, gboolean sniff_scriptable) { + char *sniffed_type = NULL; const guchar *resource = (const guchar *)buffer->data; int resource_length = MIN (512, buffer->length); int i; @@ -417,6 +457,12 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer, } } + sniffed_type = sniff_images (sniffer, buffer); + + if (sniffed_type != NULL) + return sniffed_type; + + for (i = 0; i < resource_length; i++) { if (byte_looks_binary[resource[i]]) return g_strdup ("application/octet-stream"); @@ -464,33 +510,6 @@ sniff_text_or_binary (SoupContentSniffer *sniffer, SoupBuffer *buffer) return sniff_unknown (sniffer, buffer, TRUE); } -static char* -sniff_images (SoupContentSniffer *sniffer, SoupBuffer *buffer, - const char *content_type) -{ - const guchar *resource = (const guchar *)buffer->data; - int resource_length = MIN (512, buffer->length); - int i; - - for (i = 0; i < G_N_ELEMENTS (types_table); i++) { - SoupContentSnifferPattern *type_row = &(types_table[i]); - - if (resource_length < type_row->pattern_length) - continue; - - if (!g_str_has_prefix (type_row->sniffed_type, "image/")) - continue; - - /* All of the image types use all-\xFF for the mask, - * so we can just memcmp. - */ - if (memcmp (type_row->pattern, resource, type_row->pattern_length) == 0) - return g_strdup (type_row->sniffed_type); - } - - return g_strdup (content_type); -} - static gboolean skip_insignificant_space (const char *resource, int *pos, int resource_length) { @@ -646,6 +665,7 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, { const char *content_type; const char *x_content_type_options; + char *sniffed_type = NULL; gboolean no_sniff = FALSE; content_type = soup_message_headers_get_content_type (msg->response_headers, params); @@ -685,18 +705,14 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, if (!g_ascii_strcasecmp (content_type, "text/html")) return sniff_feed_or_html (sniffer, buffer); - /* 2.7.5 Content-Type sniffing: image - * The spec says: - * - * If the resource's official type is "image/svg+xml", then - * the sniffed type of the resource is its official type (an - * XML type) - * - * The XML case is handled by the if above; if you refactor - * this code, keep this in mind. + /* 6. Image types. */ - if (!g_ascii_strncasecmp (content_type, "image/", 6)) - return sniff_images (sniffer, buffer, content_type); + if (!g_ascii_strncasecmp (content_type, "image/", 6)) { + sniffed_type = sniff_images (sniffer, buffer); + if (sniffed_type != NULL) + return sniffed_type; + return g_strdup (content_type); + } /* If we got text/plain, use text_or_binary */ if (g_str_equal (content_type, "text/plain")) { diff --git a/tests/resources/home.jpg b/tests/resources/home.jpg new file mode 100644 index 00000000..ac1f3bbc Binary files /dev/null and b/tests/resources/home.jpg differ diff --git a/tests/resources/home.png b/tests/resources/home.png new file mode 100644 index 00000000..0bb82bac Binary files /dev/null and b/tests/resources/home.png differ diff --git a/tests/resources/tux.webp b/tests/resources/tux.webp new file mode 100644 index 00000000..8764f066 Binary files /dev/null and b/tests/resources/tux.webp differ diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index 498df976..868b7c5f 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -554,9 +554,18 @@ main (int argc, char **argv) do_sniffing_test); /* Test the image sniffing path */ - g_test_add_data_func ("/sniffing/type/image", + g_test_add_data_func ("/sniffing/type/image/gif", "type/image_png/home.gif => image/gif", do_sniffing_test); + g_test_add_data_func ("/sniffing/type/image/png", + "type/image_gif/home.png => image/png", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/image/jpeg", + "type/image_png/home.jpg => image/jpeg", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/image/webp", + "type/image_png/tux.webp => image/webp", + do_sniffing_test); /* The spec tells us to only use the last Content-Type header */ g_test_add_data_func ("/sniffing/multiple-headers", diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml index 320cd63d..444ed588 100644 --- a/tests/soup-tests.gresource.xml +++ b/tests/soup-tests.gresource.xml @@ -5,6 +5,8 @@ resources/atom.xml resources/feed.rdf resources/home.gif + resources/home.jpg + resources/home.png resources/html_binary.html resources/leading_space.html resources/mbox @@ -16,5 +18,6 @@ resources/test.html resources/text.txt resources/text_binary.txt + resources/tux.webp -- cgit v1.2.1 From 9530c7b58197d7d45e21aa60a9986735ccf515b1 Mon Sep 17 00:00:00 2001 From: Gustavo Noronha Silva Date: Tue, 10 Dec 2013 19:45:55 +0100 Subject: sniffing: Add audio/video sniffing --- libsoup/soup-content-sniffer.c | 111 +++++++++++++++++++++++++++++++++++++++++ tests/resources/test.aiff | Bin 0 -> 384088 bytes tests/resources/test.mp4 | Bin 0 -> 192844 bytes tests/resources/test.ogg | Bin 0 -> 16994 bytes tests/resources/test.wav | Bin 0 -> 384080 bytes tests/resources/test.webm | Bin 0 -> 149879 bytes tests/sniffing-test.c | 19 +++++++ tests/soup-tests.gresource.xml | 5 ++ 8 files changed, 135 insertions(+) create mode 100644 tests/resources/test.aiff create mode 100644 tests/resources/test.mp4 create mode 100644 tests/resources/test.ogg create mode 100644 tests/resources/test.wav create mode 100644 tests/resources/test.webm diff --git a/libsoup/soup-content-sniffer.c b/libsoup/soup-content-sniffer.c index 5e0b2a70..5659af9a 100644 --- a/libsoup/soup-content-sniffer.c +++ b/libsoup/soup-content-sniffer.c @@ -176,6 +176,103 @@ sniff_images (SoupContentSniffer *sniffer, SoupBuffer *buffer) G_N_ELEMENTS (image_types_table)); } +/* This table is based on the MIMESNIFF spec; + * See 6.2 Matching an audio or video type pattern + */ +static SoupContentSnifferMediaPattern audio_video_types_table[] = { + { (const guchar *)"\xFF\xFF\xFF\xFF", + (const guchar *)"\x1A\x45\xDF\xA3", + 4, + "video/webm" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF", + (const guchar *)".snd", + 4, + "audio/basic" }, + + + { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", + (const guchar *)"FORM\0\0\0\0AIFF", + 12, + "audio/aiff" }, + + { (const guchar *)"\xFF\xFF\xFF", + (const guchar *)"ID3", + 3, + "audio/mpeg" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"OggS\0", + 5, + "application/ogg" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", + (const guchar *)"MThd\x00\x00\x00\x06", + 8, + "audio/midi" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", + (const guchar *)"RIFF\x00\x00\x00\x00AVI ", + 12, + "video/avi" }, + + { (const guchar *)"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF", + (const guchar *)"RIFF\x00\x00\x00\x00WAVE", + 12, + "audio/wave" }, +}; + +static gboolean +sniff_mp4 (SoupContentSniffer *sniffer, SoupBuffer *buffer) +{ + const char *resource = (const char *)buffer->data; + int resource_length = MIN (512, buffer->length); + guint32 box_size = *((guint32*)resource); + int i; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + box_size = ((box_size >> 24) | + ((box_size << 8) & 0x00FF0000) | + ((box_size >> 8) & 0x0000FF00) | + (box_size << 24)); +#endif + + if (resource_length < 12 || resource_length < box_size || box_size % 4 != 0) + return FALSE; + + if (!g_str_has_prefix (resource + 4, "ftyp")) + return FALSE; + + if (!g_str_has_prefix (resource + 8, "mp4")) + return FALSE; + + for (i = 16; i < box_size && i < resource_length; i = i + 4) { + if (g_str_has_prefix (resource + i, "mp4")) + return TRUE; + } + + return FALSE; +} + +static char* +sniff_audio_video (SoupContentSniffer *sniffer, SoupBuffer *buffer) +{ + char *sniffed_type; + + sniffed_type = sniff_media (sniffer, + buffer, + audio_video_types_table, + G_N_ELEMENTS (audio_video_types_table)); + + if (sniffed_type != NULL) + return sniffed_type; + + if (sniff_mp4 (sniffer, buffer)) + return g_strdup ("video/mp4"); + + return NULL; +} + /* This table is based on the MIMESNIFF spec; * See 7.1 Identifying a resource with an unknown MIME type */ @@ -462,6 +559,10 @@ sniff_unknown (SoupContentSniffer *sniffer, SoupBuffer *buffer, if (sniffed_type != NULL) return sniffed_type; + sniffed_type = sniff_audio_video (sniffer, buffer); + + if (sniffed_type != NULL) + return sniffed_type; for (i = 0; i < resource_length; i++) { if (byte_looks_binary[resource[i]]) @@ -714,6 +815,16 @@ soup_content_sniffer_real_sniff (SoupContentSniffer *sniffer, SoupMessage *msg, return g_strdup (content_type); } + /* 7. Audio and video types. */ + if (!g_ascii_strncasecmp (content_type, "audio/", 6) || + !g_ascii_strncasecmp (content_type, "video/", 6) || + !g_ascii_strcasecmp (content_type, "application/ogg")) { + sniffed_type = sniff_audio_video (sniffer, buffer); + if (sniffed_type != NULL) + return sniffed_type; + return g_strdup (content_type); + } + /* If we got text/plain, use text_or_binary */ if (g_str_equal (content_type, "text/plain")) { return sniff_text_or_binary (sniffer, buffer); diff --git a/tests/resources/test.aiff b/tests/resources/test.aiff new file mode 100644 index 00000000..9a1ecbb2 Binary files /dev/null and b/tests/resources/test.aiff differ diff --git a/tests/resources/test.mp4 b/tests/resources/test.mp4 new file mode 100644 index 00000000..d278c8ad Binary files /dev/null and b/tests/resources/test.mp4 differ diff --git a/tests/resources/test.ogg b/tests/resources/test.ogg new file mode 100644 index 00000000..e8f49ac3 Binary files /dev/null and b/tests/resources/test.ogg differ diff --git a/tests/resources/test.wav b/tests/resources/test.wav new file mode 100644 index 00000000..11660b29 Binary files /dev/null and b/tests/resources/test.wav differ diff --git a/tests/resources/test.webm b/tests/resources/test.webm new file mode 100644 index 00000000..7e53d0b4 Binary files /dev/null and b/tests/resources/test.webm differ diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index 868b7c5f..5b0e6ee7 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -567,6 +567,25 @@ main (int argc, char **argv) "type/image_png/tux.webp => image/webp", do_sniffing_test); + /* Test audio and video sniffing path */ + g_test_add_data_func ("/sniffing/type/audio/wav", + "type/audio_mpeg/test.wav => audio/wave", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/audio/aiff", + "type/audio_mpeg/test.aiff => audio/aiff", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/audio/ogg", + "type/audio_mpeg/test.ogg => application/ogg", + do_sniffing_test); + g_test_add_data_func ("/sniffing/type/video/webm", + "type/video_theora/test.webm => video/webm", + do_sniffing_test); + + /* Test the MP4 sniffing path */ + g_test_add_data_func ("/sniffing/type/video/mp4", + "unknown/test.mp4 => video/mp4", + do_sniffing_test); + /* The spec tells us to only use the last Content-Type header */ g_test_add_data_func ("/sniffing/multiple-headers", "multiple_headers/home.gif => image/gif", diff --git a/tests/soup-tests.gresource.xml b/tests/soup-tests.gresource.xml index 444ed588..b24a7297 100644 --- a/tests/soup-tests.gresource.xml +++ b/tests/soup-tests.gresource.xml @@ -15,7 +15,12 @@ resources/mbox.zlib resources/ps_binary.ps resources/rss20.xml + resources/test.aiff resources/test.html + resources/test.mp4 + resources/test.ogg + resources/test.wav + resources/test.webm resources/text.txt resources/text_binary.txt resources/tux.webp -- cgit v1.2.1 From 2b0de6b7de7537c7d36ab33a7e5cf0e274ea3e23 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 17 Feb 2014 22:29:44 -0500 Subject: tests: skip individual tests rather than whole test programs Use g_skip_test() to skip individual tests rather than just returning status 77 from the test program as a whole. In several cases, we still end up skipping more than necessary, due to test cases that need to be split up more. Remove the "MISSING_REGRESSION_TESTS_PACKAGES" functionality, since the skipped tests are now pointed out explicitly. --- configure.ac | 29 ---------------------------- tests/Makefile.am | 5 ----- tests/auth-test.c | 28 +++++++++++++++------------ tests/connection-test.c | 12 ++++-------- tests/forms-test.c | 27 ++++++++++++++------------ tests/ntlm-test.c | 14 ++++++++++---- tests/proxy-test.c | 22 ++++++++------------- tests/pull-api.c | 24 +++++++++++------------ tests/range-test.c | 14 ++------------ tests/server-auth-test.c | 17 +++++----------- tests/ssl-test.c | 27 ++++++++++++++++---------- tests/test-utils.h | 18 +++++++++++++++++ tests/timeout-test.c | 13 ++++--------- tests/xmlrpc-server-test.c | 12 ------------ tests/xmlrpc-test.c | 48 +++++++++++++++++++++++++++++++--------------- 15 files changed, 144 insertions(+), 166 deletions(-) diff --git a/configure.ac b/configure.ac index defe54b8..e216c99f 100644 --- a/configure.ac +++ b/configure.ac @@ -184,11 +184,6 @@ dnl ****************************** dnl *** Stuff for regression tests dnl ****************************** AC_MSG_NOTICE([checking for programs needed for regression tests]) -MISSING_REGRESSION_TEST_PACKAGES="" - -if test "$have_glib_networking" = "no"; then - MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES glib-networking" -fi AC_ARG_WITH(apache-httpd, AS_HELP_STRING([--with-apache-httpd], [Path to apache httpd (for tests)]), @@ -256,16 +251,8 @@ if test "$APACHE_HTTPD" != "no" -a -n "$APACHE_MODULE_DIR" -a -n "$APACHE_SSL_MO AC_DEFINE(HAVE_APACHE_2_4, 1, [Apache is 2.4.x]) fi have_apache=1 - if test -z "$APACHE_PHP_MODULE_DIR"; then - MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES mod_php5" - fi else have_apache=0 - if test "$APACHE_HTTPD" = "no" -o -z "$APACHE_MODULE_DIR"; then - MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES apache" - else - MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES mod_ssl" - fi fi AM_CONDITIONAL(HAVE_APACHE, test "$have_apache" = 1) AM_CONDITIONAL(HAVE_APACHE_2_2, test "$apache_version" = 2.2) @@ -281,7 +268,6 @@ if test "$have_apache" = 1; then else have_php=no IF_HAVE_PHP="\#" - MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES php5" fi AC_MSG_RESULT($have_php) AC_SUBST(IF_HAVE_PHP) @@ -290,7 +276,6 @@ if test "$have_apache" = 1; then AC_MSG_CHECKING([for php-xmlrpc]) if $PHP --rf xmlrpc_server_create | grep -q "does not exist"; then have_php_xmlrpc=no - MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES php-xmlrpc" else have_php_xmlrpc=yes AC_DEFINE(HAVE_PHP_XMLRPC, 1, [Have php-xmlrpc]) @@ -302,13 +287,8 @@ fi AC_PATH_PROG(CURL, curl, no) if test "$CURL" != no; then AC_DEFINE(HAVE_CURL, 1, [Whether or not curl can be used for tests]) -else - MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES curl" fi -AC_SUBST(MISSING_REGRESSION_TEST_PACKAGES) -AM_CONDITIONAL(MISSING_REGRESSION_TEST_PACKAGES, test -n "$MISSING_REGRESSION_TEST_PACKAGES") - dnl ********************************************************** dnl *** path of NTLM single-sign-on helper ntlm_auth dnl ********************************************************** @@ -322,8 +302,6 @@ if test "$ntlm_auth" != "no"; then dnl --with-ntlm-auth (without path) used, use default path ntlm_auth="/usr/bin/ntlm_auth" fi -else - MISSING_REGRESSION_TEST_PACKAGES="$MISSING_REGRESSION_TEST_PACKAGES ntlm_auth" fi AC_SUBST(ntlm_auth) AC_DEFINE_UNQUOTED(NTLM_AUTH, "$ntlm_auth", [Samba's 'winbind' daemon helper 'ntlm_auth' which can be used for NTLM single-sign-on]) @@ -367,10 +345,3 @@ AC_CONFIG_FILES([ libsoup/soup-version.h ]) AC_OUTPUT - -if test -n "$MISSING_REGRESSION_TEST_PACKAGES"; then - echo "" - echo Some regression tests will not be run due to missing packages: - echo $MISSING_REGRESSION_TEST_PACKAGES - echo "" -fi diff --git a/tests/Makefile.am b/tests/Makefile.am index d9ede804..a8b9d019 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -112,11 +112,6 @@ check: start-httpd check-local: check-TESTS @$(MAKE) kill-httpd -if MISSING_REGRESSION_TEST_PACKAGES - @echo "" - @echo "NOTE: some tests were not run due to missing packages:" $(MISSING_REGRESSION_TEST_PACKAGES) - @echo "" -endif .PHONY: start-httpd kill-httpd diff --git a/tests/auth-test.c b/tests/auth-test.c index c1825205..35b05cc7 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -2,8 +2,6 @@ #include "test-utils.h" -#ifdef HAVE_APACHE - static const char *base_uri; static GMainLoop *loop; @@ -294,6 +292,8 @@ do_pipelined_auth_test (void) char *uri; int i; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "Testing pipelined auth (bug 271540):\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -445,6 +445,8 @@ do_digest_expiration_test (void) SoupSession *session; char *uri; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nTesting digest nonce expiration:\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -549,6 +551,8 @@ do_async_auth_test (void) int remaining; gboolean been_there; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nTesting async auth:\n"); loop = g_main_loop_new (NULL, TRUE); @@ -820,6 +824,8 @@ do_select_auth_test (void) SoupAuthDomain *basic_auth_domain, *digest_auth_domain; SoupURI *uri; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nTesting selection among multiple auths:\n"); /* It doesn't seem to be possible to configure Apache to serve @@ -976,6 +982,8 @@ do_auth_close_test (void) SoupURI *uri; AuthCloseData acd; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nTesting auth when server times out connection:\n"); server = soup_test_server_new (FALSE); @@ -1033,6 +1041,8 @@ do_infinite_auth_test (void) char *uri; int timeout; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nTesting broken infinite-loop auth:\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -1089,6 +1099,8 @@ do_disappearing_auth_test (void) SoupSession *session; int counter; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nTesting auth when server does not repeat challenge on failure:\n"); server = soup_test_server_new (FALSE); @@ -1164,6 +1176,8 @@ do_batch_tests (gconstpointer data) guint signal; int i; + SOUP_TEST_SKIP_IF_NO_APACHE; + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); base = soup_uri_new (base_uri); @@ -1246,13 +1260,3 @@ main (int argc, char **argv) test_cleanup (); return ret; } - -#else /* HAVE_APACHE */ - -int -main (int argc, char **argv) -{ - return 77; /* SKIP */ -} - -#endif diff --git a/tests/connection-test.c b/tests/connection-test.c index 3dd2cae5..f092944b 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -621,8 +621,6 @@ do_non_idempotent_connection_test (void) soup_test_session_abort_unref (session); } -#ifdef HAVE_APACHE - #define HTTP_SERVER "http://127.0.0.1:47524" #define HTTPS_SERVER "https://127.0.0.1:47525" #define HTTP_PROXY "http://127.0.0.1:47526" @@ -724,6 +722,8 @@ do_connection_state_test (void) { SoupSession *session; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nConnection states\n"); debug_printf (1, " Async session\n"); @@ -832,6 +832,8 @@ do_connection_event_test (void) { SoupSession *session; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nConnection events\n"); debug_printf (1, " Async session\n"); @@ -845,17 +847,13 @@ do_connection_event_test (void) soup_test_session_abort_unref (session); } -#endif - int main (int argc, char **argv) { int ret; test_init (argc, argv, NULL); -#ifdef HAVE_APACHE apache_init (); -#endif server = soup_test_server_new (TRUE); soup_server_add_handler (server, NULL, server_callback, "http", NULL); @@ -867,10 +865,8 @@ main (int argc, char **argv) g_test_add_func ("/connection/max-conns", do_max_conns_test); g_test_add_func ("/connection/non-persistent", do_non_persistent_connection_test); g_test_add_func ("/connection/non-idempotent", do_non_idempotent_connection_test); -#ifdef HAVE_APACHE g_test_add_func ("/connection/state", do_connection_state_test); g_test_add_func ("/connection/event", do_connection_event_test); -#endif ret = g_test_run (); diff --git a/tests/forms-test.c b/tests/forms-test.c index da71569b..6e6334f4 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -5,8 +5,6 @@ #include "test-utils.h" -#ifdef HAVE_CURL - static struct { const char *title, *name; const char *result; @@ -92,6 +90,11 @@ do_hello_tests (gconstpointer uri) { int n; +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + debug_printf (1, "Hello tests (GET, application/x-www-form-urlencoded)\n"); for (n = 0; n < G_N_ELEMENTS (tests); n++) { do_hello_test (n, FALSE, uri); @@ -179,6 +182,11 @@ do_md5_tests (gconstpointer uri) gsize length; GError *error = NULL; +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + debug_printf (1, "\nMD5 tests (POST, multipart/form-data)\n"); if (!g_file_get_contents (MD5_TEST_FILE, &contents, &length, &error)) { @@ -204,6 +212,11 @@ do_form_decode_test (void) const gchar *value; gchar *tmp; +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + debug_printf (1, "\nDecode tests\n"); /* Test that the code handles multiple values with the same key. */ @@ -432,13 +445,3 @@ main (int argc, char **argv) test_cleanup (); return ret; } - -#else /* HAVE_CURL */ - -int -main (int argc, char **argv) -{ - return 77; /* SKIP */ -} - -#endif diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index 0fa4b478..e05213af 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -456,12 +456,16 @@ do_builtin_ntlm_test (gconstpointer data) do_ntlm_tests (uri, TRUE); } -#ifdef USE_NTLM_AUTH static void do_winbind_ntlm_test (gconstpointer data) { SoupURI *uri = (SoupURI *)data; +#ifndef USE_NTLM_AUTH + g_test_skip ("/usr/bin/ntlm_auth is not available"); + return; +#endif + /* Samba winbind /usr/bin/ntlm_auth helper support (via a * helper program that emulates its interface). */ @@ -477,6 +481,11 @@ do_fallback_ntlm_test (gconstpointer data) { SoupURI *uri = (SoupURI *)data; +#ifndef USE_NTLM_AUTH + g_test_skip ("/usr/bin/ntlm_auth is not available"); + return; +#endif + /* Support for when ntlm_auth is installed, but the user has * no cached credentials (and thus we have to fall back to * libsoup's built-in NTLM support). @@ -487,7 +496,6 @@ do_fallback_ntlm_test (gconstpointer data) g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); do_ntlm_tests (uri, TRUE); } -#endif static void retry_test_authenticate (SoupSession *session, SoupMessage *msg, @@ -582,10 +590,8 @@ main (int argc, char **argv) soup_uri_set_port (uri, soup_server_get_port (server)); g_test_add_data_func ("/ntlm/builtin", uri, do_builtin_ntlm_test); -#ifdef USE_NTLM_AUTH g_test_add_data_func ("/ntlm/winbind", uri, do_winbind_ntlm_test); g_test_add_data_func ("/ntlm/fallback", uri, do_fallback_ntlm_test); -#endif g_test_add_data_func ("/ntlm/retry", uri, do_retrying_test); ret = g_test_run (); diff --git a/tests/proxy-test.c b/tests/proxy-test.c index ceb2ff37..423a5598 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -2,8 +2,6 @@ #include "test-utils.h" -#ifdef HAVE_APACHE - typedef struct { const char *explanation; const char *url; @@ -231,6 +229,8 @@ do_async_proxy_test (gconstpointer data) { SoupProxyTest *test = (SoupProxyTest *)data; + SOUP_TEST_SKIP_IF_NO_APACHE; + do_proxy_test (test, FALSE); } @@ -239,6 +239,8 @@ do_sync_proxy_test (gconstpointer data) { SoupProxyTest *test = (SoupProxyTest *)data; + SOUP_TEST_SKIP_IF_NO_APACHE; + do_proxy_test (test, TRUE); } @@ -260,6 +262,8 @@ do_proxy_fragment_test (gconstpointer data) SoupURI *proxy_uri, *req_uri; SoupMessage *msg; + SOUP_TEST_SKIP_IF_NO_APACHE; + debug_printf (1, "\nTesting request with fragment via proxy\n"); proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]); @@ -286,8 +290,8 @@ do_proxy_redirect_test (void) SoupURI *proxy_uri, *req_uri, *new_uri; SoupMessage *msg; - if (!tls_available) - return; + SOUP_TEST_SKIP_IF_NO_APACHE; + SOUP_TEST_SKIP_IF_NO_TLS; debug_printf (1, "\nTesting redirection through proxy\n"); @@ -358,13 +362,3 @@ main (int argc, char **argv) test_cleanup (); return ret; } - -#else /* HAVE_APACHE */ - -int -main (int argc, char **argv) -{ - return 77; /* SKIP */ -} - -#endif diff --git a/tests/pull-api.c b/tests/pull-api.c index 8060646b..2915b9e4 100644 --- a/tests/pull-api.c +++ b/tests/pull-api.c @@ -2,8 +2,6 @@ #include "test-utils.h" -#ifdef HAVE_APACHE - static SoupBuffer *correct_response; static void @@ -14,6 +12,7 @@ authenticate (SoupSession *session, SoupMessage *msg, soup_auth_authenticate (auth, "user2", "realm2"); } +#if HAVE_APACHE static void get_correct_response (const char *uri) { @@ -34,6 +33,7 @@ get_correct_response (const char *uri) g_object_unref (msg); soup_test_session_abort_unref (session); } +#endif /* Pull API version 1: fully-async. More like a "poke" API. Rather * than having SoupMessage emit "got_chunk" signals whenever it wants, @@ -234,6 +234,8 @@ do_fast_async_test (gconstpointer data) const char *base_uri = data; SoupSession *session; + SOUP_TEST_SKIP_IF_NO_APACHE; + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), NULL); @@ -252,6 +254,8 @@ do_slow_async_test (gconstpointer data) const char *base_uri = data; SoupSession *session; + SOUP_TEST_SKIP_IF_NO_APACHE; + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), NULL); @@ -485,6 +489,8 @@ do_sync_async_test (gconstpointer data) const char *base_uri = data; SoupSession *session; + SOUP_TEST_SKIP_IF_NO_APACHE; + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), NULL); @@ -508,7 +514,9 @@ main (int argc, char **argv) apache_init (); base_uri = "http://127.0.0.1:47524/"; +#if HAVE_APACHE get_correct_response (base_uri); +#endif g_test_add_data_func ("/pull-api/async/fast", base_uri, do_fast_async_test); g_test_add_data_func ("/pull-api/async/slow", base_uri, do_slow_async_test); @@ -516,18 +524,10 @@ main (int argc, char **argv) ret = g_test_run (); +#if HAVE_APACHE soup_buffer_free (correct_response); +#endif test_cleanup (); return ret; } - -#else /* HAVE_APACHE */ - -int -main (int argc, char **argv) -{ - return 77; /* SKIP */ -} - -#endif diff --git a/tests/range-test.c b/tests/range-test.c index 4d008d46..c23ba462 100644 --- a/tests/range-test.c +++ b/tests/range-test.c @@ -2,8 +2,6 @@ #include "test-utils.h" -#ifdef HAVE_APACHE - SoupBuffer *full_response; int total_length; char *test_response; @@ -332,6 +330,8 @@ do_apache_range_test (void) { SoupSession *session; + SOUP_TEST_SKIP_IF_NO_APACHE; + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); #if HAVE_APACHE_2_2 @@ -397,13 +397,3 @@ main (int argc, char **argv) test_cleanup (); return ret; } - -#else /* HAVE_APACHE */ - -int -main (int argc, char **argv) -{ - return 77; /* SKIP */ -} - -#endif diff --git a/tests/server-auth-test.c b/tests/server-auth-test.c index 77a5dba1..b5580c82 100644 --- a/tests/server-auth-test.c +++ b/tests/server-auth-test.c @@ -5,8 +5,6 @@ #include "test-utils.h" -#ifdef HAVE_CURL - static struct { gboolean client_sent_basic, client_sent_digest; gboolean server_requested_basic, server_requested_digest; @@ -106,6 +104,11 @@ do_auth_tests (gconstpointer data) gboolean use_basic, use_digest, good_user, good_password; gboolean preemptive_basic, good_auth; +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + for (i = 0; i < 16; i++) { use_basic = (i & 1) == 1; use_digest = (i & 2) == 2; @@ -344,13 +347,3 @@ main (int argc, char **argv) test_cleanup (); return ret; } - -#else /* HAVE_CURL */ - -int -main (int argc, char **argv) -{ - return 77; /* SKIP */ -} - -#endif diff --git a/tests/ssl-test.c b/tests/ssl-test.c index 753a980c..3eb61af1 100644 --- a/tests/ssl-test.c +++ b/tests/ssl-test.c @@ -28,6 +28,8 @@ do_async_properties_tests (gconstpointer uri) { SoupSession *session; + SOUP_TEST_SKIP_IF_NO_TLS; + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_object_set (G_OBJECT (session), SOUP_SESSION_SSL_CA_FILE, "/dev/null", @@ -42,6 +44,8 @@ do_sync_properties_tests (gconstpointer uri) { SoupSession *session; + SOUP_TEST_SKIP_IF_NO_TLS; + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); g_object_set (G_OBJECT (session), SOUP_SESSION_SSL_CA_FILE, "/dev/null", @@ -101,6 +105,8 @@ do_strict_tests (gconstpointer uri) { SoupSession *session; + SOUP_TEST_SKIP_IF_NO_TLS; + debug_printf (1, "\nstrict/nonstrict\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -143,6 +149,8 @@ do_session_property_tests (void) char *ca_file; SoupSession *session; + SOUP_TEST_SKIP_IF_NO_TLS; + debug_printf (1, "session properties\n"); session = soup_session_async_new (); @@ -251,16 +259,13 @@ main (int argc, char **argv) test_init (argc, argv, NULL); - if (!tls_available) { - test_cleanup (); - return 77; /* SKIP */ + if (tls_available) { + server = soup_test_server_new_ssl (TRUE); + soup_server_add_handler (server, NULL, server_handler, NULL, NULL); + uri = g_strdup_printf ("https://127.0.0.1:%u/", + soup_server_get_port (server)); } - server = soup_test_server_new_ssl (TRUE); - soup_server_add_handler (server, NULL, server_handler, NULL, NULL); - uri = g_strdup_printf ("https://127.0.0.1:%u/", - soup_server_get_port (server)); - g_test_add_func ("/ssl/session-properties", do_session_property_tests); g_test_add_data_func ("/ssl/message-properties/async", uri, do_async_properties_tests); g_test_add_data_func ("/ssl/message-properties/sync", uri, do_sync_properties_tests); @@ -270,8 +275,10 @@ main (int argc, char **argv) ret = g_test_run (); - g_free (uri); - soup_test_server_quit_unref (server); + if (tls_available) { + g_free (uri); + soup_test_server_quit_unref (server); + } test_cleanup (); return ret; diff --git a/tests/test-utils.h b/tests/test-utils.h index 315d1117..03637dcf 100644 --- a/tests/test-utils.h +++ b/tests/test-utils.h @@ -17,11 +17,29 @@ void test_cleanup (void); extern int debug_level; extern gboolean tls_available; +extern gboolean apache_available; void debug_printf (int level, const char *format, ...) G_GNUC_PRINTF (2, 3); +#define SOUP_TEST_SKIP_IF_NO_TLS \ + G_STMT_START { \ + if (!tls_available) { \ + g_test_skip ("TLS is not available"); \ + return; \ + } \ + } G_STMT_END + #ifdef HAVE_APACHE void apache_init (void); void apache_cleanup (void); +#define SOUP_TEST_SKIP_IF_NO_APACHE +#else +#define apache_init() +#define apache_cleanup() +#define SOUP_TEST_SKIP_IF_NO_APACHE \ + G_STMT_START { \ + g_test_skip ("apache is not available"); \ + return; \ + } G_STMT_END #endif typedef enum { diff --git a/tests/timeout-test.c b/tests/timeout-test.c index fba515db..48c672bf 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -208,10 +208,7 @@ do_async_timeout_tests (gconstpointer data) gboolean extra_slow; if (g_str_has_prefix (fast_uri, "https")) { - if (!tls_available) { - g_test_skip ("TLS not available"); - return; - } + SOUP_TEST_SKIP_IF_NO_TLS; extra_slow = slow_https; } else @@ -252,10 +249,7 @@ do_sync_timeout_tests (gconstpointer data) gboolean extra_slow; if (g_str_has_prefix (fast_uri, "https")) { - if (!tls_available) { - g_test_skip ("TLS not available"); - return; - } + SOUP_TEST_SKIP_IF_NO_TLS; extra_slow = slow_https; } else @@ -340,7 +334,8 @@ main (int argc, char **argv) debug_printf (2, "\n"); slow_https = FALSE; } - } + } else + https_uri = g_strdup ("https://fail."); g_test_add_data_func ("/timeout/http/async", uri, do_async_timeout_tests); g_test_add_data_func ("/timeout/http/sync", uri, do_sync_timeout_tests); diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c index 89e6e8de..1a046c7a 100644 --- a/tests/xmlrpc-server-test.c +++ b/tests/xmlrpc-server-test.c @@ -5,8 +5,6 @@ #include "test-utils.h" -#ifdef HAVE_PHP_XMLRPC - #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS #endif @@ -358,13 +356,3 @@ main (int argc, char **argv) test_cleanup (); return ret; } - -#else /* HAVE_PHP_XMLRPC */ - -int -main (int argc, char **argv) -{ - return 77; /* SKIP */ -} - -#endif diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c index 3a7b20ad..46eee266 100644 --- a/tests/xmlrpc-test.c +++ b/tests/xmlrpc-test.c @@ -5,8 +5,6 @@ #include "test-utils.h" -#ifdef HAVE_PHP_XMLRPC - #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS #endif @@ -16,6 +14,18 @@ static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php"; static const char *uri = NULL; static gboolean server_test = FALSE; +#ifdef HAVE_PHP_XMLRPC +#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER +#else +#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \ + G_STMT_START { \ + if (!server_test) { \ + g_test_skip ("php-xmlrpc is not available"); \ + return; \ + } \ + } G_STMT_END +#endif + static const char *const value_type[] = { "BAD", "int", @@ -105,6 +115,8 @@ test_sum (void) GValue retval; gboolean ok; + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "sum (array of int -> int): "); ints = g_value_array_new (10); @@ -139,6 +151,8 @@ test_countBools (void) gboolean val, ok; GHashTable *result; + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "countBools (array of boolean -> struct of ints): "); bools = g_value_array_new (10); @@ -182,6 +196,8 @@ test_md5sum (void) GValue retval; gboolean ok; + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "md5sum (base64 -> base64)\n"); data = g_byte_array_new (); @@ -216,6 +232,8 @@ test_dateChange (void) GValue retval; gboolean ok; + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "dateChange (date, struct of ints -> time)\n"); date = soup_date_new (1970 + (g_random_int_range (0, 50)), @@ -323,6 +341,8 @@ test_echo (void) GValue retval; int i; + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "echo (array of string -> array of string):\n"); originals = g_value_array_new (N_ECHO_STRINGS); @@ -376,6 +396,8 @@ test_ping (gconstpointer include_params) char *out; gboolean ret; + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "ping (void (%s) -> string)\n", include_params ? "empty " : "no "); @@ -443,6 +465,8 @@ do_bad_xmlrpc (const char *body) static void test_fault_malformed (void) { + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "malformed request: "); do_bad_xmlrpc (""); @@ -451,6 +475,8 @@ test_fault_malformed (void) static void test_fault_method (void) { + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "request to non-existent method: "); do_bad_xmlrpc ("no_such_method1"); @@ -459,6 +485,8 @@ test_fault_method (void) static void test_fault_args (void) { + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; + debug_printf (1, "request with invalid args: "); do_bad_xmlrpc ("sum1"); @@ -493,9 +521,9 @@ main (int argc, char **argv) g_test_add_func ("/xmlrpc/echo", test_echo); g_test_add_data_func ("/xmlrpc/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping); g_test_add_data_func ("/xmlrpc/ping/no-params", GINT_TO_POINTER (FALSE), test_ping); - g_test_add_func ("/xmlrpc/fault_malformed", test_fault_malformed); - g_test_add_func ("/xmlrpc/fault_method", test_fault_method); - g_test_add_func ("/xmlrpc/fault_args", test_fault_args); + g_test_add_func ("/xmlrpc/fault/malformed", test_fault_malformed); + g_test_add_func ("/xmlrpc/fault/method", test_fault_method); + g_test_add_func ("/xmlrpc/fault/args", test_fault_args); ret = g_test_run (); @@ -504,13 +532,3 @@ main (int argc, char **argv) test_cleanup (); return ret; } - -#else /* HAVE_PHP_XMLRPC */ - -int -main (int argc, char **argv) -{ - return 77; /* SKIP */ -} - -#endif -- cgit v1.2.1 From 1b793c6b8f01a3b000ebfb9d9ac46174ed31dc78 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 17 Feb 2014 22:56:46 -0500 Subject: 2.45.90 --- NEWS | 31 +++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index dab58d61..f04f0ebf 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,34 @@ +Changes in libsoup from 2.45.3 to 2.45.90: + + * Fixed a problem where libsoup would use the "http" proxy + settings for "https" requests [#724316, Matt Barnes] + + * Updated SoupContentSniffer to match the current version of + the MIME sniffing specification [#648849 / #715126, Gustavo + Noronha Silva] + + * Updated the soup-tld APIs to accept ASCII-encoded hostnames + in addition to UTF-8 ones. + + * Ported the test programs to the gtestutils framework, added + support for installed tests, and made the tests use the TAP + driver. + + Some tests still need to be split up into more pieces, and + the debug output is now somewhat less useful in some cases. + + * Fixed the test programs to not depend on local proxy + settings. + + * Added some more checks to header-tests [#722341, Lionel + Landwerlin] + + * Fixed the "simple-proxy" example program, which had been + broken for a while. + + * Updated translations: + Korean + Changes in libsoup from 2.44.1 to 2.45.3: * The documentation has finally been updated to reflect the diff --git a/configure.ac b/configure.ac index e216c99f..5855f7e8 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [45]) -m4_define([soup_micro_version], [3]) +m4_define([soup_micro_version], [90]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From a82e19520989de9e3e4b69987cfed77edd51f4f0 Mon Sep 17 00:00:00 2001 From: Alexandre Franke Date: Sun, 23 Feb 2014 17:51:08 +0100 Subject: Move to the platform category --- libsoup.doap | 1 + 1 file changed, 1 insertion(+) diff --git a/libsoup.doap b/libsoup.doap index 00028649..c39f2d5d 100644 --- a/libsoup.doap +++ b/libsoup.doap @@ -12,6 +12,7 @@ + -- cgit v1.2.1 From 68735c66778188f4c8cbe531f7802b8c8cb188fd Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 9 Mar 2014 12:42:50 -0400 Subject: configure.ac: belatedly bump glib requirement to 2.38 The tests use the TAP driver now, which only exists in glib 2.38 and later. --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 5855f7e8..5bdd0798 100644 --- a/configure.ac +++ b/configure.ac @@ -78,12 +78,12 @@ dnl *********************** dnl *** Checks for glib *** dnl *********************** -GLIB_REQUIRED=2.36.0 +GLIB_REQUIRED=2.38.0 AM_PATH_GLIB_2_0($GLIB_REQUIRED,,,gobject gio) if test "$GLIB_LIBS" = ""; then AC_MSG_ERROR(GLIB $GLIB_REQUIRED or later is required to build libsoup) fi -GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_36" +GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38" GLIB_MAKEFILE='$(top_srcdir)/Makefile.glib' AC_SUBST(GLIB_MAKEFILE) -- cgit v1.2.1 From 76cd3dcd6a3eb621cf4976457c9d1b2ab9c0e468 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 9 Mar 2014 13:01:31 -0400 Subject: test-utils: change http_debug command-line flag g_test_init() intercepts "-h" for "help", so make http-debug be "-H" --- tests/test-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-utils.c b/tests/test-utils.c index 1d0d775b..69a9426b 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -38,7 +38,7 @@ static GOptionEntry debug_entry[] = { { "debug", 'd', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, increment_debug_level, "Enable (or increase) test-specific debugging", NULL }, - { "http-debug", 'h', G_OPTION_FLAG_NO_ARG, + { "http-debug", 'H', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, increment_http_debug_level, "Enable (or increase) HTTP-level debugging", NULL }, { NULL } -- cgit v1.2.1 From 96279397f976a3bf2568373e9baafb915e47c4d3 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 9 Mar 2014 12:43:16 -0400 Subject: xmlrpc-test: use g_test_skip() There was a comment about not using g_test_skip() here because of an old glib bug, but we're using g_test_skip() in lots of other places now, so... --- tests/xmlrpc-test.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c index 46eee266..15623a60 100644 --- a/tests/xmlrpc-test.c +++ b/tests/xmlrpc-test.c @@ -373,10 +373,7 @@ test_echo (void) for (i = 0; i < echoes->n_values; i++) { if (!server_test && strcmp (echo_strings_broken[i], g_value_get_string (&echoes->values[i])) == 0) { - /* We want to call g_test_skip(), but as of glib 2.38 - * that marks the test as failed rather than succeeded. - */ - // FIXME g_test_skip ("PHP bug"); + g_test_skip ("PHP bug"); g_value_array_free (echoes); return; } -- cgit v1.2.1 From 958ce5e82c1c18e6da405cebab69099def307b48 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 10 Mar 2014 10:36:12 -0400 Subject: redirect-test: remove a flaky test Bug 651446 involved a race condition when queuing a message while another message was being redirected on the same host. The fix included a regression test, but later rewrites of SoupSession made the race condition no longer possible, and made the test itself slightly flaky. So just remove it. --- tests/redirect-test.c | 103 -------------------------------------------------- 1 file changed, 103 deletions(-) diff --git a/tests/redirect-test.c b/tests/redirect-test.c index b20a3187..351946da 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -301,107 +301,6 @@ do_sync_req_api_test (gconstpointer test) do_request_api_test (sync_session, (TestCase *)test); } -typedef struct { - SoupSession *session; - SoupMessage *msg1, *msg2; - SoupURI *uri1, *uri2; - SoupSocket *sock1, *sock2; -} ConnectionTestData; - -static void -msg2_finished (SoupSession *session, SoupMessage *msg2, gpointer user_data) -{ - soup_test_assert_message_status (msg2, SOUP_STATUS_OK); -} - -static void -unpause_msg1 (SoupMessage *msg2, gpointer user_data) -{ - ConnectionTestData *data = user_data; - - soup_test_assert (data->sock1 != NULL, - "msg1 has no connection"); - soup_test_assert (data->sock2 != NULL, - "msg2 has no connection"); - soup_test_assert (data->sock1 != data->sock2, - "Both messages sharing the same connection"); - - soup_session_unpause_message (data->session, data->msg1); -} - -static gboolean -msg1_just_restarted (gpointer user_data) -{ - ConnectionTestData *data = user_data; - - soup_session_pause_message (data->session, data->msg1); - - data->msg2 = soup_message_new_from_uri ("GET", data->uri2); - - g_signal_connect (data->msg2, "got_body", - G_CALLBACK (unpause_msg1), data); - - soup_session_queue_message (data->session, data->msg2, msg2_finished, data); - return FALSE; -} - -static void -msg1_about_to_restart (SoupMessage *msg1, gpointer user_data) -{ - ConnectionTestData *data = user_data; - - /* Do nothing when loading the redirected-to resource */ - if (!SOUP_STATUS_IS_REDIRECTION (data->msg1->status_code)) - return; - - /* We have to pause msg1 after the I/O finishes, but before - * the queue runs again. - */ - g_idle_add_full (G_PRIORITY_HIGH, msg1_just_restarted, data, NULL); -} - -static void -request_started (SoupSession *session, SoupMessage *msg, - SoupSocket *socket, gpointer user_data) -{ - ConnectionTestData *data = user_data; - - if (msg == data->msg1) - data->sock1 = socket; - else if (msg == data->msg2) - data->sock2 = socket; - else - g_warn_if_reached (); -} - -static void -do_connection_test (void) -{ - ConnectionTestData data; - - memset (&data, 0, sizeof (data)); - - data.session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - g_signal_connect (data.session, "request-started", - G_CALLBACK (request_started), &data); - - data.uri1 = soup_uri_new_with_base (base_uri, "/301"); - data.uri2 = soup_uri_new_with_base (base_uri, "/"); - data.msg1 = soup_message_new_from_uri ("GET", data.uri1); - - g_signal_connect (data.msg1, "got-body", - G_CALLBACK (msg1_about_to_restart), &data); - soup_session_send_message (data.session, data.msg1); - - soup_test_assert_message_status (data.msg1, SOUP_STATUS_OK); - - g_object_unref (data.msg1); - soup_uri_free (data.uri1); - soup_uri_free (data.uri2); - - soup_test_session_abort_unref (data.session); -} - static void server_callback (SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, @@ -556,8 +455,6 @@ main (int argc, char **argv) g_free (path); } - g_test_add_func ("/redirect/reuse", do_connection_test); - ret = g_test_run (); g_main_loop_unref (loop); -- cgit v1.2.1 From 4106873f790b13f32467f8f5fd567b41b8ad5686 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 15 Mar 2014 14:08:25 -0400 Subject: auth-test: remove some erroneous SKIP_IF_NO_APACHEs --- tests/auth-test.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/auth-test.c b/tests/auth-test.c index 35b05cc7..def5cfd6 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -824,8 +824,6 @@ do_select_auth_test (void) SoupAuthDomain *basic_auth_domain, *digest_auth_domain; SoupURI *uri; - SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nTesting selection among multiple auths:\n"); /* It doesn't seem to be possible to configure Apache to serve @@ -982,8 +980,6 @@ do_auth_close_test (void) SoupURI *uri; AuthCloseData acd; - SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nTesting auth when server times out connection:\n"); server = soup_test_server_new (FALSE); @@ -1099,8 +1095,6 @@ do_disappearing_auth_test (void) SoupSession *session; int counter; - SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nTesting auth when server does not repeat challenge on failure:\n"); server = soup_test_server_new (FALSE); -- cgit v1.2.1 From 8224b826bdadcf8676854723ff51604a5645aae2 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sun, 9 Mar 2014 13:03:14 -0400 Subject: tests: split up some test programs into more tests --- tests/auth-test.c | 83 +++++-- tests/coding-test.c | 569 ++++++++++++++++++++++++--------------------- tests/continue-test.c | 68 +++++- tests/forms-test.c | 96 +++++--- tests/misc-test.c | 20 +- tests/ntlm-test.c | 131 ++++++----- tests/server-auth-test.c | 220 +++++++++--------- tests/ssl-test.c | 130 +++++------ tests/xmlrpc-server-test.c | 136 ++++++----- tests/xmlrpc-test.c | 2 +- 10 files changed, 831 insertions(+), 624 deletions(-) diff --git a/tests/auth-test.c b/tests/auth-test.c index def5cfd6..ccfed466 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -541,7 +541,7 @@ async_authenticate_assert_once_and_stop (SoupSession *session, SoupMessage *msg, } static void -do_async_auth_test (void) +do_async_auth_good_password_test (void) { SoupSession *session; SoupMessage *msg1, *msg2, *msg3, msg2_bak; @@ -549,7 +549,6 @@ do_async_auth_test (void) char *uri; SoupAuth *auth = NULL; int remaining; - gboolean been_there; SOUP_TEST_SKIP_IF_NO_APACHE; @@ -557,9 +556,8 @@ do_async_auth_test (void) loop = g_main_loop_new (NULL, TRUE); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - remaining = 0; - uri = g_strconcat (base_uri, "Basic/realm1/", NULL); + remaining = 0; msg1 = soup_message_new ("GET", uri); g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (1)); @@ -621,27 +619,46 @@ do_async_auth_test (void) memcpy (msg2, &msg2_bak, sizeof (SoupMessage)); g_object_unref (msg2); + g_free (uri); + g_main_loop_unref (loop); +} + +static void +do_async_auth_bad_password_test (void) +{ + SoupSession *session; + SoupMessage *msg; + guint auth_id; + char *uri; + SoupAuth *auth = NULL; + int remaining; + gboolean been_there; + /* Test that giving the wrong password doesn't cause multiple * authenticate signals the second time. */ debug_printf (1, "\nTesting async auth with wrong password (#522601):\n"); + SOUP_TEST_SKIP_IF_NO_APACHE; + + loop = g_main_loop_new (NULL, TRUE); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); remaining = 0; auth = NULL; - msg1 = soup_message_new ("GET", uri); - g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (1)); + msg = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (1)); auth_id = g_signal_connect (session, "authenticate", G_CALLBACK (async_authenticate), &auth); - g_object_ref (msg1); + g_object_ref (msg); remaining++; - soup_session_queue_message (session, msg1, async_finished, &remaining); + soup_session_queue_message (session, msg, async_finished, &remaining); g_main_loop_run (loop); g_signal_handler_disconnect (session, auth_id); soup_auth_authenticate (auth, "user1", "wrong"); g_object_unref (auth); - soup_session_unpause_message (session, msg1); + soup_session_unpause_message (session, msg); been_there = FALSE; auth_id = g_signal_connect (session, "authenticate", @@ -654,49 +671,67 @@ do_async_auth_test (void) "authenticate not emitted"); soup_test_session_abort_unref (session); - g_object_unref (msg1); + g_object_unref (msg); + + g_free (uri); + g_main_loop_unref (loop); +} + +static void +do_async_auth_no_password_test (void) +{ + SoupSession *session; + SoupMessage *msg; + guint auth_id; + char *uri; + int remaining; + gboolean been_there; /* Test that giving no password doesn't cause multiple * authenticate signals the second time. */ debug_printf (1, "\nTesting async auth with no password (#583462):\n"); + SOUP_TEST_SKIP_IF_NO_APACHE; + + loop = g_main_loop_new (NULL, TRUE); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); + uri = g_strconcat (base_uri, "Basic/realm1/", NULL); remaining = 0; /* Send a message that doesn't actually authenticate */ - msg1 = soup_message_new ("GET", uri); - g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (1)); + msg = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (1)); auth_id = g_signal_connect (session, "authenticate", G_CALLBACK (async_authenticate), NULL); - g_object_ref (msg1); + g_object_ref (msg); remaining++; - soup_session_queue_message (session, msg1, async_finished, &remaining); + soup_session_queue_message (session, msg, async_finished, &remaining); g_main_loop_run (loop); g_signal_handler_disconnect (session, auth_id); - soup_session_unpause_message (session, msg1); + soup_session_unpause_message (session, msg); g_main_loop_run (loop); - g_object_unref(msg1); + g_object_unref(msg); /* Now send a second message */ - msg1 = soup_message_new ("GET", uri); - g_object_set_data (G_OBJECT (msg1), "id", GINT_TO_POINTER (2)); - g_object_ref (msg1); + msg = soup_message_new ("GET", uri); + g_object_set_data (G_OBJECT (msg), "id", GINT_TO_POINTER (2)); + g_object_ref (msg); been_there = FALSE; auth_id = g_signal_connect (session, "authenticate", G_CALLBACK (async_authenticate_assert_once_and_stop), &been_there); remaining++; - soup_session_queue_message (session, msg1, async_finished, &remaining); + soup_session_queue_message (session, msg, async_finished, &remaining); g_main_loop_run (loop); - soup_session_unpause_message (session, msg1); + soup_session_unpause_message (session, msg); g_main_loop_run (loop); g_signal_handler_disconnect (session, auth_id); soup_test_session_abort_unref (session); - g_object_unref (msg1); + g_object_unref (msg); g_free (uri); g_main_loop_unref (loop); @@ -1243,7 +1278,9 @@ main (int argc, char **argv) g_test_add_data_func ("/auth/relogin-tests", relogin_tests, do_batch_tests); g_test_add_func ("/auth/pipelined-auth", do_pipelined_auth_test); g_test_add_func ("/auth/digest-expiration", do_digest_expiration_test); - g_test_add_func ("/auth/async-auth", do_async_auth_test); + g_test_add_func ("/auth/async-auth/good-password", do_async_auth_good_password_test); + g_test_add_func ("/auth/async-auth/bad-password", do_async_auth_bad_password_test); + g_test_add_func ("/auth/async-auth/no-password", do_async_auth_no_password_test); g_test_add_func ("/auth/select-auth", do_select_auth_test); g_test_add_func ("/auth/auth-close", do_auth_close_test); g_test_add_func ("/auth/infinite-auth", do_infinite_auth_test); diff --git a/tests/coding-test.c b/tests/coding-test.c index d922a19c..a044ad73 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -116,6 +116,20 @@ server_callback (SoupServer *server, SoupMessage *msg, soup_message_body_complete (msg->response_body); } +typedef struct { + SoupSession *session; + SoupMessage *msg; + SoupRequest *req; + SoupBuffer *response; +} CodingTestData; + +typedef enum { + CODING_TEST_DEFAULT = 0, + CODING_TEST_NO_DECODER = (1 << 0), + CODING_TEST_REQUEST_API = (1 << 1), + CODING_TEST_EMPTY = (1 << 2) +} CodingTestType; + typedef enum { NO_CHECK, EXPECT_DECODED, @@ -123,159 +137,195 @@ typedef enum { } MessageContentStatus; static void -check_response (SoupMessage *msg, +check_response (CodingTestData *data, const char *expected_encoding, const char *expected_content_type, - MessageContentStatus status) + MessageContentStatus status, + GByteArray *body) { const char *coding, *type; - soup_test_assert_message_status (msg, SOUP_STATUS_OK); + soup_test_assert_message_status (data->msg, SOUP_STATUS_OK); - coding = soup_message_headers_get_one (msg->response_headers, "Content-Encoding"); + coding = soup_message_headers_get_one (data->msg->response_headers, "Content-Encoding"); g_assert_cmpstr (coding, ==, expected_encoding); if (status != NO_CHECK) { if (status == EXPECT_DECODED) - g_assert_true (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED); + g_assert_true (soup_message_get_flags (data->msg) & SOUP_MESSAGE_CONTENT_DECODED); else - g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CONTENT_DECODED); + g_assert_false (soup_message_get_flags (data->msg) & SOUP_MESSAGE_CONTENT_DECODED); } - type = soup_message_headers_get_one (msg->response_headers, "Content-Type"); + type = soup_message_headers_get_one (data->msg->response_headers, "Content-Type"); g_assert_cmpstr (type, ==, expected_content_type); + + if (body) { + soup_assert_cmpmem (body->data, + body->len, + data->response->data, + data->response->length); + } else { + soup_assert_cmpmem (data->msg->response_body->data, + data->msg->response_body->length, + data->response->data, + data->response->length); + } } static void -do_coding_test (void) +setup_coding_test (CodingTestData *data, gconstpointer test_data) { - SoupSession *session; - SoupMessage *msg, *msgz, *msgj, *msge, *msgzl, *msgzlj, *msgzle, *msgzlr, *msgzlre; + CodingTestType test_type = GPOINTER_TO_INT (test_data); + SoupMessage *msg; SoupURI *uri; - debug_printf (1, "SoupMessage tests\n"); + data->session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, + SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, + NULL); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); uri = soup_uri_new_with_base (base_uri, "/mbox"); - /* Plain text data, no claim */ + if (test_type & CODING_TEST_EMPTY) + data->response = soup_buffer_new (SOUP_MEMORY_STATIC, "", 0); + else { + msg = soup_message_new_from_uri ("GET", uri); + soup_session_send_message (data->session, msg); + + data->response = soup_message_body_flatten (msg->response_body); + g_object_unref (msg); + } + + if (test_type & CODING_TEST_REQUEST_API) { + SoupRequestHTTP *reqh; + + reqh = soup_session_request_http_uri (data->session, "GET", uri, NULL); + data->req = SOUP_REQUEST (reqh); + data->msg = soup_request_http_get_message (reqh); + } else + data->msg = soup_message_new_from_uri ("GET", uri); + soup_uri_free (uri); + + if (! (test_type & CODING_TEST_NO_DECODER)) + soup_session_add_feature_by_type (data->session, SOUP_TYPE_CONTENT_DECODER); +} + +static void +teardown_coding_test (CodingTestData *data, gconstpointer test_data) +{ + soup_buffer_free (data->response); + + g_clear_object (&data->req); + g_object_unref (data->msg); + + soup_test_session_abort_unref (data->session); +} + +static void +do_coding_test_plain (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, plain\n"); - msg = soup_message_new_from_uri ("GET", uri); - soup_session_send_message (session, msg); - check_response (msg, NULL, "text/plain", EXPECT_NOT_DECODED); - /* Plain text data, claim gzip */ + soup_session_send_message (data->session, data->msg); + check_response (data, NULL, "text/plain", EXPECT_NOT_DECODED, NULL); +} + +static void +do_coding_test_gzip (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n"); - soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); - msgz = soup_message_new_from_uri ("GET", uri); - soup_session_send_message (session, msgz); - check_response (msgz, "gzip", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (msg->response_body->data, - msg->response_body->length, - msgz->response_body->data, - msgz->response_body->length); - - /* Plain text data, claim gzip w/ junk */ + + soup_session_send_message (data->session, data->msg); + check_response (data, "gzip", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n"); - msgj = soup_message_new_from_uri ("GET", uri); - soup_message_headers_append (msgj->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "trailing-junk"); - soup_session_send_message (session, msgj); - check_response (msgj, "gzip", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (msg->response_body->data, - msg->response_body->length, - msgj->response_body->data, - msgj->response_body->length); - - /* Plain text data, claim gzip with server error */ + + soup_session_send_message (data->session, data->msg); + check_response (data, "gzip", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n"); - msge = soup_message_new_from_uri ("GET", uri); - soup_message_headers_append (msge->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode"); - soup_session_send_message (session, msge); - check_response (msge, "gzip", "text/plain", EXPECT_NOT_DECODED); + + soup_session_send_message (data->session, data->msg); /* Failed content-decoding should have left the body untouched * from what the server sent... which happens to be the * uncompressed data. */ - soup_assert_cmpmem (msg->response_body->data, - msg->response_body->length, - msge->response_body->data, - msge->response_body->length); + check_response (data, "gzip", "text/plain", EXPECT_NOT_DECODED, NULL); +} - /* Plain text data, claim deflate */ +static void +do_coding_test_deflate (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n"); - msgzl = soup_message_new_from_uri ("GET", uri); - soup_message_headers_append (msgzl->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib"); - soup_session_send_message (session, msgzl); - check_response (msgzl, "deflate", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (msg->response_body->data, - msg->response_body->length, - msgzl->response_body->data, - msgzl->response_body->length); - - /* Plain text data, claim deflate w/ junk */ + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n"); - msgzlj = soup_message_new_from_uri ("GET", uri); - soup_message_headers_append (msgzlj->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); - soup_session_send_message (session, msgzlj); - check_response (msgzlj, "deflate", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (msg->response_body->data, - msg->response_body->length, - msgzlj->response_body->data, - msgzlj->response_body->length); - - /* Plain text data, claim deflate with server error */ + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n"); - msgzle = soup_message_new_from_uri ("GET", uri); - soup_message_headers_append (msgzle->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); - soup_session_send_message (session, msgzle); - check_response (msgzle, "deflate", "text/plain", EXPECT_NOT_DECODED); - soup_assert_cmpmem (msg->response_body->data, - msg->response_body->length, - msgzle->response_body->data, - msgzle->response_body->length); - - /* Plain text data, claim deflate (no zlib headers)*/ + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_NOT_DECODED, NULL); +} + +static void +do_coding_test_deflate_raw (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n"); - msgzlr = soup_message_new_from_uri ("GET", uri); - soup_message_headers_append (msgzlr->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-raw"); - soup_session_send_message (session, msgzlr); - check_response (msgzlr, "deflate", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (msg->response_body->data, - msg->response_body->length, - msgzlr->response_body->data, - msgzlr->response_body->length); - - /* Plain text data, claim deflate with server error */ + soup_session_send_message (data->session, data->msg); + + check_response (data, "deflate", "text/plain", EXPECT_DECODED, NULL); +} + +static void +do_coding_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n"); - msgzlre = soup_message_new_from_uri ("GET", uri); - soup_message_headers_append (msgzlre->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-raw"); - soup_session_send_message (session, msgzlre); - check_response (msgzlre, "deflate", "text/plain", EXPECT_NOT_DECODED); - soup_assert_cmpmem (msg->response_body->data, - msg->response_body->length, - msgzlre->response_body->data, - msgzlre->response_body->length); - - g_object_unref (msg); - g_object_unref (msgzlre); - g_object_unref (msgzlr); - g_object_unref (msgzlj); - g_object_unref (msgzle); - g_object_unref (msgzl); - g_object_unref (msgz); - g_object_unref (msgj); - g_object_unref (msge); - soup_uri_free (uri); + soup_session_send_message (data->session, data->msg); - soup_test_session_abort_unref (session); + check_response (data, "deflate", "text/plain", EXPECT_NOT_DECODED, NULL); } static void @@ -290,26 +340,25 @@ read_finished (GObject *stream, GAsyncResult *result, gpointer user_data) g_clear_error (&error); } -static GByteArray * -do_single_coding_req_test (SoupRequestHTTP *reqh, +static void +do_single_coding_req_test (CodingTestData *data, const char *expected_encoding, const char *expected_content_type, MessageContentStatus status) { GInputStream *stream; - SoupMessage *msg; - GByteArray *data; + GByteArray *body; guchar buf[1024]; gssize nread; GError *error = NULL; - data = g_byte_array_new (); + body = g_byte_array_new (); - stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error); + stream = soup_test_request_send (data->req, NULL, 0, &error); if (!stream) { g_assert_no_error (error); g_error_free (error); - return data; + return; } do { @@ -321,194 +370,125 @@ do_single_coding_req_test (SoupRequestHTTP *reqh, g_main_context_iteration (NULL, TRUE); if (nread > 0) - g_byte_array_append (data, buf, nread); + g_byte_array_append (body, buf, nread); } while (nread > 0); - soup_test_request_close_stream (SOUP_REQUEST (reqh), stream, NULL, &error); + soup_test_request_close_stream (data->req, stream, NULL, &error); g_assert_no_error (error); g_clear_error (&error); g_object_unref (stream); - msg = soup_request_http_get_message (reqh); - check_response (msg, expected_encoding, expected_content_type, status); - g_object_unref (msg); - - return data; + check_response (data, expected_encoding, expected_content_type, status, body); + g_byte_array_free (body, TRUE); } static void -do_coding_req_test (void) +do_coding_req_test_plain (CodingTestData *data, gconstpointer test_data) { - SoupSession *session; - SoupRequestHTTP *reqh; - SoupMessage *msg; - SoupURI *uri; - GByteArray *plain, *cmp; - - debug_printf (1, "\nSoupRequest tests\n"); - - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - NULL); - uri = soup_uri_new_with_base (base_uri, "/mbox"); - /* Plain text data, no claim */ debug_printf (1, " GET /mbox, plain\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - plain = do_single_coding_req_test (reqh, NULL, "text/plain", EXPECT_NOT_DECODED); - g_object_unref (reqh); - /* Plain text data, claim gzip */ + do_single_coding_req_test (data, NULL, "text/plain", EXPECT_NOT_DECODED); +} + +static void +do_coding_req_test_gzip (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n"); - soup_session_add_feature_by_type (session, SOUP_TYPE_CONTENT_DECODER); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (plain->data, plain->len, - cmp->data, cmp->len); - g_byte_array_free (cmp, TRUE); - g_object_unref (reqh); - - /* Plain text data, claim gzip w/ junk */ + + do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - msg = soup_request_http_get_message (reqh); - soup_message_headers_append (msg->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "trailing-junk"); - g_object_unref (msg); - cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (plain->data, plain->len, - cmp->data, cmp->len); - g_byte_array_free (cmp, TRUE); - g_object_unref (reqh); - - /* Plain text data, claim gzip with server error */ + + do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - msg = soup_request_http_get_message (reqh); - soup_message_headers_append (msg->request_headers, - "X-Test-Options", "force-encode"); - g_object_unref (msg); - cmp = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_NOT_DECODED); - /* Failed content-decoding should have left the body untouched - * from what the server sent... which happens to be the - * uncompressed data. - */ - soup_assert_cmpmem (plain->data, plain->len, - cmp->data, cmp->len); - g_byte_array_free (cmp, TRUE); - g_object_unref (reqh); + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "force-encode"); + do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED); +} - /* Plain text data, claim deflate */ +static void +do_coding_req_test_deflate (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - msg = soup_request_http_get_message (reqh); - soup_message_headers_append (msg->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib"); - g_object_unref (msg); - cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (plain->data, plain->len, - cmp->data, cmp->len); - g_byte_array_free (cmp, TRUE); - g_object_unref (reqh); - - /* Plain text data, claim deflate w/ junk */ + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - msg = soup_request_http_get_message (reqh); - soup_message_headers_append (msg->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); - g_object_unref (msg); - cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (plain->data, plain->len, - cmp->data, cmp->len); - g_byte_array_free (cmp, TRUE); - g_object_unref (reqh); - - /* Plain text data, claim deflate with server error */ + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - msg = soup_request_http_get_message (reqh); - soup_message_headers_append (msg->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); - g_object_unref (msg); - cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED); - soup_assert_cmpmem (plain->data, plain->len, - cmp->data, cmp->len); - g_byte_array_free (cmp, TRUE); - g_object_unref (reqh); - - /* Plain text data, claim deflate (no zlib headers)*/ + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED); +} + +static void +do_coding_req_test_deflate_raw (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - msg = soup_request_http_get_message (reqh); - soup_message_headers_append (msg->request_headers, + + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-raw"); - g_object_unref (msg); - cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_DECODED); - soup_assert_cmpmem (plain->data, plain->len, - cmp->data, cmp->len); - g_byte_array_free (cmp, TRUE); - g_object_unref (reqh); - - /* Plain text data, claim deflate with server error */ + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); +} + +static void +do_coding_req_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data) +{ debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - msg = soup_request_http_get_message (reqh); - soup_message_headers_append (msg->request_headers, - "X-Test-Options", "force-encode, prefer-deflate-raw"); - g_object_unref (msg); - cmp = do_single_coding_req_test (reqh, "deflate", "text/plain", EXPECT_NOT_DECODED); - soup_assert_cmpmem (plain->data, plain->len, - cmp->data, cmp->len); - g_byte_array_free (cmp, TRUE); - g_object_unref (reqh); - - g_byte_array_free (plain, TRUE); - soup_uri_free (uri); - soup_test_session_abort_unref (session); + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "force-encode, prefer-deflate-raw"); + do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED); } static void -do_coding_empty_test (void) +do_coding_msg_empty_test (CodingTestData *data, gconstpointer test_data) { - SoupSession *session; - SoupMessage *msg; - SoupURI *uri; - SoupRequestHTTP *reqh; - GByteArray *body; - debug_printf (1, "\nEmpty allegedly-encoded body test\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, - SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_DECODER, - SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, - NULL); - uri = soup_uri_new_with_base (base_uri, "/mbox"); - - debug_printf (1, " SoupMessage\n"); - msg = soup_message_new_from_uri ("GET", uri); - soup_message_headers_append (msg->request_headers, - "X-Test-Options", "empty"); - soup_session_send_message (session, msg); - check_response (msg, "gzip", "text/plain", EXPECT_NOT_DECODED); - g_object_unref (msg); - - debug_printf (1, " SoupRequest\n"); - reqh = soup_session_request_http_uri (session, "GET", uri, NULL); - msg = soup_request_http_get_message (reqh); - soup_message_headers_append (msg->request_headers, + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "empty"); - g_object_unref (msg); - body = do_single_coding_req_test (reqh, "gzip", "text/plain", EXPECT_NOT_DECODED); - g_byte_array_free (body, TRUE); - g_object_unref (reqh); + soup_session_send_message (data->session, data->msg); - soup_uri_free (uri); - soup_test_session_abort_unref (session); + check_response (data, "gzip", "text/plain", EXPECT_NOT_DECODED, NULL); } +static void +do_coding_req_empty_test (CodingTestData *data, gconstpointer test_data) +{ + soup_message_headers_append (data->msg->request_headers, + "X-Test-Options", "empty"); + do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED); +} int main (int argc, char **argv) @@ -522,9 +502,68 @@ main (int argc, char **argv) base_uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (base_uri, soup_server_get_port (server)); - g_test_add_func ("/coding/message", do_coding_test); - g_test_add_func ("/coding/request", do_coding_req_test); - g_test_add_func ("/coding/empty", do_coding_empty_test); + g_test_add ("/coding/message/plain", CodingTestData, + GINT_TO_POINTER (CODING_TEST_NO_DECODER), + setup_coding_test, do_coding_test_plain, teardown_coding_test); + g_test_add ("/coding/message/gzip", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_gzip, teardown_coding_test); + g_test_add ("/coding/message/gzip/with-junk", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_gzip_with_junk, teardown_coding_test); + g_test_add ("/coding/message/gzip/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_gzip_bad_server, teardown_coding_test); + g_test_add ("/coding/message/deflate", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate, teardown_coding_test); + g_test_add ("/coding/message/deflate/with-junk", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate_with_junk, teardown_coding_test); + g_test_add ("/coding/message/deflate/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate_bad_server, teardown_coding_test); + g_test_add ("/coding/message/deflate-raw", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate_raw, teardown_coding_test); + g_test_add ("/coding/message/deflate-raw/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_DEFAULT), + setup_coding_test, do_coding_test_deflate_raw_bad_server, teardown_coding_test); + + g_test_add ("/coding/request/plain", CodingTestData, + GINT_TO_POINTER (CODING_TEST_NO_DECODER | CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_plain, teardown_coding_test); + g_test_add ("/coding/request/gzip", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_gzip, teardown_coding_test); + g_test_add ("/coding/request/gzip/with-junk", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_gzip_with_junk, teardown_coding_test); + g_test_add ("/coding/request/gzip/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_gzip_bad_server, teardown_coding_test); + g_test_add ("/coding/request/deflate", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate, teardown_coding_test); + g_test_add ("/coding/request/deflate/with-junk", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate_with_junk, teardown_coding_test); + g_test_add ("/coding/request/deflate/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate_bad_server, teardown_coding_test); + g_test_add ("/coding/request/deflate-raw", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate_raw, teardown_coding_test); + g_test_add ("/coding/request/deflate-raw/bad-server", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API), + setup_coding_test, do_coding_req_test_deflate_raw_bad_server, teardown_coding_test); + + g_test_add ("/coding/message/empty", CodingTestData, + GINT_TO_POINTER (CODING_TEST_EMPTY), + setup_coding_test, do_coding_msg_empty_test, teardown_coding_test); + g_test_add ("/coding/request/empty", CodingTestData, + GINT_TO_POINTER (CODING_TEST_REQUEST_API | CODING_TEST_EMPTY), + setup_coding_test, do_coding_req_empty_test, teardown_coding_test); ret = g_test_run (); diff --git a/tests/continue-test.c b/tests/continue-test.c index 42138ce2..1736a328 100644 --- a/tests/continue-test.c +++ b/tests/continue-test.c @@ -153,7 +153,7 @@ do_message (const char *path, gboolean long_body, } static void -run_tests (void) +do_test_unauth_short_noexpect_nopass (void) { do_message ("unauth", FALSE, FALSE, FALSE, "client-wrote_headers", @@ -167,6 +167,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_unauth_long_noexpect_nopass (void) +{ do_message ("unauth", TRUE, FALSE, FALSE, "client-wrote_headers", "client-wrote_body", @@ -179,6 +184,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_unauth_short_expect_nopass (void) +{ do_message ("unauth", FALSE, TRUE, FALSE, "client-wrote_headers", "server-got_headers", @@ -193,6 +203,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_unauth_long_expect_nopass (void) +{ do_message ("unauth", TRUE, TRUE, FALSE, "client-wrote_headers", "server-got_headers", @@ -203,7 +218,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} +static void +do_test_auth_short_noexpect_nopass (void) +{ do_message ("auth", FALSE, FALSE, FALSE, "client-wrote_headers", "client-wrote_body", @@ -216,6 +235,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_auth_long_noexpect_nopass (void) +{ do_message ("auth", TRUE, FALSE, FALSE, "client-wrote_headers", "client-wrote_body", @@ -228,6 +252,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_auth_short_expect_nopass (void) +{ do_message ("auth", FALSE, TRUE, FALSE, "client-wrote_headers", "server-got_headers", @@ -238,6 +267,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_auth_long_expect_nopass (void) +{ do_message ("auth", TRUE, TRUE, FALSE, "client-wrote_headers", "server-got_headers", @@ -248,7 +282,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} +static void +do_test_auth_short_noexpect_pass (void) +{ do_message ("auth", FALSE, FALSE, TRUE, "client-wrote_headers", "client-wrote_body", @@ -270,6 +308,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_auth_long_noexpect_pass (void) +{ do_message ("auth", TRUE, FALSE, TRUE, "client-wrote_headers", "client-wrote_body", @@ -291,6 +334,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_auth_short_expect_pass (void) +{ do_message ("auth", FALSE, TRUE, TRUE, "client-wrote_headers", "server-got_headers", @@ -312,6 +360,11 @@ run_tests (void) "client-got_body", "client-finished", NULL); +} + +static void +do_test_auth_long_expect_pass (void) +{ do_message ("auth", TRUE, TRUE, TRUE, "client-wrote_headers", "server-got_headers", @@ -437,7 +490,18 @@ main (int argc, char **argv) server = setup_server (); port = soup_server_get_port (server); - g_test_add_func ("/continue", run_tests); + g_test_add_func ("/continue/unauth_short_noexpect_nopass", do_test_unauth_short_noexpect_nopass); + g_test_add_func ("/continue/unauth_long_noexpect_nopass", do_test_unauth_long_noexpect_nopass); + g_test_add_func ("/continue/unauth_short_expect_nopass", do_test_unauth_short_expect_nopass); + g_test_add_func ("/continue/unauth_long_expect_nopass", do_test_unauth_long_expect_nopass); + g_test_add_func ("/continue/auth_short_noexpect_nopass", do_test_auth_short_noexpect_nopass); + g_test_add_func ("/continue/auth_long_noexpect_nopass", do_test_auth_long_noexpect_nopass); + g_test_add_func ("/continue/auth_short_expect_nopass", do_test_auth_short_expect_nopass); + g_test_add_func ("/continue/auth_long_expect_nopass", do_test_auth_long_expect_nopass); + g_test_add_func ("/continue/auth_short_noexpect_pass", do_test_auth_short_noexpect_pass); + g_test_add_func ("/continue/auth_long_noexpect_pass", do_test_auth_long_noexpect_pass); + g_test_add_func ("/continue/auth_short_expect_pass", do_test_auth_short_expect_pass); + g_test_add_func ("/continue/auth_long_expect_pass", do_test_auth_long_expect_pass); ret = g_test_run (); diff --git a/tests/forms-test.c b/tests/forms-test.c index 6e6334f4..a3401db8 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -96,20 +96,61 @@ do_hello_tests (gconstpointer uri) #endif debug_printf (1, "Hello tests (GET, application/x-www-form-urlencoded)\n"); + for (n = 0; n < G_N_ELEMENTS (tests); n++) { do_hello_test (n, FALSE, uri); do_hello_test (n, TRUE, uri); } } +#define MD5_TEST_FILE (g_test_get_filename (G_TEST_DIST, "index.txt", NULL)) +#define MD5_TEST_FILE_BASENAME "index.txt" +#define MD5_TEST_FILE_MIME_TYPE "text/plain" + +static char * +get_md5_data (char **contents, gsize *length) +{ + char *my_contents, *md5; + gsize my_length; + GError *error = NULL; + + if (!g_file_get_contents (MD5_TEST_FILE, &my_contents, &my_length, &error)) { + g_assert_no_error (error); + g_error_free (error); + return NULL; + } + + md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, my_contents, my_length); + + if (contents) + *contents = my_contents; + else + g_free (my_contents); + if (length) + *length = my_length; + + return md5; +} + static void -do_md5_test_curl (const char *uri, const char *file, const char *md5) +do_md5_test_curl (gconstpointer data) { + const char *uri = data; + char *md5; GPtrArray *args; char *file_arg, *str_stdout; GError *error = NULL; - debug_printf (1, " via curl: "); +#ifndef HAVE_CURL + g_test_skip ("/usr/bin/curl is not available"); + return; +#endif + + debug_printf (1, "\nMD5 test via curl (POST, multipart/form-data)\n"); + + md5 = get_md5_data (NULL, NULL); + if (!md5) + return; args = g_ptr_array_new (); g_ptr_array_add (args, "curl"); @@ -117,7 +158,7 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5) g_ptr_array_add (args, "*"); g_ptr_array_add (args, "-L"); g_ptr_array_add (args, "-F"); - file_arg = g_strdup_printf ("file=@%s", file); + file_arg = g_strdup_printf ("file=@%s", MD5_TEST_FILE); g_ptr_array_add (args, file_arg); g_ptr_array_add (args, "-F"); g_ptr_array_add (args, "fmt=txt"); @@ -136,22 +177,26 @@ do_md5_test_curl (const char *uri, const char *file, const char *md5) } g_ptr_array_free (args, TRUE); g_free (file_arg); -} -#define MD5_TEST_FILE (g_test_get_filename (G_TEST_DIST, "index.txt", NULL)) -#define MD5_TEST_FILE_BASENAME "index.txt" -#define MD5_TEST_FILE_MIME_TYPE "text/plain" + g_free (md5); +} static void -do_md5_test_libsoup (const char *uri, const char *contents, - gsize length, const char *md5) +do_md5_test_libsoup (gconstpointer data) { + const char *uri = data; + char *contents, *md5; + gsize length; SoupMultipart *multipart; SoupBuffer *buffer; SoupMessage *msg; SoupSession *session; - debug_printf (1, " via libsoup: "); + debug_printf (1, "\nMD5 test via libsoup (POST, multipart/form-data)\n"); + + md5 = get_md5_data (&contents, &length); + if (!md5) + return; multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART); buffer = soup_buffer_new (SOUP_MEMORY_COPY, contents, length); @@ -173,38 +218,11 @@ do_md5_test_libsoup (const char *uri, const char *contents, g_object_unref (msg); soup_test_session_abort_unref (session); -} - -static void -do_md5_tests (gconstpointer uri) -{ - char *contents, *md5; - gsize length; - GError *error = NULL; - -#ifndef HAVE_CURL - g_test_skip ("/usr/bin/curl is not available"); - return; -#endif - - debug_printf (1, "\nMD5 tests (POST, multipart/form-data)\n"); - - if (!g_file_get_contents (MD5_TEST_FILE, &contents, &length, &error)) { - g_assert_no_error (error); - g_error_free (error); - return; - } - - md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, contents, length); - - do_md5_test_curl (uri, MD5_TEST_FILE, md5); - do_md5_test_libsoup (uri, contents, length, md5); g_free (contents); g_free (md5); } - static void do_form_decode_test (void) { @@ -428,7 +446,9 @@ main (int argc, char **argv) g_test_add_data_func_full ("/forms/hello", uri_str, do_hello_tests, g_free); uri_str = g_strdup_printf ("http://127.0.0.1:%u/md5", port); - g_test_add_data_func_full ("/forms/md5", uri_str, do_md5_tests, g_free); + g_test_add_data_func_full ("/forms/md5/curl", g_strdup (uri_str), do_md5_test_curl, g_free); + g_test_add_data_func_full ("/forms/md5/libsoup", g_strdup (uri_str), do_md5_test_libsoup, g_free); + g_free (uri_str); g_test_add_func ("/forms/decode", do_form_decode_test); diff --git a/tests/misc-test.c b/tests/misc-test.c index 46c9cb10..7ee19815 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -741,7 +741,7 @@ do_cancel_while_reading_req_test_for_session (SoupSession *session, } static void -do_cancel_while_reading_req_test (void) +do_cancel_while_reading_immediate_req_test (void) { SoupSession *session; guint flags; @@ -761,6 +761,13 @@ do_cancel_while_reading_req_test (void) NULL); do_cancel_while_reading_req_test_for_session (session, flags); soup_test_session_abort_unref (session); +} + +static void +do_cancel_while_reading_delayed_req_test (void) +{ + SoupSession *session; + guint flags; debug_printf (1, "\nCancelling (after 100ms) message while reading response (request api)\n"); flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_SOON; @@ -777,6 +784,13 @@ do_cancel_while_reading_req_test (void) NULL); do_cancel_while_reading_req_test_for_session (session, flags); soup_test_session_abort_unref (session); +} + +static void +do_cancel_while_reading_preemptive_req_test (void) +{ + SoupSession *session; + guint flags; debug_printf (1, "\nCancelling (preemptively) message while reading response (request api)\n"); flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE; @@ -939,7 +953,9 @@ main (int argc, char **argv) g_test_add_func ("/misc/early-abort/req", do_early_abort_req_test); g_test_add_func ("/misc/accept-language", do_accept_language_test); g_test_add_func ("/misc/cancel-while-reading/msg", do_cancel_while_reading_test); - g_test_add_func ("/misc/cancel-while-reading/req", do_cancel_while_reading_req_test); + g_test_add_func ("/misc/cancel-while-reading/req/immediate", do_cancel_while_reading_immediate_req_test); + g_test_add_func ("/misc/cancel-while-reading/req/delayed", do_cancel_while_reading_delayed_req_test); + g_test_add_func ("/misc/cancel-while-reading/req/preemptive", do_cancel_while_reading_preemptive_req_test); g_test_add_func ("/misc/aliases", do_aliases_test); g_test_add_func ("/misc/idle-on-dispose", do_idle_on_dispose_test); g_test_add_func ("/misc/pause-abort", do_pause_abort_test); diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index e05213af..7aa532ed 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -11,6 +11,8 @@ #include "test-utils.h" +static SoupURI *uri; + typedef enum { NTLM_UNAUTHENTICATED, NTLM_RECEIVED_REQUEST, @@ -430,71 +432,84 @@ do_ntlm_round (SoupURI *base_uri, gboolean use_ntlm, soup_test_session_abort_unref (session); } -static void -do_ntlm_tests (SoupURI *base_uri, gboolean use_builtin_ntlm) -{ - debug_printf (1, "Round 1: Non-NTLM Connection, no auth\n"); - do_ntlm_round (base_uri, FALSE, NULL, use_builtin_ntlm); - debug_printf (1, "Round 2: NTLM Connection, user=alice\n"); - do_ntlm_round (base_uri, TRUE, "alice", use_builtin_ntlm); - debug_printf (1, "Round 3: NTLM Connection, user=bob\n"); - do_ntlm_round (base_uri, TRUE, "bob", use_builtin_ntlm); - debug_printf (1, "Round 4: Non-NTLM Connection, user=alice\n"); - do_ntlm_round (base_uri, FALSE, "alice", use_builtin_ntlm); -} - -static void -do_builtin_ntlm_test (gconstpointer data) -{ - SoupURI *uri = (SoupURI *)data; +typedef enum { + BUILTIN, + WINBIND, + FALLBACK +} NtlmType; - /* Built-in NTLM auth support. (We set SOUP_NTLM_AUTH_DEBUG to - * an empty string to ensure that the built-in support is - * being used, even if /usr/bin/ntlm_auth is available.) - */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); - do_ntlm_tests (uri, TRUE); -} +typedef struct { + const char *name, *user; + gboolean conn_uses_ntlm; + NtlmType ntlm_type; +} NtlmTest; + +static const NtlmTest ntlm_tests[] = { + { "/ntlm/builtin/none", NULL, FALSE, BUILTIN }, + { "/ntlm/builtin/alice", "alice", TRUE, BUILTIN }, + { "/ntlm/builtin/bob", "bob", TRUE, BUILTIN }, + { "/ntlm/builtin/basic", "alice", FALSE, BUILTIN }, + + { "/ntlm/winbind/none", NULL, FALSE, WINBIND }, + { "/ntlm/winbind/alice", "alice", TRUE, WINBIND }, + { "/ntlm/winbind/bob", "bob", TRUE, WINBIND }, + { "/ntlm/winbind/basic", "alice", FALSE, WINBIND }, + + { "/ntlm/fallback/none", NULL, FALSE, FALLBACK }, + { "/ntlm/fallback/alice", "alice", TRUE, FALLBACK }, + { "/ntlm/fallback/bob", "bob", TRUE, FALLBACK }, + { "/ntlm/fallback/basic", "alice", FALSE, FALLBACK } +}; static void -do_winbind_ntlm_test (gconstpointer data) +do_ntlm_test (gconstpointer data) { - SoupURI *uri = (SoupURI *)data; + const NtlmTest *test = data; + gboolean use_builtin_ntlm = TRUE; + + switch (test->ntlm_type) { + case BUILTIN: + /* Built-in NTLM auth support. (We set SOUP_NTLM_AUTH_DEBUG to + * an empty string to ensure that the built-in support is + * being used, even if /usr/bin/ntlm_auth is available.) + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); + break; + case WINBIND: #ifndef USE_NTLM_AUTH - g_test_skip ("/usr/bin/ntlm_auth is not available"); - return; + g_test_skip ("/usr/bin/ntlm_auth is not available"); + return; #endif - /* Samba winbind /usr/bin/ntlm_auth helper support (via a - * helper program that emulates its interface). - */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG", - g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL), - TRUE); - g_unsetenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS"); - do_ntlm_tests (uri, FALSE); -} - -static void -do_fallback_ntlm_test (gconstpointer data) -{ - SoupURI *uri = (SoupURI *)data; - + /* Samba winbind /usr/bin/ntlm_auth helper support (via a + * helper program that emulates its interface). + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", + g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL), + TRUE); + g_unsetenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS"); + use_builtin_ntlm = FALSE; + break; + + case FALLBACK: #ifndef USE_NTLM_AUTH - g_test_skip ("/usr/bin/ntlm_auth is not available"); - return; + g_test_skip ("/usr/bin/ntlm_auth is not available"); + return; #endif - /* Support for when ntlm_auth is installed, but the user has - * no cached credentials (and thus we have to fall back to - * libsoup's built-in NTLM support). - */ - g_setenv ("SOUP_NTLM_AUTH_DEBUG", - g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL), - TRUE); - g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); - do_ntlm_tests (uri, TRUE); + /* Support for when ntlm_auth is installed, but the user has + * no cached credentials (and thus we have to fall back to + * libsoup's built-in NTLM support). + */ + g_setenv ("SOUP_NTLM_AUTH_DEBUG", + g_test_get_filename (G_TEST_BUILT, "ntlm-test-helper", NULL), + TRUE); + g_setenv ("SOUP_NTLM_AUTH_DEBUG_NOCREDS", "1", TRUE); + break; + } + + do_ntlm_round (uri, test->conn_uses_ntlm, test->user, use_builtin_ntlm); } static void @@ -576,8 +591,7 @@ main (int argc, char **argv) { SoupServer *server; GHashTable *connections; - SoupURI *uri; - int ret; + int i, ret; test_init (argc, argv, NULL); @@ -589,9 +603,8 @@ main (int argc, char **argv) uri = soup_uri_new ("http://127.0.0.1/"); soup_uri_set_port (uri, soup_server_get_port (server)); - g_test_add_data_func ("/ntlm/builtin", uri, do_builtin_ntlm_test); - g_test_add_data_func ("/ntlm/winbind", uri, do_winbind_ntlm_test); - g_test_add_data_func ("/ntlm/fallback", uri, do_fallback_ntlm_test); + for (i = 0; i < G_N_ELEMENTS (ntlm_tests); i++) + g_test_add_data_func (ntlm_tests[i].name, &ntlm_tests[i], do_ntlm_test); g_test_add_data_func ("/ntlm/retry", uri, do_retrying_test); ret = g_test_run (); diff --git a/tests/server-auth-test.c b/tests/server-auth-test.c index b5580c82..f386f526 100644 --- a/tests/server-auth-test.c +++ b/tests/server-auth-test.c @@ -5,6 +5,8 @@ #include "test-utils.h" +static SoupURI *base_uri; + static struct { gboolean client_sent_basic, client_sent_digest; gboolean server_requested_basic, server_requested_digest; @@ -21,7 +23,7 @@ curl_exited (GPid pid, int status, gpointer data) } static void -do_test (int n, SoupURI *base_uri, const char *path, +do_test (SoupURI *base_uri, const char *path, gboolean good_user, gboolean good_password, gboolean offer_basic, gboolean offer_digest, gboolean client_sends_basic, gboolean client_sends_digest, @@ -34,12 +36,6 @@ do_test (int n, SoupURI *base_uri, const char *path, GPid pid; gboolean done; - debug_printf (1, "%2d. %s, %soffer Basic, %soffer Digest, %s user, %s password\n", - n, path, offer_basic ? "" : "don't ", - offer_digest ? "" : "don't ", - good_user ? "good" : "bad", - good_password ? "good" : "bad"); - uri = soup_uri_new_with_base (base_uri, path); uri_str = soup_uri_to_string (uri, FALSE); soup_uri_free (uri); @@ -96,104 +92,95 @@ do_test (int n, SoupURI *base_uri, const char *path, g_assert_cmpint (success, ==, test_data.succeeded); } +#define TEST_USES_BASIC(t) (((t) & 1) == 1) +#define TEST_USES_DIGEST(t) (((t) & 2) == 2) +#define TEST_GOOD_USER(t) (((t) & 4) == 4) +#define TEST_GOOD_PASSWORD(t) (((t) & 8) == 8) + +#define TEST_GOOD_AUTH(t) (TEST_GOOD_USER (t) && TEST_GOOD_PASSWORD (t)) +#define TEST_PREEMPTIVE_BASIC(t) (TEST_USES_BASIC (t) && !TEST_USES_DIGEST (t)) + static void -do_auth_tests (gconstpointer data) +do_server_auth_test (gconstpointer data) { - SoupURI *base_uri = (SoupURI *)data; - int i, n = 1; - gboolean use_basic, use_digest, good_user, good_password; - gboolean preemptive_basic, good_auth; + int i = GPOINTER_TO_INT (data); #ifndef HAVE_CURL g_test_skip ("/usr/bin/curl is not available"); return; #endif - for (i = 0; i < 16; i++) { - use_basic = (i & 1) == 1; - use_digest = (i & 2) == 2; - good_user = (i & 4) == 4; - good_password = (i & 8) == 8; - - good_auth = good_user && good_password; - - /* Curl will preemptively send Basic if it's told to - * use Basic but not Digest. - */ - preemptive_basic = use_basic && !use_digest; - - /* 1. No auth required. The server will ignore the - * Authorization headers completely, and the request - * will always succeed. - */ - do_test (n++, base_uri, "/foo", - good_user, good_password, - /* request */ - use_basic, use_digest, - /* expected from client */ - preemptive_basic, FALSE, - /* expected from server */ - FALSE, FALSE, - /* success? */ - TRUE); - - /* 2. Basic auth required. The server will send - * "WWW-Authenticate: Basic" if the client fails to - * send an Authorization: Basic on the first request, - * or if it sends a bad password. - */ - do_test (n++, base_uri, "/Basic/foo", - good_user, good_password, - /* request */ - use_basic, use_digest, - /* expected from client */ - use_basic, FALSE, - /* expected from server */ - !preemptive_basic || !good_auth, FALSE, - /* success? */ - use_basic && good_auth); - - /* 3. Digest auth required. Simpler than the basic - * case because the client can't send Digest auth - * premptively. - */ - do_test (n++, base_uri, "/Digest/foo", - good_user, good_password, - /* request */ - use_basic, use_digest, - /* expected from client */ - preemptive_basic, use_digest, - /* expected from server */ - FALSE, TRUE, - /* success? */ - use_digest && good_auth); - - /* 4. Any auth required. */ - do_test (n++, base_uri, "/Any/foo", - good_user, good_password, - /* request */ - use_basic, use_digest, - /* expected from client */ - preemptive_basic, use_digest, - /* expected from server */ - !preemptive_basic || !good_auth, !preemptive_basic || !good_auth, - /* success? */ - (use_basic || use_digest) && good_auth); - - /* 5. No auth required again. (Makes sure that - * SOUP_AUTH_DOMAIN_REMOVE_PATH works.) - */ - do_test (n++, base_uri, "/Any/Not/foo", - good_user, good_password, - /* request */ - use_basic, use_digest, - /* expected from client */ - preemptive_basic, FALSE, - /* expected from server */ - FALSE, FALSE, - /* success? */ - TRUE); - } + /* 1. No auth required. The server will ignore the + * Authorization headers completely, and the request + * will always succeed. + */ + do_test (base_uri, "/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), FALSE, + /* expected from server */ + FALSE, FALSE, + /* success? */ + TRUE); + + /* 2. Basic auth required. The server will send + * "WWW-Authenticate: Basic" if the client fails to + * send an Authorization: Basic on the first request, + * or if it sends a bad password. + */ + do_test (base_uri, "/Basic/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_USES_BASIC (i), FALSE, + /* expected from server */ + !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i), FALSE, + /* success? */ + TEST_USES_BASIC (i) && TEST_GOOD_AUTH (i)); + + /* 3. Digest auth required. Simpler than the basic + * case because the client can't send Digest auth + * premptively. + */ + do_test (base_uri, "/Digest/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i), + /* expected from server */ + FALSE, TRUE, + /* success? */ + TEST_USES_DIGEST (i) && TEST_GOOD_AUTH (i)); + + /* 4. Any auth required. */ + do_test (base_uri, "/Any/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), TEST_USES_DIGEST (i), + /* expected from server */ + !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i), !TEST_PREEMPTIVE_BASIC (i) || !TEST_GOOD_AUTH (i), + /* success? */ + (TEST_USES_BASIC (i) || TEST_USES_DIGEST (i)) && TEST_GOOD_AUTH (i)); + + /* 5. No auth required again. (Makes sure that + * SOUP_AUTH_DOMAIN_REMOVE_PATH works.) + */ + do_test (base_uri, "/Any/Not/foo", + TEST_GOOD_USER (i), TEST_GOOD_PASSWORD (i), + /* request */ + TEST_USES_BASIC (i), TEST_USES_DIGEST (i), + /* expected from client */ + TEST_PREEMPTIVE_BASIC (i), FALSE, + /* expected from server */ + FALSE, FALSE, + /* success? */ + TRUE); } static gboolean @@ -290,7 +277,6 @@ main (int argc, char **argv) { GMainLoop *loop; SoupServer *server; - SoupURI *uri; SoupAuthDomain *auth_domain; int ret; @@ -325,15 +311,41 @@ main (int argc, char **argv) loop = g_main_loop_new (NULL, TRUE); if (run_tests) { - uri = soup_uri_new ("http://127.0.0.1"); - soup_uri_set_port (uri, soup_server_get_port (server)); - - /* FIXME: split this up! */ - g_test_add_data_func ("/server-auth", uri, do_auth_tests); + int i; + + base_uri = soup_uri_new ("http://127.0.0.1"); + soup_uri_set_port (base_uri, soup_server_get_port (server)); + + for (i = 0; i < 16; i++) { + char *path; + const char *authtypes; + + if (!TEST_GOOD_USER (i) && !TEST_GOOD_PASSWORD (i)) + continue; + if (TEST_USES_BASIC (i)) { + if (TEST_USES_DIGEST (i)) + authtypes = "basic+digest"; + else + authtypes = "basic"; + } else { + if (TEST_USES_DIGEST (i)) + authtypes = "digest"; + else + authtypes = "none"; + } + + path = g_strdup_printf ("/server-auth/%s/%s-user%c%s-password", + authtypes, + TEST_GOOD_USER (i) ? "good" : "bad", + TEST_GOOD_USER (i) ? '/' : '\0', + TEST_GOOD_PASSWORD (i) ? "good" : "bad"); + g_test_add_data_func (path, GINT_TO_POINTER (i), do_server_auth_test); + g_free (path); + } ret = g_test_run (); - soup_uri_free (uri); + soup_uri_free (base_uri); } else { g_print ("Listening on port %d\n", soup_server_get_port (server)); g_main_loop_run (loop); diff --git a/tests/ssl-test.c b/tests/ssl-test.c index 3eb61af1..65e8a558 100644 --- a/tests/ssl-test.c +++ b/tests/ssl-test.c @@ -2,6 +2,8 @@ #include "test-utils.h" +static char *uri; + static void do_properties_test_for_session (SoupSession *session, const char *uri) { @@ -24,7 +26,7 @@ do_properties_test_for_session (SoupSession *session, const char *uri) } static void -do_async_properties_tests (gconstpointer uri) +do_async_properties_tests (void) { SoupSession *session; @@ -40,7 +42,7 @@ do_async_properties_tests (gconstpointer uri) } static void -do_sync_properties_tests (gconstpointer uri) +do_sync_properties_tests (void) { SoupSession *session; @@ -55,80 +57,70 @@ do_sync_properties_tests (gconstpointer uri) soup_test_session_abort_unref (session); } +typedef struct { + const char *name; + gboolean sync; + gboolean strict; + gboolean with_ca_list; + guint expected_status; +} StrictnessTest; + +static const StrictnessTest strictness_tests[] = { + { "/ssl/strictness/async/strict/with-ca", + FALSE, TRUE, TRUE, SOUP_STATUS_OK }, + { "/ssl/strictness/async/strict/without-ca", + FALSE, TRUE, FALSE, SOUP_STATUS_SSL_FAILED }, + { "/ssl/strictness/async/non-strict/with-ca", + FALSE, FALSE, TRUE, SOUP_STATUS_OK }, + { "/ssl/strictness/async/non-strict/without-ca", + FALSE, FALSE, FALSE, SOUP_STATUS_OK }, + { "/ssl/strictness/sync/strict/with-ca", + TRUE, TRUE, TRUE, SOUP_STATUS_OK }, + { "/ssl/strictness/sync/strict/without-ca", + TRUE, TRUE, FALSE, SOUP_STATUS_SSL_FAILED }, + { "/ssl/strictness/sync/non-strict/with-ca", + TRUE, FALSE, TRUE, SOUP_STATUS_OK }, + { "/ssl/strictness/sync/non-strict/without-ca", + TRUE, FALSE, FALSE, SOUP_STATUS_OK }, +}; + static void -do_one_strict_test (SoupSession *session, const char *uri, - gboolean strict, gboolean with_ca_list, - guint expected_status) +do_strictness_test (gconstpointer data) { + const StrictnessTest *test = data; + SoupSession *session; SoupMessage *msg; + GTlsCertificateFlags flags = 0; - /* Note that soup_test_session_new() sets - * SOUP_SESSION_SSL_CA_FILE by default, and turns off - * SOUP_SESSION_SSL_STRICT. - */ + SOUP_TEST_SKIP_IF_NO_TLS; - g_object_set (G_OBJECT (session), - SOUP_SESSION_SSL_STRICT, strict, - SOUP_SESSION_SSL_CA_FILE, - (with_ca_list ? - g_test_get_filename (G_TEST_DIST, "/test-cert.pem", NULL) : - "/dev/null"), - NULL); - /* Close existing connections with old params */ - soup_session_abort (session); + session = soup_test_session_new (test->sync ? SOUP_TYPE_SESSION_SYNC : SOUP_TYPE_SESSION_ASYNC, + NULL); + if (!test->strict) { + g_object_set (G_OBJECT (session), + SOUP_SESSION_SSL_STRICT, FALSE, + NULL); + } + if (!test->with_ca_list) { + g_object_set (G_OBJECT (session), + SOUP_SESSION_SSL_CA_FILE, "/dev/null", + NULL); + } msg = soup_message_new ("GET", uri); soup_session_send_message (session, msg); - if (msg->status_code != expected_status) { - debug_printf (1, " FAILED: %d %s (expected %d %s)\n", - msg->status_code, msg->reason_phrase, - expected_status, - soup_status_get_phrase (expected_status)); - if (msg->status_code == SOUP_STATUS_SSL_FAILED) { - GTlsCertificateFlags flags = 0; - - soup_message_get_https_status (msg, NULL, &flags); - debug_printf (1, " tls error flags: 0x%x\n", flags); - } - } else if (with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) + soup_test_assert_message_status (msg, test->expected_status); + g_assert_true (soup_message_get_https_status (msg, NULL, &flags)); + if (test->with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) g_assert_true (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); else g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); - g_assert_true (soup_message_get_https_status (msg, NULL, NULL)); + if (msg->status_code == SOUP_STATUS_SSL_FAILED && + test->expected_status != SOUP_STATUS_SSL_FAILED) + debug_printf (1, " tls error flags: 0x%x\n", flags); g_object_unref (msg); -} - -static void -do_strict_tests (gconstpointer uri) -{ - SoupSession *session; - - SOUP_TEST_SKIP_IF_NO_TLS; - - debug_printf (1, "\nstrict/nonstrict\n"); - - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); - debug_printf (1, " async with CA list\n"); - do_one_strict_test (session, uri, TRUE, TRUE, SOUP_STATUS_OK); - debug_printf (1, " async without CA list\n"); - do_one_strict_test (session, uri, TRUE, FALSE, SOUP_STATUS_SSL_FAILED); - debug_printf (1, " async non-strict with CA list\n"); - do_one_strict_test (session, uri, FALSE, TRUE, SOUP_STATUS_OK); - debug_printf (1, " async non-strict without CA list\n"); - do_one_strict_test (session, uri, FALSE, FALSE, SOUP_STATUS_OK); - soup_test_session_abort_unref (session); - - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); - debug_printf (1, " sync with CA list\n"); - do_one_strict_test (session, uri, TRUE, TRUE, SOUP_STATUS_OK); - debug_printf (1, " sync without CA list\n"); - do_one_strict_test (session, uri, TRUE, FALSE, SOUP_STATUS_SSL_FAILED); - debug_printf (1, " sync non-strict with CA list\n"); - do_one_strict_test (session, uri, FALSE, TRUE, SOUP_STATUS_OK); - debug_printf (1, " sync non-strict without CA list\n"); - do_one_strict_test (session, uri, FALSE, FALSE, SOUP_STATUS_OK); soup_test_session_abort_unref (session); } @@ -254,8 +246,7 @@ int main (int argc, char **argv) { SoupServer *server; - char *uri; - int ret; + int i, ret; test_init (argc, argv, NULL); @@ -267,11 +258,14 @@ main (int argc, char **argv) } g_test_add_func ("/ssl/session-properties", do_session_property_tests); - g_test_add_data_func ("/ssl/message-properties/async", uri, do_async_properties_tests); - g_test_add_data_func ("/ssl/message-properties/sync", uri, do_sync_properties_tests); + g_test_add_func ("/ssl/message-properties/async", do_async_properties_tests); + g_test_add_func ("/ssl/message-properties/sync", do_sync_properties_tests); - /* FIXME: split this up */ - g_test_add_data_func ("/ssl/strict", uri, do_strict_tests); + for (i = 0; i < G_N_ELEMENTS (strictness_tests); i++) { + g_test_add_data_func (strictness_tests[i].name, + &strictness_tests[i], + do_strictness_test); + } ret = g_test_run (); diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c index 1a046c7a..bfeb200a 100644 --- a/tests/xmlrpc-server-test.c +++ b/tests/xmlrpc-server-test.c @@ -5,12 +5,12 @@ #include "test-utils.h" +static char *uri; + #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS #endif -GMainLoop *loop; - static void type_error (SoupMessage *msg, GType expected, GValueArray *params, int bad_value) { @@ -237,76 +237,64 @@ server_callback (SoupServer *server, SoupMessage *msg, g_value_array_free (params); } -static void -xmlrpc_test_exited (GPid pid, int status, gpointer data) -{ - g_assert_true (WIFEXITED (status) && WEXITSTATUS (status) == 0); - g_main_loop_quit (loop); -} - static gboolean -xmlrpc_test_print (GIOChannel *io, GIOCondition cond, gpointer data) +run_xmlrpc_test (char **argv, + char **stdout_out, + char **stderr_out, + GError **error) { - char *line; - gsize len; - GIOStatus status; + gboolean ok; + int status; - if (!(cond & G_IO_IN)) - return FALSE; + argv[0] = g_test_build_filename (G_TEST_BUILT, "xmlrpc-test", NULL); + ok = g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL, + stdout_out, stderr_out, &status, + error); + g_free (argv[0]); - status = g_io_channel_read_line (io, &line, &len, NULL, NULL); - if (status == G_IO_STATUS_NORMAL) { - /* Don't print the exit status, just the debug stuff */ - if (strncmp (line, "xmlrpc-test:", strlen ("xmlrpc-test:")) != 0) - g_print ("%s", line); - g_free (line); - return TRUE; - } else if (status == G_IO_STATUS_AGAIN) - return TRUE; - else + if (!ok) return FALSE; + + return g_spawn_check_exit_status (status, error); } static void -do_xmlrpc_tests (gconstpointer data) +do_one_xmlrpc_test (gconstpointer data) { - SoupURI *uri = (SoupURI *)data; - char *argv[10]; - int arg, out; - gboolean ok; - GPid pid; + const char *path = data; + char *argv[12]; + char *stdout_out, *stderr_out; GError *error = NULL; - GIOChannel *child_out; + int arg; - argv[0] = (char *) g_test_get_filename (G_TEST_BUILT, "xmlrpc-test", NULL); + argv[0] = NULL; argv[1] = "-S"; argv[2] = "-U"; - argv[3] = soup_uri_to_string (uri, FALSE); + argv[3] = uri; argv[4] = "-q"; + argv[5] = "-p"; + argv[6] = (char *) path; for (arg = 0; arg < debug_level && arg < 3; arg++) - argv[arg + 5] = "-d"; - argv[arg + 5] = NULL; + argv[arg + 7] = "-d"; + argv[arg + 7] = NULL; - ok = g_spawn_async_with_pipes (NULL, argv, NULL, - G_SPAWN_DO_NOT_REAP_CHILD, - NULL, NULL, &pid, - NULL, &out, NULL, - &error); - g_free (argv[3]); - - g_assert_no_error (error); - if (!ok) - return; - - g_child_watch_add (pid, xmlrpc_test_exited, NULL); - child_out = g_io_channel_unix_new (out); - g_io_add_watch (child_out, G_IO_IN | G_IO_ERR | G_IO_HUP, - xmlrpc_test_print, NULL); - g_io_channel_unref (child_out); + run_xmlrpc_test (argv, &stdout_out, &stderr_out, &error); + if (stdout_out) { + g_print ("%s", stdout_out); + g_free (stdout_out); + } + if (stderr_out) { + g_printerr ("%s", stderr_out); + g_free (stderr_out); + } - g_main_loop_run (loop); - g_main_loop_unref (loop); + if ( g_error_matches (error, G_SPAWN_EXIT_ERROR, 1) + || g_error_matches (error, G_SPAWN_EXIT_ERROR, 77)) + g_test_fail (); + else + g_assert_no_error (error); + g_clear_error (&error); } gboolean run_tests = TRUE; @@ -322,29 +310,52 @@ int main (int argc, char **argv) { SoupServer *server; - SoupURI *uri; int ret; test_init (argc, argv, no_test_entry); - server = soup_test_server_new (FALSE); + server = soup_test_server_new (run_tests); soup_server_add_handler (server, "/xmlrpc-server.php", server_callback, NULL, NULL); - - loop = g_main_loop_new (NULL, TRUE); + uri = g_strdup_printf ("http://127.0.0.1:%u/xmlrpc-server.php", + soup_server_get_port (server)); if (run_tests) { - uri = soup_uri_new ("http://127.0.0.1/xmlrpc-server.php"); - soup_uri_set_port (uri, soup_server_get_port (server)); + char *out, **tests, *path; + char *list_argv[4]; + GError *error = NULL; + int i; + + list_argv[0] = NULL; + list_argv[1] = "-S"; + list_argv[2] = "-l"; + list_argv[3] = NULL; + + if (!run_xmlrpc_test (list_argv, &out, NULL, &error)) { + g_printerr ("'xmlrpc-test -l' failed: %s\n", error->message); + g_error_free (error); + return 1; + } - g_test_add_data_func ("/xmlrpc/server", uri, do_xmlrpc_tests); + tests = g_strsplit (out, "\n", -1); + g_free (out); + + for (i = 0; tests[i] && *tests[i]; i++) { + g_assert_true (g_str_has_prefix (tests[i], "/xmlrpc/")); + path = g_strdup_printf ("/xmlrpc-server/%s", tests[i] + strlen ("/xmlrpc/")); + g_test_add_data_func (path, tests[i], do_one_xmlrpc_test); + g_free (path); + } ret = g_test_run (); - soup_uri_free (uri); + g_strfreev (tests); } else { + GMainLoop *loop; + g_print ("Listening on port %d\n", soup_server_get_port (server)); + loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); g_main_loop_unref (loop); @@ -352,6 +363,7 @@ main (int argc, char **argv) } soup_test_server_quit_unref (server); + g_free (uri); if (run_tests) test_cleanup (); return ret; diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c index 15623a60..73518c84 100644 --- a/tests/xmlrpc-test.c +++ b/tests/xmlrpc-test.c @@ -504,7 +504,7 @@ main (int argc, char **argv) test_init (argc, argv, xmlrpc_entries); - if (!uri) { + if (!uri && !server_test) { apache_init (); uri = default_uri; } -- cgit v1.2.1 From 8e2402651807403c6d42ecb75563f480405e8660 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 15 Mar 2014 11:57:34 -0400 Subject: tests: remove debug_printf()s that are redundant with test names --- tests/auth-test.c | 15 --------------- tests/cache-test.c | 8 -------- tests/chunk-io-test.c | 2 -- tests/chunk-test.c | 24 +++++------------------- tests/coding-test.c | 39 --------------------------------------- tests/connection-test.c | 14 -------------- tests/context-test.c | 14 -------------- tests/continue-test.c | 7 ------- tests/cookies-test.c | 4 ---- tests/forms-test.c | 8 -------- tests/header-parsing.c | 25 ++----------------------- tests/misc-test.c | 25 ------------------------- tests/multipart-test.c | 15 --------------- tests/no-ssl-test.c | 4 ---- tests/proxy-test.c | 6 ------ tests/redirect-test.c | 13 ------------- tests/server-test.c | 8 -------- tests/session-test.c | 4 ---- tests/sniffing-test.c | 2 -- tests/ssl-test.c | 2 -- tests/timeout-test.c | 2 -- tests/xmlrpc-test.c | 18 ++++++------------ 22 files changed, 13 insertions(+), 246 deletions(-) diff --git a/tests/auth-test.c b/tests/auth-test.c index ccfed466..cb9f07fb 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -294,7 +294,6 @@ do_pipelined_auth_test (void) SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "Testing pipelined auth (bug 271540):\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); authenticated = FALSE; @@ -447,8 +446,6 @@ do_digest_expiration_test (void) SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nTesting digest nonce expiration:\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); uri = g_strconcat (base_uri, "Digest/realm1/", NULL); @@ -552,8 +549,6 @@ do_async_auth_good_password_test (void) SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nTesting async auth:\n"); - loop = g_main_loop_new (NULL, TRUE); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); uri = g_strconcat (base_uri, "Basic/realm1/", NULL); @@ -637,7 +632,6 @@ do_async_auth_bad_password_test (void) /* Test that giving the wrong password doesn't cause multiple * authenticate signals the second time. */ - debug_printf (1, "\nTesting async auth with wrong password (#522601):\n"); SOUP_TEST_SKIP_IF_NO_APACHE; @@ -690,7 +684,6 @@ do_async_auth_no_password_test (void) /* Test that giving no password doesn't cause multiple * authenticate signals the second time. */ - debug_printf (1, "\nTesting async auth with no password (#583462):\n"); SOUP_TEST_SKIP_IF_NO_APACHE; @@ -859,8 +852,6 @@ do_select_auth_test (void) SoupAuthDomain *basic_auth_domain, *digest_auth_domain; SoupURI *uri; - debug_printf (1, "\nTesting selection among multiple auths:\n"); - /* It doesn't seem to be possible to configure Apache to serve * multiple auth types for a single URL. So we have to use * SoupServer here. We know that SoupServer handles the server @@ -1015,8 +1006,6 @@ do_auth_close_test (void) SoupURI *uri; AuthCloseData acd; - debug_printf (1, "\nTesting auth when server times out connection:\n"); - server = soup_test_server_new (FALSE); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); @@ -1074,8 +1063,6 @@ do_infinite_auth_test (void) SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nTesting broken infinite-loop auth:\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_signal_connect (session, "authenticate", G_CALLBACK (infinite_authenticate), NULL); @@ -1130,8 +1117,6 @@ do_disappearing_auth_test (void) SoupSession *session; int counter; - debug_printf (1, "\nTesting auth when server does not repeat challenge on failure:\n"); - server = soup_test_server_new (FALSE); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); diff --git a/tests/cache-test.c b/tests/cache-test.c index b60fb9c1..c499a776 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -272,8 +272,6 @@ do_basics_test (gconstpointer data) char *cache_dir; char *body1, *body2, *body3, *body4, *body5, *cmp; - debug_printf (1, "Cache basics\n"); - cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); debug_printf (2, " Caching to %s\n", cache_dir); cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); @@ -439,8 +437,6 @@ do_cancel_test (gconstpointer data) char *body1, *body2; guint flags; - debug_printf (1, "Cache cancel tests\n"); - cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); debug_printf (2, " Caching to %s\n", cache_dir); cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); @@ -526,8 +522,6 @@ do_refcounting_test (gconstpointer data) guint flags; GMainLoop *loop; - debug_printf (1, "Cache refcounting tests\n"); - cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); debug_printf (2, " Caching to %s\n", cache_dir); cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); @@ -582,8 +576,6 @@ do_headers_test (gconstpointer data) char *body1, *cmp; const char *header_value; - debug_printf (1, "Cache basics\n"); - cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); debug_printf (2, " Caching to %s\n", cache_dir); cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); diff --git a/tests/chunk-io-test.c b/tests/chunk-io-test.c index 29062a69..1e53eef1 100644 --- a/tests/chunk-io-test.c +++ b/tests/chunk-io-test.c @@ -358,8 +358,6 @@ do_io_tests (void) gssize nread, nwrote, total; gssize chunk_length, chunk_total; - debug_printf (1, "\nI/O tests\n"); - raw_contents = soup_test_get_index (); chunkified = chunkify (raw_contents->data, raw_contents->length); diff --git a/tests/chunk-test.c b/tests/chunk-test.c index de1007d7..7f4fe886 100644 --- a/tests/chunk-test.c +++ b/tests/chunk-test.c @@ -142,24 +142,17 @@ static void do_request_test (gconstpointer data) { RequestTestFlags flags = GPOINTER_TO_UINT (data); - SoupURI *uri = base_uri; + SoupURI *uri; PutTestData ptd; SoupMessage *msg; const char *client_md5, *server_md5; GChecksum *check; int i, length; - debug_printf (1, "PUT"); - if (flags & HACKY_STREAMING) - debug_printf (1, " w/ hacky streaming"); - else if (flags & PROPER_STREAMING) - debug_printf (1, " w/ proper streaming"); - if (flags & RESTART) { - debug_printf (1, " and restart"); + if (flags & RESTART) + uri = soup_uri_new_with_base (base_uri, "/redirect"); + else uri = soup_uri_copy (base_uri); - soup_uri_set_path (uri, "/redirect"); - } - debug_printf (1, "\n"); ptd.session = session; setup_request_body (&ptd); @@ -215,8 +208,7 @@ do_request_test (gconstpointer data) g_object_unref (msg); g_checksum_free (check); - if (uri != base_uri) - soup_uri_free (uri); + soup_uri_free (uri); } typedef struct { @@ -263,8 +255,6 @@ do_response_test (void) SoupMessage *msg; const char *client_md5, *server_md5; - debug_printf (1, "GET\n"); - gtd.current_chunk = NULL; gtd.length = 0; gtd.check = g_checksum_new (G_CHECKSUM_MD5); @@ -324,8 +314,6 @@ do_temporary_test (void) char *client_md5; const char *server_md5; - debug_printf (1, "PUT w/ temporary buffers\n"); - msg = soup_message_new_from_uri ("PUT", base_uri); soup_message_body_append (msg->request_body, SOUP_MEMORY_TEMPORARY, "one\r\n", 5); @@ -375,8 +363,6 @@ do_large_chunk_test (void) int i; LargeChunkData lcd; - debug_printf (1, "PUT w/ large chunk\n"); - msg = soup_message_new_from_uri ("PUT", base_uri); buf_data = g_malloc0 (LARGE_CHUNK_SIZE); diff --git a/tests/coding-test.c b/tests/coding-test.c index a044ad73..d400ca71 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -224,8 +224,6 @@ teardown_coding_test (CodingTestData *data, gconstpointer test_data) static void do_coding_test_plain (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, plain\n"); - soup_session_send_message (data->session, data->msg); check_response (data, NULL, "text/plain", EXPECT_NOT_DECODED, NULL); } @@ -233,8 +231,6 @@ do_coding_test_plain (CodingTestData *data, gconstpointer test_data) static void do_coding_test_gzip (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n"); - soup_session_send_message (data->session, data->msg); check_response (data, "gzip", "text/plain", EXPECT_DECODED, NULL); } @@ -242,8 +238,6 @@ do_coding_test_gzip (CodingTestData *data, gconstpointer test_data) static void do_coding_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "trailing-junk"); @@ -254,8 +248,6 @@ do_coding_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) static void do_coding_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode"); @@ -271,8 +263,6 @@ do_coding_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) static void do_coding_test_deflate (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib"); soup_session_send_message (data->session, data->msg); @@ -283,8 +273,6 @@ do_coding_test_deflate (CodingTestData *data, gconstpointer test_data) static void do_coding_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); soup_session_send_message (data->session, data->msg); @@ -295,8 +283,6 @@ do_coding_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) static void do_coding_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); soup_session_send_message (data->session, data->msg); @@ -307,8 +293,6 @@ do_coding_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data static void do_coding_test_deflate_raw (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-raw"); soup_session_send_message (data->session, data->msg); @@ -319,8 +303,6 @@ do_coding_test_deflate_raw (CodingTestData *data, gconstpointer test_data) static void do_coding_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-raw"); soup_session_send_message (data->session, data->msg); @@ -385,25 +367,18 @@ do_single_coding_req_test (CodingTestData *data, static void do_coding_req_test_plain (CodingTestData *data, gconstpointer test_data) { - /* Plain text data, no claim */ - debug_printf (1, " GET /mbox, plain\n"); - do_single_coding_req_test (data, NULL, "text/plain", EXPECT_NOT_DECODED); } static void do_coding_req_test_gzip (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: gzip\n"); - do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_DECODED); } static void do_coding_req_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: gzip, plus trailing junk\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "trailing-junk"); @@ -413,8 +388,6 @@ do_coding_req_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data static void do_coding_req_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: gzip, with server error\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode"); do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED); @@ -423,8 +396,6 @@ do_coding_req_test_gzip_bad_server (CodingTestData *data, gconstpointer test_dat static void do_coding_req_test_deflate (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib"); do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); @@ -433,8 +404,6 @@ do_coding_req_test_deflate (CodingTestData *data, gconstpointer test_data) static void do_coding_req_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate, plus trailing junk\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); @@ -443,8 +412,6 @@ do_coding_req_test_deflate_with_junk (CodingTestData *data, gconstpointer test_d static void do_coding_req_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate, with server error\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED); @@ -453,8 +420,6 @@ do_coding_req_test_deflate_bad_server (CodingTestData *data, gconstpointer test_ static void do_coding_req_test_deflate_raw (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data)\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-raw"); do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); @@ -463,8 +428,6 @@ do_coding_req_test_deflate_raw (CodingTestData *data, gconstpointer test_data) static void do_coding_req_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, " GET /mbox, Accept-Encoding: deflate (raw data), with server error\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-raw"); do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED); @@ -473,8 +436,6 @@ do_coding_req_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer t static void do_coding_msg_empty_test (CodingTestData *data, gconstpointer test_data) { - debug_printf (1, "\nEmpty allegedly-encoded body test\n"); - soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "empty"); soup_session_send_message (data->session, data->msg); diff --git a/tests/connection-test.c b/tests/connection-test.c index f092944b..a72d2f0a 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -166,8 +166,6 @@ do_content_length_framing_test (void) SoupURI *request_uri; goffset declared_length; - debug_printf (1, "\nInvalid Content-Length framing tests\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); debug_printf (1, " Content-Length larger than message body length\n"); @@ -353,8 +351,6 @@ do_persistent_connection_timeout_test (void) { SoupSession *session; - debug_printf (1, "\nUnexpected timing out of persistent connections\n"); - debug_printf (1, " Async session, message API\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_timeout_test_for_session (session); @@ -475,8 +471,6 @@ do_max_conns_test (void) { SoupSession *session; - debug_printf (1, "\nExceeding max-conns\n"); - debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_MAX_CONNS, MAX_CONNS, @@ -554,8 +548,6 @@ do_non_persistent_connection_test (void) { SoupSession *session; - debug_printf (1, "\nNon-persistent connections are closed immediately\n"); - debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_non_persistent_test_for_session (session); @@ -608,8 +600,6 @@ do_non_idempotent_connection_test (void) { SoupSession *session; - debug_printf (1, "\nNon-idempotent methods are always sent on new connections\n"); - debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_non_idempotent_test_for_session (session); @@ -724,8 +714,6 @@ do_connection_state_test (void) SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nConnection states\n"); - debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_connection_state_test_for_session (session); @@ -834,8 +822,6 @@ do_connection_event_test (void) SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nConnection events\n"); - debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_connection_event_test_for_session (session); diff --git a/tests/context-test.c b/tests/context-test.c index 7fe3d60b..727c63ba 100644 --- a/tests/context-test.c +++ b/tests/context-test.c @@ -88,12 +88,6 @@ do_test1 (gconstpointer data) { gboolean use_thread_context = GPOINTER_TO_INT (data); - debug_printf (1, "\nBlocking the main thread does not block other thread\n"); - if (use_thread_context) - debug_printf (1, "(Using g_main_context_push_thread_default())\n"); - else - debug_printf (1, "(Using SOUP_SESSION_ASYNC_CONTEXT)\n"); - test1_loop = g_main_loop_new (NULL, FALSE); g_idle_add (idle_start_test1_thread, GINT_TO_POINTER (use_thread_context)); g_main_loop_run (test1_loop); @@ -198,12 +192,6 @@ do_test2 (gconstpointer data) char *uri; SoupMessage *msg; - debug_printf (1, "\nA session with its own context is independent of the main loop.\n"); - if (use_thread_context) - debug_printf (1, "(Using g_main_context_push_thread_default())\n"); - else - debug_printf (1, "(Using SOUP_SESSION_ASYNC_CONTEXT)\n"); - idle = g_idle_add_full (G_PRIORITY_HIGH, idle_test2_fail, NULL, NULL); async_context = g_main_context_new (); @@ -275,8 +263,6 @@ do_multicontext_test (void) GMainContext *context1, *context2; GMainLoop *loop1, *loop2; - debug_printf (1, "\nUsing multiple async contexts\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); diff --git a/tests/continue-test.c b/tests/continue-test.c index 1736a328..b6a5805f 100644 --- a/tests/continue-test.c +++ b/tests/continue-test.c @@ -59,13 +59,6 @@ do_message (const char *path, gboolean long_body, const char *expected_event; char *actual_event; int expected_status, actual_status; - static int count = 1; - - debug_printf (1, "%d. /%s, %s body, %sExpect, %s password\n", - count++, path, - long_body ? "long" : "short", - expect_continue ? "" : "no ", - auth ? "with" : "without"); uri = g_strdup_printf ("http://%s127.0.0.1:%d/%s", auth ? "user:pass@" : "", diff --git a/tests/cookies-test.c b/tests/cookies-test.c index b36b14af..2c986b5f 100644 --- a/tests/cookies-test.c +++ b/tests/cookies-test.c @@ -55,8 +55,6 @@ do_cookies_accept_policy_test (void) GSList *l, *p; int i; - debug_printf (1, "SoupCookieJarAcceptPolicy test\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); soup_session_add_feature_by_type (session, SOUP_TYPE_COOKIE_JAR); jar = SOUP_COOKIE_JAR (soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR)); @@ -107,8 +105,6 @@ do_cookies_parsing_test (void) SoupCookie *cookie; gboolean got1, got2, got3; - debug_printf (1, "\nSoupCookie parsing test\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); soup_session_add_feature_by_type (session, SOUP_TYPE_COOKIE_JAR); jar = SOUP_COOKIE_JAR (soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR)); diff --git a/tests/forms-test.c b/tests/forms-test.c index a3401db8..1d89743b 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -95,8 +95,6 @@ do_hello_tests (gconstpointer uri) return; #endif - debug_printf (1, "Hello tests (GET, application/x-www-form-urlencoded)\n"); - for (n = 0; n < G_N_ELEMENTS (tests); n++) { do_hello_test (n, FALSE, uri); do_hello_test (n, TRUE, uri); @@ -146,8 +144,6 @@ do_md5_test_curl (gconstpointer data) return; #endif - debug_printf (1, "\nMD5 test via curl (POST, multipart/form-data)\n"); - md5 = get_md5_data (NULL, NULL); if (!md5) return; @@ -192,8 +188,6 @@ do_md5_test_libsoup (gconstpointer data) SoupMessage *msg; SoupSession *session; - debug_printf (1, "\nMD5 test via libsoup (POST, multipart/form-data)\n"); - md5 = get_md5_data (&contents, &length); if (!md5) return; @@ -235,8 +229,6 @@ do_form_decode_test (void) return; #endif - debug_printf (1, "\nDecode tests\n"); - /* Test that the code handles multiple values with the same key. */ table = soup_form_decode ("foo=first&foo=second&foo=third"); diff --git a/tests/header-parsing.c b/tests/header-parsing.c index 5f99831f..b5f6bf2f 100644 --- a/tests/header-parsing.c +++ b/tests/header-parsing.c @@ -758,9 +758,8 @@ do_request_tests (void) SoupMessageHeaders *headers; guint status; - debug_printf (1, "Request tests\n"); for (i = 0; i < num_reqtests; i++) { - debug_printf (1, "%2d. %s (%s): ", i + 1, reqtests[i].description, + debug_printf (1, "%2d. %s (%s)\n", i + 1, reqtests[i].description, soup_status_get_phrase (reqtests[i].status)); headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST); @@ -786,7 +785,6 @@ do_request_tests (void) g_free (path); soup_message_headers_free (headers); } - debug_printf (1, "\n"); } static void @@ -798,9 +796,8 @@ do_response_tests (void) SoupHTTPVersion version; SoupMessageHeaders *headers; - debug_printf (1, "Response tests\n"); for (i = 0; i < num_resptests; i++) { - debug_printf (1, "%2d. %s (%s): ", i + 1, resptests[i].description, + debug_printf (1, "%2d. %s (%s)\n", i + 1, resptests[i].description, resptests[i].reason_phrase ? "should parse" : "should NOT parse"); headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE); @@ -824,7 +821,6 @@ do_response_tests (void) g_free (reason_phrase); soup_message_headers_free (headers); } - debug_printf (1, "\n"); } static void @@ -833,7 +829,6 @@ do_qvalue_tests (void) int i, j; GSList *acceptable, *unacceptable, *iter; - debug_printf (1, "qvalue tests\n"); for (i = 0; i < num_qvaluetests; i++) { debug_printf (1, "%2d. %s:\n", i + 1, qvaluetests[i].header_value); @@ -862,8 +857,6 @@ do_qvalue_tests (void) soup_header_free_list (unacceptable); } else debug_printf (1, "(none)\n"); - - debug_printf (1, "\n"); } } @@ -887,8 +880,6 @@ do_content_disposition_tests (void) SoupMultipart *multipart; SoupMessageBody *body; - debug_printf (1, "Content-Disposition tests\n"); - hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); params = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (params, "filename", RFC5987_TEST_FILENAME); @@ -967,8 +958,6 @@ do_content_disposition_tests (void) g_assert_true (strstr (buffer->data, "filename=\"token\"")); soup_buffer_free (buffer); - - debug_printf (1, "\n"); } #define CONTENT_TYPE_TEST_MIME_TYPE "text/plain" @@ -985,8 +974,6 @@ do_content_type_tests (void) GHashTable *params; const char *header, *mime_type; - debug_printf (1, "Content-Type tests\n"); - hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); params = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (params, CONTENT_TYPE_TEST_ATTRIBUTE, @@ -1017,8 +1004,6 @@ do_content_type_tests (void) g_assert_null (mime_type); soup_message_headers_free (hdrs); - - debug_printf (1, "\n"); } struct { @@ -1039,8 +1024,6 @@ do_append_param_tests (void) GString *params; int i; - debug_printf (1, "soup_header_g_string_append_param() tests\n"); - params = g_string_new (NULL); for (i = 0; i < G_N_ELEMENTS (test_params); i++) { if (i > 0) @@ -1051,8 +1034,6 @@ do_append_param_tests (void) } g_assert_cmpstr (params->str, ==, TEST_PARAMS_RESULT); g_string_free (params, TRUE); - - debug_printf (1, "\n"); } static const struct { @@ -1075,8 +1056,6 @@ do_bad_header_tests (void) SoupMessageHeaders *hdrs; int i; - debug_printf (1, "bad header rejection tests\n"); - hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); for (i = 0; i < G_N_ELEMENTS (bad_headers); i++) { debug_printf (1, " %s\n", bad_headers[i].description); diff --git a/tests/misc-test.c b/tests/misc-test.c index 7ee19815..1f6e7773 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -99,8 +99,6 @@ do_host_test (void) SoupSession *session; SoupMessage *one, *two; - debug_printf (1, "Host handling\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); one = soup_message_new_from_uri ("GET", base_uri); @@ -158,8 +156,6 @@ do_callback_unref_test (void) GMainLoop *loop; char *bad_uri; - debug_printf (1, "\nCallback unref handling (msg api)\n"); - /* Get a guaranteed-bad URI */ addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT); soup_address_resolve_sync (addr, NULL); @@ -252,8 +248,6 @@ do_callback_unref_req_test (void) GMainLoop *loop; char *bad_uri; - debug_printf (1, "\nCallback unref handling (request api)\n"); - /* Get a guaranteed-bad URI */ addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT); soup_address_resolve_sync (addr, NULL); @@ -343,8 +337,6 @@ do_msg_reuse_test (void) SoupURI *uri; guint *signal_ids, n_signal_ids; - debug_printf (1, "\nSoupMessage reuse\n"); - signal_ids = g_signal_list_ids (SOUP_TYPE_MESSAGE, &n_signal_ids); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -435,8 +427,6 @@ do_early_abort_test (void) GMainContext *context; GMainLoop *loop; - debug_printf (1, "\nAbort with pending connection (msg api)\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); msg = soup_message_new_from_uri ("GET", base_uri); @@ -537,8 +527,6 @@ do_early_abort_req_test (void) GMainLoop *loop; GCancellable *cancellable; - debug_printf (1, "\nAbort with pending connection (request api)\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -620,8 +608,6 @@ do_accept_language_test (void) { const char *orig_language; - debug_printf (1, "\nAutomatic Accept-Language processing\n"); - orig_language = g_getenv ("LANGUAGE"); do_one_accept_language_test ("C", "en"); do_one_accept_language_test ("fr_FR", "fr-fr, fr;q=0.9"); @@ -705,8 +691,6 @@ do_cancel_while_reading_test (void) { SoupSession *session; - debug_printf (1, "\nCancelling message while reading response (msg api)\n"); - debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_cancel_while_reading_test_for_session (session); @@ -746,7 +730,6 @@ do_cancel_while_reading_immediate_req_test (void) SoupSession *session; guint flags; - debug_printf (1, "\nCancelling (immediately) message while reading response (request api)\n"); flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; debug_printf (1, " Async session\n"); @@ -769,7 +752,6 @@ do_cancel_while_reading_delayed_req_test (void) SoupSession *session; guint flags; - debug_printf (1, "\nCancelling (after 100ms) message while reading response (request api)\n"); flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_SOON; debug_printf (1, " Async session\n"); @@ -792,7 +774,6 @@ do_cancel_while_reading_preemptive_req_test (void) SoupSession *session; guint flags; - debug_printf (1, "\nCancelling (preemptively) message while reading response (request api)\n"); flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE; debug_printf (1, " Async session\n"); @@ -841,8 +822,6 @@ do_aliases_test (void) SoupSession *session; char *aliases[] = { "foo", NULL }; - debug_printf (1, "\nhttp-aliases / https-aliases\n"); - debug_printf (1, " Default behavior\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_aliases_test_for_session (session, "http"); @@ -873,8 +852,6 @@ do_idle_on_dispose_test (void) SoupMessage *msg; GMainContext *async_context; - debug_printf (1, "\nTesting SoupSessionAsync dispose behavior\n"); - async_context = g_main_context_new (); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_ASYNC_CONTEXT, async_context, @@ -903,8 +880,6 @@ do_pause_abort_test (void) SoupMessage *msg; gpointer ptr; - debug_printf (1, "\nTesting paused messages don't get leaked on abort\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); msg = soup_message_new_from_uri ("GET", base_uri); diff --git a/tests/multipart-test.c b/tests/multipart-test.c index b5ab813d..e057412e 100644 --- a/tests/multipart-test.c +++ b/tests/multipart-test.c @@ -409,19 +409,6 @@ sync_multipart_handling_cb (GObject *source, GAsyncResult *res, gpointer data) g_object_unref (multipart); } -static const char* -multipart_mode_to_string (MultipartMode mode) -{ - if (mode == NO_MULTIPART) - return "NO_MULTIPART"; - else if (mode == SYNC_MULTIPART) - return "SYNC_MULTIPART"; - else if (mode == ASYNC_MULTIPART_SMALL_READS) - return "SYNC_MULTIPART_SMALL_READS"; - - return "ASYNC_MULTIPART"; -} - static void test_multipart (gconstpointer data) { @@ -437,8 +424,6 @@ test_multipart (gconstpointer data) gboolean message_is_multipart = FALSE; GError* error = NULL; - debug_printf (1, "test_multipart(%s)\n", multipart_mode_to_string (multipart_mode)); - request = soup_session_request (session, base_uri_string, &error); g_assert_no_error (error); if (error) diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c index feffa5bd..0062c8c0 100644 --- a/tests/no-ssl-test.c +++ b/tests/no-ssl-test.c @@ -28,8 +28,6 @@ do_ssl_tests (gconstpointer uri) { SoupSession *session; - debug_printf (1, "\nSoupSession without SSL support\n"); - debug_printf (1, " plain\n"); session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); do_ssl_test_for_session (session, uri); @@ -54,8 +52,6 @@ do_session_property_tests (void) char *ca_file; SoupSession *session; - debug_printf (1, "session properties\n"); - session = soup_session_async_new (); g_object_get (G_OBJECT (session), diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 423a5598..599ff4e8 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -220,8 +220,6 @@ do_proxy_test (SoupProxyTest *test, gboolean sync) g_free (http_url); g_free (https_url); - - debug_printf (1, "\n"); } static void @@ -264,8 +262,6 @@ do_proxy_fragment_test (gconstpointer data) SOUP_TEST_SKIP_IF_NO_APACHE; - debug_printf (1, "\nTesting request with fragment via proxy\n"); - proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_PROXY_URI, proxy_uri, @@ -293,8 +289,6 @@ do_proxy_redirect_test (void) SOUP_TEST_SKIP_IF_NO_APACHE; SOUP_TEST_SKIP_IF_NO_TLS; - debug_printf (1, "\nTesting redirection through proxy\n"); - proxy_uri = soup_uri_new (proxies[SIMPLE_PROXY]); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_PROXY_URI, proxy_uri, diff --git a/tests/redirect-test.c b/tests/redirect-test.c index 351946da..c9079cf6 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -163,10 +163,6 @@ do_message_api_test (SoupSession *session, TestCase *test) SoupMessage *msg; TestRequest *treq; - debug_printf (1, "%s %s\n", - test->requests[0].method, - test->requests[0].path); - uri = soup_uri_new_with_base (base_uri, test->requests[0].path); msg = soup_message_new_from_uri (test->requests[0].method, uri); soup_uri_free (uri); @@ -189,7 +185,6 @@ do_message_api_test (SoupSession *session, TestCase *test) soup_test_assert_message_status (msg, test->final_status); g_object_unref (msg); - debug_printf (2, "\n"); } static void @@ -203,10 +198,6 @@ do_request_api_test (SoupSession *session, TestCase *test) GError *error = NULL; guint final_status; - debug_printf (1, "%s %s\n", - test->requests[0].method, - test->requests[0].path); - final_status = test->request_api_final_status; if (!final_status) final_status = test->final_status; @@ -219,7 +210,6 @@ do_request_api_test (SoupSession *session, TestCase *test) g_assert_no_error (error); if (error) { g_error_free (error); - debug_printf (2, "\n"); return; } @@ -248,7 +238,6 @@ do_request_api_test (SoupSession *session, TestCase *test) g_object_unref (msg); g_object_unref (reqh); - debug_printf (2, "\n"); return; } @@ -257,7 +246,6 @@ do_request_api_test (SoupSession *session, TestCase *test) g_error_free (error); g_object_unref (msg); g_object_unref (reqh); - debug_printf (2, "\n"); return; } @@ -274,7 +262,6 @@ do_request_api_test (SoupSession *session, TestCase *test) g_object_unref (msg); g_object_unref (reqh); - debug_printf (2, "\n"); } static void diff --git a/tests/server-test.c b/tests/server-test.c index ec5b6901..1648c4f6 100644 --- a/tests/server-test.c +++ b/tests/server-test.c @@ -65,8 +65,6 @@ do_star_test (void) SoupURI *star_uri; const char *handled_by; - debug_printf (1, "\nOPTIONS *\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); star_uri = soup_uri_copy (base_uri); soup_uri_set_path (star_uri, "*"); @@ -177,8 +175,6 @@ do_server_aliases_test (void) char *https_bad[] = { "http", "dav", "fred", NULL }; int i; - debug_printf (1, "\nserver aliases test\n"); - for (i = 0; http_good[i]; i++) do_one_server_aliases_test (base_uri, http_good[i], TRUE); for (i = 0; http_bad[i]; i++) @@ -199,8 +195,6 @@ do_dot_dot_test (void) SoupMessage *msg; SoupURI *uri; - debug_printf (1, "\n'..' smuggling test\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); uri = soup_uri_new_with_base (base_uri, "/..%2ftest"); @@ -243,8 +237,6 @@ do_ipv6_test (void) SoupSession *session; SoupMessage *msg; - debug_printf (1, "\nIPv6 server test\n"); - ipv6_addr = soup_address_new ("::1", SOUP_ADDRESS_ANY_PORT); soup_address_resolve_sync (ipv6_addr, NULL); ipv6_server = soup_server_new (SOUP_SERVER_INTERFACE, ipv6_addr, diff --git a/tests/session-test.c b/tests/session-test.c index 21d97a85..b652ee5c 100644 --- a/tests/session-test.c +++ b/tests/session-test.c @@ -202,8 +202,6 @@ do_priority_tests (gconstpointer data) SOUP_MESSAGE_PRIORITY_HIGH, SOUP_MESSAGE_PRIORITY_NORMAL }; - debug_printf (1, "\nSoupSessionAsync\n"); - session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_object_set (session, "max-conns", 1, NULL); @@ -263,8 +261,6 @@ do_property_tests (void) GTlsDatabase *tlsdb, *default_tlsdb; SoupURI *uri; - debug_printf (1, "\nTesting session init properties\n"); - default_proxy_resolver = g_proxy_resolver_get_default (); default_tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index 5b0e6ee7..59f874f4 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -397,8 +397,6 @@ test_disabled (gconstpointer data) const char *sniffed_content_type; GError *error = NULL; - debug_printf (1, "test_disabled(\"%s\")\n", path); - uri = soup_uri_new_with_base (base_uri, path); msg = soup_message_new_from_uri ("GET", uri); diff --git a/tests/ssl-test.c b/tests/ssl-test.c index 65e8a558..b042d120 100644 --- a/tests/ssl-test.c +++ b/tests/ssl-test.c @@ -143,8 +143,6 @@ do_session_property_tests (void) SOUP_TEST_SKIP_IF_NO_TLS; - debug_printf (1, "session properties\n"); - session = soup_session_async_new (); g_signal_connect (session, "notify::ssl-use-system-ca-file", G_CALLBACK (property_changed), &use_system_changed); diff --git a/tests/timeout-test.c b/tests/timeout-test.c index 48c672bf..81fb4331 100644 --- a/tests/timeout-test.c +++ b/tests/timeout-test.c @@ -155,8 +155,6 @@ do_req_tests_for_session (SoupSession *timeout_session, SoupSocket *ret, *idle_first, *idle_second; SoupSocket *plain_first, *plain_second; - debug_printf (1, "\n"); - if (idle_session) { g_signal_connect (idle_session, "request-started", G_CALLBACK (request_started_cb), &ret); diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c index 73518c84..3f26edd4 100644 --- a/tests/xmlrpc-test.c +++ b/tests/xmlrpc-test.c @@ -117,7 +117,7 @@ test_sum (void) SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "sum (array of int -> int): "); + debug_printf (2, "sum (array of int -> int): "); ints = g_value_array_new (10); for (i = sum = 0; i < 10; i++) { @@ -153,7 +153,7 @@ test_countBools (void) SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "countBools (array of boolean -> struct of ints): "); + debug_printf (2, "countBools (array of boolean -> struct of ints): "); bools = g_value_array_new (10); for (i = trues = falses = 0; i < 10; i++) { @@ -198,7 +198,7 @@ test_md5sum (void) SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "md5sum (base64 -> base64)\n"); + debug_printf (2, "md5sum (base64 -> base64)\n"); data = g_byte_array_new (); g_byte_array_set_size (data, 256); @@ -234,7 +234,7 @@ test_dateChange (void) SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "dateChange (date, struct of ints -> time)\n"); + debug_printf (2, "dateChange (date, struct of ints -> time)\n"); date = soup_date_new (1970 + (g_random_int_range (0, 50)), 1 + g_random_int_range (0, 12), @@ -343,7 +343,7 @@ test_echo (void) SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "echo (array of string -> array of string):\n"); + debug_printf (2, "echo (array of string -> array of string):\n"); originals = g_value_array_new (N_ECHO_STRINGS); for (i = 0; i < N_ECHO_STRINGS; i++) { @@ -395,7 +395,7 @@ test_ping (gconstpointer include_params) SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "ping (void (%s) -> string)\n", + debug_printf (2, "ping (void (%s) -> string)\n", include_params ? "empty " : "no "); params = soup_value_array_new (); @@ -464,8 +464,6 @@ test_fault_malformed (void) { SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "malformed request: "); - do_bad_xmlrpc (""); } @@ -474,8 +472,6 @@ test_fault_method (void) { SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "request to non-existent method: "); - do_bad_xmlrpc ("no_such_method1"); } @@ -484,8 +480,6 @@ test_fault_args (void) { SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; - debug_printf (1, "request with invalid args: "); - do_bad_xmlrpc ("sum1"); } -- cgit v1.2.1 From a1591e15bf2c4a690e79698cdd078f6ed01e48d3 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 15 Mar 2014 14:19:45 -0400 Subject: tests: use g_test_bug() to annotate test cases --- tests/auth-test.c | 8 ++ tests/cache-test.c | 4 + tests/chunk-test.c | 4 +- tests/coding-test.c | 28 ++++++ tests/connection-test.c | 8 ++ tests/cookies-test.c | 2 + tests/date.c | 228 ++++++++++++++++++++++++++++-------------------- tests/forms-test.c | 2 + tests/header-parsing.c | 164 +++++++++++++++++----------------- tests/misc-test.c | 30 ++++++- tests/no-ssl-test.c | 6 +- tests/ntlm-test.c | 2 + tests/proxy-test.c | 21 +++-- tests/redirect-test.c | 77 ++++++++-------- tests/requester-test.c | 12 +++ tests/server-test.c | 8 ++ tests/session-test.c | 4 + tests/sniffing-test.c | 4 + tests/socket-test.c | 2 + tests/ssl-test.c | 8 ++ tests/streaming-test.c | 2 + tests/test-utils.c | 1 + tests/tld-test.c | 3 + tests/uri-parsing.c | 148 ++++++++++++++++--------------- tests/xmlrpc-test.c | 2 + 25 files changed, 485 insertions(+), 293 deletions(-) diff --git a/tests/auth-test.c b/tests/auth-test.c index cb9f07fb..8ed5cead 100644 --- a/tests/auth-test.c +++ b/tests/auth-test.c @@ -292,6 +292,8 @@ do_pipelined_auth_test (void) char *uri; int i; + g_test_bug ("271540"); + SOUP_TEST_SKIP_IF_NO_APACHE; session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -632,6 +634,7 @@ do_async_auth_bad_password_test (void) /* Test that giving the wrong password doesn't cause multiple * authenticate signals the second time. */ + g_test_bug ("522601"); SOUP_TEST_SKIP_IF_NO_APACHE; @@ -684,6 +687,7 @@ do_async_auth_no_password_test (void) /* Test that giving no password doesn't cause multiple * authenticate signals the second time. */ + g_test_bug ("583462"); SOUP_TEST_SKIP_IF_NO_APACHE; @@ -852,6 +856,8 @@ do_select_auth_test (void) SoupAuthDomain *basic_auth_domain, *digest_auth_domain; SoupURI *uri; + g_test_bug ("562339"); + /* It doesn't seem to be possible to configure Apache to serve * multiple auth types for a single URL. So we have to use * SoupServer here. We know that SoupServer handles the server @@ -1117,6 +1123,8 @@ do_disappearing_auth_test (void) SoupSession *session; int counter; + g_test_bug ("https://bugzilla.redhat.com/show_bug.cgi?id=916224"); + server = soup_test_server_new (FALSE); soup_server_add_handler (server, NULL, server_callback, NULL, NULL); diff --git a/tests/cache-test.c b/tests/cache-test.c index c499a776..3478f377 100644 --- a/tests/cache-test.c +++ b/tests/cache-test.c @@ -437,6 +437,8 @@ do_cancel_test (gconstpointer data) char *body1, *body2; guint flags; + g_test_bug ("692310"); + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); debug_printf (2, " Caching to %s\n", cache_dir); cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); @@ -522,6 +524,8 @@ do_refcounting_test (gconstpointer data) guint flags; GMainLoop *loop; + g_test_bug ("682527"); + cache_dir = g_dir_make_tmp ("cache-test-XXXXXX", NULL); debug_printf (2, " Caching to %s\n", cache_dir); cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER); diff --git a/tests/chunk-test.c b/tests/chunk-test.c index 7f4fe886..864f8620 100644 --- a/tests/chunk-test.c +++ b/tests/chunk-test.c @@ -282,7 +282,7 @@ do_response_test (void) } /* Make sure TEMPORARY buffers are handled properly with non-accumulating - * message bodies. Part of https://bugs.webkit.org/show_bug.cgi?id=18343 + * message bodies. */ static void @@ -314,6 +314,8 @@ do_temporary_test (void) char *client_md5; const char *server_md5; + g_test_bug ("https://bugs.webkit.org/show_bug.cgi?id=18343"); + msg = soup_message_new_from_uri ("PUT", base_uri); soup_message_body_append (msg->request_body, SOUP_MEMORY_TEMPORARY, "one\r\n", 5); diff --git a/tests/coding-test.c b/tests/coding-test.c index d400ca71..0445f632 100644 --- a/tests/coding-test.c +++ b/tests/coding-test.c @@ -238,6 +238,9 @@ do_coding_test_gzip (CodingTestData *data, gconstpointer test_data) static void do_coding_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("606352"); + g_test_bug ("676477"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "trailing-junk"); @@ -248,6 +251,8 @@ do_coding_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) static void do_coding_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("613361"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode"); @@ -273,6 +278,9 @@ do_coding_test_deflate (CodingTestData *data, gconstpointer test_data) static void do_coding_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("606352"); + g_test_bug ("676477"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); soup_session_send_message (data->session, data->msg); @@ -283,6 +291,8 @@ do_coding_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) static void do_coding_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("613361"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); soup_session_send_message (data->session, data->msg); @@ -303,6 +313,8 @@ do_coding_test_deflate_raw (CodingTestData *data, gconstpointer test_data) static void do_coding_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("613361"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-raw"); soup_session_send_message (data->session, data->msg); @@ -379,6 +391,9 @@ do_coding_req_test_gzip (CodingTestData *data, gconstpointer test_data) static void do_coding_req_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("606352"); + g_test_bug ("676477"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "trailing-junk"); @@ -388,6 +403,8 @@ do_coding_req_test_gzip_with_junk (CodingTestData *data, gconstpointer test_data static void do_coding_req_test_gzip_bad_server (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("613361"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode"); do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED); @@ -404,6 +421,9 @@ do_coding_req_test_deflate (CodingTestData *data, gconstpointer test_data) static void do_coding_req_test_deflate_with_junk (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("606352"); + g_test_bug ("676477"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "prefer-deflate-zlib, trailing-junk"); do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_DECODED); @@ -412,6 +432,8 @@ do_coding_req_test_deflate_with_junk (CodingTestData *data, gconstpointer test_d static void do_coding_req_test_deflate_bad_server (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("613361"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-zlib"); do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED); @@ -428,6 +450,8 @@ do_coding_req_test_deflate_raw (CodingTestData *data, gconstpointer test_data) static void do_coding_req_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("613361"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "force-encode, prefer-deflate-raw"); do_single_coding_req_test (data, "deflate", "text/plain", EXPECT_NOT_DECODED); @@ -436,6 +460,8 @@ do_coding_req_test_deflate_raw_bad_server (CodingTestData *data, gconstpointer t static void do_coding_msg_empty_test (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("697527"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "empty"); soup_session_send_message (data->session, data->msg); @@ -446,6 +472,8 @@ do_coding_msg_empty_test (CodingTestData *data, gconstpointer test_data) static void do_coding_req_empty_test (CodingTestData *data, gconstpointer test_data) { + g_test_bug ("697527"); + soup_message_headers_append (data->msg->request_headers, "X-Test-Options", "empty"); do_single_coding_req_test (data, "gzip", "text/plain", EXPECT_NOT_DECODED); diff --git a/tests/connection-test.c b/tests/connection-test.c index a72d2f0a..8f8c74be 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -166,6 +166,8 @@ do_content_length_framing_test (void) SoupURI *request_uri; goffset declared_length; + g_test_bug ("611481"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); debug_printf (1, " Content-Length larger than message body length\n"); @@ -351,6 +353,8 @@ do_persistent_connection_timeout_test (void) { SoupSession *session; + g_test_bug ("631525"); + debug_printf (1, " Async session, message API\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_timeout_test_for_session (session); @@ -471,6 +475,8 @@ do_max_conns_test (void) { SoupSession *session; + g_test_bug ("634422"); + debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_MAX_CONNS, MAX_CONNS, @@ -548,6 +554,8 @@ do_non_persistent_connection_test (void) { SoupSession *session; + g_test_bug ("578990"); + debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_non_persistent_test_for_session (session); diff --git a/tests/cookies-test.c b/tests/cookies-test.c index 2c986b5f..12529d81 100644 --- a/tests/cookies-test.c +++ b/tests/cookies-test.c @@ -105,6 +105,8 @@ do_cookies_parsing_test (void) SoupCookie *cookie; gboolean got1, got2, got3; + g_test_bug ("678753"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); soup_session_add_feature_by_type (session, SOUP_TYPE_COOKIE_JAR); jar = SOUP_COOKIE_JAR (soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR)); diff --git a/tests/date.c b/tests/date.c index 6b0ff9bb..e51fa57f 100644 --- a/tests/date.c +++ b/tests/date.c @@ -24,18 +24,40 @@ make_date (const char *strdate) return date; } +static SoupDate * +check_correct_date (const char *strdate) +{ + SoupDate *date; + + date = make_date (strdate); + if (!date) { + g_assert_nonnull (date); + return NULL; + } + + g_assert_cmpint (date->year, ==, 2004); + g_assert_cmpint (date->month, ==, 11); + g_assert_cmpint (date->day, ==, 6); + g_assert_cmpint (date->hour, ==, 8); + g_assert_cmpint (date->minute, ==, 9); + g_assert_cmpint (date->second, ==, 7); + + return date; +} + typedef struct { SoupDateFormat format; const char *date; + const char *bugref; } GoodDate; static const GoodDate good_dates[] = { - { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT" }, - { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT" }, - { SOUP_DATE_RFC2822, "Sat, 6 Nov 2004 08:09:07 -0430" }, - { SOUP_DATE_ISO8601_COMPACT, "20041106T080907" }, - { SOUP_DATE_ISO8601_FULL, "2004-11-06T08:09:07" }, - { SOUP_DATE_ISO8601_XMLRPC, "20041106T08:09:07" } + { SOUP_DATE_HTTP, "Sat, 06 Nov 2004 08:09:07 GMT", NULL }, + { SOUP_DATE_COOKIE, "Sat, 06-Nov-2004 08:09:07 GMT", NULL }, + { SOUP_DATE_RFC2822, "Sat, 6 Nov 2004 08:09:07 -0430", "579055" }, + { SOUP_DATE_ISO8601_COMPACT, "20041106T080907", NULL }, + { SOUP_DATE_ISO8601_FULL, "2004-11-06T08:09:07", NULL }, + { SOUP_DATE_ISO8601_XMLRPC, "20041106T08:09:07", NULL } }; static void @@ -45,9 +67,13 @@ check_good (gconstpointer data) SoupDate *date; char *strdate2; - check_ok (good->date); + if (good->bugref) + g_test_bug (good->bugref); + + date = check_correct_date (good->date); + if (!date) + return; - date = make_date (good->date); strdate2 = soup_date_to_string (date, good->format); soup_date_free (date); @@ -57,82 +83,82 @@ check_good (gconstpointer data) g_free (strdate2); } -static const char *ok_dates[] = { +typedef struct { + const char *date; + const char *bugref; +} OkDate; + +static const OkDate ok_dates[] = { /* rfc1123-date, and broken variants */ - "Sat, 06 Nov 2004 08:09:07 GMT", - "Sat, 6 Nov 2004 08:09:07 GMT", - "Sat, 6 Nov 2004 08:09:07 GMT", - "Sat, 06 Nov 2004 08:09:07", - "06 Nov 2004 08:09:07 GMT", - "SAT, 06 NOV 2004 08:09:07 +1000", + { "Sat, 06 Nov 2004 08:09:07 GMT", NULL }, + { "Sat, 6 Nov 2004 08:09:07 GMT", NULL }, + { "Sat, 6 Nov 2004 08:09:07 GMT", NULL }, + { "Sat, 06 Nov 2004 08:09:07", NULL }, + { "06 Nov 2004 08:09:07 GMT", NULL }, + { "SAT, 06 NOV 2004 08:09:07 +1000", "644048" }, /* rfc850-date, and broken variants */ - "Saturday, 06-Nov-04 08:09:07 GMT", - "Saturday, 6-Nov-04 08:09:07 GMT", - "Saturday, 6-Nov-04 08:09:07 GMT", - "Saturday, 06-Nov-104 08:09:07 GMT", - "Saturday, 06-Nov-04 08:09:07", - "06-Nov-04 08:09:07 GMT", + { "Saturday, 06-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-104 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 08:09:07", NULL }, + { "06-Nov-04 08:09:07 GMT", NULL }, /* asctime-date, and broken variants */ - "Sat Nov 6 08:09:07 2004", - "Sat Nov 06 08:09:07 2004", - "Sat Nov 6 08:09:07 2004", - "Sat Nov 6 08:09:07 2004 GMT", + { "Sat Nov 6 08:09:07 2004", NULL }, + { "Sat Nov 06 08:09:07 2004", NULL }, + { "Sat Nov 6 08:09:07 2004", NULL }, + { "Sat Nov 6 08:09:07 2004 GMT", NULL }, /* ISO 8601 */ - "2004-11-06T08:09:07Z", - "20041106T08:09:07Z", - "20041106T08:09:07+00:00", - "20041106T080907+00:00", + { "2004-11-06T08:09:07Z", NULL }, + { "20041106T08:09:07Z", NULL }, + { "20041106T08:09:07+00:00", NULL }, + { "20041106T080907+00:00", NULL }, /* Netscape cookie spec date, and broken variants */ - "Sat, 06-Nov-2004 08:09:07 GMT", - "Sat, 6-Nov-2004 08:09:07 GMT", - "Sat, 6-Nov-2004 08:09:07 GMT", - "Sat, 06-Nov-2004 08:09:07", + { "Sat, 06-Nov-2004 08:09:07 GMT", NULL }, + { "Sat, 6-Nov-2004 08:09:07 GMT", NULL }, + { "Sat, 6-Nov-2004 08:09:07 GMT", NULL }, + { "Sat, 06-Nov-2004 08:09:07", NULL }, /* Original version of Netscape cookie spec, and broken variants */ - "Sat, 06-Nov-04 08:09:07 GMT", - "Sat, 6-Nov-04 08:09:07 GMT", - "Sat, 6-Nov-04 08:09:07 GMT", - "Sat, 06-Nov-104 08:09:07 GMT", - "Sat, 06-Nov-04 08:09:07", + { "Sat, 06-Nov-04 08:09:07 GMT", NULL }, + { "Sat, 6-Nov-04 08:09:07 GMT", NULL }, + { "Sat, 6-Nov-04 08:09:07 GMT", NULL }, + { "Sat, 06-Nov-104 08:09:07 GMT", NULL }, + { "Sat, 06-Nov-04 08:09:07", NULL }, /* Netscape cookie spec example syntax, and broken variants */ - "Saturday, 06-Nov-04 08:09:07 GMT", - "Saturday, 6-Nov-04 08:09:07 GMT", - "Saturday, 6-Nov-04 08:09:07 GMT", - "Saturday, 06-Nov-104 08:09:07 GMT", - "Saturday, 06-Nov-2004 08:09:07 GMT", - "Saturday, 6-Nov-2004 08:09:07 GMT", - "Saturday, 6-Nov-2004 08:09:07 GMT", - "Saturday, 06-Nov-04 08:09:07", + { "Saturday, 06-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-104 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-2004 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-2004 08:09:07 GMT", NULL }, + { "Saturday, 6-Nov-2004 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 08:09:07", NULL }, /* Miscellaneous broken formats seen on the web */ - "Sat 06-Nov-2004 08:9:07", - "Saturday, 06-Nov-04 8:9:07 GMT", - "Sat, 06 Nov 2004 08:09:7 GMT" + { "Sat 06-Nov-2004 08:9:07", NULL }, + { "Saturday, 06-Nov-04 8:9:07 GMT", NULL }, + { "Sat, 06 Nov 2004 08:09:7 GMT", NULL } }; static void check_ok (gconstpointer data) { - const char *strdate = data; + OkDate *ok = (OkDate *)data; SoupDate *date; - date = make_date (strdate); - if (!date) { - g_assert_true (date != NULL); - return; - } + if (ok->bugref) + g_test_bug (ok->bugref); - g_assert_cmpint (date->year, ==, 2004); - g_assert_cmpint (date->month, ==, 11); - g_assert_cmpint (date->day, ==, 6); - g_assert_cmpint (date->hour, ==, 8); - g_assert_cmpint (date->minute, ==, 9); - g_assert_cmpint (date->second, ==, 7); + date = check_correct_date (ok->date); + if (!date) + return; + soup_date_free (date); } #define TIME_T 1099728547L @@ -153,52 +179,60 @@ check_ok_time_t (void) g_assert_cmpint (date->second, ==, 7); } -static const char *bad_dates[] = { +typedef struct { + const char *date; + const char *bugref; +} BadDate; + +static const BadDate bad_dates[] = { /* broken rfc1123-date */ - ", 06 Nov 2004 08:09:07 GMT", - "Sat, Nov 2004 08:09:07 GMT", - "Sat, 06 2004 08:09:07 GMT", - "Sat, 06 Nov 08:09:07 GMT", - "Sat, 06 Nov 2004 :09:07 GMT", - "Sat, 06 Nov 2004 09:07 GMT", - "Sat, 06 Nov 2004 08::07 GMT", - "Sat, 06 Nov 2004 08:09: GMT", + { ", 06 Nov 2004 08:09:07 GMT", NULL }, + { "Sat, Nov 2004 08:09:07 GMT", NULL }, + { "Sat, 06 2004 08:09:07 GMT", NULL }, + { "Sat, 06 Nov 08:09:07 GMT", NULL }, + { "Sat, 06 Nov 2004 :09:07 GMT", NULL }, + { "Sat, 06 Nov 2004 09:07 GMT", NULL }, + { "Sat, 06 Nov 2004 08::07 GMT", NULL }, + { "Sat, 06 Nov 2004 08:09: GMT", NULL }, /* broken rfc850-date */ - ", 06-Nov-04 08:09:07 GMT", - "Saturday, -Nov-04 08:09:07 GMT", - "Saturday, Nov-04 08:09:07 GMT", - "Saturday, 06-04 08:09:07 GMT", - "Saturday, 06--04 08:09:07 GMT", - "Saturday, 06-Nov- 08:09:07 GMT", - "Saturday, 06-Nov 08:09:07 GMT", - "Saturday, 06-Nov-04 :09:07 GMT", - "Saturday, 06-Nov-04 09:07 GMT", - "Saturday, 06-Nov-04 08::07 GMT", - "Saturday, 06-Nov-04 08:09: GMT", + { ", 06-Nov-04 08:09:07 GMT", NULL }, + { "Saturday, -Nov-04 08:09:07 GMT", NULL }, + { "Saturday, Nov-04 08:09:07 GMT", NULL }, + { "Saturday, 06-04 08:09:07 GMT", NULL }, + { "Saturday, 06--04 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov- 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov 08:09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 :09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 09:07 GMT", NULL }, + { "Saturday, 06-Nov-04 08::07 GMT", NULL }, + { "Saturday, 06-Nov-04 08:09: GMT", NULL }, /* broken asctime-date */ - "Nov 6 08:09:07 2004", - "Sat 6 08:09:07 2004", - "Sat Nov 08:09:07 2004", - "Sat Nov 6 :09:07 2004", - "Sat Nov 6 09:07 2004", - "Sat Nov 6 08::07 2004", - "Sat Nov 6 08:09: 2004", - "Sat Nov 6 08:09:07", - "Sat Nov 6 08:09:07 GMT 2004" + { "Nov 6 08:09:07 2004", NULL }, + { "Sat 6 08:09:07 2004", NULL }, + { "Sat Nov 08:09:07 2004", NULL }, + { "Sat Nov 6 :09:07 2004", NULL }, + { "Sat Nov 6 09:07 2004", NULL }, + { "Sat Nov 6 08::07 2004", NULL }, + { "Sat Nov 6 08:09: 2004", NULL }, + { "Sat Nov 6 08:09:07", NULL }, + { "Sat Nov 6 08:09:07 GMT 2004", NULL } }; static void check_bad (gconstpointer data) { - const char *strdate = data; + BadDate *bad = (BadDate *)data; SoupDate *date; - date = make_date (strdate); + if (bad->bugref) + g_test_bug (bad->bugref); + + date = make_date (bad->date); soup_test_assert (date == NULL, "date parsing succeeded for '%s': %d %d %d - %d %d %d", - strdate, + bad->date, date->year, date->month, date->day, date->hour, date->minute, date->second); g_clear_pointer (&date, soup_date_free); @@ -356,15 +390,15 @@ main (int argc, char **argv) } for (i = 0; i < G_N_ELEMENTS (ok_dates); i++) { - path = g_strdup_printf ("/date/ok/%s", ok_dates[i]); - g_test_add_data_func (path, ok_dates[i], check_ok); + path = g_strdup_printf ("/date/ok/%s", ok_dates[i].date); + g_test_add_data_func (path, &ok_dates[i], check_ok); g_free (path); } g_test_add_func ("/date/ok/" TIME_T_STRING, check_ok_time_t); for (i = 0; i < G_N_ELEMENTS (bad_dates); i++) { - path = g_strdup_printf ("/date/bad/%s", bad_dates[i]); - g_test_add_data_func (path, bad_dates[i], check_bad); + path = g_strdup_printf ("/date/bad/%s", bad_dates[i].date); + g_test_add_data_func (path, &bad_dates[i], check_bad); g_free (path); } diff --git a/tests/forms-test.c b/tests/forms-test.c index 1d89743b..3915b019 100644 --- a/tests/forms-test.c +++ b/tests/forms-test.c @@ -188,6 +188,8 @@ do_md5_test_libsoup (gconstpointer data) SoupMessage *msg; SoupSession *session; + g_test_bug ("601640"); + md5 = get_md5_data (&contents, &length); if (!md5) return; diff --git a/tests/header-parsing.c b/tests/header-parsing.c index b5f6bf2f..fdc7885d 100644 --- a/tests/header-parsing.c +++ b/tests/header-parsing.c @@ -8,6 +8,7 @@ typedef struct { static struct RequestTest { const char *description; + const char *bugref; const char *request; int length; guint status; @@ -19,14 +20,14 @@ static struct RequestTest { /*** VALID REQUESTS ***/ /**********************/ - { "HTTP 1.0 request with no headers", + { "HTTP 1.0 request with no headers", NULL, "GET / HTTP/1.0\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_0, { { NULL } } }, - { "Req w/ 1 header", + { "Req w/ 1 header", NULL, "GET / HTTP/1.1\r\nHost: example.com\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -35,7 +36,7 @@ static struct RequestTest { } }, - { "Req w/ 1 header, no leading whitespace", + { "Req w/ 1 header, no leading whitespace", NULL, "GET / HTTP/1.1\r\nHost:example.com\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -44,7 +45,7 @@ static struct RequestTest { } }, - { "Req w/ 1 header including trailing whitespace", + { "Req w/ 1 header including trailing whitespace", NULL, "GET / HTTP/1.1\r\nHost: example.com \r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -53,7 +54,7 @@ static struct RequestTest { } }, - { "Req w/ 1 header, wrapped", + { "Req w/ 1 header, wrapped", NULL, "GET / HTTP/1.1\r\nFoo: bar\r\n baz\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -62,7 +63,7 @@ static struct RequestTest { } }, - { "Req w/ 1 header, wrapped with additional whitespace", + { "Req w/ 1 header, wrapped with additional whitespace", NULL, "GET / HTTP/1.1\r\nFoo: bar \r\n baz\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -71,7 +72,7 @@ static struct RequestTest { } }, - { "Req w/ 1 header, wrapped with tab", + { "Req w/ 1 header, wrapped with tab", NULL, "GET / HTTP/1.1\r\nFoo: bar\r\n\tbaz\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -80,7 +81,7 @@ static struct RequestTest { } }, - { "Req w/ 1 header, wrapped before value", + { "Req w/ 1 header, wrapped before value", NULL, "GET / HTTP/1.1\r\nFoo:\r\n bar baz\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -89,7 +90,7 @@ static struct RequestTest { } }, - { "Req w/ 1 header with empty value", + { "Req w/ 1 header with empty value", NULL, "GET / HTTP/1.1\r\nHost:\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -98,7 +99,7 @@ static struct RequestTest { } }, - { "Req w/ 2 headers", + { "Req w/ 2 headers", NULL, "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -108,7 +109,7 @@ static struct RequestTest { } }, - { "Req w/ 3 headers", + { "Req w/ 3 headers", NULL, "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\nBlah: blah\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -119,7 +120,7 @@ static struct RequestTest { } }, - { "Req w/ 3 headers, 1st wrapped", + { "Req w/ 3 headers, 1st wrapped", NULL, "GET / HTTP/1.1\r\nFoo: bar\r\n baz\r\nConnection: close\r\nBlah: blah\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -130,7 +131,7 @@ static struct RequestTest { } }, - { "Req w/ 3 headers, 2nd wrapped", + { "Req w/ 3 headers, 2nd wrapped", NULL, "GET / HTTP/1.1\r\nConnection: close\r\nBlah: blah\r\nFoo: bar\r\n baz\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -141,7 +142,7 @@ static struct RequestTest { } }, - { "Req w/ 3 headers, 3rd wrapped", + { "Req w/ 3 headers, 3rd wrapped", NULL, "GET / HTTP/1.1\r\nConnection: close\r\nBlah: blah\r\nFoo: bar\r\n baz\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -152,7 +153,7 @@ static struct RequestTest { } }, - { "Req w/ same header multiple times", + { "Req w/ same header multiple times", NULL, "GET / HTTP/1.1\r\nFoo: bar\r\nFoo: baz\r\nFoo: quux\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -161,7 +162,7 @@ static struct RequestTest { } }, - { "Connection header on HTTP/1.0 message", + { "Connection header on HTTP/1.0 message", NULL, "GET / HTTP/1.0\r\nFoo: bar\r\nConnection: Bar, Quux\r\nBar: baz\r\nQuux: foo\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_0, @@ -171,14 +172,14 @@ static struct RequestTest { } }, - { "GET with full URI", + { "GET with full URI", "667637", "GET http://example.com HTTP/1.1\r\n", -1, SOUP_STATUS_OK, "GET", "http://example.com", SOUP_HTTP_1_1, { { NULL } } }, - { "GET with full URI in upper-case", + { "GET with full URI in upper-case", "667637", "GET HTTP://example.com HTTP/1.1\r\n", -1, SOUP_STATUS_OK, "GET", "HTTP://example.com", SOUP_HTTP_1_1, @@ -188,7 +189,7 @@ static struct RequestTest { /* It's better for this to be passed through: this means a SoupServer * could implement ftp-over-http proxying, for instance */ - { "GET with full URI of unrecognised scheme", + { "GET with full URI of unrecognised scheme", "667637", "GET AbOuT: HTTP/1.1\r\n", -1, SOUP_STATUS_OK, "GET", "AbOuT:", SOUP_HTTP_1_1, @@ -201,7 +202,7 @@ static struct RequestTest { /* RFC 2616 section 4.1 says we SHOULD accept this */ - { "Spurious leading CRLF", + { "Spurious leading CRLF", NULL, "\r\nGET / HTTP/1.1\r\nHost: example.com\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -212,7 +213,7 @@ static struct RequestTest { /* RFC 2616 section 3.1 says we MUST accept this */ - { "HTTP/01.01 request", + { "HTTP/01.01 request", NULL, "GET / HTTP/01.01\r\nHost: example.com\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -223,7 +224,7 @@ static struct RequestTest { /* RFC 2616 section 19.3 says we SHOULD accept these */ - { "LF instead of CRLF after header", + { "LF instead of CRLF after header", NULL, "GET / HTTP/1.1\r\nHost: example.com\nConnection: close\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -233,7 +234,7 @@ static struct RequestTest { } }, - { "LF instead of CRLF after Request-Line", + { "LF instead of CRLF after Request-Line", NULL, "GET / HTTP/1.1\nHost: example.com\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -242,7 +243,7 @@ static struct RequestTest { } }, - { "Mixed CRLF/LF", + { "Mixed CRLF/LF", "666316", "GET / HTTP/1.1\r\na: b\r\nc: d\ne: f\r\ng: h\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -254,7 +255,7 @@ static struct RequestTest { } }, - { "Req w/ incorrect whitespace in Request-Line", + { "Req w/ incorrect whitespace in Request-Line", NULL, "GET /\tHTTP/1.1\r\nHost: example.com\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -263,7 +264,7 @@ static struct RequestTest { } }, - { "Req w/ incorrect whitespace after Request-Line", + { "Req w/ incorrect whitespace after Request-Line", "475169", "GET / HTTP/1.1 \r\nHost: example.com\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -274,10 +275,9 @@ static struct RequestTest { /* If the request/status line is parseable, then we * just ignore any invalid-looking headers after that. - * (qv bug 579318). */ - { "Req w/ mangled header", + { "Req w/ mangled header", "579318", "GET / HTTP/1.1\r\nHost: example.com\r\nFoo one\r\nBar: two\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -287,7 +287,7 @@ static struct RequestTest { } }, - { "First header line is continuation", + { "First header line is continuation", "666316", "GET / HTTP/1.1\r\n b\r\nHost: example.com\r\nc: d\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -297,7 +297,7 @@ static struct RequestTest { } }, - { "Zero-length header name", + { "Zero-length header name", "666316", "GET / HTTP/1.1\r\na: b\r\n: example.com\r\nc: d\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -307,7 +307,7 @@ static struct RequestTest { } }, - { "CR in header name", + { "CR in header name", "666316", "GET / HTTP/1.1\r\na: b\r\na\rb: cd\r\nx\r: y\r\n\rz: w\r\nc: d\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -317,7 +317,7 @@ static struct RequestTest { } }, - { "CR in header value", + { "CR in header value", "666316", "GET / HTTP/1.1\r\na: b\r\nHost: example\rcom\r\np: \rq\r\ns: t\r\r\nc: d\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -330,7 +330,7 @@ static struct RequestTest { } }, - { "Tab in header name", + { "Tab in header name", "666316", "GET / HTTP/1.1\r\na: b\r\na\tb: cd\r\nx\t: y\r\np: q\r\n\tz: w\r\nc: d\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -345,7 +345,7 @@ static struct RequestTest { } }, - { "Tab in header value", + { "Tab in header value", "666316", "GET / HTTP/1.1\r\na: b\r\nab: c\td\r\nx: \ty\r\nz: w\t\r\nc: d\r\n", -1, SOUP_STATUS_OK, "GET", "/", SOUP_HTTP_1_1, @@ -362,84 +362,84 @@ static struct RequestTest { /*** INVALID REQUESTS ***/ /************************/ - { "HTTP 0.9 request; not supported", + { "HTTP 0.9 request; not supported", NULL, "GET /\r\n", -1, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "HTTP 1.2 request (no such thing)", + { "HTTP 1.2 request (no such thing)", NULL, "GET / HTTP/1.2\r\n", -1, SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED, NULL, NULL, -1, { { NULL } } }, - { "HTTP 2000 request (no such thing)", + { "HTTP 2000 request (no such thing)", NULL, "GET / HTTP/2000.0\r\n", -1, SOUP_STATUS_HTTP_VERSION_NOT_SUPPORTED, NULL, NULL, -1, { { NULL } } }, - { "Non-HTTP request", + { "Non-HTTP request", NULL, "GET / SOUP/1.1\r\nHost: example.com\r\n", -1, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "Junk after Request-Line", + { "Junk after Request-Line", NULL, "GET / HTTP/1.1 blah\r\nHost: example.com\r\n", -1, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "NUL in Method", + { "NUL in Method", NULL, "G\x00T / HTTP/1.1\r\nHost: example.com\r\n", 37, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "NUL at beginning of Method", + { "NUL at beginning of Method", "666316", "\x00 / HTTP/1.1\r\nHost: example.com\r\n", 35, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "NUL in Path", + { "NUL in Path", NULL, "GET /\x00 HTTP/1.1\r\nHost: example.com\r\n", 38, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "NUL in header name", + { "NUL in header name", "666316", "GET / HTTP/1.1\r\n\x00: silly\r\n", 37, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "NUL in header value", + { "NUL in header value", NULL, "GET / HTTP/1.1\r\nHost: example\x00com\r\n", 37, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "No terminating CRLF", + { "No terminating CRLF", NULL, "GET / HTTP/1.1\r\nHost: example.com", -1, SOUP_STATUS_BAD_REQUEST, NULL, NULL, -1, { { NULL } } }, - { "Unrecognized expectation", + { "Unrecognized expectation", NULL, "GET / HTTP/1.1\r\nHost: example.com\r\nExpect: the-impossible\r\n", -1, SOUP_STATUS_EXPECTATION_FAILED, NULL, NULL, -1, @@ -450,6 +450,7 @@ static const int num_reqtests = G_N_ELEMENTS (reqtests); static struct ResponseTest { const char *description; + const char *bugref; const char *response; int length; SoupHTTPVersion version; @@ -461,25 +462,25 @@ static struct ResponseTest { /*** VALID RESPONSES ***/ /***********************/ - { "HTTP 1.0 response w/ no headers", + { "HTTP 1.0 response w/ no headers", NULL, "HTTP/1.0 200 ok\r\n", -1, SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok", { { NULL } } }, - { "HTTP 1.1 response w/ no headers", + { "HTTP 1.1 response w/ no headers", NULL, "HTTP/1.1 200 ok\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { NULL } } }, - { "Response w/ multi-word Reason-Phrase", + { "Response w/ multi-word Reason-Phrase", NULL, "HTTP/1.1 400 bad request\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_BAD_REQUEST, "bad request", { { NULL } } }, - { "Response w/ 1 header", + { "Response w/ 1 header", NULL, "HTTP/1.1 200 ok\r\nFoo: bar\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "bar" }, @@ -487,7 +488,7 @@ static struct ResponseTest { } }, - { "Response w/ 2 headers", + { "Response w/ 2 headers", NULL, "HTTP/1.1 200 ok\r\nFoo: bar\r\nBaz: quux\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "bar" }, @@ -496,7 +497,7 @@ static struct ResponseTest { } }, - { "Response w/ same header multiple times", + { "Response w/ same header multiple times", NULL, "HTTP/1.1 200 ok\r\nFoo: bar\r\nFoo: baz\r\nFoo: quux\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "bar, baz, quux" }, @@ -504,7 +505,7 @@ static struct ResponseTest { } }, - { "Response w/ no reason phrase", + { "Response w/ no reason phrase", NULL, "HTTP/1.1 200 \r\nFoo: bar\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "", { { "Foo", "bar" }, @@ -512,7 +513,7 @@ static struct ResponseTest { } }, - { "Connection header on HTTP/1.0 message", + { "Connection header on HTTP/1.0 message", NULL, "HTTP/1.0 200 ok\r\nFoo: bar\r\nConnection: Bar\r\nBar: quux\r\n", -1, SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok", { { "Foo", "bar" }, @@ -523,7 +524,7 @@ static struct ResponseTest { /* Tests from Cockpit */ - { "Response w/ 3 headers, check case-insensitivity", + { "Response w/ 3 headers, check case-insensitivity", "722341", "HTTP/1.0 200 ok\r\nHeader1: value3\r\nHeader2: field\r\nHead3: Another \r\n", -1, SOUP_HTTP_1_0, SOUP_STATUS_OK, "ok", { { "header1", "value3" }, @@ -540,7 +541,7 @@ static struct ResponseTest { /* RFC 2616 section 3.1 says we MUST accept this */ - { "HTTP/01.01 response", + { "HTTP/01.01 response", NULL, "HTTP/01.01 200 ok\r\nFoo: bar\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "bar" }, @@ -550,7 +551,7 @@ static struct ResponseTest { /* RFC 2616 section 19.3 says we SHOULD accept these */ - { "Response w/ LF instead of CRLF after Status-Line", + { "Response w/ LF instead of CRLF after Status-Line", NULL, "HTTP/1.1 200 ok\nFoo: bar\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "bar" }, @@ -558,7 +559,7 @@ static struct ResponseTest { } }, - { "Response w/ incorrect spacing in Status-Line", + { "Response w/ incorrect spacing in Status-Line", NULL, "HTTP/1.1 200\tok\r\nFoo: bar\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "bar" }, @@ -566,7 +567,7 @@ static struct ResponseTest { } }, - { "Response w/ no reason phrase or preceding SP", + { "Response w/ no reason phrase or preceding SP", NULL, "HTTP/1.1 200\r\nFoo: bar\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "", { { "Foo", "bar" }, @@ -574,7 +575,7 @@ static struct ResponseTest { } }, - { "Response w/ no whitespace after status code", + { "Response w/ no whitespace after status code", NULL, "HTTP/1.1 200ok\r\nFoo: bar\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "bar" }, @@ -583,7 +584,7 @@ static struct ResponseTest { }, /* Shoutcast support */ - { "Shoutcast server not-quite-HTTP", + { "Shoutcast server not-quite-HTTP", "502325", "ICY 200 OK\r\nFoo: bar\r\n", -1, SOUP_HTTP_1_0, SOUP_STATUS_OK, "OK", { { "Foo", "bar" }, @@ -591,8 +592,7 @@ static struct ResponseTest { } }, - /* qv bug 579318, do_bad_header_tests() below */ - { "Response w/ mangled header", + { "Response w/ mangled header", "579318", "HTTP/1.1 200 ok\r\nFoo: one\r\nBar two:2\r\nBaz: three\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "one" }, @@ -601,8 +601,7 @@ static struct ResponseTest { } }, - /* qv bug 602863 */ - { "HTTP 1.1 response with leading line break", + { "HTTP 1.1 response with leading line break", "602863", "\nHTTP/1.1 200 ok\r\nFoo: bar\r\n", -1, SOUP_HTTP_1_1, SOUP_STATUS_OK, "ok", { { "Foo", "bar" }, @@ -613,79 +612,79 @@ static struct ResponseTest { /*** INVALID RESPONSES ***/ /*************************/ - { "Invalid HTTP version", + { "Invalid HTTP version", NULL, "HTTP/1.2 200 OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "Non-HTTP response", + { "Non-HTTP response", NULL, "SOUP/1.1 200 OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "Non-numeric status code", + { "Non-numeric status code", NULL, "HTTP/1.1 XXX OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "No status code", + { "No status code", NULL, "HTTP/1.1 OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "One-digit status code", + { "One-digit status code", NULL, "HTTP/1.1 2 OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "Two-digit status code", + { "Two-digit status code", NULL, "HTTP/1.1 20 OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "Four-digit status code", + { "Four-digit status code", NULL, "HTTP/1.1 2000 OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "Status code < 100", + { "Status code < 100", NULL, "HTTP/1.1 001 OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "Status code > 599", + { "Status code > 599", NULL, "HTTP/1.1 600 OK\r\nFoo: bar\r\n", -1, -1, 0, NULL, { { NULL } } }, - { "NUL at start", + { "NUL at start", "666316", "\x00HTTP/1.1 200 OK\r\nFoo: bar\r\n", 28, -1, 0, NULL, { { NULL } } }, - { "NUL in Reason Phrase", + { "NUL in Reason Phrase", NULL, "HTTP/1.1 200 O\x00K\r\nFoo: bar\r\n", 28, -1, 0, NULL, { { NULL } } }, - { "NUL in header name", + { "NUL in header name", NULL, "HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28, -1, 0, NULL, { { NULL } } }, - { "NUL in header value", + { "NUL in header value", NULL, "HTTP/1.1 200 OK\r\nFoo: b\x00ar\r\n", 28, -1, 0, NULL, { { NULL } } @@ -939,7 +938,8 @@ do_content_disposition_tests (void) soup_message_headers_free (hdrs); - /* Ensure that soup-multipart always quotes filename (bug 641280) */ + /* Ensure that soup-multipart always quotes filename */ + g_test_bug ("641280"); multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART); buffer = soup_buffer_new (SOUP_MEMORY_STATIC, "foo", 3); soup_multipart_append_form_file (multipart, "test", "token", @@ -974,6 +974,8 @@ do_content_type_tests (void) GHashTable *params; const char *header, *mime_type; + g_test_bug ("576760"); + hdrs = soup_message_headers_new (SOUP_MESSAGE_HEADERS_MULTIPART); params = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (params, CONTENT_TYPE_TEST_ATTRIBUTE, @@ -997,6 +999,8 @@ do_content_type_tests (void) if (params) g_hash_table_destroy (params); + g_test_bug ("577630"); + soup_message_headers_clear (hdrs); soup_message_headers_append (hdrs, "Content-Type", CONTENT_TYPE_BAD_HEADER); @@ -1024,6 +1028,8 @@ do_append_param_tests (void) GString *params; int i; + g_test_bug ("577728"); + params = g_string_new (NULL); for (i = 0; i < G_N_ELEMENTS (test_params); i++) { if (i > 0) diff --git a/tests/misc-test.c b/tests/misc-test.c index 1f6e7773..00559a03 100644 --- a/tests/misc-test.c +++ b/tests/misc-test.c @@ -91,7 +91,6 @@ server_callback (SoupServer *server, SoupMessage *msg, /* Host header handling: client must be able to override the default * value, server must be able to recognize different Host values. - * #539803. */ static void do_host_test (void) @@ -99,6 +98,8 @@ do_host_test (void) SoupSession *session; SoupMessage *one, *two; + g_test_bug ("539803"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); one = soup_message_new_from_uri ("GET", base_uri); @@ -121,7 +122,7 @@ do_host_test (void) /* Dropping the application's ref on the session from a callback * should not cause the session to be freed at an incorrect time. - * (This test will crash if it fails.) #533473 + * (This test will crash if it fails.) */ static void cu_one_completed (SoupSession *session, SoupMessage *msg, gpointer loop) @@ -156,6 +157,8 @@ do_callback_unref_test (void) GMainLoop *loop; char *bad_uri; + g_test_bug ("533473"); + /* Get a guaranteed-bad URI */ addr = soup_address_new ("127.0.0.1", SOUP_ADDRESS_ANY_PORT); soup_address_resolve_sync (addr, NULL); @@ -301,7 +304,6 @@ do_callback_unref_req_test (void) /* SoupSession should clean up all signal handlers on a message after * it is finished, allowing the message to be reused if desired. - * #559054 */ static void ensure_no_signal_handlers (SoupMessage *msg, guint *signal_ids, guint n_signal_ids) @@ -337,6 +339,8 @@ do_msg_reuse_test (void) SoupURI *uri; guint *signal_ids, n_signal_ids; + g_test_bug ("559054"); + signal_ids = g_signal_list_ids (SOUP_TYPE_MESSAGE, &n_signal_ids); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); @@ -375,7 +379,7 @@ do_msg_reuse_test (void) g_free (signal_ids); } -/* Handle unexpectedly-early aborts. #596074, #618641 */ +/* Handle unexpectedly-early aborts. */ static void ea_msg_completed_one (SoupSession *session, SoupMessage *msg, gpointer loop) { @@ -427,6 +431,9 @@ do_early_abort_test (void) GMainContext *context; GMainLoop *loop; + g_test_bug ("596074"); + g_test_bug ("618641"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); msg = soup_message_new_from_uri ("GET", base_uri); @@ -457,6 +464,8 @@ do_early_abort_test (void) soup_test_session_abort_unref (session); + g_test_bug ("668098"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); msg = soup_message_new_from_uri ("GET", base_uri); @@ -608,6 +617,8 @@ do_accept_language_test (void) { const char *orig_language; + g_test_bug ("602547"); + orig_language = g_getenv ("LANGUAGE"); do_one_accept_language_test ("C", "en"); do_one_accept_language_test ("fr_FR", "fr-fr, fr;q=0.9"); @@ -691,6 +702,9 @@ do_cancel_while_reading_test (void) { SoupSession *session; + g_test_bug ("637741"); + g_test_bug ("676038"); + debug_printf (1, " Async session\n"); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_cancel_while_reading_test_for_session (session); @@ -730,6 +744,8 @@ do_cancel_while_reading_immediate_req_test (void) SoupSession *session; guint flags; + g_test_bug ("692310"); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_IMMEDIATE; debug_printf (1, " Async session\n"); @@ -774,6 +790,8 @@ do_cancel_while_reading_preemptive_req_test (void) SoupSession *session; guint flags; + g_test_bug ("637039"); + flags = SOUP_TEST_REQUEST_CANCEL_CANCELLABLE | SOUP_TEST_REQUEST_CANCEL_PREEMPTIVE; debug_printf (1, " Async session\n"); @@ -852,6 +870,8 @@ do_idle_on_dispose_test (void) SoupMessage *msg; GMainContext *async_context; + g_test_bug ("667364"); + async_context = g_main_context_new (); session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_ASYNC_CONTEXT, async_context, @@ -880,6 +900,8 @@ do_pause_abort_test (void) SoupMessage *msg; gpointer ptr; + g_test_bug ("673905"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); msg = soup_message_new_from_uri ("GET", base_uri); diff --git a/tests/no-ssl-test.c b/tests/no-ssl-test.c index 0062c8c0..82532c74 100644 --- a/tests/no-ssl-test.c +++ b/tests/no-ssl-test.c @@ -28,6 +28,8 @@ do_ssl_tests (gconstpointer uri) { SoupSession *session; + g_test_bug ("700518"); + debug_printf (1, " plain\n"); session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); do_ssl_test_for_session (session, uri); @@ -52,6 +54,8 @@ do_session_property_tests (void) char *ca_file; SoupSession *session; + g_test_bug ("700518"); + session = soup_session_async_new (); g_object_get (G_OBJECT (session), @@ -101,7 +105,7 @@ do_session_property_tests (void) static void server_handler (SoupServer *server, - SoupMessage *msg, + SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *client, diff --git a/tests/ntlm-test.c b/tests/ntlm-test.c index 7aa532ed..24a0f2e4 100644 --- a/tests/ntlm-test.c +++ b/tests/ntlm-test.c @@ -540,6 +540,8 @@ do_retrying_test (gconstpointer data) SoupURI *uri; gboolean retried = FALSE; + g_test_bug ("693222"); + g_setenv ("SOUP_NTLM_AUTH_DEBUG", "", TRUE); debug_printf (1, " /alice\n"); diff --git a/tests/proxy-test.c b/tests/proxy-test.c index 599ff4e8..4b6679b3 100644 --- a/tests/proxy-test.c +++ b/tests/proxy-test.c @@ -6,15 +6,16 @@ typedef struct { const char *explanation; const char *url; const guint final_status; + const char *bugref; } SoupProxyTest; static SoupProxyTest tests[] = { - { "GET -> 200", "", SOUP_STATUS_OK }, - { "GET -> 404", "/not-found", SOUP_STATUS_NOT_FOUND }, - { "GET -> 401 -> 200", "/Basic/realm1/", SOUP_STATUS_OK }, - { "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED }, - { "GET -> 403", "http://no-such-hostname.xx/", SOUP_STATUS_FORBIDDEN }, - { "GET -> 200 (unproxied)", "http://localhost:47524/", SOUP_STATUS_OK }, + { "GET -> 200", "", SOUP_STATUS_OK, NULL }, + { "GET -> 404", "/not-found", SOUP_STATUS_NOT_FOUND, NULL }, + { "GET -> 401 -> 200", "/Basic/realm1/", SOUP_STATUS_OK, NULL }, + { "GET -> 401 -> 401", "/Basic/realm2/", SOUP_STATUS_UNAUTHORIZED, NULL }, + { "GET -> 403", "http://no-such-hostname.xx/", SOUP_STATUS_FORBIDDEN, "577532" }, + { "GET -> 200 (unproxied)", "http://localhost:47524/", SOUP_STATUS_OK, "700472" }, }; static const int ntests = sizeof (tests) / sizeof (tests[0]); @@ -101,6 +102,7 @@ test_url (const char *url, int proxy, guint expected, g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), NULL); if (close) { + /* FIXME g_test_bug ("611663") */ g_signal_connect (session, "request-started", G_CALLBACK (set_close_on_connect), NULL); } @@ -131,6 +133,7 @@ test_url_new_api (const char *url, int proxy, guint expected, GError *error = NULL; gboolean noproxy = !!strstr (url, "localhost"); + /* FIXME g_test_skip() FIXME g_test_bug ("675865") */ if (!tls_available && g_str_has_prefix (url, "https:")) return; @@ -151,6 +154,7 @@ test_url_new_api (const char *url, int proxy, guint expected, g_signal_connect (session, "authenticate", G_CALLBACK (authenticate), NULL); if (close) { + /* FIXME g_test_bug ("611663") */ g_signal_connect (session, "request-started", G_CALLBACK (set_close_on_connect), NULL); } @@ -183,6 +187,9 @@ do_proxy_test (SoupProxyTest *test, gboolean sync) { char *http_url, *https_url; + if (test->bugref) + g_test_bug (test->bugref); + if (!strncmp (test->url, "http", 4)) { SoupURI *uri; guint port; @@ -286,6 +293,8 @@ do_proxy_redirect_test (void) SoupURI *proxy_uri, *req_uri, *new_uri; SoupMessage *msg; + g_test_bug ("631368"); + SOUP_TEST_SKIP_IF_NO_APACHE; SOUP_TEST_SKIP_IF_NO_TLS; diff --git a/tests/redirect-test.c b/tests/redirect-test.c index c9079cf6..ad8dabaa 100644 --- a/tests/redirect-test.c +++ b/tests/redirect-test.c @@ -19,7 +19,7 @@ typedef struct { typedef struct { TestRequest requests[3]; guint final_status; - guint request_api_final_status; + const char *bugref; } TestCase; static TestCase tests[] = { @@ -27,95 +27,95 @@ static TestCase tests[] = { { { { "GET", "/301", 301 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "GET", "/302", 302 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "GET", "/303", 303 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "GET", "/307", 307 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "HEAD", "/301", 301 }, { "HEAD", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "551190" }, { { { "HEAD", "/302", 302 }, { "HEAD", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "551190" }, /* 303 is a nonsensical response to HEAD, but some sites do * it anyway. :-/ */ { { { "HEAD", "/303", 303 }, { "HEAD", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "600830" }, { { { "HEAD", "/307", 307 }, { "HEAD", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "551190" }, /* A non-redirecty response to a GET or HEAD should not */ { { { "GET", "/300", 300 }, - { NULL } }, 300 }, + { NULL } }, 300, NULL }, { { { "GET", "/304", 304 }, - { NULL } }, 304 }, + { NULL } }, 304, NULL }, { { { "GET", "/305", 305 }, - { NULL } }, 305 }, + { NULL } }, 305, NULL }, { { { "GET", "/306", 306 }, - { NULL } }, 306 }, + { NULL } }, 306, NULL }, { { { "GET", "/308", 308 }, - { NULL } }, 308 }, + { NULL } }, 308, NULL }, { { { "HEAD", "/300", 300 }, - { NULL } }, 300 }, + { NULL } }, 300, "551190" }, { { { "HEAD", "/304", 304 }, - { NULL } }, 304 }, + { NULL } }, 304, "551190" }, { { { "HEAD", "/305", 305 }, - { NULL } }, 305 }, + { NULL } }, 305, "551190" }, { { { "HEAD", "/306", 306 }, - { NULL } }, 306 }, + { NULL } }, 306, "551190" }, { { { "HEAD", "/308", 308 }, - { NULL } }, 308 }, + { NULL } }, 308, "551190" }, /* Test double-redirect */ { { { "GET", "/301/302", 301 }, { "GET", "/302", 302 }, - { "GET", "/", 200 } }, 200 }, + { "GET", "/", 200 } }, 200, NULL }, { { { "HEAD", "/301/302", 301 }, { "HEAD", "/302", 302 }, - { "HEAD", "/", 200 } }, 200 }, + { "HEAD", "/", 200 } }, 200, "551190" }, /* POST should only automatically redirect on 301, 302 and 303 */ { { { "POST", "/301", 301 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "586692" }, { { { "POST", "/302", 302 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "POST", "/303", 303 }, { "GET", "/", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, { { { "POST", "/307", 307 }, - { NULL } }, 307 }, + { NULL } }, 307, NULL }, /* Test behavior with recoverably-bad Location header */ { { { "GET", "/bad", 302 }, { "GET", "/bad%20with%20spaces", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, "566530" }, /* Test behavior with irrecoverably-bad Location header */ { { { "GET", "/bad-no-host", 302 }, - { NULL } }, SOUP_STATUS_MALFORMED, 302 }, + { NULL } }, SOUP_STATUS_MALFORMED, "528882" }, /* Test infinite redirection */ { { { "GET", "/bad-recursive", 302, TRUE }, - { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS }, + { NULL } }, SOUP_STATUS_TOO_MANY_REDIRECTS, "604383" }, /* Test redirection to a different server */ { { { "GET", "/server2", 302 }, { "GET", "/on-server2", 200 }, - { NULL } }, 200 }, + { NULL } }, 200, NULL }, }; static const int n_tests = G_N_ELEMENTS (tests); @@ -163,6 +163,9 @@ do_message_api_test (SoupSession *session, TestCase *test) SoupMessage *msg; TestRequest *treq; + if (test->bugref) + g_test_bug (test->bugref); + uri = soup_uri_new_with_base (base_uri, test->requests[0].path); msg = soup_message_new_from_uri (test->requests[0].method, uri); soup_uri_free (uri); @@ -196,11 +199,9 @@ do_request_api_test (SoupSession *session, TestCase *test) TestRequest *treq; GInputStream *stream; GError *error = NULL; - guint final_status; - final_status = test->request_api_final_status; - if (!final_status) - final_status = test->final_status; + if (test->bugref) + g_test_bug (test->bugref); uri = soup_uri_new_with_base (base_uri, test->requests[0].path); reqh = soup_session_request_http_uri (session, @@ -229,8 +230,9 @@ do_request_api_test (SoupSession *session, TestCase *test) stream = soup_test_request_send (SOUP_REQUEST (reqh), NULL, 0, &error); - if (SOUP_STATUS_IS_TRANSPORT_ERROR (final_status)) { - g_assert_error (error, SOUP_HTTP_ERROR, final_status); + if (SOUP_STATUS_IS_TRANSPORT_ERROR (test->final_status) && + test->final_status != SOUP_STATUS_MALFORMED) { + g_assert_error (error, SOUP_HTTP_ERROR, test->final_status); g_clear_error (&error); g_assert_null (stream); @@ -258,7 +260,10 @@ do_request_api_test (SoupSession *session, TestCase *test) g_clear_error (&error); g_object_unref (stream); - g_assert_cmpint (msg->status_code, ==, final_status); + if (test->final_status == SOUP_STATUS_MALFORMED) + g_assert_cmpint (msg->status_code, ==, test->requests[0].status_code); + else + g_assert_cmpint (msg->status_code, ==, test->final_status); g_object_unref (msg); g_object_unref (reqh); diff --git a/tests/requester-test.c b/tests/requester-test.c index 52c3eac2..39b30bd5 100644 --- a/tests/requester-test.c +++ b/tests/requester-test.c @@ -336,6 +336,8 @@ do_simple_plain_test (gconstpointer uri) { SoupSession *session; + g_test_bug ("653707"); + session = soup_test_session_new (SOUP_TYPE_SESSION, NULL); do_test_for_thread_and_context (session, uri); soup_test_session_abort_unref (session); @@ -346,6 +348,8 @@ do_simple_async_test (gconstpointer uri) { SoupSession *session; + g_test_bug ("653707"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, SOUP_SESSION_USE_THREAD_CONTEXT, TRUE, NULL); @@ -359,6 +363,8 @@ do_test_with_context_and_type (const char *uri, gboolean plain_session) GMainContext *async_context; SoupSession *session; + g_test_bug ("653707"); + async_context = g_main_context_new (); g_main_context_push_thread_default (async_context); @@ -750,6 +756,9 @@ do_async_close_test (gconstpointer uri) SoupSession *session; SoupURI *slow_uri; + g_test_bug ("695652"); + g_test_bug ("711260"); + slow_uri = soup_uri_new (uri); soup_uri_set_path (slow_uri, "/slow"); @@ -768,6 +777,9 @@ do_sync_close_test (gconstpointer uri) SoupSession *session; SoupURI *slow_uri; + g_test_bug ("695652"); + g_test_bug ("711260"); + slow_uri = soup_uri_new (uri); soup_uri_set_path (slow_uri, "/slow"); diff --git a/tests/server-test.c b/tests/server-test.c index 1648c4f6..0c980908 100644 --- a/tests/server-test.c +++ b/tests/server-test.c @@ -65,6 +65,8 @@ do_star_test (void) SoupURI *star_uri; const char *handled_by; + g_test_bug ("590751"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); star_uri = soup_uri_copy (base_uri); soup_uri_set_path (star_uri, "*"); @@ -175,6 +177,8 @@ do_server_aliases_test (void) char *https_bad[] = { "http", "dav", "fred", NULL }; int i; + g_test_bug ("703694"); + for (i = 0; http_good[i]; i++) do_one_server_aliases_test (base_uri, http_good[i], TRUE); for (i = 0; http_bad[i]; i++) @@ -195,6 +199,8 @@ do_dot_dot_test (void) SoupMessage *msg; SoupURI *uri; + g_test_bug ("667635"); + session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL); uri = soup_uri_new_with_base (base_uri, "/..%2ftest"); @@ -237,6 +243,8 @@ do_ipv6_test (void) SoupSession *session; SoupMessage *msg; + g_test_bug ("666399"); + ipv6_addr = soup_address_new ("::1", SOUP_ADDRESS_ANY_PORT); soup_address_resolve_sync (ipv6_addr, NULL); ipv6_server = soup_server_new (SOUP_SERVER_INTERFACE, ipv6_addr, diff --git a/tests/session-test.c b/tests/session-test.c index b652ee5c..15072058 100644 --- a/tests/session-test.c +++ b/tests/session-test.c @@ -202,6 +202,8 @@ do_priority_tests (gconstpointer data) SOUP_MESSAGE_PRIORITY_HIGH, SOUP_MESSAGE_PRIORITY_NORMAL }; + g_test_bug ("696277"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); g_object_set (session, "max-conns", 1, NULL); @@ -261,6 +263,8 @@ do_property_tests (void) GTlsDatabase *tlsdb, *default_tlsdb; SoupURI *uri; + g_test_bug ("708696"); + default_proxy_resolver = g_proxy_resolver_get_default (); default_tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ()); diff --git a/tests/sniffing-test.c b/tests/sniffing-test.c index 59f874f4..32fad9fc 100644 --- a/tests/sniffing-test.c +++ b/tests/sniffing-test.c @@ -302,6 +302,7 @@ do_signals_tests (gconstpointer data) do_signals_test (should_content_sniff, TRUE, FALSE, TRUE, FALSE); + /* FIXME g_test_bug ("587907") */ do_signals_test (should_content_sniff, TRUE, TRUE, FALSE, TRUE); do_signals_test (should_content_sniff, @@ -397,6 +398,8 @@ test_disabled (gconstpointer data) const char *sniffed_content_type; GError *error = NULL; + g_test_bug ("574773"); + uri = soup_uri_new_with_base (base_uri, path); msg = soup_message_new_from_uri ("GET", uri); @@ -522,6 +525,7 @@ main (int argc, char **argv) g_test_add_data_func ("/sniffing/type/unknown-binary", "unknown/text_binary.txt => application/octet-stream", do_sniffing_test); + /* FIXME g_test_bug ("715126") */ g_test_add_data_func ("/sniffing/type/unknown-leading-space", "unknown/leading_space.html => text/html", do_sniffing_test); diff --git a/tests/socket-test.c b/tests/socket-test.c index 4fb0d35c..5bcc3b0c 100644 --- a/tests/socket-test.c +++ b/tests/socket-test.c @@ -18,6 +18,8 @@ do_unconnected_socket_test (void) guint res; struct sockaddr_in in_localhost; + g_test_bug ("673083"); + in_localhost.sin_family = AF_INET; in_localhost.sin_port = 0; in_localhost.sin_addr.s_addr = htonl (INADDR_LOOPBACK); diff --git a/tests/ssl-test.c b/tests/ssl-test.c index b042d120..e6bbb615 100644 --- a/tests/ssl-test.c +++ b/tests/ssl-test.c @@ -20,6 +20,8 @@ do_properties_test_for_session (SoupSession *session, const char *uri) g_assert_cmpuint (flags, ==, G_TLS_CERTIFICATE_UNKNOWN_CA); } else soup_test_assert (FALSE, "Response not https"); + + g_test_bug ("665182"); g_assert_false (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); g_object_unref (msg); @@ -110,7 +112,11 @@ do_strictness_test (gconstpointer data) msg = soup_message_new ("GET", uri); soup_session_send_message (session, msg); soup_test_assert_message_status (msg, test->expected_status); + + g_test_bug ("690176"); g_assert_true (soup_message_get_https_status (msg, NULL, &flags)); + + g_test_bug ("665182"); if (test->with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) g_assert_true (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED); else @@ -141,6 +147,8 @@ do_session_property_tests (void) char *ca_file; SoupSession *session; + g_test_bug ("673678"); + SOUP_TEST_SKIP_IF_NO_TLS; session = soup_session_async_new (); diff --git a/tests/streaming-test.c b/tests/streaming-test.c index f15e1890..8d8c02ef 100644 --- a/tests/streaming-test.c +++ b/tests/streaming-test.c @@ -126,6 +126,8 @@ do_eof_test (gconstpointer data) SoupURI *base_uri = (SoupURI *)data; SoupSession *session; + g_test_bug ("572153"); + session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL); do_request (session, base_uri, "eof"); soup_test_session_abort_unref (session); diff --git a/tests/test-utils.c b/tests/test-utils.c index 69a9426b..bc160aea 100644 --- a/tests/test-utils.c +++ b/tests/test-utils.c @@ -76,6 +76,7 @@ test_init (int argc, char **argv, GOptionEntry *entries) g_test_init (&argc, &argv, NULL); g_test_set_nonfatal_assertions (); + g_test_bug_base ("https://bugzilla.gnome.org/"); opts = g_option_context_new (NULL); g_option_context_add_main_entries (opts, debug_entry, NULL); diff --git a/tests/tld-test.c b/tests/tld-test.c index 2e7f8a21..4fad8625 100644 --- a/tests/tld-test.c +++ b/tests/tld-test.c @@ -157,6 +157,9 @@ do_non_inet_tests (void) { int i; + g_test_bug ("679230"); + g_test_bug ("681085"); + for (i = 0; i < G_N_ELEMENTS (non_inet_tld_tests); i++) { gboolean is_public; const char *base_domain; diff --git a/tests/uri-parsing.c b/tests/uri-parsing.c index e67253e3..d56b655f 100644 --- a/tests/uri-parsing.c +++ b/tests/uri-parsing.c @@ -3,154 +3,154 @@ #include "test-utils.h" static struct { - const char *uri_string, *result; + const char *uri_string, *result, *bugref; const SoupURI bits; } abs_tests[] = { - { "foo:", "foo:", + { "foo:", "foo:", NULL, { "foo", NULL, NULL, NULL, 0, "", NULL, NULL } }, - { "file:/dev/null", "file:/dev/null", + { "file:/dev/null", "file:/dev/null", NULL, { "file", NULL, NULL, NULL, 0, "/dev/null", NULL, NULL } }, - { "file:///dev/null", "file:///dev/null", + { "file:///dev/null", "file:///dev/null", NULL, { "file", NULL, NULL, "", 0, "/dev/null", NULL, NULL } }, - { "ftp://user@host/path", "ftp://user@host/path", + { "ftp://user@host/path", "ftp://user@host/path", NULL, { "ftp", "user", NULL, "host", 21, "/path", NULL, NULL } }, - { "ftp://user@host:9999/path", "ftp://user@host:9999/path", + { "ftp://user@host:9999/path", "ftp://user@host:9999/path", NULL, { "ftp", "user", NULL, "host", 9999, "/path", NULL, NULL } }, - { "ftp://user:password@host/path", "ftp://user@host/path", + { "ftp://user:password@host/path", "ftp://user@host/path", NULL, { "ftp", "user", "password", "host", 21, "/path", NULL, NULL } }, - { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path", + { "ftp://user:password@host:9999/path", "ftp://user@host:9999/path", NULL, { "ftp", "user", "password", "host", 9999, "/path", NULL, NULL } }, - { "ftp://user:password@host", "ftp://user@host", + { "ftp://user:password@host", "ftp://user@host", NULL, { "ftp", "user", "password", "host", 21, "", NULL, NULL } }, - { "http://us%65r@host", "http://user@host/", + { "http://us%65r@host", "http://user@host/", NULL, { "http", "user", NULL, "host", 80, "/", NULL, NULL } }, - { "http://us%40r@host", "http://us%40r@host/", + { "http://us%40r@host", "http://us%40r@host/", NULL, { "http", "us\x40r", NULL, "host", 80, "/", NULL, NULL } }, - { "http://us%3ar@host", "http://us%3Ar@host/", + { "http://us%3ar@host", "http://us%3Ar@host/", NULL, { "http", "us\x3ar", NULL, "host", 80, "/", NULL, NULL } }, - { "http://us%2fr@host", "http://us%2Fr@host/", + { "http://us%2fr@host", "http://us%2Fr@host/", NULL, { "http", "us\x2fr", NULL, "host", 80, "/", NULL, NULL } }, - { "http://us%3fr@host", "http://us%3Fr@host/", + { "http://us%3fr@host", "http://us%3Fr@host/", NULL, { "http", "us\x3fr", NULL, "host", 80, "/", NULL, NULL } }, - { "http://host?query", "http://host/?query", + { "http://host?query", "http://host/?query", NULL, { "http", NULL, NULL, "host", 80, "/", "query", NULL } }, { "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", - "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", + "http://host/path?query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", NULL, { "http", NULL, NULL, "host", 80, "/path", "query=http%3A%2F%2Fhost%2Fpath%3Fchildparam%3Dchildvalue¶m=value", NULL } }, { "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", - "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", + "http://control-chars/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", NULL, { "http", NULL, NULL, "control-chars", 80, "/%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F", NULL, NULL } }, { "http://space/%20", - "http://space/%20", + "http://space/%20", NULL, { "http", NULL, NULL, "space", 80, "/%20", NULL, NULL } }, { "http://delims/%3C%3E%23%25%22", - "http://delims/%3C%3E%23%25%22", + "http://delims/%3C%3E%23%25%22", NULL, { "http", NULL, NULL, "delims", 80, "/%3C%3E%23%25%22", NULL, NULL } }, { "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", - "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", + "http://unwise-chars/%7B%7D%7C%5C%5E%5B%5D%60", NULL, { "http", NULL, NULL, "unwise-chars", 80, "/%7B%7D%7C%5C%5E%5B%5D%60", NULL, NULL } }, /* From RFC 2732 */ { "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html", - "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html", + "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/index.html", NULL, { "http", NULL, NULL, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 80, "/index.html", NULL, NULL } }, { "http://[1080:0:0:0:8:800:200C:417A]/index.html", - "http://[1080:0:0:0:8:800:200C:417A]/index.html", + "http://[1080:0:0:0:8:800:200C:417A]/index.html", NULL, { "http", NULL, NULL, "1080:0:0:0:8:800:200C:417A", 80, "/index.html", NULL, NULL } }, { "http://[3ffe:2a00:100:7031::1]", - "http://[3ffe:2a00:100:7031::1]/", + "http://[3ffe:2a00:100:7031::1]/", NULL, { "http", NULL, NULL, "3ffe:2a00:100:7031::1", 80, "/", NULL, NULL } }, { "http://[1080::8:800:200C:417A]/foo", - "http://[1080::8:800:200C:417A]/foo", + "http://[1080::8:800:200C:417A]/foo", NULL, { "http", NULL, NULL, "1080::8:800:200C:417A", 80, "/foo", NULL, NULL } }, { "http://[::192.9.5.5]/ipng", - "http://[::192.9.5.5]/ipng", + "http://[::192.9.5.5]/ipng", NULL, { "http", NULL, NULL, "::192.9.5.5", 80, "/ipng", NULL, NULL } }, { "http://[::FFFF:129.144.52.38]:80/index.html", - "http://[::FFFF:129.144.52.38]/index.html", + "http://[::FFFF:129.144.52.38]/index.html", NULL, { "http", NULL, NULL, "::FFFF:129.144.52.38", 80, "/index.html", NULL, NULL } }, { "http://[2010:836B:4179::836B:4179]", - "http://[2010:836B:4179::836B:4179]/", + "http://[2010:836B:4179::836B:4179]/", NULL, { "http", NULL, NULL, "2010:836B:4179::836B:4179", 80, "/", NULL, NULL } }, /* Try to recover certain kinds of invalid URIs */ { "http://host/path with spaces", - "http://host/path%20with%20spaces", + "http://host/path%20with%20spaces", "566530", { "http", NULL, NULL, "host", 80, "/path%20with%20spaces", NULL, NULL } }, - { " http://host/path", "http://host/path", + { " http://host/path", "http://host/path", "594405", { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, - { "http://host/path ", "http://host/path", + { "http://host/path ", "http://host/path", "594405", { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, - { "http://host ", "http://host/", + { "http://host ", "http://host/", "594405", { "http", NULL, NULL, "host", 80, "/", NULL, NULL } }, - { "http://host:999 ", "http://host:999/", + { "http://host:999 ", "http://host:999/", "594405", { "http", NULL, NULL, "host", 999, "/", NULL, NULL } }, - { "http://host/pa\nth", "http://host/path", + { "http://host/pa\nth", "http://host/path", "594405", { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, - { "http:\r\n//host/path", "http://host/path", + { "http:\r\n//host/path", "http://host/path", "594405", { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, - { "http://\thost/path", "http://host/path", + { "http://\thost/path", "http://host/path", "594405", { "http", NULL, NULL, "host", 80, "/path", NULL, NULL } }, - /* Bug 594405; 0-length is different from not-present */ - { "http://host/path?", "http://host/path?", + /* 0-length is different from not-present */ + { "http://host/path?", "http://host/path?", "594405", { "http", NULL, NULL, "host", 80, "/path", "", NULL } }, - { "http://host/path#", "http://host/path#", + { "http://host/path#", "http://host/path#", "594405", { "http", NULL, NULL, "host", 80, "/path", NULL, "" } }, - /* Bug 590524; ignore badly-%-encoding */ - { "http://host/path%", "http://host/path%", + /* ignore bad %-encoding */ + { "http://host/path%", "http://host/path%", "590524", { "http", NULL, NULL, "host", 80, "/path%", NULL, NULL } }, - { "http://h%ost/path", "http://h%25ost/path", + { "http://h%ost/path", "http://h%25ost/path", "590524", { "http", NULL, NULL, "h%ost", 80, "/path", NULL, NULL } }, - { "http://host/path%%", "http://host/path%%", + { "http://host/path%%", "http://host/path%%", "590524", { "http", NULL, NULL, "host", 80, "/path%%", NULL, NULL } }, - { "http://host/path%%%", "http://host/path%%%", + { "http://host/path%%%", "http://host/path%%%", "590524", { "http", NULL, NULL, "host", 80, "/path%%%", NULL, NULL } }, - { "http://host/path%/x/", "http://host/path%/x/", + { "http://host/path%/x/", "http://host/path%/x/", "590524", { "http", NULL, NULL, "host", 80, "/path%/x/", NULL, NULL } }, - { "http://host/path%0x/", "http://host/path%0x/", + { "http://host/path%0x/", "http://host/path%0x/", "590524", { "http", NULL, NULL, "host", 80, "/path%0x/", NULL, NULL } }, - { "http://host/path%ax", "http://host/path%ax", + { "http://host/path%ax", "http://host/path%ax", "590524", { "http", NULL, NULL, "host", 80, "/path%ax", NULL, NULL } }, - /* Bug 662806; %-encode non-ASCII characters */ - { "http://host/p\xc3\xa4th/", "http://host/p%C3%A4th/", + /* %-encode non-ASCII characters */ + { "http://host/p\xc3\xa4th/", "http://host/p%C3%A4th/", "662806", { "http", NULL, NULL, "host", 80, "/p%C3%A4th/", NULL, NULL } }, - { "HTTP:////////////////", "http:////////////////", + { "HTTP:////////////////", "http:////////////////", "667637", { "http", NULL, NULL, "", 80, "//////////////", NULL, NULL } }, - { "http://@host", "http://@host/", + { "http://@host", "http://@host/", NULL, { "http", "", NULL, "host", 80, "/", NULL, NULL } }, - { "http://:@host", "http://@host/", + { "http://:@host", "http://@host/", NULL, { "http", "", "", "host", 80, "/", NULL, NULL } }, - { "http://host/keep%00nuls", "http://host/keep%00nuls", + { "http://host/keep%00nuls", "http://host/keep%00nuls", NULL, { "http", NULL, NULL, "host", 80, "/keep%00nuls", NULL, NULL } }, - /* Bug 703776; scheme parsing */ - { "foo0://host/path", "foo0://host/path", + /* scheme parsing */ + { "foo0://host/path", "foo0://host/path", "703776", { "foo0", NULL, NULL, "host", 0, "/path", NULL, NULL } }, - { "f0.o://host/path", "f0.o://host/path", + { "f0.o://host/path", "f0.o://host/path", "703776", { "f0.o", NULL, NULL, "host", 0, "/path", NULL, NULL } }, - { "http++://host/path", "http++://host/path", + { "http++://host/path", "http++://host/path", "703776", { "http++", NULL, NULL, "host", 0, "/path", NULL, NULL } }, - { "http-ish://host/path", "http-ish://host/path", + { "http-ish://host/path", "http-ish://host/path", "703776", { "http-ish", NULL, NULL, "host", 0, "/path", NULL, NULL } }, - { "99http://host/path", NULL, + { "99http://host/path", NULL, "703776", { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, - { ".http://host/path", NULL, + { ".http://host/path", NULL, "703776", { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, - { "+http://host/path", NULL, + { "+http://host/path", NULL, "703776", { NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL } }, /* IPv6 scope ID parsing (both correct and incorrect) */ - { "http://[fe80::dead:beef%em1]/", "http://[fe80::dead:beef%25em1]/", + { "http://[fe80::dead:beef%em1]/", "http://[fe80::dead:beef%25em1]/", NULL, { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } }, - { "http://[fe80::dead:beef%25em1]/", "http://[fe80::dead:beef%25em1]/", + { "http://[fe80::dead:beef%25em1]/", "http://[fe80::dead:beef%25em1]/", NULL, { "http", NULL, NULL, "fe80::dead:beef%em1", 80, "/", NULL, NULL } }, - { "http://[fe80::dead:beef%10]/", "http://[fe80::dead:beef%2510]/", + { "http://[fe80::dead:beef%10]/", "http://[fe80::dead:beef%2510]/", NULL, { "http", NULL, NULL, "fe80::dead:beef%10", 80, "/", NULL, NULL } } }; static int num_abs_tests = G_N_ELEMENTS(abs_tests); @@ -255,14 +255,14 @@ static struct { static int num_rel_tests = G_N_ELEMENTS(rel_tests); static struct { - const char *one, *two; + const char *one, *two, *bugref; } eq_tests[] = { - { "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D" }, - { "http://example.com", "http://example.com/" }, + { "example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7Bfoo%7D", "628728" }, + { "http://example.com", "http://example.com/", NULL }, /* From RFC 2616 */ - { "http://abc.com:80/~smith/home.html", "http://abc.com:80/~smith/home.html" }, - { "http://abc.com:80/~smith/home.html", "http://ABC.com/%7Esmith/home.html" }, - { "http://abc.com:80/~smith/home.html", "http://ABC.com:/%7esmith/home.html" }, + { "http://abc.com:80/~smith/home.html", "http://abc.com:80/~smith/home.html", NULL }, + { "http://abc.com:80/~smith/home.html", "http://ABC.com/%7Esmith/home.html", NULL }, + { "http://abc.com:80/~smith/home.html", "http://ABC.com:/%7esmith/home.html", NULL }, }; static int num_eq_tests = G_N_ELEMENTS(eq_tests); @@ -313,6 +313,8 @@ do_absolute_uri_tests (void) int i; for (i = 0; i < num_abs_tests; i++) { + if (abs_tests[i].bugref) + g_test_bug (abs_tests[i].bugref); do_uri (NULL, NULL, abs_tests[i].uri_string, abs_tests[i].result, &abs_tests[i].bits); } @@ -349,6 +351,9 @@ do_equality_tests (void) int i; for (i = 0; i < num_eq_tests; i++) { + if (eq_tests[i].bugref) + g_test_bug (eq_tests[i].bugref); + uri1 = soup_uri_new (eq_tests[i].one); uri2 = soup_uri_new (eq_tests[i].two); @@ -366,6 +371,9 @@ do_soup_uri_null_tests (void) SoupURI *uri, *uri2; char *uri_string; + g_test_bug ("667637"); + g_test_bug ("670431"); + uri = soup_uri_new (NULL); g_assert_false (SOUP_URI_IS_VALID (uri)); g_assert_false (SOUP_URI_VALID_FOR_HTTP (uri)); @@ -464,6 +472,8 @@ do_normalization_tests (void) char *normalized; int i; + g_test_bug ("680018"); + for (i = 0; i < num_normalization_tests; i++) { if (normalization_tests[i].unescape_extra) { debug_printf (1, "<%s> unescaping <%s> => <%s>\n", diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c index 3f26edd4..f6b20b8f 100644 --- a/tests/xmlrpc-test.c +++ b/tests/xmlrpc-test.c @@ -393,6 +393,8 @@ test_ping (gconstpointer include_params) char *out; gboolean ret; + g_test_bug ("671661"); + SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER; debug_printf (2, "ping (void (%s) -> string)\n", -- cgit v1.2.1 From 18ae820c81658b44e1ac7daf57df1ee0ef030d53 Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Tue, 18 Feb 2014 11:38:37 +0200 Subject: soup-session: force port for proxy URL Otherwise libsoup is unable to connect through proxies that use default port (say, 80 for http). Proxy resolver resolves port-less proxy URLs into network address with zero port, which is then passed to connect() --- libsoup/soup-session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index b3081f14..132554d6 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -577,7 +577,7 @@ set_proxy_resolver (SoupSession *session, SoupURI *uri, char *uri_string; priv->proxy_uri = soup_uri_copy (uri); - uri_string = soup_uri_to_string (uri, FALSE); + uri_string = soup_uri_to_string_internal (uri, FALSE, TRUE); priv->proxy_resolver = g_simple_proxy_resolver_new (uri_string, NULL); g_free (uri_string); } else if (soup_resolver) { -- cgit v1.2.1 From 8cafecb65f47752c1218e128fe63dcbaa2e6b763 Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Tue, 11 Feb 2014 15:30:59 +0200 Subject: soup-socket: fixed leak in new_socket_client() --- libsoup/soup-socket.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index e0748fd1..b9f1dfca 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -715,8 +715,13 @@ new_socket_client (SoupSocket *sock) if (priv->timeout) g_socket_client_set_timeout (client, priv->timeout); - if (priv->local_addr) - g_socket_client_set_local_address (client, soup_address_get_gsockaddr (priv->local_addr)); + if (priv->local_addr) { + GSocketAddress *addr; + + addr = soup_address_get_gsockaddr (priv->local_addr); + g_socket_client_set_local_address (client, addr); + g_object_unref (addr); + } return client; } -- cgit v1.2.1 From b873b70a73edffec41cbc6d868400693667cc234 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 17 Mar 2014 17:53:16 -0400 Subject: 2.45.92 --- NEWS | 22 ++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index f04f0ebf..97b0cd7c 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,25 @@ +Changes in libsoup from 2.45.90 to 2.45.92: + + * Fixed problems with using an http proxy on port 80. [patch + from Slava Monich on libsoup-list] + + * Plugged a small per-connection leak. [patch from Slava + Monich on libsoup-list] + + * Belatedly bumped up the glib requirement to 2.38, which is + required for the TAP driver. + + * Fixed up some leftover issues from the test porting to + gtestutils: + + test-utils: change http_debug command-line flag + xmlrpc-test: use g_test_skip() + redirect-test: remove a flaky test + auth-test: remove some erroneous SKIP_IF_NO_APACHEs + tests: split up some test programs into more tests + tests: remove debug_printf()s that are redundant with test names + tests: use g_test_bug() to annotate test cases + Changes in libsoup from 2.45.3 to 2.45.90: * Fixed a problem where libsoup would use the "http" proxy diff --git a/configure.ac b/configure.ac index 5bdd0798..f88e3f9f 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ******************************************* m4_define([soup_major_version], [2]) m4_define([soup_minor_version], [45]) -m4_define([soup_micro_version], [90]) +m4_define([soup_micro_version], [92]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1 From 6c14af04775a9de4dfa3fa0cc15a7ad0462ef3d9 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 24 Mar 2014 17:21:26 -0400 Subject: 2.46.0 --- NEWS | 4 ++++ configure.ac | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 97b0cd7c..b29aa035 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Changes in libsoup from 2.45.92 to 2.46.0: + + * (No changes, just a version bump) + Changes in libsoup from 2.45.90 to 2.45.92: * Fixed problems with using an http proxy on port 80. [patch diff --git a/configure.ac b/configure.ac index f88e3f9f..96bb378a 100644 --- a/configure.ac +++ b/configure.ac @@ -3,8 +3,8 @@ dnl *** Initialize automake and set version *** dnl ******************************************* m4_define([soup_major_version], [2]) -m4_define([soup_minor_version], [45]) -m4_define([soup_micro_version], [92]) +m4_define([soup_minor_version], [46]) +m4_define([soup_micro_version], [0]) AC_PREREQ(2.63) AC_INIT([libsoup],[soup_major_version.soup_minor_version.soup_micro_version],[http://bugzilla.gnome.org/enter_bug.cgi?product=libsoup]) -- cgit v1.2.1