ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_tburst.c
Revision: 953
Committed: Sun Jul 26 21:22:42 2009 UTC (14 years, 8 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/m_tburst.c
File size: 7360 byte(s)
Log Message:
- propset keywords

File Contents

# Content
1 /* modules/m_tburst.c
2 * Copyright (C) 2002, 2003, 2004, 2005 Hybrid Development Team
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * 1.Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2.Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3.The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id$
29 */
30
31 #include "stdinc.h"
32 #include "handlers.h"
33 #include "client.h"
34 #include "common.h"
35 #include "ircd.h"
36 #include "send.h"
37 #include "msg.h"
38 #include "modules.h"
39 #include "hash.h"
40 #include "s_serv.h"
41 #include "s_conf.h"
42
43 static void ms_tb(struct Client *, struct Client *, int, char *[]);
44 static void ms_tburst(struct Client *, struct Client *, int, char *[]);
45 static void set_topic(struct Client *, struct Channel *, time_t,
46 const char *, const char *);
47
48 struct Message tburst_msgtab = {
49 "TBURST", 0, 0, 5, 0, MFLG_SLOW, 0,
50 { m_ignore, m_ignore, ms_tburst, m_ignore, m_ignore, m_ignore }
51 };
52
53 struct Message tb_msgtab = {
54 "TB", 0, 0, 4, 0, MFLG_SLOW, 0,
55 { m_ignore, m_ignore, ms_tb, m_ignore, m_ignore, m_ignore }
56 };
57
58 #ifndef STATIC_MODULES
59
60 void
61 _modinit(void)
62 {
63 mod_add_cmd(&tb_msgtab);
64 add_capability("TB", CAP_TB, 1);
65
66 mod_add_cmd(&tburst_msgtab);
67 add_capability("TBURST", CAP_TBURST, 1);
68 }
69
70 void
71 _moddeinit(void)
72 {
73 mod_del_cmd(&tb_msgtab);
74 delete_capability("TB");
75
76 mod_del_cmd(&tburst_msgtab);
77 delete_capability("TBURST");
78 }
79
80 const char *_version = "$Revision$";
81
82 #endif /* !STATIC_MODULES */
83
84 /* ms_tburst()
85 *
86 * parv[0] = sender prefix
87 * parv[1] = channel timestamp
88 * parv[2] = channel
89 * parv[3] = topic timestamp
90 * parv[4] = topic setter
91 * parv[5] = topic
92 */
93 static void
94 ms_tburst(struct Client *client_p, struct Client *source_p,
95 int parc, char *parv[])
96 {
97 struct Channel *chptr = NULL;
98 int accept_remote = 0;
99 time_t remote_channel_ts = atol(parv[1]);
100 time_t remote_topic_ts = atol(parv[3]);
101 const char *topic = "";
102 const char *setby = "";
103
104 /*
105 * Do NOT test parv[5] for an empty string and return if true!
106 * parv[5] CAN be an empty string, i.e. if the other side wants
107 * to unset our topic. Don't forget: an empty topic is also a
108 * valid topic.
109 */
110
111
112 if ((chptr = hash_find_channel(parv[2])) == NULL)
113 return;
114
115 if (parc == 6)
116 {
117 topic = parv[5];
118 setby = parv[4];
119 }
120
121 /*
122 * The logic for accepting and rejecting channel topics was
123 * always a bit hairy, so now we got exactly 2 cases where
124 * we would accept a bursted topic
125 *
126 * Case 1:
127 * The TS of the remote channel is older than ours
128 * Case 2:
129 * The TS of the remote channel is equal to ours AND
130 * the TS of the remote topic is newer than ours
131 */
132 if (remote_channel_ts < chptr->channelts)
133 accept_remote = 1;
134 else if (remote_channel_ts == chptr->channelts)
135 if (remote_topic_ts > chptr->topic_time)
136 accept_remote = 1;
137
138 if (accept_remote)
139 {
140 int topic_differs = strcmp(chptr->topic ? chptr->topic : "", topic);
141
142 set_channel_topic(chptr, topic, setby, remote_topic_ts);
143
144 if (topic_differs)
145 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s TOPIC %s :%s",
146 ConfigServerHide.hide_servers ? me.name : source_p->name,
147 chptr->chname, chptr->topic == NULL ? "" : chptr->topic);
148 }
149
150 /*
151 * Always propagate what we have received, not only if we accept the topic.
152 * This will keep other servers in sync.
153 */
154 sendto_server(source_p, chptr, CAP_TBURST, NOCAPS,
155 ":%s TBURST %s %s %s %s :%s",
156 source_p->name, parv[1], parv[2], parv[3], setby, topic);
157 if (parc > 5 && *topic != '\0') /* unsetting a topic is not supported by TB */
158 sendto_server(source_p, chptr, CAP_TB, CAP_TBURST,
159 ":%s TB %s %s %s :%s",
160 source_p->name, parv[1], parv[2], setby, topic);
161 }
162
163 /* ms_tb()
164 *
165 * parv[0] = sender prefix
166 * parv[1] = channel name
167 * parv[2] = topic timestamp
168 * parv[3] = topic setter OR topic itself if parc == 4
169 * parv[4] = topic itself if parc == 5
170 */
171 #define tb_channel parv[1]
172 #define tb_topicts_str parv[2]
173
174 static void
175 ms_tb(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
176 {
177 struct Channel *chptr;
178 time_t tb_topicts = atol(tb_topicts_str);
179 char *tb_whoset = NULL;
180 char *tb_topic = NULL;
181
182 if ((chptr = hash_find_channel(tb_channel)) == NULL)
183 return;
184
185 if (parc == 5)
186 {
187 tb_whoset = parv[3];
188 tb_topic = parv[4];
189 }
190 else
191 {
192 tb_whoset = source_p->name;
193 tb_topic = parv[3];
194 }
195
196 set_topic(source_p, chptr, tb_topicts, tb_whoset, tb_topic);
197 }
198
199 /*
200 * set_topic
201 *
202 * inputs - source_p pointer
203 * - channel pointer
204 * - topicts to set
205 * - who to set as who doing the topic
206 * - topic
207 * output - none
208 * Side effects - simply propagates topic as needed
209 * little helper function, could be removed
210 */
211 static void
212 set_topic(struct Client *source_p, struct Channel *chptr, time_t topicts,
213 const char *topicwho, const char *topic)
214 {
215 int new_topic = strcmp(chptr->topic ? chptr->topic : "", topic);
216
217 set_channel_topic(chptr, topic, topicwho, topicts);
218
219 /* Only send TOPIC to channel if it's different */
220 if (new_topic)
221 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s TOPIC %s :%s",
222 ConfigServerHide.hide_servers ? me.name : source_p->name,
223 chptr->chname, chptr->topic == NULL ? "" : chptr->topic);
224
225 sendto_server(source_p, chptr, CAP_TBURST, NOCAPS,
226 ":%s TBURST %lu %s %lu %s :%s",
227 me.name, (unsigned long)chptr->channelts, chptr->chname,
228 (unsigned long)chptr->topic_time,
229 chptr->topic_info == NULL ? "" : chptr->topic_info,
230 chptr->topic == NULL ? "" : chptr->topic);
231 sendto_server(source_p, chptr, CAP_TB, CAP_TBURST,
232 ":%s TB %s %lu %s :%s",
233 me.name, chptr->chname,
234 (unsigned long)chptr->topic_time,
235 chptr->topic_info == NULL ? "" : chptr->topic_info,
236 chptr->topic == NULL ? "" : chptr->topic);
237 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision