protocols/ircv3/purpleircv3protocol.c

Sun, 03 Nov 2024 00:05:44 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Sun, 03 Nov 2024 00:05:44 -0500
changeset 43045
308e8d0ce68c
parent 43028
dda093fe275e
child 43082
0248f784950d
permissions
-rw-r--r--

remove purple3-url-handler.desktop.in.in

The application that did the launching was removed long ago. Also this should
be implemented by the user interfaces and they might provide separate files to
groups schemas as well.

Testing Done:
Called in the turtles.

Reviewed at https://reviews.imfreedom.org/r/3640/

/*
 * 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 "purpleircv3protocol.h"

#include "purpleircv3connection.h"
#include "purpleircv3core.h"
#include "purpleircv3protocolconversation.h"

struct _PurpleIRCv3Protocol {
	PurpleProtocol parent;
};

/******************************************************************************
 * Callbacks
 *****************************************************************************/
static void
purple_ircv3_protocol_can_reach_cb(GObject *self, GAsyncResult *result,
                                   gpointer data)
{
	GError *error = NULL;
	GTask *task = data;
	gboolean can_reach = FALSE;

	/* task and result share a cancellable, so either can be used here. */
	if(g_task_return_error_if_cancelled(task)) {
		g_clear_object(&task);

		return;
	}

	can_reach = g_network_monitor_can_reach_finish(G_NETWORK_MONITOR(self), result,
	                                               &error);

	if(error != NULL) {
		g_task_return_error(task, error);
	} else if(!can_reach) {
		g_task_return_new_error(task, PURPLE_IRCV3_DOMAIN, 0,
		                        _("Unknown network error."));
	} else {
		g_task_return_boolean(task, TRUE);
	}

	g_clear_object(&task);
}

/******************************************************************************
 * PurpleProtocol Implementation
 *****************************************************************************/
static GList *
purple_ircv3_protocol_get_user_splits(G_GNUC_UNUSED PurpleProtocol *protocol) {
	PurpleAccountUserSplit *split = NULL;
	GList *splits = NULL;

	split = purple_account_user_split_new(_("Server"),
	                                      PURPLE_IRCV3_DEFAULT_SERVER,
	                                      '@');
	splits = g_list_append(splits, split);

	return splits;
}

static GList *
purple_ircv3_protocol_get_account_options(G_GNUC_UNUSED PurpleProtocol *protocol)
{
	PurpleAccountOption *option;
	GList *options = NULL;

	option = purple_account_option_int_new(_("Port"), "port",
	                                       PURPLE_IRCV3_DEFAULT_TLS_PORT);
	options = g_list_append(options, option);

	option = purple_account_option_bool_new(_("Use TLS"), "use-tls", TRUE);
	options = g_list_append(options, option);

	option = purple_account_option_string_new(_("Server password"),
	                                          "server-password", "");
	purple_account_option_string_set_masked(option, TRUE);
	options = g_list_append(options, option);

	option = purple_account_option_string_new(_("Ident name"), "ident", "");
	options = g_list_append(options, option);

	option = purple_account_option_string_new(_("Real name"), "real-name", "");
	options = g_list_append(options, option);

	option = purple_account_option_string_new(_("SASL login name"),
	                                          "sasl-login-name", "");
	options = g_list_append(options, option);

	option = purple_account_option_string_new(_("SASL mechanisms"),
	                                          "sasl-mechanisms", "");
	options = g_list_append(options, option);

	option = purple_account_option_bool_new(_("Allow plaintext SASL auth over "
	                                          "unencrypted connection"),
	                                        "plain-sasl-in-clear", FALSE);
	options = g_list_append(options, option);

	option = purple_account_option_int_new(_("Seconds between sending "
	                                         "messages"),
	                                       "rate-limit-interval", 2);
	options = g_list_append(options, option);

	option = purple_account_option_int_new(_("Maximum messages to send at "
	                                         "once"),
	                                       "rate-limit-burst", 5);
	options = g_list_append(options, option);

	return options;
}

static PurpleConnection *
purple_ircv3_protocol_create_connection(PurpleProtocol *protocol,
                                        PurpleAccount *account,
                                        const char *password,
                                        GError **error)
{
	const char *username = NULL;

	g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), NULL);
	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);

	/* Make sure the username (which includes the servername via usersplits),
	 * does not contain any whitespace.
	 */
	username = purple_account_get_username(account);
	if(strpbrk(username, " \t\v\r\n") != NULL) {
		g_set_error(error,
		            PURPLE_CONNECTION_ERROR,
		            PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
		            _("IRC nick and server may not contain whitespace"));

		return NULL;
	}

	return g_object_new(
		PURPLE_IRCV3_TYPE_CONNECTION,
		"protocol", protocol,
		"account", account,
		"password", password,
		NULL);
}

static void
purple_ircv3_protocol_can_connect_async(PurpleProtocol *protocol,
                                        PurpleAccount *account,
                                        GCancellable *cancellable,
                                        GAsyncReadyCallback callback,
                                        gpointer data)
{
	GNetworkMonitor *monitor = NULL;
	GSocketConnectable *connectable = NULL;
	GStrv parts = NULL;
	GTask *task = NULL;
	const char *username = NULL;
	int port = 0;

	task = g_task_new(protocol, cancellable, callback, data);

	monitor = g_network_monitor_get_default();

	username = purple_account_get_username(account);
	parts = g_strsplit(username, "@", 2);
	port = purple_account_get_int(account, "port",
	                              PURPLE_IRCV3_DEFAULT_TLS_PORT);

	connectable = g_network_address_new(parts[1], (guint16)port);
	g_strfreev(parts);

	g_network_monitor_can_reach_async(monitor, connectable, cancellable,
	                                  purple_ircv3_protocol_can_reach_cb,
	                                  task);
	g_clear_object(&connectable);
}

static gboolean
purple_ircv3_protocol_can_connect_finish(G_GNUC_UNUSED PurpleProtocol *protocol,
                                         GAsyncResult *result,
                                         GError **error)
{
	return g_task_propagate_boolean(G_TASK(result), error);
}

/******************************************************************************
 * GObject Implementation
 *****************************************************************************/
G_DEFINE_DYNAMIC_TYPE_EXTENDED(
	PurpleIRCv3Protocol,
	purple_ircv3_protocol,
	PURPLE_TYPE_PROTOCOL,
	G_TYPE_FLAG_FINAL,
	G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CONVERSATION,
	                              purple_ircv3_protocol_conversation_init))

static void
purple_ircv3_protocol_init(G_GNUC_UNUSED PurpleIRCv3Protocol *protocol) {
}

static void
purple_ircv3_protocol_class_finalize(G_GNUC_UNUSED PurpleIRCv3ProtocolClass *klass) {
}

static void
purple_ircv3_protocol_class_init(PurpleIRCv3ProtocolClass *klass) {
	PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);

	protocol_class->get_user_splits = purple_ircv3_protocol_get_user_splits;
	protocol_class->get_account_options =
		purple_ircv3_protocol_get_account_options;
	protocol_class->create_connection =
		purple_ircv3_protocol_create_connection;
	protocol_class->can_connect_async =
		purple_ircv3_protocol_can_connect_async;
	protocol_class->can_connect_finish =
		purple_ircv3_protocol_can_connect_finish;
}

/******************************************************************************
 * GObject Implementation
 *****************************************************************************/
void
purple_ircv3_protocol_register(GPluginNativePlugin *plugin) {
	purple_ircv3_protocol_register_type(G_TYPE_MODULE(plugin));
}

PurpleProtocol *
purple_ircv3_protocol_new(void) {
	return g_object_new(
		PURPLE_IRCV3_TYPE_PROTOCOL,
		"id", "prpl-ircv3",
		"name", "IRCv3",
		"description", _("Version 3 of Internet Relay Chat (IRC)."),
		"icon-name", PURPLE_IRCV3_ICON_NAME,
		"icon-resource-path", "/im/pidgin/libpurple/ircv3/icons",
		"options", OPT_PROTO_CHAT_TOPIC | OPT_PROTO_PASSWORD_OPTIONAL |
		           OPT_PROTO_SLASH_COMMANDS_NATIVE,
		NULL);
}

mercurial