Freeciv-3.3
Loading...
Searching...
No Matches
handchat.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdarg.h>
19#include <stdio.h>
20#include <string.h>
21
22/* utility */
23#include "fcintl.h"
24#include "log.h"
25#include "shared.h"
26#include "support.h"
27
28/* common */
29#include "chat.h"
30#include "game.h"
31#include "packets.h"
32#include "player.h"
33
34/* server */
35#include "console.h"
36#include "notify.h"
37#include "stdinhand.h"
38
39#include "handchat.h"
40
41#define MAX_LEN_CHAT_NAME (2*MAX_LEN_NAME+10) /* for form_chat_name() names */
42
43static void send_chat_msg(struct connection *pconn,
44 const struct connection *sender,
45 const struct ft_color color,
46 const char *format, ...)
48
49/**********************************************************************/
54{
55 if (NULL != sender && NULL != dest) {
56 return conn_pattern_list_match(dest->server.ignore_list, sender);
57 } else {
58 return FALSE;
59 }
60}
61
62/**********************************************************************/
67static void form_chat_name(struct connection *pconn, char *buffer, size_t len)
68{
69 struct player *pplayer = pconn->playing;
70
71 if (!pplayer
72 || pconn->observer
73 || strcmp(player_name(pplayer), ANON_PLAYER_NAME) == 0) {
74 fc_snprintf(buffer, len, "(%s)", pconn->username);
75 } else {
76 fc_snprintf(buffer, len, "%s", player_name(pplayer));
77 }
78}
79
80/**********************************************************************/
83static void send_chat_msg(struct connection *pconn,
84 const struct connection *sender,
85 const struct ft_color color,
86 const char *format, ...)
87{
88 struct packet_chat_msg packet;
89 va_list args;
90
91 va_start(args, format);
92 vpackage_chat_msg(&packet, sender, color, format, args);
93 va_end(args);
94
96}
97
98/**********************************************************************/
103static void complain_ambiguous(struct connection *pconn, const char *name,
104 int player_conn)
105{
106 switch (player_conn) {
107 case 0:
109 _("%s is an ambiguous player name-prefix."), name);
110 break;
111 case 1:
113 _("%s is an ambiguous connection name-prefix."), name);
114 break;
115 case 2:
117 _("%s is an anonymous name. Use connection name."), name);
118 break;
119 default:
120 log_error("Unknown variant in %s(): %d.", __FUNCTION__, player_conn);
121 }
122}
123
124/**********************************************************************/
128 struct connection *dest, char *msg)
129{
131
132 form_chat_name(dest, dest_name, sizeof(dest_name));
133
134 if (conn_is_ignored(sender, dest)) {
136 _("You cannot send messages to %s; you are ignored."),
137 dest_name);
138 return;
139 }
140
141 msg = skip_leading_spaces(msg);
143
145 "->*%s* %s", dest_name, msg);
146
147 if (sender != dest) {
149 "*%s* %s", sender_name, msg);
150 }
151}
152
153/**********************************************************************/
157 struct player *pdest, char *msg)
158{
159 struct packet_chat_msg packet;
161 struct connection *dest = NULL; /* The 'pdest' user. */
163
164 msg = skip_leading_spaces(msg);
166
167 /* Find the user of the player 'pdest'. */
168 conn_list_iterate(pdest->connections, pconn) {
169 if (!pconn->observer) {
170 /* Found it! */
173 _("You cannot send messages to %s; you are ignored."),
175 return; /* NB: stop here, don't send to observers. */
176 }
177 dest = pconn;
178 break;
179 }
181
182 /* Repeat the message for the sender. */
184 "->{%s} %s", player_name(pdest), msg);
185
186 /* Send the message to destination. */
187 if (NULL != dest && dest != sender) {
189 "{%s} %s", sender_name, msg);
190 }
191
192 /* Send the message to player observers. */
194 "{%s -> %s} %s", sender_name, player_name(pdest), msg);
195 conn_list_iterate(pdest->connections, pconn) {
196 if (pconn != dest
197 && pconn != sender
199 send_packet_chat_msg(pconn, &packet);
200 }
202 if (NULL != sender->playing
203 && !sender->observer
204 && sender->playing != pdest) {
205 /* The sender is another player. */
206 conn_list_iterate(sender->playing->connections, pconn) {
207 if (pconn != sender && !conn_is_ignored(sender, pconn)) {
208 send_packet_chat_msg(pconn, &packet);
209 }
211
212 /* Add player to event cache. */
213 players = event_cache_player_add(players, sender->playing);
214 }
215
216 event_cache_add_for_players(&packet, players);
217}
218
219/**********************************************************************/
222static void chat_msg_to_allies(struct connection *sender, char *msg)
223{
224 struct packet_chat_msg packet;
225 struct event_cache_players *players = NULL;
227
228 msg = skip_leading_spaces(msg);
230
232 _("%s to allies: %s"), sender_name, msg);
233
235 if (!pplayers_allied(sender->playing, aplayer)) {
236 continue;
237 }
238
239 conn_list_iterate(aplayer->connections, pconn) {
241 send_packet_chat_msg(pconn, &packet);
242 }
244 players = event_cache_player_add(players, aplayer);
246
247 /* Add to the event cache. */
248 event_cache_add_for_players(&packet, players);
249}
250
251/**********************************************************************/
255 char *msg)
256{
257 struct packet_chat_msg packet;
259
260 msg = skip_leading_spaces(msg);
262
264 _("%s to global observers: %s"), sender_name, msg);
265
270 }
272
273 /* Add to the event cache. */
275}
276
277/**********************************************************************/
280static void chat_msg_to_all(struct connection *sender, char *msg)
281{
282 struct packet_chat_msg packet;
284
285 msg = skip_leading_spaces(msg);
287
289 "<%s> %s", sender_name, msg);
290 con_write(C_COMMENT, "%s", packet.message);
292
293 /* Add to the event cache. */
295}
296
297/**********************************************************************/
320void handle_chat_msg_req(struct connection *pconn, const char *message)
321{
323 bool double_colon;
324
326
327 /* This loop to prevent players from sending multiple lines which can
328 * be abused */
329 for (cp = real_message; *cp != '\0'; cp++) {
330 if (*cp == '\n' || *cp == '\r') {
331 *cp = '\0';
332 break;
333 }
334#ifdef FREECIV_WEB
335 if (*cp == '<' || *cp == '>' || *cp == '"' || *cp == '\'') {
336 *cp = '\0';
337 break;
338 }
339#endif /* FREECIV_WEB */
340 }
341
342 /* Server commands are prefixed with '/', which is an obvious
343 but confusing choice: even before this feature existed,
344 novice players were trying /who, /nick etc.
345 So consider this an incentive for IRC support,
346 or change it in chat.h - rp
347 */
349 /* Pass it to the command parser, which will chop the prefix off */
351
352 return;
353 }
354
355 /* Send to allies command */
357 /* This won't work if we aren't attached to a player */
358 if (NULL == pconn->playing && !pconn->observer) {
360 _("You are not attached to a player."));
361 return;
362 }
363
364 if (NULL != pconn->playing) {
366 } else {
368 }
369 return;
370 }
371
372 /* Want to allow private messages with "player_name: message",
373 (or "connection_name: message"), including unambiguously
374 abbreviated player/connection name, but also want to allow
375 sensible use of ':' within messages, and _also_ want to
376 notice intended private messages with (eg) mis-spelt name.
377
378 Approach:
379
380 If there is no ':', or ':' is first on line,
381 message is global (send to all players)
382 else if the ':' is double, try matching part before "::" against
383 connection names: for single match send to that connection,
384 for multiple matches complain, else goto heuristics below.
385 else try matching part before (single) ':' against player names:
386 for single match send to that player, for multiple matches
387 complain
388 else try matching against connection names: for single match send
389 to that connection, for multiple matches complain
390 else if some heuristics apply (a space anywhere before first ':')
391 then treat as global message,
392 else complain (might be a typo-ed intended private message)
393 */
394
396
397 if (cp && (cp != &real_message[0])) {
399 struct player *pdest = NULL;
400 struct connection *conn_dest = NULL;
401 char name[MAX_LEN_NAME];
402 char *cpblank;
403
405 cp - real_message + 1));
406
408 if (double_colon) {
412 return;
413 }
416 return;
417 }
418 } else {
419 /* Single colon */
423 return;
424 }
427 return;
428 }
431 return;
432 /* Else try for connection name match before complaining */
433 }
437 return;
438 }
441 return;
442 }
444 /* Would have done something above if connected */
446 _("%s is not connected."), player_name(pdest));
447 return;
448 }
449 }
450 /* Didn't match; check heuristics to see if this is likely
451 * to be a global message
452 */
454 if (!cpblank || (cp < cpblank)) {
455 if (double_colon) {
457 _("There is no connection by the name %s."), name);
458 } else {
460 _("There is no player nor connection by the name %s."),
461 name);
462 }
463 return;
464 }
465 }
466
467 /* Global message: */
469}
#define CHAT_DIRECT_PREFIX
Definition chat.h:31
#define CHAT_ALLIES_PREFIX
Definition chat.h:30
#define SERVER_COMMAND_PREFIX
Definition chat.h:28
char * incite_cost
Definition comments.c:76
#define MAX_LEN_MSG
Definition conn_types.h:37
struct connection * conn_by_user_prefix(const char *user_name, enum m_pre_result *result)
Definition connection.c:398
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:753
bool conn_pattern_list_match(const struct conn_pattern_list *plist, const struct connection *pconn)
Definition connection.c:850
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
void con_write(enum rfc_status rfc_status, const char *message,...)
Definition console.c:203
@ C_COMMENT
Definition console.h:37
#define MAX_LEN_NAME
Definition fc_types.h:66
#define _(String)
Definition fcintl.h:67
const struct ft_color ftc_chat_private
const struct ft_color ftc_server
const struct ft_color ftc_warning
const struct ft_color ftc_chat_public
const struct ft_color ftc_chat_ally
struct civ_game game
Definition game.c:61
static void static bool conn_is_ignored(const struct connection *sender, const struct connection *dest)
Definition handchat.c:52
static void complain_ambiguous(struct connection *pconn, const char *name, int player_conn)
Definition handchat.c:103
static void chat_msg_to_player(struct connection *sender, struct player *pdest, char *msg)
Definition handchat.c:156
static void form_chat_name(struct connection *pconn, char *buffer, size_t len)
Definition handchat.c:67
#define MAX_LEN_CHAT_NAME
Definition handchat.c:41
static void send_chat_msg(struct connection *pconn, const struct connection *sender, const struct ft_color color, const char *format,...) fc__attribute((__format__(__printf__
Definition handchat.c:83
static void chat_msg_to_all(struct connection *sender, char *msg)
Definition handchat.c:280
static void chat_msg_to_allies(struct connection *sender, char *msg)
Definition handchat.c:222
static void chat_msg_to_global_observers(struct connection *sender, char *msg)
Definition handchat.c:254
void handle_chat_msg_req(struct connection *pconn, const char *message)
Definition handchat.c:320
static void chat_msg_to_conn(struct connection *sender, struct connection *dest, char *msg)
Definition handchat.c:127
const char * name
Definition inputfile.c:127
#define log_error(message,...)
Definition log.h:104
void package_chat_msg(struct packet_chat_msg *packet, const struct connection *sender, const struct ft_color color, const char *format,...)
Definition notify.c:123
void event_cache_add_for_players(const struct packet_chat_msg *packet, struct event_cache_players *players)
Definition notify.c:671
struct event_cache_players * event_cache_player_add(struct event_cache_players *players, const struct player *pplayer)
Definition notify.c:703
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:238
void event_cache_add_for_global_observers(const struct packet_chat_msg *packet)
Definition notify.c:630
void vpackage_chat_msg(struct packet_chat_msg *packet, const struct connection *sender, const struct ft_color color, const char *format, va_list vargs)
Definition notify.c:104
void event_cache_add_for_all(const struct packet_chat_msg *packet)
Definition notify.c:619
void lsend_packet_chat_msg(struct conn_list *dest, const struct packet_chat_msg *packet)
int send_packet_chat_msg(struct connection *pc, const struct packet_chat_msg *packet)
int len
Definition packhand.c:127
struct player * player_by_name_prefix(const char *name, enum m_pre_result *result)
Definition player.c:920
const char * player_name(const struct player *pplayer)
Definition player.c:895
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1409
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define ANON_PLAYER_NAME
Definition player.h:43
char * skip_leading_spaces(char *s)
Definition shared.c:392
#define MIN(x, y)
Definition shared.h:55
m_pre_result
Definition shared.h:213
@ M_PRE_AMBIGUOUS
Definition shared.h:216
bool handle_stdin_input(struct connection *caller, char *str)
Definition stdinhand.c:4429
struct conn_list * est_connections
Definition game.h:97
Definition colors.h:21
char message[MAX_LEN_MSG]
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
#define sz_strlcpy(dest, src)
Definition support.h:195
#define fc__attribute(x)
Definition support.h:99
#define FALSE
Definition support.h:47