""" winky_proxy.py inspired by SUZUKI Hisao changed to use urllib2 instead of a raw socket copyrighted by winky released under GPL or LGPL """ import BaseHTTPServer,SocketServer import urllib,urllib2 import urlparse import cgi import re encrypt_start_tag = "" encrypt_end_tag = "" encrypt_start_tag_q = cgi.escape(encrypt_start_tag) encrypt_end_tag_q = cgi.escape(encrypt_end_tag) def encrypt(buffer): result = [] for ch in buffer : enc = "%2X" % (ord(ch)) result.append(enc.replace(" ","0")) return "".join(result) def decrypt(buffer): result = [] for i in range(0,len(buffer),2): enc = buffer[i:i+2] ch = chr(int(enc,16)) result.append(ch) return "".join(result) re_encrypt = re.compile(encrypt_start_tag+"(.*?)"+encrypt_end_tag,re.DOTALL) def encode_buffer(buffer): enc_buffer = "" end_pos = 0 for m in re_encrypt.finditer(buffer) : enc_buffer += buffer[end_pos:m.start(1)] enc_buffer += encrypt(buffer[m.start(1):m.end(1)]) end_pos = m.end(1) return enc_buffer + buffer[end_pos:] reg_decrypt = "(%s|%s)(.*?)(%s|%s)" re_decrypt = re.compile(reg_decrypt % ( encrypt_start_tag, encrypt_start_tag_q, encrypt_end_tag, encrypt_end_tag_q, ),re.DOTALL) def decode_buffer(buffer): dec_buffer = "" end_pos = 0 for m in re_decrypt.finditer(buffer): dec_buffer += buffer[end_pos:m.start(2)] dec_buffer += decrypt(buffer[m.start(2):m.end(2)]) end_pos = m.end(2) return dec_buffer + buffer[end_pos:] class ProxyHandler (BaseHTTPServer.BaseHTTPRequestHandler): __base = BaseHTTPServer.BaseHTTPRequestHandler __base_handle = __base.handle def handle(self): (ip, port) = self.client_address if hasattr(self, 'allowed_clients') and ip not in self.allowed_clients: self.raw_requestline = self.rfile.readline() if self.parse_request(): self.send_error(403) else: self.__base_handle() def _GET_POST(self,pageUrl,data=None): if data : request = urllib2.Request(url=pageUrl,data=data) else : request = urllib2.Request(url=pageUrl) request.add_header('User-agent', 'Mozilla/5.0') try : page = urllib2.urlopen(request) except urllib2.HTTPError, Error : self.send_error(400, "http error") return except urllib2.URLError, Error : self.send_error(400, "address not found") return page_body = page.read() page_body = decode_buffer(page_body) page.headers.dict['Content-Length'] = str(len(page_body)) self.send_response(page.code,page.msg) try : del page.headers.dict['transfer-encoding'] except KeyError : pass for key,value in page.headers.dict.items() : self.send_header(key,value) self.end_headers() self.wfile.write(page_body) def do_GET(self): (scm, netloc, path, query, fragment) = urlparse.urlsplit(self.path, 'http') if scm != 'http' or fragment or not netloc: self.send_error(400, "bad url %s" % self.path) return pageUrl = urlparse.urlunsplit((scm, netloc, path, query, fragment)) self._GET_POST(pageUrl) def do_POST(self): query_str = self.rfile.read(int(self.headers['Content-Length'])) query_dict = cgi.parse_qs(query_str) (scm, netloc, path, query, fragment) = urlparse.urlsplit(self.path, 'http') if scm != 'http' or fragment or not netloc: self.send_error(400, "bad url %s" % self.path) return pageUrl = urlparse.urlunsplit((scm, netloc, path, query, fragment)) if query_dict.has_key("content") : query_dict["content"] = [encode_buffer(query_dict["content"][0])] query_post = urllib.urlencode(query_dict,True) self._GET_POST(pageUrl,query_post) do_HEAD = do_GET do_PUT = do_GET do_DELETE=do_GET class ThreadingHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): pass def main() : from sys import argv if argv[1:] and argv[1] in ('-h', '--help'): print argv[0], "[port [allowed_client_name ...]]" else: if argv[2:]: allowed = [] for name in argv[2:]: client = socket.gethostbyname(name) allowed.append(client) print "Accept: %s (%s)" % (client, name) ProxyHandler.allowed_clients = allowed del argv[2:] else: print "Any clients will be served..." proxy = ThreadingHTTPServer(("127.0.0.1",8000), ProxyHandler) proxy.serve_forever() if __name__ == '__main__': import sys try: main() except KeyboardInterrupt : sys.exit(0)