implement. (soup_message_add_response_code_handler): ditto.
authorAlex Graveley <alex@ximian.com>
Thu, 7 Jun 2001 00:50:23 +0000 (00:50 +0000)
committerAlex Graveley <orph@src.gnome.org>
Thu, 7 Jun 2001 00:50:23 +0000 (00:50 +0000)
2001-06-06  Alex Graveley  <alex@ximian.com>

* src/soup-core/soup-message.c (soup_message_add_header_handler):
implement.
(soup_message_add_response_code_handler): ditto.
(soup_message_add_body_handler): ditto.
(soup_message_run_handlers): uh-huh.
(soup_message_free): Free allocated handler info.

* src/soup-core/soup-message.h: Change SOUP_MESSAGE_PROCESS_CHUNKS
to SOUP_MESSAGE_OVERWRITE_CHUNKS. This will allow large files to
be processed using a BODY_CHUNK handler, instead of keeping
everything in memory.

* src/soup-core/soup-queue.c (soup_process_headers): Run PRE_BODY
handlers.
(soup_finish_read): Run POST_BODY handlers.
(soup_queue_read_cb): Run BODY_CHUNK handlers.

ChangeLog
libsoup/soup-message.c
libsoup/soup-message.h
libsoup/soup-private.h
libsoup/soup-queue.c

index 091b2f4..902fd8a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2001-06-06  Alex Graveley  <alex@ximian.com>
+
+       * src/soup-core/soup-message.c (soup_message_add_header_handler):
+       implement.
+       (soup_message_add_response_code_handler): ditto.
+       (soup_message_add_body_handler): ditto.
+       (soup_message_run_handlers): uh-huh.
+       (soup_message_free): Free allocated handler info.
+
+       * src/soup-core/soup-message.h: Change SOUP_MESSAGE_PROCESS_CHUNKS
+       to SOUP_MESSAGE_OVERWRITE_CHUNKS. This will allow large files to
+       be processed using a BODY_CHUNK handler, instead of keeping
+       everything in memory.
+
+       * src/soup-core/soup-queue.c (soup_process_headers): Run PRE_BODY
+       handlers.
+       (soup_finish_read): Run POST_BODY handlers.
+       (soup_queue_read_cb): Run BODY_CHUNK handlers.
+
 2001-06-06  Joe Shaw  <joe@ximian.com>
 
        * src/soup-core/soup-message.c (soup_message_set_method,
index 28170de..badea47 100644 (file)
@@ -161,6 +161,9 @@ soup_message_free (SoupMessage *req)
                g_hash_table_destroy (req->response_headers);
        }
 
+       g_slist_foreach (req->priv->content_handlers, (GFunc) g_free, NULL);
+       g_slist_free (req->priv->content_handlers);
+
        g_free (req->priv);
        g_free (req->action);
        g_free (req);
@@ -358,8 +361,8 @@ soup_message_get_flags (SoupMessage *msg)
 void
 soup_message_set_method (SoupMessage *msg, const gchar *method)
 {
-       g_return_if_fail(msg);
-       g_return_if_fail(method);
+       g_return_if_fail (msg != NULL);
+       g_return_if_fail (method != NULL);
 
        msg->method = method;
 }
@@ -367,11 +370,50 @@ soup_message_set_method (SoupMessage *msg, const gchar *method)
 const gchar *
 soup_message_get_method (SoupMessage *msg)
 {
-       g_return_val_if_fail(msg, NULL);
+       g_return_val_if_fail (msg != NULL, NULL);
 
        return msg->method;
 }
 
+typedef enum {
+       RESPONSE_HEADER_HANDLER,
+       RESPONSE_CODE_HANDLER,
+       RESPONSE_BODY_HANDLER
+} SoupHandlerKind;
+
+typedef struct {
+       SoupHandlerType   type;
+       SoupHandlerFn     handler_cb;
+       gpointer          user_data;
+
+       SoupHandlerKind   kind;
+       const gchar      *header;
+       guint             code;
+} SoupHandlerData;
+
+static void 
+soup_message_add_handler (SoupMessage      *msg,
+                         SoupHandlerType   type,
+                         SoupHandlerFn     handler_cb,
+                         gpointer          user_data,
+                         SoupHandlerKind   kind,
+                         const gchar      *header,
+                         guint             code)
+{
+       SoupHandlerData *data;
+
+       data = g_new0 (SoupHandlerData, 1);
+       data->type = type;
+       data->handler_cb = handler_cb;
+       data->user_data = user_data;
+       data->kind = kind;
+       data->header = header;
+       data->code = code;
+
+       msg->priv->content_handlers = 
+               g_slist_append (msg->priv->content_handlers, data);
+}
+
 void 
 soup_message_add_header_handler (SoupMessage      *msg,
                                 const gchar      *header,
@@ -379,7 +421,17 @@ soup_message_add_header_handler (SoupMessage      *msg,
                                 SoupHandlerFn     handler_cb,
                                 gpointer          user_data)
 {
-       g_warning ("Not yet implemented.");
+       g_return_if_fail (msg != NULL);
+       g_return_if_fail (header != NULL);
+       g_return_if_fail (handler_cb != NULL);
+
+       soup_message_add_handler (msg, 
+                                 type, 
+                                 handler_cb, 
+                                 user_data, 
+                                 RESPONSE_HEADER_HANDLER, 
+                                 header, 
+                                 0);
 }
 
 void 
@@ -389,7 +441,17 @@ soup_message_add_response_code_handler (SoupMessage      *msg,
                                        SoupHandlerFn     handler_cb,
                                        gpointer          user_data)
 {
-       g_warning ("Not yet implemented.");
+       g_return_if_fail (msg != NULL);
+       g_return_if_fail (code != 0);
+       g_return_if_fail (handler_cb != NULL);
+
+       soup_message_add_handler (msg, 
+                                 type, 
+                                 handler_cb, 
+                                 user_data, 
+                                 RESPONSE_CODE_HANDLER, 
+                                 NULL, 
+                                 code);
 }
 
 void 
@@ -398,5 +460,46 @@ soup_message_add_body_handler (SoupMessage      *msg,
                               SoupHandlerFn     handler_cb,
                               gpointer          user_data)
 {
-       g_warning ("Not yet implemented.");
+       g_return_if_fail (msg != NULL);
+       g_return_if_fail (handler_cb != NULL);
+
+       soup_message_add_handler (msg, 
+                                 type, 
+                                 handler_cb, 
+                                 user_data, 
+                                 RESPONSE_BODY_HANDLER, 
+                                 NULL, 
+                                 0);
+}
+
+SoupErrorCode 
+soup_message_run_handlers (SoupMessage *msg, SoupHandlerType invoke_type)
+{
+       GSList *list;
+       SoupErrorCode retval = SOUP_ERROR_NONE;
+
+       g_return_val_if_fail (msg != NULL, retval);
+       
+       for (list = msg->priv->content_handlers; list; list = list->next) {
+               SoupHandlerData *data = list->data;
+               
+               if (data->type != invoke_type) continue;
+
+               switch (data->kind) {
+               case RESPONSE_HEADER_HANDLER:
+                       if (!soup_message_get_response_header (msg,
+                                                              data->header))
+                               continue;
+                       break;
+               case RESPONSE_CODE_HANDLER:
+                       if (msg->response_code != data->code) continue;
+                       break;
+               }
+
+               retval = (*data->handler_cb) (msg, data->user_data);
+
+               if (retval != SOUP_ERROR_NONE) break;
+       }
+
+       return retval;
 }
index 6e744a3..462776e 100644 (file)
@@ -123,7 +123,7 @@ typedef enum {
        SOUP_HANDLER_POST_BODY
 } SoupHandlerType;
 
-typedef SoupErrorCode SoupHandlerFn (SoupMessage *msg, gpointer user_data);
+typedef SoupErrorCode (*SoupHandlerFn) (SoupMessage *msg, gpointer user_data);
 
 void           soup_message_add_header_handler  (SoupMessage      *msg,
                                                 const gchar      *header,
@@ -145,9 +145,9 @@ void           soup_message_add_body_handler    (SoupMessage      *msg,
 
 /* FIXME: None of these are implemented yet, oh well... */
 typedef enum {
-       SOUP_MESSAGE_FOLLOW_REDIRECT = (1 << 1),
-       SOUP_MESSAGE_NO_COOKIE       = (1 << 2),
-       SOUP_MESSAGE_PROCESS_CHUNKS  = (1 << 3)
+       SOUP_MESSAGE_FOLLOW_REDIRECT  = (1 << 1),
+       SOUP_MESSAGE_NO_COOKIE        = (1 << 2),
+       SOUP_MESSAGE_OVERWRITE_CHUNKS = (1 << 3)
 } SoupMessageFlags;
 
 void           soup_message_set_flags          (SoupMessage       *msg,
index 311d0e8..73ba00b 100644 (file)
@@ -99,6 +99,8 @@ struct _SoupMessagePrivate {
        gpointer        digest_data;
 
        guint           msg_flags;
+
+       GSList         *content_handlers;
 };
 
 typedef struct {
index 499a557..4016f41 100644 (file)
@@ -73,6 +73,7 @@ static gboolean
 soup_process_headers (SoupMessage *req)
 {
        gchar *connection, *length, *enc;
+       SoupErrorCode err = SOUP_ERROR_MALFORMED_HEADER;
 
        /* Handle connection persistence */
        connection = g_hash_table_lookup (req->response_headers, "Connection");
@@ -95,10 +96,13 @@ soup_process_headers (SoupMessage *req)
                }
        }
 
+       err = soup_message_run_handlers (req, SOUP_HANDLER_PRE_BODY);
+       if (err) goto THROW_MALFORMED_HEADER;
+
        return TRUE;
 
  THROW_MALFORMED_HEADER:
-       soup_message_issue_callback (req, SOUP_ERROR_MALFORMED_HEADER);
+       soup_message_issue_callback (req, err);
        return FALSE;
 }
 
@@ -183,6 +187,7 @@ soup_finish_read (SoupMessage *req)
 {
        GByteArray *arr = req->priv->recv_buf;
        gint index = req->priv->header_len;
+       SoupErrorCode err;
 
        req->response.owner = SOUP_BUFFER_SYSTEM_OWNED;
        req->response.length = arr->len - index ;
@@ -194,7 +199,13 @@ soup_finish_read (SoupMessage *req)
        req->priv->recv_buf = NULL;
 
        req->status = SOUP_STATUS_FINISHED;
-       soup_message_issue_callback (req, SOUP_ERROR_NONE);
+
+       err = soup_message_run_handlers (req, SOUP_HANDLER_POST_BODY);
+
+       if (err)
+               soup_message_issue_callback (req, err); 
+       else 
+               soup_message_issue_callback (req, SOUP_ERROR_NONE);
 }
 
 static gboolean 
@@ -208,6 +219,7 @@ soup_queue_read_cb (GIOChannel* iochannel,
        gint index = req->priv->header_len;
        GByteArray *arr = req->priv->recv_buf;
        GIOError error;
+       SoupErrorCode err;
 
        error = g_io_channel_read (iochannel,
                                   read_buf,
@@ -239,6 +251,15 @@ soup_queue_read_cb (GIOChannel* iochannel,
                        return FALSE;
        }
 
+       /* Don't call chunk handlers if we didn't actually read anything */
+       if (bytes_read != 0) {
+               err = soup_message_run_handlers (req, SOUP_HANDLER_BODY_CHUNK);
+               if (err) { 
+                       soup_message_issue_callback (req, err); 
+                       return FALSE;
+               }
+       }
+
        if (bytes_read == 0) read_done = TRUE;
        else if (req->priv->is_chunked) read_done = soup_read_chunk (req);
        else if (req->priv->content_length==arr->len-index-4) read_done = TRUE;