summaryrefslogtreecommitdiff
path: root/libpurple
diff options
context:
space:
mode:
authorJohn Bailey <rekkanoryo@rekkanoryo.org>2009-09-16 15:36:24 +0000
committerJohn Bailey <rekkanoryo@rekkanoryo.org>2009-09-16 15:36:24 +0000
commita245c80a0788d33e86c8512606a9cde4ac424553 (patch)
tree5b2477b5fde7398f0846be846b66238b779797a4 /libpurple
parenta27b85d8a86ec484a4064bb924425f9889535167 (diff)
parentf0263ba7a7d0ab488519a745fba7b2f36ddc02a7 (diff)
downloadpidgin-a245c80a0788d33e86c8512606a9cde4ac424553.tar.gz
merge of '755d7efe6da376f6fbeb9f6d3e08f2d7201aabc7'
and '0848cfc68369ad686459fb7420f1e4613029b294'
Diffstat (limited to 'libpurple')
-rw-r--r--libpurple/Makefile.am1
-rw-r--r--libpurple/account.c11
-rw-r--r--libpurple/blist.c2
-rw-r--r--libpurple/blist.h6
-rw-r--r--libpurple/certificate.c401
-rw-r--r--libpurple/conversation.h2
-rw-r--r--libpurple/core.c2
-rw-r--r--libpurple/core.h10
-rw-r--r--libpurple/dbus-analyze-functions.py29
-rw-r--r--libpurple/dnssrv.c11
-rw-r--r--libpurple/dnssrv.h6
-rw-r--r--libpurple/example/Makefile.am1
-rw-r--r--libpurple/ft.c6
-rw-r--r--libpurple/idle.h2
-rw-r--r--libpurple/media-gst.h7
-rw-r--r--libpurple/media.c103
-rw-r--r--libpurple/media.h9
-rw-r--r--libpurple/mediamanager.c2
-rw-r--r--libpurple/mediamanager.h7
-rw-r--r--libpurple/plugins/joinpart.c7
-rw-r--r--libpurple/plugins/perl/common/XMLNode.xs58
-rw-r--r--libpurple/protocols/bonjour/bonjour_ft.c8
-rw-r--r--libpurple/protocols/bonjour/bonjour_ft.h2
-rw-r--r--libpurple/protocols/irc/msgs.c4
-rw-r--r--libpurple/protocols/irc/parse.c14
-rw-r--r--libpurple/protocols/jabber/adhoccommands.c6
-rw-r--r--libpurple/protocols/jabber/adhoccommands.h6
-rw-r--r--libpurple/protocols/jabber/auth.c12
-rw-r--r--libpurple/protocols/jabber/auth.h4
-rw-r--r--libpurple/protocols/jabber/bosh.c59
-rw-r--r--libpurple/protocols/jabber/bosh.h4
-rw-r--r--libpurple/protocols/jabber/buddy.c53
-rw-r--r--libpurple/protocols/jabber/buddy.h4
-rw-r--r--libpurple/protocols/jabber/caps.c16
-rw-r--r--libpurple/protocols/jabber/caps.h6
-rw-r--r--libpurple/protocols/jabber/chat.c4
-rw-r--r--libpurple/protocols/jabber/chat.h4
-rw-r--r--libpurple/protocols/jabber/data.c49
-rw-r--r--libpurple/protocols/jabber/data.h6
-rw-r--r--libpurple/protocols/jabber/disco.c4
-rw-r--r--libpurple/protocols/jabber/disco.h4
-rw-r--r--libpurple/protocols/jabber/google.c94
-rw-r--r--libpurple/protocols/jabber/ibb.c6
-rw-r--r--libpurple/protocols/jabber/ibb.h6
-rw-r--r--libpurple/protocols/jabber/iq.c4
-rw-r--r--libpurple/protocols/jabber/iq.h4
-rw-r--r--libpurple/protocols/jabber/jabber.c11
-rw-r--r--libpurple/protocols/jabber/jabber.h6
-rw-r--r--libpurple/protocols/jabber/jingle/content.c4
-rw-r--r--libpurple/protocols/jabber/jingle/content.h4
-rw-r--r--libpurple/protocols/jabber/jingle/iceudp.c4
-rw-r--r--libpurple/protocols/jabber/jingle/iceudp.h4
-rw-r--r--libpurple/protocols/jabber/jingle/jingle.c4
-rw-r--r--libpurple/protocols/jabber/jingle/jingle.h4
-rw-r--r--libpurple/protocols/jabber/jingle/rawudp.c4
-rw-r--r--libpurple/protocols/jabber/jingle/rawudp.h4
-rw-r--r--libpurple/protocols/jabber/jingle/rtp.c11
-rw-r--r--libpurple/protocols/jabber/jingle/rtp.h4
-rw-r--r--libpurple/protocols/jabber/jingle/session.c4
-rw-r--r--libpurple/protocols/jabber/jingle/session.h4
-rw-r--r--libpurple/protocols/jabber/jingle/transport.c4
-rw-r--r--libpurple/protocols/jabber/jingle/transport.h4
-rw-r--r--libpurple/protocols/jabber/jutil.c58
-rw-r--r--libpurple/protocols/jabber/jutil.h5
-rw-r--r--libpurple/protocols/jabber/message.c16
-rw-r--r--libpurple/protocols/jabber/message.h4
-rw-r--r--libpurple/protocols/jabber/oob.c9
-rw-r--r--libpurple/protocols/jabber/oob.h4
-rw-r--r--libpurple/protocols/jabber/parser.c4
-rw-r--r--libpurple/protocols/jabber/parser.h4
-rw-r--r--libpurple/protocols/jabber/pep.c6
-rw-r--r--libpurple/protocols/jabber/pep.h6
-rw-r--r--libpurple/protocols/jabber/ping.c6
-rw-r--r--libpurple/protocols/jabber/ping.h6
-rw-r--r--libpurple/protocols/jabber/presence.c11
-rw-r--r--libpurple/protocols/jabber/presence.h4
-rw-r--r--libpurple/protocols/jabber/roster.c40
-rw-r--r--libpurple/protocols/jabber/roster.h4
-rw-r--r--libpurple/protocols/jabber/si.c4
-rw-r--r--libpurple/protocols/jabber/si.h4
-rw-r--r--libpurple/protocols/jabber/useravatar.c2
-rw-r--r--libpurple/protocols/jabber/useravatar.h2
-rw-r--r--libpurple/protocols/jabber/usermood.c6
-rw-r--r--libpurple/protocols/jabber/usermood.h6
-rw-r--r--libpurple/protocols/jabber/usernick.c6
-rw-r--r--libpurple/protocols/jabber/usernick.h6
-rw-r--r--libpurple/protocols/jabber/usertune.c6
-rw-r--r--libpurple/protocols/jabber/usertune.h6
-rw-r--r--libpurple/protocols/jabber/xdata.c4
-rw-r--r--libpurple/protocols/jabber/xdata.h4
-rw-r--r--libpurple/protocols/msn/Makefile.mingw1
-rw-r--r--libpurple/protocols/msn/cmdproc.h2
-rw-r--r--libpurple/protocols/msn/contact.c2
-rw-r--r--libpurple/protocols/msn/contact.h2
-rw-r--r--libpurple/protocols/msn/error.c2
-rw-r--r--libpurple/protocols/msn/msn.c46
-rw-r--r--libpurple/protocols/msn/msn.h2
-rw-r--r--libpurple/protocols/msn/notification.c52
-rw-r--r--libpurple/protocols/msn/oim.c24
-rw-r--r--libpurple/protocols/msn/oim.h2
-rw-r--r--libpurple/protocols/msn/slp.c17
-rw-r--r--libpurple/protocols/msn/slpcall.c4
-rw-r--r--libpurple/protocols/msn/slplink.c8
-rw-r--r--libpurple/protocols/msn/soap.c2
-rw-r--r--libpurple/protocols/msn/soap.h2
-rw-r--r--libpurple/protocols/msn/switchboard.c4
-rw-r--r--libpurple/protocols/msnp9/slp.c5
-rw-r--r--libpurple/protocols/msnp9/slplink.c3
-rw-r--r--libpurple/protocols/oscar/clientlogin.c141
-rw-r--r--libpurple/protocols/oscar/family_auth.c2
-rw-r--r--libpurple/protocols/oscar/family_buddy.c3
-rw-r--r--libpurple/protocols/oscar/family_icbm.c33
-rw-r--r--libpurple/protocols/oscar/family_locate.c127
-rw-r--r--libpurple/protocols/oscar/oscar.c225
-rw-r--r--libpurple/protocols/oscar/oscar.h17
-rw-r--r--libpurple/protocols/oscar/snactypes.h1
-rw-r--r--libpurple/protocols/qq/buddy_list.c12
-rw-r--r--libpurple/protocols/qq/buddy_opt.c8
-rw-r--r--libpurple/protocols/qq/file_trans.c10
-rw-r--r--libpurple/protocols/qq/group_im.c2
-rw-r--r--libpurple/protocols/qq/group_internal.c4
-rw-r--r--libpurple/protocols/qq/qq_base.c44
-rw-r--r--libpurple/protocols/qq/qq_crypt.c9
-rw-r--r--libpurple/protocols/qq/qq_crypt.h2
-rw-r--r--libpurple/protocols/qq/qq_network.c18
-rw-r--r--libpurple/protocols/qq/qq_process.c2
-rw-r--r--libpurple/protocols/qq/send_file.c6
-rw-r--r--libpurple/protocols/simple/Makefile.am2
-rw-r--r--libpurple/protocols/yahoo/libyahoo.c8
-rw-r--r--libpurple/protocols/yahoo/libyahoojp.c8
-rw-r--r--libpurple/protocols/yahoo/libymsg.c93
-rw-r--r--libpurple/protocols/yahoo/libymsg.h21
-rw-r--r--libpurple/protocols/yahoo/util.c515
-rw-r--r--libpurple/proxy.c2
-rw-r--r--libpurple/server.c11
-rw-r--r--libpurple/smiley.c20
-rw-r--r--libpurple/smiley.h6
-rw-r--r--libpurple/status.h30
-rw-r--r--libpurple/tests/Makefile.am2
-rw-r--r--libpurple/tests/check_libpurple.c1
-rw-r--r--libpurple/tests/test_jabber_jutil.c10
-rw-r--r--libpurple/tests/test_qq.c105
-rw-r--r--libpurple/tests/test_yahoo_util.c98
-rw-r--r--libpurple/tests/tests.h7
-rw-r--r--libpurple/theme-loader.c2
-rw-r--r--libpurple/theme-loader.h4
-rw-r--r--libpurple/theme.c2
-rw-r--r--libpurple/theme.h6
-rw-r--r--libpurple/util.c34
-rw-r--r--libpurple/util.h16
150 files changed, 1928 insertions, 1310 deletions
diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
index 54fc19ec81..01f42bec74 100644
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -299,7 +299,6 @@ libpurple_la_LIBADD = \
-lm
AM_CPPFLAGS = \
- -DBR_PTHREADS=0 \
-DDATADIR=\"$(datadir)\" \
-DLIBDIR=\"$(libdir)/purple-$(PURPLE_MAJOR_VERSION)/\" \
-DLOCALEDIR=\"$(datadir)/locale\" \
diff --git a/libpurple/account.c b/libpurple/account.c
index a8c32ed88e..af2397ea38 100644
--- a/libpurple/account.c
+++ b/libpurple/account.c
@@ -1206,11 +1206,14 @@ void
purple_account_disconnect(PurpleAccount *account)
{
PurpleConnection *gc;
+ const char *username;
g_return_if_fail(account != NULL);
g_return_if_fail(!purple_account_is_disconnected(account));
- purple_debug_info("account", "Disconnecting account %p\n", account);
+ username = purple_account_get_username(account);
+ purple_debug_info("account", "Disconnecting account %s (%p)\n",
+ username ? username : "(null)", account);
account->disconnecting = TRUE;
@@ -2287,9 +2290,13 @@ void
purple_account_add_buddy(PurpleAccount *account, PurpleBuddy *buddy)
{
PurplePluginProtocolInfo *prpl_info = NULL;
- PurpleConnection *gc = purple_account_get_connection(account);
+ PurpleConnection *gc;
PurplePlugin *prpl = NULL;
+ g_return_if_fail(account != NULL);
+ g_return_if_fail(buddy != NULL);
+
+ gc = purple_account_get_connection(account);
if (gc != NULL)
prpl = purple_connection_get_prpl(gc);
diff --git a/libpurple/blist.c b/libpurple/blist.c
index 53179acb3b..09faeb676d 100644
--- a/libpurple/blist.c
+++ b/libpurple/blist.c
@@ -1118,7 +1118,7 @@ void purple_blist_alias_buddy(PurpleBuddy *buddy, const char *alias)
old_alias = buddy->alias;
if ((new_alias != NULL) && (*new_alias != '\0'))
- buddy->alias = g_strdup(alias);
+ buddy->alias = new_alias;
else {
buddy->alias = NULL;
g_free(new_alias); /* could be "\0" */
diff --git a/libpurple/blist.h b/libpurple/blist.h
index 57047265a1..ba16f73426 100644
--- a/libpurple/blist.h
+++ b/libpurple/blist.h
@@ -223,7 +223,7 @@ struct _PurpleBlistUiOps
* be set to a fallback function that saves data to blist.xml like in
* previous libpurple versions.
*
- * @attrib node The node which has been modified.
+ * @param node The node which has been modified.
*
* @since 2.6.0.
*/
@@ -238,7 +238,7 @@ struct _PurpleBlistUiOps
* be set to a fallback function that saves data to blist.xml like in
* previous libpurple versions.
*
- * @attrib node The node which has been modified.
+ * @param node The node which has been modified.
* @since 2.6.0.
*/
void (*remove_node)(PurpleBlistNode *node);
@@ -252,7 +252,7 @@ struct _PurpleBlistUiOps
* be set to a fallback function that saves data to blist.xml like in
* previous libpurple versions.
*
- * @attrib account The account whose data to save. If NULL, save all data
+ * @param account The account whose data to save. If NULL, save all data
* for all accounts.
* @since 2.6.0.
*/
diff --git a/libpurple/certificate.c b/libpurple/certificate.c
index 270ecc42ae..8c1f85d067 100644
--- a/libpurple/certificate.c
+++ b/libpurple/certificate.c
@@ -43,6 +43,91 @@ static GList *cert_verifiers = NULL;
/** List of registered Pools */
static GList *cert_pools = NULL;
+/*
+ * TODO: Merge this with PurpleCertificateVerificationStatus for 3.0.0 */
+typedef enum {
+ PURPLE_CERTIFICATE_UNKNOWN_ERROR = -1,
+
+ /* Not an error */
+ PURPLE_CERTIFICATE_NO_PROBLEMS = 0,
+
+ /* Non-fatal */
+ PURPLE_CERTIFICATE_NON_FATALS_MASK = 0x0000FFFF,
+
+ /* The certificate is self-signed. */
+ PURPLE_CERTIFICATE_SELF_SIGNED = 0x01,
+
+ /* The CA is not in libpurple's pool of certificates. */
+ PURPLE_CERTIFICATE_CA_UNKNOWN = 0x02,
+
+ /* The current time is before the certificate's specified
+ * activation time.
+ */
+ PURPLE_CERTIFICATE_NOT_ACTIVATED = 0x04,
+
+ /* The current time is after the certificate's specified expiration time */
+ PURPLE_CERTIFICATE_EXPIRED = 0x08,
+
+ /* The certificate's subject name doesn't match the expected */
+ PURPLE_CERTIFICATE_NAME_MISMATCH = 0x10,
+
+ /* No CA pool was found. This shouldn't happen... */
+ PURPLE_CERTIFICATE_NO_CA_POOL = 0x20,
+
+ /* Fatal */
+ PURPLE_CERTIFICATE_FATALS_MASK = 0xFFFF0000,
+
+ /* The signature chain could not be validated. Due to limitations in the
+ * the current API, this also indicates one of the CA certificates in the
+ * chain is expired (or not yet activated). FIXME 3.0.0 */
+ PURPLE_CERTIFICATE_INVALID_CHAIN = 0x10000,
+
+ /* The signature has been revoked. */
+ PURPLE_CERTIFICATE_REVOKED = 0x20000,
+
+ PURPLE_CERTIFICATE_LAST = 0x40000,
+} PurpleCertificateInvalidityFlags;
+
+static const gchar *
+invalidity_reason_to_string(PurpleCertificateInvalidityFlags flag)
+{
+ switch (flag) {
+ case PURPLE_CERTIFICATE_SELF_SIGNED:
+ return _("The certificate is self-signed and cannot be "
+ "automatically checked.");
+ break;
+ case PURPLE_CERTIFICATE_CA_UNKNOWN:
+ return _("The root certificate this one claims to be issued by is "
+ "unknown.");
+ break;
+ case PURPLE_CERTIFICATE_NOT_ACTIVATED:
+ return _("The certificate is not valid yet.");
+ break;
+ case PURPLE_CERTIFICATE_EXPIRED:
+ return _("The certificate has expired and should not be "
+ "considered valid.");
+ break;
+ case PURPLE_CERTIFICATE_NAME_MISMATCH:
+ /* Translators: "domain" refers to a DNS domain (e.g. talk.google.com) */
+ return _("The certificate presented is not issued to this domain.");
+ break;
+ case PURPLE_CERTIFICATE_NO_CA_POOL:
+ return _("You have no database of root certificates, so "
+ "this certificate cannot be validated.");
+ break;
+ case PURPLE_CERTIFICATE_INVALID_CHAIN:
+ return _("The certificate chain presented is invalid.");
+ break;
+ case PURPLE_CERTIFICATE_REVOKED:
+ return _("The certificate has been revoked.");
+ break;
+ case PURPLE_CERTIFICATE_UNKNOWN_ERROR:
+ default:
+ return _("An unknown certificate error occurred.");
+ break;
+ }
+}
+
void
purple_certificate_verify (PurpleCertificateVerifier *verifier,
const gchar *subject_name, GList *cert_chain,
@@ -1265,10 +1350,104 @@ x509_tls_cached_user_auth(PurpleCertificateVerificationRequest *vrq,
}
static void
-x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq);
+x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq,
+ PurpleCertificateInvalidityFlags flags);
static void
-x509_tls_cached_cert_in_cache(PurpleCertificateVerificationRequest *vrq)
+x509_tls_cached_complete(PurpleCertificateVerificationRequest *vrq,
+ PurpleCertificateInvalidityFlags flags)
+{
+ PurpleCertificatePool *tls_peers;
+ PurpleCertificate *peer_crt = vrq->cert_chain->data;
+
+ if (flags & PURPLE_CERTIFICATE_FATALS_MASK) {
+ /* TODO: Also print any other warnings? */
+ const gchar *error;
+ gchar *tmp, *secondary;
+
+ if (flags & PURPLE_CERTIFICATE_INVALID_CHAIN)
+ error = invalidity_reason_to_string(PURPLE_CERTIFICATE_INVALID_CHAIN);
+ else if (flags & PURPLE_CERTIFICATE_REVOKED)
+ error = invalidity_reason_to_string(PURPLE_CERTIFICATE_REVOKED);
+ else
+ error = invalidity_reason_to_string(PURPLE_CERTIFICATE_UNKNOWN_ERROR);
+
+ tmp = g_strdup_printf(_("The certificate for %s could not be validated."),
+ vrq->subject_name);
+ secondary = g_strconcat(tmp, " ", error, NULL);
+ g_free(tmp);
+
+ purple_notify_error(NULL, /* TODO: Probably wrong. */
+ _("SSL Certificate Error"),
+ _("Unable to validate certificate"),
+ secondary);
+ g_free(secondary);
+
+ purple_certificate_verify_complete(vrq, PURPLE_CERTIFICATE_INVALID);
+ return;
+ } else if (flags & PURPLE_CERTIFICATE_NON_FATALS_MASK) {
+ /* Non-fatal error. Prompt the user. */
+ gchar *tmp;
+ GString *errors;
+ guint32 i = 1;
+
+ tmp = g_strdup_printf(_("The certificate for %s could not be validated."),
+ vrq->subject_name);
+ errors = g_string_new(tmp);
+ g_free(tmp);
+
+ errors = g_string_append_c(errors, '\n');
+
+ /* Special case a name mismatch because we want to display the two names... */
+ if (flags & PURPLE_CERTIFICATE_NAME_MISMATCH) {
+ gchar *sn = purple_certificate_get_subject_name(peer_crt);
+
+ g_string_append_printf(errors, _("The certificate claims to be "
+ "from \"%s\" instead. This could mean that you are "
+ "not connecting to the service you believe you are."),
+ sn);
+ g_free(sn);
+
+ flags &= ~PURPLE_CERTIFICATE_NAME_MISMATCH;
+ }
+
+ while (i != PURPLE_CERTIFICATE_LAST) {
+ if (flags & i) {
+ errors = g_string_append_c(errors, '\n');
+ g_string_append(errors, invalidity_reason_to_string(i));
+ }
+
+ i <<= 1;
+ }
+
+ x509_tls_cached_user_auth(vrq, errors->str);
+ g_string_free(errors, TRUE);
+ return;
+ }
+
+ /* If we reach this point, the certificate is good. */
+
+ /* Look up the local cache and store it there for future use */
+ tls_peers = purple_certificate_find_pool(x509_tls_cached.scheme_name,
+ "tls_peers");
+ if (tls_peers) {
+ if (!purple_certificate_pool_contains(tls_peers, vrq->subject_name) &&
+ !purple_certificate_pool_store(tls_peers,vrq->subject_name,
+ peer_crt)) {
+ purple_debug_error("certificate/x509/tls_cached",
+ "FAILED to cache peer certificate\n");
+ }
+ } else {
+ purple_debug_error("certificate/x509/tls_cached",
+ "Unable to locate tls_peers certificate cache.\n");
+ }
+
+ purple_certificate_verify_complete(vrq, PURPLE_CERTIFICATE_VALID);
+}
+
+static void
+x509_tls_cached_cert_in_cache(PurpleCertificateVerificationRequest *vrq,
+ PurpleCertificateInvalidityFlags flags)
{
/* TODO: Looking this up by name over and over is expensive.
Fix, please! */
@@ -1291,7 +1470,7 @@ x509_tls_cached_cert_in_cache(PurpleCertificateVerificationRequest *vrq)
"Lookup failed on cached certificate!\n"
"Falling back to full verification.\n");
/* vrq now becomes the problem of unknown_peer */
- x509_tls_cached_unknown_peer(vrq);
+ x509_tls_cached_unknown_peer(vrq, flags);
return;
}
@@ -1302,14 +1481,12 @@ x509_tls_cached_cert_in_cache(PurpleCertificateVerificationRequest *vrq)
if (!memcmp(peer_fpr->data, cached_fpr->data, peer_fpr->len)) {
purple_debug_info("certificate/x509/tls_cached",
"Peer cert matched cached\n");
- /* vrq is now finished */
- purple_certificate_verify_complete(vrq,
- PURPLE_CERTIFICATE_VALID);
+ x509_tls_cached_complete(vrq, flags);
} else {
purple_debug_error("certificate/x509/tls_cached",
"Peer cert did NOT match cached\n");
/* vrq now becomes the problem of the user */
- x509_tls_cached_unknown_peer(vrq);
+ x509_tls_cached_unknown_peer(vrq, flags);
}
purple_certificate_destroy(cached_crt);
@@ -1324,9 +1501,8 @@ x509_tls_cached_cert_in_cache(PurpleCertificateVerificationRequest *vrq)
*/
static void
x509_tls_cached_check_subject_name(PurpleCertificateVerificationRequest *vrq,
- gboolean had_ca_pool)
+ PurpleCertificateInvalidityFlags flags)
{
- PurpleCertificatePool *tls_peers;
PurpleCertificate *peer_crt;
GList *chain = vrq->cert_chain;
@@ -1337,77 +1513,14 @@ x509_tls_cached_check_subject_name(PurpleCertificateVerificationRequest *vrq,
vrq->subject_name) ) {
gchar *sn = purple_certificate_get_subject_name(peer_crt);
+ flags |= PURPLE_CERTIFICATE_NAME_MISMATCH;
purple_debug_error("certificate/x509/tls_cached",
"Name mismatch: Certificate given for %s "
"has a name of %s\n",
vrq->subject_name, sn);
-
- if (had_ca_pool) {
- /* Prompt the user to authenticate the certificate */
- /* TODO: Provide the user with more guidance about why he is
- being prompted */
- /* vrq will be completed by user_auth */
- gchar *msg;
- msg = g_strdup_printf(_("The certificate presented by \"%s\" "
- "claims to be from \"%s\" instead. "
- "This could mean that you are not "
- "connecting to the service you "
- "believe you are."),
- vrq->subject_name, sn);
-
- x509_tls_cached_user_auth(vrq, msg);
- g_free(msg);
- } else {
- /* Had no CA pool, so couldn't verify the chain *and*
- * the subject name isn't valid.
- * I think this is bad enough to warrant a fatal error. It's
- * not likely anyway...
- */
- purple_notify_error(NULL, /* TODO: Probably wrong. */
- _("SSL Certificate Error"),
- _("Invalid certificate chain"),
- _("You have no database of root certificates, so "
- "this certificate cannot be validated."));
- }
-
- g_free(sn);
- return;
- } /* if (name mismatch) */
-
- if (!had_ca_pool) {
- /* The subject name is correct, but we weren't able to verify the
- * chain because there was no pool of root CAs found. Prompt the user
- * to validate it.
- */
-
- /* vrq will be completed by user_auth */
- x509_tls_cached_user_auth(vrq,_("You have no database of root "
- "certificates, so this "
- "certificate cannot be "
- "validated."));
- return;
}
- /* If we reach this point, the certificate is good. */
- /* Look up the local cache and store it there for future use */
- tls_peers = purple_certificate_find_pool(x509_tls_cached.scheme_name,
- "tls_peers");
-
- if (tls_peers) {
- if (!purple_certificate_pool_store(tls_peers,vrq->subject_name,
- peer_crt) ) {
- purple_debug_error("certificate/x509/tls_cached",
- "FAILED to cache peer certificate\n");
- }
- } else {
- purple_debug_error("certificate/x509/tls_cached",
- "Unable to locate tls_peers certificate "
- "cache.\n");
- }
-
- /* Whew! Done! */
- purple_certificate_verify_complete(vrq, PURPLE_CERTIFICATE_VALID);
-
+ x509_tls_cached_complete(vrq, flags);
}
/* For when we've never communicated with this party before */
@@ -1415,7 +1528,8 @@ x509_tls_cached_check_subject_name(PurpleCertificateVerificationRequest *vrq,
least reprioritize them.
*/
static void
-x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
+x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq,
+ PurpleCertificateInvalidityFlags flags)
{
PurpleCertificatePool *ca;
PurpleCertificate *peer_crt;
@@ -1430,22 +1544,13 @@ x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
/* TODO: Figure out a way to check for a bad signature, as opposed to
"not self-signed" */
if ( purple_certificate_signed_by(peer_crt, peer_crt) ) {
- gchar *msg;
+ flags |= PURPLE_CERTIFICATE_SELF_SIGNED;
purple_debug_info("certificate/x509/tls_cached",
"Certificate for %s is self-signed.\n",
vrq->subject_name);
- /* Prompt the user to authenticate the certificate */
- /* vrq will be completed by user_auth */
- msg = g_strdup_printf(_("The certificate presented by \"%s\" "
- "is self-signed. It cannot be "
- "automatically checked."),
- vrq->subject_name);
-
- x509_tls_cached_user_auth(vrq,msg);
-
- g_free(msg);
+ x509_tls_cached_check_subject_name(vrq, flags);
return;
} /* if (self signed) */
@@ -1491,32 +1596,11 @@ x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
* If we get here, either the cert matched the stuff right above
* or it didn't, in which case we give up and complain to the user.
*/
- if (chain_validated) {
- x509_tls_cached_check_subject_name(vrq, TRUE);
- } else {
+ if (!chain_validated)
/* TODO: Tell the user where the chain broke? */
- /* TODO: This error will hopelessly confuse any
- non-elite user. */
- gchar *secondary;
-
- secondary = g_strdup_printf(_("The certificate chain presented"
- " for %s is not valid."),
- vrq->subject_name);
-
- /* TODO: Make this error either block the ensuing SSL
- connection error until the user dismisses this one, or
- stifle it. */
- purple_notify_error(NULL, /* TODO: Probably wrong. */
- _("SSL Certificate Error"),
- _("Invalid certificate chain"),
- secondary );
- g_free(secondary);
-
- /* Okay, we're done here */
- purple_certificate_verify_complete(vrq,
- PURPLE_CERTIFICATE_INVALID);
- }
+ flags |= PURPLE_CERTIFICATE_INVALID_CHAIN;
+ x509_tls_cached_check_subject_name(vrq, flags);
return;
} /* if (signature chain not good) */
@@ -1527,7 +1611,9 @@ x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
"No X.509 Certificate Authority pool "
"could be found!\n");
- x509_tls_cached_check_subject_name(vrq, FALSE);
+ flags |= PURPLE_CERTIFICATE_NO_CA_POOL;
+
+ x509_tls_cached_check_subject_name(vrq, flags);
return;
}
@@ -1540,15 +1626,15 @@ x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
ca_id);
ca_crt = purple_certificate_pool_retrieve(ca, ca_id);
if ( NULL == ca_crt ) {
+ flags |= PURPLE_CERTIFICATE_CA_UNKNOWN;
+
purple_debug_warning("certificate/x509/tls_cached",
"Certificate Authority with DN='%s' not "
"found. I'll prompt the user, I guess.\n",
ca_id);
g_free(ca_id);
- /* vrq will be completed by user_auth */
- x509_tls_cached_user_auth(vrq,_("The root certificate this "
- "one claims to be issued by "
- "is unknown to Pidgin."));
+
+ x509_tls_cached_check_subject_name(vrq, flags);
return;
}
@@ -1579,36 +1665,15 @@ x509_tls_cached_unknown_peer(PurpleCertificateVerificationRequest *vrq)
/* TODO: Also mention the CA involved. While I could do this
now, a full DN is a little much with which to assault the
user's poor, leaky eyes. */
- /* TODO: This error message makes my eyes cross, and I wrote it */
- gchar * secondary =
- g_strdup_printf(_("The certificate chain presented by "
- "%s does not have a valid digital "
- "signature from the Certificate "
- "Authority from which it claims to "
- "have a signature."),
- vrq->subject_name);
-
- purple_notify_error(NULL, /* TODO: Probably wrong */
- _("SSL Certificate Error"),
- _("Invalid certificate authority"
- " signature"),
- secondary);
- g_free(secondary);
-
- /* Signal "bad cert" */
- purple_certificate_verify_complete(vrq,
- PURPLE_CERTIFICATE_INVALID);
-
- purple_certificate_destroy(ca_crt);
- g_byte_array_free(ca_fpr, TRUE);
- g_byte_array_free(last_fpr, TRUE);
- return;
- } /* if (CA signature not good) */
+ flags |= PURPLE_CERTIFICATE_INVALID_CHAIN;
+ }
g_byte_array_free(ca_fpr, TRUE);
g_byte_array_free(last_fpr, TRUE);
- x509_tls_cached_check_subject_name(vrq, TRUE);
+ purple_certificate_destroy(ca_crt);
+
+ x509_tls_cached_check_subject_name(vrq, flags);
}
static void
@@ -1617,6 +1682,7 @@ x509_tls_cached_start_verify(PurpleCertificateVerificationRequest *vrq)
const gchar *tls_peers_name = "tls_peers"; /* Name of local cache */
PurpleCertificatePool *tls_peers;
time_t now, activation, expiration;
+ PurpleCertificateInvalidityFlags flags = PURPLE_CERTIFICATE_NO_PROBLEMS;
gboolean ret;
g_return_if_fail(vrq);
@@ -1632,37 +1698,21 @@ x509_tls_cached_start_verify(PurpleCertificateVerificationRequest *vrq)
now = time(NULL);
ret = purple_certificate_get_times(vrq->cert_chain->data, &activation,
&expiration);
- if (!ret || now > expiration || now < activation) {
- gchar *secondary;
-
- if (!ret)
- purple_debug_error("certificate/x509/tls_cached",
- "Failed to get validity times for certificate %s\n",
- vrq->subject_name);
- else if (now > expiration)
- purple_debug_error("certificate/x509/tls_cached",
- "Certificate %s expired at %s\n",
- vrq->subject_name, ctime(&expiration));
- else
- purple_debug_error("certificate/x509/tls_cached",
- "Certificate %s is not yet valid, will be at %s\n",
- vrq->subject_name, ctime(&activation));
-
- /* FIXME 2.6.1 */
- secondary = g_strdup_printf(_("The certificate chain presented"
- " for %s is not valid."),
- vrq->subject_name);
-
- purple_notify_error(NULL, /* TODO: Probably wrong. */
- _("SSL Certificate Error"),
- _("Invalid certificate chain"),
- secondary );
- g_free(secondary);
-
- /* Okay, we're done here */
- purple_certificate_verify_complete(vrq,
- PURPLE_CERTIFICATE_INVALID);
- return;
+ if (!ret) {
+ flags |= PURPLE_CERTIFICATE_EXPIRED | PURPLE_CERTIFICATE_NOT_ACTIVATED;
+ purple_debug_error("certificate/x509/tls_cached",
+ "Failed to get validity times for certificate %s\n",
+ vrq->subject_name);
+ } else if (now > expiration) {
+ flags |= PURPLE_CERTIFICATE_EXPIRED;
+ purple_debug_error("certificate/x509/tls_cached",
+ "Certificate %s expired at %s\n",
+ vrq->subject_name, ctime(&expiration));
+ } else if (now < activation) {
+ flags |= PURPLE_CERTIFICATE_NOT_ACTIVATED;
+ purple_debug_error("certificate/x509/tls_cached",
+ "Certificate %s is not yet valid, will be at %s\n",
+ vrq->subject_name, ctime(&activation));
}
tls_peers = purple_certificate_find_pool(x509_tls_cached.scheme_name,tls_peers_name);
@@ -1672,9 +1722,8 @@ x509_tls_cached_start_verify(PurpleCertificateVerificationRequest *vrq)
"Couldn't find local peers cache %s\n",
tls_peers_name);
-
/* vrq now becomes the problem of unknown_peer */
- x509_tls_cached_unknown_peer(vrq);
+ x509_tls_cached_unknown_peer(vrq, flags);
return;
}
@@ -1685,12 +1734,12 @@ x509_tls_cached_start_verify(PurpleCertificateVerificationRequest *vrq)
purple_debug_info("certificate/x509/tls_cached",
"...Found cached cert\n");
/* vrq is now the responsibility of cert_in_cache */
- x509_tls_cached_cert_in_cache(vrq);
+ x509_tls_cached_cert_in_cache(vrq, flags);
} else {
purple_debug_warning("certificate/x509/tls_cached",
"...Not in cache\n");
/* vrq now becomes the problem of unknown_peer */
- x509_tls_cached_unknown_peer(vrq);
+ x509_tls_cached_unknown_peer(vrq, flags);
}
}
diff --git a/libpurple/conversation.h b/libpurple/conversation.h
index 9090645d4e..5cd0b12a24 100644
--- a/libpurple/conversation.h
+++ b/libpurple/conversation.h
@@ -1308,7 +1308,7 @@ void purple_conv_chat_left(PurpleConvChat *chat);
* @param user The user to invite to the chat.
* @param message The message to send with the invitation.
* @param confirm Prompt before sending the invitation. The user is always
- * prompted if either #user or #message is @c NULL.
+ * prompted if either \a user or \a message is @c NULL.
*
* @since 2.6.0
*/
diff --git a/libpurple/core.c b/libpurple/core.c
index d4e02dc5c2..a8d179cf0b 100644
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -497,7 +497,7 @@ purple_core_migrate(void)
{
char *link;
#if GLIB_CHECK_VERSION(2,4,0)
- GError *err = NULL;
+ err = NULL;
if ((link = g_file_read_link(name, &err)) == NULL)
{
diff --git a/libpurple/core.h b/libpurple/core.h
index 954c930015..3ae05c2010 100644
--- a/libpurple/core.h
+++ b/libpurple/core.h
@@ -24,6 +24,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
+
+/*! @mainpage Pidgin/Finch/libpurple API Documentation
+ *
+ * <a href="group__core.html">libpurple</a> is intended to be the core of an IM
+ * program. <a href="group__pidgin.html">Pidgin</a> is a GTK+ frontend
+ * to libpurple, and <a href="group__finch.html">Finch</a> is an ncurses
+ * frontend built using <a href="group__gnt.html">libgnt</a>
+ * (GLib Ncurses Toolkit).
+ */
+
#ifndef _PURPLE_CORE_H_
#define _PURPLE_CORE_H_
diff --git a/libpurple/dbus-analyze-functions.py b/libpurple/dbus-analyze-functions.py
index 2433256327..a52a88dfb0 100644
--- a/libpurple/dbus-analyze-functions.py
+++ b/libpurple/dbus-analyze-functions.py
@@ -181,15 +181,20 @@ class Binding:
def processoutput(self, type, name):
+ const = False
+ unsigned = False
# the "void" type is simple ...
if type == ["void"]:
return self.outputvoid(type, name)
- const = False
if type[0] == "const":
type = type[1:]
const = True
+ if type[0] == "unsigned":
+ type = type[1:]
+ unsigned = True
+
# a string
if type == ["char", pointer] or type == ["gchar", pointer]:
return self.outputstring(type, name, const)
@@ -197,7 +202,7 @@ class Binding:
# simple types (ints, booleans, enums, ...)
if (len(type) == 1) and \
((type[0] in simpletypes) or (type[0].startswith("Purple"))):
- return self.outputsimple(type, name)
+ return self.outputsimple(type, name, unsigned)
# pointers ...
if (len(type) == 2) and (type[1] == pointer):
@@ -303,10 +308,13 @@ class ClientBinding (Binding):
# self.returncode.append("NULLIFY(%s);" % name)
self.returncode.append("return %s;" % name);
- def outputsimple(self, type, name):
+ def outputsimple(self, type, name, us):
self.functiontype = type[0]
self.decls.append("%s %s = 0;" % (type[0], name))
- self.outputparams.append(("G_TYPE_INT", name))
+ if us:
+ self.outputparams.append(("G_TYPE_UINT", name))
+ else:
+ self.outputparams.append(("G_TYPE_INT", name))
self.returncode.append("return %s;" % name);
# we could add "const" to the return type but this would probably
@@ -455,11 +463,16 @@ class ServerBinding (Binding):
if not const:
self.ccodeout.append("\tg_free(%s);" % name)
- def outputsimple(self, type, name):
- self.cdecls.append("\tdbus_int32_t %s;" % name)
+ def outputsimple(self, type, name, us):
+ if us:
+ self.cdecls.append("\tdbus_uint32_t %s;" % name)
+ self.cparamsout.append(("UINT32", name))
+ self.addouttype("u", name)
+ else:
+ self.cdecls.append("\tdbus_int32_t %s;" % name)
+ self.cparamsout.append(("INT32", name))
+ self.addouttype("i", name)
self.ccode.append("\t%s = %s;" % (name, self.call))
- self.cparamsout.append(("INT32", name))
- self.addouttype("i", name)
def outputpurplestructure(self, type, name):
self.cdecls.append("\tdbus_int32_t %s;" % name)
diff --git a/libpurple/dnssrv.c b/libpurple/dnssrv.c
index ed6ba7e25a..82b1f0deaa 100644
--- a/libpurple/dnssrv.c
+++ b/libpurple/dnssrv.c
@@ -465,9 +465,16 @@ res_main_thread_cb(gpointer data)
{
PurpleSrvResponse *srvres = NULL;
PurpleSrvQueryData *query_data = data;
- if(query_data->error_message != NULL)
+ if(query_data->error_message != NULL) {
purple_debug_error("dnssrv", query_data->error_message);
- else {
+ if (query_data->type == DNS_TYPE_SRV) {
+ if (query_data->cb.srv)
+ query_data->cb.srv(srvres, 0, query_data->extradata);
+ } else if (query_data->type == DNS_TYPE_TXT) {
+ if (query_data->cb.txt)
+ query_data->cb.txt(NULL, query_data->extradata);
+ }
+ } else {
if (query_data->type == DNS_TYPE_SRV) {
PurpleSrvResponse *srvres_tmp = NULL;
GList *lst = query_data->results;
diff --git a/libpurple/dnssrv.h b/libpurple/dnssrv.h
index 376310a2a5..19f8adc46e 100644
--- a/libpurple/dnssrv.h
+++ b/libpurple/dnssrv.h
@@ -98,11 +98,11 @@ void purple_txt_cancel(PurpleSrvQueryData *query_data);
/**
* Get the value of the current TXT record.
*
- * @param resp The TXT response record
+ * @param response The TXT response record
* @returns The value of the current TXT record.
* @since 2.6.0
*/
-const gchar *purple_txt_response_get_content(PurpleTxtResponse *resp);
+const gchar *purple_txt_response_get_content(PurpleTxtResponse *response);
/**
* Destroy a TXT DNS response object.
@@ -110,7 +110,7 @@ const gchar *purple_txt_response_get_content(PurpleTxtResponse *resp);
* @param response The PurpleTxtResponse to destroy.
* @since 2.6.0
*/
-void purple_txt_response_destroy(PurpleTxtResponse *resp);
+void purple_txt_response_destroy(PurpleTxtResponse *response);
#ifdef __cplusplus
}
diff --git a/libpurple/example/Makefile.am b/libpurple/example/Makefile.am
index e44edd3721..583420917e 100644
--- a/libpurple/example/Makefile.am
+++ b/libpurple/example/Makefile.am
@@ -12,7 +12,6 @@ nullclient_LDADD = \
AM_CPPFLAGS = \
-DSTANDALONE \
- -DBR_PTHREADS=0 \
-DDATADIR=\"$(datadir)\" \
-DLIBDIR=\"$(libdir)/purple-$(PURPLE_MAJOR_VERSION)/\" \
-DLOCALEDIR=\"$(datadir)/locale\" \
diff --git a/libpurple/ft.c b/libpurple/ft.c
index 8ebbbdf349..f1ee489a28 100644
--- a/libpurple/ft.c
+++ b/libpurple/ft.c
@@ -1313,7 +1313,7 @@ purple_xfer_cancel_local(PurpleXfer *xfer)
if (purple_xfer_get_filename(xfer) != NULL)
{
- msg = g_strdup_printf(_("You canceled the transfer of %s"),
+ msg = g_strdup_printf(_("You cancelled the transfer of %s"),
purple_xfer_get_filename(xfer));
}
else
@@ -1376,12 +1376,12 @@ purple_xfer_cancel_remote(PurpleXfer *xfer)
if (purple_xfer_get_filename(xfer) != NULL)
{
- msg = g_strdup_printf(_("%s canceled the transfer of %s"),
+ msg = g_strdup_printf(_("%s cancelled the transfer of %s"),
buddy ? purple_buddy_get_alias(buddy) : xfer->who, purple_xfer_get_filename(xfer));
}
else
{
- msg = g_strdup_printf(_("%s canceled the file transfer"),
+ msg = g_strdup_printf(_("%s cancelled the file transfer"),
buddy ? purple_buddy_get_alias(buddy) : xfer->who);
}
purple_xfer_conversation_write(xfer, msg, TRUE);
diff --git a/libpurple/idle.h b/libpurple/idle.h
index 486021c8c7..f01c75bc60 100644
--- a/libpurple/idle.h
+++ b/libpurple/idle.h
@@ -26,6 +26,8 @@
#ifndef _PURPLE_IDLE_H_
#define _PURPLE_IDLE_H_
+#include <time.h>
+
/**
* Idle UI operations.
*/
diff --git a/libpurple/media-gst.h b/libpurple/media-gst.h
index 3840792d2b..d729e32aa5 100644
--- a/libpurple/media-gst.h
+++ b/libpurple/media-gst.h
@@ -21,7 +21,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#ifndef _PURPLE_MEDIA_GST_H_
@@ -42,7 +42,7 @@ G_BEGIN_DECLS
#define PURPLE_IS_MEDIA_ELEMENT_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), PURPLE_TYPE_MEDIA_ELEMENT_INFO))
#define PURPLE_MEDIA_ELEMENT_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MEDIA_ELEMENT_INFO, PurpleMediaElementInfo))
-/** @copydoc _PurpleMediaElementInfo */
+/** An opaque structure representing an audio/video source/sink. */
typedef struct _PurpleMediaElementInfo PurpleMediaElementInfo;
typedef struct _PurpleMediaElementInfoClass PurpleMediaElementInfoClass;
typedef GstElement *(*PurpleMediaElementCreateCallback)(PurpleMedia *media,
@@ -138,6 +138,9 @@ GstElement *purple_media_manager_get_pipeline(PurpleMediaManager *manager);
*
* @param manager The media manager to use to obtain the source/sink.
* @param type The type of source/sink to get.
+ * @param media The media call this element is requested for.
+ * @param session_id The id of the session this element is requested for or NULL.
+ * @param participant The remote user this element is requested for or NULL.
*
* @since 2.6.0
*/
diff --git a/libpurple/media.c b/libpurple/media.c
index c6479b3932..1e334db06a 100644
--- a/libpurple/media.c
+++ b/libpurple/media.c
@@ -21,7 +21,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <string.h>
@@ -2046,13 +2046,32 @@ media_bus_call(GstBus *bus, GstMessage *msg, PurpleMedia *media)
FsError error_no;
gst_structure_get_enum(msg->structure, "error-no",
FS_TYPE_ERROR, (gint*)&error_no);
- /*
- * Unknown CName is only a problem for the
- * multicast transmitter which isn't used.
- */
- if (error_no != FS_ERROR_UNKNOWN_CNAME)
- purple_debug_error("media", "farsight-error: %i: %s\n", error_no,
- gst_structure_get_string(msg->structure, "error-msg"));
+ switch (error_no) {
+ case FS_ERROR_NO_CODECS:
+ purple_media_error(media, _("No codecs found. Install some GStreamer codecs found in GStreamer plugins packages."));
+ purple_media_end(media, NULL, NULL);
+ break;
+ case FS_ERROR_NO_CODECS_LEFT:
+ purple_media_error(media, _("No codecs left. Your codec preferences in fs-codecs.conf are too strict."));
+ purple_media_end(media, NULL, NULL);
+ break;
+ case FS_ERROR_UNKNOWN_CNAME:
+ /*
+ * Unknown CName is only a problem for the
+ * multicast transmitter which isn't used.
+ * It is also deprecated.
+ */
+ break;
+ default:
+ purple_debug_error("media", "farsight-error: %i: %s\n", error_no,
+ gst_structure_get_string(msg->structure, "error-msg"));
+ break;
+ }
+
+ if (FS_ERROR_IS_FATAL(error_no)) {
+ purple_media_error(media, _("A non-recoverable Farsight2 error has occurred."));
+ purple_media_end(media, NULL, NULL);
+ }
} else if (gst_structure_has_name(msg->structure,
"farsight-new-local-candidate")) {
FsStream *stream = g_value_get_object(gst_structure_get_value(msg->structure, "stream"));
@@ -2129,6 +2148,35 @@ media_bus_call(GstBus *bus, GstMessage *msg, PurpleMedia *media)
}
break;
}
+ case GST_MESSAGE_ERROR: {
+ GstElement *element = GST_ELEMENT(GST_MESSAGE_SRC(msg));
+ GstElement *lastElement = NULL;
+ while (!GST_IS_PIPELINE(element)) {
+ if (element == media->priv->confbin) {
+ purple_media_error(media, _("Conference error"));
+ purple_media_end(media, NULL, NULL);
+ break;
+ }
+ lastElement = element;
+ element = GST_ELEMENT_PARENT(element);
+ }
+ if (GST_IS_PIPELINE(element)) {
+ GList *sessions = g_hash_table_get_values(media->priv->sessions);
+ for (; sessions; sessions = g_list_delete_link(sessions, sessions)) {
+ PurpleMediaSession *session = sessions->data;
+
+ if (session->src == lastElement) {
+ if (session->type & PURPLE_MEDIA_AUDIO)
+ purple_media_error(media, _("Error with your microphone"));
+ else
+ purple_media_error(media, _("Error with your webcam"));
+ purple_media_end(media, NULL, NULL);
+ break;
+ }
+ }
+ g_list_free(sessions);
+ }
+ }
default:
break;
}
@@ -2230,6 +2278,18 @@ purple_media_stream_info(PurpleMedia *media, PurpleMediaInfoType type,
purple_media_to_fs_stream_direction(
stream->session->type), NULL);
stream->accepted = TRUE;
+
+ if (stream->remote_candidates != NULL) {
+ GError *err = NULL;
+ fs_stream_set_remote_candidates(stream->stream,
+ stream->remote_candidates, &err);
+
+ if (err) {
+ purple_debug_error("media", "Error adding remote"
+ " candidates: %s\n", err->message);
+ g_error_free(err);
+ }
+ }
}
} else if (local == TRUE && (type == PURPLE_MEDIA_INFO_MUTE ||
type == PURPLE_MEDIA_INFO_UNMUTE)) {
@@ -2541,7 +2601,7 @@ purple_media_add_stream(PurpleMedia *media, const gchar *sess_id,
media->priv->conference, media_type, &err);
if (err != NULL) {
- purple_media_error(media, "Error creating session: %s\n", err->message);
+ purple_media_error(media, _("Error creating session: %s"), err->message);
g_error_free(err);
g_free(session);
return FALSE;
@@ -2730,10 +2790,13 @@ purple_media_add_stream(PurpleMedia *media, const gchar *sess_id,
num_params, params, &err);
}
- if (err) {
- purple_debug_error("media", "Error creating stream: %s\n",
- err->message);
- g_error_free(err);
+ if (fsstream == NULL) {
+ purple_debug_error("media",
+ "Error creating stream: %s\n",
+ err && err->message ?
+ err->message : "NULL");
+ if (err)
+ g_error_free(err);
g_object_unref(participant);
g_hash_table_remove(media->priv->participants, who);
purple_media_remove_session(media, session);
@@ -2852,13 +2915,15 @@ purple_media_add_remote_candidates(PurpleMedia *media, const gchar *sess_id,
stream->remote_candidates = g_list_concat(stream->remote_candidates,
purple_media_candidate_list_to_fs(remote_candidates));
- fs_stream_set_remote_candidates(stream->stream,
- stream->remote_candidates, &err);
+ if (stream->accepted == TRUE) {
+ fs_stream_set_remote_candidates(stream->stream,
+ stream->remote_candidates, &err);
- if (err) {
- purple_debug_error("media", "Error adding remote"
- " candidates: %s\n", err->message);
- g_error_free(err);
+ if (err) {
+ purple_debug_error("media", "Error adding remote"
+ " candidates: %s\n", err->message);
+ g_error_free(err);
+ }
}
#endif
}
diff --git a/libpurple/media.h b/libpurple/media.h
index dd8942fb56..d58f94f367 100644
--- a/libpurple/media.h
+++ b/libpurple/media.h
@@ -21,7 +21,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#ifndef _PURPLE_MEDIA_H_
@@ -59,11 +59,11 @@ G_BEGIN_DECLS
#define PURPLE_MEDIA_TYPE_STATE (purple_media_state_changed_get_type())
#define PURPLE_MEDIA_TYPE_INFO_TYPE (purple_media_info_type_get_type())
-/** @copydoc _PurpleMedia */
+/** An opaque structure representing a media call. */
typedef struct _PurpleMedia PurpleMedia;
-/** @copydoc _PurpleMediaCandidate */
+/** An opaque structure representing a network candidate (IP Address and port pair). */
typedef struct _PurpleMediaCandidate PurpleMediaCandidate;
-/** @copydoc _PurpleMediaCodec */
+/** An opaque structure representing an audio or video codec. */
typedef struct _PurpleMediaCodec PurpleMediaCodec;
/** Media caps */
@@ -559,6 +559,7 @@ GList *purple_media_get_active_remote_candidates(PurpleMedia *media,
* @param media The media object to find the session in.
* @param sess_id The session id of the session find the stream in.
* @param participant The name of the remote user to set the candidates from.
+ * @param codecs The list of remote codecs to set.
*
* @return @c TRUE The codecs were set successfully, or @c FALSE otherwise.
*
diff --git a/libpurple/mediamanager.c b/libpurple/mediamanager.c
index 1bcaefd76c..07de5c97e7 100644
--- a/libpurple/mediamanager.c
+++ b/libpurple/mediamanager.c
@@ -21,7 +21,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include "internal.h"
diff --git a/libpurple/mediamanager.h b/libpurple/mediamanager.h
index 8fdf06662f..2d6199c618 100644
--- a/libpurple/mediamanager.h
+++ b/libpurple/mediamanager.h
@@ -21,7 +21,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#ifndef _PURPLE_MEDIA_MANAGER_H_
@@ -30,9 +30,9 @@
#include <glib.h>
#include <glib-object.h>
-/** @copydoc _PurpleMediaManager */
+/** An opaque structure representing a group of (usually all) media calls. */
typedef struct _PurpleMediaManager PurpleMediaManager;
-/** @copydoc _PurpleMediaManagerClass */
+/** The GObject class structure of the PurpleMediaManager object. */
typedef struct _PurpleMediaManagerClass PurpleMediaManagerClass;
#include "account.h"
@@ -81,6 +81,7 @@ PurpleMediaManager *purple_media_manager_get(void);
* @param account The account to create the session on.
* @param conference_type The conference type to feed into Farsight2.
* @param remote_user The remote user to initiate the session with.
+ * @param initiator TRUE if the local user is the initiator of this media call, FALSE otherwise.
*
* @return A newly created media session.
*
diff --git a/libpurple/plugins/joinpart.c b/libpurple/plugins/joinpart.c
index 35c1bfbe22..9969022d36 100644
--- a/libpurple/plugins/joinpart.c
+++ b/libpurple/plugins/joinpart.c
@@ -229,16 +229,17 @@ get_plugin_pref_frame(PurplePlugin *plugin)
frame = purple_plugin_pref_frame_new();
- ppref = purple_plugin_pref_new_with_label(_("Join/Part Hiding Configuration"));
+ ppref = purple_plugin_pref_new_with_label(_("Hide Joins/Parts"));
purple_plugin_pref_frame_add(frame, ppref);
ppref = purple_plugin_pref_new_with_name_and_label(THRESHOLD_PREF,
- _("Minimum Room Size"));
+ /* Translators: Followed by an input request a number of people */
+ _("For rooms with more than this many people"));
purple_plugin_pref_set_bounds(ppref, 0, 1000);
purple_plugin_pref_frame_add(frame, ppref);
ppref = purple_plugin_pref_new_with_name_and_label(DELAY_PREF,
- _("User Inactivity Timeout (in minutes)"));
+ _("If user has not spoken in this many minutes"));
purple_plugin_pref_set_bounds(ppref, 0, 8 * 60); /* 8 Hours */
purple_plugin_pref_frame_add(frame, ppref);
diff --git a/libpurple/plugins/perl/common/XMLNode.xs b/libpurple/plugins/perl/common/XMLNode.xs
index cc437e6e55..0c02e58427 100644
--- a/libpurple/plugins/perl/common/XMLNode.xs
+++ b/libpurple/plugins/perl/common/XMLNode.xs
@@ -4,21 +4,24 @@ MODULE = Purple::XMLNode PACKAGE = Purple::XMLNode PREFIX = xmlnode_
PROTOTYPES: ENABLE
Purple::XMLNode
-xmlnode_copy(class, src)
+xmlnode_copy(src)
Purple::XMLNode src
- C_ARGS:
- src
void
xmlnode_free(node)
Purple::XMLNode node
Purple::XMLNode
-xmlnode_from_str(class, str, size)
- const char *str
- gssize size
- C_ARGS:
- str, size
+xmlnode_from_str(const char *str, gssize length(str))
+ PROTOTYPE: $
+
+const char *
+xmlnode_get_name(node)
+ Purple::XMLNode node
+ CODE:
+ RETVAL = node->name;
+ OUTPUT:
+ RETVAL
const char *
xmlnode_get_attrib(node, attr)
@@ -29,6 +32,18 @@ Purple::XMLNode
xmlnode_get_child(parent, name)
Purple::XMLNode parent
const char *name
+PREINIT:
+ xmlnode *tmp;
+CODE:
+ if (!name || *name == '\0') {
+ tmp = parent->child;
+ while (tmp && tmp->type != XMLNODE_TYPE_TAG)
+ tmp = tmp->next;
+ RETVAL = tmp;
+ } else
+ RETVAL = xmlnode_get_child(parent, name);
+OUTPUT:
+ RETVAL
Purple::XMLNode
xmlnode_get_child_with_namespace(parent, name, xmlns)
@@ -41,6 +56,19 @@ xmlnode_get_data(node)
Purple::XMLNode node
Purple::XMLNode
+xmlnode_get_next(node)
+ Purple::XMLNode node
+PREINIT:
+ xmlnode *tmp;
+CODE:
+ tmp = node->next;
+ while (tmp && tmp->type != XMLNODE_TYPE_TAG)
+ tmp = tmp->next;
+ RETVAL = tmp;
+OUTPUT:
+ RETVAL
+
+Purple::XMLNode
xmlnode_get_next_twin(node)
Purple::XMLNode node
@@ -78,11 +106,17 @@ xmlnode_set_attrib(node, attr, value)
const char *value
gchar_own *
-xmlnode_to_formatted_str(node, len)
+xmlnode_to_formatted_str(node)
Purple::XMLNode node
- int *len
+ CODE:
+ RETVAL = xmlnode_to_formatted_str(node, NULL);
+ OUTPUT:
+ RETVAL
gchar_own *
-xmlnode_to_str(node, len)
+xmlnode_to_str(node)
Purple::XMLNode node
- int *len
+ CODE:
+ RETVAL = xmlnode_to_str(node, NULL);
+ OUTPUT:
+ RETVAL
diff --git a/libpurple/protocols/bonjour/bonjour_ft.c b/libpurple/protocols/bonjour/bonjour_ft.c
index 44eab1a8d0..6fd68fce7c 100644
--- a/libpurple/protocols/bonjour/bonjour_ft.c
+++ b/libpurple/protocols/bonjour/bonjour_ft.c
@@ -17,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "internal.h"
#include "util.h"
@@ -450,9 +450,11 @@ xep_si_parse(PurpleConnection *pc, xmlnode *packet, PurpleBuddy *pb)
/* TODO: Make sure that it is advertising a bytestreams transfer */
- bonjour_xfer_receive(pc, id, sid, name, filesize, filename, XEP_BYTESTREAMS);
+ if (filename) {
+ bonjour_xfer_receive(pc, id, sid, name, filesize, filename, XEP_BYTESTREAMS);
- parsed_receive = TRUE;
+ parsed_receive = TRUE;
+ }
}
if (!parsed_receive) {
diff --git a/libpurple/protocols/bonjour/bonjour_ft.h b/libpurple/protocols/bonjour/bonjour_ft.h
index 94db38a1c8..bb1ed4699d 100644
--- a/libpurple/protocols/bonjour/bonjour_ft.h
+++ b/libpurple/protocols/bonjour/bonjour_ft.h
@@ -17,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _BONJOUR_FT_H_
#define _BONJOUR_FT_H_
diff --git a/libpurple/protocols/irc/msgs.c b/libpurple/protocols/irc/msgs.c
index 2bfd0dc651..1075c52887 100644
--- a/libpurple/protocols/irc/msgs.c
+++ b/libpurple/protocols/irc/msgs.c
@@ -445,9 +445,13 @@ void irc_msg_topic(struct irc_conn *irc, const char *name, const char *from, cha
PurpleConversation *convo;
if (!strcmp(name, "topic")) {
+ if (!args[0] || !args[1])
+ return;
chan = args[0];
topic = irc_mirc2txt (args[1]);
} else {
+ if (!args[0] || !args[1] || !args[2])
+ return;
chan = args[1];
topic = irc_mirc2txt (args[2]);
}
diff --git a/libpurple/protocols/irc/parse.c b/libpurple/protocols/irc/parse.c
index 1b3d9dae10..e7d200f0b4 100644
--- a/libpurple/protocols/irc/parse.c
+++ b/libpurple/protocols/irc/parse.c
@@ -361,7 +361,12 @@ char *irc_mirc2html(const char *string)
char fg[3] = "\0\0", bg[3] = "\0\0";
int fgnum, bgnum;
int font = 0, bold = 0, underline = 0, italic = 0;
- GString *decoded = g_string_sized_new(strlen(string));
+ GString *decoded;
+
+ if (string == NULL)
+ return NULL;
+
+ decoded = g_string_sized_new(strlen(string));
cur = string;
do {
@@ -461,9 +466,14 @@ char *irc_mirc2html(const char *string)
char *irc_mirc2txt (const char *string)
{
- char *result = g_strdup (string);
+ char *result;
int i, j;
+ if (string == NULL)
+ return NULL;
+
+ result = g_strdup (string);
+
for (i = 0, j = 0; result[i]; i++) {
switch (result[i]) {
case '\002':
diff --git a/libpurple/protocols/jabber/adhoccommands.c b/libpurple/protocols/jabber/adhoccommands.c
index 8c84d0104c..c15a45335b 100644
--- a/libpurple/protocols/jabber/adhoccommands.c
+++ b/libpurple/protocols/jabber/adhoccommands.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/adhoccommands.h b/libpurple/protocols/jabber/adhoccommands.h
index 407467466c..67958c09bb 100644
--- a/libpurple/protocols/jabber/adhoccommands.h
+++ b/libpurple/protocols/jabber/adhoccommands.h
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/auth.c b/libpurple/protocols/jabber/auth.c
index 78078c5bb7..1e57a7f635 100644
--- a/libpurple/protocols/jabber/auth.c
+++ b/libpurple/protocols/jabber/auth.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -573,6 +575,7 @@ static void auth_old_result_cb(JabberStream *js, const char *from,
xmlnode *packet, gpointer data)
{
if (type == JABBER_IQ_RESULT) {
+ jabber_stream_set_state(js, JABBER_STREAM_POST_AUTH);
jabber_disco_items_server(js);
} else {
PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
@@ -1070,7 +1073,12 @@ void jabber_auth_handle_success(JabberStream *js, xmlnode *packet)
}
#endif
- jabber_stream_set_state(js, JABBER_STREAM_REINITIALIZING);
+ /*
+ * The stream will be reinitialized later in jabber_recv_cb_ssl() or
+ * jabber_bosh_connection_send.
+ */
+ js->reinit = TRUE;
+ jabber_stream_set_state(js, JABBER_STREAM_POST_AUTH);
}
void jabber_auth_handle_failure(JabberStream *js, xmlnode *packet)
diff --git a/libpurple/protocols/jabber/auth.h b/libpurple/protocols/jabber/auth.h
index f89133f380..647fdfe158 100644
--- a/libpurple/protocols/jabber/auth.h
+++ b/libpurple/protocols/jabber/auth.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/bosh.c b/libpurple/protocols/jabber/bosh.c
index d3ad1e7b0d..f7438ad99c 100644
--- a/libpurple/protocols/jabber/bosh.c
+++ b/libpurple/protocols/jabber/bosh.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2008, Tobias Markmann <tmarkmann@googlemail.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -68,7 +70,6 @@ struct _PurpleBOSHConnection {
gboolean pipelining;
gboolean ssl;
- gboolean needs_restart;
enum {
BOSH_CONN_OFFLINE,
@@ -195,7 +196,6 @@ jabber_bosh_connection_init(JabberStream *js, const char *url)
conn->path = g_strdup_printf("/%s", path);
g_free(path);
conn->pipelining = TRUE;
- conn->needs_restart = FALSE;
if ((user && user[0] != '\0') || (passwd && passwd[0] != '\0')) {
purple_debug_info("jabber", "Ignoring unexpected username and password "
@@ -375,10 +375,10 @@ jabber_bosh_connection_send(PurpleBOSHConnection *conn,
conn->sid,
conn->js->user->domain);
- if (conn->needs_restart) {
+ if (conn->js->reinit) {
packet = g_string_append(packet, " xmpp:restart='true'/>");
/* TODO: Do we need to wait for a response? */
- conn->needs_restart = FALSE;
+ conn->js->reinit = FALSE;
} else {
gsize read_amt;
if (type == PACKET_TERMINATE)
@@ -404,12 +404,6 @@ void jabber_bosh_connection_close(PurpleBOSHConnection *conn)
jabber_bosh_connection_send(conn, PACKET_TERMINATE, NULL);
}
-static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn)
-{
- conn->needs_restart = TRUE;
- jabber_bosh_connection_send(conn, PACKET_NORMAL, NULL);
-}
-
static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node) {
const char *type;
@@ -488,35 +482,8 @@ static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode
}
}
-static void auth_response_cb(PurpleBOSHConnection *conn, xmlnode *node) {
- xmlnode *child;
-
- g_return_if_fail(node != NULL);
- if (jabber_bosh_connection_error_check(conn, node))
- return;
-
- child = node->child;
- while(child != NULL && child->type != XMLNODE_TYPE_TAG) {
- child = child->next;
- }
-
- /* We're only expecting one XML node here, so only process the first one */
- if (child != NULL && child->type == XMLNODE_TYPE_TAG) {
- JabberStream *js = conn->js;
- if (!strcmp(child->name, "success")) {
- jabber_bosh_connection_stream_restart(conn);
- jabber_process_packet(js, &child);
- conn->receive_cb = jabber_bosh_connection_received;
- } else {
- js->state = JABBER_STREAM_AUTHENTICATING;
- jabber_process_packet(js, &child);
- }
- } else {
- purple_debug_warning("jabber", "Received unexepcted empty BOSH packet.\n");
- }
-}
-
static void boot_response_cb(PurpleBOSHConnection *conn, xmlnode *node) {
+ JabberStream *js = conn->js;
const char *sid, *version;
const char *inactivity, *requests;
xmlnode *packet;
@@ -534,7 +501,7 @@ static void boot_response_cb(PurpleBOSHConnection *conn, xmlnode *node) {
if (sid) {
conn->sid = g_strdup(sid);
} else {
- purple_connection_error_reason(conn->js->gc,
+ purple_connection_error_reason(js->gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
_("No session ID given"));
return;
@@ -551,7 +518,7 @@ static void boot_response_cb(PurpleBOSHConnection *conn, xmlnode *node) {
minor = atoi(dot + 1);
if (major != 1 || minor < 6) {
- purple_connection_error_reason(conn->js->gc,
+ purple_connection_error_reason(js->gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
_("Unsupported version of BOSH protocol"));
return;
@@ -581,11 +548,13 @@ static void boot_response_cb(PurpleBOSHConnection *conn, xmlnode *node) {
if (requests)
conn->max_requests = atoi(requests);
+ jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING);
+
/* FIXME: Depending on receiving features might break with some hosts */
packet = xmlnode_get_child(node, "features");
conn->state = BOSH_CONN_ONLINE;
- conn->receive_cb = auth_response_cb;
- jabber_stream_features_parse(conn->js, packet);
+ conn->receive_cb = jabber_bosh_connection_received;
+ jabber_stream_features_parse(js, packet);
}
static void jabber_bosh_connection_boot(PurpleBOSHConnection *conn) {
@@ -661,8 +630,8 @@ connection_common_established_cb(PurpleHTTPConnection *conn)
conn->headers_done = FALSE;
conn->handled_len = conn->body_len = 0;
- if (conn->bosh->needs_restart)
- jabber_bosh_connection_stream_restart(conn->bosh);
+ if (conn->bosh->js->reinit)
+ jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL);
else if (conn->bosh->state == BOSH_CONN_ONLINE) {
purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n");
if (conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0) {
diff --git a/libpurple/protocols/jabber/bosh.h b/libpurple/protocols/jabber/bosh.h
index 29e0f23715..1f1d2e7d63 100644
--- a/libpurple/protocols/jabber/bosh.h
+++ b/libpurple/protocols/jabber/bosh.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2008, Tobias Markmann <tmarkmann@googlemail.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/buddy.c b/libpurple/protocols/jabber/buddy.c
index 38abdbf232..f2a8853eb0 100644
--- a/libpurple/protocols/jabber/buddy.c
+++ b/libpurple/protocols/jabber/buddy.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -749,7 +751,9 @@ add_jbr_info(JabberBuddyInfo *jbi, const char *resource,
const char *status_name = jabber_buddy_state_get_name(jbr->state);
if (jbr->status) {
- purdy = purple_strdup_withhtml(jbr->status);
+ tmp = purple_markup_escape_text(jbr->status, -1);
+ purdy = purple_strdup_withhtml(tmp);
+ g_free(tmp);
if (purple_strequal(status_name, purdy))
status_name = NULL;
@@ -908,12 +912,14 @@ static void jabber_vcard_save_mine(JabberStream *js, const char *from,
(binval = xmlnode_get_child(photo, "BINVAL"))) {
gsize size;
char *bintext = xmlnode_get_data(binval);
- guchar *data = purple_base64_decode(bintext, &size);
- g_free(bintext);
+ if (bintext) {
+ guchar *data = purple_base64_decode(bintext, &size);
+ g_free(bintext);
- if (data) {
- vcard_hash = jabber_calculate_data_sha1sum(data, size);
- g_free(data);
+ if (data) {
+ vcard_hash = jabber_calculate_data_sha1sum(data, size);
+ g_free(data);
+ }
}
}
@@ -1675,23 +1681,44 @@ static void jabber_buddy_make_visible(PurpleBlistNode *node, gpointer data)
jabber_buddy_set_invisibility(js, purple_buddy_get_name(buddy), FALSE);
}
-static void jabber_buddy_cancel_presence_notification(PurpleBlistNode *node,
- gpointer data)
+static void cancel_presence_notification(gpointer data)
{
PurpleBuddy *buddy;
PurpleConnection *gc;
JabberStream *js;
- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
- buddy = (PurpleBuddy *) node;
+ buddy = data;
gc = purple_account_get_connection(purple_buddy_get_account(buddy));
js = purple_connection_get_protocol_data(gc);
- /* I wonder if we should prompt the user before doing this */
jabber_presence_subscription_set(js, purple_buddy_get_name(buddy), "unsubscribed");
}
+static void
+jabber_buddy_cancel_presence_notification(PurpleBlistNode *node,
+ gpointer data)
+{
+ PurpleBuddy *buddy;
+ PurpleAccount *account;
+ PurpleConnection *gc;
+ const gchar *name;
+ char *msg;
+
+ g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+ buddy = (PurpleBuddy *) node;
+ name = purple_buddy_get_name(buddy);
+ account = purple_buddy_get_account(buddy);
+ gc = purple_account_get_connection(account);
+
+ msg = g_strdup_printf(_("%s will no longer be able to see your status "
+ "updates. Do you want to continue?"), name);
+ purple_request_yes_no(gc, NULL, _("Cancel Presence Notification"),
+ msg, 0 /* Yes */, account, name, NULL, buddy,
+ cancel_presence_notification, NULL /* Do nothing */);
+ g_free(msg);
+}
+
static void jabber_buddy_rerequest_auth(PurpleBlistNode *node, gpointer data)
{
PurpleBuddy *buddy;
diff --git a/libpurple/protocols/jabber/buddy.h b/libpurple/protocols/jabber/buddy.h
index 09a5c21c17..ebe033c637 100644
--- a/libpurple/protocols/jabber/buddy.h
+++ b/libpurple/protocols/jabber/buddy.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/caps.c b/libpurple/protocols/jabber/caps.c
index 87090ff1c8..c05a1436b1 100644
--- a/libpurple/protocols/jabber/caps.c
+++ b/libpurple/protocols/jabber/caps.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
@@ -468,8 +470,10 @@ jabber_caps_client_iqcb(JabberStream *js, const char *from, JabberIqType type,
}
if (!hash || strcmp(hash, userdata->ver)) {
- purple_debug_warning("jabber", "Could not validate caps info from %s\n",
- xmlnode_get_attrib(packet, "from"));
+ purple_debug_warning("jabber", "Could not validate caps info from "
+ "%s. Expected %s, got %s\n",
+ xmlnode_get_attrib(packet, "from"),
+ userdata->ver, hash ? hash : "(null)");
userdata->cb(NULL, NULL, userdata->cb_data);
jabber_caps_client_info_destroy(info);
@@ -597,8 +601,8 @@ void jabber_caps_get_info(JabberStream *js, const char *who, const char *node,
jabber_caps_cbplususerdata *userdata;
if (exts && hash) {
- purple_debug_info("jabber", "Ignoring exts in new-style caps from %s\n",
- who);
+ purple_debug_misc("jabber", "Ignoring exts in new-style caps from %s\n",
+ who);
g_strfreev(exts);
exts = NULL;
}
diff --git a/libpurple/protocols/jabber/caps.h b/libpurple/protocols/jabber/caps.h
index 46a31ac625..46a6dd770e 100644
--- a/libpurple/protocols/jabber/caps.h
+++ b/libpurple/protocols/jabber/caps.h
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/chat.c b/libpurple/protocols/jabber/chat.c
index 1fbcd0302f..b1db544f36 100644
--- a/libpurple/protocols/jabber/chat.c
+++ b/libpurple/protocols/jabber/chat.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/chat.h b/libpurple/protocols/jabber/chat.h
index 26a12a37c6..466bafb0c5 100644
--- a/libpurple/protocols/jabber/chat.h
+++ b/libpurple/protocols/jabber/chat.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/data.c b/libpurple/protocols/jabber/data.c
index 37619650bf..7d78cf8982 100644
--- a/libpurple/protocols/jabber/data.c
+++ b/libpurple/protocols/jabber/data.c
@@ -1,4 +1,8 @@
/*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
@@ -11,7 +15,7 @@
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <stdlib.h>
@@ -52,32 +56,45 @@ jabber_data_create_from_data(gconstpointer rawdata, gsize size, const char *type
JabberData *
jabber_data_create_from_xml(xmlnode *tag)
{
- JabberData *data = g_new0(JabberData, 1);
- gsize size;
- gpointer raw_data = NULL;
-
- if (data == NULL) {
- purple_debug_error("jabber", "Could not allocate data object\n");
- g_free(data);
- return NULL;
- }
+ JabberData *data;
+ gchar *raw_data = NULL;
+ const gchar *cid, *type;
/* check if this is a "data" tag */
if (strcmp(tag->name, "data") != 0) {
- purple_debug_error("jabber", "Invalid data element");
- g_free(data);
+ purple_debug_error("jabber", "Invalid data element\n");
return NULL;
}
- data->cid = g_strdup(xmlnode_get_attrib(tag, "cid"));
- data->type = g_strdup(xmlnode_get_attrib(tag, "type"));
+ cid = xmlnode_get_attrib(tag, "cid");
+ type = xmlnode_get_attrib(tag, "type");
+
+ if (!cid || !type) {
+ purple_debug_error("jabber", "cid or type missing\n");
+ return NULL;
+ }
raw_data = xmlnode_get_data(tag);
- data->data = purple_base64_decode(raw_data, &size);
- data->size = size;
+ if (raw_data == NULL || *raw_data == '\0') {
+ purple_debug_error("jabber", "data element was empty");
+ g_free(raw_data);
+ return NULL;
+ }
+
+ data = g_new0(JabberData, 1);
+ data->data = purple_base64_decode(raw_data, &data->size);
g_free(raw_data);
+ if (data->data == NULL) {
+ purple_debug_error("jabber", "Malformed base64 data\n");
+ g_free(data);
+ return NULL;
+ }
+
+ data->cid = g_strdup(cid);
+ data->type = g_strdup(type);
+
return data;
}
diff --git a/libpurple/protocols/jabber/data.h b/libpurple/protocols/jabber/data.h
index 764ed062a3..5f02731f6a 100644
--- a/libpurple/protocols/jabber/data.h
+++ b/libpurple/protocols/jabber/data.h
@@ -1,4 +1,8 @@
/*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
@@ -11,7 +15,7 @@
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#ifndef PURPLE_JABBER_DATA_H
diff --git a/libpurple/protocols/jabber/disco.c b/libpurple/protocols/jabber/disco.c
index 39ba131f77..42c3425563 100644
--- a/libpurple/protocols/jabber/disco.c
+++ b/libpurple/protocols/jabber/disco.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Service Discovery
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/disco.h b/libpurple/protocols/jabber/disco.h
index 7f76985420..588c62fd8b 100644
--- a/libpurple/protocols/jabber/disco.h
+++ b/libpurple/protocols/jabber/disco.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/google.c b/libpurple/protocols/jabber/google.c
index 3fdd92e9d3..5619881289 100644
--- a/libpurple/protocols/jabber/google.c
+++ b/libpurple/protocols/jabber/google.c
@@ -91,20 +91,6 @@ google_session_create_xmlnode(GoogleSession *session, const char *type)
}
static void
-google_session_send_terminate(GoogleSession *session)
-{
- xmlnode *sess;
- JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
-
- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
- sess = google_session_create_xmlnode(session, "terminate");
- xmlnode_insert_child(iq->node, sess);
-
- jabber_iq_send(iq);
- google_session_destroy(session);
-}
-
-static void
google_session_send_candidates(PurpleMedia *media, gchar *session_id,
gchar *participant, GoogleSession *session)
{
@@ -310,6 +296,9 @@ google_session_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
gchar *sid, gchar *name, gboolean local,
GoogleSession *session)
{
+ if (sid != NULL || name != NULL)
+ return;
+
if (type == PURPLE_MEDIA_INFO_HANGUP) {
xmlnode *sess;
JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
@@ -328,6 +317,8 @@ google_session_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
xmlnode_insert_child(iq->node, sess);
jabber_iq_send(iq);
+ } else if (type == PURPLE_MEDIA_INFO_ACCEPT && local == TRUE) {
+ google_session_ready(session);
}
}
@@ -398,6 +389,16 @@ jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSe
purple_media_set_prpl_data(session->media, session);
+ g_signal_connect_swapped(G_OBJECT(session->media),
+ "candidates-prepared",
+ G_CALLBACK(google_session_ready), session);
+ g_signal_connect_swapped(G_OBJECT(session->media), "codecs-changed",
+ G_CALLBACK(google_session_ready), session);
+ g_signal_connect(G_OBJECT(session->media), "state-changed",
+ G_CALLBACK(google_session_state_changed_cb), session);
+ g_signal_connect(G_OBJECT(session->media), "stream-info",
+ G_CALLBACK(google_session_stream_info_cb), session);
+
params = jabber_google_session_get_params(js, &num_params);
if (purple_media_add_stream(session->media, "google-voice",
@@ -408,23 +409,11 @@ jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSe
session->remote_jid, PURPLE_MEDIA_VIDEO,
TRUE, "nice", num_params, params) == FALSE)) {
purple_media_error(session->media, "Error adding stream.");
- purple_media_stream_info(session->media,
- PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, TRUE);
- google_session_destroy(session);
+ purple_media_end(session->media, NULL, NULL);
g_free(params);
return FALSE;
}
- g_signal_connect_swapped(G_OBJECT(session->media),
- "candidates-prepared",
- G_CALLBACK(google_session_ready), session);
- g_signal_connect_swapped(G_OBJECT(session->media), "codecs-changed",
- G_CALLBACK(google_session_ready), session);
- g_signal_connect(G_OBJECT(session->media), "state-changed",
- G_CALLBACK(google_session_state_changed_cb), session);
- g_signal_connect(G_OBJECT(session->media), "stream-info",
- G_CALLBACK(google_session_stream_info_cb), session);
-
g_free(params);
return (session->media != NULL) ? TRUE : FALSE;
@@ -466,6 +455,16 @@ google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode
purple_media_set_prpl_data(session->media, session);
+ g_signal_connect_swapped(G_OBJECT(session->media),
+ "candidates-prepared",
+ G_CALLBACK(google_session_ready), session);
+ g_signal_connect_swapped(G_OBJECT(session->media), "codecs-changed",
+ G_CALLBACK(google_session_ready), session);
+ g_signal_connect(G_OBJECT(session->media), "state-changed",
+ G_CALLBACK(google_session_state_changed_cb), session);
+ g_signal_connect(G_OBJECT(session->media), "stream-info",
+ G_CALLBACK(google_session_stream_info_cb), session);
+
params = jabber_google_session_get_params(js, &num_params);
if (purple_media_add_stream(session->media, "google-voice",
@@ -477,8 +476,7 @@ google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode
FALSE, "nice", num_params, params) == FALSE)) {
purple_media_error(session->media, "Error adding stream.");
purple_media_stream_info(session->media,
- PURPLE_MEDIA_INFO_HANGUP, NULL, NULL, TRUE);
- google_session_send_terminate(session);
+ PURPLE_MEDIA_INFO_REJECT, NULL, NULL, TRUE);
g_free(params);
return FALSE;
}
@@ -535,18 +533,6 @@ google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode
purple_media_codec_list_free(codecs);
purple_media_codec_list_free(video_codecs);
- g_signal_connect_swapped(G_OBJECT(session->media), "accepted",
- G_CALLBACK(google_session_ready), session);
- g_signal_connect_swapped(G_OBJECT(session->media),
- "candidates-prepared",
- G_CALLBACK(google_session_ready), session);
- g_signal_connect_swapped(G_OBJECT(session->media), "codecs-changed",
- G_CALLBACK(google_session_ready), session);
- g_signal_connect(G_OBJECT(session->media), "state-changed",
- G_CALLBACK(google_session_state_changed_cb), session);
- g_signal_connect(G_OBJECT(session->media), "stream-info",
- G_CALLBACK(google_session_stream_info_cb), session);
-
result = jabber_iq_new(js, JABBER_IQ_RESULT);
jabber_iq_set_id(result, iq_id);
xmlnode_set_attrib(result->node, "to", session->remote_jid);
@@ -778,8 +764,7 @@ jabber_google_session_parse(JabberStream *js, const char *from,
session->js = js;
session->remote_jid = g_strdup(session->id.initiator);
- if (!google_session_handle_initiate(js, session, session_node, iq_id))
- google_session_destroy(session);
+ google_session_handle_initiate(js, session, session_node, iq_id);
}
#endif /* USE_VV */
@@ -1316,6 +1301,7 @@ jabber_google_stun_lookup_cb(GSList *hosts, gpointer data,
purple_debug_error("jabber", "Google STUN lookup failed: %s\n",
error_message);
g_slist_free(hosts);
+ js->stun_query = NULL;
return;
}
@@ -1334,18 +1320,16 @@ jabber_google_stun_lookup_cb(GSList *hosts, gpointer data,
port = ntohs(((struct sockaddr_in *) addr)->sin_port);
}
- if (js) {
- if (js->stun_ip) {
- g_free(js->stun_ip);
- }
- js->stun_ip = g_strdup(dst);
- purple_debug_info("jabber", "set Google STUN IP address: %s\n", dst);
- js->stun_port = port;
- purple_debug_info("jabber", "set Google STUN port: %d\n", port);
- purple_debug_info("jabber", "set Google STUN port: %d\n", port);
- /* unmark ongoing query */
- js->stun_query = NULL;
- }
+ if (js->stun_ip)
+ g_free(js->stun_ip);
+ js->stun_ip = g_strdup(dst);
+ js->stun_port = port;
+
+ purple_debug_info("jabber", "set Google STUN IP/port address: "
+ "%s:%d\n", dst, port);
+
+ /* unmark ongoing query */
+ js->stun_query = NULL;
}
while (hosts != NULL) {
diff --git a/libpurple/protocols/jabber/ibb.c b/libpurple/protocols/jabber/ibb.c
index 416f6f7f53..0b0683266a 100644
--- a/libpurple/protocols/jabber/ibb.c
+++ b/libpurple/protocols/jabber/ibb.c
@@ -1,4 +1,8 @@
/*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
@@ -11,7 +15,7 @@
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include "internal.h"
diff --git a/libpurple/protocols/jabber/ibb.h b/libpurple/protocols/jabber/ibb.h
index 54da63a20f..a1223b05b2 100644
--- a/libpurple/protocols/jabber/ibb.h
+++ b/libpurple/protocols/jabber/ibb.h
@@ -1,4 +1,8 @@
/*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
@@ -11,7 +15,7 @@
*
* 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
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#ifndef PURPLE_JABBER_IBB_H_
diff --git a/libpurple/protocols/jabber/iq.c b/libpurple/protocols/jabber/iq.c
index 2fd2af685c..299aa3ce8a 100644
--- a/libpurple/protocols/jabber/iq.c
+++ b/libpurple/protocols/jabber/iq.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/iq.h b/libpurple/protocols/jabber/iq.h
index 5d506841dc..aa4123f072 100644
--- a/libpurple/protocols/jabber/iq.h
+++ b/libpurple/protocols/jabber/iq.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
index 824f48ecef..9c746ac908 100644
--- a/libpurple/protocols/jabber/jabber.c
+++ b/libpurple/protocols/jabber/jabber.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -1603,13 +1605,10 @@ void jabber_stream_set_state(JabberStream *js, JabberStreamState state)
jabber_auth_start_old(js);
}
break;
- case JABBER_STREAM_REINITIALIZING:
+ case JABBER_STREAM_POST_AUTH:
purple_connection_update_progress(js->gc, _("Re-initializing Stream"),
(js->gsc ? 8 : 4), JABBER_CONNECT_STEPS);
- /* The stream will be reinitialized later, in jabber_recv_cb_ssl() */
- js->reinit = TRUE;
-
break;
case JABBER_STREAM_CONNECTED:
/* Send initial presence */
@@ -3302,7 +3301,7 @@ void jabber_register_commands(void)
PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
jabber_cmd_chat_role,
- _("role &lt;moderator|participant|visitor|none&gt; [nick1] [nick2] ...: Get the users with an role or set users' role with the room."),
+ _("role &lt;moderator|participant|visitor|none&gt; [nick1] [nick2] ...: Get the users with a role or set users' role with the room."),
NULL);
jabber_cmds = g_slist_prepend(jabber_cmds, GUINT_TO_POINTER(id));
diff --git a/libpurple/protocols/jabber/jabber.h b/libpurple/protocols/jabber/jabber.h
index f2c1e9c5e1..27a7139bff 100644
--- a/libpurple/protocols/jabber/jabber.h
+++ b/libpurple/protocols/jabber/jabber.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -85,7 +87,7 @@ typedef enum {
JABBER_STREAM_INITIALIZING,
JABBER_STREAM_INITIALIZING_ENCRYPTION,
JABBER_STREAM_AUTHENTICATING,
- JABBER_STREAM_REINITIALIZING,
+ JABBER_STREAM_POST_AUTH,
JABBER_STREAM_CONNECTED
} JabberStreamState;
diff --git a/libpurple/protocols/jabber/jingle/content.c b/libpurple/protocols/jabber/jingle/content.c
index e3d06c9662..f57fce6255 100644
--- a/libpurple/protocols/jabber/jingle/content.c
+++ b/libpurple/protocols/jabber/jingle/content.c
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/content.h b/libpurple/protocols/jabber/jingle/content.h
index bb23be01f1..91dc4e86ca 100644
--- a/libpurple/protocols/jabber/jingle/content.h
+++ b/libpurple/protocols/jabber/jingle/content.h
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/iceudp.c b/libpurple/protocols/jabber/jingle/iceudp.c
index 966fff28fe..210dddf970 100644
--- a/libpurple/protocols/jabber/jingle/iceudp.c
+++ b/libpurple/protocols/jabber/jingle/iceudp.c
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/iceudp.h b/libpurple/protocols/jabber/jingle/iceudp.h
index bf3b961f37..95e81be674 100644
--- a/libpurple/protocols/jabber/jingle/iceudp.h
+++ b/libpurple/protocols/jabber/jingle/iceudp.h
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/jingle.c b/libpurple/protocols/jabber/jingle/jingle.c
index 12b51737bf..99c1e6b08a 100644
--- a/libpurple/protocols/jabber/jingle/jingle.c
+++ b/libpurple/protocols/jabber/jingle/jingle.c
@@ -3,6 +3,10 @@
*
* purple - Jabber Protocol Plugin
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/jingle.h b/libpurple/protocols/jabber/jingle/jingle.h
index cb3d3e9ad8..7ccdc55fe2 100644
--- a/libpurple/protocols/jabber/jingle/jingle.h
+++ b/libpurple/protocols/jabber/jingle/jingle.h
@@ -1,6 +1,10 @@
/*
* @file jingle.h
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/rawudp.c b/libpurple/protocols/jabber/jingle/rawudp.c
index 8948aa58f3..8b431ff81d 100644
--- a/libpurple/protocols/jabber/jingle/rawudp.c
+++ b/libpurple/protocols/jabber/jingle/rawudp.c
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/rawudp.h b/libpurple/protocols/jabber/jingle/rawudp.h
index 99135cc384..785ba3ddf6 100644
--- a/libpurple/protocols/jabber/jingle/rawudp.h
+++ b/libpurple/protocols/jabber/jingle/rawudp.h
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/rtp.c b/libpurple/protocols/jabber/jingle/rtp.c
index 76960f0a52..36aa9237f0 100644
--- a/libpurple/protocols/jabber/jingle/rtp.c
+++ b/libpurple/protocols/jabber/jingle/rtp.c
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
@@ -607,8 +611,11 @@ jingle_rtp_init_media(JingleContent *content)
is_creator = !jingle_session_is_initiator(session);
g_free(creator);
- purple_media_add_stream(media, name, remote_jid,
- type, is_creator, transmitter, num_params, params);
+ if(!purple_media_add_stream(media, name, remote_jid,
+ type, is_creator, transmitter, num_params, params)) {
+ purple_media_end(media, NULL, NULL);
+ return FALSE;
+ }
g_free(name);
g_free(media_type);
diff --git a/libpurple/protocols/jabber/jingle/rtp.h b/libpurple/protocols/jabber/jingle/rtp.h
index db21706f45..a372711a3f 100644
--- a/libpurple/protocols/jabber/jingle/rtp.h
+++ b/libpurple/protocols/jabber/jingle/rtp.h
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/session.c b/libpurple/protocols/jabber/jingle/session.c
index 2a262e9d7d..ef79258f28 100644
--- a/libpurple/protocols/jabber/jingle/session.c
+++ b/libpurple/protocols/jabber/jingle/session.c
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/session.h b/libpurple/protocols/jabber/jingle/session.h
index 15c90fda98..51e5a71e95 100644
--- a/libpurple/protocols/jabber/jingle/session.h
+++ b/libpurple/protocols/jabber/jingle/session.h
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/transport.c b/libpurple/protocols/jabber/jingle/transport.c
index c3105f43eb..1a465bbb2a 100644
--- a/libpurple/protocols/jabber/jingle/transport.c
+++ b/libpurple/protocols/jabber/jingle/transport.c
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jingle/transport.h b/libpurple/protocols/jabber/jingle/transport.h
index 6b00d06a35..c2827d461b 100644
--- a/libpurple/protocols/jabber/jingle/transport.h
+++ b/libpurple/protocols/jabber/jingle/transport.h
@@ -3,6 +3,10 @@
*
* purple
*
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
* 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
diff --git a/libpurple/protocols/jabber/jutil.c b/libpurple/protocols/jabber/jutil.c
index 426755131a..82c9b78f77 100644
--- a/libpurple/protocols/jabber/jutil.c
+++ b/libpurple/protocols/jabber/jutil.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -151,10 +153,9 @@ jabber_idn_validate(const char *str, const char *at, const char *slash,
if (!jabber_resourceprep(idn_buffer, sizeof(idn_buffer))) {
jabber_id_free(jid);
jid = NULL;
- /* goto out; */
- }
-
- jid->resource = g_strdup(idn_buffer);
+ goto out;
+ } else
+ jid->resource = g_strdup(idn_buffer);
}
out:
@@ -275,8 +276,8 @@ gboolean jabber_resourceprep_validate(const char *str)
#endif /* USE_IDN */
}
-JabberID*
-jabber_id_new(const char *str)
+static JabberID*
+jabber_id_new_internal(const char *str, gboolean allow_terminating_slash)
{
const char *at = NULL;
const char *slash = NULL;
@@ -321,7 +322,7 @@ jabber_id_new(const char *str)
/* JIDs cannot start with / */
return NULL;
}
- if (c[1] == '\0') {
+ if (c[1] == '\0' && !allow_terminating_slash) {
/* JIDs cannot end with / */
return NULL;
}
@@ -384,14 +385,16 @@ jabber_id_new(const char *str)
jid->node = g_ascii_strdown(str, at - str);
if (slash) {
jid->domain = g_ascii_strdown(at + 1, slash - (at + 1));
- jid->resource = g_strdup(slash + 1);
+ if (*(slash + 1))
+ jid->resource = g_strdup(slash + 1);
} else {
jid->domain = g_ascii_strdown(at + 1, -1);
}
} else {
if (slash) {
jid->domain = g_ascii_strdown(str, slash - str);
- jid->resource = g_strdup(slash + 1);
+ if (*(slash + 1))
+ jid->resource = g_strdup(slash + 1);
} else {
jid->domain = g_ascii_strdown(str, -1);
}
@@ -419,14 +422,16 @@ jabber_id_new(const char *str)
node = g_utf8_casefold(str, at-str);
if(slash) {
domain = g_utf8_casefold(at+1, slash-(at+1));
- jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC);
+ if (*(slash + 1))
+ jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC);
} else {
domain = g_utf8_casefold(at+1, -1);
}
} else {
if(slash) {
domain = g_utf8_casefold(str, slash-str);
- jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC);
+ if (*(slash + 1))
+ jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC);
} else {
domain = g_utf8_casefold(str, -1);
}
@@ -483,21 +488,37 @@ char *jabber_get_resource(const char *in)
return out;
}
-char *jabber_get_bare_jid(const char *in)
+char *
+jabber_get_bare_jid(const char *in)
{
JabberID *jid = jabber_id_new(in);
char *out;
- if(!jid)
+ if (!jid)
return NULL;
-
- out = g_strdup_printf("%s%s%s", jid->node ? jid->node : "",
- jid->node ? "@" : "", jid->domain);
+ out = jabber_id_get_bare_jid(jid);
jabber_id_free(jid);
return out;
}
+char *
+jabber_id_get_bare_jid(const JabberID *jid)
+{
+ g_return_val_if_fail(jid != NULL, NULL);
+
+ return g_strconcat(jid->node ? jid->node : "",
+ jid->node ? "@" : "",
+ jid->domain,
+ NULL);
+}
+
+JabberID *
+jabber_id_new(const char *str)
+{
+ return jabber_id_new_internal(str, FALSE);
+}
+
const char *jabber_normalize(const PurpleAccount *account, const char *in)
{
PurpleConnection *gc = account ? account->gc : NULL;
@@ -505,8 +526,7 @@ const char *jabber_normalize(const PurpleAccount *account, const char *in)
static char buf[3072]; /* maximum legal length of a jabber jid */
JabberID *jid;
- jid = jabber_id_new(in);
-
+ jid = jabber_id_new_internal(in, TRUE);
if(!jid)
return NULL;
diff --git a/libpurple/protocols/jabber/jutil.h b/libpurple/protocols/jabber/jutil.h
index e32c4bbff9..a9fcc57f0b 100644
--- a/libpurple/protocols/jabber/jutil.h
+++ b/libpurple/protocols/jabber/jutil.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -35,6 +37,7 @@ void jabber_id_free(JabberID *jid);
char *jabber_get_resource(const char *jid);
char *jabber_get_bare_jid(const char *jid);
+char *jabber_id_get_bare_jid(const JabberID *jid);
const char *jabber_normalize(const PurpleAccount *account, const char *in);
diff --git a/libpurple/protocols/jabber/message.c b/libpurple/protocols/jabber/message.c
index c11da76a23..3104b709f5 100644
--- a/libpurple/protocols/jabber/message.c
+++ b/libpurple/protocols/jabber/message.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -87,8 +89,12 @@ static void handle_chat(JabberMessage *jm)
}
if(!jm->xhtml && !jm->body) {
- if (jbr)
- jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
+ if (jbr) {
+ if (jm->chat_state != JM_STATE_NONE)
+ jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
+ else
+ jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED;
+ }
if(JM_STATE_COMPOSING == jm->chat_state) {
serv_got_typing(jm->js->gc, from, 0, PURPLE_TYPING);
@@ -487,7 +493,7 @@ jabber_message_get_data_cb(JabberStream *js, const char *from,
xmlnode *item_not_found = xmlnode_get_child(packet, "item-not-found");
/* did we get a data element as result? */
- if (data_element) {
+ if (data_element && type == JABBER_IQ_RESULT) {
JabberData *data = jabber_data_create_from_xml(data_element);
if (data) {
@@ -1219,7 +1225,7 @@ int jabber_message_send_chat(PurpleConnection *gc, int id, const char *msg, Purp
jm->id = jabber_get_next_id(jm->js);
tmp = purple_utf8_strip_unprintables(msg);
- purple_markup_html_to_xhtml(msg, &xhtml, &jm->body);
+ purple_markup_html_to_xhtml(tmp, &xhtml, &jm->body);
g_free(tmp);
tmp = jabber_message_smileyfy_xhtml(jm, xhtml);
if (tmp) {
diff --git a/libpurple/protocols/jabber/message.h b/libpurple/protocols/jabber/message.h
index 34669cab32..8fb1b43133 100644
--- a/libpurple/protocols/jabber/message.h
+++ b/libpurple/protocols/jabber/message.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/oob.c b/libpurple/protocols/jabber/oob.c
index 73b18fb030..468e2706f9 100644
--- a/libpurple/protocols/jabber/oob.c
+++ b/libpurple/protocols/jabber/oob.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -207,7 +209,10 @@ void jabber_oob_parse(JabberStream *js, const char *from, JabberIqType type,
url = xmlnode_get_data(urlnode);
jox = g_new0(JabberOOBXfer, 1);
- purple_url_parse(url, &jox->address, &jox->port, &jox->page, NULL, NULL);
+ if (!purple_url_parse(url, &jox->address, &jox->port, &jox->page, NULL, NULL)) {
+ g_free(url);
+ return;
+ }
g_free(url);
jox->js = js;
jox->headers = g_string_new("");
diff --git a/libpurple/protocols/jabber/oob.h b/libpurple/protocols/jabber/oob.h
index c1103e6b12..89724232da 100644
--- a/libpurple/protocols/jabber/oob.h
+++ b/libpurple/protocols/jabber/oob.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/parser.c b/libpurple/protocols/jabber/parser.c
index 3cc5e0e2c3..e2115c6412 100644
--- a/libpurple/protocols/jabber/parser.c
+++ b/libpurple/protocols/jabber/parser.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber XML parser stuff
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/parser.h b/libpurple/protocols/jabber/parser.h
index b08f0c950e..a99e29b26b 100644
--- a/libpurple/protocols/jabber/parser.h
+++ b/libpurple/protocols/jabber/parser.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/pep.c b/libpurple/protocols/jabber/pep.c
index bdc91815a2..b7013a344c 100644
--- a/libpurple/protocols/jabber/pep.c
+++ b/libpurple/protocols/jabber/pep.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/pep.h b/libpurple/protocols/jabber/pep.h
index 5be64754e9..30b5529ece 100644
--- a/libpurple/protocols/jabber/pep.h
+++ b/libpurple/protocols/jabber/pep.h
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/ping.c b/libpurple/protocols/jabber/ping.c
index 4fabbe575d..6fb7653ba1 100644
--- a/libpurple/protocols/jabber/ping.c
+++ b/libpurple/protocols/jabber/ping.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -16,7 +18,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/ping.h b/libpurple/protocols/jabber/ping.h
index f34a5a4be5..5420ea531c 100644
--- a/libpurple/protocols/jabber/ping.h
+++ b/libpurple/protocols/jabber/ping.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -17,7 +19,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#ifndef PURPLE_JABBER_PING_H_
#define PURPLE_JABBER_PING_H_
diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c
index 88e4a6cad5..bb88c1189e 100644
--- a/libpurple/protocols/jabber/presence.c
+++ b/libpurple/protocols/jabber/presence.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -469,10 +471,17 @@ jabber_presence_set_capabilities(JabberCapsClientInfo *info, GList *exts,
jbr->commands_fetched = TRUE;
}
+#if 0
+ /*
+ * Versions of libpurple before 2.6.0 didn't advertise this capability, so
+ * we can't yet use Entity Capabilities to determine whether or not the
+ * other client supports Entity Capabilities.
+ */
if (jabber_resource_has_capability(jbr, "http://jabber.org/protocol/chatstates"))
jbr->chat_states = JABBER_CHAT_STATES_SUPPORTED;
else
jbr->chat_states = JABBER_CHAT_STATES_UNSUPPORTED;
+#endif
out:
g_free(userdata->from);
diff --git a/libpurple/protocols/jabber/presence.h b/libpurple/protocols/jabber/presence.h
index 03872135bd..4bb7595668 100644
--- a/libpurple/protocols/jabber/presence.h
+++ b/libpurple/protocols/jabber/presence.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/roster.c b/libpurple/protocols/jabber/roster.c
index 625bc5ebff..e13df65ab0 100644
--- a/libpurple/protocols/jabber/roster.c
+++ b/libpurple/protocols/jabber/roster.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -24,6 +26,7 @@
#include "util.h"
#include "buddy.h"
+#include "chat.h"
#include "google.h"
#include "presence.h"
#include "roster.h"
@@ -334,6 +337,7 @@ void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
{
JabberStream *js = gc->proto_data;
char *who;
+ JabberID *jid;
JabberBuddy *jb;
JabberBuddyResource *jbr;
const char *name;
@@ -343,13 +347,39 @@ void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
return;
name = purple_buddy_get_name(buddy);
- if(!(who = jabber_get_bare_jid(name)))
+ jid = jabber_id_new(name);
+ if (jid == NULL) {
+ /* TODO: Remove the buddy from the list? */
return;
+ }
+
+ /* Adding a chat room or a chat buddy to the roster is *not* supported. */
+ if (jabber_chat_find(js, jid->node, jid->domain) != NULL) {
+ /*
+ * This is the same thing Bonjour does. If it causes problems, move
+ * it to an idle callback.
+ */
+ purple_debug_warning("jabber", "Cowardly refusing to add a MUC user "
+ "to your buddy list and removing the buddy. "
+ "Buddies can only be added by real (non-MUC) "
+ "JID\n");
+ purple_blist_remove_buddy(buddy);
+ jabber_id_free(jid);
+ return;
+ }
+
+ who = jabber_id_get_bare_jid(jid);
+ if (jid->resource != NULL) {
+ /*
+ * If the buddy name added contains a resource, strip that off and
+ * rename the buddy.
+ */
+ purple_blist_rename_buddy(buddy, who);
+ }
- jb = jabber_buddy_find(js, name, FALSE);
+ jb = jabber_buddy_find(js, who, FALSE);
- purple_debug_info("jabber", "jabber_roster_add_buddy(): Adding %s\n",
- name);
+ purple_debug_info("jabber", "jabber_roster_add_buddy(): Adding %s\n", who);
jabber_roster_update(js, who, NULL);
diff --git a/libpurple/protocols/jabber/roster.h b/libpurple/protocols/jabber/roster.h
index d84b806bd7..4bc4384e03 100644
--- a/libpurple/protocols/jabber/roster.h
+++ b/libpurple/protocols/jabber/roster.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/si.c b/libpurple/protocols/jabber/si.c
index fcd3eb911a..4ba7d1f262 100644
--- a/libpurple/protocols/jabber/si.c
+++ b/libpurple/protocols/jabber/si.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/si.h b/libpurple/protocols/jabber/si.h
index 8186d94554..95794799e0 100644
--- a/libpurple/protocols/jabber/si.h
+++ b/libpurple/protocols/jabber/si.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/useravatar.c b/libpurple/protocols/jabber/useravatar.c
index dabe2873bc..1f58264649 100644
--- a/libpurple/protocols/jabber/useravatar.c
+++ b/libpurple/protocols/jabber/useravatar.c
@@ -17,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/useravatar.h b/libpurple/protocols/jabber/useravatar.h
index 0ae77dfdfa..07e8658162 100644
--- a/libpurple/protocols/jabber/useravatar.h
+++ b/libpurple/protocols/jabber/useravatar.h
@@ -17,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/usermood.c b/libpurple/protocols/jabber/usermood.c
index 0caaa2fd83..997df5237e 100644
--- a/libpurple/protocols/jabber/usermood.c
+++ b/libpurple/protocols/jabber/usermood.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/usermood.h b/libpurple/protocols/jabber/usermood.h
index ebea275ba9..4e27b2bb39 100644
--- a/libpurple/protocols/jabber/usermood.h
+++ b/libpurple/protocols/jabber/usermood.h
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/usernick.c b/libpurple/protocols/jabber/usernick.c
index 7a6a5c0c5a..c622ff3c95 100644
--- a/libpurple/protocols/jabber/usernick.c
+++ b/libpurple/protocols/jabber/usernick.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/usernick.h b/libpurple/protocols/jabber/usernick.h
index f3f000041a..f2768a72e1 100644
--- a/libpurple/protocols/jabber/usernick.h
+++ b/libpurple/protocols/jabber/usernick.h
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/usertune.c b/libpurple/protocols/jabber/usertune.c
index 0c1996cc0e..03e485ef1b 100644
--- a/libpurple/protocols/jabber/usertune.c
+++ b/libpurple/protocols/jabber/usertune.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/usertune.h b/libpurple/protocols/jabber/usertune.h
index 8b72923c1b..c0a3095360 100644
--- a/libpurple/protocols/jabber/usertune.h
+++ b/libpurple/protocols/jabber/usertune.h
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2007, Andreas Monitzer <andy@monitzer.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
@@ -15,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*
*/
diff --git a/libpurple/protocols/jabber/xdata.c b/libpurple/protocols/jabber/xdata.c
index 3a1914fc32..aeda049af5 100644
--- a/libpurple/protocols/jabber/xdata.c
+++ b/libpurple/protocols/jabber/xdata.c
@@ -1,7 +1,9 @@
/*
* purple - Jabber Protocol Plugin
*
- * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/jabber/xdata.h b/libpurple/protocols/jabber/xdata.h
index c0cba5b931..c737fdeda3 100644
--- a/libpurple/protocols/jabber/xdata.h
+++ b/libpurple/protocols/jabber/xdata.h
@@ -3,7 +3,9 @@
*
* purple
*
- * Copyright (C) 2003 Nathan Walp <faceprint@faceprint.com>
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
*
* 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
diff --git a/libpurple/protocols/msn/Makefile.mingw b/libpurple/protocols/msn/Makefile.mingw
index fe75c1cb68..40d5ea9db8 100644
--- a/libpurple/protocols/msn/Makefile.mingw
+++ b/libpurple/protocols/msn/Makefile.mingw
@@ -41,7 +41,6 @@ C_SRC = cmdproc.c \
command.c \
contact.c\
dialog.c \
- directconn.c \
error.c \
group.c \
history.c \
diff --git a/libpurple/protocols/msn/cmdproc.h b/libpurple/protocols/msn/cmdproc.h
index 11a71eed99..509c8dfb06 100644
--- a/libpurple/protocols/msn/cmdproc.h
+++ b/libpurple/protocols/msn/cmdproc.h
@@ -71,6 +71,4 @@ void msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command);
void msn_cmdproc_process_payload(MsnCmdProc *cmdproc,
char *payload, int payload_len);
-void msn_cmdproc_disconnect(MsnCmdProc *cmdproc);
-
#endif /* _MSN_CMDPROC_H_ */
diff --git a/libpurple/protocols/msn/contact.c b/libpurple/protocols/msn/contact.c
index cf70e4947c..fc9e160832 100644
--- a/libpurple/protocols/msn/contact.c
+++ b/libpurple/protocols/msn/contact.c
@@ -21,7 +21,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "msn.h"
diff --git a/libpurple/protocols/msn/contact.h b/libpurple/protocols/msn/contact.h
index b44097c794..6697acb8f6 100644
--- a/libpurple/protocols/msn/contact.h
+++ b/libpurple/protocols/msn/contact.h
@@ -20,7 +20,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _MSN_CONTACT_H_
#define _MSN_CONTACT_H_
diff --git a/libpurple/protocols/msn/error.c b/libpurple/protocols/msn/error.c
index c2aac882f1..fd13bea29f 100644
--- a/libpurple/protocols/msn/error.c
+++ b/libpurple/protocols/msn/error.c
@@ -198,7 +198,7 @@ msn_error_get_text(unsigned int type, gboolean *debug)
break;
case 800:
- result = _("Friendly name changes too rapidly");
+ result = _("Friendly name is changing too rapidly");
break;
case 910:
diff --git a/libpurple/protocols/msn/msn.c b/libpurple/protocols/msn/msn.c
index 63c3f0a2e2..32495a8f2d 100644
--- a/libpurple/protocols/msn/msn.c
+++ b/libpurple/protocols/msn/msn.c
@@ -89,6 +89,7 @@ typedef struct
typedef struct
{
char *smile;
+ PurpleSmiley *ps;
MsnObject *obj;
} MsnEmoticon;
@@ -265,6 +266,7 @@ send_to_mobile(PurpleConnection *gc, const char *who, const char *entry)
MsnSession *session;
MsnCmdProc *cmdproc;
MsnPage *page;
+ MsnMessage *msg;
MsnUser *user;
char *payload = NULL;
const char *mobile_number = NULL;
@@ -295,6 +297,9 @@ send_to_mobile(PurpleConnection *gc, const char *who, const char *entry)
msn_transaction_set_payload(trans, payload, payload_len);
g_free(payload);
+ msg = msn_message_new_plain(entry);
+ msn_transaction_set_data(trans, msg);
+
msn_page_destroy(page);
msn_cmdproc_send_trans(cmdproc, trans);
@@ -1078,12 +1083,10 @@ msn_msg_emoticon_add(GString *current, MsnEmoticon *emoticon)
strobj = msn_object_to_string(obj);
if (current)
- g_string_append_printf(current, "\t%s\t%s",
- emoticon->smile, strobj);
+ g_string_append_printf(current, "\t%s\t%s", emoticon->smile, strobj);
else {
current = g_string_new("");
- g_string_printf(current,"%s\t%s",
- emoticon->smile, strobj);
+ g_string_printf(current, "%s\t%s", emoticon->smile, strobj);
}
g_free(strobj);
@@ -1141,6 +1144,7 @@ static GSList* msn_msg_grab_emoticons(const char *msg, const char *username)
emoticon = g_new0(MsnEmoticon, 1);
emoticon->smile = g_strdup(purple_smiley_get_shortcut(smiley));
+ emoticon->ps = smiley;
emoticon->obj = msn_object_new_from_image(img,
purple_imgstore_get_filename(img),
username, MSN_OBJECT_EMOTICON);
@@ -1163,7 +1167,7 @@ msn_send_im_message(MsnSession *session, MsnMessage *msg)
smileys = msn_msg_grab_emoticons(msg->body, username);
while (smileys) {
- smile = (MsnEmoticon*)smileys->data;
+ smile = (MsnEmoticon *)smileys->data;
emoticons = msn_msg_emoticon_add(emoticons, smile);
msn_emoticon_destroy(smile);
smileys = g_slist_delete_link(smileys, smileys);
@@ -1714,13 +1718,19 @@ msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFl
{
PurpleAccount *account;
MsnSession *session;
+ const char *username;
MsnSwitchBoard *swboard;
MsnMessage *msg;
char *msgformat;
char *msgtext;
+ size_t msglen;
+ MsnEmoticon *smile;
+ GSList *smileys;
+ GString *emoticons = NULL;
account = purple_connection_get_account(gc);
session = gc->proto_data;
+ username = purple_account_get_username(account);
swboard = msn_session_find_swboard_with_id(session, id);
if (swboard == NULL)
@@ -1732,8 +1742,9 @@ msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFl
swboard->flag |= MSN_SB_FLAG_IM;
msn_import_html(message, &msgformat, &msgtext);
+ msglen = strlen(msgtext);
- if (strlen(msgtext) + strlen(msgformat) + strlen(VERSION) > 1564)
+ if ((msglen == 0) || (msglen + strlen(msgformat) + strlen(VERSION) > 1564))
{
g_free(msgformat);
g_free(msgtext);
@@ -1743,6 +1754,29 @@ msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFl
msg = msn_message_new_plain(msgtext);
msn_message_set_attr(msg, "X-MMS-IM-Format", msgformat);
+
+ smileys = msn_msg_grab_emoticons(msg->body, username);
+ while (smileys) {
+ smile = (MsnEmoticon *)smileys->data;
+ emoticons = msn_msg_emoticon_add(emoticons, smile);
+ if (purple_conv_custom_smiley_add(swboard->conv, smile->smile,
+ "sha1", purple_smiley_get_checksum(smile->ps),
+ FALSE)) {
+ gconstpointer data;
+ size_t len;
+ data = purple_smiley_get_data(smile->ps, &len);
+ purple_conv_custom_smiley_write(swboard->conv, smile->smile, data, len);
+ purple_conv_custom_smiley_close(swboard->conv, smile->smile);
+ }
+ msn_emoticon_destroy(smile);
+ smileys = g_slist_delete_link(smileys, smileys);
+ }
+
+ if (emoticons) {
+ msn_send_emoticons(swboard, emoticons);
+ g_string_free(emoticons, TRUE);
+ }
+
msn_switchboard_send_msg(swboard, msg, FALSE);
msn_message_destroy(msg);
diff --git a/libpurple/protocols/msn/msn.h b/libpurple/protocols/msn/msn.h
index 185d7da576..b9369aee01 100644
--- a/libpurple/protocols/msn/msn.h
+++ b/libpurple/protocols/msn/msn.h
@@ -127,7 +127,7 @@ typedef enum
} MsnClientVerId;
#define MSN_CLIENT_ID_VERSION MSN_CLIENT_VER_7_0
-#define MSN_CLIENT_ID_CAPABILITIES (MSN_CLIENT_CAP_PACKET|MSN_CLIENT_CAP_INK_GIF|MSN_CLIENT_CAP_VOICEIM|MSN_CLIENT_CAP_WINKS)
+#define MSN_CLIENT_ID_CAPABILITIES (MSN_CLIENT_CAP_PACKET|MSN_CLIENT_CAP_INK_GIF|MSN_CLIENT_CAP_VOICEIM)
#define MSN_CLIENT_ID \
((MSN_CLIENT_ID_VERSION << 24) | \
diff --git a/libpurple/protocols/msn/notification.c b/libpurple/protocols/msn/notification.c
index d64d52f6a1..9aef684904 100644
--- a/libpurple/protocols/msn/notification.c
+++ b/libpurple/protocols/msn/notification.c
@@ -599,6 +599,8 @@ update_contact_network(MsnSession *session, const char *passport, MsnNetwork net
/* Decrement the count for unknown results so that we'll continue login.
Also, need to finish the login process here as well, because ADL OK
will not be called. */
+ if (purple_debug_is_verbose())
+ purple_debug_info("msn", "ADL/FQY count is %d\n", session->adl_fqy);
if (--session->adl_fqy == 0)
msn_session_finish_login(session);
return;
@@ -680,6 +682,9 @@ msn_notification_dump_contact(MsnSession *session)
/* ADL's are returned all-together */
session->adl_fqy++;
+ if (purple_debug_is_verbose())
+ purple_debug_info("msn", "Posting ADL, count is %d\n",
+ session->adl_fqy);
msn_notification_post_adl(session->notification->cmdproc,
payload, payload_len);
@@ -694,6 +699,9 @@ msn_notification_dump_contact(MsnSession *session)
} else {
/* FQY's are returned one-at-a-time */
session->adl_fqy++;
+ if (purple_debug_is_verbose())
+ purple_debug_info("msn", "Adding FQY address, count is %d\n",
+ session->adl_fqy);
msn_add_contact_xml(session, fqy_node, user->passport,
0, user->networkid);
@@ -718,6 +726,9 @@ msn_notification_dump_contact(MsnSession *session)
/* ADL's are returned all-together */
session->adl_fqy++;
+ if (purple_debug_is_verbose())
+ purple_debug_info("msn", "Posting ADL, count is %d\n",
+ session->adl_fqy);
msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
@@ -809,6 +820,9 @@ adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
if (!strcmp(cmd->params[1], "OK")) {
/* ADL ack */
+ if (purple_debug_is_verbose())
+ purple_debug_info("msn", "ADL ACK, count is %d\n",
+ session->adl_fqy);
if (--session->adl_fqy == 0)
msn_session_finish_login(session);
} else {
@@ -1178,14 +1192,36 @@ ipg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
id = xmlnode_get_attrib(msg, "id");
if (id && !strcmp(id, "407")) {
- /* TODO: Use this to NAK the transaction, maybe print the text, too.
- unsigned int trId;
- id = xmlnode_get_attrib(payloadNode, "id");
- trId = atol(id);
- */
- purple_conv_present_error(who, gc->account,
- _("Mobile message was not sent because it was too long."));
-
+ PurpleConversation *conv
+ = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
+ who, gc->account);
+ if (conv != NULL) {
+ purple_conversation_write(conv, NULL,
+ _("Mobile message was not sent because it was too long."),
+ PURPLE_MESSAGE_ERROR, time(NULL));
+
+ if ((id = xmlnode_get_attrib(payloadNode, "id")) != NULL) {
+ unsigned int trId = atol(id);
+ MsnTransaction *trans;
+ MsnMessage *msg;
+
+ trans = msn_history_find(cmdproc->history, trId);
+ msg = (MsnMessage *)trans->data;
+
+ if (msg) {
+ char *body_str = msn_message_to_string(msg);
+ char *body_enc = g_markup_escape_text(body_str, -1);
+
+ purple_conversation_write(conv, NULL, body_enc,
+ PURPLE_MESSAGE_RAW, time(NULL));
+
+ g_free(body_str);
+ g_free(body_enc);
+ msn_message_destroy(msg);
+ trans->data = NULL;
+ }
+ }
+ }
} else {
serv_got_im(gc, who, text, 0, time(NULL));
}
diff --git a/libpurple/protocols/msn/oim.c b/libpurple/protocols/msn/oim.c
index 1c6aabab96..ddd36c45ca 100644
--- a/libpurple/protocols/msn/oim.c
+++ b/libpurple/protocols/msn/oim.c
@@ -21,7 +21,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "msn.h"
#include "soap.h"
@@ -172,8 +172,18 @@ msn_oim_request_cb(MsnSoapMessage *request, MsnSoapMessage *response,
if (faultcode) {
gchar *faultcode_str = xmlnode_get_data(faultcode);
+ gboolean need_token_update = FALSE;
+
+ if (faultcode_str) {
+ if (g_str_equal(faultcode_str, "q0:BadContextToken") ||
+ g_str_equal(faultcode_str, "AuthenticationFailed"))
+ need_token_update = TRUE;
+ else if (g_str_equal(faultcode_str, "q0:AuthenticationFailed") &&
+ xmlnode_get_child(fault, "detail/RequiredAuthPolicy") != NULL)
+ need_token_update = TRUE;
+ }
- if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
+ if (need_token_update) {
purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
msn_nexus_update_token(data->oim->session->nexus,
data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
@@ -181,16 +191,8 @@ msn_oim_request_cb(MsnSoapMessage *request, MsnSoapMessage *response,
g_free(faultcode_str);
return;
- } else if (faultcode_str && g_str_equal(faultcode_str, "q0:AuthenticationFailed")) {
- if (xmlnode_get_child(fault, "detail/RequiredAuthPolicy") != NULL) {
- purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
- msn_nexus_update_token(data->oim->session->nexus,
- data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
- (GSourceFunc)msn_oim_request_helper, data);
- g_free(faultcode_str);
- return;
- }
}
+
g_free(faultcode_str);
}
diff --git a/libpurple/protocols/msn/oim.h b/libpurple/protocols/msn/oim.h
index dc5df9c54c..87a35ffba5 100644
--- a/libpurple/protocols/msn/oim.h
+++ b/libpurple/protocols/msn/oim.h
@@ -20,7 +20,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _MSN_OIM_H_
#define _MSN_OIM_H_
diff --git a/libpurple/protocols/msn/slp.c b/libpurple/protocols/msn/slp.c
index b4a3ece36d..39b67f3f37 100644
--- a/libpurple/protocols/msn/slp.c
+++ b/libpurple/protocols/msn/slp.c
@@ -351,7 +351,7 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
g_free(bin);
- purple_xfer_set_filename(xfer, file_name);
+ purple_xfer_set_filename(xfer, file_name ? file_name : "");
g_free(file_name);
purple_xfer_set_size(xfer, file_size);
purple_xfer_set_init_fnc(xfer, msn_xfer_init);
@@ -403,9 +403,8 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
if (conv) {
char *buf;
buf = g_strdup_printf(
- _("%s has sent you a webcam "
- "invite, which is not yet "
- "supported."), from);
+ _("%s invited you to view his/her webcam, but "
+ "this is not yet supported."), from);
purple_conversation_write(conv, NULL, buf,
PURPLE_MESSAGE_SYSTEM |
PURPLE_MESSAGE_NOTIFY,
@@ -709,7 +708,15 @@ msn_slp_sip_recv(MsnSlpLink *slplink, const char *body)
content = get_token(body, "\r\n\r\n", NULL);
- got_invite(slpcall, branch, content_type, content);
+ if (branch && content_type && content)
+ {
+ got_invite(slpcall, branch, content_type, content);
+ }
+ else
+ {
+ msn_slpcall_destroy(slpcall);
+ slpcall = NULL;
+ }
g_free(branch);
g_free(content_type);
diff --git a/libpurple/protocols/msn/slpcall.c b/libpurple/protocols/msn/slpcall.c
index 6bb1357f2a..5a656cb50c 100644
--- a/libpurple/protocols/msn/slpcall.c
+++ b/libpurple/protocols/msn/slpcall.c
@@ -205,7 +205,7 @@ msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
if (slpmsg->session_id == 64)
{
/* This is for handwritten messages (Ink) */
- GError *error;
+ GError *error = NULL;
gsize bytes_read, bytes_written;
body_str = g_convert((const gchar *)body, body_len / 2,
@@ -232,7 +232,7 @@ msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
g_free(body_str);
body_str = g_convert((const gchar *)body, body_len / 2,
- "UTF-8", "UTF16-LE",
+ "UTF-8", "UTF-16LE",
&bytes_read, &bytes_written, &error);
if (!body_str)
{
diff --git a/libpurple/protocols/msn/slplink.c b/libpurple/protocols/msn/slplink.c
index d23ae98a0d..0b921fa633 100644
--- a/libpurple/protocols/msn/slplink.c
+++ b/libpurple/protocols/msn/slplink.c
@@ -441,6 +441,7 @@ msn_slplink_send_ack(MsnSlpLink *slplink, MsnMessage *msg)
slpmsg->info = "SLP ACK";
msn_slplink_send_slpmsg(slplink, slpmsg);
+ msn_slpmsg_destroy(slpmsg);
}
static void
@@ -504,11 +505,6 @@ msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
data = msn_message_get_bin_data(msg, &len);
- /*
- OVERHEAD!
- if (msg->msnslp_header.length < msg->msnslp_header.total_size)
- */
-
offset = msg->msnslp_header.offset;
if (offset == 0)
@@ -578,7 +574,7 @@ msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
/* fseek(slpmsg->fp, offset, SEEK_SET); */
len = fwrite(data, 1, len, slpmsg->fp);
}
- else if (slpmsg->size)
+ else if (slpmsg->size && slpmsg->buffer)
{
if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size)
{
diff --git a/libpurple/protocols/msn/soap.c b/libpurple/protocols/msn/soap.c
index badb8a9494..c7d2a64075 100644
--- a/libpurple/protocols/msn/soap.c
+++ b/libpurple/protocols/msn/soap.c
@@ -20,7 +20,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "internal.h"
diff --git a/libpurple/protocols/msn/soap.h b/libpurple/protocols/msn/soap.h
index e862e4e570..61881c369d 100644
--- a/libpurple/protocols/msn/soap.h
+++ b/libpurple/protocols/msn/soap.h
@@ -20,7 +20,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _MSN_SOAP_H
diff --git a/libpurple/protocols/msn/switchboard.c b/libpurple/protocols/msn/switchboard.c
index c4f9c13baa..1f6cd22d2a 100644
--- a/libpurple/protocols/msn/switchboard.c
+++ b/libpurple/protocols/msn/switchboard.c
@@ -248,9 +248,11 @@ msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user)
{
purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL,
PURPLE_CBFLAGS_NONE, TRUE);
+ msn_servconn_set_idle_timeout(swboard->servconn, 0);
}
else if (swboard->current_users > 1 || swboard->total_users > 1)
{
+ msn_servconn_set_idle_timeout(swboard->servconn, 0);
if (swboard->conv == NULL ||
purple_conversation_get_type(swboard->conv) != PURPLE_CONV_TYPE_CHAT)
{
@@ -920,7 +922,7 @@ msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
}
imgid = purple_imgstore_add_with_id(image_data, image_len, NULL);
- image_msg = g_strdup_printf("<IMG ID=%d/>", imgid);
+ image_msg = g_strdup_printf("<IMG ID='%d'/>", imgid);
if (swboard->current_users > 1 ||
((swboard->conv != NULL) &&
diff --git a/libpurple/protocols/msnp9/slp.c b/libpurple/protocols/msnp9/slp.c
index 8c4e07cb61..3ccc898678 100644
--- a/libpurple/protocols/msnp9/slp.c
+++ b/libpurple/protocols/msnp9/slp.c
@@ -338,7 +338,7 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
char *bin;
gsize bin_len;
guint32 file_size;
- char *file_name;
+ gchar *file_name;
gunichar2 *uni_name;
account = slpcall->slplink->session->account;
@@ -368,7 +368,8 @@ got_sessionreq(MsnSlpCall *slpcall, const char *branch,
g_free(bin);
- purple_xfer_set_filename(xfer, file_name);
+ purple_xfer_set_filename(xfer, file_name ? file_name : "");
+ g_free(file_name);
purple_xfer_set_size(xfer, file_size);
purple_xfer_set_init_fnc(xfer, msn_xfer_init);
purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
diff --git a/libpurple/protocols/msnp9/slplink.c b/libpurple/protocols/msnp9/slplink.c
index 33e18b60e8..dfad7bf7f4 100644
--- a/libpurple/protocols/msnp9/slplink.c
+++ b/libpurple/protocols/msnp9/slplink.c
@@ -477,6 +477,7 @@ msn_slplink_send_ack(MsnSlpLink *slplink, MsnMessage *msg)
#endif
msn_slplink_send_slpmsg(slplink, slpmsg);
+ msn_slpmsg_destroy(slpmsg);
}
static void
@@ -603,7 +604,7 @@ msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg)
/* fseek(slpmsg->fp, offset, SEEK_SET); */
len = fwrite(data, 1, len, slpmsg->fp);
}
- else if (slpmsg->size)
+ else if (slpmsg->size && slpmsg->buffer)
{
if (G_MAXSIZE - len < offset || (offset + len) > slpmsg->size)
{
diff --git a/libpurple/protocols/oscar/clientlogin.c b/libpurple/protocols/oscar/clientlogin.c
index ead30ed00a..6b131600cc 100644
--- a/libpurple/protocols/oscar/clientlogin.c
+++ b/libpurple/protocols/oscar/clientlogin.c
@@ -62,50 +62,6 @@ static const char *get_client_key(OscarData *od)
}
/**
- * This is similar to purple_url_encode() except that it follows
- * RFC3986 a little more closely by not encoding - . _ and ~
- * It also uses capital letters as hex characters because capital
- * letters are required by AOL. The RFC says that capital letters
- * are a SHOULD and that URLs that use capital letters are
- * equivalent to URLs that use small letters.
- *
- * TODO: Check if purple_url_encode() can be replaced with this
- * version without breaking anything.
- */
-static const char *oscar_auth_url_encode(const char *str)
-{
- const char *iter;
- static char buf[BUF_LEN];
- char utf_char[6];
- guint i, j = 0;
-
- g_return_val_if_fail(str != NULL, NULL);
- g_return_val_if_fail(g_utf8_validate(str, -1, NULL), NULL);
-
- iter = str;
- for (; *iter && j < (BUF_LEN - 1) ; iter = g_utf8_next_char(iter)) {
- gunichar c = g_utf8_get_char(iter);
- /* If the character is an ASCII character and is alphanumeric
- * no need to escape */
- if ((c < 128 && isalnum(c)) || c =='-' || c == '.' || c == '_' || c == '~') {
- buf[j++] = c;
- } else {
- int bytes = g_unichar_to_utf8(c, utf_char);
- for (i = 0; i < bytes; i++) {
- if (j > (BUF_LEN - 4))
- break;
- sprintf(buf + j, "%%%02X", utf_char[i] & 0xff);
- j += 3;
- }
- }
- }
-
- buf[j] = '\0';
-
- return buf;
-}
-
-/**
* @return A null-terminated base64 encoded version of the HMAC
* calculated using the given key and data.
*/
@@ -134,8 +90,8 @@ static gchar *generate_signature(const char *method, const char *url, const char
char *encoded_url, *signature_base_string, *signature;
const char *encoded_parameters;
- encoded_url = g_strdup(oscar_auth_url_encode(url));
- encoded_parameters = oscar_auth_url_encode(parameters);
+ encoded_url = g_strdup(purple_url_encode(url));
+ encoded_parameters = purple_url_encode(parameters);
signature_base_string = g_strdup_printf("%s&%s&%s",
method, encoded_url, encoded_parameters);
g_free(encoded_url);
@@ -156,11 +112,15 @@ static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const g
response_node = xmlnode_from_str(response, response_len);
if (response_node == NULL)
{
+ char *msg;
purple_debug_error("oscar", "startOSCARSession could not parse "
"response as XML: %s\n", response);
+ /* Note to translators: %s in this string is a URL */
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_START_OSCAR_SESSION);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Received unexpected response from " URL_START_OSCAR_SESSION));
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
return FALSE;
}
@@ -175,11 +135,14 @@ static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const g
/* Make sure we have a status code */
if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
+ char *msg;
purple_debug_error("oscar", "startOSCARSession response was "
"missing statusCode: %s\n", response);
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_START_OSCAR_SESSION);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Received unexpected response from " URL_START_OSCAR_SESSION));
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
xmlnode_free(response_node);
return FALSE;
}
@@ -197,10 +160,14 @@ static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const g
"frequently. Wait ten minutes and try again. If "
"you continue to try, you will need to wait even "
"longer."));
- else
+ else {
+ char *msg;
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_START_OSCAR_SESSION);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
- _("Received unexpected response from " URL_START_OSCAR_SESSION));
+ PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
+ g_free(msg);
+ }
g_free(tmp);
xmlnode_free(response_node);
@@ -212,11 +179,14 @@ static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const g
if (data_node == NULL || host_node == NULL ||
port_node == NULL || cookie_node == NULL)
{
+ char *msg;
purple_debug_error("oscar", "startOSCARSession response was missing "
"something: %s\n", response);
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_START_OSCAR_SESSION);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Received unexpected response from " URL_START_OSCAR_SESSION));
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
xmlnode_free(response_node);
return FALSE;
}
@@ -227,11 +197,14 @@ static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const g
*cookie = xmlnode_get_data_unescaped(cookie_node);
if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || cookie == NULL || *cookie == '\0')
{
+ char *msg;
purple_debug_error("oscar", "startOSCARSession response was missing "
"something: %s\n", response);
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_START_OSCAR_SESSION);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Received unexpected response from " URL_START_OSCAR_SESSION));
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
g_free(*host);
g_free(tmp);
g_free(*cookie);
@@ -261,8 +234,10 @@ static void start_oscar_session_cb(PurpleUtilFetchUrlData *url_data, gpointer us
if (error_message != NULL || len == 0) {
gchar *tmp;
- tmp = g_strdup_printf(_("Error requesting " URL_START_OSCAR_SESSION
- ": %s"), error_message);
+ /* Note to translators: The first %s is a URL, the second is an
+ error message. */
+ tmp = g_strdup_printf(_("Error requesting %s: %s"),
+ URL_START_OSCAR_SESSION, error_message);
purple_connection_error_reason(gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
g_free(tmp);
@@ -290,7 +265,7 @@ static void send_start_oscar_session(OscarData *od, const char *token, const cha
"&k=%s"
"&ts=%" PURPLE_TIME_T_MODIFIER
"&useTLS=0",
- oscar_auth_url_encode(token), get_client_key(od), hosttime);
+ purple_url_encode(token), get_client_key(od), hosttime);
signature = generate_signature("GET", URL_START_OSCAR_SESSION,
query_string, session_key);
url = g_strdup_printf(URL_START_OSCAR_SESSION "?%s&sig_sha256=%s",
@@ -339,11 +314,14 @@ static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *r
response_node = xmlnode_from_str(response, response_len);
if (response_node == NULL)
{
+ char *msg;
purple_debug_error("oscar", "clientLogin could not parse "
"response as XML: %s\n", response);
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_CLIENT_LOGIN);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Received unexpected response from " URL_CLIENT_LOGIN));
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
return FALSE;
}
@@ -360,11 +338,14 @@ static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *r
/* Make sure we have a status code */
if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
+ char *msg;
purple_debug_error("oscar", "clientLogin response was "
"missing statusCode: %s\n", response);
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_CLIENT_LOGIN);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Received unexpected response from " URL_CLIENT_LOGIN));
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
xmlnode_free(response_node);
return FALSE;
}
@@ -393,10 +374,14 @@ static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *r
purple_connection_error_reason(gc,
PURPLE_CONNECTION_ERROR_OTHER_ERROR,
_("AOL does not allow your screen name to authenticate here"));
- } else
+ } else {
+ char *msg;
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_CLIENT_LOGIN);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
- _("Received unexpected response from " URL_CLIENT_LOGIN));
+ PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
+ g_free(msg);
+ }
xmlnode_free(response_node);
return FALSE;
@@ -407,11 +392,14 @@ static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *r
if (data_node == NULL || secret_node == NULL ||
token_node == NULL || tokena_node == NULL)
{
+ char *msg;
purple_debug_error("oscar", "clientLogin response was missing "
"something: %s\n", response);
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_CLIENT_LOGIN);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Received unexpected response from " URL_CLIENT_LOGIN));
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
xmlnode_free(response_node);
return FALSE;
}
@@ -422,11 +410,14 @@ static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *r
tmp = xmlnode_get_data_unescaped(hosttime_node);
if (*token == NULL || **token == '\0' || *secret == NULL || **secret == '\0' || tmp == NULL || *tmp == '\0')
{
+ char *msg;
purple_debug_error("oscar", "clientLogin response was missing "
"something: %s\n", response);
+ msg = g_strdup_printf(_("Received unexpected response from %s"),
+ URL_CLIENT_LOGIN);
purple_connection_error_reason(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Received unexpected response from " URL_CLIENT_LOGIN));
+ PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
g_free(*token);
g_free(*secret);
g_free(tmp);
@@ -458,8 +449,8 @@ static void client_login_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data
if (error_message != NULL || len == 0) {
gchar *tmp;
- tmp = g_strdup_printf(_("Error requesting " URL_CLIENT_LOGIN
- ": %s"), error_message);
+ tmp = g_strdup_printf(_("Error requesting %s: %s"),
+ URL_CLIENT_LOGIN, error_message);
purple_connection_error_reason(gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
g_free(tmp);
@@ -518,8 +509,8 @@ void send_client_login(OscarData *od, const char *username)
body = g_string_new("");
g_string_append_printf(body, "devId=%s", get_client_key(od));
g_string_append_printf(body, "&f=xml");
- g_string_append_printf(body, "&pwd=%s", oscar_auth_url_encode(password));
- g_string_append_printf(body, "&s=%s", oscar_auth_url_encode(username));
+ g_string_append_printf(body, "&pwd=%s", purple_url_encode(password));
+ g_string_append_printf(body, "&s=%s", purple_url_encode(username));
g_free(password);
/* Construct an HTTP POST request */
diff --git a/libpurple/protocols/oscar/family_auth.c b/libpurple/protocols/oscar/family_auth.c
index 1aced5cf76..88e8630688 100644
--- a/libpurple/protocols/oscar/family_auth.c
+++ b/libpurple/protocols/oscar/family_auth.c
@@ -277,7 +277,7 @@ aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *
* If set, old-fashioned buddy lists will not work. You will need
* to use SSI.
*/
- aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x02));
+ aim_tlvlist_add_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));
aim_tlvlist_write(&frame->data, &tlvlist);
diff --git a/libpurple/protocols/oscar/family_buddy.c b/libpurple/protocols/oscar/family_buddy.c
index 3b98664519..9ca1dfae07 100644
--- a/libpurple/protocols/oscar/family_buddy.c
+++ b/libpurple/protocols/oscar/family_buddy.c
@@ -221,9 +221,6 @@ buddychange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *f
if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
ret = userfunc(od, conn, frame, &userinfo);
- if (snac->subtype == SNAC_SUBTYPE_BUDDY_ONCOMING && userinfo.flags & AIM_FLAG_AWAY)
- aim_locate_autofetch_away_message(od, userinfo.bn);
-
aim_info_free(&userinfo);
return ret;
diff --git a/libpurple/protocols/oscar/family_icbm.c b/libpurple/protocols/oscar/family_icbm.c
index bbfb8a4bea..bfe98cca5d 100644
--- a/libpurple/protocols/oscar/family_icbm.c
+++ b/libpurple/protocols/oscar/family_icbm.c
@@ -1466,7 +1466,7 @@ static int incomingim_ch1_parsemsgs(OscarData *od, aim_userinfo_t *userinfo, gui
/* Should this be ASCII -> UNICODE -> Custom */
static const guint16 charsetpri[] = {
AIM_CHARSET_ASCII, /* ASCII first */
- AIM_CHARSET_CUSTOM, /* then ISO-8859-1 */
+ AIM_CHARSET_LATIN_1, /* then ISO-8859-1 */
AIM_CHARSET_UNICODE, /* UNICODE as last resort */
};
static const int charsetpricount = 3;
@@ -2714,7 +2714,7 @@ int aim_im_reqofflinemsgs(OscarData *od)
* and Purple 0.60 and newer.
*
*/
-int aim_im_sendmtn(OscarData *od, guint16 type1, const char *bn, guint16 type2)
+int aim_im_sendmtn(OscarData *od, guint16 channel, const char *bn, guint16 event)
{
FlapConnection *conn;
ByteStream bs;
@@ -2730,19 +2730,14 @@ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *bn, guint16 type2)
snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0014, 0x0000, NULL, 0);
- /*
- * 8 days of light
- * Er, that is to say, 8 bytes of 0's
- */
- byte_stream_put16(&bs, 0x0000);
- byte_stream_put16(&bs, 0x0000);
- byte_stream_put16(&bs, 0x0000);
- byte_stream_put16(&bs, 0x0000);
+ /* ICBM cookie */
+ byte_stream_put32(&bs, 0x00000000);
+ byte_stream_put32(&bs, 0x00000000);
/*
- * Type 1 (should be 0x0001 for mtn)
+ * Channel (should be 0x0001 for mtn)
*/
- byte_stream_put16(&bs, type1);
+ byte_stream_put16(&bs, channel);
/*
* Dest buddy name
@@ -2751,9 +2746,9 @@ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *bn, guint16 type2)
byte_stream_putstr(&bs, bn);
/*
- * Type 2 (should be 0x0000, 0x0001, or 0x0002 for mtn)
+ * Event (should be 0x0000, 0x0001, or 0x0002 for mtn)
*/
- byte_stream_put16(&bs, type2);
+ byte_stream_put16(&bs, event);
flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0014, 0x0000, snacid, &bs);
@@ -2775,16 +2770,16 @@ static int mtn_receive(OscarData *od, FlapConnection *conn, aim_module_t *mod, F
aim_rxcallback_t userfunc;
char *bn;
guint8 bnlen;
- guint16 type1, type2;
+ guint16 channel, event;
- byte_stream_advance(bs, 8); /* Unknown - All 0's */
- type1 = byte_stream_get16(bs);
+ byte_stream_advance(bs, 8); /* ICBM cookie */
+ channel = byte_stream_get16(bs);
bnlen = byte_stream_get8(bs);
bn = byte_stream_getstr(bs, bnlen);
- type2 = byte_stream_get16(bs);
+ event = byte_stream_get16(bs);
if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
- ret = userfunc(od, conn, frame, type1, bn, type2);
+ ret = userfunc(od, conn, frame, channel, bn, event);
g_free(bn);
diff --git a/libpurple/protocols/oscar/family_locate.c b/libpurple/protocols/oscar/family_locate.c
index a42996cd22..98d469413f 100644
--- a/libpurple/protocols/oscar/family_locate.c
+++ b/libpurple/protocols/oscar/family_locate.c
@@ -250,8 +250,6 @@ static void
aim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo)
{
aim_userinfo_t *cur;
- FlapConnection *conn;
- aim_rxcallback_t userfunc;
cur = aim_locate_finduserinfo(od, userinfo->bn);
@@ -353,73 +351,6 @@ aim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo)
}
cur->away_len = 0;
}
-
- /*
- * This callback can be used by a client if they want to know whenever
- * info for a buddy is updated. For example, if a client shows away
- * messages in its buddy list, then it would need to know if a user's
- * away message changes.
- */
- conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE);
- if ((userfunc = aim_callhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK)))
- userfunc(od, conn, NULL, cur);
-}
-
-/**
- * Remove this buddy name from our queue. If this info was requested
- * by our info request queue, then pop the next element off of the queue.
- *
- * @param od The aim session.
- * @param bn Buddy name of the info we just received.
- * @return True if the request was explicit (client requested the info),
- * false if the request was implicit (libfaim request the info).
- */
-static int
-aim_locate_gotuserinfo(OscarData *od, FlapConnection *conn, const char *bn)
-{
- struct userinfo_node *cur, *del;
- int was_explicit = TRUE;
-
- while ((od->locate.requested != NULL) && (oscar_util_name_compare(bn, od->locate.requested->bn) == 0)) {
- del = od->locate.requested;
- od->locate.requested = del->next;
- was_explicit = FALSE;
- g_free(del->bn);
- g_free(del);
- }
-
- cur = od->locate.requested;
- while ((cur != NULL) && (cur->next != NULL)) {
- if (oscar_util_name_compare(bn, cur->next->bn) == 0) {
- del = cur->next;
- cur->next = del->next;
- was_explicit = FALSE;
- g_free(del->bn);
- g_free(del);
- } else
- cur = cur->next;
- }
-
- return was_explicit;
-}
-
-void
-aim_locate_autofetch_away_message(OscarData *od, const char *bn)
-{
- struct userinfo_node *cur;
-
- /* Make sure we haven't already made an info request for this buddy */
- for (cur = od->locate.requested; cur != NULL; cur = cur->next)
- if (oscar_util_name_compare(bn, cur->bn) == 0)
- return;
-
- /* Add a new node to our request queue */
- cur = (struct userinfo_node *)g_malloc(sizeof(struct userinfo_node));
- cur->bn = g_strdup(bn);
- cur->next = od->locate.requested;
- od->locate.requested = cur;
-
- aim_locate_getinfoshort(od, cur->bn, 0x00000002);
}
aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *bn) {
@@ -745,6 +676,13 @@ aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo)
outinfo->sessionlen = byte_stream_get32(bs);
outinfo->present |= AIM_USERINFO_PRESENT_SESSIONLEN;
+ } else if (type == 0x0014) {
+ /*
+ * My instance number.
+ */
+ guint8 instance_number;
+ instance_number = byte_stream_get8(bs);
+
} else if (type == 0x0019) {
/*
* OSCAR short capability information. A shortened
@@ -866,10 +804,32 @@ aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo)
} else if (type == 0x001f) {
/*
+ * Upper bytes of user flags. Can be any size
+ *
* Seen on a buddy using DeadAIM. Data was 4 bytes:
* 0x00 00 00 10
*/
+ } else if (type == 0x0023) {
+ /*
+ * Last Buddy Feed update time, in seconds since the epoch.
+ */
+
+ } else if (type == 0x0026) {
+ /*
+ * Time that the profile was set, in seconds since the epoch.
+ */
+
+ } else if (type == 0x0027) {
+ /*
+ * Time that the away message was set, in seconds since the epoch.
+ */
+
+ } else if (type == 0x002a) {
+ /*
+ * Country code based on GeoIP data.
+ */
+
} else {
/*
@@ -956,7 +916,6 @@ error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame,
aim_snac_t *snac2;
guint16 reason;
char *bn;
- int was_explicit;
if (!(snac2 = aim_remsnac(od, snac->id))) {
purple_debug_misc("oscar", "locate error: received response from unknown request!\n");
@@ -978,15 +937,9 @@ error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame,
reason = byte_stream_get16(bs);
- /*
- * Remove this buddy name from our queue. If the client requested
- * this buddy's info explicitly, then notify them that we do not have
- * info for this buddy.
- */
- was_explicit = aim_locate_gotuserinfo(od, conn, bn);
- if (was_explicit == TRUE)
- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
- ret = userfunc(od, conn, frame, reason, bn);
+ /* Notify the user that we do not have info for this buddy */
+ if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+ ret = userfunc(od, conn, frame, reason, bn);
if (snac2)
g_free(snac2->data);
@@ -1202,7 +1155,6 @@ userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *fram
aim_userinfo_t *userinfo, *userinfo2;
GSList *tlvlist;
aim_tlv_t *tlv = NULL;
- int was_explicit;
userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t));
aim_info_extract(od, bs, userinfo);
@@ -1238,18 +1190,9 @@ userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *fram
aim_info_free(userinfo);
g_free(userinfo);
- /*
- * Remove this buddy name from our queue. If the client requested
- * this buddy's info explicitly, then notify them that we have info
- * for this buddy.
- */
- if (userinfo2 != NULL)
- {
- was_explicit = aim_locate_gotuserinfo(od, conn, userinfo2->bn);
- if (was_explicit == TRUE)
- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
- ret = userfunc(od, conn, frame, userinfo2);
- }
+ /* Show the info to the user */
+ if (userinfo2 != NULL && ((userfunc = aim_callhandler(od, snac->family, snac->subtype))))
+ ret = userfunc(od, conn, frame, userinfo2);
return ret;
}
diff --git a/libpurple/protocols/oscar/oscar.c b/libpurple/protocols/oscar/oscar.c
index 2febc6d8c1..620042f876 100644
--- a/libpurple/protocols/oscar/oscar.c
+++ b/libpurple/protocols/oscar/oscar.c
@@ -160,7 +160,6 @@ static int purple_parse_incoming_im(OscarData *, FlapConnection *, FlapFrame *,
static int purple_parse_misses (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_userinfo (OscarData *, FlapConnection *, FlapFrame *, ...);
-static int purple_got_infoblock (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_parse_motd (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_chatnav_info (OscarData *, FlapConnection *, FlapFrame *, ...);
static int purple_conv_chat_join (OscarData *, FlapConnection *, FlapFrame *, ...);
@@ -242,7 +241,7 @@ oscar_charset_check(const char *utf8)
{
if ((unsigned char)utf8[i] > 0x7f) {
/* not ASCII! */
- charset = AIM_CHARSET_CUSTOM;
+ charset = AIM_CHARSET_LATIN_1;
break;
}
i++;
@@ -429,7 +428,7 @@ purple_plugin_oscar_decode_im_part(PurpleAccount *account, const char *sourcebn,
if (charset == AIM_CHARSET_UNICODE) {
charsetstr1 = "UTF-16BE";
charsetstr2 = "UTF-8";
- } else if (charset == AIM_CHARSET_CUSTOM) {
+ } else if (charset == AIM_CHARSET_LATIN_1) {
if ((sourcebn != NULL) && oscar_util_valid_name_icq(sourcebn))
charsetstr1 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
else
@@ -540,7 +539,7 @@ purple_plugin_oscar_convert_to_best_encoding(PurpleConnection *gc,
*/
*msg = g_convert(from, -1, charsetstr, "UTF-8", NULL, &msglen, &err);
if (*msg != NULL) {
- *charset = AIM_CHARSET_CUSTOM;
+ *charset = AIM_CHARSET_LATIN_1;
*charsubset = 0x0000;
*msglen_int = msglen;
return;
@@ -812,37 +811,43 @@ static void oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUser
od = purple_connection_get_protocol_data(gc);
- if (userinfo == NULL)
- userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
-
- if ((user_info == NULL) || ((b == NULL) && (userinfo == NULL)))
+ if (b == NULL && userinfo == NULL)
return;
if (b == NULL)
b = purple_find_buddy(purple_connection_get_account(gc), userinfo->bn);
+ else
+ userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
if (b) {
presence = purple_buddy_get_presence(b);
status = purple_presence_get_active_status(presence);
+ }
- message = g_strdup(purple_status_get_attr_string(status, "message"));
- itmsurl = g_strdup(purple_status_get_attr_string(status, "itmsurl"));
-
- } else {
- /* This is an OSCAR contact for whom we don't have a PurpleBuddy but do have information. */
- if ((userinfo->flags & AIM_FLAG_AWAY)) {
- /* Away message? */
- if ((userinfo->flags & AIM_FLAG_AWAY) && (userinfo->away_len > 0) && (userinfo->away != NULL) && (userinfo->away_encoding != NULL)) {
- tmp = oscar_encoding_extract(userinfo->away_encoding);
- message = oscar_encoding_to_utf8(account, tmp, userinfo->away,
- userinfo->away_len);
- g_free(tmp);
- }
+ /* If we have both b and userinfo we favor userinfo, because if we're
+ viewing someone's profile then we want the HTML away message, and
+ the "message" attribute of the status contains only the plaintext
+ message. */
+ if (userinfo) {
+ if ((userinfo->flags & AIM_FLAG_AWAY)
+ && userinfo->away_len > 0
+ && userinfo->away != NULL
+ && userinfo->away_encoding != NULL)
+ {
+ /* Away message */
+ tmp = oscar_encoding_extract(userinfo->away_encoding);
+ message = oscar_encoding_to_utf8(account,
+ tmp, userinfo->away, userinfo->away_len);
+ g_free(tmp);
} else {
- /* Available message? */
+ /*
+ * Available message or non-HTML away message (because that's
+ * all we have right now.
+ */
if ((userinfo->status != NULL) && userinfo->status[0] != '\0') {
- message = oscar_encoding_to_utf8(account, userinfo->status_encoding,
- userinfo->status, userinfo->status_len);
+ message = oscar_encoding_to_utf8(account,
+ userinfo->status_encoding, userinfo->status,
+ userinfo->status_len);
}
#if defined (_WIN32) || defined (__APPLE__)
if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0'))
@@ -850,6 +855,9 @@ static void oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUser
userinfo->itmsurl, userinfo->itmsurl_len);
#endif
}
+ } else {
+ message = g_strdup(purple_status_get_attr_string(status, "message"));
+ itmsurl = g_strdup(purple_status_get_attr_string(status, "itmsurl"));
}
is_away = ((status && !purple_status_is_available(status)) ||
@@ -916,7 +924,6 @@ static void oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUser
g_free(message);
message = g_strdup(_("Offline"));
}
-
}
purple_notify_user_info_add_pair(user_info, _("Status"), message);
@@ -1478,7 +1485,6 @@ oscar_login(PurpleAccount *account)
oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_RIGHTSINFO, purple_parse_locaterights, 0);
oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_USERINFO, purple_parse_userinfo, 0);
oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_ERROR, purple_parse_locerr, 0);
- oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK, purple_got_infoblock, 0);
oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0001, purple_parse_genericerr, 0);
oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, purple_selfinfo, 0);
oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, purple_memrequest, 0);
@@ -2139,6 +2145,23 @@ static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame
g_return_val_if_fail(info != NULL, 1);
g_return_val_if_fail(info->bn != NULL, 1);
+ /*
+ * If this is an AIM buddy and their name has formatting, set their
+ * server alias.
+ */
+ if (!oscar_util_valid_name_icq(info->bn)) {
+ gboolean bn_has_formatting = FALSE;
+ char *c;
+ for (c = info->bn; *c != '\0'; c++) {
+ if (!islower(*c)) {
+ bn_has_formatting = TRUE;
+ break;
+ }
+ }
+ serv_got_alias(gc, info->bn,
+ bn_has_formatting ? info->bn : NULL);
+ }
+
if (info->present & AIM_USERINFO_PRESENT_FLAGS) {
if (info->flags & AIM_FLAG_AWAY)
buddy_is_away = TRUE;
@@ -2388,6 +2411,21 @@ static int incomingim_chan1(OscarData *od, FlapConnection *conn, aim_userinfo_t
if (purple_markup_find_tag("body", tmp, &start, &end, &attribs))
{
const char *ichattextcolor, *ichatballooncolor;
+ const char *start2, *end2;
+ GData *unused;
+
+ /*
+ * Find the ending </body> so we can strip off the outer <html/>
+ * and <body/>
+ */
+ if (purple_markup_find_tag("/body", end + 1, &start2, &end2, &unused))
+ {
+ gchar *tmp2;
+ tmp2 = g_strndup(end + 1, (start2 - 1) - (end + 1) + 1);
+ g_free(tmp);
+ tmp = tmp2;
+ g_datalist_clear(&unused);
+ }
ichattextcolor = g_datalist_get_data(&attribs, "ichattextcolor");
if (ichattextcolor != NULL)
@@ -2769,7 +2807,7 @@ incomingim_chan4(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo,
gchar *reason = NULL;
if (msg2[5] != NULL)
- reason = purple_plugin_oscar_decode_im_part(account, bn, AIM_CHARSET_CUSTOM, 0x0000, msg2[5], strlen(msg2[5]));
+ reason = purple_plugin_oscar_decode_im_part(account, bn, AIM_CHARSET_LATIN_1, 0x0000, msg2[5], strlen(msg2[5]));
purple_debug_info("oscar",
"Received an authorization request from UIN %u\n",
@@ -3198,16 +3236,16 @@ static int purple_parse_msgerr(OscarData *od, FlapConnection *conn, FlapFrame *f
static int purple_parse_mtn(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
PurpleConnection *gc = od->gc;
va_list ap;
- guint16 type1, type2;
+ guint16 channel, event;
char *bn;
va_start(ap, fr);
- type1 = (guint16) va_arg(ap, unsigned int);
+ channel = (guint16) va_arg(ap, unsigned int);
bn = va_arg(ap, char *);
- type2 = (guint16) va_arg(ap, unsigned int);
+ event = (guint16) va_arg(ap, unsigned int);
va_end(ap);
- switch (type2) {
+ switch (event) {
case 0x0000: { /* Text has been cleared */
serv_got_typing_stopped(gc, bn);
} break;
@@ -3220,12 +3258,14 @@ static int purple_parse_mtn(OscarData *od, FlapConnection *conn, FlapFrame *fr,
serv_got_typing(gc, bn, 0, PURPLE_TYPING);
} break;
+ case 0x000f: { /* Closed IM window */
+ serv_got_typing_stopped(gc, bn);
+ } break;
+
default: {
- /*
- * It looks like iChat sometimes sends typing notification
- * with type1=0x0001 and type2=0x000f. Not sure why.
- */
- purple_debug_info("oscar", "Received unknown typing notification message from %s. Type1 is 0x%04x and type2 is 0x%04hx.\n", bn, type1, type2);
+ purple_debug_info("oscar", "Received unknown typing "
+ "notification message from %s. Channel is 0x%04x "
+ "and event is 0x%04hx.\n", bn, channel, event);
} break;
}
@@ -3287,7 +3327,7 @@ static int purple_parse_userinfo(OscarData *od, FlapConnection *conn, FlapFrame
oscar_user_info_append_extra_info(gc, user_info, NULL, userinfo);
if ((userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) && !oscar_util_valid_name_sms(userinfo->bn)) {
- /* An SMS contact is always online; its Online Since valid is not useful */
+ /* An SMS contact is always online; its Online Since value is not useful */
time_t t = userinfo->onlinesince;
oscar_user_info_add_pair(user_info, _("Online Since"), purple_date_format_full(localtime(&t)));
}
@@ -3330,55 +3370,6 @@ static int purple_parse_userinfo(OscarData *od, FlapConnection *conn, FlapFrame
return 1;
}
-static int purple_got_infoblock(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
-{
- PurpleConnection *gc = od->gc;
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleBuddy *b;
- PurplePresence *presence;
- PurpleStatus *status;
- gchar *message = NULL;
-
- va_list ap;
- aim_userinfo_t *userinfo;
-
- va_start(ap, fr);
- userinfo = va_arg(ap, aim_userinfo_t *);
- va_end(ap);
-
- b = purple_find_buddy(account, userinfo->bn);
- if (b == NULL)
- return 1;
-
- if (!oscar_util_valid_name_icq(userinfo->bn))
- {
- if (strcmp(purple_buddy_get_name(b), userinfo->bn) != 0)
- serv_got_alias(gc, purple_buddy_get_name(b), userinfo->bn);
- else
- serv_got_alias(gc, purple_buddy_get_name(b), NULL);
- }
-
- presence = purple_buddy_get_presence(b);
- status = purple_presence_get_active_status(presence);
-
- if (purple_status_is_online(status) && !purple_status_is_available(status) &&
- userinfo->flags & AIM_FLAG_AWAY && userinfo->away_len > 0 &&
- userinfo->away != NULL && userinfo->away_encoding != NULL)
- {
- gchar *charset = oscar_encoding_extract(userinfo->away_encoding);
- message = oscar_encoding_to_utf8(account, charset,
- userinfo->away,
- userinfo->away_len);
- g_free(charset);
- purple_prpl_got_user_status(account, userinfo->bn,
- purple_status_get_id(status),
- "message", message, NULL);
- g_free(message);
- }
-
- return 1;
-}
-
static int purple_parse_motd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
{
char *msg;
@@ -4704,7 +4695,7 @@ gchar *purple_prpl_oscar_convert_to_infotext(const gchar *str, gsize *ret_len, c
if (charset == AIM_CHARSET_UNICODE) {
encoded = g_convert(str, -1, "UTF-16BE", "UTF-8", NULL, ret_len, NULL);
*encoding = "unicode-2-0";
- } else if (charset == AIM_CHARSET_CUSTOM) {
+ } else if (charset == AIM_CHARSET_LATIN_1) {
encoded = g_convert(str, -1, "ISO-8859-1", "UTF-8", NULL, ret_len, NULL);
*encoding = "iso-8859-1";
} else {
@@ -5607,7 +5598,7 @@ static int purple_ssi_authrequest(OscarData *od, FlapConnection *conn, FlapFrame
buddy = purple_find_buddy(account, bn);
if (msg != NULL)
- reason = purple_plugin_oscar_decode_im_part(account, bn, AIM_CHARSET_CUSTOM, 0x0000, msg, strlen(msg));
+ reason = purple_plugin_oscar_decode_im_part(account, bn, AIM_CHARSET_LATIN_1, 0x0000, msg, strlen(msg));
data = g_new(struct name_data, 1);
data->gc = gc;
@@ -5844,7 +5835,7 @@ int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMes
charsetstr = "us-ascii";
else if (charset == AIM_CHARSET_UNICODE)
charsetstr = "unicode-2-0";
- else if (charset == AIM_CHARSET_CUSTOM)
+ else if (charset == AIM_CHARSET_LATIN_1)
charsetstr = "iso-8859-1";
aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "en");
g_free(buf2);
@@ -6335,6 +6326,44 @@ oscar_ask_directim(gpointer object, gpointer ignored)
}
static void
+oscar_close_directim(gpointer object, gpointer ignored)
+{
+ PurpleBlistNode *node;
+ PurpleBuddy *buddy;
+ PurpleAccount *account;
+ PurpleConnection *gc;
+ PurpleConversation *conv;
+ OscarData *od;
+ PeerConnection *conn;
+ const char *name;
+
+ node = object;
+
+ g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+ buddy = (PurpleBuddy*)node;
+ name = purple_buddy_get_name(buddy);
+ account = purple_buddy_get_account(buddy);
+ gc = purple_account_get_connection(account);
+ od = gc->proto_data;
+ conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM);
+
+ if (conn != NULL)
+ {
+ if (!conn->ready)
+ aim_im_sendch2_cancel(conn);
+
+ peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+
+ /* OSCAR_DISCONNECT_LOCAL_CLOSED doesn't write anything to the convo
+ * window. Let the user know that we canceled the Direct IM. */
+ conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name);
+ purple_conversation_write(conv, NULL, _("You closed the connection."),
+ PURPLE_MESSAGE_SYSTEM, time(NULL));
+ }
+}
+
+static void
oscar_get_aim_info_cb(PurpleBlistNode *node, gpointer ignore)
{
PurpleBuddy *buddy;
@@ -6397,11 +6426,23 @@ oscar_buddy_menu(PurpleBuddy *buddy) {
oscar_util_name_compare(purple_account_get_username(account), bname) &&
PURPLE_BUDDY_IS_ONLINE(buddy))
{
+ PeerConnection *conn;
+ conn = peer_connection_find_by_type(od, bname, OSCAR_CAPABILITY_DIRECTIM);
+
if (userinfo->capabilities & OSCAR_CAPABILITY_DIRECTIM)
{
- act = purple_menu_action_new(_("Direct IM"),
- PURPLE_CALLBACK(oscar_ask_directim),
- NULL, NULL);
+ if (conn)
+ {
+ act = purple_menu_action_new(_("End Direct IM Session"),
+ PURPLE_CALLBACK(oscar_close_directim),
+ NULL, NULL);
+ }
+ else
+ {
+ act = purple_menu_action_new(_("Direct IM"),
+ PURPLE_CALLBACK(oscar_ask_directim),
+ NULL, NULL);
+ }
menu = g_list_prepend(menu, act);
}
#if 0
diff --git a/libpurple/protocols/oscar/oscar.h b/libpurple/protocols/oscar/oscar.h
index b5e5ee4c8d..fc6aa1da64 100644
--- a/libpurple/protocols/oscar/oscar.h
+++ b/libpurple/protocols/oscar/oscar.h
@@ -533,7 +533,6 @@ struct _OscarData
struct {
struct aim_userinfo_s *userinfo;
- struct userinfo_node *requested;
} locate;
/* Server-stored information (ssi) */
@@ -809,9 +808,9 @@ void oscar_chat_destroy(struct chat_connection *cc);
#define AIM_IMFLAGS_OFFLINE 0x0800 /* send to offline user */
#define AIM_IMFLAGS_TYPINGNOT 0x1000 /* typing notification */
-#define AIM_CHARSET_ASCII 0x0000
-#define AIM_CHARSET_UNICODE 0x0002 /* UTF-16BE */
-#define AIM_CHARSET_CUSTOM 0x0003
+#define AIM_CHARSET_ASCII 0x0000 /* ISO 646 */
+#define AIM_CHARSET_UNICODE 0x0002 /* ISO 10646 (UTF-16/UCS-2BE) */
+#define AIM_CHARSET_LATIN_1 0x0003 /* ISO 8859-1 */
/*
* Multipart message structures.
@@ -1007,7 +1006,7 @@ struct aim_incomingim_ch4_args
/* 0x0008 */ int aim_im_warn(OscarData *od, FlapConnection *conn, const char *destbn, guint32 flags);
/* 0x000b */ int aim_im_denytransfer(OscarData *od, const char *bn, const guchar *cookie, guint16 code);
/* 0x0010 */ int aim_im_reqofflinemsgs(OscarData *od);
-/* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *bn, guint16 type2);
+/* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 channel, const char *bn, guint16 event);
void aim_icbm_makecookie(guchar* cookie);
gchar *oscar_encoding_extract(const char *encoding);
gchar *oscar_encoding_to_utf8(PurpleAccount *account, const char *encoding, const char *text, int textlen);
@@ -1027,11 +1026,12 @@ gchar *purple_plugin_oscar_decode_im_part(PurpleAccount *account, const char *so
#define AIM_FLAG_ICQ 0x0040
#define AIM_FLAG_WIRELESS 0x0080
#define AIM_FLAG_UNKNOWN100 0x0100
-#define AIM_FLAG_UNKNOWN200 0x0200
+#define AIM_FLAG_IMFORWARDING 0x0200
#define AIM_FLAG_ACTIVEBUDDY 0x0400
#define AIM_FLAG_UNKNOWN800 0x0800
-#define AIM_FLAG_ABINTERNAL 0x1000
-#define AIM_FLAG_ALLUSERS 0x001f
+#define AIM_FLAG_ONEWAYWIRELESS 0x1000
+#define AIM_FLAG_NOKNOCKKNOCK 0x00040000
+#define AIM_FLAG_FORWARD_MOBILE 0x00080000
#define AIM_USERINFO_PRESENT_FLAGS 0x00000001
#define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002
@@ -1133,7 +1133,6 @@ void aim_locate_dorequest(OscarData *od);
/* 0x000f */ int aim_locate_setinterests(OscarData *od, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, guint16 privacy);
/* 0x0015 */ int aim_locate_getinfoshort(OscarData *od, const char *bn, guint32 flags);
-void aim_locate_autofetch_away_message(OscarData *od, const char *bn);
guint32 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len);
guint32 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len);
void aim_info_free(aim_userinfo_t *);
diff --git a/libpurple/protocols/oscar/snactypes.h b/libpurple/protocols/oscar/snactypes.h
index 5a697aa827..1ce256babe 100644
--- a/libpurple/protocols/oscar/snactypes.h
+++ b/libpurple/protocols/oscar/snactypes.h
@@ -96,7 +96,6 @@
#define SNAC_SUBTYPE_LOCATE_USERINFO 0x0006
#define SNAC_SUBTYPE_LOCATE_WATCHERSUBREQ 0x0007
#define SNAC_SUBTYPE_LOCATE_WATCHERNOT 0x0008
-#define SNAC_SUBTYPE_LOCATE_GOTINFOBLOCK 0xfffd
#define SNAC_SUBTYPE_LOCATE_DEFAULT 0xffff
/*
diff --git a/libpurple/protocols/qq/buddy_list.c b/libpurple/protocols/qq/buddy_list.c
index a1712f90a9..d89fb11fc9 100644
--- a/libpurple/protocols/qq/buddy_list.c
+++ b/libpurple/protocols/qq/buddy_list.c
@@ -215,7 +215,7 @@ guint8 qq_process_get_buddies_online(guint8 *data, gint data_len, PurpleConnecti
if (qd->client_version >= 2007) bytes += 4;
if (bs.uid == 0 || (bytes - bytes_start) != entry_len) {
- purple_debug_error("QQ", "uid=0 or entry complete len(%d) != %d",
+ purple_debug_error("QQ", "uid=0 or entry complete len(%d) != %d\n",
(bytes - bytes_start), entry_len);
continue;
} /* check if it is a valid entry */
@@ -281,7 +281,7 @@ guint16 qq_process_get_buddies(guint8 *data, gint data_len, PurpleConnection *gc
qd = (qq_data *) gc->proto_data;
if (data_len <= 2) {
- purple_debug_error("QQ", "empty buddies list");
+ purple_debug_error("QQ", "empty buddies list\n");
return -1;
}
/* qq_show_packet("QQ get buddies list", data, data_len); */
@@ -352,7 +352,7 @@ guint16 qq_process_get_buddies(guint8 *data, gint data_len, PurpleConnection *gc
if(bytes > data_len) {
purple_debug_error("QQ",
- "qq_process_get_buddies: Dangerous error! maybe protocol changed, notify developers!");
+ "qq_process_get_buddies: Dangerous error! maybe protocol changed, notify developers!\n");
}
purple_debug_info("QQ", "Received %d buddies, nextposition=%u\n",
@@ -397,7 +397,7 @@ guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConn
/* 05: skip unknow 0x00 */
bytes += 1;
if (uid == 0 || (type != 0x1 && type != 0x4)) {
- purple_debug_info("QQ", "Buddy entry, uid=%u, type=%d", uid, type);
+ purple_debug_info("QQ", "Buddy entry, uid=%u, type=%d\n", uid, type);
continue;
}
if(0x1 == type) { /* a buddy */
@@ -407,7 +407,7 @@ guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConn
} else { /* a group */
rmd = qq_room_data_find(gc, uid);
if(rmd == NULL) {
- purple_debug_info("QQ", "Unknow room id %u", uid);
+ purple_debug_info("QQ", "Unknown room id %u\n", uid);
qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, uid);
} else {
rmd->my_role = QQ_ROOM_ROLE_YES;
@@ -418,7 +418,7 @@ guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConn
if(bytes > data_len) {
purple_debug_error("QQ",
- "qq_process_get_buddies_and_rooms: Dangerous error! maybe protocol changed, notify developers!");
+ "qq_process_get_buddies_and_rooms: Dangerous error! maybe protocol changed, notify developers!\n");
}
purple_debug_info("QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position);
diff --git a/libpurple/protocols/qq/buddy_opt.c b/libpurple/protocols/qq/buddy_opt.c
index f33ec7615b..2d3e73d4f5 100644
--- a/libpurple/protocols/qq/buddy_opt.c
+++ b/libpurple/protocols/qq/buddy_opt.c
@@ -805,7 +805,7 @@ void qq_process_add_buddy_no_auth(PurpleConnection *gc,
dest_uid = segments[0];
reply = segments[1];
if (strtoul(dest_uid, NULL, 10) != qd->uid) { /* should not happen */
- purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", dest_uid);
+ purple_debug_error("QQ", "Add buddy reply is to [%s], not me!\n", dest_uid);
g_strfreev(segments);
return;
}
@@ -822,7 +822,7 @@ void qq_process_add_buddy_no_auth(PurpleConnection *gc,
}
qq_request_get_buddies_online(gc, 0, 0);
- purple_debug_info("QQ", "Successed adding into %u's buddy list", uid);
+ purple_debug_info("QQ", "Successed adding into %u's buddy list\n", uid);
g_strfreev(segments);
return;
}
@@ -868,7 +868,7 @@ void qq_process_add_buddy_no_auth_ex(PurpleConnection *gc,
g_return_if_fail(dest_uid == uid);
if (reply == 0x99) {
- purple_debug_info("QQ", "Successed adding buddy %u\n", uid);
+ purple_debug_info("QQ", "Successfully added buddy %u\n", uid);
qq_buddy_find_or_new(gc, uid);
qq_request_buddy_info(gc, uid, 0, 0);
@@ -882,7 +882,7 @@ void qq_process_add_buddy_no_auth_ex(PurpleConnection *gc,
}
if (reply != 0) {
- purple_debug_info("QQ", "Failed adding buddy %u, Unknow reply 0x%02X\n",
+ purple_debug_info("QQ", "Failed adding buddy %u, Unknown reply 0x%02X\n",
uid, reply);
}
diff --git a/libpurple/protocols/qq/file_trans.c b/libpurple/protocols/qq/file_trans.c
index bbcdb8da68..1ee9a3172c 100644
--- a/libpurple/protocols/qq/file_trans.c
+++ b/libpurple/protocols/qq/file_trans.c
@@ -325,7 +325,7 @@ void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, guint32
}
if (bytes != bytes_expected) {
- purple_debug_error("QQ", "qq_send_file_ctl_packet: Expected to get %d bytes, but get %d",
+ purple_debug_error("QQ", "qq_send_file_ctl_packet: Expected to get %d bytes, but get %d\n",
bytes_expected, bytes);
return;
}
@@ -334,7 +334,7 @@ void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, guint32
raw_data, bytes,
"sending packet[%s]:", qq_get_file_cmd_desc(packet_type));
- encrypted = g_newa(guint8, bytes + 16);
+ encrypted = g_newa(guint8, bytes + 17);
encrypted_len = qq_encrypt(encrypted, raw_data, bytes, info->file_session_key);
/*debug: try to decrypt it */
@@ -342,7 +342,7 @@ void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, guint32
guint8 *buf;
int buflen;
hex_dump = hex_dump_to_str(encrypted, encrypted_len);
- purple_debug_info("QQ", "encrypted packet: \n%s", hex_dump);
+ purple_debug_info("QQ", "encrypted packet: \n%s\n", hex_dump);
g_free(hex_dump);
buf = g_newa(guint8, MAX_PACKET_SIZE);
buflen = encrypted_len;
@@ -352,7 +352,7 @@ void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, guint32
purple_debug_info("QQ", "checksum ok\n");
hex_dump = hex_dump_to_str(buf, buflen);
- purple_debug_info("QQ", "decrypted packet: \n%s", hex_dump);
+ purple_debug_info("QQ", "decrypted packet: \n%s\n", hex_dump);
g_free(hex_dump);
} else {
purple_debug_info("QQ", "decrypt fail\n");
@@ -820,6 +820,6 @@ void qq_process_recv_file(PurpleConnection *gc, guint8 *data, gint len)
_qq_process_recv_file_data(gc, data + bytes, len - bytes);
break;
default:
- purple_debug_info("QQ", "unknown packet tag");
+ purple_debug_info("QQ", "unknown packet tag\n");
}
}
diff --git a/libpurple/protocols/qq/group_im.c b/libpurple/protocols/qq/group_im.c
index 2c4ef4d31c..cba79accf5 100644
--- a/libpurple/protocols/qq/group_im.c
+++ b/libpurple/protocols/qq/group_im.c
@@ -185,7 +185,7 @@ void qq_room_got_chat_in(PurpleConnection *gc,
}
if (NULL == conv) {
- purple_debug_info("QQ", "Conversion of %u is not open, missing from %d:/n%s/v",
+ purple_debug_info("QQ", "Conversion of %u is not open, missing from %d:/n%s/v\n",
room_id, uid_from, msg);
return;
}
diff --git a/libpurple/protocols/qq/group_internal.c b/libpurple/protocols/qq/group_internal.c
index e8f0645f69..5bc2c0f08b 100644
--- a/libpurple/protocols/qq/group_internal.c
+++ b/libpurple/protocols/qq/group_internal.c
@@ -188,7 +188,7 @@ void qq_room_remove(PurpleConnection *gc, guint32 id)
g_return_if_fail (gc != NULL && gc->proto_data != NULL);
qd = (qq_data *) gc->proto_data;
- purple_debug_info("QQ", "Find and remove room data, id %u", id);
+ purple_debug_info("QQ", "Find and remove room data, id %u\n", id);
rmd = qq_room_data_find(gc, id);
g_return_if_fail (rmd != NULL);
@@ -196,7 +196,7 @@ void qq_room_remove(PurpleConnection *gc, guint32 id)
qd->groups = g_list_remove(qd->groups, rmd);
room_data_free(rmd);
- purple_debug_info("QQ", "Find and remove chat, ext_id %u", ext_id);
+ purple_debug_info("QQ", "Find and remove chat, ext_id %u\n", ext_id);
num_str = g_strdup_printf("%u", ext_id);
chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str);
g_free(num_str);
diff --git a/libpurple/protocols/qq/qq_base.c b/libpurple/protocols/qq/qq_base.c
index 511a98e6a3..969e698fe2 100644
--- a/libpurple/protocols/qq/qq_base.c
+++ b/libpurple/protocols/qq/qq_base.c
@@ -245,10 +245,10 @@ void qq_request_login(PurpleConnection *gc)
g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
- raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
- memset(raw_data, 0, MAX_PACKET_SIZE - 16);
+ raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
+ memset(raw_data, 0, MAX_PACKET_SIZE - 17);
- encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
+ encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
bytes = 0;
/* now generate the encrypted data
@@ -609,7 +609,7 @@ void qq_request_get_server(PurpleConnection *gc)
raw_data = g_newa(guint8, 128);
memset(raw_data, 0, 128);
- encrypted = g_newa(guint8, 128 + 16); /* 16 bytes more */
+ encrypted = g_newa(guint8, 128 + 17); /* 17 bytes more */
bytes = 0;
if (qd->redirect == NULL) {
@@ -682,10 +682,10 @@ void qq_request_token_ex(PurpleConnection *gc)
g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
- raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
- memset(raw_data, 0, MAX_PACKET_SIZE - 16);
+ raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
+ memset(raw_data, 0, MAX_PACKET_SIZE - 17);
- encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
+ encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
bytes = 0;
bytes += qq_put8(raw_data + bytes, qd->ld.token_len);
@@ -721,10 +721,10 @@ void qq_request_token_ex_next(PurpleConnection *gc)
g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
- raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
- memset(raw_data, 0, MAX_PACKET_SIZE - 16);
+ raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
+ memset(raw_data, 0, MAX_PACKET_SIZE - 17);
- encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
+ encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
bytes = 0;
bytes += qq_put8(raw_data + bytes, qd->ld.token_len);
@@ -765,10 +765,10 @@ static void request_token_ex_code(PurpleConnection *gc,
g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
g_return_if_fail(code != NULL && code_len > 0);
- raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
- memset(raw_data, 0, MAX_PACKET_SIZE - 16);
+ raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
+ memset(raw_data, 0, MAX_PACKET_SIZE - 17);
- encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
+ encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
bytes = 0;
bytes += qq_put8(raw_data + bytes, qd->ld.token_len);
@@ -998,10 +998,10 @@ void qq_request_check_pwd(PurpleConnection *gc)
g_return_if_fail(qd->ld.token_ex != NULL && qd->ld.token_ex_len > 0);
- raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
- memset(raw_data, 0, MAX_PACKET_SIZE - 16);
+ raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
+ memset(raw_data, 0, MAX_PACKET_SIZE - 17);
- encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
+ encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
/* Encrypted password and put in encrypted */
bytes = 0;
@@ -1166,10 +1166,10 @@ void qq_request_login_2007(PurpleConnection *gc)
g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
- raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
- memset(raw_data, 0, MAX_PACKET_SIZE - 16);
+ raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
+ memset(raw_data, 0, MAX_PACKET_SIZE - 17);
- encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
+ encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
/* Encrypted password and put in encrypted */
bytes = 0;
@@ -1342,10 +1342,10 @@ void qq_request_login_2008(PurpleConnection *gc)
g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
- raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
- memset(raw_data, 0, MAX_PACKET_SIZE - 16);
+ raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
+ memset(raw_data, 0, MAX_PACKET_SIZE - 17);
- encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
+ encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
/* Encrypted password and put in encrypted */
bytes = 0;
diff --git a/libpurple/protocols/qq/qq_crypt.c b/libpurple/protocols/qq/qq_crypt.c
index c6a0914ef4..07f1d2a869 100644
--- a/libpurple/protocols/qq/qq_crypt.c
+++ b/libpurple/protocols/qq/qq_crypt.c
@@ -19,7 +19,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*
* QQ encryption algorithm
@@ -171,7 +171,12 @@ static inline void encrypt_out(guint8 *crypted, const gint crypted_len, const gu
}
}
-/* length of crypted buffer must be plain_len + 16*/
+/* length of crypted buffer must be plain_len + 17*/
+/*
+ * The above comment used to say "plain_len + 16", but based on the
+ * behavior of the function that is wrong. If you give this function
+ * a plain string with len%8 = 7 then the returned length is len+17
+ */
gint qq_encrypt(guint8* crypted, const guint8* const plain, const gint plain_len, const guint8* const key)
{
guint8 *crypted_ptr = crypted; /* current position of dest */
diff --git a/libpurple/protocols/qq/qq_crypt.h b/libpurple/protocols/qq/qq_crypt.h
index dbcda15761..e66f4fb695 100644
--- a/libpurple/protocols/qq/qq_crypt.h
+++ b/libpurple/protocols/qq/qq_crypt.h
@@ -19,7 +19,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef _QQ_CRYPT_H_
diff --git a/libpurple/protocols/qq/qq_network.c b/libpurple/protocols/qq/qq_network.c
index da3f033d45..0c31b608b4 100644
--- a/libpurple/protocols/qq/qq_network.c
+++ b/libpurple/protocols/qq/qq_network.c
@@ -968,7 +968,7 @@ gboolean connect_to_server(PurpleConnection *gc, gchar *server, gint port)
qd->conn_data = purple_proxy_connect_udp(gc, account, server, port, connect_cb, gc);
}
if ( qd->conn_data == NULL ) {
- purple_debug_error("QQ", "Couldn't create socket");
+ purple_debug_error("QQ", "Couldn't create socket\n");
return FALSE;
}
#else
@@ -978,7 +978,7 @@ gboolean connect_to_server(PurpleConnection *gc, gchar *server, gint port)
if(qd->use_tcp) {
qd->conn_data = purple_proxy_connect(gc, account, server, port, connect_cb, gc);
if ( qd->conn_data == NULL ) {
- purple_debug_error("QQ", "Unable to connect.");
+ purple_debug_error("QQ", "Unable to connect.\n");
return FALSE;
}
return TRUE;
@@ -987,7 +987,7 @@ gboolean connect_to_server(PurpleConnection *gc, gchar *server, gint port)
purple_debug_info("QQ", "UDP Connect to %s:%d\n", server, port);
qd->udp_query_data = purple_dnsquery_a(server, port, udp_host_resolved, gc);
if ( qd->udp_query_data == NULL ) {
- purple_debug_error("QQ", "Could not resolve hostname");
+ purple_debug_error("QQ", "Could not resolve hostname\n");
return FALSE;
}
#endif
@@ -1146,8 +1146,8 @@ static gint send_cmd_detail(PurpleConnection *gc, guint16 cmd, guint16 seq,
qd = (qq_data *)gc->proto_data;
g_return_val_if_fail(data != NULL && data_len > 0, -1);
- /* at most 16 bytes more */
- encrypted = g_newa(guint8, data_len + 16);
+ /* at most 17 bytes more */
+ encrypted = g_newa(guint8, data_len + 17);
encrypted_len = qq_encrypt(encrypted, data, data_len, qd->session_key);
if (encrypted_len < 16) {
purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n",
@@ -1223,8 +1223,8 @@ gint qq_send_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8
purple_debug_info("QQ", "<== [SRV-%05d] %s(0x%04X), datalen %d\n",
seq, qq_get_cmd_desc(cmd), cmd, data_len);
#endif
- /* at most 16 bytes more */
- encrypted = g_newa(guint8, data_len + 16);
+ /* at most 17 bytes more */
+ encrypted = g_newa(guint8, data_len + 17);
encrypted_len = qq_encrypt(encrypted, data, data_len, qd->session_key);
if (encrypted_len < 16) {
purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n",
@@ -1270,8 +1270,8 @@ static gint send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id
seq = qd->send_seq;
/* Encrypt to encrypted with session_key */
- /* at most 16 bytes more */
- encrypted = g_newa(guint8, buf_len + 16);
+ /* at most 17 bytes more */
+ encrypted = g_newa(guint8, buf_len + 17);
encrypted_len = qq_encrypt(encrypted, buf, buf_len, qd->session_key);
if (encrypted_len < 16) {
purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] %s (0x%02X)\n",
diff --git a/libpurple/protocols/qq/qq_process.c b/libpurple/protocols/qq/qq_process.c
index 14fd6fb846..f90ba20304 100644
--- a/libpurple/protocols/qq/qq_process.c
+++ b/libpurple/protocols/qq/qq_process.c
@@ -426,7 +426,7 @@ static void do_server_notice(PurpleConnection *gc, gchar *from, gchar *to,
if (qd->is_show_notice) {
qq_got_message(gc, content);
} else {
- purple_debug_info("QQ", "QQ Server notice from %s:\n%s", from, msg_utf8);
+ purple_debug_info("QQ", "QQ Server notice from %s:\n%s\n", from, msg_utf8);
}
g_free(msg_utf8);
g_free(title);
diff --git a/libpurple/protocols/qq/send_file.c b/libpurple/protocols/qq/send_file.c
index c5041b9186..7bc427836b 100644
--- a/libpurple/protocols/qq/send_file.c
+++ b/libpurple/protocols/qq/send_file.c
@@ -390,7 +390,7 @@ static void _qq_xfer_init_socket(PurpleXfer *xfer)
info->local_real_ip = 0x7f000001;
*/
info->local_real_ip = g_ntohl(inet_addr(purple_network_get_my_ip(-1)));
- purple_debug_info("QQ", "local real ip is %x", info->local_real_ip);
+ purple_debug_info("QQ", "local real ip is %x\n", info->local_real_ip);
for (i = 0; i < 2; i++) {
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
@@ -558,7 +558,7 @@ static void _qq_send_packet_file_reject (PurpleConnection *gc, guint32 to_uid)
guint8 *raw_data;
gint packet_len, bytes;
- purple_debug_info("_qq_send_packet_file_reject", "start");
+ purple_debug_info("_qq_send_packet_file_reject", "start\n");
qd = (qq_data *) gc->proto_data;
packet_len = 64;
@@ -730,7 +730,7 @@ void qq_process_recv_file_cancel (guint8 *data, gint data_len,
*/
filename = g_path_get_basename(purple_xfer_get_local_filename(qd->xfer));
msg = g_strdup_printf
- (_("%d canceled the transfer of %s"),
+ (_("%d cancelled the transfer of %s"),
sender_uid, filename);
purple_notify_warning (gc, _("File Send"), msg, NULL);
diff --git a/libpurple/protocols/simple/Makefile.am b/libpurple/protocols/simple/Makefile.am
index 8e23459fc5..94b21d01e3 100644
--- a/libpurple/protocols/simple/Makefile.am
+++ b/libpurple/protocols/simple/Makefile.am
@@ -13,7 +13,7 @@ AM_CFLAGS = $(st)
libsimple_la_LDFLAGS = -module -avoid-version
-if STATIC_MSN
+if STATIC_SIMPLE
st = -DPURPLE_STATIC_PRPL
noinst_LTLIBRARIES = libsimple.la
diff --git a/libpurple/protocols/yahoo/libyahoo.c b/libpurple/protocols/yahoo/libyahoo.c
index 1e1b890da6..2f78e562d2 100644
--- a/libpurple/protocols/yahoo/libyahoo.c
+++ b/libpurple/protocols/yahoo/libyahoo.c
@@ -278,7 +278,7 @@ static PurplePluginInfo info =
NULL, /**< dependencies */
PURPLE_PRIORITY_DEFAULT, /**< priority */
"prpl-yahoo", /**< id */
- "Yahoo!", /**< name */
+ "Yahoo", /**< name */
DISPLAY_VERSION, /**< version */
/** summary */
N_("Yahoo! Protocol Plugin"),
@@ -321,12 +321,14 @@ init_plugin(PurplePlugin *plugin)
option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOO_ROOMLIST_LOCALE);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
- option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
+ option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
- option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
+ option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+ option = purple_account_option_bool_new(_("Use account proxy for SSL connections"), "proxy_ssl", FALSE);
+ prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
#if 0
option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
diff --git a/libpurple/protocols/yahoo/libyahoojp.c b/libpurple/protocols/yahoo/libyahoojp.c
index 7131dd4b10..d15001ea32 100644
--- a/libpurple/protocols/yahoo/libyahoojp.c
+++ b/libpurple/protocols/yahoo/libyahoojp.c
@@ -174,7 +174,7 @@ static PurplePluginInfo info =
NULL, /**< dependencies */
PURPLE_PRIORITY_DEFAULT, /**< priority */
"prpl-yahoojp", /**< id */
- "Yahoo! JAPAN", /**< name */
+ "Yahoo JAPAN", /**< name */
DISPLAY_VERSION, /**< version */
/** summary */
N_("Yahoo! JAPAN Protocol Plugin"),
@@ -217,12 +217,14 @@ init_plugin(PurplePlugin *plugin)
option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOOJP_ROOMLIST_LOCALE);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
- option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
+ option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
- option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
+ option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+ option = purple_account_option_bool_new(_("Use account proxy for SSL connections"), "proxy_ssl", FALSE);
+ prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
#if 0
option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
diff --git a/libpurple/protocols/yahoo/libymsg.c b/libpurple/protocols/yahoo/libymsg.c
index 485c9d3ec1..66b12f7029 100644
--- a/libpurple/protocols/yahoo/libymsg.c
+++ b/libpurple/protocols/yahoo/libymsg.c
@@ -220,7 +220,12 @@ static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt)
if (f->status == YAHOO_STATUS_IDLE) {
/* Idle may have already been set in a more precise way in case 137 */
if (f->idle == 0)
- f->idle = time(NULL);
+ {
+ if(pkt->service == YAHOO_SERVICE_STATUS_15)
+ f->idle = -1;
+ else
+ f->idle = time(NULL);
+ }
} else
f->idle = 0;
@@ -253,15 +258,20 @@ static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt)
if (f->away == 2) {
/* Idle may have already been set in a more precise way in case 137 */
if (f->idle == 0)
- f->idle = time(NULL);
+ {
+ if(pkt->service == YAHOO_SERVICE_STATUS_15)
+ f->idle = -1;
+ else
+ f->idle = time(NULL);
+ }
}
break;
- case 138: /* either we're not idle, or we are but won't say how long */
+ case 138: /* when value is 1, either we're not idle, or we are but won't say how long */
if (!f)
break;
- if (f->idle)
+ if( (strtol(pair->value, NULL, 10) == 1) && (f->idle) )
f->idle = -1;
break;
case 137: /* usually idle time in seconds, sometimes login time */
@@ -1839,11 +1849,12 @@ static void yahoo_auth16_stage1_cb(PurpleUtilFetchUrlData *unused, gpointer user
PurpleAccount *account = purple_connection_get_account(gc);
char *url = NULL;
gboolean yahoojp = yahoo_is_japan(account);
+ gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
url = g_strdup_printf(yahoojp ? YAHOOJP_LOGIN_URL : YAHOO_LOGIN_URL, token);
- url_data = purple_util_fetch_url_request_len_with_account(account, url,
- TRUE, YAHOO_CLIENT_USERAGENT, TRUE, NULL, FALSE, -1,
- yahoo_auth16_stage2, auth_data);
+ url_data = purple_util_fetch_url_request_len_with_account(
+ proxy_ssl ? account : NULL, url, TRUE, YAHOO_CLIENT_USERAGENT,
+ TRUE, NULL, FALSE, -1, yahoo_auth16_stage2, auth_data);
g_free(url);
g_free(token);
}
@@ -1852,12 +1863,14 @@ static void yahoo_auth16_stage1_cb(PurpleUtilFetchUrlData *unused, gpointer user
static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed)
{
+ PurpleAccount *account = purple_connection_get_account(gc);
PurpleUtilFetchUrlData *url_data = NULL;
struct yahoo_auth_data *auth_data = NULL;
char *url = NULL;
char *encoded_username;
char *encoded_password;
- gboolean yahoojp;
+ gboolean yahoojp = yahoo_is_japan(account);
+ gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
purple_debug_info("yahoo", "Authentication: In yahoo_auth16_stage1\n");
@@ -1866,7 +1879,6 @@ static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed)
return;
}
- yahoojp = yahoo_is_japan(purple_connection_get_account(gc));
auth_data = g_new0(struct yahoo_auth_data, 1);
auth_data->gc = gc;
auth_data->seed = g_strdup(seed);
@@ -1879,7 +1891,7 @@ static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed)
g_free(encoded_username);
url_data = purple_util_fetch_url_request_len_with_account(
- purple_connection_get_account(gc), url, TRUE,
+ proxy_ssl ? account : NULL, url, TRUE,
YAHOO_CLIENT_USERAGENT, TRUE, NULL, FALSE, -1,
yahoo_auth16_stage1_cb, auth_data);
@@ -2013,11 +2025,11 @@ static void yahoo_process_ignore(PurpleConnection *gc, struct yahoo_packet *pkt)
break;
}
case 2:
- purple_debug_info("yahoo", "Server reported that %s is already in the ignore list.",
+ purple_debug_info("yahoo", "Server reported that %s is already in the ignore list.\n",
who);
break;
case 3:
- purple_debug_info("yahoo", "Server reported that %s is not in the ignore list; could not delete",
+ purple_debug_info("yahoo", "Server reported that %s is not in the ignore list; could not delete\n",
who);
case 0:
default:
@@ -2077,21 +2089,24 @@ static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pk
if (!purple_account_get_remember_password(account))
purple_account_set_password(account, NULL);
- msg = g_strdup(_("Incorrect password"));
+ msg = g_strdup(_("Invalid username or password"));
reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
break;
case 14:
- msg = g_strdup(_("Your account is locked, please log in to the Yahoo! website."));
+ msg = g_strdup(_("Your account has been locked due to too many failed login attempts."
+ " Please try logging into the Yahoo! website."));
reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
break;
case 52:
/* See #9660. As much as we know, reconnecting shouldn't hurt */
purple_debug_info("yahoo", "Got error 52, Set to autoreconnect\n");
- msg = g_strdup_printf(_("Unknown error"));
+ msg = g_strdup_printf(_("Unknown error 52. Reconnecting should fix this."));
reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
break;
case 1013:
- msg = g_strdup(_("Invalid username"));
+ msg = g_strdup(_("Error 1013: The username you have entered is invalid."
+ " The most common cause of this error is entering your email"
+ " address instead of your Yahoo! ID."));
reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
break;
default:
@@ -4271,7 +4286,7 @@ int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, Purpl
}
}
- msn = !g_strncasecmp(who, "msn/", 4);
+ msn = !g_ascii_strncasecmp(who, "msn/", 4);
if( strncmp(who, "+", 1) == 0 ) {
/* we have an sms to be sent */
@@ -4395,7 +4410,7 @@ unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypi
{
YahooData *yd = gc->proto_data;
struct yahoo_p2p_data *p2p_data;
- gboolean msn = !g_strncasecmp(who, "msn/", 4);
+ gboolean msn = !g_ascii_strncasecmp(who, "msn/", 4);
struct yahoo_packet *pkt = NULL;
/* Don't do anything if sms is being typed */
@@ -4420,7 +4435,7 @@ unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypi
else
yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc),
14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
- 5, who+4, 1002, "1");
+ 5, who, 1002, "1");
yahoo_packet_send_and_free(pkt, yd);
}
@@ -4495,8 +4510,12 @@ void yahoo_set_status(PurpleAccount *account, PurpleStatus *status)
if (purple_presence_is_idle(presence))
yahoo_packet_hash_str(pkt, 47, "2");
- else if (!purple_status_is_available(status))
- yahoo_packet_hash_str(pkt, 47, "1");
+ else {
+ if (!purple_status_is_available(status))
+ yahoo_packet_hash_str(pkt, 47, "1");
+ else
+ yahoo_packet_hash_str(pkt, 47, "0");
+ }
yahoo_packet_send_and_free(pkt, yd);
@@ -4517,6 +4536,7 @@ void yahoo_set_idle(PurpleConnection *gc, int idle)
struct yahoo_packet *pkt = NULL;
char *msg = NULL, *msg2 = NULL;
PurpleStatus *status = NULL;
+ gboolean invisible = FALSE;
if (idle && yd->current_status != YAHOO_STATUS_CUSTOM)
yd->current_status = YAHOO_STATUS_IDLE;
@@ -4525,9 +4545,15 @@ void yahoo_set_idle(PurpleConnection *gc, int idle)
yd->current_status = get_yahoo_status_from_purple_status(status);
}
+ invisible = !( purple_presence_is_available(purple_account_get_presence(purple_connection_get_account(gc))) );
+
pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
- yahoo_packet_hash_int(pkt, 10, yd->current_status);
+ if (!idle && invisible)
+ yahoo_packet_hash_int(pkt, 10, YAHOO_STATUS_AVAILABLE);
+ else
+ yahoo_packet_hash_int(pkt, 10, yd->current_status);
+
if (yd->current_status == YAHOO_STATUS_CUSTOM) {
const char *tmp;
if (status == NULL)
@@ -4550,8 +4576,6 @@ void yahoo_set_idle(PurpleConnection *gc, int idle)
if (idle)
yahoo_packet_hash_str(pkt, 47, "2");
- else if (!purple_presence_is_available(purple_account_get_presence(purple_connection_get_account(gc))))
- yahoo_packet_hash_str(pkt, 47, "1");
yahoo_packet_send_and_free(pkt, yd);
@@ -4668,7 +4692,7 @@ void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g)
return;
f = yahoo_friend_find(gc, bname);
- msn = !g_strncasecmp(bname, "msn/", 4);
+ msn = !g_ascii_strncasecmp(bname, "msn/", 4);
g = purple_buddy_get_group(buddy);
if (g)
@@ -4766,6 +4790,7 @@ void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g
void yahoo_add_deny(PurpleConnection *gc, const char *who) {
YahooData *yd = (YahooData *)gc->proto_data;
struct yahoo_packet *pkt;
+ gboolean msn = FALSE;
if (!yd->logged_in)
return;
@@ -4773,15 +4798,21 @@ void yahoo_add_deny(PurpleConnection *gc, const char *who) {
if (!who || who[0] == '\0')
return;
+ msn = !g_ascii_strncasecmp(who, "msn/", 4);
pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc),
- 7, who, 13, "1");
+
+ if(msn)
+ yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc), 7, who+4, 241, "2", 13, "1");
+ else
+ yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "1");
+
yahoo_packet_send_and_free(pkt, yd);
}
void yahoo_rem_deny(PurpleConnection *gc, const char *who) {
YahooData *yd = (YahooData *)gc->proto_data;
struct yahoo_packet *pkt;
+ gboolean msn = FALSE;
if (!yd->logged_in)
return;
@@ -4789,8 +4820,14 @@ void yahoo_rem_deny(PurpleConnection *gc, const char *who) {
if (!who || who[0] == '\0')
return;
+ msn = !g_ascii_strncasecmp(who, "msn/", 4);
pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "2");
+
+ if(msn)
+ yahoo_packet_hash(pkt, "ssss", 1, purple_connection_get_display_name(gc), 7, who+4, 241, "2", 13, "2");
+ else
+ yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "2");
+
yahoo_packet_send_and_free(pkt, yd);
}
diff --git a/libpurple/protocols/yahoo/libymsg.h b/libpurple/protocols/yahoo/libymsg.h
index c636ab48c9..f94dedbe32 100644
--- a/libpurple/protocols/yahoo/libymsg.h
+++ b/libpurple/protocols/yahoo/libymsg.h
@@ -280,6 +280,27 @@ typedef struct {
void yahoo_init_colorht(void);
void yahoo_dest_colorht(void);
char *yahoo_codes_to_html(const char *x);
+
+/**
+ * This function takes a normal HTML message and converts it to the message
+ * format used by Yahoo, which uses a frankensteinish combination of ANSI
+ * escape codes and broken HTML.
+ *
+ * It results in slightly different output than would be sent by official
+ * Yahoo clients. The two main differences are:
+ *
+ * 1. We always close all tags, whereas official Yahoo clients leave tags
+ * dangling open at the end of each message (and the client treats them
+ * as closed).
+ * 2. We always close inner tags first before closing outter tags.
+ *
+ * For example, if you want to send this message:
+ * <b> bold <i> bolditalic </i></b><i> italic </i>
+ * Official Yahoo clients would send:
+ * ESC[1m bold ESC[2m bolditalic ESC[x1m italic
+ * But we will send:
+ * ESC[1m bold ESC[2m bolditalic ESC[x2mESC[x1mESC[2m italic ESC[x2m
+ */
char *yahoo_html_to_codes(const char *src);
gboolean
diff --git a/libpurple/protocols/yahoo/util.c b/libpurple/protocols/yahoo/util.c
index 6fdd8942b5..2299e03ea6 100644
--- a/libpurple/protocols/yahoo/util.c
+++ b/libpurple/protocols/yahoo/util.c
@@ -513,7 +513,7 @@ char *yahoo_codes_to_html(const char *x)
int i, j;
gboolean no_more_gt_brackets = FALSE;
const char *match;
- gchar *xmlstr1, *xmlstr2;
+ gchar *xmlstr1, *xmlstr2, *esc;
x_len = strlen(x);
html = xmlnode_new("html");
@@ -553,12 +553,15 @@ char *yahoo_codes_to_html(const char *x)
#endif /* !USE_CSS_FORMATTING */
} else if ((match = g_hash_table_lookup(esc_codes_ht, code))) {
- gboolean is_closing_tag;
- gchar *tag_name;
-
- tag_name = yahoo_markup_get_tag_name(match, &is_closing_tag);
- yahoo_codes_to_html_add_tag(&cur, match, is_closing_tag, tag_name, FALSE);
- g_free(tag_name);
+ /* Some tags are in the hash table only because we
+ * want to ignore them */
+ if (match[0] != '\0') {
+ gboolean is_closing_tag;
+ gchar *tag_name;
+ tag_name = yahoo_markup_get_tag_name(match, &is_closing_tag);
+ yahoo_codes_to_html_add_tag(&cur, match, is_closing_tag, tag_name, FALSE);
+ g_free(tag_name);
+ }
} else {
purple_debug_error("yahoo",
@@ -608,7 +611,6 @@ char *yahoo_codes_to_html(const char *x)
if (match == NULL) {
/* Unknown tag. The user probably typed a less-than sign */
g_string_append_c(cdata, x[i]);
- no_more_gt_brackets = TRUE;
g_free(tag);
g_free(tag_name);
break;
@@ -657,7 +659,10 @@ char *yahoo_codes_to_html(const char *x)
xmlstr2 = g_strndup(xmlstr1 + 6, strlen(xmlstr1) - 13);
g_free(xmlstr1);
- purple_debug_misc("yahoo", "yahoo_codes_to_html: Returning string: '%s'.\n", xmlstr2);
+ esc = g_strescape(x, NULL);
+ purple_debug_misc("yahoo", "yahoo_codes_to_html(%s)=%s\n", esc, xmlstr2);
+ g_free(esc);
+
return xmlstr2;
}
@@ -666,33 +671,16 @@ char *yahoo_codes_to_html(const char *x)
#define POINT_SIZE(x) (_point_sizes [MIN ((x > 0 ? x : 1), MAX_FONT_SIZE) - 1])
static const gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 };
-enum fatype
-{
- FATYPE_SIZE,
- FATYPE_COLOR,
- FATYPE_FACE,
- FATYPE_JUNK
-};
-
typedef struct
{
- enum fatype type;
- union {
- int size;
- char *color;
- char *face;
- char *junk;
- } u;
-} fontattr;
-
-static void fontattr_free(fontattr *f)
-{
- if (f->type == FATYPE_COLOR)
- g_free(f->u.color);
- else if (f->type == FATYPE_FACE)
- g_free(f->u.face);
- g_free(f);
-}
+ gboolean bold;
+ gboolean italic;
+ gboolean underline;
+ gboolean in_link;
+ int font_size;
+ char *font_face;
+ char *font_color;
+} CurrentMsgState;
static void yahoo_htc_list_cleanup(GSList *l)
{
@@ -702,338 +690,203 @@ static void yahoo_htc_list_cleanup(GSList *l)
}
}
-static void _parse_font_tag(const char *src, GString *dest, int *i, int *j,
- int len, GSList **colors, GSList **tags, GQueue *ftattr)
+static void parse_font_tag(GString *dest, const char *tag_name, const char *tag,
+ GSList **colors, GSList **tags)
{
- int m, n, vstart;
- gboolean quote = FALSE, done = FALSE;
-
- m = *j;
-
- while (1) {
- m++;
-
- if (m >= len) {
- g_string_append(dest, &src[*i]);
- *i = len;
- break;
- }
-
- if (src[m] == '=') {
- n = vstart = m;
- while (1) {
- n++;
-
- if (n >= len) {
- m = n;
- break;
- }
-
- if (src[n] == '"') {
- if (!quote) {
- quote = TRUE;
- vstart = n;
- continue;
- } else {
- done = 1;
- }
- }
+ const char *start;
+ const char *end;
+ GData *attributes;
+ const char *attribute;
+ gboolean needendtag;
+ GString *tmp;
+
+ purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
+
+ needendtag = FALSE;
+ tmp = g_string_new(NULL);
+
+ attribute = g_datalist_get_data(&attributes, "color");
+ if (attribute != NULL) {
+ g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m");
+ g_string_append_printf(dest, "\033[%sm", attribute);
+ *colors = g_slist_prepend(*colors,
+ g_strdup_printf("\033[%sm", attribute));
+ } else {
+ /* We need to add a value to the colors stack even if we're not
+ * setting a color because we ALWAYS pop exactly 1 element from
+ * this stack for every </font> tag. If we don't add anything
+ * then we'll pop something that we shouldn't when we hit this
+ * corresponding </font>. */
+ *colors = g_slist_prepend(*colors,
+ *colors ? g_strdup((*colors)->data) : g_strdup("\033[#000000m"));
+ }
- if (!quote && ((src[n] == ' ') || (src[n] == '>')))
- done = TRUE;
-
- if (done) {
- if (!g_ascii_strncasecmp(&src[*j+1], "FACE", m - *j - 1)) {
- fontattr *f;
-
- f = g_new(fontattr, 1);
- f->type = FATYPE_FACE;
- f->u.face = g_strndup(&src[vstart+1], n-vstart-1);
- if (!ftattr)
- ftattr = g_queue_new();
- g_queue_push_tail(ftattr, f);
- m = n;
- break;
- } else if (!g_ascii_strncasecmp(&src[*j+1], "SIZE", m - *j - 1)) {
- fontattr *f;
-
- f = g_new(fontattr, 1);
- f->type = FATYPE_SIZE;
- f->u.size = POINT_SIZE(strtol(&src[vstart+1], NULL, 10));
- if (!ftattr)
- ftattr = g_queue_new();
- g_queue_push_tail(ftattr, f);
- m = n;
- break;
- } else if (!g_ascii_strncasecmp(&src[*j+1], "COLOR", m - *j - 1)) {
- fontattr *f;
-
- f = g_new(fontattr, 1);
- f->type = FATYPE_COLOR;
- f->u.color = g_strndup(&src[vstart+1], n-vstart-1);
- if (!ftattr)
- ftattr = g_queue_new();
- g_queue_push_head(ftattr, f);
- m = n;
- break;
- } else {
- fontattr *f;
-
- f = g_new(fontattr, 1);
- f->type = FATYPE_JUNK;
- f->u.junk = g_strndup(&src[*j+1], n-*j);
- if (!ftattr)
- ftattr = g_queue_new();
- g_queue_push_tail(ftattr, f);
- m = n;
- break;
- }
+ attribute = g_datalist_get_data(&attributes, "face");
+ if (attribute != NULL) {
+ needendtag = TRUE;
+ g_string_append(dest, "<font ");
+ g_string_append_printf(dest, "face=\"%s\" ", attribute);
+ }
- }
- }
+ attribute = g_datalist_get_data(&attributes, "size");
+ if (attribute != NULL) {
+ if (!needendtag) {
+ needendtag = TRUE;
+ g_string_append(dest, "<font ");
}
- if (src[m] == ' ')
- *j = m;
-
- if (src[m] == '>') {
- gboolean needendtag = FALSE;
- fontattr *f;
- GString *tmp = g_string_new(NULL);
-
- if (!g_queue_is_empty(ftattr)) {
- while ((f = g_queue_pop_tail(ftattr))) {
- switch (f->type) {
- case FATYPE_SIZE:
- if (!needendtag) {
- needendtag = TRUE;
- g_string_append(dest, "<font ");
- }
-
- g_string_append_printf(dest, "size=\"%d\" ", f->u.size);
- break;
- case FATYPE_FACE:
- if (!needendtag) {
- needendtag = TRUE;
- g_string_append(dest, "<font ");
- }
-
- g_string_append_printf(dest, "face=\"%s\" ", f->u.face);
- break;
- case FATYPE_JUNK:
- if (!needendtag) {
- needendtag = TRUE;
- g_string_append(dest, "<font ");
- }
-
- g_string_append(dest, f->u.junk);
- break;
-
- case FATYPE_COLOR:
- if (needendtag) {
- g_string_append(tmp, "</font>");
- dest->str[dest->len-1] = '>';
- needendtag = TRUE;
- }
-
- g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m");
- g_string_append_printf(dest, "\033[%sm", f->u.color);
- *colors = g_slist_prepend(*colors,
- g_strdup_printf("\033[%sm", f->u.color));
- break;
- }
- fontattr_free(f);
- }
-
- g_queue_free(ftattr);
- ftattr = NULL;
-
- if (needendtag) {
- dest->str[dest->len-1] = '>';
- *tags = g_slist_prepend(*tags, g_strdup("</font>"));
- g_string_free(tmp, TRUE);
- } else {
- *tags = g_slist_prepend(*tags, tmp->str);
- g_string_free(tmp, FALSE);
- }
- }
+ g_string_append_printf(dest, "size=\"%d\" ",
+ POINT_SIZE(strtol(attribute, NULL, 10)));
+ }
- *i = *j = m;
- break;
- }
+ if (needendtag) {
+ dest->str[dest->len-1] = '>';
+ *tags = g_slist_prepend(*tags, g_strdup("</font>"));
+ g_string_free(tmp, TRUE);
+ } else {
+ *tags = g_slist_prepend(*tags, tmp->str);
+ g_string_free(tmp, FALSE);
}
+
+ g_datalist_clear(&attributes);
}
char *yahoo_html_to_codes(const char *src)
{
GSList *colors = NULL;
+
+ /**
+ * A stack of char*s where each char* is the string that should be
+ * appended to dest in order to close all the tags that were opened
+ * by a <font> tag.
+ */
GSList *tags = NULL;
+
size_t src_len;
int i, j;
GString *dest;
char *esc;
- GQueue *ftattr = NULL;
- gboolean no_more_specials = FALSE;
+ gboolean no_more_gt_brackets = FALSE;
+ gchar *tag, *tag_name;
+ gboolean is_closing_tag;
+ CurrentMsgState current_state;
+
+ memset(&current_state, 0, sizeof(current_state));
src_len = strlen(src);
dest = g_string_sized_new(src_len);
for (i = 0; i < src_len; i++) {
-
- if (src[i] == '<' && !no_more_specials) {
+ if (src[i] == '<' && !no_more_gt_brackets) {
+ /* The start of an HTML tag */
j = i;
- while (1) {
- j++;
+ while (j++ < src_len) {
+ if (src[j] != '>') {
+ if (src[j] == '"') {
+ /* We're inside a quoted attribute value. Skip to the end */
+ j++;
+ while (j != src_len && src[j] != '"')
+ j++;
+ } else if (src[j] == '\'') {
+ /* We're inside a quoted attribute value. Skip to the end */
+ j++;
+ while (j != src_len && src[j] != '\'')
+ j++;
+ }
+ if (j != src_len)
+ /* Keep looking for the end of this tag */
+ continue;
- if (j >= src_len) { /* no '>' */
+ /* This < has no corresponding > */
g_string_append_c(dest, src[i]);
- no_more_specials = TRUE;
+ no_more_gt_brackets = TRUE;
break;
}
- if (src[j] == '<') {
- /* FIXME: This doesn't convert outgoing entities.
- * However, I suspect this case may never
- * happen anymore because of the entities.
+ tag = g_strndup(src + i, j - i + 1);
+ tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag);
+
+ if (g_str_equal(tag_name, "a")) {
+ const char *start;
+ const char *end;
+ GData *attributes;
+ const char *attribute;
+
+ /*
+ * TODO: Ideally we would replace this:
+ * <a href="http://pidgin.im/">Pidgin</a>
+ * with this:
+ * Pidgin (http://pidgin.im/)
+ *
+ * Currently we drop the text within the <a> tag and
+ * just show the URL. Doing it the fancy way is
+ * complicated when dealing with HTML tags within the
+ * <a> tag.
*/
- g_string_append_len(dest, &src[i], j - i);
- i = j - 1;
- if (ftattr) {
- fontattr *f;
-
- while ((f = g_queue_pop_head(ftattr)))
- fontattr_free(f);
- g_queue_free(ftattr);
- ftattr = NULL;
- }
- break;
- }
- if (src[j] == ' ') {
- if (!g_ascii_strncasecmp(&src[i+1], "BODY", j - i - 1)) {
- char *t = strchr(&src[j], '>');
- if (!t) {
- g_string_append(dest, &src[i]);
- i = src_len;
- break;
- } else {
- i = t - src;
- break;
- }
- } else if (!g_ascii_strncasecmp(&src[i+1], "A HREF=\"", j - i - 1)) {
- j += 7;
- g_string_append(dest, "\033[lm");
- if (purple_str_has_prefix(src + j, "mailto:"))
- j += sizeof("mailto:") - 1;
- while (1) {
- g_string_append_c(dest, src[j]);
- if (++j >= src_len) {
- i = src_len;
- break;
- }
- if (src[j] == '"') {
- g_string_append(dest, "\033[xlm");
- while (1) {
- if (++j >= src_len) {
- i = src_len;
- break;
- }
- if (!g_ascii_strncasecmp(&src[j], "</A>", 4)) {
- j += 3;
- break;
- }
- }
- i = j;
- break;
- }
- }
- } else if (!g_ascii_strncasecmp(&src[i+1], "SPAN", j - i - 1)) { /* drop span tags */
- while (1) {
- if (++j >= src_len) {
- g_string_append(dest, &src[i]);
- i = src_len;
- break;
- }
- if (src[j] == '>') {
- i = j;
- break;
- }
- }
- } else if (g_ascii_strncasecmp(&src[i+1], "FONT", j - i - 1)) { /* not interested! */
- while (1) {
- if (++j >= src_len) {
- g_string_append(dest, &src[i]);
- i = src_len;
- break;
- }
- if (src[j] == '>') {
- g_string_append_len(dest, &src[i], j - i + 1);
- i = j;
- break;
- }
- }
- } else { /* yay we have a font tag */
- _parse_font_tag(src, dest, &i, &j, src_len, &colors, &tags, ftattr);
+ /* Append the URL */
+ purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
+ attribute = g_datalist_get_data(&attributes, "href");
+ if (attribute != NULL) {
+ if (purple_str_has_prefix(attribute, "mailto:"))
+ attribute += 7;
+ g_string_append(dest, attribute);
}
-
- break;
- }
-
- if (src[j] == '>') {
- /* This has some problems like the FIXME for the
- * '<' case. and like that case, I suspect the case
- * that this has problems is won't happen anymore anyway.
- */
- int sublen = j - i - 1;
-
- if (sublen) {
- if (!g_ascii_strncasecmp(&src[i+1], "B", sublen)) {
- g_string_append(dest, "\033[1m");
- } else if (!g_ascii_strncasecmp(&src[i+1], "/B", sublen)) {
- g_string_append(dest, "\033[x1m");
- } else if (!g_ascii_strncasecmp(&src[i+1], "I", sublen)) {
- g_string_append(dest, "\033[2m");
- } else if (!g_ascii_strncasecmp(&src[i+1], "/I", sublen)) {
- g_string_append(dest, "\033[x2m");
- } else if (!g_ascii_strncasecmp(&src[i+1], "U", sublen)) {
- g_string_append(dest, "\033[4m");
- } else if (!g_ascii_strncasecmp(&src[i+1], "/U", sublen)) {
- g_string_append(dest, "\033[x4m");
- } else if (!g_ascii_strncasecmp(&src[i+1], "/A", sublen)) {
- g_string_append(dest, "\033[xlm");
- } else if (!g_ascii_strncasecmp(&src[i+1], "BR", sublen)) {
- g_string_append_c(dest, '\n');
- } else if (!g_ascii_strncasecmp(&src[i+1], "/BODY", sublen)) {
- /* mmm, </body> tags. *BURP* */
- } else if (!g_ascii_strncasecmp(&src[i+1], "/SPAN", sublen)) {
- /* </span> tags. dangerously close to </spam> */
- } else if (!g_ascii_strncasecmp(&src[i+1], "/FONT", sublen) && tags != NULL) {
- char *etag;
-
- etag = tags->data;
- tags = g_slist_delete_link(tags, tags);
- if (etag) {
- g_string_append(dest, etag);
- if (!strcmp(etag, "</font>")) {
- if (colors != NULL) {
- g_free(colors->data);
- colors = g_slist_delete_link(colors, colors);
- }
- }
- g_free(etag);
- }
- } else {
- g_string_append_len(dest, &src[i], j - i + 1);
+ g_datalist_clear(&attributes);
+
+ /* Skip past the closing </a> tag */
+ end = purple_strcasestr(src + j, "</a>");
+ if (end != NULL)
+ j = end - src + 3;
+
+ } else if (g_str_equal(tag_name, "font")) {
+ parse_font_tag(dest, tag_name, tag, &colors, &tags);
+ } else if (g_str_equal(tag_name, "b")) {
+ g_string_append(dest, "\033[1m");
+ current_state.bold = TRUE;
+ } else if (g_str_equal(tag_name, "/b")) {
+ if (current_state.bold) {
+ g_string_append(dest, "\033[x1m");
+ current_state.bold = FALSE;
+ }
+ } else if (g_str_equal(tag_name, "i")) {
+ current_state.italic = TRUE;
+ g_string_append(dest, "\033[2m");
+ } else if (g_str_equal(tag_name, "/i")) {
+ if (current_state.italic) {
+ g_string_append(dest, "\033[x2m");
+ current_state.italic = FALSE;
+ }
+ } else if (g_str_equal(tag_name, "u")) {
+ current_state.underline = TRUE;
+ g_string_append(dest, "\033[4m");
+ } else if (g_str_equal(tag_name, "/u")) {
+ if (current_state.underline) {
+ g_string_append(dest, "\033[x4m");
+ current_state.underline = FALSE;
+ }
+ } else if (g_str_equal(tag_name, "/a")) {
+ /* Do nothing */
+ } else if (g_str_equal(tag_name, "br")) {
+ g_string_append_c(dest, '\n');
+ } else if (g_str_equal(tag_name, "/font")) {
+ if (tags != NULL) {
+ char *etag = tags->data;
+ tags = g_slist_delete_link(tags, tags);
+ g_string_append(dest, etag);
+ if (colors != NULL) {
+ g_free(colors->data);
+ colors = g_slist_delete_link(colors, colors);
}
- } else {
- g_string_append_len(dest, &src[i], j - i + 1);
+ g_free(etag);
}
-
- i = j;
- break;
}
+ i = j;
+ g_free(tag);
+ g_free(tag_name);
+ break;
}
} else {
@@ -1052,7 +905,7 @@ char *yahoo_html_to_codes(const char *src)
}
esc = g_strescape(dest->str, NULL);
- purple_debug_misc("yahoo", "yahoo_html_to_codes: Returning string: '%s'.\n", esc);
+ purple_debug_misc("yahoo", "yahoo_html_to_codes(%s)=%s\n", src, esc);
g_free(esc);
yahoo_htc_list_cleanup(colors);
diff --git a/libpurple/proxy.c b/libpurple/proxy.c
index ed1a6edbf3..111c1896bf 100644
--- a/libpurple/proxy.c
+++ b/libpurple/proxy.c
@@ -245,7 +245,7 @@ purple_gnome_proxy_get_info(void)
return &info;
}
- if (purple_strequal(tmp, "manual\n")) {
+ if (!purple_strequal(tmp, "manual\n")) {
/* Unknown setting. Fallback to using our global proxy settings. */
g_free(tmp);
return purple_global_proxy_get_info();
diff --git a/libpurple/server.c b/libpurple/server.c
index fffbce583b..351e6d0888 100644
--- a/libpurple/server.c
+++ b/libpurple/server.c
@@ -592,13 +592,10 @@ void serv_got_im(PurpleConnection *gc, const char *who, const char *msg,
*/
flags |= PURPLE_MESSAGE_RECV;
- if (PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc))->set_permit_deny == NULL) {
- /* protocol does not support privacy, handle it ourselves */
- if (!purple_privacy_check(account, who)) {
- purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
- account, who, msg, flags, (unsigned int)mtime);
- return;
- }
+ if (!purple_privacy_check(account, who)) {
+ purple_signal_emit(purple_conversations_get_handle(), "blocked-im-msg",
+ account, who, msg, flags, (unsigned int)mtime);
+ return;
}
/*
diff --git a/libpurple/smiley.c b/libpurple/smiley.c
index 2c08b5994b..304d292a47 100644
--- a/libpurple/smiley.c
+++ b/libpurple/smiley.c
@@ -80,7 +80,7 @@ static char *smileys_dir = NULL;
* XML descriptor file layout *
******************************************************************************
*
- * Althought we are creating the profile XML structure here, now we
+ * Although we are creating the profile XML structure here, now we
* won't handle it.
* So, we just add one profile named "default" that has no associated
* account elements, and have only the smiley_set that will contain
@@ -163,14 +163,14 @@ add_smiley_to_main_node(gpointer key, gpointer value, gpointer user_data)
}
static xmlnode *
-smileys_to_xmlnode()
+smileys_to_xmlnode(void)
{
xmlnode *root_node, *profile_node, *smileyset_node;
root_node = xmlnode_new(XML_ROOT_TAG);
xmlnode_set_attrib(root_node, "version", "1.0");
- /* See the top comment's above to understand why initial tag elements
+ /* See the top comments above to understand why initial tag elements
* are not being considered by now. */
profile_node = xmlnode_new(XML_PROFILE_TAG);
if (profile_node) {
@@ -188,7 +188,7 @@ smileys_to_xmlnode()
}
static void
-sync_smileys()
+sync_smileys(void)
{
xmlnode *root_node;
char *data;
@@ -216,7 +216,7 @@ save_smileys_cb(gpointer data)
}
static void
-purple_smileys_save()
+purple_smileys_save(void)
{
if (save_timer == 0)
save_timer = purple_timeout_add_seconds(5, save_smileys_cb, NULL);
@@ -248,7 +248,7 @@ parse_smiley(xmlnode *smiley_node)
}
static void
-purple_smileys_load()
+purple_smileys_load(void)
{
xmlnode *root_node, *profile_node;
xmlnode *smileyset_node = NULL;
@@ -262,7 +262,7 @@ purple_smileys_load()
if (root_node == NULL)
return;
- /* See the top comment's above to understand why initial tag elements
+ /* See the top comments above to understand why initial tag elements
* are not being considered by now. */
profile_node = xmlnode_get_child(root_node, XML_PROFILE_TAG);
if (profile_node)
@@ -456,7 +456,7 @@ purple_smiley_get_type(void)
}
/*********************************************************************
- * Other Stuff *
+ * Other Stuff *
*********************************************************************/
static char *get_file_full_path(const char *filename)
@@ -876,7 +876,7 @@ purple_smileys_get_storing_dir(void)
}
void
-purple_smileys_init()
+purple_smileys_init(void)
{
smiley_shortcut_index = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
smiley_checksum_index = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
@@ -887,7 +887,7 @@ purple_smileys_init()
}
void
-purple_smileys_uninit()
+purple_smileys_uninit(void)
{
if (save_timer != 0) {
purple_timeout_remove(save_timer);
diff --git a/libpurple/smiley.h b/libpurple/smiley.h
index 8d96fddd0e..73202bda47 100644
--- a/libpurple/smiley.h
+++ b/libpurple/smiley.h
@@ -95,7 +95,7 @@ PurpleSmiley *
purple_smiley_new_from_file(const char *shortcut, const char *filepath);
/**
- * Destroys the custom smiley and release the associated resources.
+ * Destroys the custom smiley and releases the associated resources.
*
* @param smiley The custom smiley.
*/
@@ -183,7 +183,7 @@ const char *purple_smiley_get_extension(const PurpleSmiley *smiley);
* If the custom smiley has data and the file exists in the cache, this
* will return a full path to the cached file.
*
- * In general, it is not appropriate to be poking in the file cached
+ * In general, it is not appropriate to be poking in the file cache
* directly. If you find yourself wanting to use this function, think
* very long and hard about it, and then don't.
*
@@ -192,7 +192,7 @@ const char *purple_smiley_get_extension(const PurpleSmiley *smiley);
* @param smiley The custom smiley.
*
* @return A full path to the file, or @c NULL under various conditions.
- * The caller should use #g_free to free the returned string.
+ * The caller should use g_free to free the returned string.
*/
char *purple_smiley_get_full_path(PurpleSmiley *smiley);
diff --git a/libpurple/status.h b/libpurple/status.h
index f79a1958cc..743dd4dbb3 100644
--- a/libpurple/status.h
+++ b/libpurple/status.h
@@ -50,28 +50,38 @@
* your accounts are saved so that the next time you start Purple,
* your accounts will be set to their last known statuses. There
* is also a list of saved statuses that are written to the
- * status.xml file. Also, each PurpleStatus has a "savable" boolean.
- * If "savable" is set to FALSE then the status is NEVER saved.
+ * status.xml file. Also, each PurpleStatus has a "saveable" boolean.
+ * If "saveable" is set to FALSE then the status is NEVER saved.
* All PurpleStatuses should be inside a PurplePresence.
*
*
- * A PurpleStatus is either "indepedent" or "exclusive."
- * Independent statuses can be active or inactive and it doesn't
+ * A PurpleStatus is either "independent" or "exclusive."
+ * Independent statuses can be active or inactive and they don't
* affect anything else. However, you can only have one exclusive
- * status per PurplePresence. If you activate one exlusive status,
+ * status per PurplePresence. If you activate one exclusive status,
* then the previous exclusive status is automatically deactivated.
*
* A PurplePresence is like a collection of PurpleStatuses (plus some
* other random info). For any buddy, or for any one of your accounts,
- * or for any person you're chatting with, you may know various
+ * or for any person with which you're chatting, you may know various
* amounts of information. This information is all contained in
* one PurplePresence. If one of your buddies is away and idle,
* then the presence contains the PurpleStatus for their awayness,
* and it contains their current idle time. PurplePresences are
- * never saved to disk. The information they contain is only relevent
+ * never saved to disk. The information they contain is only relevant
* for the current PurpleSession.
*/
+/**
+ * PurpleStatusType's are created by each PRPL. They outline the
+ * available statuses of the protocol. AIM, for example, supports
+ * an available state with an optional available message, an away
+ * state with a mandatory message, and an invisible state (which is
+ * technically "independent" of the other two, but we'll get into
+ * that later). PurpleStatusTypes are very permanent. They are
+ * hardcoded in each PRPL and will not change often. And because
+ * they are hardcoded, they do not need to be saved to any XML file.
+ */
typedef struct _PurpleStatusType PurpleStatusType;
typedef struct _PurpleStatusAttr PurpleStatusAttr;
typedef struct _PurplePresence PurplePresence;
@@ -80,7 +90,7 @@ typedef struct _PurpleStatus PurpleStatus;
/**
* A context for a presence.
*
- * The context indicates what the presence applies to.
+ * The context indicates to what the presence applies.
*/
typedef enum
{
@@ -134,7 +144,7 @@ extern "C" {
#endif
/**************************************************************************/
-/** @name PurpleStatusPrimitive API */
+/** @name PurpleStatusPrimitive API */
/**************************************************************************/
/*@{*/
@@ -172,7 +182,7 @@ PurpleStatusPrimitive purple_primitive_get_type_from_id(const char *id);
/*@}*/
/**************************************************************************/
-/** @name PurpleStatusType API */
+/** @name PurpleStatusType API */
/**************************************************************************/
/*@{*/
diff --git a/libpurple/tests/Makefile.am b/libpurple/tests/Makefile.am
index efc6285618..a3d881878c 100644
--- a/libpurple/tests/Makefile.am
+++ b/libpurple/tests/Makefile.am
@@ -11,6 +11,7 @@ check_libpurple_SOURCES=\
tests.h \
test_cipher.c \
test_jabber_jutil.c \
+ test_qq.c \
test_yahoo_util.c \
test_util.c \
$(top_builddir)/libpurple/util.h
@@ -28,6 +29,7 @@ check_libpurple_LDADD=\
@CHECK_LIBS@ \
$(GLIB_LIBS) \
$(top_builddir)/libpurple/protocols/jabber/libjabber.la \
+ $(top_builddir)/libpurple/protocols/qq/libqq.la \
$(top_builddir)/libpurple/protocols/yahoo/libymsg.la \
$(top_builddir)/libpurple/libpurple.la
diff --git a/libpurple/tests/check_libpurple.c b/libpurple/tests/check_libpurple.c
index afc297ab63..e22ad6727e 100644
--- a/libpurple/tests/check_libpurple.c
+++ b/libpurple/tests/check_libpurple.c
@@ -76,6 +76,7 @@ int main(void)
srunner_add_suite(sr, cipher_suite());
srunner_add_suite(sr, jabber_jutil_suite());
+ srunner_add_suite(sr, qq_suite());
srunner_add_suite(sr, yahoo_util_suite());
srunner_add_suite(sr, util_suite());
diff --git a/libpurple/tests/test_jabber_jutil.c b/libpurple/tests/test_jabber_jutil.c
index e540e269a1..b8c85bb4ad 100644
--- a/libpurple/tests/test_jabber_jutil.c
+++ b/libpurple/tests/test_jabber_jutil.c
@@ -132,6 +132,7 @@ START_TEST(test_jabber_id_new)
assert_invalid_jid("mark.doliner@gmail\\stuff.org");
assert_invalid_jid("paul@[::1]124");
assert_invalid_jid("paul@2[::1]124/as");
+ assert_invalid_jid("paul@まつ.おおかみ/\x01");
/* Ensure that jabber_id_new is properly lowercasing node and domains */
assert_jid_parts("paul", "darkrain42.org", "PaUL@darkrain42.org");
@@ -153,6 +154,14 @@ START_TEST(test_jabber_id_new)
}
END_TEST
+START_TEST(test_jabber_normalize)
+{
+ assert_string_equal("paul@darkrain42.org", jabber_normalize(NULL, "PaUL@DaRkRain42.org"));
+ assert_string_equal("paul@darkrain42.org", jabber_normalize(NULL, "PaUL@DaRkRain42.org/"));
+ assert_string_equal("paul@darkrain42.org", jabber_normalize(NULL, "PaUL@DaRkRain42.org/resource"));
+}
+END_TEST
+
Suite *
jabber_jutil_suite(void)
{
@@ -172,6 +181,7 @@ jabber_jutil_suite(void)
tcase_add_test(tc, test_nodeprep_validate_illegal_chars);
tcase_add_test(tc, test_nodeprep_validate_too_long);
tcase_add_test(tc, test_jabber_id_new);
+ tcase_add_test(tc, test_jabber_normalize);
suite_add_tcase(s, tc);
return s;
diff --git a/libpurple/tests/test_qq.c b/libpurple/tests/test_qq.c
new file mode 100644
index 0000000000..147b233b99
--- /dev/null
+++ b/libpurple/tests/test_qq.c
@@ -0,0 +1,105 @@
+#include <string.h>
+
+#include "tests.h"
+#include "../protocols/qq/qq_crypt.h"
+
+START_TEST(test_qq_encrypt)
+{
+ const guint8 * const key = (guint8 *)"hamburger";
+ guint8 crypted[80];
+ gint ret;
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"a", 1, key);
+ assert_int_equal(16, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aa", 2, key);
+ assert_int_equal(16, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aaa", 3, key);
+ assert_int_equal(16, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aaaa", 4, key);
+ assert_int_equal(16, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aaaaa", 5, key);
+ assert_int_equal(16, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaa", 6, key);
+ assert_int_equal(16, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaaa", 7, key);
+ assert_int_equal(24, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaaaa", 8, key);
+ assert_int_equal(24, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaaaaa", 9, key);
+ assert_int_equal(24, ret);
+
+ ret = qq_encrypt(crypted, (const guint8 * const)"aaaaaaaaaa", 10, key);
+ assert_int_equal(24, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaa", 11, key);
+ assert_int_equal(24, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaaa", 12, key);
+ assert_int_equal(24, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaaaa", 13, key);
+ assert_int_equal(24, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaaaaa", 14, key);
+ assert_int_equal(24, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaaaaaa", 15, key);
+ assert_int_equal(32, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaaaaaaa", 16, key);
+ assert_int_equal(32, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaaaaaaaa", 17, key);
+ assert_int_equal(32, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaaaaaaaaa", 18, key);
+ assert_int_equal(32, ret);
+
+ ret = qq_encrypt(crypted,
+ (const guint8 * const)"aaaaaaaaaaaaaaaaaaa", 19, key);
+ assert_int_equal(32, ret);
+
+ /*
+ fprintf(stderr, "crypted=%s\n", crypted);
+ assert_string_equal_free("plain",
+ yahoo_codes_to_html("plain"));
+ */
+}
+END_TEST
+
+START_TEST(test_qq_decrypt)
+{
+}
+END_TEST
+
+Suite *
+qq_suite(void)
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("QQ");
+
+ tc = tcase_create("QQ Crypt Functions");
+ tcase_add_test(tc, test_qq_encrypt);
+ tcase_add_test(tc, test_qq_decrypt);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/libpurple/tests/test_yahoo_util.c b/libpurple/tests/test_yahoo_util.c
index c76158153c..4a049c53a1 100644
--- a/libpurple/tests/test_yahoo_util.c
+++ b/libpurple/tests/test_yahoo_util.c
@@ -25,6 +25,10 @@ START_TEST(test_codes_to_html)
yahoo_codes_to_html("plain <peanut"));
assert_string_equal_free("plain&gt; peanut",
yahoo_codes_to_html("plain> peanut"));
+ assert_string_equal_free("<font face='inva&gt;lid'>test</font>",
+ yahoo_codes_to_html("<font face='inva>lid'>test"));
+ assert_string_equal_free("&lt;font face=&apos;inva&gt;lid",
+ yahoo_codes_to_html("<font face='inva>lid"));
/* bold/italic/underline */
assert_string_equal_free("<b>bold</b>",
@@ -46,6 +50,10 @@ START_TEST(test_codes_to_html)
assert_string_equal_free("<b>bold <i>bolditalic <u>bolditalicunderline</u></i></b><i><u> italicunderline</u></i>",
yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x1m italicunderline"));
+ /* link */
+ assert_string_equal_free("http://pidgin.im/",
+ yahoo_codes_to_html("\x1B[lmhttp://pidgin.im/\x1B[xlm"));
+
#ifdef USE_CSS_FORMATTING
/* font color */
assert_string_equal_free("<span style='color: #0000FF'>blue</span>",
@@ -92,19 +100,105 @@ START_TEST(test_codes_to_html)
yahoo_codes_to_html("<font face='Georgia' size='32'>test"));
assert_string_equal_free("<font color='#FF0080'><font size='4' absz='15'>test</font></font>",
yahoo_codes_to_html("\x1B[35m<font size='15'>test"));
+ assert_string_equal_free(":&lt;",
+ yahoo_codes_to_html("<FADE #ff0000,#00ff00,#0000ff>:<</FADE>"));
#endif /* !USE_CSS_FORMATTING */
}
END_TEST
+START_TEST(test_html_to_codes)
+{
+ assert_string_equal_free("plain",
+ yahoo_html_to_codes("plain"));
+ assert_string_equal_free("plain <peanut>",
+ yahoo_html_to_codes("plain &lt;peanut&gt;"));
+ assert_string_equal_free("plain <peanut",
+ yahoo_html_to_codes("plain &lt;peanut"));
+ assert_string_equal_free("plain> peanut",
+ yahoo_html_to_codes("plain&gt; peanut"));
+ assert_string_equal_free("plain >",
+ yahoo_html_to_codes("plain &gt;"));
+ assert_string_equal_free("plain > ",
+ yahoo_html_to_codes("plain &gt; "));
+ assert_string_equal_free("plain <",
+ yahoo_html_to_codes("plain &lt;"));
+ assert_string_equal_free("plain < ",
+ yahoo_html_to_codes("plain &lt; "));
+ assert_string_equal_free("plain &lt",
+ yahoo_html_to_codes("plain &lt"));
+ assert_string_equal_free("plain &",
+ yahoo_html_to_codes("plain &amp;"));
+
+ /* bold/italic/underline */
+ assert_string_equal_free("\x1B[1mbold\x1B[x1m",
+ yahoo_html_to_codes("<b>bold</b>"));
+ assert_string_equal_free("\x1B[2mitalic\x1B[x2m",
+ yahoo_html_to_codes("<i>italic</i>"));
+ assert_string_equal_free("\x1B[4munderline\x1B[x4m",
+ yahoo_html_to_codes("<u>underline</u>"));
+ assert_string_equal_free("no markup",
+ yahoo_html_to_codes("no</u> markup"));
+ assert_string_equal_free("\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline\x1B[x4m",
+ yahoo_html_to_codes("<b>bold</b> <i>italic</i> <u>underline</u>"));
+ assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m italic\x1B[x2m",
+ yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> italic</i>"));
+ assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m",
+ yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>"));
+
+ /* link */
+ assert_string_equal_free("http://pidgin.im/",
+ yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">http://pidgin.im/</A>"));
+ assert_string_equal_free("mark@example.com",
+ yahoo_html_to_codes("<A HREF=\"mailto:mark@example.com\">mark@example.com</A>"));
+#if 0
+ assert_string_equal_free("Pidgin (http://pidgin.im/)",
+ yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">Pidgin</A>"));
+#endif
+
+ /* font nothing */
+ assert_string_equal_free("nothing",
+ yahoo_html_to_codes("<font>nothing</font>"));
+
+ /* font color */
+ assert_string_equal_free("\x1B[#E71414mred\x1B[#000000m",
+ yahoo_html_to_codes("<font color=\"#E71414\">red</font>"));
+ assert_string_equal_free("\x1B[#FF0000mred\x1B[#000000m \x1B[#0000FFmblue\x1B[#000000m black",
+ yahoo_html_to_codes("<font color=\"#FF0000\">red</font> <font color=\"#0000FF\">blue</font> black"));
+
+ /* font size */
+ assert_string_equal_free("<font size=\"10\">test</font>",
+ yahoo_html_to_codes("<font size=\"2\">test</font>"));
+ assert_string_equal_free("<font size=\"30\">test</font>",
+ yahoo_html_to_codes("<font size=\"6\">test</font>"));
+
+ /* combinations */
+ assert_string_equal_free("\x1B[#FF0000m<font size=\"8\">redsmall</font> rednormal\x1B[#000000m",
+ yahoo_html_to_codes("<font color=\"#FF0000\"><font size=\"1\">redsmall</font> rednormal</font>"));
+
+ assert_string_equal_free("\x1B[#FF0000m<font size=\"8\">redsmall</font> \x1B[#00FF00mgreennormal\x1B[#FF0000m rednormal\x1B[#000000m",
+ yahoo_html_to_codes("<font color=\"#FF0000\"><font size=\"1\">redsmall</font> <font color=\"#00FF00\">greennormal</font> rednormal</font>"));
+
+ assert_string_equal_free("\x1B[1mbold \x1B[#FF0000mred <font face=\"Comic Sans MS\" size=\"20\">larger \x1B[#000000mbacktoblack <font size=\"12\">normalsize</font>\x1B[#FF0000m</font>\x1B[#000000m\x1B[x1m",
+ yahoo_html_to_codes("<b>bold <font color=\"#FF0000\">red <font face=\"Comic Sans MS\" size=\"5\">larger <font color=\"#000000\">backtoblack <font size=\"3\">normalsize</font></font></font></font></b>"));
+}
+END_TEST
+
Suite *
yahoo_util_suite(void)
{
- Suite *s = suite_create("Yahoo Utility Functions");
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("Yahoo Utility Functions");
- TCase *tc = tcase_create("Convert to Numeric");
+ tc = tcase_create("Convert IM from network format to HTML");
tcase_add_unchecked_fixture(tc, setup_codes_to_html, teardown_codes_to_html);
tcase_add_test(tc, test_codes_to_html);
suite_add_tcase(s, tc);
+ tc = tcase_create("Convert IM from HTML to network format");
+ tcase_add_test(tc, test_html_to_codes);
+ suite_add_tcase(s, tc);
+
return s;
}
diff --git a/libpurple/tests/tests.h b/libpurple/tests/tests.h
index 8ac8508538..1862a6e47e 100644
--- a/libpurple/tests/tests.h
+++ b/libpurple/tests/tests.h
@@ -10,13 +10,18 @@
Suite * master_suite(void);
Suite * cipher_suite(void);
Suite * jabber_jutil_suite(void);
+Suite * qq_suite(void);
Suite * yahoo_util_suite(void);
Suite * util_suite(void);
/* helper macros */
+#define assert_int_equal(expected, actual) { \
+ fail_if(expected != actual, "Expected '%d' but got '%d'", expected, actual); \
+}
+
#define assert_string_equal(expected, actual) { \
const gchar *a = actual; \
- fail_unless(strcmp(expected, a) == 0, "Expecting '%s' but got '%s'", expected, a); \
+ fail_unless(strcmp(expected, a) == 0, "Expected '%s' but got '%s'", expected, a); \
}
#define assert_string_equal_free(expected, actual) { \
diff --git a/libpurple/theme-loader.c b/libpurple/theme-loader.c
index d50c28dec0..84d7bfd9da 100644
--- a/libpurple/theme-loader.c
+++ b/libpurple/theme-loader.c
@@ -118,7 +118,7 @@ purple_theme_loader_class_init(PurpleThemeLoaderClass *klass)
/* TYPE STRING (read only) */
pspec = g_param_spec_string("type", "Type",
- "The string represtenting the type of the theme",
+ "The string representing the type of the theme",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property(obj_class, PROP_TYPE, pspec);
diff --git a/libpurple/theme-loader.h b/libpurple/theme-loader.h
index 5496f2c7e2..bf76b38920 100644
--- a/libpurple/theme-loader.h
+++ b/libpurple/theme-loader.h
@@ -71,11 +71,11 @@ G_BEGIN_DECLS
GType purple_theme_loader_get_type(void);
/**
- * Returns the string represtenting the type of the theme loader
+ * Returns the string representing the type of the theme loader
*
* @param self The theme loader
*
- * @returns The string represting this type
+ * @returns The string representing this type
*/
const gchar *purple_theme_loader_get_type_string(PurpleThemeLoader *self);
diff --git a/libpurple/theme.c b/libpurple/theme.c
index 384a44a945..49f5c89fad 100644
--- a/libpurple/theme.c
+++ b/libpurple/theme.c
@@ -190,7 +190,7 @@ purple_theme_class_init(PurpleThemeClass *klass)
/* TYPE STRING (read only) */
pspec = g_param_spec_string("type", "Type",
- "The string represtenting the type of the theme",
+ "The string representing the type of the theme",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property(obj_class, PROP_TYPE, pspec);
diff --git a/libpurple/theme.h b/libpurple/theme.h
index 5efae71a82..e6ffa130e5 100644
--- a/libpurple/theme.h
+++ b/libpurple/theme.h
@@ -73,7 +73,7 @@ GType purple_theme_get_type(void);
*
* @param theme The purple theme.
*
- * @return The string representating the name of the theme.
+ * @return The string representing the name of the theme.
*/
const gchar *purple_theme_get_name(PurpleTheme *theme);
@@ -124,7 +124,7 @@ void purple_theme_set_author(PurpleTheme *theme, const gchar *author);
*
* @param theme The purple theme.
*
- * @return The string represtenting the type.
+ * @return The string representing the type.
*/
const gchar *purple_theme_get_type_string(PurpleTheme *theme);
@@ -133,7 +133,7 @@ const gchar *purple_theme_get_type_string(PurpleTheme *theme);
*
* @param theme The purple theme.
*
- * @return The string represtenting the theme directory.
+ * @return The string representing the theme directory.
*/
const gchar *purple_theme_get_dir(PurpleTheme *theme);
diff --git a/libpurple/util.c b/libpurple/util.c
index d842a38d30..7f26e0078f 100644
--- a/libpurple/util.c
+++ b/libpurple/util.c
@@ -3129,6 +3129,9 @@ purple_normalize(const PurpleAccount *account, const char *str)
const char *ret = NULL;
static char buf[BUF_LEN];
+ /* This should prevent a crash if purple_normalize gets called with NULL str, see #10115 */
+ g_return_val_if_fail(str != NULL, "");
+
if (account != NULL)
{
PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
@@ -3820,7 +3823,7 @@ find_header_content(const char *data, size_t data_len, const char *header, size_
/* Note: data is _not_ nul-terminated. */
if (data_len > header_len) {
if (header[0] == '\n')
- p = (g_strncasecmp(data, header + 1, header_len - 1) == 0) ? data : NULL;
+ p = (g_ascii_strncasecmp(data, header + 1, header_len - 1) == 0) ? data : NULL;
if (!p)
p = purple_strcasestr(data, header);
if (p)
@@ -3857,7 +3860,7 @@ static gboolean
content_is_chunked(const char *data, size_t data_len)
{
const char *p = find_header_content(data, data_len, "\nTransfer-Encoding: ", sizeof("\nTransfer-Encoding: ") - 1);
- if (p && g_strncasecmp(p, "chunked", 7) == 0)
+ if (p && g_ascii_strncasecmp(p, "chunked", 7) == 0)
return TRUE;
return FALSE;
@@ -4375,14 +4378,14 @@ purple_url_encode(const char *str)
gunichar c = g_utf8_get_char(iter);
/* If the character is an ASCII character and is alphanumeric
* no need to escape */
- if (c < 128 && isalnum(c)) {
+ if (c < 128 && (isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~')) {
buf[j++] = c;
} else {
int bytes = g_unichar_to_utf8(c, utf_char);
for (i = 0; i < bytes; i++) {
if (j > (BUF_LEN - 4))
break;
- sprintf(buf + j, "%%%02x", utf_char[i] & 0xff);
+ sprintf(buf + j, "%%%02X", utf_char[i] & 0xff);
j += 3;
}
}
@@ -4652,25 +4655,26 @@ gchar *
purple_utf8_strip_unprintables(const gchar *str)
{
gchar *workstr, *iter;
+ const gchar *bad;
if (str == NULL)
/* Act like g_strdup */
return NULL;
- g_return_val_if_fail(g_utf8_validate(str, -1, NULL), NULL);
+ if (!g_utf8_validate(str, -1, &bad)) {
+ purple_debug_error("util", "purple_utf8_strip_unprintables(%s) failed; "
+ "first bad character was %02x (%c)\n",
+ str, *bad, *bad);
+ g_return_val_if_reached(NULL);
+ }
workstr = iter = g_new(gchar, strlen(str) + 1);
- while (*str) {
- gunichar c = g_utf8_get_char(str);
- const gchar *next = g_utf8_next_char(str);
- size_t len = next - str;
-
- if (g_unichar_isprint(c)) {
- memcpy(iter, str, len);
- iter += len;
+ for ( ; *str; ++str) {
+ guchar c = *str;
+ if (c >= 0x20 || c == '\t' || c == '\n' || c == '\r') {
+ *iter = c;
+ ++iter;
}
-
- str = next;
}
/* nul-terminate the new string */
diff --git a/libpurple/util.h b/libpurple/util.h
index e1be673e24..34067fb24d 100644
--- a/libpurple/util.h
+++ b/libpurple/util.h
@@ -31,8 +31,14 @@
#include <stdio.h>
+/**
+ * An opaque structure representing a URL request. Can be used to cancel
+ * the request.
+ */
typedef struct _PurpleUtilFetchUrlData PurpleUtilFetchUrlData;
+/** @copydoc _PurpleMenuAction */
typedef struct _PurpleMenuAction PurpleMenuAction;
+/** @copydoc _PurpleKeyValuePair */
typedef struct _PurpleKeyValuePair PurpleKeyValuePair;
#include "account.h"
@@ -107,7 +113,7 @@ void purple_util_set_current_song(const char *title, const char *artist,
* @param album The album of the song, can be @c NULL.
* @param unused Currently unused, must be @c NULL.
*
- * @return The formatted string. The caller must #g_free the returned string.
+ * @return The formatted string. The caller must g_free the returned string.
* @since 2.4.0
*/
char * purple_util_format_song_info(const char *title, const char *artist,
@@ -1286,16 +1292,14 @@ gchar *purple_utf8_salvage(const char *str);
/**
* Removes unprintable characters from a UTF-8 string. These characters
* (in particular low-ASCII characters) are invalid in XML 1.0 and thus
- * are not allowed in XMPP and are rejected by libxml2 by default. This
- * function uses g_unichar_isprint to determine what characters should
- * be stripped. The returned string must be freed by the caller.
+ * are not allowed in XMPP and are rejected by libxml2 by default.
+ *
+ * The returned string must be freed by the caller.
*
* @param str A valid UTF-8 string.
*
* @return A newly allocated UTF-8 string without the unprintable characters.
* @since 2.6.0
- *
- * @see g_unichar_isprint
*/
gchar *purple_utf8_strip_unprintables(const gchar *str);