Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 396 lines (322 sloc) 9.749 kb
ff20af9 @alobbs Adds the new admin
alobbs authored
1 # -*- coding: utf-8 -*-
2 #
3 # Cherokee-admin
4 #
5 # Authors:
6 # Alvaro Lopez Ortega <alvaro@alobbs.com>
7 #
920e20b @alobbs Happy new year!
alobbs authored
8 # Copyright (C) 2001-2011 Alvaro Lopez Ortega
ff20af9 @alobbs Adds the new admin
alobbs authored
9 #
10 # This program is free software; you can redistribute it and/or
11 # modify it under the terms of version 2 of the GNU General Public
12 # License as published by the Free Software Foundation.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 # 02110-1301, USA.
23 #
24
25 import os
26 import sys
27 import glob
28 import socket
7b005ca @alobbs Branch merge
alobbs authored
29 import subprocess
30
ff20af9 @alobbs Adds the new admin
alobbs authored
31 import CTK
32
7b005ca @alobbs Branch merge
alobbs authored
33
34 #
35 # Deal with os.popen and subprocess issues in Python 2.4
36 #
d4853a1 @alobbs Extends the function so it can return stderr and the process return
alobbs authored
37 def run (command, stdout=True, stderr=False, retcode=False):
38 returns = 0
39
40 args = {'shell': True, 'close_fds': True}
41 if stdout:
42 args['stdout'] = subprocess.PIPE
43 returns += 1
44 if stderr:
45 args['stderr'] = subprocess.PIPE
46 returns += 1
47 if retcode:
48 returns += 1
49
50 p = subprocess.Popen (command, **args)
51
52 if stdout:
53 stdout_output = p.stdout.read()
54 if stderr:
55 stderr_output = p.stderr.read()
56
57 if stdout:
58 p.stdout.close()
59 if stderr:
60 p.stderr.close()
61
62 ret = p.poll()
63
64 if returns > 1:
65 d = {}
66 if stdout:
67 d['stdout'] = stdout_output
68 if stderr:
69 d['stderr'] = stderr_output
70 if retcode:
71 d['retcode'] = ret
72 return d
73
74 if stdout:
75 return stdout_output
76 elif stderr:
77 return stderr_output
78 elif retcode:
79 return ret
80
81 assert False, "Should not happened"
82
7b005ca @alobbs Branch merge
alobbs authored
83
ff20af9 @alobbs Adds the new admin
alobbs authored
84 #
85 # Strings
86 #
87 def bool_to_active (b):
86c6d79 Some i18n fixes
taher authored
88 return (_('Inactive'), _('Active'))[bool(b)]
ff20af9 @alobbs Adds the new admin
alobbs authored
89
90 def bool_to_onoff (b):
91 return (_('Off'), _('On'))[bool(b)]
92
93 def bool_to_yesno (b):
94 return (_('No'), _('Yes'))[bool(b)]
95
ceaf427 @alobbs Clean up: The constants file was definitely not the right place for a
alobbs authored
96 def trans_options (options):
97 """Translate the options with gettext"""
98 return [(x[0], _(x[1])) for x in options]
99
ff20af9 @alobbs Adds the new admin
alobbs authored
100
101 #
102 # Virtual Server
103 #
104
105 def cfg_vsrv_get_next():
106 """ Get the prefix of the next vserver """
107 tmp = [int(x) for x in CTK.cfg.keys("vserver")]
108 tmp.sort()
109 next = str(tmp[-1] + 10)
110 return "vserver!%s" % (next)
111
112 def cfg_vsrv_rule_get_next (pre):
113 """ Get the prefix of the next rule of a vserver """
114 tmp = [int(x) for x in CTK.cfg.keys("%s!rule"%(pre))]
115 tmp.sort()
116 if tmp:
117 next = tmp[-1] + 100
118 else:
119 next = 100
120 return (next, "%s!rule!%d" % (pre, next))
121
122 def cfg_vsrv_rule_find_extension (pre, extension):
123 """Find an extension rule in a virtual server """
124 for r in CTK.cfg.keys("%s!rule"%(pre)):
125 p = "%s!rule!%s" % (pre, r)
126 if CTK.cfg.get_val ("%s!match"%(p)) == "extensions":
127 if extension in CTK.cfg.get_val ("%s!match!extensions"%(p)):
128 return p
129
130 def cfg_vsrv_rule_find_regexp (pre, regexp):
131 """Find a regular expresion rule in a virtual server """
132 for r in CTK.cfg.keys("%s!rule"%(pre)):
133 p = "%s!rule!%s" % (pre, r)
134 if CTK.cfg.get_val ("%s!match"%(p)) == "request":
135 if regexp == CTK.cfg.get_val ("%s!match!request"%(p)):
136 return p
137
138 #
139 # Information Sources
140 #
141
142 def cfg_source_get_next ():
143 tmp = [int(x) for x in CTK.cfg.keys("source")]
144 if not tmp:
145 return (1, "source!1")
146 tmp.sort()
147 next = tmp[-1] + 10
148 return (next, "source!%d" % (next))
149
150 def cfg_source_find_interpreter (in_interpreter = None,
151 in_nick = None):
152 for i in CTK.cfg.keys("source"):
153 if CTK.cfg.get_val("source!%s!type"%(i)) != 'interpreter':
154 continue
155
156 if (in_interpreter and
a341e46 cfg_source_find_interpreter would raise an exception if a configuration ...
taher authored
157 in_interpreter in CTK.cfg.get_val("source!%s!interpreter"%(i), '')):
ff20af9 @alobbs Adds the new admin
alobbs authored
158 return "source!%s" % (i)
159
160 if (in_nick and
a341e46 cfg_source_find_interpreter would raise an exception if a configuration ...
taher authored
161 in_nick in CTK.cfg.get_val("source!%s!nick"%(i), '')):
ff20af9 @alobbs Adds the new admin
alobbs authored
162 return "source!%s" % (i)
163
164 def cfg_source_find_empty_port (n_ports=1):
165 ports = []
166 for i in CTK.cfg.keys("source"):
167 host = CTK.cfg.get_val ("source!%s!host"%(i))
168 if not host: continue
169
170 colon = host.rfind(':')
171 if colon < 0: continue
172
173 port = int (host[colon+1:])
174 if port < 1024: continue
175
176 ports.append (port)
177
178 pport = 1025
8b95ba5 Fix empty_port finder
taher authored
179 while pport+n_ports < 65535:
180 pports = range(pport, pport + n_ports)
181 for x in pports:
182 if x in ports:
183 pport += 1
184 break
ff20af9 @alobbs Adds the new admin
alobbs authored
185 return pport
186
187 assert (False)
188
189 def cfg_source_find_free_port (host_name='localhost'):
190 """Return a port not currently running anything"""
191 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
192 s.bind((host_name, 0))
193 addr, port = s.getsockname()
194 s.close()
195 return port
196
197 def cfg_source_get_localhost_addr ():
198 x, x, addrs = socket.gethostbyname_ex('localhost')
199 if addrs:
200 return addrs[0]
201 return None
202
203 def cfg_get_surrounding_repls (macro, value, n_minus=9, n_plus=9):
204 replacements = {}
205
206 tmp = value.split('!')
207 pre = '!'.join(tmp[:-1])
208 num = int(tmp[-1])
209
210 for n in range(n_minus):
211 replacements['%s_minus%d'%(macro,n+1)] = '%s!%d' %(pre, num-(n+1))
212
213 for n in range(n_plus):
214 replacements['%s_plus%d'%(macro,n+1)] = '%s!%d' %(pre, num+(n+1))
215
216 return replacements
217
1c2e01f @alobbs Adds a new function to compare version strings. It's a specialized
alobbs authored
218 #
219 # Version strings management
220 #
221
222 def version_to_int (v):
223 num = 0
224 tmp = v.split('.')
225
226 if len(tmp) >= 3:
227 num += int(tmp[2]) * (10**3)
228 if len(tmp) >= 2:
229 num += int(tmp[1]) * (10**6)
230 if len(tmp) >= 1:
231 num += int(tmp[0]) * (10**9)
232
233 return num
234
235 def version_cmp (x, y):
236 xp = x.split('b')
237 yp = y.split('b')
238
239 if len(xp) > 1:
240 x_ver = version_to_int(xp[0])
241 x_beta = xp[1]
242 else:
243 x_ver = version_to_int(xp[0])
244 x_beta = None
245
246 if len(yp) > 1:
247 y_ver = version_to_int(yp[0])
248 y_beta = yp[1]
249 else:
250 y_ver = version_to_int(yp[0])
251 y_beta = None
252
253 if x_ver == y_ver:
254 if not x_beta and not y_beta: return 0
255 if not y_beta: return -1
256 if not x_beta: return 1
257 return cmp(int(x_beta),int(y_beta))
258
259 elif x_ver > y_ver:
260 return 1
261
262 return -1
263
ff20af9 @alobbs Adds the new admin
alobbs authored
264
265 #
266 # Paths
267 #
268
94f6529 @alobbs Makes the interface function a little more flexible.
alobbs authored
269 def path_find_binary (executable, extra_dirs=[], custom_test=None, default=None):
ff20af9 @alobbs Adds the new admin
alobbs authored
270 """Find an executable.
271 It checks 'extra_dirs' and the PATH.
272 The 'executable' parameter can be either a string or a list.
273 """
274
275 assert (type(executable) in [str, list])
276
151b0ab @alobbs The path_find_binary() helper functions supports globs in the extra
alobbs authored
277 # Extra dirs evaluation
278 dirs = []
279 for d in extra_dirs:
280 if '*' in d or '?' in d:
281 dirs += glob.glob (d)
282 else:
283 dirs.append(d)
284
285 # $PATH
ff20af9 @alobbs Adds the new admin
alobbs authored
286 env_path = os.getenv("PATH")
287 if env_path:
288 dirs += filter (lambda x: x, env_path.split(":"))
289
151b0ab @alobbs The path_find_binary() helper functions supports globs in the extra
alobbs authored
290 # Check
35026a8 @alobbs Check each binary on the different directories, instead of each
alobbs authored
291 if type(executable) != list:
292 executable = [executable]
293
294 for exe in executable:
295 for dir in dirs:
296 fp = os.path.join (dir, exe)
297 if os.path.exists (fp):
ff20af9 @alobbs Adds the new admin
alobbs authored
298 if custom_test:
35026a8 @alobbs Check each binary on the different directories, instead of each
alobbs authored
299 if not custom_test(fp):
ff20af9 @alobbs Adds the new admin
alobbs authored
300 continue
35026a8 @alobbs Check each binary on the different directories, instead of each
alobbs authored
301 return fp
ff20af9 @alobbs Adds the new admin
alobbs authored
302
94f6529 @alobbs Makes the interface function a little more flexible.
alobbs authored
303 # Not found
304 return default
305
ff20af9 @alobbs Adds the new admin
alobbs authored
306 def path_find_w_default (path_list, default=''):
307 """Find a path.
308 It checks a list of paths (that can contain wildcards),
309 if none exists default is returned.
310 """
311 for path in path_list:
312 if '*' in path or '?' in path:
313 to_check = glob.glob (path)
314 else:
315 to_check = [path]
316 for p in to_check:
317 if os.path.exists (p):
318 return p
319 return default
320
20a9a0d @alobbs Adds a new utility function
alobbs authored
321 def path_eval_exist (path_list):
322 """Evaluate a list of potential paths.
323 Returns the paths that actually exist.
324 """
325 exist = []
326 for path in path_list:
327 if '*' in path or '?' in path:
328 to_check = glob.glob (path)
329 else:
330 to_check = [path]
331 for p in to_check:
332 if os.path.exists (p):
333 exist.append (p)
334 return exist
335
336
ff20af9 @alobbs Adds the new admin
alobbs authored
337
338 #
339 # OS
340 #
341 def os_get_document_root():
342 if sys.platform == 'darwin':
343 return "/Library/WebServer/Documents"
344 elif sys.platform == 'linux2':
345 if os.path.exists ("/etc/redhat-release"):
346 return '/var/www'
347 elif os.path.exists ("/etc/fedora-release"):
348 return '/var/www'
349 elif os.path.exists ("/etc/SuSE-release"):
350 return '/srv/www/htdocs'
351 elif os.path.exists ("/etc/debian_version"):
352 return '/var/www'
353 elif os.path.exists ("/etc/gentoo-release"):
354 return '/var/www'
355 elif os.path.exists ("/etc/slackware-version"):
356 return '/var/www'
357 return '/var/www'
358
359 return ''
360
361
362 #
363 # Misc
364 #
365 def split_list (value):
366 ids = []
367 for t1 in value.split(','):
368 for t2 in t1.split(' '):
369 id = t2.strip()
370 if not id:
371 continue
372 ids.append(id)
373 return ids
374
375
376 def lists_differ (a, b):
377 """Compare lists disregarding order"""
378 if len(a) != len(b):
379 return True
380 if bool (set(a)-set(b)):
381 return True
382 if bool (set(b)-set(a)):
383 return True
384 return False
a22f4c0 Fixes possible issues with chroot
taher authored
385
386
8d75aa2 Fix issue with chrooted paths
taher authored
387 def get_real_path (name, nochroot=False):
a22f4c0 Fixes possible issues with chroot
taher authored
388 """Get real path accounting for chrooted environments"""
389 chroot = CTK.cfg.get_val('server!chroot')
8d75aa2 Fix issue with chrooted paths
taher authored
390 if chroot and not nochroot:
a22f4c0 Fixes possible issues with chroot
taher authored
391 fullname = os.path.normpath (chroot + os.path.sep + name)
392 else:
393 fullname = name
394
395 return fullname
Something went wrong with that request. Please try again.