daily pastebin goal
55%
SHARE
TWEET

Untitled

a guest Jan 14th, 2018 53 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python
  2. #-*- coding: utf-8 -*-
  3.  
  4. import socket
  5. import threading
  6.  
  7. class BadWordsServer:
  8.     """Represent a server which is designed to filter "bad words"
  9.        from data which is send to the network, and then resend
  10.        the cleaned data to the client."""
  11.  
  12.     def __init__(self, bad_words, host='127.0.0.1', port=8000):
  13.         """bad_words: words to ban
  14.            host: host to use for the server
  15.            port: port to use for the server"""
  16.  
  17.         self.bad_words = bad_words
  18.         self.bad_replace = ['*' * len(x) for x in bad_words]
  19.  
  20.         self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  21.         self.s.bind((host, port))
  22.         self.s.listen(1)
  23.  
  24.     def serve(self, buf_size=1024, encoding='UTF-8'):
  25.         """Run the server. It can handle multiple connection concurrently.
  26.  
  27.            buf_size: size of the buffer to use for recieving data
  28.            encoding: encoding of input/output data"""
  29.  
  30.         while True:
  31.             conn, _ = self.s.accept()
  32.             threading.Thread(None, self.serve_one, None,\
  33.                              (conn, buf_size, encoding)).start()
  34.  
  35.     def serve_one(self, conn, buf_size=1024, encoding='UTF-8'):
  36.         """Serve only one connection. Close it recieve an empty data."""
  37.  
  38.         while True:
  39.             data = conn.recv(buf_size).decode(encoding)
  40.  
  41.             if not data:
  42.                 break
  43.  
  44.             print('Raw data:', data)
  45.             data = self.filter_bad_words(data)
  46.             print('Cleaned data:', data)
  47.             conn.send(bytes(data, encoding))
  48.  
  49.         conn.close()
  50.  
  51.     def filter_bad_words(self, data):
  52.         """Remove the "bad words" from data, and return the cleaned data."""
  53.  
  54.         for w, r in zip(self.bad_words, self.bad_replace):
  55.             data = data.replace(w, r)
  56.  
  57.         return data
  58.  
  59. class BadWordsClient:
  60.     """Represent a client which ask user for input, and which send that
  61.        data to a BadWordsServer for cleaning it. Once the client recieve
  62.        the cleaned data it prints it."""
  63.  
  64.     def __init__(self, host='127.0.0.1', port=8000):
  65.         """host: host of the server
  66.            port: port of the server"""
  67.  
  68.         self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  69.         self.s.connect((host, port))
  70.  
  71.     def run(self, buf_size=1024, encoding='UTF-8'):
  72.         """Ask the user for data, clean it through the BadWordsServer,
  73.            and then print the result.
  74.  
  75.            buf_size: size of the buffer to use for recieving data
  76.            encoding: encoding of input/output data"""
  77.  
  78.         while True:
  79.             data = input('Data to filter? ')
  80.  
  81.             if not data:
  82.                 break
  83.  
  84.             self.s.send(bytes(data, encoding))
  85.  
  86.             data = self.s.recv(buf_size).decode(encoding)
  87.             print('Cleaned data:', data)
  88.  
  89.         self.s.close()
  90.  
  91. if __name__ == '__main__':
  92.     import sys
  93.  
  94.     def yes_no(prompt, default_yes=True):
  95.         """Ask the user for a yes/no question.
  96.  
  97.            prompt: the question to ask
  98.            default_yes: the default choice is yes if True no otherwise
  99.  
  100.            Return True for yes, False for no"""
  101.  
  102.         y, n = 'y', 'n'
  103.  
  104.         if default_yes:
  105.             y = y.upper()
  106.         else:
  107.             n = n.upper()
  108.  
  109.         i = None
  110.  
  111.         while i not in ['', 'y', 'n']:
  112.             i = input('%s (%c/%c)? ' % (prompt, y, n)).lower()
  113.  
  114.         if i == '':
  115.             return default_yes
  116.         elif i == 'y':
  117.             return True
  118.         else:
  119.             return False
  120.  
  121.     def get_host_port():
  122.         """Ask the user for an host and a port, and return them."""
  123.  
  124.         host = input('host? ')
  125.         port = None
  126.  
  127.         while port == None:
  128.             try:
  129.                 port = int(input('port? '))
  130.             except ValueError:
  131.                 print('port should be an integer.', file=sys.stderr)
  132.  
  133.         return host, port
  134.  
  135.     arg_error = 'This program takes exactly one argument serve or client.'
  136.  
  137.     if len(sys.argv) != 2:
  138.         print(arg_error, file=sys.stderr)
  139.     elif sys.argv[1] == 'serve':
  140.         bad_words = ['fuck', 'shit', 'dumb']
  141.  
  142.         if yes_no('Would you like to serve on localhost:8000'):
  143.             host, port = 'localhost', 8000
  144.         else:
  145.             host, port = get_host_port()
  146.  
  147.         try:
  148.             BadWordsServer(bad_words, host, port).serve()
  149.         except socket.error as e:
  150.             print('Error occured:', e, file=sys.stderr)
  151.     elif sys.argv[1] == 'client':
  152.         if yes_no('Would you like to use localhost:8000 as server'):
  153.             host, port = 'localhost', 8000
  154.         else:
  155.             host, port = get_host_port()
  156.  
  157.         try:
  158.             BadWordsClient(host, port).run()
  159.         except socket.error as e:
  160.             print('Error occured:', e, file=sys.stderr)
  161.     else:
  162.         print(arg_error, file=sys.stderr)
  163.  
  164. # Q4:
  165.  
  166. # One way of passing more information in a message, like encoding, language
  167. # or degree of cleaning would be to use "headers" in the message, the first
  168. # one would be the encoding, followed by (for instance) a semicolon, then
  169. # the language followed by a semicolon, then the degree of cleaning followed
  170. # by a semicolon and finally the message.
  171.  
  172. # e.g.
  173. # UTF-8;french;moderate;<the actual message>
  174.  
  175. # the encoding and first semicolon should be in UTF-8 to be sure that it
  176. # will be well undestand by the server, all the following data in the
  177. # message (including the two remaining semicolons) should be encoded
  178. # with the "new" encoding.
RAW Paste Data
Top