pyTivo
[pyTivo/krkeegan.git] / httpserver.py
blob224d634330a4c0817c52c49447270552a388ef21
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 __init__(self, server_address, RequestHandlerClass):
15 BaseHTTPServer.HTTPServer.__init__(self, server_address, RequestHandlerClass)
16 self.daemon_threads = True
18 def add_container(self, name, type, path):
19 if self.containers.has_key(name) or name == 'TivoConnect':
20 raise "Container Name in use"
21 self.containers[name] = {'type' : type, 'path' : path}
23 class TivoHTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
24 def do_GET(self):
26 for name, container in self.server.containers.items():
27 #XXX make a regex
28 if self.path.startswith('/' + name):
29 self.send_static(name, container)
30 return
32 if not self.path.startswith('/TiVoConnect'):
33 self.infopage()
34 return
36 o = urlparse("http://fake.host" + self.path)
37 query = parse_qs(o.query)
39 mname = False
40 if query.has_key('Command') and len(query['Command']) >= 1:
41 mname = 'do_' + query['Command'][0]
42 if mname and hasattr(self, mname):
43 method = getattr(self, mname)
44 method(query)
45 else:
46 self.unsuported(query)
48 def do_QueryContainer(self, query):
50 if not query.has_key('Container'):
51 query['Container'] = ['/']
52 self.send_response(200)
53 self.end_headers()
54 if query['Container'][0] == '/':
55 t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'root_container.tmpl'))
56 t.containers = self.server.containers
57 t.hostname = socket.gethostname()
58 self.wfile.write(t)
59 else:
61 subcname = query['Container'][0]
62 cname = subcname.split('/')[0]
64 if not self.server.containers.has_key(cname):
65 return
67 container = self.server.containers[cname]
69 folders = subcname.split('/')
70 path = container['path']
71 for folder in folders[1:]:
72 if folder == '..':
73 return
74 path = os.path.join(path, folder)
77 files = os.listdir(path)
79 files = filter(lambda f: os.path.isdir(os.path.join(path, f)) or transcode.suported_format(os.path.join(path,f)), files)
81 totalFiles = len(files)
83 def isdir(file):
84 return os.path.isdir(os.path.join(path, file))
86 index = 0
87 if query.has_key('ItemCount'):
88 count = int(query['ItemCount'] [0])
90 if query.has_key('AnchorItem'):
91 anchor = unquote(query['AnchorItem'][0])
92 for i in range(len(files)):
94 if isdir(files[i]):
95 file_url = '/TiVoConnect?Command=QueryContainer&Container=' + subcname + '/' + files[i]
96 else:
97 file_url = '/' + subcname + '/' + files[i]
98 if file_url == anchor:
99 index = i + 1
100 break
101 if query.has_key('AnchorOffset'):
102 index = index + int(query['AnchorOffset'][0])
103 files = files[index:index + count]
107 t = Template(file=os.path.join(SCRIPTDIR,'templates', 'container.tmpl'))
108 t.name = subcname
109 t.files = files
110 t.total = totalFiles
111 t.start = index
112 t.isdir = isdir
113 t.quote = quote
114 t.escape = escape
115 self.wfile.write(t)
117 def send_static(self, name, container):
119 #cheep hack
120 if self.headers.getheader('Range') and not self.headers.getheader('Range') == 'bytes=0-':
121 self.send_response(404)
122 self.end_headers()
123 return
125 o = urlparse("http://fake.host" + self.path)
126 path = unquote_plus(o.path)
127 self.send_response(200)
128 self.end_headers()
129 transcode.output_video(container['path'] + path[len(name)+1:], self.wfile)
131 def infopage(self):
132 self.send_response(200)
133 self.send_header('Content-type', 'text/html')
134 self.end_headers()
135 t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl'))
136 self.wfile.write(t)
137 self.end_headers()
139 def unsuported(self, query):
140 self.send_response(404)
141 self.send_header('Content-type', 'text/html')
142 self.end_headers()
143 t = Template(file=os.path.join(SCRIPTDIR,'templates','unsuported.tmpl'))
144 t.query = query
145 self.wfile.write(t)
147 if __name__ == '__main__':
148 def start_server():
149 httpd = TivoHTTPServer(('', 9032), TivoHTTPHandler)
150 httpd.add_container('test', 'x-container/tivo-videos', r'C:\Documents and Settings\Armooo\Desktop\pyTivo\test')
151 httpd.serve_forever()
153 start_server()