- A35F64EE21532CC117FB36691ECE37E2F523CB01855FB4EB8268AC745519F27FD36ADDB324D56D4893FB7A84FE70302630E53BECF3571E250B3B578CA46ABCE3+ 98E1E99D7EA8FE523728CA8F5661B244F3769A09A44CFA8C40236FE5CB32BB2EE267C7EE2E2028D1E455B5FC3BAE9EFB53E91A457033133C4BB25162EBCF8E5Eblatta/lib/client.py(6 . 6)(6 . 8)
50 import os
51 import base64
52 import traceback
53 import logging
54 from lib.state import State
55 from lib.message import Message
56 from lib.server import VERSION
57 from funcs import *
(22 . 6)(24 . 7)
59
60 def __init__(self, server, socket):
61 self.server = server
62 self.state = State.get_instance()
63 self.socket = socket
64 self.channels = {} # irc_lower(Channel name) --> Channel
65 self.nickname = None
(37 . 15)(40 . 11)
67 else:
68 self.__handle_command = self.__registration_handler
69
70 def is_addressed_to_me(self, message):
71 command = self.__parse_udp_message(message)
72 if command[0] == 'PRIVMSG':
73 if command[1][0][0] == '#' or command[1][0] == self.nickname:
74 return True
75 else:
76 return False
77 else:
78 return True
79 def message_from_station(self, msg):
80 targetname = self.server.channel_name if msg.command == BROADCAST else self.nickname
81 pest_prefix = msg.prefix if msg.prefix else msg.speaker
82 formatted_message = ":%s PRIVMSG %s :%s" % (pest_prefix, targetname, msg.body)
83 self.__writebuffer += formatted_message + "\r\n"
84
85 def get_prefix(self):
86 return "%s" % (self.nickname)
(68 . 30)(67 . 6)
88 def write_queue_size(self):
89 return len(self.__writebuffer)
90
91 def __parse_udp_message(self, message):
92 data = " ".join(message.split()[1:]) + "\r\n"
93 lines = self.__linesep_regexp.split(data)
94 lines = lines[:-1]
95 commands = []
96 for line in lines:
97 if not line:
98 # Empty line. Ignore.
99 continue
100 x = line.split(" ", 1)
101 command = x[0].upper()
102 if len(x) == 1:
103 arguments = []
104 else:
105 if len(x[1]) > 0 and x[1][0] == ":":
106 arguments = [x[1][1:]]
107 else:
108 y = string.split(x[1], " :", 1)
109 arguments = string.split(y[0])
110 if len(y) == 2:
111 arguments.append(y[1])
112 commands.append([command, arguments])
113 return commands[0]
114
115 def __parse_read_buffer(self):
116 lines = self.__linesep_regexp.split(self.__readbuffer)
117 self.__readbuffer = lines[-1]
(159 . 7)(134 . 6)
119 % self.nickname)
120 self.reply("004 %s :%s blatta-%s o o"
121 % (self.nickname, server.name, VERSION))
122 self.send_lusers()
123 self.send_motd()
124 self.__handle_command = self.__command_handler
125
(182 . 32)(156 . 20)
127 if arguments[0] == "0":
128 for (channelname, channel) in self.channels.items():
129 self.message_channel(channel, "PART", channelname, True)
130 self.channel_log(channel, "left", meta=True)
131 server.remove_member_from_channel(self, channelname)
132 self.channels = {}
133 return
134 channelnames = arguments[0].split(",")
135 if len(arguments) > 1:
136 keys = arguments[1].split(",")
137 else:
138 keys = []
139 keys.extend((len(channelnames) - len(keys)) * [None])
140 for (i, channelname) in enumerate(channelnames):
141 for channelname in channelnames:
142 if irc_lower(channelname) in self.channels:
143 continue
144 if not valid_channel_re.match(channelname):
145 self.reply_403(channelname)
146 continue
147 channel = server.get_channel(channelname)
148 if channel.key is not None and channel.key != keys[i]:
149 self.reply(
150 "475 %s %s :Cannot join channel (+k) - bad key"
151 % (self.nickname, channelname))
152 continue
153 channel.add_member(self)
154 self.channels[irc_lower(channelname)] = channel
155 self.message_channel(channel, "JOIN", channelname, True)
156 self.channel_log(channel, "joined", meta=True)
157 if channel.topic:
158 self.reply("332 %s %s :%s"
159 % (self.nickname, channel.name, channel.topic))
(218 . 7)(180 . 7)
161 % (self.nickname,
162 channelname,
163 " ".join(sorted(x
164 for x in self.server.state.get_peer_handles()))))
165 for x in self.state.get_peer_handles()))))
166 self.reply("366 %s %s :End of NAMES list"
167 % (self.nickname, channelname))
168
(238 . 7)(200 . 7)
170 self.reply("323 %s :End of LIST" % self.nickname)
171
172 def lusers_handler():
173 self.send_lusers()
174 pass
175
176 def mode_handler():
177 if len(arguments) < 1:
(268 . 8)(230 . 6)
179 self.message_channel(
180 channel, "MODE", "%s +k %s" % (channel.name, key),
181 True)
182 self.channel_log(
183 channel, "set channel key to %s" % key, meta=True)
184 else:
185 self.reply("442 %s :You're not on that channel"
186 % targetname)
(279 . 8)(239 . 6)
188 self.message_channel(
189 channel, "MODE", "%s -k" % channel.name,
190 True)
191 self.channel_log(
192 channel, "removed channel key", meta=True)
193 else:
194 self.reply("442 %s :You're not on that channel"
195 % targetname)
(313 . 9)(271 . 6)
197 self.reply("432 %s %s :Erroneous Nickname"
198 % (self.nickname, newnick))
199 else:
200 for x in self.channels.values():
201 self.channel_log(
202 x, "changed nickname to %s" % newnick, meta=True)
203 oldnickname = self.nickname
204 self.nickname = newnick
205 server.client_changed_nickname(self, oldnickname)
(340 . 16)(295 . 23)
207 channel = server.get_channel(targetname)
208 self.message_channel(
209 channel, command, "%s :%s" % (channel.name, message))
210 self.channel_log(channel, message)
211 # send the channel message to peers as well
212 self.server.station.infosec.message(
213 Message(
214 {
215 "speaker": self.nickname,
216 "command": BROADCAST,
217 "bounces": 0,
218 "body": message
219 }))
220 else:
221 formatted_message = ":%s %s %s :%s" % (self.prefix, command, targetname, message)
222 self.server.peer_message(Message({
223 self.server.station.infosec.message(Message({
224 "speaker": self.nickname,
225 "handle": targetname,
226 "body": formatted_message,
227 "body": message,
228 "bounces": 0,
229 "command": DIRECT
230 }, self.server))
231 }))
232 if(client):
233 client.message(formatted_message)
234
(372 . 7)(334 . 6)
236 self.message_channel(
237 channel, "PART", "%s :%s" % (channelname, partmsg),
238 True)
239 self.channel_log(channel, "left (%s)" % partmsg, meta=True)
240 del self.channels[irc_lower(channelname)]
241 server.remove_member_from_channel(self, channelname)
242
(405 . 8)(366 . 6)
244 self.message_channel(
245 channel, "TOPIC", "%s :%s" % (channelname, newtopic),
246 True)
247 self.channel_log(
248 channel, "set topic to %r" % newtopic, meta=True)
249 else:
250 if channel.topic:
251 self.reply("332 %s %s :%s"
(464 . 17)(423 . 21)
253 def wot_handler():
254 if len(arguments) < 1:
255 # Display the current WOT
256 peers = self.server.state.get_peers()
257 peers = self.state.get_peers()
258 if len(peers) > 0:
259 for peer in peers:
260 self.pest_reply("%s %s:%s" % (string.join(peer.handles, ","), peer.address, peer.port))
261 if peer.address and peer.port:
262 address = "%s:%s" % (peer.address, peer.port)
263 else:
264 address = "<address not configured>"
265 self.pest_reply("%s %s" % (string.join(peer.handles, ","), address))
266 else:
267 self.pest_reply("WOT is empty")
268 elif len(arguments) == 1:
269 # Display all WOT data concerning the peer identified by HANDLE,
270 # including all known keys, starting with the most recently used, for that peer.
271 handle = arguments[0]
272 peer = self.server.state.get_peer_by_handle(handle)
273 peer = self.state.get_peer_by_handle(handle)
274 if peer:
275 self.pest_reply("keys:")
276 for key in peer.keys:
(488 . 7)(451 . 7)
278 def peer_handler():
279 if len(arguments) == 1:
280 try:
281 self.server.state.add_peer(arguments[0])
282 self.state.add_peer(arguments[0])
283 self.pest_reply("added new peer %s" % arguments[0])
284 self.message(":%s JOIN %s" % (arguments[0], self.server.channel_name))
285 except:
(499 . 11)(462 . 11)
287 def unpeer_handler():
288 if len(arguments) == 1:
289 try:
290 self.server.state.remove_peer(arguments[0])
291 self.state.remove_peer(arguments[0])
292 self.pest_reply("removed peer %s" % arguments[0])
293 self.message(":%s PART %s" % (arguments[0], self.server.channel_name))
294 except Exception, e:
295 self.server.print_debug(e)
296 logging.debug(e)
297 self.pest_reply("Error attempting to remove peer")
298 else:
299 self.pest_reply("Usage: UNPEER <HANDLE>")
(518 . 7)(481 . 7)
301 handle = arguments[0]
302 key = arguments[1]
303 try:
304 self.server.state.add_key(handle, key)
305 self.state.add_key(handle, key)
306 self.pest_reply("added key: %s" % key)
307 except:
308 self.pest_reply("Error attempting to add key")
(528 . 23)(491 . 23)
310 self.pest_reply("Usage: UNKEY <KEY>")
311 else:
312 try:
313 self.server.state.remove_key(arguments[0])
314 self.state.remove_key(arguments[0])
315 self.pest_reply("removed key: %s" % arguments[0])
316 except Exception, e:
317 self.pest_reply("Error attempting to remove key")
318 self.server.print_debug(e)
319 logging.debug(e)
320
321 def at_handler():
322 if len(arguments) == 0:
323 at = self.server.state.get_at()
324 at = self.state.get_at()
325 elif len(arguments) == 1:
326 handle = arguments[0]
327 at = self.server.state.get_at(handle)
328 at = self.state.get_at(handle)
329 elif len(arguments) == 2:
330 try:
331 handle, address = arguments
332 address_ip, port = string.split(address, ":")
333 self.server.state.update_address_table({"handle": handle,
334 self.state.update_at({"handle": handle,
335 "address": address_ip,
336 "port": port},
337 False)
(552 . 7)(515 . 7)
339 except Exception as ex:
340 self.pest_reply("Error attempting to update address table")
341 stack = traceback.format_exc()
342 print(stack)
343 logger.debug(stack)
344 return
345 elif len(arguments) > 2:
346 self.pest_reply("Usage: AT [<HANDLE>] [<ADDRESS>]")
(599 . 12)(562 . 12)
348 except KeyError:
349 self.reply("421 %s %s :Unknown command" % (self.nickname, command))
350 stack = traceback.format_exc()
351 print(stack)
352 logger.debug(stack)
353
354 def socket_readable_notification(self):
355 try:
356 data = self.socket.recv(2 ** 10)
357 self.server.print_debug(
358 logging.debug(
359 "[%s:%d] -> %r" % (self.host, self.port, data))
360 quitmsg = "EOT"
361 except socket.error as x:
(621 . 7)(584 . 7)
363 def socket_writable_notification(self):
364 try:
365 sent = self.socket.send(self.__writebuffer)
366 self.server.print_debug(
367 logging.debug(
368 "[%s:%d] <- %r" % (
369 self.host, self.port, self.__writebuffer[:sent]))
370 self.__writebuffer = self.__writebuffer[sent:]
(630 . 7)(593 . 7)
372
373 def disconnect(self, quitmsg):
374 self.message("ERROR :%s" % quitmsg)
375 self.server.print_info(
376 logging.info(
377 "Disconnected connection from %s:%s (%s)." % (
378 self.host, self.port, quitmsg))
379 self.socket.close()
(654 . 31)(617 . 8)
381
382 def message_channel(self, channel, command, message, include_self=False):
383 line = ":%s %s %s" % (self.prefix, command, message)
384 for client in channel.members:
385 if client != self or include_self:
386 client.message(line)
387 # send the channel message to peers as well
388 self.server.peer_message(
389 Message(
390 {
391 "speaker": self.nickname,
392 "command": BROADCAST,
393 "bounces": 0,
394 "body": line
395 }, self.server))
396
397 def channel_log(self, channel, message, meta=False):
398 if not self.server.logdir:
399 return
400 if meta:
401 format = "[%s] * %s %s\n"
402 else:
403 format = "[%s] <%s> %s\n"
404 timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
405 logname = channel.name.replace("_", "__").replace("/", "_")
406 fp = open("%s/%s.log" % (self.server.logdir, logname), "a")
407 fp.write(format % (timestamp, self.nickname, message))
408 fp.close()
409 if include_self:
410 self.message(line)
411
412 def message_related(self, msg, include_self=False):
413 clients = set()
(691 . 10)(631 . 6)
415 for client in clients:
416 client.message(msg)
417
418 def send_lusers(self):
419 self.reply("251 %s :There are %d users and 0 services on 1 server"
420 % (self.nickname, len(self.server.clients)))
421
422 def send_motd(self):
423 server = self.server
424 motdlines = server.get_motd_lines()