diff options
author | John Bailey <rekkanoryo@rekkanoryo.org> | 2009-09-16 15:36:24 +0000 |
---|---|---|
committer | John Bailey <rekkanoryo@rekkanoryo.org> | 2009-09-16 15:36:24 +0000 |
commit | a245c80a0788d33e86c8512606a9cde4ac424553 (patch) | |
tree | 5b2477b5fde7398f0846be846b66238b779797a4 /libpurple | |
parent | a27b85d8a86ec484a4064bb924425f9889535167 (diff) | |
parent | f0263ba7a7d0ab488519a745fba7b2f36ddc02a7 (diff) | |
download | pidgin-a245c80a0788d33e86c8512606a9cde4ac424553.tar.gz |
merge of '755d7efe6da376f6fbeb9f6d3e08f2d7201aabc7'
and '0848cfc68369ad686459fb7420f1e4613029b294'
Diffstat (limited to 'libpurple')
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 <moderator|participant|visitor|none> [nick1] [nick2] ...: Get the users with an role or set users' role with the room."), + _("role <moderator|participant|visitor|none> [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(¤t_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> peanut", yahoo_codes_to_html("plain> peanut")); + assert_string_equal_free("<font face='inva>lid'>test</font>", + yahoo_codes_to_html("<font face='inva>lid'>test")); + assert_string_equal_free("<font face='inva>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(":<", + 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 <peanut>")); + assert_string_equal_free("plain <peanut", + yahoo_html_to_codes("plain <peanut")); + assert_string_equal_free("plain> peanut", + yahoo_html_to_codes("plain> peanut")); + assert_string_equal_free("plain >", + yahoo_html_to_codes("plain >")); + assert_string_equal_free("plain > ", + yahoo_html_to_codes("plain > ")); + assert_string_equal_free("plain <", + yahoo_html_to_codes("plain <")); + assert_string_equal_free("plain < ", + yahoo_html_to_codes("plain < ")); + assert_string_equal_free("plain <", + yahoo_html_to_codes("plain <")); + assert_string_equal_free("plain &", + yahoo_html_to_codes("plain &")); + + /* 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); |