libpurple/ciphers/rc4.c

branch
soc.2013.gobjectification
changeset 34536
38cc893bae51
parent 33914
2ae6a9601d0f
child 34547
45b72366ddde
--- a/libpurple/ciphers/rc4.c	Thu Jun 13 19:39:47 2013 +0530
+++ b/libpurple/ciphers/rc4.c	Thu Jun 13 20:43:35 2013 +0530
@@ -19,74 +19,67 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
  */
+#include "rc4.h"
 
-#include "internal.h"
-#include <cipher.h>
-#include "ciphers.h"
-#include <util.h>
+/*******************************************************************************
+ * Structs
+ ******************************************************************************/
+#define PURPLE_RC4_CIPHER_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherPrivate))
 
-struct RC4Context {
-	guchar state[256];
-	guchar x;
-	guchar y;
-	gint key_len;
+typedef struct {
+  guchar state[256];
+  guchar x;
+  guchar y;
+  gint key_len;
+} PurpleRC4CipherPrivate;
+
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+enum {
+	PROP_ZERO,
+	PROP_KEY_LEN,
+	PROP_KEY,
+	PROP_LAST,
 };
 
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
+static GObjectClass *parent_class = NULL;
+
+/******************************************************************************
+ * Cipher Stuff
+ *****************************************************************************/
 static void
-rc4_init(PurpleCipherContext *context, void *extra) {
-	struct RC4Context *rc4_ctx;
-	rc4_ctx = g_new0(struct RC4Context, 1);
-	purple_cipher_context_set_data(context, rc4_ctx);
-	purple_cipher_context_reset(context, extra);
-}
-
-
-static void
-rc4_reset(PurpleCipherContext *context, void *extra) {
-	struct RC4Context *rc4_ctx;
+purple_rc4_cipher_reset(PurpleCipher *cipher) {
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
+	PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
 	guint i;
 
-	rc4_ctx = purple_cipher_context_get_data(context);
-
-	g_return_if_fail(rc4_ctx);
-
 	for(i = 0; i < 256; i++)
-		rc4_ctx->state[i] = i;
-	rc4_ctx->x = 0;
-	rc4_ctx->y = 0;
+		priv->state[i] = i;
+	priv->x = 0;
+	priv->y = 0;
 
 	/* default is 5 bytes (40bit key) */
-	rc4_ctx->key_len = 5;
-
+	priv->key_len = 5;
 }
 
 static void
-rc4_uninit(PurpleCipherContext *context) {
-	struct RC4Context *rc4_ctx;
-
-	rc4_ctx = purple_cipher_context_get_data(context);
-	memset(rc4_ctx, 0, sizeof(*rc4_ctx));
-
-	g_free(rc4_ctx);
-	rc4_ctx = NULL;
-}
-
-
-
-static void
-rc4_set_key (PurpleCipherContext *context, const guchar * key, size_t len) {
-	struct RC4Context *ctx;
+purple_rc4_cipher_set_key(PurpleCipher *cipher, const guchar *key, size_t len) {
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
+	PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
 	guchar *state;
 	guchar temp_swap;
 	guchar x, y;
 	guint i;
 
-	ctx = purple_cipher_context_get_data(context);
-
 	x = 0;
 	y = 0;
-	state = &ctx->state[0];
-	ctx->key_len = len;
+	state = &priv->state[0];
+	priv->key_len = len;
 	for(i = 0; i < 256; i++)
 	{
 		y = (key[x] + state[i] + y) % 256;
@@ -95,23 +88,35 @@
 		state[y] = temp_swap;
 		x = (x + 1) % len;
 	}
+
+	g_object_notify(G_OBJECT(rc4_cipher), "key");
+}
+
+
+static size_t
+purple_rc4_cipher_get_key_size(PurpleCipher *cipher)
+{
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
+	PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
+
+	return priv->key_len;
 }
 
 
 static ssize_t
-rc4_encrypt(PurpleCipherContext *context, const guchar input[], size_t in_len,
-	guchar output[], size_t out_size) {
-	struct RC4Context *ctx;
+purple_rc4_cipher_encrypt(PurpleCipher *cipher, const guchar input[], size_t in_len,
+							guchar output[], size_t out_size)
+{
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
 	guchar temp_swap;
 	guchar x, y, z;
 	guchar *state;
 	guint i;
-
-	ctx = purple_cipher_context_get_data(context);
+	PurpleRC4CipherPrivate *priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
 
-	x = ctx->x;
-	y = ctx->y;
-	state = &ctx->state[0];
+	x = priv->x;
+	y = priv->y;
+	state = &priv->state[0];
 
 	for(i = 0; i < in_len; i++)
 	{
@@ -123,37 +128,144 @@
 		z = state[x] + (state[y]) % 256;
 		output[i] = input[i] ^ state[z];
 	}
-	ctx->x = x;
-	ctx->y = y;
+	priv->x = x;
+	priv->y = y;
 
 	return in_len;
 }
 
-static PurpleCipherOps RC4Ops = {
-	NULL,          /* Set Option    */
-	NULL,          /* Get Option    */
-	rc4_init,      /* init          */
-	rc4_reset,     /* reset         */
-	NULL,          /* reset state   */
-	rc4_uninit,    /* uninit        */
-	NULL,          /* set iv        */
-	NULL,          /* append        */
-	NULL,          /* digest        */
-	NULL,          /* get digest size */
-	rc4_encrypt,   /* encrypt       */
-	NULL,          /* decrypt       */
-	NULL,          /* set salt      */
-	NULL,          /* get salt size */
-	rc4_set_key,   /* set key       */
-	NULL,          /* get key size  */
-	NULL,          /* set batch mode */
-	NULL,          /* get batch mode */
-	NULL,          /* get block size */
-	NULL, NULL, NULL, NULL /* reserved */
-};
+/******************************************************************************
+ * Object Stuff
+ *****************************************************************************/
+static void
+purple_rc4_cipher_set_property(GObject *obj, guint param_id,
+							   const GValue *value, GParamSpec *pspec)
+{
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj);
 
-PurpleCipherOps *
-purple_rc4_cipher_get_ops(void) {
-	return &RC4Ops;
+	switch(param_id) {
+		case PROP_KEY_LEN:
+			purple_rc4_cipher_set_key_len(rc4_cipher, g_value_get_int(value));
+			break;
+		case PROP_KEY:
+			{
+				guchar *key = (guchar *)g_value_get_string(value);
+				purple_rc4_cipher_set_key(cipher, key, strlen((gchar *) key));
+			}
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_rc4_cipher_get_property(GObject *obj, guint param_id, GValue *value,
+							   GParamSpec *pspec)
+{
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj);
+
+	switch(param_id) {
+		case PROP_KEY_LEN:
+			g_value_set_int(value,
+							purple_rc4_cipher_get_key_len(rc4_cipher));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
 }
 
+static void
+purple_rc4_cipher_class_init(PurpleRC4CipherClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	parent_class = g_type_class_peek_parent(klass);
+
+	obj_class->set_property = purple_rc4_cipher_set_property;
+	obj_class->get_property = purple_rc4_cipher_get_property;
+
+	cipher_class->reset = purple_rc4_cipher_reset;
+	cipher_class->encrypt = purple_rc4_cipher_encrypt;
+	cipher_class->set_key = purple_rc4_cipher_set_key;
+	cipher_class->get_key_size = purple_rc4_cipher_get_key_size;
+
+	pspec = g_param_spec_int("key_len", "key_len", "key_len",
+							 G_MININT, G_MAXINT, 0,
+							 G_PARAM_READWRITE);
+	g_object_class_install_property(obj_class, PROP_KEY_LEN, pspec);
+
+	pspec = g_param_spec_string("key", "key", "key", NULL,
+								G_PARAM_WRITABLE);
+	g_object_class_install_property(obj_class, PROP_KEY, pspec);
+
+	g_type_class_add_private(klass, sizeof(PurpleRC4CipherPrivate));
+}
+
+static void
+purple_rc4_cipher_init(PurpleCipher *cipher) {
+	purple_rc4_cipher_reset(cipher);
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GType
+purple_rc4_cipher_get_gtype(void) {
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(PurpleRC4CipherClass),
+			NULL,
+			NULL,
+			(GClassInitFunc)purple_rc4_cipher_class_init,
+			NULL,
+			NULL,
+			sizeof(PurpleRC4Cipher),
+			0,
+			(GInstanceInitFunc)purple_rc4_cipher_init,
+			NULL,
+		};
+
+		type = g_type_register_static(PURPLE_TYPE_CIPHER,
+									  "PurpleRC4Cipher",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+PurpleCipher *
+purple_rc4_cipher_new(void) {
+	return g_object_new(PURPLE_TYPE_RC4_CIPHER, NULL);
+}
+
+void
+purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher,
+							  gint key_len)
+{
+	PurpleRC4CipherPrivate *priv;
+
+	g_return_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher));
+
+	priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
+	priv->key_len = key_len;
+
+	g_object_notify(G_OBJECT(rc4_cipher), "key_len");
+}
+
+gint
+purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher)
+{
+	PurpleRC4CipherPrivate *priv;
+
+	g_return_val_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher), 0);
+
+	priv = PURPLE_RC4_CIPHER_GET_PRIVATE(rc4_cipher);
+
+	return priv->key_len;
+}

mercurial