Strip the Tribune notice from the descriptions.
[pyTivo/wgw.git] / httpserver.py
blob0a7e73e718b2361e69f4b3afb454276a25d61ab0
1 import time, os, BaseHTTPServer, SocketServer, socket, re
2 from urllib import unquote_plus, quote, unquote
3 from urlparse import urlparse
4 from cgi import parse_qs
5 from Cheetah.Template import Template
6 from plugin import GetPlugin
7 import config
8 from xml.sax.saxutils import escape
9 import logging
11 SCRIPTDIR = os.path.dirname(__file__)
13 hack83 = config.getHack83()
15 class TivoHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
16 containers = {}
18 def __init__(self, server_address, RequestHandlerClass):
19 BaseHTTPServer.HTTPServer.__init__(self, server_address,
20 RequestHandlerClass)
21 self.daemon_threads = True
23 def add_container(self, name, settings):
24 if self.containers.has_key(name) or name == 'TiVoConnect':
25 raise "Container Name in use"
26 try:
27 settings['content_type'] = GetPlugin(settings['type']).CONTENT_TYPE
28 self.containers[name] = settings
29 except KeyError:
30 print 'Unable to add container', name
32 def reset(self):
33 self.containers.clear()
34 for section, settings in config.getShares():
35 self.add_container(section, settings)
37 def set_beacon(self, beacon):
38 self.beacon = beacon
40 class TivoHTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
41 tivos = {}
42 tivo_names = {}
44 def address_string(self):
45 host, port = self.client_address[:2]
46 return host
48 def do_GET(self):
49 tsn = self.headers.getheader('TiVo_TCD_ID',
50 self.headers.getheader('tsn', ''))
51 if tsn:
52 ip = self.address_string()
53 self.tivos[tsn] = ip
55 if not tsn in self.tivo_names:
56 self.tivo_names[tsn] = self.server.beacon.get_name(ip)
58 basepath = unquote_plus(self.path).split('/')[1]
60 ## Get File
61 for name, container in self.server.containers.items():
62 if basepath == name:
63 plugin = GetPlugin(container['type'])
64 plugin.send_file(self, container, name)
65 return
67 ## Not a file not a TiVo command fuck them
68 if not self.path.startswith('/TiVoConnect'):
69 self.infopage()
70 return
72 o = urlparse("http://fake.host" + self.path)
73 query = parse_qs(o[4])
75 mname = False
76 if query.has_key('Command') and len(query['Command']) >= 1:
78 command = query['Command'][0]
80 # If we are looking at the root container
81 if command == "QueryContainer" and \
82 (not query.has_key('Container') or query['Container'][0] == '/'):
83 self.root_container()
84 return
86 if query.has_key('Container'):
87 # Dispatch to the container plugin
88 basepath = unquote(query['Container'][0].split('/')[0])
89 for name, container in self.server.containers.items():
90 if basepath == name:
91 plugin = GetPlugin(container['type'])
92 if hasattr(plugin, command):
93 method = getattr(plugin, command)
94 method(self, query)
95 return
96 else:
97 break
99 # If we made it here it means we couldn't match the request to
100 # anything.
101 self.unsupported(query)
103 def root_container(self):
104 tsn = self.headers.getheader('TiVo_TCD_ID', '')
105 tsnshares = config.getShares(tsn)
106 tsncontainers = {}
107 for section, settings in tsnshares:
108 try:
109 settings['content_type'] = \
110 GetPlugin(settings['type']).CONTENT_TYPE
111 tsncontainers[section] = settings
112 except Exception, msg:
113 print section, '-', msg
114 t = Template(file=os.path.join(SCRIPTDIR, 'templates',
115 'root_container.tmpl'))
116 t.containers = tsncontainers
117 t.hostname = socket.gethostname()
118 t.escape = escape
119 t.quote = quote
120 self.send_response(200)
121 self.end_headers()
122 self.wfile.write(t)
124 def infopage(self):
125 self.send_response(200)
126 self.send_header('Content-type', 'text/html')
127 self.end_headers()
128 t = Template(file=os.path.join(SCRIPTDIR, 'templates',
129 'info_page.tmpl'))
130 t.admin = ''
131 for section, settings in config.getShares():
132 if 'type' in settings and settings['type'] == 'admin':
133 t.admin += '<a href="/TiVoConnect?Command=Admin&Container=' + quote(section)\
134 + '">pyTivo Web Configuration</a><br>'\
135 + '<a href="/TiVoConnect?Command=NPL&Container=' + quote(section)\
136 + '">pyTivo ToGo</a><br>'
137 if t.admin == '':
138 t.admin = '<br><b>No Admin plugin installed in pyTivo.conf</b><br> If you wish to use'\
139 + ' the admin plugin add the following lines to pyTivo.conf<br><br>'\
140 + '[Admin]<br>type=admin'
142 t.shares = 'Video shares:<br/>'
143 for section, settings in config.getShares():
144 if settings.get('type') == 'video':
145 t.shares += '<a href="TiVoConnect?Command=QueryContainer&Container=' + quote(section)\
146 + '">' + section + '</a><br/>'
148 self.wfile.write(t)
149 self.end_headers()
151 def unsupported(self, query):
152 if hack83 and 'Command' in query and 'Filter' in query:
153 logger = logging.getLogger('pyTivo.hack83')
155 logger.debug('Unsupported request checking to see if it is video.')
156 command = query['Command'][0]
157 plugin = GetPlugin('video')
158 if ''.join(query['Filter']).find('video') >= 0 and \
159 hasattr(plugin, command):
160 logger.debug('Unsupported request yup it is video send to video plugin for it to sort out.')
161 method = getattr(plugin, command)
162 method(self, query)
163 return
165 self.send_response(404)
166 self.send_header('Content-type', 'text/html')
167 self.end_headers()
168 t = Template(file=os.path.join(SCRIPTDIR, 'templates',
169 'unsupported.tmpl'))
170 t.query = query
171 self.wfile.write(t)
173 if __name__ == '__main__':
174 def start_server():
175 httpd = TivoHTTPServer(('', 9032), TivoHTTPHandler)
176 httpd.add_container('test', 'x-container/tivo-videos',
177 r'C:\Documents and Settings\Armooo\Desktop\pyTivo\test')
178 httpd.serve_forever()
180 start_server()