def root_container(self): tsn = self.headers.getheader('TiVo_TCD_ID', '') tsnshares = config.getShares(tsn) tsncontainers = [] for section, settings in tsnshares: try: mime = GetPlugin(settings['type']).CONTENT_TYPE if mime.split('/')[1] in ('tivo-videos', 'tivo-music', 'tivo-photos'): settings['content_type'] = mime tsncontainers.append((section, settings)) except Exception, msg: self.server.logger.error(section + ' - ' + str(msg))
def add_container(self, name, settings): if self.containers.has_key(name) or name == 'TiVoConnect': raise "Container Name in use" try: settings['content_type'] = GetPlugin(settings['type']).CONTENT_TYPE self.containers[name] = settings except KeyError: print 'Unable to add container', name
def handle_query(self, query, tsn): mname = False if 'Command' in query and len(query['Command']) >= 1: command = query['Command'][0] # If we are looking at the root container if (command == 'QueryContainer' and (not 'Container' in query or query['Container'][0] == '/')): self.root_container() return if 'Container' in query: # Dispatch to the container plugin basepath = query['Container'][0].split('/')[0] if self.do_command(query, command, basepath, tsn): return elif command == 'QueryItem': path = query.get('Url', [''])[0] splitpath = [x for x in unquote_plus(path).split('/') if x] if splitpath and not '..' in splitpath: if self.do_command(query, command, splitpath[0], tsn): return elif (command == 'QueryFormats' and 'SourceFormat' in query and query['SourceFormat'][0].startswith('video')): if config.is_ts_capable(tsn): self.send_xml(VIDEO_FORMATS_TS) else: self.send_xml(VIDEO_FORMATS) return elif command == 'QueryServer': self.send_xml(SERVER_INFO) return elif command in ('GetActiveTransferCount', 'GetTransferStatus'): plugin = GetPlugin('video') if hasattr(plugin, command): method = getattr(plugin, command) method(self, query) return True elif command in ('FlushServer', 'ResetServer'): # Does nothing -- included for completeness self.send_response(200) self.send_header('Content-Length', '0') self.end_headers() self.wfile.flush() return # If we made it here it means we couldn't match the request to # anything. self.unsupported(query)
def handle_file(self, query, splitpath): if '..' not in splitpath: # Protect against path exploits ## Pass it off to a plugin? for name, container in self.server.containers.items(): if splitpath[0] == name: self.cname = name self.container = container base = os.path.normpath(container['path']) path = os.path.join(base, *splitpath[1:]) plugin = GetPlugin(container['type']) plugin.send_file(self, path, query) return ## Serve it from a "content" directory? base = os.path.join(SCRIPTDIR, *splitpath[:-1]) path = os.path.join(base, 'content', splitpath[-1]) if os.path.isfile(path): try: handle = open(path, 'rb') except: self.send_error(404) return # Send the header mime = mimetypes.guess_type(path)[0] self.send_response(200) if mime: self.send_header('Content-type', mime) self.send_header('Content-length', os.path.getsize(path)) self.end_headers() # Send the body of the file try: shutil.copyfileobj(handle, self.wfile) except: pass handle.close() return ## Give up self.send_error(404)
def root_container(self): tsn = self.headers.getheader('TiVo_TCD_ID', '') tsnshares = config.getShares(tsn) tsncontainers = {} for section, settings in tsnshares: try: settings['content_type'] = \ GetPlugin(settings['type']).CONTENT_TYPE tsncontainers[section] = settings except Exception, msg: print section, '-', msg
def do_command(self, query, command, target, tsn): for name, container in config.getShares(tsn): if target == name: plugin = GetPlugin(container['type']) if hasattr(plugin, command): self.cname = name self.container = container method = getattr(plugin, command) method(self, query) return True else: break return False
def root_container(self): tsn = self.headers.get('TiVo_TCD_ID', '') tsnshares = config.getShares(tsn) tsncontainers = [] for section, settings in tsnshares: try: mime = GetPlugin(settings['type']).CONTENT_TYPE if mime.split('/')[1] in ('tivo-videos', 'tivo-music', 'tivo-photos'): settings['content_type'] = mime tsncontainers.append((section, settings)) except Exception as msg: self.server.logger.error('%s - %s', section, str(msg)) t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'root_container.tmpl')) if self.server.beacon.bd: t.renamed = self.server.beacon.bd.renamed else: t.renamed = {} t.containers = tsncontainers t.hostname = socket.gethostname() t.escape = escape t.quote = quote self.send_xml(str(t))
def handle_file(self, query, splitpath): if '..' not in splitpath: # Protect against path exploits ## Pass it off to a plugin? for name, container in self.server.containers.items(): if splitpath[0] == name: self.cname = name self.container = container base = os.path.normpath(container['path']) path = os.path.join(base, *splitpath[1:]) plugin = GetPlugin(container['type']) plugin.send_file(self, path, query) return ## Serve it from a "content" directory? base = os.path.join(SCRIPTDIR, *splitpath[:-1]) path = os.path.join(base, 'content', splitpath[-1]) if os.path.isfile(path): self.send_content_file(path) return ## Give up self.send_error(404)
def setup(in_service=False): config.init(sys.argv[1:]) config.init_logging() sys.excepthook = exceptionLogger port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) logger = logging.getLogger('pyTivo') logger.info('Last modified: ' + last_date()) logger.info('Python: ' + platform.python_version()) logger.info('System: ' + platform.platform()) for section, settings in config.getShares(): httpd.add_container(section, settings) # Precaching of files: does a recursive list of base path if settings.get('precache', 'False').lower() == 'true': plugin = GetPlugin(settings.get('type')) if hasattr(plugin, 'pre_cache'): logger.info('Pre-caching the ' + section + ' share.') pre_cache_filter = getattr(plugin, 'pre_cache') def build_recursive_list(path): try: for f in os.listdir(path): f = os.path.join(path, f) if os.path.isdir(f): build_recursive_list(f) else: pre_cache_filter(f) except: pass build_recursive_list(settings.get('path')) b = beacon.Beacon() b.add_service('TiVoMediaServer:%s/http' % port) b.start() if 'listen' in config.getBeaconAddresses(): b.listen() httpd.set_beacon(b) httpd.set_service_status(in_service) logger.info('pyTivo is ready.') return httpd
def do_GET(self): tsn = self.headers.getheader('TiVo_TCD_ID', self.headers.getheader('tsn', '')) ip = self.address_string() self.tivos[tsn] = ip basepath = unquote_plus(self.path).split('/')[1] ## Get File for name, container in self.server.containers.items(): if basepath == name: plugin = GetPlugin(container['type']) plugin.send_file(self, container, name) return ## Not a file not a TiVo command f**k them if not self.path.startswith('/TiVoConnect'): self.infopage() return o = urlparse("http://fake.host" + self.path) query = parse_qs(o[4]) mname = False if query.has_key('Command') and len(query['Command']) >= 1: command = query['Command'][0] # If we are looking at the root container if command == "QueryContainer" and \ (not query.has_key('Container') or query['Container'][0] == '/'): self.root_container() return if query.has_key('Container'): # Dispatch to the container plugin basepath = unquote(query['Container'][0].split('/')[0]) for name, container in self.server.containers.items(): if basepath == name: plugin = GetPlugin(container['type']) if hasattr(plugin, command): method = getattr(plugin, command) method(self, query) return else: break # If we made it here it means we couldn't match the request to # anything. self.unsupported(query)
def infopage(self): t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'info_page.tmpl'), filter=EncodeUnicode) t.admin = '' if config.get_server('tivo_mak') and config.get_server('togo_path'): t.togo = '<br>Pull from TiVos:<br>' else: t.togo = '' if (config.get_server('tivo_username') and config.get_server('tivo_password')): t.shares = '<br>Push from video shares:<br>' else: t.shares = '' for section, settings in config.getShares(): plugin_type = settings.get('type') if plugin_type == 'settings': t.admin += ('<a href="/TiVoConnect?Command=Settings&' + 'Container=' + quote(section) + '">Settings</a><br>') elif plugin_type == 'togo' and t.togo: for tsn in config.tivos: if tsn and 'address' in config.tivos[tsn]: t.togo += ('<a href="/TiVoConnect?' + 'Command=NPL&Container=' + quote(section) + '&TiVo=' + config.tivos[tsn]['address'] + '">' + config.tivos[tsn]['name'] + '</a><br>') elif plugin_type and t.shares: plugin = GetPlugin(plugin_type) if hasattr(plugin, 'Push'): t.shares += ('<a href="/TiVoConnect?Command=' + 'QueryContainer&Container=' + quote(section) + '&Format=text/html">' + section + '</a><br>') self.send_html(str(t))
def unsupported(self, query): if hack83 and 'Command' in query and 'Filter' in query: debug_write(__name__, fn_attr(), ['Unsupported request,', 'checking to see if it is video.']) command = query['Command'][0] plugin = GetPlugin('video') if ''.join(query['Filter']).find('video') >= 0 and \ hasattr(plugin, command): debug_write(__name__, fn_attr(), ['Unsupported request,', 'yup it is video', 'send to video plugin for it to sort out.']) method = getattr(plugin, command) method(self, query) return self.send_response(404) self.send_header('Content-type', 'text/html') self.end_headers() t = Template(file=os.path.join(SCRIPTDIR, 'templates', 'unsupported.tmpl')) t.query = query self.wfile.write(t)
#!/usr/bin/env python import beacon, httpserver, os, sys import config from plugin import GetPlugin port = config.getPort() httpd = httpserver.TivoHTTPServer(('', int(port)), httpserver.TivoHTTPHandler) for section, settings in config.getShares(): httpd.add_container(section, settings) # Precaching of files: does a recursive list of base path if settings.get('precache', 'False').lower() == 'true': plugin = GetPlugin(settings.get('type')) if hasattr(plugin, 'pre_cache'): print 'Pre-caching the', section, 'share.' pre_cache_filter = getattr(plugin, 'pre_cache') def build_recursive_list(path): try: for f in os.listdir(path): f = os.path.join(path, f) if os.path.isdir(f): build_recursive_list(f) else: pre_cache_filter(f) except: pass build_recursive_list(settings.get('path'))