Enable rereading of pyTivo.conf without restart
[pyTivo/wgw.git] / plugins / admin / admin.py
blob770de18fe3663e2f8985b824da33bfbf350d34f9
1 import os, socket, re, sys, ConfigParser, config
2 from ConfigParser import NoOptionError
3 from Cheetah.Template import Template
4 from plugin import Plugin
5 from urllib import unquote_plus, quote, unquote
6 from xml.sax.saxutils import escape
7 from lrucache import LRUCache
9 SCRIPTDIR = os.path.dirname(__file__)
11 CLASS_NAME = 'Admin'
13 p = os.path.dirname(__file__)
14 p = p.split(os.path.sep)
15 p.pop()
16 p.pop()
17 p = os.path.sep.join(p)
18 config_file_path = os.path.join(p, 'pyTivo.conf')
20 class Admin(Plugin):
21 CONTENT_TYPE = 'text/html'
23 def Restart(self, handler, query):
24 config.reset()
25 handler.server.reset()
26 handler.send_response(200)
27 handler.end_headers()
29 def Admin(self, handler, query):
30 #Read config file new each time in case there was any outside edits
31 config = ConfigParser.ConfigParser()
32 config.read(config_file_path)
34 subcname = query['Container'][0]
35 cname = subcname.split('/')[0]
36 handler.send_response(200)
37 handler.end_headers()
38 t = Template(file=os.path.join(SCRIPTDIR,'templates', 'settings.tmpl'))
39 t.container = cname
40 t.server_data = dict(config.items('Server'))
41 t.server_known = ["port", "guid", "ffmpeg", "beacon", "hack83", "debug", \
42 "optres", "audio_br", "video_br", "max_video_br", "width",\
43 "height", "ffmpeg_prams", "bufsize"]
44 t.shares_data = shares_data = [ (section, dict(config.items(section))) \
45 for section in config.sections() \
46 if not(section.startswith('_tivo_') \
47 or section.startswith('Server')) and \
48 (config.has_option(section,'type') and \
49 config.get(section,'type').lower() != 'admin')]
50 t.shares_known = ["type", "path", "auto_subshares"]
51 t.tivos_data = [ (section, dict(config.items(section))) for section in config.sections() \
52 if section.startswith('_tivo_')]
53 t.tivos_known = ["aspect169", "audio_br", "video_br", "width", "height", "ffmpeg_prams"]
54 handler.wfile.write(t)
56 def QueryContainer(self, handler, query):
57 #Read config file new each time in case there was any outside edits
58 config = ConfigParser.ConfigParser()
59 config.read(config_file_path)
61 def build_inputs(settings, data, section):
62 output = ''
63 for key in settings:
64 try:
65 output += "<tr><td>" + key + ": </td><td><input type='text' name='" + section + "." + key + "' value='" + data[key] +"'></td></tr>"
66 del data[key]
67 except:
68 output += "<tr><td>" + key + ": </td><td><input type='text' name='" + section + "." + key + "' value=''></td></tr>"
69 #print remaining miscellaneous settings
70 if len(data) > 0:
71 output += '<tr><td colspan="2" align="center">User Defined Settings</td></tr>'
72 for item in data:
73 output += "<tr><td>" + item + ": </td><td><input type='text' name='" + section + "." + item + "' value='" + data[item] +"'></td></tr>"
74 output += '<tr><td colspan="2" align="center">Add a User Defined Setting to this Share</td></tr>'
75 output += "<tr><td><input type='text' name='" + section + ".new__setting' value=''></td><td><input type='text' name='" + section + ".new__value' value=''></td></tr>"
76 return output
78 server_data = dict(config.items('Server'))
79 server = ''
80 #build an array with configuration settings to use
81 settings = ["port", "guid", "ffmpeg", "beacon", "hack83", "debug", "optres", "audio_br", "video_br", "max_video_br", "width", "height", "ffmpeg_prams", "bufsize"]
82 server += build_inputs(settings, server_data, 'Server')
84 #Keep track of the different sections
85 section_map = ''
86 section_count = 1
88 shares_data = [ (section, dict(config.items(section))) for section in config.sections() if not(section.startswith('_tivo_') or section.startswith('Server')) and (config.has_option(section,'type') and config.get(section,'type').lower() != 'admin')]
89 shares =''
90 for name, data in shares_data:
91 shares += '<tr><td colspan="2" align="center">----------------------------------</td></tr>'
92 shares += '<tr><td colspan="2" align="center">[<input type="text" id="section_' + str(section_count) + '" name="section-' + str(section_count) + '" value="' + name + '">]</td></tr>'
93 #build an array with configuration settings to use
94 settings = ["type", "path", "auto_subshares"]
95 shares += build_inputs(settings, data, "section-" + str(section_count))
96 shares += '<tr><td colspan="2" align="center">Mark this share for deletion <input type="button" value="Delete" onclick="deleteme(\'section_' + str(section_count) + '\')"></td></tr>'
97 section_map += "section-" + str(section_count) + ":" + name + "/"
98 section_count += 1
100 tivos_data = [ (section, dict(config.items(section))) for section in config.sections() if section.startswith('_tivo_')]
101 tivos =''
102 for name, data in tivos_data:
103 tivos += '<tr><td colspan="2" align="center">----------------------------------</td></tr>'
104 tivos += '<tr><td colspan="2" align="center">[<input type="text" id="section_' + str(section_count) + '" name="section-' + str(section_count) + '" value="' + name + '">]</td></tr>'
105 #build an array with configuration settings to use
106 settings = ["aspect169", "audio_br", "video_br", "width", "height", "ffmpeg_prams"]
107 tivos += build_inputs(settings, data, "section-" + str(section_count))
108 tivos += '<tr><td colspan="2" align="center">Mark this TiVo for deletion <input type="button" value="Delete" onclick="deleteme(\'section_' + str(section_count) + '\')"></td></tr>'
109 section_map += "section-" + str(section_count) + ":" + name + "/"
110 section_count += 1
112 subcname = query['Container'][0]
113 cname = subcname.split('/')[0]
114 handler.send_response(200)
115 handler.end_headers()
116 t = Template(file=os.path.join(SCRIPTDIR,'templates', 'admin.tmpl'))
117 t.container = cname
118 t.server = server
119 t.shares = shares
120 t.tivos = tivos
121 t.section_map = section_map
122 handler.wfile.write(t)
123 config.read(config_file_path + '.dist')
125 def UpdateSettings(self, handler, query):
126 config = ConfigParser.ConfigParser()
127 config.read(config_file_path)
128 for key in query:
129 if key.startswith('Server.'):
130 section, option = key.split('.')
131 if option == "new__setting":
132 new_setting = query[key][0]
133 continue
134 if option == "new__value":
135 new_value = query[key][0]
136 continue
137 if query[key][0] == " ":
138 config.remove_option(section, option)
139 else:
140 config.set(section, option, query[key][0])
141 if not(new_setting == ' ' and new_value == ' '):
142 config.set('Server', new_setting, new_value)
144 sections = query['Section_Map'][0].split('/')
145 sections.pop() #last item is junk
146 for section in sections:
147 ID, name = section.split(':')
148 if query[ID][0] == "Delete_Me":
149 config.remove_section(name)
150 continue
151 if query[ID][0] != name:
152 config.remove_section(name)
153 config.add_section(query[ID][0])
154 for key in query:
155 if key.startswith(ID + '.'):
156 junk, option = key.split('.')
157 if option == "new__setting":
158 new_setting = query[key][0]
159 continue
160 if option == "new__value":
161 new_value = query[key][0]
162 continue
163 if query[key][0] == " ":
164 config.remove_option(query[ID][0], option)
165 else:
166 config.set(query[ID][0], option, query[key][0])
167 if not(new_setting == ' ' and new_value == ' '):
168 config.set(query[ID][0], new_setting, new_value)
169 if query['new_Share'][0] != " ":
170 config.add_section(query['new_Share'][0])
171 config.set(query['new_Share'][0], 'type', 'video')
172 if query['new_TiVo'][0] != " ":
173 config.add_section(query['new_TiVo'][0])
174 f = open(config_file_path, "w")
175 config.write(f)
176 f.close()
178 subcname = query['Container'][0]
179 cname = subcname.split('/')[0]
180 handler.send_response(200)
181 handler.end_headers()
182 t = Template(file=os.path.join(SCRIPTDIR,'templates', 'redirect.tmpl'))
183 t.container = cname
184 handler.wfile.write(t)