pyTivo
[pyTivo/krkeegan.git] / httpserver.py
blob6cb79339f87d22fc8c6334d578d3f5ea07438e55
1 import time, os, BaseHTTPServer, SocketServer, socket, shutil, os.path
2 from urllib import unquote_plus, quote, unquote
3 from urlparse import urlparse
4 from xml.sax.saxutils import escape
5 from cgi import parse_qs
6 from Cheetah.Template import Template
7 import transcode
9 SCRIPTDIR = os.path.dirname(__file__)
11 class TivoHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
12 containers = {}
14 def add_container(self, name, type, path):
15 if self.containers.has_key(name) or name == 'TivoConnect':
16 raise "Container Name in use"
17 self.containers[name] = {'type' : type, 'path' : path}
19 class TivoHTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
20 def do_GET(self):
22 for name, container in self.server.containers.items():
23 #XXX make a regex
24 if self.path.startswith('/' + name):
25 self.send_static(name, container)
26 return
28 if not self.path.startswith('/TiVoConnect'):
29 self.infopage()
30 return
32 o = urlparse("http://fake.host" + self.path)
33 query = parse_qs(o.query)
35 mname = False
36 if query.has_key('Command') and len(query['Command']) >= 1:
37 mname = 'do_' + query['Command'][0]
38 if mname and hasattr(self, mname):
39 method = getattr(self, mname)
40 method(query)
41 else:
42 self.unsuported(query)
44 def do_QueryContainer(self, query):
46 if not query.has_key('Container'):
47 query['Container'] = ['/']
48 self.send_response(200)
49 self.end_headers()
50 if query['Container'][0] == '/':
51 t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'root_container.tmpl'))
52 t.containers = self.server.containers
53 t.hostname = socket.gethostname()
54 self.wfile.write(t)
55 else:
57 subcname = query['Container'][0]
58 cname = subcname.split('/')[0]
60 if not self.server.containers.has_key(cname):
61 return
63 container = self.server.containers[cname]
65 folders = subcname.split('/')
66 path = container['path']
67 for folder in folders[1:]:
68 if folder == '..':
69 return
70 path = os.path.join(path, folder)
73 files = os.listdir(path)
75 files = filter(lambda f: os.path.isdir(os.path.join(path, f)) or transcode.suported_format(os.path.join(path,f)), files)
77 totalFiles = len(files)
79 def isdir(file):
80 return os.path.isdir(os.path.join(path, file))
82 index = 0
83 if query.has_key('ItemCount'):
84 count = int(query['ItemCount'] [0])
86 if query.has_key('AnchorItem'):
87 anchor = unquote(query['AnchorItem'][0])
88 print anchor
89 for i in range(len(files)):
91 if isdir(files[i]):
92 file_url = '/TiVoConnect?Command=QueryContainer&Container=' + subcname + '/' + files[i]
93 else:
94 file_url = '/' + subcname + '/' + files[i]
95 if file_url == anchor:
96 index = i + 1
97 break
98 if query.has_key('AnchorOffset'):
99 index = index + int(query['AnchorOffset'][0])
100 files = files[index:index + count]
104 t = Template(file=os.path.join(SCRIPTDIR,'templates', 'container.tmpl'))
105 t.name = subcname
106 t.files = files
107 t.total = totalFiles
108 t.start = index
109 t.isdir = isdir
110 t.quote = quote
111 t.escape = escape
112 self.wfile.write(t)
114 def send_static(self, name, container):
116 #cheep hack
117 if self.headers.getheader('Range') and not self.headers.getheader('Range') == 'bytes=0-':
118 self.send_response(404)
119 self.end_headers()
120 return
122 o = urlparse("http://fake.host" + self.path)
123 path = unquote_plus(o.path)
124 self.send_response(200)
125 self.end_headers()
126 transcode.output_video(container['path'] + path[len(name)+1:], self.wfile)
128 def infopage(self):
129 self.send_response(200)
130 self.send_header('Content-type', 'text/html')
131 self.end_headers()
132 t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl'))
133 self.wfile.write(t)
134 self.end_headers()
136 def unsuported(self, query):
137 self.send_response(404)
138 self.send_header('Content-type', 'text/html')
139 self.end_headers()
140 t = Template(file=os.path.join(SCRIPTDIR,'templates','unsuported.tmpl'))
141 t.query = query
142 self.wfile.write(t)
144 if __name__ == '__main__':
145 def start_server():
146 httpd = TivoHTTPServer(('', 9032), TivoHTTPHandler)
147 httpd.add_container('test', 'x-container/tivo-videos', r'C:\Documents and Settings\Armooo\Desktop\pyTivo\test')
148 httpd.serve_forever()
150 start_server()