1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-27 05:16:38 +02:00
Files
weechat/src/plugins/relay/api/relay-api.c
T
2026-06-20 17:30:41 +02:00

391 lines
12 KiB
C

/*
* SPDX-FileCopyrightText: 2023-2026 Sébastien Helleu <flashcode@flashtux.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat 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 3 of the License, or
* (at your option) any later version.
*
* WeeChat 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 WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
/* API protocol for relay to client */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <errno.h>
#include <arpa/inet.h>
#include "../../weechat-plugin.h"
#include "../relay.h"
#include "../relay-client.h"
#include "../relay-config.h"
#include "../relay-http.h"
#include "../relay-raw.h"
#include "../relay-raw.h"
#include "relay-api.h"
#include "relay-api-protocol.h"
/*
* Return buffer id.
*/
long long
relay_api_get_buffer_id (struct t_gui_buffer *buffer)
{
const char *ptr_id;
long long id;
if (!buffer)
return -1;
ptr_id = weechat_buffer_get_string (buffer, "id");
if (!ptr_id)
return -1;
if (!weechat_util_parse_longlong (ptr_id, 10, &id))
return -1;
return id;
}
/*
* Return value of "colors" URL parameter, an enum with one of these values:
* - RELAY_API_COLORS_ANSI (default)
* - RELAY_API_COLORS_WEECHAT
* - RELAY_API_COLORS_STRIP
*/
int
relay_api_search_colors (const char *colors)
{
if (!colors)
return -1;
if (strcmp (colors, "ansi") == 0)
return RELAY_API_COLORS_ANSI;
if (strcmp (colors, "weechat") == 0)
return RELAY_API_COLORS_WEECHAT;
if (strcmp (colors, "strip") == 0)
return RELAY_API_COLORS_STRIP;
return -1;
}
/*
* Hook signals for a client.
*/
void
relay_api_hook_signals (struct t_relay_client *client)
{
if (!RELAY_API_DATA(client, hook_signal_buffer))
{
RELAY_API_DATA(client, hook_signal_buffer) =
weechat_hook_signal ("buffer_*",
&relay_api_protocol_signal_buffer_cb,
client, NULL);
}
if (RELAY_API_DATA(client, sync_nicks))
{
if (!RELAY_API_DATA(client, hook_hsignal_nicklist))
{
RELAY_API_DATA(client, hook_hsignal_nicklist) =
weechat_hook_hsignal ("nicklist_*",
&relay_api_protocol_hsignal_nicklist_cb,
client, NULL);
}
}
else
{
if (RELAY_API_DATA(client, hook_hsignal_nicklist))
{
weechat_unhook (RELAY_API_DATA(client, hook_hsignal_nicklist));
RELAY_API_DATA(client, hook_hsignal_nicklist) = NULL;
}
}
if (RELAY_API_DATA(client, sync_input))
{
if (!RELAY_API_DATA(client, hook_signal_input))
{
RELAY_API_DATA(client, hook_signal_input) =
weechat_hook_signal ("input_prompt_changed;"
"input_text_changed;"
"input_text_cursor_moved",
&relay_api_protocol_signal_input_cb,
client, NULL);
}
}
else
{
if (RELAY_API_DATA(client, hook_signal_input))
{
weechat_unhook (RELAY_API_DATA(client, hook_signal_input));
RELAY_API_DATA(client, hook_signal_input) = NULL;
}
}
if (!RELAY_API_DATA(client, hook_signal_upgrade))
{
RELAY_API_DATA(client, hook_signal_upgrade) =
weechat_hook_signal ("upgrade*;quit",
&relay_api_protocol_signal_upgrade_cb,
client, NULL);
}
}
/*
* Unhook signals for a client.
*/
void
relay_api_unhook_signals (struct t_relay_client *client)
{
if (RELAY_API_DATA(client, hook_signal_buffer))
{
weechat_unhook (RELAY_API_DATA(client, hook_signal_buffer));
RELAY_API_DATA(client, hook_signal_buffer) = NULL;
}
if (RELAY_API_DATA(client, hook_hsignal_nicklist))
{
weechat_unhook (RELAY_API_DATA(client, hook_hsignal_nicklist));
RELAY_API_DATA(client, hook_hsignal_nicklist) = NULL;
}
if (RELAY_API_DATA(client, hook_signal_input))
{
weechat_unhook (RELAY_API_DATA(client, hook_signal_input));
RELAY_API_DATA(client, hook_signal_input) = NULL;
}
if (RELAY_API_DATA(client, hook_signal_upgrade))
{
weechat_unhook (RELAY_API_DATA(client, hook_signal_upgrade));
RELAY_API_DATA(client, hook_signal_upgrade) = NULL;
}
}
/*
* Read HTTP request from a client.
*/
void
relay_api_recv_http (struct t_relay_client *client)
{
relay_api_protocol_recv_http (client);
}
/*
* Read JSON string from a client.
*/
void
relay_api_recv_json (struct t_relay_client *client, const char *json)
{
relay_api_protocol_recv_json (client, json);
}
/*
* Close connection with a client.
*/
void
relay_api_close_connection (struct t_relay_client *client)
{
/*
* IMPORTANT: if changes are made in this function or sub-functions called,
* please also update the function relay_api_add_to_infolist:
* when the flag force_disconnected_state is set to 1 we simulate
* a disconnected state for client in infolist (used on /upgrade -save)
*/
relay_api_unhook_signals (client);
}
/*
* Initialize relay data specific to API protocol.
*/
void
relay_api_alloc (struct t_relay_client *client)
{
client->protocol_data = malloc (sizeof (struct t_relay_api_data));
if (!client->protocol_data)
return;
RELAY_API_DATA(client, hook_signal_buffer) = NULL;
RELAY_API_DATA(client, hook_hsignal_nicklist) = NULL;
RELAY_API_DATA(client, hook_signal_input) = NULL;
RELAY_API_DATA(client, hook_signal_upgrade) = NULL;
RELAY_API_DATA(client, buffers_closing) = weechat_hashtable_new (
32,
WEECHAT_HASHTABLE_POINTER,
WEECHAT_HASHTABLE_STRING,
NULL,
NULL);
RELAY_API_DATA(client, sync_enabled) = 0;
RELAY_API_DATA(client, sync_nicks) = 0;
RELAY_API_DATA(client, sync_input) = 0;
RELAY_API_DATA(client, sync_colors) = RELAY_API_COLORS_ANSI;
}
/*
* Initialize relay data specific to API protocol with an infolist.
*
* This is called after /upgrade.
*/
void
relay_api_alloc_with_infolist (struct t_relay_client *client,
struct t_infolist *infolist)
{
client->protocol_data = malloc (sizeof (struct t_relay_api_data));
if (!client->protocol_data)
return;
RELAY_API_DATA(client, hook_signal_buffer) = NULL;
RELAY_API_DATA(client, hook_hsignal_nicklist) = NULL;
RELAY_API_DATA(client, hook_signal_input) = NULL;
RELAY_API_DATA(client, hook_signal_upgrade) = NULL;
RELAY_API_DATA(client, buffers_closing) = weechat_hashtable_new (
32,
WEECHAT_HASHTABLE_POINTER,
WEECHAT_HASHTABLE_STRING,
NULL,
NULL);
RELAY_API_DATA(client, sync_enabled) = weechat_infolist_integer (
infolist, "sync_enabled");
RELAY_API_DATA(client, sync_nicks) = weechat_infolist_integer (
infolist, "sync_nicks");
RELAY_API_DATA(client, sync_input) = weechat_infolist_integer (
infolist, "sync_input");
RELAY_API_DATA(client, sync_colors) = weechat_infolist_integer (
infolist, "sync_colors");
if (!RELAY_STATUS_HAS_ENDED(client->status)
&& RELAY_API_DATA(client, sync_enabled))
{
relay_api_hook_signals (client);
}
}
/*
* Return the client initial status: it is always "authenticating" for API
* protocol because we always expect the client to authenticate.
*/
enum t_relay_status
relay_api_get_initial_status (struct t_relay_client *client)
{
/* make C compiler happy */
(void) client;
return RELAY_STATUS_AUTHENTICATING;
}
/*
* Free relay data specific to API protocol.
*/
void
relay_api_free (struct t_relay_client *client)
{
if (!client)
return;
if (client->protocol_data)
{
weechat_unhook (RELAY_API_DATA(client, hook_signal_buffer));
weechat_unhook (RELAY_API_DATA(client, hook_hsignal_nicklist));
weechat_unhook (RELAY_API_DATA(client, hook_signal_input));
weechat_unhook (RELAY_API_DATA(client, hook_signal_upgrade));
weechat_hashtable_free (RELAY_API_DATA(client, buffers_closing));
free (client->protocol_data);
client->protocol_data = NULL;
}
}
/*
* Add client API data in an infolist.
*
* If force_disconnected_state == 1, the infolist contains the client
* in a disconnected state (but the client is unchanged, still connected if it
* was).
*
* Return:
* 1: OK
* 0: error
*/
int
relay_api_add_to_infolist (struct t_infolist_item *item,
struct t_relay_client *client,
int force_disconnected_state)
{
if (!item || !client)
return 0;
/* parameter not used today, it may be in future */
(void) force_disconnected_state;
if (!weechat_infolist_new_var_pointer (item, "hook_signal_buffer", RELAY_API_DATA(client, hook_signal_buffer)))
return 0;
if (!weechat_infolist_new_var_pointer (item, "hook_hsignal_nicklist", RELAY_API_DATA(client, hook_hsignal_nicklist)))
return 0;
if (!weechat_infolist_new_var_pointer (item, "hook_signal_input", RELAY_API_DATA(client, hook_signal_input)))
return 0;
if (!weechat_infolist_new_var_pointer (item, "hook_signal_upgrade", RELAY_API_DATA(client, hook_signal_upgrade)))
return 0;
if (!weechat_infolist_new_var_integer (item, "sync_enabled", RELAY_API_DATA(client, sync_enabled)))
return 0;
if (!weechat_infolist_new_var_integer (item, "sync_nicks", RELAY_API_DATA(client, sync_nicks)))
return 0;
if (!weechat_infolist_new_var_integer (item, "sync_input", RELAY_API_DATA(client, sync_input)))
return 0;
if (!weechat_infolist_new_var_integer (item, "sync_colors", RELAY_API_DATA(client, sync_colors)))
return 0;
return 1;
}
/*
* Print client API data in WeeChat log file (usually for crash dump).
*/
void
relay_api_print_log (struct t_relay_client *client)
{
if (client->protocol_data)
{
weechat_log_printf (" hook_signal_buffer. . . : %p", RELAY_API_DATA(client, hook_signal_buffer));
weechat_log_printf (" hook_hsignal_nicklist . : %p", RELAY_API_DATA(client, hook_hsignal_nicklist));
weechat_log_printf (" hook_signal_input . . . : %p", RELAY_API_DATA(client, hook_signal_input));
weechat_log_printf (" hook_signal_upgrade . . : %p", RELAY_API_DATA(client, hook_signal_upgrade));
weechat_log_printf (" buffers_closing. . . . .: %p (hashtable: '%s')",
RELAY_API_DATA(client, buffers_closing),
weechat_hashtable_get_string (
RELAY_API_DATA(client, buffers_closing),
"keys_values"));
weechat_log_printf (" sync_enabled. . . . . . : %d", RELAY_API_DATA(client, sync_enabled));
weechat_log_printf (" sync_nicks. . . . . . . : %d", RELAY_API_DATA(client, sync_nicks));
weechat_log_printf (" sync_input. . . . . . . : %d", RELAY_API_DATA(client, sync_input));
weechat_log_printf (" sync_colors . . . . . . : %d", RELAY_API_DATA(client, sync_colors));
}
}