changeset 12311:a2ebf585d8c6

[gaim-migrate @ 14615] should work fine, but I have to go home now. This ought to clean up all the signedness warnings, start to remove some unnecessary features (server-stored status messages), and add a useful feature (pretending to be an official client when the server is blocking unofficial clients) committer: Tailor Script <tailor@pidgin.im>
author Christopher O'Brien <siege@pidgin.im>
date Sun, 04 Dec 2005 04:09:30 +0000
parents a532eccfc7bb
children 1c8ea8f3b84e
files src/protocols/sametime/meanwhile/cipher.c src/protocols/sametime/meanwhile/common.c src/protocols/sametime/meanwhile/mw_cipher.h src/protocols/sametime/meanwhile/mw_common.h src/protocols/sametime/meanwhile/mw_debug.c src/protocols/sametime/meanwhile/mw_debug.h src/protocols/sametime/meanwhile/mw_session.h src/protocols/sametime/meanwhile/mw_srvc_im.h src/protocols/sametime/meanwhile/mw_util.c src/protocols/sametime/meanwhile/mw_util.h src/protocols/sametime/meanwhile/session.c src/protocols/sametime/meanwhile/srvc_conf.c src/protocols/sametime/meanwhile/srvc_im.c src/protocols/sametime/sametime.c
diffstat 14 files changed, 210 insertions(+), 217 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/sametime/meanwhile/cipher.c	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/cipher.c	Sun Dec 04 04:09:30 2005 +0000
@@ -35,7 +35,7 @@
 
 
 /** From RFC2268 */
-static unsigned char PT[] = {
+static guchar PT[] = {
   0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
   0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
   0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
@@ -72,7 +72,7 @@
 
 
 /** prime number used in DH exchange */
-static unsigned char dh_prime[] = {
+static guchar dh_prime[] = {
   0xCF, 0x84, 0xAF, 0xCE, 0x86, 0xDD, 0xFA, 0x52,
   0x7F, 0x13, 0x6D, 0x10, 0x35, 0x75, 0x28, 0xEE,
   0xFB, 0xA0, 0xAF, 0xEF, 0x80, 0x8F, 0x29, 0x17,
@@ -129,7 +129,7 @@
 
 static void mp_set_rand(mp_int *i, guint bits) {
   size_t len, l;
-  unsigned char *buf;
+  guchar *buf;
 
   l = len = (bits / 8) + 1;
   buf = g_malloc(len);
@@ -221,7 +221,7 @@
 }
 
 
-void mwKeyRandom(unsigned char *key, gsize keylen) {
+void mwKeyRandom(guchar *key, gsize keylen) {
   g_return_if_fail(key != NULL);
 
   srand(clock());
@@ -229,9 +229,9 @@
 }
 
 
-void mwIV_init(unsigned char *iv) {
+void mwIV_init(guchar *iv) {
   int i;
-  static unsigned char normal_iv[] = {
+  static guchar normal_iv[] = {
     0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
   };
   for(i = 8; i--; iv[i] = normal_iv[i]);
@@ -242,8 +242,8 @@
 /* This does not seem to produce the same results as normal RC2 key
    expansion would, but it works, so eh. It might be smart to farm
    this out to mozilla or openssl */
-void mwKeyExpand(int *ekey, const char *key, gsize keylen) {
-  unsigned char tmp[128];
+void mwKeyExpand(int *ekey, const guchar *key, gsize keylen) {
+  guchar tmp[128];
   int i, j;
 
   g_return_if_fail(keylen > 0);
@@ -271,7 +271,7 @@
 
 
 /* normal RC2 encryption given a full 128-byte (as 64 ints) key */
-static void mwEncryptBlock(const int *ekey, char *out) {
+static void mwEncryptBlock(const int *ekey, guchar *out) {
 
   int a, b, c, d;
   int i, j;
@@ -315,14 +315,14 @@
 }
 
 
-void mwEncryptExpanded(const int *ekey, unsigned char *iv,
+void mwEncryptExpanded(const int *ekey, guchar *iv,
 		       struct mwOpaque *in_data,
 		       struct mwOpaque *out_data) {
 
-  unsigned char *i = in_data->data;
+  guchar *i = in_data->data;
   gsize i_len = in_data->len;
 
-  unsigned char *o;
+  guchar *o;
   gsize o_len;
 
   int x, y;
@@ -354,7 +354,8 @@
 }
 
 
-void mwEncrypt(const char *key, gsize keylen, unsigned char *iv,
+void mwEncrypt(const guchar *key, gsize keylen,
+	       guchar *iv,
 	       struct mwOpaque *in, struct mwOpaque *out) {
 
   int ekey[64];
@@ -363,7 +364,7 @@
 }
 
 
-static void mwDecryptBlock(const int *ekey, unsigned char *out) {
+static void mwDecryptBlock(const int *ekey, guchar *out) {
 
   int a, b, c, d;
   int i, j;
@@ -407,14 +408,14 @@
 }
 
 
-void mwDecryptExpanded(const int *ekey, unsigned char *iv,
+void mwDecryptExpanded(const int *ekey, guchar *iv,
 		       struct mwOpaque *in_data,
 		       struct mwOpaque *out_data) {
 
-  unsigned char *i = in_data->data;
+  guchar *i = in_data->data;
   gsize i_len = in_data->len;
 
-  unsigned char *o;
+  guchar *o;
   gsize o_len;
 
   int x, y;
@@ -448,7 +449,7 @@
 }
 
 
-void mwDecrypt(const char *key, gsize keylen, unsigned char *iv,
+void mwDecrypt(const guchar *key, gsize keylen, guchar *iv,
 	       struct mwOpaque *in, struct mwOpaque *out) {
 
   int ekey[64];
@@ -468,8 +469,8 @@
 struct mwCipherInstance_RC2_40 {
   struct mwCipherInstance instance;
   int incoming_key[64];
-  unsigned char outgoing_iv[8];
-  unsigned char incoming_iv[8];
+  guchar outgoing_iv[8];
+  guchar incoming_iv[8];
 };
 
 
@@ -536,7 +537,7 @@
   /* a bit of lazy initialization here */
   if(! cr->ready) {
     struct mwLoginInfo *info = mwSession_getLoginInfo(cipher->session);
-    mwKeyExpand(cr->session_key, info->login_id, 5);
+    mwKeyExpand(cr->session_key, (guchar *) info->login_id, 5);
     cr->ready = TRUE;
   }
 
@@ -578,7 +579,7 @@
   info = mwChannel_getUser(ci->channel);
 
   if(info->login_id) {
-    mwKeyExpand(cir->incoming_key, info->login_id, 5);
+    mwKeyExpand(cir->incoming_key, (guchar *) info->login_id, 5);
   }
 }
 
@@ -623,8 +624,8 @@
 struct mwCipherInstance_RC2_128 {
   struct mwCipherInstance instance;
   int shared[64];      /* shared secret determined via DH exchange */
-  unsigned char outgoing_iv[8];
-  unsigned char incoming_iv[8];
+  guchar outgoing_iv[8];
+  guchar incoming_iv[8];
 };
 
 
--- a/src/protocols/sametime/meanwhile/common.c	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/common.c	Sun Dec 04 04:09:30 2005 +0000
@@ -53,20 +53,20 @@
 
 
 struct mwPutBuffer {
-  char *buf;  /**< head of buffer */
-  gsize len;  /**< length of buffer */
+  guchar *buf;  /**< head of buffer */
+  gsize len;    /**< length of buffer */
 
-  char *ptr;  /**< offset to first unused byte */
-  gsize rem;  /**< count of unused bytes remaining */
+  guchar *ptr;  /**< offset to first unused byte */
+  gsize rem;    /**< count of unused bytes remaining */
 };
 
 
 struct mwGetBuffer {
-  char *buf;  /**< head of buffer */
-  gsize len;  /**< length of buffer */
+  guchar *buf;  /**< head of buffer */
+  gsize len;    /**< length of buffer */
 
-  char *ptr;  /**< offset to first unused byte */
-  gsize rem;  /**< count of unused bytes remaining */
+  guchar *ptr;  /**< offset to first unused byte */
+  gsize rem;    /**< count of unused bytes remaining */
 
   gboolean wrap;   /**< TRUE to indicate buf shouldn't be freed */
   gboolean error;  /**< TRUE to indicate an error */
@@ -82,7 +82,7 @@
 static void ensure_buffer(struct mwPutBuffer *b, gsize needed) {
   if(b->rem < needed) {
     gsize len = b->len, use = BUFFER_USED(b);
-    char *buf;
+    guchar *buf;
 
     /* newly created buffers are empty until written to, and then they
        have 1024 available */
@@ -171,7 +171,7 @@
   struct mwGetBuffer *b = g_new0(struct mwGetBuffer, 1);
 
   if(o && o->len) {
-    b->buf = b->ptr = (char *) o->data;
+    b->buf = b->ptr = o->data;
     b->len = b->rem = o->len;
   }
   b->wrap = TRUE;
@@ -266,7 +266,7 @@
 
 
 guint16 guint16_peek(struct mwGetBuffer *b) {
-  char *buf = b->buf;
+  guchar *buf = b->buf;
   guint16 r = 0;
   
   if(b->rem >= guint16_buflen())
@@ -300,7 +300,7 @@
 
 
 guint32 guint32_peek(struct mwGetBuffer *b) {
-  char *buf = b->buf;
+  guchar *buf = b->buf;
   guint32 r = 0;
 
   if(b->rem >= guint32_buflen())
@@ -925,58 +925,3 @@
   memset(idb, 0x00, sizeof(struct mwAwareSnapshot));
 }
 
-
-const char *mwLoginType_getName(enum mwLoginType type) {
-  switch(type) {
-  case mwLogin_LIB:
-    return "Lotus Binary Library";
-
-  case mwLogin_JAVA_WEB:
-    return "Lotus Java Client Applet";
-
-  case mwLogin_BINARY:
-    return "Lotus Sametime Connect";
-
-  case mwLogin_JAVA_APP:
-    return "Lotus Java Client Application";
-
-  case mwLogin_LINKS:
-    return "Lotus Sametime Links";
-
-  case mwLogin_NOTES_6_5:
-  case mwLogin_NOTES_6_5_3:
-  case mwLogin_NOTES_7_0_beta:
-  case mwLogin_NOTES_7_0:
-    return "Lotus Notes Client";
-
-  case mwLogin_ICT:
-  case mwLogin_ICT_1_7_8_2:
-  case mwLogin_ICT_SIP:
-    return "IBM Community Tools";
-
-  case mwLogin_NOTESBUDDY_4_14:
-  case mwLogin_NOTESBUDDY_4_15:
-  case mwLogin_NOTESBUDDY_4_16:
-    return "Alphaworks NotesBuddy";
-
-  case mwLogin_SANITY:
-    return "Sanity";
-
-  case mwLogin_ST_PERL:
-    return "ST-Send-Message";
-
-  case mwLogin_PMR_ALERT:
-    return "PMR Alert";
-
-  case mwLogin_TRILLIAN:
-  case mwLogin_TRILLIAN_IBM:
-    return "Trillian";
-
-  case mwLogin_MEANWHILE:
-    return "Meanwhile";
-
-  default:
-    return NULL;
-  }
-}
-
--- a/src/protocols/sametime/meanwhile/mw_cipher.h	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/mw_cipher.h	Sun Dec 04 04:09:30 2005 +0000
@@ -195,37 +195,37 @@
     @param keylen  count of bytes to write into key
     @param key     buffer to write keys into
 */
-void mwKeyRandom(unsigned char *key, gsize keylen);
+void mwKeyRandom(guchar *key, gsize keylen);
 
 
 /** Setup an Initialization Vector. IV must be at least 8 bytes */
-void mwIV_init(unsigned char *iv);
+void mwIV_init(guchar *iv);
 
 
 /** Expand a variable-length key into a 128-byte key (represented as
     an an array of 64 ints) */
-void mwKeyExpand(int *ekey, const char *key, gsize keylen);
+void mwKeyExpand(int *ekey, const guchar *key, gsize keylen);
 
 
 /** Encrypt data using an already-expanded key */
-void mwEncryptExpanded(const int *ekey, unsigned char *iv,
+void mwEncryptExpanded(const int *ekey, guchar *iv,
 		       struct mwOpaque *in,
 		       struct mwOpaque *out);
 
 
 /** Encrypt data using an expanded form of the given key */
-void mwEncrypt(const char *key, gsize keylen, unsigned char *iv,
+void mwEncrypt(const guchar *key, gsize keylen, guchar *iv,
 	       struct mwOpaque *in, struct mwOpaque *out);
 
 
 /** Decrypt data using an already expanded key */
-void mwDecryptExpanded(const int *ekey, unsigned char *iv,
+void mwDecryptExpanded(const int *ekey, guchar *iv,
 		       struct mwOpaque *in,
 		       struct mwOpaque *out);
 
 
 /** Decrypt data using an expanded form of the given key */
-void mwDecrypt(const char *key, gsize keylen, unsigned char *iv,
+void mwDecrypt(const guchar *key, gsize keylen, guchar *iv,
 	       struct mwOpaque *in, struct mwOpaque *out);
 
 
--- a/src/protocols/sametime/meanwhile/mw_common.h	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/mw_common.h	Sun Dec 04 04:09:30 2005 +0000
@@ -72,8 +72,8 @@
 
 /** A length of binary data, not null-terminated. */
 struct mwOpaque {
-  gsize len;            /**< length of data. */
-  unsigned char *data;  /**< data, normally with no NULL termination */
+  gsize len;     /**< length of data. */
+  guchar *data;  /**< data, normally with no NULL termination */
 };
 
 
@@ -83,14 +83,7 @@
     used to login with.
 
     If you know of any additional client identifiers, please add them
-    below.
-
-    If you are using Meanwhile in your client code and would like to
-    differentiate yourself, please email siege at preoccupied dot net
-    with all the relevant information you can think of and I'll add it
-    to the text mapping as well
-
-    @see mwLoginType_getName
+    below or submit an RFE to the meanwhile tracker.
 */
 enum mwLoginType {
   mwLogin_LIB           = 0x1000,  /**< official Lotus binary library */
@@ -288,11 +281,6 @@
 /*@}*/
 
 
-/** provides a textual name for a given login type. If the type is not
-    known by name, returns NULL */
-const char *mwLoginType_getName(enum mwLoginType type);
-
-
 /** @name Basic Data Type Marshalling
     The basic types are combined to construct the complex types.
  */
--- a/src/protocols/sametime/meanwhile/mw_debug.c	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/mw_debug.c	Sun Dec 04 04:09:30 2005 +0000
@@ -31,57 +31,53 @@
 #define FRMT8            FRMT4 FRMT4
 #define FRMT16           FRMT8 FRMT8
 
-#define BUF(n)            ((unsigned char) buf[n])
 #define ADVANCE(b, n, c)  {b += c; n -= c;}
 
 
 
 /** writes hex pairs of buf to str */
-static void pretty_print(GString *str, const char *buf, gsize len) {
-  while(len) {
-    if(len >= 16) {
-      /* write a complete line */
-      g_string_append_printf(str, FRMT16,
-			     BUF(0),  BUF(1),  BUF(2),  BUF(3),
-			     BUF(4),  BUF(5),  BUF(6),  BUF(7),
-			     BUF(8),  BUF(9),  BUF(10), BUF(11),
-			     BUF(12), BUF(13), BUF(14), BUF(15));
-      ADVANCE(buf, len, 16);
-
-    } else {
-      /* write an incomplete line */
-      if(len >= 8) {
-	g_string_append_printf(str, FRMT8,
-			       BUF(0), BUF(1), BUF(2), BUF(3),
-			       BUF(4), BUF(5), BUF(6), BUF(7));
-	ADVANCE(buf, len, 8);
-      }
-      
-      if(len >= 4) {
-	g_string_append_printf(str, FRMT4,
-			       BUF(0), BUF(1), BUF(2), BUF(3));
-	ADVANCE(buf, len, 4);
-      }
-
-      if(len >= 2) {
-	g_string_append_printf(str, FRMT2, BUF(0), BUF(1));
-	ADVANCE(buf, len, 2);
-      }
-
-      if(len >= 1) {
-	g_string_append_printf(str, FRMT1, BUF(0));
-	ADVANCE(buf, len, 1);
-      }
-    }
+static void pretty_print(GString *str, const guchar *buf, gsize len) {
+  while(len >= 16) {
+    /* write a complete line */
+    g_string_append_printf(str, FRMT16,
+			   buf[0],  buf[1],  buf[2],  buf[3],
+			   buf[4],  buf[5],  buf[6],  buf[7],
+			   buf[8],  buf[9],  buf[10], buf[11],
+			   buf[12], buf[13], buf[14], buf[15]);
+    ADVANCE(buf, len, 16);
     
     /* append \n to each line but the last */
     if(len) g_string_append(str, "\n");
   }
+
+  /* write an incomplete line */
+  if(len >= 8) {
+    g_string_append_printf(str, FRMT8,
+			   buf[0], buf[1], buf[2], buf[3],
+			   buf[4], buf[5], buf[6], buf[7]);
+    ADVANCE(buf, len, 8);
+  }
+  
+  if(len >= 4) {
+    g_string_append_printf(str, FRMT4,
+			   buf[0], buf[1], buf[2], buf[3]);
+    ADVANCE(buf, len, 4);
+  }
+
+  if(len >= 2) {
+    g_string_append_printf(str, FRMT2, buf[0], buf[1]);
+    ADVANCE(buf, len, 2);
+  }
+
+  if(len >= 1) {
+    g_string_append_printf(str, FRMT1, buf[0]);
+    ADVANCE(buf, len, 1);
+  }
 }
 
 
 
-void mw_debug_datav(const char *buf, gsize len,
+void mw_debug_datav(const guchar *buf, gsize len,
 		    const char *msg, va_list args) {
   GString *str;
 
@@ -102,7 +98,7 @@
 
 
 
-void mw_debug_data(const char *buf, gsize len,
+void mw_debug_data(const guchar *buf, gsize len,
 		   const char *msg, ...) {
   va_list args;
   
@@ -133,7 +129,7 @@
 }
 
 
-void mw_mailme_datav(const char *buf, gsize len,
+void mw_mailme_datav(const guchar *buf, gsize len,
 		     const char *info, va_list args) {
 
 #if MW_MAILME
@@ -164,7 +160,7 @@
 
 
 
-void mw_mailme_data(const char *buf, gsize len,
+void mw_mailme_data(const guchar *buf, gsize len,
 		    const char *info, ...) {
   va_list args;
   va_start(args, info);
--- a/src/protocols/sametime/meanwhile/mw_debug.h	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/mw_debug.h	Sun Dec 04 04:09:30 2005 +0000
@@ -74,11 +74,11 @@
 #endif
 
 
-void mw_debug_datav(const char *buf, gsize len,
+void mw_debug_datav(const guchar *buf, gsize len,
 		    const char *info, va_list args);
 
 
-void mw_debug_data(const char *buf, gsize len,
+void mw_debug_data(const guchar *buf, gsize len,
 		   const char *info, ...);
 
 
@@ -88,10 +88,10 @@
 void mw_debug_opaque(struct mwOpaque *o, const char *info, ...);
 
 
-void mw_mailme_datav(const char *buf, gsize len,
+void mw_mailme_datav(const guchar *buf, gsize len,
 		     const char *info, va_list args);
 
-void mw_mailme_data(const char *buf, gsize len,
+void mw_mailme_data(const guchar *buf, gsize len,
 		    const char *info, ...);
 
 
--- a/src/protocols/sametime/meanwhile/mw_session.h	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/mw_session.h	Sun Dec 04 04:09:30 2005 +0000
@@ -150,7 +150,7 @@
   
   /** write data to the server connection. Required. Should return
       zero for success, non-zero for error */
-  int (*io_write)(struct mwSession *, const char *buf, gsize len);
+  int (*io_write)(struct mwSession *, const guchar *buf, gsize len);
   
   /** close the server connection. Required */
   void (*io_close)(struct mwSession *);
@@ -214,7 +214,7 @@
 
 /** Data is buffered, unpacked, and parsed into a message, then
     processed accordingly. */
-void mwSession_recv(struct mwSession *, const char *, gsize);
+void mwSession_recv(struct mwSession *, const guchar *, gsize);
 
 
 /** primarily used by services to have messages serialized and sent
--- a/src/protocols/sametime/meanwhile/mw_srvc_im.h	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/mw_srvc_im.h	Sun Dec 04 04:09:30 2005 +0000
@@ -82,6 +82,7 @@
   mwImSend_HTML,    /**< char *, HTML formatted message (NOTESBUDDY) */
   mwImSend_SUBJECT, /**< char *, conversation subject (NOTESBUDDY) */
   mwImSend_MIME,    /**< char *, MIME-encoded message (NOTESBUDDY) */
+  mwImSend_TIMESTAMP, /**< char *, YYYY:MM:DD:HH:mm:SS format (NOTESBUDDY) */
 };
 
 
--- a/src/protocols/sametime/meanwhile/mw_util.c	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/mw_util.c	Sun Dec 04 04:09:30 2005 +0000
@@ -78,17 +78,3 @@
   mw_datum_clear(d);
   g_free(d);
 }
-
-gboolean
-mw_str_has_prefix(const char *s, const char *p)
-{
-#if GLIB_CHECK_VERSION(2,2,0)
-	return g_str_has_prefix(s, p);
-#else
-	if (!strncmp(s, p, strlen(p)))
-		return TRUE;
-
-	return FALSE;
-#endif
-}
-
--- a/src/protocols/sametime/meanwhile/mw_util.h	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/mw_util.h	Sun Dec 04 04:09:30 2005 +0000
@@ -21,7 +21,7 @@
 #ifndef _MW_UTIL_H
 #define _MW_UTIL_H
 
-#include <string.h>
+
 #include <glib.h>
 #include <glib/ghash.h>
 #include <glib/glist.h>
@@ -81,6 +81,5 @@
 
 void mw_datum_free(struct mw_datum *d);
 
-gboolean mw_str_has_prefix(const char *s, const char *p);
 
 #endif
--- a/src/protocols/sametime/meanwhile/session.c	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/session.c	Sun Dec 04 04:09:30 2005 +0000
@@ -51,9 +51,9 @@
   gpointer state_info;        /**< additional state info */
 
   /* input buffering for an incoming message */
-  char *buf;       /**< buffer for incoming message data */
-  gsize buf_len;   /**< length of buf */
-  gsize buf_used;  /**< offset to last-used byte of buf */
+  guchar *buf;  /**< buffer for incoming message data */
+  gsize buf_len;       /**< length of buf */
+  gsize buf_used;      /**< offset to last-used byte of buf */
   
   struct mwLoginInfo login;      /**< login information */
   struct mwUserStatus status;    /**< user status */
@@ -180,7 +180,7 @@
   }
 
   h = s->handler;
-  if(h) h->clear(s);
+  if(h && h->clear) h->clear(s);
   s->handler = NULL;
 
   session_buf_free(s);
@@ -199,7 +199,7 @@
 
 
 /** write data to the session handler */
-static int io_write(struct mwSession *s, const char *buf, gsize len) {
+static int io_write(struct mwSession *s, const guchar *buf, gsize len) {
   g_return_val_if_fail(s != NULL, -1);
   g_return_val_if_fail(s->handler != NULL, -1);
   g_return_val_if_fail(s->handler->io_write != NULL, -1);
@@ -329,13 +329,13 @@
 /** compose authentication information into an opaque based on the
     password, encrypted via RC2/40 */
 static void compose_auth_rc2_40(struct mwOpaque *auth, const char *pass) {
-  char iv[8], key[5];
+  guchar iv[8], key[5];
   struct mwOpaque a, b, z;
   struct mwPutBuffer *p;
 
   /* get an IV and a random five-byte key */
-  mwIV_init((char *) iv);
-  mwKeyRandom((char *) key, 5);
+  mwIV_init(iv);
+  mwKeyRandom(key, 5);
 
   /* the opaque with the key */
   a.len = 5;
@@ -347,7 +347,7 @@
 
   /* the plain-text pass dressed up as an opaque */
   z.len = strlen(pass);
-  z.data = (char *) pass;
+  z.data = (guchar *) pass;
 
   /* the opaque with the encrypted pass */
   mwEncrypt(a.data, a.len, iv, &z, &b);
@@ -366,7 +366,7 @@
 static void compose_auth_rc2_128(struct mwOpaque *auth, const char *pass,
 				 guint32 magic, struct mwOpaque *rkey) {
 
-  char iv[8];
+  guchar iv[8];
   struct mwOpaque a, b, c;
   struct mwPutBuffer *p;
 
@@ -633,9 +633,9 @@
 
 
 static void session_process(struct mwSession *s,
-			    const char *buf, gsize len) {
+			    const guchar *buf, gsize len) {
 
-  struct mwOpaque o = { .len = len, .data = (char *) buf };
+  struct mwOpaque o = { .len = len, .data = (guchar *) buf };
   struct mwGetBuffer *b;
   struct mwMessage *msg;
 
@@ -689,7 +689,8 @@
 
 
 /* handle input to complete an existing buffer */
-static gsize session_recv_cont(struct mwSession *s, const char *b, gsize n) {
+static gsize session_recv_cont(struct mwSession *s,
+			       const guchar *b, gsize n) {
 
   /* determine how many bytes still required */
   gsize x = s->buf_len - s->buf_used;
@@ -721,9 +722,9 @@
 	/* there isn't enough to meet the demands of the length, so
 	   we'll buffer it for next time */
 
-	char *t;
+	guchar *t;
 	x += 4;
-	t = (char *) g_malloc(x);
+	t = (guchar *) g_malloc(x);
 	memcpy(t, s->buf, 4);
 	memcpy(t+4, b, n);
 	
@@ -757,15 +758,17 @@
 
 
 /* handle input when there's nothing previously buffered */
-static gsize session_recv_empty(struct mwSession *s, const char *b, gsize n) {
-  struct mwOpaque o = { n, (char *) b };
+static gsize session_recv_empty(struct mwSession *s,
+				const guchar *b, gsize n) {
+
+  struct mwOpaque o = { n, (guchar *) b };
   struct mwGetBuffer *gb;
   gsize x;
 
   if(n < 4) {
     /* uh oh. less than four bytes means we've got an incomplete
        length indicator. Have to buffer to get the rest of it. */
-    s->buf = (char *) g_malloc0(4);
+    s->buf = (guchar *) g_malloc0(4);
     memcpy(s->buf, b, n);
     s->buf_len = 4;
     s->buf_used = n;
@@ -786,7 +789,7 @@
        session_recv takes place */
 
     x += 4;
-    s->buf = (char *) g_malloc(x);
+    s->buf = (guchar *) g_malloc(x);
     memcpy(s->buf, b, n);
     s->buf_len = x;
     s->buf_used = n;
@@ -806,7 +809,9 @@
 }
 
 
-static gsize session_recv(struct mwSession *s, const char *b, gsize n) {
+static gsize session_recv(struct mwSession *s,
+			  const guchar *b, gsize n) {
+
   /* This is messy and kind of confusing. I'd like to simplify it at
      some point, but the constraints are as follows:
 
@@ -854,8 +859,8 @@
 #undef ADVANCE
 
 
-void mwSession_recv(struct mwSession *s, const char *buf, gsize n) {
-  char *b = (char *) buf;
+void mwSession_recv(struct mwSession *s, const guchar *buf, gsize n) {
+  guchar *b = (guchar *) buf;
   gsize remain = 0;
 
   g_return_if_fail(s != NULL);
@@ -909,7 +914,7 @@
 
 
 int mwSession_sendKeepalive(struct mwSession *s) {
-  const char b = 0x80;
+  const guchar b = 0x80;
 
   g_return_val_if_fail(s != NULL, -1);
   return io_write(s, &b, 1);
--- a/src/protocols/sametime/meanwhile/srvc_conf.c	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/srvc_conf.c	Sun Dec 04 04:09:30 2005 +0000
@@ -723,7 +723,7 @@
   if(conf->channel) {
     if(text && *text) {
       info.len = strlen(text);
-      info.data = (char *) text;
+      info.data = (guchar *) text;
     }
 
     ret = mwChannel_destroy(conf->channel, reason, &info);
--- a/src/protocols/sametime/meanwhile/srvc_im.c	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/meanwhile/srvc_im.c	Sun Dec 04 04:09:30 2005 +0000
@@ -66,6 +66,7 @@
   mwImData_SUBJECT  = 0x00000003,  /**< notesbuddy IM topic */
   mwImData_HTML     = 0x00000004,  /**< notesbuddy HTML message */
   mwImData_MIME     = 0x00000005,  /**< notesbuddy MIME message, w/image */
+  mwImData_TIMESTAMP = 0x00000006, /**< notesbuddy timestamp */
 
   mwImData_INVITE   = 0x0000000a,  /**< Places invitation */
 
@@ -184,7 +185,7 @@
     c->features = srvc->features;
 
     /* mark external users */
-    c->ext_id = mw_str_has_prefix(to->user, "@E ");
+    /* c->ext_id = g_str_has_prefix(to->user, "@E "); */
 
     srvc->convs = g_list_prepend(srvc->convs, c);
   }
@@ -577,11 +578,11 @@
   case mwImData_HTML:
     if(o.len) {
       if(conv->multi) {
-	g_string_append_len(conv->multi, o.data, o.len);
+	g_string_append_len(conv->multi, (char *) o.data, o.len);
 	conv->multi_type = mwImSend_HTML;
 
       } else {
-	x = g_strndup(o.data, o.len);
+	x = g_strndup((char *) o.data, o.len);
 	convo_recv(conv, mwImSend_HTML, x);
 	g_free(x);
       }
@@ -589,23 +590,27 @@
     break;
 
   case mwImData_SUBJECT:
-    x = g_strndup(o.data, o.len);
+    x = g_strndup((char *) o.data, o.len);
     convo_recv(conv, mwImSend_SUBJECT, x);
     g_free(x);
     break;
 
   case mwImData_MIME:
     if(conv->multi) {
-      g_string_append_len(conv->multi, o.data, o.len);
+      g_string_append_len(conv->multi, (char *) o.data, o.len);
       conv->multi_type = mwImSend_MIME;
 
     } else {
-      x = g_strndup(o.data, o.len);
+      x = g_strndup((char *) o.data, o.len);
       convo_recv(conv, mwImSend_MIME, x);
       g_free(x);
     }
     break;
 
+  case mwImData_TIMESTAMP:
+    /* todo */
+    break;
+
   case mwImData_INVITE:
     convo_invite(conv, &o);
     break;
@@ -756,6 +761,7 @@
   case mwImSend_SUBJECT:
   case mwImSend_HTML:
   case mwImSend_MIME:
+  case mwImSend_TIMESTAMP:
     return srvc->features == mwImClient_NOTESBUDDY;
 
   default:
@@ -885,7 +891,7 @@
   struct mwOpaque o;
 
   o.len = strlen(subject);
-  o.data = (char *) subject;
+  o.data = (guchar *) subject;
 
   return convo_send_data(conv, mwImData_SUBJECT, 0x00, &o);
 }
@@ -895,7 +901,7 @@
   struct mwOpaque o;
 
   o.len = strlen(html);
-  o.data = (char *) html;
+  o.data = (guchar *) html;
 
   if(o.len > BREAKUP) {
     return convo_sendSegmented(conv, html, convo_sendHtml);
@@ -909,7 +915,7 @@
   struct mwOpaque o;
 
   o.len = strlen(mime);
-  o.data = (char *) mime;
+  o.data = (guchar *) mime;
 
   if(o.len > BREAKUP) {
     return convo_sendSegmented(conv, mime, convo_sendMime);
--- a/src/protocols/sametime/sametime.c	Sun Dec 04 02:53:47 2005 +0000
+++ b/src/protocols/sametime/sametime.c	Sun Dec 04 04:09:30 2005 +0000
@@ -148,6 +148,7 @@
 #define MW_KEY_INVITE      "conf_invite"
 #define MW_KEY_ENCODING    "encoding"
 #define MW_KEY_FORCE       "force_login"
+#define MW_KEY_FAKE_IT     "fake_client_id"
 
 
 /** number of seconds from the first blist change before a save to the
@@ -341,7 +342,7 @@
 
 
 static int mw_session_io_write(struct mwSession *session,
-			       const char *buf, gsize len) {
+			       const guchar *buf, gsize len) {
   struct mwGaimPluginData *pd;
   int ret = 0;
 
@@ -1618,7 +1619,7 @@
     pass it to the session, passing back the return code from the read
     call for handling in read_cb */
 static int read_recv(struct mwSession *session, int sock) {
-  char buf[BUF_LEN];
+  guchar buf[BUF_LEN];
   int len;
 
   len = read(sock, buf, BUF_LEN);
@@ -2106,7 +2107,7 @@
 
 
 static void ft_send(struct mwFileTransfer *ft, FILE *fp) {
-  char buf[BUF_LONG];
+  guchar buf[BUF_LONG];
   struct mwOpaque o = { .data = buf, .len = BUF_LONG };
   guint32 rem;
   GaimXfer *xfer;
@@ -3645,7 +3646,7 @@
   struct mwGaimPluginData *pd;
 
   char *user, *pass, *host;
-  guint port;
+  guint port, client;
 
   gc = gaim_account_get_connection(account);
   pd = mwGaimPluginData_new(gc);
@@ -3685,8 +3686,15 @@
 			(char *) no_secret, NULL);
   mwSession_setProperty(pd->session, mwSession_AUTH_USER_ID, user, g_free);
   mwSession_setProperty(pd->session, mwSession_AUTH_PASSWORD, pass, NULL);
+
+  client = MW_CLIENT_TYPE_ID;
+  if(gaim_account_get_bool(account, MW_KEY_FAKE_IT, FALSE))
+    client = mwLogin_BINARY;
+
+  DEBUG_INFO("client id: 0x%04x\n", client);
+
   mwSession_setProperty(pd->session, mwSession_CLIENT_TYPE_ID,
-			GUINT_TO_POINTER(MW_CLIENT_TYPE_ID), NULL);
+			GUINT_TO_POINTER(client), NULL);
 
   gaim_connection_update_progress(gc, _("Connecting"), 1, MW_CONNECT_STEPS);
 
@@ -4065,6 +4073,58 @@
 }
 
 
+static const char *mw_client_name(guint16 type) {
+  switch(type) {
+  case mwLogin_LIB:
+    return "Lotus Binary Library";
+    
+  case mwLogin_JAVA_WEB:
+    return "Lotus Java Client Applet";
+
+  case mwLogin_BINARY:
+    return "Lotus Sametime Connect";
+
+  case mwLogin_JAVA_APP:
+    return "Lotus Java Client Application";
+
+  case mwLogin_LINKS:
+    return "Lotus Sametime Links";
+
+  case mwLogin_NOTES_6_5:
+  case mwLogin_NOTES_6_5_3:
+  case mwLogin_NOTES_7_0_beta:
+  case mwLogin_NOTES_7_0:
+    return "Lotus Notes Client";
+
+  case mwLogin_ICT:
+  case mwLogin_ICT_1_7_8_2:
+  case mwLogin_ICT_SIP:
+    return "IBM Community Tools";
+
+  case mwLogin_NOTESBUDDY_4_14:
+  case mwLogin_NOTESBUDDY_4_15:
+  case mwLogin_NOTESBUDDY_4_16:
+    return "Alphaworks NotesBuddy";
+
+  case mwLogin_SANITY:
+    return "Sanity";
+
+  case mwLogin_ST_PERL:
+    return "ST-Send-Message";
+
+  case mwLogin_TRILLIAN:
+  case mwLogin_TRILLIAN_IBM:
+    return "Trillian";
+
+  case mwLogin_MEANWHILE:
+    return "Meanwhile";
+
+  default:
+    return NULL;
+  }
+}
+
+
 static void mw_prpl_get_info(GaimConnection *gc, const char *who) {
 
   struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
@@ -4104,7 +4164,7 @@
     if(type) {
       g_string_append(str, _("<b>Last Known Client:</b> "));
 
-      tmp = mwLoginType_getName(type);
+      tmp = mw_client_name(type);
       if(tmp) {
 	g_string_append(str, tmp);
 	g_string_append(str, "<br>");
@@ -5201,6 +5261,7 @@
 };
 
 
+#if 0
 static void status_msg_action_cb(GaimConnection *gc,
 				 GaimRequestFields *fields) {
   GaimAccount *acct;
@@ -5234,7 +5295,6 @@
   unit = mwStorageUnit_newString(mwStore_BUSY_MESSAGES, msg);
   mwServiceStorage_save(srvc, unit, NULL, NULL, NULL);
 
-#if 0
   /* XXX */
   /* need to propagate the message change if we're in any of those
      default states */
@@ -5248,7 +5308,6 @@
   }
   if(msg)
     serv_set_away(gc, msg, NULL);
-#endif
 }
 
 
@@ -5300,6 +5359,7 @@
 		      _("Cancel"), NULL,
 		      gc);
 }
+#endif
 
 
 static void st_import_action_cb(GaimConnection *gc, char *filename) {
@@ -5608,9 +5668,11 @@
   GaimPluginAction *act;
   GList *l = NULL;
 
+#if 0
   act = gaim_plugin_action_new(_("Set Status Messages..."),
 			       status_msg_action);
   l = g_list_append(l, act);
+#endif
 
   act = gaim_plugin_action_new(_("Import Sametime List..."),
 			       st_import_action);
@@ -5732,6 +5794,10 @@
     l = g_list_append(l, opt);
   }
 
+  /* pretend to be Sametime Connect */
+  opt = gaim_account_option_bool_new(_("Hide Client Identity"),
+				     MW_KEY_FAKE_IT, FALSE);
+
   mw_prpl_info.protocol_options = l;
   l = NULL;