--- /dev/null
+#include "ribbonmanager.h"
+
+#include <QDebug>
+#include <QFile>
+#include <libpurple/purple.h>
+#include <cstdio>
+
+/* Eventloop and glib IO stuff copied verbatim from nullclient.c */
+#define PURPLE_GLIB_READ_COND (G_IO_IN | G_IO_HUP | G_IO_ERR)
+#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)
+
+typedef struct _PurpleGLibIOClosure {
+ PurpleInputFunction function;
+ guint result;
+ gpointer data;
+} PurpleGLibIOClosure;
+
+static void purple_glib_io_destroy(gpointer data)
+{
+ g_free(data);
+}
+
+static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+ PurpleGLibIOClosure *closure = (PurpleGLibIOClosure*)data;
+ PurpleInputCondition purple_cond = (PurpleInputCondition)0;
+
+ if (condition & PURPLE_GLIB_READ_COND)
+ purple_cond = (PurpleInputCondition)(purple_cond | PURPLE_INPUT_READ);
+ if (condition & PURPLE_GLIB_WRITE_COND)
+ purple_cond = (PurpleInputCondition)(purple_cond | PURPLE_INPUT_WRITE);
+
+ closure->function(closure->data, g_io_channel_unix_get_fd(source),
+ purple_cond);
+
+ return TRUE;
+}
+
+static guint glib_input_add(gint fd, PurpleInputCondition condition,
+ PurpleInputFunction function, gpointer data)
+{
+ PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);
+ GIOChannel *channel;
+ GIOCondition cond = (GIOCondition)0;
+
+ closure->function = function;
+ closure->data = data;
+
+ if (condition & PURPLE_INPUT_READ)
+ cond = (GIOCondition)(cond | PURPLE_GLIB_READ_COND);
+ if (condition & PURPLE_INPUT_WRITE)
+ cond = (GIOCondition)(cond | PURPLE_GLIB_WRITE_COND);
+
+ channel = g_io_channel_unix_new(fd);
+ closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
+ cond, purple_glib_io_invoke, closure, purple_glib_io_destroy);
+
+ g_io_channel_unref(channel);
+ return closure->result;
+}
+
+static PurpleEventLoopUiOps glib_eventloops =
+{
+ g_timeout_add, /* guint timeout_add(guint interval, GSourceFunc function, gpointer data) */
+ g_source_remove, /* gboolean timeout_remove(guint handle); */
+ glib_input_add, /* guint input_add(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer user_data) */
+ g_source_remove, /* gboolean input_remove(guint handle) */
+ NULL, /* int input_get_error(int fd, int* error) */
+ g_timeout_add_seconds, /* guint timeout_add_seconds(guint interval, GSourceFunc function, gpointer data) */
+
+ /* padding */
+ //NULL,
+ NULL,
+ NULL,
+ NULL
+};
+/* End verbatim copied code */
+
+/* noops for now, add features later */
+static PurpleConversationUiOps ribbon_conversation_callbacks = {
+ NULL, /* create_conversation */
+ NULL, /* destroy_conversation */
+ NULL, /* write_chat */
+ NULL, /* write_im */
+ NULL, /* write_conv */
+ NULL, /* chat_add_users */
+ NULL, /* chat_rename_user */
+ NULL, /* chat_remove_users */
+ NULL, /* chat_update_user */
+ NULL, /* present */
+ NULL, /* has_focus */
+ NULL, /* custom_smiley_add */
+ NULL, /* custom_smiley_write */
+ NULL, /* custom_smiley_close */
+ NULL, /* send_confirm */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void connect_progress(PurpleConnection *gc, const char* text, size_t step, size_t step_count)
+{
+ Q_UNUSED(gc);
+ qDebug() << "Connection progress:" << text << step << "of" << step_count;
+}
+
+static void connection_notice(PurpleConnection *gc, const char* text)
+{
+ Q_UNUSED(gc);
+ qDebug() << "Connection notice:" << text;
+}
+
+static void connection_disconnected(PurpleConnection *gc, const char* text)
+{
+ Q_UNUSED(gc);
+ qDebug() << "Connection disconnected:" << text;
+}
+
+static void network_connected(void)
+{
+ printf("Network connection established\n");
+}
+
+static void network_disconnected(void)
+{
+ printf("This machine has been disconnected from the internet\n");
+}
+
+static void report_disconnect_reason(PurpleConnection *gc, PurpleConnectionError reason, const char *text)
+{
+ PurpleAccount *account = purple_connection_get_account(gc);
+ printf("Connection disconnected: \"%s\" (%s)\n >Error: %d\n >Reason: %s\n", purple_account_get_username(account), purple_account_get_protocol_id(account), reason, text);
+}
+
+static PurpleConnectionUiOps connection_uiops =
+{
+ connect_progress, /* connect_progress */
+ NULL, /* connected */
+ NULL, /* disconnected */
+ connection_notice, /* notice */
+ connection_disconnected, /* report_disconnect */
+ network_connected, /* network_connected */
+ network_disconnected, /* network_disconnected */
+ report_disconnect_reason, /* report_disconnect_reason */
+ NULL,
+ NULL,
+ NULL
+};
+
+static void ribbon_core_init(void) {
+ printf("core_init called\n");
+ printf("setting connection callbacks\n");
+ purple_connections_set_ui_ops(&connection_uiops);
+}
+
+static PurpleCoreUiOps ribbon_core_callbacks = {
+ NULL, /* ui_prefs_init - called just after preferences subsystem is initialized */
+ NULL, /* debug_ui_init - called just after the debug system is inited, but before other components init */
+ ribbon_core_init, /* ui_init - called after all of libpurple has been initialized */
+ NULL, /* quit - called after most of libpurple has been uninitialized */
+ NULL, /* get_ui_info - called by purple_core_get_ui_info, should return a
+ GHashTable* with string key/value pairs containing info about the UI, like:
+ name, version, website, dev_website */
+ /* padding */
+ //NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void signed_on(PurpleConnection *gc)
+{
+ PurpleAccount *account = purple_connection_get_account(gc);
+ printf("Account connected: \"%s\" (%s)\n", purple_account_get_username(account), purple_account_get_protocol_id(account));
+}
+
+static void received_im_msg(PurpleAccount *account, char *sender, char *message,
+ PurpleConversation *conv, PurpleMessageFlags flags)
+{
+ Q_UNUSED(flags);
+ if (conv==NULL) {
+ conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender);
+ }
+ printf("(%s) %s (%s): %s\n", purple_utf8_strftime("%H:%M:%S", NULL), sender, purple_conversation_get_name(conv), message);
+}
+
+void connect_to_signals(void)
+{
+ static int handle;
+ purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
+ PURPLE_CALLBACK(signed_on), NULL);
+ purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", &handle,
+ PURPLE_CALLBACK(received_im_msg), NULL);
+}
+
+RibbonManager::RibbonManager(QObject* parent) : QObject(parent)
+{
+}
+
+RibbonManager::~RibbonManager()
+{
+}
+
+void RibbonManager::init_libpurple(void)
+{
+ /* optional:
+ purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
+ */
+
+ /* Enable debugging messages */
+ purple_debug_set_enabled(FALSE);
+
+ /* configure purple core callbacks */
+ purple_core_set_ui_ops(&ribbon_core_callbacks);
+ /* configure purple eventloop */
+ purple_eventloop_set_ui_ops(&glib_eventloops);
+ /* Init purple core */
+ if (!purple_core_init(UI_ID)) {
+ /* Initializing the core failed. Terminate. */
+ fprintf(stderr,
+ "libpurple initialization failed. Dumping core.\n"
+ "Please report this!\n");
+ abort();
+ }
+
+ /* Create and load the buddylist */
+ purple_set_blist(purple_blist_new());
+ purple_blist_load();
+
+ /* Hopefully this is an okay time for this? */
+ connect_to_signals();
+}
+
+const char* RibbonManager::get_version(void)
+{
+ return purple_core_get_version();
+}
+
+void RibbonManager::sign_in_user(void)
+{
+ QFile file("account.txt");
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qDebug() << "Couldn't load account information from account.txt!";
+ return;
+ }
+ QByteArray protocol = file.readLine().trimmed();
+ QByteArray username = file.readLine().trimmed();
+ QByteArray password = file.readLine().trimmed();
+ // Allocate and enable an account.
+ // PurpleAccount *account = purple_account_new("YOUR_IM_ACCOUNTS_USERNAME_HERE", "prpl-IM_NETWORK_HERE"); //this could be prpl-aim, prpl-yahoo, prpl-msn, prpl-icq, etc.
+ PurpleAccount *account = purple_account_new(username.data(), protocol.data());
+ // purple_account_set_password(account, "YOUR_IM_ACCOUNTS_PASSWORD_HERE");
+ purple_account_set_password(account, password.data());
+ purple_accounts_add(account);
+ purple_account_set_enabled(account, UI_ID, TRUE);
+}