mkv

nibblenet

mkv
Mar 3rd, 2014
349
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.59 KB | None | 0 0
  1. #!/usr/bin/env python
  2. """nibblenet.py: Telnet Nibbles Server"""
  3. __version__   = "1.0"
  4. __author__    = "ed <irc.rizon.net>"
  5. __license__   = "BSD"
  6. __copyright__ = 2014
  7.  
  8. import re
  9. import os
  10. import sys
  11. import time
  12. import collections
  13. import asyncore
  14. import socket
  15. import threading
  16.  
  17. PASSWORD = 'hinamizawa'
  18. ENABLE_AUTH = False
  19. MSG_LEN = 512
  20.  
  21.  
  22.  
  23. class Printer:
  24.    
  25.     def __init__(self):
  26.         self.mutex = threading.Lock()
  27.    
  28.     def p(self, data, usercount=None):
  29.         with self.mutex:
  30.             if len(data) < 13:
  31.                 data += ' ' * 13
  32.             if usercount:
  33.                 sys.stdout.write('%s\n     %d users\r' % (data, usercount))
  34.             else:
  35.                 sys.stdout.write('%s\n' % (data,))
  36.             sys.stdout.flush()
  37.  
  38. def fmt():
  39.     return time.strftime('%d/%m/%Y, %H:%M:%S')
  40.  
  41. def num(c):
  42.     try:
  43.         return int(c)
  44.     except:
  45.         return None
  46.  
  47.  
  48.  
  49. class RemoteClient(asyncore.dispatcher):
  50.    
  51.     def __init__(self, host, socket, address):
  52.         asyncore.dispatcher.__init__(self, socket)
  53.         self.host = host
  54.         self.socket = socket
  55.         self.authed = not ENABLE_AUTH
  56.         self.esc = 0
  57.         self.inbox = ''
  58.         self.commands = []
  59.         self.outbox = collections.deque()
  60.         self.replies = collections.deque()
  61.         self.input_mode = None
  62.         self.w = None
  63.         self.h = None
  64.    
  65.     def say(self, message):
  66.         if self.input_mode is None:
  67.             self.outbox.append(message)
  68.    
  69.     def reply(self, message):
  70.         self.replies.append(message.replace('\r', '').replace('\n', '\r\n'))
  71.    
  72.     def handle_read(self):
  73.         data = self.recv(MSG_LEN)
  74.         if not data:
  75.             self.host.part(self)
  76.        
  77.         elif not self.authed:
  78.             if data[:len(PASSWORD)] == PASSWORD:
  79.                 host.con('@  ', self.addr)
  80.                 self.authed = True
  81.                 self.send_title()
  82.             else:
  83.                 host.con('~  ', self.addr)
  84.        
  85.         elif len(data) > MSG_LEN or len(self.inbox) > MSG_LEN:
  86.             self.inbox = ''
  87.        
  88.         else:
  89.             self.inbox += data
  90.             if self.input_mode == 'i':
  91.                 m = re.search(r'\033\133(.*);(.*)R.*\012', self.inbox)
  92.                 if m:
  93.                     self.reply('\033[?25h\033[0m\033[H\033[J\n\033[H')
  94.                     self.w = num(m.group(2))
  95.                     self.h = num(m.group(1)) + 1
  96.                     self.reply('%dx%d' % (self.w, self.h))
  97.                     self.input_mode = None
  98.                     self.inbox = ''
  99.            
  100.             if self.input_mode != None:
  101.                 return
  102.            
  103.             commands = []
  104.             while len(self.inbox) > 0:
  105.                 c = ord(self.inbox[0:1])
  106.                 self.inbox = self.inbox[1:]
  107.                 esc = self.esc
  108.                
  109.                 if   c == 27:                         esc = 1
  110.                 elif esc == 1 and c == 91:            esc = 2
  111.                 elif esc == 2 and c > 64 and c < 69:  esc = 3
  112.                 else:                                 esc = 0
  113.                
  114.                 self.esc = esc
  115.                 if esc == 3:
  116.                     if    c == 65: commands.append('u')
  117.                     elif  c == 66: commands.append('d')
  118.                     elif  c == 67: commands.append('r')
  119.                     elif  c == 68: commands.append('l')
  120.                     else: commands.append(str(c))
  121.                     esc = 0
  122.                
  123.                 elif esc == 0:
  124.                     if    c == 119 or c == 87: commands.append('u')
  125.                     elif  c == 115 or c == 83: commands.append('d')
  126.                     elif  c == 100 or c == 68: commands.append('r')
  127.                     elif  c ==  97 or c == 65: commands.append('l')
  128.                     elif  c ==  99 or c == 67: commands.append('color')
  129.                     else: commands.append(str(c))
  130.            
  131.             for c in commands:
  132.                 self.reply(c + '\n')
  133.    
  134.     def writable(self):
  135.         return self.replies or \
  136.             (self.outbox and self.input_mode is None )
  137.    
  138.     def handle_write(self):
  139.         if not self.writable():
  140.             return
  141.        
  142.         box = self.outbox
  143.         if self.replies:
  144.             box = self.replies
  145.        
  146.         message = box.popleft()
  147.         if self.authed:
  148.             sent = self.send(message)
  149.             if sent < len(message):
  150.                 box.appendleft(message[sent:])
  151.  
  152.  
  153.  
  154. class Host(asyncore.dispatcher):
  155.    
  156.     def __init__(self, p, address=('localhost', 0)):
  157.         asyncore.dispatcher.__init__(self)
  158.         self.p = p
  159.         self.stdin = False
  160.         self.filename = None
  161.         self.remote_clients = []
  162.         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  163.         self.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  164.         self.bind(address)
  165.         self.listen(1)
  166.    
  167.     def con(self, msg, adr, cli=None):
  168.         if (cli is None):
  169.             cli = len(self.remote_clients)
  170.         msg = ' %s %s - %s :%s' % (msg, fmt(), adr[0], adr[1])
  171.         self.p.p(msg, cli)
  172.    
  173.     def handle_accept(self):
  174.         socket, addr = self.accept()
  175.         self.con(' ++', addr, len(self.remote_clients) + 1)
  176.         remote = RemoteClient(self, socket, addr)
  177.         self.remote_clients.append(remote)
  178.         remote.input_mode = 'i'
  179.         remote.reply("""
  180.  
  181.   --==[ nibblenet ]==--
  182.  
  183.   To enable unbuffered input,
  184.   run this command before connecting:
  185.  
  186.      stty -icanon
  187.  
  188.   Play with WASD or Arrows
  189.  
  190.   Enable colors with C
  191.  
  192.   Press [ENTER] to Continue
  193.  
  194.  
  195. \033[?25l\033[8m\033[200;400H\033[A\033[6n""")
  196.    
  197.     def handle_read(self):
  198.         self.recv(MSG_LEN)
  199.    
  200.     def broadcast(self, message):
  201.         for remote_client in self.remote_clients:
  202.             #if remote_client.input_mode is None:
  203.             remote_client.say(message)
  204.    
  205.     def part(self, remote):
  206.         self.remote_clients.remove(remote)
  207.         self.con('  -', remote.addr)
  208.         raise asyncore.ExitNow('rebooting')
  209.  
  210.  
  211.  
  212. if __name__ == '__main__':
  213.    
  214.     if len(sys.argv) != 2:
  215.         print
  216.         print '  Usage:  %s  port' % sys.argv[0]
  217.         print
  218.         sys.exit(1)
  219.    
  220.     print " -!- %s" % fmt()
  221.     p = Printer()
  222.    
  223.     p.p(" -!- Binding")
  224.     host = Host(p, ('0.0.0.0', int(sys.argv[1])))
  225.    
  226.     p.p(" -!- Listening")
  227.     try:
  228.         asyncore.loop(0.05)
  229.     except Exception:
  230.         print
  231.         host.close()
  232.         sys.exit(0)
  233.         #os.execl(sys.executable, *([sys.executable]+sys.argv))
Advertisement
Add Comment
Please, Sign In to add comment