irc-write.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. * Please read the file COPYING, README and AUTHORS for more information.
  10. */
  11. #include "portab.h"
  12. /**
  13. * @file
  14. * Sending IRC commands over the network
  15. */
  16. #include "imp.h"
  17. #include <assert.h>
  18. #ifdef PROTOTYPES
  19. # include <stdarg.h>
  20. #else
  21. # include <varargs.h>
  22. #endif
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "defines.h"
  26. #include "conn-func.h"
  27. #include "channel.h"
  28. #include "exp.h"
  29. #include "irc-write.h"
  30. #define SEND_TO_USER 1
  31. #define SEND_TO_SERVER 2
  32. static const char *Get_Prefix PARAMS((CLIENT *Target, CLIENT *Client));
  33. static void cb_writeStrServersPrefixFlag PARAMS((CLIENT *Client,
  34. CLIENT *Prefix, void *Buffer));
  35. static bool Send_Marked_Connections PARAMS((CLIENT *Prefix, const char *Buffer));
  36. #ifdef PROTOTYPES
  37. GLOBAL bool
  38. IRC_WriteStrClient( CLIENT *Client, const char *Format, ... )
  39. #else
  40. GLOBAL bool
  41. IRC_WriteStrClient( Client, Format, va_alist )
  42. CLIENT *Client;
  43. const char *Format;
  44. va_dcl
  45. #endif
  46. {
  47. char buffer[1000];
  48. bool ok = CONNECTED;
  49. va_list ap;
  50. assert( Client != NULL );
  51. assert( Format != NULL );
  52. #ifdef PROTOTYPES
  53. va_start( ap, Format );
  54. #else
  55. va_start( ap );
  56. #endif
  57. vsnprintf( buffer, 1000, Format, ap );
  58. va_end( ap );
  59. /* to the client itself */
  60. ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), "%s", buffer );
  61. return ok;
  62. } /* IRC_WriteStrClient */
  63. #ifdef PROTOTYPES
  64. GLOBAL bool
  65. IRC_WriteStrClientPrefix(CLIENT *Client, CLIENT *Prefix, const char *Format, ...)
  66. #else
  67. GLOBAL bool
  68. IRC_WriteStrClientPrefix(Client, Prefix, Format, va_alist)
  69. CLIENT *Client;
  70. CLIENT *Prefix;
  71. const char *Format;
  72. va_dcl
  73. #endif
  74. {
  75. /* send text to local and remote clients */
  76. char buffer[1000];
  77. va_list ap;
  78. assert( Client != NULL );
  79. assert( Format != NULL );
  80. assert( Prefix != NULL );
  81. #ifdef PROTOTYPES
  82. va_start( ap, Format );
  83. #else
  84. va_start( ap );
  85. #endif
  86. vsnprintf( buffer, 1000, Format, ap );
  87. va_end( ap );
  88. return Conn_WriteStr(Client_Conn(Client_NextHop(Client)), ":%s %s",
  89. Get_Prefix(Client_NextHop(Client), Prefix), buffer);
  90. } /* IRC_WriteStrClientPrefix */
  91. #ifdef PROTOTYPES
  92. GLOBAL bool
  93. IRC_WriteStrChannel(CLIENT *Client, CHANNEL *Chan, bool Remote,
  94. const char *Format, ...)
  95. #else
  96. GLOBAL bool
  97. IRC_WriteStrChannel(Client, Chan, Remote, Format, va_alist)
  98. CLIENT *Client;
  99. CHANNEL *Chan;
  100. bool Remote;
  101. const char *Format;
  102. va_dcl
  103. #endif
  104. {
  105. char buffer[1000];
  106. va_list ap;
  107. assert( Client != NULL );
  108. assert( Format != NULL );
  109. #ifdef PROTOTYPES
  110. va_start( ap, Format );
  111. #else
  112. va_start( ap );
  113. #endif
  114. vsnprintf( buffer, 1000, Format, ap );
  115. va_end( ap );
  116. return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, "%s", buffer );
  117. } /* IRC_WriteStrChannel */
  118. /**
  119. * send message to all clients in the same channel, but only send message
  120. * once per remote server.
  121. */
  122. #ifdef PROTOTYPES
  123. GLOBAL bool
  124. IRC_WriteStrChannelPrefix(CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix,
  125. bool Remote, const char *Format, ...)
  126. #else
  127. GLOBAL bool
  128. IRC_WriteStrChannelPrefix(Client, Chan, Prefix, Remote, Format, va_alist)
  129. CLIENT *Client;
  130. CHANNEL *Chan;
  131. CLIENT *Prefix;
  132. bool Remote;
  133. const char *Format;
  134. va_dcl
  135. #endif
  136. {
  137. char buffer[1000];
  138. CL2CHAN *cl2chan;
  139. CONN_ID conn;
  140. CLIENT *c;
  141. va_list ap;
  142. assert( Client != NULL );
  143. assert( Chan != NULL );
  144. assert( Prefix != NULL );
  145. assert( Format != NULL );
  146. #ifdef PROTOTYPES
  147. va_start( ap, Format );
  148. #else
  149. va_start( ap );
  150. #endif
  151. vsnprintf( buffer, 1000, Format, ap );
  152. va_end( ap );
  153. Conn_ClearFlags( );
  154. cl2chan = Channel_FirstMember( Chan );
  155. while( cl2chan )
  156. {
  157. c = Channel_GetClient( cl2chan );
  158. if( ! Remote )
  159. {
  160. if( Client_Conn( c ) <= NONE ) c = NULL;
  161. else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
  162. }
  163. if( c ) c = Client_NextHop( c );
  164. if( c && ( c != Client ))
  165. {
  166. /* Ok, another Client */
  167. conn = Client_Conn( c );
  168. if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
  169. else Conn_SetFlag( conn, SEND_TO_USER );
  170. }
  171. cl2chan = Channel_NextMember( Chan, cl2chan );
  172. }
  173. return Send_Marked_Connections(Prefix, buffer);
  174. } /* IRC_WriteStrChannelPrefix */
  175. #ifdef PROTOTYPES
  176. GLOBAL void
  177. IRC_WriteStrServers(CLIENT *ExceptOf, const char *Format, ...)
  178. #else
  179. GLOBAL void
  180. IRC_WriteStrServers(ExceptOf, Format, va_alist)
  181. CLIENT *ExceptOf;
  182. const char *Format;
  183. va_dcl
  184. #endif
  185. {
  186. char buffer[1000];
  187. va_list ap;
  188. assert( Format != NULL );
  189. #ifdef PROTOTYPES
  190. va_start( ap, Format );
  191. #else
  192. va_start( ap );
  193. #endif
  194. vsnprintf( buffer, 1000, Format, ap );
  195. va_end( ap );
  196. IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), "%s", buffer );
  197. } /* IRC_WriteStrServers */
  198. #ifdef PROTOTYPES
  199. GLOBAL void
  200. IRC_WriteStrServersPrefix(CLIENT *ExceptOf, CLIENT *Prefix,
  201. const char *Format, ...)
  202. #else
  203. GLOBAL void
  204. IRC_WriteStrServersPrefix(ExceptOf, Prefix, Format, va_alist)
  205. CLIENT *ExceptOf;
  206. CLIENT *Prefix;
  207. const char *Format;
  208. va_dcl
  209. #endif
  210. {
  211. char buffer[1000];
  212. va_list ap;
  213. assert( Format != NULL );
  214. assert( Prefix != NULL );
  215. #ifdef PROTOTYPES
  216. va_start( ap, Format );
  217. #else
  218. va_start( ap );
  219. #endif
  220. vsnprintf( buffer, 1000, Format, ap );
  221. va_end( ap );
  222. IRC_WriteStrServersPrefixFlag( ExceptOf, Prefix, '\0', "%s", buffer );
  223. } /* IRC_WriteStrServersPrefix */
  224. #ifdef PROTOTYPES
  225. GLOBAL void
  226. IRC_WriteStrServersPrefixFlag(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
  227. const char *Format, ...)
  228. #else
  229. GLOBAL void
  230. IRC_WriteStrServersPrefixFlag(ExceptOf, Prefix, Flag, Format, va_alist)
  231. CLIENT *ExceptOf;
  232. CLIENT *Prefix;
  233. char Flag;
  234. const char *Format;
  235. va_dcl
  236. #endif
  237. {
  238. char buffer[1000];
  239. va_list ap;
  240. assert( Format != NULL );
  241. assert( Prefix != NULL );
  242. #ifdef PROTOTYPES
  243. va_start( ap, Format );
  244. #else
  245. va_start( ap );
  246. #endif
  247. vsnprintf( buffer, 1000, Format, ap );
  248. va_end( ap );
  249. IRC_WriteStrServersPrefixFlag_CB(ExceptOf, Prefix, Flag,
  250. cb_writeStrServersPrefixFlag, buffer);
  251. } /* IRC_WriteStrServersPrefixFlag */
  252. GLOBAL void
  253. IRC_WriteStrServersPrefixFlag_CB(CLIENT *ExceptOf, CLIENT *Prefix, char Flag,
  254. void (*callback)(CLIENT *, CLIENT *, void *), void *cb_data)
  255. {
  256. CLIENT *c;
  257. c = Client_First();
  258. while(c) {
  259. if (Client_Type(c) == CLIENT_SERVER && Client_Conn(c) > NONE &&
  260. c != Client_ThisServer() && c != ExceptOf) {
  261. /* Found a target server, do the flags match? */
  262. if (Flag == '\0' || strchr(Client_Flags(c), Flag))
  263. callback(c, Prefix, cb_data);
  264. }
  265. c = Client_Next(c);
  266. }
  267. } /* IRC_WriteStrServersPrefixFlag */
  268. /**
  269. * send message to all clients that are in the same channels as the client sending this message.
  270. * only send message once per reote server.
  271. */
  272. #ifdef PROTOTYPES
  273. GLOBAL bool
  274. IRC_WriteStrRelatedPrefix(CLIENT *Client, CLIENT *Prefix, bool Remote,
  275. const char *Format, ...)
  276. #else
  277. GLOBAL bool
  278. IRC_WriteStrRelatedPrefix(Client, Prefix, Remote, Format, va_alist)
  279. CLIENT *Client;
  280. CLIENT *Prefix;
  281. bool Remote;
  282. const char *Format;
  283. va_dcl
  284. #endif
  285. {
  286. CL2CHAN *chan_cl2chan, *cl2chan;
  287. char buffer[1000];
  288. CHANNEL *chan;
  289. CONN_ID conn;
  290. va_list ap;
  291. CLIENT *c;
  292. assert( Client != NULL );
  293. assert( Prefix != NULL );
  294. assert( Format != NULL );
  295. #ifdef PROTOTYPES
  296. va_start( ap, Format );
  297. #else
  298. va_start( ap );
  299. #endif
  300. vsnprintf( buffer, 1000, Format, ap );
  301. va_end( ap );
  302. Conn_ClearFlags( );
  303. chan_cl2chan = Channel_FirstChannelOf( Client );
  304. while( chan_cl2chan )
  305. {
  306. chan = Channel_GetChannel( chan_cl2chan );
  307. cl2chan = Channel_FirstMember( chan );
  308. while( cl2chan )
  309. {
  310. c = Channel_GetClient( cl2chan );
  311. if( ! Remote )
  312. {
  313. if( Client_Conn( c ) <= NONE ) c = NULL;
  314. else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
  315. }
  316. if( c ) c = Client_NextHop( c );
  317. if( c && ( c != Client ))
  318. {
  319. conn = Client_Conn( c );
  320. if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER );
  321. else Conn_SetFlag( conn, SEND_TO_USER );
  322. }
  323. cl2chan = Channel_NextMember( chan, cl2chan );
  324. }
  325. chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
  326. }
  327. return Send_Marked_Connections(Prefix, buffer);
  328. } /* IRC_WriteStrRelatedPrefix */
  329. /**
  330. * Send WALLOPS message.
  331. */
  332. #ifdef PROTOTYPES
  333. GLOBAL void
  334. IRC_SendWallops(CLIENT *Client, CLIENT *From, const char *Format, ...)
  335. #else
  336. GLOBAL void
  337. IRC_SendWallops(Client, From, Format, va_alist )
  338. CLIENT *Client;
  339. CLIENT *From;
  340. const char *Format;
  341. va_dcl
  342. #endif
  343. {
  344. va_list ap;
  345. char msg[1000];
  346. CLIENT *to;
  347. #ifdef PROTOTYPES
  348. va_start(ap, Format);
  349. #else
  350. va_start(ap);
  351. #endif
  352. vsnprintf(msg, 1000, Format, ap);
  353. va_end(ap);
  354. for (to=Client_First(); to != NULL; to=Client_Next(to)) {
  355. if (Client_Conn(to) == NONE) /* no local connection */
  356. continue;
  357. switch (Client_Type(to)) {
  358. case CLIENT_USER:
  359. if (Client_HasMode(to, 'w'))
  360. IRC_WriteStrClientPrefix(to, From,
  361. "WALLOPS :%s", msg);
  362. break;
  363. case CLIENT_SERVER:
  364. if (to != Client)
  365. IRC_WriteStrClientPrefix(to, From,
  366. "WALLOPS :%s", msg);
  367. break;
  368. }
  369. }
  370. } /* IRC_SendWallops */
  371. GLOBAL void
  372. IRC_SetPenalty( CLIENT *Client, time_t Seconds )
  373. {
  374. CONN_ID c;
  375. assert( Client != NULL );
  376. assert( Seconds > 0 );
  377. if( Client_Type( Client ) == CLIENT_SERVER ) return;
  378. c = Client_Conn( Client );
  379. if (c > NONE)
  380. Conn_SetPenalty(c, Seconds);
  381. } /* IRC_SetPenalty */
  382. static const char *
  383. Get_Prefix(CLIENT *Target, CLIENT *Client)
  384. {
  385. assert (Target != NULL);
  386. assert (Client != NULL);
  387. if (Client_Type(Target) == CLIENT_SERVER)
  388. return Client_ID(Client);
  389. else
  390. return Client_MaskCloaked(Client);
  391. } /* Get_Prefix */
  392. static void
  393. cb_writeStrServersPrefixFlag(CLIENT *Client, CLIENT *Prefix, void *Buffer)
  394. {
  395. IRC_WriteStrClientPrefix(Client, Prefix, "%s", Buffer);
  396. } /* cb_writeStrServersPrefixFlag */
  397. static bool
  398. Send_Marked_Connections(CLIENT *Prefix, const char *Buffer)
  399. {
  400. CONN_ID conn;
  401. bool ok = CONNECTED;
  402. assert(Prefix != NULL);
  403. assert(Buffer != NULL);
  404. conn = Conn_First();
  405. while (conn != NONE) {
  406. if (Conn_Flag(conn) == SEND_TO_SERVER)
  407. ok = Conn_WriteStr(conn, ":%s %s",
  408. Client_ID(Prefix), Buffer);
  409. else if (Conn_Flag(conn) == SEND_TO_USER)
  410. ok = Conn_WriteStr(conn, ":%s %s",
  411. Client_MaskCloaked(Prefix), Buffer);
  412. if (!ok)
  413. break;
  414. conn = Conn_Next( conn );
  415. }
  416. return ok;
  417. }
  418. /* -eof- */