Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- #-*- coding: utf-8 -*-
- import socket
- import threading
- class BadWordsServer:
- """Represent a server which is designed to filter "bad words"
- from data which is send to the network, and then resend
- the cleaned data to the client."""
- def __init__(self, bad_words, host='127.0.0.1', port=8000):
- """bad_words: words to ban
- host: host to use for the server
- port: port to use for the server"""
- self.bad_words = bad_words
- self.bad_replace = ['*' * len(x) for x in bad_words]
- self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.s.bind((host, port))
- self.s.listen(1)
- def serve(self, buf_size=1024, encoding='UTF-8'):
- """Run the server. It can handle multiple connection concurrently.
- buf_size: size of the buffer to use for recieving data
- encoding: encoding of input/output data"""
- while True:
- conn, _ = self.s.accept()
- threading.Thread(None, self.serve_one, None,\
- (conn, buf_size, encoding)).start()
- def serve_one(self, conn, buf_size=1024, encoding='UTF-8'):
- """Serve only one connection. Close it recieve an empty data."""
- while True:
- data = conn.recv(buf_size).decode(encoding)
- if not data:
- break
- print('Raw data:', data)
- data = self.filter_bad_words(data)
- print('Cleaned data:', data)
- conn.send(bytes(data, encoding))
- conn.close()
- def filter_bad_words(self, data):
- """Remove the "bad words" from data, and return the cleaned data."""
- for w, r in zip(self.bad_words, self.bad_replace):
- data = data.replace(w, r)
- return data
- class BadWordsClient:
- """Represent a client which ask user for input, and which send that
- data to a BadWordsServer for cleaning it. Once the client recieve
- the cleaned data it prints it."""
- def __init__(self, host='127.0.0.1', port=8000):
- """host: host of the server
- port: port of the server"""
- self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.s.connect((host, port))
- def run(self, buf_size=1024, encoding='UTF-8'):
- """Ask the user for data, clean it through the BadWordsServer,
- and then print the result.
- buf_size: size of the buffer to use for recieving data
- encoding: encoding of input/output data"""
- while True:
- data = input('Data to filter? ')
- if not data:
- break
- self.s.send(bytes(data, encoding))
- data = self.s.recv(buf_size).decode(encoding)
- print('Cleaned data:', data)
- self.s.close()
- if __name__ == '__main__':
- import sys
- def yes_no(prompt, default_yes=True):
- """Ask the user for a yes/no question.
- prompt: the question to ask
- default_yes: the default choice is yes if True no otherwise
- Return True for yes, False for no"""
- y, n = 'y', 'n'
- if default_yes:
- y = y.upper()
- else:
- n = n.upper()
- i = None
- while i not in ['', 'y', 'n']:
- i = input('%s (%c/%c)? ' % (prompt, y, n)).lower()
- if i == '':
- return default_yes
- elif i == 'y':
- return True
- else:
- return False
- def get_host_port():
- """Ask the user for an host and a port, and return them."""
- host = input('host? ')
- port = None
- while port == None:
- try:
- port = int(input('port? '))
- except ValueError:
- print('port should be an integer.', file=sys.stderr)
- return host, port
- arg_error = 'This program takes exactly one argument serve or client.'
- if len(sys.argv) != 2:
- print(arg_error, file=sys.stderr)
- elif sys.argv[1] == 'serve':
- bad_words = ['fuck', 'shit', 'dumb']
- if yes_no('Would you like to serve on localhost:8000'):
- host, port = 'localhost', 8000
- else:
- host, port = get_host_port()
- try:
- BadWordsServer(bad_words, host, port).serve()
- except socket.error as e:
- print('Error occured:', e, file=sys.stderr)
- elif sys.argv[1] == 'client':
- if yes_no('Would you like to use localhost:8000 as server'):
- host, port = 'localhost', 8000
- else:
- host, port = get_host_port()
- try:
- BadWordsClient(host, port).run()
- except socket.error as e:
- print('Error occured:', e, file=sys.stderr)
- else:
- print(arg_error, file=sys.stderr)
- # Q4:
- # One way of passing more information in a message, like encoding, language
- # or degree of cleaning would be to use "headers" in the message, the first
- # one would be the encoding, followed by (for instance) a semicolon, then
- # the language followed by a semicolon, then the degree of cleaning followed
- # by a semicolon and finally the message.
- # e.g.
- # UTF-8;french;moderate;<the actual message>
- # the encoding and first semicolon should be in UTF-8 to be sure that it
- # will be well undestand by the server, all the following data in the
- # message (including the two remaining semicolons) should be encoded
- # with the "new" encoding.
Add Comment
Please, Sign In to add comment