Author: abrander
Date: 2009-12-27 22:17:23 +0100 (Sun, 27 Dec 2009)
New Revision: 2859

Added:
   trunk/plugins/output-facebook/rs-facebook-client.c
   trunk/plugins/output-facebook/rs-facebook-client.h
Removed:
   trunk/plugins/output-facebook/facebook.c
   trunk/plugins/output-facebook/facebook.h
Modified:
   trunk/plugins/output-facebook/Makefile.am
   trunk/plugins/output-facebook/output-facebook.c
Log:
GObjectified Facebook client library.

Modified: trunk/plugins/output-facebook/Makefile.am
===================================================================
--- trunk/plugins/output-facebook/Makefile.am   2009-12-27 21:14:51 UTC (rev 
2858)
+++ trunk/plugins/output-facebook/Makefile.am   2009-12-27 21:17:23 UTC (rev 
2859)
@@ -2,6 +2,7 @@
 
 AM_CFLAGS =\
        -Wall\
+       -Wstrict-aliasing=0\
        -O4
 
 AM_CXXFLAGS = $(AM_CFLAGS)
@@ -18,4 +19,6 @@
 
 output_facebook_la_LIBADD = @PACKAGE_LIBS@ 
 output_facebook_la_LDFLAGS = -module -avoid-version -L/usr/lib -lcurl
-output_facebook_la_SOURCES = output-facebook.c facebook.c
+output_facebook_la_SOURCES = output-facebook.c output-facebook.h \
+       rs-facebook-client.c rs-facebook-client.h \
+       rs-facebook-client-param.c rs-facebook-client-param.h

Deleted: trunk/plugins/output-facebook/facebook.c
===================================================================
--- trunk/plugins/output-facebook/facebook.c    2009-12-27 21:14:51 UTC (rev 
2858)
+++ trunk/plugins/output-facebook/facebook.c    2009-12-27 21:17:23 UTC (rev 
2859)
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2006-2009 Anders Brander <[email protected]> and 
- * Anders Kvist <[email protected]>
- *
- * 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
- * of the License, 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
- */
-
-#include <string.h>
-#include <curl/curl.h>
-#include <glib-2.0/glib.h>
-#include <libxml/encoding.h>
-#include "facebook.h"
-
-static facebook *fb = NULL;
-
-gboolean request(gchar *method, GList *params, GString *result);
-static gint sort_alphabetical(gconstpointer a, gconstpointer b);
-GString *get_param_string(GList *params, gboolean separate);
-gchar *get_signature(GList *params);
-size_t write_callback(void *ptr, size_t size, size_t nmemb, void *userp);
-gboolean xml_error(gchar *xml, gint length);
-gchar *parse_xml_response(gchar *xml, gint length, gchar *key, gboolean root);
-
-gboolean
-request(gchar *method, GList *params, GString *result)
-{
-       curl_easy_reset(fb->curl);
-
-#ifdef fb_debug
-       curl_easy_setopt(fb->curl, CURLOPT_VERBOSE, TRUE);
-#endif
-
-        curl_easy_setopt(fb->curl, CURLOPT_URL, fb->server);
-
-       params = g_list_append(params, g_strdup_printf("api_key=%s", 
fb->api_key));
-       params = g_list_append(params, g_strdup_printf("method=%s", method));
-       params = g_list_append(params, g_strdup_printf("v=1.0"));
-       params = g_list_append(params, g_strdup_printf("call_id=%d", 
fb->call_id));
-
-       fb->call_id++;
-
-       if(fb->session_key)
-               params = g_list_append(params, 
g_strdup_printf("session_key=%s", fb->session_key));
-
-       params = g_list_sort(params, sort_alphabetical);        
-
-       params = g_list_append(params, 
g_strdup_printf("sig=%s",get_signature(params)));
-
-       GString *query = get_param_string(params, TRUE);
-
-       struct curl_slist *header = NULL;
-       gchar *temp = g_strdup_printf("Content-Type: multipart/form-data; 
boundary=%s", fb->boundary);
-       header = curl_slist_append(header, temp);
-       g_free(temp);
-       header = curl_slist_append(header, "MIME-version: 1.0;");
-
-        curl_easy_setopt(fb->curl, CURLOPT_POST, TRUE);
-       curl_easy_setopt(fb->curl, CURLOPT_POSTFIELDS, query->str);
-       curl_easy_setopt(fb->curl, CURLOPT_POSTFIELDSIZE, query->len);
-       curl_easy_setopt(fb->curl, CURLOPT_WRITEFUNCTION, write_callback);
-       curl_easy_setopt(fb->curl, CURLOPT_WRITEDATA, result);
-       curl_easy_setopt(fb->curl, CURLOPT_HTTPHEADER, header);
-       fb->res = curl_easy_perform(fb->curl);
-       fb->call_id++;
-       return (fb->res == 0);
-}
-
-static gint
-sort_alphabetical(gconstpointer a, gconstpointer b)
-{
-       gchar *str1 = (gchar *) a;
-       gchar *str2 = (gchar *) b;
-
-       return g_strcmp0(str1, str2);
-}
-
-GString *
-get_param_string(GList *params, gboolean separate)
-{
-       GString *str = g_string_new("");
-       GString *image = NULL;
-
-       gint i;
-
-       for (i = 0; i < g_list_length(params); i++)
-       {
-               if (separate) 
-               {
-                       gchar **split = g_strsplit(g_list_nth_data(params, i), 
"=", 0);
-                       if(g_strcmp0(split[0], "filename") == 0)
-                       {
-                               gchar *contents;
-                               gsize length;
-                               if (g_file_get_contents(split[1], &contents, 
&length, NULL))
-                               {
-                                       
-                                       image = g_string_new("--");
-                                       g_string_append_printf(image, "%s\r\n", 
fb->boundary);
-                                       g_string_append_printf(image, 
"Content-Disposition: form-data; filename=%s\r\n", split[1]);
-                                       g_string_append_printf(image, 
"Content-Type: image/jpg\r\n\r\n");
-                                       image = g_string_append_len(image, 
contents, length);
-                                       g_string_append_printf(image, 
"\r\n--%s\r\n", fb->boundary);
-                               }
-                       }
-                       g_string_append_printf(str, 
"--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n", 
fb->boundary, split[0], split[1]);
-               } else {
-                       str = g_string_append(str, g_list_nth_data(params, i));
-               }
-       }
-
-       if (image)
-               str = g_string_append_len(str, image->str, image->len);
-
-       return str;
-}
-
-gchar *
-get_signature(GList *params)
-{
-       GString *str = get_param_string(params, FALSE);
-       str = g_string_append(str, fb->secret);
-       gchar *signature = g_compute_checksum_for_string(G_CHECKSUM_MD5, 
str->str, strlen(str->str));
-       g_string_free(str, TRUE);
-       return signature;
-}
-
-size_t
-write_callback(void *ptr, size_t size, size_t nmemb, void *userp)
-{
-       GString *string = (GString *) userp;
-       string = g_string_append_len(string, (char *) ptr, size * nmemb);
-       return (size * nmemb);
-}
-
-gboolean
-xml_error(gchar *xml, gint length)
-{
-       gchar *error_code = parse_xml_response(xml, length, "error_code", 
FALSE);
-       gchar *error_msg = parse_xml_response(xml, length, "error_msg", FALSE);
-
-       if (error_code)
-       {
-               printf("error: %s\n", error_msg);
-               g_free(error_code);
-               g_free(error_msg);
-               return TRUE;
-       }
-       g_free(error_code);
-       g_free(error_msg);
-       return FALSE;
-}
-
-gchar *
-parse_xml_response(gchar *xml, gint length, gchar *key, gboolean root)
-{
-       xmlDocPtr doc = xmlParseMemory(xml, length);
-        xmlNodePtr cur;
-
-       cur = xmlDocGetRootElement(doc);
-
-       if (!root)
-               cur = cur->xmlChildrenNode;
-
-       gchar *result = NULL;
-
-       while (cur)
-       {
-               if ((!xmlStrcmp(cur->name, BAD_CAST(key))))
-                       result = xmlNodeListGetString(doc, 
cur->xmlChildrenNode, 1);
-
-               cur = cur->next;
-       }
-       return result;
-}
-
-/* BEGIN PUBLIC FUNCTIONS */
-
-gboolean
-facebook_upload_photo(const gchar *filename, const char *caption)
-{
-       GList *params = NULL;
-       GString *xml = g_string_new("");
-
-       params = g_list_append(params, g_strdup_printf("filename=%s", 
filename));
-       params = g_list_append(params, g_strdup_printf("caption=%s", caption));
-
-       if (!request("facebook.Photos.upload", params, xml))
-               return FALSE;
-
-       if (g_utf8_strlen(xml->str, 1048576) == 0)
-               return FALSE;
-
-       gboolean error = xml_error(xml->str, strlen(xml->str));
-       if (error)
-               return FALSE;
-
-       g_string_free(xml, TRUE);
-       return TRUE;
-}
-
-
-gboolean
-facebook_init(gchar *my_key, gchar *my_secret, gchar *my_server)
-{
-       fb = g_malloc(sizeof(facebook));
-       fb->api_key = my_key;
-       fb->secret = my_secret;
-       fb->server = my_server;
-       fb->call_id = 0;
-       fb->token = NULL;
-       fb->session_key = NULL;
-       fb->boundary = g_compute_checksum_for_string(G_CHECKSUM_MD5, 
"boundary", strlen("boundary"));
-
-       fb->curl = curl_easy_init();
-       if(!fb->curl)
-       {
-               g_error("Could not initialize curl.");
-               return FALSE;
-       }
-       return TRUE;
-}
-
-gboolean
-facebook_get_token()
-{
-       GList *params = NULL;
-       GString *xml = g_string_new("");
-
-       if (!request("facebook.auth.createToken", params, xml))
-               return FALSE;
-
-       if (g_utf8_strlen(xml->str, 1048576) == 0)
-               return FALSE;
-
-       /* Check for errors */
-       gboolean error = xml_error(xml->str, strlen(xml->str));
-       if (error)
-               return FALSE;
-
-       /* Get auth token */
-       fb->token = parse_xml_response(xml->str, strlen(xml->str), 
"auth_createToken_response", TRUE);
-
-       if (!fb->token)
-               return FALSE;
-
-       return TRUE;
-}
-
-gchar *
-facebook_get_auth_url(gchar *url)
-{
-       GString *str = g_string_new(url);
-       str = g_string_append(str, "?api_key=");
-       str = g_string_append(str, fb->api_key);
-       str = g_string_append(str, "&auth_token=");
-       str = g_string_append(str, fb->token);
-
-       gchar *ret = str->str;
-       g_string_free(str, FALSE);
-
-       return ret;
-}
-
-void
-facebook_set_session(gchar *session)
-{
-       fb->session_key = session;
-}
-
-gchar *
-facebook_get_session()
-{
-       GList *params = NULL;
-       GString *xml = g_string_new("");
-
-       params = g_list_append(params, g_strdup_printf("auth_token=%s", 
fb->token));    
-
-       if (!request("facebook.auth.getSession", params, xml))
-               return NULL;
-
-       if (g_utf8_strlen(xml->str, 1048576) == 0)
-               return NULL;
-
-       /* Check for errors */
-       gboolean error = xml_error(xml->str, strlen(xml->str));
-       if (error)
-               return NULL;
-
-       /* Get session_key */
-       fb->session_key = parse_xml_response(xml->str, strlen(xml->str), 
"session_key", FALSE);
-       g_string_free(xml, TRUE);
-
-       if (!fb->session_key)
-               return NULL;
-
-       return fb->session_key;
-}
-
-gboolean
-facebook_ping()
-{
-       GList *params = NULL;
-       GString *xml = g_string_new("");
-
-       if (!request("facebook.users.isAppAdded", params, xml))
-               return FALSE;
-
-       if (g_utf8_strlen(xml->str, 1048576) == 0)
-               return FALSE;
-
-       gboolean error = xml_error(xml->str, strlen(xml->str));
-       if (error)
-               return FALSE;
-
-       gchar *result = parse_xml_response(xml->str, strlen(xml->str), 
"users_isAppAdded_response", TRUE);
-
-       if (g_strcmp0(result, "1") != 0)
-               return FALSE;
-
-       g_string_free(xml, TRUE);
-       return TRUE;
-}
-
-void
-facebook_close()
-{
-       curl_easy_cleanup(fb->curl);
-       g_free(fb);
-}
-
-/* END PUBLIC FUNCTIONS */

Deleted: trunk/plugins/output-facebook/facebook.h
===================================================================
--- trunk/plugins/output-facebook/facebook.h    2009-12-27 21:14:51 UTC (rev 
2858)
+++ trunk/plugins/output-facebook/facebook.h    2009-12-27 21:17:23 UTC (rev 
2859)
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2006-2009 Anders Brander <[email protected]> and 
- * Anders Kvist <[email protected]>
- *
- * 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
- * of the License, 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
- */
-
-#ifndef FACEBOOK_H
-#define FACEBOOK_H
-
-#include <glib-2.0/glib.h>
-#include <curl/curl.h>
-
-typedef struct {
-        gchar *api_key;
-       gchar *secret;
-       gchar *token;
-       gchar *server;
-       gchar *session_key;
-       gchar *boundary;
-
-       /* curl */
-       CURL *curl;
-       CURLcode res;
-       gint call_id;
-} facebook;
-
-gboolean facebook_upload_photo(const gchar *filename, const char *caption);
-gboolean facebook_init(gchar *my_key, gchar *my_secret, gchar *my_server);
-gboolean facebook_get_token();
-gchar * facebook_get_auth_url(gchar *url);
-void facebook_set_session(gchar *session);
-gchar * facebook_get_session();
-gboolean facebook_ping();
-void facebook_close();
-
-#endif /* FACEBOOK_H */

Modified: trunk/plugins/output-facebook/output-facebook.c
===================================================================
--- trunk/plugins/output-facebook/output-facebook.c     2009-12-27 21:14:51 UTC 
(rev 2858)
+++ trunk/plugins/output-facebook/output-facebook.c     2009-12-27 21:17:23 UTC 
(rev 2859)
@@ -31,7 +31,7 @@
 #include "output-facebook.h"
 #include <unistd.h>
 #include <string.h>
-#include "facebook.h"
+#include "rs-facebook-client.h"
 
 /* Ugly HACK - conf_interface.c|h needs to be ported to librawstudio */
 gchar *rs_conf_get_string (const gchar * name);
@@ -215,7 +215,7 @@
 }
 
 gboolean
-auth_popup(gchar *text, gchar *auth_url)
+auth_popup(const gchar *text, const gchar *auth_url)
 {
        /* FIXME: move this to librawstudio */
 
@@ -272,31 +272,53 @@
 }
 
 static gboolean
+deal_with_error(GError **error)
+{
+       if (!*error)
+               return FALSE;
+
+       g_warning("Error from Facebook: '%s'", (*error)->message);
+
+       gdk_threads_enter();
+       GtkWidget *dialog = gtk_message_dialog_new(NULL, 0, GTK_MESSAGE_ERROR, 
GTK_BUTTONS_CLOSE,
+               "Error: '%s'", (*error)->message);
+
+       gtk_window_set_title(GTK_WINDOW(dialog), _("Unhandled error from 
Facebook"));
+       gtk_dialog_set_default_response (GTK_DIALOG (dialog), 
GTK_RESPONSE_CLOSE);
+
+       g_signal_connect(dialog, "response", G_CALLBACK(gtk_widget_destroy), 
NULL);
+
+       gtk_widget_show (dialog);
+
+       gdk_threads_leave();
+
+       g_clear_error(error);
+
+       return TRUE;
+}
+
+static gboolean
 execute (RSOutput * output, RSFilter * filter)
 {
+       GError *error = NULL;
        RSFacebook *facebook = RS_FACEBOOK (output);
 
-       if (!facebook_init(FACEBOOK_API_KEY, FACEBOOK_SECRET_KEY, 
FACEBOOK_SERVER))
-               return FALSE;
-
        gchar *session = rs_conf_get_string("facebook_session");
+       RSFacebookClient *facebook_client = 
rs_facebook_client_new(FACEBOOK_API_KEY, FACEBOOK_SECRET_KEY, session);
+       g_free(session);
 
-       if (session)
-               facebook_set_session(session);
+       gboolean ping = rs_facebook_client_ping(facebook_client, &error);
+       deal_with_error(&error);
 
-       if(!facebook_ping())
+       if (!ping)
        {
-
-               facebook_set_session(NULL);
-
-               if (!facebook_get_token())
-                       return FALSE;
-
-               gchar *url =  facebook_get_auth_url(FACEBOOK_LOGIN);
+               const gchar *url = 
rs_facebook_client_get_auth_url(facebook_client, FACEBOOK_LOGIN, &error);
+               deal_with_error(&error);
                if (!auth_popup(_("Rawstudio needs to be authenticated before 
it will be able to upload photos to your Facebook account."), url))
                        return FALSE;
 
-               gchar *session = facebook_get_session();
+               const gchar *session = 
rs_facebook_client_get_session_key(facebook_client, &error);
+               deal_with_error(&error);
                if (!session)
                        return FALSE;
 
@@ -310,12 +332,12 @@
        rs_output_execute (jpegsave, filter);
        g_object_unref (jpegsave);
 
-       if(!facebook_upload_photo(temp_file, facebook->caption))
-               return FALSE;
+       gboolean ret = rs_facebook_client_upload_image(facebook_client, 
temp_file, facebook->caption, &error);
+       deal_with_error(&error);
 
        unlink (temp_file);
        g_free (temp_file);
-       facebook_close();
+       g_object_unref(facebook_client);
 
-       return TRUE;
+       return ret;
 }

Added: trunk/plugins/output-facebook/rs-facebook-client.c
===================================================================
--- trunk/plugins/output-facebook/rs-facebook-client.c                          
(rev 0)
+++ trunk/plugins/output-facebook/rs-facebook-client.c  2009-12-27 21:17:23 UTC 
(rev 2859)
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2006-2009 Anders Brander <[email protected]> and 
+ * Anders Kvist <[email protected]>
+ *
+ * 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
+ * of the License, 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
+ */
+
+#include <curl/curl.h>
+#include <libxml/encoding.h>
+#include "rs-facebook-client.h"
+
+#define HTTP_BOUNDARY "4wncn84cq4ncto874ytnv90w43htn"
+
+/**
+ * Get a quark used to describe Facebook error domain
+ * @return A quark touse in GErrors from Facebook code
+ */
+GQuark
+rs_facebook_client_error_quark(void)
+{
+       static GStaticMutex lock = G_STATIC_MUTEX_INIT;
+       static GQuark quark;
+
+       g_static_mutex_lock(&lock);
+       if (!quark)
+               quark = 
g_quark_from_static_string("rawstudio_facebook_client_error");
+       g_static_mutex_unlock(&lock);
+
+       return quark;
+}
+
+struct _RSFacebookClient {
+       GObject parent;
+
+       const gchar *api_key;
+       const gchar *secret;
+
+       gchar *session_key;
+       gchar *auth_token;
+       gchar *auth_url;
+
+       CURL *curl;
+};
+
+G_DEFINE_TYPE(RSFacebookClient, rs_facebook_client, G_TYPE_OBJECT)
+
+static void
+rs_facebook_client_finalize(GObject *object)
+{
+       RSFacebookClient *facebook = RS_FACEBOOK_CLIENT(object);
+
+       g_free(facebook->session_key);
+       g_free(facebook->auth_token);
+       g_free(facebook->auth_url);
+
+       curl_easy_cleanup(facebook->curl);
+
+       G_OBJECT_CLASS(rs_facebook_client_parent_class)->finalize(object);
+}
+
+static void
+rs_facebook_client_class_init(RSFacebookClientClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS(klass);
+
+       object_class->finalize = rs_facebook_client_finalize;
+}
+
+static void
+rs_facebook_client_init(RSFacebookClient *facebook)
+{
+       facebook->curl = curl_easy_init();
+}
+
+static gchar *
+xml_simple_response(const GString *xml, const gchar *needle, const gboolean 
root)
+{
+       xmlDocPtr doc = xmlParseMemory(xml->str, xml->len);
+       xmlNodePtr cur;
+
+       cur = xmlDocGetRootElement(doc);
+
+       if (!root)
+               cur = cur->xmlChildrenNode;
+
+       gchar *result = NULL;
+
+       while (cur)
+       {
+               if ((!xmlStrcmp(cur->name, BAD_CAST(needle))))
+                       result = (gchar *) xmlNodeListGetString(doc, 
cur->xmlChildrenNode, 1);
+
+               cur = cur->next;
+       }
+       return result;
+}
+
+static gboolean
+xml_error(const GString *xml, GError **error)
+{
+       gchar *error_code = xml_simple_response(xml, "error_code", FALSE);
+       gchar *error_msg = xml_simple_response(xml, "error_msg", FALSE);
+
+       if (error_code)
+       {
+               g_set_error(error, RS_FACEBOOK_CLIENT_ERROR_DOMAIN, 0, "%s", 
error_msg);
+               g_free(error_code);
+               g_free(error_msg);
+               return TRUE;
+       }
+       g_free(error_code);
+       g_free(error_msg);
+       return FALSE;
+}
+
+static size_t
+write_callback(void *ptr, size_t size, size_t nmemb, void *userp)
+{
+    GString *string = (GString *) userp;
+    g_string_append_len(string, (char *) ptr, size * nmemb);
+    return (size * nmemb);
+}
+
+static gboolean
+facebook_client_request(RSFacebookClient *facebook, const gchar *method, 
RSFacebookClientParam *param, GString *content, GError **error)
+{
+       volatile static gint call_id = 0;
+       CURLcode result;
+       struct curl_slist *header = NULL;
+       gint post_length = 0;
+       gchar *post_str;
+
+       /* We start by resetting all CURL parameters */
+       curl_easy_reset(facebook->curl);
+
+#ifdef fb_debug
+       curl_easy_setopt(facebook->curl, CURLOPT_VERBOSE, TRUE);
+#endif /* fb_debug */
+
+       g_atomic_int_inc(&call_id);
+
+       curl_easy_setopt(facebook->curl, CURLOPT_URL, 
"api.facebook.com/restserver.php");
+       rs_facebook_client_param_add_string(param, "api_key2", 
facebook->api_key);
+       rs_facebook_client_param_add_string(param, "method", method);
+       rs_facebook_client_param_add_string(param, "v", "1.0");
+       rs_facebook_client_param_add_integer(param, "call_id", 
g_atomic_int_get(&call_id));
+
+       /* If we have a session key, we will use it */
+       if(facebook->session_key)
+               rs_facebook_client_param_add_string(param, "session_key", 
facebook->session_key);
+
+       header = curl_slist_append(header, "Content-Type: multipart/form-data; 
boundary=" HTTP_BOUNDARY);
+       header = curl_slist_append(header, "MIME-version: 1.0;");
+
+       post_str = rs_facebook_client_param_get_post(param, facebook->secret, 
HTTP_BOUNDARY, &post_length);
+
+       curl_easy_setopt(facebook->curl, CURLOPT_POST, TRUE);
+       curl_easy_setopt(facebook->curl, CURLOPT_POSTFIELDS, post_str);
+       curl_easy_setopt(facebook->curl, CURLOPT_POSTFIELDSIZE, post_length);
+       curl_easy_setopt(facebook->curl, CURLOPT_WRITEFUNCTION, write_callback);
+       curl_easy_setopt(facebook->curl, CURLOPT_WRITEDATA, content);
+       curl_easy_setopt(facebook->curl, CURLOPT_HTTPHEADER, header);
+       result = curl_easy_perform(facebook->curl);
+
+       curl_slist_free_all(header);
+       g_free(post_str);
+       g_object_unref(param);
+
+       if (xml_error(content, error))
+               return FALSE;
+
+       return (result==0);
+}
+
+static const gchar *
+facebook_client_get_auth_token(RSFacebookClient *facebook, GError **error)
+{
+       static GStaticMutex lock = G_STATIC_MUTEX_INIT;
+
+       g_static_mutex_lock(&lock);
+       if (!facebook->auth_token)
+       {
+               GString *content = g_string_new("");
+               facebook_client_request(facebook, "facebook.auth.createToken", 
rs_facebook_client_param_new(), content, error);
+               facebook->auth_token = xml_simple_response(content, 
"auth_createToken_response", TRUE);
+               g_string_free(content, TRUE);
+       }
+       g_static_mutex_unlock(&lock);
+
+       return facebook->auth_token;
+}
+
+/**
+ * Initializes a new RSFacebookClient
+ * @param api_key The API key from Facebook
+ * @param secret The secret provided by Facebook
+ * @param session_key The stored session key or NULL if you haven't got one yet
+ * @return A new RSFacebookClient, this must be unreffed
+ */
+RSFacebookClient *
+rs_facebook_client_new(const gchar *api_key, const gchar *secret, const gchar 
*session_key)
+{
+       RSFacebookClient *facebook = g_object_new(RS_TYPE_FACEBOOK_CLIENT, 
NULL);
+
+       facebook->api_key = api_key;
+       facebook->secret = secret;
+
+       rs_facebook_client_set_session_key(facebook, session_key);
+
+       return facebook;
+}
+
+
+/**
+ * Get the url that the user must visit to authenticate this application 
(api_key)
+ * @param facebook A RSFacebookClient
+ * @param base_url A prefix URL, "http://api.facebook.com/login.php"; would 
make sense
+ * @param error NULL or a pointer to a GError * initialized to NULL
+ * @return A URL that the user can visit to authenticate this application. 
Thisshould not be freed
+ */
+const gchar *
+rs_facebook_client_get_auth_url(RSFacebookClient *facebook, const gchar 
*base_url, GError **error)
+{
+       static GStaticMutex lock = G_STATIC_MUTEX_INIT;
+
+       g_assert(RS_IS_FACEBOOK_CLIENT(facebook));
+
+       g_static_mutex_lock(&lock);
+       if (!facebook->auth_url)
+               facebook->auth_url = 
g_strdup_printf("%s?api_key=%s&auth_token=%s", base_url, facebook->api_key, 
facebook_client_get_auth_token(facebook, error));
+       g_static_mutex_unlock(&lock);
+
+       return facebook->auth_url;
+}
+
+/**
+ * Get the session key as returned from Facebook
+ * @param facebook A RSFacebookClient
+ * @param error NULL or a pointer to a GError * initialized to NULL
+ * @return The session key from Facebook or NULL on error
+ */
+const gchar *
+rs_facebook_client_get_session_key(RSFacebookClient *facebook, GError **error)
+{
+       static GStaticMutex lock = G_STATIC_MUTEX_INIT;
+
+       g_assert(RS_IS_FACEBOOK_CLIENT(facebook));
+
+       g_static_mutex_lock(&lock);
+       RSFacebookClientParam *param = rs_facebook_client_param_new();
+
+       rs_facebook_client_param_add_string(param, "auth_token", 
facebook->auth_token);
+       GString *content = g_string_new("");
+       facebook_client_request(facebook, "facebook.auth.getSession", param, 
content, error);
+
+       g_free(facebook->session_key);
+       facebook->session_key = xml_simple_response(content, "session_key", 
FALSE);
+       g_string_free(content, TRUE);
+       g_static_mutex_unlock(&lock);
+
+       return facebook->session_key;
+}
+
+/**
+ * Set the session key, this can be used to cache the session_key
+ * @param facebook A RSFacebookClient
+ * @param session_key A new session key to use
+ */
+void
+rs_facebook_client_set_session_key(RSFacebookClient *facebook, const gchar 
*session_key)
+{
+       g_assert(RS_IS_FACEBOOK_CLIENT(facebook));
+
+       g_free(facebook->session_key);
+
+       facebook->session_key = g_strdup(session_key);
+}
+
+/**
+ * Check if we are authenticated to Facebook
+ * @param facebook A RSFacebookClient
+ * @param error NULL or a pointer to a GError * initialized to NULL
+ * @return TRUE if we're authenticated both by the Facebook API and by the 
end-user, FALSE otherwise
+ */
+gboolean
+rs_facebook_client_ping(RSFacebookClient *facebook, GError **error)
+{
+       gboolean ret = FALSE;
+       g_assert(RS_IS_FACEBOOK_CLIENT(facebook));
+
+       GString *content = g_string_new("");
+       facebook_client_request(facebook, "facebook.users.isAppAdded", 
rs_facebook_client_param_new(), content, error);
+       gchar *result = xml_simple_response(content, 
"users_isAppAdded_response", TRUE);
+       g_string_free(content, TRUE);
+
+       if (result && g_str_equal(result, "1"))
+               ret = TRUE;
+
+       g_free(result);
+
+       return ret;
+}
+
+/**
+ * Upload a photo to Facebook, will be placed in the registered applications 
default photo folder
+ * @param facebook A RSFacebookClient
+ * @param filename Full path to an image to upload. JPEG, PNG, TIFF accepted
+ * @param caption The caption to use for the image
+ * @param error NULL or a pointer to a GError * initialized to NULL
+ * @return TRUE on success, FALSE otherwise
+ */
+gboolean
+rs_facebook_client_upload_image(RSFacebookClient *facebook, const gchar 
*filename, const gchar *caption, GError **error)
+{
+       g_assert(RS_IS_FACEBOOK_CLIENT(facebook));
+       g_return_val_if_fail(filename != NULL, FALSE);
+       g_return_val_if_fail(g_path_is_absolute(filename), FALSE);
+
+       RSFacebookClientParam *param = rs_facebook_client_param_new();
+
+       rs_facebook_client_param_add_string(param, "filename", filename);
+       if (caption)
+               rs_facebook_client_param_add_string(param, "caption", caption);
+
+       GString *content = g_string_new("");
+       facebook_client_request(facebook, "facebook.photos.upload", param, 
content, error);
+
+       g_string_free(content, TRUE);
+
+       return TRUE;
+}

Added: trunk/plugins/output-facebook/rs-facebook-client.h
===================================================================
--- trunk/plugins/output-facebook/rs-facebook-client.h                          
(rev 0)
+++ trunk/plugins/output-facebook/rs-facebook-client.h  2009-12-27 21:17:23 UTC 
(rev 2859)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2006-2009 Anders Brander <[email protected]> and 
+ * Anders Kvist <[email protected]>
+ *
+ * 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
+ * of the License, 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
+ */
+
+#ifndef RS_FACEBOOK_CLIENT_H
+#define RS_FACEBOOK_CLIENT_H
+
+#include <glib-object.h>
+#include "rs-facebook-client-param.h"
+
+G_BEGIN_DECLS
+
+/**
+ * Get a quark used to describe Facebook error domain
+ * @return A quark touse in GErrors from Facebook code
+ */
+GQuark
+rs_facebook_client_error_quark(void);
+
+#define RS_FACEBOOK_CLIENT_ERROR_DOMAIN rs_facebook_client_error_quark()
+
+#define RS_TYPE_FACEBOOK_CLIENT rs_facebook_client_get_type()
+#define RS_FACEBOOK_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
RS_TYPE_FACEBOOK_CLIENT, RSFacebookClient))
+#define RS_FACEBOOK_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), 
RS_TYPE_FACEBOOK_CLIENT, RSFacebookClientClass))
+#define RS_IS_FACEBOOK_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
RS_TYPE_FACEBOOK_CLIENT))
+#define RS_IS_FACEBOOK_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
RS_TYPE_FACEBOOK_CLIENT))
+#define RS_FACEBOOK_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
RS_TYPE_FACEBOOK_CLIENT, RSFacebookClientClass))
+
+typedef struct _RSFacebookClient RSFacebookClient;
+
+typedef struct {
+       GObjectClass parent_class;
+} RSFacebookClientClass;
+
+GType rs_facebook_client_get_type(void);
+
+/**
+ * Initializes a new RSFacebookClient
+ * @param api_key The API key from Facebook
+ * @param secret The secret provided by Facebook
+ * @param session_key The stored session key or NULL if you haven't got one yet
+ * @return A new RSFacebookClient, this must be unreffed
+ */
+RSFacebookClient *
+rs_facebook_client_new(const gchar *api_key, const gchar *secret, const gchar 
*session_key);
+
+/**
+ * Get the url that the user must visit to authenticate this application 
(api_key)
+ * @param facebook A RSFacebookClient
+ * @param base_url A prefix URL, "http://api.facebook.com/login.php"; would 
make sense
+ * @param error NULL or a pointer to a GError * initialized to NULL
+ * @return A URL that the user can visit to authenticate this application. 
Thisshould not be freed
+ */
+const gchar *
+rs_facebook_client_get_auth_url(RSFacebookClient *facebook, const gchar 
*base_url, GError **error);
+
+/**
+ * Get the session key as returned from Facebook
+ * @param facebook A RSFacebookClient
+ * @param error NULL or a pointer to a GError * initialized to NULL
+ * @return The session key from Facebook or NULL on error
+ */
+const gchar *
+rs_facebook_client_get_session_key(RSFacebookClient *facebook, GError **error);
+
+/**
+ * Set the session key, this can be used to cache the session_key
+ * @param facebook A RSFacebookClient
+ * @param session_key A new session key to use
+ */
+void
+rs_facebook_client_set_session_key(RSFacebookClient *facebook, const gchar 
*session_key);
+
+/**
+ * Check if we are authenticated to Facebook
+ * @param facebook A RSFacebookClient
+ * @param error NULL or a pointer to a GError * initialized to NULL
+ * @return TRUE if we're authenticated both by the Facebook API and by the 
end-user, FALSE otherwise
+ */
+gboolean
+rs_facebook_client_ping(RSFacebookClient *facebook, GError **error);
+
+/**
+ * Upload a photo to Facebook, will be placed in the registered applications 
default photo folder
+ * @param facebook A RSFacebookClient
+ * @param filename Full path to an image to upload. JPEG, PNG, TIFF accepted
+ * @param caption The caption to use for the image
+ * @param error NULL or a pointer to a GError * initialized to NULL
+ * @return TRUE on success, FALSE otherwise
+ */
+gboolean
+rs_facebook_client_upload_image(RSFacebookClient *facebook, const gchar 
*filename, const gchar *caption, GError **error);
+
+G_END_DECLS
+
+#endif /* RS_FACEBOOK_CLIENT_H */


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to