Guest User

Untitled

a guest
Jan 14th, 2018
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.32 KB | None | 0 0
  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.
Add Comment
Please, Sign In to add comment