download fproxyproxy.py
Language: Python
LOC: 307
Project Info
Freenet
Server: FreenetProject.org
Type: svn
...t\trunk\apps\pyFreenet\fcp\
   __init__.py
   fproxyproxy.py
   freenetfs.py
   genkey.py
   get.py
   invertkey.py
   names.py
   node.py
   put.py
   redirect.py
   sitemgr.py
   xmlobject.py
   xmlrpc.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#@+leo-ver=4
#@+node:@file fproxyproxy.py
"""
fproxyproxy

An http proxy atop fproxy which uses pyfcp's 'name services'
"""

#@+others
#@+node:imports
import sys, os, getopt, traceback, mimetypes, time
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
from SocketServer import ThreadingMixIn
from httplib import HTTPConnection
import socket

import node
from node import ERROR, INFO, DETAIL, DEBUG

#@-node:imports
#@+node:globals
progname = sys.argv[0]

#@-node:globals
#@+node:class Handler
class Handler(SimpleHTTPRequestHandler):
    """
    Handles each FProxyProxy client request
    """
    #@    @+others
    #@+node:__init__
    def __init__(self, request, client_address, server):
        
        self.server = server
        SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
    
    #@-node:__init__
    #@+node:do_GET
    def do_GET(self):
        
        print "GET: client=%s path=%s" % (self.client_address, self.path)
    
        #SimpleHTTPRequestHandler.do_GET(self)
    
        try:
            #mimetype, data = self.server.node.get(self.path[1:])
            #self.send_response(200)
            #self.send_header("Content-type", mimetype)
            #self.send_header("Content-Length", str(len(data)))
            #self.end_headers()
            #self.wfile.write(data)
            #self.wfile.flush()
    
            self.fproxyGet(self.path)
    
        except:
            traceback.print_exc()
            self.send_error(404, "File not found")
            return None
    
    #@-node:do_GET
    #@+node:fproxyGet
    def fproxyGet(self, path):
        """
        Fetches from fproxy, returns (status, mimetype, data)
        """
        server = self.server
        headers = self.headers
    
        print "--------------------------------------------"
        print "** path=%s" % path
    
        # first scenario - user is pointing their browser directly at
        # fproxyfproxy, barf!
        if not path.startswith("http://"):
            self.send_response(400)
            self.send_header("Content-type", "text/html")
            data = "\n".join([
                "<html><head>",
                "<title>Access Denied</title>",
                "</head><body>",
                "<h1>Access Denied</h1>",
                "Sorry, but FProxyProxy is an http proxy server.<br>",
                "Please don't try to access it like a web server.",
                "</body></html>",
                "",
                ])
            self.send_header("Content-Length", str(len(data)))
            self.send_header("Location", location)
            self.end_headers()
            self.wfile.write(data)
            self.wfile.flush()
            return
    
        # convert path to relative
        path = "/" + path[7:].split("/", 1)[-1]
        #print "** path=%s" % repr(path)
    
    
        try:
            # check host header
            hostname = headers.get("Host", 'fproxy')
            pathbits = path.split("/")
    
            print "** hostname = %s" % hostname
    
            # second scenario, user has just given a domain name without trailing /
            if len(pathbits) == 1:
                # redirect to force trailing slash
                location = path + "/"
                print "** redirecting to: %s" % location
    
                self.send_response(301)
                self.send_header("Content-type", "text/html")
                data = "\n".join([
                    "<html><head>",
                    "<title>Permanent redirect: new URI</title>",
                    "</head><body>",
                    "<h1>Permanent redirect: new URI</h1>",
                    "<a href=\"%s\">Click here</a>",
                    "</body></html>",
                    "",
                    ]) % location
                self.send_header("Content-Length", str(len(data)))
                self.send_header("Location", location)
                self.end_headers()
                self.wfile.write(data)
                self.wfile.flush()
                return
    
            tail = "/".join(pathbits[1:])
    
            # third scenario - request into fproxy
            if hostname == 'fproxy':
    
                # tis an fproxy request, go straight through
                conn = HTTPConnection(server.fproxyHost, server.fproxyPort)
                conn.request("GET", path)
                resp = conn.getresponse()
                self.send_response(resp.status)
                self.send_header("Content-type",
                                 resp.getheader("Content-Type", "text/plain"))
                data = resp.read()
                self.send_header("Content-Length", str(len(data)))
                self.end_headers()
                self.wfile.write(data)
                self.wfile.flush()
                conn.close()
                return
    
            else:
                # final scenario - some other domain, try lookup
                uri = server.node.namesiteLookup(hostname)
    
                if not uri:
                    # lookup failed, do the usual 404 thang
                    print "** lookup of domain %s failed" % hostname
                    self.send_response(404)
                    self.send_header("Content-type", "text/html")
                    data = "\n".join([
                        "<html><head>",
                        "<title>404 - Freenet name not found</title>",
                        "</head><body",
                        "<h1>404 - Freenet name not found</title>",
                        "The pyfcp name service was unable to resolve ",
                        "the name %s" % hostname,
                        "<br><br>",
                        "You might like to find its freenet uri and try that ",
                        "within <a href=\"/fproxy/\">FProxy</a>",
                        "</body></html>",
                        "",
                        ])
                    self.send_header("Content-Length", str(len(data)))
                    self.end_headers()
                    self.wfile.write(data)
                    self.wfile.flush()
    
                # lookup succeeded - ok to go now via fproxy
                conn = HTTPConnection(server.fproxyHost, server.fproxyPort)
                newpath = "/" + uri
                if tail:
                    if not newpath.endswith("/"):
                        newpath += "/"
                    newpath += tail
                print "** newpath=%s" % newpath
                conn.request("GET", newpath)
                resp = conn.getresponse()
                print "** status=%s" % resp.status
                self.send_response(resp.status)
                self.send_header("Content-type",
                                 resp.getheader("Content-Type", "text/plain"))
    
                # has fproxy sent us a redirect?
                if resp.status == 301:
                    # yuck, fproxy is telling us to redirect, which
                    # sadly means we have to lose the domain name
                    # from our browser address bar
                    location = resp.getheader("location")
                    newLocation = "http://fproxy" + location
                    print "*** redirected!!!"
                    print "*** old location = %s" % location
                    print "***  --> %s" % newLocation
                    self.send_header("Location", newLocation)
    
                # get the data from fproxy and send it up to the client
                data = resp.read()
                self.send_header("Content-Length", str(len(data)))
                self.end_headers()
                self.wfile.write(data)
                self.wfile.flush()
                conn.close()
                return
    
            return
    
        except socket.error:
            raise
    
    #@-node:fproxyGet
    #@-others

#@-node:class Handler
#@+node:class FProxyProxy
class FProxyProxy(ThreadingMixIn, HTTPServer):
    """
    an http proxy that runs atop fproxy, and uses the pyfcp name service
    """
    #@    @+others
    #@+node:__init__
    def __init__(self, **kw):
        """
        runs the FProxyProxy service
        
        Keywords:
            - node - a live FCPNode object
            - fproxyHost - hostname of fproxy
            - fproxyPort - port of fproxy
            - listenHost - hostname to listen on for client HTTP connections
            - listenPort - port to listen on for client HTTP connections
        """
        for k in ['node', 'fproxyHost', 'fproxyPort', 'listenHost', 'listenPort']:
            setattr(self, k, kw[k])
    
        self.log = self.node._log
    
        HTTPServer.__init__(self, (self.listenHost, self.listenPort), Handler)
    
    #@-node:__init__
    #@+node:run
    def run(self):
        """
        Starts the proxy, runs forever till interrupted
        """
        log = self.log
        log(ERROR, "FproxyProxy listening on %s:%s" % (self.listenHost, self.listenPort))
        log(ERROR, "  -> forwarding requests to fproxy at %s:%s" % (
                    self.fproxyHost, self.fproxyPort))
    
        self.serve_forever()
    
    #@-node:run
    #@-others

#@-node:class FProxyProxy
#@+node:usage
def usage(msg=None, ret=1):
    """
    Prints usage message then exits
    """
    if msg:
        sys.stderr.write(msg+"\n")
    sys.stderr.write("Usage: %s [options] src-uri target-uri\n" % progname)
    sys.stderr.write("Type '%s -h' for help\n" % progname)
    sys.exit(ret)

#@-node:usage
#@+node:help
def help():
    """
    print help options, then exit
    """
    print "%s: runs an http proxy atop fproxy,"  % progname
    print "which uses pyfcp 'name services'"
    print
    print "Note - you should configure fproxyproxy as an http proxy"
    print "in your browser (best done via Firefox's 'switchproxy' extension"
    print
    print "Usage: %s [options] src-uri target-uri" % progname
    print
    print "Options:"
    print "  -h, -?, --help"
    print "     Print this help message"
    print "  -v, --verbose"
    print "     Print verbose progress messages to stderr"
    print "  -H, --fcpHost=<hostname>"
    print "     Connect to FCP service at host <hostname>"
    print "  -P, --fcpPort=<portnum>"
    print "     Connect to FCP service at port <portnum>"
    print "  -p, --fproxyAddress=[<hostname>][:<portnum>]"
    print "     Use fproxy service at <hostname>:<portnum>,"
    print "     default 127.0.0.1:8888"
    print "  -L, --listenAddress=[<hostname>][:<portnum>]"
    print "     Listen for http connections on <hostname>:<portnum>,"
    print "     default is 127.0.0.1:8889"
    print "  -V, --version"
    print "     Print version number and exit"
    print
    print "Environment:"
    print "  Instead of specifying -H and/or -P, you can define the environment"
    print "  variables FCP_HOST and/or FCP_PORT respectively"

    sys.exit(0)

#@-node:help
#@+node:main
def main():
    """
    Front end for fproxyproxy utility
    """
    # default job options
    verbosity = node.ERROR
    verbose = False
    fcpHost = node.defaultFCPHost
    fcpPort = node.defaultFCPPort
    fproxyHost = os.environ.get("FPROXY_HOST", "127.0.0.1")
    fproxyPort = int(os.environ.get("FPROXY_PORT", 8888))
    listenHost = os.environ.get("FPROXYPROXY_HOST", "127.0.0.1")
    listenPort = int(os.environ.get("FPROXYPROXY_PORT", 8889))

    opts = {
            "Verbosity" : 0,
            }

    # process command line switches
    try:
        cmdopts, args = getopt.getopt(
            sys.argv[1:],
            "?hvH:P:Vp:L:",
            ["help", "verbose", "fcpHost=", "fcpPort=", "version",
             "listenAddress=", "fproxyAddress=",
             ]
            )
    except getopt.GetoptError:
        # print help information and exit:
        usage()
        sys.exit(2)
    output = None
    verbose = False
    #print cmdopts
    for o, a in cmdopts:

        if o in ("-?", "-h", "--help"):
            help()

        if o in ("-V", "--version"):
            print "This is %s, version %s" % (progname, node.fcpVersion)
            sys.exit(0)

        if o in ("-v", "--verbosity"):
            verbosity = node.DETAIL
            opts['Verbosity'] = 1023
            verbose = True

        if o in ("-H", "--fcpHost"):
            fcpHost = a
        
        if o in ("-P", "--fcpPort"):
            try:
                fcpPort = int(a)
            except:
                usage("Invalid fcpPort argument %s" % repr(a))

        if o in ("-L", "--listenAddress"):
            parts = a.split(":")
            if len(parts) == 1:
                listenHost = parts[0]
            elif len(parts) == 2:
                if parts[0]:
                    listenHost = parts[0]
                if parts[1]:
                    listenPort = int(parts[1])
            else:
                usage("Invalid listen address '%s'" % a)

        if o in ("-p", "--fproxyAddress"):
            parts = a.split(":")
            if len(parts) == 1:
                fproxyHost = parts[0]
            elif len(parts) == 2:
                if parts[0]:
                    fproxyHost = parts[0]
                if parts[1]:
                    fproxyPort = int(parts[1])
            
    # try to create an FCP node, needed for name lookups
    try:
        n = node.FCPNode(host=fcpHost, port=fcpPort, verbosity=verbosity,
                         logfile=sys.stderr)
        log = n._log
    except:
        if verbose:
            traceback.print_exc(file=sys.stderr)
        usage("Failed to connect to FCP service at %s:%s" % (fcpHost, fcpPort))

    try:
        proxy = FProxyProxy(
                    node=n,
                    fproxyHost=fproxyHost, fproxyPort=fproxyPort,
                    listenHost=listenHost, listenPort=listenPort)
        proxy.run()
        sys.exit(0)
    except KeyboardInterrupt:
        print "fproxyproxy terminated by user"
        n.shutdown()
        sys.exit(0)
    except:
        traceback.print_exc()
        print "fproxyproxy terminated"
        n.shutdown()
        sys.exit(1)

#@-node:main
#@-others

#@-node:@file fproxyproxy.py
#@-leo

About Koders | Resources | Downloads | Support | Black Duck | Submit Project | Terms of Service | DMCA | Privacy Policy | Site Map| Contact Us