Sunday, February 20, 2011

Software for CUPS, Host headers, NAT'd access and workarounds

Here is what I promised earlier. It's got all sort of caveat written all over it, but it seems to work.
Comments welcome!

This software is totally freeware and I'm not responsible for anything you do or don't do with it, any problems it causes or solutions it brings, etc...





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
#! /usr/bin/python
import sys
import os
import getopt
import BaseHTTPServer
import httplib

class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
  def do_GET(self):
    conn = httplib.HTTPConnection("localhost:631")
    conn._http_vsn_str = 'HTTP/1.0'
    conn.putrequest(self.command, self.path)
    for h in self.headers:
      if h.lower() == 'connection':
        v = 'close'
      elif h.lower() == 'host':
        continue
      else:
        v = self.headers[h]
      conn.putheader(h, v)
    conn.endheaders()
    # copy payload, only for POST
    if self.command == 'POST':
      content_length = int(self.headers['content-length'])
      remaining = content_length
      while remaining > 0:
        data = self.rfile.read( min(4096, remaining) )
        if not data:
          break
        conn.send(data)
        remaining -= len(data)
    self.rfile.close()
    resp = conn.getresponse()
    if resp.version == 11:
      http_version = 'HTTP/1.1'
    elif resp.version == 10:
      http_version = 'HTTP/1.0'
    else:
      raise ValueError
    self.wfile.write( http_version + ' ' + str(resp.status) + ' ' + resp.reason + '\n' )
    self.wfile.write( str(resp.msg) )
    self.wfile.write( '\n' )
    datalen = 0
    while True:
      data = resp.read( 4096 )
      if not data:
        break
      datalen += len(data)
      self.wfile.write(data)
    conn.close()
    self.wfile.close()
    if datalen:
      self.log_request(resp.status, datalen)
    else:
      self.log_request(resp.status)

  def do_POST(self):
    return self.do_GET()

def run(server_class=BaseHTTPServer.HTTPServer, handler_class=Handler):
  (optlist, args) = getopt.getopt( sys.argv[1:], 'dp:', [ 'no-daemon', 'port=' ] )
  daemonize = True
  port = 6310
  for (o,arg) in optlist:
    if o in [ '-d', '--no-daemon' ]:
      daemonize = False
    elif o in [ '-p', '--port' ]:
      port = int(arg)

  # FIXME: add parsing for listen addresses and ports, etc....
  if daemonize:
    pid = os.fork()
    if pid == 0:
      # child
      os.setsid()
      pid2 = os.fork()
      if pid2 == 0:
        # second child
        pass
      else:
        os._exit(0)
    else:
      os._exit(0)

  server_address = ('127.0.0.1', port )
  httpd = server_class(server_address, handler_class)
  httpd.serve_forever()

def main():
  run()

if __name__ == '__main__':
  main()

2 comments:

D. Brooks said...

Thank you so much. That script was a lifesaver! <3

What I want to know is why the heck the cups developers institute such an utterly pointless 'security' feature in the first place.. and _hard-code_ it, no less!?

Anonymous said...

nice idea1! thanks!!
but how do I install/run it.
it must be like a daemon ... but
some some install instructions please?