[couchdb-glib: 9/21] This commit makes everything compile again - but there is still



commit 1722eface5457bf75aca0e52fa97be180c1b2a15
Author: Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>
Date:   Mon Oct 5 00:34:28 2009 +0200

    This commit makes everything compile again - but there is still
    quite some cleanup needed. There are some notable source
    code changes:
    
     - Make the object struct of CouchDBDocument privately declared
    
     - Add a public method to CouchDBDocument, get_json_object(),
       other code used lots of refs to the now private root_node
       JSonObject member
    
     - Make all object struct declarations private. Since lots of code
       assumed access to CouchDBDocument->root_node, add a new public
       accessor couchdb_document_get_json_object() and use this where
       needed
    
     - Don't make the CouchDB struct declaration depennd on whether OAUTH
       is configured. We always keep the oauth members around, using stub
       values when necessary.
    
     - Add new method couchdb_is_oauth_enabled()
    
     - Remove the method send_message_and_parse() from util.* and add a
       variant of it as public method on the CouchDB class,
       couchdb_send_message(). This method takes the JsonParser as param
       to allow external reuse of the parser. Update all refs to the
       removed util-method
    
     - Fix some refs to private member coucdb->hostname, and use
       couchdb_get_hostname() instead

 NOTES.kamstrup                          |    8 +
 couchdb-glib/couchdb-document-contact.c |   20 ++--
 couchdb-glib/couchdb-document.c         |   39 +++--
 couchdb-glib/couchdb-document.h         |    3 +
 couchdb-glib/couchdb.c                  |  238 +++++++++++++++++++++++++-----
 couchdb-glib/couchdb.h                  |    5 +
 couchdb-glib/dbwatch.c                  |   14 +-
 couchdb-glib/dbwatch.h                  |    2 +
 couchdb-glib/utils.c                    |  144 -------------------
 couchdb-glib/utils.h                    |    6 -
 10 files changed, 257 insertions(+), 222 deletions(-)
---
diff --git a/NOTES.kamstrup b/NOTES.kamstrup
index 265fb67..d936659 100644
--- a/NOTES.kamstrup
+++ b/NOTES.kamstrup
@@ -1,3 +1,11 @@
+TODO:
+Move typedefs to couchdb-types.h
+
+In couchdb.*:
+ * Don't make API depend on whether we are configured with OAUTH
+ * Move OAUTH related functionality from util.* here
+ * New method couchdb_send_message() replacing send_message_and_parse() from util.*
+
 In couchdb-document.c:
  * Change refs to internal API of CouchDB object's ->hostname to method calls
  * Change refs to internal API of CouchDBStructField ->json_object to use method call
diff --git a/couchdb-glib/couchdb-document-contact.c b/couchdb-glib/couchdb-document-contact.c
index 4e9857e..2950570 100644
--- a/couchdb-glib/couchdb-document-contact.c
+++ b/couchdb-glib/couchdb-document-contact.c
@@ -337,7 +337,7 @@ couchdb_document_contact_get_email_addresses (CouchDBDocument *document)
 	g_return_val_if_fail (couchdb_document_is_contact (document), NULL);
 
 	addresses_json = json_object_get_object_member (
-		json_node_get_object (document->root_node), "email_addresses");;
+		couchdb_document_get_json_object (document), "email_addresses");;
 	if (addresses_json) {
 		json_object_foreach_member (addresses_json,
 					    (JsonObjectForeach) foreach_object_cb,
@@ -375,7 +375,7 @@ couchdb_document_contact_set_email_addresses (CouchDBDocument *document, GSList
 		}
 	}
 
-	json_object_set_object_member (json_node_get_object (document->root_node), "email_addresses", addresses_json);
+	json_object_set_object_member (couchdb_document_get_json_object (document), "email_addresses", addresses_json);
 }
 
 GSList *
@@ -388,7 +388,7 @@ couchdb_document_contact_get_phone_numbers (CouchDBDocument *document)
 	g_return_val_if_fail (couchdb_document_is_contact (document), NULL);
 
 	phone_numbers = json_object_get_object_member (
-		json_node_get_object (document->root_node), "phone_numbers");
+		couchdb_document_get_json_object (document), "phone_numbers");
 	if (phone_numbers) {
 		json_object_foreach_member (phone_numbers,
 					    (JsonObjectForeach) foreach_object_cb,
@@ -428,7 +428,7 @@ couchdb_document_contact_set_phone_numbers (CouchDBDocument *document, GSList *l
 		}
 	}
 
-	json_object_set_object_member (json_node_get_object (document->root_node), "phone_numbers", phone_numbers);
+	json_object_set_object_member (couchdb_document_get_json_object (document), "phone_numbers", phone_numbers);
 }
 
 GSList *
@@ -441,7 +441,7 @@ couchdb_document_contact_get_addresses (CouchDBDocument *document)
 	g_return_val_if_fail (couchdb_document_is_contact (document), NULL);
 
 	addresses = json_object_get_object_member (
-		json_node_get_object (document->root_node), "addresses");
+		couchdb_document_get_json_object (document), "addresses");
 	if (addresses) {
 		json_object_foreach_member (addresses,
 					    (JsonObjectForeach) foreach_object_cb,
@@ -489,7 +489,7 @@ couchdb_document_contact_set_addresses (CouchDBDocument *document, GSList *list)
 		}
 	}
 
-	json_object_set_object_member (json_node_get_object (document->root_node), "addresses", addresses);
+	json_object_set_object_member (couchdb_document_get_json_object (document), "addresses", addresses);
 }
 
 GSList *
@@ -502,7 +502,7 @@ couchdb_document_contact_get_im_addresses (CouchDBDocument *document)
 	g_return_val_if_fail (couchdb_document_is_contact (document), NULL);
 
 	im_addresses = json_object_get_object_member (
-		json_node_get_object (document->root_node), "im_addresses");
+		couchdb_document_get_json_object (document), "im_addresses");
 	if (im_addresses != NULL) {
 		json_object_foreach_member (im_addresses,
 					    (JsonObjectForeach) foreach_object_cb,
@@ -542,7 +542,7 @@ couchdb_document_contact_set_im_addresses (CouchDBDocument *document, GSList *li
 		}
 	}
 
-	json_object_set_object_member (json_node_get_object (document->root_node), "im_addresses", im_addresses_json);
+	json_object_set_object_member (couchdb_document_get_json_object (document), "im_addresses", im_addresses_json);
 }
 
 GSList *
@@ -555,7 +555,7 @@ couchdb_document_contact_get_urls (CouchDBDocument *document)
 	g_return_val_if_fail (couchdb_document_is_contact (document), NULL);
 
 	urls = json_object_get_object_member (
-		json_node_get_object (document->root_node), "urls");
+		couchdb_document_get_json_object (document), "urls");
 	if (urls) {
 		json_object_foreach_member (urls,
 					    (JsonObjectForeach) foreach_object_cb,
@@ -593,7 +593,7 @@ couchdb_document_contact_set_urls (CouchDBDocument *document, GSList *list)
 		}
 	}
 
-	json_object_set_object_member (json_node_get_object (document->root_node), "urls", urls_json);
+	json_object_set_object_member (couchdb_document_get_json_object (document), "urls", urls_json);
 }
 
 const char *
diff --git a/couchdb-glib/couchdb-document.c b/couchdb-glib/couchdb-document.c
index 20356e3..1a856a5 100644
--- a/couchdb-glib/couchdb-document.c
+++ b/couchdb-glib/couchdb-document.c
@@ -1,8 +1,10 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2009 Canonical Services Ltd (www.canonical.com)
+ *               2009 Mikkel Kamstrup Erlandsen
  *
  * Authors: Rodrigo Moya <rodrigo moya canonical com>
+ *          Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU Lesser General Public
@@ -94,16 +96,15 @@ couchdb_document_get (CouchDB *couchdb,
 
 	encoded_docid = soup_uri_encode (docid, NULL);
 	url = g_strdup_printf ("%s/%s/%s", couchdb_get_hostname (couchdb), dbname, encoded_docid);
-	parser = send_message_and_parse (couchdb, SOUP_METHOD_GET, url, NULL, error);
-	if (parser) {
+	parser = json_parser_new ();
+	if (couchdb_send_message (couchdb, SOUP_METHOD_GET, url, NULL, parser, error)) {
 		document = g_object_new (COUCHDB_TYPE_DOCUMENT, NULL);
 		document->couchdb = couchdb;
 		document->dbname = g_strdup (dbname);
 
-		document->root_node = json_node_copy (json_parser_get_root (parser));
-		g_object_unref (G_OBJECT (parser));
+		document->root_node = json_node_copy (json_parser_get_root (parser));		
 	}
-
+	g_object_unref (G_OBJECT (parser));
 	g_free (encoded_docid);
 	g_free (url);
 
@@ -119,34 +120,34 @@ couchdb_document_put (CouchDBDocument *document,
 	const char *id;
 	JsonParser *parser;
 	gboolean result = FALSE;
+	gboolean send_ok;;
 
 	g_return_val_if_fail (COUCHDB_IS_DOCUMENT (document), FALSE);
 	g_return_val_if_fail (dbname != NULL, FALSE);
 
 	id = couchdb_document_get_id (document);
 	body = couchdb_document_to_string (document);
+	parser = json_parser_new ();
 	if (id) {
 		char *encoded_docid;
 
 		encoded_docid = soup_uri_encode (id, NULL);
-		url = g_strdup_printf ("%s/%s/%s", couchdb_get_hostname (document->couchdb), dbname, encoded_docid);
-		parser = send_message_and_parse (document->couchdb, SOUP_METHOD_PUT, url, body, error);
+		url = g_strdup_printf ("%s/%s/%s", couchdb_get_hostname (document->couchdb), dbname, encoded_docid);		
+		send_ok = couchdb_send_message (document->couchdb, SOUP_METHOD_PUT, url, body, parser, error);
 
 		g_free (encoded_docid);
 	} else {
 		url = g_strdup_printf ("%s/%s/", couchdb_get_hostname (document->couchdb), dbname);
-		parser = send_message_and_parse (document->couchdb, SOUP_METHOD_POST, url, body, error);
+		send_ok = couchdb_send_message (document->couchdb, SOUP_METHOD_POST, url, body, parser, error);
 	}
 
-	if (parser) {
+	if (send_ok) {
 		JsonObject *object;
 
 		object = json_node_get_object (json_parser_get_root (parser));
 		couchdb_document_set_id (document, json_object_get_string_member (object, "id"));
 		couchdb_document_set_revision (document, json_object_get_string_member (object, "rev"));
 
-		g_object_unref (G_OBJECT (parser));
-
 		if (document->dbname) {
 			g_free (document->dbname);
 			document->dbname = g_strdup (dbname);
@@ -163,6 +164,7 @@ couchdb_document_put (CouchDBDocument *document,
 	/* free memory */
 	g_free (url);
 	g_free (body);
+	g_object_unref (G_OBJECT (parser));
 
 	return result;
 }
@@ -183,10 +185,9 @@ couchdb_document_delete (CouchDBDocument *document, GError **error)
 		return FALSE;
 
 	url = g_strdup_printf ("%s/%s/%s?rev=%s", couchdb_get_hostname (document->couchdb), document->dbname, id, revision);
-	parser = send_message_and_parse (document->couchdb, SOUP_METHOD_DELETE, url, NULL, error);
-	if (parser) {
-		g_object_unref (G_OBJECT (parser));
-
+	
+	/* We don't parse the http response, therefore the parser arg is NULL */
+	if (couchdb_send_message (document->couchdb, SOUP_METHOD_DELETE, url, NULL, NULL, error)) {		
 		g_signal_emit_by_name (document->couchdb, "document_deleted", document->dbname, id);
 	}
 
@@ -458,3 +459,11 @@ couchdb_document_to_string (CouchDBDocument *document)
 
 	return NULL;
 }
+
+JsonObject *
+couchdb_document_get_json_object (CouchDBDocument *document)
+{
+	g_return_val_if_fail (COUCHDB_IS_DOCUMENT (document), NULL);
+	
+	return json_node_get_object (document->root_node);
+}
diff --git a/couchdb-glib/couchdb-document.h b/couchdb-glib/couchdb-document.h
index c86c24b..cacec47 100644
--- a/couchdb-glib/couchdb-document.h
+++ b/couchdb-glib/couchdb-document.h
@@ -26,6 +26,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
+#include <json-glib/json-glib.h>
 #include "couchdb-types.h"
 #include "couchdb-struct-field.h"
 
@@ -126,6 +127,8 @@ void             couchdb_document_set_application_annotations
       
 char*		couchdb_document_to_string		(CouchDBDocument *document);
 
+JsonObject*	couchdb_document_get_json_object	(CouchDBDocument *document);
+
 G_END_DECLS
 
 #endif /* __COUCHDB_DOCUMENT_H__ */
diff --git a/couchdb-glib/couchdb.c b/couchdb-glib/couchdb.c
index 018591b..ced3442 100644
--- a/couchdb-glib/couchdb.c
+++ b/couchdb-glib/couchdb.c
@@ -1,8 +1,10 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
  * Copyright (C) 2009 Canonical Services Ltd (www.canonical.com)
+ *               2009 Mikkel Kamstrup Erlandsen
  *
  * Authors: Rodrigo Moya <rodrigo moya canonical com>
+ *          Mikkel Kamstrup Erlandsen <mikkel kamstrup gmail com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU Lesser General Public
@@ -21,12 +23,17 @@
 
 #include <libsoup/soup-logger.h>
 #include <libsoup/soup-gnome.h>
-#include <json-glib/json-glib.h>
+#include <libsoup/soup-message.h>
 #include "couchdb.h"
 #include "couchdb-document-info.h"
 #include "couchdb-marshal.h"
 #include "dbwatch.h"
 #include "utils.h"
+#include <string.h>
+#ifdef HAVE_OAUTH
+#include <time.h>
+#include "oauth.h"
+#endif
 
 struct _CouchDB {
 	GObject parent;
@@ -36,16 +43,11 @@ struct _CouchDB {
 
 	GHashTable *db_watchlist;
 
-	/* COMMENT:
-	 * Our ABI now depends on OAUTH config - here be dragons! //kamstrup
-	 */
-	#ifdef HAVE_OAUTH
-		gboolean oauth_enabled;
-		char *oauth_consumer_key;
-		char *oauth_consumer_secret;
-		char *oauth_token_key;
-		char *oauth_token_secret;
-	#endif
+	gboolean oauth_enabled;
+	char *oauth_consumer_key;
+	char *oauth_consumer_secret;
+	char *oauth_token_key;
+	char *oauth_token_secret;	
 };
 
 G_DEFINE_TYPE(CouchDB, couchdb, G_TYPE_OBJECT)
@@ -70,12 +72,14 @@ couchdb_finalize (GObject *object)
 	g_free (couchdb->hostname);
 	g_object_unref (couchdb->http_session);
 
-#ifdef HAVE_OAUTH
-	g_free (couchdb->oauth_consumer_key);
-	g_free (couchdb->oauth_consumer_secret);
-	g_free (couchdb->oauth_token_key);
-	g_free (couchdb->oauth_token_secret);
-#endif
+	if (couchdb->oauth_consumer_key)
+		g_free (couchdb->oauth_consumer_key);
+	if (couchdb->oauth_consumer_secret)
+		g_free (couchdb->oauth_consumer_secret);
+	if (couchdb->oauth_token_key)
+		g_free (couchdb->oauth_token_key);
+	if (couchdb->oauth_token_secret)
+		g_free (couchdb->oauth_token_secret);
 
 	G_OBJECT_CLASS (couchdb_parent_class)->finalize (object);
 }
@@ -156,6 +160,13 @@ couchdb_new (const char *hostname)
 	couchdb->http_session = soup_session_sync_new_with_options (
 		SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_GNOME_FEATURES_2_26,
                 NULL);
+	
+	couchdb->oauth_consumer_key = NULL;        
+	couchdb->oauth_consumer_secret = NULL;
+	couchdb->oauth_token_key = NULL;
+	couchdb->oauth_token_secret = NULL;
+	couchdb->oauth_enabled = FALSE;
+	
 	soup_session_add_feature_by_type (couchdb->http_session, SOUP_TYPE_LOGGER);
 
 	return couchdb;
@@ -180,8 +191,8 @@ couchdb_list_databases (CouchDB *couchdb, GError **error)
 
 	/* Prepare request */
 	url = g_strdup_printf ("%s/_all_dbs", couchdb->hostname);
-	parser = send_message_and_parse (couchdb, SOUP_METHOD_GET, url, NULL, error);
-	if (parser) {
+	parser = json_parser_new ();
+	if (couchdb_send_message (couchdb, SOUP_METHOD_GET, url, NULL, parser, error)) {
 		JsonNode *root_node;
 
 		root_node = json_parser_get_root (parser);
@@ -194,10 +205,9 @@ couchdb_list_databases (CouchDB *couchdb, GError **error)
 					dblist,
 					g_strdup (json_node_get_string ((JsonNode *) sl->data)));
 			}
-		}
-
-		g_object_unref (G_OBJECT (parser));
+		}		
 	}
+	g_object_unref (G_OBJECT (parser));
 
 	/* Free memory */
 	g_free (url);
@@ -216,8 +226,8 @@ couchdb_get_database_info (CouchDB *couchdb, const char *dbname, GError **error)
 	g_return_val_if_fail (dbname != NULL, NULL);
 
 	url = g_strdup_printf ("%s/%s/", couchdb->hostname, dbname);
-	parser = send_message_and_parse (couchdb, SOUP_METHOD_GET, url, NULL, error);
-	if (parser) {
+	parser = json_parser_new ();
+	if (couchdb_send_message (couchdb, SOUP_METHOD_GET, url, NULL, parser, error)) {
 		JsonNode *root_node;
 
 		root_node = json_parser_get_root (parser);
@@ -231,9 +241,8 @@ couchdb_get_database_info (CouchDB *couchdb, const char *dbname, GError **error)
 							    json_object_get_boolean_member (object, "compact_running"),
 							    json_object_get_int_member (object, "disk_size"));
 		}
-		
-		g_object_unref (G_OBJECT (parser));
 	}
+	g_object_unref (G_OBJECT (parser));
 
 	return result;
 }
@@ -249,18 +258,17 @@ couchdb_create_database (CouchDB *couchdb, const char *dbname, GError **error)
 	g_return_val_if_fail (dbname != NULL, FALSE);
 
 	url = g_strdup_printf ("%s/%s/", couchdb->hostname, dbname);
-	parser = send_message_and_parse (couchdb, SOUP_METHOD_PUT, url, NULL, error);
-	if (parser) {
+	parser = json_parser_new ();
+	if (couchdb_send_message (couchdb, SOUP_METHOD_PUT, url, NULL, parser, error)) {
 		JsonNode *root_node;
 
 		root_node = json_parser_get_root (parser);
 		if (json_node_get_node_type (root_node) == JSON_NODE_OBJECT)
 			result = json_object_get_boolean_member (
-				json_node_get_object (root_node), "ok");
-
-		g_object_unref (G_OBJECT (parser));
+				json_node_get_object (root_node), "ok");		
 	}
-
+	
+	g_object_unref (G_OBJECT (parser));
 	g_free (url);
 
 	if (result)
@@ -280,17 +288,16 @@ couchdb_delete_database (CouchDB *couchdb, const char *dbname, GError **error)
 	g_return_val_if_fail (dbname != NULL, FALSE);
 
 	url = g_strdup_printf ("%s/%s/", couchdb->hostname, dbname);
-	parser = send_message_and_parse (couchdb, SOUP_METHOD_DELETE, url, NULL, error);
-	if (parser) {
+	parser = json_parser_new ();
+	if (couchdb_send_message (couchdb, SOUP_METHOD_DELETE, url, NULL, parser, error)) {
 		JsonNode *root_node;
 
 		root_node = json_parser_get_root (parser);
 		if (json_node_get_node_type (root_node) == JSON_NODE_OBJECT)
 			result = json_object_get_boolean_member (
-				json_node_get_object (root_node), "ok");
-
-		g_object_unref (G_OBJECT (parser));
+				json_node_get_object (root_node), "ok");		
 	}
+	g_object_unref (G_OBJECT (parser));
 
 	g_free (url);
 
@@ -325,8 +332,8 @@ couchdb_list_documents (CouchDB *couchdb, const char *dbname, GError **error)
 	g_return_val_if_fail (dbname != NULL, NULL);
 
 	url = g_strdup_printf ("%s/%s/_all_docs", couchdb->hostname, dbname);
-	parser = send_message_and_parse (couchdb, SOUP_METHOD_GET, url, NULL, error);
-	if (parser) {
+	parser = json_parser_new ();
+	if (couchdb_send_message (couchdb, SOUP_METHOD_GET, url, NULL, parser, error)) {
 		JsonNode *root_node;
 
 		root_node = json_parser_get_root (parser);
@@ -353,7 +360,7 @@ couchdb_list_documents (CouchDB *couchdb, const char *dbname, GError **error)
 			}
 		}
 	}
-
+	g_object_unref (G_OBJECT (parser));
 	g_free (url);
 
 	return doclist;
@@ -444,3 +451,154 @@ couchdb_enable_oauth (CouchDB *couchdb,
 	return FALSE;
 #endif
 }
+
+gboolean
+couchdb_is_oauth_enabled (CouchDB *couchdb)
+{
+	g_return_val_if_fail (COUCHDB_IS (couchdb), FALSE);
+	
+	return couchdb->oauth_enabled;
+}
+
+
+static void
+couchdb_add_oauth_signature (CouchDB *couchdb, SoupMessage *http_message, const char *method, const char *url)
+{
+	/* This method is a no-op if we are configured without OAUTH */
+#ifdef HAVE_OAUTH
+	char *signed_url;
+
+	signed_url = oauth_sign_url2 (url, NULL, OA_HMAC, method,
+				      couchdb->oauth_consumer_key,
+				      couchdb->oauth_consumer_secret,
+				      couchdb->oauth_token_key,
+				      couchdb->oauth_token_secret);
+	if (signed_url != NULL) {
+		char **parsed_url;
+		GString *header = NULL;
+
+		/* Get the OAuth signature from the signed URL */
+		parsed_url = g_strsplit (signed_url, "?", 2);
+		if (parsed_url != NULL) {
+			gchar **params;
+			int i;
+
+			params = g_strsplit (parsed_url[1], "&", 0);
+#ifdef DEBUG_OAUTH
+			g_debug ("Parsing %s", parsed_url[1]);
+#endif
+			for (i = 0; params[i] != NULL; i++) {
+				gchar **url_param;
+
+#ifdef DEBUG_OAUTH
+				g_debug ("%s\n", params[i]);
+#endif
+				url_param = g_strsplit (params[i], "=", 2);
+				if (url_param == NULL)
+					continue;
+
+				if (header != NULL)
+					header = g_string_append (header, ", ");
+				else
+					header = g_string_new ("OAuth ");
+
+				header = g_string_append (header, url_param[0]);
+				header = g_string_append (header, "=\"");
+				header = g_string_append (header, url_param[1]);
+				header = g_string_append (header, "\"");
+
+				g_strfreev (url_param);
+			}
+
+			if (params)
+				g_strfreev (params);
+
+			g_strfreev (parsed_url);
+		}
+
+		if (header != NULL) {
+			soup_message_headers_append (http_message->request_headers, "Authorization", header->str);
+
+			g_string_free (header, TRUE);
+		}
+
+		free (signed_url);
+	}
+#endif /* HAVE_OAUTH */
+}
+
+static gboolean
+parse_json_response (CouchDB *couchdb, JsonParser *json_parser, SoupMessage *http_message, GError **error)
+{
+	SoupBuffer *buffer;
+        GString *str = NULL;
+        goffset offset = 0;
+        gboolean success = TRUE;
+	
+	while ((buffer = soup_message_body_get_chunk (http_message->response_body, offset))) {
+		if (!str)
+                        str = g_string_new ("");
+                g_string_append_len (str, buffer->data, buffer->length);
+
+                offset += buffer->length;
+                soup_buffer_free (buffer);
+	}
+
+	if (str && str->len > 0) {
+		g_debug ("Response body: %s", str->str);
+		if (!json_parser_load_from_data (json_parser,
+						 (const gchar *) str->str,
+						 str->len,
+						 error)) {
+			g_object_unref (G_OBJECT (json_parser));
+			g_set_error (error, COUCHDB_ERROR, -1, "Invalid JSON response");
+			success = FALSE;
+		}
+
+		g_string_free (str, TRUE);
+	}
+
+	return success;
+}
+
+static void
+debug_print_headers (const char *name, const char *value, gpointer user_data)
+{
+	g_print ("\t%s: %s\n", name, value);
+}
+
+gboolean
+couchdb_send_message (CouchDB *couchdb, const char *method, const char *url, const char *body, JsonParser *parser, GError **error)
+{
+	SoupMessage *http_message;
+	guint status;
+	
+	g_return_val_if_fail (COUCHDB_IS (couchdb), FALSE);
+	g_return_val_if_fail (method != NULL, FALSE);
+	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+	
+	http_message = soup_message_new (method, url);
+	if (body != NULL) {
+		soup_message_set_request (http_message, "application/json", SOUP_MEMORY_COPY,
+					  body, strlen (body));
+	}
+
+	if (couchdb_is_oauth_enabled (couchdb))
+		couchdb_add_oauth_signature (couchdb, http_message, method, url);
+	
+
+	g_debug ("Sending %s to %s... with headers\n: ", method, url);
+	soup_message_headers_foreach (http_message->request_headers,
+				      (SoupMessageHeadersForeachFunc) debug_print_headers,
+				      NULL);
+
+	status = soup_session_send_message (couchdb->http_session, http_message);
+	if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
+		if (parser != NULL)
+		       	parse_json_response (couchdb, parser, http_message, error);
+	       	return TRUE;
+	} else {
+		g_set_error (error, COUCHDB_ERROR, status, "%s", http_message->reason_phrase);
+		return FALSE;
+	}
+}
diff --git a/couchdb-glib/couchdb.h b/couchdb-glib/couchdb.h
index 63011eb..e87bd99 100644
--- a/couchdb-glib/couchdb.h
+++ b/couchdb-glib/couchdb.h
@@ -26,6 +26,7 @@
 
 #include <glib.h>
 #include <glib-object.h>
+#include <json-glib/json-glib.h>
 #include "couchdb-types.h"
 #include "couchdb-database-info.h"
 
@@ -71,6 +72,10 @@ gboolean             couchdb_enable_oauth (CouchDB *couchdb,
 					   const char *token_secret);
 void                 couchdb_disable_oauth (CouchDB *couchdb);
 
+gboolean             couchdb_is_oauth_enabled (CouchDB *couchdb);
+
+gboolean             couchdb_send_message (CouchDB *couchdb, const char *method, const char *url, const char *body, JsonParser *parser, GError **error);
+
 GSList          *couchdb_list_documents (CouchDB *couchdb, const char *dbname, GError **error);
 void             couchdb_free_document_list (GSList *doclist);
 
diff --git a/couchdb-glib/dbwatch.c b/couchdb-glib/dbwatch.c
index bb9adc0..dc20f50 100644
--- a/couchdb-glib/dbwatch.c
+++ b/couchdb-glib/dbwatch.c
@@ -19,7 +19,8 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#include "couchdb-glib.h"
+#include <libsoup/soup-method.h>
+#include "couchdb-document.h"
 #include "dbwatch.h"
 #include "utils.h"
 
@@ -78,11 +79,11 @@ watch_timeout_cb (gpointer user_data)
 	DBWatch *watch = (DBWatch *) user_data;
 
 	url = g_strdup_printf ("%s/%s/_changes?since=%d",
-			       watch->couchdb->hostname,
+			       couchdb_get_hostname (watch->couchdb),
 			       watch->dbname,
 			       watch->last_update_seq);
-	parser = send_message_and_parse (watch->couchdb, SOUP_METHOD_GET, url, NULL, &error);
-	if (parser != NULL) {
+	parser = json_parser_new ();
+	if (couchdb_send_message (watch->couchdb, SOUP_METHOD_GET, url, NULL, parser, &error)) {
 		JsonNode *root_node;
 
 		root_node = json_parser_get_root (parser);
@@ -102,12 +103,11 @@ watch_timeout_cb (gpointer user_data)
 
 			if (json_object_has_member (root_object, "last_seq"))
 				watch->last_update_seq = json_object_get_int_member (root_object, "last_seq");
-		}
-
-		g_object_unref (G_OBJECT (parser));
+		}		
 	}
 
 	/* Free memory */
+	g_object_unref (G_OBJECT (parser));
 	g_free (url);
 }
 
diff --git a/couchdb-glib/dbwatch.h b/couchdb-glib/dbwatch.h
index 7c1e056..24d59bd 100644
--- a/couchdb-glib/dbwatch.h
+++ b/couchdb-glib/dbwatch.h
@@ -22,6 +22,8 @@
 #ifndef __DBWATCH_H__
 #define __DBWATCH_H__
 
+#include <glib.h>
+#include "couchdb.h"
 #include "utils.h"
 
 typedef struct {
diff --git a/couchdb-glib/utils.c b/couchdb-glib/utils.c
index fce7aa0..296be5e 100644
--- a/couchdb-glib/utils.c
+++ b/couchdb-glib/utils.c
@@ -24,46 +24,6 @@
 #include <libsoup/soup-session-async.h>
 #include "couchdb-glib.h"
 #include "utils.h"
-#ifdef HAVE_OAUTH
-#include <time.h>
-#include "oauth.h"
-#endif
-
-static JsonParser *
-parse_json_response (SoupMessage *http_message, GError **error)
-{
-	SoupBuffer *buffer;
-        GString *str = NULL;
-        goffset offset = 0;
-	JsonParser *json_parser = NULL;
-
-	while ((buffer = soup_message_body_get_chunk (http_message->response_body, offset))) {
-		if (!str)
-                        str = g_string_new ("");
-                g_string_append_len (str, buffer->data, buffer->length);
-
-                offset += buffer->length;
-                soup_buffer_free (buffer);
-	}
-
-	if (str && str->len > 0) {
-		g_debug ("Response body: %s", str->str);
-		json_parser = json_parser_new ();
-		if (!json_parser_load_from_data (json_parser,
-						 (const gchar *) str->str,
-						 str->len,
-						 error)) {
-			g_object_unref (G_OBJECT (json_parser));
-			json_parser = NULL;
-
-			g_set_error (error, COUCHDB_ERROR, -1, "Invalid JSON response");
-		}
-
-		g_string_free (str, TRUE);
-	}
-
-	return json_parser;
-}
 
 GQuark
 couchdb_error_quark (void)
@@ -76,110 +36,6 @@ couchdb_error_quark (void)
 	return error;
 }
 
-#ifdef HAVE_OAUTH
-static void
-add_oauth_signature (CouchDB *couchdb, SoupMessage *http_message, const char *method, const char *url)
-{
-	char *signed_url;
-
-	signed_url = oauth_sign_url2 (url, NULL, OA_HMAC, method,
-				      couchdb->oauth_consumer_key,
-				      couchdb->oauth_consumer_secret,
-				      couchdb->oauth_token_key,
-				      couchdb->oauth_token_secret);
-	if (signed_url != NULL) {
-		char **parsed_url;
-		GString *header = NULL;
-
-		/* Get the OAuth signature from the signed URL */
-		parsed_url = g_strsplit (signed_url, "?", 2);
-		if (parsed_url != NULL) {
-			gchar **params;
-			int i;
-
-			params = g_strsplit (parsed_url[1], "&", 0);
-#ifdef DEBUG_OAUTH
-			g_debug ("Parsing %s", parsed_url[1]);
-#endif
-			for (i = 0; params[i] != NULL; i++) {
-				gchar **url_param;
-
-#ifdef DEBUG_OAUTH
-				g_debug ("%s\n", params[i]);
-#endif
-				url_param = g_strsplit (params[i], "=", 2);
-				if (url_param == NULL)
-					continue;
-
-				if (header != NULL)
-					header = g_string_append (header, ", ");
-				else
-					header = g_string_new ("OAuth ");
-
-				header = g_string_append (header, url_param[0]);
-				header = g_string_append (header, "=\"");
-				header = g_string_append (header, url_param[1]);
-				header = g_string_append (header, "\"");
-
-				g_strfreev (url_param);
-			}
-
-			if (params)
-				g_strfreev (params);
-
-			g_strfreev (parsed_url);
-		}
-
-		if (header != NULL) {
-			soup_message_headers_append (http_message->request_headers, "Authorization", header->str);
-
-			g_string_free (header, TRUE);
-		}
-
-		free (signed_url);
-	}
-}
-#endif
-
-static void
-debug_print_headers (const char *name, const char *value, gpointer user_data)
-{
-	g_print ("\t%s: %s\n", name, value);
-}
-
-JsonParser *
-send_message_and_parse (CouchDB *couchdb, const char *method, const char *url, const char *body, GError **error)
-{
-	SoupMessage *http_message;
-	guint status;
-	JsonParser *parser = NULL;
-
-	http_message = soup_message_new (method, url);
-	if (body != NULL) {
-		soup_message_set_request (http_message, "application/json", SOUP_MEMORY_COPY,
-					  body, strlen (body));
-	}
-
-#ifdef HAVE_OAUTH
-	if (couchdb->oauth_enabled)
-		add_oauth_signature (couchdb, http_message, method, url);
-#endif
-
-	g_debug ("Sending %s to %s... with headers\n: ", method, url);
-	soup_message_headers_foreach (http_message->request_headers,
-				      (SoupMessageHeadersForeachFunc) debug_print_headers,
-				      NULL);
-
-	status = soup_session_send_message (couchdb->http_session, http_message);
-	if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
-	       	parser = parse_json_response (http_message, error);
-	} else {
-		g_set_error (error, COUCHDB_ERROR, status, "%s", http_message->reason_phrase);
-	}
-
-	return parser;
-}
-
 char *
 generate_uuid (void)
 {
diff --git a/couchdb-glib/utils.h b/couchdb-glib/utils.h
index 2b8f8f1..94e6bcd 100644
--- a/couchdb-glib/utils.h
+++ b/couchdb-glib/utils.h
@@ -30,12 +30,6 @@
 #define COUCHDB_ERROR couchdb_error_quark()
 GQuark      couchdb_error_quark (void);
 
-JsonParser* send_message_and_parse (CouchDB *couchdb,
-				    const char *method,
-				    const char *url,
-				    const char *body,
-				    GError **error);
-
 char* generate_uuid (void);
 
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]