Sat, 09 Aug 2025 17:37:27 +0800
Fix the birb header path
The birb header referred would only work with birb provided by wrap casuing
build to fail because of system-installed birb dependency. The commit points
it to the correct path <birb.h>.
See: https://keep.imfreedom.org/birb/birb/file/5bf00c7d7f80/birb/meson.build#l77
/* * Purple - Internet Messaging Library * Copyright (C) Pidgin Developers <devel@pidgin.im> * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this library; if not, see <https://www.gnu.org/licenses/>. */ #include <glib/gi18n-lib.h> #include "purpleconnection.h" #include "debug.h" #include "prefs.h" #include "proxy.h" #include "purpleaccount.h" #include "purpleenums.h" #include "request.h" #include "util.h" typedef struct { GObject gparent; char *id; GCancellable *cancellable; PurpleProtocol *protocol; /* The protocol. */ PurpleAccount *account; /* The account being connected to. */ char *password; /* The password used. */ } PurpleConnectionPrivate; enum { PROP_0, PROP_ID, PROP_CANCELLABLE, PROP_PROTOCOL, PROP_ACCOUNT, PROP_PASSWORD, N_PROPERTIES, }; static GParamSpec *properties[N_PROPERTIES] = {NULL, }; G_DEFINE_TYPE_WITH_PRIVATE(PurpleConnection, purple_connection, G_TYPE_OBJECT) /************************************************************************** * Connection API **************************************************************************/ /* * d:)->-< * * d:O-\-< * * d:D-/-< * * d8D->-< DANCE! */ PurpleAccount * purple_connection_get_account(PurpleConnection *connection) { PurpleConnectionPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), NULL); priv = purple_connection_get_instance_private(connection); return priv->account; } const char * purple_connection_get_id(PurpleConnection *connection) { PurpleConnectionPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), NULL); priv = purple_connection_get_instance_private(connection); return priv->id; } PurpleProtocol * purple_connection_get_protocol(PurpleConnection *connection) { PurpleConnectionPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), NULL); priv = purple_connection_get_instance_private(connection); return priv->protocol; } const char * purple_connection_get_password(PurpleConnection *connection) { PurpleConnectionPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), NULL); priv = purple_connection_get_instance_private(connection); return priv->password; } void purple_connection_set_password(PurpleConnection *connection, const char *password) { PurpleConnectionPrivate *priv = NULL; g_return_if_fail(PURPLE_IS_CONNECTION(connection)); priv = purple_connection_get_instance_private(connection); purple_str_wipe(priv->password); priv->password = g_strdup(password); g_object_notify_by_pspec(G_OBJECT(connection), properties[PROP_PASSWORD]); } gboolean purple_connection_error_is_fatal(PurpleConnectionError reason) { switch (reason) { case PURPLE_CONNECTION_ERROR_NETWORK_ERROR: case PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR: case PURPLE_CONNECTION_ERROR_CUSTOM_TEMPORARY: return FALSE; case PURPLE_CONNECTION_ERROR_INVALID_USERNAME: case PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED: case PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE: case PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT: case PURPLE_CONNECTION_ERROR_NAME_IN_USE: case PURPLE_CONNECTION_ERROR_INVALID_SETTINGS: case PURPLE_CONNECTION_ERROR_CERT_NOT_PROVIDED: case PURPLE_CONNECTION_ERROR_CERT_UNTRUSTED: case PURPLE_CONNECTION_ERROR_CERT_EXPIRED: case PURPLE_CONNECTION_ERROR_CERT_NOT_ACTIVATED: case PURPLE_CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH: case PURPLE_CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH: case PURPLE_CONNECTION_ERROR_CERT_SELF_SIGNED: case PURPLE_CONNECTION_ERROR_CERT_OTHER_ERROR: case PURPLE_CONNECTION_ERROR_CUSTOM_FATAL: case PURPLE_CONNECTION_ERROR_OTHER_ERROR: return TRUE; default: g_return_val_if_reached(TRUE); } } /************************************************************************** * Helpers **************************************************************************/ static void purple_connection_set_id(PurpleConnection *connection, const char *id) { PurpleConnectionPrivate *priv = NULL; priv = purple_connection_get_instance_private(connection); if(g_set_str(&priv->id, id)) { g_object_notify_by_pspec(G_OBJECT(connection), properties[PROP_ID]); } } static void purple_connection_set_account(PurpleConnection *connection, PurpleAccount *account) { PurpleConnectionPrivate *priv = NULL; priv = purple_connection_get_instance_private(connection); if(g_set_object(&priv->account, account)) { g_object_notify_by_pspec(G_OBJECT(connection), properties[PROP_ACCOUNT]); } } /************************************************************************** * GObject Implementation **************************************************************************/ static void purple_connection_set_property(GObject *obj, guint param_id, const GValue *value, GParamSpec *pspec) { PurpleConnection *connection = PURPLE_CONNECTION(obj); PurpleConnectionPrivate *priv = NULL; priv = purple_connection_get_instance_private(connection); switch (param_id) { case PROP_ID: purple_connection_set_id(connection, g_value_get_string(value)); break; case PROP_PROTOCOL: priv->protocol = g_value_get_object(value); break; case PROP_ACCOUNT: purple_connection_set_account(connection, g_value_get_object(value)); break; case PROP_PASSWORD: purple_connection_set_password(connection, g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); break; } } static void purple_connection_get_property(GObject *obj, guint param_id, GValue *value, GParamSpec *pspec) { PurpleConnection *connection = PURPLE_CONNECTION(obj); switch (param_id) { case PROP_ID: g_value_set_string(value, purple_connection_get_id(connection)); break; case PROP_CANCELLABLE: g_value_set_object(value, purple_connection_get_cancellable(connection)); break; case PROP_PROTOCOL: g_value_set_object(value, purple_connection_get_protocol(connection)); break; case PROP_ACCOUNT: g_value_set_object(value, purple_connection_get_account(connection)); break; case PROP_PASSWORD: g_value_set_string(value, purple_connection_get_password(connection)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); break; } } static void purple_connection_init(PurpleConnection *connection) { PurpleConnectionPrivate *priv = NULL; priv = purple_connection_get_instance_private(connection); priv->cancellable = g_cancellable_new(); } static void purple_connection_constructed(GObject *object) { PurpleConnection *connection = PURPLE_CONNECTION(object); PurpleConnectionPrivate *priv = NULL; G_OBJECT_CLASS(purple_connection_parent_class)->constructed(object); priv = purple_connection_get_instance_private(connection); if(priv->id == NULL) { char *uuid = g_uuid_string_random(); purple_connection_set_id(connection, uuid); g_free(uuid); } } static void purple_connection_dispose(GObject *obj) { PurpleConnection *connection = PURPLE_CONNECTION(obj); PurpleConnectionPrivate *priv = NULL; priv = purple_connection_get_instance_private(connection); g_clear_object(&priv->account); G_OBJECT_CLASS(purple_connection_parent_class)->dispose(obj); } static void purple_connection_finalize(GObject *object) { PurpleConnection *connection = PURPLE_CONNECTION(object); PurpleConnectionPrivate *priv = NULL; priv = purple_connection_get_instance_private(connection); purple_str_wipe(priv->password); g_free(priv->id); g_clear_object(&priv->cancellable); G_OBJECT_CLASS(purple_connection_parent_class)->finalize(object); } static void purple_connection_class_init(PurpleConnectionClass *klass) { GObjectClass *obj_class = G_OBJECT_CLASS(klass); obj_class->get_property = purple_connection_get_property; obj_class->set_property = purple_connection_set_property; obj_class->dispose = purple_connection_dispose; obj_class->finalize = purple_connection_finalize; obj_class->constructed = purple_connection_constructed; /** * PurpleConnection:id: * * The unique identifier for the connection. * * Since: 3.0 */ properties[PROP_ID] = g_param_spec_string( "id", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** * PurpleConnection:cancellable: * * A [class@Gio.Cancellable] to be used with the connection. * * This can be passed function that require a cancellable for the * connection. * * Since: 3.0 */ properties[PROP_CANCELLABLE] = g_param_spec_object( "cancellable", NULL, NULL, G_TYPE_CANCELLABLE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * PurpleConnection:protocol: * * The protocol that this connection is for. * * Since: 3.0 */ properties[PROP_PROTOCOL] = g_param_spec_object( "protocol", NULL, NULL, PURPLE_TYPE_PROTOCOL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** * PurpleConnection:account: * * The account this connection belongs to. * * Since: 3.0 */ properties[PROP_ACCOUNT] = g_param_spec_object( "account", NULL, NULL, PURPLE_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** * PurpleConnection:password: * * The password for this connection. * * This is only stored for reconnections and may go away in the future. * * Since: 3.0 */ properties[PROP_PASSWORD] = g_param_spec_string( "password", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); g_object_class_install_properties(obj_class, N_PROPERTIES, properties); } gboolean purple_connection_connect(PurpleConnection *connection, GError **error) { PurpleConnectionClass *klass = NULL; PurpleConnectionPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), FALSE); priv = purple_connection_get_instance_private(connection); if(!purple_account_is_connecting(priv->account)) { g_set_error(error, PURPLE_CONNECTION_ERROR, 0, "account %s is not in a connecting state", purple_account_get_username(priv->account)); return TRUE; } if(((priv->password == NULL) || (*priv->password == '\0')) && !(purple_protocol_get_options(priv->protocol) & OPT_PROTO_NO_PASSWORD) && !(purple_protocol_get_options(priv->protocol) & OPT_PROTO_PASSWORD_OPTIONAL)) { g_set_error(error, PURPLE_CONNECTION_ERROR, 0, "Cannot connect to account %s without a password.", purple_account_get_username(priv->account)); return FALSE; } purple_debug_info("connection", "Connecting. connection = %p", connection); klass = PURPLE_CONNECTION_GET_CLASS(connection); if(klass != NULL && klass->connect != NULL) { return klass->connect(connection, error); } g_set_error(error, PURPLE_CONNECTION_ERROR, 0, "The connection for %s did not implement the connect method", purple_account_get_username(priv->account)); return FALSE; } gboolean purple_connection_disconnect(PurpleConnection *connection, GError **error) { PurpleConnectionClass *klass = NULL; PurpleConnectionPrivate *priv = NULL; gboolean ret = TRUE; g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), FALSE); /* We don't check if the connection's state is connected as everything * should be idempotent when doing cleanup. */ priv = purple_connection_get_instance_private(connection); purple_debug_info("connection", "Disconnecting connection %p", connection); /* Dispatch to the connection's disconnect method. */ klass = PURPLE_CONNECTION_GET_CLASS(connection); if(klass != NULL && klass->disconnect != NULL) { ret = klass->disconnect(connection, error); } purple_account_request_close_with_account(priv->account); purple_request_close_with_handle(connection); purple_debug_info("connection", "Destroying connection %p", connection); return ret; } GCancellable * purple_connection_get_cancellable(PurpleConnection *connection) { PurpleConnectionPrivate *priv = NULL; g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), NULL); priv = purple_connection_get_instance_private(connection); return priv->cancellable; }