Merge upstream, resolve conflicts
--- a/ChangeLog.API Mon Nov 04 10:00:14 2019 +0300
+++ b/ChangeLog.API Mon Nov 04 14:43:49 2019 +0300
@@ -393,6 +393,7 @@
* purple_buddy_icons_has_custom_icon
* purple_buddy_icons_find_custom_icon
* purple_buddy_icons_set_custom_icon
+ * purple_build_dir. Use g_mkdir_with_parents instead * purple_certificate_check_signature_chain_with_failing. Use
purple_certificate_check_signature_chain, instead
* purple_certificate_display_x509. Use purple_request_certificate,
@@ -416,10 +417,12 @@
event loop yourself. See GLib Main Event Loop docs.
* PurpleEventLoopUiOps. Manually drive the GLib event loop
yourself. See GLib Main Event Loop docs.
+ * purple_get_host_name. Use g_get_host_name, instead. * purple_get_tzoff_str(). Use g_date_time_format, instead.
* purple_ip_address_is_valid, purple_ipv4_address_is_valid, and
purple_ipv6_address_is_valid. Use g_hostname_is_ip_address()
or #GInetAddress instead.
+ * purple_markup_extract_info_field * PurpleMimeDocument, PurpleMimePart,
purple_mime_document_new, purple_mime_document_free,
purple_mime_document_parse, purple_mime_document_parsen,
@@ -496,6 +499,9 @@
* purple_status_type_set_primary_attr
+ * purple_str_binary_to_ascii + * purple_str_has_prefix. Use g_str_has_prefix instead + * purple_str_has_suffix. Use g_str_has_suffix instead * purple_str_size_to_units. Use g_format_size() instead.
* purple_timeout_*. Use g_timeout_* or g_idle_* instead.
@@ -508,6 +514,7 @@
purple_util_fetch_url_request, instead.
* purple_util_get_image_checksum. Use
g_compute_checksum_for_data(G_CHECKSUM_SHA1, ...), instead.
* PurpleCertificateVerificationStatus.PURPLE_CERTIFICATE_INVALID
* PurpleConnectionUiOps.report_disconnect_reason
* PurplePluginProtocolInfo.add_buddy_with_invite
--- a/finch/gntblist.c Mon Nov 04 10:00:14 2019 +0300
+++ b/finch/gntblist.c Mon Nov 04 14:43:49 2019 +0300
@@ -2066,8 +2066,6 @@
PURPLE_SIGNAL_PRIORITY_HIGHEST);
finch_blist_install_manager(&default_manager);
--- a/finch/gntrequest.c Mon Nov 04 10:00:14 2019 +0300
+++ b/finch/gntrequest.c Mon Nov 04 14:43:49 2019 +0300
@@ -433,9 +433,9 @@
purple_request_field_string_get_default_value(field));
gnt_entry_set_masked(GNT_ENTRY(entry),
purple_request_field_string_is_masked(field));
- if (hint && purple_str_has_prefix(hint, "screenname")) {
+ if (hint && g_str_has_prefix(hint, "screenname")) { PurpleBlistNode *node = purple_blist_get_default_root();
- gboolean offline = purple_str_has_suffix(hint, "all");
+ gboolean offline = g_str_has_suffix(hint, "all"); for (; node; node = purple_blist_node_next(node, offline)) {
if (!PURPLE_IS_BUDDY(node))
--- a/finch/plugins/gntclipboard.c Mon Nov 04 10:00:14 2019 +0300
+++ b/finch/plugins/gntclipboard.c Mon Nov 04 14:43:49 2019 +0300
@@ -90,7 +90,6 @@
--- a/libpurple/buddylist.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/buddylist.c Mon Nov 04 14:43:49 2019 +0300
@@ -727,9 +727,7 @@
buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify)g_hash_table_destroy);
- groups_cache = g_hash_table_new_full((GHashFunc)g_str_hash,
- (GEqualFunc)g_str_equal,
- (GDestroyNotify)g_free, NULL);
+ groups_cache = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); for (account = purple_accounts_get_all(); account != NULL; account = account->next)
--- a/libpurple/core.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/core.c Mon Nov 04 14:43:49 2019 +0300
@@ -249,7 +249,7 @@
_purple_message_uninit();
/* Everything after util_uninit cannot try to write things to the
- * confdir nor use purple_escape_js
--- a/libpurple/image-store.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/image-store.c Mon Nov 04 14:43:49 2019 +0300
@@ -169,8 +169,9 @@
g_return_val_if_fail(uri != NULL, NULL);
- if (!purple_str_has_prefix(uri, PURPLE_IMAGE_STORE_PROTOCOL))
+ if (!g_str_has_prefix(uri, PURPLE_IMAGE_STORE_PROTOCOL)) { uri += sizeof(PURPLE_IMAGE_STORE_PROTOCOL) - 1;
--- a/libpurple/keyring.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/keyring.c Mon Nov 04 14:43:49 2019 +0300
@@ -1287,8 +1287,7 @@
GPluginPluginInfo *info =
GPLUGIN_PLUGIN_INFO(purple_plugin_get_info(plugin));
- if (!purple_str_has_prefix(gplugin_plugin_info_get_id(info),
+ if (!g_str_has_prefix(gplugin_plugin_info_get_id(info), "keyring-")) { --- a/libpurple/log.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/log.c Mon Nov 04 14:43:49 2019 +0300
@@ -871,7 +871,7 @@
- purple_build_dir (dir, S_IRUSR | S_IWUSR | S_IXUSR);
+ g_mkdir_with_parents(dir, S_IRUSR | S_IWUSR | S_IXUSR); dt = g_date_time_to_local(log->time);
tz = purple_escape_filename(g_date_time_get_timezone_abbreviation(dt));
@@ -927,9 +927,8 @@
while ((filename = g_dir_read_name(dir)))
- if (purple_str_has_suffix(filename, ext) &&
- strlen(filename) >= (17 + strlen(ext)))
+ if (g_str_has_suffix(filename, ext) && + strlen(filename) >= (17 + strlen(ext))) { PurpleLogCommonLoggerData *data;
GDateTime *stamp = purple_str_to_date_time(purple_unescape_filename(filename), FALSE);
@@ -971,9 +970,8 @@
while ((filename = g_dir_read_name(dir)))
- if (purple_str_has_suffix(filename, ext) &&
- strlen(filename) >= (17 + strlen(ext)))
+ if (g_str_has_suffix(filename, ext) && + strlen(filename) >= (17 + strlen(ext))) { char *tmp = g_build_filename(path, filename, NULL);
--- a/libpurple/network.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/network.c Mon Nov 04 14:43:49 2019 +0300
@@ -150,6 +150,29 @@
+purple_network_get_local_system_ip_from_gio(GSocketConnection *sockconn) + GInetSocketAddress *inetsockaddr; + addr = g_socket_connection_get_local_address(sockconn, NULL); + if ((inetsockaddr = G_INET_SOCKET_ADDRESS(addr)) != NULL) { + GInetAddress *inetaddr = + g_inet_socket_address_get_address(inetsockaddr); + if (g_inet_address_get_family(inetaddr) == G_SOCKET_FAMILY_IPV4 && + !g_inet_address_get_is_loopback(inetaddr)) { + ip = g_inet_address_to_string(inetaddr); + return g_strdup("0.0.0.0"); purple_network_get_all_local_system_ips(void)
@@ -286,6 +309,42 @@
return purple_network_get_local_system_ip(fd);
+purple_network_get_my_ip_from_gio(GSocketConnection *sockconn) + const gchar *ip = NULL; + PurpleStunNatDiscovery *stun; + /* Check if the user specified an IP manually */ + if (!purple_prefs_get_bool("/purple/network/auto_ip")) { + ip = purple_network_get_public_ip(); + /* Make sure the IP address entered by the user is valid */ + if ((ip != NULL) && (purple_network_is_ipv4(ip))) { + /* Check if STUN discovery was already done */ + stun = purple_stun_discover(NULL); + if ((stun != NULL) && (stun->status == PURPLE_STUN_STATUS_DISCOVERED)) { + return g_strdup(stun->publicip); + /* Attempt to get the IP from a NAT device using UPnP */ + ip = purple_upnp_get_public_ip(); + /* Attempt to get the IP from a NAT device using NAT-PMP */ + ip = purple_pmp_get_public_ip(); + /* Just fetch the IP of the local system */ + return purple_network_get_local_system_ip_from_gio(sockconn); purple_network_set_upnp_port_mapping_cb(gboolean success, gpointer data)
--- a/libpurple/network.h Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/network.h Mon Nov 04 14:43:49 2019 +0300
@@ -29,6 +29,7 @@
@@ -113,6 +114,23 @@
const char *purple_network_get_my_ip(int fd);
+ * purple_network_get_my_ip_from_gio: + * @sockconn: The socket connection to use to help figure out the IP, or %NULL. + * Returns the IP address that should be used anywhere a + * public IP addresses is needed (listening for an incoming + * If the user has manually specified an IP address via + * preferences, then this IP is returned. Otherwise the + * IP address returned by purple_network_get_local_system_ip_from_gio() + * Returns: The local IP address to be used. +gchar *purple_network_get_my_ip_from_gio(GSocketConnection *sockconn); * @port: The port number to bind to. Must be greater than 0.
* @socket_family: The protocol family of the socket. This should be
--- a/libpurple/plugins/autoaccept.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/plugins/autoaccept.c Mon Nov 04 14:43:49 2019 +0300
@@ -54,8 +54,9 @@
if (!g_file_test(dir, G_FILE_TEST_IS_DIR))
- if (purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR))
+ if (g_mkdir_with_parents(dir, S_IRUSR | S_IWUSR | S_IXUSR)) { --- a/libpurple/plugins/keyrings/internalkeyring.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/plugins/keyrings/internalkeyring.c Mon Nov 04 14:43:49 2019 +0300
@@ -849,7 +849,7 @@
- *destroy = (GDestroyNotify)g_free;
--- a/libpurple/plugins/log_reader.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/plugins/log_reader.c Mon Nov 04 14:43:49 2019 +0300
@@ -100,9 +100,11 @@
while ((file = g_dir_read_name(dir))) {
- if (!purple_str_has_prefix(file, sn))
+ if (!g_str_has_prefix(file, sn)) { - if (purple_str_has_suffix(file, ".html") || purple_str_has_suffix(file, ".AdiumHTMLLog")) {
+ if (g_str_has_suffix(file, ".html") || + g_str_has_suffix(file, ".AdiumHTMLLog")) { gint year, month, day, hour, minute, second;
@@ -165,7 +167,7 @@
list = g_list_prepend(list, log);
- } else if (purple_str_has_suffix(file, ".adiumLog")) {
+ } else if (g_str_has_suffix(file, ".adiumLog")) { gint year, month, day, hour, minute, second;
@@ -269,8 +271,7 @@
/* This problem only seems to show up on Windows.
* The BOM is displaying as a space at the beginning of the log.
- if (purple_str_has_prefix(read, "\xef\xbb\xbf"))
+ if (g_str_has_prefix(read, "\xef\xbb\xbf")) { /* FIXME: This feels so wrong... */
char *temp = g_strdup(&(read[3]));
@@ -578,8 +579,9 @@
while ((name = g_dir_read_name(dir))) {
- if (!purple_str_has_prefix(c, username))
+ if (!g_str_has_prefix(c, username)) { @@ -631,8 +633,9 @@
- if (!purple_str_has_prefix(c, username))
+ if (!g_str_has_prefix(c, username)) { @@ -862,16 +865,18 @@
* friendly name or alias. For this test, "match" is defined as:
* ^(friendly_name|alias)([^a-zA-Z0-9].*)?$
- from_name_matches = (purple_str_has_prefix(from_name, friendly_name) &&
- !isalnum(*(from_name + friendly_name_length))) ||
- (purple_str_has_prefix(from_name, alias) &&
- !isalnum(*(from_name + alias_length)));
- to_name_matches = to_name != NULL && (
- (purple_str_has_prefix(to_name, friendly_name) &&
- !isalnum(*(to_name + friendly_name_length))) ||
- (purple_str_has_prefix(to_name, alias) &&
- !isalnum(*(to_name + alias_length))));
+ (g_str_has_prefix(from_name, friendly_name) && + !isalnum(*(from_name + friendly_name_length))) || + (g_str_has_prefix(from_name, alias) && + !isalnum(*(from_name + alias_length))); + ((g_str_has_prefix(to_name, friendly_name) && + !isalnum(*(to_name + friendly_name_length))) || + (g_str_has_prefix(to_name, alias) && + !isalnum(*(to_name + alias_length)))); @@ -901,15 +906,13 @@
* matches their alias. For this test, "match" is
* defined as: ^alias([^a-zA-Z0-9].*)?$
- from_name_matches = (purple_str_has_prefix(
- to_name_matches = to_name && (purple_str_has_prefix(
+ (g_str_has_prefix(from_name, alias) && + !isalnum(*(from_name + alias_length))); + to_name_matches = to_name && + (g_str_has_prefix(to_name, alias) && + !isalnum(*(to_name + alias_length))); @@ -929,17 +932,17 @@
* this test, "match" is defined as:
* ^friendly_name([^a-zA-Z0-9].*)?$
- from_name_matches = (purple_str_has_prefix(
- friendly_name_length)));
- to_name_matches = to_name && (
- (purple_str_has_prefix(
- to_name, server_alias) &&
- friendly_name_length))));
+ (g_str_has_prefix(from_name, + friendly_name_length))); + ((g_str_has_prefix(to_name, server_alias) && + friendly_name_length)))); @@ -1142,7 +1145,7 @@
- if (purple_str_has_prefix(line, "Session Close ")) {
+ if (g_str_has_prefix(line, "Session Close ")) { if (data && !data->length) {
if (!(data->length = last_line_offset - data->offset)) {
/* This log had no data, so we remove it. */
@@ -1156,7 +1159,7 @@
} else if (line[0] && line[1] && line[2] &&
- purple_str_has_prefix(&line[3], "sion Start ")) {
+ g_str_has_prefix(&line[3], "sion Start ")) { /* The conditional is to make sure we're not reading off
* the end of the string. We don't want strlen(), as that'd
* have to count the whole string needlessly.
@@ -1418,17 +1421,18 @@
- if (purple_str_has_prefix(line, "*** ")) {
+ if (g_str_has_prefix(line, "*** ")) { line += (sizeof("*** ") - 1);
g_string_append(formatted, "<b>");
- if (purple_str_has_prefix(line, "NOTE: This user is offline.")) {
+ if (g_str_has_prefix(line, "NOTE: This user is offline.")) { line = _("User is offline.");
- } else if (purple_str_has_prefix(line,
- "NOTE: Your status is currently set to ")) {
+ } else if (g_str_has_prefix( + "NOTE: Your status is currently set to ")) { line += (sizeof("NOTE: ") - 1);
- } else if (purple_str_has_prefix(line, "Auto-response sent to ")) {
+ } else if (g_str_has_prefix(line, "Auto-response sent to ")) { g_string_append(formatted, _("Auto-response sent:"));
while (*line && *line != ':')
@@ -1462,8 +1466,8 @@
g_string_append(formatted, log->name);
- } else if (purple_str_has_prefix(line,
- "One or more messages may have been undeliverable.")) {
+ } else if (g_str_has_prefix(line, "One or more messages may " + "have been undeliverable.")) { g_string_append(formatted,
"<span style=\"color: #ff0000;\">");
@@ -1472,8 +1476,8 @@
- } else if (purple_str_has_prefix(line,
- "You have been disconnected.")) {
+ } else if (g_str_has_prefix(line, + "You have been disconnected.")) { g_string_append(formatted,
"<span style=\"color: #ff0000;\">");
@@ -1481,8 +1485,8 @@
_("You were disconnected from the server."));
- } else if (purple_str_has_prefix(line,
- "You are currently disconnected.")) {
+ } else if (g_str_has_prefix( + line, "You are currently disconnected.")) { g_string_append(formatted,
"<span style=\"color: #ff0000;\">");
@@ -1490,15 +1494,16 @@
"will not be received unless you are "
- } else if (purple_str_has_prefix(line,
- "Your previous message has not been sent.")) {
+ } else if (g_str_has_prefix(line, "Your previous message has " g_string_append(formatted,
"<span style=\"color: #ff0000;\">");
- if (purple_str_has_prefix(line,
- "Your previous message has not been sent. "
- "Reason: Maximum length exceeded.")) {
+ "Your previous message has not been sent. " + "Reason: Maximum length exceeded.")) { g_string_append(formatted,
_("Message could not be sent because "
@@ -1514,7 +1519,7 @@
- } else if (purple_str_has_prefix(line, data->their_nickname)) {
+ } else if (g_str_has_prefix(line, data->their_nickname)) { const char *alias = purple_buddy_get_alias(buddy);
@@ -1684,8 +1689,8 @@
gboolean add_new_log = FALSE;
- if (purple_str_has_prefix(c, QIP_LOG_IN_MESSAGE) ||
- purple_str_has_prefix(c, QIP_LOG_OUT_MESSAGE)) {
+ if (g_str_has_prefix(c, QIP_LOG_IN_MESSAGE) || + g_str_has_prefix(c, QIP_LOG_OUT_MESSAGE)) { @@ -1841,12 +1846,12 @@
gboolean is_in_message = FALSE;
- if (purple_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC) ||
- purple_str_has_prefix(line, QIP_LOG_OUT_MESSAGE_ESC)) {
+ if (g_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC) || + g_str_has_prefix(line, QIP_LOG_OUT_MESSAGE_ESC)) { - is_in_message = purple_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC);
+ is_in_message = g_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC); @@ -2010,7 +2015,7 @@
gint year, month, day, hour, minute, second;
- if (purple_str_has_prefix(c, AMSN_LOG_CONV_START)) {
+ if (g_str_has_prefix(c, AMSN_LOG_CONV_START)) { if (sscanf(c + strlen(AMSN_LOG_CONV_START),
@@ -2027,7 +2032,7 @@
- } else if (purple_str_has_prefix(c, AMSN_LOG_CONV_END) && found_start) {
+ } else if (g_str_has_prefix(c, AMSN_LOG_CONV_END) && found_start) { data = g_new0(struct amsn_logger_data, 1);
data->path = g_strdup(filename);
@@ -2215,7 +2220,7 @@
- if (purple_str_has_prefix(start, AMSN_LOG_FORMAT_TAG) && in_span) {
+ if (g_str_has_prefix(start, AMSN_LOG_FORMAT_TAG) && in_span) { /* New format for this line */
g_string_append(formatted, "</span><br>");
@@ -2244,19 +2249,19 @@
old_tag = tag + 7; /* C + xxxxxx */
/* |"Lxxx is a 3-digit colour code */
- if (purple_str_has_prefix(tag, "RED")) {
+ if (g_str_has_prefix(tag, "RED")) { g_string_append(formatted, "<span style=\"color: red;\">");
- } else if (purple_str_has_prefix(tag, "GRA")) {
+ } else if (g_str_has_prefix(tag, "GRA")) { g_string_append(formatted, "<span style=\"color: gray;\">");
- } else if (purple_str_has_prefix(tag, "NOR")) {
+ } else if (g_str_has_prefix(tag, "NOR")) { g_string_append(formatted, "<span style=\"color: black;\">");
- } else if (purple_str_has_prefix(tag, "ITA")) {
+ } else if (g_str_has_prefix(tag, "ITA")) { g_string_append(formatted, "<span style=\"color: blue;\">");
- } else if (purple_str_has_prefix(tag, "GRE")) {
+ } else if (g_str_has_prefix(tag, "GRE")) { g_string_append(formatted, "<span style=\"color: darkgreen;\">");
@@ -2429,7 +2434,7 @@
- if (purple_str_has_suffix(value, "trillian.exe")) {
+ if (g_str_has_suffix(value, "trillian.exe")) { value[strlen(value) - (sizeof("trillian.exe") - 1)] = '\0';
path = g_build_filename(value, "users", "default", "talk.ini", NULL);
@@ -2472,7 +2477,7 @@
/* XXX: This assumes the first Directory key is under [Logging]. */
- if (purple_str_has_prefix(line, "Directory=")) {
+ if (g_str_has_prefix(line, "Directory=")) { line += (sizeof("Directory=") - 1);
--- a/libpurple/presence.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/presence.c Mon Nov 04 14:43:49 2019 +0300
@@ -462,7 +462,7 @@
purple_presence_get_instance_private(PURPLE_PRESENCE(object));
- g_list_free_full(priv->statuses, (GDestroyNotify)g_object_unref);
+ g_list_free_full(priv->statuses, g_object_unref); --- a/libpurple/protocols.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols.c Mon Nov 04 14:43:49 2019 +0300
@@ -690,7 +690,7 @@
void *handle = purple_protocols_get_handle();
protocols = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
- (GDestroyNotify)g_object_unref);
purple_signal_register(handle, "protocol-added",
purple_marshal_VOID__POINTER,
--- a/libpurple/protocols/bonjour/bonjour_ft.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/bonjour/bonjour_ft.c Mon Nov 04 14:43:49 2019 +0300
@@ -33,7 +33,7 @@
bonjour_xfer_init(PurpleXfer *xfer);
bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *sid, const char *from,
- const goffset filesize, const char *filename, int option);
+ goffset filesize, const char *filename, int option); /* Look for specific xfer handle */
static unsigned int next_id = 0;
@@ -727,7 +727,7 @@
bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *sid, const char *from,
- const goffset filesize, const char *filename, int option)
+ goffset filesize, const char *filename, int option) @@ -877,7 +877,6 @@
@@ -943,8 +942,6 @@
bonjour_bytestreams_listen, xfer);
if (xf->listen_data == NULL)
purple_xfer_cancel_local(xfer);
--- a/libpurple/protocols/bonjour/mdns_dns_sd.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/bonjour/mdns_dns_sd.c Mon Nov 04 14:43:49 2019 +0300
@@ -460,7 +460,7 @@
gboolean _mdns_init_session(BonjourDnsSd *data) {
data->mdns_impl_data = g_new0(Win32SessionImplData, 1);
- bonjour_dns_sd_set_jid(data->account, purple_get_host_name());
+ bonjour_dns_sd_set_jid(data->account, g_get_host_name()); --- a/libpurple/protocols/facebook/api.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/facebook/api.c Mon Nov 04 14:43:49 2019 +0300
@@ -2339,7 +2339,7 @@
g_signal_emit_by_name(api, "contacts-delta", added, removed);
g_slist_free_full(added, (GDestroyNotify) fb_api_user_free);
- g_slist_free_full(removed, (GDestroyNotify) g_free);
+ g_slist_free_full(removed, g_free); --- a/libpurple/protocols/gg/blist.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/gg/blist.c Mon Nov 04 14:43:49 2019 +0300
@@ -187,7 +187,7 @@
-const char * ggp_buddylist_get_buddy_name(PurpleConnection *gc, const uin_t uin)
+const char * ggp_buddylist_get_buddy_name(PurpleConnection *gc, uin_t uin) const char *uin_s = ggp_uin_to_str(uin);
PurpleBuddy *buddy = purple_blist_find_buddy(
--- a/libpurple/protocols/gg/blist.h Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/gg/blist.h Mon Nov 04 14:43:49 2019 +0300
@@ -57,7 +57,7 @@
* @return Name of the buddy, or UIN converted to string, if there is no such
-const char * ggp_buddylist_get_buddy_name(PurpleConnection *gc, const uin_t uin);
+const char * ggp_buddylist_get_buddy_name(PurpleConnection *gc, uin_t uin); #endif /* PURPLE_GG_BLIST_H */
--- a/libpurple/protocols/gg/edisc.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/gg/edisc.c Mon Nov 04 14:43:49 2019 +0300
@@ -358,15 +358,14 @@
msg = soup_message_new("PUT", "https://drive.mpa.gg.pl/signin");
ggp_edisc_set_defaults(msg);
- "\"os_version\": \"" GGP_EDISC_OS "\", "
- "\"client_version\": \"%s\", "
- "\"type\": \"" GGP_EDISC_TYPE "\"}",
- g_random_int_range(1, 1 << 16),
- purple_get_host_name(), ggp_libgaduw_version(gc));
+ metadata = g_strdup_printf("{" + "\"os_version\": \"" GGP_EDISC_OS "\", " + "\"client_version\": \"%s\", " + "\"type\": \"" GGP_EDISC_TYPE "\"}", + g_random_int_range(1, 1 << 16), + g_get_host_name(), ggp_libgaduw_version(gc)); tmp = g_strdup_printf("IMToken %s", imtoken);
soup_message_headers_replace(msg->request_headers, "Authorization", tmp);
--- a/libpurple/protocols/irc/cmds.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/irc/cmds.c Mon Nov 04 14:43:49 2019 +0300
@@ -694,6 +694,4 @@
--- a/libpurple/protocols/irc/msgs.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/irc/msgs.c Mon Nov 04 14:43:49 2019 +0300
@@ -333,8 +333,6 @@
purple_conversation_write_system_message(PURPLE_CONVERSATION(chat), buf, 0);
void irc_msg_whois(struct irc_conn *irc, const char *name, const char *from, char **args)
@@ -495,8 +493,8 @@
realname = g_strdup(cur);
- g_object_set_data_full(G_OBJECT(cb), "userhost", userhost, (GDestroyNotify)g_free);
- g_object_set_data_full(G_OBJECT(cb), "realname", realname, (GDestroyNotify)g_free);
+ g_object_set_data_full(G_OBJECT(cb), "userhost", userhost, g_free); + g_object_set_data_full(G_OBJECT(cb), "realname", realname, g_free); flags = purple_chat_user_get_flags(cb);
@@ -971,7 +969,7 @@
cb = purple_chat_conversation_find_user(chat, nick);
- g_object_set_data_full(G_OBJECT(cb), "userhost", userhost, (GDestroyNotify)g_free);
+ g_object_set_data_full(G_OBJECT(cb), "userhost", userhost, g_free); if ((ib = g_hash_table_lookup(irc->buddies, nick)) != NULL) {
@@ -1010,7 +1008,6 @@
void irc_msg_mode(struct irc_conn *irc, const char *name, const char *from, char **args)
@@ -1362,8 +1359,6 @@
irc_buddy_status(data[0], ib, irc);
void irc_msg_unavailable(struct irc_conn *irc, const char *name, const char *from, char **args)
--- a/libpurple/protocols/jabber/auth_cyrus.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/jabber/auth_cyrus.c Mon Nov 04 14:43:49 2019 +0300
@@ -402,11 +402,22 @@
jabber_cyrus_start(JabberStream *js, PurpleXmlNode *mechanisms,
PurpleXmlNode **reply, char **error)
- PurpleXmlNode *mechnode;
+ PurpleXmlNode *mechnode, *hostname; js->sasl_mechs = g_string_new("");
js->sasl_password = g_strdup(purple_connection_get_password(js->gc));
+ /* XEP-0233 says we should grab the hostname for Kerberos v5, but there + * is no claim about other SASL mechanisms. Fortunately, most don't + * care what we use, so just use the domainpart. */ + hostname = purple_xmlnode_get_child_with_namespace( + mechanisms, "hostname", NS_XMPP_SERVER_REGISTRATION); + js->serverFQDN = purple_xmlnode_get_data(hostname); + if (js->serverFQDN == NULL) { + js->serverFQDN = g_strdup(js->user->domain); for(mechnode = purple_xmlnode_get_child(mechanisms, "mechanism"); mechnode;
mechnode = purple_xmlnode_get_next_twin(mechnode))
--- a/libpurple/protocols/jabber/bosh.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/jabber/bosh.c Mon Nov 04 14:43:49 2019 +0300
@@ -134,12 +134,6 @@
conn->rid = (((guint64)g_random_int() << 32) | g_random_int());
conn->rid &= 0xFFFFFFFFFFFFFLL;
- if (g_hostname_is_ip_address(url_p->host)) {
- js->serverFQDN = g_strdup(js->user->domain);
- js->serverFQDN = g_strdup(url_p->host);
g_object_unref(resolver);
--- a/libpurple/protocols/jabber/google/gmail.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/jabber/google/gmail.c Mon Nov 04 14:43:49 2019 +0300
@@ -176,7 +176,6 @@
purple_xmlnode_set_attrib(query, "newer-than-tid", js->gmail_last_tid);
void jabber_gmail_init(JabberStream *js) {
--- a/libpurple/protocols/jabber/google/google_presence.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/jabber/google/google_presence.c Mon Nov 04 14:43:49 2019 +0300
@@ -26,7 +26,7 @@
- if (jbr->status && purple_str_has_prefix(jbr->status, "♫ ")) {
+ if (jbr->status && g_str_has_prefix(jbr->status, "♫ ")) { purple_protocol_got_user_status(purple_connection_get_account(js->gc), user, "tune",
PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL);
--- a/libpurple/protocols/jabber/jabber.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/jabber/jabber.c Mon Nov 04 14:43:49 2019 +0300
@@ -35,6 +35,7 @@
#include "purpleaccountoption.h"
@@ -222,12 +223,13 @@
PurpleAccount *account = NULL;
PurpleXmlNode *starttls = NULL;
- /* It's a secure BOSH connection, just return FALSE and skip, without doing anything extra.
- * XEP-0206 (XMPP Over BOSH): The client SHOULD ignore any Transport Layer Security (TLS)
- * feature since BOSH channel encryption SHOULD be negotiated at the HTTP layer.
+ /* It's a secure BOSH connection, just return FALSE and skip, without doing + * anything extra. XEP-0206 (XMPP Over BOSH): The client SHOULD ignore any + * Transport Layer Security (TLS) feature since BOSH channel encryption + * SHOULD be negotiated at the HTTP layer. - * Note: we are already receiving STARTTLS at this point from a SSL/TLS BOSH connection,
- * so it is not necessary to check if purple_ssl_is_supported().
+ * Note: we are already receiving STARTTLS at this point from a SSL/TLS BOSH + * connection, so it is not necessary to check if SSL is supported. if (js->bosh && jabber_bosh_connection_is_ssl(js->bosh)) {
@@ -366,9 +368,10 @@
jabber_auth_handle_failure(js, *packet);
} else if (purple_strequal(xmlns, NS_XMPP_TLS)) {
- if (js->state != JABBER_STREAM_INITIALIZING_ENCRYPTION || js->gsc)
+ if (js->state != JABBER_STREAM_INITIALIZING_ENCRYPTION || + G_IS_TLS_CONNECTION(js->stream)) { purple_debug_warning("jabber", "Ignoring spurious %s\n", name);
if (purple_strequal(name, "proceed"))
/* TODO: Handle <failure/>, I guess? */
@@ -378,52 +381,27 @@
-static int jabber_do_send(JabberStream *js, const char *data, int len)
+jabber_push_bytes_cb(GObject *source, GAsyncResult *res, gpointer data)
- ret = purple_ssl_write(js->gsc, data, len);
- ret = write(js->fd, data, len);
-static void jabber_send_cb(gpointer data, gint source, PurpleInputCondition cond)
+ PurpleQueuedOutputStream *stream = PURPLE_QUEUED_OUTPUT_STREAM(source); - const gchar *output = NULL;
- writelen = purple_circular_buffer_get_max_read(js->write_buffer);
- output = purple_circular_buffer_get_output(js->write_buffer);
- purple_input_remove(js->writeh);
+ result = purple_queued_output_stream_push_bytes_finish(stream, res, &error); + purple_queued_output_stream_clear_queue(stream); + g_prefix_error(&error, "%s", _("Lost connection with server: ")); + purple_connection_take_error(js->gc, error);
- ret = jabber_do_send(js, output, writelen);
- if (ret < 0 && errno == EAGAIN)
- gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
- purple_connection_error(js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
- purple_circular_buffer_mark_read(js->write_buffer, ret);
static gboolean do_jabber_send_raw(JabberStream *js, const char *data, int len)
g_return_val_if_fail(len > 0, FALSE);
@@ -431,39 +409,11 @@
if (js->state == JABBER_STREAM_CONNECTED)
jabber_stream_restart_inactivity_timer(js);
- ret = jabber_do_send(js, data, len);
- if (ret < 0 && errno != EAGAIN) {
- PurpleAccount *account = purple_connection_get_account(js->gc);
- * The server may have closed the socket (on a stream error), so if
- * we're disconnecting, don't generate (possibly another) error that
- * (for some UIs) would mask the first.
- if (!purple_account_is_disconnecting(account)) {
- gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
- purple_connection_error(js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
- } else if (ret < len) {
- js->writeh = purple_input_add(
- js->gsc ? js->gsc->fd : js->fd,
- PURPLE_INPUT_WRITE, jabber_send_cb, js);
- purple_circular_buffer_append(js->write_buffer,
- data + ret, len - ret);
+ output = g_bytes_new(data, len); + purple_queued_output_stream_push_bytes_async( + js->output, output, G_PRIORITY_DEFAULT, js->cancellable, + jabber_push_bytes_cb, js); @@ -531,8 +481,7 @@
- if (!js->gsc && js->fd<0)
+ g_return_if_fail(js->input != NULL); @@ -647,51 +596,21 @@
-jabber_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc,
- PurpleInputCondition cond)
+jabber_recv_cb(GObject *stream, gpointer data) PurpleConnection *gc = data;
JabberStream *js = purple_connection_get_protocol_data(gc);
PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- while((len = purple_ssl_read(gsc, buf, sizeof(buf) - 1)) > 0) {
- purple_connection_update_last_received(gc);
- purple_debug_misc("jabber", "Recv (ssl)(%d): %s", len, buf);
- jabber_parser_process(js, buf, len);
- jabber_stream_init(js);
- if(len < 0 && errno == EAGAIN)
- tmp = g_strdup(_("Server closed the connection"));
- tmp = g_strdup_printf(_("Lost connection with server: %s"),
- purple_connection_error(js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
-jabber_recv_cb(gpointer data, gint source, PurpleInputCondition condition)
- PurpleConnection *gc = data;
- JabberStream *js = purple_connection_get_protocol_data(gc);
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- if((len = read(js->fd, buf, sizeof(buf) - 1)) > 0) {
+ len = g_pollable_input_stream_read_nonblocking( + G_POLLABLE_INPUT_STREAM(stream), buf, sizeof(buf) - 1, + js->cancellable, &error); purple_connection_update_last_received(gc);
if (js->sasl_maxbuf > 0) {
@@ -720,43 +639,20 @@
- purple_debug_misc("jabber", "Recv (%d): %s", len, buf);
+ purple_debug_misc("jabber", "Recv (%" G_GSSIZE_FORMAT "): %s", len, jabber_parser_process(js, buf, len);
- } else if(len < 0 && errno == EAGAIN) {
- tmp = g_strdup(_("Server closed the connection"));
- tmp = g_strdup_printf(_("Lost connection with server: %s"),
- purple_connection_error(js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+ purple_connection_error(js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Server closed the connection")); + } else if (error->code != G_IO_ERROR_WOULD_BLOCK && + error->code != G_IO_ERROR_CANCELLED) { + g_prefix_error(&error, "%s", _("Lost connection with server: ")); + purple_connection_g_error(js->gc, error);
-jabber_login_callback_ssl(gpointer data, PurpleSslConnection *gsc,
- PurpleInputCondition cond)
- PurpleConnection *gc = data;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- js = purple_connection_get_protocol_data(gc);
- if(js->state == JABBER_STREAM_CONNECTING)
- jabber_send_raw(js, "<?xml version='1.0' ?>", -1);
- jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING);
- purple_ssl_input_add(gsc, jabber_recv_cb_ssl, gc);
- /* Tell the app that we're doing encryption */
- jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION);
@@ -823,130 +719,184 @@
-jabber_login_callback(gpointer data, gint source, const gchar *error)
+jabber_stream_connect_finish(JabberStream *js, GIOStream *stream) + js->input = g_io_stream_get_input_stream(js->stream); + js->output = purple_queued_output_stream_new( + g_io_stream_get_output_stream(js->stream)); + if (js->state == JABBER_STREAM_CONNECTING) { + jabber_send_raw(js, "<?xml version='1.0' ?>", -1); + jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING); + source = g_pollable_input_stream_create_source( + G_POLLABLE_INPUT_STREAM(js->input), js->cancellable); + g_source_set_callback(source, (GSourceFunc)jabber_recv_cb, js->gc, NULL); + js->inpa = g_source_attach(source, NULL); +jabber_login_callback(GObject *source_object, GAsyncResult *res, gpointer data) - PurpleConnection *gc = data;
- JabberStream *js = purple_connection_get_protocol_data(gc);
- GResolver *resolver = g_resolver_get_default();
- gchar *name = g_strdup_printf("_xmppconnect.%s", js->user->domain);
- purple_debug_info("jabber", "Couldn't connect directly to %s. Trying to find alternative connection methods, like BOSH.\n", js->user->domain);
- g_resolver_lookup_records_async(resolver,
+ GSocketClient *client = G_SOCKET_CLIENT(source_object); + JabberStream *js = data; + GSocketConnection *conn; + gboolean is_old_ssl = g_socket_client_get_tls(client); + conn = g_socket_client_connect_to_host_finish(client, res, &error); + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + } else if (is_old_ssl) { + /* Old-style SSL only makes a direct connection, or fails. */ + purple_connection_take_error(js->gc, error); + name = g_strdup_printf("_xmppconnect.%s", js->user->domain); + purple_debug_info("jabber", + "Couldn't connect directly to %s. Trying to find " + "alternative connection methods, like BOSH.\n", + resolver = g_resolver_get_default(); + g_resolver_lookup_records_async(resolver, name, G_RESOLVER_RECORD_TXT, + js->cancellable, txt_resolved_cb, js); g_object_unref(resolver);
- if(js->state == JABBER_STREAM_CONNECTING)
- jabber_send_raw(js, "<?xml version='1.0' ?>", -1);
- jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING);
- js->inpa = purple_input_add(js->fd, PURPLE_INPUT_READ, jabber_recv_cb, gc);
+ stream = G_IO_STREAM(g_tcp_wrapper_connection_get_base_io_stream( + G_TCP_WRAPPER_CONNECTION(conn))); + stream = G_IO_STREAM(conn); + jabber_stream_connect_finish(js, stream); + /* Tell the app that we're doing encryption */ + jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION); -jabber_ssl_connect_failure(PurpleSslConnection *gsc, PurpleSslErrorType error,
+tls_handshake_cb(GObject *source_object, GAsyncResult *res, gpointer data) - PurpleConnection *gc = data;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- js = purple_connection_get_protocol_data(gc);
- purple_connection_ssl_error (gc, error);
+ JabberStream *js = data; + if (!g_tls_connection_handshake_finish(G_TLS_CONNECTION(source_object), res, + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + /* Connection already closed/freed. Escape. */ + } else if (g_error_matches(error, G_TLS_ERROR, G_TLS_ERROR_HANDSHAKE)) { + /* In Gio, a handshake error is because of the cert */ + purple_connection_ssl_error(js->gc, PURPLE_SSL_CERTIFICATE_INVALID); + /* Report any other errors as handshake failing */ + purple_connection_ssl_error(js->gc, PURPLE_SSL_HANDSHAKE_FAILED); + jabber_stream_connect_finish(js, js->stream); + /* Tell the app that we're doing encryption */ + jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION); static void tls_init(JabberStream *js)
- purple_input_remove(js->inpa);
+ GSocketConnectable *identity; + g_source_remove(js->inpa); - js->gsc = purple_ssl_connect_with_host_fd(purple_connection_get_account(js->gc), js->fd,
- jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc);
- /* The fd is no longer our concern */
-static gboolean jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port,
- gboolean fatal_failure)
- /* host should be used in preference to domain to
- * allow SASL authentication to work with FQDN of the server,
- * but we use domain as fallback for when users enter IP address
- g_free(js->serverFQDN);
- if (g_hostname_is_ip_address(host)) {
- js->serverFQDN = g_strdup(domain);
- js->serverFQDN = g_strdup(host);
+ g_filter_output_stream_set_close_base_stream( + G_FILTER_OUTPUT_STREAM(js->output), FALSE); + g_output_stream_close(G_OUTPUT_STREAM(js->output), js->cancellable, NULL); + identity = g_network_address_new(js->certificate_CN, 0); + tls_conn = g_tls_client_connection_new(js->stream, identity, &error); + g_object_unref(identity); + if (tls_conn == NULL) { + purple_debug_warning("jabber", + "Error creating TLS client connection: %s", + purple_connection_ssl_error(js->gc, PURPLE_SSL_CONNECT_FAILED); - if (purple_proxy_connect(js->gc, purple_connection_get_account(js->gc),
- host, port, jabber_login_callback, js->gc) == NULL) {
- purple_connection_error(js->gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Unable to connect"));
+ g_clear_object(&js->stream); + js->stream = G_IO_STREAM(tls_conn); + g_tls_connection_handshake_async(G_TLS_CONNECTION(tls_conn), + G_PRIORITY_DEFAULT, js->cancellable, -srv_resolved_cb(GObject *sender, GAsyncResult *result, gpointer data)
+srv_resolved_cb(GObject *source_object, GAsyncResult *result, gpointer data)
- GList *targets = NULL, *l = NULL;
+ GSocketClient *client = G_SOCKET_CLIENT(source_object);
- targets = g_resolver_lookup_service_finish(G_RESOLVER(sender),
- purple_debug_warning("jabber",
- "SRV lookup failed, proceeding with normal connection : %s",
+ GSocketConnection *conn; + conn = g_socket_client_connect_to_service_finish(client, result, &error); + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + /* Do nothing; cancelled. */ + } else if (g_error_matches(error, G_RESOLVER_ERROR, + G_RESOLVER_ERROR_NOT_FOUND)) { + /* If there was no response, then attempt fallback behaviour of XMPP + "SRV lookup failed, proceeding with normal connection : %s", + g_socket_client_connect_to_host_async( + js->client, js->user->domain, + purple_account_get_int( + purple_connection_get_account(js->gc), "port", + js->cancellable, jabber_login_callback, js); + /* If resolving failed or connecting failed, then just error out, as + * in XMPP Core 3.2.1 step 8. */ + purple_connection_g_error(js->gc, error);
- jabber_login_connect(js, js->user->domain, js->user->domain,
- purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
- for(l = targets; l; l = l->next) {
- GSrvTarget *target = (GSrvTarget *)l->data;
- const gchar *hostname = g_srv_target_get_hostname(target);
- guint port = g_srv_target_get_port(target);
- if(jabber_login_connect(js, hostname, hostname, port, FALSE)) {
- g_resolver_free_targets(targets);
- g_resolver_free_targets(targets);
- jabber_login_connect(js, js->user->domain, js->user->domain,
- purple_account_get_int(purple_connection_get_account(js->gc), "port", 5222),
+ jabber_stream_connect_finish(js, G_IO_STREAM(conn)); @@ -971,7 +921,6 @@
js = g_new0(JabberStream, 1);
purple_connection_set_protocol_data(gc, js);
js->http_conns = soup_session_new_with_options(SOUP_SESSION_PROXY_RESOLVER,
g_object_unref(resolver);
@@ -1039,7 +988,6 @@
js->chats = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, (GDestroyNotify)jabber_chat_free);
js->next_id = g_random_int();
- js->write_buffer = purple_circular_buffer_new(512);
js->keepalive_timeout = 0;
js->max_inactivity = DEFAULT_INACTIVITY_TIME;
@@ -1071,6 +1019,7 @@
const char *bosh_url = purple_account_get_string(account,
jabber_stream_set_state(js, JABBER_STREAM_CONNECTING);
@@ -1088,37 +1037,35 @@
+ js->client = purple_gio_socket_client_new(account, &error); + if (js->client == NULL) { + purple_connection_take_error(gc, error); js->certificate_CN = g_strdup(connect_server[0] ? connect_server : js->user->domain);
/* if they've got old-ssl mode going, we probably want to ignore SRV lookups */
if (purple_strequal("old_ssl", purple_account_get_string(account, "connection_security", JABBER_DEFAULT_REQUIRE_TLS))) {
- js->gsc = purple_ssl_connect(account, js->certificate_CN,
- purple_account_get_int(account, "port", 5223),
- jabber_login_callback_ssl, jabber_ssl_connect_failure, gc);
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
- _("Unable to establish SSL connection"));
+ g_socket_client_set_tls(js->client, TRUE); + g_socket_client_connect_to_host_async( + js->client, js->certificate_CN, + purple_account_get_int(account, "port", 5223), js->cancellable, + jabber_login_callback, js); /* no old-ssl, so if they've specified a connect server, we'll use that, otherwise we'll
* invoke the magic of SRV lookups, to figure out host and port */
- jabber_login_connect(js, js->user->domain, connect_server,
- purple_account_get_int(account, "port", 5222), TRUE);
+ g_socket_client_connect_to_host_async( + js->client, connect_server, + purple_account_get_int(account, "port", 5222), js->cancellable, + jabber_login_callback, js); - GResolver *resolver = g_resolver_get_default();
- g_resolver_lookup_service_async(resolver,
- g_object_unref(resolver);
+ g_socket_client_connect_to_service_async(js->client, js->user->domain, + "xmpp-client", js->cancellable, @@ -1649,19 +1596,21 @@
jabber_bosh_connection_destroy(js->bosh);
- } else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0)
+ } else if (js->output != NULL) { jabber_send_raw(js, "</stream:stream>", -1);
- purple_ssl_close(js->gsc);
- } else if (js->fd > 0) {
- purple_input_remove(js->inpa);
+ g_source_remove(js->inpa);
+ purple_gio_graceful_close(js->stream, js->input, + G_OUTPUT_STREAM(js->output)); + g_clear_object(&js->output); + g_clear_object(&js->input); + g_clear_object(&js->stream); jabber_buddy_remove_all_pending_buddy_info_requests(js);
@@ -1690,10 +1639,6 @@
- g_object_unref(G_OBJECT(js->write_buffer));
- purple_input_remove(js->writeh);
if (js->auth_mech && js->auth_mech->dispose)
js->auth_mech->dispose(js);
@@ -1746,7 +1691,11 @@
void jabber_stream_set_state(JabberStream *js, JabberStreamState state)
-#define JABBER_CONNECT_STEPS ((js->gsc || js->state == JABBER_STREAM_INITIALIZING_ENCRYPTION) ? 9 : 5)
+#define JABBER_CONNECT_STEPS \ + ((G_IS_TLS_CONNECTION(js->stream) || \ + js->state == JABBER_STREAM_INITIALIZING_ENCRYPTION) \ @@ -1757,8 +1706,10 @@
case JABBER_STREAM_INITIALIZING:
- purple_connection_update_progress(js->gc, _("Initializing Stream"),
- js->gsc ? 5 : 2, JABBER_CONNECT_STEPS);
+ purple_connection_update_progress( + js->gc, _("Initializing Stream"), + G_IS_TLS_CONNECTION(js->stream) ? 5 : 2, case JABBER_STREAM_INITIALIZING_ENCRYPTION:
@@ -1766,12 +1717,16 @@
6, JABBER_CONNECT_STEPS);
case JABBER_STREAM_AUTHENTICATING:
- purple_connection_update_progress(js->gc, _("Authenticating"),
- js->gsc ? 7 : 3, JABBER_CONNECT_STEPS);
+ purple_connection_update_progress( + js->gc, _("Authenticating"), + G_IS_TLS_CONNECTION(js->stream) ? 7 : 3, case JABBER_STREAM_POST_AUTH:
- purple_connection_update_progress(js->gc, _("Re-initializing Stream"),
- (js->gsc ? 8 : 4), JABBER_CONNECT_STEPS);
+ purple_connection_update_progress( + js->gc, _("Re-initializing Stream"), + (G_IS_TLS_CONNECTION(js->stream) ? 8 : 4), case JABBER_STREAM_CONNECTED:
@@ -2105,7 +2060,7 @@
gboolean jabber_stream_is_ssl(JabberStream *js)
return (js->bosh && jabber_bosh_connection_is_ssl(js->bosh)) ||
- (!js->bosh && js->gsc);
+ (!js->bosh && G_IS_TLS_CONNECTION(js->stream)); --- a/libpurple/protocols/jabber/jabber.h Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/jabber/jabber.h Mon Nov 04 14:43:49 2019 +0300
@@ -67,6 +67,7 @@
#include "mediamanager.h"
+#include "queuedoutputstream.h" @@ -119,7 +120,6 @@
GCancellable *cancellable;
@@ -196,7 +196,10 @@
- PurpleSslConnection *gsc;
+ PurpleQueuedOutputStream *output; @@ -206,9 +209,6 @@
GSList *pending_buddy_info_requests;
- PurpleCircularBuffer *write_buffer;
JabberCapabilities server_caps;
--- a/libpurple/protocols/jabber/namespaces.h Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/jabber/namespaces.h Mon Nov 04 14:43:49 2019 +0300
@@ -89,6 +89,9 @@
/* XEP-0231 BoB (Bits of Binary) */
#define NS_BOB "urn:xmpp:bob"
+/* XEP-0233 XMPP Server Registration for use with Kerberos V5 */ +#define NS_XMPP_SERVER_REGISTRATION "urn:xmpp:domain-based-name:1" /* XEP-0237 Roster Versioning */
#define NS_ROSTER_VERSIONING "urn:xmpp:features:rosterver"
--- a/libpurple/protocols/jabber/si.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/jabber/si.c Mon Nov 04 14:43:49 2019 +0300
@@ -416,7 +416,7 @@
char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/
purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_again_cb\n");
@@ -495,7 +495,8 @@
- host = purple_network_get_my_ip(jsx->js->fd);
+ host = purple_network_get_my_ip_from_gio( + G_SOCKET_CONNECTION(jsx->js->stream)); jsx->rxmaxlen = 5 + strlen(host) + 2;
jsx->rxqueue = g_malloc(jsx->rxmaxlen);
@@ -514,6 +515,8 @@
jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer));
jabber_si_xfer_bytestreams_send_read_again_resp_cb(xfer, source,
@@ -844,7 +847,7 @@
purple_network_get_all_local_system_ips();
gboolean has_public_ip = FALSE;
jsx->local_streamhost_fd = sock;
@@ -854,7 +857,8 @@
purple_xfer_set_local_port(xfer, purple_network_get_port_from_fd(sock));
g_snprintf(port, sizeof(port), "%hu", purple_xfer_get_local_port(xfer));
- public_ip = purple_network_get_my_ip(jsx->js->fd);
+ public_ip = purple_network_get_my_ip_from_gio( + G_SOCKET_CONNECTION(jsx->js->stream)); /* Include the localhost's IPs (for in-network transfers) */
@@ -880,6 +884,7 @@
/* The listener for the local proxy */
purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ,
--- a/libpurple/protocols/novell/nmconn.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/novell/nmconn.c Mon Nov 04 14:43:49 2019 +0300
@@ -20,9 +20,11 @@
@@ -34,27 +36,6 @@
#define NO_ESCAPE(ch) ((ch == 0x20) || (ch >= 0x30 && ch <= 0x39) || \
(ch >= 0x41 && ch <= 0x5a) || (ch >= 0x61 && ch <= 0x7a))
-/* Read data from conn until the end of a line */
-read_line(NMConn * conn, char *buff, int len)
- while ((rc == NM_OK) && (total_bytes < (len - 1))) {
- rc = nm_read_all(conn, &buff[total_bytes], 1);
- if (buff[total_bytes - 1] == '\n') {
- buff[total_bytes] = '\0';
url_escape_string(char *src)
@@ -180,100 +161,27 @@
void nm_release_conn(NMConn *conn)
- g_slist_free_full(conn->requests, (GDestroyNotify)nm_release_request);
+ g_return_if_fail(conn != NULL); + g_slist_free_full(conn->requests, (GDestroyNotify)nm_release_request);
-nm_tcp_write(NMConn * conn, const void *buff, int len)
- if (conn == NULL || buff == NULL)
+ purple_gio_graceful_close(conn->stream, G_INPUT_STREAM(conn->input), + g_clear_object(&conn->input); + g_clear_object(&conn->output); + g_clear_object(&conn->stream); - return conn->write(conn->data, buff, len);
-nm_tcp_read(NMConn * conn, void *buff, int len)
- if (conn == NULL || buff == NULL)
- return conn->read(conn->data, buff, len);
+ g_clear_pointer(&conn->addr, g_free); -nm_read_all(NMConn * conn, char *buff, int len)
+nm_write_fields(NMUser *user, NMField *fields)
- if (conn == NULL || buff == NULL)
- /* Keep reading until buffer is full */
- bytes_read = nm_tcp_read(conn, &buff[total_bytes], bytes_left);
- bytes_left -= bytes_read;
- total_bytes += bytes_read;
-nm_read_uint32(NMConn *conn, guint32 *val)
- rc = nm_read_all(conn, (char *)val, sizeof(*val));
- *val = GUINT32_FROM_LE(*val);
-nm_read_uint16(NMConn *conn, guint16 *val)
- rc = nm_read_all(conn, (char *)val, sizeof(*val));
- *val = GUINT16_FROM_LE(*val);
-nm_write_fields(NMConn * conn, NMField * fields)
@@ -283,9 +191,11 @@
- if (conn == NULL || fields == NULL) {
+ g_return_val_if_fail(user != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(user->conn != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(fields != NULL, NMERR_BAD_PARM); /* Format each field as valid "post" data and write it out */
for (field = fields; (rc == NM_OK) && (field->tag); field++) {
@@ -298,7 +208,8 @@
/* Write the field tag */
bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&tag=%s", field->tag);
- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); @@ -307,7 +218,8 @@
method = encode_method(field->method);
bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&cmd=%s", method);
- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); @@ -323,9 +235,13 @@
bytes_to_send = g_snprintf(buffer, sizeof(buffer),
if (bytes_to_send > (int)sizeof(buffer)) {
- ret = nm_tcp_write(conn, buffer, sizeof(buffer));
+ ret = g_output_stream_write(conn->output, buffer, + user->cancellable, NULL); - ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, + user->cancellable, NULL); @@ -342,7 +258,9 @@
val = nm_count_fields((NMField *) field->ptr_value);
bytes_to_send = g_snprintf(buffer, sizeof(buffer),
- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, + user->cancellable, NULL); @@ -353,7 +271,9 @@
bytes_to_send = g_snprintf(buffer, sizeof(buffer),
"&val=%u", field->value);
- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, + user->cancellable, NULL); @@ -366,7 +286,8 @@
bytes_to_send = g_snprintf(buffer, sizeof(buffer),
"&type=%u", field->type);
- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); @@ -377,8 +298,7 @@
if (field->type == NMFIELD_TYPE_ARRAY ||
field->type == NMFIELD_TYPE_MV) {
- rc = nm_write_fields(conn, (NMField *) field->ptr_value);
+ rc = nm_write_fields(user, (NMField *)field->ptr_value); @@ -387,9 +307,10 @@
-nm_send_request(NMConn *conn, char *cmd, NMField *fields,
- nm_response_cb cb, gpointer data, NMRequest **request)
+nm_send_request(NMUser *user, char *cmd, NMField *fields, nm_response_cb cb, + gpointer data, NMRequest **request) @@ -397,13 +318,17 @@
NMField *request_fields = NULL;
- if (conn == NULL || cmd == NULL)
+ g_return_val_if_fail(user != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(user->conn != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(cmd != NULL, NMERR_BAD_PARM); bytes_to_send = g_snprintf(buffer, sizeof(buffer),
"POST /%s HTTP/1.0\r\n", cmd);
- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); @@ -413,13 +338,15 @@
if (purple_strequal("login", cmd)) {
bytes_to_send = g_snprintf(buffer, sizeof(buffer),
"Host: %s:%d\r\n\r\n", conn->addr, conn->port);
- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); bytes_to_send = g_snprintf(buffer, sizeof(buffer), "\r\n");
- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+ ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); @@ -439,12 +366,13 @@
/* Send the request to the server */
- rc = nm_write_fields(conn, request_fields);
+ rc = nm_write_fields(user, request_fields); /* Write the CRLF to terminate the data */
- ret = nm_tcp_write(conn, "\r\n", strlen("\r\n"));
+ ret = g_output_stream_write(conn->output, "\r\n", strlen("\r\n"), + user->cancellable, NULL); @@ -470,22 +398,25 @@
-nm_read_header(NMConn * conn)
+nm_read_header(NMUser *user)
+ g_return_val_if_fail(user != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(user->conn != NULL, NMERR_BAD_PARM);
- rc = read_line(conn, buffer, sizeof(buffer));
+ buffer = g_data_input_stream_read_line(conn->input, NULL, user->cancellable, /* Find the return code */
ptr = strchr(buffer, ' ');
@@ -506,8 +437,19 @@
/* Finish reading header, in the future we might want to do more processing here */
/* TODO: handle more general redirects in the future */
- while ((rc == NM_OK) && (!purple_strequal(buffer, "\r\n"))) {
- rc = read_line(conn, buffer, sizeof(buffer));
+ while ((error == NULL) && !purple_strequal(buffer, "\r")) { + buffer = g_data_input_stream_read_line(conn->input, NULL, + user->cancellable, &error); + if (error->code != G_IO_ERROR_WOULD_BLOCK && + error->code != G_IO_ERROR_CANCELLED) { if (rc == NM_OK && rtn_code == 301)
@@ -517,8 +459,9 @@
-nm_read_fields(NMConn * conn, int count, NMField ** fields)
+nm_read_fields(NMUser *user, int count, NMField **fields) @@ -526,9 +469,13 @@
NMField *sub_fields = NULL;
- if (conn == NULL || fields == NULL)
+ g_return_val_if_fail(user != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(user->conn != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(fields != NULL, NMERR_BAD_PARM); @@ -536,36 +483,46 @@
/* Read the field type, method, and tag */
- rc = nm_read_all(conn, (char *)&type, sizeof(type));
- if (rc != NM_OK || type == 0)
+ type = g_data_input_stream_read_byte(conn->input, user->cancellable, + if (error != NULL || type == 0) { - rc = nm_read_all(conn, (char *)&method, sizeof(method));
+ method = g_data_input_stream_read_byte(conn->input, user->cancellable, - rc = nm_read_uint32(conn, &val);
+ val = g_data_input_stream_read_uint32(conn->input, user->cancellable, - rc = nm_read_all(conn, tag, val);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), tag, val, NULL, + user->cancellable, &error); if (type == NMFIELD_TYPE_MV || type == NMFIELD_TYPE_ARRAY) {
/* Read the subarray (first read the number of items in the array) */
- rc = nm_read_uint32(conn, &val);
+ val = g_data_input_stream_read_uint32(conn->input, + user->cancellable, &error); - rc = nm_read_fields(conn, val, &sub_fields);
+ rc = nm_read_fields(user, val, &sub_fields); @@ -578,9 +535,11 @@
} else if (type == NMFIELD_TYPE_UTF8 || type == NMFIELD_TYPE_DN) {
/* Read the string (first read the length) */
- rc = nm_read_uint32(conn, &val);
+ val = g_data_input_stream_read_uint32(conn->input, + user->cancellable, &error); if (val >= NMFIELD_MAX_STR_LENGTH) {
@@ -590,9 +549,11 @@
str = g_new0(char, val + 1);
- rc = nm_read_all(conn, str, val);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), str, val, + NULL, user->cancellable, &error); *fields = nm_field_add_pointer(*fields, tag, 0, method,
@@ -602,9 +563,11 @@
/* Read the numerical value */
- rc = nm_read_uint32(conn, &val);
+ val = g_data_input_stream_read_uint32(conn->input, + user->cancellable, &error); *fields = nm_field_add_number(*fields, tag, 0, method,
@@ -618,6 +581,13 @@
nm_free_fields(&sub_fields);
+ if (error->code != G_IO_ERROR_WOULD_BLOCK && error->code != G_IO_ERROR_CANCELLED) { --- a/libpurple/protocols/novell/nmconn.h Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/novell/nmconn.h Mon Nov 04 14:43:49 2019 +0300
@@ -21,6 +21,8 @@
#ifndef PURPLE_NOVELL_NMCONN_H
#define PURPLE_NOVELL_NMCONN_H
typedef struct _NMConn NMConn;
@@ -44,12 +46,11 @@
/* A list of requests currently awaiting a response. */
- /* Data to pass to the callbacks */
- /* Callbacks for reading/writing */
+ /* Connections to server. */ + GDataInputStream *input; @@ -72,64 +73,9 @@
void nm_release_conn(NMConn *conn);
- * Write len bytes from the given buffer.
- * @param conn The connection to write to.
- * @param buff The buffer to write from.
- * @param len The number of bytes to write.
- * @return The number of bytes written.
-int nm_tcp_write(NMConn * conn, const void *buff, int len);
- * Read at most len bytes into the given buffer.
- * @param conn The connection to read from.
- * @param buff The buffer to write to.
- * @param len The maximum number of bytes to read.
- * @return The number of bytes read.
-int nm_tcp_read(NMConn * conn, void *buff, int len);
- * Read exactly len bytes into the given buffer.
- * @param conn The connection to read from.
- * @param buff The buffer to write to.
- * @param len The number of bytes to read.
- * @return NM_OK on success, NMERR_TCP_READ if read fails.
-NMERR_T nm_read_all(NMConn * conn, char *buf, int len);
- * Read a 32 bit value and convert it to the host byte order.
- * @param conn The connection to read from.
- * @param val A pointer to unsigned 32 bit integer
- * @return NM_OK on success, NMERR_TCP_READ if read fails.
-nm_read_uint32(NMConn *conn, guint32 *val);
- * Read a 16 bit value and convert it to the host byte order.
- * @param conn The connection to read from.
- * @param val A pointer to unsigned 16 bit integer
- * @return NM_OK on success, NMERR_TCP_READ if read fails.
-nm_read_uint16(NMConn *conn, guint16 *val);
* Dispatch a request to the server.
- * @param conn The connection.
+ * @param user The logged-in user. * @param cmd The request to dispatch.
* @param fields The field list for the request.
* @param cb The response callback for the new request object.
@@ -139,32 +85,32 @@
* @return NM_OK on success.
-nm_send_request(NMConn *conn, char *cmd, NMField *fields,
- nm_response_cb cb, gpointer data, NMRequest **request);
+nm_send_request(NMUser *user, char *cmd, NMField *fields, nm_response_cb cb, + gpointer data, NMRequest **request); * Write out the given field list.
- * @param conn The connection to write to.
+ * @param user The logged-in user. * @param fields The field list to write.
* @return NM_OK on success.
-NMERR_T nm_write_fields(NMConn * conn, NMField * fields);
+NMERR_T nm_write_fields(NMUser *user, NMField *fields); * Read the headers for a response.
- * @param conn The connection to read from.
+ * @param user The logged-in user. * @return NM_OK on success.
-NMERR_T nm_read_header(NMConn * conn);
+NMERR_T nm_read_header(NMUser *user); * Read a field list from the connection.
- * @param conn The connection to read from.
+ * @param user The logged-in user. * @param count The maximum number of fields to read (or -1 for no max).
* @param fields The field list. This is an out param. It
* should be freed by calling nm_free_fields
@@ -172,7 +118,7 @@
* @return NM_OK on success.
-NMERR_T nm_read_fields(NMConn * conn, int count, NMField ** fields);
+NMERR_T nm_read_fields(NMUser *user, int count, NMField **fields); * Add a request to the connections request list.
--- a/libpurple/protocols/novell/nmevent.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/novell/nmevent.c Mon Nov 04 14:43:49 2019 +0300
@@ -144,31 +144,43 @@
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, NULL, + user->cancellable, &error); /* Read the conference flags */
- rc = nm_read_uint32(conn, &flags);
+ flags = g_data_input_stream_read_uint32(conn->input, user->cancellable, /* Read the message text */
- rc = nm_read_uint32(conn, &size);
- if (size > 100000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
msg = g_new0(char, size + 1);
- rc = nm_read_all(conn, msg, size);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), msg, size, + NULL, user->cancellable, &error); purple_debug(PURPLE_DEBUG_INFO, "novell", "Message is %s\n", msg);
@@ -194,6 +206,16 @@
+ if (error->code == G_IO_ERROR_CANCELLED) { /* Check to see if we already know about the conference */
conference = nm_conference_list_find(user, guid);
@@ -260,31 +282,42 @@
NMUserRecord *user_record;
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, NULL, + user->cancellable, &error); /* Read the the message */
- rc = nm_read_uint32(conn, &size);
- if (size > 100000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
msg = g_new0(char, size + 1);
- rc = nm_read_all(conn, msg, size);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), msg, size, + NULL, user->cancellable, &error); /* Store the event data */
NMConference *conference;
nm_event_set_text(event, msg);
@@ -316,6 +349,11 @@
nm_release_conference(conference);
+ if (error->code != G_IO_ERROR_CANCELLED) { @@ -336,16 +374,32 @@
NMConference *conference;
NMUserRecord *user_record;
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, NULL, + user->cancellable, &error); + if (error->code == G_IO_ERROR_CANCELLED) { conference = nm_conference_list_find(user, guid);
@@ -387,25 +441,36 @@
NMConference *conference;
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
- guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
+ guid = g_new0(char, size + 1); + g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, NULL, + user->cancellable, &error); conference = nm_conference_list_find(user, guid);
nm_event_set_conference(event, conference);
rc = NMERR_CONFERENCE_NOT_FOUND;
+ if (error->code != G_IO_ERROR_CANCELLED) { @@ -425,24 +490,31 @@
NMConference *conference;
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, NULL, + user->cancellable, &error); /* Read the conference flags */
- rc = nm_read_uint32(conn, &flags);
+ flags = g_data_input_stream_read_uint32(conn->input, user->cancellable,
conference = nm_conference_list_find(user, guid);
nm_event_set_conference(event, conference);
@@ -456,6 +528,11 @@
rc = NMERR_CONFERENCE_NOT_FOUND;
+ if (error->code != G_IO_ERROR_CANCELLED) { @@ -474,19 +551,25 @@
NMConference *conference;
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
- guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
+ guid = g_new0(char, size + 1); + g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, NULL, + user->cancellable, &error); conference = nm_conference_list_find(user, guid);
nm_event_set_conference(event, conference);
@@ -494,6 +577,11 @@
rc = NMERR_CONFERENCE_NOT_FOUND;
+ if (error->code != G_IO_ERROR_CANCELLED) { @@ -513,24 +601,31 @@
NMConference *conference;
NMUserRecord *user_record;
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, NULL, + user->cancellable, &error); /* Read the conference flags */
- rc = nm_read_uint32(conn, &flags);
+ flags = g_data_input_stream_read_uint32(conn->input, user->cancellable,
conference = nm_conference_list_find(user, guid);
nm_conference_set_flags(conference, flags);
@@ -555,6 +650,11 @@
rc = NMERR_CONFERENCE_NOT_FOUND;
+ if (error->code != G_IO_ERROR_CANCELLED) { @@ -571,25 +671,36 @@
NMConference *conference;
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
- guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
+ guid = g_new0(char, size + 1); + g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, NULL, + user->cancellable, &error); conference = nm_conference_list_find(user, guid);
nm_event_set_conference(event, conference);
rc = NMERR_CONFERENCE_NOT_FOUND;
+ if (error->code != G_IO_ERROR_CANCELLED) { @@ -609,24 +720,31 @@
NMUserRecord *user_record;
conn = nm_user_get_conn(user);
- rc = nm_read_uint16(conn, &status);
+ status = g_data_input_stream_read_uint16(conn->input, user->cancellable, /* Read the status text */
- rc = nm_read_uint32(conn, &size);
- if (size > 10000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
text = g_new0(char, size + 1);
- rc = nm_read_all(conn, text, size);
+ g_input_stream_read_all(G_INPUT_STREAM(conn->input), text, size, + NULL, user->cancellable, &error);
nm_event_set_text(event, text);
/* Get a reference to the user record and store the new status */
@@ -635,6 +753,11 @@
nm_event_set_user_record(event, user_record);
nm_user_record_set_status(user_record, status, text);
+ if (error->code != G_IO_ERROR_CANCELLED) { @@ -650,16 +773,27 @@
conn = nm_user_get_conn(user);
/* Read the conference guid */
- rc = nm_read_uint32(conn, &size);
- if (size > 1000) return NMERR_PROTOCOL;
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable,
guid = g_new0(char, size + 1);
- rc = nm_read_all(conn, guid, size);
+ rc = g_input_stream_read_all(G_INPUT_STREAM(conn->input), guid, size, + NULL, user->cancellable, &error); + if (error->code != G_IO_ERROR_CANCELLED) { @@ -803,6 +937,7 @@
@@ -813,20 +948,22 @@
conn = nm_user_get_conn(user);
/* Read the event source */
- rc = nm_read_uint32(conn, &size);
+ size = g_data_input_stream_read_uint32(conn->input, user->cancellable, /* Size is larger than our 1MB sanity check. Ignore it. */
source = g_new0(char, size);
- rc = nm_read_all(conn, source, size);
+ rc = g_input_stream_read_all(G_INPUT_STREAM(conn->input), source, + size, NULL, user->cancellable, &error); /* Read the event data */
event = nm_create_event(type, source, time(0));
@@ -901,6 +1038,11 @@
+ if (error->code != G_IO_ERROR_CANCELLED) { --- a/libpurple/protocols/novell/nmuser.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/novell/nmuser.c Mon Nov 04 14:43:49 2019 +0300
@@ -56,7 +56,7 @@
user = g_new0(NMUser, 1);
+ user->cancellable = g_cancellable_new(); g_hash_table_new_full(g_str_hash, nm_utf8_str_equal,
@@ -81,6 +81,8 @@
nm_deinitialize_user(NMUser * user)
+ g_cancellable_cancel(user->cancellable); nm_release_conn(user->conn);
@@ -104,6 +106,8 @@
nm_conference_list_free(user);
nm_destroy_contact_list(user);
+ g_object_unref(user->cancellable); @@ -135,7 +139,7 @@
- rc = nm_send_request(user->conn, "login", fields, callback, data, NULL);
+ rc = nm_send_request(user, "login", fields, callback, data, NULL); @@ -168,7 +172,7 @@
- rc = nm_send_request(user->conn, "setstatus", fields, callback, data, NULL);
+ rc = nm_send_request(user, "setstatus", fields, callback, data, NULL); @@ -191,7 +195,7 @@
g_strdup(node->data), NMFIELD_TYPE_UTF8);
- rc = nm_send_request(user->conn, "getdetails", fields, callback, data, NULL);
+ rc = nm_send_request(user, "getdetails", fields, callback, data, NULL); @@ -225,7 +229,7 @@
- rc = nm_send_request(user->conn, "getdetails", fields, callback, data, NULL);
+ rc = nm_send_request(user, "getdetails", fields, callback, data, NULL); @@ -277,7 +281,7 @@
- rc = nm_send_request(user->conn, "createconf", fields, callback, data, &req);
+ rc = nm_send_request(user, "createconf", fields, callback, data, &req); if (rc == NM_OK && req) {
nm_conference_add_ref(conference);
nm_request_set_data(req, conference);
@@ -313,7 +317,7 @@
/* Send the request to the server */
- rc = nm_send_request(user->conn, "leaveconf", fields, callback, data, &req);
+ rc = nm_send_request(user, "leaveconf", fields, callback, data, &req); nm_request_set_data(req, conference);
@@ -346,7 +350,7 @@
/* Send the request to the server */
- rc = nm_send_request(user->conn, "joinconf", fields, callback, data, &req);
+ rc = nm_send_request(user, "joinconf", fields, callback, data, &req); nm_request_set_data(req, conference);
@@ -380,7 +384,7 @@
/* Send the request to the server */
- rc = nm_send_request(user->conn, "rejectconf", fields, callback, data, &req);
+ rc = nm_send_request(user, "rejectconf", fields, callback, data, &req); nm_request_set_data(req, conference);
@@ -424,7 +428,7 @@
g_strdup(message), NMFIELD_TYPE_UTF8);
/* Send the request to the server */
- rc = nm_send_request(user->conn, "sendinvite", fields, callback, data, &req);
+ rc = nm_send_request(user, "sendinvite", fields, callback, data, &req); nm_request_set_data(req, conference);
@@ -501,7 +505,7 @@
- rc = nm_send_request(user->conn, "sendmessage", fields, callback, NULL, NULL);
+ rc = nm_send_request(user, "sendmessage", fields, callback, NULL, NULL); @@ -541,7 +545,7 @@
tmp, NMFIELD_TYPE_ARRAY);
- rc = nm_send_request(user->conn, "sendtyping", fields, callback, NULL, NULL);
+ rc = nm_send_request(user, "sendtyping", fields, callback, NULL, NULL); @@ -592,7 +596,7 @@
g_strdup(display_name), NMFIELD_TYPE_UTF8);
/* Dispatch the request */
- rc = nm_send_request(user->conn, "createcontact", fields, callback, data, &req);
+ rc = nm_send_request(user, "createcontact", fields, callback, data, &req); nm_request_set_data(req, contact);
@@ -627,7 +631,7 @@
/* Dispatch the request */
- rc = nm_send_request(user->conn, "deletecontact", fields, callback, data, &req);
+ rc = nm_send_request(user, "deletecontact", fields, callback, data, &req); nm_request_set_data(req, contact);
@@ -665,7 +669,7 @@
g_strdup("-1"), NMFIELD_TYPE_UTF8);
/* Dispatch the request */
- rc = nm_send_request(user->conn, "createfolder", fields, callback, data, &req);
+ rc = nm_send_request(user, "createfolder", fields, callback, data, &req); nm_request_set_data(req, g_strdup(name));
@@ -694,7 +698,7 @@
/* Dispatch the request */
- rc = nm_send_request(user->conn, "deletecontact", fields, callback, data, &req);
+ rc = nm_send_request(user, "deletecontact", fields, callback, data, &req); nm_request_set_data(req, folder);
@@ -726,7 +730,7 @@
g_strdup(dn), NMFIELD_TYPE_UTF8);
/* Dispatch the request */
- rc = nm_send_request(user->conn, "getstatus", fields, callback, data, &req);
+ rc = nm_send_request(user, "getstatus", fields, callback, data, &req); nm_request_set_data(req, user_record);
@@ -775,7 +779,8 @@
0, fields, NMFIELD_TYPE_ARRAY);
- rc = nm_send_request(user->conn, "updateitem", list, callback, data, &req);
+ rc = nm_send_request(user, "updateitem", list, callback, data, nm_request_set_data(req, contact);
@@ -828,7 +833,8 @@
0, fields, NMFIELD_TYPE_ARRAY);
- rc = nm_send_request(user->conn, "updateitem", list, callback, data, &req);
+ rc = nm_send_request(user, "updateitem", list, callback, data, nm_request_set_data(req, folder);
@@ -877,7 +883,7 @@
/* Dispatch the request */
- rc = nm_send_request(user->conn, "movecontact", list, callback, data, &req);
+ rc = nm_send_request(user, "movecontact", list, callback, data, &req); nm_request_set_data(req, contact);
@@ -912,7 +918,7 @@
fields = nm_field_add_pointer(fields, tag, 0, NMFIELD_METHOD_ADD, 0,
g_strdup(who), NMFIELD_TYPE_UTF8);
- rc = nm_send_request(user->conn, "createblock", fields, callback, data, NULL);
+ rc = nm_send_request(user, "createblock", fields, callback, data, NULL); @@ -946,7 +952,7 @@
fields = nm_field_add_pointer(fields, tag, 0, NMFIELD_METHOD_DELETE, 0,
g_strdup(dn), NMFIELD_TYPE_DN);
- rc = nm_send_request(user->conn, "updateblocks", fields, callback, data, NULL);
+ rc = nm_send_request(user, "updateblocks", fields, callback, data, NULL); @@ -967,7 +973,7 @@
(default_deny ? g_strdup("1") : g_strdup("0")),
- rc = nm_send_request(user->conn, "updateblocks", fields, callback, data, NULL);
+ rc = nm_send_request(user, "updateblocks", fields, callback, data, NULL); @@ -981,7 +987,7 @@
- rc = nm_send_request(user->conn, "ping", NULL, callback, data, NULL);
+ rc = nm_send_request(user, "ping", NULL, callback, data, NULL); @@ -992,6 +998,7 @@
@@ -999,18 +1006,22 @@
/* Check to see if this is an event or a response */
- rc = nm_read_all(conn, (char *) &val, sizeof(val));
- if (strncmp((char *) &val, "HTTP", strlen("HTTP")) == 0)
+ val = g_data_input_stream_read_uint32(conn->input, user->cancellable, + if (val == ('H' + ('T' << 8) + ('T' << 16) + ('P' << 24))) { rc = nm_process_response(user);
- rc = nm_process_event(user, GUINT32_FROM_LE(val));
+ rc = nm_process_event(user, val);
+ if (error->code == G_IO_ERROR_WOULD_BLOCK || error->code == G_IO_ERROR_CANCELLED) { + /* Try again later or ignore. */
@@ -1753,9 +1764,9 @@
NMConn *conn = user->conn;
- rc = nm_read_header(conn);
+ rc = nm_read_header(user); - rc = nm_read_fields(conn, -1, &fields);
+ rc = nm_read_fields(user, -1, &fields); --- a/libpurple/protocols/novell/nmuser.h Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/novell/nmuser.h Mon Nov 04 14:43:49 2019 +0300
@@ -67,6 +67,7 @@
/* This represents user that we are currently logged in as */
+ GCancellable *cancellable; --- a/libpurple/protocols/novell/novell.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/novell/novell.c Mon Nov 04 14:43:49 2019 +0300
@@ -27,9 +27,9 @@
#include "purpleaccountoption.h"
@@ -1672,22 +1672,7 @@
******************************************************************************/
-novell_ssl_connect_error(PurpleSslConnection * gsc,
- PurpleSslErrorType error, gpointer data)
- user = purple_connection_get_protocol_data(gc);
- user->conn->data = NULL;
- purple_connection_ssl_error (gc, error);
-novell_ssl_recv_cb(gpointer data, PurpleSslConnection * gsc,
- PurpleInputCondition condition)
+novell_ssl_recv_cb(GObject *stream, gpointer data) PurpleConnection *gc = data;
@@ -1716,19 +1701,28 @@
-novell_ssl_connected_cb(gpointer data, PurpleSslConnection * gsc,
- PurpleInputCondition cond)
+novell_login_callback(GObject *source_object, GAsyncResult *res, gpointer data) + GSocketClient *client = G_SOCKET_CLIENT(source_object); PurpleConnection *gc = data;
+ GSocketConnection *sockconn; - const char *my_addr = NULL;
- if (gc == NULL || gsc == NULL)
+ sockconn = g_socket_client_connect_to_host_finish(client, res, &error); + if (sockconn == NULL) { + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + purple_connection_take_error(gc, error); user = purple_connection_get_protocol_data(gc);
if ((user == NULL) || (conn = user->conn) == NULL)
@@ -1737,13 +1731,27 @@
purple_connection_update_progress(gc, _("Authenticating..."),
2, NOVELL_CONNECT_STEPS);
- my_addr = purple_network_get_my_ip(gsc->fd);
+ conn->stream = G_IO_STREAM(sockconn); + g_data_input_stream_new(g_io_stream_get_input_stream(conn->stream)); + conn->output = g_io_stream_get_output_stream(conn->stream); + g_data_input_stream_set_byte_order(conn->input, + G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN); + g_data_input_stream_set_newline_type(conn->input, + G_DATA_STREAM_NEWLINE_TYPE_LF); + my_addr = purple_network_get_my_ip_from_gio(sockconn); pwd = purple_connection_get_password(gc);
ua = _user_agent_string();
rc = nm_send_login(user, pwd, my_addr, ua, _login_resp_cb, NULL);
- purple_ssl_input_add(gsc, novell_ssl_recv_cb, gc);
+ source = g_pollable_input_stream_create_source( + G_POLLABLE_INPUT_STREAM(conn->input), user->cancellable); + g_source_set_callback(source, (GSourceFunc)novell_ssl_recv_cb, gc, purple_connection_error(gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
@@ -1754,6 +1762,7 @@
3, NOVELL_CONNECT_STEPS);
/*******************************************************************************
@@ -2167,6 +2176,7 @@
@@ -2204,17 +2214,16 @@
purple_connection_update_progress(gc, _("Connecting"),
1, NOVELL_CONNECT_STEPS);
- user->conn->read = (nm_ssl_read_cb)purple_ssl_read;
- user->conn->write = (nm_ssl_write_cb)purple_ssl_write;
- user->conn->data = purple_ssl_connect(
- user->client_data, user->conn->addr, user->conn->port,
- novell_ssl_connected_cb, novell_ssl_connect_error, gc);
- if (user->conn->data == NULL) {
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
- _("SSL support unavailable"));
+ user->conn->client = purple_gio_socket_client_new(account, &error); + if (user->conn->client == NULL) { + purple_connection_take_error(gc, error); + g_socket_client_set_tls(user->conn->client, TRUE); + g_socket_client_connect_to_host_async( + user->conn->client, user->conn->addr, user->conn->port, + user->cancellable, novell_login_callback, gc); @@ -2231,7 +2240,7 @@
- purple_ssl_close(user->conn->data);
nm_deinitialize_user(user);
--- a/libpurple/protocols/sametime/sametime.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/sametime/sametime.c Mon Nov 04 14:43:49 2019 +0300
@@ -812,7 +812,7 @@
static gboolean buddy_is_external(PurpleBuddy *b) {
g_return_val_if_fail(b != NULL, FALSE);
- return purple_str_has_prefix(purple_buddy_get_name(b), "@E ");
+ return g_str_has_prefix(purple_buddy_get_name(b), "@E "); @@ -3869,9 +3869,10 @@
b = purple_blist_find_buddy(acct, who);
user_info = purple_notify_user_info_new();
- if(purple_str_has_prefix(who, "@E ")) {
- purple_notify_user_info_add_pair_html(user_info, _("External User"), NULL);
+ if (g_str_has_prefix(who, "@E ")) { + purple_notify_user_info_add_pair_html(user_info, _("External User"), purple_notify_user_info_add_pair_plaintext(user_info, _("User ID"), who);
--- a/libpurple/protocols/silc/ops.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/silc/ops.c Mon Nov 04 14:43:49 2019 +0300
@@ -182,7 +182,7 @@
- if (purple_str_has_prefix(type, "image/")) {
+ if (g_str_has_prefix(type, "image/")) { --- a/libpurple/protocols/silc/silc.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/silc/silc.c Mon Nov 04 14:43:49 2019 +0300
@@ -42,6 +42,25 @@
+silcpurple_free(SilcPurple sg) + g_return_if_fail(sg != NULL); + g_cancellable_cancel(sg->cancellable); + g_clear_object(&sg->cancellable); + g_clear_object(&sg->sockconn); + g_clear_pointer(&sg->client, silc_client_free); + g_clear_pointer(&sg->sha1hash, silc_hash_free); + g_clear_pointer(&sg->mimeass, silc_mime_assembler_free); + g_clear_pointer(&sg->public_key, silc_pkcs_public_key_free); + g_clear_pointer(&sg->private_key, silc_pkcs_private_key_free); silcpurple_list_icon(PurpleAccount *a, PurpleBuddy *b)
@@ -135,15 +154,6 @@
-#if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1)
-silcpurple_scheduler(gpointer *context)
- SilcClient client = (SilcClient)context;
- silc_client_run_one(client);
@@ -241,7 +251,6 @@
-#endif /* __SILC_TOOLKIT_VERSION */
silcpurple_connect_cb(SilcClient client, SilcClientConnection conn,
@@ -378,9 +387,7 @@
purple_connection_error(gc,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- silc_pkcs_public_key_free(sg->public_key);
- silc_pkcs_private_key_free(sg->private_key);
purple_connection_set_protocol_data(gc, NULL);
@@ -413,29 +420,43 @@
-silcpurple_login_connected(gpointer data, gint source, const gchar *error_message)
+silcpurple_login_connected(GObject *source, GAsyncResult *res, gpointer data) PurpleConnection *gc = data;
+ GSocketConnection *conn; g_return_if_fail(gc != NULL);
sg = purple_connection_get_protocol_data(gc);
- purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Connection failed"));
- silc_pkcs_public_key_free(sg->public_key);
- silc_pkcs_private_key_free(sg->private_key);
- purple_connection_set_protocol_data(gc, NULL);
+ conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source), + if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Connection failed")); + purple_connection_set_protocol_data(gc, NULL); + socket = g_socket_connection_get_socket(conn); + g_assert(socket != NULL); + fd = g_socket_get_fd(socket); silc_hash_alloc((unsigned char *)"sha1", &sg->sha1hash);
/* Wrap socket to TCP stream */
- silc_socket_tcp_stream_create(source, TRUE, FALSE,
+ silc_socket_tcp_stream_create(fd, TRUE, FALSE, silcpurple_stream_created, gc);
@@ -444,20 +465,27 @@
PurpleConnection *gc = sg->gc;
PurpleAccount *account = purple_connection_get_account(gc);
+ client = purple_gio_socket_client_new(account, &error); + /* Assume it's a proxy error */ + purple_notify_error(NULL, NULL, _("Invalid proxy settings"), + purple_request_cpar_from_account(account)); + purple_connection_take_error(gc, error); + purple_connection_set_protocol_data(gc, NULL); /* Connect to the SILC server */
- if (purple_proxy_connect(gc, account,
+ g_socket_client_connect_to_host_async(client, purple_account_get_string(account, "server",
purple_account_get_int(account, "port", 706),
- silcpurple_login_connected, gc) == NULL)
- purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Unable to connect"));
- purple_connection_set_protocol_data(gc, NULL);
+ sg->cancellable, silcpurple_login_connected, gc); + g_object_unref(client); static void silcpurple_got_password_cb(PurpleConnection *gc, PurpleRequestFields *fields)
@@ -480,7 +508,7 @@
_("Password is required to sign on."), NULL,
purple_request_cpar_from_connection(gc));
purple_connection_set_protocol_data(gc, NULL);
@@ -499,7 +527,7 @@
purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
_("Unable to load SILC key pair"));
purple_connection_set_protocol_data(gc, NULL);
silcpurple_continue_running(sg);
@@ -516,7 +544,7 @@
purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
_("Unable to load SILC key pair"));
purple_connection_set_protocol_data(gc, NULL);
static void silcpurple_running(SilcClient client, void *context)
@@ -545,7 +573,7 @@
purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
_("Unable to load SILC key pair"));
purple_connection_set_protocol_data(gc, NULL);
silcpurple_continue_running(sg);
@@ -616,6 +644,7 @@
sg = silc_calloc(1, sizeof(*sg));
+ sg->cancellable = g_cancellable_new(); @@ -627,7 +656,7 @@
purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
_("Unable to initialize SILC protocol"));
purple_connection_set_protocol_data(gc, NULL);
@@ -640,20 +669,15 @@
purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
_("Error loading SILC key pair"));
purple_connection_set_protocol_data(gc, NULL);
-#if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1)
- /* Schedule SILC using Glib's event loop */
- sg->scheduler = g_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client);
sg->tasks = silc_dlist_init();
silc_schedule_set_notify(client->schedule, silcpurple_scheduler,
silc_client_run_one(client);
-#endif /* __SILC_TOOLKIT_VERSION */
@@ -664,12 +688,8 @@
purple_debug_info("silc", "Finalizing SilcPurple %p\n", sg);
silc_client_stop(sg->client, NULL, NULL);
- silc_client_free(sg->client);
- silc_hash_free(sg->sha1hash);
- silc_mime_assembler_free(sg->mimeass);
@@ -677,9 +697,7 @@
silcpurple_close(PurpleConnection *gc)
SilcPurple sg = purple_connection_get_protocol_data(gc);
-#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1)
-#endif /* __SILC_TOOLKIT_VERSION */
const char *ui_name = NULL, *ui_website = NULL;
@@ -709,7 +727,6 @@
silc_client_close_connection(sg->client, sg->conn);
-#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1)
silc_client_run_one(sg->client);
silc_schedule_set_notify(sg->client->schedule, NULL, NULL);
@@ -720,7 +737,6 @@
silc_dlist_uninit(sg->tasks);
-#endif /* __SILC_TOOLKIT_VERSION */
g_source_remove(sg->scheduler);
--- a/libpurple/protocols/silc/silcpurple.h Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/silc/silcpurple.h Mon Nov 04 14:43:49 2019 +0300
@@ -37,9 +37,6 @@
-#define SILC_VERSION(a, b, c) (((a) << 24) + ((b) << 16) + ((c) << 8))
#define SILCPURPLE_TYPE_PROTOCOL (silcpurple_protocol_get_type())
#define SILCPURPLE_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SILCPURPLE_TYPE_PROTOCOL, SilcProtocol))
#define SILCPURPLE_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SILCPURPLE_TYPE_PROTOCOL, SilcProtocolClass))
@@ -86,6 +83,9 @@
/* The SILC Purple plugin context */
typedef struct SilcPurpleStruct {
+ GCancellable *cancellable; + GSocketConnection *sockconn; SilcClientConnection conn;
SilcPublicKey public_key;
--- a/libpurple/protocols/simple/simple.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/simple/simple.c Mon Nov 04 14:43:49 2019 +0300
@@ -117,7 +117,6 @@
purple_debug_error("simple", "failed sending keep alive\n");
static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc);
@@ -1288,8 +1287,7 @@
- if (purple_str_has_prefix(ssparts[i], "terminated"))
+ if (g_str_has_prefix(ssparts[i], "terminated")) { purple_debug_info("simple", "Subscription expired!");
--- a/libpurple/protocols/zephyr/Zinternal.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/zephyr/Zinternal.c Mon Nov 04 14:43:49 2019 +0300
@@ -850,7 +850,6 @@
qptr->prev->next = qptr->next;
qptr->next->prev = qptr->prev;
Code_t Z_SendFragmentedNotice(notice, len, cert_func, send_func)
--- a/libpurple/protocols/zephyr/zephyr.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/protocols/zephyr/zephyr.c Mon Nov 04 14:43:49 2019 +0300
@@ -55,10 +55,7 @@
static GSList *cmds = NULL;
extern Code_t ZGetLocations(ZLocations_t *, int *);
-extern Code_t ZSetLocation(char *);
-extern Code_t ZUnsetLocation(void);
extern Code_t ZGetSubscriptions(ZSubscription_t *, int*);
-extern char __Zephyr_realm[];
typedef struct _zframe zframe;
typedef struct _zephyr_triple zephyr_triple;
typedef struct _zephyr_account zephyr_account;
@@ -1333,25 +1330,9 @@
/* XXX add real error reporting */
/* doesn't matter if this fails or not; we'll just move on to the next one */
if (use_zeph02(zephyr)) {
- ZLocateUser(chk,&numlocs,ZAUTH);
- for(i=0;i<numlocs;i++) {
- ZGetLocations(&locations,&one);
- purple_protocol_got_user_status(account,name,"available",NULL);
- purple_protocol_got_user_status(account,name,"offline",NULL);
ZRequestLocations(chk, &ald, UNACKED, ZAUTH);
gchar *zlocstr = g_strdup_printf("((tzcfodder . zlocate) \"%s\")\n",chk);
@@ -1419,8 +1400,6 @@
g_strlcpy(zephyr->ourhostcanon, hent->h_name, sizeof(zephyr->ourhostcanon));
static void process_zsubs(zephyr_account *zephyr)
@@ -2601,7 +2580,6 @@
topic_utf8 = zephyr_recv_convert(gc,(gchar *)topic);
purple_chat_conversation_set_topic(gcc,sender,topic_utf8);
--- a/libpurple/upnp.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/upnp.c Mon Nov 04 14:43:49 2019 +0300
@@ -340,8 +340,8 @@
tmp = purple_xmlnode_get_data(controlURLNode);
- if(baseURL && !purple_str_has_prefix(tmp, "http://") &&
- !purple_str_has_prefix(tmp, "HTTP://")) {
+ if (baseURL && !g_str_has_prefix(tmp, "http://") && + !g_str_has_prefix(tmp, "HTTP://")) { /* Handle absolute paths in a relative URL. This probably
@@ -355,7 +355,7 @@
controlURL = g_strdup_printf("%s%s", baseURL, tmp);
--- a/libpurple/util.c Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/util.c Mon Nov 04 14:43:49 2019 +0300
@@ -35,15 +35,9 @@
static gchar *config_dir = NULL;
static gchar *data_dir = NULL;
-static JsonNode *escape_js_node = NULL;
-static JsonGenerator *escape_js_gen = NULL;
- escape_js_node = json_node_new(JSON_NODE_VALUE);
- escape_js_gen = json_generator_new();
- json_node_set_boolean(escape_js_node, FALSE);
@@ -65,12 +59,6 @@
- json_node_free(escape_js_node);
- g_object_unref(escape_js_gen);
/**************************************************************************
@@ -573,333 +561,6 @@
-purple_uts35_to_str(const char *format, size_t len, struct tm *tm)
- time_t now = time(NULL);
- string = g_string_sized_new(len);
- while ((i + count) < len && format[i] == format[i+count])
- } else if (count == 4) {
- } else if (count >= 5) {
- g_string_append(string, purple_utf8_strftime("%y", tm));
- g_string_append_printf(string, "%0*d",
- /* Year (in "Week of Year" based calendars) */
- } else if (count == 4) {
- } else if (count >= 5) {
- /* Stand-alone Quarter */
- } else if (count == 3) {
- } else if (count >= 4) {
- /* Stand-alone Month */
- g_string_append(string, purple_utf8_strftime("%m", tm));
- } else if (count == 3) {
- g_string_append(string, purple_utf8_strftime("%b", tm));
- } else if (count == 4) {
- g_string_append(string, purple_utf8_strftime("%B", tm));
- } else if (count >= 5) {
- g_string_append_len(string, purple_utf8_strftime("%b", tm), 1);
- g_string_append(string, purple_utf8_strftime("%W", tm));
- g_string_append(string, purple_utf8_strftime("%d", tm));
- g_string_append(string, purple_utf8_strftime("%j", tm));
- /* Day of Year in Month */
- /* Modified Julian Day */
- g_string_append(string, purple_utf8_strftime("%a", tm));
- } else if (count == 4) {
- g_string_append(string, purple_utf8_strftime("%A", tm));
- } else if (count >= 5) {
- g_string_append_len(string, purple_utf8_strftime("%a", tm), 1);
- /* Local Day of Week */
- g_string_append(string, purple_utf8_strftime("%u", tm));
- } else if (count == 3) {
- g_string_append(string, purple_utf8_strftime("%a", tm));
- } else if (count == 4) {
- g_string_append(string, purple_utf8_strftime("%A", tm));
- } else if (count >= 5) {
- g_string_append_len(string, purple_utf8_strftime("%a", tm), 1);
- /* Stand-alone Local Day of Week */
- g_string_append(string, purple_utf8_strftime("%u", tm));
- } else if (count == 3) {
- g_string_append(string, purple_utf8_strftime("%a", tm));
- } else if (count == 4) {
- g_string_append(string, purple_utf8_strftime("%A", tm));
- } else if (count >= 5) {
- g_string_append_len(string, purple_utf8_strftime("%a", tm), 1);
- g_string_append(string, purple_utf8_strftime("%p", tm));
- g_string_append(string, purple_utf8_strftime("%I", tm));
- } else if (count >= 2) {
- g_string_append(string, purple_utf8_strftime("%I", tm));
- g_string_append(string, purple_utf8_strftime("%H", tm));
- } else if (count >= 2) {
- g_string_append(string, purple_utf8_strftime("%H", tm));
- } else if (count >= 2) {
- /* Hour (hHkK by locale) */
- g_string_append(string, purple_utf8_strftime("%M", tm));
- g_string_append(string, purple_utf8_strftime("%S", tm));
- /* Fractional Sub-second */
- /* Time Zone (specific non-location format) */
- } else if (count >= 4) {
- g_string_append(string, purple_utf8_strftime("%z", tm));
- } else if (count == 4) {
- } else if (count >= 5) {
- g_string_append(string, purple_utf8_strftime("%z", tm));
- /* Time Zone (generic non-location format) */
- g_string_append(string, purple_utf8_strftime("%Z", tm));
- } else if (count >= 4) {
- g_string_append(string, purple_utf8_strftime("%Z", tm));
- } else if (count >= 4) {
- /* Generic Location Format) */
- g_string_append(string, purple_utf8_strftime("%Z", tm));
- g_string_append_len(string, format + i, count);
- return g_string_free(string, FALSE);
/**************************************************************************
**************************************************************************/
@@ -1282,100 +943,6 @@
-purple_markup_extract_info_field(const char *str, int len, PurpleNotifyUserInfo *user_info,
- const char *start_token, int skip,
- const char *end_token, char check_value,
- const char *no_value_token,
- const char *display_name, gboolean is_link,
- const char *link_prefix,
- PurpleInfoFieldFormatCallback format_cb)
- g_return_val_if_fail(str != NULL, FALSE);
- g_return_val_if_fail(user_info != NULL, FALSE);
- g_return_val_if_fail(start_token != NULL, FALSE);
- g_return_val_if_fail(end_token != NULL, FALSE);
- g_return_val_if_fail(display_name != NULL, FALSE);
- p = strstr(str, start_token);
- p += strlen(start_token) + skip;
- if (check_value != '\0' && *p == check_value)
- q = strstr(p, end_token);
- /* Trim leading blanks */
- while (*p != '\n' && g_ascii_isspace(*p)) {
- /* Trim trailing blanks */
- while (q > p && g_ascii_isspace(*(q - 1))) {
- /* Don't bother with null strings */
- if (q != NULL && (!no_value_token ||
- strncmp(p, no_value_token, strlen(no_value_token)))) {
- GString *dest = g_string_new("");
- g_string_append(dest, "<a href=\"");
- g_string_append(dest, link_prefix);
- char *reformatted = format_cb(p, q - p);
- g_string_append(dest, reformatted);
- g_string_append_len(dest, p, q - p);
- g_string_append(dest, "\">");
- g_string_append(dest, link_prefix);
- g_string_append_len(dest, p, q - p);
- g_string_append(dest, "</a>");
- char *reformatted = format_cb(p, q - p);
- g_string_append(dest, reformatted);
- g_string_append_len(dest, p, q - p);
- purple_notify_user_info_add_pair_html(user_info, display_name, dest->str);
- g_string_free(dest, TRUE);
struct purple_parse_tag {
@@ -2599,7 +2166,7 @@
gboolean xdg_path_exists;
/* Create destination directory */
- mkdir_res = purple_build_dir(purple_xdg_dir, S_IRWXU);
+ mkdir_res = g_mkdir_with_parents(purple_xdg_dir, S_IRWXU); purple_debug_error("util", "Error creating xdg directory %s: %s; failed migration\n",
purple_xdg_dir, g_strerror(errno));
@@ -2648,11 +2215,6 @@
-int purple_build_dir(const char *path, int mode)
- return g_mkdir_with_parents(path, mode);
purple_util_write_data_to_file_common(const char *dir, const char *filename, const char *data, gssize size)
@@ -3112,12 +2674,6 @@
-purple_str_has_prefix(const char *s, const char *p)
- return g_str_has_prefix(s, p);
purple_str_has_caseprefix(const gchar *s, const gchar *p)
g_return_val_if_fail(s, FALSE);
@@ -3126,12 +2682,6 @@
return (g_ascii_strncasecmp(s, p, strlen(p)) == 0);
-purple_str_has_suffix(const char *s, const char *x)
- return g_str_has_suffix(s, x);
purple_str_add_cr(const char *text)
@@ -3351,27 +2901,6 @@
-purple_str_binary_to_ascii(const unsigned char *binary, guint len)
- g_return_val_if_fail(len > 0, NULL);
- ret = g_string_sized_new(len);
- for (i = 0; i < len; i++)
- if (binary[i] < 32 || binary[i] > 126)
- g_string_append_printf(ret, "\\x%02x", binary[i] & 0xFF);
- else if (binary[i] == '\\')
- g_string_append(ret, "\\\\");
- g_string_append_c(ret, binary[i]);
- return g_string_free(ret, FALSE);
purple_utf16_size(const gunichar2 *str)
@@ -4146,18 +3675,6 @@
-gchar * purple_escape_js(const gchar *str)
- json_node_set_string(escape_js_node, str);
- json_generator_set_root(escape_js_gen, escape_js_node);
- escaped = json_generator_to_data(escape_js_gen, NULL);
- json_node_set_boolean(escape_js_node, FALSE);
void purple_restore_default_signal_handlers(void)
@@ -4261,12 +3778,6 @@
-purple_get_host_name(void)
- return g_get_host_name();
--- a/libpurple/util.h Mon Nov 04 10:00:14 2019 +0300
+++ b/libpurple/util.h Mon Nov 04 14:43:49 2019 +0300
@@ -314,21 +314,6 @@
GDateTime *purple_str_to_date_time(const char *timestamp, gboolean utc);
- * @format: The formatting string, according to UTS \#35
- * See http://unicode.org/reports/tr35/
- * (NOTE: not all formats are supported)
- * @len: The length of the formatting string
- * @tm: The time to format, or %NULL to use the current local time
- * Formats a datetime according to a UTS-35 Date Format Pattern.
- * Returns: The time, formatted as per the user's settings.
-char *purple_uts35_to_str(const char *format, size_t len, struct tm *tm);
/**************************************************************************/
/**************************************************************************/
@@ -370,38 +355,6 @@
- * purple_markup_extract_info_field:
- * @str: The string to parse.
- * @len: The size of str.
- * @user_info: The destination PurpleNotifyUserInfo to which the new
- * field info should be added.
- * @start_token: The beginning token.
- * @skip: The number of characters to skip after the
- * @end_token: The ending token.
- * @check_value: The value that the last character must meet.
- * @no_value_token: The token indicating no value is given.
- * @display_name: The short descriptive name to display for this token.
- * @is_link: TRUE if this should be a link, or FALSE otherwise.
- * @link_prefix: The prefix for the link.
- * @format_cb: (scope call): A callback to format the value before adding it.
- * Extracts a field of data from HTML.
- * This is a scary function. It used to be used for MSN and Yahoo prpls,
- * but since those prpls have been removed, this is now deprecated.
- * Returns: TRUE if successful, or FALSE otherwise.
-gboolean purple_markup_extract_info_field(const char *str, int len, PurpleNotifyUserInfo *user_info,
- const char *start_token, int skip,
- const char *end_token, char check_value,
- const char *no_value_token,
- const char *display_name, gboolean is_link,
- const char *link_prefix,
- PurpleInfoFieldFormatCallback format_cb);
* purple_markup_html_to_xhtml:
* @html: The HTML markup.
* @dest_xhtml: The destination XHTML output.
@@ -646,19 +599,6 @@
void purple_util_set_user_dir(const char *dir);
- * @path: The path you wish to create. Note that it must start
- * from the root or this function will fail.
- * @mode: Unix-style permissions for this directory.
- * Builds a complete path from the root, making any directories along
- * the path which do not already exist.
- * Returns: 0 for success, nonzero on any error.
-int purple_build_dir(const char *path, int mode);
* purple_util_write_data_to_file:
* @filename: The basename of the file to write in the purple_user_dir.
* @data: A string of data to write.
@@ -995,18 +935,6 @@
gboolean purple_validate(const PurpleProtocol *protocol, const char *str);
- * purple_str_has_prefix:
- * @s: The string to check.
- * @p: The prefix in question.
- * Compares two strings to see if the first contains the second as
- * Returns: TRUE if p is a prefix of s, otherwise FALSE.
-gboolean purple_str_has_prefix(const char *s, const char *p);
* purple_str_has_caseprefix:
* @s: The string to check.
* @p: The prefix in question.
@@ -1020,18 +948,6 @@
purple_str_has_caseprefix(const gchar *s, const gchar *p);
- * purple_str_has_suffix:
- * @s: The string to check.
- * @x: The suffix in question.
- * Compares two strings to see if the second is a proper suffix
- * Returns: TRUE if x is a a suffix of s, otherwise FALSE.
-gboolean purple_str_has_suffix(const char *s, const char *x);
* purple_strdup_withhtml:
* @src: The source string.
@@ -1165,22 +1081,6 @@
char *purple_str_seconds_to_string(guint sec);
- * purple_str_binary_to_ascii:
- * @binary: A string of random data, possibly with embedded NULs
- * @len: The length in bytes of the input string. Must not be 0.
- * Converts a binary string into a NUL terminated ascii string,
- * replacing nonascii characters and characters below SPACE (including
- * NUL) into \\xyy, where yy are two hex digits. Also backslashes are
- * changed into two backslashes (\\\\). The returned, newly allocated
- * string can be outputted to the console, and must be g_free()d.
- * Returns: A newly allocated ASCIIZ string.
-char *purple_str_binary_to_ascii(const unsigned char *binary, guint len);
@@ -1252,16 +1152,6 @@
gboolean purple_email_is_valid(const char *address);
- * purple_ipv6_address_is_valid:
- * @ip: The IP address to validate.
- * Checks if the given IP address is a syntactically valid IPv6 address.
- * Returns: True if the IP address is syntactically correct.
-gboolean purple_ipv6_address_is_valid(const char *ip);
* purple_uri_list_extract_uris:
* @uri_list: An uri-list in the standard format.
@@ -1429,16 +1319,6 @@
const char *purple_escape_filename(const char *str);
- * @str: The string to escape.
- * Escapes javascript-unfriendly substrings from a string.
- * Returns: The javascript-safe string (must be g_free'd after use).
-gchar * purple_escape_js(const gchar *str);
* purple_restore_default_signal_handlers:
* Restore default signal handlers for signals which might reasonably have
@@ -1448,16 +1328,6 @@
void purple_restore_default_signal_handlers(void);
- * purple_get_host_name:
- * Gets the host name of the machine. If it not possible to determine the
- * host name, "localhost" is returned
- * Returns: The hostname
-const gchar *purple_get_host_name(void);
* Returns a type 4 (random) UUID
--- a/meson.build Mon Nov 04 10:00:14 2019 +0300
+++ b/meson.build Mon Nov 04 14:43:49 2019 +0300
@@ -455,7 +455,7 @@
#######################################################################
# Check for SILC client includes and libraries
#######################################################################
-silc = dependency('silcclient', version : '>= 1.1', required : get_option('silc'))
+silc = dependency('silcclient', version : '>= 1.1.1', required : get_option('silc')) #######################################################################
# Check for Gadu-Gadu protocol library (libgadu)
--- a/pidgin/gtkblist.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/gtkblist.c Mon Nov 04 14:43:49 2019 +0300
@@ -5686,8 +5686,9 @@
enteredstring = g_utf8_casefold(tmp, -1);
- if (purple_str_has_prefix(compare, enteredstring))
+ if (g_str_has_prefix(compare, enteredstring)) { --- a/pidgin/gtkconv.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/gtkconv.c Mon Nov 04 14:43:49 2019 +0300
@@ -479,7 +479,7 @@
cmd = talkatu_buffer_get_plain_text(TALKATU_BUFFER(buffer));
- if (cmd && purple_str_has_prefix(cmd, prefix)) {
+ if (cmd && g_str_has_prefix(cmd, prefix)) { char *error, *cmdline, *markup, *send_history;
@@ -2258,7 +2258,7 @@
win = pidgin_buddy_icon_chooser_new(GTK_WINDOW(toplevel),
custom_icon_sel_cb, contact);
g_object_set_data_full(G_OBJECT(contact), "buddy-icon-chooser", win,
- (GDestroyNotify)g_object_unref);
gtk_native_dialog_show(GTK_NATIVE_DIALOG(win));
@@ -2744,7 +2744,7 @@
buddy = purple_buddy_new(account, purple_conversation_get_name(conv), NULL);
purple_blist_node_set_transient((PurpleBlistNode *)buddy, TRUE);
g_object_set_data_full(G_OBJECT(gtkconv->history), "transient_buddy",
- buddy, (GDestroyNotify)g_object_unref);
+ buddy, g_object_unref); --- a/pidgin/gtkdialogs.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/gtkdialogs.c Mon Nov 04 14:43:49 2019 +0300
@@ -417,8 +417,9 @@
username = g_strdup(purple_normalize(account,
purple_request_fields_get_string(fields, "screenname")));
- if (username != NULL && purple_str_has_suffix(username, "rocksmyworld"))
+ if (username != NULL && g_str_has_suffix(username, "rocksmyworld")) { found = pidgin_dialogs_ee(username);
if (!found && username != NULL && *username != '\0' && account != NULL)
pidgin_retrieve_user_info(purple_account_get_connection(account), username);
--- a/pidgin/gtknotify.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/gtknotify.c Mon Nov 04 14:43:49 2019 +0300
@@ -360,7 +360,7 @@
-reset_mail_dialog(GtkDialog *unused)
+reset_mail_dialog(gpointer unused) g_return_if_fail(mail_dialog != NULL);
@@ -841,7 +841,7 @@
pidgin_blist_set_headline(label_text, "mail-unread",
G_CALLBACK(pidgin_notify_emails_present),
- (GDestroyNotify)reset_mail_dialog);
mail_dialog->in_use = FALSE;
} else if (!gtk_widget_has_focus(mail_dialog->dialog))
@@ -1555,8 +1555,6 @@
gtk_widget_show_all(pounce_dialog->dialog);
static PidginNotifyDialog *
--- a/pidgin/gtkprefs.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/gtkprefs.c Mon Nov 04 14:43:49 2019 +0300
@@ -1259,8 +1259,9 @@
gchar *destdir_escaped = g_shell_quote(destdir);
- if (!g_file_test(destdir, G_FILE_TEST_IS_DIR))
- purple_build_dir(destdir, S_IRUSR | S_IWUSR | S_IXUSR);
+ if (!g_file_test(destdir, G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents(destdir, S_IRUSR | S_IWUSR | S_IXUSR); command = g_strdup_printf("tar > /dev/null xzf %s -C %s", path_escaped, destdir_escaped);
@@ -1298,8 +1299,9 @@
purple_theme_get_name(theme),
"purple", info->type, NULL);
- if (!g_file_test(theme_dest, G_FILE_TEST_IS_DIR))
- purple_build_dir(theme_dest, S_IRUSR | S_IWUSR | S_IXUSR);
+ if (!g_file_test(theme_dest, G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents(theme_dest, S_IRUSR | S_IWUSR | S_IXUSR); theme_dest = g_build_filename(purple_data_dir(), "themes",
@@ -1344,8 +1346,9 @@
- if (!g_file_test(temp_path, G_FILE_TEST_IS_DIR))
- purple_build_dir(temp_path, S_IRUSR | S_IWUSR | S_IXUSR);
+ if (!g_file_test(temp_path, G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents(temp_path, S_IRUSR | S_IWUSR | S_IXUSR); if (purple_theme_file_copy(path, temp_file)) {
/* find the theme, could be in subfolder */
@@ -1357,8 +1360,9 @@
purple_theme_get_name(theme), "purple",
- if(!g_file_test(theme_dest, G_FILE_TEST_IS_DIR))
- purple_build_dir(theme_dest, S_IRUSR | S_IWUSR | S_IXUSR);
+ if(!g_file_test(theme_dest, G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents(theme_dest, S_IRUSR | S_IWUSR | S_IXUSR); if (g_rename(purple_theme_get_dir(theme), theme_dest)) {
purple_debug_error("gtkprefs", "Error renaming %s to %s: "
--- a/pidgin/gtkrequest.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/gtkrequest.c Mon Nov 04 14:43:49 2019 +0300
@@ -1073,8 +1073,7 @@
if ((type_hint = purple_request_field_get_field_type_hint(field)) != NULL)
- if (purple_str_has_prefix(type_hint, "screenname"))
+ if (g_str_has_prefix(type_hint, "screenname")) { GtkWidget *optmenu = NULL;
PurpleRequestFieldGroup *group = purple_request_field_get_group(field);
GList *fields = purple_request_field_group_get_fields(group);
--- a/pidgin/gtkutils.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/gtkutils.c Mon Nov 04 14:43:49 2019 +0300
@@ -699,7 +699,7 @@
if (*s != '\0') *s++ = '\0';
/* Clear past any whitespace */
- while (*s != '\0' && *s == ' ')
/* Now let's grab until the end of the line. */
@@ -1374,7 +1374,7 @@
/* Are we trying to send a .desktop file? */
- else if (purple_str_has_suffix(basename, ".desktop")) {
+ else if (g_str_has_suffix(basename, ".desktop")) { pidgin_dnd_file_send_desktop(account, who, filename);
@@ -1579,8 +1579,7 @@
gtk_tree_model_get_value(model, iter, COMPLETION_NORMALIZED_COLUMN, &val1);
tmp = g_value_get_string(&val1);
- if (tmp != NULL && purple_str_has_prefix(tmp, key))
+ if (tmp != NULL && g_str_has_prefix(tmp, key)) { @@ -1589,8 +1588,7 @@
gtk_tree_model_get_value(model, iter, COMPLETION_COMPARISON_COLUMN, &val2);
tmp = g_value_get_string(&val2);
- if (tmp != NULL && purple_str_has_prefix(tmp, key))
+ if (tmp != NULL && g_str_has_prefix(tmp, key)) { @@ -2351,15 +2349,13 @@
normalized = g_utf8_casefold(tmp, -1);
- if (purple_str_has_prefix(normalized, enteredstring))
+ if (g_str_has_prefix(normalized, enteredstring)) {
/* Use Pango to separate by words. */
len = g_utf8_strlen(normalized, -1);
log_attrs = g_new(PangoLogAttr, len + 1);
@@ -2371,8 +2367,7 @@
for (i = 0; i < (len - 1) ; i++)
if (log_attrs[i].is_word_start &&
- purple_str_has_prefix(word, enteredstring))
+ g_str_has_prefix(word, enteredstring)) { @@ -2390,7 +2385,7 @@
if (!g_unichar_isalnum(c))
word = g_utf8_find_next_char(word, NULL);
- if (purple_str_has_prefix(word, enteredstring))
+ if (g_str_has_prefix(word, enteredstring)) --- a/pidgin/gtkxfer.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/gtkxfer.c Mon Nov 04 14:43:49 2019 +0300
@@ -482,10 +482,11 @@
char *escaped = g_shell_quote(filename);
- if (purple_str_has_suffix(filename, ".desktop"))
+ if (g_str_has_suffix(filename, ".desktop")) { command = g_strdup_printf("kfmclient openURL %s 'text/plain'", escaped);
command = g_strdup_printf("kfmclient openURL %s", escaped);
--- a/pidgin/libpidgin.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/libpidgin.c Mon Nov 04 14:43:49 2019 +0300
@@ -152,7 +152,7 @@
written = write(signal_sockets[0], &sig, sizeof(int));
- if (written < 0 || written != sizeof(int)) {
+ if (written != sizeof(int)) { /* This should never happen */
purple_debug_error("sighandler", "Received signal %d but only "
"wrote %" G_GSSIZE_FORMAT " bytes out of %"
--- a/pidgin/pidgincontactcompletion.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/pidgincontactcompletion.c Mon Nov 04 14:43:49 2019 +0300
@@ -113,7 +113,7 @@
- if(!purple_str_has_prefix(name, key)) {
+ if (!g_str_has_prefix(name, key)) { --- a/pidgin/pidgintooltip.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/pidgintooltip.c Mon Nov 04 14:43:49 2019 +0300
@@ -112,6 +112,8 @@
tipwindow = gtk_window_new(GTK_WINDOW_POPUP);
+ gtk_window_set_transient_for(GTK_WINDOW(tipwindow), + GTK_WINDOW(pidgin_tooltip.widget)); name = gtk_window_get_title(GTK_WINDOW(pidgin_tooltip.widget));
gtk_window_set_type_hint(GTK_WINDOW(tipwindow), GDK_WINDOW_TYPE_HINT_TOOLTIP);
gtk_widget_set_app_paintable(tipwindow, TRUE);
--- a/pidgin/plugins/spellchk.c Mon Nov 04 10:00:14 2019 +0300
+++ b/pidgin/plugins/spellchk.c Mon Nov 04 14:43:49 2019 +0300
@@ -677,7 +677,6 @@
g_signal_connect(G_OBJECT(gtkconv->entry), "message_send",
G_CALLBACK(message_send_cb), spell);
static int buf_get_line(char *ibuf, char **buf, gsize *position, gsize len)