merge with tux-join
authorsandro
Mon, 26 Apr 2021 11:16:23 +0200
changeset 5199a841a49a674
parent 518 dd367cf3930b
parent 512 6aefb43518e5
child 520 533981846633
merge with tux-join
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Mon Apr 26 11:16:23 2010 +0200
     1.3 @@ -0,0 +1,23 @@
     1.4 +.backups
     1.5 +build*
     1.6 +configure-stamp
     1.7 +debian/file
     1.8 +debian/.*ex
     1.9 +debian/tmp
    1.10 +debian/isi
    1.11 +debian/isi-checkup
    1.12 +debian/isi-docs
    1.13 +debian/python-isi
    1.14 +docs/allegati/netkit
    1.15 +docs/.build
    1.16 +docs/img/icone
    1.17 +etc/isi/checkup/exclude
    1.18 +log
    1.19 +usr/share/isi-checkup/tests/TODO
    1.20 +lib/isi.egg-info.*
    1.21 +lab/srv-isi.disk
    1.22 +#web
    1.23 +lab/.*isi
    1.24 +web/local_settings.py
    1.25 +.exlude_rsync_files
    1.26 +sync_all
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/2dreamnet	Mon Apr 26 11:16:23 2010 +0200
     2.3 @@ -0,0 +1,18 @@
     2.4 +#!/bin/bash
     2.5 +
     2.6 +#remote_srv='isibeta6 192.168.1.220'
     2.7 +#remote_srv='192.168.5.151'
     2.8 +#remote_srv='192.168.1.233 isibeta6' # test-isi-lenny
     2.9 +remote_srv='192.168.1.218'
    2.10 +
    2.11 +path_locale='/home/dream/src/isi/isi-checkup/usr'  
    2.12 +path_remoto='/usr'  
    2.13 +
    2.14 +for srv in $remote_srv; do
    2.15 +	echo "rsync -P -r $path_locale/* root@$srv:$path_remoto/"
    2.16 +	rsync -P -r $path_locale/* root@$srv:$path_remoto/
    2.17 +	echo "ssh root@$srv isi-checkup -t isi"
    2.18 +	ssh root@$srv isi-checkup -T
    2.19 +	#echo ssh root@$srv isi-checkup
    2.20 +done
    2.21 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/Makefile	Mon Apr 26 11:16:23 2010 +0200
     3.3 @@ -0,0 +1,40 @@
     3.4 +# $pkg
     3.5 +.PHONY: all install clean
     3.6 +PKG=$(shell echo $(shell pwd)| sed 's/.*\///')
     3.7 +DEB=$(shell cat debian/files |cut -f 1 -d " ")
     3.8 +
     3.9 +all: 
    3.10 +	echo "nessuna compilazione"
    3.11 +
    3.12 +deb:
    3.13 +	dpkg-buildpackage -rfakeroot -us -uc -b | tee log
    3.14 +	echo pkg=$(PKG)  deb=$(DEB)
    3.15 +#	hg status
    3.16 +
    3.17 +content:  
    3.18 +	dpkg -c ../$(DEB)
    3.19 +
    3.20 +lcheck: 
    3.21 +	find -newer ../$(DEB)
    3.22 +
    3.23 +upload:
    3.24 +	upload
    3.25 +
    3.26 +lenny:
    3.27 +	upload-deb lenny/main $(DEB) 
    3.28 +
    3.29 +lenny-force:
    3.30 +	upload-deb -F lenny/main $(DEB) 
    3.31 +
    3.32 +dpkg:
    3.33 +	su root "dpkg -i ../$(DEB)"
    3.34 +
    3.35 +check:  lcheck
    3.36 +	find -newer uploaded
    3.37 +
    3.38 +ver:
    3.39 +	head -n1 debian/changelog
    3.40 +	echo dch -v
    3.41 +
    3.42 +clean:
    3.43 +	echo
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/TODO	Mon Apr 26 11:16:23 2010 +0200
     4.3 @@ -0,0 +1,17 @@
     4.4 +TODO (#### = fatto)
     4.5 +1. Debian: 
     4.6 +    Control
     4.7 +    ###Changelog
     4.8 +    README
     4.9 +    rules
    4.10 +
    4.11 +2. file di conf
    4.12 +    #### /etc/isi/*
    4.13 +    #### /etc/skel
    4.14 +    #### /etc/samba/smb.conf 
    4.15 +    /etc/ldap/ldap.conf
    4.16 +    /etc/ldap/slapd.conf
    4.17 +    #### samba.schema corretto
    4.18 +    /etc/smbldap-tools/*
    4.19 +    
    4.20 +3. ### Makefile (editare solo con jmacs)
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/checkup/isi-checkup	Mon Apr 26 11:16:23 2010 +0200
     5.3 @@ -0,0 +1,556 @@
     5.4 +#!/usr/bin/python
     5.5 +# coding: utf-8
     5.6 +"""
     5.7 +### DocString
     5.8 +Opzioni supportate
     5.9 +-------------------
    5.10 +
    5.11 +Gestire i template
    5.12 +~~~~~~~~~~~~~~~~~~
    5.13 +
    5.14 +isi-checkup -l
    5.15 +
    5.16 +* elenca i template disponibili
    5.17 +
    5.18 +isi-checkup -t NOMETEMPLATE
    5.19 +
    5.20 +* abilita tutti i test rel relativo template
    5.21 +* imposta il template scelto come template di default, salvando la preferenza
    5.22 +  nel file "/etc/isi/checkup/template-default".
    5.23 +
    5.24 +isi-checkup -T
    5.25 +
    5.26 +* Disabilita tutti i test attivi
    5.27 +* SE ESISTE "/etc/isi/checkup/template-default" abilita tutti i test del profilo
    5.28 +  impostato come default.
    5.29 +* SE NON ESISTE "/etc/isi/checkup/template-default" e dunque non è mai stato
    5.30 +  impostato un profilo di default, abilita tutti i test del profilo "isi".
    5.31 +
    5.32 +isi-checkup -r
    5.33 +
    5.34 +* disattiva tutti i test abilitati
    5.35 +
    5.36 +Tipi di test disponibili
    5.37 +~~~~~~~~~~~~~~~~~~~~~~~~
    5.38 +
    5.39 +isi-checkup -s
    5.40 +
    5.41 +* lancia SOLO i TEST DI SISTEMA (boot, servizi, ISI)
    5.42 +
    5.43 +isi-checkup -u UTENTE
    5.44 +
    5.45 +* lancia SOLO i TEST relativi all'UTENTE per l'UTENTE SPECIFICATO
    5.46 +
    5.47 +isi-checkup -U
    5.48 +
    5.49 +* lancia SOLO i test relativi all'UTENTE per TUTTI GLI UTENTI
    5.50 +
    5.51 +isi-checkup -L
    5.52 +
    5.53 +* lancia SOLO i TEST LOCALI (se creati dall'amministratore di sistema)
    5.54 +
    5.55 +isi-checkup -A
    5.56 +
    5.57 +* lancia TUTTI i test disponibili (Sistema, Utente, Locali)
    5.58 +
    5.59 +Altre opzioni
    5.60 +~~~~~~~~~~~~~
    5.61 +
    5.62 +isi-checkup -v
    5.63 +
    5.64 +* Mostra più informazioni relative ai test che vengono lanciati (verbose)
    5.65 +
    5.66 +isi-checkup -h
    5.67 +
    5.68 +* mostra le opzioni disponibili e ne fornisce una breve descrizione
    5.69 +###
    5.70 +"""
    5.71 +
    5.72 +from dry.utils import Container
    5.73 +import sys
    5.74 +
    5.75 +### isi-checkup option
    5.76 +USAGE = """
    5.77 +        usage: %prog [options]
    5.78 +        -t, --template=modello: imposta i test secondo il modello
    5.79 +        -T, --templateDefault: attiva i test del template di default
    5.80 +        -l, --list: elenca i template disponibili
    5.81 +        -r, --reset: disattiva tutti i test del template in uso
    5.82 +        -s, --system: lancia i test (boot, servizi, ISI)
    5.83 +        -u, --user=user: utente da testare
    5.84 +        -U, --users: lancia solo i test relativi agli utenti
    5.85 +        -L, --local: lancia solo i test locali
    5.86 +        -A, --all: lancia tutti i test
    5.87 +        -v, --verbose: be verbose
    5.88 +"""
    5.89 +
    5.90 +import os
    5.91 +import sys
    5.92 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
    5.93 +import re
    5.94 +from dry import optionparse
    5.95 +from dry.functions import execute
    5.96 +from checkup import IsiTest, TestError
    5.97 +from colorize import Colorize
    5.98 +import inspect
    5.99 +
   5.100 +class NotAtest(Exception):
   5.101 +    pass
   5.102 +
   5.103 +class Test(object):
   5.104 +    path_tests = '/usr/share/isi-checkup/tests'
   5.105 +    path_links = '/etc/isi/checkup'
   5.106 +
   5.107 +    def __init__(self, filename):
   5.108 +        pattern = '^(?P<order>\d+)+_(?P<name>.*)(?P<extension>.sh|.py)$'
   5.109 +        m = re.search(pattern, filename)
   5.110 +        if not m:
   5.111 +            raise NotAtest
   5.112 +        m = m.groupdict()
   5.113 +        self.filename = filename
   5.114 +        self.order = m['order']
   5.115 +        self.name = m['name']
   5.116 +        self.extension = m['extension']
   5.117 +        self.path_filename = '%s/%s' % (self.path_tests, filename)
   5.118 +        self.path_link = '%s/%s' % (self.path_links, filename)
   5.119 +
   5.120 +class TestList(Container):
   5.121 +    def del_element(self, key):
   5.122 +        if key in self._attrs:
   5.123 +            j = self._attrs.index(key)
   5.124 +            # Don't shift index if deleting a 'used' test
   5.125 +            if j < self._n:
   5.126 +                return
   5.127 +            self._attrs.pop(j)
   5.128 +            
   5.129 +class TestManager(object):
   5.130 +    """
   5.131 +    files
   5.132 +
   5.133 +    # TODO : trovare modo piu elegante per passare parametri a xrange()
   5.134 +    """
   5.135 +    path_tests = '/usr/share/isi-checkup/tests'
   5.136 +    path_links = '/etc/isi/checkup'
   5.137 +    path_templates = '/usr/share/isi-checkup'
   5.138 +    file_exclude = '/etc/isi/checkup/exclude'
   5.139 +    file_template_default = '/etc/isi/checkup/template-default'
   5.140 +
   5.141 +### Priority schema
   5.142 +    range_system = (0, 499)
   5.143 +    range_user = (500, 700)
   5.144 +    range_local = (701, 2000)
   5.145 +    range_any = (0, 2000)
   5.146 +
   5.147 +    range_all_tests = (0, 2000)
   5.148 +    range_tests = (0, 499)
   5.149 +
   5.150 +    msg_passed = Colorize('[ PASSATO ]').BOLD_GREEN
   5.151 +    msg_warning = Colorize('[ ATTENZIONE ]').BOLD_YELLOW
   5.152 +    msg_error = Colorize('[ ERRORE ]').BOLD_RED
   5.153 +
   5.154 +### Constructor
   5.155 +    def __init__(self):
   5.156 +        self.failed_tests = []
   5.157 +        self.set_range()
   5.158 +        self.excluded = self.get_excluded()
   5.159 +        self.tests = self.get_tests_enabled()
   5.160 +        
   5.161 +    def set_range(self):
   5.162 +        if opts.template:
   5.163 +            # if wrong template given
   5.164 +            if self.set_template(opts.template) == True:
   5.165 +                sys.exit(1)
   5.166 +            f = open(self.file_template_default, 'w')
   5.167 +            f.write(opts.template)
   5.168 +            f.close()
   5.169 +
   5.170 +            sys.exit(0)
   5.171 +        
   5.172 +        elif opts.templateDefault:
   5.173 +            # se non viene specificato 
   5.174 +            template = 'isi'
   5.175 +            if os.path.isfile(self.file_template_default):
   5.176 +                # Using Default template file found.
   5.177 +                f = open(self.file_template_default)
   5.178 +                for line in f.readlines():
   5.179 +                    if re.search('^$', line):
   5.180 +                        continue
   5.181 +                    template = line
   5.182 +            self.reset_templates()
   5.183 +            self.set_template(template)
   5.184 +            sys.exit(0)
   5.185 +            
   5.186 +        elif opts.list:
   5.187 +            for t in self.get_templates(): print t
   5.188 +            sys.exit(0)
   5.189 +
   5.190 +        elif opts.reset:
   5.191 +            self.reset_templates()
   5.192 +            sys.exit(0)
   5.193 +
   5.194 +        else:
   5.195 +            # setting range
   5.196 +
   5.197 +            if opts.system:
   5.198 +                self.range_tests = self.range_system
   5.199 +
   5.200 +            if opts.user:
   5.201 +                self.range_tests = self.range_user
   5.202 +
   5.203 +            if opts.users:
   5.204 +                self.range_tests = self.range_user
   5.205 +
   5.206 +            if opts.local:
   5.207 +                self.range_tests = self.range_local
   5.208 +
   5.209 +            if opts.all:
   5.210 +                self.range_tests = self.range_any
   5.211 +
   5.212 +
   5.213 +### Templates Setting
   5.214 +    def get_template_tests(self, template=None):
   5.215 +	""" Returns list of tests in templates """
   5.216 +        path = self.path_templates
   5.217 +        tests = []
   5.218 +
   5.219 +        if template:
   5.220 +            templates = ('%s.conf' % template).split()
   5.221 +        else:
   5.222 +            templates = os.listdir(path)
   5.223 +        for template in templates:
   5.224 +            pattern = '^(?P<name>.*)(?P<extension>.conf)$'
   5.225 +            m = re.search(pattern, template)
   5.226 +
   5.227 +            if not m:
   5.228 +                continue
   5.229 +            if not os.path.isfile('%s/%s' % (path, template)):
   5.230 +                continue
   5.231 +
   5.232 +            f = open('%s/%s' % (path, template))
   5.233 +            for line in f.readlines():
   5.234 +		line = line.strip()
   5.235 +                if line == '':
   5.236 +                    continue
   5.237 +                tests.append(line)
   5.238 +        return tests
   5.239 +
   5.240 +    def get_templates(self):
   5.241 +        """ Returns list of the Available Templates """
   5.242 +        path = self.path_templates
   5.243 +        templates = []
   5.244 +        for template in os.listdir(path):
   5.245 +            pattern = '^(?P<name>.*)(?P<extension>.conf)$'
   5.246 +            m = re.search(pattern, template)
   5.247 +            if not m:
   5.248 +                continue
   5.249 +            m = m.groupdict()
   5.250 +            test_name = m['name']
   5.251 +            templates.append(test_name)
   5.252 +        return templates
   5.253 +
   5.254 +    def set_template(self, template):
   5.255 +        """
   5.256 +        Adds test symlinks for the given template
   5.257 +
   5.258 +        Return True if given template's wrong
   5.259 +        """        
   5.260 +	# PATH definition
   5.261 +	path_test = self.path_tests
   5.262 +        path_link = self.path_links
   5.263 +        tests = self.get_template_tests(template)
   5.264 +        linked_tests = []
   5.265 +        for test in tests:
   5.266 +            link_src =  '/'.join([path_test, test])
   5.267 +            link_dest = '/'.join([path_link, test])
   5.268 +            if os.path.isfile(link_dest):
   5.269 +                continue
   5.270 +            os.symlink(link_src, link_dest)
   5.271 +            print ' Aggiunto test "%s"' % test            
   5.272 +            linked_tests.append(test)
   5.273 +
   5.274 +        if linked_tests:
   5.275 +            #print '\n Test aggiunti: ', linked_tests
   5.276 +            pass
   5.277 +        elif tests:
   5.278 +            print '\n Nessun altro test da aggiungere per il template "%s"\n' % template
   5.279 +        else:
   5.280 +            print 'Template sconosciuto "%s"' % template
   5.281 +            return True
   5.282 +            
   5.283 +    def is_to_be_deleted(self, order_number):
   5.284 +        if int(order_number) > 1000:
   5.285 +            return False
   5.286 +        else:
   5.287 +            return True
   5.288 +                            
   5.289 +    def reset_templates(self):
   5.290 +        """ Resets template deleting links to tests """
   5.291 +        path = self.path_links
   5.292 +        files = os.listdir(path)
   5.293 +        files_removed = []
   5.294 +
   5.295 +        for f in files:
   5.296 +            path_filename = '%s/%s' % (path, f)
   5.297 +            pattern = '^(?P<order>\d+)+_(?P<name>.*)(?P<extension>.sh|.py)$'
   5.298 +            m = re.search(pattern, f)
   5.299 +            if not m:
   5.300 +                continue
   5.301 +            m = m.groupdict()
   5.302 +            order = m['order']
   5.303 +            name = m['name']
   5.304 +            extension = m['extension']
   5.305 +            if not self.is_to_be_deleted(order):
   5.306 +                continue
   5.307 +            if not os.path.islink(path_filename):
   5.308 +                continue
   5.309 +            os.remove(path_filename)
   5.310 +            files_removed.append(f)
   5.311 +
   5.312 +        print '%s test disabilitati' % files_removed.__len__()
   5.313 +        
   5.314 +### Test Run
   5.315 +    def exec_test_python(self, test):
   5.316 +        # Eseguo script python
   5.317 +        for isi_test in self.get_isitest(test):
   5.318 +            try:
   5.319 +                obj = isi_test(user=opts.user)
   5.320 +            except Exception, e:
   5.321 +                print e
   5.322 +                continue
   5.323 +            if opts.verbose:
   5.324 +                print test.order, obj
   5.325 +            for key, meth in self.get_test_methods(obj):
   5.326 +                try:
   5.327 +                    ## i metodi ritornano un booleano
   5.328 +                    if not meth():
   5.329 +                        self.failed_tests += [(obj.name, test)]
   5.330 +                        self.skip_dependant(obj)
   5.331 +                except Exception, e:
   5.332 +                    e.obj = obj
   5.333 +                    e.method = meth
   5.334 +                    print test.order, e
   5.335 +                    #raise e
   5.336 +                obj.report()
   5.337 +    def exec_test_bash(self, test):
   5.338 +        # Eseguo script bash
   5.339 +
   5.340 +        if opts.verbose:
   5.341 +            print test.order, test.name #test.name
   5.342 +        if opts.user:
   5.343 +            ret_code, out, err = execute([test.path_link, opts.user])
   5.344 +        else:
   5.345 +            ret_code, out, err = execute([test.path_link])
   5.346 +                
   5.347 +        if ret_code:
   5.348 +            print out
   5.349 +            self.failed_tests += [(test.name, test)]
   5.350 +
   5.351 +            if opts.verbose:
   5.352 +                print "ERRORI:\n"+err
   5.353 +
   5.354 +    def skip_dependant(self, obj):
   5.355 +        if isinstance(obj.skip, (str, unicode)):
   5.356 +            skip = obj.skip.split()
   5.357 +        else:
   5.358 +            skip = obj.skip
   5.359 +            
   5.360 +        for key in skip:
   5.361 +            self.tests.del_element(key)
   5.362 +
   5.363 +        for key in self.expand(obj.skip_range):
   5.364 +            key = str(key)
   5.365 +            self.tests.del_element(key)
   5.366 +
   5.367 +    def expand(self, range):
   5.368 +        ## FIXME
   5.369 +        start, stop = range
   5.370 +        return str(start)
   5.371 +    
   5.372 +    def get_test_methods(self, obj):
   5.373 +        meths = []
   5.374 +        for key in dir(obj):
   5.375 +            if not key.startswith('test'):
   5.376 +                continue
   5.377 +            attr =  getattr(obj, key)
   5.378 +            if inspect.ismethod(attr):
   5.379 +                meths += [(key, attr)]
   5.380 +        return meths
   5.381 +
   5.382 +    def get_isitest(self, test):
   5.383 +        GLOB = {}
   5.384 +        tests = []
   5.385 +        execfile(test.path_link, GLOB)
   5.386 +        for key, elem in GLOB.iteritems():
   5.387 +            if inspect.isclass(elem) and issubclass(elem, IsiTest):
   5.388 +                if elem.run:
   5.389 +                    tests += [elem]
   5.390 +        return tests
   5.391 +
   5.392 +    def is_to_be_run(self, test):
   5.393 +
   5.394 +        name = "%s%s" % (test.name, test.extension)
   5.395 +        if name in self.excluded:
   5.396 +            return False
   5.397 +        # xrange(*self.range_test) ;-) è più breve, non più leggibile...
   5.398 +        start, end = self.range_tests
   5.399 +        if not int(test.order) in xrange(start, end):  
   5.400 +            return False
   5.401 +        else:
   5.402 +            return True
   5.403 +
   5.404 +    def run(self):
   5.405 +        """ Launches tests in self.test """
   5.406 +
   5.407 +        for test in self.tests:
   5.408 +            if test.filename.endswith(".py"):
   5.409 +                self.exec_test_python(test)
   5.410 +                
   5.411 +            if test.filename.endswith(".sh"):
   5.412 +                self.exec_test_bash(test)
   5.413 +
   5.414 +    def get_excluded(self):
   5.415 +        """ Returns exclude list
   5.416 +        es.
   5.417 +        ['need_process_dansguardian.py', 'need_process_master.py']
   5.418 +        """
   5.419 +        file_exclude = self.file_exclude
   5.420 +        exclude = [] # test *NAME*
   5.421 +
   5.422 +        if not os.path.exists(file_exclude):
   5.423 +            return exclude
   5.424 +        ## Adding exclude-file tests to exclude list
   5.425 +        f  = open(file_exclude)
   5.426 +        for line in f.readlines():
   5.427 +            # skips emtpy line
   5.428 +            if re.match('^$', line):
   5.429 +                continue
   5.430 +            exclude.append(line.split()[0])
   5.431 +
   5.432 +            test_name = line.split()[0]
   5.433 +
   5.434 +        exclude_dep = self.test2exclude_dep(exclude)
   5.435 +        exclude += exclude_dep
   5.436 +
   5.437 +        return exclude
   5.438 +
   5.439 +    def get_tests_enabled(self):
   5.440 +        """
   5.441 +        Returns a dictionary composed as follows:
   5.442 +        { order : testObject }
   5.443 +        """
   5.444 +        tests = TestList()
   5.445 +        
   5.446 +        for filename in sorted(os.listdir(self.path_links)):
   5.447 +            try:
   5.448 +                test = Test(filename)
   5.449 +            except Exception:
   5.450 +                continue
   5.451 +            
   5.452 +            if self.is_to_be_run(test):
   5.453 +                tests[test.order] = test
   5.454 +                
   5.455 +        return tests
   5.456 +
   5.457 +    def _test2exclude_get_name(self, numbers):
   5.458 +        """ Returns filename list for the provided *numbers* of the test
   5.459 +            es.
   5.460 +              012_test.py
   5.461 +        """
   5.462 +
   5.463 +        path = self.path_links
   5.464 +        pattern = '^(?P<order>\d+)+_(?P<name>.*)(?P<extension>.sh|.py)$'
   5.465 +        test_dict = {}        
   5.466 +        test_list = []
   5.467 +        for filename in os.listdir(path):
   5.468 +            m = re.search(pattern, filename)
   5.469 +            if not m:
   5.470 +                continue
   5.471 +            m = m.groupdict()
   5.472 +            order, extension, name = m.itervalues()
   5.473 +            
   5.474 +            test_filename = '%s%s' % (name, extension)
   5.475 +            test_dict[order] = test_filename
   5.476 +
   5.477 +        for number in numbers:
   5.478 +            test_list += [test_dict[number]]
   5.479 +
   5.480 +        return test_list
   5.481 +
   5.482 +
   5.483 +    def _test2exclude_get_pathfilename(self, test_name_list):
   5.484 +        """ Returns *complete* path+filename for test
   5.485 +            Returns None if test not found in path
   5.486 +            es.
   5.487 +              /etc/isi/checkup/tests/112_test.py
   5.488 +        """
   5.489 +        path = self.path_links
   5.490 +        path_filename_list = []
   5.491 +        
   5.492 +        for test_name in test_name_list:
   5.493 +            pattern = '^(?P<order>\d+)+_(?P<name>.*)(?P<extension>.sh|.py)$'
   5.494 +#            test_list = {}
   5.495 +            for filename in os.listdir(path):
   5.496 +                m = re.search(pattern, filename)
   5.497 +                if not m:
   5.498 +                    continue
   5.499 +                m = m.groupdict()
   5.500 +                order, extension, name = m.itervalues()
   5.501 +                
   5.502 +                path_filename = '%s/%s_%s%s' % (path, order, name, extension) 
   5.503 +
   5.504 +                if test_name == '%s%s' % (name, extension): 
   5.505 +                    path_filename_list += [path_filename]
   5.506 +                else:
   5.507 +                    continue
   5.508 +        return path_filename_list
   5.509 +    
   5.510 +    def _test2exclude_get_skips(self, path_filename_list):
   5.511 +        """ Looks in the provided *path_filename_list* for skips
   5.512 +            returning a skip list
   5.513 +
   5.514 +            es.
   5.515 +            ['11', '22', '33', '44', '55', '66', '77', '88', '99']
   5.516 +        """
   5.517 +        GLOB = {}
   5.518 +        skip_list = []
   5.519 +
   5.520 +        for path_filename in path_filename_list:
   5.521 +            execfile(path_filename, GLOB)
   5.522 +            
   5.523 +            for key, elem in GLOB.iteritems():
   5.524 +                if inspect.isclass(elem) and issubclass(elem, IsiTest):
   5.525 +                    if hasattr(elem, 'skip') and elem.skip:
   5.526 +                        skip_list += elem.skip.split()
   5.527 +        return skip_list
   5.528 +
   5.529 +
   5.530 +    def test2exclude_dep(self, exclude):
   5.531 +        """ Creates and returns the Dependent Test path_filename list """
   5.532 +        path_filename_list = []
   5.533 +        tests_to_exclude = []
   5.534 +        
   5.535 +        path_filename_list = self._test2exclude_get_pathfilename(exclude)
   5.536 +        #['/etc/isi/checkup/266_need_process_dansguardian.py', '/etc/isi/checkup/267_need_process_master.py'
   5.537 +            
   5.538 +        skip_list = self._test2exclude_get_skips(path_filename_list)
   5.539 +        
   5.540 +        tests_to_exclude = self._test2exclude_get_name(skip_list)
   5.541 +        
   5.542 +        return tests_to_exclude
   5.543 +
   5.544 +
   5.545 +
   5.546 +### Main ####
   5.547 +opts, args = optionparse.parse(USAGE)
   5.548 +
   5.549 +isi_test = TestManager()
   5.550 +isi_test.run()
   5.551 +
   5.552 +### Print Report
   5.553 +if isi_test.failed_tests:
   5.554 +    msg = '\nI seguenti test non sono andati a buon fine'
   5.555 +    print Colorize(msg).BOLD_RED_U
   5.556 +    #print '-'*len(msg)
   5.557 +    for test_obj, test in isi_test.failed_tests:
   5.558 +        print "%-40s %s" % (test.name + test.extension, test_obj)
   5.559 +###
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/debian/README	Mon Apr 26 11:16:23 2010 +0200
     6.3 @@ -0,0 +1,6 @@
     6.4 +The Debian Package isi
     6.5 +----------------------------
     6.6 +
     6.7 +Comments regarding the Package
     6.8 +
     6.9 + -- Sandro Dentella <[email protected]>  Mon, 15 Feb 2022 17:18:50 +0100
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/debian/README.Debian	Mon Apr 26 11:16:23 2010 +0200
     7.3 @@ -0,0 +1,6 @@
     7.4 +isi for Debian
     7.5 +--------------
     7.6 +
     7.7 +<possible notes regarding this package - if none, delete this file>
     7.8 +
     7.9 + -- Sandro Dentella <[email protected]>  Mon, 15 Feb 2022 17:18:50 +0100
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/debian/changelog	Mon Apr 26 11:16:23 2010 +0200
     8.3 @@ -0,0 +1,162 @@
     8.4 +isi (2.7.3) hardy; urgency=low
     8.5 +
     8.6 +  * web for printers: fix when administrator has a different password form
     8.7 +    ldap admin
     8.8 +
     8.9 + -- Sandro Dentella <[email protected]>  Fri, 23 Apr 2021 11:32:57 +0200
    8.10 +
    8.11 +isi (2.7.2) hardy; urgency=low
    8.12 +
    8.13 +  * ora logon.pl non è più considerato un modulo di configurazione
    8.14 +
    8.15 + -- Sandro Dentella <[email protected]>  Wed, 21 Apr 2021 16:50:37 +0200
    8.16 +
    8.17 +isi (2.7.1) hardy; urgency=low
    8.18 +
    8.19 +  * fix stampanti mancanti
    8.20 +
    8.21 + -- Sandro Dentella <[email protected]>  Tue, 20 Apr 2021 16:56:06 +0200
    8.22 +
    8.23 +isi (2.7) hardy; urgency=low
    8.24 +
    8.25 +  * printers with web interface, UserPrinter/PcPrinter
    8.26 +
    8.27 + -- Sandro Dentella <[email protected]>  Mon, 19 Apr 2021 18:53:08 +0200
    8.28 +
    8.29 +isi (2.6) hardy; urgency=low
    8.30 +
    8.31 +  * grub4dos, printers, web per IE
    8.32 +
    8.33 + -- Sandro Dentella <[email protected]>  Sun, 18 Apr 2021 18:31:30 +0200
    8.34 +
    8.35 +isi (2.5.10) hardy; urgency=low
    8.36 +
    8.37 +  * fix classse minuscola + permessi isi-alulink 
    8.38 +
    8.39 + -- Sandro Dentella <[email protected]>  Wed, 14 Apr 2021 00:51:49 +0200
    8.40 +
    8.41 +isi (2.5.9) hardy; urgency=low
    8.42 +
    8.43 +  * fix in xls parser
    8.44 +
    8.45 + -- Sandro Dentella <[email protected]>  Tue, 13 Apr 2021 15:01:49 +0200
    8.46 +
    8.47 +isi (2.5.8) hardy; urgency=low
    8.48 +
    8.49 +  * important fix in dnsmasq configuration save
    8.50 +
    8.51 + -- Sandro Dentella <[email protected]>  Tue, 13 Apr 2021 12:13:05 +0200
    8.52 +
    8.53 +isi (2.5.7) hardy; urgency=low
    8.54 +
    8.55 +  * fix convert
    8.56 +
    8.57 + -- Sandro Dentella <[email protected]>  Mon, 12 Apr 2022 20:16:59 +0200
    8.58 +
    8.59 +isi (2.5.6) hardy; urgency=low
    8.60 +
    8.61 +  * fixes: new_passwd -> new_password
    8.62 +
    8.63 + -- Sandro Dentella <[email protected]>  Mon, 12 Apr 2022 19:09:33 +0200
    8.64 +
    8.65 +isi (2.5.5) hardy; urgency=low
    8.66 +
    8.67 +  * web interfaces fixes: dnsmasq + missing object template
    8.68 +
    8.69 + -- Sandro Dentella <[email protected]>  Mon, 12 Apr 2022 12:04:35 +0200
    8.70 +
    8.71 +isi (2.5.4) hardy; urgency=low
    8.72 +
    8.73 +  * minor fixes
    8.74 +
    8.75 + -- Sandro Dentella <[email protected]>  Sun, 11 Apr 2022 20:23:48 +0200
    8.76 +
    8.77 +isi (2.5.3) hardy; urgency=low
    8.78 +
    8.79 +  * web interface from code
    8.80 +
    8.81 + -- Sandro Dentella <[email protected]>  Sun, 11 Apr 2022 17:46:08 +0200
    8.82 +
    8.83 +isi (2.5.2) hardy; urgency=low
    8.84 +
    8.85 +  * migliorata gestione errori web e dipendenze. Isi-alulink in python
    8.86 +
    8.87 + -- Sandro Dentella <[email protected]>  Sun, 11 Apr 2022 13:00:31 +0200
    8.88 +
    8.89 +isi (2.5.1) hardy; urgency=low
    8.90 +
    8.91 +  * fix postinst
    8.92 +
    8.93 + -- Sandro Dentella <[email protected]>  Sat, 10 Apr 2022 23:29:13 +0200
    8.94 +
    8.95 +isi (2.5) hardy; urgency=low
    8.96 +
    8.97 +  * vari fix e migliorie all'interfaccia web
    8.98 +
    8.99 + -- Sandro Dentella <[email protected]>  Sat, 10 Apr 2022 23:17:18 +0200
   8.100 +
   8.101 +isi (2.4.2) hardy; urgency=low
   8.102 +
   8.103 +  * fix vari: cambo passwd/IsiUser -> Manager
   8.104 +
   8.105 + -- Sandro Dentella <[email protected]>  Wed, 07 Apr 2022 15:35:23 +0200
   8.106 +
   8.107 +isi (2.4.1) hardy; urgency=low
   8.108 +
   8.109 +  * navigazione
   8.110 +
   8.111 + -- Sandro Dentella <[email protected]>  Tue, 06 Apr 2022 23:11:36 +0200
   8.112 +
   8.113 +isi (2.4) hardy; urgency=low
   8.114 +
   8.115 +  * aggiunta quota e creazione link
   8.116 +
   8.117 + -- Sandro Dentella <[email protected]>  Tue, 06 Apr 2022 16:56:32 +0200
   8.118 +
   8.119 +isi (2.3) hardy; urgency=low
   8.120 +
   8.121 +  * isi-adduser + isi-convert in interfaccia web
   8.122 +
   8.123 + -- Sandro Dentella <[email protected]>  Thu, 01 Apr 2022 21:19:43 +0200
   8.124 +
   8.125 +isi (2.2.2) hardy; urgency=low
   8.126 +
   8.127 +  * qualche fix
   8.128 +
   8.129 + -- Sandro Dentella <[email protected]>  Fri, 26 Mar 2022 02:36:48 +0100
   8.130 +
   8.131 +isi (2.2.1) hardy; urgency=low
   8.132 +
   8.133 +  * defaults.py in /etc/isi + aggiunto quiet=False in get_user
   8.134 +
   8.135 + -- Sandro Dentella <[email protected]>  Wed, 24 Mar 2022 13:07:54 +0100
   8.136 +
   8.137 +isi (2.2) hardy; urgency=low
   8.138 +
   8.139 +  * fixes on isi-adduser
   8.140 +
   8.141 + -- Sandro Dentella <[email protected]>  Wed, 24 Mar 2022 12:00:22 +0100
   8.142 +
   8.143 +isi (2.1-2) hardy; urgency=low
   8.144 +
   8.145 +  * fix docs
   8.146 +
   8.147 + -- Sandro Dentella <[email protected]>  Tue, 23 Mar 2022 16:36:18 +0100
   8.148 +
   8.149 +isi (2.1) hardy; urgency=low
   8.150 +
   8.151 +  * complete rewrite of python library based on pumpkin
   8.152 +
   8.153 + -- Sandro Dentella <[email protected]>  Mon, 22 Mar 2022 16:01:15 +0100
   8.154 +
   8.155 +isi (2.0.1) hardy; urgency=low
   8.156 +
   8.157 +  * fix in isi-domain - isi-setup  (Simone)
   8.158 +
   8.159 + -- Sandro Dentella <[email protected]>  Sun, 28 Feb 2022 21:13:21 +0100
   8.160 +
   8.161 +isi (2.0) unstable; urgency=low
   8.162 +
   8.163 +  * Initial Release.
   8.164 +
   8.165 + -- Sandro Dentella <[email protected]>  Mon, 15 Feb 2022 17:18:50 +0100
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/debian/compat	Mon Apr 26 11:16:23 2010 +0200
     9.3 @@ -0,0 +1,1 @@
     9.4 +5
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/debian/control	Mon Apr 26 11:16:23 2010 +0200
    10.3 @@ -0,0 +1,56 @@
    10.4 +Source: isi
    10.5 +Section: isi
    10.6 +Priority: extra
    10.7 +Maintainer: Sandro Dentella <[email protected]>
    10.8 +Build-Depends: cdbs, debhelper (>= 5)
    10.9 +Standards-Version: 3.7.2
   10.10 +
   10.11 +Package: isi
   10.12 +Architecture: all
   10.13 +Depends: at, acl, quota, tofrodos, 
   10.14 +  procinfo, reiserfsprogs, xfsprogs, slapd, libnss-ldap, libpam-ldap,
   10.15 +  libnet-ldap-perl, samba, smbldap-tools, migrationtools, db4.2-util, 
   10.16 +  libcrack2|cracklib2, python-ldap, python-dry, python-urwid, python-smbpasswd,
   10.17 +  win-perl, isi, mercurial, nscd, python-pumpkin, lsb-release,
   10.18 +  libcompress-zlib-perl, python-xlrd, python-isi (>= 2.7.3), smbclient
   10.19 +Conflicts: isi-ldap3-def,  isi-ldap3,  isi-logon,  isi-perl, isi-setup
   10.20 +Replaces: isi-ldap3-def,  isi-ldap3,  isi-logon,  isi-perl
   10.21 +Description: all you need to setup and manage a pdc samba+ldap at school
   10.22 + 
   10.23 +Package: python-isi
   10.24 +Architecture: all
   10.25 +Provides: python-isi
   10.26 +Depends: python-ldap, python-pexpect, isi (>= 2.7.3)
   10.27 +XB-Python-Version: ${python:Versions}
   10.28 +Description: python modules for isi project
   10.29 + Questa versione dipende da python 2.5 o successivi
   10.30 +
   10.31 +Package: isi-docs
   10.32 +Architecture: all
   10.33 +Depends: 
   10.34 +Description: documentazione progetto reteisi
   10.35 + Documentazione completa del pacchetto reteisi.
   10.36 + Al momento è possibile sfogliare la documentazione dal sito:
   10.37 +    http://reteisi.argolinux.org
   10.38 +
   10.39 +Package: isi-checkup
   10.40 +Architecture: all
   10.41 +Depends: python-dry, python-isi (>= 2.7.3)
   10.42 +Description: suite di checkup per un sistema ReteIsi
   10.43 +  il sistema fornisce una struttura per potere gestire una serie di test
   10.44 +  per fare un checkup al sistema
   10.45 +
   10.46 +Package: isi-web
   10.47 +Architecture: all
   10.48 +Depends: python-django (>=1.2), python-vov (>= 0.8.5), isi (>=2.7.3),  
   10.49 +  isi-docs (>=2.7.3),
   10.50 +  libapache2-mod-fastcgi, python-dry, ipython, python-flup, apache2
   10.51 +Description: Interfaccia web per amministrazione ReteISI
   10.52 +  Interfaccia web per amministrazione ReteISI comprensivo di
   10.53 +  .
   10.54 +  * cambio nome dominio
   10.55 +  * configurazione logon.conf
   10.56 +  * gestione utenti
   10.57 +  * gestione dns/boot options
   10.58 +  * controllo navigazione classi (non squid/dansguardian)
   10.59 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/debian/copyright	Mon Apr 26 11:16:23 2010 +0200
    11.3 @@ -0,0 +1,40 @@
    11.4 +This package was debianized by Sandro Dentella <[email protected]> on
    11.5 +Mon, 15 Feb 2022 17:18:50 +0100.
    11.6 +
    11.7 +It was downloaded from <url://example.com>
    11.8 +
    11.9 +Upstream Author(s): 
   11.10 +
   11.11 +    <put author's name and email here>
   11.12 +    <likewise for another author>
   11.13 +
   11.14 +Copyright: 
   11.15 +
   11.16 +    <Copyright (C) YYYY Name OfAuthor>
   11.17 +    <likewise for another author>
   11.18 +
   11.19 +License:
   11.20 +
   11.21 +    This package is free software; you can redistribute it and/or modify
   11.22 +    it under the terms of the GNU General Public License as published by
   11.23 +    the Free Software Foundation; either version 2 of the License, or
   11.24 +    (at your option) any later version.
   11.25 + 
   11.26 +    This package is distributed in the hope that it will be useful,
   11.27 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.28 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.29 +    GNU General Public License for more details.
   11.30 + 
   11.31 +    You should have received a copy of the GNU General Public License
   11.32 +    along with this package; if not, write to the Free Software
   11.33 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
   11.34 +
   11.35 +On Debian systems, the complete text of the GNU General
   11.36 +Public License can be found in `/usr/share/common-licenses/GPL'.
   11.37 +
   11.38 +The Debian packaging is (C) 2010, Sandro Dentella <[email protected]> and
   11.39 +is licensed under the GPL, see above.
   11.40 +
   11.41 +
   11.42 +# Please also look if there are files or directories which have a
   11.43 +# different copyright/license attached and list them here.
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/debian/files	Mon Apr 26 11:16:23 2010 +0200
    12.3 @@ -0,0 +1,5 @@
    12.4 +isi_2.7.3_all.deb isi extra
    12.5 +python-isi_2.7.3_all.deb isi extra
    12.6 +isi-docs_2.7.3_all.deb isi extra
    12.7 +isi-checkup_2.7.3_all.deb isi extra
    12.8 +isi-web_2.7.3_all.deb isi extra
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/debian/isi-checkup.1	Mon Apr 26 11:16:23 2010 +0200
    13.3 @@ -0,0 +1,59 @@
    13.4 +.\"                                      Hey, EMACS: -*- nroff -*-
    13.5 +.\" First parameter, NAME, should be all caps
    13.6 +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
    13.7 +.\" other parameters are allowed: see man(7), man(1)
    13.8 +.TH ISI-CHECKUP SECTION "aprile 11, 2008"
    13.9 +.\" Please adjust this date whenever revising the manpage.
   13.10 +.\"
   13.11 +.\" Some roff macros, for reference:
   13.12 +.\" .nh        disable hyphenation
   13.13 +.\" .hy        enable hyphenation
   13.14 +.\" .ad l      left justify
   13.15 +.\" .ad b      justify to both left and right margins
   13.16 +.\" .nf        disable filling
   13.17 +.\" .fi        enable filling
   13.18 +.\" .br        insert line break
   13.19 +.\" .sp <n>    insert n+1 empty lines
   13.20 +.\" for manpage-specific macros, see man(7)
   13.21 +.SH NAME
   13.22 +isi-checkup \- suite di test estendibile
   13.23 +.SH SYNOPSIS
   13.24 +.B isi-checkup
   13.25 +.RI [  ] " files" ...
   13.26 +.br
   13.27 +.B bar
   13.28 +.RI [ options ] " files" ...
   13.29 +.SH DESCRIPTION
   13.30 +This manual page documents briefly the
   13.31 +.B isi-checkup
   13.32 +and
   13.33 +.B bar
   13.34 +commands.
   13.35 +.PP
   13.36 +.\" TeX users may be more comfortable with the \fB<whatever>\fP and
   13.37 +.\" \fI<whatever>\fP escape sequences to invode bold face and italics, 
   13.38 +.\" respectively.
   13.39 +\fBisi-checkup\fP is a program that...
   13.40 +.SH OPTIONS
   13.41 +These programs follow the usual GNU command line syntax, with long
   13.42 +options starting with two dashes (`-').
   13.43 +A summary of options is included below.
   13.44 +For a complete description, see the Info files.
   13.45 +.TP
   13.46 +.B \-h, \-\-help
   13.47 +Show summary of options.
   13.48 +.TP
   13.49 +.B \-v, \-\-version
   13.50 +Show version of program.
   13.51 +.SH SEE ALSO
   13.52 +.BR bar (1),
   13.53 +.BR baz (1).
   13.54 +.br
   13.55 +The programs are documented fully by
   13.56 +.IR "The Rise and Fall of a Fooish Bar" ,
   13.57 +available via the Info system.
   13.58 +.SH AUTHOR
   13.59 +isi-checkup was written by <upstream author>.
   13.60 +.PP
   13.61 +This manual page was written by Alessandro Dentella <[email protected]>,
   13.62 +for the Debian project (but may be used by others).
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/debian/isi-checkup.install	Mon Apr 26 11:16:23 2010 +0200
    14.3 @@ -0,0 +1,2 @@
    14.4 +checkup/isi-checkup usr/sbin
    14.5 +usr/share/isi-checkup /usr/share/
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/debian/isi-checkup.manpages	Mon Apr 26 11:16:23 2010 +0200
    15.3 @@ -0,0 +1,1 @@
    15.4 +debian/isi-checkup.1
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/debian/isi-checkup.postinst	Mon Apr 26 11:16:23 2010 +0200
    16.3 @@ -0,0 +1,43 @@
    16.4 +#!/bin/sh
    16.5 +# postinst script for isi
    16.6 +#
    16.7 +# see: dh_installdeb(1)
    16.8 +
    16.9 +set -e
   16.10 +
   16.11 +# summary of how this script can be called:
   16.12 +#        * <postinst> `configure' <most-recently-configured-version>
   16.13 +#        * <old-postinst> `abort-upgrade' <new version>
   16.14 +#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
   16.15 +#          <new-version>
   16.16 +#        * <postinst> `abort-remove'
   16.17 +#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
   16.18 +#          <failed-install-package> <version> `removing'
   16.19 +#          <conflicting-package> <version>
   16.20 +# for details, see http://www.debian.org/doc/debian-policy/ or
   16.21 +# the debian-policy package
   16.22 +
   16.23 +
   16.24 +case "$1" in
   16.25 +    configure)
   16.26 +	mkdir -p /etc/isi/checkup
   16.27 +	isi-checkup -T 
   16.28 +    ;;
   16.29 +
   16.30 +    abort-upgrade|abort-remove|abort-deconfigure)
   16.31 +    ;;
   16.32 +
   16.33 +    *)
   16.34 +        echo "postinst called with unknown argument \`$1'" >&2
   16.35 +        exit 1
   16.36 +    ;;
   16.37 +esac
   16.38 +
   16.39 +# dh_installdeb will replace this with shell code automatically
   16.40 +# generated by other debhelper scripts.
   16.41 +
   16.42 +#DEBHELPER#
   16.43 +
   16.44 +exit 0
   16.45 +
   16.46 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/debian/isi-web.install	Mon Apr 26 11:16:23 2010 +0200
    17.3 @@ -0,0 +1,7 @@
    17.4 +etc/apache2 /etc/
    17.5 +etc/init.d/isiweb /etc/init.d
    17.6 +etc/default etc
    17.7 +web/logon web/samba web/dnsmasq web/navigazione web/users web/templates  usr/share/isi/isiweb
    17.8 +web/urls.py web/manage.py web/__init__.py web/logger.py web/static web/ldap-auth.py usr/share/isi/isiweb
    17.9 +
   17.10 +web/settings.py web/local_settings.py usr/share/doc/isi-web
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/debian/isi-web.links	Mon Apr 26 11:16:23 2010 +0200
    18.3 @@ -0,0 +1,3 @@
    18.4 +/etc/isi/web/settings.py        usr/share/isi/isiweb/settings.py  
    18.5 +/etc/isi/web/local_settings.py  usr/share/isi/isiweb/local_settings.py  
    18.6 +var/cache/isiweb/mako_modules  usr/share/isi/isiweb/mako_modules
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/debian/isi-web.postinst	Mon Apr 26 11:16:23 2010 +0200
    19.3 @@ -0,0 +1,73 @@
    19.4 +#!/bin/bash
    19.5 +# postinst script for isi
    19.6 +#
    19.7 +# see: dh_installdeb(1)
    19.8 +
    19.9 +set -e
   19.10 +
   19.11 +# summary of how this script can be called:
   19.12 +#        * <postinst> `configure' <most-recently-configured-version>
   19.13 +#        * <old-postinst> `abort-upgrade' <new version>
   19.14 +#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
   19.15 +#          <new-version>
   19.16 +#        * <postinst> `abort-remove'
   19.17 +#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
   19.18 +#          <failed-install-package> <version> `removing'
   19.19 +#          <conflicting-package> <version>
   19.20 +# for details, see http://www.debian.org/doc/debian-policy/ or
   19.21 +# the debian-policy package
   19.22 +
   19.23 +function start_isiweb () {
   19.24 +    a2enmod rewrite
   19.25 +    a2enmod expires
   19.26 +    a2enmod fastcgi
   19.27 +#    a2dissite 000-default || true
   19.28 +    a2dissite isiweb-all.conf
   19.29 +    a2ensite isiweb.conf
   19.30 +    /etc/init.d/apache2 reload
   19.31 +    update-rc.d isiweb start 20 2 . stop 80 2 .
   19.32 +    mkdir -p /var/cache/isiweb/mako_modules
   19.33 +    PTH_DIR=/usr/lib/python2.5/site-packages
   19.34 +    if [ -d $PTH_DIR ] ; then
   19.35 +	echo /usr/share/isi > $PTH_DIR/isi.pth
   19.36 +    fi
   19.37 +
   19.38 +    mkdir -p /etc/isi/web
   19.39 +    if [ ! -f /etc/isi/web/settings.py ] ; then
   19.40 +	cp /usr/share/doc/isi-web/settings.py /etc/isi/web
   19.41 +    fi
   19.42 +    if [ ! -f /etc/isi/web/local_settings.py ] ; then
   19.43 +	cp /usr/share/doc/isi-web/local_settings.py /etc/isi/web
   19.44 +    fi
   19.45 +    cd /usr/share/isi/isiweb
   19.46 +    ./manage.py syncdb --verbosity=0 --noinput
   19.47 +
   19.48 +    /etc/init.d/isiweb start
   19.49 +}
   19.50 +
   19.51 +case "$1" in
   19.52 +    configure)
   19.53 +	rm -f /usr/share/isi/isiweb/isi.db
   19.54 +	rm -f /etc/isi/web/settings.py
   19.55 +	if [ ! -f /usr/share/isi/isiweb/isi.db ]; then
   19.56 +	    start_isiweb
   19.57 +	fi
   19.58 +    ;;
   19.59 +
   19.60 +    abort-upgrade|abort-remove|abort-deconfigure)
   19.61 +    ;;
   19.62 +
   19.63 +    *)
   19.64 +        echo "postinst called with unknown argument \`$1'" >&2
   19.65 +        exit 1
   19.66 +    ;;
   19.67 +esac
   19.68 +
   19.69 +# dh_installdeb will replace this with shell code automatically
   19.70 +# generated by other debhelper scripts.
   19.71 +
   19.72 +#DEBHELPER#
   19.73 +
   19.74 +exit 0
   19.75 +
   19.76 +
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/debian/isi.install	Mon Apr 26 11:16:23 2010 +0200
    20.3 @@ -0,0 +1,5 @@
    20.4 +usr/bin /usr
    20.5 +usr/sbin /usr
    20.6 +usr/lib /usr
    20.7 +usr/share/WinActivePerl
    20.8 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/debian/isi.postinst	Mon Apr 26 11:16:23 2010 +0200
    21.3 @@ -0,0 +1,63 @@
    21.4 +#!/bin/bash
    21.5 +# postinst script for isi
    21.6 +#
    21.7 +# see: dh_installdeb(1)
    21.8 +
    21.9 +set -e
   21.10 +
   21.11 +# summary of how this script can be called:
   21.12 +#        * <postinst> `configure' <most-recently-configured-version>
   21.13 +#        * <old-postinst> `abort-upgrade' <new version>
   21.14 +#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
   21.15 +#          <new-version>
   21.16 +#        * <postinst> `abort-remove'
   21.17 +#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
   21.18 +#          <failed-install-package> <version> `removing'
   21.19 +#          <conflicting-package> <version>
   21.20 +# for details, see http://www.debian.org/doc/debian-policy/ or
   21.21 +# the debian-policy package
   21.22 +
   21.23 +
   21.24 +case "$1" in
   21.25 +    configure)
   21.26 +	mkdir -p /etc/isi/
   21.27 +	grep -v /etc/isi/defaults.py /usr/share/doc/isi/etc/isi/defaults.py > /etc/isi/defaults.py
   21.28 +        ### copia grub4dos nella share software
   21.29 +        if [ -d /home/shares/software ]; then
   21.30 +	    GRUP_DEST=/home/shares/software
   21.31 +	else
   21.32 +	    GRUP_DEST=/home/software
   21.33 +	fi
   21.34 +        if [ -d $GRUB_DEST ]; then
   21.35 +	    if [ ! -d $GRUB_DEST/grub4dos ]; then
   21.36 +		cp -a /usr/share/doc/isi/grub4dos $GRUB_DEST
   21.37 +	    fi
   21.38 +            find $GRUB_DEST/grub4dos -name \*gz -exec gunzip {} \;
   21.39 +        fi
   21.40 +	rm -f /etc/isi/logon.pl /etc/isi/logonupd.pl
   21.41 +	## there was a time logon.pl was in /etc/isi (before 2.7.1) and 
   21.42 +	## we pointed there from WinActivePerl
   21.43 +	WIN_PERL=/usr/share/WinActivePerl/
   21.44 +	if test -h $WIN_PERL/logon.pl  ; then
   21.45 +	    rm -f $WIN_PERL/logon.pl $WIN_PERL/logonupd.pl
   21.46 +	    cp /usr/share/doc/isi/etc/isi/{logon,logonupd}.pl $WIN_PERL
   21.47 +	fi
   21.48 +	;;
   21.49 +
   21.50 +    abort-upgrade|abort-remove|abort-deconfigure)
   21.51 +    ;;
   21.52 +
   21.53 +    *)
   21.54 +        echo "postinst called with unknown argument \`$1'" >&2
   21.55 +        exit 1
   21.56 +    ;;
   21.57 +esac
   21.58 +
   21.59 +# dh_installdeb will replace this with shell code automatically
   21.60 +# generated by other debhelper scripts.
   21.61 +
   21.62 +#DEBHELPER#
   21.63 +
   21.64 +exit 0
   21.65 +
   21.66 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/debian/python-isi.install	Mon Apr 26 11:16:23 2010 +0200
    22.3 @@ -0,0 +1,1 @@
    22.4 +debian/tmp/usr/lib/python2.5 /usr/lib/
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/debian/rules	Mon Apr 26 11:16:23 2010 +0200
    23.3 @@ -0,0 +1,21 @@
    23.4 +#!/usr/bin/make -f
    23.5 +
    23.6 +#DEB_TAR_SRCDIR                  := python-dateutil
    23.7 +DEB_AUTO_CLEANUP_RCS            := yes
    23.8 +
    23.9 +DEB_PYTHON_SYSTEM = pysupport
   23.10 +DEB_PYTHON_CLEAN_ARGS = --all
   23.11 +
   23.12 +# Add here any variable or target overrides you need
   23.13 +include /usr/share/cdbs/1/rules/debhelper.mk
   23.14 +include /usr/share/cdbs/1/class/python-distutils.mk
   23.15 +#include /usr/share/cdbs/1/rules/patchsys-quilt.mk
   23.16 +
   23.17 +
   23.18 +
   23.19 +DEB_COMPRESS_EXCLUDE := .py
   23.20 +
   23.21 +# install/isi-docs::
   23.22 +# 	mkdir -p doc/html doc/.doctrees
   23.23 +# 	sphinx-build doc doc/html
   23.24 +# 	perl -i -p -e 's/xxxx/$(VER)/g' doc/html/sqlkit/download.html
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/docs/Makefile	Mon Apr 26 11:16:23 2010 +0200
    24.3 @@ -0,0 +1,88 @@
    24.4 +# Makefile for Sphinx documentation
    24.5 +#
    24.6 +
    24.7 +# You can set these variables from the command line.
    24.8 +SPHINXOPTS    =
    24.9 +SPHINXBUILD   = sphinx-build
   24.10 +PAPER         =
   24.11 +
   24.12 +# Internal variables.
   24.13 +PAPEROPT_a4     = -D latex_paper_size=a4
   24.14 +PAPEROPT_letter = -D latex_paper_size=letter
   24.15 +ALLSPHINXOPTS   = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
   24.16 +
   24.17 +all: html
   24.18 +
   24.19 +.PHONY: help clean html web htmlhelp latex changes linkcheck
   24.20 +
   24.21 +help:
   24.22 +	@echo "Please use \`make <target>' where <target> is one of"
   24.23 +	@echo "  html      to make standalone HTML files"
   24.24 +	@echo "  web       to make files usable by Sphinx.web"
   24.25 +	@echo "  htmlhelp  to make HTML files and a HTML help project"
   24.26 +	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
   24.27 +	@echo "  changes   to make an overview over all changed/added/deprecated items"
   24.28 +	@echo "  linkcheck to check all external links for integrity"
   24.29 +
   24.30 +clean:
   24.31 +	-rm -rf .build/*
   24.32 +
   24.33 +html:
   24.34 +	mkdir -p .build/html .build/doctrees
   24.35 +	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) .build/html
   24.36 +	@echo
   24.37 +	@echo "Build finished. The HTML pages are in .build/html."
   24.38 +
   24.39 +web:
   24.40 +	mkdir -p .build/web .build/doctrees
   24.41 +	$(SPHINXBUILD) -b web $(ALLSPHINXOPTS) .build/web
   24.42 +	@echo
   24.43 +	@echo "Build finished; now you can run"
   24.44 +	@echo "  python -m sphinx.web .build/web"
   24.45 +	@echo "to start the server."
   24.46 +
   24.47 +htmlhelp:
   24.48 +	mkdir -p .build/htmlhelp .build/doctrees
   24.49 +	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp
   24.50 +	@echo
   24.51 +	@echo "Build finished; now you can run HTML Help Workshop with the" \
   24.52 +	      ".hhp project file in .build/htmlhelp."
   24.53 +
   24.54 +latex:
   24.55 +	mkdir -p .build/latex .build/doctrees
   24.56 +	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex
   24.57 +	@echo
   24.58 +	@echo "Build finished; the LaTeX files are in .build/latex."
   24.59 +	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
   24.60 +	      "run these through (pdf)latex."
   24.61 +
   24.62 +changes:
   24.63 +	mkdir -p .build/changes .build/doctrees
   24.64 +	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes
   24.65 +	@echo
   24.66 +	@echo "The overview file is in .build/changes."
   24.67 +
   24.68 +linkcheck:
   24.69 +	mkdir -p .build/linkcheck .build/doctrees
   24.70 +	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck
   24.71 +	@echo
   24.72 +	@echo "Link check complete; look for any errors in the above output " \
   24.73 +	      "or in .build/linkcheck/output.txt."
   24.74 +
   24.75 +rsync:	html
   24.76 +	rsync -r --delete --progress --stats ./.build/html/ www3:docs/reteisi
   24.77 +
   24.78 +nrsync:	html
   24.79 +	rsync -r --delete --progress --stats ./.build/html/ www3:docs/reteisi/2.0/
   24.80 +
   24.81 +pdf:    latex
   24.82 +	cd .build/latex; make all-pdf || true
   24.83 +	Print -s -o "-b 20" .build/latex/reteisi.pdf
   24.84 +	gv --orientation=seascape .build/latex/reteisi.2.ps
   24.85 +
   24.86 +galeon: 
   24.87 +	galeon ./.build/html/index.html
   24.88 +firefox: 
   24.89 +	firefox ./.build/html/index.html
   24.90 +
   24.91 +chtml:  clean html
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/docs/README	Mon Apr 26 11:16:23 2010 +0200
    25.3 @@ -0,0 +1,12 @@
    25.4 +Documentation can be generated with sphinx:
    25.5 +
    25.6 +
    25.7 +easy_install sphinx
    25.8 +make html
    25.9 +make firefox
   25.10 +
   25.11 +
   25.12 +it is available on the web:
   25.13 +
   25.14 +   http://docs.argolinux.org/jungle/index.html
   25.15 +
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/docs/_static/reteisi.css	Mon Apr 26 11:16:23 2010 +0200
    26.3 @@ -0,0 +1,520 @@
    26.4 +/**
    26.5 + * Alternate Sphinx design
    26.6 + * Originally created by Armin Ronacher for Werkzeug, adapted by Georg Brandl.
    26.7 + * modified by Sandro Dentella per ReteIsi
    26.8 + */
    26.9 +
   26.10 +body {
   26.11 +    font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif;
   26.12 +    font-size: 13px;
   26.13 +    letter-spacing: -0.01em;
   26.14 +    line-height: 130%;
   26.15 +    text-align: center;
   26.16 +    /*background-color: #AFC1C4; */
   26.17 +    background-color: #e9d56c;
   26.18 +    color: #333333;
   26.19 +    padding: 0;
   26.20 +    border: 1px solid #aaa;
   26.21 +
   26.22 +    margin: 0px 80px 0px 80px;
   26.23 +    min-width: 740px
   26.24 +    }
   26.25 +section h1 {
   26.26 +    background-color: #FDFAF3;
   26.27 +    font-size: 180%;
   26.28 +    font-weight: bold
   26.29 +    }
   26.30 +.section h2, h2 {
   26.31 +    font-size: 150%;
   26.32 +    font-weight: normal
   26.33 +    }
   26.34 +.section h1, .section h2, h1, h2 {
   26.35 +    font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
   26.36 +    border-color: #E2DCC8;
   26.37 +    border-style: solid;
   26.38 +    border-width: 0pt 0pt 1px
   26.39 +    }
   26.40 +.section h1, .section h2, .section h3, h1, h2, h3 {
   26.41 +    color: #940000
   26.42 +    }
   26.43 +a {
   26.44 +    color: #CA7900;
   26.45 +    text-decoration: none
   26.46 +    }
   26.47 +a:hover {
   26.48 +    color: #2491CF
   26.49 +    }
   26.50 +pre {
   26.51 +    font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
   26.52 +    font-size: 0.95em;
   26.53 +    letter-spacing: 0.015em;
   26.54 +    padding: 0.5em;
   26.55 +    border: 1px solid #ccc;
   26.56 +    background-color: #f8f8f8
   26.57 +    }
   26.58 +td.linenos pre {
   26.59 +    padding: 0;
   26.60 +    border: 0;
   26.61 +    background-color: transparent;
   26.62 +    color: #aaa
   26.63 +    }
   26.64 +table.highlighttable {
   26.65 +    margin-left: 0.5em
   26.66 +    }
   26.67 +table.highlighttable td {
   26.68 +    padding: 0 0.5em 0 0.5em
   26.69 +    }
   26.70 +cite, code, tt {
   26.71 +    font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
   26.72 +    font-size: 1.05em;
   26.73 +    letter-spacing: 0.01em;
   26.74 +    font-style: normal
   26.75 +    }
   26.76 +hr {
   26.77 +    border: 1px solid #abc;
   26.78 +    margin: 2em
   26.79 +    }
   26.80 +tt {
   26.81 +    /*     background-color: #f2f2f2; */
   26.82 +    /*     border-bottom: 1px solid #ddd; */
   26.83 +    color: #222;
   26.84 +    font-weight: bold
   26.85 +    }
   26.86 +tt.descname {
   26.87 +    background-color: transparent;
   26.88 +    font-weight: bold;
   26.89 +    font-size: 1.2em;
   26.90 +    border: 0
   26.91 +    }
   26.92 +tt.descclassname {
   26.93 +    background-color: transparent;
   26.94 +    border: 0
   26.95 +    }
   26.96 +tt.xref {
   26.97 +    background-color: transparent;
   26.98 +    font-weight: bold;
   26.99 +    border: 0
  26.100 +    }
  26.101 +a tt {
  26.102 +    background-color: transparent;
  26.103 +    font-weight: bold;
  26.104 +    border: 0;
  26.105 +    color: #CA7900
  26.106 +    }
  26.107 +a tt:hover {
  26.108 +    color: #2491CF;
  26.109 +}
  26.110 +
  26.111 +.field-list ul {
  26.112 +    margin: 0;
  26.113 +    padding-left: 1em;
  26.114 +}
  26.115 +
  26.116 +.field-list p {
  26.117 +    margin: 0;
  26.118 +}
  26.119 +
  26.120 +dl {
  26.121 +    margin-bottom: 15px;
  26.122 +}
  26.123 +
  26.124 +dd p {
  26.125 +    margin-top: 0px;
  26.126 +}
  26.127 +
  26.128 +dd ul, dd table {
  26.129 +    margin-bottom: 10px;
  26.130 +}
  26.131 +
  26.132 +dd {
  26.133 +    margin-top: 3px;
  26.134 +    margin-bottom: 10px;
  26.135 +    margin-left: 30px;
  26.136 +}
  26.137 +
  26.138 +.refcount {
  26.139 +    color: #060;
  26.140 +}
  26.141 +
  26.142 +dt:target,
  26.143 +.highlight {
  26.144 +    background-color: #fbe54e;
  26.145 +}
  26.146 +
  26.147 +dl.glossary dt {
  26.148 +    font-weight: bold;
  26.149 +    font-size: 1.1em;
  26.150 +}
  26.151 +
  26.152 +pre {
  26.153 +    line-height: 120%;
  26.154 +}
  26.155 +
  26.156 +pre a {
  26.157 +/*     color: inherit; */
  26.158 +    text-decoration: underline;
  26.159 +}
  26.160 +
  26.161 +.first {
  26.162 +    margin-top: 0 !important;
  26.163 +}
  26.164 +
  26.165 +div.document {
  26.166 +    background-color: white;
  26.167 +    text-align: left;
  26.168 +    background-image: url(contents.png);
  26.169 +    background-repeat: repeat-x;
  26.170 +}
  26.171 +
  26.172 +/*
  26.173 +div.documentwrapper {
  26.174 +    width: 100%;
  26.175 +}
  26.176 +*/
  26.177 +
  26.178 +div.clearer {
  26.179 +    clear: both;
  26.180 +}
  26.181 +
  26.182 +div.related h3 {
  26.183 +    display: none;
  26.184 +}
  26.185 +
  26.186 +div.related ul {
  26.187 +    background-image: url(navigation.png);
  26.188 +    height: 2em;
  26.189 +    list-style: none;
  26.190 +    border-top: 1px solid #ddd;
  26.191 +    border-bottom: 1px solid #ddd;
  26.192 +    margin: 0;
  26.193 +    padding-left: 10px;
  26.194 +}
  26.195 +
  26.196 +div.related ul li {
  26.197 +    margin: 0;
  26.198 +    padding: 0;
  26.199 +    height: 2em;
  26.200 +    float: left;
  26.201 +}
  26.202 +
  26.203 +div.related ul li.right {
  26.204 +    float: right;
  26.205 +    margin-right: 5px;
  26.206 +}
  26.207 +
  26.208 +div.related ul li a {
  26.209 +    margin: 0;
  26.210 +    padding: 0 5px 0 5px;
  26.211 +    line-height: 1.75em;
  26.212 +    color: #EE9816;
  26.213 +}
  26.214 +
  26.215 +div.related ul li a:hover {
  26.216 +    color: #3CA8E7;
  26.217 +}
  26.218 +
  26.219 +div.body {
  26.220 +    margin: 0;
  26.221 +    padding: 0.5em 20px 20px 20px;
  26.222 +}
  26.223 +
  26.224 +div.bodywrapper {
  26.225 +    margin: 0 240px 0 0;
  26.226 +    border-right: 1px solid #ccc;
  26.227 +}
  26.228 +
  26.229 +div.body a {
  26.230 +    text-decoration: underline;
  26.231 +}
  26.232 +
  26.233 +div.sphinxsidebar {
  26.234 +    margin: 0;
  26.235 +    padding: 0.5em 15px 15px 0;
  26.236 +    width: 210px;
  26.237 +    float: right;
  26.238 +    text-align: left;
  26.239 +/*    margin-left: -100%; */
  26.240 +}
  26.241 +
  26.242 +div.sphinxsidebar h4, div.sphinxsidebar h3 {
  26.243 +    margin: 1em 0 0.5em 0;
  26.244 +    font-size: 0.9em;
  26.245 +    padding: 0.1em 0 0.1em 0.5em;
  26.246 +    color: #940000;
  26.247 +    border: 1px solid #940000;
  26.248 +    background-color: #f0ae4a
  26.249 +    }
  26.250 +div.sphinxsidebar ul ul {
  26.251 +    padding-left: 1.5em;
  26.252 +    margin-top: 7px;
  26.253 +    list-style: none;
  26.254 +    padding: 0;
  26.255 +    line-height: 130%;
  26.256 +}
  26.257 +
  26.258 +div.sphinxsidebar ul ul {
  26.259 +    list-style: square;
  26.260 +    margin-left: 20px;
  26.261 +}
  26.262 +
  26.263 +p {
  26.264 +    margin: 0.8em 0 0.5em 0;
  26.265 +}
  26.266 +
  26.267 +p.rubric {
  26.268 +    font-weight: bold;
  26.269 +}
  26.270 +
  26.271 +h1 {
  26.272 +    margin: 0;
  26.273 +    padding: 0.7em 0 0.3em 0;
  26.274 +    font-size: 1.5em;
  26.275 +    color: #11557C;
  26.276 +}
  26.277 +
  26.278 +h2 {
  26.279 +    margin: 1.3em 0 0.2em 0;
  26.280 +    font-size: 1.35em;
  26.281 +    padding: 0;
  26.282 +}
  26.283 +
  26.284 +h3 {
  26.285 +    margin: 1em 0 -0.3em 0;
  26.286 +    font-size: 1.2em;
  26.287 +}
  26.288 +
  26.289 +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
  26.290 +    color: #333333
  26.291 +    }
  26.292 +h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
  26.293 +    display: none;
  26.294 +    margin: 0 0 0 0.3em;
  26.295 +    padding: 0 0.2em 0 0.2em;
  26.296 +    color: #aaa!important;
  26.297 +}
  26.298 +
  26.299 +h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
  26.300 +h5:hover a.anchor, h6:hover a.anchor {
  26.301 +    display: inline;
  26.302 +}
  26.303 +
  26.304 +h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
  26.305 +h5 a.anchor:hover, h6 a.anchor:hover {
  26.306 +    color: #777;
  26.307 +    background-color: #eee;
  26.308 +}
  26.309 +
  26.310 +table {
  26.311 +    border-collapse: collapse;
  26.312 +    margin: 0 -0.5em 0 -0.5em;
  26.313 +}
  26.314 +
  26.315 +table td, table th {
  26.316 +    padding: 0.2em 0.5em 0.2em 0.5em;
  26.317 +}
  26.318 +
  26.319 +div.footer {
  26.320 +    background-color: #f0ae4a;
  26.321 +    color: #86989B;
  26.322 +    padding: 3px 8px 3px 0;
  26.323 +    clear: both;
  26.324 +    font-size: 0.8em;
  26.325 +    text-align: right;
  26.326 +}
  26.327 +
  26.328 +div.footer a {
  26.329 +    color: #86989B;
  26.330 +    text-decoration: underline;
  26.331 +}
  26.332 +
  26.333 +div.pagination {
  26.334 +    margin-top: 2em;
  26.335 +    padding-top: 0.5em;
  26.336 +    border-top: 1px solid black;
  26.337 +    text-align: center;
  26.338 +}
  26.339 +
  26.340 +div.sphinxsidebar ul.toc {
  26.341 +    margin: 1em 0 1em 0;
  26.342 +    padding: 0 0 0 0.5em;
  26.343 +    list-style: none;
  26.344 +}
  26.345 +
  26.346 +div.sphinxsidebar ul.toc li {
  26.347 +    margin: 0.5em 0 0.5em 0;
  26.348 +    font-size: 0.9em;
  26.349 +    line-height: 130%;
  26.350 +}
  26.351 +
  26.352 +div.sphinxsidebar ul.toc li p {
  26.353 +    margin: 0;
  26.354 +    padding: 0;
  26.355 +}
  26.356 +
  26.357 +div.sphinxsidebar ul.toc ul {
  26.358 +    margin: 0.2em 0 0.2em 0;
  26.359 +    padding: 0 0 0 1.8em;
  26.360 +}
  26.361 +
  26.362 +div.sphinxsidebar ul.toc ul li {
  26.363 +    padding: 0;
  26.364 +}
  26.365 +
  26.366 +div.admonition, div.warning {
  26.367 +    font-size: 0.9em;
  26.368 +    margin: 1em 0 0 0;
  26.369 +    border: 1px solid #86989B;
  26.370 +    background-color: #f7f7f7;
  26.371 +}
  26.372 +
  26.373 +div.admonition p, div.warning p {
  26.374 +    margin: 0.5em 1em 0.5em 1em;
  26.375 +    padding: 0;
  26.376 +}
  26.377 +
  26.378 +div.admonition pre, div.warning pre {
  26.379 +    margin: 0.4em 1em 0.4em 1em;
  26.380 +}
  26.381 +
  26.382 +div.admonition p.admonition-title,
  26.383 +div.warning p.admonition-title {
  26.384 +    margin: 0;
  26.385 +    padding: 0.1em 0 0.1em 0.5em;
  26.386 +    color: white;
  26.387 +    border-bottom: 1px solid #86989B;
  26.388 +    font-weight: bold;
  26.389 +    background-color: #fe6f20;
  26.390 +}
  26.391 +
  26.392 +div.warning {
  26.393 +    border: 1px solid #940000;
  26.394 +}
  26.395 +
  26.396 +div.warning p.admonition-title {
  26.397 +    background-color: #CF0000;
  26.398 +    border-bottom-color: #940000;
  26.399 +}
  26.400 +
  26.401 +div.admonition ul, div.admonition ol,
  26.402 +div.warning ul, div.warning ol {
  26.403 +    margin: 0.1em 0.5em 0.5em 3em;
  26.404 +    padding: 0;
  26.405 +}
  26.406 +
  26.407 +div.versioninfo {
  26.408 +    margin: 1em 0 0 0;
  26.409 +    border: 1px solid #ccc;
  26.410 +    background-color: #DDEAF0;
  26.411 +    padding: 8px;
  26.412 +    line-height: 1.3em;
  26.413 +    font-size: 0.9em;
  26.414 +}
  26.415 +
  26.416 +
  26.417 +a.headerlink {
  26.418 +    color: #c60f0f!important;
  26.419 +    font-size: 1em;
  26.420 +    margin-left: 6px;
  26.421 +    padding: 0 4px 0 4px;
  26.422 +    text-decoration: none!important;
  26.423 +    visibility: hidden;
  26.424 +}
  26.425 +
  26.426 +h1:hover > a.headerlink,
  26.427 +h2:hover > a.headerlink,
  26.428 +h3:hover > a.headerlink,
  26.429 +h4:hover > a.headerlink,
  26.430 +h5:hover > a.headerlink,
  26.431 +h6:hover > a.headerlink,
  26.432 +dt:hover > a.headerlink {
  26.433 +    visibility: visible;
  26.434 +}
  26.435 +
  26.436 +a.headerlink:hover {
  26.437 +    background-color: #ccc;
  26.438 +    color: white!important;
  26.439 +}
  26.440 +
  26.441 +table.indextable td {
  26.442 +    text-align: left;
  26.443 +    vertical-align: top;
  26.444 +}
  26.445 +
  26.446 +table.indextable dl, table.indextable dd {
  26.447 +    margin-top: 0;
  26.448 +    margin-bottom: 0;
  26.449 +}
  26.450 +
  26.451 +table.indextable tr.pcap {
  26.452 +    height: 10px;
  26.453 +}
  26.454 +
  26.455 +table.indextable tr.cap {
  26.456 +    margin-top: 10px;
  26.457 +    background-color: #f2f2f2;
  26.458 +}
  26.459 +
  26.460 +img.toggler {
  26.461 +    margin-right: 3px;
  26.462 +    margin-top: 3px;
  26.463 +    cursor: pointer;
  26.464 +}
  26.465 +
  26.466 +form.pfform {
  26.467 +    margin: 10px 0 20px 0;
  26.468 +}
  26.469 +
  26.470 +table.contentstable {
  26.471 +    width: 90%;
  26.472 +}
  26.473 +
  26.474 +table.contentstable p.biglink {
  26.475 +    line-height: 150%;
  26.476 +}
  26.477 +
  26.478 +a.biglink {
  26.479 +    font-size: 1.3em;
  26.480 +}
  26.481 +
  26.482 +span.linkdescr {
  26.483 +    font-style: italic;
  26.484 +    padding-top: 5px;
  26.485 +    font-size: 90%;
  26.486 +}
  26.487 +
  26.488 +ul.search {
  26.489 +    margin: 10px 0 0 20px;
  26.490 +    padding: 0;
  26.491 +}
  26.492 +
  26.493 +ul.search li {
  26.494 +    padding: 5px 0 5px 20px;
  26.495 +    background-image: url(file.png);
  26.496 +    background-repeat: no-repeat;
  26.497 +    background-position: 0 7px;
  26.498 +}
  26.499 +
  26.500 +ul.search li a {
  26.501 +    font-weight: bold;
  26.502 +}
  26.503 +
  26.504 +ul.search li div.context {
  26.505 +    color: #888;
  26.506 +    margin: 2px 0 0 30px;
  26.507 +    text-align: left;
  26.508 +}
  26.509 +
  26.510 +ul.keywordmatches li.goodmatch a {
  26.511 +    font-weight: bold
  26.512 +    }
  26.513 +div.sidebar {
  26.514 +    margin-left: 1em;
  26.515 +    margin-top: 1em;
  26.516 +    border: 1px solid orange;
  26.517 +    padding: 1em;
  26.518 +    background-color: #FFFFCC;
  26.519 +    width: 40%;
  26.520 +    float: right;
  26.521 +    clear: right;
  26.522 +    margin-bottom: 20px
  26.523 +    }
    27.1 Binary file docs/_static/reteisi.png has changed
    28.1 Binary file docs/_static/sphinx.png has changed
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/docs/_templates/index.html	Mon Apr 26 11:16:23 2010 +0200
    29.3 @@ -0,0 +1,86 @@
    29.4 +{% extends "layout.html" %}
    29.5 +{% set title = 'Overview' %}
    29.6 +{% block body %}
    29.7 +<!--  <p style="background-color: #fcc; font-size: large; border: 1px solid #f00; padding: 10px;">
    29.8 +    <b>Attention:</b> this is a preview. Sphinx is not released yet on PyPI,
    29.9 +    and the contents of this documentation are subject to change.
   29.10 +  </p> -->
   29.11 +
   29.12 +  <h1>Benvenuti</h1>
   29.13 +
   29.14 +  <p>
   29.15 +  La nuova documentazione è <a href="2.0/" >ora disponibile</a>
   29.16 +
   29.17 +  ReteIsi è una soluzione che cerca di rendere l'amministrazione di un
   29.18 +  sistema scolastico accessibile al personale scolastico senza richiedere un
   29.19 +  eccessivo sforzo. Il progetto <a href="http://www.reteisi.org">ReteIsi</a>
   29.20 +  è nato come prodotto di una associazione di scuole nel 2002, anno in cui
   29.21 +  ricevette un cospicuo finanziamento, viene costantemente aggiornato e
   29.22 +  migliorato. Nel 2008 e 2010 ha ricevuto finanziamenti dal progetto 
   29.23 +  <a href="http://www.reteidra.org">ReteIdra</a>grazie al quale fra le altre
   29.24 +  cose, è stata aggiunta una interfaccia web per la gestione utenti, dns e
   29.25 +  logon ed è stato potenziata la gestione del server come server LTSP.
   29.26 +  
   29.27 + </p>
   29.28 + <p>
   29.29 + Questo obiettivo è raggiunto
   29.30 + <ul>
   29.31 +   <li>
   29.32 +      Avendo fatto a monte una scelta degli strumenti più idonei (distribuzione,
   29.33 +       processo di autenticazione, firewall, ...)
   29.34 +   </li>
   29.35 +   <li>
   29.36 +      Avendo creato degli strumenti idonei alla gestione di utenti in massa
   29.37 +      (ad esempio l'inserimento di 5/800 utenti all'inizio dell'anno può
   29.38 +        essere fatta in una decina di minuti)
   29.39 +   </li>
   29.40 +   <li>
   29.41 +      Avendo raccolto la documentazione pertinente ai casi d'uso più
   29.42 +      frequenti
   29.43 +    </li>
   29.44 +   </ul>
   29.45 +
   29.46 +  <h2>Stiamo lavorando su...</h2>
   29.47 +
   29.48 +  I lavori appena ultimati sono:
   29.49 +  <ul>
   29.50 +    <li>Una completa riscrittura delle librerie in python che usa 
   29.51 +        <a href="http://pumpkin.prymitive.com/">pumpkin</a>come wrapper per ldap<li>
   29.52 +    <li>Una <a href="gestione/web.html">interfaccia web</a> per la gestione degli utenti, del logon (da
   29.53 +    client Windows) e del dns (con particolare attenzione a boot di macchien
   29.54 +    LTSP in modalità thin e fat)</li>
   29.55 +    <li>Sandro Dentella sta tenendo un corso per amministratori scolastici
   29.56 +      in 8 giornate. Se siete interessati alle presentazioni delle lezioni
   29.57 +      le trovate nel sito del <a href="http://tickets.reteidra.org/corsi/">corso</a>
   29.58 +    </li>
   29.59 +    </ul>
   29.60 +
   29.61 +  <h2>Documentazione</h2>
   29.62 +
   29.63 +  La documentazione è scritta con un tool chiamato <a
   29.64 +  href="http://sphinx.pocoo.org/" >Sphinx</a>, sviluppato da Georg Brandl,
   29.65 +  originariamente scritto per il nuovo sistema di documentazione di 
   29.66 +  <a href="http://docs.python.org/dev/">Python</a>. Sphinx è basato su un
   29.67 +  reST, un linguaggio di markup molto comodo da usare.
   29.68 +
   29.69 +  Qui puoi leggere maggiori informazioni sul sistema di documentazione e su
   29.70 +  come puoi contribuire a renderlo migliore.
   29.71 +
   29.72 +
   29.73 +  <table class="contentstable" align="center" style="margin-left: 30px"><tr>
   29.74 +    <td width="50%">
   29.75 +      <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Contenuti</a><br>
   29.76 +         <span class="linkdescr">per la documentazione completa</span></p>
   29.77 +      <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br>
   29.78 +         <span class="linkdescr">cerca nella documentazione - non ancora configurato</span></p>
   29.79 +    </td><td width="50%">
   29.80 +      <p class="biglink"><a class="biglink" href="{{ pathto("genindex")
   29.81 + }}">Indice Generale</a><br>
   29.82 +         <span class="linkdescr">comandi, voci utili....</span></p>
   29.83 +      <p class="biglink"><a class="biglink" href="http://sphinx.pocoo.org/rest.html">Markup</a><br>
   29.84 +         <span class="linkdescr">Sistema di markup usato (reST)</span></p>
   29.85 +    </td></tr>
   29.86 +  </table>
   29.87 +
   29.88 +  
   29.89 +{% endblock %}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/docs/_templates/indexsidebar.html	Mon Apr 26 11:16:23 2010 +0200
    30.3 @@ -0,0 +1,17 @@
    30.4 +<h3>Download</h3>
    30.5 +
    30.6 +    ReteIsi offre una distribuzione live scaricabile dal sito di  
    30.7 +    <a href="http://download.argolinux.org/isi/">Argolinux</a>
    30.8 +
    30.9 +    L'ultima versione è la 
   30.10 +    <a href="http://download.argolinux.org/isi/newisi-libata-beta6.iso">
   30.11 +    newisi-libata-beta6</a> basata su etch.
   30.12 +
   30.13 +<h3>Domande? Problemi?</h3>
   30.14 +
   30.15 +<p>Iscriviti al <a href="http://groups.google.com/group/reteisi">
   30.16 +   Google group</a>:</p>
   30.17 +<form action="http://groups.google.com/group/reteisi/boxsubscribe" style="padding-left: 1em">
   30.18 +  <input type="text" name="email" value="your@email"/>
   30.19 +  <input type="submit" name="sub" value="Subscribe" />
   30.20 +</form>
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/docs/_templates/layout.html	Mon Apr 26 11:16:23 2010 +0200
    31.3 @@ -0,0 +1,17 @@
    31.4 +{% extends "!layout.html" %}
    31.5 +
    31.6 +{% block rootrellink %}
    31.7 +        <li><a href="{{ pathto('index') }}">ReteIsi </a> | </li>
    31.8 +        <li><a href="{{ pathto('contents') }}">Documentazione </a> »</li>
    31.9 +{% endblock %}
   31.10 +
   31.11 +{% block beforerelbar %}
   31.12 +QUI
   31.13 +<div style="background-color: white; text-align: left; padding: 10px 10px 15px 15px">
   31.14 +<a href="http://www.reteisi.org" ><img src="{{ pathto("img/reteisi.png",1) }}" border="0"></a>
   31.15 +</div>
   31.16 +{% endblock %}
   31.17 +
   31.18 +{# put the sidebar before the body #}
   31.19 +{% block sidebar1 %}{{ sidebar() }}{% endblock %}
   31.20 +{% block sidebar2 %}{% endblock %}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/docs/_templates/macros.html	Mon Apr 26 11:16:23 2010 +0200
    32.3 @@ -0,0 +1,49 @@
    32.4 +{%- macro sidebar %}
    32.5 +      {%- if builder != 'htmlhelp' %}
    32.6 +      <div class="sidebar_sphinx">
    32.7 +        <div class="sidebarwrapper">
    32.8 +          {% if display_toc %}
    32.9 +            <h3>Contentenuti</h3>
   32.10 +            {{ toc }}
   32.11 +          {% endif %}
   32.12 +          {%- if prev %}
   32.13 +            <h4>Argomento precedente</h4>
   32.14 +            <p class="topless"><a href="{{ prev.link|e }}" title="previous chapter">{{ prev.title }}</a></p>
   32.15 +          {%- endif %}
   32.16 +          {%- if next %}
   32.17 +            <h4>Argomento successivo</h4>
   32.18 +            <p class="topless"><a href="{{ next.link|e }}" title="next chapter">{{ next.title }}</a></p>
   32.19 +          {%- endif %}
   32.20 +          {% if sourcename %}
   32.21 +            <h3>Questa Pagina</h3>
   32.22 +            <ul class="this-page-menu">
   32.23 +            {% if builder == 'web' %}
   32.24 +              <li><a href="#comments">Commenti ({{ comments|length }} so far)</a></li>
   32.25 +              <li><a href="{{ pathto('@edit/' + sourcename)|e }}">Suggest Change</a></li>
   32.26 +              <li><a href="{{ pathto('@source/' + sourcename)|e }}">Sorgente della pagina</a></li>
   32.27 +      
   32.28 +            {% elif builder == 'html' %}
   32.29 +              <li><a href="{{ pathto('_sources/' + sourcename, true)|e
   32.30 +              }}">Mostra Sorgente</a></li>
   32.31 +            {% endif %}
   32.32 +            </ul>
   32.33 +          {% endif %}
   32.34 +          {% if customsidebar %}
   32.35 +          {{ rendertemplate(customsidebar) }}
   32.36 +          {% endif %}
   32.37 +          {% if current_page_name != "search" %}
   32.38 +            <h3>{{ builder == 'web' and 'Keyword' or 'Quick' }} search</h3>
   32.39 +            <form class="search" action="{{ pathto('search') }}" method="get">
   32.40 +              <input type="text" name="q" size="18"> <input type="submit" value="Go">
   32.41 +              <input type="hidden" name="check_keywords" value="yes">
   32.42 +              <input type="hidden" name="area" value="default">
   32.43 +            </form>
   32.44 +            {% if builder == 'web' %}
   32.45 +            <p style="font-size: 90%">Enter a module, class or function name.</p>
   32.46 +            {% endif %}
   32.47 +          {% endif %}
   32.48 +        </div>
   32.49 +      </div>
   32.50 +      {%- endif %}
   32.51 +{%- endmacro %}
   32.52 +
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/docs/allegati/biblioteca.rst	Mon Apr 26 11:16:23 2010 +0200
    33.3 @@ -0,0 +1,10 @@
    33.4 +=====================================
    33.5 + Supporto alla biblioteca scolastica
    33.6 +=====================================
    33.7 +
    33.8 +
    33.9 +E` possibile installare u software di gestione della biblioteca (PBM) integrato
   33.10 +nel sistema.
   33.11 +
   33.12 +
   33.13 +DOCUMENTAZIONE DA SCRIVERE
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/docs/allegati/contents.rst	Mon Apr 26 11:16:23 2010 +0200
    34.3 @@ -0,0 +1,13 @@
    34.4 +==========
    34.5 + Allegati
    34.6 +==========
    34.7 +
    34.8 +.. toctree::
    34.9 +
   34.10 +   changelog
   34.11 +   glossario
   34.12 +   debug/contents
   34.13 +   netkit/intro
   34.14 +   masterizzare
   34.15 +   biblioteca
   34.16 +   
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/docs/allegati/debug/contents.rst	Mon Apr 26 11:16:23 2010 +0200
    35.3 @@ -0,0 +1,23 @@
    35.4 +Troubleshooting
    35.5 +=================
    35.6 +
    35.7 +In questo capitolo affrontiamo alcune linee guida per il debug di
    35.8 +problemi. Lo strumento principale è :command:`isi-checkup` che però si
    35.9 +limita a fare i test che è possibile fare **dall'interno** della macchina.
   35.10 +
   35.11 +Per i test che è necessario fare dall'esterno suggeriamo di usare macchine
   35.12 +virtuali se il vostro server è sufficientemente potente per permettervelo.
   35.13 +
   35.14 +Una cosa che suggeriamo è di avere su ogni server reale anche un server
   35.15 +vmware con un client per ogni SO che usate (W98, XP, ubuntu...). Vi sarà
   35.16 +facile connettervi anche da remoto, abilitare il client e fare le prove
   35.17 +necessarie in caso di intervento. Alternativamente dovrete chiedere di
   35.18 +lasciare acceso un server con VNC attivato: è molto meno pratico.
   35.19 +
   35.20 +.. toctree:: 
   35.21 +   
   35.22 +   isi-checkup
   35.23 +   vmware
   35.24 +   faq
   35.25 +   
   35.26 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/docs/allegati/debug/faq.rst	Mon Apr 26 11:16:23 2010 +0200
    36.3 @@ -0,0 +1,11 @@
    36.4 +=====
    36.5 + Faq
    36.6 +=====
    36.7 +::
    36.8 + 
    36.9 + + prima installazione
   36.10 +  D: Ho inserito il cd e riavviato la macchina ma il sistema non boota da cd.
   36.11 +  
   36.12 +  R: Verificare che il bios sia configurato correttamente per boot da cdrom. 
   36.13 +  Spesso l'impostazione default è di avviare direttamente dal primo disco
   36.14 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/docs/allegati/debug/isi-checkup.rst	Mon Apr 26 11:16:23 2010 +0200
    37.3 @@ -0,0 +1,61 @@
    37.4 +Server
    37.5 +------
    37.6 +
    37.7 +E` appena stato terminato lo strumento :command:`isi-checkup` che renderà
    37.8 +assolutamente semplice fare ogni controllo che possa essere fatto
    37.9 +dall'interno della macchina per via di un :ref:`test`. Sarà facile per
   37.10 +intendersi verificare se una password è valida o se gli utenti hanno i
   37.11 +permessi corretti, mentre non sarà possibile verificare se un client riesce
   37.12 +a fare il :ref:`join <join>`
   37.13 +
   37.14 +
   37.15 +.. _test:
   37.16 +
   37.17 +test
   37.18 +----
   37.19 +
   37.20 +Per test si intende un piccolo codice (una script bash o una funzione in
   37.21 +python) che effettua un singolo controllo e ritorna un valore chiaro:
   37.22 +
   37.23 +* per una script di shell: 0 in caso il test sia passato e un valore
   37.24 +  positivo se il test non è passato
   37.25 +
   37.26 +* per una funzione in python: True se il test è passato ed un errore
   37.27 +  opportuno (ereditato da ``IsiCheckupError``) in caso contrario
   37.28 +
   37.29 +sarà possibile chiamare :command:`isi-checkup` in 3 modi:
   37.30 +
   37.31 +1. ``isi-checkup -s``: checkup dei test di sistema
   37.32 +2. ``isi-checkup -u user``: checkup per un singolo user
   37.33 +3. ``isi-checkup -a``: check di tutti gli utenti (lungo)
   37.34 +
   37.35 +Esempio bash
   37.36 +~~~~~~~~~~~~
   37.37 +:file:`/etc/isi/checkup/tests-enabled/test-smbd.sh` ::
   37.38 +
   37.39 +  #!/bin/bash
   37.40 +
   37.41 +  if pgrep -x smbd ; then
   37.42 +     exit 0
   37.43 +  else
   37.44 +     echo "il processo smbd non sta girando"
   37.45 +     exit 1
   37.46 +  fi
   37.47 +
   37.48 +Interoperabilità
   37.49 +----------------
   37.50 +
   37.51 +edubuntu + dominio isi
   37.52 +~~~~~~~~~~~~~~~~~~~~~~
   37.53 +
   37.54 + * gli utenti non sentono i suoni
   37.55 + * gli utenti non montano la chiavetta e ricevono il seguente messaggio 
   37.56 +   d'errore: HAL....
   37.57 +
   37.58 +windows + dominio
   37.59 +~~~~~~~~~~~~~~~~~
   37.60 +
   37.61 + * win98 + dominio isi
   37.62 + * win2k + dominio isi
   37.63 + * xp + dominio isi
   37.64 +    
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/docs/allegati/debug/vmware.rst	Mon Apr 26 11:16:23 2010 +0200
    38.3 @@ -0,0 +1,54 @@
    38.4 +
    38.5 +Vmware Server
    38.6 +=============
    38.7 +
    38.8 +Vmware è un server di virtualizzazione. La licenza è (verificare) e quindi è
    38.9 +possibile utilizzarlo anche a scuola. Ne apprezzo la struttura in quanto è
   38.10 +separato fra un server ed un client e quindi è possibile usarlo da remoto,
   38.11 +fare partire e fermare le macchine virtuali e quindi rende possibile fare
   38.12 +partire macchie virtuali su server che non siano dotati di server X.
   38.13 +
   38.14 +Installazione
   38.15 +-------------
   38.16 +
   38.17 +Il CD di Argo ha già tutto quanto serve per installare vmware-server tranne
   38.18 +vmware stesso.
   38.19 +
   38.20 +Per chi invece debba installarlo in una distribuzione debian semplice o in Argo
   38.21 +probabilmente mancheranno alcune dipendenze::
   38.22 +
   38.23 + apt-get install libx11-6 libxtst6 libxext6 libxt6 libice6 libsm6 libxrender1
   38.24 +
   38.25 +L'installazione è composta da pochi passi:
   38.26 +
   38.27 +1. scompattazione della immagine scaricata dal sito hyyp://www.vmware.com
   38.28 +2. ./vmware-install.pl
   38.29 +
   38.30 +   Questa fase pone alcune domande: si può rispondere accettando i default,
   38.31 +   a tutte le domande, compresa la configurazione della rete, tranne a
   38.32 +   quelle in cui chiede il percorso del compilatore per le API perl di
   38.33 +   Vmware (che non vi servono).
   38.34 +
   38.35 +   Nel CD Reteisi non c'è compilatore ma c'è un modulo per vmware quindi non
   38.36 +   è necessario. L installatore di Vmware se ne accorge e non vi chiede di
   38.37 +   compilarlo.
   38.38 +
   38.39 +3. installazione del sistema operativo nella macchina virtualizzata. 
   38.40 +
   38.41 +   Per fare questo in genere partirete da un CD o da una immagine iso. In
   38.42 +   questa ultima ipotesi non avete neanche bisogno di
   38.43 +   masterizzarla: configurate il CD della macchina (doppio click sulla icona
   38.44 +   del CD) perché usi l'immagine iso *come cd*
   38.45 +
   38.46 +
   38.47 +Setup
   38.48 +-----
   38.49 +
   38.50 +
   38.51 +Personalmente (Sandro) facendo molti interventi da remoto nelle scuole, lo
   38.52 +sto usando per testare la rete su macchine sicuramente ben configurate. 
   38.53 +
   38.54 +Quando installo un laboratorio, installo anche una macchina client in
   38.55 +vmware. Nel caso insorgano problemi posso usare quella macchina (virtuale)
   38.56 +per prove da remoto.
   38.57 +
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/docs/allegati/glossario.rst	Mon Apr 26 11:16:23 2010 +0200
    39.3 @@ -0,0 +1,91 @@
    39.4 +===============
    39.5 + MiniGlossario
    39.6 +===============
    39.7 +
    39.8 +editor
    39.9 +======
   39.10 +
   39.11 +.. glossary::
   39.12 +
   39.13 +   nano
   39.14 +     editor considerano normalmente molto semplice da usare
   39.15 +
   39.16 +   jmacs
   39.17 +     editor molto leggero, facile da usare secondo me (Sandro) per il fatto
   39.18 +     che ha gli stessi comandi di :term:`emacs`
   39.19 +  
   39.20 +   emacs
   39.21 +     il migliore degli editor, senza dubbi... almeno se fate programmazione,
   39.22 +     siete disposti ad essere di parte e.... siete dalla mia parte! \*:-)
   39.23 +
   39.24 +concetti
   39.25 +========
   39.26 +
   39.27 +.. glossary::
   39.28 +
   39.29 +
   39.30 +   raid
   39.31 +     sistema di uso di più dischi che vengono visti dal sistema come una sola
   39.32 +     unità allo scopo di avere una ridondanza dei dati (raid1, raid5, raid6) o
   39.33 +     una maggiore velocità di accesso al disco (raid0)
   39.34 +  
   39.35 +    
   39.36 +   raid1
   39.37 +     sistema raid che mette i dischi in mirroring. I dati vengono
   39.38 +     scritti in parallelo su due (o più) dischi. La lettura risulta più
   39.39 +     rapida che con un solo disco. In caso di guasto di un disco, il sistema
   39.40 +     esclude il disco dall'array e permette di continuare il normale
   39.41 +     lavoro. A questo punto è necessario sostituire il disco. Può essere
   39.42 +     implementato sia via software che via hardware.
   39.43 +
   39.44 +
   39.45 +   network
   39.46 +     maschera di rete.
   39.47 +   
   39.48 +       .. seealso:: http://it.wikipedia.org/wiki/Subnet_mask
   39.49 +
   39.50 +   gateway   
   39.51 +     macchina o router che permette di congiungere due reti. Spesso una rete
   39.52 +     interna ad 
   39.53 +
   39.54 +
   39.55 +
   39.56 +comandi di sistema
   39.57 +==================
   39.58 +
   39.59 +.. glossary::
   39.60 +
   39.61 +   ifconfig
   39.62 +     comando per impostare l'IP della interfaccia di rete::
   39.63 +   
   39.64 +       ifconfig eth0 192.168.5.1
   39.65 +
   39.66 +
   39.67 +   route
   39.68 +     comando di sistema che permette di impostare un instradamento, ovvero di
   39.69 +     dire al kernel che strada devono prendere i pacchetti per poter
   39.70 +     raggiungere una destinazione, il comando::
   39.71 +  
   39.72 +       route add -net default gw 192.168.5.254
   39.73 +  
   39.74 +     imposta come destinazione di default l'IP 192..168.5.254
   39.75 +  
   39.76 +   df
   39.77 +     disk free. Mostra quali partizioni sono montate e quanto spazio libero
   39.78 +     hanno. Molto comoda l'opzione ``-h`` che restituisce i dati in formato
   39.79 +     _human_ (Gbytes e non blocchi)
   39.80 +
   39.81 +   ldapsearch
   39.82 +     client ldap. l'uso è sostanzialmente limitato al debug. Ad esempio::
   39.83 +
   39.84 +       ldapsearch -xLLL uid=Administrator
   39.85 +
   39.86 +     dovrebbe sempre restituire i dati dell'utente Administrator in formato 
   39.87 +     ``ldif``
   39.88 +
   39.89 +   getent
   39.90 +     ``getent passwd``: restituisce tutti gli utenti del sistema, sia reali
   39.91 +     che ldap, secondo quanto definito nel file :file:`/etc/nsswitch`
   39.92 +     
   39.93 +     ``getent group``: analogo al precedente restituisce i gruppi
   39.94 +
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/docs/allegati/masterizzare.rst	Mon Apr 26 11:16:23 2010 +0200
    40.3 @@ -0,0 +1,26 @@
    40.4 +.. _masterizzare_iso:
    40.5 +
    40.6 +==========================
    40.7 + Masterizzare le immagini
    40.8 +==========================
    40.9 +
   40.10 +
   40.11 +Masterizzare un'immagine ISO da Windows
   40.12 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   40.13 +
   40.14 ++ nero ...
   40.15 ++ altri programmi
   40.16 +
   40.17 +Masterizzare un'immagine ISO da Linux
   40.18 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   40.19 +
   40.20 +Aprire un terminale e posizionarsi nella directory contenente il file iso
   40.21 +scaricato. Dopo aver inserito un cd vuoto, lanciare il comando::
   40.22 +
   40.23 +        cdrecord -v nomefile.iso
   40.24 +
   40.25 +Qualora non fosse presente sul sistema in uso il programma *cdrecord*, lo si
   40.26 +potrà installare lanciando come super-utente *root* il seguente comando::
   40.27 +
   40.28 +        apt-get install cdrecord
   40.29 +
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/docs/conf.py	Mon Apr 26 11:16:23 2010 +0200
    41.3 @@ -0,0 +1,172 @@
    41.4 +# -*- coding: utf-8 -*-
    41.5 +#
    41.6 +# Sphinx documentation build configuration file, created by
    41.7 +# sphinx-quickstart.py on Sat Mar  8 21:47:50 2008.
    41.8 +#
    41.9 +# This file is execfile()d with the current directory set to its containing dir.
   41.10 +#
   41.11 +# The contents of this file are pickled, so don't put values in the namespace
   41.12 +# that aren't pickleable (module imports are okay, they're removed automatically).
   41.13 +#
   41.14 +# All configuration values have a default value; values that are commented out
   41.15 +# serve to show the default value.
   41.16 +
   41.17 +import sys, os, re
   41.18 +cur_dir = os.path.dirname(__file__)
   41.19 +sys.path += [cur_dir]
   41.20 +sys.path += [os.path.dirname(cur_dir)]
   41.21 +import docusage
   41.22 +extensions = ['sphinx.ext.autodoc', 'docusage']
   41.23 +
   41.24 +# If your extensions are in another directory, add it here.
   41.25 +#sys.path.append(os.path.dirname(__file__))
   41.26 +
   41.27 +# General configuration
   41.28 +# ---------------------
   41.29 +
   41.30 +# Add any Sphinx extension module names here, as strings. They can be extensions
   41.31 +# coming with Sphinx (named 'sphinx.addons.*') or your custom ones.
   41.32 +#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
   41.33 +
   41.34 +# Add any paths that contain templates here, relative to this directory.
   41.35 +templates_path = ['_templates']
   41.36 +language="it"
   41.37 +# The suffix of source filenames.
   41.38 +source_suffix = '.rst'
   41.39 +
   41.40 +# The master toctree document.
   41.41 +master_doc = 'contents'
   41.42 +
   41.43 +# General substitutions.
   41.44 +project = 'ReteIsi'
   41.45 +#copyright = '2008, Sandro Dentella, Max Mancini'
   41.46 +
   41.47 +# The default replacements for |version| and |release|, also used in various
   41.48 +# other places throughout the built documents.
   41.49 +#
   41.50 +# The short X.Y version.
   41.51 +version = '0.1'
   41.52 +# The full version, including alpha/beta/rc tags.
   41.53 +release = '0.1'
   41.54 +
   41.55 +# There are two options for replacing |today|: either, you set today to some
   41.56 +# non-false value, then it is used:
   41.57 +#today = ''
   41.58 +# Else, today_fmt is used as the format for a strftime call.
   41.59 +today_fmt = '%B %d, %Y'
   41.60 +
   41.61 +# List of documents that shouldn't be included in the build.
   41.62 +#unused_docs = []
   41.63 +
   41.64 +# If true, '()' will be appended to :func: etc. cross-reference text.
   41.65 +#add_function_parentheses = True
   41.66 +
   41.67 +# If true, the current module name will be prepended to all description
   41.68 +# unit titles (such as .. function::).
   41.69 +#add_module_names = True
   41.70 +
   41.71 +show_authors = True
   41.72 +
   41.73 +# The name of the Pygments (syntax highlighting) style to use.
   41.74 +pygments_style = 'sphinx'
   41.75 +
   41.76 +
   41.77 +# Options for HTML output
   41.78 +# -----------------------
   41.79 +
   41.80 +# The style sheet to use for HTML and HTML Help pages. A file of that name
   41.81 +# must exist either in Sphinx' static/ path, or in one of the custom paths
   41.82 +# given in html_static_path.
   41.83 +#html_style = 'sphinxdoc.css'
   41.84 +html_style = 'reteisi.css'
   41.85 +
   41.86 +html_logo = 'reteisi.png'
   41.87 +
   41.88 +# Add any paths that contain custom static files (such as style sheets) here,
   41.89 +# relative to this directory. They are copied after the builtin static files,
   41.90 +# so a file named "default.css" will overwrite the builtin "default.css".
   41.91 +html_static_path = ['_static']
   41.92 +
   41.93 +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
   41.94 +# using the given strftime format.
   41.95 +html_last_updated_fmt = '%b %d, %Y'
   41.96 +
   41.97 +#html_logo = 'reteisi.png'
   41.98 +
   41.99 +# If true, SmartyPants will be used to convert quotes and dashes to
  41.100 +# typographically correct entities.
  41.101 +#html_use_smartypants = True
  41.102 +
  41.103 +# Content template for the index page.
  41.104 +html_index = 'index.html'
  41.105 +
  41.106 +# Custom sidebar templates, maps page names to templates.
  41.107 +html_sidebars = {'index': 'indexsidebar.html'}
  41.108 +
  41.109 +# Additional templates that should be rendered to pages, maps page names to
  41.110 +# templates.
  41.111 +html_additional_pages = {'index': 'index.html'}
  41.112 +
  41.113 +# If true, the reST sources are included in the HTML build as _sources/<name>.
  41.114 +#html_copy_source = True
  41.115 +
  41.116 +# Output file base name for HTML help builder.
  41.117 +htmlhelp_basename = 'Sphinxdoc'
  41.118 +
  41.119 +
  41.120 +# Options for LaTeX output
  41.121 +# ------------------------
  41.122 +
  41.123 +# The paper size ('letter' or 'a4').
  41.124 +latex_paper_size = 'a4'
  41.125 +
  41.126 +# The font size ('10pt', '11pt' or '12pt').
  41.127 +latex_font_size = '10pt'
  41.128 +
  41.129 +# Grouping the document tree into LaTeX files. List of tuples
  41.130 +# (source start file, target name, title, author, document class [howto/manual]).
  41.131 +latex_documents = [('contents', 'reteisi.tex', 'Documentazione ReteIsi',
  41.132 +                    'Sandro Dentella, Massimo Mancini, Simone Castellazzi',
  41.133 +                    'manual')]
  41.134 +
  41.135 +# Additional stuff for the LaTeX preamble.
  41.136 +#latex_preamble = ''
  41.137 +
  41.138 +# Documents to append as an appendix to all manuals.
  41.139 +#latex_appendices = []
  41.140 +
  41.141 +automodule_skip_lines = 4
  41.142 +
  41.143 +
  41.144 +# Extension interface
  41.145 +# -------------------
  41.146 +
  41.147 +from sphinx import addnodes
  41.148 +
  41.149 +dir_sig_re = re.compile(r'\.\. ([^:]+)::(.*)$')
  41.150 +
  41.151 +def parse_directive(env, sig, signode):
  41.152 +    if not sig.startswith('.'):
  41.153 +        dec_sig = '.. %s::' % sig
  41.154 +        signode += addnodes.desc_name(dec_sig, dec_sig)
  41.155 +        return sig
  41.156 +    m = dir_sig_re.match(sig)
  41.157 +    if not m:
  41.158 +        signode += addnodes.desc_name(sig, sig)
  41.159 +        return sig
  41.160 +    name, args = m.groups()
  41.161 +    dec_name = '.. %s::' % name
  41.162 +    signode += addnodes.desc_name(dec_name, dec_name)
  41.163 +    signode += addnodes.desc_classname(args, args)
  41.164 +    return name
  41.165 +
  41.166 +
  41.167 +def parse_role(env, sig, signode):
  41.168 +    signode += addnodes.desc_name(':%s:' % sig, ':%s:' % sig)
  41.169 +    return sig
  41.170 +
  41.171 +
  41.172 +def setup(app):
  41.173 +    app.add_description_unit('directive', 'dir', 'pair: %s; directive', parse_directive)
  41.174 +    app.add_description_unit('role', 'role', 'pair: %s; role', parse_role)
  41.175 +    app.add_description_unit('confval', 'confval', 'pair: %s; configuration value')
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/docs/contents.rst	Mon Apr 26 11:16:23 2010 +0200
    42.3 @@ -0,0 +1,22 @@
    42.4 +.. ReteIsi documentation master file, created by sphinx-quickstart on Thu Apr 10 21:38:49 2008.
    42.5 +   You can adapt this file completely to your liking, but it should at least
    42.6 +   contain the root `toctree` directive.
    42.7 +
    42.8 +=================================================
    42.9 + Benvenuti nel sito di documentazione di ReteIsi
   42.10 +=================================================
   42.11 +
   42.12 +
   42.13 +.. toctree::
   42.14 +   :maxdepth: 2
   42.15 +   
   42.16 +   progetto/contents
   42.17 +   install/contents
   42.18 +   gestione/contents
   42.19 +   allegati/contents
   42.20 +
   42.21 +Indices and tables
   42.22 +==================
   42.23 +
   42.24 +* :ref:`search`
   42.25 +
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/docs/docusage.py	Mon Apr 26 11:16:23 2010 +0200
    43.3 @@ -0,0 +1,121 @@
    43.4 +# -*- coding: utf-8 -*-
    43.5 +'''
    43.6 +This module provides the ``includesh`` directive. It is implemented by
    43.7 +:class:`IncludeShellDirective` class.
    43.8 +'''
    43.9 +import os
   43.10 +import re
   43.11 +import types
   43.12 +import tempfile
   43.13 +
   43.14 +# Import required docutils modules
   43.15 +from sphinx.util.compat import Directive
   43.16 +
   43.17 +from docutils import io, nodes, statemachine, utils
   43.18 +from docutils.parsers.rst import directives
   43.19 +from docutils.parsers.rst.directives.misc import Include
   43.20 +# from docutils.parsers.rst.directives.tables import ListTable
   43.21 +
   43.22 +import sphinx
   43.23 +
   43.24 +
   43.25 +#---------------------------------------------------------#
   43.26 +class IncludePyProgramDirective(Include):
   43.27 +  '''
   43.28 +  IncludeShellDirective implements the directive. The class
   43.29 +  is registered as a directive in :func:`rusty.includesh.setup`
   43.30 +  '''
   43.31 +  required_arguments = 1
   43.32 +  optional_arguments = 0
   43.33 +  has_content = None
   43.34 +  node_class = None
   43.35 +  option_spec = {
   43.36 +      'verbatim': directives.flag,
   43.37 +      'docstring': directives.unchanged,
   43.38 +  }
   43.39 +
   43.40 +  #---------------------------------------------------------#
   43.41 +  def run(self):
   43.42 +    '''
   43.43 +    Called automatically by the docutils.
   43.44 +    '''
   43.45 +
   43.46 +    # Take the current inclusion file, read it and save in
   43.47 +    # temporary location where the actual ``Include`` directive
   43.48 +    # can read it
   43.49 +
   43.50 +    # This part is taken from docutils
   43.51 +    if not self.state.document.settings.file_insertion_enabled:
   43.52 +      raise self.warning('"%s" directive disabled.' % self.name)
   43.53 +
   43.54 +    source = self.state_machine.input_lines.source(
   43.55 +      self.lineno - self.state_machine.input_offset - 1)
   43.56 +
   43.57 +    source_dir = os.path.dirname(os.path.abspath(source))
   43.58 +    path = directives.path(self.arguments[0])
   43.59 +
   43.60 +    if path.startswith('<') and path.endswith('>'):
   43.61 +      path = os.path.join(self.standard_include_path, path[1:-1])
   43.62 +
   43.63 +    path = os.path.normpath(os.path.join(source_dir, path))
   43.64 +    path = utils.relative_path(None, path)
   43.65 +
   43.66 +    try:
   43.67 +      self.state.document.settings.record_dependencies.add(path)
   43.68 +      include_file = open(path, 'r+b')
   43.69 +    except IOError, error:
   43.70 +      raise self.severe('Problems with "%s" directive path:\n%s: %s.'
   43.71 +                        % (self.name, error.__class__.__name__, error))
   43.72 +
   43.73 +    try:
   43.74 +      include_text = include_file.read()
   43.75 +    except UnicodeError, error:
   43.76 +      raise self.severe(
   43.77 +        'Problem with "%s" directive:\n%s: %s'
   43.78 +        % (self.name, error.__class__.__name__, error))
   43.79 +
   43.80 +    if not 'docstring' in self.options:
   43.81 +      self.options['docstring'] = '__doc__'
   43.82 +      
   43.83 +    self.arguments[0] = self.get_docstring_file(path)
   43.84 +
   43.85 +    return Include.run(self)
   43.86 +
   43.87 +  def get_docstring_file(self, path):
   43.88 +    p = Program(path)
   43.89 +    tfd, target_path = tempfile.mkstemp(prefix='sd-')
   43.90 +    f = open(target_path, 'wb')
   43.91 +    text = p.docstring
   43.92 +    
   43.93 +    if 'verbatim' in self.options:
   43.94 +      f.write('::\n')
   43.95 +      pat = re.compile('^', re.MULTILINE)
   43.96 +      text = re.sub(pat, "  ", text )      
   43.97 +
   43.98 +    f.write("%s\n" % text)
   43.99 +    return target_path
  43.100 +
  43.101 +
  43.102 +def setup(app):
  43.103 +  '''
  43.104 +  Extension setup, called by Sphinx
  43.105 +  '''
  43.106 +  # Sphinx 5 support
  43.107 +  if '5' in sphinx.__version__.split('.'):
  43.108 +    app.add_directive('docusage', IncludePyProgramDirective, 0, (0,0,0))
  43.109 +  else:
  43.110 +    app.add_directive('docusage', IncludePyProgramDirective)
  43.111 +
  43.112 +class Program(object):
  43.113 +
  43.114 +    DOCSTRING = re.compile(
  43.115 +        r'''
  43.116 +        """(?P<docstring>.*?)"""
  43.117 +        ''',
  43.118 +        re.VERBOSE|re.DOTALL
  43.119 +        )
  43.120 +    def __init__(self, filename):
  43.121 +
  43.122 +        self.text = open(filename).read()
  43.123 +        self.docstring = self.DOCSTRING.search(self.text).group('docstring')
  43.124 +    
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/docs/gestione/comandi_isi.rst	Mon Apr 26 11:16:23 2010 +0200
    44.3 @@ -0,0 +1,339 @@
    44.4 +.. _gestione_comandi_isi:
    44.5 +
    44.6 +I comandi isi*
    44.7 +==============
    44.8 +
    44.9 +Come operare sul server
   44.10 +-----------------------
   44.11 +
   44.12 +E` possibile gestire gli utenti per mezzo dei comandi presentati di seguito
   44.13 +o tramite l'interfaccia web.
   44.14 +
   44.15 +comandi isi2* e isi*
   44.16 +--------------------
   44.17 +
   44.18 +Con la versione 2.0 di isi, tutti i comandi sono stati riscritti in
   44.19 +Python. In un momento di transizione ci sono state due seria di comandi isi* ed isi2*
   44.20 +ora gli unici comandi non hanno lídentificativo '2' ma sono quelli in python.
   44.21 +
   44.22 +Con questa release gli utenti vengono gestiti senza usare i tools
   44.23 +smbldap-tools, il che permette in generale una velocità maggiore di
   44.24 +esecuzione ed un controllo molto più elevato degli errori.
   44.25 +
   44.26 +Gestione utenti
   44.27 +---------------
   44.28 +
   44.29 +.. index:: isi-adduser, creazione utenti;
   44.30 +  
   44.31 +.. _isi-adduser:
   44.32 +
   44.33 +isi-adduser
   44.34 +~~~~~~~~~~~~
   44.35 +
   44.36 +.. docusage:: ../../usr/sbin/isi-adduser
   44.37 +   :verbatim:
   44.38 +
   44.39 +Utility per aggiugere utenti. Puo' essere usata sia interattivamente sia in
   44.40 +modo script leggendo da file (opzione ``-f``) che passando la definizione dell'
   44.41 +alunno da riga di comando.  
   44.42 +
   44.43 +.. note:: Formato file/formato dati
   44.44 +
   44.45 +   Non bisogna confondete il formato dei dati (la successione delle colonne)
   44.46 +   con il formato del file (.csv o .xls). Nel gergo comune entrambi sono
   44.47 +   noti come "formato di file"
   44.48 +
   44.49 +   ``csv`` (comma separated values) è un formato di testo in cui le colonne
   44.50 +   sono separate da "," o da altri caratteri (";" nel nostro caso, "Tab" a
   44.51 +   volte). Per editare un file .csv si può usare ``opencalc`` o anche un editor
   44.52 +   di testo qualunque.
   44.53 +
   44.54 +   ``xls`` è un formato binario proprietario della suite Office di
   44.55 +   Microsoft, deve essere editto con un programma come Excel, opencalc della
   44.56 +   suite OpenOffice o gnumeric. Il motivo per cui lo supportiamo qui è che
   44.57 +   il programma ministeriale ``Sissi`` esporta i dati unicamnete in ``.xls``
   44.58 +
   44.59 +   La successione delle colonne determina il modo in cui il programma
   44.60 +   interpreta i dati. E` una cosa completamente distinta (ed aggiuntiva)
   44.61 +   rispetto l formato del file, e sono descritti in modo completo di seguito.
   44.62 +
   44.63 +
   44.64 +
   44.65 +
   44.66 +Formato file .isi
   44.67 +.................
   44.68 +
   44.69 +Il formato della riga deve essere almeno::
   44.70 +
   44.71 +  logname;cognome;nome;gruppo_principale;classe;CF;password  
   44.72 +
   44.73 +possono essere accodati altri campi rispettando il seguente formato::
   44.74 +
   44.75 +  sesso;indirizzo;cap;comune;provincia;telefono  
   44.76 +
   44.77 +ogni campo puo' essere vuoto tranne ``logname``, ``cognome`` e ``gruppo 
   44.78 +principale`` che deve essere uno fra: admins, alunni, docenti, esterni,
   44.79 +segreteria, ata.  La classe ha senso per *alunni* ed *esterni* e verra'
   44.80 +usata per connettere la risorsa classe.
   44.81 +
   44.82 +Aggiornamenti
   44.83 +.............
   44.84 +
   44.85 +Se viene usata l'opzione ``--update-users`` ogni utente già esistente viene
   44.86 +semplicemente ridefinito, questa è la situazione normale che avviene ad
   44.87 +inizio anno. Se non viene usata questa opzione il programma esce con un errore.
   44.88 +
   44.89 +Ogni riga che inizi  con ``-`` corrisponde ad un utente da eliminare. Esempi::
   44.90 +
   44.91 +  -a_dntlsn
   44.92 +  -a_test;Alunno;Test
   44.93 +  d_test;Docente;test;docenti;;CF;isi
   44.94 +
   44.95 +Aggiunge un utente d_test con password *isi* ed elimina due utenti con
   44.96 +logname a_dntlsn e a_test.
   44.97 +
   44.98 +L'opzione ``-z`` indica di eliminare la home degli utenti da cancellare,
   44.99 +mentre l'opzione ``--home tar`` (default) crea un file .tgz della home.
  44.100 +
  44.101 +La forma ``isi-adduser user gruppo`` aggiunge l'utente al gruppo. Ogni nuovo
  44.102 +utente viene aggiunto ad alcuni gruppi definiti in
  44.103 +``/etc/isi/defaults.py`` nella variabile EXTRA_GROUPS: per default sono
  44.104 +gruppi necessari per i sistemi LTSP ``plugdev`` e ``audio``::
  44.105 +
  44.106 +
  44.107 +  EXTRA_GROUPS = ['plugdev','audio']
  44.108 +
  44.109 +Gestione password
  44.110 +.................
  44.111 +
  44.112 +nel momento dell'inserimento è possibile sovrascrivere la password
  44.113 +eventualmente presente nel file in formato ``.isi`` con le opzioni di
  44.114 +comando:
  44.115 +
  44.116 +:--default-passwd, -p:  ogni utente avrà quella password assegnata
  44.117 +
  44.118 +:--use-cf, -C: usa i primi o caratteri del CF con la prima lettera maiuscola
  44.119 +
  44.120 +:--passwd-random, -P: viene generata una password randomica di 8 caratteri
  44.121 +
  44.122 +:--force-change-passwd, -B: viene imposto il cambio password al primo
  44.123 +   collegamento. Questo funziona sotto Windows ma non viene forzato con linux
  44.124 +   in quanto l'interfaccia grafica GDM non permette di fare il login e quindi
  44.125 +   non si riuscirebbe ad arrivare al cambio password... Accettiamo suggerimenti
  44.126 +
  44.127 +
  44.128 +isi-deluser
  44.129 +~~~~~~~~~~~~
  44.130 +.. docusage:: ../../usr/sbin/isi-deluser
  44.131 +   :verbatim:
  44.132 +
  44.133 +
  44.134 +isi-passwd
  44.135 +~~~~~~~~~~~
  44.136 +
  44.137 +.. docusage:: ../../usr/bin/isi-passwd
  44.138 +   :verbatim:
  44.139 +
  44.140 +
  44.141 +isi-groupcat
  44.142 +~~~~~~~~~~~~~
  44.143 +.. docusage:: ../../usr/sbin/isi-groupcat
  44.144 +   :verbatim:
  44.145 +
  44.146 +
  44.147 +isi-alulink
  44.148 +~~~~~~~~~~~~~
  44.149 +.. docusage:: ../../usr/sbin/isi-alulink
  44.150 +   :verbatim:
  44.151 +
  44.152 +
  44.153 +isi-classe
  44.154 +~~~~~~~~~~~~~
  44.155 +.. docusage:: ../../usr/sbin/isi-classe
  44.156 +   :verbatim:
  44.157 +
  44.158 +
  44.159 +isi-computer
  44.160 +~~~~~~~~~~~~~
  44.161 +.. docusage:: ../../usr/sbin/isi-computer
  44.162 +   :verbatim:
  44.163 +
  44.164 +isi-quota
  44.165 +~~~~~~~~~~~~~
  44.166 +.. docusage:: ../../usr/sbin/isi-quota
  44.167 +   :verbatim:
  44.168 +
  44.169 +isi-wlg
  44.170 +~~~~~~~~~~~~~
  44.171 +.. docusage:: ../../usr/sbin/isi-wlg
  44.172 +   :verbatim:
  44.173 +
  44.174 +isi-perms
  44.175 +~~~~~~~~~~
  44.176 +
  44.177 +.. docusage:: ../../usr/sbin/isi-perms
  44.178 +   :verbatim:
  44.179 +
  44.180 +.. _isi-convert:
  44.181 +
  44.182 +isi-convert
  44.183 +~~~~~~~~~~~
  44.184 +.. docusage:: ../../usr/sbin/isi-convert
  44.185 +   :verbatim:
  44.186 +
  44.187 +A differenza di ``isi-prepusers``, ``isi-convert`` non genera file se non
  44.188 +richiesto. Analizza un file in :ref:`formato_sissi` (.csv o .xls), ovvero con colonne di nomi 
  44.189 +standard e compone un nome di login per l'utente, aggiungendo un progressivo se trova
  44.190 +doppioni. E` possibile generare nomi con schemi differenti:
  44.191 +
  44.192 +  :name: il logname viene composta con *nome.cognome*
  44.193 +         (alessandro.dentella). Opzione ``--name``
  44.194 +
  44.195 +  :cf: il logname viene compostao come identificativo gruppo seguito dal
  44.196 +       codice fiscale (a_dntlsn63d07). Opzione  ``--use-cf``
  44.197 +
  44.198 +  :id-name: il logname viene composto da identificativo gruppo seguito da
  44.199 +       nome.cognome (d_sandro.dentella). Opzion e ``--id-name``
  44.200 +
  44.201 +E possibile ottenere come output l'elenco degli utenti che verranno
  44.202 +eliminati (opt: ``--delete`` o quello degli utenti rinominati -usando un
  44.203 +progressivo- a causa di colisione con nomi esistenti (opt: ``--rename``).
  44.204 +
  44.205 +Il formato esteso è usato solo nelle scuole dove viene gestita anche la
  44.206 +biblioteca. In queste scuole è necessario che il file Sissi abbia anche i
  44.207 +dati di residenza e telefono.
  44.208 +
  44.209 +Il file prodotto da isi-convert può essere usato come input per
  44.210 +:ref:`isi-adduser`. 
  44.211 +
  44.212 +``isi-convert`` accetta come input file con dati in due formati differenti:
  44.213 +
  44.214 +:sissi: il programma di gestione alunni usato da molte scuole italiane
  44.215 +:isi:   il formato ufficiale di ReteISI. l'ultilità di convertire da .isi a
  44.216 +   .isi è di potere:
  44.217 +
  44.218 +   * gestire nomi doppi
  44.219 +   * usare file di input in formato .xls
  44.220 +
  44.221 +.. _formato_sissi:
  44.222 +
  44.223 +formato sissi
  44.224 +.............
  44.225 +
  44.226 +Il formato "Sissi" è basato su alcune colonne con nomi standard, il nome
  44.227 +della colonna deve rispettare anche nelle maiuscole/Minuscole quanto sotto
  44.228 +riportato, ed è per altro il default di Sissi.:
  44.229 +
  44.230 +:Anno di corso:  es.:  3  per la terza classe
  44.231 +:Sezione:  es.: A
  44.232 +:Corso:  es.: Programmatori Mercurio
  44.233 +:Cognome: ovvio
  44.234 +:Nome: ovvio
  44.235 +:Codice fiscale: ovvio
  44.236 +
  44.237 +Da una tabella con queste intestazioni è possibile generare la classe di
  44.238 +appartenenza solo in presenza di un opportuno file di corrispondenza fra il
  44.239 +Corso e la sigla che si vuole usare, questo file è
  44.240 +``/etc/isi/sissi-tabcorsi``::
  44.241 +
  44.242 +  progetto cinque = geo
  44.243 +  geometri        = geo
  44.244 +  indirizzo giuridico economico aziendale = ige
  44.245 +  programmatori mercurio = pro
  44.246 +
  44.247 +
  44.248 +In questo esempio la classe di appartenenza dell'alunno è ``pro3a``
  44.249 +
  44.250 +
  44.251 +isi-tools
  44.252 +~~~~~~~~~~~
  44.253 +
  44.254 +.. docusage:: ../../usr/sbin/isi-tools
  44.255 +   :verbatim:
  44.256 +
  44.257 +isi-user
  44.258 +~~~~~~~~~~~
  44.259 +
  44.260 +Il programma ``isi-user`` fa alcune funzioni che sono state reimplementate
  44.261 +nella interfaccia web. Per questioni di usabilità e di manutenzione del
  44.262 +codice raccomandiamo di usare l'interfaccia web.
  44.263 +
  44.264 +Importare utenti da sissi
  44.265 +~~~~~~~~~~~~~~~~~~~~~~~~~
  44.266 +
  44.267 +.. note:: 
  44.268 +
  44.269 +   le operazioni di importazione utenti da Sissi erano fatte nelle release
  44.270 +   precedenti da ``isi-prepusers``, un programma in perl. Nella
  44.271 +   ristrutturazione che ha portato alla nuova release di isi il prgramma è
  44.272 +   stato sostituito da ``isi-convert`` (in python) che ha alcune migliorie
  44.273 +   fra cui: l'abilità di leggere da formato ``.xls`` (formato di output di
  44.274 +   Sissi) e la maggiore estensibilità ad accettare altri formati in futuro.
  44.275 +
  44.276 +Estrazione dei dati con Open Sissi.
  44.277 +Open Sissi è il programma di utilità compreso nel pacchetto SISSI in rete messo a 
  44.278 +disposizione di tutte le scuole italiane dal MIUR per la gestione delle segreterie 
  44.279 +scolastiche (e non solo). Per quanto ci riguarda, siamo interessati alla capacità 
  44.280 +di Open Sissi di produrre un file con i dati degli studenti estraendoli dal db Sql
  44.281 +gestito da SISSI. La funzionalità da utilizzare è, dal menù di Open Sissi, Utilità,
  44.282 +Report dinamici, che ci metterà in condizione di comporre un report con i campi 
  44.283 +desiderati (per noi, oltre a nome, cognome, data di nascita, anche codice fiscale, 
  44.284 +corso, anno di corso e sezione). Open Sissi produce il report in formato Excel che 
  44.285 +viene richiamato automaticamente (non sembra ci sia la possibilità di avere un semplice
  44.286 +salvataggio del report, quindi bisogna che sulla macchina su cui gira Open Sissi
  44.287 +ci sia anche Excel - incredibile ma vero). 
  44.288 +
  44.289 +
  44.290 +Da questo momento è possibile sia procedere via interfaccia web sia come
  44.291 +descritto usando il comando :ref:`isi-convert`
  44.292 +
  44.293 +
  44.294 +isi-perms
  44.295 +~~~~~~~~~~~
  44.296 +
  44.297 +A cosa serve?
  44.298 +..............
  44.299 +
  44.300 +Le ACL solitamente vengono impostate subito dopo l'installazione del sistema e 
  44.301 +non dovrebbero richiedere alcuna manutenzione. Esperienza insegna che questo
  44.302 +non sempre è vero. Qualche imprevisto può sempre capitare e talvolta coinvolgere
  44.303 +diversi utenti. Per garantire la ricostituzione di una situazione di "coerente"
  44.304 +ci viene in aiuto isi-perms, grazie al quale è possibile impostare le acl 
  44.305 +impostate sul nostro filesystem.
  44.306 +Chi non sapesse cosa sono le acl potrà approfondire `qui <http://a2.pluto.it/a2227.htm>`_
  44.307 +
  44.308 +I file di configurazione
  44.309 +...........................
  44.310 +
  44.311 +isi-perms utilizza due file di configurazione:
  44.312 +
  44.313 +:/etc/isi/acl.conf: Configurazione di default
  44.314 +
  44.315 +:/etc/isi/acl-local.conf: Configurazione personalizzabile dall'utente; può 
  44.316 +  sovrascrivere le opzioni di default.
  44.317 +
  44.318 +.. Note::
  44.319 +
  44.320 +    Non apportare le tue modifiche a /etc/isi/acl.conf o rieschierai di perderle
  44.321 +    in fase di aggiornamento del sistema!.
  44.322 +
  44.323 +Per definire nuove acl per directory non definite nella configurazione di default,
  44.324 +si potrà usare a modello il file ``acl.conf`` ed inserire le proprie 
  44.325 +ersonalizzazioni nel file acl-local.conf.
  44.326 +Qualora si volesse sovrascrivere una particolare configurazione già definita, 
  44.327 +basterà ridefinirla (la versione inserita in acl-local.conf avrà sempre la
  44.328 +precedenza).
  44.329 +    
  44.330 +Esempi di utilizzo
  44.331 +.....................
  44.332 +
  44.333 +Inizializzare le acl per tutti gli utenti e le share::
  44.334 +
  44.335 +    isi-perms
  44.336 +
  44.337 +Risettare i permessi di una particolare directory::
  44.338 +
  44.339 +    isi-perms <directory>
  44.340 +
  44.341 +isi-perms lanciato senza specificare una directory, può impiegare molto tempo.
  44.342 +Quando possibile, lo si utilizi su directory ben precise.
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/docs/gestione/contents.rst	Mon Apr 26 11:16:23 2010 +0200
    45.3 @@ -0,0 +1,9 @@
    45.4 +========
    45.5 +Gestione 
    45.6 +========
    45.7 +
    45.8 +.. toctree::
    45.9 +
   45.10 +   comandi_isi.rst
   45.11 +   web.rst
   45.12 +   isi-checkup.rst
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/docs/gestione/isi-checkup.rst	Mon Apr 26 11:16:23 2010 +0200
    46.3 @@ -0,0 +1,116 @@
    46.4 +.. _isi-checkup:
    46.5 +
    46.6 +isi-checkup
    46.7 +==============
    46.8 +
    46.9 +Esiste una esperienza di laboratorio sull'uso di :ref:`lab_checkup`
   46.10 +
   46.11 +Cos'è
   46.12 +------
   46.13 +
   46.14 +``isi-checkup`` è la suite di diagnostica del progetto ReteISI. Nasce con lo scopo di 
   46.15 +rilevare e notificare i problemi di configurazione più comuni. Viene costantemente
   46.16 +aggiornata al fine di permettere di indentificare un numero sempre crescente di
   46.17 +errori.
   46.18 +Molto importanti ed apprezzati, sono quindi tutte le segnalazioni di problemi non
   46.19 +coperti dalla Suite, fatte in mailing list Rete ISI. Segnalazioni che si tradurranno
   46.20 +con tutta probabilità in un nuovi test.
   46.21 +
   46.22 +Cosa non è
   46.23 +-------------
   46.24 +
   46.25 +Non è una tool di correzione degli errori: effettua checkup, non fix!
   46.26 +
   46.27 +Installazione
   46.28 +---------------
   46.29 +
   46.30 +Chi non lo avesse già installato potrà farlo, come root, con un semplice::
   46.31 +
   46.32 +    apt-get install isi-checkup
   46.33 +
   46.34 +Le componenti
   46.35 +----------------
   46.36 +
   46.37 +Il sistema è composto principalmente da:
   46.38 +
   46.39 +- test
   46.40 +- template
   46.41 +- file di esclusione : /etc/isi/checkup/exclude
   46.42 +
   46.43 +I test
   46.44 +++++++++++
   46.45 +
   46.46 +I test presenti nel sistema, scritti principalmente in codice python( e
   46.47 +qualcuno in shell script), sono contenuti in ``/usr/share/isi-checkup/tests/``.
   46.48 +
   46.49 +Ogni script di test ha un nome che indica, con la prima parte numerica, la sua
   46.50 +appartenenza ad un particolare gruppo. I gruppi definiti ad oggi (release
   46.51 +in hg numero 119) sono i seguenti :
   46.52 +
   46.53 +-    test di sistema ( range   0 ~ 499 )
   46.54 +-    test utente     ( range 500 ~ 700 )
   46.55 +-    test locali     ( range 701 ~ 2000)
   46.56 +-    tutti i test    ( range   0 ~ 2000)
   46.57 +
   46.58 +I test di ``sistema`` si occupano principalmente di rilevare problemi di configurazione
   46.59 +legati al boot, file di configurazioni mancanti, etc...
   46.60 +
   46.61 +I test ``utente`` effettuano una serie di controlli concentrandosi esclusivamente
   46.62 +su un singolo utente o tutti gli utenti. Viene controllato, ad esempio, che l'utente
   46.63 +possa leggere, scrivere od attraversare determinati file o cartelle.
   46.64 +Sarà capitato a tutti di incappare nel famigerato messaggio di windows "Impossibile 
   46.65 +trovare il profilo". Quasi sempre, questo problema è dovuto all'impossibilità 
   46.66 +dell'utente di accedere ad alcuni file della propria home directory.
   46.67 +
   46.68 +I test ``locali`` sono test che un utente può decidere di aggiungere per conto 
   46.69 +proprio. Andranno aggiunti in :file:`/etc/isi/checkup` e dovranno appartenere al range
   46.70 +(701 ~ 2000).
   46.71 +
   46.72 +Per lanciare un particolare gruppo di test, basterà invocare il comando 
   46.73 +``isi-checkup`` con la relativa opzione. Si faccia riferimento all'help
   46.74 +del comando per le opzioni da usare.
   46.75 +
   46.76 +I template
   46.77 +++++++++++++
   46.78 +
   46.79 +In ``/usr/share/isi-checkup`` troveremo invece i file template *\*.conf*.
   46.80 +Cos'è un template? Un template è un semplice file di testo in cui vengono
   46.81 +elencati tutti i test da attivare all'attivazione del profilo. Questo
   46.82 +permette, tramite la semplice preparazione di template differenti di coprire
   46.83 +le necessità di differenti tipologie di macchine (server ReteISI, server
   46.84 +LTSP, firewall, client Linux). Al momento esiste un solo template che è
   46.85 +quello del server ReteISI.
   46.86 +
   46.87 +Volendo, ad esempio, attivare tutti i test contenuti nel profilo di default
   46.88 +``isi.conf`` ::
   46.89 +
   46.90 +    isi-checkup -t isi
   46.91 +
   46.92 +.. Note::
   46.93 +
   46.94 +    - Il template ``isi.conf`` copre la totalità dei test presenti.
   46.95 +    - Non modificate i file di template, il file viene sovrascritto ad ogni
   46.96 +      aggiornamento della suite e le vostre modifiche andranno perdute.
   46.97 +
   46.98 +Il file exclude
   46.99 ++++++++++++++++++
  46.100 +
  46.101 +E' possibile evitare che un test venga lanciato accodandone il nome al file
  46.102 +/etc/isi/checkup/exclude.
  46.103 +
  46.104 +.. Note ::
  46.105 +
  46.106 +    Con *nome* ci si riferisce al nome del file privo della parte numerica.
  46.107 +    es. squid_run_on_boot.py
  46.108 +
  46.109 +    E' inoltre possibile copiare-incollare direttamente dal report a due
  46.110 +    colonne di isi-checkup.
  46.111 +
  46.112 +
  46.113 +    Esempio::
  46.114 +
  46.115 +     I seguenti test non sono andati a buon fine
  46.116 + 
  46.117 +     squid_run_on_boot.py                     BootProcessSquid
  46.118 +
  46.119 +    (notare la riga relativa al test squid_run_on_boot.py fallito)
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/docs/gestione/phpldapadmin.rst	Mon Apr 26 11:16:23 2010 +0200
    47.3 @@ -0,0 +1,71 @@
    47.4 +.. _gestione_frontends_phpldapadmin:
    47.5 +
    47.6 +phpldapadmin
    47.7 +============
    47.8 +
    47.9 +.. figure:: ../img/frontends/phpldapadmin.jpg
   47.10 +   :align: center
   47.11 +
   47.12 +Requisiti
   47.13 +---------
   47.14 +- Server Apache2 installato e configurato.
   47.15 +- PHP5 (testata la versione versione 5).
   47.16 +
   47.17 +
   47.18 +
   47.19 +Installazione del pacchetto
   47.20 +---------------------------
   47.21 +
   47.22 +Autenticarsi nel sistema come utente root e digitare::
   47.23 +
   47.24 +    dpkg -l |grep phpldapadmin
   47.25 +
   47.26 +Se l'output mostrerà che il pacchetto è già installato (notare ``ii``) potremo
   47.27 +saltare il passaggio successivo::
   47.28 +
   47.29 +    ii  phpldapadmin  0.9.8.3-8  web based interface for administering LDAP s
   47.30 +
   47.31 +In caso contrario, dovremo installare ``phpldapadmin`` come segue::
   47.32 +
   47.33 +    apt-get install phpldapadmin
   47.34 +
   47.35 +Configurazione di apache2
   47.36 +-------------------------
   47.37 +
   47.38 +La configurazione consisterà semplicemente nel creare un `alias` che permetta
   47.39 +di raggiungere gli script php del programma ed una configurazione di default( 
   47.40 +modificabile come meglio si creda) relativa all'accesso alla risorsa, compresa
   47.41 +tra `<Directory>` e `</Directory>`.
   47.42 +
   47.43 +Modificare quindi la configurazione del proprio sito aggiungendo tra `<VirtualHost>` e
   47.44 +`</VirtualHost>` ::
   47.45 +
   47.46 +    Alias "/usr/share/phpldapadmin/" /phpldapadmin/"
   47.47 +    <Directory "/usr/share/phpldapadmin/">
   47.48 +        Options Indexes MultiViews FollowSymLinks
   47.49 +        AllowOverride None
   47.50 +        Order deny,allow
   47.51 +        Deny from all
   47.52 +        Allow from 127.0.0.0/255.0.0.0 ::1/128
   47.53 +    </Directory>
   47.54 +
   47.55 +.. Note::
   47.56 +
   47.57 +    Salvo casi particolari, la configurazione di apache da modificare dovrebbe
   47.58 +    essere contenuta nel file ``/etc/apache2/sites-available/default``.
   47.59 +    
   47.60 +    Si potrà provvedere dunque alla modifica di tale file con un editor di testo 
   47.61 +    qualunque::
   47.62 +
   47.63 +        jmacs /etc/apache2/sites-available/default
   47.64 +
   47.65 +Terminata la modifica alla configurazione, basterà farla ricaricare al servente::
   47.66 +
   47.67 +    /etc/init.d/apache2 reload
   47.68 +
   47.69 +Verifica
   47.70 +--------
   47.71 +
   47.72 +Sarà ora possibile verificare che tutto funzioni puntando il proprio browser
   47.73 +all'url ``http://ip-WebServer/phpldapadmin``.
   47.74 +
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/docs/gestione/web.rst	Mon Apr 26 11:16:23 2010 +0200
    48.3 @@ -0,0 +1,91 @@
    48.4 +.. _web:
    48.5 +
    48.6 +================
    48.7 +Interfaccia web
    48.8 +================
    48.9 +
   48.10 +Struttura
   48.11 +=========
   48.12 +
   48.13 +L'interfaccia web ha cinque sezioni:
   48.14 +
   48.15 +:utenti: permette di inserire utenti, modificarli, cancellarli, navigare fra
   48.16 +         gli utenti definiti, vedere i gruppi  e le classi, impostare la
   48.17 +         quota per ogni grupo
   48.18 +
   48.19 +:samba:  permette di rinominare il dominio
   48.20 +
   48.21 +:navigazione: gestisce il gruppo ``nowww``. Il proxy web può usare questo
   48.22 +         gruppo per interdire la navigazione agli utenti.
   48.23 +
   48.24 +:dnsmasq: questa è una interfaccia web alla configurazione del server dns e
   48.25 +         dhcp ``dnsmasq``
   48.26 +
   48.27 +:logon:  permette la configurazione della fare di logon dei client Windows
   48.28 +
   48.29 +
   48.30 +Screenshot
   48.31 +==========
   48.32 +
   48.33 +Alcune immagini in ordine sparso:
   48.34 +
   48.35 +.. image:: ../img/web/web-start.png
   48.36 +
   48.37 +.. image:: ../img/web/web-utenti.png
   48.38 +
   48.39 +.. image:: ../img/web/web-users-file.png
   48.40 +
   48.41 +.. image:: ../img/web/web-nomi.png
   48.42 +
   48.43 +.. image:: ../img/web/web-sissi.png
   48.44 +
   48.45 +.. image:: ../img/web/web-classi.png
   48.46 +
   48.47 +.. image:: ../img/web/web-dns.png
   48.48 +
   48.49 +.. image:: ../img/web/web-navigazione.png
   48.50 +
   48.51 +Accesso
   48.52 +=======
   48.53 +
   48.54 +
   48.55 +L'accesso alla interfaccia web è garantito all'utente ``admin`` con password
   48.56 +identica a quella contenuta in :file:`/etc/ldap.secret`  (leggibile solo a
   48.57 +root) o a qualunque utente del gruppo ``admins`` con la propria password. 
   48.58 +
   48.59 +I docenti hanno pure accesso all'interfaccia limitatamente alla sola
   48.60 +inibizione della navigazione.
   48.61 +
   48.62 +Installazione
   48.63 +==============
   48.64 +
   48.65 +L'interfaccia web viene lanciata da uno script di init
   48.66 +:file:`/etc/init.d/isiweb` che legge un file in :file:`/etc/defaults/isiweb`
   48.67 +dove è possibile inibire l'avviamento dell'interfaccia valorizzando a '0' la
   48.68 +variabile START_FSCGI::
   48.69 +
   48.70 +  START_FSCI=1
   48.71 +
   48.72 +l'installazione del pacchetto ``isi-web`` viene fatta nel solito modo::
   48.73 +
   48.74 +  apt-get install isi-web
   48.75 +
   48.76 +e mette la configurazione di apache in
   48.77 +:file:`/etc/apache2/site-available/isiweb.conf` in come VirtualHost con nome
   48.78 +web.isi.lan: questo significa che per potere raggiungere questa interfaccia
   48.79 +occorre avere una risoluzione corretta nel server, che risolva l'ip del
   48.80 +server. Questa risoluzioe può essere messa in :file:`/etc/hosts` del server se usate
   48.81 +il server come dns ed usate dnsmasq, ad esempio se avete il server
   48.82 +all'indirizzo 192.168.10.1::
   48.83 +
   48.84 +  192.168.10.1  web.isi.lan srv
   48.85 +  /etc/init.d/dnsmasq restart
   48.86 +
   48.87 +se non avete altre interfacce web sul server e quindi non vi serve avere i
   48.88 +VirtualHosts potete semplicemente abilitare ``isiweb-all`` che è la
   48.89 +configurazione che risponde su ogni nome::
   48.90 +
   48.91 +  a2dissite isiweb.conf
   48.92 +  a2ensite isiweb-all.conf
   48.93 +  /etc/init.d/apache2 reload
   48.94 +
    49.1 Binary file docs/img/frontends/phpldapadmin.jpg has changed
    50.1 Binary file docs/img/grub4dos/common_01_share-software.png has changed
    51.1 Binary file docs/img/grub4dos/win98_03_menu-ltsp.png has changed
    52.1 Binary file docs/img/grub4dos/win98_bat.png has changed
    53.1 Binary file docs/img/grub4dos/xp_02b01_installazione-personalizzata.png has changed
    54.1 Binary file docs/img/grub4dos/xp_02b02_installazione_personalizzata.png has changed
    55.1 Binary file docs/img/grub4dos/xp_03_menu-lst.png has changed
    56.1 Binary file docs/img/grub4dos/xp_bat.png has changed
    57.1 Binary file docs/img/join/w98_1.png has changed
    58.1 Binary file docs/img/join/w98_2.png has changed
    59.1 Binary file docs/img/join/w98_3.png has changed
    60.1 Binary file docs/img/join/w98_4.png has changed
    61.1 Binary file docs/img/join/w98_5.png has changed
    62.1 Binary file docs/img/join/w98_6.png has changed
    63.1 Binary file docs/img/join/xp1.png has changed
    64.1 Binary file docs/img/join/xp2.png has changed
    65.1 Binary file docs/img/join/xp3.png has changed
    66.1 Binary file docs/img/join/xp4.png has changed
    67.1 Binary file docs/img/join/xp5.png has changed
    68.1 Binary file docs/img/join/xp6.png has changed
    69.1 Binary file docs/img/join/xp7.png has changed
    70.1 Binary file docs/img/join/xp8.png has changed
    71.1 Binary file docs/img/rete-fwisi.png has changed
    72.1 Binary file docs/img/rete-srvisi.png has changed
    73.1 Binary file docs/img/reteisi.png has changed
    74.1 Binary file docs/img/ssh-key/big/0_accessoDominio.png has changed
    75.1 Binary file docs/img/ssh-key/big/10_putty-connessione2.png has changed
    76.1 Binary file docs/img/ssh-key/big/11_putty-connessione3.png has changed
    77.1 Binary file docs/img/ssh-key/big/12_putty-connessione4.png has changed
    78.1 Binary file docs/img/ssh-key/big/13_putty-connessione5.png has changed
    79.1 Binary file docs/img/ssh-key/big/1_estensioni1.png has changed
    80.1 Binary file docs/img/ssh-key/big/2_estensioni2.png has changed
    81.1 Binary file docs/img/ssh-key/big/3_import1.png has changed
    82.1 Binary file docs/img/ssh-key/big/4_import2.png has changed
    83.1 Binary file docs/img/ssh-key/big/5_import3.png has changed
    84.1 Binary file docs/img/ssh-key/big/6_import4.png has changed
    85.1 Binary file docs/img/ssh-key/big/7_putty-addkey1.png has changed
    86.1 Binary file docs/img/ssh-key/big/8_putty-addkey2.png has changed
    87.1 Binary file docs/img/ssh-key/big/9_putty-connessione1.png has changed
    88.1 Binary file docs/img/ssh-key/small/0_accessoDominio.jpg has changed
    89.1 Binary file docs/img/ssh-key/small/10_putty-connessione2.jpg has changed
    90.1 Binary file docs/img/ssh-key/small/11_putty-connessione3.jpg has changed
    91.1 Binary file docs/img/ssh-key/small/12_putty-connessione4.jpg has changed
    92.1 Binary file docs/img/ssh-key/small/13_putty-connessione5.jpg has changed
    93.1 Binary file docs/img/ssh-key/small/1_estensioni1.jpg has changed
    94.1 Binary file docs/img/ssh-key/small/2_estensioni2.jpg has changed
    95.1 Binary file docs/img/ssh-key/small/3_import1.jpg has changed
    96.1 Binary file docs/img/ssh-key/small/4_import2.jpg has changed
    97.1 Binary file docs/img/ssh-key/small/5_import3.jpg has changed
    98.1 Binary file docs/img/ssh-key/small/6_import4.jpg has changed
    99.1 Binary file docs/img/ssh-key/small/7_putty-addkey1.jpg has changed
   100.1 Binary file docs/img/ssh-key/small/8_putty-addkey2.jpg has changed
   101.1 Binary file docs/img/ssh-key/small/9_putty-connessione1.jpg has changed
   102.1 Binary file docs/img/web/web-classi.png has changed
   103.1 Binary file docs/img/web/web-dns.png has changed
   104.1 Binary file docs/img/web/web-navigazione.png has changed
   105.1 Binary file docs/img/web/web-nomi.png has changed
   106.1 Binary file docs/img/web/web-sissi.png has changed
   107.1 Binary file docs/img/web/web-start.png has changed
   108.1 Binary file docs/img/web/web-users-file.png has changed
   109.1 Binary file docs/img/web/web-utenti.png has changed
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/docs/install/client/client_linux.rst	Mon Apr 26 11:16:23 2010 +0200
   110.3 @@ -0,0 +1,393 @@
   110.4 +==============
   110.5 +Client Linux
   110.6 +==============
   110.7 +
   110.8 +
   110.9 +Per i sistemi Linux non esiste un'operazione analoga al join dei sistemi
  110.10 +Microsoft ma è comunque possibile avere:
  110.11 +
  110.12 + #. Autenticazione unica su server centrale: questo significa che tutti gli
  110.13 +    utenti sono riconosciuti da ogni client e la password con cui si
  110.14 +    autenticano è la medesima (che potrebbe anche essere differente da
  110.15 +    quella usata epr il logon su windows)
  110.16 +
  110.17 + #. La home è servita dal fileserver: se il server è anche PDC la home è la
  110.18 +    medesima sia sotto windows che sotto Linux. Il server esporta la HOME
  110.19 +    degli utenti via :ref:`nfs <config_nfs>`. Fare riferimento a quel capitolo per
  110.20 +    capire come configurare anche il client.
  110.21 +
  110.22 +Limitiamo la nostra trattazione ai client linux Ubuntu ed ai sistemi Debian.
  110.23 +
  110.24 +
  110.25 +Debian
  110.26 +======
  110.27 +
  110.28 +Esiste il pacchetto isi-ldap3-client che si occupa di permettere
  110.29 +l'autenticazione su server centrale. Manca la documentazione...
  110.30 +
  110.31 +Ubuntu
  110.32 +======
  110.33 +
  110.34 +
  110.35 +.. index:: 
  110.36 +   single: auth_config
  110.37 +   single: client; linux
  110.38 +
  110.39 +.. _auth_client:
  110.40 +
  110.41 +Configurazione di un client Ubuntu per l'accesso ad un dominio isi
  110.42 +------------------------------------------------------------------
  110.43 +
  110.44 +Dalla release di Ubuntu 7.10, è stato introdotto auth_client_config_ che 
  110.45 +consente di gestire agevolmente più configurazioni(profili) e di passare da 
  110.46 +uno all'altro in modo molto semplce. I procedimenti seguenti utilizzeranno 
  110.47 +tale feature.
  110.48 +
  110.49 +.. _auth_client_config: https://wiki.ubuntu.com/AuthClientConfig
  110.50 +
  110.51 +Installare i pacchetti necessari::
  110.52 +
  110.53 + root@ubuntu-desktop:~# apt-get install ldap-auth-config ldap-utils
  110.54 +
  110.55 +.. Note::
  110.56 +
  110.57 +   L'installazione del pacchetto ``ldap-utils`` non è strettamente necessaria.
  110.58 +   Torna però utile per testare le interrogazioni ldap.
  110.59 +
  110.60 +Una volta installati i pacchetti,verrà lanciato uno script di configurazione.
  110.61 +Si risponda alle domande come indicato di seguito, sostituendo i dati di 
  110.62 +esempio con i propri:
  110.63 +
  110.64 +.. container:: debconf
  110.65 +
  110.66 + ============================================  =============================
  110.67 +  Should debconf manage LDAP configuration?:     sì
  110.68 +  
  110.69 +  LDAP server Uniform Resource Identifier:       ldap://192.168.1.150
  110.70 +  
  110.71 +  Distinguished name:                               dc=isi,dc=lan
  110.72 +  
  110.73 +  LDAP account for root:                         cn=admin,dc=isi,dc=lan
  110.74 +  
  110.75 +  Password di root:                               passwordDiRoot
  110.76 +  
  110.77 + ============================================  =============================
  110.78 +
  110.79 +(Per ciò che non viene espressamente citato sopra, si accetti il valore 
  110.80 +di default proposto)
  110.81 +
  110.82 +.. Note ::
  110.83 +
  110.84 +   ``Per Ubuntu versione 8.10``
  110.85 +
  110.86 +   - ``/etc/ldap/ldap.conf`` non viene configurato automaticamente, sarà quindi necessario
  110.87 +     effettuarne la configurazione manualmente.
  110.88 +
  110.89 +   ``Per Ubuntu versione < 8.10``
  110.90 +
  110.91 +   - ``/etc/ldap/ldap.conf`` non viene configurato automaticamente, sarà quindi necessario 
  110.92 +     effettuarne la configurazione manualmente.
  110.93 +   - ``/etc/ldap.conf`` viene configurato in modo errato, sarà quindi necessario verificarne
  110.94 +     la configurazione.
  110.95 +
  110.96 +   Per le modifiche si faccia riferimento ai parametri indicati di seguito.
  110.97 +
  110.98 +``/etc/ldap.conf``
  110.99 +::
 110.100 +
 110.101 + host 192.168.1.150
 110.102 + base dc=isi,dc=lan
 110.103 + rootbinddn cn=admin,dc=isi,dc=lan
 110.104 + bind_policy soft
 110.105 +
 110.106 +controllare anche che la direttiva ldap1://192.168.150 ``sia commentata``,
 110.107 +in presenza di più modi per identificare il server ldap, l'autenticazione
 110.108 +non funzionerà.
 110.109 +
 110.110 +``/etc/ldap/ldap.conf``
 110.111 +::
 110.112 +
 110.113 + BASE    dc=isi,dc=lan     
 110.114 + URI     ldap://192.168.1.150
 110.115 +
 110.116 +
 110.117 +Creazione e aggiunta di un profilo ``auth-client-config``
 110.118 +---------------------------------------------------------
 110.119 +
 110.120 +Creare, con un editor di testo, un file chiamato ``isi``, popolandolo con le 
 110.121 +righe seguenti, e salvarlo in ``/etc/auth-client-config/profile.d/``
 110.122 +
 110.123 +Se il sistema in uso è una Ubuntu di versione inferiore alla 8.10::
 110.124 +
 110.125 + [isi-ldap]
 110.126 + nss_passwd=passwd: compat ldap
 110.127 + nss_group=group: compat ldap
 110.128 + nss_shadow=shadow: compat ldap
 110.129 + pam_auth=auth       sufficient   pam_ldap.so   
 110.130 +         auth       required     pam_unix.so nullok_secure use_first_pass
 110.131 + pam_account=account    sufficient   pam_ldap.so 
 110.132 +         account    required     pam_unix.so
 110.133 + pam_password=password   sufficient   pam_ldap.so
 110.134 +         password   required     pam_unix.so nullok obscure min=4 max=8 md5
 110.135 + pam_session=session    required     pam_unix.so
 110.136 +         session    required     pam_mkhomedir.so skel=/etc/skel/
 110.137 +         session    optional     pam_ldap.so
 110.138 +         session    optional     pam_foreground.so
 110.139 +
 110.140 + [isi-local]
 110.141 + nss_group=group:          compat 
 110.142 + nss_passwd=passwd:         compat
 110.143 + nss_shadow=shadow:         compat
 110.144 + pam_account=account     required        pam_unix.so
 110.145 + pam_auth=auth   required        pam_unix.so nullok_secure
 110.146 + pam_password=password   required   pam_unix.so nullok obscure md5
 110.147 + pam_session=session     required        pam_unix.so
 110.148 +         session optional        pam_foreground.so
 110.149 +
 110.150 +Se il sistema in uso è Ubuntu versione 8.10::
 110.151 +
 110.152 +    [isi-ldap]
 110.153 +    nss_passwd=passwd: compat ldap
 110.154 +    nss_group=group: compat ldap
 110.155 +    nss_shadow=shadow: compat ldap  
 110.156 +    nss_netgroup=netgroup: nis
 110.157 +    pam_auth=auth       sufficient   pam_ldap.so
 110.158 +            auth       required     pam_unix.so nullok_secure use_first_pass
 110.159 +    pam_account=account    sufficient   pam_ldap.so
 110.160 +            account    required     pam_unix.so
 110.161 +    pam_password=password   sufficient   pam_ldap.so
 110.162 +            password   required     pam_unix.so nullok obscure min=4 max=8 md5
 110.163 +    pam_session=session    required     pam_unix.so
 110.164 +            session    required     pam_mkhomedir.so skel=/etc/skel/
 110.165 +            session    optional     pam_ldap.so
 110.166 +            session    optional     pam_foreground.so
 110.167 +
 110.168 +    [isi-local]
 110.169 +    nss_group=group:          compat
 110.170 +    nss_netgroup=netgroup:       nis
 110.171 +    nss_passwd=passwd:         compat
 110.172 +    nss_shadow=shadow:         compat
 110.173 +    pam_account=account     [success=2 new_authtok_reqd=done default=ignore]        pam_unix.so
 110.174 +            account [success=1 default=ignore]      pam_ldap.so
 110.175 +            account requisite                       pam_deny.so
 110.176 +            account required                        pam_permit.so
 110.177 +    pam_auth=auth   [success=2 default=ignore]      pam_unix.so nullok_secure 
 110.178 +            auth    [success=1 default=ignore]      pam_ldap.so use_first_pass
 110.179 +            auth    requisite                       pam_deny.so
 110.180 +            auth    required                        pam_permit.so
 110.181 +    pam_password=password   [success=2 default=ignore]      pam_unix.so obscure sha512
 110.182 +            password        [success=1 user_unknown=ignore default=die]     pam_ldap.so use_authtok try
 110.183 +            password        requisite                       pam_deny.so
 110.184 +            password        required                        pam_permit.so
 110.185 +    pam_session=session     [default=1]                     pam_permit.so
 110.186 +            session requisite                       pam_deny.so
 110.187 +            session required                        pam_permit.so
 110.188 +            session required        pam_unix.so 
 110.189 +            session optional                        pam_ldap.so
 110.190 +            session optional                        pam_ck_connector.so nox11
 110.191 +
 110.192 +
 110.193 +Per verificare che il profilo venga rilevato correttamente si potrà
 110.194 +utilizzare il comando ``auth-client-config -l``::
 110.195 +
 110.196 + root@ubuntu-desktop:~# auth-client-config -l 
 110.197 + Available profiles are:
 110.198 +   isi-ldap
 110.199 +   isi-local
 110.200 +   kerberos_example
 110.201 +   lac_ldap
 110.202 +   ldap_example
 110.203 +
 110.204 +Come si può notare, i profili ``isi-ldap`` e ``isi-local`` aggiunti in
 110.205 +precedenza vengono trovati ed elencati. Non resta che attivare il profilo ``isi-ldap``::
 110.206 +
 110.207 + root@ubuntu-desktop:~# auth-client-config -a -p isi-ldap
 110.208 +
 110.209 +Ed effettuare un tentativo di interrogazione del database ldap::
 110.210 +
 110.211 + root@ubuntu-desktop:~# getent passwd
 110.212 + 
 110.213 +L'output del comando dovrebbe mostrare tutto il contenuto del file locale 
 110.214 +``/etc/passwd`` seguito da quello aggiuntivo fornito dal database ldap.
 110.215 +
 110.216 +.. note::
 110.217 +
 110.218 +  E' indispensabile che in ``/etc/hosts`` venga inserito un riferimento del
 110.219 +  tipo <ipserver> <nomeserver> (es. 192.168.1.150 srv-isi).  L'assenza di
 110.220 +  tale direttiva, comporterà un ritardo considerevole ad ogni interrogazione
 110.221 +  dell'albero ldap.
 110.222 +
 110.223 +Consentire ad un utente ldap l'utilizzo di stick usb e dell'audio del client ubuntu.
 110.224 +------------------------------------------------------------------------------------
 110.225 +
 110.226 +In Ubuntu un utente ldap riesce a far funzionare uno stick usb solo in
 110.227 +lettura e non ha accesso all'audio della macchina. Questo dipende dal fatto
 110.228 +che per utilizzare l'audio e vedere montato il proprio dispositivo usb in
 110.229 +lettura/scrittura l'utente deve essere membro dei gruppi locali *plugdev
 110.230 +(46)* e *audio (29)*, il che è automatico per gli utenti locali ma non
 110.231 +succede per quelli remoti.  Occorre quindi implementare un meccanismo che
 110.232 +assegni automaticamente l'appartenenza (membership) a questi gruppi agli
 110.233 +utenti autenticati dal server ldap.  Fortunatamente la cosa è piuttosto
 110.234 +semplice, anche se comporta un riprocessamento di tutti gli utenti
 110.235 +remoti. Vediamo quanto è necessario.
 110.236 +
 110.237 +LATO SERVER
 110.238 +~~~~~~~~~~~
 110.239 +
 110.240 +  1. creare i gruppi ldap *plugdev* e *audio* (attenzione, quei gruppi
 110.241 +  esistono già sul server come gruppi locali, saranno quindi duplicati come
 110.242 +  gruppi ldap
 110.243 +
 110.244 +  2. assegnare gli utenti a cui si vuole consentiro l'uso dei dispositivi
 110.245 +  usb e audio del client (potenzialmente tutti) ai gruppi plugdev e audio
 110.246 +  (eventualmente ad altri)
 110.247 +
 110.248 +La prima operazione si fa con i comandi::
 110.249 +
 110.250 +  smbldap-groupadd -o -g 46 plugdev
 110.251 +  smbldap-groupadd -o -g 29 audio
 110.252 +
 110.253 +``l'opzione -o`` è necessaria per la duplicazione dei gruppi. L'assegnazione
 110.254 +della membership può eseguirsi con i comandi::
 110.255 +
 110.256 +    isi-addgroup user_id plugdev
 110.257 +    isi-addgroup user_id audio
 110.258 +
 110.259 +LATO CLIENT
 110.260 +~~~~~~~~~~~
 110.261 +
 110.262 +Per assegnare on the fly la membership ai gruppi locali agli utenti ldap
 110.263 +occorre ricorrere a ``pam_group.so``, lo si fa aggiungedo al file
 110.264 +``/etc/pam.d/common-auth`` la linea::
 110.265 +
 110.266 +    auth     optional        pam_group.so
 110.267 +
 110.268 +A questo punto non resta che configurare ``pam_group``. Lo si fa aggiungendo
 110.269 +in testa al suo file di configurazione ``/etc/security/group.conf`` le righe
 110.270 +seguenti::
 110.271 +
 110.272 +    gdm; *; *; Al0000-2400; audio, video, cdrom, floppy, plugdev
 110.273 +    kdm; *; *; Al0000-2400; audio, video, cdrom, floppy, plugdev
 110.274 +    login; *; *; Al0000-2400; audio, video, cdrom, floppy, plugdev 
 110.275 +
 110.276 +(le prove fatte rivelano che i gruppi video, cdrom e floppy, possono essere
 110.277 +omessi, in ogni caso male non fanno)
 110.278 + 
 110.279 +Fare il reboot del client e godersi l'effetto
 110.280 +
 110.281 +
 110.282 +  
 110.283 +LTSP
 110.284 +====
 110.285 +
 110.286 +
 110.287 +una menzione particolare per i client LTSP. Per questi client non c'è molto
 110.288 +da dire, in quanto gli utenti sono definiti sul server LTSP per il quale
 110.289 +potete seguire esattamente le istruzioni scritte sopra.
 110.290 +
 110.291 +L'unica informazione aggiuntiva che voglio dare è relativa alla
 110.292 +configurazione di GRUB
 110.293 +
 110.294 +.. index:: ltsp; grub
 110.295 +
 110.296 +Un progetto alternativo a questo è il progetto drbl_ che include anche
 110.297 +clonezilla (progetto simile a ghost)
 110.298 + 
 110.299 +.. _drbl: http://drbl.sourceforge.net/
 110.300 +
 110.301 +GRUB
 110.302 +----
 110.303 +
 110.304 +capita spesso che serva configurare una macchina per il dual boot Linux come
 110.305 +client LTSP e windows. In questo caso è opportuno installare GRUB
 110.306 +direttamente su hard disk e quindi in windows. Non c'è alcun problema, GRUB
 110.307 +non è razzista, gli basta risiedere in un filesystem che riconosca al boot,
 110.308 +e fat32 va bene (al momento non so dire se va bene anche ntfs).
 110.309 +
 110.310 +il driver
 110.311 +~~~~~~~~~
 110.312 +
 110.313 +Occorre anzitutto procurarsi il driver della scheda di rete della vostra
 110.314 +macchina, potete scaricarla da questo sito:
 110.315 +http://www.rom-o-matic.net/5.4.1/ (la versione non è vincolante).
 110.316 +Per il download vi chiedono il formato del file, scegliete .zlilo.
 110.317 +
 110.318 +/boot in C:
 110.319 +~~~~~~~~~~~
 110.320 +
 110.321 +Installate ora la cartella ``boot`` con all'intero la cartella ``grub`` come
 110.322 +fareste per una normale distro linux (copiate ad esempio ``/boot/grub`` del
 110.323 +cd). Ipotizziamo ad esempio che la partizione windows (unico sistema sulla
 110.324 +macchina) sia la numero 1::
 110.325 +
 110.326 +  mount /dev/sda1 /mnt
 110.327 +  mkdir -p /boot
 110.328 +  cp -av /boot/grub /mnt/boot
 110.329 +
 110.330 +a questo punto dovete:
 110.331 +
 110.332 + 1. aggiungere il driver
 110.333 + 2. cofigurare menu.lst ad esempio come segue::
 110.334 +
 110.335 +      title LTSP (scheda 
 110.336 +      root (hd0,0)
 110.337 +      kernel /boot/eb-5.0.8-3c509.lzlilo
 110.338 +
 110.339 +      title         Windows 95/98/NT/2000
 110.340 +      root          (hd0,0)
 110.341 +      makeactive
 110.342 +      chainloader   +1
 110.343 +            
 110.344 +
 110.345 +installazione grub
 110.346 +~~~~~~~~~~~~~~~~~~
 110.347 +
 110.348 +Ultimo passo è quello di installare effettivamente grub sul MBR (Master boot
 110.349 +record) del disco. Per questo basterà partire con il cd reteisi, fermersi
 110.350 +subito (alla splash inisiale che attualmente ha i pinguini).
 110.351 +
 110.352 +Una voce dice "inizializzazione HD per RAID", che di fatto inizializza sia
 110.353 +il primo che il secondo disco. Potete usarlo anche se avete un solo
 110.354 +disco. Probabilmente si lamenta quando si accorge che manda il secondo
 110.355 +disco, ma ormai il primo lo avr`a inizializzato correttamente.
 110.356 +
 110.357 +Se invece volete fare le cose senza scorciatoie, dicitate ``c``  che vi
 110.358 +mette nella console di grub e digitate::
 110.359 +
 110.360 +  root            (hd0,0)
 110.361 +  setup           (hd0)
 110.362 +
 110.363 +Se per case a partizione non fose la prima ma la seconda, usate 
 110.364 +``root (hd0,1)``
 110.365 +
 110.366 +
 110.367 +
 110.368 +dividere il carico fra più server
 110.369 +-----------------------------------
 110.370 +
 110.371 +Qualora ci siano molti client ltsp e non sia possibile suddividere la rete,
 110.372 +è possibile suddividere il carico fra più server lasciando al server dhcp
 110.373 +il compito di assegnare non solo l'indirizzo di rete ma anche il server da
 110.374 +cui prendere il root filesystem da caricare via nfs.
 110.375 +
 110.376 +La direttiva da usare è ``next-server`` ed indica quale sia il server
 110.377 +successivo dopo quello che ha fornito il kernel. Un esemio per due macchine
 110.378 +che usino rispettivamente il server ltsp 192.168.1.1 e 192.168.1.2 potrebbe
 110.379 +essere così::
 110.380 +
 110.381 +  host ltsp01 {
 110.382 +      hardware ethernet    00:a0:24:52:5a:bc;
 110.383 +      fixed-address        192.168.1.50;
 110.384 +      next-server  192.168.1.1;
 110.385 +  }
 110.386 +  host ltsp02 {
 110.387 +      hardware ethernet    00:a0:24:52:5a:bc;
 110.388 +      fixed-address        192.168.1.51;
 110.389 +      next-server  192.168.1.2;
 110.390 +  }
 110.391 +  
 110.392 +APT
 110.393 +===
 110.394 +
 110.395 +Ricordate che per potere usare apt con apt dovrete :ref:`apt_squid`
 110.396 +
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/docs/install/client/client_microsoft.rst	Mon Apr 26 11:16:23 2010 +0200
   111.3 @@ -0,0 +1,74 @@
   111.4 +.. _join:
   111.5 +
   111.6 +Inserire client Microsoft nel dominio: Il Join
   111.7 +==============================================
   111.8 +
   111.9 +.. index:: 
  111.10 +   single: client; windows
  111.11 +
  111.12 +Esiste una esperienza di laboratorio sul :ref:`lab_join`
  111.13 +
  111.14 +XP Professional
  111.15 +---------------
  111.16 +
  111.17 +.. sidebar:: ``Eliminare la sincronizzazione``
  111.18 +
  111.19 +   Ricordati anche di eliminare la sincronizzazione dei file altrimenti
  111.20 +   ad ogni disconnessione si attendera' un tempo eterno!!!
  111.21 +   
  111.22 +
  111.23 +.. figure:: ../../img/join/xp1.png
  111.24 +   :align: center
  111.25 +
  111.26 +.. figure:: ../../img/join/xp2.png
  111.27 +   :align: center
  111.28 +
  111.29 +.. figure:: ../../img/join/xp3.png
  111.30 +   :align: center
  111.31 +
  111.32 +.. figure:: ../../img/join/xp4.png
  111.33 +   :align: center
  111.34 +
  111.35 +.. figure:: ../../img/join/xp5.png
  111.36 +   :align: center
  111.37 +
  111.38 +.. figure:: ../../img/join/xp6.png
  111.39 +   :align: center
  111.40 +
  111.41 +.. figure:: ../../img/join/xp7.png
  111.42 +   :align: center
  111.43 +
  111.44 +.. figure:: ../../img/join/xp8.png
  111.45 +   :align: center
  111.46 +
  111.47 +Windows 2000
  111.48 +------------
  111.49 +
  111.50 +La procedura è analoga a quella per i Client XP
  111.51 +
  111.52 +Windows98 SE
  111.53 +------------
  111.54 +
  111.55 +.. figure:: ../../img/join/w98_1.png
  111.56 +   :align: center
  111.57 +
  111.58 +.. figure:: ../../img/join/w98_2.png
  111.59 +   :align: center
  111.60 +
  111.61 +.. figure:: ../../img/join/w98_3.png
  111.62 +   :align: center
  111.63 +
  111.64 +.. figure:: ../../img/join/w98_4.png
  111.65 +   :align: center
  111.66 +
  111.67 +.. figure:: ../../img/join/w98_5.png
  111.68 +   :align: center
  111.69 +
  111.70 +.. figure:: ../../img/join/w98_6.png
  111.71 +   :align: center
  111.72 +
  111.73 +Sistemi non supportati
  111.74 +----------------------
  111.75 +
  111.76 ++ Windows XP Home edition
  111.77 ++ Windows 95
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/docs/install/client/grub4dos.rst	Mon Apr 26 11:16:23 2010 +0200
   112.3 @@ -0,0 +1,122 @@
   112.4 +.. _grub4dos:
   112.5 +
   112.6 +
   112.7 +=============================
   112.8 +Installazione GRUB sui client
   112.9 +=============================
  112.10 +
  112.11 +In un sistema di dual boot occorre potere partire da Linux o da Windows. Il
  112.12 +menu di scelta al boot è gestito direttamente dagli installer Linux se si
  112.13 +installa Linux come secondo sistema operativo ma in una situazione di
  112.14 +thin/fat client occorre installarlo a mano.
  112.15 +
  112.16 +Il progetto ReteISI propone una semplice soluzione basata sul software
  112.17 +``grub4dos``.  L'operazione va svolta sui singoli client ed è differente a
  112.18 +seconda che si usi Windows 98 o un sistema più recente.
  112.19 +
  112.20 +L'obiettivo di questa procedura è quella di ottenere sui client una
  112.21 +configurazione come questa:
  112.22 +
  112.23 +.. image:: ../../img/grub4dos/win98_03_menu-ltsp.png
  112.24 +   :align: right
  112.25 +   :scale: 40
  112.26 +
  112.27 +L'installazione del pacchetto ReteISI mette nella share :file:`software` una
  112.28 +cartella chiamata appunto ``grub4dos`` che contiene tutti i file necessari,
  112.29 +per cui è sufficiente eseguire il file di installazione (doppio click) per
  112.30 +ogni client per installare grub.
  112.31 +
  112.32 +La fase di boot
  112.33 +===============
  112.34 +
  112.35 +Normalmente il Master Boot Record (MBR) di un sistema Windows passa il
  112.36 +comando alla partizione dove un loader Windows carica il sistema.
  112.37 +
  112.38 +Con ``grub4dos`` invece il MBR passa la palla al comando ``grldr`` che legge
  112.39 +il file di configurazione :file:`menul.lst` che deve essere preparato per
  112.40 +proporre le varie voci di menu. A noi interessa di avere la scelta:
  112.41 +
  112.42 +1. LTSP
  112.43 +2. Windows
  112.44 +
  112.45 +Ovviamente LTSP *non* è un sistema operativo presente ma è un eseguibile che
  112.46 +a sua volta emula un PXE, ovvero una scheda di rete con boot da rete. Noi
  112.47 +abbiamo messo come default gPXE_ ed in particolare l'eseguibile con tutti i
  112.48 +driver di rete diposnibili nel sito rom-o-matic_ in modo da coprire il maggior numero possibile di schede.
  112.49 +
  112.50 +
  112.51 +.. _gPXE: http://etherboot.org/wiki/index.php
  112.52 +.. _rom-o-matic: http://rom-o-matic.net/gpxe/gpxe-1.0.0/contrib/rom-o-matic/
  112.53 +
  112.54 +Personalizziamo il menu di avvio
  112.55 +---------------------------------
  112.56 +
  112.57 +Nelle cartelle xp/c, win98/c, troverete il file :file:`menu.lst`. Questo
  112.58 +file, che verrà copiato in ``c:`` dalla script che lancerete, contiene la
  112.59 +configurazione del boot loader::
  112.60 +
  112.61 +  # imposta i colori
  112.62 +  color blue/white white/green white/blue white/blue 
  112.63 +
  112.64 +  # imposta il tempo di attesa prima di scegliere la prima voce di menù
  112.65 +  timeout 10
  112.66 +  
  112.67 +  title gPXE (LTSP)
  112.68 +  find --set-root /boot/grub/gpxe.iso
  112.69 +  map /boot/grub/gpxe.iso (0xff) || map --mem /boot/grub/gpxe.iso (0xff)
  112.70 +  map --hook
  112.71 +  chainloader (0xff)
  112.72 +  
  112.73 +  title Windows XP/2K/NT
  112.74 +  find --set-root --ignore-floppies /ntldr
  112.75 +  chainloader /ntldr
  112.76 +
  112.77 +  title halt
  112.78 +  halt
  112.79 +
  112.80 +
  112.81 +Installare grub e gPXE da un sistema microsoft
  112.82 +=================================================
  112.83 +
  112.84 +.. image:: ../../img/grub4dos/common_01_share-software.png
  112.85 +   :align: right
  112.86 +
  112.87 +
  112.88 +Prima di procedere con l'installazione di grub, assicuriamoci che, in
  112.89 +``Risorse del computer``, la share ``software`` sia montata; in caso
  112.90 +contrario le script potrebbero non funzionare correttamente.
  112.91 +
  112.92 +Grub verrà installato diversamente a seconda del sistema operativo
  112.93 +utilizzato, si segua dunque il percorso adatto alle proprie esigenze. I
  112.94 +passaggi sono molto semplici si tratta di doppioclickare su di una script
  112.95 +batch.
  112.96 +
  112.97 +
  112.98 +Lanciamo la script di installazione in W98 ed w2k, XP rispettivamente
  112.99 +
 112.100 +.. image:: ../../img/grub4dos/win98_bat.png
 112.101 +   :align: left
 112.102 +
 112.103 +
 112.104 +.. image:: ../../img/grub4dos/xp_bat.png
 112.105 +   :align: center
 112.106 +
 112.107 +
 112.108 +Installazione di grub personalizzata
 112.109 +-------------------------------------
 112.110 +
 112.111 +Chi dovesse avere esigente particolari come, ad esempio, installare il MBR
 112.112 +su di un disco che non è il primo collegato (scelta di default), potrà
 112.113 +affinare manualmente la propria installazione di grub con la seconda script
 112.114 +presente: :file:``
 112.115 +
 112.116 +Dopo aver copiato i file necessari in ``c:\`` la script lancerà ``Grub4Dos
 112.117 +Installer``, un'applicazione che permetterà in modo abbastanza semplice di
 112.118 +installare grub nel disco desiderato. Fate riferimento ai numeri in figura
 112.119 +per non saltare degli step importanti.
 112.120 +
 112.121 +.. figure:: ../../img/grub4dos/xp_02b02_installazione_personalizzata.png
 112.122 +   :scale: 50
 112.123 +   :align: center
 112.124 +
 112.125 +
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/docs/install/contents.rst	Mon Apr 26 11:16:23 2010 +0200
   113.3 @@ -0,0 +1,63 @@
   113.4 +================================
   113.5 + Installazione e configurazione
   113.6 +================================
   113.7 +
   113.8 +Installazione
   113.9 +=============
  113.10 +Scelta dei setup e della topologia della rete.
  113.11 +Installazione del sistema a partire da disco live. 
  113.12 +
  113.13 +.. toctree::
  113.14 +   :maxdepth: 2
  113.15 +
  113.16 +   intro
  113.17 +   install_base
  113.18 +
  113.19 +Configurazioni servizi server
  113.20 +=============================
  113.21 +
  113.22 +Configurazione dei servizi essenziali che devono necessariamente risiedere
  113.23 +sul server
  113.24 +
  113.25 +.. toctree::
  113.26 +   :maxdepth: 2
  113.27 +
  113.28 +   eth_dns
  113.29 +   servizi/pdc
  113.30 +   reteisi
  113.31 +   sshd_key
  113.32 +   servizi/firewall
  113.33 +   servizi/nfs
  113.34 +   servizi/ftp
  113.35 +   servizi/sarg-report
  113.36 +   servizi/apache_userdir
  113.37 +   servizi/apache_limit_pub
  113.38 +
  113.39 +Configurazione servizi firewall
  113.40 +===============================
  113.41 +
  113.42 +Configurazione dei servizi che possono essere installati sul server o su un
  113.43 +firewall a scelta dell'amministratore a seconda della topologia della rete
  113.44 +prescelta. 
  113.45 +
  113.46 +.. toctree::
  113.47 +   :maxdepth: 2
  113.48 +
  113.49 +   servizi/bind
  113.50 +   servizi/bind_server
  113.51 +   servizi/dhcpd
  113.52 +   servizi/squid_dans
  113.53 +
  113.54 +
  113.55 +
  113.56 +Configurazione Client
  113.57 +=====================
  113.58 +
  113.59 +Configurazione delle macchine client
  113.60 +
  113.61 +.. toctree::
  113.62 +   :maxdepth: 2
  113.63 +
  113.64 +   client/client_linux
  113.65 +   client/client_microsoft
  113.66 +   client/grub4dos
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/docs/install/eth_dns.rst	Mon Apr 26 11:16:23 2010 +0200
   114.3 @@ -0,0 +1,126 @@
   114.4 +.. _config_eth_dns:
   114.5 +
   114.6 +Rete e dns (come client)
   114.7 +========================
   114.8 +
   114.9 +Esiste una esperienza di laboratorio sui concetti base del
  114.10 +:ref:`lab_routing` ed una sul :ref:`lab_tinydns`
  114.11 +
  114.12 +Configurazione /etc/hosts
  114.13 +-------------------------
  114.14 +
  114.15 +Sostituire il proprio hostname e localdomain.
  114.16 +
  114.17 +A titolo di esempio è stato sostituito a::
  114.18 +
  114.19 +    127.0.0.1 argo localhost localhost.lan
  114.20 +
  114.21 +La seguente riga
  114.22 +::
  114.23 +  
  114.24 +    127.0.0.1 srv-scuolax localhost srv-scuolax.lan
  114.25 +
  114.26 +
  114.27 +interfacce di rete
  114.28 +------------------
  114.29 +
  114.30 +E' indispensabile che ogni interfaccia di rete che si intende utilizzare sia
  114.31 +configurata con il proprio indirizzo IP.
  114.32 +
  114.33 +Per visualizzare l'elenco completo delle interfacce disponibili si usi il
  114.34 +comando *ifconfig -a* ::
  114.35 +
  114.36 +    root@argo:~$ ifconfig -a
  114.37 +
  114.38 +    eth0      Link encap:Ethernet  HWaddr 03:01:12:35:84:G2
  114.39 +                UP BROADCAST MULTICAST  MTU:1500  Metric:1
  114.40 +                RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  114.41 +                TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  114.42 +                collisions:0 txqueuelen:1000 
  114.43 +                RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
  114.44 +                Interrupt:5 Base address:0x8000 Memory:90000000-90000fff 
  114.45 +
  114.46 +    eth1      Link encap:Ethernet  HWaddr 03:02:24:14:44:A1
  114.47 +                UP BROADCAST MULTICAST  MTU:1500  Metric:1
  114.48 +                RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  114.49 +                TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  114.50 +                collisions:0 txqueuelen:1000 
  114.51 +                RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
  114.52 +                Interrupt:5 Base address:0x8000 Memory:90000000-90000fff 
  114.53 +
  114.54 +    lo        Link encap:Local Loopback  
  114.55 +              inet addr:127.0.0.1  Mask:255.0.0.0
  114.56 +              inet6 addr: ::1/128 Scope:Host
  114.57 +              UP LOOPBACK RUNNING  MTU:16436  Metric:1
  114.58 +              RX packets:382 errors:0 dropped:0 overruns:0 frame:0
  114.59 +              TX packets:382 errors:0 dropped:0 overruns:0 carrier:0
  114.60 +              collisions:0 txqueuelen:0 
  114.61 +              RX bytes:58097 (56.7 KB)  TX bytes:58097 (56.7 KB)
  114.62 +
  114.63 +    
  114.64 +Come si può notare dall'esempio sopra, sul sistema preso in esame sono
  114.65 +presenti due interfacce di rete: *eth0* ed *eth1*.
  114.66 +
  114.67 +Configurare tali interfacce è molto semplice; l'operazione viene effettuata
  114.68 +utilizzando il comando *ifconfig*.
  114.69 +
  114.70 +Si supponga di voler assegnare all'interfaccia di rete eth0 ip 192.168.1.1::
  114.71 +
  114.72 +    argo:~# ifconfig eth0 192.168.1.1 up
  114.73 +
  114.74 +Per verificare che l'interfaccia sia stata configurata correttamente è
  114.75 +possibile eseguire nuovamente il comando *ifconfig -a* od in alternativa il
  114.76 +più selettivo *ifconfig INTERFACCIA* che, diversamente, mostrerà la
  114.77 +configurazione attuale della sola interfaccia specificata, ad esempio eth0.
  114.78 +
  114.79 +Si supponga inoltre di volere impostare un gateway predefinito di ip
  114.80 +192.168.1.254, raggiungibile attraverso l'interfaccia eth0::
  114.81 +
  114.82 +    argo:~# route add -net default gw 192.168.1.254 eth0
  114.83 +
  114.84 +Sarà possibile verificare la bontà di tale configurazione con il comando *route -n*::
  114.85 +
  114.86 +                    Kernel IP routing table
  114.87 +    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
  114.88 +    192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
  114.89 +    169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 eth1
  114.90 +    0.0.0.0         192.168.1.254   0.0.0.0         UG    100    0        0 eth0
  114.91 +
  114.92 +.. commento: 
  114.93 +
  114.94 +  Nota: 
  114.95 +
  114.96 +  169.254.0.0 è un indirizzo  che viene assegnato alle
  114.97 +  interfacce di rete *non* configurate quando
  114.98 +
  114.99 +Tutte le configurazione effettuate, sebbene già operative, hanno carattere
 114.100 +temporaneo. Al riavvio della macchina verranno infatti perse. Per questa
 114.101 +ragione è indispensabile "fissarle" modificando il file di sistema
 114.102 +``/etc/network/interfaces``.  Fortunatamente, un tool argo, rende questo
 114.103 +passaggio del tutto automatico. Basterà infatti lanciare il comando
 114.104 +``save-net`` per "fissare" la configurazione di rete attivata.
 114.105 +
 114.106 +
 114.107 +Dns
 114.108 +---
 114.109 +
 114.110 +Per impostare i DNS, basterà modificare il file */etc/resolv.conf*::
 114.111 +
 114.112 +        nameserver INDIRIZZO_IP_DNS1
 114.113 +        nameserver INDIRIZZO_IP_DNS2
 114.114 +
 114.115 +*Nota*: L'ordine con il quale vengono elencati i server dns da utilizzare ne
 114.116 + stabiliscono la priorità.
 114.117 +
 114.118 +
 114.119 +Qualora si decidesse di utilizzare un servente DNS attivo sulla macchina
 114.120 +stessa, basterà modificare ``/etc/resolv.conf`` come segue::
 114.121 +
 114.122 +        nameserver 127.0.0.1
 114.123 +        nameserver INDIRIZZO_IP_DNS1
 114.124 +        nameserver INDIRIZZO_IP_DNS2
 114.125 +
 114.126 +In questo modo il DNS utilizzato prioritariamente sarà quello locale.
 114.127 +
 114.128 +
 114.129 +
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/docs/install/install_base.rst	Mon Apr 26 11:16:23 2010 +0200
   115.3 @@ -0,0 +1,240 @@
   115.4 +.. _install_base:
   115.5 +
   115.6 +===========================
   115.7 + Installazione base di ISI
   115.8 +===========================
   115.9 +
  115.10 +Installazione in 3 passi
  115.11 +========================
  115.12 +
  115.13 +Installare un sistema ReteIsi dal CD live ad un PDC perfettamente
  115.14 +funzionante è molto semplice se si seguono poche linee sotto elencate che si
  115.15 +riassumono in:
  115.16 +
  115.17 +#. decidere come creare le partizioni (:term:`raid` è suggerito).  La
  115.18 +   installazione non è altro che una copia del cd live che avviene per mezzo
  115.19 +   di un comando che legge un file di configurazione. Se ne può usare uno
  115.20 +   preconfezionato (prelevandolo dalla cartella /etc/clone/examples) ed
  115.21 +   eventualmente modificarlo
  115.22 +
  115.23 +#. lanciare il comando ``clone`` e riavviare 
  115.24 +  
  115.25 +#. fare la prima configurazione con il comando::
  115.26 +
  115.27 +     isi-startup DOMINIO NOME_PDC PWD
  115.28 +
  115.29 +Il sistema a questo punto è pronto per fare il join da una macchina Windows
  115.30 +o per diventare server di autenticazione di una macchina Linux salvo le
  115.31 +ovvie configurazioni di :ref:`firewalling <config_firewall>` 
  115.32 +e :ref:`rete <config_eth_dns>`.
  115.33 +
  115.34 +
  115.35 +Note hardware
  115.36 +-------------
  115.37 +
  115.38 +Quanti hardisk utilizzare
  115.39 ++++++++++++++++++++++++++
  115.40 +
  115.41 +Talvolta, per una politica di risparmio, si preferisce utilizzare un solo
  115.42 +disco. L'attuale costo degli hardisk ed il buon senso scoraggiano tale
  115.43 +pratica in favore di una configurazione raid1(mirroring) che utilizzi due
  115.44 +dischi. Tale configurazione assicura che, in caso di rottura di uno dei due
  115.45 +dischi, il disco gemello garantisca il normale uso del sistema. Si potrà
  115.46 +inoltre collegare in seguito, in sostituzione del disco danneggiato, un
  115.47 +nuovo disco su cui riattivare il "gemellaggio".
  115.48 +
  115.49 +Procurarsi l'ultima versione di ISI
  115.50 ++++++++++++++++++++++++++++++++++++
  115.51 +
  115.52 +Si potrà scaricare la versione più recente dal sito 
  115.53 +http://download.argolinux.org/isi/. Se avete problemi potete seguire qui le
  115.54 +istruzioni per :ref:`masterizzarla <masterizzare_iso>`.
  115.55 +
  115.56 +Iniziare l'installazione
  115.57 +------------------------
  115.58 +
  115.59 +Avviare la macchina con il cd dell'ultima release di ISI nel lettore cdrom (
  115.60 +ci si assicuri preventivamente che il BIOS sia stato correttamente
  115.61 +configurato per avviare prioritariamente da cdrom).
  115.62 +
  115.63 +La procedura di boot terminerà con una richiesta di autenticazione.
  115.64 +::
  115.65 +
  115.66 +    Debian GNU/Linux 4.0 argo tty1
  115.67 +
  115.68 +    argo login: root
  115.69 +
  115.70 +Ci si autentichi inserendo come nome utente *root*; per quanto riguarda la
  115.71 +password, basterà un semplice invio.
  115.72 +
  115.73 +.. commento: img/icone/dialog-information.svg
  115.74 +
  115.75 +
  115.76 +Clone
  115.77 +=======
  115.78 +
  115.79 +*Cos'è Clone*
  115.80 +-------------
  115.81 +
  115.82 +Clone è una script (in python) che si occupa dell'intero processo di
  115.83 +installazione a partire da un file di configurazione. Argoisi viene
  115.84 +distribuita con una serie di esempi di file di configurazione e le modifiche
  115.85 +da apportare a questi esempi sono minime
  115.86 +
  115.87 +
  115.88 +Creazione del file di configurazione
  115.89 +++++++++++++++++++++++++++++++++++++
  115.90 +
  115.91 +Il file di configurazione, contiene fra le altre queste informazioni: 
  115.92 +
  115.93 +* se si vuole un RAID o no
  115.94 +* il numero di partizioni da creare
  115.95 +* gli hardisk da utilizzare 
  115.96 +* il tipo di filesystem scelto per ogni partizione
  115.97 +
  115.98 +Creazione di un file-schema ad hoc
  115.99 +++++++++++++++++++++++++++++++++++
 115.100 +
 115.101 +ISI-live mette a disposizione in "/etc/clone/examples" una serie di modelli
 115.102 +a tal proposito.  A seconda del tipo di installazione che si intende
 115.103 +effettuare potrebbe essere preferibile utilizzare un modello piuttosto che
 115.104 +un altro. Per installare il sistema verrà utilizzato il modello
 115.105 +``/etc/clone/examples/isi``. Si crei dunque copia di tale file in ``/etc/clone/isi`` e
 115.106 +lo si modifichi affinchè risponda alle proprie esigenze.  ::
 115.107 +
 115.108 +  argo:~# cp /etc/clone/examples/isi /etc/clone/
 115.109 +  
 115.110 +  argo:~# jmacs /etc/clone/isi
 115.111 +  
 115.112 +.. sidebar:: **Nota**
 115.113 +
 115.114 +   Chi non avesse molta famigliarità con l'editor di testo :term:`jmacs` potrà
 115.115 +   utilizzare un editor di testo più intuitivo come :term:`nano` ::
 115.116 +
 115.117 +    argo:~# nano /etc/clone/isi
 115.118 +
 115.119 +Aperto il file, si proceda alla modifica inserendo i dati più opportuni.
 115.120 +::
 115.121 +
 115.122 +    GRUB_DEV="hd0,0"
 115.123 +    EMAIL="[email protected]"                 
 115.124 +    RAID='raid1'
 115.125 +    PARTITIONING=1
 115.126 +    FORMATTING=1
 115.127 +    LIVE=1
 115.128 +    DISCS="/dev/sda /dev/sdb"
 115.129 +    DESCR="""
 115.130 +    mnt_p     fmt   fs              dim     part_n  overwrite opt
 115.131 +    /boot     1     ext2            24      1       0
 115.132 +    swap      1     swap            512     5       1
 115.133 +    /free     1     reiserfs        3500    6       1
 115.134 +    /         1     reiserfs        3500    7       1         defaults,acl
 115.135 +    /home     1     reiserfs        fill    8       0         defaults,acl
 115.136 +    """
 115.137 +
 115.138 +Qualche osservazione sul contenuto del file
 115.139 ++++++++++++++++++++++++++++++++++++++++++++
 115.140 +
 115.141 +.. sidebar:: Nota
 115.142 +   
 115.143 +  In caso si stia utilizzando un solo disco, rinunciando quindi alla
 115.144 +  configurazione raid1, si dovrà commentare  inserendo il simbolo # ad
 115.145 +  inizio riga) o rimuovere la riga contentente la direttiva
 115.146 +  ``RAID='raid1'`` ed impostare la direttiva ``DISCS`` con il solo disco
 115.147 +  disponibile. Un RAID hardware viene visto dal sistema come un disco unico
 115.148 +  e rientra quindi nel caso appena citato.
 115.149 +
 115.150 ++ Il parametro *DISCS* fa espresso riferimento al modo in cui gli hardisk
 115.151 +  vengono visti dal sistema. Alcuni sistemi potrebbero riferirsi a tali
 115.152 +  dispositivi utilizzando nome diversi a seconda del controller rilevato. Si
 115.153 +  potrebbe, per esempio, trovare ``/dev/hda`` al posto di ``/dev/sda``.  Per
 115.154 +  fugare ogni dubbio in merito si dovrà utilizzare il seguente comando::
 115.155 +
 115.156 +    argo:~# cat /proc/partitions 
 115.157 +    major minor  #blocks  name
 115.158 +
 115.159 +       7     1       1612 loop1
 115.160 +       7     2       2068 loop2
 115.161 +       7     3       2284 loop3
 115.162 +       7     4          4 loop4
 115.163 +       7     5      12652 loop5
 115.164 +       7     6          4 loop6
 115.165 +       7     7      59840 loop7
 115.166 +       7     8       2144 loop8
 115.167 +       7     9     133264 loop9
 115.168 +       7    10      22984 loop10
 115.169 +       8     0    3145728 sda
 115.170 +       8     0    3145728 sdb
 115.171 +
 115.172 +Come si può notare dall'output, i dischi vengono riconosciuti come come "sd*"
 115.173 +
 115.174 +.. sidebar:: Nota
 115.175 +
 115.176 +  Utilizzando il parametro ``fill``, in sostituzione della dimensione da
 115.177 +  occupare, clone assegnerà alla partizione tutto lo spazio libero
 115.178 +  rimanente. Questo parametro può essere utilizzato solo nell'ultima
 115.179 +  partizione. 
 115.180 +  
 115.181 +
 115.182 +Avvio del processo di Clonazione
 115.183 +--------------------------------
 115.184 +
 115.185 +Ora che il file di configurazione è pronto, non resterà che lanciare *clone* in modo
 115.186 +che carichi la configurazione appena creata::
 115.187 +
 115.188 +    argo:~# clone /etc/clone/isi
 115.189 +    PARTITIONING        : True
 115.190 +    FORMATTING          : True
 115.191 +    RAID                : True
 115.192 +    disc0               : sda sdb
 115.193 +    PART:  /dev/sda1 /boot ext2 defaults 0 2 (format: True)
 115.194 +    PART:  /dev/sda5 swap swap defaults 0 0 (format: True)
 115.195 +    PART:  /dev/sda6 /free reiserfs defaults 0 2 (format: True)
 115.196 +    PART:  /dev/sda7 / reiserfs defaults,acl 0 1 (format: True)
 115.197 +    PART:  /dev/sda8 /home reiserfs defaults,acl 0 2 (format: True)
 115.198 +    Continuo? [Y/n (n default)] 
 115.199 +
 115.200 +Dopo aver confermato l'avvio del processo e atteso il tempo di un caffè, non
 115.201 +resterà che scegliere una password per l'utente amministrativo root e
 115.202 +riavviare la macchina::
 115.203 +
 115.204 +    bin... boot... dev... etc... lib... home... opt... sbin... root... usr... var... 
 115.205 +    chroot /.clone mkinitramfs -o /boot/initrd-2.6.20.11argo1 -r /dev/sda6 2.6.20.11argo1
 115.206 +    Inoltro a  [email protected]
 115.207 +    grub-install --recheck --force-lba --no-floppy --root-directory=/.clone /dev/sda
 115.208 +    chroot /.clone /usr/sbin/update-grub
 115.209 +    Total clone time 3:06 minutes
 115.210 +       fdisk: 0:06
 115.211 +       copy: 2:39
 115.212 +       format: 0:00
 115.213 +    New password: 
 115.214 +    Re-enter new password: 
 115.215 +    LDAP password information changed for root
 115.216 +    passwd: password updated successfully
 115.217 +    umount  /.clone/boot
 115.218 +    umount  /.clone/
 115.219 +
 115.220 +    argo:~# reboot
 115.221 +
 115.222 +A reboot effettuato, si potrà accedere al sistema autenticandosi come utente
 115.223 +*root* ed utilizzando la password scelta in precedenza.
 115.224 +
 115.225 +Configurazione Dominio
 115.226 +----------------------
 115.227 +
 115.228 +Per installare il dominio è sufficiente  lanciare il comando::
 115.229 +
 115.230 +  isi-startup NOME_DOMINIO nome_server password_root
 115.231 +
 115.232 +questa script si occupa di fare tutto il necessario:
 115.233 +
 115.234 +* configura samba impostando il nome di dominio ed il nome server netbios
 115.235 +* imposta la password di amministratore (root) della macchina linux
 115.236 +* imposta la password di amminstratore samba (administrator) del dominio
 115.237 +* imposta la password di accesso al sottosistema di autenticazione (ldap)
 115.238 +* controlla che tutti i SID definiti in LDAP siano dello stesso dominio
 115.239 +* cambia ove necessario il nome dell'host
 115.240 +* corregge il campo dell'ID del'utente nuovo da creare
 115.241 +* imposta i permessi del filesystem (``isi-perms`` & ``isi-classe``)
 115.242 +
 115.243 +
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/docs/install/intro.rst	Mon Apr 26 11:16:23 2010 +0200
   116.3 @@ -0,0 +1,173 @@
   116.4 +=================
   116.5 + Possibili setup
   116.6 +=================
   116.7 +
   116.8 +Firewall
   116.9 +========
  116.10 +
  116.11 +.. figure:: ../img/rete-fwisi.png
  116.12 +   :align: center
  116.13 +
  116.14 ++ :ref:`La rete <config_eth_dns>`
  116.15 +
  116.16 ++ Le politiche di :ref:`firewalling <config_firewall>`
  116.17 +
  116.18 +
  116.19 +Server di dominio ISI
  116.20 +=====================
  116.21 +
  116.22 +.. figure:: ../img/rete-srvisi.png
  116.23 +   :align: center
  116.24 +
  116.25 +Questa tipologia di installazione presuppone che ci sia già un firewall a
  116.26 +protezione della rete. Il comando ``firewall`` del server, configurato per
  116.27 +considerare la zona a cui è collegato come *interna*, adotterà pertanto una
  116.28 +politica di filtraggio più permissiva.
  116.29 +
  116.30 +
  116.31 ++ :ref:`La rete <config_eth_dns>`
  116.32 +
  116.33 ++ Le politiche di :ref:`firewalling <config_firewall>`
  116.34 +
  116.35 ++ Attivare il server di Dominio
  116.36 +
  116.37 ++ I servizi principali
  116.38 +
  116.39 +    + demone nfs
  116.40 +
  116.41 +        + a cosa serve
  116.42 +
  116.43 +        + files di configurazione
  116.44 +
  116.45 +        + configurazione del servizio
  116.46 +
  116.47 +    + demone dhcp
  116.48 +
  116.49 +        + a cosa serve
  116.50 +
  116.51 +        + files di configurazione
  116.52 +
  116.53 +        + :ref:`configurazione del servizio <config_dhcpd>`
  116.54 +
  116.55 +
  116.56 +    + demone dns
  116.57 +
  116.58 +        + a cosa serve
  116.59 +
  116.60 +        + files di configurazione
  116.61 +
  116.62 +        + configurazione del servizio
  116.63 +
  116.64 +
  116.65 +    + proxy
  116.66 +
  116.67 +        + Squid
  116.68 +
  116.69 +            + a cosa serve
  116.70 +
  116.71 +            + files di configurazione
  116.72 +
  116.73 +            + configurazione del servizio
  116.74 +
  116.75 +        + Dans Guardian
  116.76 +
  116.77 +            + a cosa serve
  116.78 +
  116.79 +            + requisiti
  116.80 +
  116.81 +            + files di configurazione
  116.82 +
  116.83 +            + configurazione del servizio
  116.84 +
  116.85 +        + ClamAV
  116.86 +
  116.87 +            + a cosa serve
  116.88 +
  116.89 +            + requisiti
  116.90 +
  116.91 +            + files di configurazione
  116.92 +
  116.93 +            + configurazione del servizio
  116.94 +
  116.95 +
  116.96 +        + sarg
  116.97 +
  116.98 +            + a cosa serve
  116.99 +
 116.100 +            + requisiti
 116.101 +
 116.102 +            + files di configurazione
 116.103 +
 116.104 +            + configurazione del servizio
 116.105 +
 116.106 +    + web server: apache
 116.107 +
 116.108 +    + posta
 116.109 +    
 116.110 +        + pop3
 116.111 +
 116.112 +            popa3d
 116.113 +
 116.114 +                + a cosa serve
 116.115 +
 116.116 +                + requisiti
 116.117 +
 116.118 +                + files di configurazione
 116.119 +
 116.120 +                + configurazione del servizio
 116.121 +
 116.122 +        + smtp
 116.123 +
 116.124 +
 116.125 +
 116.126 +Aggiornare una precedente release di ISI
 116.127 +----------------------------------------
 116.128 +
 116.129 +DA COMPLETARE
 116.130 +
 116.131 ++ aggiornare un sistema ISI preesistente
 116.132 +
 116.133 +        + Principali salti di versione (e link al changelog)
 116.134 +
 116.135 +        + Aggiornare da una isi versione X ad una isi versione Y....
 116.136 +
 116.137 +
 116.138 +
 116.139 +            
 116.140 +
 116.141 +Configurare i client per il dominio
 116.142 +-----------------------------------
 116.143 +
 116.144 +
 116.145 ++ Client Windows
 116.146 +
 116.147 +    + Windows98 Second Edition
 116.148 +
 116.149 +        procedura illustrata
 116.150 +
 116.151 +    + Windows2000
 116.152 +
 116.153 +        procedura illustrata
 116.154 +
 116.155 +
 116.156 +    + Windows XP Home
 116.157 +
 116.158 +        tale versione non è in grado do accedere al dominio.
 116.159 +
 116.160 +    + Windows XP Professional
 116.161 +
 116.162 +        procedura illustrata
 116.163 +
 116.164 +
 116.165 +
 116.166 +
 116.167 ++ Client Linux
 116.168 +
 116.169 +    + Edubuntu linux
 116.170 +
 116.171 +        pacchetti aggiuntivi necessari
 116.172 +        
 116.173 +        Configurazione del client
 116.174 +        
 116.175 +
 116.176 +
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/docs/install/reteisi.rst	Mon Apr 26 11:16:23 2010 +0200
   117.3 @@ -0,0 +1,39 @@
   117.4 +.. _config_files:
   117.5 +
   117.6 +Reteisi
   117.7 +=======
   117.8 +
   117.9 +
  117.10 +/etc/isi
  117.11 +--------
  117.12 +
  117.13 +.. index:: logon.bat
  117.14 +
  117.15 +logon.bat
  117.16 +~~~~~~~~~
  117.17 +
  117.18 +.. index:: logon.conf
  117.19 +
  117.20 +logon.conf
  117.21 +~~~~~~~~~~
  117.22 +
  117.23 +.. index:: acl.conf
  117.24 +
  117.25 +acl.conf
  117.26 +~~~~~~~~
  117.27 +
  117.28 +
  117.29 +Home e share
  117.30 +============
  117.31 +
  117.32 +
  117.33 +/home/users
  117.34 +-----------
  117.35 +
  117.36 +/home/shares
  117.37 +------------
  117.38 +
  117.39 +
  117.40 +/home/samba
  117.41 +-----------
  117.42 +
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/docs/install/servizi/apache_limit_pub.rst	Mon Apr 26 11:16:23 2010 +0200
   118.3 @@ -0,0 +1,143 @@
   118.4 +Pubblicare una directory e restringerne l'accsso via Apache2
   118.5 +============================================================
   118.6 +
   118.7 +Cosa si intende con pubblicare una directory?
   118.8 +------------------------------------------------
   118.9 +
  118.10 +Pubblicare una directory del nostro filesystem via webserver ci permette
  118.11 +di poterla raggiungere remotamente con il nostro browser preferito, puntando
  118.12 +semplicemente ad un indirizzo del tipo ``http://<server>/directory``.
  118.13 +
  118.14 +Un esempio concreto : Pubblichiamo le statistiche del server proxy Squid
  118.15 +----------------------------------------------------------------------------
  118.16 +
  118.17 +Ci porremo come obiettivo la pubblicazione del contenuto della directory
  118.18 +"/var/www/squid-reports", contenente i report generati da :ref:`sarg <sarg-report>`
  118.19 +relativi al proxy.
  118.20 +Dato che le informazioni contenute nella directory in questione sono
  118.21 +riservate, l'accesso verra' limitato ad alcuni particolari network, ai quali
  118.22 +si rendera' comunque obbligatorio un processo autenticativo. 
  118.23 +
  118.24 +Prepariamo il file delle password
  118.25 +---------------------------------
  118.26 +Il file delle password contiene le credenziali necessarie per il processo di
  118.27 +autenticazione. 
  118.28 +
  118.29 +Creiamo la directory in cui mettere il nostro file::
  118.30 +
  118.31 +    mkdir /etc/apache2/htpasswd-sites/squid-reports
  118.32 +
  118.33 +Generiamo il file password ::
  118.34 +
  118.35 +    htpasswd -c /etc/apache2/htpasswd-sites/squid-reports nomeutente
  118.36 +
  118.37 +E ne restringiamo l'accesso il piu' possibile ::
  118.38 +
  118.39 +    chown root.www-data /etc/apache2/htpasswd-sites/squid-reports
  118.40 +    chmod 640 /etc/apache2/htpasswd-sites/squid-reports
  118.41 +
  118.42 +Ora siamo pronti per apportare le modifiche ad apache2.
  118.43 +
  118.44 +Modifichiamo quindi "/etc/apache2/sites-enabled/000-default" od il file di
  118.45 +configurazione di un sito abilitato (000-default e' solitamente attivo gia'
  118.46 +attivo di default), e aggiungiamo nella sezione compresa tra
  118.47 +<VirtualHost></VirtualHost>, una sottosezione <directory> che istruisca
  118.48 +apache su come pubblicare la nostra directory "/var/www/squid-reports". 
  118.49 +
  118.50 +Nella configurazione di esempio verrà consentito solo a localhost ed al
  118.51 +network 192.168.1.0/24 l'accesso alla fase autenticativa che consente di
  118.52 +raggiungere la directory, tutti gli altri host verranno rifiutati ::
  118.53 +
  118.54 +    <Directory "/var/www/http/squid-reports/">
  118.55 +    #########################################################################
  118.56 +    # Permette solo a 127.0.0.1 ed al network 192.168.1.0/24 di accedere alla
  118.57 +    # directory
  118.58 +      Deny from all
  118.59 +      Order Deny,Allow
  118.60 +
  118.61 +      Allow from 127.0.0.1/255.0.0.0 ::1/128
  118.62 +      Allow from 192.168.1.0/255.0.0.0
  118.63 +    #########################################################################
  118.64 +    # Attivare autenticazione tramite file di password
  118.65 +    # -----------------------------------------------------
  118.66 +    # Creare il file password ::
  118.67 +    #
  118.68 +    #     htpasswd -c /dir/filepassword utente
  118.69 +    #
  118.70 +    # Limitiamo il piu' possibile i permessi del file ma teniamo anche presente
  118.71 +    # che Apache dovra' poterlo leggere per verificare le credenziali fornitegli::
  118.72 +    #
  118.73 +    #     chown root.www-data /dir/filepassword
  118.74 +    #     chmod 640 /dir/filepassword
  118.75 +    #
  118.76 +      AuthType Basic
  118.77 +    # Si potra' personalizzare il messaggio che compare alla richiesta di
  118.78 +    # autenticazione.
  118.79 +      AuthName "Area ad accesso limitato."
  118.80 +      AuthUserFile /dir/filepassword
  118.81 +    # Richiede un utente particolare
  118.82 +    #  Require user nomeutente
  118.83 +    # Ritiene valido uno qualunque degli utenti inseriti nel file di password
  118.84 +      Require valid-user
  118.85 +    </Directory>
  118.86 +
  118.87 +E' anche possibile definire un Alias( lo si puo' intendere come un soprannome
  118.88 +che diamo alla nostra directory di destinazione), anteponendo al blocco
  118.89 +<Directory></Directory> una direttiva "Alias".
  118.90 +
  118.91 +Es. ::
  118.92 +
  118.93 +    Alias /reports "/var/www/http/squid-reports/"
  118.94 +
  118.95 +Nell'esempio sopra si e' definito un Alias "reports" che permette di raggiungere
  118.96 +"/var/www/http/squid-reports/" anche tramite l'url "http://server/reports".
  118.97 +
  118.98 +Ultimate le modifiche, il nostro file di configurazione dovrebbe contenere un
  118.99 +blocco simile alla seguente ::
 118.100 +
 118.101 +    Alias /reports "/var/www/http/squid-reports/"
 118.102 +    <Directory "/var/www/http/squid-reports/">
 118.103 +    #########################################################################
 118.104 +    # Permette solo a 127.0.0.1 ed al network 192.168.1.0/24 di accedere alla
 118.105 +    # directory
 118.106 +      Deny from all
 118.107 +      Order Deny,Allow
 118.108 +
 118.109 +      Allow from 127.0.0.1/255.0.0.0 ::1/128
 118.110 +      Allow from 192.168.1.0/255.0.0.0
 118.111 +    #########################################################################
 118.112 +    # Attivare autenticazione tramite file di password
 118.113 +    # -----------------------------------------------------
 118.114 +    # Creare il file password ::
 118.115 +    #
 118.116 +    #     htpasswd -c /dir/filepassword utente
 118.117 +    #
 118.118 +    # Limitiamo il piu' possibile i permessi del file ma teniamo anche presente
 118.119 +    # che Apache dovra' poterlo leggere per verificare le credenziali fornitegli::
 118.120 +    #
 118.121 +    #     chown root.www-data /dir/filepassword
 118.122 +    #     chmod 640 /dir/filepassword
 118.123 +    #
 118.124 +      AuthType Basic
 118.125 +    # Si potra' personalizzare il messaggio che compare alla richiesta di
 118.126 +    # autenticazione.
 118.127 +      AuthName "Area ad accesso limitato."
 118.128 +      AuthUserFile /dir/filepassword
 118.129 +    # Richiede un utente particolare
 118.130 +    #  Require user nomeutente
 118.131 +    # Ritiene valido uno qualunque degli utenti inseriti nel file di password
 118.132 +      Require valid-user
 118.133 +    ### Personalizzazione messaggi di errore
 118.134 +    # CODICE 401 : Credenziali fornite non valide
 118.135 +    # CODICE 403 : Indirizzo di rete rifiutato
 118.136 +      ErrorDocument 401 "Credenziali fornite non valide !"
 118.137 +      ErrorDocument 403 "Non ti e' consentito accedere a quest'area."
 118.138 +
 118.139 +    </Directory>
 118.140 +
 118.141 +
 118.142 +
 118.143 +Per spiegazioni ulteriori sulle direttive usate si rimanda alla
 118.144 +documentazione_ ufficiale di apache2
 118.145 +
 118.146 +.. _documentazione: http://httpd.apache.org/docs/1.3/howto/auth.html
   119.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.2 +++ b/docs/install/servizi/apache_userdir.rst	Mon Apr 26 11:16:23 2010 +0200
   119.3 @@ -0,0 +1,148 @@
   119.4 +.. _config_apache_userdir:
   119.5 +
   119.6 +Pubblicare le  home utente  con Apache2
   119.7 +=======================================
   119.8 +
   119.9 +Cosa serve?
  119.10 +-----------
  119.11 +
  119.12 +1. Apache2 installato e configurato correttamente
  119.13 +2. Modulo ``userdir`` del webserver configurato ed attivato
  119.14 +
  119.15 +Focalizzeremo la nostra attenzione sul punto ``2``.
  119.16 +
  119.17 +I moduli estendono le funzionalità del webserver. Per gestirne attivazione e
  119.18 +disattivazione, Apache mette a disposizione due comandi:
  119.19 +
  119.20 +- ``a2enmod`` elenca i moduli `non avviati` disponibili e permette di attivarli.
  119.21 +-  ``a2dismod`` elenca i moduli `avviati` disponibili e permette di disattivarli.
  119.22 +
  119.23 +Nella pratica, attivazione e disattivazione consistono nella semplice creazione di
  119.24 +un collegamento simbolico da ``/etc/apache2/mods-available/nomemodulo.load`` a 
  119.25 +``/etc/apache2/mods-enabled/.load``.
  119.26 +Alcuni moduli hanno inoltre un file aggiuntivo di configurazione del tipo 
  119.27 +`nomemodulo.conf` qualora si procedesse all'attivazione manuale, non si dimentichi
  119.28 +di aggiungere anche quel collegamento simbolico se necessario!.
  119.29 +
  119.30 +Quali moduli ho a disposizione?
  119.31 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  119.32 +
  119.33 +::
  119.34 +
  119.35 +    ls /etc/apache2/mods-available/
  119.36 +    
  119.37 +    actions.load        authz_dbm.load        charset_lite.load  dump_io.load   
  119.38 +    log_forensic.load    proxy_connect.load           unique_id.load
  119.39 +    alias.load          authz_default.load    dav_fs.conf        env.load       
  119.40 +    mem_cache.conf       proxy_ftp.load               userdir.conf
  119.41 +    asis.load           authz_groupfile.load  dav_fs.load        expires.load   
  119.42 +    mem_cache.load       proxy_http.load              userdir.load
  119.43 +    auth_basic.load     authz_host.load       dav.load           ext_filter.load
  119.44 +    mime.load            proxy.load                   usertrack.load
  119.45 +    auth_digest.load    authz_owner.load      dav_lock.load      file_cache.load
  119.46 +    mime_magic.conf      rewrite.load                 version.load
  119.47 +    authn_alias.load    authz_user.load       dbd.load           filter.load    
  119.48 +    mime_magic.load      setenvif.load                vhost_alias.load
  119.49 +    authn_anon.load     autoindex.load        deflate.conf       headers.load   
  119.50 +    negotiation.load     sick-hack-to-update-modules
  119.51 +    authn_dbd.load      cache.load            deflate.load       ident.load     
  119.52 +    php5.conf            speling.load
  119.53 +    authn_dbm.load      cern_meta.load        dir.conf           imagemap.load  
  119.54 +    php5.load            ssl.conf
  119.55 +    authn_default.load  cgid.conf             dir.load           include.load   
  119.56 +    proxy_ajp.load       ssl.load
  119.57 +    authn_file.load     cgid.load             disk_cache.conf    info.load      
  119.58 +    proxy_balancer.load  status.load
  119.59 +    authnz_ldap.load    cgi.load              disk_cache.load    ldap.load      
  119.60 +    proxy.conf           suexec.load
  119.61 +
  119.62 +Quali sono già stati attivati?
  119.63 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  119.64 +
  119.65 +::
  119.66 +
  119.67 +    ls /etc/apache2/mods-enabled/
  119.68 +    
  119.69 +    actions.load  auth_basic.load  authz_default.load    authz_host.load  
  119.70 +    autoindex.load  dir.conf  env.load   negotiation.load  php5.load      
  119.71 +    status.load    alias.load    authn_file.load  authz_groupfile.load  
  119.72 +    authz_user.load  cgi.load    dir.load  mime.load  php5.conf    setenvif.load
  119.73 +
  119.74 +.. Note::
  119.75 +    
  119.76 +    Notare l'assenza di ``userdir.load``
  119.77 +
  119.78 +Configurare il modulo ``userdir.load``
  119.79 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  119.80 +
  119.81 +Affinchè il webserver pubblicizzi il sito personale di ogni utente, contenuto in
  119.82 +~utente/public_html, modificheremo ``userdir.conf``.
  119.83 +
  119.84 +.. Note::
  119.85 +
  119.86 +   Nota probabilmente ovvia:
  119.87 +   Nell'esempio che segue viene usato l'editor `jmacs`. Ovviamente nulla viete di 
  119.88 +   usare il proprio editor di testi preferito.
  119.89 +
  119.90 +::
  119.91 +    
  119.92 +    jmacs /etc/apache2/mods-available/userdir.conf
  119.93 +
  119.94 +    <IfModule mod_userdir.c>
  119.95 +            UserDir public_html
  119.96 +            UserDir disabled root
  119.97 +
  119.98 +            <Directory /home/*/public_html>
  119.99 +                    AllowOverride FileInfo AuthConfig Limit
 119.100 +                    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
 119.101 +            </Directory>
 119.102 +    </IfModule>
 119.103 +
 119.104 +In questo modo::
 119.105 +    
 119.106 +    <IfModule mod_userdir.c>
 119.107 +            UserDir public_html
 119.108 +            UserDir disabled root
 119.109 +
 119.110 +            <Directory /home/users/*/*/public_html>
 119.111 +                    AllowOverride FileInfo AuthConfig Limit
 119.112 +                    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
 119.113 +            </Directory>
 119.114 +    </IfModule>
 119.115 +
 119.116 +.. Note::
 119.117 +
 119.118 +    Ovviamente è stato impostato ``/home/users/*/*/public_html`` per rispettare
 119.119 +    l'organizzazione delle `home utente` ISI.
 119.120 +
 119.121 +Attivare ``userdir.load``
 119.122 +~~~~~~~~~~~~~~~~~~~~~~~~~
 119.123 +
 119.124 +Non resta che procedere all'attivazione di ``userdir`` usando ``a2enmod`` ::
 119.125 +
 119.126 +    a2enmod userdir
 119.127 +
 119.128 +    Module userdir installed; run /etc/init.d/apache2 force-reload to enable.
 119.129 +
 119.130 +E ad inizializzare apache2 come indicato da ``a2enmod``
 119.131 +::
 119.132 +
 119.133 +    /etc/init.d/apache2 force-reload
 119.134 +    Forcing reload of web server (apache2)...apache2: Could not reliably determine
 119.135 +    the server's fully qualified domain name, using 127.0.0.1 for ServerName
 119.136 +    waiting apache2: Could not reliably determine the server's fully qualified 
 119.137 +    domain name, using 127.0.0.1 for ServerName
 119.138 +
 119.139 +Verificare che tutto funzioni
 119.140 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 119.141 +
 119.142 +La verifica viene fatta, molto semplicemente, puntando un qualunque browser
 119.143 +su ``http://server/~nomeutente``.
 119.144 +
 119.145 +Od in alternativa, direttamente da server, con un semplicissimo::
 119.146 +
 119.147 +    lynx http://localhost/~test
 119.148 +
 119.149 +Se a risponderci sarà la pagina `index.html` contenuta in `~test/public_html` la 
 119.150 +procedura sarà andata a buon fine =)
 119.151 +
   120.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   120.2 +++ b/docs/install/servizi/bind.rst	Mon Apr 26 11:16:23 2010 +0200
   120.3 @@ -0,0 +1,52 @@
   120.4 +.. _config_bind:
   120.5 +
   120.6 +dns server: bind9
   120.7 +===================
   120.8 +
   120.9 +Bind è il server dns. 
  120.10 +
  120.11 +.. sidebar:: Serve? 
  120.12 +
  120.13 +  La configurazione di questo servizio è necessaria solo
  120.14 +  se si ha un server web interno alla scuola, con IP privato e si deidera
  120.15 +  poterlo raggiungere con lo stesso nome dall'interno e dall'esterno della
  120.16 +  scuola. In questo caso la configurazione è più complessa di quanto riportato
  120.17 +  di seguito.
  120.18 +  
  120.19 +
  120.20 +L'attivazione di bind non richiede nessuna modifica particolare; la
  120.21 +configurazione trovata di default andrà dunque benissimo.
  120.22 +
  120.23 +Ci si assicuri che sia avviato::
  120.24 +
  120.25 +    srv-scuolax:/etc/dhcp3# ps aux|grep bind
  120.26 +    root      5118  0.0  0.2   2860   692 pts/0    R+   17:24   0:00 grep  bind
  120.27 +
  120.28 +Tale comando, visualizza l'elenco dei processi attivi al momento il cui nome
  120.29 +contenga la parola *bind*. Come si evince dall'output non c'è nessun
  120.30 +processo bind9 attivo nell'esempio.
  120.31 +
  120.32 +Qualora bind9 non fosse attivo si potrà avviarlo manualmente::
  120.33 +
  120.34 +    srv-scuolax:/etc/dhcp3# /etc/init.d/bind9 start
  120.35 +    Starting domain name service...: bind.
  120.36 +
  120.37 +Verifichiamo che si sia attivato::
  120.38 +
  120.39 +    srv-scuolax:~# ps aux | grep bind
  120.40 +    bind      5136  0.0  1.4  33972  3712 ?        Ssl  Feb15   0:00 /usr/sbin/named -u bind
  120.41 +    root      6723  0.0  0.2   2856   696 pts/0    S+   00:01   0:00 grep bind
  120.42 +
  120.43 +
  120.44 +Non resta che modificare di conseguenza ``/etc/resolv.conf`` affinchè, per la
  120.45 +risoluzione degli hostname, venga usato prioritariamente bind9::
  120.46 +
  120.47 +    srv-scuolax:/etc/dhcp3# cat /etc/resolv.conf
  120.48 +    nameserver 127.0.0.1
  120.49 +    nameserver 192.84.138.160
  120.50 +    nameserver 192.84.138.1
  120.51 +
  120.52 +E' importante verificare inoltre che il servizio venga attivato ad ogni
  120.53 +avvio della macchina. A tal proposito, come visto in altre occasioni, si
  120.54 +modifichi */etc/runlevel.conf* rimuovendo il simbolo # ad inizio riga, se
  120.55 +presente.
   121.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   121.2 +++ b/docs/install/servizi/bind_server.rst	Mon Apr 26 11:16:23 2010 +0200
   121.3 @@ -0,0 +1,260 @@
   121.4 +.. _config_bind_server:
   121.5 +
   121.6 +DNS Server
   121.7 +==========
   121.8 +
   121.9 +Qui troverete i file di configurazione del servizio DNS per una intranet
  121.10 +scolastica concepita secondo il modello ISI. Il DNS assicurerà la
  121.11 +risoluzione dei nomi delle macchine sulla intranet, comprese quelle ad
  121.12 +indirizzo dinamico (aggiornamento del DNS via DHCP). Si tenga presente che
  121.13 +nelle nostre scuole la segreteria opera in ambiente win2000 server
  121.14 +configurato con Active Directory e quindi realizzante un dominio
  121.15 +separato. Al momento l'integrazione segreteria resto della intranet è al
  121.16 +livello della condivisione dell'accesso internet (magari con l'attivazione
  121.17 +della doppia adsl) attraverso un unico firewall e alla connessione permessa
  121.18 +solo da client particolari esterne alla sottorete specifica.
  121.19 +
  121.20 +    * /etc/bind/named.conf.local
  121.21 +    * /etc/bind/named.conf.options
  121.22 +    * /etc/bind/miascuola.lan
  121.23 +    * /etc/bind/rev1.lan
  121.24 +    * /etc/bind/rev2.lan
  121.25 +    * /etc/bind/rev5.lan 
  121.26 +
  121.27 +Per quanto riguarda i dettagli circa la configurazione di Bind9 si rimanda
  121.28 +alla documentazione tecnica disponibile in rete, qui ci si limiterà ad
  121.29 +illustrare l'organizzazione e il contenuto dei file di configurazione.
  121.30 +
  121.31 +L'architettura della intranet sia la seguente:
  121.32 +
  121.33 +    * vlan1 sottorete di staff e di amministrazione
  121.34 +    * vlan2 sottorete di laboratorio (ce ne può essere una per laboratorio)
  121.35 +    * vlan5 sottorete della segreteria (si ipotizza che la segreteria
  121.36 +      sfrutti, per fondamentali ragioni di sicurezza) il firewall principale
  121.37 +      per l'accesso internet, si tenga presente inoltre che nel modello isi,
  121.38 +      la segreteria è integrata nella intranet dell'istituto.
  121.39 +
  121.40 +Il server DNS può essere ospitato dovunque, ma nel modello isi tale
  121.41 +servizio, insieme al DHCP, è in funzione sulla macchina firewall che, grazie
  121.42 +al sistema delle vlan, è attestata su tutte le vlan.
  121.43 +
  121.44 +il dominio dns si chiamerà miascuola.lan. Il che significa, ad esempio, che
  121.45 +l'url del server web interno sarà www.miascuola.lan
  121.46 +
  121.47 +In Debian tutti i file di configurazione necessari si trovano sotto
  121.48 +/etc/bind e quelli per noi significativi sono:
  121.49 +
  121.50 +    * /etc/bind/named.conf in cui sono elencate le zone standard del domio
  121.51 +      DNS ALERT! lo si lascia inalterato
  121.52 +
  121.53 +    * /etc/bind/named.conf.local in cui sono elencate le zone dirette del
  121.54 +      dominio e quelle inverse del nostro dominio
  121.55 +
  121.56 +    * /etc/bind/named.conf.option in cui vengono elencate i forwarders
  121.57 +
  121.58 +    * /etc/bind/miascuola.lan in cui sono elencate nomi e ip di tutte le
  121.59 +      macchine sulla rete
  121.60 +
  121.61 +    * /etc/bind/rev1 e simili che costituiscono le zone inverse, cioè il
  121.62 +      meccanismo con cui dall'ip si risale al nome
  121.63 +
  121.64 +Ma vediamoli in dettaglio:
  121.65 +
  121.66 +/etc/bind/named.conf.local
  121.67 +
  121.68 +Si noti la direttiva key DHCP_UPDATER. Si ricordi che il valore di
  121.69 +quest'ultima deve essere identico a quella dichiarata nel file di
  121.70 +configurazione del server dhcp (/etc/dhcp3/dhcpd.conf) altrimenti
  121.71 +l'aggiornamento dinamico dei record dns non funzionerà.::
  121.72 +
  121.73 +  // -*- c++ -*-
  121.74 +  // Do any local configuration here
  121.75 +  //
  121.76 +  
  121.77 +  // Consider adding the 1918 zones here, if they are not used in your
  121.78 +  // organization
  121.79 +  //include "/etc/bind/zones.rfc1918";
  121.80 +  
  121.81 +  
  121.82 +  // Tells the nameserver who to allow updates from, with what keys
  121.83 +  controls {
  121.84 +    inet 127.0.0.1 allow { localhost; } keys { DHCP_UPDATER; };
  121.85 +  };
  121.86 +  
  121.87 +  
  121.88 +  // ddns - key
  121.89 +  key DHCP_UPDATER {
  121.90 +    algorithm HMAC-MD5.SIG-ALG.REG.INT;
  121.91 +    secret NmfU90eVsfpLk2Ht07R2IQ==;
  121.92 +  ';
  121.93 +  
  121.94 +  zone "miascuola.lan" {
  121.95 +       type master;
  121.96 +       file "/etc/bind/miascuola.lan";
  121.97 +       allow-update { key DHCP_UPDATER; ';
  121.98 +  };
  121.99 +  
 121.100 +  
 121.101 +  // staff - reverse - vlan1
 121.102 +  zone "1.168.192.in-addr.arpa" {
 121.103 +       type master;
 121.104 +       file "/etc/bind/rev1";
 121.105 +       allow-update { key DHCP_UPDATER; ';
 121.106 +  };
 121.107 +  
 121.108 +  
 121.109 +  // lab - reverse - vlan2
 121.110 +  zone "2.168.192.in-addr.arpa" {
 121.111 +       type master;
 121.112 +       file "/etc/bind/rev2";
 121.113 +       allow-update { key DHCP_UPDATER; ';
 121.114 +  };
 121.115 +  
 121.116 +  
 121.117 +  // segreteria - reverse - vlan5
 121.118 +  zone "5.168.192.in-addr.arpa" {
 121.119 +       type master;
 121.120 +       file "/etc/bind/rev5;
 121.121 +       allow-update { key DHCP_UPDATER; ';
 121.122 +  };
 121.123 +  
 121.124 +  
 121.125 +/etc/bind/named.conf.options
 121.126 +
 121.127 +Qui la cosa importante sono i forwarders. Il concetto è semplice: quando il
 121.128 +nostro DNS non riesce a risolvere un nome, perché esterno alle zone locali,
 121.129 +passerà la richiesta ai server DNS esterni dichiarati dalla direttiva
 121.130 +forwarders. In pratica si tratta dei DNS primario o secondario indicatici
 121.131 +dal nostro provider oppure di DNS pubblici.::
 121.132 +
 121.133 +  options {
 121.134 +     directory "/var/cache/bind";
 121.135 +  
 121.136 +     // If there is a firewall between you and nameservers you want
 121.137 +     // to talk to, you might need to uncomment the query-source
 121.138 +     // directive below.  Previous versions of BIND always asked
 121.139 +     // questions using port 53, but BIND 8.1 and later use an unprivileged
 121.140 +     // port by default.
 121.141 +  
 121.142 +     // query-source address * port 53;
 121.143 +  
 121.144 +     // If your ISP provided one or more IP addresses for stable
 121.145 +     // nameservers, you probably want to use them as forwarders.
 121.146 +     // Uncomment the following block, and insert the addresses replacing
 121.147 +     // the all-0's placeholder.
 121.148 +  
 121.149 +          // i forwarders sono gli ip dei DNS esterni 
 121.150 +	  // (quelli del vostro provider)
 121.151 +          // qui saranno automaticamente redirette tutte le richieste DNS
 121.152 +          // non soddisfatte all'interno del nostro dominio
 121.153 +  
 121.154 +     forwarders {
 121.155 +         151.99.125.2;
 121.156 +         194.243.154.62;
 121.157 +     };
 121.158 +  
 121.159 +     auth-nxdomain no;    # conform to RFC1035
 121.160 +  
 121.161 +  };
 121.162 +  
 121.163 +
 121.164 +/etc/bind/miascuola.lan
 121.165 +
 121.166 +Sono elencati i server, gli apparati di rete ed eventuali pc con ip
 121.167 +statico. Questo file provvede alla fondamentale funzione di risoluzione dei
 121.168 +nomi nel corrispondente indirizzo ip. Visualizzando questo file a server in
 121.169 +funzione, vi si troveranno dentro anche gli aggiornamenti effettuati dal
 121.170 +server dhcp ogni volta che un client si connette alla rete.
 121.171 +
 121.172 +fw-scuola = il firewall della scuola, cioè la macchina interposta fra la
 121.173 +nostra rete e internet. Il router adsl è direttamente connesso a questa
 121.174 +macchina attraverso una delle sue schede di rete (deve averne infatti almeno
 121.175 +due, o tante quante sono le sottoreti che si vogliono gestire nel caso non
 121.176 +si disponga di dispositivi 802.1q) srv-uno = il server principale (quello
 121.177 +che fa anche da PDC)
 121.178 +
 121.179 +srv-due = un altro server stp-lx = stampanti laser di rete sw-xxx = switch
 121.180 +managed con gestione VLAN (802.1q) rt-adslx = router adsl (potrebbe
 121.181 +essercene piu' di uno) xp-xxxxx = client qualificati con ip statico e
 121.182 +funzioni amministrative::
 121.183 +
 121.184 +  $ORIGIN .
 121.185 +  $TTL 86400      ; 1 day
 121.186 +  miascuola.lan           IN SOA  fw-scuola.miascuola.lan. root.miascuola.lan. (
 121.187 +                                  1          ; serial
 121.188 +                                  28800      ; refresh (8 hours)
 121.189 +                                  14400      ; retry (4 hours)
 121.190 +                                  3600000    ; expire (5 weeks 6 days 16 hours)
 121.191 +                                  86400      ; minimum (1 day)
 121.192 +                                  )
 121.193 +                          NS      fw-scuola.miascuola.lan.
 121.194 +  fw-scuola               A       192.168.1.1        //sulla vlan1 (sottorete di staff)
 121.195 +  srv-uno                 A       192.168.1.2        //sulla vlan1 
 121.196 +  srv-due                 A       192.168.1.3        //sulla vlan1 
 121.197 +  stp-l1                  A       192.168.1.6        //stampante tcp/ip su vlan1  
 121.198 +  sw-uno                  A       192.168.1.21       //switch managed su vlan1 
 121.199 +  sw-due                  A       192.168.1.22       //switch managed su vlan1
 121.200 +  rt-adsl1                A       192.168.200.2      //router adsl 
 121.201 +  www                     CNAME   srv-uno
 121.202 +  xp-admin01              A       192.168.1.25       //pc con funzioni particolari
 121.203 +  xp-preside              A       192.168.1.26
 121.204 +  stp-l2                  A       192.168.2.7        //stanpante tcp/ip su vlan2
 121.205 +  srv-segreteria          A       192.168.5.2        //sulla vlan5 (segreteria)
 121.206 +  
 121.207 +
 121.208 +/etc/bind/rev1.lan
 121.209 +File di risoluzione inversa per la vlan1
 121.210 +
 121.211 +::
 121.212 +
 121.213 +  $ORIGIN .
 121.214 +  $TTL 86400      ; 1 day
 121.215 +  1.168.192.in-addr.arpa IN SOA  fw-scuola.miascuola.lan. root.miascuola.lan. (
 121.216 +                                  1          ; serial
 121.217 +                                  28800      ; refresh (8 hours)
 121.218 +                                  14400      ; retry (4 hours)
 121.219 +                                  3600000    ; expire (5 weeks 6 days 16 hours)
 121.220 +                                  86400      ; minimum (1 day)
 121.221 +                                  )
 121.222 +                          NS      fw-scuola.miascuola.lan.
 121.223 +  1                       PTR     fw-miascuola.miascuola.lan.
 121.224 +  2                       PTR     srv-uno.miascuola.lan.
 121.225 +  3                       PTR     srv-due.miascuola.lan.
 121.226 +  6                       PTR     stp-l1.miascuola.lan.
 121.227 +  10                      PTR     xp-preside.miascuola.lan.
 121.228 +  11                      PTR     xp-admin01.miascuola.lan.
 121.229 +  21                      PTR     sw-rag.miascuola.lan.
 121.230 +  22                      PTR     sw-due.miascuola.lan.
 121.231 +  
 121.232 +  
 121.233 +/etc/bind/rev2.lan
 121.234 +::
 121.235 +
 121.236 +  $ORIGIN .
 121.237 +  $TTL 86400      ; 1 day
 121.238 +  2.168.192.in-addr.arpa      IN SOA  fw-scuola.miascuola.lan. root.miascuola.lan. (
 121.239 +                                  1          ; serial
 121.240 +                                  28800      ; refresh (8 hours)
 121.241 +                                  14400      ; retry (4 hours)
 121.242 +                                  3600000    ; expire (5 weeks 6 days 16 hours)
 121.243 +                                  86400      ; minimum (1 day)
 121.244 +                                  )
 121.245 +                          NS      fw-scuola.miascuola.lan.
 121.246 +  1                       PTR     fw-scuola.miascuola.lan.
 121.247 +  7                       PTR     stp-l2.miascuola.lan.
 121.248 +  
 121.249 +  
 121.250 +  /etc/bind/rev5.lan
 121.251 +  
 121.252 +  $TTL 86400      ; 1 day
 121.253 +  5.168.192.in-addr.arpa     IN SOA  fw-scuola.miascuola.lan. root.miascuola.lan. (
 121.254 +                                  1                  ; serial
 121.255 +                                  28800      ; refresh (8 hours)
 121.256 +                                  14400      ; retry (4 hours)
 121.257 +                                  3600000    ; expire (5 weeks 6 days 16 hours)
 121.258 +                                  86400      ; minimum (1 day)
 121.259 +                                  )
 121.260 +                          NS              fw-scuola.miascuola.lan.
 121.261 +  1                       PTR             fw-scuola.miascuola.lan.
 121.262 +  2                       PTR             srv-segreteria.miascuola.lan.
 121.263 +  
   122.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   122.2 +++ b/docs/install/servizi/dhcpd.rst	Mon Apr 26 11:16:23 2010 +0200
   122.3 @@ -0,0 +1,86 @@
   122.4 +.. _config_dhcpd:   
   122.5 +
   122.6 +dhcpd
   122.7 +==================================
   122.8 +Il servizio dhcp consente di configurare automaticamente impostazioni di rete
   122.9 +come ip, dns, winserver, e molto altro ancora ancora, su tutti i client presenti
  122.10 +nella nostra rete, siano essi Linux o Microsoft. 
  122.11 +Usando un dhcp-server potremmo dunque evitare di configurare a mano le impostazioni
  122.12 +di ogni singolo client.
  122.13 +
  122.14 +Per approfondimenti: `http://it.wikipedia.org/wiki/DHCP`.
  122.15 +
  122.16 +.. sidebar:: **Ci serve?**
  122.17 +
  122.18 +   Non è necessario usare dhcp ma è mia esperienza che gli amministratori
  122.19 +   scolastici che spesso non comprendono l'importanza del winserver,
  122.20 +   dimenticano di impostarlo e conseguentemente -in alcune stutture di rete-
  122.21 +   alcuni client non trovano il server di dominio. Con il dhcp server siamo
  122.22 +   sicuri che tutti i client avranno la stessa configurazione.
  122.23 +
  122.24 +dhcpd.conf
  122.25 +----------
  122.26 +La configurazione del servizio viene effettuata modificando il file di 
  122.27 +configurazione ``/etc/dhcp3/dhcpd.conf`` con un qualunque editor di testo.
  122.28 +*Nota*: Prestare attenzione a non confondere dhcp3 con dhcp( se presente).
  122.29 +Essendo i parametri configurabili molteplici, verrà fornito, a seguire, un 
  122.30 +esempio pratico funzionante di configurazione utile in un ambiente ISI. Nulla 
  122.31 +vieta, come ovvio, di aggiungere o rimuovere direttive ulteriori. 
  122.32 +Una lettura del file del file ``/etc/dhcp3/dhcpd.conf.isi.sample`` potrebbe
  122.33 +risultare utile fonte di spunto.
  122.34 +
  122.35 +La configurazione di ``/etc/dhcp3/dhcpd.conf`` suggerita, per un'installazione
  122.36 +"standard", è la seguente::
  122.37 +
  122.38 +    ##### option definitions common to all supported networks...
  122.39 +    option domain-name "srv-scuolax.lan";
  122.40 +    option domain-name-servers 10.1.2.1;
  122.41 +
  122.42 +    option subnet-mask 255.255.255.0;
  122.43 +    default-lease-time 600;
  122.44 +    max-lease-time 7200;
  122.45 +
  122.46 +    option option-128 code 128 = string;
  122.47 +    option option-129 code 129 = text;
  122.48 +
  122.49 +    ##### subnet
  122.50 +    subnet 10.1.2.0 netmask 255.255.255.0 {
  122.51 +      range 10.1.2.100 10.1.2.200;
  122.52 +      option routers 10.1.2.1;
  122.53 +      option netbios-name-servers 10.1.2.1;
  122.54 +      option netbios-node-type 8;
  122.55 +
  122.56 +      option subnet-mask 255.255.255.0;
  122.57 +      option broadcast-address 10.1.2.255;
  122.58 +      default-lease-time 600;
  122.59 +      max-lease-time 7200;
  122.60 +    }
  122.61 +
  122.62 +Adottando tale configurazione, il server dhcp risulterà impostato per:
  122.63 +
  122.64 ++ assegnare un indirizzo IP (ed una netmask)
  122.65 ++ *GATEWAY* ( option routers )
  122.66 ++ *DNS* ( domain-name-servers )
  122.67 ++ *WINS* o server di risoluzione nomi netbios ( netbios-name-servers )
  122.68 +
  122.69 +.. Note:
  122.70 +
  122.71 +    Ovviamente ai riferimenti dell'esempio andranno sostituiti i propri riferimenti
  122.72 +    di rete (network, ip, wins, etc...)
  122.73 +
  122.74 +Riavvio del servente
  122.75 +--------------------
  122.76 +
  122.77 +Ultimata la modifica della configurazione, per attivare il servizio, non resterà
  122.78 +che riavviarlo::
  122.79 +
  122.80 +    srv-scuolax:/etc/dhcp3# /etc/init.d/dhcp3-server restart
  122.81 +    Stopping DHCP server: dhcpd3.
  122.82 +    Starting DHCP server: dhcpd3.
  122.83 +
  122.84 +Attivazione al boot
  122.85 +-------------------
  122.86 +Ora che DHCP è configurato e attivato, non resta che assicurare che venga avviato
  122.87 +automaticamente in fase di boot. Ci si assicuri pertanto che nel file ``/etc/runlevel.conf``
  122.88 +le linee riferite al servizio DHCP non siano commentate( commentata è una qualunque linea
  122.89 +iniziante con il simbolo ``#``).
   123.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   123.2 +++ b/docs/install/servizi/firewall.rst	Mon Apr 26 11:16:23 2010 +0200
   123.3 @@ -0,0 +1,173 @@
   123.4 +.. _config_firewall:
   123.5 +
   123.6 +Il firewall
   123.7 +===========
   123.8 +
   123.9 +.. sidebar:: Serve?
  123.10 +
  123.11 +   si. Il firewall deve essere sempre configurato. Probabilmente vi basta
  123.12 +   la configurazione base descritta di seguito ed ottenuta modificando il
  123.13 +   solo file ``fw.conf``
  123.14 +
  123.15 +Esiste una esperienza di laboratorio per la 
  123.16 +:ref:`configurazione base <lab_firewalling>`  del firewall ed una sul 
  123.17 +:ref:`lab_dnat`
  123.18 +
  123.19 +.. note::
  123.20 +
  123.21 +   dalla versione *lenny* di ``argo`` il comando ``firewall`` è stato sostituito
  123.22 +   dal comando ``pyrewall``, che ha i medesimi file di configurazione ma è
  123.23 +   implementato in Python
  123.24 +
  123.25 +Introduzione
  123.26 +------------
  123.27 +
  123.28 +Ricordo che il firewalling in un sistema Linux è appannaggio del
  123.29 +kernel. Possono essere usati molti programmi per configurare il kernel. Qui
  123.30 +illustro il comando ``pyrewall`` sviluppato specificamente per la
  123.31 +distribuzione Argolinux da una idea di una script analoga nella
  123.32 +distribuzione gibraltar_.
  123.33 +
  123.34 +Il comando ``pyrewall`` legge due file di configurazione: 
  123.35 +
  123.36 +:``fw.conf``:  per le impostazioni di variabili
  123.37 +:``fw.add``:   per i comandi
  123.38 +
  123.39 +nel primo è sufficiente impostare alcune variabili ed avremo una
  123.40 +configurazione sicura nella stragrande maggioranza delle situazioni
  123.41 +
  123.42 +.. index:: pyrewall; fw.add
  123.43 +
  123.44 +variabili disponibili in fw.conf
  123.45 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  123.46 +INT    lista dei device 'interni' per il traffico entrante da questi device
  123.47 +       ha come politica di defaul ``ACCEPT``
  123.48 +
  123.49 +EXT    lista dei device 'esterni' per il traffico entrante da questi device
  123.50 +       ha come politica di defaul ``DROP``
  123.51 +
  123.52 +LAN    IPs e network che dovranno essere mascherati (nattati)
  123.53 +
  123.54 +
  123.55 +FORWARD
  123.56 +       Abilita il forward dei pacchetti tramite ``/proc/sys/net/ipv4/ip_forwad``
  123.57 +       if this  variable  is  not  set  to  0.  Ivviamente il forward andrà
  123.58 +       in ogni caso esplicitamente accettato
  123.59 +
  123.60 +IP_MODE
  123.61 +       Può essere ``static`` e ``dynamic``.  Determina se la modalità sarà
  123.62 +       ``masquerading`` (dynamic) o ``natting`` (static)
  123.63 +       Se si sceglie statico occorre anche definire IP_EXT.
  123.64 +
  123.65 +        
  123.66 +LOG    if  this  value  is  set to 1, logging will take
  123.67 +       place before dropping packets.  You  can  "color
  123.68 +       parse"  log  fil  with  fwparse(1).  2 different
  123.69 +       labels are used to mark packets dropped in INPUT
  123.70 +       chain or FORWARD chain.
  123.71 +
  123.72 +INPUT_CHAINS
  123.73 +       List  of  INPUT  chains   that  should  be  created/destroyed with start/stop
  123.74 +
  123.75 +FWD_CHAINS
  123.76 +       List of in the FORWARD chains   that  should  be
  123.77 +       created/destroyed with start/stop
  123.78 +
  123.79 +TCP_DPORTS
  123.80 +       List of tcp ports that should be opened from the
  123.81 +       external interface
  123.82 +
  123.83 +UDP_DPORTS
  123.84 +       List of udp ports that should be opened from the
  123.85 +       external interface
  123.86 +
  123.87 +PROXY_REDIR_PORT
  123.88 +       Porta alla quale redirigere il traffico che cerca di passare dalla
  123.89 +       porta 80. normalmente è 3128 o 8128 a seconda che si usi squid o
  123.90 +       dansguardian. Questo è utile solo in caso di proxy trasparente (non
  123.91 +       raccomandato nelle scuole). 
  123.92 +
  123.93 +       Nel caso di proxy non trasparente non è sufficiente a fare funzionare
  123.94 +       il proxy ma è sufficiente a bloccare il traffico sulla 80.
  123.95 +
  123.96 +
  123.97 +
  123.98 +principi funzionamento fw.add
  123.99 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 123.100 +
 123.101 +
 123.102 +Il principio di funzionamento di ``fw.add`` è invece particolarmente adatto
 123.103 +quando ci siano (molte) configurazioni aggiuntive, combinazioni di ip e porte
 123.104 +che vogliamo filtrare o nattare. In questo caso ``pyrewall`` permette
 123.105 +sintassi molto succinte per un utilizzo efficace di un programma che fa il
 123.106 +prodotto cartesiano [1]_ delle variabili.
 123.107 +
 123.108 +Configurazione di *pyrewall* per FileServer ISI
 123.109 +-----------------------------------------------
 123.110 +
 123.111 +.. figure:: ../../img/rete-srvisi.png
 123.112 +   :align: center
 123.113 +   :width: 400
 123.114 +
 123.115 +   caso firewall separato dal server
 123.116 +   
 123.117 +   
 123.118 +Presupponendo che la rete sia protetta a monte da un firewall e che si stia
 123.119 +utilizzando una sola interfaccia di rete eth0, impostiamo l'interfaccia
 123.120 +``eth0``  come interfaccia interna, modificando ``/etc/argo/fw.conf`` come
 123.121 +segue::
 123.122 +
 123.123 +    INT="eth0"
 123.124 +    #EXT="eth1"
 123.125 +    TCP_DPORTS="22"
 123.126 +
 123.127 +*Nota*: Si è commentata la linea relativa alla seconda interfaccia, in
 123.128 + quanto non presente.
 123.129 +
 123.130 +Per appplicare le modifiche appena effettuate, sarà necessario riavviare
 123.131 +*pyrewall*::
 123.132 +
 123.133 +    argo:~# pyrewall restart
 123.134 +
 123.135 +Configurazione di *pyrewall* per un Firewall ISI
 123.136 +------------------------------------------------
 123.137 +
 123.138 +.. figure:: ../../img/rete-fwisi.png
 123.139 +   :align: center
 123.140 +
 123.141 +Presupponendo che il Firewall ISI abbia due interfacce di rete *eth0* ed
 123.142 +*eth1*, *eth1* collegata direttamente al gateway ADSL ed *eth1* l'altra ad
 123.143 +uno switch, in contatto dunque con il resto della LAN interna, imposteremo
 123.144 +il *firewall* affinchè consideri l'interfaccia *eth0* interna e
 123.145 +l'interfaccia *eth1* esterna, modificando ``/etc/argo/fw.conf`` come segue::
 123.146 +
 123.147 +    INT="eth0"
 123.148 +    EXT="eth1"
 123.149 +    TCP_DPORTS="22"
 123.150 +
 123.151 +Nota: In questo caso la direttiva "EXT" è ovviamente necessaria.
 123.152 +
 123.153 +Per appplicare le modifiche appena effettuate, sarà necessario riavviare 
 123.154 +*pyrewall*::
 123.155 +
 123.156 +    argo:~# pyrewall restart
 123.157 +
 123.158 +-------------
 123.159 +
 123.160 +.. _gibraltar: http://www.gibraltar.at
 123.161 +
 123.162 +.. [1]
 123.163 +  prodotto cartesiano di due insiemi A e B è l'insieme delle coppie ordinate 
 123.164 +  (a,b) con a in A e b in B. Si pensi a questo esempio dove il comando mex
 123.165 +  opera il prodotto cartesiano fra l'insieme SRC e l'insieme DST::
 123.166 +
 123.167 +     SRC="192.168.1.1 192.168.1.2"
 123.168 +     DST="10.10.1.1 10.10.1.2"
 123.169 +     mex iptables -A FORAWRD -s $SRC -d $DST -j ACCEPT
 123.170 +      
 123.171 +     iptables -A FORAWRD -s 192.168.1.1 -d 10.10.1.1 -j ACCEPT
 123.172 +     iptables -A FORAWRD -s 192.168.1.2 -d 10.10.1.1 -j ACCEPT
 123.173 +     iptables -A FORAWRD -s 192.168.1.1 -d 10.10.1.2 -j ACCEPT
 123.174 +     iptables -A FORAWRD -s 192.168.1.2 -d 10.10.1.2 -j ACCEPT
 123.175 +
 123.176 +
   124.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   124.2 +++ b/docs/install/servizi/ftp.rst	Mon Apr 26 11:16:23 2010 +0200
   124.3 @@ -0,0 +1,62 @@
   124.4 +Proftpd
   124.5 +=======
   124.6 +
   124.7 +
   124.8 +Ftp-proxy
   124.9 +=========
  124.10 +
  124.11 +Cos'è?
  124.12 +------
  124.13 +
  124.14 +*Citando la man page*...
  124.15 +
  124.16 +FTP-Proxy  acts  as  an  application level gateway between FTP clients and servers.
  124.17 +Its main purpose is to secure local FTP servers against possibly insecure clients 
  124.18 +or malicious attacks.  FTP-Proxy  is  believed  to  be  immune against current 
  124.19 +known attacks based on the FTP protocol.
  124.20 +
  124.21 +FTP-Proxy  can be started from the inetd (or xinetd, or any other) internet super
  124.22 +daemon or executed on its own as a standalone daemon, in which case it will fork
  124.23 +child processes to handle connections.  The behaviour  depends  on the
  124.24 +ftp-proxy.conf(5) configuration option ServerType or the -i and -d command line
  124.25 +switches, where the latter two take precedence.
  124.26 +
  124.27 +FTP-Proxy features a rich set of auditing and command restriction capabilities 
  124.28 +and  is  specifically  suited  for deployment in firewall environments.
  124.29 +
  124.30 +
  124.31 +Installazione
  124.32 +-------------
  124.33 +
  124.34 +L'installazione è molto semplice e si riduce al solo::
  124.35 +
  124.36 +    apt-get install ftp-proxy
  124.37 +
  124.38 +Configurazione
  124.39 +--------------
  124.40 +
  124.41 +Modificare con il proprio editor di testo preferito ``/etc/proxy-suite/ftp-proxy.conf``
  124.42 +impostando le seguenti direttive:
  124.43 +
  124.44 +- DestinationAddress ( Indirizzo del servente FTP )
  124.45 +- DestinationPort ( Porta del servente FTP )
  124.46 +- ServerType ( modalità di avvio del servizio )
  124.47 +
  124.48 +``ftp-proxy`` supporta numerose opzioni. E', ad esempio, possibile imporre la
  124.49 +modalità Attiva / Passiva che, di default, viene scelta in base alla richiesta dei
  124.50 +client.
  124.51 +
  124.52 +Verifica della configurazione
  124.53 +-----------------------------
  124.54 +
  124.55 +E' possibile verificare la propria configurazione del servizio grazie al comando
  124.56 +``ftp-proxy -c``.
  124.57 +    
  124.58 +L'output restituito dovrebbe rispecchiare quello che segue di esempio ::
  124.59 +
  124.60 +    Config-File: '/etc/proxy-suite/ftp-proxy.conf'
  124.61 +    Config-Section ------ '(-global-)'
  124.62 +    Config:        DestinationAddress       = '192.168.1.253'
  124.63 +    Config:        DestinationPort          = '21'
  124.64 +    Config:        ServerType               = 'standalone'
  124.65 +
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/docs/install/servizi/nfs.rst	Mon Apr 26 11:16:23 2010 +0200
   125.3 @@ -0,0 +1,159 @@
   125.4 +.. _config_nfs:
   125.5 +
   125.6 +=====
   125.7 + NFS
   125.8 +=====
   125.9 +
  125.10 +Lato Server
  125.11 +===========
  125.12 +
  125.13 +Il protocollo NFS consente di condividere il contenuto di intere directory
  125.14 +tra macchine Linux/Unix. Tali risorse condivise, potranno essere *esportate*
  125.15 +dalla macchina server e *montate* dai client desiderati.
  125.16 +
  125.17 +Come si può immaginare, l'utilizzo di NFS, è fondamentale in un contesto come 
  125.18 +quello di ReteISI, dove si vuole che i file degli utenti restino ospitati
  125.19 +dal server di dominio. Ciò verrà garantito imponendo che la ``/home`` dei singoli
  125.20 +client coincida con la ``/home`` esportata dal server.
  125.21 +
  125.22 +Installazione dei pacchetti necessari::
  125.23 +
  125.24 + apt-get install nfs-common nfs-kernel-server
  125.25 +
  125.26 +Alla domanda "Should portmap be bound to the loopback address?" Scegliere 
  125.27 +No (default) a meno che non vi siano particolari esigenze.
  125.28 +
  125.29 +Le singole macchine, od i network, a cui verrà esportato il fileserver andranno
  125.30 +inserite in ``/etc/exports``.
  125.31 +Modificare dunque tale file aggiungendo una linea come la seguente::
  125.32 + 
  125.33 +  /home   192.168.1.0/255.255.255.0(rw,no_root_squash)
  125.34 +
  125.35 +*Nota:*
  125.36 +192.168.1.0 è il network in cui risulterà visibile la risorsa ``/home`` esportata.
  125.37 + 
  125.38 +Sarà possibile elencare le esportazioni attive grazie al comando ``showmount`` ::
  125.39 +
  125.40 + srv-isi:~# showmount --all
  125.41 + All mount points on srv-isi:
  125.42 + 192.168.1.0/255.255.255.0:/home
  125.43 + 192.168.1.230:192.168.1.0/255.255.255.0
  125.44 +
  125.45 +
  125.46 +Lato Client (ubuntu 7.10)
  125.47 +=========================
  125.48 +
  125.49 +Montare una directory esportata via nfs in una directory locale non-vuota 
  125.50 +impedirà l'accesso al contenuto locale preesistente. Tale contenuto tornerà 
  125.51 +accessibile una volta smontata la risorsa.
  125.52 +
  125.53 +utenti solo locali
  125.54 +------------------
  125.55 +
  125.56 +Qualora si desideri mantenere la possibilità di loggarsi anche con utenti
  125.57 +locali, sarà quindi necessario rinominare la ``/home`` locale in ``/home_local`` e 
  125.58 +si creerà una nuova ``/home`` locale, vuota, in cui montare la ``/home`` remota.
  125.59 +Ovviamente saranno anche da aggiornare in ``/etc/passwd`` i percorsi delle 
  125.60 +home-utente, portandoli da ``/home`` a ``/home_local``::
  125.61 +
  125.62 + root@ubuntu-desktop:~# mv /home/ /home_local
  125.63 + root@ubuntu-desktop:~# mkdir /home
  125.64 + root@ubuntu-desktop:~# sed -i 's/home\//home_local\//g' /etc/passwd
  125.65 +
  125.66 +/home
  125.67 +-----
  125.68 +
  125.69 +Si potrà ora procedere con l'installazione del client nfs::
  125.70 + 
  125.71 + root@ubuntu-desktop:~# sudo apt-get install nfs-common
  125.72 +
  125.73 +e la modifica di ``/etc/fstab``, al quale andrà aggiunta la seguente direttiva ::
  125.74 +
  125.75 + srv-isi:/home   /home nfs defaults,soft,rw,auto 0 2
  125.76 +
  125.77 +*Dove:*
  125.78 + "srv-isi" è l'hostname (ci si assicuri che tale nome sia presente in ``/etc/hosts``)
  125.79 + della macchina che esporta risorse nfs.
  125.80 + "/home" che segue i due punti la da essa risorsa esportata.
  125.81 + il secondo "/home" è il punto locale in cui verrà montata la risorsa remota.
  125.82 +
  125.83 +*Nota:*
  125.84 +Ci si assicuri che il file ``/etc/fstab`` sia terminato con un "a capo".
  125.85 +
  125.86 +NFS con automount
  125.87 +=================
  125.88 +
  125.89 +NFS può essere associato ad ``autofs`` per ottenere il mount al volo della cartella esportata a seconda dell'utente che effettua il login
  125.90 +
  125.91 +Lato server
  125.92 +-----------
  125.93 +Non c'è differenza rispetto a quanto detto in precedenza, viene però mostrato il contenuto
  125.94 +di ``/etc/exports`` nel caso della struttura di cartelle ReteIsi e in modo che le stesse possano
  125.95 +essere raggiunte da più sottoreti (si osservino ip e ipmask)::
  125.96 +
  125.97 +    /home/users/admins      192.168.0.0/255.255.0.0(rw,sync)
  125.98 +    /home/users/alunni      192.168.0.0/255.255.0.0(rw,sync)
  125.99 +    /home/users/ata         192.168.0.0/255.255.0.0(rw,sync)
 125.100 +    /home/users/docenti     192.168.0.0/255.255.0.0(rw,sync)
 125.101 +    /home/users/esterni     192.168.0.0/255.255.0.0(rw,sync)
 125.102 +    /home/shares/classi     192.168.0.0/255.255.0.0(rw,sync)
 125.103 +
 125.104 +Lato client
 125.105 +-----------
 125.106 +Installazione dei pacchetti necessari::
 125.107 +
 125.108 + apt-get install portmap nfs-common autofs
 125.109 +
 125.110 +Verranno generati in /etc due file di configurazione il cui contenuto potrà essere il seguente (nel caso si vogliano esportare solo le radici delle home di ciascun gruppo principale):
 125.111 +
 125.112 +``/etc/auto.master``
 125.113 +::
 125.114 +
 125.115 +    /home/users/alunni      /etc/auto.home_alunni
 125.116 +    /home/users/admins      /etc/auto.home_admins
 125.117 +    /home/users/ata         /etc/auto.home_ata
 125.118 +    /home/users/docenti     /etc/auto.home_docenti
 125.119 +    /home/users/esterni     /etc/auto.home_esterni
 125.120 +    /home/shares/classi     /etc/auto.classi
 125.121 +
 125.122 +``/etc/auto.misc``
 125.123 +::
 125.124 +
 125.125 +    lasciare invariato
 125.126 +
 125.127 +occorrerà poi creare i seguenti altri file di configurazione, uno per ogni cartella esportata (SERVER è l'ip o il namehost della macchina che esporta)
 125.128 +
 125.129 +``/etc/auto.classi``
 125.130 +::
 125.131 +
 125.132 +    *  -fstype=nfs,soft,intr,rsize=32768,wsize=32768  SERVER:/home/shares/classi/&
 125.133 +
 125.134 +``/etc/auto.home_admins``
 125.135 +::
 125.136 +
 125.137 +    *  -fstype=nfs,soft,intr,rsize=32768,wsize=32768   SERVER:/home/users/admins/&
 125.138 +
 125.139 +``/etc/auto.home_alunni``
 125.140 +::
 125.141 +
 125.142 +    *   -fstype=nfs,soft,intr,rsize=32768,wsize=32768   SERVER:/home/users/alunni/&
 125.143 +
 125.144 +``/etc/auto.home_ata``
 125.145 +::
 125.146 +
 125.147 +    *-fstype=nfs,soft,intr,rsize=32768,wsize=32768   SERVER:/home/users/alunni/&
 125.148 +
 125.149 +``/etc/auto.home_docenti``
 125.150 +::
 125.151 +    
 125.152 +    *  -fstype=nfs,soft,intr,rsize=32768,wsize=32768   SERVER:/home/users/docenti/&
 125.153 +
 125.154 +``/etc/auto.home_esterni``
 125.155 +::
 125.156 +    
 125.157 +    *-fstype=nfs,soft,intr,rsize=32768,wsize=32768   SERVER:/home/users/esterni/&
 125.158 +
 125.159 +Per far funzionare il tutto basterà a questo punto fa ripartire il servizio autofs
 125.160 +::
 125.161 +    
 125.162 +    /etc/init.d/autofs restart
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/docs/install/servizi/pdc.rst	Mon Apr 26 11:16:23 2010 +0200
   126.3 @@ -0,0 +1,99 @@
   126.4 +.. _config_pdc:   
   126.5 +
   126.6 +Dominio PDC
   126.7 +===========
   126.8 +
   126.9 +Configurazione del dominio: isi-startup
  126.10 +---------------------------------------
  126.11 +
  126.12 +Per configurare l'intero dominio, basterà lanciare il comando::
  126.13 +
  126.14 +   isi-startup <NOMEDOMINIO> <nomenetbios> <password>
  126.15 +
  126.16 +Per semplicità, si suggerisce di utilzzare il nome del proprio istituto 
  126.17 +scolastico come *nome di DOMINIO* e, come *nome netbios*, il nome dell'istituto
  126.18 +preceduto da "srv-", scritto in minuscolo.
  126.19 +
  126.20 +Esempio:
  126.21 +
  126.22 ++ *nome dominio: SCUOLAX*
  126.23 +
  126.24 ++ *nome server: srv-scuolax*
  126.25 +
  126.26 +La password da specificare sarà quella che verrà assegnata 
  126.27 +
  126.28 +  * all'utente root
  126.29 +  * all'admin di slapd
  126.30 +  * all'utente administrator con il quale potremo fare il join dei
  126.31 +    client windows
  126.32 +
  126.33 +Si proceda dunque come segue::
  126.34 +
  126.35 +    argo:~# isi-startup SCUOLAX srv-scuolax segreto
  126.36 +    check_syntax
  126.37 +    read_conf
  126.38 +    SID per ISI-DOMAIN: S-1-5-21-4285446429-3958797296-3242910830
  126.39 +    reset_secrets
  126.40 +    Setting stored password for "cn=admin,dc=isi,dc=lan" in secrets.tdb
  126.41 +    fix_DOMAIN_name
  126.42 +    fix_PDC_name
  126.43 +    get_set_new_SID
  126.44 +    Esiste un SID memorizzato. Vuoi usare questo (s/n)? N
  126.45 +    NUOVO SID: S-1-5-21-4285446429-3958797296-3242910830
  126.46 +    NEW SID: S-1-5-21-4285446429-3958797296-3242910830
  126.47 +    change_password
  126.48 +    sistema
  126.49 +    smbtools
  126.50 +    ldap
  126.51 +    ldapmodify -x -h 127.0.0.1 -w isi -D cn=admin,dc=isi,dc=lan
  126.52 +    modifying entry "cn=admin,dc=isi,dc=lan"
  126.53 +
  126.54 +    smbpasswd
  126.55 +    Setting stored password for "cn=admin,dc=isi,dc=lan" in secrets.tdb
  126.56 +    root samba
  126.57 +    ldap.secret libnss-ldap.secret pam_ldap.secret
  126.58 +    reimposto pwd
  126.59 +    fix_SID_in_ldap
  126.60 +    fix_SID_in_smbldap_tools
  126.61 +    add_samba_at_boot
  126.62 +    samba already in /etc/runlevel.conf: No change.
  126.63 +    start_samba
  126.64 +    Stopping Samba daemons: nmbd smbd.
  126.65 +    Samba spento
  126.66 +    Starting Samba daemons: nmbd smbd.
  126.67 +    Nuovo pid di samba 6161 6155, nmbd: 6153
  126.68 +    fix_LDAP_sambaDomainName
  126.69 +    ldapsearch -x -LLL -xD cn=admin,dc=isi,dc=lan -w segreto (sambaDomainName=SCUOLAX)
  126.70 +    modifying entry "sambaDomainName=SCUOLAX,dc=isi,dc=lan"
  126.71 +
  126.72 +    ----------------------prima-----
  126.73 +    dn: sambaDomainName=SCUOLAX,dc=isi,dc=lan
  126.74 +    gidNumber: 1009
  126.75 +    uidNumber: 1000
  126.76 +
  126.77 +    modifying entry "sambaDomainName=SCUOLAX,dc=isi,dc=lan"
  126.78 +
  126.79 +    ----------------------dopo-----
  126.80 +    dn: sambaDomainName=SCUOLAX,dc=isi,dc=lan
  126.81 +    gidNumber: 1009
  126.82 +    uidNumber: 1000
  126.83 +    
  126.84 +Alla domanda *Esiste un SID memorizzato. Vuoi usare questo (s/n)?* si risponda negativamente.
  126.85 +
  126.86 +Il processo di attivazione del dominio è completato. Da questo momento in
  126.87 +poi sarà possibile iniziare ad effettuare il join di tutti i client della
  126.88 +rete. Si suggerisce però, prima di continuare con tale operazione, di
  126.89 +configurare ed attivare il servizio dhcp. In tal modo, tutti i client
  126.90 +verranno istruire automaticamente con le informazioni di rete necessaria,
  126.91 +evitando di dover configurare manualmente ogni client.
  126.92 +
  126.93 +.. Note ::
  126.94 +
  126.95 +    Per join_ ci si riferisce all'operazione che permette di associare
  126.96 +    client Microsoft (Xp Professional o windows2000) al Dominio appena
  126.97 +    creato. Le W98 non contemplano questa operazione
  126.98 +
  126.99 +
 126.100 +
 126.101 +.. _join: ../client_microsoft.html
 126.102 +
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/docs/install/servizi/sarg-report.rst	Mon Apr 26 11:16:23 2010 +0200
   127.3 @@ -0,0 +1,132 @@
   127.4 +====================
   127.5 + LOG e reportistica
   127.6 +====================
   127.7 +
   127.8 +LOG SQUID con SARG-REPORT
   127.9 +==========================
  127.10 +
  127.11 +Configurazione di sarg
  127.12 +-----------------------
  127.13 +
  127.14 +Cercare in ``/etc/squid/sarg.conf`` la direttiva ``language English`` e sostituire
  127.15 +a ``English`` il linguaggio voluto.
  127.16 +es.::
  127.17 +
  127.18 +    language Italian
  127.19 +
  127.20 +Assicurarsi che la direttiva ``access_log`` punti correttamente al file contenente
  127.21 +i logs di squid (solitamente ``/var/log/squid/access.log``) e verificare che
  127.22 +coincida con la direttiva ``access_log`` presente in ``/etc/squid.conf``.
  127.23 +
  127.24 +Per eventuali affinamenti alla configurazione si potrà fare riferimento ai numerosi
  127.25 +esempi commentati nel file di configurazione.
  127.26 +
  127.27 +.. _sarg-report:
  127.28 +
  127.29 +Configurazione di sarg-reports
  127.30 +------------------------------
  127.31 +
  127.32 +La configurazione di ``/etc/squid/sarg-reports.conf`` di default dovrebbe andare
  127.33 +benone, modificarla eventualmente per rispondere alle proprie esigenze.
  127.34 +
  127.35 +
  127.36 +sarg e sarg-reports
  127.37 +-------------------
  127.38 +
  127.39 +``sarg-report`` è un shell script che permette di parsare il contenuto dei logs di
  127.40 +squid relativi ad un certo periodo di tempo e, utilizzando ``sarg``,  generare 
  127.41 +automaticamente del codice html. Il codice html, di default, viene salvato in 
  127.42 +``/var/www/https/squid-reports/``. Sarà necessario dunque modificare la configurazione
  127.43 +di apache per assicurarsi che venga pubblicata.
  127.44 +
  127.45 +Nota
  127.46 +----
  127.47 +
  127.48 +Si farà riferimento esclusivamente all'uso di ``sarg-report``.
  127.49 +I più curiosi, dopo una rapida consultazione del suo help, potranno provare a generare
  127.50 +con ``sarg`` qualche statistica personalizzata.
  127.51 +
  127.52 +L'help di sarg-reports è abbastanza esplicativo::
  127.53 +
  127.54 +    sarg-reports --help
  127.55 +    
  127.56 +    SARG - Daily / Weekly / Monthly - Squid proxy usage reports creation tool
  127.57 +    Written by Ugo Viti <[email protected]>
  127.58 +    Version: 20050202
  127.59 +
  127.60 +    Usage: /usr/sbin/sarg-reports [OPTIONS]
  127.61 +
  127.62 +    Allowed options:
  127.63 +        manual,  Create Manual report
  127.64 +         today,  Create Today report
  127.65 +         daily,  Create Daily report
  127.66 +        weekly,  Create Weekly report
  127.67 +        montly,  Create Monthly report
  127.68 +
  127.69 +Come riportato dall'help, se volessimo generare logs per una data specifica potremmo
  127.70 +usare::
  127.71 +
  127.72 +    sarg-reports manual 18/12/2021
  127.73 +
  127.74 +Tutte le informazioni relative al giorno 18/12/2021 trovate in ``/var/log/squid/access.log``
  127.75 +verranno parsate e verrà generato un output html in ``/vaar/www/squid-reports/``
  127.76 +
  127.77 +Per verificare il risultato, si potrà provare a puntare con ``lynx`` a 
  127.78 +``/var/www/squid-reports/index.html`` come segue::
  127.79 +
  127.80 +    lynx /var/www/squid-reports/index.html
  127.81 +
  127.82 +
  127.83 +Automatizzare la creazione dei logs con Crontab
  127.84 +-----------------------------------------------
  127.85 +
  127.86 +Aggiungere la creazione dei logs a Cron, per eseguirle in modo automatico alla
  127.87 +cadenza voluta::
  127.88 +
  127.89 +    crontab -e
  127.90 +
  127.91 +    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
  127.92 +    00 00      * * * sarg-reports daily
  127.93 +    00 01      * * 1 sarg-reports weekly 
  127.94 +    30 02      1 * * sarg-reports monthly
  127.95 +
  127.96 +Per chi non conoscesse Cron e la sintassi di definizione del tempo:
  127.97 +http://www.adminschoice.com/docs/crontab.htm#Crontab%20file
  127.98 +
  127.99 +
 127.100 +
 127.101 +Dglog
 127.102 +=====
 127.103 +
 127.104 +cos'è
 127.105 +-----
 127.106 +dglog  è un utilissimo perl-script che permette di analizzare comodamente i logs
 127.107 +generati da ``dansguardian``. Con questo  utile strumento sarà possibile, ad 
 127.108 +esempio, elencare tutti i contenuti web negati/permessi ad un particolare utente.
 127.109 +
 127.110 +
 127.111 +Configurazione dglog
 127.112 +--------------------
 127.113 +
 127.114 +Creare il file di configurazione
 127.115 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 127.116 +::
 127.117 +
 127.118 +    cd /etc/isi
 127.119 +    cp dglog.conf.pl.sample dglog.conf.pl
 127.120 +
 127.121 +Rendere eseguibile il cgi-script "dglog.pl"
 127.122 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 127.123 +::
 127.124 +
 127.125 +    chmod +x /usr/lib/cgi-bin/dglog/dglog.pl
 127.126 +
 127.127 +
 127.128 +Verifica
 127.129 +~~~~~~~~
 127.130 +
 127.131 +Per una rapida verifica basterà puntare con il proprio browser al seguente URL:
 127.132 +
 127.133 +http://<IP SERVER>/cgi-bin/dglog/dglog.pl
 127.134 +
 127.135 +
   128.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   128.2 +++ b/docs/install/servizi/squid_dans.rst	Mon Apr 26 11:16:23 2010 +0200
   128.3 @@ -0,0 +1,253 @@
   128.4 +.. _config_squid_dans:
   128.5 +
   128.6 +======================
   128.7 + Squid & Dansguardian
   128.8 +======================
   128.9 +
  128.10 +Squid
  128.11 +=====
  128.12 +
  128.13 +Modificare ``/etc/squid/squid.conf``::
  128.14 +
  128.15 +    visible_hostname srv-scuolax
  128.16 +
  128.17 +    auth_param basic program /usr/lib/squid/ldap_auth -v 3 -b ou=People,dc=isi,dc=lan srv-scuolax
  128.18 +
  128.19 +    external_acl_type ldap_group %LOGIN  /usr/lib/squid/squid_ldap_group \
  128.20 +    -v 3 -b ou=Groups,dc=isi,dc=lan -B ou=People,dc=isi,dc=lan  -f \
  128.21 +    "(&(memberUid=%v)(objectClass=posixGroup)(cn=%g))"  srv-scuolax 
  128.22 +
  128.23 +Assicurarsi inoltre che le seguenti direttive siano presenti::
  128.24 +
  128.25 +    http_port 3128
  128.26 +    access_log /var/log/squid/access.log
  128.27 +
  128.28 +La seconda direttiva, è indispensabile se si intende utilizzare un
  128.29 +analizzatore dei logs come "Sarg", già incluso nella distribuzione..
  128.30 +
  128.31 +Dans Guardian
  128.32 +=============
  128.33 +
  128.34 +Le modifiche da apportare al fine di configurazione
  128.35 +``/etc/dansguardian/dansguardian.conf`` sono modeste::
  128.36 +
  128.37 +    language = 'italian'
  128.38 +    # the port that DansGuardian listens to. 
  128.39 +    filterport = 8128
  128.40 +     
  128.41 +    # the ip of the proxy (default is the loopback - i.e. this server)
  128.42 +    proxyip = 127.0.0.1
  128.43 +      
  128.44 +    # the port DansGuardian connects to proxy on
  128.45 +    proxyport = 3128
  128.46 +
  128.47 +    # accessdeniedaddress is the address of your web server to which the cgi
  128.48 +    # dansguardian reporting script was copied
  128.49 +    # Do NOT change from the default if you are not using the cgi.
  128.50 +    #
  128.51 +    accessdeniedaddress = 'http://localhost/cgi-bin/dansguardian.pl'
  128.52 +
  128.53 +è inoltre possibile, non indispensabile, attivare il filtro antivirus. Nella
  128.54 +distribuzione si troverà già incluso il supporto per ClamAV.
  128.55 +
  128.56 +::
  128.57 +
  128.58 +    virusscan = on
  128.59 +      
  128.60 +    # OPTION: virusengine
  128.61 +    # Set the embedded virus scan engine to be used
  128.62 +    virusengine = 'clamav'
  128.63 +
  128.64 +Si può dunque scegliere di disattivare la feature impostando la direttiva
  128.65 +
  128.66 +::
  128.67 +
  128.68 +    virusscan = off
  128.69 +
  128.70 +Prima di attivare DansGuardian, come si evince dal suo contenuto, è
  128.71 +indispensabile rimuovere la seguente riga (localizzata di solito ad inizio
  128.72 +file)::
  128.73 +
  128.74 +    UNCONFIGURED - Please remove this line after configuration
  128.75 +
  128.76 +Chi volesse modificare le varie tipologie di filtraggio, troverà
  128.77 +indispensabile il file ``/etc/dansguardian/dansguardianf1.conf``
  128.78 +
  128.79 +Per ulteriori informazioni su dansguardian e le tipologie di filtraggio:
  128.80 +http://dansguardian.org/
  128.81 +
  128.82 +.. sidebar: Nota
  128.83 +
  128.84 +  Per installazioni datate potrebbe essere necessario, in caso si desideri
  128.85 +  utilizzare il sistema antivirus, aggiornare il pacchetto clamav all'ultima
  128.86 +  versione. Al fine di tenere sempre aggiornata la propria versione di
  128.87 +  ClamAV, si suggerisce di aggiungere il seguente repository al file
  128.88 +  ``/etc/apt/sources.lst``: ``deb http://ftp2.de.debian.org/debian-volatile sarge/volatile main``
  128.89 +  
  128.90 +
  128.91 +
  128.92 +SARG
  128.93 +====
  128.94 +
  128.95 +Per utilizzare SARG, utile strumento di interpretazione dei logs di accesso
  128.96 +di squid, è *necessario* assicurare la presenza di
  128.97 +``/var/log/squid/access.log``.
  128.98 +
  128.99 +Il file ``/var/log/squid/access.log``, di default assente( o così sembra,
 128.100 +almeno su debian etch) , si può "far generare" aggiungendo al file
 128.101 +*/etc/squid/squid.conf* la seguente direttiva::
 128.102 +
 128.103 +    access_log /var/log/squid/access.log
 128.104 +    
 128.105 +
 128.106 +Grazie a SARG è possibile generare report al momento o semplicemente
 128.107 +consultare quelli generati in automatico, in formato html, in
 128.108 +*/var/www/squid-reports/*.
 128.109 +
 128.110 +Dall'help di sarg-reports ::
 128.111 +
 128.112 +    Usage: /usr/sbin/sarg-reports [OPTIONS]
 128.113 +
 128.114 +    Allowed options:
 128.115 +        manual,  Create Manual report
 128.116 +         today,  Create Today report
 128.117 +         daily,  Create Daily report
 128.118 +        weekly,  Create Weekly report
 128.119 +        montly,  Create Monthly report
 128.120 +
 128.121 +
 128.122 +I logs di SARG, generati con ``sarg-reports`` verranno salvati anch'essi come
 128.123 +codice html, di default, in */var/www/squid-reports*. Tale percorso è
 128.124 +modificabile apportando qualche semplice modifica a
 128.125 +``/etc/squid/sarg-reports.conf``.
 128.126 +
 128.127 +Lo strano bug di /etc/logrotate.d/squid
 128.128 +----------------------------------------
 128.129 +
 128.130 +Con le prime versioni di sarg, prima della rotazione dei log di squid,
 128.131 +veniva invocata giornalmente la script "/usr/sbin/sarg-maint". Tale script è
 128.132 +stata "recentemente" rimpiazzata con "/usr/sbin/sarg-reports". Non è stato
 128.133 +però modificato il riferimento in "/etc/logrotate.d/squid", che punta ancora
 128.134 +all'inesistente vecchia script.
 128.135 +Curiosamente, sembra che ad oggi il bug non sia ancora stato corretto.
 128.136 +
 128.137 +La soluzione al problema
 128.138 +-------------------------------
 128.139 +
 128.140 +E' stato modificato dunque il file "/etc/logrotate.d/squid" affinchè lanci
 128.141 +"/usr/sbin/sarg-reports monthly". 
 128.142 +
 128.143 +/etc/logrotate.d/squid originale ::
 128.144 +
 128.145 +    #
 128.146 +    #       Logrotate fragment for squid.
 128.147 +    #
 128.148 +    /var/log/squid/*.log {
 128.149 +            daily
 128.150 +            compress
 128.151 +            delaycompress
 128.152 +            rotate 1000
 128.153 +            missingok
 128.154 +            nocreate
 128.155 +            sharedscripts
 128.156 +            prerotate
 128.157 +                    test ! -x /usr/sbin/sarg-maint || /usr/sbin/sarg-maint
 128.158 +            endscript 
 128.159 +            postrotate
 128.160 +                    test ! -e /var/run/squid.pid || /usr/sbin/squid -k rotate
 128.161 +            endscript
 128.162 +    }
 128.163 +
 128.164 +/etc/logrotate.d/squid modificato ::
 128.165 +
 128.166 +    #
 128.167 +    #       Logrotate fragment for squid.
 128.168 +    #
 128.169 +    /var/log/squid/*.log {
 128.170 +            monthly
 128.171 +            compress
 128.172 +            delaycompress
 128.173 +            rotate 1000
 128.174 +            missingok
 128.175 +            nocreate
 128.176 +            sharedscripts
 128.177 +            prerotate
 128.178 +                    test ! -x /usr/sbin/sarg-reports || /usr/sbin/sarg-reports monthly
 128.179 +            endscript 
 128.180 +            postrotate
 128.181 +                    test ! -e /var/run/squid.pid || /usr/sbin/squid -k rotate
 128.182 +            endscript
 128.183 +    }
 128.184 +
 128.185 +Ed è stato riavviato il servizio "/etc/init.d/cron" ::
 128.186 +
 128.187 +    /etc/init.d/cron restart
 128.188 +
 128.189 +Generazione dei report schedulata tramite crontab
 128.190 +--------------------------------------------------------
 128.191 +
 128.192 +La creazione schedulata dei report( giornalieri, settimanali, mensili) viene
 128.193 +garantita dalle seguenti script :: 
 128.194 +
 128.195 +    /etc/cron.daily/sarg
 128.196 +    /etc/cron.weekly/sarg
 128.197 +    /etc/cron.monthly/sarg
 128.198 +
 128.199 +Il cui codice, molto elementare, altro non fa che avviare "sarg-reports" e
 128.200 +passargli il periodo di tempo di cui generare i logs. 
 128.201 +
 128.202 +es. ::
 128.203 +
 128.204 +    /usr/sbin/sarg-reports monthly
 128.205 +
 128.206 +
 128.207 +Assicurarsi che i servizi voluti partiranno al boot
 128.208 +===================================================
 128.209 +
 128.210 +Modificare ``/etc/runlevel.conf`` commentando i servizi che non si intende
 128.211 +far partire al boot e decommentare quelli che si desidera far partire.
 128.212 +
 128.213 +
 128.214 +Configurare i clientXP per passare da squid
 128.215 +===========================================
 128.216 +
 128.217 +Affinchè le macchine XP vengano correttamente configurate, in fase di logon,
 128.218 +per passare attraverso dansguardian, modificare ``/etc/isi/logon.conf``
 128.219 +impostando le seguenti direttive::
 128.220 +
 128.221 +    ### WinSet sezione 'proxy'
 128.222 +    ProxyServer          = 192.168.1.222:8128    # DansGuardian
 128.223 +    ProxyServer[admins]  = 192.168.1.222:3128    # Squid (FW permettendo)
 128.224 +    #ProxyOverride        = www.XXX.XXX,<local>
 128.225 +
 128.226 +
 128.227 +
 128.228 +
 128.229 +.. _apt_squid:
 128.230 +
 128.231 +Configurare apt dei client per passare da squid
 128.232 +===============================================
 128.233 +
 128.234 +Affinchè le macchine debian/ubuntu possano passare il firewall occorre
 128.235 +creare un account apposito ed istruire apt di usare quello per evitare di
 128.236 +essere bloccato dal firewall che blocca appunto la porta 80.
 128.237 +
 128.238 +Apt-get legge un file di configurazione,
 128.239 +
 128.240 +   1. /etc/apt/apt.conf o un qualunque file della directory
 128.241 +   2. etc/apt/apt.conf.d/ 
 128.242 +
 128.243 +E` sufficiente mettere in questo file la istruzione::
 128.244 +
 128.245 +  Acquire::http::Proxy "http://user:pwd@ip_squid_box:3128";
 128.246 +
 128.247 +una scritta alternativa e'::
 128.248 +
 128.249 +  Acquire 
 128.250 +  {
 128.251 +     http 
 128.252 +     {
 128.253 +       Proxy "http://user:pwd@ip_squid_box:3128";
 128.254 +     };
 128.255 +  };
 128.256 +  
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/docs/install/sshd_key.rst	Mon Apr 26 11:16:23 2010 +0200
   129.3 @@ -0,0 +1,281 @@
   129.4 +.. _config_sshd_key:
   129.5 +
   129.6 +=========
   129.7 +Sicurezza
   129.8 +=========
   129.9 +
  129.10 +.. sidebar:: Importante
  129.11 +
  129.12 +   non possiamo lasciare nel cd reteisi il default nel modo più sicuro 
  129.13 +   senza rendere la vita difficile a chi deve caricare le chiavi la
  129.14 +   prima volta.... voi però fatelo!!!
  129.15 +
  129.16 +Nel momento stesso in cui mettete una macchina in internet con alcune porte
  129.17 +aperte sapete per certo che sarà oggetto di ogni possibile attacco. Spesso i
  129.18 +nostri server funzionanao anche da firewall in situazioni "piccole", ovvero
  129.19 +di poche macchine.
  129.20 +
  129.21 +In queste occasioni le fonti più comuni di debolezze sono:
  129.22 +
  129.23 +1. ssh tramite account troppo semplici (password banali)
  129.24 +2. apache tramite applicazioni poso sicure
  129.25 +
  129.26 +per quanto riguarda il primo punto è facile mettere la macchina in sicurezza
  129.27 +con ben poca fatica, tramite l'uso delle chiavi crittografiche. 
  129.28 +
  129.29 +Accedere al server tramite SSH usando le chiavi
  129.30 +===============================================
  129.31 +
  129.32 +Accedere remotamente al proprio server mediante l'utilizzo delle chiavi
  129.33 +crittografiche aumenta la sicurezza del proprio server, rendendo inutile,
  129.34 +ad esempio, la quasi totalità dei tipi di attacco di tipo `dizionario` o
  129.35 +`brute force`.
  129.36 +
  129.37 +Per le delucidazioni circa il concetto di "chiave di criptazione" si rimanda
  129.38 +al seguente indirizzo:
  129.39 +http://it.wikipedia.org/wiki/Crittografia_asimmetrica
  129.40 +
  129.41 +
  129.42 +Configurazione del server OpenSSH
  129.43 +---------------------------------
  129.44 +
  129.45 +Senza dilungarci troppo in trattazioni sulla sicurezza, si suggerisce l'adozione
  129.46 +dei seguenti accorgimenti, considerati ragionevole compromesso tra "paranoia" e
  129.47 +usabilità.
  129.48 +
  129.49 +- disattivazione dell'accesso tramite password.
  129.50 +- attivazione dell'accesso esclusivamente tramite chiavi.
  129.51 +- disattivazione dell'accesso diretto al sistema da parte di root ( sarà comunque
  129.52 +  accessibile grazie al comando ``su -`` ).
  129.53 +
  129.54 +Per ottenere tutto ciò, sarà sufficiente assicurarsi che le direttive del proprio
  129.55 +``/etc/ssh/sshd.conf`` siano così configurate::
  129.56 +
  129.57 +    PasswordAuthentication no
  129.58 +    PubkeyAuthentication yes
  129.59 +    ChallengeResponseAuthentication no
  129.60 +    PermitRootLogin no
  129.61 +
  129.62 +Per i più curiosi, viene riportata di seguito una configurazione integrale del file
  129.63 +``/etc/ssh/sshd.conf``::
  129.64 +
  129.65 +    Port 22
  129.66 +    Protocol 2
  129.67 +    HostKey /etc/ssh/ssh_host_rsa_key
  129.68 +    HostKey /etc/ssh/ssh_host_dsa_key
  129.69 +    UsePrivilegeSeparation yes
  129.70 +
  129.71 +    # Lifetime and size of ephemeral version 1 server key
  129.72 +    KeyRegenerationInterval 3600
  129.73 +    ServerKeyBits 768
  129.74 +
  129.75 +    # Logging
  129.76 +    SyslogFacility AUTH
  129.77 +    LogLevel INFO
  129.78 +
  129.79 +    # Authentication:
  129.80 +    LoginGraceTime 120s
  129.81 +    PermitRootLogin no
  129.82 +    StrictModes yes
  129.83 +    MaxAuthTries 4
  129.84 +
  129.85 +    #RSAAuthentication no
  129.86 +    PubkeyAuthentication yes
  129.87 +    #AuthorizedKeysFile     %h/.ssh/authorized_keys
  129.88 +
  129.89 +    # Don't read the user's ~/.rhosts and ~/.shosts files
  129.90 +    IgnoreRhosts yes
  129.91 +    # For this to work you will also need host keys in /etc/ssh_known_hosts
  129.92 +    RhostsRSAAuthentication no
  129.93 +    # similar for protocol version 2
  129.94 +
  129.95 +    HostbasedAuthentication no
  129.96 +    # Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
  129.97 +    #IgnoreUserKnownHosts yes
  129.98 +
  129.99 +    # To enable empty passwords, change to yes (NOT RECOMMENDED)
 129.100 +    PermitEmptyPasswords no
 129.101 +
 129.102 +    # Change to yes to enable challenge-response passwords (beware issues with
 129.103 +    # some PAM modules and threads)
 129.104 +    ChallengeResponseAuthentication no
 129.105 +
 129.106 +    # Change to no to disable tunnelled clear text passwords
 129.107 +    PasswordAuthentication no
 129.108 +
 129.109 +    X11DisplayOffset 10
 129.110 +    PrintMotd no
 129.111 +    PrintLastLog yes
 129.112 +    TCPKeepAlive yes
 129.113 +
 129.114 +    AcceptEnv LANG LC_*
 129.115 +
 129.116 +    Subsystem sftp /usr/lib/openssh/sftp-server
 129.117 +
 129.118 +    UsePAM yes
 129.119 +
 129.120 +    #l'utente "utente1" si puo' loggare solo da qualunque indirizzo
 129.121 +    #AllowUsers utente1@*
 129.122 +
 129.123 +    #l'utente "utente2" si puo' loggare solo da tutte le postazioni del network
 129.124 +    #192.168.0.0 :
 129.125 +    #[email protected].*
 129.126 +
 129.127 +    #Solo "utente1" potrà collegarsi a ssh. Questa direttiva escluderà tutti gli 
 129.128 +    #altri
 129.129 +    #AllowUsers utente1
 129.130 +     
 129.131 +    #Per creare un utente guest "localuser" con una password nota a tutti ma
 129.132 +    #impedirne l'accesso via ssh da remoto:
 129.133 +    #DenyUsers localuser
 129.134 +
 129.135 +.. Note::
 129.136 +
 129.137 +    Le ultime righe commentate, potranno tornare utili a chi vorrà limitare 
 129.138 +    ulteriormente i propri accessi.
 129.139 +
 129.140 +
 129.141 +Generazione ed aggiunta delle chiavi utente sul server
 129.142 +------------------------------------------------------
 129.143 +
 129.144 +1. Autenticarsi con il proprio utente per generare la coppia di chiavi pubblica/privata::
 129.145 +
 129.146 +    utente1@srv-isi:~$ ssh-keygen -t dsa
 129.147 +    Generating public/private dsa key pair.
 129.148 +    
 129.149 +    Enter file in which to save the key (~utente1/.ssh/id_dsa):   
 129.150 +    <INVIO>
 129.151 +    Created directory '~utente1/.ssh'.
 129.152 +    
 129.153 +    Enter passphrase (empty for no passphrase): <PASSWORD PER LA CHIAVE>
 129.154 +    Enter same passphrase again: <PASSWORD PER LA CHIAVE>
 129.155 +    
 129.156 +    Your identification has been saved in ~utente1/.ssh/id_dsa.
 129.157 +    Your public key has been saved in /home/users/admins/utente1/.ssh/id_dsa.pub.
 129.158 +    The key fingerprint is:
 129.159 +    20:d6:94:95:cf:59:a8:81:f0:e4:1e:98:98:47:54:71 utente1@srv-isi
 129.160 +
 129.161 +    cp .ssh/id_dsa.pub /tmp
 129.162 +    chmod a+r /tmp/id_dsa.pub
 129.163 +    
 129.164 +2. Aggiungere la chiave `pubblica` generata nel file ``authorized_keys`` 
 129.165 +   dell'utente da controllare( utente2)::
 129.166 +    
 129.167 +        su utente2 <PASSWORD utente2>
 129.168 +    
 129.169 +   Ci si assicuri che la directory ``.ssh`` esista::
 129.170 +
 129.171 +        cd
 129.172 +        ls .ssh
 129.173 +        
 129.174 +   Se non dovesse essere presente, si provveda a crearla::
 129.175 +
 129.176 +        mkdir .ssh
 129.177 +
 129.178 +   Sarà ora possibile aggiungere la propria chiave pubblica, precedentemente 
 129.179 +   copiata in /tmp ::
 129.180 +
 129.181 +        cat /tmp/id_dsa.pub >> .ssh/authorized_keys
 129.182 +        
 129.183 +.. Note::
 129.184 +
 129.185 +    Il file ``authorized_keys`` contiene le chiavi pubbliche degli utenti 
 129.186 +    abilitati ad accedere remotamente, via ssh e senza password, all'account 
 129.187 +    dell'utente. Modificando tale file con un editor di testo si potranno 
 129.188 +    rimuovere le chiavi pubbliche aggiunte in precedenza, impedendo alle 
 129.189 +    relative utenze di accedere senza password con il nostro utente.
 129.190 +
 129.191 +3. Testare che tutto funzioni, autenticandosi come `utente1` e cercando 
 129.192 +   con esso di accedere, via ssh, all'account `utente2`::
 129.193 +
 129.194 +    utente1@srv-isi:~$ ssh -l utente2 127.0.0.1
 129.195 +    Enter passphrase for key '/home/users/admins/utente1/.ssh/id_dsa':
 129.196 +    <PASSWORD DELLA CHIAVE PRIVATA> 
 129.197 +    utente2@srv-isi:~$ 
 129.198 +
 129.199 +Utilizzo delle chiavi in ambiente Windows
 129.200 +-----------------------------------------
 129.201 +
 129.202 +In ambiente windows, uno dei client più usati per controllo remoto via
 129.203 +ssh è probabilmente ``Putty``. Esistono diverse pacchettizzazioni di tale
 129.204 +programma, installabili tramite setup o `portabili`.
 129.205 +Si suggerisce di optare per la versione `portabile`, che consente di 
 129.206 +portare putty sempre con sè, magari su chiavetta usb.
 129.207 +
 129.208 +.. Note::
 129.209 +
 129.210 +    La procedura a seguire, tratterà esclusivamente della versione `portabile`.
 129.211 +
 129.212 +Da dove scaricare Putty?
 129.213 +~~~~~~~~~~~~~~~~~~~~~~~~
 129.214 +
 129.215 +le versioni di putty sono liberamente scaricabili dai seguenti indirizzi:
 129.216 +
 129.217 +http://the.earth.li/~sgtatham/putty/latest/x86/putty-0.60-installer.exe
 129.218 +http://the.earth.li/~sgtatham/putty/latest/x86/putty.zip
 129.219 +
 129.220 +Configurazione ed utilizzo di putty
 129.221 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 129.222 +
 129.223 +1. Accedere al dominio autenticandosi con il proprio utente.
 129.224 +
 129.225 +.. image:: ../img/ssh-key/small/0_accessoDominio.jpg
 129.226 +
 129.227 +2. Aprire una cartella qualunque ed attivare la visualizzazione delle 
 129.228 +   "estensioni per i nomi file conosciuti".
 129.229 +
 129.230 +.. image:: ../img/ssh-key/small/1_estensioni1.jpg
 129.231 +
 129.232 +
 129.233 +.. image:: ../img/ssh-key/small/2_estensioni2.jpg
 129.234 +
 129.235 +
 129.236 +2. Scaricare ed estrarre il file ``putty.zip`` e lanciare l'eseguibile ``puttygen.exe``.
 129.237 +
 129.238 +3. Selezionare la voce di menù ``Conversions >> Import key`` ed importare la chiave 
 129.239 +   privata **id_dsa** generata in precedenza sul server.
 129.240 +
 129.241 +.. Note::
 129.242 + 
 129.243 +    La chiave di `utente1` verrà localizzata dai client microsoft in **H:\\.ssh\\id_dsa**
 129.244 +    nella home del relativo utente.
 129.245 +
 129.246 +.. image:: ../img/ssh-key/small/3_import1.jpg
 129.247 +
 129.248 +
 129.249 +.. image:: ../img/ssh-key/small/4_import2.jpg
 129.250 +
 129.251 +
 129.252 +4. Una volta importata la chiave privata in formato Unix, si procederà alla sua 
 129.253 +   conversione nel formato usato da putty, arrivando ad ottenere una chiave 
 129.254 +   privata "id_dsa.ppk".
 129.255 +
 129.256 +.. image:: ../img/ssh-key/small/5_import3.jpg
 129.257 +
 129.258 +
 129.259 +.. image:: ../img/ssh-key/small/6_import4.jpg
 129.260 +
 129.261 +
 129.262 +5. Non resta che configurare putty affinchè utilizzi la nostra chiave appena convertita e si colleghi all'ip del nostro server.
 129.263 +
 129.264 +.. image:: ../img/ssh-key/small/7_putty-addkey1.jpg
 129.265 +
 129.266 +
 129.267 +.. image:: ../img/ssh-key/small/8_putty-addkey2.jpg
 129.268 +
 129.269 +
 129.270 +.. image:: ../img/ssh-key/small/9_putty-connessione1.jpg
 129.271 +
 129.272 +
 129.273 +.. image:: ../img/ssh-key/small/10_putty-connessione2.jpg
 129.274 +
 129.275 +
 129.276 +.. image:: ../img/ssh-key/small/11_putty-connessione3.jpg
 129.277 +
 129.278 +
 129.279 +.. image:: ../img/ssh-key/small/12_putty-connessione4.jpg
 129.280 +
 129.281 +
 129.282 +.. image:: ../img/ssh-key/small/13_putty-connessione5.jpg
 129.283 +
 129.284 +
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/docs/progetto/contents.rst	Mon Apr 26 11:16:23 2010 +0200
   130.3 @@ -0,0 +1,25 @@
   130.4 +.. _reteisi_intro:   
   130.5 +
   130.6 +Il progetto ReteIsi
   130.7 +===================
   130.8 +
   130.9 +ReteIsi, il cui acronimo significa Intranet Scolastiche Integrate, è una
  130.10 +libera associazione di scuole nata per sviluppare una soluzione informatica
  130.11 +open source per reti scolastiche. Lo scopo principale del progetto è
  130.12 +sviluppare una soluzione facile da adottare, in cui le necessità di una
  130.13 +scuola siano state affrontate e possibilmente risolte in modo semplice.
  130.14 +
  130.15 +Il CD di ReteIsi permette di fare funzionare un dominio Windows basato su
  130.16 +samba senza neanche l'installazione con soli pochi comandi. Questo dominio
  130.17 +serve in realtà solo per demo ma è una prova efficace della facilità di
  130.18 +utilizzo. Le macchine Windows potranno fare un join, le macchine linux
  130.19 +possono decidere di delegare a questo sistema l'autenticazione.
  130.20 +
  130.21 +.. toctree::
  130.22 +   :maxdepth: 2
  130.23 +   
  130.24 +   project
  130.25 +   presentazione_tecnica
  130.26 +   devel
  130.27 +   docs
  130.28 +
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/docs/progetto/devel.rst	Mon Apr 26 11:16:23 2010 +0200
   131.3 @@ -0,0 +1,43 @@
   131.4 +.. _reteisi_devel:
   131.5 +
   131.6 +Sviluppo
   131.7 +==========
   131.8 +
   131.9 +Lo sviluppo dell'infrastruttura ISI viene portato avanti principalmente da:
  131.10 +
  131.11 +  * **Sandro Dentella**: consulente del progetto iniziale e principale
  131.12 +    responsabile della architettura nonché della riscrittura delle librerie
  131.13 +    in python. E` anche responsabile della distribuzione Argo_ su cui è
  131.14 +    basata la iso
  131.15 +
  131.16 +  * **Massimo Mancini**: insegnante della scuola capofila e principale
  131.17 +    sviluppatore della fase di logon e di tutte le procedure di estrazione
  131.18 +    dei dati da SISSI. E` anche responsabile della integrazione di applicazioni
  131.19 +    open (PMB, TWiki) nell'ambiente determinato da una rete ISI
  131.20 +
  131.21 +  * **Simone Castellazzi**: valente tester, scopritore di bug e autore di gran
  131.22 +    parte della documentazione.
  131.23 +
  131.24 +
  131.25 +Mailing list
  131.26 +============
  131.27 +
  131.28 +  puoi seguire lo sviluppo, chiedere aiuto e contribuire allo sviluppo sul
  131.29 +  googlegroup: http://reteisi.google.com
  131.30 +
  131.31 +
  131.32 +Sorgenti
  131.33 +========
  131.34 +
  131.35 +Il codice è stato sviluppato nel corso di alcuni anni ed è composto da
  131.36 +script di shell, perl e python. Attualmente tutti i comandi ad eccezione
  131.37 +della fase di login stanno subendo una riscrittura in python_ per renderli
  131.38 +più omogenei. Sono raggiungibili nella forma di repository mercurial al
  131.39 +sito: http://hg.argolinux.org e sono quelli nella cartella isi.
  131.40 +
  131.41 +Vengono poi prodotti pacchetti debian che sono disponibili nel repository::
  131.42 +
  131.43 +  deb http://apt.reteisi.org/ etch isi
  131.44 +
  131.45 +.. _python: http://www.python.org
  131.46 +.. _Argo: http://www.argolinux.org
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/docs/progetto/docs.rst	Mon Apr 26 11:16:23 2010 +0200
   132.3 @@ -0,0 +1,130 @@
   132.4 +Documentazione
   132.5 +==============
   132.6 +
   132.7 +  Stiamo riscrivendo completamente la documentazione nella speranza di
   132.8 +  rendere un migliore servizio a tutti voi. In questo momento troverete molti
   132.9 +  punti incompleti: data la mole della documentazione non ci è facile
  132.10 +  aggiornarla tutta insieme. 
  132.11 +
  132.12 +  Avete due modi di contribuire:
  132.13 +
  132.14 +  1. In ogni pagina trovate un link a destra con scritto "Sorgente della
  132.15 +     pagina", potete vedere cosa sta scritto, copiare il sorgente, correggerlo
  132.16 +     e inviarcelo. Saremo ben contenti di integrarlo.
  132.17 +
  132.18 +  2. potete scaricare il repository mercurial della documentazione::
  132.19 +
  132.20 +       hg clone http://hg.argolinux.org/isi/isi-docs/
  132.21 +
  132.22 +     Ed `inviarmi <[email protected]>`_  la patch con le vostre migliorie
  132.23 +
  132.24 +
  132.25 +TODO
  132.26 +----
  132.27 +
  132.28 +Questa documentazione è chiaramente incompleta. Queste sono alcune delle
  132.29 +cose che mi saltano all'occhio, siete incoraggiati ad aggiungere punti:
  132.30 +
  132.31 +1. Analisi della documentazione dal sito istituzionale_ per capire quali
  132.32 +   parti non sono state riportate, quali vadano riportate.
  132.33 +
  132.34 +2. Documentare LTSP: cosa è come integrarla con ReteIsi
  132.35 +
  132.36 +3. Parte relativa alle biblioteche (pmb)
  132.37 +
  132.38 +4. Documentazione librerie nuove e man di ogni comando
  132.39 +
  132.40 +5. Gestione stampanti
  132.41 +
  132.42 +6. Backup
  132.43 +
  132.44 +7. Gestione installazione/clonazione client
  132.45 +
  132.46 +8. Configurazione firefox nei client
  132.47 +
  132.48 +9. Creazione di tutte le voci degli indici
  132.49 +
  132.50 +10. Allegati formativi: acl, scripting bash, scripting python.
  132.51 +    Qui dovrebbero essere più propriamente link a documentazione esistente
  132.52 +
  132.53 +11. Uso di vmware per esercitazione e per test. Uso di VNC.
  132.54 +
  132.55 +12. sicurezza (ssh senza chiave anche con putty)
  132.56 +
  132.57 +13. documentare runlevel.conf
  132.58 +
  132.59 +14. chiave repository
  132.60 +
  132.61 +
  132.62 +.. _istituzionale: http://www.reteisi.org
  132.63 +
  132.64 +Il pacchetto isi-docs
  132.65 +---------------------
  132.66 +
  132.67 +  Il comando qui sopra scarica sul vostro pc i sorgenti del pacchetto
  132.68 +  isi-docs come repository mercurial_ per generare la documentazione per
  132.69 +  provare in locale il risultato.
  132.70 +
  132.71 +  Tutta la documentazione del sito è raccolta in un pacchetto debian
  132.72 +  ``isi-docs`` che potete installare con il comando::
  132.73 +
  132.74 +    apt-get install isi-docs
  132.75 +
  132.76 +Contribuire alla documentazione
  132.77 +-------------------------------
  132.78 +
  132.79 +  Per contribuire alla documentazione occorre scrivere usando il sistema di
  132.80 +  markup reST. Vedrete presto che questo è facile e viene molto naturalmente.
  132.81 +
  132.82 +  Occorrono però due passi:
  132.83 +  
  132.84 +  1. Procurarsi il sorgente di isi-docs che è in un repository formato
  132.85 +     mercurial::
  132.86 + 
  132.87 +       apt-get install mercurial
  132.88 +       hg clone http://hg.argolinux.org/isi/isi-docs
  132.89 +
  132.90 +  2. Modificare le pagine che stanno in docs, eventualmente aggiungerne
  132.91 +     ed inviarmi le modifiche
  132.92 +
  132.93 +     Per fare nel modo più comodo questo secondo passaggio, anche se non
  132.94 +     necessario, consiglio di installare sphinx::
  132.95 +
  132.96 +       sudo apt-get install subversion-tools python-docutils python-jinja python-dev
  132.97 +       svn co http://svn.python.org/projects/doctools
  132.98 +       cd doctools/trunk
  132.99 +       python setup.py install
 132.100 +
 132.101 +    Avendo sphinx installato, dalla cartella isi-docs::
 132.102 +
 132.103 +       cd docs
 132.104 +       (editate i file)
 132.105 +       make html
 132.106 +
 132.107 +    Che produce i file in formato html in docs/.build/html
 132.108 +    Chi ha diritto di accesso può committare i risultati, gli altri possono
 132.109 +    mandarmi un diff::
 132.110 +
 132.111 +       hg tip > patch
 132.112 +       hg diff >> patch
 132.113 +       mutt -a patch -s "RetIsiDoc: aggiunta documentazione" [email protected] < /dev/null
 132.114 +
 132.115 +    
 132.116 +     	
 132.117 +
 132.118 +reST
 132.119 +----
 132.120 +
 132.121 +Per contribuire alla documentazione vi conviene familiarizzare con la
 132.122 +sintassi di reST_ , il linguaggio di markup usato
 132.123 +
 132.124 +.. toctree::
 132.125 +
 132.126 +  rest
 132.127 +
 132.128 +.. _reST :ref: `reteisi_rest`
 132.129 +
 132.130 +.. _mercurial: http://www.selenic.com/mercurial/wiki/
 132.131 +
 132.132 +
 132.133 +
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/docs/progetto/presentazione_tecnica.rst	Mon Apr 26 11:16:23 2010 +0200
   133.3 @@ -0,0 +1,121 @@
   133.4 +.. _reteisi_presentazione_tecnica:
   133.5 +
   133.6 +Presentazione tecnica
   133.7 +=======================
   133.8 +
   133.9 +le fondamenta di ISI: argolinux
  133.10 +-------------------------------
  133.11 +
  133.12 +ArgoLinux è un progetto basato su Debian (ramo stabile) con
  133.13 +caratteristiche che abbiamo trovato adatte alle nostre esigenze, in
  133.14 +particolare:
  133.15 +
  133.16 +
  133.17 +    * preinstallazione e preconfigurazione di tutti i pacchetti che servono
  133.18 +      ad implementare le previste funzionalità di networking
  133.19 +
  133.20 +    * installazione e replica semplificata
  133.21 +
  133.22 +    * funzionamento da cdrom con salvataggio della configurazione su
  133.23 +      floppy: in questo modo è facile implementare un servizio di firewall
  133.24 +      sicuro e di immediato ripristino
  133.25 +
  133.26 +    * semplicità della gestione dei runlevel e della configurazione di
  133.27 +      startup dei servizi (Argo adotta il pacchetto Debian file-rc che
  133.28 +      mappa il sistema di cartelle e file di boot SysV? su un unico file)
  133.29 +
  133.30 +    * facilità di configurazione del firewall
  133.31 +
  133.32 +Queste caratteristiche non alterano la compatibilità con la distribuzione
  133.33 +ufficiale Debian stabile, di cui possono perciò essere adottati tutti i
  133.34 +pacchetti esistenti. Sono garantite pertanto tutte quelle caratteristiche
  133.35 +che fanno di Debian una delle distribuzione più stabili, sicure e meglio
  133.36 +supportate in circolazione.
  133.37 +
  133.38 +
  133.39 +requisiti hardware
  133.40 +------------------
  133.41 +
  133.42 +ISI come firewall
  133.43 ++++++++++++++++++
  133.44 +        
  133.45 +Per realizzare un potente firewall da interporre tra il router ADSL e la
  133.46 +rete locale in modo da evitare attacchi indesiderati da internet, e nel
  133.47 +contempo consentire l'accesso da remoto ai server e agli apparati di rete, è
  133.48 +sufficiente una macchina con le seguenti caratteristiche:
  133.49 +
  133.50 +  * CPU pentium 2 (in teoria dovrebbe essere possibile anche con macchine
  133.51 +    pentium ma il kernel è ottimizzato per pentium2 e superiori)
  133.52 +
  133.53 +  * RAM 64 mb sono stati sufficienti a gestire un firewall con 3 schede di
  133.54 +    rete 10/100 mbps (una per la lan e le altre per due router collegati a
  133.55 +    differenti linee adsl)
  133.56 +
  133.57 +  * HD 10 Gb dovrebbe essere più che sufficiente anche per i log (I servizi
  133.58 +    offerti da una configurazione normale comprendono anche Dhcp e DNS
  133.59 +    server, VPN per il collegamento con i plessi non raggiungibili
  133.60 +    altrimenti)
  133.61 +
  133.62 +Per questa soluzione (non gira samba) è più indicato usare la distribuzione
  133.63 +Argo originale.
  133.64 +
  133.65 +ISI come fileserver
  133.66 ++++++++++++++++++++
  133.67 +
  133.68 +Per realizzare un file server è opportuno utilizzare una macchina più
  133.69 +potente, sia come processore, che soprattutto come Ram e capacità di
  133.70 +memorizzazione.  Le macchine originariamente acquistate (2003) per il
  133.71 +progetto ISI avevano le seguenti caratteristiche:
  133.72 +
  133.73 + * CPU Pentium 4 2,4 gHz
  133.74 + * RAM 1 Gb ddr
  133.75 + * HD n.2 dischi da 80 Gb in mirroring software
  133.76 + * device di backup: masterizzatore DVD-ram
  133.77 + * scheda di rete gigabit 
  133.78 +
  133.79 +Tutto questo è largamente sufficiente per gestire una rete di 100-200 client
  133.80 +con vari servizi, oltre al file server, e in particolare:
  133.81 +
  133.82 + * PDC per autenticazione utenti tramite Ldap e Samba
  133.83 + * Web, Ftp e mail server
  133.84 + * proxy 
  133.85 +
  133.86 +Queste caratteristiche sono ora più che mai normali
  133.87 +
  133.88 +sistemi operativi supportati
  133.89 +++++++++++++++++++++++++++++
  133.90 +
  133.91 +    + Linux
  133.92 +
  133.93 +        Qualunque distribuzione ( Per il nutrito numero di applicativi
  133.94 +        educativi contenuti è stata preferita EDUBUNTU )
  133.95 +
  133.96 +    + Microsoft
  133.97 +
  133.98 +        + Windows98 Second Edition
  133.99 +
 133.100 +        + Windows2000
 133.101 +
 133.102 +        + Windows XP Professional
 133.103 +
 133.104 +
 133.105 +perché scegliere isi
 133.106 +--------------------
 133.107 +
 133.108 +    I vantaggi rispetto ad un sistema proprietario sono molteplici:
 133.109 +
 133.110 +        + azzeramento degli onerosi costi di licenza
 133.111 +
 133.112 +        + Maggiore sicurezza
 133.113 +        
 133.114 +        + Standard aperti
 133.115 +        
 133.116 +        + Personalizzabile per adattarla alle proprie esigenze
 133.117 +        
 133.118 +ottenere isi
 133.119 +------------
 133.120 +
 133.121 +    è possibile scaricare la versione più recente all'indirizzo 
 133.122 +    http://download.argolinux.org/isi/ 
 133.123 +
 133.124 +
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/docs/progetto/project.rst	Mon Apr 26 11:16:23 2010 +0200
   134.3 @@ -0,0 +1,155 @@
   134.4 +.. _reteisi_project:   
   134.5 +
   134.6 +Il progetto e le sue finalità
   134.7 +=============================
   134.8 +
   134.9 +ReteIsi nasce nel 2002 come libera associazione di Scuole proponenti un
  134.10 +progetto di informatizzazione dell'organizzazione scolastica finanziato
  134.11 +dall'USR Lombardia nell'ambito degli interventi previsti dalla CM 152/2001
  134.12 +(progetti azione B).
  134.13 +
  134.14 +Raggiunti gli obiettivi principali (definizione di un modello architetturale
  134.15 +di una intranet scolastica, individuazione della piattaforma software e dei
  134.16 +servizi da attivare, traduzione del modello e dei sistemi individuati in
  134.17 +installazioni funzionanti) ora ReteIsi mette a disposizione di tutte le
  134.18 +Istituzioni Scolastiche interessate a perseguire "politiche" informatiche
  134.19 +non episodiche, i risultati raggiunti, proponendosi come punto di raccordo
  134.20 +delle esperienze in atto.
  134.21 +
  134.22 +
  134.23 +Finalità (estratto dai documenti di progetto)
  134.24 +---------------------------------------------
  134.25 +
  134.26 +Il progetto ha come oggetto lo sviluppo, in ambiente Open Source, di un
  134.27 +framework HW/SW modulare e standardizzato che consenta la razionalizzazione,
  134.28 +la conservazione, la gestione collaborativa, la trasmissione e la
  134.29 +pubblicazione dei flussi informativi generati dalle attività scolastiche
  134.30 +relativamente
  134.31 +
  134.32 +   * all'istituzione scolastica nel suo complesso e ai suoi rapporti con
  134.33 +     altri Istituti (processi interni di raccolta dati, di decisione, di
  134.34 +     pianificazione delle attività, ed esterni di trasmissione di
  134.35 +     informazioni, anche afferenti alla didattica, alle attività a distanza
  134.36 +     e alle collaborazioni su progetti comuni); Interoperable Delivery of
  134.37 +     European eGovernment Services
  134.38 +
  134.39 +   * ai percorsi formativi degli alunni, (valutazione degli apprendimenti e
  134.40 +     problematica della relativa comunicazione scuola/famiglia anche
  134.41 +     attraverso l'accesso remoto al fascicolo dello studente );
  134.42 +
  134.43 +   * ai rapporti dell'istituzione scolastica con il territorio (iniziative
  134.44 +     formative rivolte alla cittadinanza promosse in collaborazione con gli
  134.45 +     EE.LL., certificazione ECDL, pubblicazione/interrogazione patrimonio
  134.46 +     librario ecc., integrazione in eventuali reti civiche esistenti ecc).
  134.47 +
  134.48 +L'architettura HW/SW individuata a sostegno del progetto è quella della
  134.49 +intranet d'Istituto, cioè la connessione tra le reti didattiche esistenti,
  134.50 +la segreteria e gli ambienti di staff (presidenza, sale insegnanti,
  134.51 +biblioteca e quant'altro costituisce luogo in cui abitualmente vengono poste
  134.52 +in essere attività relative all'elaborazione e alla gestione delle attività
  134.53 +della Scuola). Secondo il ventaglio illustrato nel RGL, le scuole aderenti a
  134.54 +questo progetto si collocano, per motivi diversi, all'interno delle
  134.55 +tipologie C-D-E: lo strato fisico di rete è già in gran parte disponibile, i
  134.56 +completamenti necessari consistono nella posa di dorsali tra edifici diversi
  134.57 +poco distanti, nell'aggiunta di punti rete in locali di staff non ancora
  134.58 +raggiunti e nell'interconnessione dei segmenti LAN già in essere. Per quanto
  134.59 +riguarda le aule tre di noi, ISSS Majorana, IC Bernareggio e IC Bellano,
  134.60 +adotteranno anche soluzioni wireless. La connessione delle sedi staccate
  134.61 +avverrà adottando canali VPN su ADSL (laddove ADSL è disponibile).
  134.62 +
  134.63 +Su questa infrastruttura, si definiranno in modo modulare, valutandone di
  134.64 +volta in volta la completezza e la riutilizzabilità e utilizzando standard
  134.65 +aperti e strumenti Open Source, procedure e servizi rivolti
  134.66 +all'organizzazione e alla gestione di elementi importanti della vita
  134.67 +scolastica quali:
  134.68 +
  134.69 +processi interni
  134.70 +~~~~~~~~~~~~~~~~
  134.71 +
  134.72 +   * definizione del 'manuale' per la configurazione e il buon uso della
  134.73 +     struttura intranet, comprese le fondamentali procedure di backup e
  134.74 +     quelle relative alla sicurezza;
  134.75 +
  134.76 +   * gestione degli account personali di docenti, non docenti e alunni
  134.77 +     necessari per l'autenticazione e l'accesso sicuro e controllato alla
  134.78 +     rete d'Istituto e ai suoi servizi;
  134.79 +
  134.80 +   * esportazione dei dati personali dello studente solitamente 'sepolti' in
  134.81 +     segreteria, per la predisposizione di modulistica e/o report;
  134.82 +
  134.83 +   * pianificazione e documentazione della programmazione didattica e
  134.84 +     curricolare secondo modalità che ne permettano la pubblicazione sulla
  134.85 +     rete, il confronto e la verifica;
  134.86 +
  134.87 +   * definizione del fascicolo dello studente (FAST) che è alla base di
  134.88 +     qualsiasi servizio interattivo scuola/famiglia riutilizzabile in ambito
  134.89 +     regionale;
  134.90 +
  134.91 +   * registro elettronico dei voti e delle valutazioni; 
  134.92 +
  134.93 +   * gestione delle verbalizzazioni e degli strumenti di supporto alle
  134.94 +     decisioni (griglie, quadri valutativi);
  134.95 +
  134.96 +   * procedure per la pianificazione e il calendario delle attività; 
  134.97 +
  134.98 +   * comunicazioni interne: albi elettronici con funzionalità di
  134.99 +     organizzazione e ricerca documentale;
 134.100 +
 134.101 +   * gestione delle risorse strumentali disponibili (prenotazione,
 134.102 +     monitoraggio dell'uso, manutenzioni);
 134.103 +
 134.104 +   * gestione della biblioteca e dei servizi correlati (compresa
 134.105 +     l'interrogazione remota e l'eventuale integrazione del patrimonio
 134.106 +     librario scolastico con quello delle locali biblioteche civiche);
 134.107 +
 134.108 +processi esterni
 134.109 +~~~~~~~~~~~~~~~~
 134.110 +
 134.111 +   * connessione (VPN) delle sedi staccate e/o dei plessi in cui si articola
 134.112 +     l'Istituto;
 134.113 +
 134.114 +   * assistenza/manutenzione remota degli apparati server anche fra Istituti
 134.115 +     diversi (collaborazione sistemistica e consolidamento delle competenze
 134.116 +     interne rese disponibili anche ad altri istituti);
 134.117 +
 134.118 +   * interazione remota territorio-scuola (comunicazioni scuola/famiglia e
 134.119 +     problematica dell'autenticazione e del riconoscimento digitale,
 134.120 +     integrazione in reti civiche esistenti,);
 134.121 +
 134.122 +La natura eterogenea del raggruppamento di Scuole che presenta questo
 134.123 +progetto e gli accordi orientati allo sviluppo parallelo e mutuamente
 134.124 +assistibile della piattaforma intranet, consentirà
 134.125 +
 134.126 +   * lo sviluppo di un modello hw/sw di intranet scolastica facilmente
 134.127 +     duplicabile in altre realtà grazie alla standardizzazione,
 134.128 +     all'economicità e al modelle di sviluppo aperto che caratterizza le
 134.129 +     soluzioni sistemistiche adottate;
 134.130 +
 134.131 +   * lo studio delle problematiche connesse con l'autenticazione e il
 134.132 +     riconoscimento digitale di tutti i soggetti che per vari motivi devono
 134.133 +     o vogliono interagire in modo sicuro con la scuola;
 134.134 +
 134.135 +   * l'individuazione dei sistemi per la comunicazione sicura tra plessi e/o
 134.136 +     scuole diverse (connessioni VPN, sviluppo collaborativo di siti web,
 134.137 +     forum);
 134.138 +
 134.139 +   * lo sviluppo di servizi significativi per la gestione, il monitoraggio,
 134.140 +     il reporting e la comunicazione dell'attività didattica anche
 134.141 +     attraverso connessioni remote sicure e personalizzate;
 134.142 +
 134.143 +   * lo sviluppo di strutture dati fondamentali, estensibili ed aperte,
 134.144 +     capaci di descrivere e rendere accessibili ed elaborabili i flussi
 134.145 +     informativi legati all'ordinaria attività didattica e alla sua
 134.146 +     organizzazione;
 134.147 +
 134.148 +   * la definizione e lo sviluppo di servizi sicuri per l'interrogazione
 134.149 +     remota di database scolastici;
 134.150 +
 134.151 +   * la costitituzione di una rete di scuole di ordini diversi che
 134.152 +     condividono soluzioni applicative modulari, sia hardware che software,
 134.153 +     sperimentando anche forme di assistenza remota di tipo sistemistico su
 134.154 +     infrastrutture simili;
 134.155 +
 134.156 +   * la sperimentazione di forme di lavoro collaborativo relativamente alla
 134.157 +     progettazione di infrastrutture e servizi comuni ad istituzioni
 134.158 +     scolastiche di natura diversa.
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/docs/progetto/rest.rst	Mon Apr 26 11:16:23 2010 +0200
   135.3 @@ -0,0 +1,264 @@
   135.4 +.. _reteisi_rest:
   135.5 +
   135.6 +reStructuredText Primer
   135.7 +=======================
   135.8 +
   135.9 +This section is a brief introduction to reStructuredText (reST) concepts and
  135.10 +syntax, intended to provide authors with enough information to author documents
  135.11 +productively.  Since reST was designed to be a simple, unobtrusive markup
  135.12 +language, this will not take too long.
  135.13 +
  135.14 +.. seealso::
  135.15 +
  135.16 +    The authoritative `reStructuredText User
  135.17 +    Documentation <http://docutils.sourceforge.net/rst.html>`_.
  135.18 +
  135.19 +
  135.20 +Paragraphs
  135.21 +----------
  135.22 +
  135.23 +The paragraph is the most basic block in a reST document.  Paragraphs are simply
  135.24 +chunks of text separated by one or more blank lines.  As in Python, indentation
  135.25 +is significant in reST, so all lines of the same paragraph must be left-aligned
  135.26 +to the same level of indentation.
  135.27 +
  135.28 +
  135.29 +Inline markup
  135.30 +-------------
  135.31 +
  135.32 +The standard reST inline markup is quite simple: use
  135.33 +
  135.34 +* one asterisk: ``*text*`` for emphasis (italics),
  135.35 +* two asterisks: ``**text**`` for strong emphasis (boldface), and
  135.36 +* backquotes: ````text```` for code samples.
  135.37 +
  135.38 +If asterisks or backquotes appear in running text and could be confused with
  135.39 +inline markup delimiters, they have to be escaped with a backslash.
  135.40 +
  135.41 +Be aware of some restrictions of this markup:
  135.42 +
  135.43 +* it may not be nested,
  135.44 +* content may not start or end with whitespace: ``* text*`` is wrong,
  135.45 +* it must be separated from surrounding text by non-word characters.  Use a
  135.46 +  backslash escaped space to work around that: ``thisis\ *one*\ word``.
  135.47 +
  135.48 +These restrictions may be lifted in future versions of the docutils.
  135.49 +
  135.50 +reST also allows for custom "interpreted text roles"', which signify that the
  135.51 +enclosed text should be interpreted in a specific way.  Sphinx uses this to
  135.52 +provide semantic markup and cross-referencing of identifiers, as described in
  135.53 +the appropriate section.  The general syntax is ``:rolename:`content```.
  135.54 +
  135.55 +
  135.56 +Lists and Quotes
  135.57 +----------------
  135.58 +
  135.59 +List markup is natural: just place an asterisk at the start of a paragraph and
  135.60 +indent properly.  The same goes for numbered lists; they can also be
  135.61 +autonumbered using a ``#`` sign::
  135.62 +
  135.63 +   * This is a bulleted list.
  135.64 +   * It has two items, the second
  135.65 +     item uses two lines.
  135.66 +
  135.67 +   1. This is a numbered list.
  135.68 +   2. It has two items too.
  135.69 +
  135.70 +   #. This is a numbered list.
  135.71 +   #. It has two items too.
  135.72 +
  135.73 +Note that Sphinx disables the use of enumerated lists introduced by alphabetic
  135.74 +or roman numerals, such as ::
  135.75 +
  135.76 +   A. First item
  135.77 +   B. Second item
  135.78 +   
  135.79 +
  135.80 +Nested lists are possible, but be aware that they must be separated from the
  135.81 +parent list items by blank lines::
  135.82 +
  135.83 +   * this is
  135.84 +   * a list
  135.85 +
  135.86 +     * with a nested list
  135.87 +     * and some subitems
  135.88 +
  135.89 +   * and here the parent list continues
  135.90 +
  135.91 +Definition lists are created as follows::
  135.92 +
  135.93 +   term (up to a line of text)
  135.94 +      Definition of the term, which must be indented
  135.95 +
  135.96 +      and can even consist of multiple paragraphs
  135.97 +
  135.98 +   next term
  135.99 +      Description.
 135.100 +
 135.101 +
 135.102 +Paragraphs are quoted by just indenting them more than the surrounding
 135.103 +paragraphs.
 135.104 +
 135.105 +
 135.106 +Source Code
 135.107 +-----------
 135.108 +
 135.109 +Literal code blocks are introduced by ending a paragraph with the special marker
 135.110 +``::``.  The literal block must be indented, to be able to include blank lines::
 135.111 +
 135.112 +   This is a normal text paragraph. The next paragraph is a code sample::
 135.113 +
 135.114 +      It is not processed in any way, except
 135.115 +      that the indentation is removed.
 135.116 +
 135.117 +      It can span multiple lines.
 135.118 +
 135.119 +   This is a normal text paragraph again.
 135.120 +
 135.121 +The handling of the ``::`` marker is smart:
 135.122 +
 135.123 +* If it occurs as a paragraph of its own, that paragraph is completely left
 135.124 +  out of the document.
 135.125 +* If it is preceded by whitespace, the marker is removed.
 135.126 +* If it is preceded by non-whitespace, the marker is replaced by a single
 135.127 +  colon.
 135.128 +
 135.129 +That way, the second sentence in the above example's first paragraph would be
 135.130 +rendered as "The next paragraph is a code sample:".
 135.131 +
 135.132 +
 135.133 +Hyperlinks
 135.134 +----------
 135.135 +
 135.136 +External links
 135.137 +^^^^^^^^^^^^^^
 135.138 +
 135.139 +Use ```Link text <http://target>`_`` for inline web links.  If the link text
 135.140 +should be the web address, you don't need special markup at all, the parser
 135.141 +finds links and mail addresses in ordinary text.
 135.142 +
 135.143 +Internal links
 135.144 +^^^^^^^^^^^^^^
 135.145 +
 135.146 +Internal linking is done via a special reST role, see the section on specific
 135.147 +markup, :ref: `ref-role`.
 135.148 +
 135.149 +
 135.150 +Sections
 135.151 +--------
 135.152 +
 135.153 +Section headers are created by underlining (and optionally overlining) the
 135.154 +section title with a punctuation character, at least as long as the text::
 135.155 +
 135.156 +   =================
 135.157 +   This is a heading
 135.158 +   =================
 135.159 +
 135.160 +Normally, there are no heading levels assigned to certain characters as the
 135.161 +structure is determined from the succession of headings.  However, for the
 135.162 +Python documentation, this convention is used which you may follow:
 135.163 +
 135.164 +* ``#`` with overline, for parts
 135.165 +* ``*`` with overline, for chapters
 135.166 +* ``=``, for sections
 135.167 +* ``-``, for subsections
 135.168 +* ``^``, for subsubsections
 135.169 +* ``"``, for paragraphs
 135.170 +
 135.171 +
 135.172 +Explicit Markup
 135.173 +---------------
 135.174 +
 135.175 +"Explicit markup" is used in reST for most constructs that need special
 135.176 +handling, such as footnotes, specially-highlighted paragraphs, comments, and
 135.177 +generic directives.
 135.178 +
 135.179 +An explicit markup block begins with a line starting with ``..`` followed by
 135.180 +whitespace and is terminated by the next paragraph at the same level of
 135.181 +indentation.  (There needs to be a blank line between explicit markup and normal
 135.182 +paragraphs.  This may all sound a bit complicated, but it is intuitive enough
 135.183 +when you write it.)
 135.184 +
 135.185 +
 135.186 +Directives
 135.187 +----------
 135.188 +
 135.189 +A directive is a generic block of explicit markup.  Besides roles, it is one of
 135.190 +the extension mechanisms of reST, and Sphinx makes heavy use of it.
 135.191 +
 135.192 +Basically, a directive consists of a name, arguments, options and content. (Keep
 135.193 +this terminology in mind, it is used in the next chapter describing custom
 135.194 +directives.)  Looking at this example, ::
 135.195 +
 135.196 +   .. function:: foo(x)
 135.197 +                 foo(y, z)
 135.198 +      :bar: no
 135.199 +
 135.200 +      Return a line of text input from the user.
 135.201 +
 135.202 +``function`` is the directive name.  It is given two arguments here, the
 135.203 +remainder of the first line and the second line, as well as one option ``bar``
 135.204 +(as you can see, options are given in the lines immediately following the
 135.205 +arguments and indicated by the colons).
 135.206 +
 135.207 +The directive content follows after a blank line and is indented relative to the
 135.208 +directive start.
 135.209 +
 135.210 +
 135.211 +Images
 135.212 +------
 135.213 +
 135.214 +reST supports an image directive, used like so::
 135.215 +
 135.216 +   .. image:: filename
 135.217 +      (options)
 135.218 +
 135.219 +When used within Sphinx, the ``filename`` given must be relative to the source
 135.220 +file, and Sphinx will automatically copy image files over to a subdirectory of
 135.221 +the output directory on building.
 135.222 +
 135.223 +
 135.224 +Footnotes
 135.225 +---------
 135.226 +
 135.227 +For footnotes, use ``[#]_`` to mark the footnote location, and add the footnote
 135.228 +body at the bottom of the document after a "Footnotes" rubric heading, like so::
 135.229 +
 135.230 +   Lorem ipsum [#]_ dolor sit amet ... [#]_
 135.231 +
 135.232 +   .. rubric:: Footnotes
 135.233 +
 135.234 +   .. [#] Text of the first footnote.
 135.235 +   .. [#] Text of the second footnote.
 135.236 +
 135.237 +You can also explicitly number the footnotes for better context.
 135.238 +
 135.239 +
 135.240 +Comments
 135.241 +--------
 135.242 +
 135.243 +Every explicit markup block which isn't a valid markup construct (like the
 135.244 +footnotes above) is regarded as a comment.
 135.245 +
 135.246 +
 135.247 +Source encoding
 135.248 +---------------
 135.249 +
 135.250 +Since the easiest way to include special characters like em dashes or copyright
 135.251 +signs in reST is to directly write them as Unicode characters, one has to
 135.252 +specify an encoding:
 135.253 +
 135.254 +All documentation source files must be in UTF-8 encoding, and the HTML
 135.255 +documents written from them will be in that encoding as well.
 135.256 +
 135.257 +
 135.258 +Gotchas
 135.259 +-------
 135.260 +
 135.261 +There are some problems one commonly runs into while authoring reST documents:
 135.262 +
 135.263 +* **Separation of inline markup:** As said above, inline markup spans must be
 135.264 +  separated from the surrounding text by non-word characters, you have to use
 135.265 +  an escaped space to get around that.
 135.266 +
 135.267 +.. XXX more?
   136.1 Binary file docs/reteisi.png has changed
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/etc/apache2/sites-available/isiweb-all.conf	Mon Apr 26 11:16:23 2010 +0200
   137.3 @@ -0,0 +1,45 @@
   137.4 +#### configurazione con fastcgi
   137.5 +
   137.6 +<VirtualHost *:80>
   137.7 +     #ServerName fscgi.isi.lan
   137.8 +     #ServerAlias web.isi.lan
   137.9 +
  137.10 +     FastCGIExternalServer /usr/share/isi/isiweb.fcgi -host 127.0.0.1:3033 -idle-timeout 800
  137.11 +     #FastCGIExternalServer /usr/share/isi/isiweb.fcgi -socket /var/run/isiweb.sock
  137.12 +
  137.13 +
  137.14 +     DocumentRoot /usr/share/isi/
  137.15 +     Alias /static/ /usr/share/isi/isiweb/static/
  137.16 +     Alias /media/  /usr/share/python-support/python-django/django/contrib/admin/media/
  137.17 +     Alias /docs/ /usr/share/doc/isi/html/
  137.18 +
  137.19 +     RewriteEngine On
  137.20 +     RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
  137.21 +     RewriteRule ^/(static.*)$ /$1 [QSA,L,PT]
  137.22 +     RewriteRule ^/(docs.*)$ /$1 [QSA,L,PT]
  137.23 +     RewriteCond %{REQUEST_FILENAME} !-f
  137.24 +     RewriteRule ^/(.*)$ /isiweb.fcgi/$1 [QSA,L]
  137.25 +
  137.26 +
  137.27 +     <LocationMatch "/(static|media)/">
  137.28 + 	SetHandler none
  137.29 +	ExpiresActive On
  137.30 +	ExpiresByType application/javascript "access plus 4 weeks"
  137.31 +	ExpiresByType text/html "access plus 4 weeks"
  137.32 +	ExpiresByType text/css "access plus 4 weeks"
  137.33 +	ExpiresDefault "now plus 2 days"
  137.34 +     </LocationMatch>
  137.35 +
  137.36 +
  137.37 +     <Directory "/usr/share/isi/">
  137.38 +         Order Deny,Allow
  137.39 +         Allow from 10 172 192 127
  137.40 +         Deny from all
  137.41 +     </Directory>
  137.42 +
  137.43 +    ErrorLog /var/log/apache2/isi.lan-error.log
  137.44 +
  137.45 +    LogLevel warn
  137.46 +    CustomLog /var/log/apache2/isi.lan-access.log combined
  137.47 +
  137.48 +</VirtualHost>
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/etc/apache2/sites-available/isiweb.conf	Mon Apr 26 11:16:23 2010 +0200
   138.3 @@ -0,0 +1,45 @@
   138.4 +#### configurazione con fastcgi
   138.5 +
   138.6 +<VirtualHost *:80>
   138.7 +     ServerName fscgi.isi.lan
   138.8 +     ServerAlias web.isi.lan
   138.9 +
  138.10 +     FastCGIExternalServer /usr/share/isi/isiweb.fcgi -host 127.0.0.1:3033 -idle-timeout 800
  138.11 +     #FastCGIExternalServer /usr/share/isi/isiweb.fcgi -socket /var/run/isiweb.sock
  138.12 +
  138.13 +
  138.14 +     DocumentRoot /usr/share/isi/
  138.15 +     Alias /static/ /usr/share/isi/isiweb/static/
  138.16 +     Alias /media/  /usr/share/python-support/python-django/django/contrib/admin/media/
  138.17 +     Alias /docs/ /usr/share/doc/isi/html/
  138.18 +
  138.19 +     RewriteEngine On
  138.20 +     RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
  138.21 +     RewriteRule ^/(static.*)$ /$1 [QSA,L,PT]
  138.22 +     RewriteRule ^/(docs.*)$ /$1 [QSA,L,PT]
  138.23 +     RewriteCond %{REQUEST_FILENAME} !-f
  138.24 +     RewriteRule ^/(.*)$ /isiweb.fcgi/$1 [QSA,L]
  138.25 +
  138.26 +
  138.27 +     <LocationMatch "/(static|media)/">
  138.28 + 	SetHandler none
  138.29 +	ExpiresActive On
  138.30 +	ExpiresByType application/javascript "access plus 4 weeks"
  138.31 +	ExpiresByType text/html "access plus 4 weeks"
  138.32 +	ExpiresByType text/css "access plus 4 weeks"
  138.33 +	ExpiresDefault "now plus 2 days"
  138.34 +     </LocationMatch>
  138.35 +
  138.36 +
  138.37 +     <Directory "/usr/share/isi/">
  138.38 +         Order Deny,Allow
  138.39 +         Allow from 10 172 192 127
  138.40 +         Deny from all
  138.41 +     </Directory>
  138.42 +
  138.43 +    ErrorLog /var/log/apache2/isi.lan-error.log
  138.44 +
  138.45 +    LogLevel warn
  138.46 +    CustomLog /var/log/apache2/isi.lan-access.log combined
  138.47 +
  138.48 +</VirtualHost>
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/etc/default/isiweb	Mon Apr 26 11:16:23 2010 +0200
   139.3 @@ -0,0 +1,1 @@
   139.4 +START_FSCI=1
   140.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   140.2 +++ b/etc/init.d/isiweb	Mon Apr 26 11:16:23 2010 +0200
   140.3 @@ -0,0 +1,144 @@
   140.4 +#! /bin/sh
   140.5 +### BEGIN INIT INFO
   140.6 +# Provides:          skeleton
   140.7 +# Required-Start:    $remote_fs
   140.8 +# Required-Stop:     $remote_fs
   140.9 +# Default-Start:     2 3 4 5
  140.10 +# Default-Stop:      0 1 6
  140.11 +# Short-Description: Example initscript
  140.12 +# Description:       This file should be used to construct scripts to be
  140.13 +#                    placed in /etc/init.d.
  140.14 +### END INIT INFO
  140.15 +
  140.16 +# Author: Foo Bar <[email protected]>
  140.17 +#
  140.18 +# Please remove the "Author" lines above and replace them
  140.19 +# with your own name if you copy and modify this script.
  140.20 +
  140.21 +# Do NOT "set -e"
  140.22 +
  140.23 +# PATH should only include /usr/* if it runs after the mountnfs.sh script
  140.24 +PATH=/sbin:/usr/sbin:/bin:/usr/bin
  140.25 +DESC="Interfaccia Web per ReteISI"
  140.26 +NAME=isiweb
  140.27 +#DAEMON=/usr/sbin/$NAME
  140.28 +DAEMON_ARGS="socket=$SOCKET pidfile=$PIDFILE"
  140.29 +PIDFILE=/var/run/$NAME.pid
  140.30 +SCRIPTNAME=/etc/init.d/$NAME
  140.31 +SOCKET=/var/run/$NAME.sock
  140.32 +PROJDIR="/usr/share/isi/isiweb/"
  140.33 +#DAEMON_ARGS="socket=$SOCKET pidfile=$PIDFILE maxspare=1"
  140.34 +DAEMON_ARGS="host=127.0.0.1 port=3033 pidfile=$PIDFILE maxspare=1 errlog=/var/log/isiweb.log"
  140.35 +
  140.36 +# # Exit if the package is not installed
  140.37 +# [ -x "$DAEMON" ] || exit 0
  140.38 +
  140.39 +# Read configuration variable file if it is present
  140.40 +[ -r /etc/default/$NAME ] && . /etc/default/$NAME
  140.41 +
  140.42 +# Load the VERBOSE setting and other rcS variables
  140.43 +. /lib/init/vars.sh
  140.44 +
  140.45 +# Define LSB log_* functions.
  140.46 +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
  140.47 +. /lib/lsb/init-functions
  140.48 +
  140.49 +#
  140.50 +# Function that starts the daemon/service
  140.51 +#
  140.52 +do_start()
  140.53 +{
  140.54 +    do_stop
  140.55 +    cd $PROJDIR
  140.56 +    if [ $START_FSCI = 1 ] ; then
  140.57 +       echo "Starting $DESC" $NAME
  140.58 +       exec /usr/bin/env - \
  140.59 +	 PYTHONPATH="../python:.." ./manage.py runfcgi $DAEMON_ARGS
  140.60 +       RETVAL=$?
  140.61 +       echo -e "\n"
  140.62 +       return $RETVAL
  140.63 +    else
  140.64 +       echo "You must enable in /etc/default/isiweb: START_FSCI=1"
  140.65 +    fi
  140.66 +
  140.67 +}
  140.68 +
  140.69 +#
  140.70 +# Function that stops the daemon/service
  140.71 +#
  140.72 +do_stop()
  140.73 +{
  140.74 +     cd $PROJDIR
  140.75 +     if [ -f $PIDFILE ]; then
  140.76 +         kill `cat -- $PIDFILE`
  140.77 +	 RETVAL=$?
  140.78 +         rm -f -- $PIDFILE
  140.79 +     fi
  140.80 +    return $RETVAL
  140.81 +}
  140.82 +
  140.83 +#
  140.84 +# Function that sends a SIGHUP to the daemon/service
  140.85 +#
  140.86 +# do_reload() {
  140.87 +
  140.88 +#   do_stop()
  140.89 +#   do_start()
  140.90 +# }
  140.91 +
  140.92 +case "$1" in
  140.93 +  start)
  140.94 +	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
  140.95 +	do_start
  140.96 +	case "$?" in
  140.97 +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
  140.98 +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
  140.99 +	esac
 140.100 +	;;
 140.101 +  stop)
 140.102 +	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
 140.103 +	do_stop
 140.104 +	case "$?" in
 140.105 +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
 140.106 +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
 140.107 +	esac
 140.108 +	;;
 140.109 +  #reload|force-reload)
 140.110 +	#
 140.111 +	# If do_reload() is not implemented then leave this commented out
 140.112 +	# and leave 'force-reload' as an alias for 'restart'.
 140.113 +	#
 140.114 +	#log_daemon_msg "Reloading $DESC" "$NAME"
 140.115 +	#do_reload
 140.116 +	#log_end_msg $?
 140.117 +	#;;
 140.118 +  restart|force-reload)
 140.119 +	#
 140.120 +	# If the "reload" option is implemented then remove the
 140.121 +	# 'force-reload' alias
 140.122 +	#
 140.123 +	log_daemon_msg "Restarting $DESC" "$NAME"
 140.124 +	do_stop
 140.125 +	case "$?" in
 140.126 +	  0|1)
 140.127 +		do_start
 140.128 +		case "$?" in
 140.129 +			0) log_end_msg 0 ;;
 140.130 +			1) log_end_msg 1 ;; # Old process is still running
 140.131 +			*) log_end_msg 1 ;; # Failed to start
 140.132 +		esac
 140.133 +		;;
 140.134 +	  *)
 140.135 +	  	# Failed to stop
 140.136 +		log_end_msg 1
 140.137 +		;;
 140.138 +	esac
 140.139 +	;;
 140.140 +  *)
 140.141 +	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
 140.142 +	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
 140.143 +	exit 3
 140.144 +	;;
 140.145 +esac
 140.146 +
 140.147 +:
   141.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.2 +++ b/etc/isi/dglog.conf.pl.sample	Mon Apr 26 11:16:23 2010 +0200
   141.3 @@ -0,0 +1,3 @@
   141.4 +$ldap_server ='127.0.0.1';
   141.5 +$ldap_base   ='<dc=isi,dc=lan>';
   141.6 +@ldap_fields=('gecos','departmentNumber');
   142.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.2 +++ b/etc/isi/logon.bat.sample	Mon Apr 26 11:16:23 2010 +0200
   142.3 @@ -0,0 +1,3 @@
   142.4 +:: ##### LOGON.BAT creato da ISI-LOGON #####
   142.5 +@ECHO OFF
   142.6 +\\ISI-PDC\perl\bin\perl \\ISI-PDC\perl\logon.pl ISI-PDC
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/lab/README	Mon Apr 26 11:16:23 2010 +0200
   143.3 @@ -0,0 +1,40 @@
   143.4 +Uso di netkit
   143.5 +-------------
   143.6 +
   143.7 +Pe rilanciare questo laboratorio occorre:
   143.8 +
   143.9 +  1. installare isi-netkit
  143.10 +
  143.11 +  2. copiare l'immagine
  143.12 +
  143.13 +     http://download.argolinux.org/isi/lenny-isi-netkit.img.bz2
  143.14 +
  143.15 +     in /usr/share/netkit/fs ed unzipparla
  143.16 +
  143.17 +  3. lanciare lstart da dentro questa cartella
  143.18 +
  143.19 +     A questo punto si apre una console grafica che è la console sulla
  143.20 +     macchina virtuale srv-isi, il cui ip è 172.16.0.11 per cui potete
  143.21 +     aggiungere nella vostra macchina in /etc/hosts::
  143.22 +
  143.23 +       172.16.0.11 web.isi.lan srv-isi.isi.lan
  143.24 +
  143.25 +    
  143.26 +     Questa macchina virtuale quando parte lancia automaticamente tutti i
  143.27 +     comandid che ci sono nel file srv-isi.startup, in particolare lancia:
  143.28 +
  143.29 +       isi-setup isi srv-isi isi
  143.30 +
  143.31 +    Potete connettervi a questa macchina virtuale via ssh
  143.32 +
  143.33 +  4. per lanciare i test, andate nella cartella 'tests' seguite le istruzioni
  143.34 +     la dentro.
  143.35 +        
  143.36 +
  143.37 +
  143.38 +
  143.39 +
  143.40 +
  143.41 +     
  143.42 +
  143.43 +
   144.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.2 +++ b/lab/lab.conf	Mon Apr 26 11:16:23 2010 +0200
   144.3 @@ -0,0 +1,16 @@
   144.4 +LAB_DESCRIPTION="Interfaccia Web per ReteISI"
   144.5 +LAB_VERSION="1.0"
   144.6 +LAB_AUTHOR="Sandro Dentella"
   144.7 +LAB_EMAIL="[email protected]"
   144.8 +LAB_WEB="http://reteisi.argolinux.org/reteisi"
   144.9 +
  144.10 +## sede
  144.11 +srv-isi[1]="lan1"
  144.12 +#
  144.13 +#srv-isi[eth0]=tap,172.16.0.254,172.16.0.1
  144.14 +srv-isi[eth0]=tap,192.168.50.254,192.168.50.1
  144.15 +srv-isi[m]=isi-lenny.img
  144.16 +#srv-isi[m]=alcatel
  144.17 +srv-isi[mem]=200
  144.18 +srv-isi[no-log]=
  144.19 +
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/lab/srv-isi.startup	Mon Apr 26 11:16:23 2010 +0200
   145.3 @@ -0,0 +1,9 @@
   145.4 +#!/bin/bash
   145.5 +
   145.6 +mount -o remount,acl /
   145.7 +isi-setup -UAT isi srv-isi isi
   145.8 +a2enmod rewrite
   145.9 +a2enmod expires
  145.10 +/etc/init.d/isiweb start
  145.11 +/etc/init.d/apache2 restart
  145.12 +
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/lab/srv-isi/etc/argo/fw.conf	Mon Apr 26 11:16:23 2010 +0200
   146.3 @@ -0,0 +1,32 @@
   146.4 +# this is meant to just allow ssh to configure it
   146.5 +
   146.6 +### variable definitions
   146.7 +# if LOG=1, a log chain is created to log all dropped packets
   146.8 +# take care: log can be a lot of space!
   146.9 +LOG=1
  146.10 +
  146.11 +INT=eth0
  146.12 +EXT=eth1
  146.13 +# LAN=192.168.0.0/24
  146.14 +TCP_DPORTS=" 22 80 443"
  146.15 +UDP_DPORTS=""
  146.16 +
  146.17 +# Input chains w/ 'tnl' in the name (expr match $name tnl -eq 3) will not
  146.18 +#   be considered by 'firewall' script
  146.19 +INPUT_CHAINS="int ext "
  146.20 +FWD_CHAINS="fwd "
  146.21 +
  146.22 +FORWARD=1
  146.23 +IP_MODE=dynamic
  146.24 +IP_EXT=
  146.25 +
  146.26 +# uncomment this for transparent proxy
  146.27 +# PROXY_REDIR_PORT=3128   
  146.28 +
  146.29 +# SSH_ADMINS="213.145.6.133 , 151.38.133.188 , 151.38.134.51 , 81.116.83.242"
  146.30 +
  146.31 +ICMP_TYPES=" 0 , 3 , 8 , 11 "
  146.32 +# 0 = echo reply
  146.33 +# 3 = dest unreachable
  146.34 +# 8 = echo request
  146.35 +# 11 = time exceeded for datagram
   147.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.2 +++ b/lab/srv-isi/etc/default/isiweb	Mon Apr 26 11:16:23 2010 +0200
   147.3 @@ -0,0 +1,1 @@
   147.4 +START_FSCI=1
   148.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.2 +++ b/lab/srv-isi/etc/dnsmasq.conf	Mon Apr 26 11:16:23 2010 +0200
   148.3 @@ -0,0 +1,98 @@
   148.4 +# -*- mode: conf -*-
   148.5 +# non inoltrare mai ai server dns esterni
   148.6 +# query senza nome dominio
   148.7 +domain-needed
   148.8 +
   148.9 +# Tutti i reverse lookup per la subnet privata
  148.10 +# non presenti in /etc/hosts o nei lease dhcp
  148.11 +# ottengono "host not found"
  148.12 +# invece di essere inoltrati ai dns esterni
  148.13 +bogus-priv
  148.14 +
  148.15 +# Filtra le ricorrenti richieste SOA, SRV e altre,
  148.16 +# provenienti da macchine windows
  148.17 +# serve in particolare a non attivare
  148.18 +# per sbaglio il link quando si
  148.19 +# hanno connessioni "on demand"
  148.20 +filterwin2k
  148.21 +
  148.22 +# server dns esterni di riferimento
  148.23 +# inserire i server dns uno per riga
  148.24 +# usati in questo caso i server di opendns.org
  148.25 +server=208.67.220.220
  148.26 +server=208.67.220.220
  148.27 +
  148.28 +# aggiunge sempre il nome dominio al nome host
  148.29 +expand-hosts
  148.30 +
  148.31 +# nome del mio dominio
  148.32 +domain=vega.it
  148.33 +
  148.34 +# Se si intende passare ai client un dominio differente
  148.35 +# dhcp-option=option:domain-name,isi.lan
  148.36 +
  148.37 +# range dei lease dhcp: indirizzo iniziale, indirizzo finale, netmask, durata del lease
  148.38 +dhcp-range=192.168.50.130,192.168.50.140,255.255.255.0,8h
  148.39 +
  148.40 +# Range dhcp per-tag
  148.41 +# ~~~~~~~~~~~~~~~~~~~
  148.42 +# E` anche possibile riservare un determinato range filtrando per TAG.
  148.43 +# I tag possono essere associati anche ad un'intera famiglia di indirizzi MAC
  148.44 +# Ciò risulta utilissimo, ad esempio, per limitare le macchine virtuali vmware
  148.45 +# ad un certo range.
  148.46 +#
  148.47 +# Settare il tag "macchinevmware" per le macchine con mac iniziante per
  148.48 +# 00:0c:29:*:*:* (gruppo di indirizzi mac riservati a vmware)
  148.49 +#
  148.50 +#   dhcp-mac=macchinevmware,00:0c:29:*:*:*
  148.51 +#
  148.52 +# Sintassi ::
  148.53 +#
  148.54 +#   dhcp-range=[[net:]network-id,]<start-addr>,<end-addr>[[,<net‐netmask>],<broadcast>][,<lease time>]
  148.55 +#
  148.56 +# Esempio ::
  148.57 +#
  148.58 +# dhcp-range=net:macchinevmware,192.168.150,160,255.255.255.0,8h
  148.59 +
  148.60 +
  148.61 +# Esempio di ip-reservation per client
  148.62 +#
  148.63 +# MAC address, indirizzo, nome host, tag(utile per associare a più server)
  148.64 +#
  148.65 +# dhcp-host=00:0c:29:c9:69:35,192.168.96.190,vm-ltsp01,net:ns1  # client1
  148.66 +# dhcp-host=00:0c:29:5e:69:b5,192.168.96.191,vm-ltsp02,net:ns2  # client2
  148.67 +#
  148.68 +# le associazioni vengono definite esternamente, vedi inclusioni a fine file.
  148.69 +# il file usato è /etc/isi/dns/dnsmasq/hosts.mac
  148.70 +
  148.71 +# dnsmasq supporta la maggior parte delle
  148.72 +# opzioni dhcp e bootp specificate in
  148.73 +# http://www.faqs.org/rfcs/rfc2132.html
  148.74 +# la sintassi e':
  148.75 +# dhcp-option=[numero relativo all'opzione],parametro
  148.76 +
  148.77 +# GATEWAY di default (3)
  148.78 +dhcp-option=44,192.168.50.1
  148.79 +
  148.80 +# DNS da passare ai client (6)
  148.81 +dhcp-option=6,192.168.50.1
  148.82 +
  148.83 +# WINS da passare ai client (44)
  148.84 +dhcp-option=44,192.168.96.1
  148.85 +#
  148.86 +# Il server dhcp sarà AUTORITATIVO.
  148.87 +dhcp-authoritative
  148.88 +cache-size=1024
  148.89 +### LOG
  148.90 +# da usare per debug
  148.91 +log-queries
  148.92 +
  148.93 +# Da abilitare *solo* in caso di debug, logga tutte le transazioni che avvengono
  148.94 +# tra servente DHCP e i client.
  148.95 +#
  148.96 +log-dhcp
  148.97 +
  148.98 +# Configurazione aggiuntiva per isi.
  148.99 +conf-file=/etc/isi/dnsmasq/boot
 148.100 +conf-file=/etc/isi/dnsmasq/hosts.mac
 148.101 +dhcp-option=3,192.168.50.254
 148.102 \ No newline at end of file
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/lab/srv-isi/etc/hosts	Mon Apr 26 11:16:23 2010 +0200
   149.3 @@ -0,0 +1,7 @@
   149.4 +127.0.0.1  localhost
   149.5 +#172.16.0.254  srv-isi web.isi.lan
   149.6 +#172.16.0.1  gw
   149.7 +
   149.8 +192.168.50.254  srv-isi web.isi.lan
   149.9 +192.168.50.1  gw
  149.10 +
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/lab/srv-isi/etc/init.d/isiweb	Mon Apr 26 11:16:23 2010 +0200
   150.3 @@ -0,0 +1,144 @@
   150.4 +#! /bin/sh
   150.5 +### BEGIN INIT INFO
   150.6 +# Provides:          skeleton
   150.7 +# Required-Start:    $remote_fs
   150.8 +# Required-Stop:     $remote_fs
   150.9 +# Default-Start:     2 3 4 5
  150.10 +# Default-Stop:      0 1 6
  150.11 +# Short-Description: Example initscript
  150.12 +# Description:       This file should be used to construct scripts to be
  150.13 +#                    placed in /etc/init.d.
  150.14 +### END INIT INFO
  150.15 +
  150.16 +# Author: Foo Bar <[email protected]>
  150.17 +#
  150.18 +# Please remove the "Author" lines above and replace them
  150.19 +# with your own name if you copy and modify this script.
  150.20 +
  150.21 +# Do NOT "set -e"
  150.22 +
  150.23 +# PATH should only include /usr/* if it runs after the mountnfs.sh script
  150.24 +PATH=/sbin:/usr/sbin:/bin:/usr/bin
  150.25 +DESC="Interfaccia Web per ReteISI"
  150.26 +NAME=isiweb
  150.27 +#DAEMON=/usr/sbin/$NAME
  150.28 +DAEMON_ARGS="socket=$SOCKET pidfile=$PIDFILE"
  150.29 +PIDFILE=/var/run/$NAME.pid
  150.30 +SCRIPTNAME=/etc/init.d/$NAME
  150.31 +SOCKET=/var/run/$NAME.sock
  150.32 +PROJDIR="/usr/share/isi/isiweb/"
  150.33 +#DAEMON_ARGS="socket=$SOCKET pidfile=$PIDFILE maxspare=1"
  150.34 +DAEMON_ARGS="host=127.0.0.1 port=3033 pidfile=$PIDFILE maxspare=1 errlog=/var/log/isiweb.log"
  150.35 +
  150.36 +# # Exit if the package is not installed
  150.37 +# [ -x "$DAEMON" ] || exit 0
  150.38 +
  150.39 +# Read configuration variable file if it is present
  150.40 +[ -r /etc/default/$NAME ] && . /etc/default/$NAME
  150.41 +
  150.42 +# Load the VERBOSE setting and other rcS variables
  150.43 +. /lib/init/vars.sh
  150.44 +
  150.45 +# Define LSB log_* functions.
  150.46 +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
  150.47 +. /lib/lsb/init-functions
  150.48 +
  150.49 +#
  150.50 +# Function that starts the daemon/service
  150.51 +#
  150.52 +do_start()
  150.53 +{
  150.54 +    do_stop
  150.55 +    cd $PROJDIR
  150.56 +    if [ $START_FSCI = 1 ] ; then
  150.57 +       echo "Starting $DESC" $NAME
  150.58 +       exec /usr/bin/env - \
  150.59 +	 PYTHONPATH="../python:.." ./manage.py runfcgi $DAEMON_ARGS
  150.60 +       RETVAL=$?
  150.61 +       echo -e "\n"
  150.62 +       return $RETVAL
  150.63 +    else
  150.64 +       echo "You must enable in /etc/default/isiweb: START_FSCI=1"
  150.65 +    fi
  150.66 +
  150.67 +}
  150.68 +
  150.69 +#
  150.70 +# Function that stops the daemon/service
  150.71 +#
  150.72 +do_stop()
  150.73 +{
  150.74 +     cd $PROJDIR
  150.75 +     if [ -f $PIDFILE ]; then
  150.76 +         kill `cat -- $PIDFILE`
  150.77 +	 RETVAL=$?
  150.78 +         rm -f -- $PIDFILE
  150.79 +     fi
  150.80 +    return $RETVAL
  150.81 +}
  150.82 +
  150.83 +#
  150.84 +# Function that sends a SIGHUP to the daemon/service
  150.85 +#
  150.86 +# do_reload() {
  150.87 +
  150.88 +#   do_stop()
  150.89 +#   do_start()
  150.90 +# }
  150.91 +
  150.92 +case "$1" in
  150.93 +  start)
  150.94 +	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
  150.95 +	do_start
  150.96 +	case "$?" in
  150.97 +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
  150.98 +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
  150.99 +	esac
 150.100 +	;;
 150.101 +  stop)
 150.102 +	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
 150.103 +	do_stop
 150.104 +	case "$?" in
 150.105 +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
 150.106 +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
 150.107 +	esac
 150.108 +	;;
 150.109 +  #reload|force-reload)
 150.110 +	#
 150.111 +	# If do_reload() is not implemented then leave this commented out
 150.112 +	# and leave 'force-reload' as an alias for 'restart'.
 150.113 +	#
 150.114 +	#log_daemon_msg "Reloading $DESC" "$NAME"
 150.115 +	#do_reload
 150.116 +	#log_end_msg $?
 150.117 +	#;;
 150.118 +  restart|force-reload)
 150.119 +	#
 150.120 +	# If the "reload" option is implemented then remove the
 150.121 +	# 'force-reload' alias
 150.122 +	#
 150.123 +	log_daemon_msg "Restarting $DESC" "$NAME"
 150.124 +	do_stop
 150.125 +	case "$?" in
 150.126 +	  0|1)
 150.127 +		do_start
 150.128 +		case "$?" in
 150.129 +			0) log_end_msg 0 ;;
 150.130 +			1) log_end_msg 1 ;; # Old process is still running
 150.131 +			*) log_end_msg 1 ;; # Failed to start
 150.132 +		esac
 150.133 +		;;
 150.134 +	  *)
 150.135 +	  	# Failed to stop
 150.136 +		log_end_msg 1
 150.137 +		;;
 150.138 +	esac
 150.139 +	;;
 150.140 +  *)
 150.141 +	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
 150.142 +	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
 150.143 +	exit 3
 150.144 +	;;
 150.145 +esac
 150.146 +
 150.147 +:
   151.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.2 +++ b/lab/srv-isi/etc/isi/dnsmasq/boot	Mon Apr 26 11:16:23 2010 +0200
   151.3 @@ -0,0 +1,30 @@
   151.4 +# le prossime sono quelle che servono
   151.5 +# in particolare ai thin client
   151.6 +# root-path (17)
   151.7 +# percorso dove montare la partizione root, usata con nfs
   151.8 +# dhcp-option=17,"/opt/ltsp/i386"
   151.9 +
  151.10 +# file di boot (percorso relativo alla root del server tftp),
  151.11 +# nome tftp server, ip tftp server
  151.12 +# l'indirizzo e il nome del server
  151.13 +# devono essere inseriti in /etc/hosts
  151.14 +dhcp-boot=/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222
  151.15 +
  151.16 +# file di boot (percorso relativo alla root del server tftp),
  151.17 +# nome tftp server, ip tftp server
  151.18 +# l'indirizzo e il nome del server
  151.19 +# devono essere inseriti in /etc/hosts
  151.20 +#dhcp-boot=/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222
  151.21 +
  151.22 +# PXE / Etherboot
  151.23 +#dhcp-vendorclass=pxe,PXEClient
  151.24 +#dhcp-vendorclass=eth,Etherboot
  151.25 +#    dhcp-option=vendor:PXEClient,1,0.0.0.0
  151.26 +dhcp-boot=net:thin_srv1,/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222
  151.27 +dhcp-boot=net:fat_srv1,/ltsp/ifat386/pxelinux.0,ltsp-server, 192.168.96.222
  151.28 +dhcp-boot=net:fat_srv2,/ltsp/ifat386/pxelinux.0,ltsp-server, 192.168.96.224
  151.29 +
  151.30 +# other
  151.31 +dhcp-boot=net:gpxe,/ltsp/i386/nbi.img,ltsp-server,192.168.96.222
  151.32 +# default
  151.33 +dhcp-boot=/ltsp/ifat386/pxelinux.0,ltsp-server, 192.168.96.222
   152.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.2 +++ b/lab/srv-isi/etc/isi/dnsmasq/hosts.mac	Mon Apr 26 11:16:23 2010 +0200
   152.3 @@ -0,0 +1,3 @@
   152.4 +dhcp-host=00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1
   152.5 +dhcp-host=00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2,net:ns1
   152.6 +dhcp-host=00:0c:29:10:a6:48,192.168.5.55
   152.7 \ No newline at end of file
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/lab/srv-isi/etc/isi/web/local_settings.py	Mon Apr 26 11:16:23 2010 +0200
   153.3 @@ -0,0 +1,7 @@
   153.4 +LOGON_FILE = '/etc/isi/logon.conf'
   153.5 +SAMBA_FILE = '/etc/samba/smb.conf'
   153.6 +DNSMASQ_CONF = '/etc/dnsmasq.conf'
   153.7 +HOSTS_CONF = '/etc/hosts'
   153.8 +MAC_CONF = '/etc/isi/dnsmasq/hosts.mac'
   153.9 +LEASES_FILE = '/var/lib/misc/dnsmasq.leases'
  153.10 +BOOT_CONF = '/etc/isi/dnsmasq/boot'
   154.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.2 +++ b/lab/srv-isi/etc/libnss-ldap.conf	Mon Apr 26 11:16:23 2010 +0200
   154.3 @@ -0,0 +1,323 @@
   154.4 +###DEBCONF###
   154.5 +# the configuration of this file will be done by debconf as long as the
   154.6 +# first line of the file says '###DEBCONF###'
   154.7 +#
   154.8 +# you should use dpkg-reconfigure libnss-ldap to configure this file.
   154.9 +#
  154.10 +# @(#)$Id: ldap.conf,v 2.48 2021/07/03 02:30:29 lukeh Exp $
  154.11 +#
  154.12 +# This is the configuration file for the LDAP nameservice
  154.13 +# switch library and the LDAP PAM module.
  154.14 +#
  154.15 +# PADL Software
  154.16 +# http://www.padl.com
  154.17 +#
  154.18 +
  154.19 +# Your LDAP server. Must be resolvable without using LDAP.
  154.20 +# Multiple hosts may be specified, each separated by a 
  154.21 +# space. How long nss_ldap takes to failover depends on
  154.22 +# whether your LDAP client library supports configurable
  154.23 +# network or connect timeouts (see bind_timelimit).
  154.24 +#host 127.0.0.1
  154.25 +
  154.26 +# The distinguished name of the search base.
  154.27 +base dc=example,dc=net
  154.28 +
  154.29 +# Another way to specify your LDAP server is to provide an
  154.30 +uri ldapi:///
  154.31 +# Unix Domain Sockets to connect to a local LDAP Server.
  154.32 +#uri ldap://127.0.0.1/
  154.33 +#uri ldaps://127.0.0.1/   
  154.34 +#uri ldapi://%2fvar%2frun%2fldapi_sock/
  154.35 +# Note: %2f encodes the '/' used as directory separator
  154.36 +
  154.37 +# The LDAP version to use (defaults to 3
  154.38 +# if supported by client library)
  154.39 +ldap_version 3
  154.40 +
  154.41 +# The distinguished name to bind to the server with.
  154.42 +# Optional: default is to bind anonymously.
  154.43 +# Please do not put double quotes around it as they
  154.44 +# would be included literally.
  154.45 +#binddn cn=proxyuser,dc=padl,dc=com
  154.46 +
  154.47 +# The credentials to bind with. 
  154.48 +# Optional: default is no credential.
  154.49 +#bindpw secret
  154.50 +
  154.51 +# The distinguished name to bind to the server with
  154.52 +# if the effective user ID is root. Password is
  154.53 +# stored in /etc/libnss-ldap.secret (mode 600)
  154.54 +# Use 'echo -n "mypassword" > /etc/libnss-ldap.secret' instead
  154.55 +# of an editor to create the file.
  154.56 +rootbinddn cn=manager,dc=example,dc=net
  154.57 +
  154.58 +# The port.
  154.59 +# Optional: default is 389.
  154.60 +#port 389
  154.61 +
  154.62 +# The search scope.
  154.63 +#scope sub
  154.64 +#scope one
  154.65 +#scope base
  154.66 +
  154.67 +# Search timelimit
  154.68 +#timelimit 30
  154.69 +
  154.70 +# Bind/connect timelimit
  154.71 +bind_timelimit 3
  154.72 +
  154.73 +# Reconnect policy:
  154.74 +#  hard_open: reconnect to DSA with exponential backoff if
  154.75 +#             opening connection failed
  154.76 +#  hard_init: reconnect to DSA with exponential backoff if
  154.77 +#             initializing connection failed
  154.78 +#  hard:      alias for hard_open
  154.79 +#  soft:      return immediately on server failure
  154.80 +bind_policy soft
  154.81 +
  154.82 +# Connection policy:
  154.83 +#  persist:   DSA connections are kept open (default)
  154.84 +#  oneshot:   DSA connections destroyed after request
  154.85 +#nss_connect_policy persist
  154.86 +
  154.87 +# Idle timelimit; client will close connections
  154.88 +# (nss_ldap only) if the server has not been contacted
  154.89 +# for the number of seconds specified below.
  154.90 +#idle_timelimit 3600
  154.91 +
  154.92 +# Use paged rseults
  154.93 +#nss_paged_results yes
  154.94 +
  154.95 +# Pagesize: when paged results enable, used to set the
  154.96 +# pagesize to a custom value
  154.97 +#pagesize 1000
  154.98 +
  154.99 +# Filter to AND with uid=%s
 154.100 +#pam_filter objectclass=account
 154.101 +
 154.102 +# The user ID attribute (defaults to uid)
 154.103 +#pam_login_attribute uid
 154.104 +
 154.105 +# Search the root DSE for the password policy (works
 154.106 +# with Netscape Directory Server)
 154.107 +#pam_lookup_policy yes
 154.108 +
 154.109 +# Check the 'host' attribute for access control
 154.110 +# Default is no; if set to yes, and user has no
 154.111 +# value for the host attribute, and pam_ldap is
 154.112 +# configured for account management (authorization)
 154.113 +# then the user will not be allowed to login.
 154.114 +#pam_check_host_attr yes
 154.115 +
 154.116 +# Check the 'authorizedService' attribute for access
 154.117 +# control
 154.118 +# Default is no; if set to yes, and the user has no
 154.119 +# value for the authorizedService attribute, and
 154.120 +# pam_ldap is configured for account management
 154.121 +# (authorization) then the user will not be allowed
 154.122 +# to login.
 154.123 +#pam_check_service_attr yes
 154.124 +
 154.125 +# Group to enforce membership of
 154.126 +#pam_groupdn cn=PAM,ou=Groups,dc=padl,dc=com
 154.127 +
 154.128 +# Group member attribute
 154.129 +#pam_member_attribute uniquemember
 154.130 +
 154.131 +# Specify a minium or maximum UID number allowed
 154.132 +#pam_min_uid 0
 154.133 +#pam_max_uid 0
 154.134 +
 154.135 +# Template login attribute, default template user
 154.136 +# (can be overriden by value of former attribute
 154.137 +# in user's entry)
 154.138 +#pam_login_attribute userPrincipalName
 154.139 +#pam_template_login_attribute uid
 154.140 +#pam_template_login nobody
 154.141 +
 154.142 +# HEADS UP: the pam_crypt, pam_nds_passwd,
 154.143 +# and pam_ad_passwd options are no
 154.144 +# longer supported.
 154.145 +#
 154.146 +# Do not hash the password at all; presume
 154.147 +# the directory server will do it, if
 154.148 +# necessary. This is the default.
 154.149 +#pam_password clear
 154.150 +
 154.151 +# Hash password locally; required for University of
 154.152 +# Michigan LDAP server, and works with Netscape
 154.153 +# Directory Server if you're using the UNIX-Crypt
 154.154 +# hash mechanism and not using the NT Synchronization
 154.155 +# service. 
 154.156 +#pam_password crypt
 154.157 +
 154.158 +# Remove old password first, then update in
 154.159 +# cleartext. Necessary for use with Novell
 154.160 +# Directory Services (NDS)
 154.161 +#pam_password nds
 154.162 +
 154.163 +# RACF is an alias for the above. For use with
 154.164 +# IBM RACF
 154.165 +#pam_password racf
 154.166 +
 154.167 +# Update Active Directory password, by
 154.168 +# creating Unicode password and updating
 154.169 +# unicodePwd attribute.
 154.170 +#pam_password ad
 154.171 +
 154.172 +# Use the OpenLDAP password change
 154.173 +# extended operation to update the password.
 154.174 +#pam_password exop
 154.175 +
 154.176 +# Redirect users to a URL or somesuch on password
 154.177 +# changes.
 154.178 +#pam_password_prohibit_message Please visit http://internal to change your password.
 154.179 +
 154.180 +# Use backlinks for answering initgroups()
 154.181 +#nss_initgroups backlink
 154.182 +
 154.183 +# Enable support for RFC2307bis (distinguished names in group
 154.184 +# members)
 154.185 +#nss_schema rfc2307bis
 154.186 +
 154.187 +# RFC2307bis naming contexts
 154.188 +# Syntax:
 154.189 +# nss_base_XXX		base?scope?filter
 154.190 +# where scope is {base,one,sub}
 154.191 +# and filter is a filter to be &'d with the
 154.192 +# default filter.
 154.193 +# You can omit the suffix eg:
 154.194 +# nss_base_passwd	ou=People,
 154.195 +# to append the default base DN but this
 154.196 +# may incur a small performance impact.
 154.197 +#nss_base_passwd	ou=People,dc=padl,dc=com?one
 154.198 +#nss_base_shadow	ou=People,dc=padl,dc=com?one
 154.199 +#nss_base_group		ou=Group,dc=padl,dc=com?one
 154.200 +#nss_base_hosts		ou=Hosts,dc=padl,dc=com?one
 154.201 +#nss_base_services	ou=Services,dc=padl,dc=com?one
 154.202 +#nss_base_networks	ou=Networks,dc=padl,dc=com?one
 154.203 +#nss_base_protocols	ou=Protocols,dc=padl,dc=com?one
 154.204 +#nss_base_rpc		ou=Rpc,dc=padl,dc=com?one
 154.205 +#nss_base_ethers	ou=Ethers,dc=padl,dc=com?one
 154.206 +#nss_base_netmasks	ou=Networks,dc=padl,dc=com?ne
 154.207 +#nss_base_bootparams	ou=Ethers,dc=padl,dc=com?one
 154.208 +#nss_base_aliases	ou=Aliases,dc=padl,dc=com?one
 154.209 +#nss_base_netgroup	ou=Netgroup,dc=padl,dc=com?one
 154.210 +
 154.211 +# attribute/objectclass mapping
 154.212 +# Syntax:
 154.213 +#nss_map_attribute	rfc2307attribute	mapped_attribute
 154.214 +#nss_map_objectclass	rfc2307objectclass	mapped_objectclass
 154.215 +
 154.216 +# configure --enable-nds is no longer supported.
 154.217 +# NDS mappings
 154.218 +#nss_map_attribute uniqueMember member
 154.219 +
 154.220 +# Services for UNIX 3.5 mappings
 154.221 +#nss_map_objectclass posixAccount User
 154.222 +#nss_map_objectclass shadowAccount User
 154.223 +#nss_map_attribute uid msSFU30Name
 154.224 +#nss_map_attribute uniqueMember msSFU30PosixMember
 154.225 +#nss_map_attribute userPassword msSFU30Password
 154.226 +#nss_map_attribute homeDirectory msSFU30HomeDirectory
 154.227 +#nss_map_attribute homeDirectory msSFUHomeDirectory
 154.228 +#nss_map_objectclass posixGroup Group
 154.229 +#pam_login_attribute msSFU30Name
 154.230 +#pam_filter objectclass=User
 154.231 +#pam_password ad
 154.232 +
 154.233 +# configure --enable-mssfu-schema is no longer supported.
 154.234 +# Services for UNIX 2.0 mappings
 154.235 +#nss_map_objectclass posixAccount User
 154.236 +#nss_map_objectclass shadowAccount user
 154.237 +#nss_map_attribute uid msSFUName
 154.238 +#nss_map_attribute uniqueMember posixMember
 154.239 +#nss_map_attribute userPassword msSFUPassword
 154.240 +#nss_map_attribute homeDirectory msSFUHomeDirectory
 154.241 +#nss_map_attribute shadowLastChange pwdLastSet
 154.242 +#nss_map_objectclass posixGroup Group
 154.243 +#nss_map_attribute cn msSFUName
 154.244 +#pam_login_attribute msSFUName
 154.245 +#pam_filter objectclass=User
 154.246 +#pam_password ad
 154.247 +
 154.248 +# RFC 2307 (AD) mappings
 154.249 +#nss_map_objectclass posixAccount user
 154.250 +#nss_map_objectclass shadowAccount user
 154.251 +#nss_map_attribute uid sAMAccountName
 154.252 +#nss_map_attribute homeDirectory unixHomeDirectory
 154.253 +#nss_map_attribute shadowLastChange pwdLastSet
 154.254 +#nss_map_objectclass posixGroup group
 154.255 +#nss_map_attribute uniqueMember member
 154.256 +#pam_login_attribute sAMAccountName
 154.257 +#pam_filter objectclass=User
 154.258 +#pam_password ad
 154.259 +
 154.260 +# configure --enable-authpassword is no longer supported
 154.261 +# AuthPassword mappings
 154.262 +#nss_map_attribute userPassword authPassword
 154.263 +
 154.264 +# AIX SecureWay mappings
 154.265 +#nss_map_objectclass posixAccount aixAccount
 154.266 +#nss_base_passwd ou=aixaccount,?one
 154.267 +#nss_map_attribute uid userName
 154.268 +#nss_map_attribute gidNumber gid
 154.269 +#nss_map_attribute uidNumber uid
 154.270 +#nss_map_attribute userPassword passwordChar
 154.271 +#nss_map_objectclass posixGroup aixAccessGroup
 154.272 +#nss_base_group ou=aixgroup,?one
 154.273 +#nss_map_attribute cn groupName
 154.274 +#nss_map_attribute uniqueMember member
 154.275 +#pam_login_attribute userName
 154.276 +#pam_filter objectclass=aixAccount
 154.277 +#pam_password clear
 154.278 +
 154.279 +# For pre-RFC2307bis automount schema
 154.280 +#nss_map_objectclass automountMap nisMap
 154.281 +#nss_map_attribute automountMapName nisMapName
 154.282 +#nss_map_objectclass automount nisObject
 154.283 +#nss_map_attribute automountKey cn
 154.284 +#nss_map_attribute automountInformation nisMapEntry
 154.285 +
 154.286 +# Netscape SDK LDAPS
 154.287 +#ssl on
 154.288 +
 154.289 +# Netscape SDK SSL options
 154.290 +#sslpath /etc/ssl/certs
 154.291 +
 154.292 +# OpenLDAP SSL mechanism
 154.293 +# start_tls mechanism uses the normal LDAP port, LDAPS typically 636
 154.294 +#ssl start_tls
 154.295 +#ssl on
 154.296 +
 154.297 +# OpenLDAP SSL options
 154.298 +# Require and verify server certificate (yes/no)
 154.299 +# Default is to use libldap's default behavior, which can be configured in
 154.300 +# /etc/openldap/ldap.conf using the TLS_REQCERT setting.  The default for
 154.301 +# OpenLDAP 2.0 and earlier is "no", for 2.1 and later is "yes".
 154.302 +#tls_checkpeer yes
 154.303 +
 154.304 +# CA certificates for server certificate verification
 154.305 +# At least one of these are required if tls_checkpeer is "yes"
 154.306 +#tls_cacertfile /etc/ssl/ca.cert
 154.307 +#tls_cacertdir /etc/ssl/certs
 154.308 +
 154.309 +# Seed the PRNG if /dev/urandom is not provided
 154.310 +#tls_randfile /var/run/egd-pool
 154.311 +
 154.312 +# SSL cipher suite
 154.313 +# See man ciphers for syntax
 154.314 +#tls_ciphers TLSv1
 154.315 +
 154.316 +# Client certificate and key
 154.317 +# Use these, if your server requires client authentication.
 154.318 +#tls_cert
 154.319 +#tls_key
 154.320 +
 154.321 +# Disable SASL security layers. This is needed for AD.
 154.322 +#sasl_secprops maxssf=0
 154.323 +
 154.324 +# Override the default Kerberos ticket cache location.
 154.325 +#krb5_ccname FILE:/etc/.ldapcache
 154.326 +
   155.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.2 +++ b/lab/srv-isi/etc/network/interfaces	Mon Apr 26 11:16:23 2010 +0200
   155.3 @@ -0,0 +1,3 @@
   155.4 +auto lo
   155.5 +iface lo inet loopback
   155.6 +
   156.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.2 +++ b/lab/srv-isi/root/.aptitude/config	Mon Apr 26 11:16:23 2010 +0200
   156.3 @@ -0,0 +1,2 @@
   156.4 +aptitude "";
   156.5 +aptitude::Ignore-Recommends-Important "true";
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/lab/srv-isi/root/.bash_history	Mon Apr 26 11:16:23 2010 +0200
   157.3 @@ -0,0 +1,312 @@
   157.4 +l
   157.5 +jmacs /etc/inittab
   157.6 +l
   157.7 +ls
   157.8 +ln -s ../init.d/netkit-phase1    /etc/rcS.d/S37netkit-phase1
   157.9 +ln -s ../init.d/S99netkit-phase2 /etc/rcS.d/S99netkit-phase2
  157.10 +l
  157.11 +cd /etc/init.d/
  157.12 +l
  157.13 +l
  157.14 +cd ..
  157.15 +cd rcS.d/
  157.16 +l
  157.17 +l
  157.18 +l
  157.19 +rm S99netkit-phase2 
  157.20 +ln -s ../init.d/netkit-phase2 /etc/rcS.d/S99netkit-phase2
  157.21 +l
  157.22 +ls /etc/rc*.d/*
  157.23 +ls /etc/rc*.d/fire*
  157.24 +ls /etc/rc*.d/*/fire*
  157.25 +ls /etc/rc*.d/*
  157.26 +ls /etc/rc*.d/*firew*
  157.27 +ls -l
  157.28 +ln -s ../init.d/firewall /etc/rcS.d/S38firewall
  157.29 +l
  157.30 +mv S99netkit-phase2 ../rc2.d/
  157.31 +cd ../rc2.d/
  157.32 +l
  157.33 +cd ..
  157.34 +l
  157.35 +cd rcS.d/
  157.36 +l
  157.37 +apt-get install -y openvpn
  157.38 +apt-cache search locale
  157.39 +apt-get install localepurge
  157.40 +dpkg-reconfigure localepurge
  157.41 +dpkg-reconfigure locale
  157.42 +apt-get install locales
  157.43 +apt-get update
  157.44 +dpkg-reconfigure locales
  157.45 +apt-get install -y openvpn squid 
  157.46 +mount
  157.47 +l
  157.48 +cd /etc/init.d/
  157.49 +l
  157.50 +cd ../
  157.51 +ls rc*.d
  157.52 +ls rc*.d/*squid
  157.53 +ls rc*.d/S*squid
  157.54 +rm rc*.d/S*squid
  157.55 +ls rc*.d/S*openvpn
  157.56 +rm rc*.d/S*openvpn
  157.57 +apt-get install -y dansguardian
  157.58 +l
  157.59 +ls rc*.d/S*dansg*
  157.60 +rm rc*.d/S*dansg*
  157.61 +apt-get install vtund
  157.62 +apt-get install vtun
  157.63 +ls rc*.d/S*vtun*
  157.64 +rm rc*.d/S*vtun*
  157.65 +ls rc*.d/S*samba*
  157.66 +ls /etc/rc*.d/S*samba*
  157.67 +ls /etc/rc*.d/S*postfix*
  157.68 +ls /etc/rc*.d/S*md*
  157.69 +rm /etc/rc*.d/S*md*
  157.70 +ls /etc/rc*.d/S*atop*
  157.71 +rm /etc/rc*.d/S*atop*
  157.72 +apt-get install mingetty
  157.73 +jmacs /etc/inittab
  157.74 +jmacs /etc/inittab
  157.75 +l
  157.76 +l
  157.77 +l
  157.78 +l
  157.79 +cd /etc/rcS.d/
  157.80 +l
  157.81 +cp /etc/rc2.d/S99netkit-phase2 .
  157.82 +l
  157.83 +rm S99netkit-phase2 
  157.84 +ln -s ../init.d/netkit-phase2 S99netkit-phase2
  157.85 +l
  157.86 +rm ../rc2.d/S99netkit-phase2 
  157.87 +l
  157.88 +dpkg-reconfigure firewall
  157.89 +l
  157.90 +l
  157.91 +l
  157.92 +cd /etc/
  157.93 +cd rcS.d/
  157.94 +l
  157.95 +rm S99netkit-phase2 
  157.96 +cd ../rc2.d/
  157.97 +ln -s ../init.d/netkit-phase2 S99netkit-phase2
  157.98 +l
  157.99 +l
 157.100 +find . -uid 1001
 157.101 +dpkg-reconfigure locales
 157.102 +jmacs /etc/inittab
 157.103 +cd /etc/
 157.104 +ls rc*d
 157.105 +ls rc*d/S*
 157.106 +ls rc*d/S*samba*
 157.107 +rm rc*d/S*samba*
 157.108 +rm rc*d/S*postfix*
 157.109 +rm rc*d/S*nscd*
 157.110 +rm rc*d/S*slapd*
 157.111 +rm rc*d/S*rsync*
 157.112 +rm rc*d/S*clama*
 157.113 +ls rc*d/S*samba*
 157.114 +rm rc*d/S**
 157.115 +l rc*d/
 157.116 +l
 157.117 +l rc*d/
 157.118 +ls /etc/rc*
 157.119 +l
 157.120 +dpkg -l | grep open
 157.121 +dpkg -l | grep pyre
 157.122 +dpkg -l | grep isi
 157.123 +cat /etc/squid/squid.conf 
 157.124 +cat /etc/squid/squid.conf |egrep -v "^#"
 157.125 +cat /etc/squid/squid.conf |egrep -v "^#|^$"
 157.126 +l
 157.127 +dpkg -l |grep nma
 157.128 +dpkg -l |grep smb
 157.129 +dpkg -l |grep sam
 157.130 +dpkg -l |grep isi
 157.131 +apt-get update
 157.132 +jmacs /etc/apt/sources.list
 157.133 +apt-get update
 157.134 +jmacs /etc/apt/sources.list
 157.135 +apt-get update
 157.136 +apt-get install tshark
 157.137 +l
 157.138 +aptitude clean
 157.139 +aptitude autoclean
 157.140 +l
 157.141 +ls /etc/
 157.142 +rm /etc/*~
 157.143 +ls /root/
 157.144 +l
 157.145 +apt-get update
 157.146 +apt-get install -y pyrewall
 157.147 +dpkg -l | grep twire
 157.148 +apt-get install twireshark
 157.149 +cd
 157.150 +cd /root/
 157.151 +jmacs /etc/bash.bashrc 
 157.152 +. /etc/bash.bashrc 
 157.153 +ipl
 157.154 +ls
 157.155 +l
 157.156 +apt-cache search
 157.157 +apt-cache search lsb
 157.158 +apt-get install lsb-release
 157.159 +lsb_release -a
 157.160 +ipl
 157.161 +ipl
 157.162 +ipl
 157.163 +ipl
 157.164 +ipl
 157.165 +ipl
 157.166 +l
 157.167 +cd /etc/init.d/
 157.168 +l
 157.169 +cd ..
 157.170 +cd rc0.d/
 157.171 +l
 157.172 +l
 157.173 +cd ../rc1.d/
 157.174 +l
 157.175 +cd ../rc2.d/
 157.176 +l
 157.177 +l
 157.178 +l
 157.179 +ipl
 157.180 +ls -l /tmp/
 157.181 +ls -l /tmp/
 157.182 +l
 157.183 +ls
 157.184 +l
 157.185 +l
 157.186 +cat /etc/init.d/netkit-phase1 
 157.187 +cd /etc/rc2.d/
 157.188 +l
 157.189 +l
 157.190 +l
 157.191 +cat $(which isi-setup )
 157.192 +l
 157.193 +apt-get install mercurial nscd at acl quota tofrodos procinfo reiserfsprogs xfsprogs slapd libnss-ldap libpam-ldap  libnet-ldap-perl samba smbldap-tools migrationtools db4.2-util python-ldap python-dry python-urwid python-isi win-perl isi libcrack2
 157.194 +aptitude update
 157.195 +apt-get install mercurial nscd at acl quota tofrodos procinfo reiserfsprogs xfsprogs slapd libnss-ldap libpam-ldap  libnet-ldap-perl samba smbldap-tools migrationtools db4.2-util python-ldap python-dry python-urwid python-isi win-perl isi libcrack2
 157.196 +apt-get install mercurial nscd at acl quota tofrodos procinfo reiserfsprogs xfsprogs slapd libnss-ldap libpam-ldap  libnet-ldap-perl samba smbldap-tools migrationtools db4.2-util python-ldap python-dry python-urwid python-isi win-perl isi libcrack2
 157.197 +apt-get install mercurial nscd at acl quota tofrodos procinfo reiserfsprogs xfsprogs slapd libnss-ldap libpam-ldap  libnet-ldap-perl samba smbldap-tools migrationtools db4.2-util python-ldap python-dry python-urwid python-isi win-perl isi libcrack2
 157.198 +mount /proc/
 157.199 +apt-get install mercurial nscd at acl quota tofrodos procinfo reiserfsprogs xfsprogs slapd libnss-ldap libpam-ldap  libnet-ldap-perl samba smbldap-tools migrationtools db4.2-util python-ldap python-dry python-urwid python-isi win-perl isi libcrack2
 157.200 +apt-get install libapache2-mod-wsgi dnsmasq apache2
 157.201 +apt-get install python-mako libjs-jquery libjs-jquery-ui
 157.202 +aptitude show python-django
 157.203 +apt-cache search python-django
 157.204 +jmacs /etc/apt/sources.list
 157.205 +aptitude udate
 157.206 +aptitude update
 157.207 +jmacs /etc/apt/sources.list
 157.208 +aptitude update
 157.209 +cd /tmp/
 157.210 +wget http://www.backports.org/debian/pool/main/p/python-django/python-django_1.1.1-1~bpo50+1_all.deb
 157.211 +dpkg -i python-django_1.1.1-1~bpo50+1_all.deb 
 157.212 +apt-show python-mako
 157.213 +apt-cache show python-mako
 157.214 +apt-get install python-mako
 157.215 +apt-cache show libjs-jquery
 157.216 +apt-et install  libjs-jquery
 157.217 +apt-get install  libjs-jquery
 157.218 +apt-get install  libjs-jquery-ui
 157.219 +aptitude show jquery
 157.220 +aptitude search jquery
 157.221 +wget      http://http.us.debian.org/debian/pool/main/j/jqueryui/libjs-jquery-ui_1.7.2-1_all.deb
 157.222 +dpkg -i libjs-jquery-ui_1.7.2-1_all.deb 
 157.223 +wget http://ftp.us.debian.org/debian/pool/main/j/jquery/libjs-jquery_1.4-1_all.deb
 157.224 +dpkg -i libjs-jquery_1.4-1_all.deb 
 157.225 +dpkg -i libjs-jquery-ui_1.7.2-1_all.deb 
 157.226 +dpkg -l | grep libjs
 157.227 +l
 157.228 +dpkg -l | grep dhcp
 157.229 +apt-get install dnsmasq apache2
 157.230 +l
 157.231 +cat /etc/samba/smb.conf 
 157.232 +cat /etc/samba/smb.conf 
 157.233 +umount  /proc/
 157.234 +edit /usr/sbin/isi-setup 
 157.235 +emacs /usr/sbin/isi-setup 
 157.236 +jmacs /usr/sbin/isi-setup 
 157.237 +l
 157.238 +ls /etc/rc*
 157.239 +l /etc/rc*
 157.240 +tree -L /etc/rc*
 157.241 +tree -L 2 /etc/rc*
 157.242 +tree -L 2 /etc/rc*|grep -i slap
 157.243 +l
 157.244 +apt-get install ipython
 157.245 +apt-get update
 157.246 +gpg --keyserver subkeys.pgp.net --recv-keys EA8E8B2116BA136C
 157.247 + gpg --export | apt-key add - 
 157.248 +apt-get update
 157.249 +ls /etc/rc*.d/[K,S]*|grep network
 157.250 +ls /etc/rc*.d/[K,S]*|grep slapd
 157.251 +ls /etc/rc*.d/[K,S]*|grep samba
 157.252 +update-rc.d samba start 20 S  . stop 19 S .
 157.253 +ls /etc/rc*.d/[K,S]*|grep samba
 157.254 +update-rc.d 
 157.255 +update-rc.d samba start 20 2 . stop 19 S .
 157.256 +ls /etc/rc*.d/[K,S]*|grep samba
 157.257 +ls -l /etc/rc0.d/K19samba
 157.258 +ln -s ../init.d/samba /etc/rc2.d/S20samba /etc/rc3.d/S20samba
 157.259 +ln -s ../init.d/samba /etc/rc2.d/S20samba 
 157.260 +ln -s ../init.d/samba /etc/rc3.d/S20samba 
 157.261 +ln -s ../init.d/samba /etc/rc4.d/S20samba 
 157.262 +ln -s ../init.d/samba /etc/rc5.d/S20samba 
 157.263 +ls -l /etc/rc0.d/K19samba
 157.264 +ls /etc/rc*.d/[K,S]*|grep samba
 157.265 +ls /etc/rc*.d/[K,S]*|grep samba
 157.266 +ls /etc/rc*.d/[K,S]*|grep slapd
 157.267 +ls -l /etc/rc2.d/S19slapd
 157.268 +ls -l /etc/rc2.d/S20samba 
 157.269 +ls -l /etc/rc*.d/*samba 
 157.270 +ln -s ../init.d/slapd /etc/rc2.d/S19slapd
 157.271 +ln -s ../init.d/slapd /etc/rc3.d/S19slapd
 157.272 +ln -s ../init.d/slapd /etc/rc4.d/S19slapd
 157.273 +ln -s ../init.d/slapd /etc/rc5.d/S19slapd
 157.274 +ls -l /etc/rc*.d/*samba 
 157.275 +ls -l /etc/rc*.d/*slapd
 157.276 +ls -l /etc/rc*.d/*slapd
 157.277 +ls -l /etc/rc*.d/*samba
 157.278 +apt-get install etc_keeper
 157.279 +aptitude search etckeeper
 157.280 +apt-get install etckeeper
 157.281 +l
 157.282 +cd /etc/
 157.283 +l
 157.284 +jmacs /etc/cron.d/hgetc 
 157.285 +jmacs /etc/etckeeper/etckeeper.conf 
 157.286 +etckeeper init
 157.287 +etckeeper status
 157.288 +hg st
 157.289 +etckeeper add
 157.290 +etckeeper commit -m 'init'
 157.291 +hg st
 157.292 +hgtip
 157.293 +hg tip
 157.294 +hg rollback
 157.295 +etckeeper commit 'initialize'
 157.296 +hg st
 157.297 +hgtip
 157.298 +hg tip
 157.299 +l
 157.300 +cat /etc/cron.d/hgetc
 157.301 +jmacs /etc/cron.d/hgetc 
 157.302 +ll
 157.303 +hg st
 157.304 +l
 157.305 +
 157.306 +dpkg -l | grep ipython
 157.307 +hg rollback
 157.308 +etckeeper commit 'initialize'
 157.309 +hg st
 157.310 +apt-get install bash-completion
 157.311 +cd etc/
 157.312 +hg st
 157.313 +rm -Rf /root/.ipython/
 157.314 +dpkg -l apache2
 157.315 +ipl
   158.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.2 +++ b/lab/srv-isi/root/.bashrc	Mon Apr 26 11:16:23 2010 +0200
   158.3 @@ -0,0 +1,37 @@
   158.4 +# ~/.bashrc: executed by bash(1) for non-login shells.
   158.5 +
   158.6 +. /etc/bash.bashrc
   158.7 +
   158.8 +export PS1='\h:\w\$ '
   158.9 +umask 022
  158.10 +
  158.11 +### get rid of autologin after first login
  158.12 +if [ -f /etc/inittab-hd -a "$(tty)" = "/dev/tty1" ] ; then
  158.13 +    mv  /etc/inittab-hd /etc/inittab
  158.14 +    init q
  158.15 +    ipl
  158.16 +    ESC="\033["
  158.17 +    RED="${ESC}31;1m"
  158.18 +    BLUE="${ESC}34;1m"
  158.19 +    GREEN="${ESC}44;33;1m"
  158.20 +    YELLOW="${ESC}33;1m"
  158.21 +    NOR="${ESC};0m"
  158.22 +
  158.23 +    ps ax|grep 'login -f' |grep -v tty1|awk '{print $1}'|xargs kill
  158.24 +    echo -e "\n${YELLOW}Imposta una password per ${RED}root:${NOR} \n\n"
  158.25 +    passwd root
  158.26 +
  158.27 +fi
  158.28 +
  158.29 +    
  158.30 +# You may uncomment the following lines if you want `ls' to be colorized:
  158.31 +# export LS_OPTIONS='--color=auto'
  158.32 +# eval "`dircolors`"
  158.33 +# alias ls='ls $LS_OPTIONS'
  158.34 +# alias ll='ls $LS_OPTIONS -l'
  158.35 +# alias l='ls $LS_OPTIONS -lA'
  158.36 +#
  158.37 +# Some more alias to avoid making mistakes:
  158.38 +# alias rm='rm -i'
  158.39 +# alias cp='cp -i'
  158.40 +# alias mv='mv -i'
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/lab/srv-isi/root/.emacs	Mon Apr 26 11:16:23 2010 +0200
   159.3 @@ -0,0 +1,396 @@
   159.4 +;; FIRST:   Do:  M-x outline-minor-mode
   159.5 +;; SECOND:  try M-h too see the index of the file! (outline-minor-mode)
   159.6 +; I don't know why it beahaves oddly if you force it w/ -*- line
   159.7 +
   159.8 +;;;; dir where to load  & REMAPPING HELP!!! (C-h is to eat backword!!!)
   159.9 +;; we add a dir where lo took for files when loading 
  159.10 +(setq load-path (cons "~/.emacsdir" load-path))
  159.11 +(setq default-major-mode 'text-mode)
  159.12 +
  159.13 +;;;; Just for emacs21
  159.14 +(if (string-equal "21" (substring (emacs-version) 10 12))
  159.15 +    (progn
  159.16 +      (blink-cursor-mode 0)
  159.17 +      ;; Insert newline when you press `C-n' (next-line)
  159.18 +      ;; at the end of the buffer
  159.19 +      (setq next-line-add-newlines t)
  159.20 +      ;; Turn on image viewing
  159.21 +      (auto-image-file-mode t)
  159.22 +      ;; Turn on menu bar (this bar has text)
  159.23 +      ;; (Use numeric argument to turn on)
  159.24 +      (menu-bar-mode 1)
  159.25 +      ;; Turn off tool bar (this bar has icons)
  159.26 +      ;; (Use numeric argument to turn on)
  159.27 +      (tool-bar-mode nil)
  159.28 +      ;; Turn off tooltip mode for tool bar
  159.29 +      ;; (This mode causes icon explanations to pop up)
  159.30 +      ;; (Use numeric argument to turn on)
  159.31 +;      (tooltip-mode nil)
  159.32 +      ;; If tooltips turned on, make tips appear promptly
  159.33 +      (setq tooltip-delay 0.1)  ; default is one second
  159.34 +       ))
  159.35 +
  159.36 +
  159.37 +; (hscroll-global-mode nil)
  159.38 +;;;; hilighting & fill
  159.39 +;(server-start nil)
  159.40 +;;(load-file "~/.emacs.elc")
  159.41 +;; this remaps C-h -> C-xh
  159.42 +(global-set-key "\C-xh" 'help-command) ;; overrides mark-whole-buffer
  159.43 +(global-unset-key "\C-h" ) 
  159.44 +; non perdere l' ultimo bit dell' input
  159.45 +;(set-input-mode nil nil 1)
  159.46 +;;;; look & feel: decoration & hiligting
  159.47 +;; maximum decoration in hilighting
  159.48 +    (setq font-lock-maximum-decoration t)
  159.49 +    (global-font-lock-mode t)
  159.50 +; auto-copress will correcly deal w/ tar.gz files (gunzip then tar t)
  159.51 +    (auto-compression-mode nil)
  159.52 +;; autofill si ferma alla colonna 77
  159.53 +    (setq-default fill-column 76)
  159.54 +;;;; Scrolling 1 row at a time
  159.55 +   (global-set-key "\C-z"  (lambda () (interactive) (scroll-up 1)))
  159.56 +   (global-set-key "\M-z"  (lambda () (interactive) (scroll-up -1)))
  159.57 +   (global-set-key "\C-h" 'delete-backward-char)
  159.58 +;; C-u kill backward
  159.59 +  (global-set-key "\C-cu" [?\C-  ?\C-a ?\C-w])
  159.60 +;;;; Paren
  159.61 +   (require 'paren)
  159.62 +   (show-paren-mode 1)
  159.63 +;;;; kill & yank / search & replace
  159.64 +;; search & replace
  159.65 +    (global-set-key "\C-cr" 'query-replace-regexp)
  159.66 +;;;; Font-Lock Mode - Add color to text moden
  159.67 +; Here I add some colors for text mode (my default)
  159.68 + (defvar text-font-lock-keywords
  159.69 +   (eval-when-compile
  159.70 +       (list
  159.71 +	;;
  159.72 +	;; Function name declarations.
  159.73 +;	'("\\<\\(proc\\|AA\-\\)\\>[ \t]*\\(\\sw+\\)?\\(.*\\)"
  159.74 +	'("^\\(#.*|\\)[ \t]*\\([A-z(){}._]+\\)?\\(.*\\)"
  159.75 +	  (1 font-lock-comment-face) (2 font-lock-function-name-face nil t)
  159.76 +	  (3 font-lock-keyword-face nil t))
  159.77 +     '("^\\s-*\\([-]\\S-*\\) +\\(\\sw+\\)" (1 font-lock-warning-face) 
  159.78 +       (2 font-lock-keyword-face nil t))
  159.79 +     ; bold face for *words*
  159.80 +     '("\\s-\\(\\*[^*]+\\*\\)\\s-" . font-lock-string-face) 
  159.81 +     ; italic face for _words*
  159.82 +     '("\\s-\\(\\_[^*]+\\*\\)\\s-" . font-lock-comment-face) 
  159.83 +     ; title row for menu.lst in grub...
  159.84 +     '("^\\(title \\)\\(.*\\)" 
  159.85 +	  (1 font-lock-comment-face) (2 font-lock-function-name-face nil t))
  159.86 +     ;; NOTE: it is important the order of the lines defining color match
  159.87 +     ; the next colors a line beginning w/ >% but > is redefined below
  159.88 +     '("^\\(\\s-*>\\s-*>.*\\|%[^\n]*\\)" . font-lock-type-face) 
  159.89 +     ; the next colors a  line beginning w/ >>
  159.90 +     '("^\\(\\s-*>[^>\n]+\\)" . font-lock-comment-face) 
  159.91 +     '("^\\([.']H +\\w+\\) \\(.+\\)" (1 font-lock-keyword-face) 
  159.92 +       (2 font-lock-function-name-face nil t))
  159.93 +       ))
  159.94 +   "Default expressions to highlight in text mode.")
  159.95 +
  159.96 + (add-hook 'text-mode-hook
  159.97 +  (function (lambda ()
  159.98 +              (make-local-variable 'font-lock-defaults)
  159.99 +              (setq font-lock-defaults 
 159.100 +		 '(text-font-lock-keywords nil nil ))
 159.101 +;  questo pare non servire... (?: . "w") (?_ . "w") 
 159.102 +	      ; copiato senza capire gran che' da tcl-mode
 159.103 +;	      (set-syntax-table (copy-syntax-table))
 159.104 +	      (modify-syntax-entry ?# "<")
 159.105 +;	      (modify-syntax-entry ?\n ">")
 159.106 +	      (modify-syntax-entry ?| ">")
 159.107 +	      (modify-syntax-entry ?\n ">")
 159.108 +)))
 159.109 + (add-hook 'tex-mode-hook
 159.110 +  (function (lambda ()
 159.111 +              (make-local-variable 'font-lock-defaults)
 159.112 +              (setq font-lock-defaults nil)
 159.113 +)))
 159.114 +
 159.115 +
 159.116 +;;;; Outline & related bind - use add-hooks for tcl, text, python, sh
 159.117 +    (set-variable (quote outline-minor-mode-prefix) (quote "\C-ch"))
 159.118 +    (require 'outline)
 159.119 +;;     (require 'allout)
 159.120 +;;     (outline-init t)
 159.121 +    (require 'foldout)
 159.122 +;    (outline-minor-mode t)
 159.123 +;    (require 'out-xtra)
 159.124 +;    (make-local-variable (quote outline-regexp))
 159.125 +;    (global-set-key "\C-chi" 'make-indirect-buffer)
 159.126 +;    (global-set-key "\C-chj" 'show-entry)
 159.127 +;    (global-set-key "\C-chb" 'show-branches)
 159.128 +;    (global-set-key "\C-chh" 'hide-sublevels)
 159.129 +    (global-set-key "\M-h" 'hide-sublevels)
 159.130 +    (global-set-key "\M-j" 'show-subtree)
 159.131 +    (global-set-key "\M-k" 'hide-subtree)
 159.132 +;    (global-set-key "\C-chk" 'hide-leaves)
 159.133 +;    (global-set-key "\C-ch2" 'make-indirect-buffer)
 159.134 +;    (global-set-key "\C-cht" 'hide-body)
 159.135 +;    (global-set-key "\C-cht" 'hide-body)
 159.136 +    (add-hook 'tcl-mode-hook
 159.137 +              (function
 159.138 +                (lambda ()
 159.139 +		  (turn-on-follow-mode)
 159.140 +		 (outline-minor-mode t)
 159.141 +;		 (hscroll-mode t)
 159.142 +                 (make-local-variable (quote outline-regexp))
 159.143 +                 (setq outline-level 'outline-level)
 159.144 +                 (set-variable (quote outline-regexp) 
 159.145 + 	         (quote "proc\\|####?\\|# - #\\| +###\\|    for\\|    if ")))))
 159.146 +    (add-hook 'python-mode-hook
 159.147 +              (function
 159.148 +                (lambda ()
 159.149 +;		  (turn-on-follow-mode)
 159.150 +		 (outline-minor-mode t)
 159.151 +;		 (hscroll-mode t)
 159.152 +                 (make-local-variable (quote outline-regexp))
 159.153 +                 (set-variable (quote outline-regexp) 
 159.154 + 	         (quote " *def ..\\|####?\\|# - #\\|class")))))
 159.155 +    (add-hook 'text-mode-hook
 159.156 +              (function
 159.157 +                (lambda ()
 159.158 +		  (turn-on-follow-mode)
 159.159 +		 (outline-minor-mode t)
 159.160 +;                 (set-variable (quote comment-start) (quote "# "))
 159.161 +		 (set (make-local-variable 'comment-start) "# ")
 159.162 +		 (set (make-local-variable 'comment-start-skip) "# *")
 159.163 +                 (make-local-variable (quote outline-regexp))
 159.164 +                 (set-variable (quote outline-regexp) (quote "\\.H *[0-9]")))))
 159.165 +    (add-hook 'sh-mode-hook
 159.166 +              (function
 159.167 +                (lambda ()
 159.168 +		  (turn-on-follow-mode)
 159.169 +		 (outline-minor-mode t)
 159.170 +                 (setq outline-level 'sh-outline-level)
 159.171 +                 (make-local-variable (quote outline-regexp))
 159.172 +                 (set-variable (quote outline-regexp) 
 159.173 +			       (quote "### \\|func\\|.*()")))))
 159.174 +     (add-hook 'lisp-mode-hook
 159.175 +               (function
 159.176 +                 (lambda ()
 159.177 + 		 (outline-minor-mode t))))
 159.178 +;                  (make-local-variable (quote outline-regexp)))))
 159.179 +
 159.180 +
 159.181 +
 159.182 +;;;; functions
 159.183 +;; this function forces all pattern of outline-regexp of a function to behave 
 159.184 +;; the same way, independent of thei length. Use it in cnjunction w/
 159.185 +; -*- outline-regexp: "## # \\|.*()" -*-
 159.186 +;; and all functions will be part of the "index" toghether w/ all the lines 
 159.187 +;; that have ## # at the beginning 
 159.188 +(defun sh-outline-level () 1)
 159.189 +
 159.190 +;; sst C-cs
 159.191 +;; I repeat it twice so that colors get ok... this seem to depend on outline 
 159.192 +;; mode being requested by the -*- line at beginning!!! 
 159.193 +(fset 'sd-sost
 159.194 +   [?\C-a ?\C-  ?\M-f escape ?1 escape ?| ?s ?s ?t return])
 159.195 +; (fset 'sd-sost
 159.196 +;    [?\C-a ?\C-  ?\M-f escape ?1 escape ?| ?s ?s ?t return])
 159.197 +  (global-set-key "\C-cs" 'sd-sost)
 159.198 +;;;; EDIFF
 159.199 +  (global-set-key "\C-cer" 'ediff-revision)
 159.200 +  (global-set-key "\C-cef" 'ediff-files)
 159.201 +  (global-set-key "\C-ceb" 'ediff-buffers)
 159.202 +  (global-set-key "\C-cem" 'ediff-merge)
 159.203 +  (global-set-key "\C-ced" 'ediff-directories)
 159.204 +  ; the following position the control-frame for ediff 5 pixel lower than default
 159.205 +  (set-variable (quote ediff-control-frame-upward-shift) -5)
 159.206 +;;;; Comment region
 159.207 +  (global-set-key "\C-cc" 'comment-region)
 159.208 +  (global-set-key "\C-cU" [escape ?- ?1 ?\C-c ?c])
 159.209 +  ;  (global-set-key "\C-cu" '(comment-region -1))
 159.210 +;;;; Text-mode - definig paragraph
 159.211 +(add-hook 'text-mode-hook
 159.212 +   (function
 159.213 +    (lambda ()
 159.214 +     (set-variable (quote paragraph-start) "[ 	]*$\\|^\\|^[ 	]*-"))))
 159.215 +
 159.216 +;;;; TAGS
 159.217 +  (global-set-key "\C-ctv" 'visit-tags-table)
 159.218 +  (global-set-key "\C-ctr" 'tags-reset-tags-tables)
 159.219 +  (global-set-key "\C-cts" 'tags-search)
 159.220 +  (global-set-key "\C-ctq" 'tags-query-replace)
 159.221 +  (global-set-key "\C-cta" 'tags-apropos)
 159.222 +;;;; MULE & iso-accent 
 159.223 +;; Sistemiamo MULE (internazionalizzazione)
 159.224 +;  (standard-display-european t)
 159.225 +;  (set-input-mode nil nil 1)
 159.226 +  (load-library "iso-insert")
 159.227 +  (load-library "iso-acc")
 159.228 +  (add-hook 'text-mode-hook 'iso-accents-mode)
 159.229 +  ; Con la segg istruzione evito che // diventi �
 159.230 +;  (iso-accents-customize "french")
 159.231 +;  (iso-accents-customize "spanish")
 159.232 +  ;; non voglio che "a venga modificato: rinuncio anche alla dieresi: Tant pis
 159.233 +(setq iso-accents-enable '(?' ?` ?^  ?~ ))
 159.234 +;;;; Ispell (if .emacsdir is there)
 159.235 +(if (file-exists-p "~/.emacsdir") 
 159.236 +    (progn
 159.237 +      (require 'ispell)
 159.238 +      (load-library "ispell-patch.el")
 159.239 +    ; (setq ispell-dictionary-alist
 159.240 +    ;      (append ispell-dictionary-alist
 159.241 +    ;       '(("italian"
 159.242 +    ;          "[A-Za-z]"
 159.243 +    ;          "[^A-Za-z]"
 159.244 +    ;           "[---']" t nil "~list" iso-8859-1))))
 159.245 +
 159.246 +      (global-set-key "\C-cir" 'ispell-region) 
 159.247 +      (global-set-key "\C-cib" 'ispell-buffer) 
 159.248 +      (global-set-key "\C-cim" 'ispell-minor-mode) 
 159.249 +      (global-set-key "\C-cid" 'ispell-change-dictionary)
 159.250 +      (global-set-key "\C-x\C-t" 'write-region) 
 159.251 +      (set-default 'ispell-local-dictionary "italian-ge")))
 159.252 +
 159.253 +;;;; Misc: comint, repeat, goto...
 159.254 +    (add-hook 'text-mode-hook 'turn-on-auto-fill)
 159.255 +    ;; questo in origine e` C-x ESC ESC
 159.256 +    (global-set-key "\C-cx" 'repeat-complex-command)
 159.257 +    (global-set-key "\C-c " 'comint-dynamic-complete)  
 159.258 +    (global-set-key "\C-\M-g" 'goto-line)  
 159.259 +    (put 'downcase-region 'disabled nil)
 159.260 +
 159.261 +    (setq auto-mode-alist
 159.262 +	    (cons '("\\.py$" . python-mode) auto-mode-alist))
 159.263 +    (setq interpreter-mode-alist
 159.264 +	  (cons '("python" . python-mode)
 159.265 +		  interpreter-mode-alist))
 159.266 +    (autoload 'python-mode "python-mode" "Python editing mode." t)
 159.267 +    ;; psgml
 159.268 +    (autoload 'sgml-mode "psgml" "Major mode to edit SGML files." t)
 159.269 +    (autoload 'xml-mode "psgml" "Major mode to edit XML files." t)
 159.270 +
 159.271 +
 159.272 +;;;; Desktop
 159.273 +  (load "desktop")
 159.274 +  (desktop-load-default)
 159.275 +  ;      (desktop-read)
 159.276 +;;;; ps-printing
 159.277 +  (setq ps-print-color-p t)
 159.278 +  ;; (setq ps-paper-type "a4")
 159.279 +  (set-variable (quote ps-paper-type) (quote a4))
 159.280 +  (setq ps-lpr-command "lpr")
 159.281 +  (setq ps-lpr-switches '("-Pfile"))
 159.282 +  (setq ps-bold-faces '(times))
 159.283 +  (setq ps-zebra-stripes t)
 159.284 +  (setq ps-build-face-reference t)
 159.285 +  (setq ps-zebra-stripe-height 4)
 159.286 +  (setq ps-line-number nil)
 159.287 +  (global-set-key "\C-cpb" 'ps-print-buffer-with-faces)
 159.288 +  (global-set-key "\C-cpr" 'ps-print-region-with-faces)
 159.289 +  (global-set-key "\C-cpxd" 'ps-despool)
 159.290 +  ;(global-set-key '(control f22) 'ps-despool)
 159.291 +;;;; Latex & dvi
 159.292 +   (setq tex-dvi-view-command "tkdvi")
 159.293 +   ;(setq latex-run-command "lx -q")
 159.294 +   (setq latex-run-command "latex")
 159.295 +   ;;(setq tex-directory "./")
 159.296 +;;;; custom set faces
 159.297 +(custom-set-faces
 159.298 +  ;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
 159.299 +  ;; Your init file should contain only one such instance.
 159.300 + '(sh-heredoc-face ((((class color) (background light)) (:background "darkseagreen" :foreground "Navy")))))
 159.301 +
 159.302 +
 159.303 +
 159.304 +;;;; GNU Server
 159.305 +(if (file-exists-p ".emacsdir/gnuserv")
 159.306 +    (progn
 159.307 +      (gnuserv-start)
 159.308 +      (global-set-key "\C-x\C-c" 'gnuserv-edit)))
 159.309 +;(require 'preview)
 159.310 +;;;; msb-mode - fancy buffer menu
 159.311 +(msb-mode)
 159.312 +(defconst msb--sd-many-menus  
 159.313 +  '(((and (boundp 'server-buffer-clients)
 159.314 +	  server-buffer-clients
 159.315 +	  'multi)
 159.316 +     1010
 159.317 +     "Clients (%d)")
 159.318 +    ((and (boundp 'vc-mode) vc-mode 'multi)
 159.319 +     1020
 159.320 +     "Version Control (%d)")
 159.321 +    ((and buffer-file-name
 159.322 +	  (buffer-modified-p)
 159.323 +	  'multi)
 159.324 +     1030
 159.325 +     "Changed files (%d)")
 159.326 +    ((and (get-buffer-process (current-buffer))
 159.327 +	  'multi)
 159.328 +     1040
 159.329 +     "Processes (%d)")
 159.330 +    ((and msb-display-invisible-buffers-p
 159.331 +	  (msb-invisible-buffer-p)
 159.332 +	  'multi)
 159.333 +     1090
 159.334 +     "Invisible buffers (%d)")
 159.335 +    ((eq major-mode 'dired-mode)
 159.336 +     2010
 159.337 +     "Dired (%d)"
 159.338 +     ;; Note this different menu-handler
 159.339 +     msb-dired-item-handler
 159.340 +     ;; Also note this item-sorter
 159.341 +     msb-sort-by-directory)
 159.342 +    ((eq major-mode 'Man-mode)
 159.343 +     5030
 159.344 +     "Manuals (%d)")
 159.345 +    ((eq major-mode 'w3-mode)
 159.346 +     5020
 159.347 +     "WWW (%d)")
 159.348 +    ((or (memq major-mode
 159.349 +	       '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode))
 159.350 +	 (memq major-mode '(mh-letter-mode mh-show-mode mh-folder-mode))
 159.351 +	 (memq major-mode '(gnus-summary-mode message-mode gnus-group-mode
 159.352 +			    gnus-article-mode score-mode
 159.353 +			    gnus-browse-killed-mode)))
 159.354 +     5010
 159.355 +     "Mail (%d)")
 159.356 +    ;; Catchup for all non-file buffers
 159.357 +    ((and (not buffer-file-name)
 159.358 +	  'no-multi)
 159.359 +     5099
 159.360 +     "Other non-file buffers (%d)")
 159.361 +    ((and (string-match "/\\.[^/]*$" buffer-file-name)
 159.362 +	  'multi)
 159.363 +     1080
 159.364 +     "Hidden Files (%d)")
 159.365 +    ((eq major-mode 'tcl-mode)
 159.366 +     1071
 159.367 +     "Tcl Files (%d)")
 159.368 +    ((memq major-mode '(c-mode c++-mode))
 159.369 +     3010
 159.370 +     "C/C++ Files (%d)")
 159.371 +    ((eq major-mode 'emacs-lisp-mode)
 159.372 +     3020
 159.373 +     "Elisp Files (%d)")
 159.374 +    ((eq major-mode 'sh-mode)
 159.375 +     3021
 159.376 +     "Shell Files (%d)")
 159.377 +    ((eq major-mode 'awk-mode)
 159.378 +     3022
 159.379 +     "Awk Files (%d)")
 159.380 +    ((eq major-mode 'latex-mode)
 159.381 +     3030
 159.382 +     "LaTex Files (%d)")
 159.383 +    ((eq major-mode 'nroff-mode)
 159.384 +     3031
 159.385 +     "Nroff Files (%d)")
 159.386 +    ((eq major-mode 'text-mode)
 159.387 +     3032
 159.388 +     "Text Files (%d)")
 159.389 +    ('no-multi
 159.390 +     3099
 159.391 +     "Other files (%d)")))
 159.392 +(custom-set-variables
 159.393 +  ;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
 159.394 +  ;; Your init file should contain only one such instance.
 159.395 + '(case-fold-search t)
 159.396 + '(msb-display-most-recently-used 25)
 159.397 + '(msb-max-menu-items 25)
 159.398 + '(msb-menu-cond msb--sd-many-menus))
 159.399 +(setq inhibit-splash-screen t)
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/lab/srv-isi/root/.hgignore	Mon Apr 26 11:16:23 2010 +0200
   160.3 @@ -0,0 +1,10 @@
   160.4 +syntax:glob
   160.5 +*~
   160.6 +
   160.7 +syntax: regexp
   160.8 +.*~
   160.9 +\#.*[\#]
  160.10 +\.\#.*
  160.11 +.*.dpkg-new
  160.12 +.*.dpkg-old
  160.13 +mtab
   161.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.2 +++ b/lab/srv-isi/root/.hgrc	Mon Apr 26 11:16:23 2010 +0200
   161.3 @@ -0,0 +1,4 @@
   161.4 +[ui]
   161.5 +username = root
   161.6 +ignore.other = ~/.hgignore
   161.7 +
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/lab/srv-isi/root/.ipython/ipythonrc	Mon Apr 26 11:16:23 2010 +0200
   162.3 @@ -0,0 +1,636 @@
   162.4 +# -*- Mode: Shell-Script -*-  Not really, but shows comments correctly
   162.5 +# $Id: ipythonrc 2156 2022-03-19 02:32:19Z fperez $
   162.6 +
   162.7 +#***************************************************************************
   162.8 +#
   162.9 +# Configuration file for IPython -- ipythonrc format
  162.10 +#
  162.11 +# ===========================================================
  162.12 +# Deprecation note: you should look into modifying ipy_user_conf.py (located 
  162.13 +# in ~/.ipython or ~/_ipython, depending on your platform) instead, it's a 
  162.14 +# more flexible and robust (and better supported!) configuration
  162.15 +# method.
  162.16 +# ===========================================================
  162.17 +#
  162.18 +# The format of this file is simply one of 'key value' lines.
  162.19 +# Lines containing only whitespace at the beginning and then a # are ignored
  162.20 +# as comments. But comments can NOT be put on lines with data.
  162.21 +
  162.22 +# The meaning and use of each key are explained below.
  162.23 +
  162.24 +#---------------------------------------------------------------------------
  162.25 +# Section: included files
  162.26 +
  162.27 +# Put one or more *config* files (with the syntax of this file) you want to
  162.28 +# include. For keys with a unique value the outermost file has precedence. For
  162.29 +# keys with multiple values, they all get assembled into a list which then
  162.30 +# gets loaded by IPython.
  162.31 +
  162.32 +# In this file, all lists of things should simply be space-separated.
  162.33 +
  162.34 +# This allows you to build hierarchies of files which recursively load
  162.35 +# lower-level services. If this is your main ~/.ipython/ipythonrc file, you
  162.36 +# should only keep here basic things you always want available. Then you can
  162.37 +# include it in every other special-purpose config file you create.
  162.38 +include 
  162.39 +
  162.40 +#---------------------------------------------------------------------------
  162.41 +# Section: startup setup
  162.42 +
  162.43 +# These are mostly things which parallel a command line option of the same
  162.44 +# name.
  162.45 +
  162.46 +# Keys in this section should only appear once. If any key from this section
  162.47 +# is encountered more than once, the last value remains, all earlier ones get
  162.48 +# discarded.
  162.49 +
  162.50 +
  162.51 +# Automatic calling of callable objects.  If set to 1 or 2, callable objects
  162.52 +# are automatically called when invoked at the command line, even if you don't
  162.53 +# type parentheses.  IPython adds the parentheses for you.  For example:
  162.54 +
  162.55 +#In [1]: str 45
  162.56 +#------> str(45)
  162.57 +#Out[1]: '45'
  162.58 +
  162.59 +# IPython reprints your line with '---->' indicating that it added
  162.60 +# parentheses.  While this option is very convenient for interactive use, it
  162.61 +# may occasionally cause problems with objects which have side-effects if
  162.62 +# called unexpectedly.
  162.63 +
  162.64 +# The valid values for autocall are:
  162.65 +
  162.66 +# autocall 0 -> disabled (you can toggle it at runtime with the %autocall magic)
  162.67 +
  162.68 +# autocall 1 -> active, but do not apply if there are no arguments on the line.
  162.69 +
  162.70 +# In this mode, you get:
  162.71 +
  162.72 +#In [1]: callable
  162.73 +#Out[1]: <built-in function callable>
  162.74 +
  162.75 +#In [2]: callable 'hello'
  162.76 +#------> callable('hello')
  162.77 +#Out[2]: False
  162.78 +
  162.79 +# 2 -> Active always.  Even if no arguments are present, the callable object
  162.80 +# is called:
  162.81 +
  162.82 +#In [4]: callable
  162.83 +#------> callable()
  162.84 +
  162.85 +# Note that even with autocall off, you can still use '/' at the start of a
  162.86 +# line to treat the first argument on the command line as a function and add
  162.87 +# parentheses to it:
  162.88 +
  162.89 +#In [8]: /str 43
  162.90 +#------> str(43)
  162.91 +#Out[8]: '43'
  162.92 +
  162.93 +autocall 1
  162.94 +
  162.95 +# Auto-edit syntax errors.  When you use the %edit magic in ipython to edit
  162.96 +# source code (see the 'editor' variable below), it is possible that you save
  162.97 +# a file with syntax errors in it.  If this variable is true, IPython will ask
  162.98 +# you whether to re-open the editor immediately to correct such an error.
  162.99 +
 162.100 +autoedit_syntax 0
 162.101 +
 162.102 +# Auto-indent. IPython can recognize lines ending in ':' and indent the next
 162.103 +# line, while also un-indenting automatically after 'raise' or 'return'.  
 162.104 +
 162.105 +# This feature uses the readline library, so it will honor your ~/.inputrc
 162.106 +# configuration (or whatever file your INPUTRC variable points to).  Adding
 162.107 +# the following lines to your .inputrc file can make indent/unindenting more
 162.108 +# convenient (M-i indents, M-u unindents):
 162.109 +
 162.110 +#  $if Python
 162.111 +#  "\M-i": "    "
 162.112 +#  "\M-u": "\d\d\d\d"
 162.113 +#  $endif
 162.114 +
 162.115 +# The feature is potentially a bit dangerous, because it can cause problems
 162.116 +# with pasting of indented code (the pasted code gets re-indented on each
 162.117 +# line).  But it's a huge time-saver when working interactively.  The magic
 162.118 +# function %autoindent allows you to toggle it on/off at runtime.
 162.119 +
 162.120 +autoindent 1
 162.121 +
 162.122 +# Auto-magic. This gives you access to all the magic functions without having
 162.123 +# to prepend them with an % sign. If you define a variable with the same name
 162.124 +# as a magic function (say who=1), you will need to access the magic function
 162.125 +# with % (%who in this example). However, if later you delete your variable
 162.126 +# (del who), you'll recover the automagic calling form.
 162.127 +
 162.128 +# Considering that many magic functions provide a lot of shell-like
 162.129 +# functionality, automagic gives you something close to a full Python+system
 162.130 +# shell environment (and you can extend it further if you want).
 162.131 +
 162.132 +automagic 1
 162.133 +
 162.134 +# Size of the output cache. After this many entries are stored, the cache will
 162.135 +# get flushed. Depending on the size of your intermediate calculations, you
 162.136 +# may have memory problems if you make it too big, since keeping things in the
 162.137 +# cache prevents Python from reclaiming the memory for old results. Experiment
 162.138 +# with a value that works well for you.
 162.139 +
 162.140 +# If you choose cache_size 0 IPython will revert to python's regular >>>
 162.141 +# unnumbered prompt. You will still have _, __ and ___ for your last three
 162.142 +# results, but that will be it.  No dynamic _1, _2, etc. will be created. If
 162.143 +# you are running on a slow machine or with very limited memory, this may
 162.144 +# help.
 162.145 +
 162.146 +cache_size 1000
 162.147 +
 162.148 +# Classic mode: Setting 'classic 1' you lose many of IPython niceties,
 162.149 +# but that's your choice! Classic 1 -> same as IPython -classic.
 162.150 +# Note that this is _not_ the normal python interpreter, it's simply
 162.151 +# IPython emulating most of the classic interpreter's behavior.
 162.152 +classic 0
 162.153 +
 162.154 +# colors - Coloring option for prompts and traceback printouts.
 162.155 +
 162.156 +# Currently available schemes: NoColor, Linux, LightBG.
 162.157 +
 162.158 +# This option allows coloring the prompts and traceback printouts. This
 162.159 +# requires a terminal which can properly handle color escape sequences. If you
 162.160 +# are having problems with this, use the NoColor scheme (uses no color escapes
 162.161 +# at all).
 162.162 +
 162.163 +# The Linux option works well in linux console type environments: dark
 162.164 +# background with light fonts.
 162.165 +
 162.166 +# LightBG is similar to Linux but swaps dark/light colors to be more readable
 162.167 +# in light background terminals.
 162.168 +
 162.169 +# keep uncommented only the one you want:
 162.170 +#colors Linux
 162.171 +colors LightBG
 162.172 +#colors NoColor
 162.173 +
 162.174 +########################
 162.175 +# Note to Windows users
 162.176 +#
 162.177 +# Color and readline support is avaialble to Windows users via Gary Bishop's
 162.178 +# readline library.  You can find Gary's tools at
 162.179 +# http://sourceforge.net/projects/uncpythontools.
 162.180 +# Note that his readline module requires in turn the ctypes library, available
 162.181 +# at http://starship.python.net/crew/theller/ctypes.
 162.182 +########################
 162.183 +
 162.184 +# color_info: IPython can display information about objects via a set of
 162.185 +# functions, and optionally can use colors for this, syntax highlighting
 162.186 +# source code and various other elements. This information is passed through a
 162.187 +# pager (it defaults to 'less' if $PAGER is not set). 
 162.188 +
 162.189 +# If your pager has problems, try to setting it to properly handle escapes
 162.190 +# (see the less manpage for detail), or disable this option.  The magic
 162.191 +# function %color_info allows you to toggle this interactively for testing.
 162.192 +
 162.193 +color_info 1
 162.194 +
 162.195 +# confirm_exit: set to 1 if you want IPython to confirm when you try to exit
 162.196 +# with an EOF (Control-d in Unix, Control-Z/Enter in Windows). Note that using
 162.197 +# the magic functions %Exit or %Quit you can force a direct exit, bypassing
 162.198 +# any confirmation.
 162.199 +
 162.200 +confirm_exit 0
 162.201 +
 162.202 +# Use deep_reload() as a substitute for reload() by default. deep_reload() is
 162.203 +# still available as dreload() and appears as a builtin.
 162.204 +
 162.205 +deep_reload 0
 162.206 +
 162.207 +# Which editor to use with the %edit command. If you leave this at 0, IPython
 162.208 +# will honor your EDITOR environment variable. Since this editor is invoked on
 162.209 +# the fly by ipython and is meant for editing small code snippets, you may
 162.210 +# want to use a small, lightweight editor here.
 162.211 +
 162.212 +# For Emacs users, setting up your Emacs server properly as described in the
 162.213 +# manual is a good idea. An alternative is to use jed, a very light editor
 162.214 +# with much of the feel of Emacs (though not as powerful for heavy-duty work).
 162.215 +
 162.216 +editor 0
 162.217 +
 162.218 +# log 1 -> same as ipython -log. This automatically logs to ./ipython.log
 162.219 +log 0
 162.220 +
 162.221 +# Same as ipython -Logfile YourLogfileName. 
 162.222 +# Don't use with log 1 (use one or the other)
 162.223 +logfile ''
 162.224 +
 162.225 +# banner 0 -> same as ipython -nobanner
 162.226 +banner 0
 162.227 +
 162.228 +# messages 0 -> same as ipython -nomessages
 162.229 +messages 1
 162.230 +
 162.231 +# Automatically call the pdb debugger after every uncaught exception. If you
 162.232 +# are used to debugging using pdb, this puts you automatically inside of it
 162.233 +# after any call (either in IPython or in code called by it) which triggers an
 162.234 +# exception which goes uncaught.
 162.235 +pdb 1
 162.236 +
 162.237 +# Enable the pprint module for printing. pprint tends to give a more readable
 162.238 +# display (than print) for complex nested data structures.
 162.239 +pprint 1
 162.240 +
 162.241 +# Prompt strings
 162.242 +
 162.243 +# Most bash-like escapes can be used to customize IPython's prompts, as well as
 162.244 +# a few additional ones which are IPython-specific.  All valid prompt escapes
 162.245 +# are described in detail in the Customization section of the IPython HTML/PDF
 162.246 +# manual.
 162.247 +
 162.248 +# Use \# to represent the current prompt number, and quote them to protect
 162.249 +# spaces.
 162.250 +prompt_in1 'In [\#]: '
 162.251 +
 162.252 +# \D is replaced by as many dots as there are digits in the
 162.253 +# current value of \#.
 162.254 +prompt_in2 '   .\D.: '
 162.255 +
 162.256 +prompt_out 'Out[\#]: '
 162.257 +
 162.258 +# Select whether to left-pad the output prompts to match the length of the
 162.259 +# input ones.  This allows you for example to use a simple '>' as an output
 162.260 +# prompt, and yet have the output line up with the input.  If set to false,
 162.261 +# the output prompts will be unpadded (flush left).
 162.262 +prompts_pad_left 1
 162.263 +
 162.264 +# Pylab support: when ipython is started with the -pylab switch, by default it
 162.265 +# executes 'from matplotlib.pylab import *'.  Set this variable to false if you
 162.266 +# want to disable this behavior.
 162.267 +
 162.268 +# For details on pylab, see the matplotlib website:
 162.269 +# http://matplotlib.sf.net
 162.270 +pylab_import_all 1
 162.271 +
 162.272 +
 162.273 +# quick 1 -> same as ipython -quick
 162.274 +quick 0
 162.275 +
 162.276 +# Use the readline library (1) or not (0). Most users will want this on, but
 162.277 +# if you experience strange problems with line management (mainly when using
 162.278 +# IPython inside Emacs buffers) you may try disabling it. Not having it on
 162.279 +# prevents you from getting command history with the arrow keys, searching and
 162.280 +# name completion using TAB.
 162.281 +
 162.282 +readline 1
 162.283 +
 162.284 +# Screen Length: number of lines of your screen. This is used to control
 162.285 +# printing of very long strings. Strings longer than this number of lines will
 162.286 +# be paged with the less command instead of directly printed.
 162.287 +
 162.288 +# The default value for this is 0, which means IPython will auto-detect your
 162.289 +# screen size every time it needs to print. If for some reason this isn't
 162.290 +# working well (it needs curses support), specify it yourself. Otherwise don't
 162.291 +# change the default.
 162.292 +
 162.293 +screen_length 0
 162.294 +
 162.295 +# Prompt separators for input and output.
 162.296 +# Use \n for newline explicitly, without quotes.
 162.297 +# Use 0 (like at the cmd line) to turn off a given separator.
 162.298 +
 162.299 +# The structure of prompt printing is:
 162.300 +# (SeparateIn)Input....
 162.301 +# (SeparateOut)Output...
 162.302 +# (SeparateOut2),   # that is, no newline is printed after Out2
 162.303 +# By choosing these you can organize your output any way you want.
 162.304 +
 162.305 +separate_in \n
 162.306 +separate_out 0
 162.307 +separate_out2 0
 162.308 +
 162.309 +# 'nosep 1' is a shorthand for '-SeparateIn 0 -SeparateOut 0 -SeparateOut2 0'.
 162.310 +# Simply removes all input/output separators, overriding the choices above.
 162.311 +nosep 0
 162.312 +
 162.313 +# Wildcard searches - IPython has a system for searching names using
 162.314 +# shell-like wildcards; type %psearch? for details.  This variables sets
 162.315 +# whether by default such searches should be case sensitive or not.  You can
 162.316 +# always override the default at the system command line or the IPython
 162.317 +# prompt.
 162.318 +
 162.319 +wildcards_case_sensitive 1
 162.320 +
 162.321 +# Object information: at what level of detail to display the string form of an
 162.322 +# object.  If set to 0, ipython will compute the string form of any object X,
 162.323 +# by calling str(X), when X? is typed.  If set to 1, str(X) will only be
 162.324 +# computed when X?? is given, and if set to 2 or higher, it will never be
 162.325 +# computed (there is no X??? level of detail).  This is mostly of use to
 162.326 +# people who frequently manipulate objects whose string representation is
 162.327 +# extremely expensive to compute.
 162.328 +
 162.329 +object_info_string_level 0
 162.330 +
 162.331 +# xmode - Exception reporting mode. 
 162.332 +
 162.333 +# Valid modes: Plain, Context and Verbose.
 162.334 +
 162.335 +# Plain: similar to python's normal traceback printing.
 162.336 +
 162.337 +# Context: prints 5 lines of context source code around each line in the
 162.338 +# traceback.
 162.339 +
 162.340 +# Verbose: similar to Context, but additionally prints the variables currently
 162.341 +# visible where the exception happened (shortening their strings if too
 162.342 +# long). This can potentially be very slow, if you happen to have a huge data
 162.343 +# structure whose string representation is complex to compute. Your computer
 162.344 +# may appear to freeze for a while with cpu usage at 100%. If this occurs, you
 162.345 +# can cancel the traceback with Ctrl-C (maybe hitting it more than once).
 162.346 +
 162.347 +#xmode Plain
 162.348 +xmode Context
 162.349 +#xmode Verbose
 162.350 +
 162.351 +# multi_line_specials: if true, allow magics, aliases and shell escapes (via
 162.352 +# !cmd) to be used in multi-line input (like for loops).  For example, if you
 162.353 +# have this active, the following is valid in IPython:
 162.354 +#
 162.355 +#In [17]: for i in range(3):
 162.356 +#   ....:     mkdir $i
 162.357 +#   ....:     !touch $i/hello
 162.358 +#   ....:     ls -l $i
 162.359 +
 162.360 +multi_line_specials 1
 162.361 +
 162.362 +
 162.363 +# System calls: When IPython makes system calls (e.g. via special syntax like
 162.364 +# !cmd or !!cmd, or magics like %sc or %sx), it can print the command it is
 162.365 +# executing to standard output, prefixed by a header string.
 162.366 +
 162.367 +system_header "IPython system call: "
 162.368 +
 162.369 +system_verbose 1
 162.370 +
 162.371 +# wxversion: request a specific wxPython version (used for -wthread)
 162.372 +
 162.373 +# Set this to the value of wxPython you want to use, but note that this
 162.374 +# feature requires you to have the wxversion Python module to work.  If you
 162.375 +# don't have the wxversion module (try 'import wxversion' at the prompt to
 162.376 +# check) or simply want to leave the system to pick up the default, leave this
 162.377 +# variable at 0.
 162.378 +
 162.379 +wxversion 0
 162.380 +
 162.381 +#---------------------------------------------------------------------------
 162.382 +# Section: Readline configuration (readline is not available for MS-Windows)
 162.383 +
 162.384 +# This is done via the following options:
 162.385 +
 162.386 +# (i) readline_parse_and_bind: this option can appear as many times as you
 162.387 +# want, each time defining a string to be executed via a
 162.388 +# readline.parse_and_bind() command. The syntax for valid commands of this
 162.389 +# kind can be found by reading the documentation for the GNU readline library,
 162.390 +# as these commands are of the kind which readline accepts in its
 162.391 +# configuration file.
 162.392 +
 162.393 +# The TAB key can be used to complete names at the command line in one of two
 162.394 +# ways: 'complete' and 'menu-complete'. The difference is that 'complete' only
 162.395 +# completes as much as possible while 'menu-complete' cycles through all
 162.396 +# possible completions. Leave the one you prefer uncommented.
 162.397 +
 162.398 +readline_parse_and_bind tab: complete
 162.399 +#readline_parse_and_bind tab: menu-complete
 162.400 +
 162.401 +# This binds Control-l to printing the list of all possible completions when
 162.402 +# there is more than one (what 'complete' does when hitting TAB twice, or at
 162.403 +# the first TAB if show-all-if-ambiguous is on)
 162.404 +readline_parse_and_bind "\C-l": possible-completions
 162.405 +
 162.406 +# This forces readline to automatically print the above list when tab
 162.407 +# completion is set to 'complete'. You can still get this list manually by
 162.408 +# using the key bound to 'possible-completions' (Control-l by default) or by
 162.409 +# hitting TAB twice. Turning this on makes the printing happen at the first
 162.410 +# TAB.
 162.411 +readline_parse_and_bind set show-all-if-ambiguous on
 162.412 +
 162.413 +# If you have TAB set to complete names, you can rebind any key (Control-o by
 162.414 +# default) to insert a true TAB character.
 162.415 +
 162.416 +
 162.417 +#readline_parse_and_bind "\C-o": tab-insert
 162.418 +readline_parse_and_bind "\C-o": operate-and-get-next 
 162.419 +
 162.420 +
 162.421 +# These commands allow you to indent/unindent easily, with the 4-space
 162.422 +# convention of the Python coding standards.  Since IPython's internal
 162.423 +# auto-indent system also uses 4 spaces, you should not change the number of
 162.424 +# spaces in the code below.
 162.425 +readline_parse_and_bind "\M-i": "    "
 162.426 +readline_parse_and_bind "\M-o": "\d\d\d\d"
 162.427 +readline_parse_and_bind "\M-I": "\d\d\d\d"
 162.428 +
 162.429 +# Bindings for incremental searches in the history. These searches use the
 162.430 +# string typed so far on the command line and search anything in the previous
 162.431 +# input history containing them.
 162.432 +readline_parse_and_bind "\C-r": reverse-search-history
 162.433 +readline_parse_and_bind "\C-s": forward-search-history
 162.434 +
 162.435 +# Bindings for completing the current line in the history of previous
 162.436 +# commands. This allows you to recall any previous command by typing its first
 162.437 +# few letters and hitting Control-p, bypassing all intermediate commands which
 162.438 +# may be in the history (much faster than hitting up-arrow 50 times!)
 162.439 +readline_parse_and_bind "\C-p": history-search-backward
 162.440 +readline_parse_and_bind "\C-n": history-search-forward
 162.441 +
 162.442 +# I also like to have the same functionality on the plain arrow keys. If you'd
 162.443 +# rather have the arrows use all the history (and not just match what you've
 162.444 +# typed so far), comment out or delete the next two lines.
 162.445 +readline_parse_and_bind "\e[A": history-search-backward
 162.446 +readline_parse_and_bind "\e[B": history-search-forward
 162.447 +
 162.448 +# These are typically on by default under *nix, but not win32.
 162.449 +readline_parse_and_bind "\C-k": kill-line
 162.450 +readline_parse_and_bind "\C-u": unix-line-discard
 162.451 +
 162.452 +# (ii) readline_remove_delims: a string of characters to be removed from the
 162.453 +# default word-delimiters list used by readline, so that completions may be
 162.454 +# performed on strings which contain them.
 162.455 +
 162.456 +readline_remove_delims -/~
 162.457 +
 162.458 +# (iii) readline_merge_completions: whether to merge the result of all
 162.459 +# possible completions or not.  If true, IPython will complete filenames,
 162.460 +# python names and aliases and return all possible completions.  If you set it
 162.461 +# to false, each completer is used at a time, and only if it doesn't return
 162.462 +# any completions is the next one used.
 162.463 +
 162.464 +# The default order is: [python_matches, file_matches, alias_matches]
 162.465 +
 162.466 +readline_merge_completions 1
 162.467 +
 162.468 +# (iv) readline_omit__names: normally hitting <tab> after a '.' in a name
 162.469 +# will complete all attributes of an object, including all the special methods
 162.470 +# whose names start with single or double underscores (like __getitem__ or
 162.471 +# __class__).
 162.472 +
 162.473 +# This variable allows you to control this completion behavior:
 162.474 +
 162.475 +# readline_omit__names 1 -> completion will omit showing any names starting
 162.476 +# with two __, but it will still show names starting with one _.
 162.477 +
 162.478 +# readline_omit__names 2 -> completion will omit all names beginning with one
 162.479 +# _ (which obviously means filtering out the double __ ones).
 162.480 +
 162.481 +# Even when this option is set, you can still see those names by explicitly
 162.482 +# typing a _ after the period and hitting <tab>: 'name._<tab>' will always
 162.483 +# complete attribute names starting with '_'.
 162.484 +
 162.485 +# This option is off by default so that new users see all attributes of any
 162.486 +# objects they are dealing with.
 162.487 +
 162.488 +readline_omit__names 0
 162.489 +
 162.490 +#---------------------------------------------------------------------------
 162.491 +# Section: modules to be loaded with 'import ...'
 162.492 +
 162.493 +# List, separated by spaces, the names of the modules you want to import
 162.494 +
 162.495 +# Example:
 162.496 +# import_mod sys os
 162.497 +# will produce internally the statements
 162.498 +# import sys
 162.499 +# import os
 162.500 +
 162.501 +# Each import is executed in its own try/except block, so if one module
 162.502 +# fails to load the others will still be ok.
 162.503 +
 162.504 +import_mod 
 162.505 +
 162.506 +#---------------------------------------------------------------------------
 162.507 +# Section: modules to import some functions from: 'from ... import ...'
 162.508 +
 162.509 +# List, one per line, the modules for which you want only to import some
 162.510 +# functions. Give the module name first and then the name of functions to be
 162.511 +# imported from that module.
 162.512 +
 162.513 +# Example:
 162.514 +
 162.515 +# import_some IPython.genutils timing timings
 162.516 +# will produce internally the statement
 162.517 +# from IPython.genutils import timing, timings
 162.518 +
 162.519 +# timing() and timings() are two IPython utilities for timing the execution of
 162.520 +# your own functions, which you may find useful.  Just commment out the above
 162.521 +# line if you want to test them.
 162.522 +
 162.523 +# If you have more than one modules_some line, each gets its own try/except
 162.524 +# block (like modules, see above).
 162.525 +
 162.526 +import_some 
 162.527 +
 162.528 +#---------------------------------------------------------------------------
 162.529 +# Section: modules to import all from : 'from ... import *'
 162.530 +
 162.531 +# List (same syntax as import_mod above) those modules for which you want to
 162.532 +# import all functions. Remember, this is a potentially dangerous thing to do,
 162.533 +# since it is very easy to overwrite names of things you need. Use with
 162.534 +# caution.
 162.535 +
 162.536 +# Example:
 162.537 +# import_all sys os
 162.538 +# will produce internally the statements
 162.539 +# from sys import *
 162.540 +# from os import *
 162.541 +
 162.542 +# As before, each will be called in a separate try/except block.
 162.543 +
 162.544 +import_all 
 162.545 +
 162.546 +#---------------------------------------------------------------------------
 162.547 +# Section: Python code to execute.
 162.548 +
 162.549 +# Put here code to be explicitly executed (keep it simple!)
 162.550 +# Put one line of python code per line. All whitespace is removed (this is a
 162.551 +# feature, not a bug), so don't get fancy building loops here.
 162.552 +# This is just for quick convenient creation of things you want available.
 162.553 +
 162.554 +# Example:
 162.555 +# execute x = 1
 162.556 +# execute print 'hello world'; y = z = 'a'
 162.557 +# will produce internally
 162.558 +# x = 1
 162.559 +# print 'hello world'; y = z = 'a'
 162.560 +# and each *line* (not each statement, we don't do python syntax parsing) is
 162.561 +# executed in its own try/except block.
 162.562 +
 162.563 +execute 
 162.564 +
 162.565 +# Note for the adventurous: you can use this to define your own names for the
 162.566 +# magic functions, by playing some namespace tricks:
 162.567 +
 162.568 +# execute __IPYTHON__.magic_pf = __IPYTHON__.magic_profile
 162.569 +
 162.570 +# defines %pf as a new name for %profile.
 162.571 +
 162.572 +#---------------------------------------------------------------------------
 162.573 +# Section: Pyhton files to load and execute.
 162.574 +
 162.575 +# Put here the full names of files you want executed with execfile(file).  If
 162.576 +# you want complicated initialization, just write whatever you want in a
 162.577 +# regular python file and load it from here.
 162.578 +
 162.579 +# Filenames defined here (which *must* include the extension) are searched for
 162.580 +# through all of sys.path. Since IPython adds your .ipython directory to
 162.581 +# sys.path, they can also be placed in your .ipython dir and will be
 162.582 +# found. Otherwise (if you want to execute things not in .ipyton nor in
 162.583 +# sys.path) give a full path (you can use ~, it gets expanded)
 162.584 +
 162.585 +# Example:
 162.586 +# execfile file1.py ~/file2.py
 162.587 +# will generate
 162.588 +# execfile('file1.py')
 162.589 +# execfile('_path_to_your_home/file2.py')
 162.590 +
 162.591 +# As before, each file gets its own try/except block.
 162.592 +
 162.593 +execfile
 162.594 +
 162.595 +# If you are feeling adventurous, you can even add functionality to IPython
 162.596 +# through here. IPython works through a global variable called __ip which
 162.597 +# exists at the time when these files are read. If you know what you are doing
 162.598 +# (read the source) you can add functions to __ip in files loaded here. 
 162.599 +
 162.600 +# The file example-magic.py contains a simple but correct example. Try it:
 162.601 +
 162.602 +# execfile example-magic.py
 162.603 +
 162.604 +# Look at the examples in IPython/iplib.py for more details on how these magic
 162.605 +# functions need to process their arguments.
 162.606 +
 162.607 +#---------------------------------------------------------------------------
 162.608 +# Section: aliases for system shell commands
 162.609 +
 162.610 +# Here you can define your own names for system commands. The syntax is
 162.611 +# similar to that of the builtin %alias function:
 162.612 +
 162.613 +# alias alias_name command_string
 162.614 +
 162.615 +# The resulting aliases are auto-generated magic functions (hence usable as
 162.616 +# %alias_name)
 162.617 +
 162.618 +# For example:
 162.619 +
 162.620 +# alias myls ls -la
 162.621 +
 162.622 +# will define 'myls' as an alias for executing the system command 'ls -la'.
 162.623 +# This allows you to customize IPython's environment to have the same aliases
 162.624 +# you are accustomed to from your own shell.
 162.625 +
 162.626 +# You can also define aliases with parameters using %s specifiers (one per
 162.627 +# parameter):
 162.628 +
 162.629 +# alias parts echo first %s second %s
 162.630 +
 162.631 +# will give you in IPython:
 162.632 +# >>> %parts A B
 162.633 +# first A second B
 162.634 +
 162.635 +# Use one 'alias' statement per alias you wish to define.
 162.636 +
 162.637 +# alias 
 162.638 +
 162.639 +#************************* end of file <ipythonrc> ************************
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/lab/srv-isi/root/.joe_state	Mon Apr 26 11:16:23 2010 +0200
   163.3 @@ -0,0 +1,59 @@
   163.4 +# JOE state file v1.0
   163.5 +search
   163.6 +	pattern "help"
   163.7 +	backwards 0
   163.8 +	ignore 1
   163.9 +	replace 0
  163.10 +	block_restrict 0
  163.11 +done
  163.12 +macros
  163.13 +done
  163.14 +files
  163.15 +	"/etc/inittab\n"
  163.16 +	"/etc/apt/sources.list\n"
  163.17 +	"/etc/apt/sources.list\n"
  163.18 +	"/etc/bash.bashrc\n"
  163.19 +	"/etc/apt/sources.list\n"
  163.20 +	"/etc/apt/sources.list\n"
  163.21 +	"/usr/sbin/isi-setup\n"
  163.22 +	"/etc/cron.d/hgetc\n"
  163.23 +	"/etc/etckeeper/etckeeper.conf\n"
  163.24 +	"/etc/cron.d/hgetc\n"
  163.25 +done
  163.26 +find
  163.27 +done
  163.28 +replace
  163.29 +done
  163.30 +run
  163.31 +done
  163.32 +build
  163.33 +done
  163.34 +grep
  163.35 +done
  163.36 +cmd
  163.37 +done
  163.38 +math
  163.39 +done
  163.40 +yank
  163.41 +	"\n"
  163.42 +	"\n1:2345:respawn:/sbin/getty 38400 tty1\n2:23:respawn:/sbin/getty 38400 tty2\n"
  163.43 +	"deb http://ftp.it.debian.org/debian/ lenny main non-free"
  163.44 +	"it."
  163.45 +	"deb http://ftp.it.debian.org/debian/ lenny main"
  163.46 +	"5C"
  163.47 +	".it"
  163.48 +	"#deb http://ftp.it.debian.org/debian/ lenny main\n"
  163.49 +	"#deb http://ftp.it.debian.org/debian/ lenny main non-free\n"
  163.50 +	"    http://www.backports.org/debian/pool/main/p/python-django/python-django_1.1.1-1~bpo50+1_all.deb"
  163.51 +	"# "
  163.52 +	"#"
  163.53 +done
  163.54 +file_pos
  163.55 +	42 "/etc/inittab"
  163.56 +	48 "/etc/bash.bashrc"
  163.57 +	9 "/etc/apt/sources.list"
  163.58 +	1199 "/usr/sbin/isi-setup"
  163.59 +	1 "/etc/etckeeper/etckeeper.conf"
  163.60 +	0 "* Startup Log *"
  163.61 +	2 "/etc/cron.d/hgetc"
  163.62 +done
   164.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.2 +++ b/lab/srv-isi/root/.lessfilter	Mon Apr 26 11:16:23 2010 +0200
   164.3 @@ -0,0 +1,33 @@
   164.4 +#!/bin/sh
   164.5 +
   164.6 +file=$1
   164.7 +if [ $(expr match $file '/') = 0 ] ;  then
   164.8 +    # il file $file NON ha path completo
   164.9 +    file=$(pwd)/$file
  164.10 +fi
  164.11 +
  164.12 +if [ $(expr match $file '/etc\|.*.conf') -gt 3  ] ; then
  164.13 +    # $file � un file di configurazione
  164.14 +    COLOR=1
  164.15 +fi
  164.16 +
  164.17 +if [ ! `file $file|egrep 'shell script|\.php|\.awk' > /dev/null` ] ; then
  164.18 +    COLOR=1
  164.19 +fi
  164.20 +
  164.21 +case "$COLOR" in
  164.22 +    1)
  164.23 +	awk ' {
  164.24 +          gsub(/#.*/,"\033[31m&\033[0m",$0);
  164.25 +          print
  164.26 +        }' $1
  164.27 +
  164.28 +	;;
  164.29 +    *)
  164.30 +                 # We don't handle this format.
  164.31 +	exit 1
  164.32 +esac
  164.33 +
  164.34 +         # No further processing by lesspipe necessary
  164.35 +exit 0
  164.36 +
   165.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.2 +++ b/lab/srv-isi/root/.profile	Mon Apr 26 11:16:23 2010 +0200
   165.3 @@ -0,0 +1,9 @@
   165.4 +# ~/.profile: executed by Bourne-compatible login shells.
   165.5 +
   165.6 +if [ "$BASH" ]; then
   165.7 +  if [ -f ~/.bashrc ]; then
   165.8 +    . ~/.bashrc
   165.9 +  fi
  165.10 +fi
  165.11 +
  165.12 +mesg n
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/lab/srv-isi/root/.ssh/authorized_keys	Mon Apr 26 11:16:23 2010 +0200
   166.3 @@ -0,0 +1,1 @@
   166.4 +ssh-dss AAAAB3NzaC1kc3MAAACBAPgNz70XAMBhdfcw6AOfjJIDB5hLt03dS3VN/BZYHKzVJq7c4FxRy+PeqOSXQjAxIp467Dt3eb4i7SqJ0W4AwjGpg6A35nKPgbLda+SEruv0ticeVYbYxkwbcBA1Vu07qN/pof8J6iJ6sUerPhRN2FP8I+zP8h4UcaOcfk/tiv/LAAAAFQCBiVzZiRBeaJNSv1cklANPKOdY3QAAAIAyGZjA5Nnr2jdTdeoadq2DRGhaIgIx00qxpFwc9oC9xSuwHGjsahaKfPsYdX4lcMHl5Jf3Di6255PN2/xsYuR2qaB4S5gxjkMhkB7GDQdKACXsSGyEKzPlKbMUl/qm3kRq1yQcHQlfQohj7LkpEX99YI7hrL5LAihCo+9Na3un0gAAAIBHy0XcUQkYFNWP7EhaBcgdOM7hYXmr8hWXSX6vVtcbHHRrwZfcb+V/zfKo0F5aYsOU8OczKru+/4mBa7TYv3pO9UMiTr6DpJjiKYfYY2rkCPStvaTzr1JBtXfG1Bu8VaghS2T5llR0ro/Pp/niSj0N/CoAytuYQrm8+9fZgOBkoQ== [email protected]
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/lab/srv-isi/var/lib/misc/leases	Mon Apr 26 11:16:23 2010 +0200
   167.3 @@ -0,0 +1,54 @@
   167.4 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
   167.5 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
   167.6 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
   167.7 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
   167.8 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
   167.9 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  167.10 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  167.11 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  167.12 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  167.13 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  167.14 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  167.15 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  167.16 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  167.17 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  167.18 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  167.19 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  167.20 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  167.21 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  167.22 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  167.23 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  167.24 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  167.25 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  167.26 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  167.27 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  167.28 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  167.29 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  167.30 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  167.31 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  167.32 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  167.33 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  167.34 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  167.35 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  167.36 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  167.37 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  167.38 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  167.39 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  167.40 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  167.41 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  167.42 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  167.43 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  167.44 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  167.45 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  167.46 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  167.47 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  167.48 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  167.49 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  167.50 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  167.51 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  167.52 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  167.53 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  167.54 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  167.55 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  167.56 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  167.57 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
   168.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   168.2 +++ b/lib/isi/__init__.py	Mon Apr 26 11:16:23 2010 +0200
   168.3 @@ -0,0 +1,5 @@
   168.4 +from srv import Manager, IsiConn, get_main_groups, get_logger
   168.5 +from conf import defaults
   168.6 +import conf
   168.7 +import models
   168.8 +import exc
   169.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.2 +++ b/lib/isi/bulk_users.py	Mon Apr 26 11:16:23 2010 +0200
   169.3 @@ -0,0 +1,450 @@
   169.4 +# coding: utf-8 
   169.5 +
   169.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   169.7 +#
   169.8 +#  This program is free software: you can redistribute it and/or modify
   169.9 +#  it under the terms of the GNU General Public License as published by
  169.10 +#  the Free Software Foundation, either version 3 of the License, or
  169.11 +#  (at your option) any later version.
  169.12 +#
  169.13 +#  This program is distributed in the hope that it will be useful,
  169.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  169.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  169.16 +#  GNU General Public License for more details.
  169.17 +#
  169.18 +#  You should have received a copy of the GNU General Public License
  169.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  169.20 +
  169.21 +
  169.22 +"""
  169.23 +class Users that handles Users in bulk and can generate a .isi format list
  169.24 +
  169.25 +"""
  169.26 +import os
  169.27 +import re
  169.28 +import srv
  169.29 +from isi import models, exc
  169.30 +from isi.conf import defaults, tools
  169.31 +from parser import new_password
  169.32 +
  169.33 +class BulkUsers(object):
  169.34 +    """
  169.35 +    A set of users that must be added to the system.
  169.36 +    """
  169.37 +    user_format = None
  169.38 +    def __init__(self, maingroup, user_format=None, random_password=False):
  169.39 +        """
  169.40 +        :param maingroup: the maingroup for which we are inserting users
  169.41 +        :param user_format: the user format we want. Mainformat must be in the format of
  169.42 +           template strings %(attr_name)s, but 3 other formats are recognized:
  169.43 +           'cf', and 'name', 'id-name'
  169.44 +           If user-format is not passed it's taken from defaults.py (cf for students and name for others)
  169.45 +        """
  169.46 +
  169.47 +        self.random_password = random_password
  169.48 +        self.l = srv.Manager()
  169.49 +        self.maingroup = maingroup
  169.50 +        self.gid = self.l.get_group(maingroup).gid
  169.51 +        self.users = self.l.pumpkin_conn.search(models.PosixUser)
  169.52 +        self.user_list = [u.logname for u in self.users]
  169.53 +        self.cf_dict = {}
  169.54 +        self.users_dict = {}
  169.55 +        for u in self.users:
  169.56 +            self.cf_dict[u.cf] = u
  169.57 +            self.users_dict[u.logname] = u
  169.58 +        self.file_users = []
  169.59 +        self.file_users_dict = {}
  169.60 +        self.renamed = []
  169.61 +        self.used_lognames = []
  169.62 +        self.user_format = user_format
  169.63 +        self.filename = None
  169.64 +        self.file_users = []
  169.65 +
  169.66 +    def read_file(self, filename, file_format=None):
  169.67 +        """
  169.68 +        read a file with a list of all users of the group for which BulkUsers was instantiated
  169.69 +
  169.70 +        :param file_format: can be sissi or isi
  169.71 +
  169.72 +        """
  169.73 +        assert file_format in ('isi', 'sissi'), "File format must in 'isi' or 'sissi'"
  169.74 +        self.filename = filename
  169.75 +        self.file_users = []
  169.76 +        first = True if file_format in ('sissi',) else False
  169.77 +        for line in self.get_lines(filename):
  169.78 +            if first == True:
  169.79 +                ## heading
  169.80 +                try:
  169.81 +                    SissiUser.read_heading(line)
  169.82 +                except exc.WrongFileFormat, e:
  169.83 +                    msg = """Forse il file '%s' non e' nel formato corretto (Sissi)
  169.84 +                             Errore originale: KeyError %s""" % (filename, e.message)
  169.85 +                    raise exc.WrongFileFormat(msg)
  169.86 +                first = False
  169.87 +                continue
  169.88 +            line = line.strip()
  169.89 +
  169.90 +            if line:
  169.91 +                if file_format == 'sissi':
  169.92 +                    self.file_users += [SissiUser(line, self)]
  169.93 +                elif file_format == 'isi':
  169.94 +                    self.file_users += [IsiUser(line, self)]
  169.95 +        self.get_overlap()
  169.96 +
  169.97 +    def get_lines(self, filename):
  169.98 +        
  169.99 +        if filename.endswith('.xls'):
 169.100 +            lines = tools.Xls(filename).xls2csv()
 169.101 +            return lines.split('\n')
 169.102 +
 169.103 +        return open(filename)        
 169.104 +
 169.105 +    def get_new_users(self, logname=False):
 169.106 +        """
 169.107 +        return a list of users, not yet saved
 169.108 +        """
 169.109 +        new = set(u.logname for u in self.file_users)
 169.110 +        old = set(self.user_list)
 169.111 +        if logname:
 169.112 +            return set(new.difference(old))
 169.113 +        else:
 169.114 +            return [self.file_users_dict[name] for name in set(new.difference(old))]
 169.115 +
 169.116 +    def get_updated_users(self, logname=False):
 169.117 +        """
 169.118 +        return a list of old users updated in this file
 169.119 +        """
 169.120 +        new = set(u.logname for u in self.file_users)
 169.121 +        old = set(self.user_list)
 169.122 +        if logname:
 169.123 +            return set(old.intersection(new))
 169.124 +        else:
 169.125 +            return [self.file_users_dict[name] for name in new.intersection(old)]
 169.126 +
 169.127 +    def get_users_to_be_removed(self, logname=False):
 169.128 +        """
 169.129 +        return a list of users that need to be removed
 169.130 +
 169.131 +        :param logname: if True return a set of lognames else a list of PosixUsersx
 169.132 +
 169.133 +        """
 169.134 +        new = set(u.logname for u in self.file_users)
 169.135 +        old = set(u.logname for u in self.users if u.gid == self.gid)
 169.136 +        if logname:
 169.137 +            return old.difference(new)
 169.138 +        else:
 169.139 +            return [self.users_dict[name] for name in old.difference(new)]
 169.140 +
 169.141 +    deleted = property(get_users_to_be_removed)
 169.142 +    def get_overlap(self):
 169.143 +        """
 169.144 +        return list of users that have same first and last name and do not have
 169.145 +        the same CF or have empty CF
 169.146 +        """
 169.147 +        overlap = []
 169.148 +        for u in self.file_users:
 169.149 +            unique = self.is_unique(u)
 169.150 +            if not unique:
 169.151 +                u.logname = self.get_unique_name(u.logname)
 169.152 +                self.renamed += [u]
 169.153 +                overlap += [u]
 169.154 +            self.used_lognames += [u.logname]
 169.155 +            self.file_users_dict[u.logname] = u
 169.156 +        return overlap
 169.157 +
 169.158 +    def is_unique(self, user):
 169.159 +        """
 169.160 +        return a boolean saying if the name is unique. Uses CF
 169.161 +
 169.162 +        :param user: a NewUser object
 169.163 +        """
 169.164 +        if user.logname not in (self.user_list + self.used_lognames):
 169.165 +            return True
 169.166 +        else:
 169.167 +            if user.cf and user.cf in self.cf_dict:
 169.168 +                return True
 169.169 +        return False
 169.170 +        
 169.171 +    def get_unique_name(self, username):
 169.172 +        """
 169.173 +        return a unique name for user according to already present users
 169.174 +        """
 169.175 +        print "get-unique-name", username
 169.176 +        for i in range(2, 20):
 169.177 +            name = "%s%2.2d" % (username, i)
 169.178 +            if not self.l.user_exists(name) and not name in self.used_lognames:
 169.179 +                return name
 169.180 +
 169.181 +    def as_isi(self, filename=None, extended=False):
 169.182 +        """
 169.183 +        return a file in .isi format suitable to be fed to isi-addusers
 169.184 +
 169.185 +        :param filename: write in filename
 169.186 +        """
 169.187 +        output = [u.as_isi(extended=extended) for u in self.file_users]
 169.188 +        output += ["-%s" % u.as_isi_format(extended=extended) for u in self.get_users_to_be_removed(logname=False)]
 169.189 +        if filename:
 169.190 +            open(filename, 'w').write("\n".join(output) + "\n")
 169.191 +            return
 169.192 +        return "\n".join(output)
 169.193 +
 169.194 +    def renamed_as_text(self):
 169.195 +        """
 169.196 +        return a list of users renamed as text
 169.197 +        """
 169.198 +        output = []
 169.199 +        for u in self.renamed:
 169.200 +            output += ["\t".join([u.logname, u.last_name, u.first_name])]
 169.201 +        return "\n".join(output)
 169.202 +
 169.203 +    def deleted_as_text(self):
 169.204 +        """
 169.205 +        return a list of users deleted as text
 169.206 +        """
 169.207 +        output = []
 169.208 +        for u in self.get_users_to_be_removed(logname=False):
 169.209 +            output += ["\t".join([u.logname, u.last_name, u.first_name])]
 169.210 +        return "\n".join(output)
 169.211 +
 169.212 +    def _get_user_format(self):
 169.213 +
 169.214 +        return self._user_format
 169.215 +
 169.216 +    def _set_user_format(self, format):
 169.217 +
 169.218 +        if format == 'cf':
 169.219 +            format = u'%(group_id)s_%(cf).11s'
 169.220 +        elif format == 'name':
 169.221 +            format = u'%(first_name)s.%(last_name)s'
 169.222 +        elif format == 'id-name':
 169.223 +            format = u'%(group_id)s_%(first_name)s.%(last_name)s'
 169.224 +
 169.225 +        self._user_format = format
 169.226 +
 169.227 +    user_format = property(_get_user_format, _set_user_format)
 169.228 +
 169.229 +    def __str__(self):
 169.230 +        return "<BulkUser %s (%s)>" % (self.maingroup, self.filename)
 169.231 +
 169.232 +class NewUser(object):
 169.233 +
 169.234 +    user_format = None
 169.235 +    def _get_logname(self):
 169.236 +        try:
 169.237 +            return self._logname
 169.238 +        except AttributeError:
 169.239 +            fmt = self.user_format or defaults.USER_FORMAT.get(self.maingroup, None) or defaults.USER_FORMAT.get('default')
 169.240 +            return (fmt % self).lower()
 169.241 +
 169.242 +    def _set_logname(self, logname):
 169.243 +        self._logname = logname
 169.244 +        
 169.245 +    def _get_group_id(self):
 169.246 +        return defaults.GROUP_IDS[self.maingroup]
 169.247 +
 169.248 +    group_id = property(_get_group_id)
 169.249 +    logname = property(_get_logname, _set_logname)
 169.250 +
 169.251 +    def _get_password(self):
 169.252 +        if self.bulk_instance.random_password:
 169.253 +            return new_password()
 169.254 +        try:
 169.255 +            return self._password
 169.256 +        except AttributeError:
 169.257 +            return ''
 169.258 +
 169.259 +    password = property(_get_password)
 169.260 +    
 169.261 +    def __getitem__(self, key):
 169.262 +        """
 169.263 +        Cast all None values to '' otherwise the lookup can be scattered with 'None'
 169.264 +        as %(field_name)s would render as 'None' a None value
 169.265 +        """
 169.266 +        return getattr(self, key, '') or ''
 169.267 +
 169.268 +    def as_isi(self, extended=False):
 169.269 +        """
 169.270 +        return the user isi 'isi'  format: ie. as used by isi-adduser
 169.271 +        """
 169.272 +        record = [self.logname, self.last_name, self.first_name or '', self.maingroup,
 169.273 +                  self.classe or '', self.cf or '', self.password]
 169.274 +        if extended:
 169.275 +            city, pv = '', ''
 169.276 +            pattern = re.compile('^(?P<city>.*)\((?P<pv>..)\)')
 169.277 +            m = pattern.match(self.city or '')
 169.278 +            if m:
 169.279 +                city = cp.group('city').strip()
 169.280 +                pv = cp.group('pv')
 169.281 +
 169.282 +            
 169.283 +            record += [self.sex or '', self.address or '', city, pv, self.zip_code or '', self.phone or '']
 169.284 +
 169.285 +        return ";".join(record)
 169.286 +            
 169.287 +    def _get_classe(self):
 169.288 +        """
 169.289 +        return the school_class according to:
 169.290 +
 169.291 +          * year (anno_corso)
 169.292 +          * corsi mapping
 169.293 +          * section
 169.294 +          
 169.295 +        """
 169.296 +        return (defaults.CLASSE_FORMAT % self).lower()
 169.297 +
 169.298 +    classe = property(_get_classe)
 169.299 +
 169.300 +    def __str__(self):
 169.301 +        return "%(first_name)s %(last_name)s" % self
 169.302 +
 169.303 +    def __repr__(self):
 169.304 +        return "<NewUser: %(logname)s (%(first_name)s %(last_name)s - %(maingroup)s)>" % self
 169.305 +
 169.306 +def get_sissi_tabcorsi():
 169.307 +    """
 169.308 +    read /etc/isi/sissi-tabcorsi and produce a suitable class  mapping object
 169.309 +    that returns an acronim 
 169.310 +    """
 169.311 +    tabsissi = {}
 169.312 +    if not os.path.exists('/etc/isi/sissi-tabcorsi'):
 169.313 +        raise exc.MissingCourseMapping("Manca sissi-tabcorsi vecessario per tradurre i corsi in sigle")
 169.314 +        
 169.315 +    for line in open('/etc/isi/sissi-tabcorsi'):
 169.316 +        line = line.strip().split('=')
 169.317 +        if len(line) == 2:
 169.318 +            corso_def   = line[0].strip().lower()
 169.319 +            corso_sigla = line[1].strip().lower()
 169.320 +            tabsissi[corso_def] = corso_sigla
 169.321 +
 169.322 +    return tabsissi
 169.323 +    
 169.324 +class SissiUser(NewUser):
 169.325 +    """
 169.326 +    A user object as described in the file, one attribute for each (needed) column
 169.327 +    Anno di corso;Sezione;Corso;Cognome;Nome;Data di nascita;Sesso;Comune di nascita;Prov. Nascita;
 169.328 +    Codice fiscale;Indirizzo;Comune di residenza;CAP;Prov. Residenza;Telefono 1;Telefono 2;
 169.329 +    Cognome padre;Nome padre;Cognome madre;Nome madre;Anno Sc.
 169.330 +
 169.331 +    """
 169.332 +    cols = {}
 169.333 +    attrs = ['first_name', 'last_name', 'sex', 'cf']
 169.334 +    corsi_dict = get_sissi_tabcorsi()
 169.335 +    col_map = {
 169.336 +        'anno_corso' :        'Anno di corso',
 169.337 +        'sezione' :           'Sezione',
 169.338 +        'last_name' :         'Cognome',
 169.339 +        'first_name' :        'Nome',
 169.340 +        'birth_date' :        'Data di nascita',
 169.341 +        'sex' :               'Sesso',
 169.342 +        'birth_city' :        'Comune di nascita',
 169.343 +        'birth_pv' :          'Prov. Nascita',
 169.344 +        'cf' :                'Codice fiscale',
 169.345 +        'address' :           'Indirizzo',
 169.346 +        'city' :              'Comune di residenza',
 169.347 +        'zip_code' :          'CAP',
 169.348 +        'pv' :                'Prov. Residenza',
 169.349 +        'phone' :             'Telefono 1',
 169.350 +        'phone2' :            'Telefono 2',
 169.351 +        'father_last_name' :  'Cognome padre',
 169.352 +        'father_first_name' : 'Nome padre',
 169.353 +        'mother_last_name' :  'Cognome madre',
 169.354 +        'mother_first_name' : 'Nome madre',
 169.355 +        'shool_year' :        'Anno Sc.',
 169.356 +        }        
 169.357 +    
 169.358 +    def __init__(self, line, bulk_instance):
 169.359 +
 169.360 +        self.bulk_instance = bulk_instance
 169.361 +        self.user_format = bulk_instance.user_format
 169.362 +        if isinstance(line, basestring):
 169.363 +            line = line.split(';')
 169.364 +
 169.365 +        self.maingroup   = bulk_instance.maingroup
 169.366 +        for att_name, col_description in self.col_map.iteritems():
 169.367 +
 169.368 +            try:
 169.369 +                key = self.cols[col_description]
 169.370 +            except KeyError, e:
 169.371 +                msg = """Forse il file di input non e' nel formato corretto (Sissi)
 169.372 +                         Errore originale: KeyError: '%s'""" % (e.message)
 169.373 +                raise exc.WrongFileFormat(msg)
 169.374 +
 169.375 +            try:
 169.376 +                setattr(self, att_name, line[key] or '')
 169.377 +            except IndexError:
 169.378 +                pass
 169.379 +
 169.380 +        try:
 169.381 +            self.corso       = self.corsi_dict[line[self.cols['Corso']].lower()]
 169.382 +        except KeyError:
 169.383 +            msg = u"Il corso '%s' non puo' essere tradotto in una sigla. Guarda /etc/isi/sissi-tabcorsi"
 169.384 +            raise exc.MissingCourseMapping(msg % line[self.cols['Corso']])
 169.385 +        
 169.386 +        self.last_name   = self.last_name.title()
 169.387 +        self.first_name  = self.first_name.title()
 169.388 +        self.birth_date  = self.birth_date.title()
 169.389 +        self.city        = self.city.title()
 169.390 +        self.pv          = self.pv.upper()
 169.391 +        self.anno_corso  = int(float(self.anno_corso))  # xls writes '3' as numeric, 
 169.392 +#        self.school_year = int(float(self.school_year)) # so that it turns as 3.0
 169.393 +
 169.394 +    @classmethod
 169.395 +    def read_heading(cls, line):
 169.396 +        for i, col_name in enumerate(line.strip().split(';')):
 169.397 +            cls.cols[col_name] = i
 169.398 +        
 169.399 +class IsiUser(NewUser):
 169.400 +    """
 169.401 +    A User as described for .isi format:
 169.402 +      1. logname
 169.403 +      2. last_name
 169.404 +      3. first_name
 169.405 +      4. maingroup
 169.406 +      5. more groups (i.e.: class)
 169.407 +      6. cf (italian  CF codice fiscale, any unique key will do - optional)
 169.408 +      7. password (optional)
 169.409 +    """
 169.410 +    
 169.411 +    def __init__(self, line, bulk_instance):
 169.412 +
 169.413 +        self.bulk_instance = bulk_instance
 169.414 +        self.user_format = bulk_instance.user_format
 169.415 +        if isinstance(line, basestring):
 169.416 +            line = line.split(';')
 169.417 +
 169.418 +
 169.419 +        self._logname   = line[0].lower()
 169.420 +        self.last_name   = line[1].title()
 169.421 +        self.first_name  = line[2].title()
 169.422 +        self.maingroup   = bulk_instance.maingroup
 169.423 +
 169.424 +        try:
 169.425 +            self.groups      = line[4].lower()
 169.426 +        except IndexError, e:
 169.427 +            self.groups      = ''
 169.428 +            
 169.429 +        try:
 169.430 +            self.cf  = line[5].upper()
 169.431 +        except IndexError, e:
 169.432 +            self.cf = ''
 169.433 +            
 169.434 +        try:
 169.435 +            self._password  = line[6]
 169.436 +        except IndexError, e:
 169.437 +            self.password = None
 169.438 +        
 169.439 +
 169.440 +    def _get_classe(self):
 169.441 +        """
 169.442 +        return the school_class according to:
 169.443 +
 169.444 +          * year (anno_corso)
 169.445 +          * corsi mapping
 169.446 +          * section
 169.447 +          
 169.448 +        """
 169.449 +        if self.groups:
 169.450 +            return self.groups.split(',')[0]
 169.451 +        return None
 169.452 +
 169.453 +    classe = property(_get_classe)
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/lib/isi/conf/__init__.py	Mon Apr 26 11:16:23 2010 +0200
   170.3 @@ -0,0 +1,22 @@
   170.4 +"""
   170.5 +This module provide a way to handle configuration files related to the isi project:
   170.6 +
   170.7 +  logon.conf
   170.8 +  dnsmasq.conf
   170.9 +
  170.10 +The latter has been split into 3 different conf files:
  170.11 +
  170.12 +  * boot:  with all boot related option *except dhcp-options*
  170.13 +           tjese are all options related to boot but NOT related to a single MAC
  170.14 +           
  170.15 +  * hosts.mac: with dhcp-options, i.e.: all options related to a host
  170.16 +          related or not to the boot phase
  170.17 +
  170.18 +tool.py provides a Class used by any ot the other modules
  170.19 +logon.py + params.py is just for logon.conf
  170.20 +dnsmasq.py is ok for dnsmasq.conf
  170.21 +hosts.py is ok for /etc/hosts
  170.22 +mac.py is ok for hosts.mac
  170.23 +
  170.24 +
  170.25 +"""
   171.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   171.2 +++ b/lib/isi/conf/defaults.py	Mon Apr 26 11:16:23 2010 +0200
   171.3 @@ -0,0 +1,80 @@
   171.4 +#!/usr/bin/python
   171.5 +# -*- coding: utf-8 -*-
   171.6 +
   171.7 +# This program is free software; you can redistribute it and/or modify
   171.8 +# it under the terms of the GNU General Public License as published by
   171.9 +# the Free Software Foundation; either version 2, or (at your option)
  171.10 +# any later version.
  171.11 +
  171.12 +
  171.13 +# AUTHORS: Sandro Dentella - Massimo Mancini
  171.14 +
  171.15 +"""
  171.16 +These defaults will be overwritten by values in /etc/isi/defaults.py
  171.17 +"""
  171.18 +import os
  171.19 +# struttura della /home
  171.20 +GROUPS_PATH = '/home/users'
  171.21 +CLASSES_PATH = '/home/shares/classi'
  171.22 +COURSES_PATH = '/home/shares/corsi'
  171.23 +
  171.24 +# gruppi a cui vanno assegnati gli utenti se si vuole che possano
  171.25 +# usare chiavette e audio dei client linux
  171.26 +#EXTRA_GROUPS = []
  171.27 +EXTRA_GROUPS = ['plugdev','audio', 'fuse']
  171.28 +
  171.29 +        
  171.30 +# usato da isi2-adduser per l'imput interattivo
  171.31 +DATI_USER = "USER_ID COGNOME NOME GRUPPO GRUPPI COD.FISC. PASSWORD SESSO INDIRIZZO COMUNE CAP PROVINCIA TELEFONO"    
  171.32 +
  171.33 +# configurazione del logger
  171.34 +LOG_FILE = '/var/log/users_error.log'
  171.35 +LOG_MODE = 'w'
  171.36 +LOG_FORMAT = '%(asctime)s %(name)-8s %(levelname)-8s %(message)s'
  171.37 +LOG_DATE_FORMAT='%y-%m-%d %H:%M'
  171.38 +
  171.39 +# configurazione del backup ldap
  171.40 +BAK_LDAP_FILE = '/etc/isi/slapcat.ldif'
  171.41 +
  171.42 +# QUOTA
  171.43 +QUOTA_S1 = 0
  171.44 +QUOTA_S2 = 0
  171.45 +QUOTA_F1 = 0
  171.46 +QUOTA_F2 = 0
  171.47 +QUOTA_REP = '/tmp/repquota.txt'
  171.48 +
  171.49 +# PERMESSI DI DEFAULT SU HOME E FILE (indipendenti da acl)
  171.50 +# alunni ed esterni
  171.51 +PERMS_HOME_ALU = '2770'
  171.52 +PERMS_FILE_ALU = '660'
  171.53 +# tutti gli altri
  171.54 +PERMS_HOME_ALL = '2700'
  171.55 +PERMS_FILE_ALL = '600'
  171.56 +
  171.57 +# NUMERI INIZIALI LDAP
  171.58 +UID_MIN = 1000
  171.59 +GID_MIN = 1000
  171.60 +UID_MAX = 30000
  171.61 +GID_MAX = 30000
  171.62 +
  171.63 +## User's logname format
  171.64 +
  171.65 +GROUP_IDS = {
  171.66 +    'alunni'     : 'a',
  171.67 +    'docenti'    : 'd',
  171.68 +    'admins'     : 'ad',
  171.69 +    'esterni'    : 'e',
  171.70 +    'segreteria' : 's',
  171.71 +    'ata'        : 'at',
  171.72 +    }
  171.73 +
  171.74 +USER_FORMAT = {
  171.75 +    'default' : u'%(group_id)s_%(cf).8s',
  171.76 +    'docenti' : u'%(first_name)s.%(last_name)s',
  171.77 +    }
  171.78 +
  171.79 +CLASSE_FORMAT = u"%(corso)s%(anno_corso)s%(sezione)s" 
  171.80 +
  171.81 +if os.path.exists('/etc/isi/defaults.py'):
  171.82 +    execfile('/etc/isi/defaults.py')
  171.83 +
   172.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.2 +++ b/lib/isi/conf/dnsmasq.py	Mon Apr 26 11:16:23 2010 +0200
   172.3 @@ -0,0 +1,177 @@
   172.4 +# -*- coding: utf-8 -*-
   172.5 +
   172.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   172.7 +#
   172.8 +#  This program is free software: you can redistribute it and/or modify
   172.9 +#  it under the terms of the GNU General Public License as published by
  172.10 +#  the Free Software Foundation, either version 3 of the License, or
  172.11 +#  (at your option) any later version.
  172.12 +#
  172.13 +#  This program is distributed in the hope that it will be useful,
  172.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  172.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  172.16 +#  GNU General Public License for more details.
  172.17 +#
  172.18 +#  You should have received a copy of the GNU General Public License
  172.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  172.20 +
  172.21 +
  172.22 +"""
  172.23 +domain-needed
  172.24 +bogus-priv
  172.25 +server=208.67.222.222
  172.26 +server=208.67.220.220
  172.27 +filterwin2k
  172.28 +expand-hosts
  172.29 +domain=isi.lan
  172.30 +dhcp-range=192.168.96.130,192.168.96.140,255.255.255.0,8h
  172.31 +dhcp-host=00:0c:29:c9:69:35,192.168.96.190,vm-ltsp01,net:ns1  # client1
  172.32 +dhcp-host=00:0c:29:5e:69:b5,192.168.96.191,vm-ltsp02,net:ns2  # client2
  172.33 +dhcp-option=3,192.168.96.1
  172.34 +dhcp-option=6,192.168.96.254
  172.35 +dhcp-authoritative
  172.36 +cache-size=1024
  172.37 +conf-dir=/etc/isi/dns/dnsmasq
  172.38 +addn-hosts=/etc/isi/dns/hosts
  172.39 +# comment
  172.40 +"""
  172.41 +import re 
  172.42 +import time
  172.43 +import datetime
  172.44 +import urllib
  172.45 +from isi.conf import tools
  172.46 +
  172.47 +SIMPLE_PARAMS = "domain-needed bogus-priv filterwin2k expand-hosts dhcp-authoritative log-queries log-dhcp".split()
  172.48 +PARAMS = "server domain dhcp-range dhcp-host  dhcp-option dhcp-boot dhcp-vendorclass".split() + \
  172.49 +         "cache-size conf-dir addn-hosts conf-file conf-dir".split()
  172.50 +
  172.51 +
  172.52 +class UnknownParamName(tools.ValidationError): pass
  172.53 +class ParamRequireValue(tools.ValidationError): pass
  172.54 +
  172.55 +class Line(tools.Line):
  172.56 +
  172.57 +    VAR_PATTERN = re.compile(r"""
  172.58 +       (?P<comment>\s*\#\s*)?   # a possible comment of the line
  172.59 +       (?P<param_name>[\w-]+)            # the variable name
  172.60 +       \s*=*                      #  ok, that's an assignement
  172.61 +       (?P<value>.*?)           # got the value!, non greedy 
  172.62 +       (?P<final_comment>\s*(\#.*)?)               # a possible final comment
  172.63 +       $""", re.VERBOSE)
  172.64 +    param_name = None
  172.65 +    value = ''
  172.66 +    str_format = "%(param_name)s=%(value)s"
  172.67 +    
  172.68 +
  172.69 +    def validate(self):
  172.70 +        if self.is_comment:
  172.71 +            return True
  172.72 +        if self.param_name not in (PARAMS + SIMPLE_PARAMS):
  172.73 +            raise UnknownParamName("Param is not valid: %s" % self.param_name)
  172.74 +        if self.param_name in PARAMS and not self.value:
  172.75 +            raise ParamRequireValue("Param %s requires a value" % self.param_name)
  172.76 +        return True
  172.77 +        
  172.78 +    def __str__(self):
  172.79 +        if self.is_comment:
  172.80 +            return self.line
  172.81 +        if self.param_name in PARAMS:
  172.82 +            return "%s=%s" % (self.param_name, self.value)
  172.83 +        else:
  172.84 +            return "%s" % (self.param_name)
  172.85 +            
  172.86 +            
  172.87 +class Conf(tools.Conf):
  172.88 +     line_class = Line
  172.89 +     search_value = None
  172.90 +
  172.91 +     gw = '3'
  172.92 +     dns = '6'
  172.93 +     wins = '44'
  172.94 +
  172.95 +     def get_option(self, option=None, tag=False, ip=True):
  172.96 +         """option may be gw, dns or wins"""
  172.97 +
  172.98 +         assert option in ('gw', 'dns', 'wins'), "Option must be one of gw, dns or wins"
  172.99 +
 172.100 +         option_id = getattr(self, option)
 172.101 +         lines = [l for l in self.get_param('dhcp-option') if 
 172.102 +                 l.value.startswith(option_id)]
 172.103 +
 172.104 +         if tag:
 172.105 +             line = [l for l in lines if l.value.endswith("net:%s" % tag)]
 172.106 +
 172.107 +         if lines:
 172.108 +             if ip:
 172.109 +                 return get_ip(lines[0].value, option_id, tag)
 172.110 +             else:
 172.111 +                 return lines
 172.112 +
 172.113 +     def set_option(self, option=None, value=None, tag=False, ):
 172.114 +         """option may be gw, dns or wins"""
 172.115 +
 172.116 +         lines = self.get_option(option, tag, ip=False)
 172.117 +         option_id = getattr(self, option)
 172.118 +         tag_str = ",net:%s" if tag else ''
 172.119 +         new_value = "%s,%s%s" % (option_id, value, tag_str)
 172.120 +
 172.121 +         if lines:
 172.122 +             line = lines[0] ## FIXME
 172.123 +             line.value = new_value
 172.124 +         else:
 172.125 +             self.lines += [Line('dhcp-option=%s' % new_value)]
 172.126 +
 172.127 +def get_ip(value, option_id, tag=None):
 172.128 +    
 172.129 +    PATTERN = '%s,(?P<ip>[0-9.]*)(,net:(?P<tag>.*))?$' % option_id
 172.130 +    m = re.search(PATTERN, value)
 172.131 +    
 172.132 +    if m:
 172.133 +        if tag:
 172.134 +            if m.group('tag') == tag:
 172.135 +                return m.group('ip')
 172.136 +        else:
 172.137 +            return m.group('ip')
 172.138 +    return None
 172.139 +
 172.140 +class Lease(object):
 172.141 +    """
 172.142 +    A simple object that stores info on leases:
 172.143 +
 172.144 +    mac
 172.145 +    ip
 172.146 +    hostname
 172.147 +    extra
 172.148 +    """
 172.149 +    def __init__(self, mac, ip, hostname, client_id, lease):
 172.150 +        self.mac = mac
 172.151 +        self.ip = ip
 172.152 +        self.hostname = hostname if hostname != '*' else None
 172.153 +        self.client_id = client_id  if client_id != '*' else None
 172.154 +        self.lease_datetime = datetime.datetime(*time.localtime(int(lease))[:6])
 172.155 +
 172.156 +    def __repr__(self):
 172.157 +        return u"<Lease: %s %s %s>" % (self.mac, self.ip, self.hostname)
 172.158 +
 172.159 +def get_leases(filename='/var/lib/misc/dnsmasq.leases'):
 172.160 +    """
 172.161 +    fill and return a list of Lease instances using the dnsmasq.leases
 172.162 +    file's informations
 172.163 +    
 172.164 +    1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
 172.165 +    1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
 172.166 +    file format:
 172.167 +    http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2006q2/000734.html
 172.168 +
 172.169 +    """
 172.170 +    COMMENT = re.compile('^\s*#\s*.+$|^\s*$')
 172.171 +    leases = {}
 172.172 +
 172.173 +    for line in open(filename):
 172.174 +        if not re.match(COMMENT, line):
 172.175 +            m = re.match('\s*(.+)\s*', line)
 172.176 +            lease_time, mac, ip, hostname, client_id = m.group().split()
 172.177 +            leases[mac] = Lease(mac, ip, hostname, client_id, lease_time)
 172.178 +
 172.179 +    return leases.values()
 172.180 +
   173.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.2 +++ b/lib/isi/conf/hosts.py	Mon Apr 26 11:16:23 2010 +0200
   173.3 @@ -0,0 +1,59 @@
   173.4 +# -*- coding: utf-8 -*-
   173.5 +
   173.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   173.7 +#
   173.8 +#  This program is free software: you can redistribute it and/or modify
   173.9 +#  it under the terms of the GNU General Public License as published by
  173.10 +#  the Free Software Foundation, either version 3 of the License, or
  173.11 +#  (at your option) any later version.
  173.12 +#
  173.13 +#  This program is distributed in the hope that it will be useful,
  173.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  173.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  173.16 +#  GNU General Public License for more details.
  173.17 +#
  173.18 +#  You should have received a copy of the GNU General Public License
  173.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  173.20 +
  173.21 +
  173.22 +"""
  173.23 +127.0.0.1 localhost
  173.24 +127.0.1.1 ISI-PDC
  173.25 +192.168.96.222 srv-ltsp
  173.26 +192.168.96.210 ISI-PDC
  173.27 +192.168.96.22 www.tin.it
  173.28 +192.168.96.199 vm-client-ltsp1
  173.29 +192.168.96.44 srv-prova srv # questi sono dei commenti
  173.30 +"""
  173.31 +import re 
  173.32 +import urllib
  173.33 +from isi.conf import tools
  173.34 +
  173.35 +class WrongIPError(tools.ValidationError): pass
  173.36 +
  173.37 +class Line(tools.Line):
  173.38 +
  173.39 +    VAR_PATTERN = re.compile(r"""
  173.40 +       (?P<comment>\s*\#\s*)?            # a possible comment of the line
  173.41 +       (?P<param_name>[\w.]+)            # the variable name
  173.42 +       \s+                               #  ok, that's an assignement
  173.43 +       (?P<value>.+?)                    # got the value!, non greedy 
  173.44 +       (?P<final_comment>\s*(\#.*)?)     # a possible final comment
  173.45 +       $""", re.VERBOSE)
  173.46 +    param_name = None
  173.47 +    name = None
  173.48 +    str_format = "%(param_name)s %(value)s"
  173.49 +    
  173.50 +    def validate(self):
  173.51 +        if tools.is_ip_address(self.param_name) and self.value:
  173.52 +            return True
  173.53 +        raise WrongIPError("%s is not a valid IP" % self.param_name)
  173.54 +                    
  173.55 +class Hosts(tools.Conf):
  173.56 +    line_class = Line
  173.57 +
  173.58 +    def set_param(self, param_name, value=None):
  173.59 +
  173.60 +        return tools.Conf.set_param(self, param_name, value=value)
  173.61 +        
  173.62 +
   174.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   174.2 +++ b/lib/isi/conf/logon.py	Mon Apr 26 11:16:23 2010 +0200
   174.3 @@ -0,0 +1,232 @@
   174.4 +# -*- coding: utf-8 -*-
   174.5 +
   174.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   174.7 +#
   174.8 +#  This program is free software: you can redistribute it and/or modify
   174.9 +#  it under the terms of the GNU General Public License as published by
  174.10 +#  the Free Software Foundation, either version 3 of the License, or
  174.11 +#  (at your option) any later version.
  174.12 +#
  174.13 +#  This program is distributed in the hope that it will be useful,
  174.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  174.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  174.16 +#  GNU General Public License for more details.
  174.17 +#
  174.18 +#  You should have received a copy of the GNU General Public License
  174.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  174.20 +
  174.21 +
  174.22 +"""
  174.23 +Start__Page          = www.google.it #
  174.24 +Start__Page[admins]  = www.google.it
  174.25 +ProxyServer          = XXX.XXX.XXX:8128    # DansGuardian
  174.26 +ProxyServer[admins]  = XXX.XXX.XXX:3128    # Squid (FW permettendo)
  174.27 +ProxyOverride        = www.XXX.XXX,<local>
  174.28 +"""
  174.29 +import re 
  174.30 +class MultipleParamError(Exception): pass
  174.31 +class UnknownParamError(Exception): pass
  174.32 +from params import PARAMS
  174.33 +import urllib
  174.34 +
  174.35 +class Line(object):
  174.36 +
  174.37 +    VAR_PATTERN = re.compile(r"""
  174.38 +       (?P<comment>\s*\#\s*)?   # a possible comment of the line
  174.39 +       (?P<name>\w+)            # the variable name
  174.40 +       ((\[
  174.41 +          (?P<drive>.:)?           # if it's a share we may have a 'drive'
  174.42 +          (?P<group>\w+)       
  174.43 +          \])?)?                 # can be Start__Page[admin] in which case I need just Start__Page
  174.44 +       \s*=\s*                  #  ok, that's an assignement
  174.45 +       (?P<value>.+?)           # got the value!, non greedy 
  174.46 +       (?P<final_comment>\s*(\#.*)?)               # a possible final comment
  174.47 +       $""", re.VERBOSE)
  174.48 +
  174.49 +    def __init__(self, line=None, param_name=None, group=None, value=None, drive=None):
  174.50 +        """
  174.51 +        create a line of the conf file. Comment line can be created passing line arg only::
  174.52 +
  174.53 +        Line('Start__Page          = www.google.it')
  174.54 +        Line('ProxyServer[admins]  = XXX.XXX.XXX:3128    # Squid (FW permettendo)')
  174.55 +        
  174.56 +        """
  174.57 +
  174.58 +        if line is None:
  174.59 +            self.param_name = param_name
  174.60 +            self.group = group
  174.61 +            self.value = value or ''
  174.62 +            self.final_comment = ''
  174.63 +            self.is_comment = False
  174.64 +            self.drive = drive
  174.65 +            self.line = str(self)
  174.66 +        else:
  174.67 +            self.line = line
  174.68 +            m = self.VAR_PATTERN.match(line.strip())
  174.69 +            if m:
  174.70 +                comm = m.group('comment')
  174.71 +                self.is_comment = True if (comm and  '#' in comm) else False
  174.72 +                self.param_name = m.group('name')
  174.73 +                self.value = m.group('value')
  174.74 +                self.final_comment = m.group('final_comment') or ''
  174.75 +                self.group = m.group('group')
  174.76 +                self.drive = m.group('drive') and re.sub(':', '', m.group('drive')) 
  174.77 +                ## let's fix the parser for drive w/o group
  174.78 +                ## _NetFolder[K] = classi: K would be put in group and drive empty
  174.79 +                if self.group and len(self.group) == 1 and not self.drive:
  174.80 +                    self.drive = self.group
  174.81 +                    self.group = None
  174.82 +
  174.83 +            else:
  174.84 +                self.is_comment = True
  174.85 +
  174.86 +    def variable(self):
  174.87 +        if self.group:
  174.88 +            if self.drive:
  174.89 +                return "%s[%s:%s]" % (self.param_name, self.drive, self.group)
  174.90 +            else:
  174.91 +                return "%s[%s]" % (self.param_name, self.group)
  174.92 +        else:
  174.93 +            if self.drive:
  174.94 +                return "%s[%s]" % (self.param_name, self.drive)
  174.95 +                
  174.96 +        return self.param_name
  174.97 +
  174.98 +    def __str__(self):
  174.99 +        if self.is_comment:
 174.100 +            return self.line
 174.101 +        return "%s = %s%s" % (self.variable(), self.value or '',
 174.102 +                              self.final_comment and (" " + self.final_comment))
 174.103 +            
 174.104 +    def __repr__(self):
 174.105 +        if self.is_comment:
 174.106 +            return self.line[:10]
 174.107 +        return "<%s>" % vars(self)
 174.108 +
 174.109 +    def _url(self):
 174.110 +        """
 174.111 +        return the url as used in web application
 174.112 +        """
 174.113 +        if self.is_comment:
 174.114 +            return ''
 174.115 +        add = ''
 174.116 +        url = u"/%s/?param_name=%s&" % ((self.param_name,) *2)
 174.117 +        if self.group:
 174.118 +            url += "group=%s" % self.group
 174.119 +            add = '&'
 174.120 +        if self.drive:
 174.121 +            url += "%sdrive=%s" % (add, self.drive)
 174.122 +        return url
 174.123 +    url = property(_url)
 174.124 +
 174.125 +    def _url_del(self):
 174.126 +        """
 174.127 +        return an url w/ valu suitable for del
 174.128 +        """
 174.129 +        return self.url + "&value=" + (urllib.quote(self.value) or '')
 174.130 +
 174.131 +    url_del = property(_url_del)
 174.132 +
 174.133 +class Logon(object):
 174.134 +
 174.135 +    def __init__(self, filename=None, text=None):
 174.136 +
 174.137 +        assert filename or text, "You must set filename or text"
 174.138 +        self.filename = filename
 174.139 +        if filename:
 174.140 +            self.lines = [Line(l) for l in open(filename)]
 174.141 +        else:
 174.142 +            self.lines = [Line(l) for l in text.split('\n')]
 174.143 +
 174.144 +    def set_param(self, param_name, value=None, group=None, drive=None):
 174.145 +        """
 174.146 +        set a value that can only have one value as e.g.:
 174.147 +        _debug
 174.148 +        """
 174.149 +        if param_name not in PARAMS:
 174.150 +            raise UnknownParamError("%s is not a valid ParamName" % param_name)
 174.151 +
 174.152 +        lines = self.get_param(param_name, group=group, drive=drive)
 174.153 +
 174.154 +        if len(lines) > 1:
 174.155 +            raise MultipleParamError("Param %s is present %d times" % (param_name, len(lines)))
 174.156 +        
 174.157 +        if lines:
 174.158 +            line = lines[0]
 174.159 +            line.param_name = param_name
 174.160 +            line.value = value
 174.161 +            line.group = group
 174.162 +        else:
 174.163 +            line = Line(param_name=param_name, value=value, group=group, drive=drive)
 174.164 +            l = self.get_param(param_name, group=False, drive=False)
 174.165 +            if len(l) == 0:
 174.166 +                idx = len(self.lines)
 174.167 +            else:
 174.168 +                idx = self.lines.index(l[-1])
 174.169 +
 174.170 +            self.lines.insert(idx + 1, line)
 174.171 +
 174.172 +        return line
 174.173 +
 174.174 +    def get_param(self, param_name, group=False, drive=False, value=False):
 174.175 +        """
 174.176 +        return the (possible) Line objects that have param_name and possibly group
 174.177 +        """
 174.178 +        ret = []
 174.179 +        for l in self.lines:
 174.180 +            if not l.is_comment and l.param_name == param_name:
 174.181 +                ret += [l]
 174.182 +        if group is not False:
 174.183 +            ret = [l for l in ret if l.group == group]
 174.184 +        if drive is not False:
 174.185 +            ret = [l for l in ret if l.drive == drive]
 174.186 +        if value is not False:
 174.187 +            ret = [l for l in ret if l.value == value]
 174.188 +        return ret
 174.189 +
 174.190 +    def del_param(self, param_name,  group=None, drive=None, value=None):
 174.191 +        """
 174.192 +        delete a parameter
 174.193 +        """
 174.194 +        kw = { 'group' :group, 'drive' :drive,}
 174.195 +        if value:
 174.196 +            kw['value'] = value
 174.197 +        try:
 174.198 +            l = self.get_param(param_name, **kw)[0]
 174.199 +        except IndexError, e:
 174.200 +            return
 174.201 +        
 174.202 +        self.lines.remove(l)
 174.203 +        return l
 174.204 +
 174.205 +    def __str__(self):
 174.206 +        return "\n".join([str(l).strip() for l in self.lines])
 174.207 +        
 174.208 +    def __len__(self):
 174.209 +        return len(self.lines)
 174.210 +
 174.211 +    def len(self):
 174.212 +        """Return the number of non-comment lines"""
 174.213 +        return len([l for l in self.lines if not l.is_comment])
 174.214 +
 174.215 +    def diff(self, other, this_file='this.conf', other_file='other.conf'):
 174.216 +        """return a diff between self and other"""
 174.217 +
 174.218 +        assert isinstance(other, Logon), "other must be a Logon instance (is %s)" % oter.__class__
 174.219 +        import difflib
 174.220 +        diff = []
 174.221 +        
 174.222 +        for line in difflib.unified_diff(["%s\n" % l for l in str(self).split('\n')],
 174.223 +                                         ["%s\n" % l for l in str(other).split('\n')],
 174.224 +                                         this_file, other_file):
 174.225 +            diff += [line]
 174.226 +        return "".join(diff)
 174.227 +    
 174.228 +    def save(self, filename=None):
 174.229 +
 174.230 +        filename = filename or self.filename
 174.231 +        
 174.232 +        f = open(filename, 'w')
 174.233 +        f.write(str(self) + '\n')
 174.234 +        f.close()
 174.235 +        
   175.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.2 +++ b/lib/isi/conf/mac.py	Mon Apr 26 11:16:23 2010 +0200
   175.3 @@ -0,0 +1,106 @@
   175.4 +# -*- coding: utf-8 -*-
   175.5 +
   175.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   175.7 +#
   175.8 +#  This program is free software: you can redistribute it and/or modify
   175.9 +#  it under the terms of the GNU General Public License as published by
  175.10 +#  the Free Software Foundation, either version 3 of the License, or
  175.11 +#  (at your option) any later version.
  175.12 +#
  175.13 +#  This program is distributed in the hope that it will be useful,
  175.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  175.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  175.16 +#  GNU General Public License for more details.
  175.17 +#
  175.18 +#  You should have received a copy of the GNU General Public License
  175.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  175.20 +
  175.21 +
  175.22 +"""
  175.23 +### sample : hosts_mac (vecchio formato, da non supportare!)
  175.24 +dhcp-host=00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1 # commento1
  175.25 +dhcp-host=00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2
  175.26 +
  175.27 +### sample : hosts_mac (nuovo formato che prevede anche l'uso dei tag)
  175.28 +dhcp-host=00:0c:29:c9:69:35,192.168.96.190,vm-ltsp01,net:ns1 # client1
  175.29 +dhcp-host=00:0c:29:5e:69:b5,192.168.96.191,vm-ltsp02,net:ns2
  175.30 +"""
  175.31 +import re 
  175.32 +import urllib
  175.33 +from isi.conf import tools
  175.34 +
  175.35 +class WrongMACError(tools.ValidationError): pass
  175.36 +class WrongValueError(tools.ValidationError): pass
  175.37 +
  175.38 +###  DISCLAIMER: this parser is seriously incomplete and only meant for ReteISI Project!!!!
  175.39 +###
  175.40 +class Line(tools.Line):
  175.41 +
  175.42 +    VAR_PATTERN = re.compile(r"""
  175.43 +       (?P<comment>\s*\#\s*)?       # a possible comment of the line
  175.44 +       (?P<param_name>[\w-]+)        # the variable name
  175.45 +       \s*=\s*                      #  ok, that's an assignement
  175.46 +       (?P<value>.+?)                  # got the value!, non greedy 
  175.47 +       (?P<final_comment>\s*(\#.*)?)   # a possible final comment
  175.48 +       $""", re.VERBOSE)
  175.49 +    param_name = None
  175.50 +    name = None
  175.51 +    str_format      = "%(param_name)s=%(value)s"
  175.52 +    ip = ''
  175.53 +    tag = ''
  175.54 +    mac = None
  175.55 +    hostname = ''
  175.56 +    
  175.57 +    def validate(self):
  175.58 +        if self.mac and (self.ip or self.tag or self.hostname):
  175.59 +            return True
  175.60 +        raise WrongMACError("%s is not a valid MAC Address" % self.param_name)
  175.61 +                    
  175.62 +    def parse_value(self):
  175.63 +        """
  175.64 +        this is NOT a complete parser for dnsmasq. It's rather a usefull parser
  175.65 +        for the values that ReteISI project wants to use
  175.66 +        """
  175.67 +
  175.68 +        for tk in self.value.split(','):
  175.69 +            if tools.is_mac_address(tk):
  175.70 +                self.mac = tk
  175.71 +            elif tools.is_ip_address(tk):
  175.72 +                self.ip = tk
  175.73 +            elif tk.startswith('net:'):
  175.74 +                self.tag = tk
  175.75 +            else:
  175.76 +                self.hostname = tk
  175.77 +
  175.78 +class Mac(tools.Conf):
  175.79 +    line_class = Line
  175.80 +
  175.81 +    def get_param(self, param_name, value=None, ip=None, mac=None, tag=None):
  175.82 +
  175.83 +        if mac:
  175.84 +            value = None
  175.85 +            
  175.86 +        ret = tools.Conf.get_param(self, param_name, value=value)
  175.87 +
  175.88 +        if ip:
  175.89 +            ret = [l for l in ret if l.ip == ip]
  175.90 +        
  175.91 +        if mac:
  175.92 +            ret = [l for l in ret if l.mac == mac]
  175.93 +        
  175.94 +        if tag:
  175.95 +            ret = [l for l in ret if l.tag == tag]
  175.96 +        
  175.97 +        return ret
  175.98 +
  175.99 +    def set_param(self, param_name, value=None, mac=None, ip=None, tag=None, hostname=None):
 175.100 +
 175.101 +        if value and not mac:
 175.102 +            mac = value.split(',')[0]
 175.103 +
 175.104 +        if not value:
 175.105 +            self.value = ",".join([locals()[at] for at in ('mac', 'ip', 'hostname', 'tag')
 175.106 +                                   if locals()[at]])
 175.107 +            
 175.108 +        return tools.Conf.set_param(self, param_name, value=value, mac=mac, ip=ip, tag=tag)
 175.109 +        
   176.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.2 +++ b/lib/isi/conf/misc.py	Mon Apr 26 11:16:23 2010 +0200
   176.3 @@ -0,0 +1,108 @@
   176.4 +import re
   176.5 +import os
   176.6 +import StringIO
   176.7 +import ConfigParser
   176.8 +from dry.functions import execute, ExecuteError
   176.9 +import re
  176.10 +from isi import models, exc
  176.11 +
  176.12 +def get_samba_conf():
  176.13 +    """
  176.14 +    test if a share is present in 'testparm -s'
  176.15 +    """
  176.16 +    ret_code, out, err = execute('testparm -s')
  176.17 +    if ret_code:
  176.18 +        raise ExecuteError("Error while testing samba configuration: %s" % err)
  176.19 +
  176.20 +    testparm = StringIO.StringIO("\n".join(l.strip() for l in out.split('\n')))
  176.21 +    c = ConfigParser.ConfigParser()
  176.22 +    c.readfp(testparm)
  176.23 +    return c
  176.24 +    
  176.25 +    
  176.26 +def get_shares(descr=True, all=False):
  176.27 +    """
  176.28 +    return a dict of samba shares
  176.29 +
  176.30 +    :param descr: yield a description rather that path
  176.31 +    :param all: if False (default) only some shares are returned
  176.32 +    """
  176.33 +    shares = {}
  176.34 +    c = get_samba_conf()
  176.35 +    for sec in c.sections():
  176.36 +        if sec in ('print$', 'home', 'netlogon', 'printers') and not all:
  176.37 +            continue
  176.38 +        try:
  176.39 +            path =  c.get(sec, 'path')
  176.40 +            if re.match('/home/shares/(classi|corsi)/.*', path) and not all:
  176.41 +                continue
  176.42 +            shares[sec] = path
  176.43 +        except ConfigParser.NoOptionError:
  176.44 +            pass
  176.45 +    if descr:
  176.46 +        return [(key, "%s (%s)" % (key, shares[key])) for key in sorted(shares.keys())]
  176.47 +    else:
  176.48 +        return [(key, shares[key]) for  key in sorted(shares.keys())]
  176.49 +                
  176.50 +    
  176.51 +def get_printers_with_rpcclient():
  176.52 +    """
  176.53 +    return a list of Printer objects initialized from the 
  176.54 +    """
  176.55 +    printers = []
  176.56 +    passwd = file('/etc/ldap.secret').read().strip()
  176.57 +    u = models.get_samba_user('administrator')
  176.58 +    if not u.test_samba_password(passwd):
  176.59 +        if os.path.exists('/etc/administrator.secret'):
  176.60 +            passwd = file('/etc/administrator.secret').read().strip()
  176.61 +
  176.62 +        if not u.test_samba_password(passwd):
  176.63 +            raise exc.AuthenticationError("Administrator could not authenticate with correct secret (looking ldap.secret and administrator.secret)")
  176.64 +        
  176.65 +    cmd = ["rpcclient", "-U", 'administrator%%%s' % passwd,
  176.66 +           '-c', 'enumprinters 2', '127.0.0.1', '-d0']
  176.67 +
  176.68 +    ret_code, output, err = execute(cmd)
  176.69 +    if ret_code:
  176.70 +        raise exc.ExecutionError("failed cmd: %s" % " ".join(cmd))
  176.71 +    if output.startswith('No printers returned'):
  176.72 +        return []
  176.73 +    for prn in output.split("\n\n"):
  176.74 +        if prn.strip():
  176.75 +            printers += [Printer(prn)]
  176.76 +    return printers
  176.77 +    
  176.78 +
  176.79 +def get_samba_printers(driver=False):
  176.80 +
  176.81 +    ret_code, out, err = execute('smbclient -N -L localhost')
  176.82 +    printers = {}
  176.83 +    if out:
  176.84 +        for line in out.split('\n'):
  176.85 +            tokens = line.split()
  176.86 +            if len(tokens)> 1 and tokens[1] == 'Printer':
  176.87 +                printers[tokens[0]] =  " ".join(tokens[2:])
  176.88 +    if not driver:
  176.89 +        return [(key, printers[key]) for key in printers]
  176.90 +    else:
  176.91 +        return 
  176.92 +
  176.93 +class Printer(object):
  176.94 +
  176.95 +    def __init__(self, definition):
  176.96 +
  176.97 +        for line in definition.split('\n'):
  176.98 +            try:
  176.99 +                name, value = line.strip().split(':')
 176.100 +                setattr(self, name, value.replace('[', '').replace(']',''))
 176.101 +            except:
 176.102 +                pass
 176.103 +
 176.104 +    def __str__(self):
 176.105 +        return "%s (%s)" % (self.sharename, self.drivername)
 176.106 +
 176.107 +    def __repr__(self):
 176.108 +        return "<Printer: %s>" % self
 176.109 +        
 176.110 +
 176.111 +            
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/lib/isi/conf/params.py	Mon Apr 26 11:16:23 2010 +0200
   177.3 @@ -0,0 +1,61 @@
   177.4 +PARAMS = [
   177.5 + 'DaysToKeep',
   177.6 + 'ExcludeProfileDirs',
   177.7 + 'LegalNoticeCaption',
   177.8 + 'LegalNoticeText',
   177.9 + 'My__Picture',
  177.10 + 'My__Video',
  177.11 + 'My__Music',
  177.12 + 'MustBeValidated',
  177.13 + 'NoAdminPage',
  177.14 + 'NoConfigPage',
  177.15 + 'NoDevMgrPage',
  177.16 + 'NoDispAppearancePage',
  177.17 + 'NoDispBackgroundPage',
  177.18 + 'NoDispCPL',
  177.19 + 'NoDispScrSavPage',
  177.20 + 'NoDispSettingsPage',
  177.21 + 'NoFileSysPage',
  177.22 + 'NoProfilePage',
  177.23 + 'NoVirtMemPage',
  177.24 + 'Personal',
  177.25 + 'ProxyOverride',
  177.26 + 'ProxyServer',
  177.27 + 'Start__Page',
  177.28 + 'UseHomeDirectory',
  177.29 + 'UserProfiles',
  177.30 + 'UserPrinter',
  177.31 + 'PcPrinter',
  177.32 + '_DebugLevel',
  177.33 + '_DebugUsers',
  177.34 + '_DebugClients',
  177.35 + '_DebugShare',
  177.36 + '_EnvWin98',
  177.37 + '_EnvWinXP',
  177.38 + '_NetFolder',
  177.39 + '_NetTime',
  177.40 + '_NoAppWiz',
  177.41 + '_NoDispLastUser',
  177.42 + '_NoDispLastUser9X',
  177.43 + '_NoSync',
  177.44 + '_OkParanoia',
  177.45 + '_ProfileDirs',
  177.46 + '_RestrictActiveDesktop',
  177.47 + '_RestrictCpan',
  177.48 + '_RestrictDrive',
  177.49 + '_RestrictDriveC',
  177.50 + '_RestrictFind',
  177.51 + '_RestrictHistory',
  177.52 + '_RestrictIEPasswordCaching',
  177.53 + '_RestrictLogon',
  177.54 + '_RestrictNet',
  177.55 + '_RestrictOldApp',
  177.56 + '_RestrictPasswd',
  177.57 + '_RestrictPrinter',
  177.58 + '_RestrictRegTools',
  177.59 + '_RestrictRun',
  177.60 + '_RestrictSaveSettings',
  177.61 + '_RestrictScreen',
  177.62 + '_RestrictSystem',
  177.63 + '_SetIECache',
  177.64 + '_Versione']
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/lib/isi/conf/tools.py	Mon Apr 26 11:16:23 2010 +0200
   178.3 @@ -0,0 +1,300 @@
   178.4 +# -*- coding: utf-8 -*-
   178.5 +
   178.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   178.7 +#
   178.8 +#  This program is free software: you can redistribute it and/or modify
   178.9 +#  it under the terms of the GNU General Public License as published by
  178.10 +#  the Free Software Foundation, either version 3 of the License, or
  178.11 +#  (at your option) any later version.
  178.12 +#
  178.13 +#  This program is distributed in the hope that it will be useful,
  178.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  178.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  178.16 +#  GNU General Public License for more details.
  178.17 +#
  178.18 +#  You should have received a copy of the GNU General Public License
  178.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  178.20 +
  178.21 +
  178.22 +"""
  178.23 +Classes to manage a configuration file adding and removing parameters
  178.24 +
  178.25 +Line
  178.26 +----
  178.27 +
  178.28 +The module is based on Line, a class that holds the data of the single line and the
  178.29 +information if it's a comment or not and handles the representation via str()
  178.30 +
  178.31 +It possible to build the line from a tring (when reading conf files) or by
  178.32 +supplying paramteres param_name and value to the constructor.
  178.33 +
  178.34 +It's normal to need to customize deeply
  178.35 +
  178.36 +
  178.37 +Conf
  178.38 +----
  178.39 +
  178.40 +The class that represent the conf file, it's build from a real filename but
  178.41 +can be fed a text (mainly for test purposes)
  178.42 +
  178.43 +it has these useful methods:
  178.44 +
  178.45 +  * get_param(param_name)
  178.46 +  * set_param(param_name, value)
  178.47 +  * del_param(param_name, value=None)
  178.48 +  * len() # number of non-comment lines
  178.49 +  * len(obj) # number of physical lines
  178.50 +  * diff(other) # prints a unified diff format file of self and other
  178.51 +  * save() # save
  178.52 +  
  178.53 +"""
  178.54 +
  178.55 +import re 
  178.56 +import xlrd
  178.57 +
  178.58 +class ValidationError(Exception): pass
  178.59 +class UnknownParamName(ValidationError): pass
  178.60 +class ParamRequireValue(ValidationError): pass
  178.61 +
  178.62 +class Line(object):
  178.63 +
  178.64 +    VAR_PATTERN = re.compile(r"""
  178.65 +       (?P<comment>\s*\#\s*)?   # a possible comment of the line
  178.66 +       (?P<param_name>[\w-]+)            # the variable name
  178.67 +       \s*=*                      #  ok, that's an assignement
  178.68 +       (?P<value>.*?)           # got the value!, non greedy 
  178.69 +       (?P<final_comment>\s*(\#.*)?)               # a possible final comment
  178.70 +       $""", re.VERBOSE)
  178.71 +    param_name = None
  178.72 +    value = ''
  178.73 +    str_format = "%(param_name)s %(value)s"
  178.74 +    repr_format = "<%(param_name)s %(value)s>"
  178.75 +    
  178.76 +    def __init__(self, line=None, param_name=None, value=None, **kw):
  178.77 +        """
  178.78 +        create a line of the conf file. Comment line can be created passing line arg only::
  178.79 +
  178.80 +        Line(domain-needed)
  178.81 +        Line(server=208.67.222.222)
  178.82 +        Line(param_name=..., value=...)
  178.83 +        
  178.84 +        """
  178.85 +        if line is None:
  178.86 +            self.param_name = param_name
  178.87 +            self.value = value
  178.88 +            self.final_comment = ''
  178.89 +            self.is_comment = False
  178.90 +            self.line = str(self)
  178.91 +            for key, val in kw.iteritems():
  178.92 +                setattr(self, key, val)
  178.93 +        else:
  178.94 +            self.line = line
  178.95 +            m = self.VAR_PATTERN.match(line.strip())
  178.96 +            if m:
  178.97 +                comm = m.group('comment')
  178.98 +                self.is_comment = True if (comm and  '#' in comm) else False
  178.99 +                self.param_name = m.group('param_name')
 178.100 +                self.value = m.group('value')
 178.101 +                self.final_comment = m.group('final_comment') or ''
 178.102 +
 178.103 +            else:
 178.104 +                self.is_comment = True
 178.105 +
 178.106 +        if not self.is_comment:
 178.107 +            self.parse_value()
 178.108 +            self.validate()
 178.109 +
 178.110 +    def parse_value(self):
 178.111 +        """
 178.112 +        parse the value and possibly assign istance attributes
 178.113 +        """
 178.114 +        return
 178.115 +
 178.116 +    def validate(self):
 178.117 +        """
 178.118 +        raise ValidationError if value is not valid
 178.119 +        """
 178.120 +        return True
 178.121 +        
 178.122 +    def __str__(self):
 178.123 +        if self.is_comment:
 178.124 +            return self.line
 178.125 +        return self.str_format % vars(self)
 178.126 +            
 178.127 +    def __repr__(self):
 178.128 +        if self.is_comment:
 178.129 +            return self.line
 178.130 +        return self.repr_format % vars(self)
 178.131 +
 178.132 +class Conf(object):
 178.133 +
 178.134 +    line_class = Line
 178.135 +    search_value = None
 178.136 +    
 178.137 +    def __init__(self, filename=None, text=None):
 178.138 +        """
 178.139 +        :param filename: the conf filename to be read
 178.140 +        :param text: a text to be used (test purpose)
 178.141 +        """
 178.142 +
 178.143 +        assert filename or text, "You must set filename or text"
 178.144 +        self.filename = filename
 178.145 +        if filename:
 178.146 +            self.lines = [self.line_class(l) for l in open(filename)]
 178.147 +        else:
 178.148 +            self.lines = [self.line_class(l) for l in text.split('\n')]
 178.149 +
 178.150 +    def get_param(self, param_name, value=None):
 178.151 +        """
 178.152 +        return the (possible) Line objects that have param_name
 178.153 +        """
 178.154 +        ret = []
 178.155 +        for l in self.lines:
 178.156 +            if not l.is_comment and l.param_name == param_name:
 178.157 +                ret += [l]
 178.158 +        if value:
 178.159 +            ret = [l for l in ret if l.value == value]
 178.160 +        return ret
 178.161 +
 178.162 +    def set_param(self, param_name, value=None, **kw):
 178.163 +        """
 178.164 +        set a param/value
 178.165 +        if a row already exists for that param, it is used
 178.166 +        Kw: may be other params specific for Line
 178.167 +        """
 178.168 +        if self.search_value:
 178.169 +            lines = self.get_param(param_name, value=value, **kw)
 178.170 +        else:
 178.171 +            lines = self.get_param(param_name, **kw)
 178.172 +        
 178.173 +        if lines:
 178.174 +            line = lines[0]
 178.175 +            line.value = value
 178.176 +            for key, val in kw.iteritems():
 178.177 +                setattr(line, key, val)
 178.178 +        else:
 178.179 +
 178.180 +            line = self.line_class(param_name=param_name, value=value, **kw)
 178.181 +            l = self.get_param(param_name)
 178.182 +            if len(l) == 0:
 178.183 +                idx = len(self.lines)
 178.184 +            else:
 178.185 +                idx = self.lines.index(l[-1])
 178.186 +
 178.187 +            self.lines.insert(idx + 1, line)
 178.188 +
 178.189 +        return line
 178.190 +
 178.191 +    def del_param(self, param_name,  value=None):
 178.192 +        """
 178.193 +        delete a parameter
 178.194 +        """
 178.195 +        kw = {}
 178.196 +        if value:
 178.197 +            kw['value'] = value
 178.198 +        try:
 178.199 +            l = self.get_param(param_name, **kw)[0]
 178.200 +        except IndexError, e:
 178.201 +            return
 178.202 +        
 178.203 +        self.lines.remove(l)
 178.204 +        return l
 178.205 +
 178.206 +    def __str__(self):
 178.207 +        return "\n".join([str(l).strip() for l in self.lines])
 178.208 +        
 178.209 +    def __len__(self):
 178.210 +        return len(self.lines)
 178.211 +
 178.212 +    def len(self):
 178.213 +        """Return the number of non-comment lines"""
 178.214 +        return len([l for l in self.lines if not l.is_comment])
 178.215 +
 178.216 +    def diff(self, other, this_file='this.conf', other_file='other.conf'):
 178.217 +        """return a diff between self and other"""
 178.218 +
 178.219 +        assert isinstance(other, self.__class__), "other must be a Logon instance (is %s)" % oter.__class__
 178.220 +        import difflib
 178.221 +        diff = []
 178.222 +        
 178.223 +        for line in difflib.unified_diff(["%s\n" % l for l in str(self).split('\n')],
 178.224 +                                         ["%s\n" % l for l in str(other).split('\n')],
 178.225 +                                         this_file, other_file):
 178.226 +            diff += [line]
 178.227 +        return "".join(diff)
 178.228 +    
 178.229 +    def save(self, filename=None):
 178.230 +        """
 178.231 +        saves the file
 178.232 +
 178.233 +        :param filename: name of the file where to save (default: self.filename)
 178.234 +        """
 178.235 +        filename = filename or self.filename
 178.236 +        
 178.237 +        f = open(filename, 'w')
 178.238 +        f.write(str(self) + "\n")
 178.239 +        f.close()
 178.240 +        
 178.241 +class Xls(object):
 178.242 +
 178.243 +    def __init__(self, filename):
 178.244 +        try:
 178.245 +            self.book = xlrd.open_workbook(filename)
 178.246 +        except IOError, e:
 178.247 +            print e
 178.248 +
 178.249 +    def xls2csv(self):
 178.250 +        "Really poor version of csv file just aimed at .isi format"
 178.251 +        output = []
 178.252 +        for i in self.get_sheet_as_list():
 178.253 +            output += [";".join([unicode(x.value) for x in i])]
 178.254 +        return "\n".join(output)
 178.255 +
 178.256 +    def get_sheet_as_list(self, sheet_name=None, all_sheets=True):
 178.257 +        "get  named sheet or all sheets"
 178.258 +        rows = []
 178.259 +        if sheet_name:
 178.260 +            try:
 178.261 +                sheet = self.book.sheet_by_name(sheet_name)
 178.262 +            except Exception, e:
 178.263 +                raise
 178.264 +
 178.265 +            rows += self.get_rows(sheet)
 178.266 +
 178.267 +        elif all_sheets is True and sheet_name is None:
 178.268 +            for index in range(self.book.nsheets):
 178.269 +                sheet = self.book.sheet_by_index(index)
 178.270 +                rows += self.get_rows(sheet)
 178.271 +        else:
 178.272 +            sheet = self.book.sheet_by_index(0)
 178.273 +            rows += self.get_rows(sheet)
 178.274 +
 178.275 +        return rows
 178.276 +
 178.277 +    def get_rows(self, sheet):
 178.278 +        if isinstance(sheet, int):
 178.279 +            sheet = self.book.sheet_by_index(sheet)
 178.280 +        rows = []
 178.281 +        for nrow in range(sheet.nrows):
 178.282 +            rows += [sheet.row(nrow)]
 178.283 +        return rows
 178.284 +
 178.285 +        
 178.286 +    
 178.287 +def is_mac_address(mac):
 178.288 +    pattern = '([a-f0-9]{2}[:|\-]?){6}'
 178.289 +    m = re.compile(pattern, re.I).search(mac)
 178.290 +    if m:
 178.291 +        return True
 178.292 +    return False
 178.293 +
 178.294 +def is_ip_address(ip):
 178.295 +
 178.296 +    try:
 178.297 +        for token in ip.split('.'):
 178.298 +            if int(token) > 255:
 178.299 +                return False
 178.300 +    except ValueError:
 178.301 +        return False
 178.302 +    return True
 178.303 +
   179.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.2 +++ b/lib/isi/exc.py	Mon Apr 26 11:16:23 2010 +0200
   179.3 @@ -0,0 +1,39 @@
   179.4 +from dry.functions import ExecuteError
   179.5 +
   179.6 +class MultipleMatch(Exception): pass
   179.7 +class MissingClass(Exception): pass
   179.8 +class MissingCourse(Exception): pass
   179.9 +class MissingCourseMapping(Exception): pass
  179.10 +class MissingMatch(Exception): pass
  179.11 +class MissingPassword(Exception): pass
  179.12 +class AuthenticationError(Exception): pass
  179.13 +class MissingCF(Exception): pass
  179.14 +class MissingMainGroup(Exception):
  179.15 +    def __init__(self, message, maingroup, user):
  179.16 +        super(MissingMainGroup, self).__init__(message)
  179.17 +        self.maingroup = maingroup
  179.18 +        self.user = user
  179.19 +              
  179.20 +class MissingOrVoidGroup(Exception): pass
  179.21 +
  179.22 +class MultipleErrors(Exception): pass
  179.23 +class AlreadyExistingUser(Exception):
  179.24 +    def __init__(self, message, logname):
  179.25 +        super(AlreadyExistingUser, self).__init__(message)
  179.26 +        self.logname = logname
  179.27 +
  179.28 +class AlreadyExistingGroup(Exception):
  179.29 +    def __init__(self, message, name):
  179.30 +        super(AlreadyExistingGroup, self).__init__(message)
  179.31 +        self.name = name
  179.32 +
  179.33 +class WrongParameters(Exception): pass
  179.34 +class WrongOperation(Exception): pass
  179.35 +
  179.36 +class WrongLineFormat(Exception): pass
  179.37 +class WrongFileFormat(Exception): pass
  179.38 +
  179.39 +class QuotaError(Exception): pass
  179.40 +class DuplicateUid(Exception): pass
  179.41 +class InvalidValue(Exception): pass
  179.42 +
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/lib/isi/filesystem.py	Mon Apr 26 11:16:23 2010 +0200
   180.3 @@ -0,0 +1,305 @@
   180.4 +#!/usr/bin/python
   180.5 +# -*- coding: utf-8 -*-
   180.6 +
   180.7 +# This program is free software; you can redistribute it and/or modify
   180.8 +# it under the terms of the GNU General Public License as published by
   180.9 +# the Free Software Foundation; either version 2, or (at your option)
  180.10 +# any later version.
  180.11 +
  180.12 +# AUTHORS: Sandro Dentella - Massimo Mancini
  180.13 +
  180.14 +
  180.15 +
  180.16 +"""
  180.17 +interaction with os system
  180.18 +
  180.19 +"""
  180.20 +
  180.21 +import os
  180.22 +import sys
  180.23 +from dry.functions import execute, ExecuteError
  180.24 +from isi.conf import defaults, misc
  180.25 +from isi import exc
  180.26 +import isi
  180.27 +import pexpect
  180.28 +import shutil
  180.29 +from glob import glob
  180.30 +
  180.31 +CLASS_SHARE = """
  180.32 +
  180.33 +[%(share_name)s]
  180.34 +  comment = Classe %(share_name)s
  180.35 +  path = %(share_path)s
  180.36 +  guest ok = no
  180.37 +  writable = yes
  180.38 +  browseable = no
  180.39 +"""
  180.40 +
  180.41 +def samba_version():
  180.42 +    """le versioni successive alla 3.0.24 gestiscono 
  180.43 +    in altro modo la scadenza password 
  180.44 +    """
  180.45 +    ret = "3.0.24"
  180.46 +    try:
  180.47 +        r, o, e = execute("smbd -V")
  180.48 +        ret = o.replace('Version ', '')
  180.49 +    except:
  180.50 +        pass
  180.51 +    return ret
  180.52 +
  180.53 +def samba_domain():
  180.54 +    """restituisce il nome del dominio samba"""
  180.55 +    domain = None
  180.56 +    try:
  180.57 +        for line in open('/etc/samba/smb.conf'):
  180.58 +            line = line.strip('\n')
  180.59 +            line = line.strip()
  180.60 +            if "workgroup" in line:
  180.61 +                ll = line.split('=')
  180.62 +                if not '#' in ll[0] or ';' in ll[0]:
  180.63 +                    domain = ll[1].strip()
  180.64 +                    break
  180.65 +    except:
  180.66 +        pass
  180.67 +    return domain
  180.68 +    
  180.69 +    
  180.70 +def show_file(out_file):
  180.71 +   ret = raw_input("Vuoi vedere %s (S/n)? " % out_file)
  180.72 +   if not ret: ret = 's'
  180.73 +   if ret in 'sS':
  180.74 +        cmd = 'less %s' % out_file
  180.75 +        c = pexpect.spawn(cmd)
  180.76 +        try:
  180.77 +            c.interact()
  180.78 +        except OSError, e:
  180.79 +            pass
  180.80 +
  180.81 +def has_acl_support(directory='/home'):
  180.82 +   """ return True if /home has acl support """
  180.83 +
  180.84 +   ret_code, out, err = execute("df %s" % directory)
  180.85 +   info = out.split('\n')[1]  # first line are headers
  180.86 +   partition = info.split()[0]
  180.87 +   ret_code, out, err = execute("grep -w %s /etc/mtab" % partition)
  180.88 +   if not ret_code:
  180.89 +      # /dev/sda8 /home xfs rw,usrquota,grpquota 0 0
  180.90 +      # /dev/sda8 /home ext3 defaults,rw,acl,usrquota,grpquota 0 0
  180.91 +      part, directory, fs, opts, j1, j2 = out.split()
  180.92 +      if fs == 'xfs':
  180.93 +         return True
  180.94 +      if 'acl' in opts:
  180.95 +         return True
  180.96 +
  180.97 +      return False
  180.98 +
  180.99 +    
 180.100 +def home_delete(user, home=None, mode='tar', dry_run=False):
 180.101 +    """delete home. 'mode' can be: rm | tar | none"""
 180.102 +
 180.103 +    if mode == 'none' or not os.path.exists(home):
 180.104 +        return
 180.105 +
 180.106 +    if mode == 'tar':
 180.107 +        dest_file = "%s/%s.tgz" % (os.path.dirname(home), user)
 180.108 +        cmd = 'tar -czvf %s %s' % (dest_file, home)
 180.109 +        if os.path.exists(home):
 180.110 +            if dry_run:
 180.111 +                sys.stderr.write("DRY-RUN: else: %s\n" % cmd)
 180.112 +            else:
 180.113 +                ret_code, out, err = execute(cmd)
 180.114 +                if ret_code:
 180.115 +                    raise ExecuteError("Error while tarring %s:\n   %s" % (
 180.116 +                        home, err))
 180.117 +        else:
 180.118 +            sys.stderr.write("Info: No %s to delete\n" % home)
 180.119 +
 180.120 +    if dry_run:
 180.121 +        sys.stderr.write("DRY-RUN: else: %s\n" % "rm -Rf %s" % (home))
 180.122 +    else:
 180.123 +        try:
 180.124 +            shutil.rmtree(home)
 180.125 +        except Exception, e:
 180.126 +            raise ExecuteError("Error while deleting %s:\n   %s" %
 180.127 +                               (home, e))
 180.128 +        
 180.129 +
 180.130 +def home_create(user, home):
 180.131 +
 180.132 +    shutil.copytree('/etc/skel', home)
 180.133 +    ret_code, out, err = execute('chown -R %s %s' % (user, home))
 180.134 +    if ret_code:
 180.135 +        raise Exception(err)
 180.136 +    home_perms(home, user)
 180.137 +
 180.138 +def create_class(name, course=False, samba_reload=True, manager=None):
 180.139 +    """
 180.140 +    create a class
 180.141 +
 180.142 +    :param course: create a course instead
 180.143 +    :param samba_restart: restart samba so that it immediately make
 180.144 +                 the class available to samba users
 180.145 +
 180.146 +    """
 180.147 +    manager = manager or isi.Manager()
 180.148 +    try:
 180.149 +        group = manager.get_group(name)
 180.150 +    except exc.MissingMatch, e:
 180.151 +        group = manager.add_group(name)
 180.152 +
 180.153 +    share_path = "%s/%s" % (defaults.COURSES_PATH if course else defaults.CLASSES_PATH, name)
 180.154 +    students = 'alunni' if not course else 'esterni'
 180.155 +    if not os.path.exists(share_path):
 180.156 +        os.mkdir(share_path)
 180.157 +        os.chown(share_path, -1, group.gid)
 180.158 +        os.chmod(share_path, 0755)
 180.159 +        cmd1 = "setfacl -R    -m g:%s:rwx,g:%s:--- %s"
 180.160 +        cmd2 = "setfacl -R -d -m g:%s:rwx,g:%s:--- %s"
 180.161 +
 180.162 +        for cmd in (cmd1, cmd2):
 180.163 +            ret_code, out, err = execute(cmd % (name, students, share_path))
 180.164 +            if ret_code:
 180.165 +                raise ExecuteError("Error while executing %s: %s" %(cmd, err))
 180.166 +
 180.167 +    conf = misc.get_samba_conf()
 180.168 +    if not name in conf.sections():
 180.169 +        create_samba_class_share(name, share_path)
 180.170 +
 180.171 +    if samba_reload:
 180.172 +        execute("/etc/init.d/samba reload")
 180.173 +
 180.174 +
 180.175 +def create_samba_class_share(share_name, share_path, course=False):
 180.176 +    """
 180.177 +    Create a samba share for the class
 180.178 +
 180.179 +    :param course: it's a course rathre that class
 180.180 +    
 180.181 +    """
 180.182 +    
 180.183 +    conf_file = "/etc/isi/samba/smb_%s.conf" % ('corsi' if course else 'classi')
 180.184 +    f = open(conf_file, 'a+')
 180.185 +    f.write(CLASS_SHARE % locals() + '\n')
 180.186 +    
 180.187 +
 180.188 +def home_move(user, old_home, new_home, maingroup,  dry_run=False):
 180.189 +    """ sposta la homedir e riassegna i permessi"""
 180.190 +    if old_home == new_home: return
 180.191 +    cmd = "mv  %s %s" % (old_home, new_home)
 180.192 +    if dry_run:
 180.193 +        sys.stderr.write("DRY-RUN: else: %s\n" % cmd)
 180.194 +    else:
 180.195 +        ret_code, out, err = execute(cmd)
 180.196 +        if ret_code:
 180.197 +            raise ExecuteError("Error while moving %s in %s:\n   %s" %
 180.198 +                               (old_home, new_home,  err))
 180.199 +        home_perms(new_home)
 180.200 +
 180.201 +def home_perms(home, user):
 180.202 +
 180.203 +    maingroup = home.split('/')[-2]
 180.204 +
 180.205 +    # ownership
 180.206 +#    cmd  = "chown -R %s:%s %s" % (user, maingroup, home)
 180.207 +#    cmd  = "chown -R %s %s" % (user, home)
 180.208 +#    ret_code, out, err = execute(cmd)
 180.209 +#    if ret_code:
 180.210 +#        raise ExecuteError( \
 180.211 +#            "Error while assign ownership to %s at %s:\n   %s" % \
 180.212 +#                               (user, home,  err))
 180.213 +
 180.214 +    if maingroup in ('alunni', 'esterni'):
 180.215 +        cmd = "chgrp -R %s %s" % ('docenti', home)
 180.216 +    else:
 180.217 +        cmd = "chgrp -R %s %s" % (maingroup, home)
 180.218 +    ret_code, out, err = execute(cmd)
 180.219 +    if ret_code:
 180.220 +        raise ExecuteError( \
 180.221 +            "Error while assign group ownership to %s at %s:\n   %s" % \
 180.222 +                               (maingroup, home,  err))
 180.223 +
 180.224 +    # default permissions con o senza acl
 180.225 +    if maingroup in ('alunni', 'esterni'):
 180.226 +        cmd1 = "find %s -type d -exec chmod %s {} ;" % (home, defaults.PERMS_HOME_ALU)
 180.227 +        cmd2 = "find %s -type f -exec chmod %s {} ;" % (home, defaults.PERMS_FILE_ALU)
 180.228 +    else:
 180.229 +        cmd1 = "find %s -type d -exec chmod %s {} ;" % (home, defaults.PERMS_HOME_ALL)
 180.230 +        cmd2 = "find %s -type f -exec chmod %s {} ;" % (home, defaults.PERMS_FILE_ALL)
 180.231 +    ret_code, out, err = execute(cmd1)
 180.232 +    if ret_code:
 180.233 +        raise ExecuteError( \
 180.234 +            "Error while assign permission to dir in %s:\n  %s" % (home,  err))
 180.235 +    ret_code, out, err = execute(cmd2)
 180.236 +    if ret_code:
 180.237 +        raise ExecuteError( \
 180.238 +            "Error while assign permission to file in %s:\n  %s" % (home,  err))
 180.239 +    if has_acl_support('/home'):
 180.240 +        cmd = "setfacl -R -m u:%s:rwx %s" % (user, home)
 180.241 +        ret_code, out, err = execute(cmd)
 180.242 +        if ret_code:
 180.243 +            raise ExecuteError("Error while setfacl to %s\n  %s\n  %s" % (home,  err, cmd))
 180.244 +                               
 180.245 +        # cosa può fare www-data                       
 180.246 +        cmd = "setfacl -m u:www-data:x-- %s" % (home)
 180.247 +        ret_code, out, err = execute(cmd)
 180.248 +        if ret_code:
 180.249 +            raise ExecuteError("Error while setfacl to %s\n  %s" % (home,  err))
 180.250 +
 180.251 +        public_html = home+'/public_html'
 180.252 +        if os.path.exists(public_html):
 180.253 +            cmd = "setfacl -R  -m u:www-data:rx %s" % (public_html)
 180.254 +            ret_code, out, err = execute(cmd)
 180.255 +            if ret_code:
 180.256 +                raise ExecuteError("Error while setfacl to %s\n   %s" %
 180.257 +                                (public_html,  err))
 180.258 +            cmd = "setfacl -dR -m u:www-data:rx %s" % (public_html)
 180.259 +            ret_code, out, err = execute(cmd)
 180.260 +            if ret_code:
 180.261 +                raise ExecuteError("Error while setfacl to %s\n   %s" %
 180.262 +                                (public_html,  err))
 180.263 +
 180.264 +        
 180.265 +def create_alulink(classes, manager=None, group=None):
 180.266 +    """
 180.267 +    Create links of students belonging to classes
 180.268 +    :param classes: all classe or course for which alulink must be run
 180.269 +    :param group: the models.PosixGroup for which the links must be created
 180.270 +    :param manager: the isi.Manager() if group is not passed
 180.271 +
 180.272 +        The difference is that courses have a separate share
 180.273 +        (COURSES_PATH rather that CLASSES_PATH)
 180.274 +    
 180.275 +    """
 180.276 +
 180.277 +    if group:
 180.278 +        assert len(classes) < 2, "When setting group arg classes must have just 1 element"
 180.279 +
 180.280 +    if not classes:
 180.281 +        return
 180.282 +    
 180.283 +    for cls in classes:
 180.284 +        if not group:
 180.285 +            group = manager.get_group(cls)
 180.286 +        members = group.members_as_users()
 180.287 +        if not members:
 180.288 +            continue
 180.289 +
 180.290 +        PATH = defaults.COURSES_PATH if members[0].maingroup == 'esterni' else defaults.CLASSES_PATH
 180.291 +        class_path = '%s/%s' % (PATH, cls)
 180.292 +        if not os.path.exists(class_path):
 180.293 +            raise exc.MissingClass("The directory %s is not present" % class_path)
 180.294 +
 180.295 +        alulink_path = '%s/alulink' % class_path
 180.296 +        if not os.path.exists(alulink_path):
 180.297 +            os.mkdir(alulink_path, 0755)
 180.298 +
 180.299 +        for f in glob(alulink_path + '/*'):
 180.300 +            os.remove(f)
 180.301 +
 180.302 +        for user in members:
 180.303 +            if isinstance(user, basestring):
 180.304 +                continue
 180.305 +            link_name = '%s/%s_%s' % (alulink_path, user.logname, user.full_name.replace(' ', '_'))
 180.306 +            os.symlink(user.home, link_name)
 180.307 +
 180.308 +        group = None
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/lib/isi/models.py	Mon Apr 26 11:16:23 2010 +0200
   181.3 @@ -0,0 +1,674 @@
   181.4 +# -*- coding: utf-8 -*-
   181.5 +
   181.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   181.7 +#
   181.8 +#  This program is free software: you can redistribute it and/or modify
   181.9 +#  it under the terms of the GNU General Public License as published by
  181.10 +#  the Free Software Foundation, either version 3 of the License, or
  181.11 +#  (at your option) any later version.
  181.12 +#
  181.13 +#  This program is distributed in the hope that it will be useful,
  181.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  181.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  181.16 +#  GNU General Public License for more details.
  181.17 +#
  181.18 +#  You should have received a copy of the GNU General Public License
  181.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  181.20 +
  181.21 +
  181.22 +import re
  181.23 +import os
  181.24 +import time
  181.25 +import pumpkin
  181.26 +from pumpkin import fields, filters
  181.27 +from pumpkin.resource import LDAPResource
  181.28 +from pumpkin.directory import Directory
  181.29 +from pumpkin.base import Model
  181.30 +import smbpasswd
  181.31 +from dry.functions import execute, ExecuteError
  181.32 +import exc
  181.33 +import isi
  181.34 +#from isi import filesystem 
  181.35 +from isi.conf import defaults
  181.36 +import ldap
  181.37 +import hashlib
  181.38 +
  181.39 +
  181.40 +def get_conn(isiconn):
  181.41 +
  181.42 +    LDAP_RES = LDAPResource()
  181.43 +    LDAP_RES.server = isiconn.uri
  181.44 +    LDAP_RES.login =  isiconn.rootdn
  181.45 +    LDAP_RES.password = isiconn.passwd
  181.46 +    LDAP_RES.TLS = False
  181.47 +    LDAP_RES.basedn = isiconn.base
  181.48 +    LDAP_RES.method = pumpkin.resource.AUTH_SIMPLE
  181.49 +
  181.50 +    LDAP_CONN = Directory()
  181.51 +    LDAP_CONN.connect(LDAP_RES)
  181.52 +    return LDAP_CONN
  181.53 +
  181.54 +def get_user(username, conn=None):
  181.55 +    if not conn:
  181.56 +        conn = isi.Manager().pumpkin_conn
  181.57 +        
  181.58 +    return conn.get(PosixUser, search_filter=filters.eq('uid', username))
  181.59 +
  181.60 +def get_samba_user(username, conn=None):
  181.61 +    if not conn:
  181.62 +        conn = isi.Manager().pumpkin_conn
  181.63 +    return conn.get(SambaUser, search_filter=filters.eq('uid', username))
  181.64 +
  181.65 +def get_user_by_cf(cf, conn):
  181.66 +    try:
  181.67 +        user = conn.get(PosixUser, search_filter=filters.eq('employeeNumber', cf))
  181.68 +    except Exception, e:
  181.69 +        if e.message == 'Multiple objects found':
  181.70 +            raise exc.MultipleMatch("CF %s is not unique!" % cf)
  181.71 +
  181.72 +def get_group(group_name, conn):
  181.73 +
  181.74 +    g = conn.get(PosixGroup, search_filter=filters.eq('name', group_name))
  181.75 +    if not g:
  181.76 +        raise exc.MissingMatch("No group with name '%s'" % group_name)
  181.77 +    return g
  181.78 +
  181.79 +def get_domain(domain_name, conn):
  181.80 +    d = conn.get(SambaDomain, search_filter=filters.eq('sambaDomainName', domain_name))
  181.81 +    if not d:
  181.82 +        raise exc.MissingMatch("No domain with name '%s'" % domain_name)
  181.83 +    return d
  181.84 +
  181.85 +def get_samba_group(group_name, conn):
  181.86 +    g = conn.get(SambaGroup, search_filter=filters.eq('name', group_name))
  181.87 +    if not g:
  181.88 +        raise exc.MissingMatch("No group with name '%s'" % group_name)
  181.89 +    return g
  181.90 +
  181.91 +def get_group_by_gid(gidNumber, conn):
  181.92 +    g = conn.get(PosixGroup, search_filter=filters.eq('gidNumber', gidNumber))
  181.93 +    if not g:
  181.94 +        raise exc.MissingMatch("No group with gid = %s" % gidNumber)
  181.95 +    return g
  181.96 +
  181.97 +class StringField(fields.StringField):
  181.98 +    """Unicode string
  181.99 +    """
 181.100 +    default = None
 181.101 +
 181.102 +    def validate(self, values):
 181.103 +        """Check if new value is unicode
 181.104 +        """
 181.105 +        if isinstance(values, unicode):
 181.106 +            return values
 181.107 +        elif isinstance(values, basestring):
 181.108 +            return unicode(values)
 181.109 +        else:
 181.110 +            raise ValueError, "Not a unicode value: %s" % values
 181.111 +
 181.112 +class PosixUser(Model):
 181.113 +
 181.114 +    """This is my custom model"""
 181.115 +
 181.116 +    _object_class_ = ['posixAccount', 'inetOrgPerson', 'shadowAccount', 'organizationalPerson']
 181.117 +                      
 181.118 +    _rdn_ = 'logname'
 181.119 +
 181.120 +    __base_data__ = ['classe','first_name', 'last_name', 'cf']
 181.121 +    __extended_data__ = ['sex', 'address', 'city', 'zip_code', 'phone']
 181.122 +    # __orphan__ = ['password', 'full_name', 'logname', 'uid', 'gid']
 181.123 +    logname = StringField('uid')
 181.124 +    _classe = StringField('departmentNumber')
 181.125 +    uid = fields.IntegerField('uidNumber')
 181.126 +    gid = fields.IntegerField('gidNumber')
 181.127 +    full_name = StringField('cn')
 181.128 +    first_name = StringField('givenName')
 181.129 +    last_name = StringField('sn')
 181.130 +    shell = StringField('loginShell')
 181.131 +    home = StringField('homeDirectory')
 181.132 +    mail = fields.StringListField('mail')
 181.133 +    cf = StringField('employeeNumber')
 181.134 +    password = StringField('userPassword')
 181.135 +
 181.136 +    sex = StringField('employeeType')
 181.137 +    address = StringField('postalAddress')
 181.138 +    city = StringField('postOfficeBox')
 181.139 +    zip_code = StringField('postalCode')
 181.140 +    phone = StringField('telephoneNumber')
 181.141 +
 181.142 +    
 181.143 +    def url(self, text=None):
 181.144 +        return u'<a href="/users/user/detail/%s">%s</a>' % (self.logname, text or self.logname)
 181.145 +
 181.146 +    ### password
 181.147 +    def test_password(self, pwd):
 181.148 +        """
 181.149 +        controlla la validità delle credenziali
 181.150 +        """
 181.151 +        if not pwd:
 181.152 +            return False
 181.153 +        conn = ldap.initialize(self.directory._ldapconn._uri)
 181.154 +        try:
 181.155 +            conn.bind_s(self.dn, pwd, ldap.AUTH_SIMPLE)
 181.156 +            return True
 181.157 +        except ldap.INVALID_CREDENTIALS, e:
 181.158 +            return False
 181.159 +        
 181.160 +    def set_password(self, password, force_change=False):
 181.161 +        """set password for user. 
 181.162 +        :param password: the new password
 181.163 +        :param force_change: set force_change_password
 181.164 +        """
 181.165 +        if not password:
 181.166 +            return 
 181.167 +
 181.168 +        self.password = make_pass(password)
 181.169 +
 181.170 +        if force_change:
 181.171 +            self.expire_password()
 181.172 +        self.save()
 181.173 +
 181.174 +    def expire_password(self, gg=0):
 181.175 +        """
 181.176 +        Forza la scandenza password. Al momento disabilitato causa probelmi con gdm
 181.177 +        """
 181.178 +        # shadowLastChange al momento non funziona con X
 181.179 +        #self.srv.modify(user,'shadowLastChange','0')
 181.180 +        return
 181.181 +    
 181.182 +    def get_my_groups(self, as_text=False, as_plain_list=False):
 181.183 +        """
 181.184 +        return the groups the user belongs to
 181.185 +        :param as_test: as  text string to be shown
 181.186 +        """
 181.187 +
 181.188 +        filter_cond = filters.opand(filters.eq('memberUid', self.logname),
 181.189 +                                    filters.eq('objectClass', 'posixGroup'))
 181.190 +        groups = self.directory.search(PosixGroup, search_filter=filter_cond)
 181.191 +        if not isinstance(groups, list):
 181.192 +            groups = [groups]
 181.193 +        if as_text:
 181.194 +            return ",".join(g.name for g in groups)
 181.195 +        if as_plain_list:
 181.196 +            return [g.name for g in groups]
 181.197 +        return groups
 181.198 +
 181.199 +    def _get_maingroup(self):
 181.200 +        try:
 181.201 +            return self._maingroup
 181.202 +        except AttributeError:
 181.203 +            try:
 181.204 +                return get_group_by_gid(self.gid, self.directory).name
 181.205 +            except:
 181.206 +                return self.gid
 181.207 +
 181.208 +    def _set_maingroup(self, group_name):
 181.209 +        group = get_group(group_name, self.directory)
 181.210 +        self._maingroup = group_name
 181.211 +        self.gid = group.gid
 181.212 +
 181.213 +    maingroup = property(_get_maingroup, _set_maingroup)
 181.214 +
 181.215 +    def _get_classe(self):
 181.216 +        return self._classe
 181.217 +
 181.218 +    def _set_classe(self, classe):
 181.219 +
 181.220 +        if self.maingroup not in ('alunni', 'esterni'):
 181.221 +            return
 181.222 +
 181.223 +        if self.classe == classe:
 181.224 +            ## nothing to do
 181.225 +            return
 181.226 +        
 181.227 +        old_class_name = self.classe
 181.228 +        try:
 181.229 +            old_class = get_group(old_class_name, self.directory)
 181.230 +            old_class.remove_member(self.logname)
 181.231 +        except exc.MissingMatch, e:
 181.232 +            pass
 181.233 +            
 181.234 +        self._classe = classe
 181.235 +        classe = get_group(classe, self.directory)
 181.236 +        classe.add_member(self.logname)
 181.237 +
 181.238 +    classe = property(_get_classe, _set_classe)
 181.239 +    
 181.240 +    def set_groups(self, new_groups, posix_groups=None):
 181.241 +        """
 181.242 +        set membership of groups to reflect that of 'new_groups'
 181.243 +
 181.244 +        :param new_groups: a set of groups that should be set
 181.245 +        :param posix_groups: for efficiency reason, a dict of group items
 181.246 +              can be passed
 181.247 +        """
 181.248 +        posix_groups = posix_groups or {}
 181.249 +        old_groups   = set(self.get_my_groups(as_plain_list=True))
 181.250 +        if not isinstance(new_groups, set):
 181.251 +            new_groups = set(new_groups)
 181.252 +        
 181.253 +        for group_name in old_groups.union(new_groups):
 181.254 +            if group_name not in posix_groups:
 181.255 +                group = get_group(group_name, self.directory)
 181.256 +                if group:
 181.257 +                    posix_groups[group_name] = group
 181.258 +                else:
 181.259 +                    raise
 181.260 +
 181.261 +        ## remove from groups no longer needed
 181.262 +        for group_name in old_groups.difference(new_groups):
 181.263 +            posix_groups[group_name].remove_member(self.logname, save=True)
 181.264 +        
 181.265 +        ## add membership to new groups
 181.266 +        for group_name in new_groups.difference(old_groups):
 181.267 +            posix_groups[group_name].add_member(self.logname, save=True)
 181.268 +        
 181.269 +
 181.270 +    def delete(self, home_mode='tar'):
 181.271 +        self.home_mode = home_mode
 181.272 +        Model.delete(self)
 181.273 +
 181.274 +    def _hook_post_delete(self):
 181.275 +        """
 181.276 +        Delete the personal group if it exists
 181.277 +        """
 181.278 +        ## delete personal group
 181.279 +        try:
 181.280 +            personal_group = get_group(self.logname, self.directory)
 181.281 +            personal_group.delete()
 181.282 +        except Exception:
 181.283 +            pass
 181.284 +
 181.285 +        ### membership
 181.286 +        for g in self.get_my_groups():
 181.287 +            g.remove_member(self.logname)
 181.288 +
 181.289 +        ### delete the home
 181.290 +        if self.home_mode:
 181.291 +            filesystem.home_delete(self.logname, self.home, mode=self.home_mode)
 181.292 +
 181.293 +    def set_quota(self, soft_space, hard_space, soft_files, hard_files, fs='/home'):
 181.294 +        """ imposta la quota di un utente
 181.295 +
 181.296 +        :param soft_space: soft disc space limit 
 181.297 +        :param hard_space: hard disc space limit
 181.298 +        :param soft_files: soft file number limit
 181.299 +        :param hard_files: hard file number limit
 181.300 +        :param fs: the filesystem for which quota must be set
 181.301 +        """
 181.302 +        
 181.303 +        cmd = "setquota -u %s %s %s %s %s %s" % (self.logname, soft_space, hard_space, soft_files, hard_files, fs)
 181.304 +
 181.305 +        ret, out, err = execute(cmd)
 181.306 +        if ret:
 181.307 +            raise exc.QuotaError(err)
 181.308 +    
 181.309 +    def as_isi_format(self, extended=False):
 181.310 +        """
 181.311 +        return the user isi 'isi'  format: ie. as used by isi-adduser
 181.312 +        """
 181.313 +
 181.314 +        record = [self.logname, self.last_name, self.first_name or '', self.maingroup,
 181.315 +                  self.classe or '', self.cf or '', '']
 181.316 +        if extended:
 181.317 +            city, pv = '', ''
 181.318 +            pattern = re.compile('^(?P<city>.*)\((?P<pv>..)\)')
 181.319 +            m = pattern.match(self.city or '')
 181.320 +            if m:
 181.321 +                city = cp.group('city').strip()
 181.322 +                pv = cp.group('pv')
 181.323 +
 181.324 +            
 181.325 +            record += [self.sex or '', self.address or '', city, pv, self.zip_code or '', self.phone or '']
 181.326 +
 181.327 +        return ";".join(record)
 181.328 +            
 181.329 +    def as_dict(self):
 181.330 +        """return a dict with all attributes of the user if non empty
 181.331 +        used in django views to fill forms"""
 181.332 +
 181.333 +        user_dict = {}
 181.334 +        for attr in self.__base_data__ + self.__extended_data__ + [
 181.335 +            'logname', 'uid', 'full_name', 'home', 'maingroup', 'gid']:
 181.336 +            if getattr(self, attr):
 181.337 +                user_dict[attr] = getattr(self, attr)
 181.338 +        user_dict['groups'] = self.get_my_groups(as_text=True)
 181.339 +        return user_dict
 181.340 +
 181.341 +    def get_quota(self, fs='/home'):
 181.342 +        """
 181.343 +        return (used, quota, limit) for space limits
 181.344 +        """
 181.345 +        
 181.346 +        ret_code, out, err = execute("quota -v %s " % self.logname)
 181.347 +        if ret_code:
 181.348 +            raise exc.MissingQuotaSupport()
 181.349 +        info = out.split('\n')[-1]
 181.350 +        
 181.351 +        filesystem, self.used, self.quota, self.limit = info.split()[:3]
 181.352 +        return (self.used, self.quota, self.limit)
 181.353 +
 181.354 +    def __str__(self):
 181.355 +        return u'%s' % (self.logname, )
 181.356 +
 181.357 +    def __repr__(self):
 181.358 +        return u'<PosixUser %s>' % (self.logname, )
 181.359 +
 181.360 +class SambaUser(PosixUser):
 181.361 +    _object_class_ = ['sambaSamAccount',]
 181.362 +
 181.363 +    nthash = StringField('sambaNTPassword')
 181.364 +    lmhash = StringField('sambaLMPassword')
 181.365 +    logon = StringField('sambaLogonScript')
 181.366 +    sambaHomePath = StringField('sambaHomePath')
 181.367 +    sambamax = fields.IntegerField('shadowMax')
 181.368 +    sambaPwdMustChange = fields.IntegerField('sambaPwdMustChange')
 181.369 +    sambaPwdLastSet = fields.IntegerField('sambaPwdLastSet')
 181.370 +    flags = StringField('sambaAcctFlags')
 181.371 +
 181.372 +    def test_samba_password(self, pwd, client=False):
 181.373 +        """
 181.374 +        controlla la validità delle credenziali
 181.375 +        :param client: use an external client (smbclient)
 181.376 +                 the problem is that a password that has been forced to expire
 181.377 +                 would not validate
 181.378 +        """
 181.379 +        if not pwd:
 181.380 +            return False
 181.381 +        if client:
 181.382 +            ret_code, out, err = execute('smbclient -L localhost -U %s%%%s' % (self.logname, pwd))
 181.383 +            return not bool(ret_code)
 181.384 +        else:
 181.385 +            return (self.lmhash, self.nthash) == smbpasswd.hash(pwd)
 181.386 +
 181.387 +    def expire_password(self, gg=0):
 181.388 +        """
 181.389 +        force the password to expire
 181.390 +
 181.391 +        :param gg: termine entro il quale deve essere fatta scadere la password (non implementato)
 181.392 +        """
 181.393 +
 181.394 +        PosixUser.expire_password(self, gg=gg)
 181.395 +        
 181.396 +        self.sambaPwdLastSet = 0
 181.397 +        # for samba < 3.0.24
 181.398 +        #self.srv.modify(user,'sambaPwdMustChange','0')
 181.399 +        
 181.400 +    def set_password(self, password, force_change=False):
 181.401 +        """
 181.402 +        force the password to expire
 181.403 +        """
 181.404 +        if not password:
 181.405 +            return
 181.406 +        self.lmhash, self.nthash = [unicode(s) for s in smbpasswd.hash(password)]
 181.407 +        self.sambaPwdLastSet = int(time.time())
 181.408 +        PosixUser.set_password(self, password, force_change=force_change)
 181.409 +        
 181.410 +class PosixGroup(Model):
 181.411 +    _object_class_ = ['posixGroup', ]
 181.412 +    _rdn_ = 'name'
 181.413 +    name = StringField('cn')
 181.414 +    gid = fields.IntegerField('gidNumber')
 181.415 +    members = fields.StringListField('memberUid')
 181.416 +    description = StringField('description')
 181.417 +
 181.418 +    def __repr__(self):
 181.419 +        return u'<%s %s >' % (self.__class__.__name__, self.name)
 181.420 +
 181.421 +    def __str__(self):
 181.422 +        return u'%s' % (self.name)
 181.423 +
 181.424 +    def url(self, text=None):
 181.425 +        return u'<a href="/users/group/%s">%s</a>' % (self.name, text or self.name)
 181.426 +
 181.427 +    def is_class(self):
 181.428 +        "return true if a directory exists in CLASSES_PATH with this name"
 181.429 +        return os.path.exists(os.path.join(defaults.CLASSES_PATH, self.name))
 181.430 +    
 181.431 +    def is_course(self):
 181.432 +        "return true if a directory exists in COURSES_PATH with this name"
 181.433 +        return os.path.exists(os.path.join(defaults.COURSES_PATH, self.name))
 181.434 +    
 181.435 +    def create_links(self):
 181.436 +        """
 181.437 +        run alulink if this is a aclass or course
 181.438 +        """
 181.439 +        from isi import filesystem
 181.440 +        if self.is_class() or self.is_course():
 181.441 +            filesystem.create_alulink((self.name,), group=self)
 181.442 +
 181.443 +    def _get_my_share(self):
 181.444 +        """
 181.445 +        return class or course path if group is class or course
 181.446 +        return None otherwise 
 181.447 +        """
 181.448 +        try:
 181.449 +            return self._share
 181.450 +        except AttributeError:
 181.451 +            if self.is_class():
 181.452 +                self._share = os.path.join(defaults.CLASSES_PATH, self.name)
 181.453 +            elif self.is_course():
 181.454 +                self._share = os.path.join(defaults.COURSES_PATH, self.name)
 181.455 +            return self._share
 181.456 +        return None
 181.457 +
 181.458 +    share = property(_get_my_share)
 181.459 +        
 181.460 +
 181.461 +    def members_info(self):
 181.462 +        if self.members:
 181.463 +            return "members: %s (%s)" % (len(self.members), ",".join(self.members[:8]))
 181.464 +        return ''
 181.465 +
 181.466 +    def ismember(self, uid):
 181.467 +        """Return True if given uid is member of this group.
 181.468 +        """
 181.469 +        return uid in self.members
 181.470 +
 181.471 +    def members_as_users(self,  fake=False, order_by=None, samba=True):
 181.472 +        """
 181.473 +        :param fake: get also fake users as unicode strings
 181.474 +            A fake user is a user that no more exists but is still referenced as a member
 181.475 +        :param ordered: return members in alfabetical order on the last_name (only if fake=False)
 181.476 +        """
 181.477 +
 181.478 +        members = sorted(self.members)
 181.479 +        if fake:
 181.480 +            return [get_user(u, self.directory) or u for u in members]
 181.481 +        else:
 181.482 +            if samba:
 181.483 +                members = filter(None, [get_samba_user(u, self.directory) for u in members])
 181.484 +            else:
 181.485 +                members = filter(None, [get_user(u, self.directory) for u in members])
 181.486 +                
 181.487 +            if order_by:
 181.488 +                return sorted(members, key=lambda x: getattr(x, order_by))
 181.489 +            else:
 181.490 +                return members
 181.491 +        
 181.492 +    def get_zombie_users(self):
 181.493 +        """check that each member is a system user, returns a list of
 181.494 +        user that are not system users (fake users)"""
 181.495 +
 181.496 +        return [u for u in self.members_as_users(fake=True) if not u]
 181.497 +    
 181.498 +    def add_member(self, name, save=True):
 181.499 +        """
 181.500 +        add a user as mamber of this group
 181.501 +        """
 181.502 +        if name not in self.members:
 181.503 +            self.members += [unicode(name)]
 181.504 +            if save:
 181.505 +                self.save()
 181.506 +            
 181.507 +    def remove_member(self, member, save=True):
 181.508 +        """
 181.509 +        Remove a member from the group. The user is not deleted
 181.510 +        :param member: the member to remove: string or PosixUser
 181.511 +        :param save: (boolean) save the group after removeing the user
 181.512 +        """
 181.513 +        # Note! members.pop() doesn't work!
 181.514 +
 181.515 +        if isinstance(member, basestring):
 181.516 +            logname = member
 181.517 +        else:
 181.518 +            logname = member.logname
 181.519 +        
 181.520 +        if logname in self.members:
 181.521 +            self.members = [u for u in self.members if not u == logname]
 181.522 +            if save:
 181.523 +                self.save()
 181.524 +
 181.525 +    def delete_members(self, save=True, home_mode='tar', maingroup=True):
 181.526 +        """
 181.527 +        Delete all members of this group
 181.528 +        :param maingroup: delete also people that have this as maingroup
 181.529 +        """
 181.530 +        for u in self.members_as_users(fake=True):
 181.531 +            self.remove_member(u, save=True)
 181.532 +            try:
 181.533 +                u.delete(home_mode=home_mode)
 181.534 +            except AttributeError: # fake users
 181.535 +                pass
 181.536 +        self.members = []
 181.537 +
 181.538 +        if maingroup:
 181.539 +            others = self.directory.search(PosixUser, search_filter=filters.eq('gidNumber', self.gid))
 181.540 +            for user in others:
 181.541 +                user.delete(home_mode=home_mode)
 181.542 +                
 181.543 +        if save:
 181.544 +            self.save()
 181.545 +
 181.546 +    def expire_password(self, gg=0, samba=True):
 181.547 +
 181.548 +        for user in self.members_as_users(samba=samba):
 181.549 +            user.expire_password(gg=gg)
 181.550 +        
 181.551 +    def get_www(self):
 181.552 +
 181.553 +        return 'nowww' in (self.description or '')
 181.554 +
 181.555 +    def as_isi_format(self, extended=False):
 181.556 +        """
 181.557 +        return all members in 'isi' format
 181.558 +        """
 181.559 +        records = [u.as_isi_format(extended) for u in  self.members_as_users() if u]
 181.560 +        return "\n".join(records)
 181.561 +        
 181.562 +    def set_www(self, www):
 181.563 +        """
 181.564 +        inhibit internet browsing to all users
 181.565 +        """
 181.566 +        wgroup = get_group('nowww', self.directory)
 181.567 +
 181.568 +        if www: # permetti navigazioe
 181.569 +            self.description = re.sub('nowww', '', self.description or '')
 181.570 +            for name in self.members:
 181.571 +                wgroup.remove_member(name)
 181.572 +
 181.573 +        else:  # inhibit browsing
 181.574 +            self.description = u"%s nowww" % (self.description or '')
 181.575 +            for name in self.members:
 181.576 +                wgroup.members += [name]
 181.577 +        self.save()
 181.578 +        wgroup.save()
 181.579 +
 181.580 +    def set_quota(self, soft_space, hard_space, soft_files, hard_files, fs='/home'):
 181.581 +        """ imposta la quota di un utente
 181.582 +
 181.583 +        :param soft_space: soft disc space limit 
 181.584 +        :param hard_space: hard disc space limit
 181.585 +        :param soft_files: soft file number limit
 181.586 +        :param hard_files: hard file number limit
 181.587 +        :param fs: the filesystem for which quota must be set (default: /home)
 181.588 +        """
 181.589 +        
 181.590 +        cmd = "setquota -g %s %s %s %s %s %s" % (self.logname, soft_space, hard_space, soft_files, hard_files, fs)
 181.591 +
 181.592 +        ret_code, out, err = execute(cmd)
 181.593 +        if ret_code:
 181.594 +            raise exc.QuotaError(err)
 181.595 +    
 181.596 +    def set_members_quota(self, soft_space, hard_space, soft_files, hard_files, fs='/home'):
 181.597 +        """ setta la quota di tutti i membri di un gruppo """
 181.598 +
 181.599 +        for user in self.members_as_users(fake=False):
 181.600 +
 181.601 +            touch_file = '%s/touch.%s' % (fs, u)
 181.602 +            open(touch_file).close()
 181.603 +            os.chown(touch_file, user.logname, gruppo.name)
 181.604 +            user.set_quota(soft_space, hard_space, soft_files, hard_files, fs)
 181.605 +            
 181.606 +            
 181.607 +        # setta la quota di gruppo come somma delle quote dei membri
 181.608 +#         n = len(self.members)
 181.609 +#         cmd = "setquota -g %s %s %s %s %s %s" % (self.name, soft_space*n, hard_space*n,
 181.610 +#                                                  soft_files*n, hard_files*n, fs)
 181.611 +#         ret, out, err = execute(cmd)
 181.612 +#         if ret:
 181.613 +#             raise QuotaError(err)
 181.614 +            
 181.615 +        ## a che serve?
 181.616 +#        execute('repquota -au', stdout='/tmp/repquota.txt')
 181.617 +#        execute('repquota -ag', stdout='>>/tmp/repquota.txt')
 181.618 +        execute('rm %s/touch.*' % fs)
 181.619 +
 181.620 +
 181.621 +class SambaGroup(PosixGroup):
 181.622 +    _object_class_ = ['posixGroup', 'sambaGroupMapping' ]
 181.623 +    sid = StringField('sambaSID')
 181.624 +
 181.625 +    def members_as_users(self):
 181.626 +
 181.627 +        return [get_samba_user(u, self.directory) for u in sorted(self.members)]
 181.628 +        
 181.629 +class SambaDomain(Model):
 181.630 +    _object_class_ = ['sambaUnixIdPool', 'sambaDomain' ]
 181.631 +    domain_name = StringField('sambaDomainName')
 181.632 +    sid = StringField('sambaSID')
 181.633 +    next_gid = fields.IntegerField('gidNumber')
 181.634 +    next_uid = fields.IntegerField('uidNumber')
 181.635 +    sambaPwdHistoryLength = fields.IntegerField('sambaPwdHistoryLength')
 181.636 +    sambaMinPwdLength     = fields.IntegerField('sambaMinPwdLength')
 181.637 +    sambaMinPwdAge        = fields.IntegerField('sambaMinPwdAge')
 181.638 +    sambaMaxPwdAge        = fields.IntegerField('sambaMaxPwdAge')
 181.639 +    sambaLogonToChgPwd    = fields.IntegerField('sambaLogonToChgPwd')
 181.640 +
 181.641 +    def get_next_uid(self):
 181.642 +        """return the next uid and increments it"""
 181.643 +
 181.644 +        next = self.next_uid
 181.645 +        self.next_uid += 1
 181.646 +        self.save()
 181.647 +        return next
 181.648 +
 181.649 +    def get_next_gid(self):
 181.650 +        """return the next uid and increments it"""
 181.651 +
 181.652 +        next = self.next_gid
 181.653 +        self.next_gid += 1
 181.654 +        self.save()
 181.655 +        return next
 181.656 +
 181.657 +def make_pass(password):
 181.658 +    """
 181.659 +    generate a pass suitable for openldap
 181.660 +    """
 181.661 +    # http://www.openldap.org/faq/data/cache/347.html
 181.662 +    from base64 import encodestring as encode
 181.663 +    salt = os.urandom(4)
 181.664 +    h = hashlib.sha1(password)
 181.665 +    h.update(salt)
 181.666 +    return u"{SSHA}" + encode(h.digest() + salt)
 181.667 +
 181.668 +def check_pass(challenge_password, password):
 181.669 +
 181.670 +    from base64 import decodestring as decode
 181.671 +
 181.672 +    challenge_bytes = decode(challenge_password[6:])
 181.673 +    digest = challenge_bytes[:20]
 181.674 +    salt = challenge_bytes[20:]
 181.675 +    hr = hashlib.sha1(password)
 181.676 +    hr.update(salt)
 181.677 +    return digest == hr.digest()
   182.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.2 +++ b/lib/isi/parser.py	Mon Apr 26 11:16:23 2010 +0200
   182.3 @@ -0,0 +1,172 @@
   182.4 +# -*- coding: utf-8 -*-
   182.5 +
   182.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   182.7 +#
   182.8 +#  This program is free software: you can redistribute it and/or modify
   182.9 +#  it under the terms of the GNU General Public License as published by
  182.10 +#  the Free Software Foundation, either version 3 of the License, or
  182.11 +#  (at your option) any later version.
  182.12 +#
  182.13 +#  This program is distributed in the hope that it will be useful,
  182.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  182.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  182.16 +#  GNU General Public License for more details.
  182.17 +#
  182.18 +#  You should have received a copy of the GNU General Public License
  182.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  182.20 +
  182.21 +
  182.22 +import re
  182.23 +import exc
  182.24 +import string
  182.25 +import random
  182.26 +
  182.27 +class UserParser(object):
  182.28 +
  182.29 +    
  182.30 +    action = None
  182.31 +    "action may be: add, delete, update"
  182.32 +
  182.33 +    def __init__(self,
  182.34 +                 manager,
  182.35 +                 definition_string,
  182.36 +                 interactive = False,
  182.37 +                 update_user = True,
  182.38 +                 no_filesystem = False,
  182.39 +                 run_alulink = True,
  182.40 +
  182.41 +                 default_passwd = None,
  182.42 +                 update_passwd = True,
  182.43 +                 force_passwd_change = True,
  182.44 +                 passwd_random = False,
  182.45 +                 use_cf=None,
  182.46 +                 ):
  182.47 +        """
  182.48 +        Definition string may have 6, 7 or 13 fields
  182.49 +        logname last_name, first_name, maingroup, minor_groups, cf, [password]
  182.50 +        extended fields:
  182.51 +            sesso, indirizzo, comune_residenza, cap, provincia, tel1
  182.52 +
  182.53 +        :param no_filesystem: opts.no_filesystem,
  182.54 +        :param update_user: if the user exists must be updated,
  182.55 +        :param update_passwd: opts.update_passwd,
  182.56 +        :param home_mode: 'tar' if not opts.home_zap or 'rm',
  182.57 +        :param force_passwd_change: opts.force_change_passwd
  182.58 +
  182.59 +
  182.60 +        logname;last;name;maingrp;other_grp1,othergrp2...;CF;PASS;list_ext_flds
  182.61 +        If password is missing, password is set from cf
  182.62 +        If cf is missing password MUST be set
  182.63 +
  182.64 +        """
  182.65 +        self.manager = manager
  182.66 +        self.interactive = interactive
  182.67 +        self.manager = manager
  182.68 +        self.update_user = update_user
  182.69 +        self.no_filesystem = no_filesystem
  182.70 +        self.run_alulink = run_alulink
  182.71 +
  182.72 +        ### password related options
  182.73 +        self.update_passwd = update_passwd
  182.74 +        self.force_passwd_change = force_passwd_change
  182.75 +        self.default_passwd = default_passwd
  182.76 +        self.passwd_random = passwd_random
  182.77 +        self.use_cf = use_cf
  182.78 +        
  182.79 +        ## parsing the definition_string
  182.80 +        self.definition_string = definition_string.strip()
  182.81 +        fields = [x.strip() for x in self.definition_string.split(';')]
  182.82 +        
  182.83 +        self.action, self.logname = self.guess_action(fields[0])
  182.84 +
  182.85 +        if self.action == 'delete':
  182.86 +            return
  182.87 +        
  182.88 +        self.last_name    = fields[1].title()
  182.89 +        self.first_name   = fields[2].title()
  182.90 +        self.maingroup    = fields[3].lower()
  182.91 +        self.groups       = [x for x in fields[4].split(',') if x]
  182.92 +        self.classe       = self.groups and self.groups[0] or None
  182.93 +        try:
  182.94 +            self.cf = fields[5].upper()
  182.95 +        except IndexError:
  182.96 +            self.cf = ''
  182.97 +
  182.98 +        self.passwd = self.create_passwd(fields)
  182.99 +        if len(fields) >= 13:
 182.100 +            self.sex, self.address, self.city, self.zip, self.pv, self.phone = fields[7:13]
 182.101 +        else:
 182.102 +            self.sex, self.address, self.city, self.zip, self.pv, self.phone = [None] * 6
 182.103 +            
 182.104 +        self.extended_attrs = {}
 182.105 +
 182.106 +
 182.107 +    def guess_action(self, logname):
 182.108 +        """
 182.109 +        guess which action should be taken from the logname depending on +, -, * or None
 182.110 +        """
 182.111 +
 182.112 +        m = re.match('(?P<mode>[-*+])?(?P<logname>.*)', logname)
 182.113 +        mode = m.group('mode')
 182.114 +        logname = m.group('logname').lower()
 182.115 +
 182.116 +        if mode == '-':
 182.117 +            action = 'delete'
 182.118 +            return action, logname
 182.119 +            
 182.120 +        user_exists = self.manager.user_exists(logname)
 182.121 +        if user_exists and not self.update_user:
 182.122 +            raise exc.AlreadyExistingUser("User %s already exists" % logname, logname)
 182.123 +
 182.124 +        if mode == '*' or user_exists:
 182.125 +            action = 'update'
 182.126 +        else:
 182.127 +            action = 'add'
 182.128 +
 182.129 +        return action, logname
 182.130 +
 182.131 +    def create_passwd(self, fields):
 182.132 +
 182.133 +        if not self.update_passwd and self.action == 'update':
 182.134 +            return None
 182.135 +
 182.136 +        if self.use_cf:
 182.137 +            passwd = self.cf[:8].title()
 182.138 +        elif self.passwd_random:
 182.139 +            passwd = new_password()
 182.140 +        elif self.default_passwd:
 182.141 +            passwd = self.default_passwd
 182.142 +        else:
 182.143 +            try:
 182.144 +                passwd = fields[6]
 182.145 +            except IndexError:
 182.146 +                raise exc.MissingPassword("Missing password for user %s defined by\n%s" %
 182.147 +                                          (self.logname, self.definition_string))
 182.148 +            
 182.149 +        return passwd
 182.150 +
 182.151 +    def get_opts(self):
 182.152 +
 182.153 +        user_opts = {
 182.154 +            'interactive' : self.interactive,
 182.155 +            'no_filesystem' : self.no_filesystem,
 182.156 +            'run_alulink' : self.run_alulink,
 182.157 +            'force_passwd_change' : self.force_passwd_change, 
 182.158 +            'last_name' : self.last_name,
 182.159 +            'first_name' : self.first_name, 
 182.160 +            'groups' : self.groups,
 182.161 +            'passwd' : self.passwd,
 182.162 +            'classe' : self.classe,
 182.163 +            'cf' : self.cf,
 182.164 +            'sex' : self.sex,
 182.165 +            'address' : self.address,
 182.166 +            'city' : self.city, 
 182.167 +            'zip_code' : self.zip,
 182.168 +            'phone' : self.phone,
 182.169 +            }
 182.170 +        return user_opts
 182.171 +    
 182.172 +def new_password(length=8, chars=string.letters + string.digits):    
 182.173 +        """ genera una password casuale """
 182.174 +        return ''.join([random.choice(chars) for i in range(length)])
 182.175 +
   183.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   183.2 +++ b/lib/isi/srv.py	Mon Apr 26 11:16:23 2010 +0200
   183.3 @@ -0,0 +1,1182 @@
   183.4 +#!/usr/bin/python
   183.5 +# -*- coding: utf-8 -*-
   183.6 +
   183.7 +# This program is free software; you can redistribute it and/or modify
   183.8 +# it under the terms of the GNU General Public License as published by
   183.9 +# the Free Software Foundation; either version 2, or (at your option)
  183.10 +# any later version.
  183.11 +
  183.12 +
  183.13 +# AUTHORS: Sandro Dentella - Massimo Mancini
  183.14 +
  183.15 +
  183.16 +"""module to perform all basic operations with ldap server
  183.17 +"""
  183.18 +
  183.19 +import ldap
  183.20 +import re, string, random
  183.21 +import sys
  183.22 +import os
  183.23 +import logging
  183.24 +from logging import handlers
  183.25 +from pprint import pprint
  183.26 +#import subprocess as sub
  183.27 +import datetime
  183.28 +from dry.functions import execute, ExecuteError
  183.29 +from isi import filesystem, exc
  183.30 +from isi.conf import defaults
  183.31 +from time import mktime, localtime, strftime
  183.32 +from parser import UserParser
  183.33 +import models
  183.34 +
  183.35 +SCOPE = ldap.SCOPE_SUBTREE
  183.36 +
  183.37 +## logger generico 
  183.38 +def get_logger(web=False):
  183.39 +    if web:
  183.40 +        # create logger
  183.41 +        logger = logging.getLogger("IdraWeb")
  183.42 +        logger.setLevel(logging.DEBUG)
  183.43 +
  183.44 +        # create syslog handler and set level to debug
  183.45 +        sl = handlers.SysLogHandler(address='/dev/log')
  183.46 +        sl.setLevel(logging.DEBUG)
  183.47 +
  183.48 +        # create formatter
  183.49 +        formatter = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
  183.50 +        sl.setFormatter(formatter)
  183.51 +
  183.52 +        logger.addHandler(sl)
  183.53 +
  183.54 +    else:
  183.55 +        logging.basicConfig(filename=defaults.LOG_FILE,
  183.56 +                       filemode=defaults.LOG_MODE, 
  183.57 +                       format=defaults.LOG_FORMAT,
  183.58 +                       datefmt=defaults.LOG_DATE_FORMAT)
  183.59 +
  183.60 +        logger = logging.getLogger('isi')
  183.61 +    return logger
  183.62 +
  183.63 +
  183.64 +### Definizione classi ###     
  183.65 +
  183.66 +class IsiConn(object):
  183.67 +    """
  183.68 +    Allows ANONYMOUS BIND passing dn="", passwd="" to __init__ method
  183.69 +    """
  183.70 +    def __init__(self, uri='ldap://localhost', conf='/etc/ldap/slapd.conf',
  183.71 +                 dry_run=False, dn=None, passwd=None, test_runnning=False, web=False):
  183.72 +        """
  183.73 +        :param uri:  the ldap server to connect to (default: ldap://localhost)
  183.74 +        :param conf: the con file for slapd (default: /etc/ldap/slapd.conf
  183.75 +        :param dry_run: don't really change the ldap server
  183.76 +        :param dn: bind with this user
  183.77 +        :param passwd: authenticate with this password
  183.78 +        :param test_running: we are running tests, don't make backup copies
  183.79 +               so that tests are faster
  183.80 +        """
  183.81 +        self.uri  = uri
  183.82 +        self.conf = conf
  183.83 +        self.dry_run = dry_run
  183.84 +        self.base = self.get_base()
  183.85 +        self.conn = ldap.initialize(uri)
  183.86 +
  183.87 +        self.rootdn = dn
  183.88 +        self.passwd = passwd
  183.89 +
  183.90 +        if     dn is None: self.rootdn = self.get_rootdn()
  183.91 +        if passwd is None: self.passwd = self.get_rootdn_passwd()
  183.92 +
  183.93 +        self.bind()
  183.94 +        self.test_running = test_runnning
  183.95 +        self.logger = get_logger(web=web)
  183.96 +    
  183.97 +    def bind(self, dn=None, passwd=None):
  183.98 +        """
  183.99 +        make a syncronous connection to the server for ``self.conn``
 183.100 +        """
 183.101 +        if dn is None: dn = self.rootdn
 183.102 +        if passwd is None: passwd = self.passwd
 183.103 +        try:
 183.104 +            self.conn.bind_s(dn, passwd, ldap.AUTH_SIMPLE)
 183.105 +        except ldap.INVALID_CREDENTIALS, e:
 183.106 +            raise
 183.107 +
 183.108 +    def test_password(self, uid, pwd):
 183.109 +        """
 183.110 +        controlla la validità delle credenziali
 183.111 +        """
 183.112 +        if not pwd: return False
 183.113 +        dn = self.get_dn(uid, search_type='uid')
 183.114 +        conn = ldap.initialize(self.uri)
 183.115 +        try:
 183.116 +            conn.bind_s(dn, pwd, ldap.AUTH_SIMPLE)
 183.117 +            return True
 183.118 +        except ldap.INVALID_CREDENTIALS, e:
 183.119 +            return False
 183.120 +        
 183.121 +    def get_rootdn(self):
 183.122 +        """
 183.123 +        should be implemented reading just slapd.conf...
 183.124 +        I don't want to depend on smbldap_tools.
 183.125 +        """
 183.126 +
 183.127 +        return "cn=admin,%s" % self.base
 183.128 +    
 183.129 +    def get_rootdn_passwd(self):
 183.130 +        """
 183.131 +        return password in ldap.secret
 183.132 +        """
 183.133 +        f= open('/etc/ldap.secret')
 183.134 +        passwd = f.readline()
 183.135 +        f.close()
 183.136 +        return passwd.rstrip('\n')
 183.137 +    
 183.138 +    def set_rootdn_passwd(self, password):
 183.139 +        """cambia la pass di rootbinddn"""
 183.140 +        
 183.141 +        self.set_smbldap_bind_passwd(password)
 183.142 +
 183.143 +        cmd = 'slappasswd -s %s' % password
 183.144 +        ret_code, newpwd, err = execute(cmd)
 183.145 +        if ret_code:
 183.146 +            raise ExecuteError("OUT: %s\nERR: %s" % (out, err))
 183.147 +
 183.148 +        self.modify(self.rootdn,'userPassword',newpwd)
 183.149 +        try:
 183.150 +            self.bind(passwd=password)
 183.151 +            self.passwd = password
 183.152 +        except:
 183.153 +            raise ExecuteError("I can't get auth bind: %s" % err)
 183.154 +
 183.155 +        secrets = ( '/etc/ldap.secret', 
 183.156 +                    '/etc/libnss-ldap.secret',
 183.157 +                    '/etc/pam_ldap.secret')
 183.158 +                        
 183.159 +        for f in secrets:
 183.160 +            if not os.path.islink(f):
 183.161 +                f = open(f, 'w')
 183.162 +                f.write("%s\n" % password)
 183.163 +                f.close()
 183.164 +                    
 183.165 +        cmd = "smbpasswd -w %s" % password
 183.166 +        ret_code, out, err = execute(cmd)
 183.167 +        if ret_code:
 183.168 +            raise ExecuteError("could not change password in secret.tdb: %s" % err)
 183.169 +
 183.170 + 
 183.171 +    def set_smbldap_bind_passwd(self, password):
 183.172 +        """
 183.173 +        replace pwd in file /etc/smbldap-tools/smbldap_bind.conf
 183.174 +        that looks like::
 183.175 +
 183.176 +          slaveDN="cn=admin,dc=isi,dc=lan"
 183.177 +          slavePw="xxxxxx"
 183.178 +          masterDN="cn=admin,dc=isi,dc=lan"
 183.179 +          masterPw="xxxxxx"
 183.180 +        """
 183.181 +        conf_file = '/etc/smbldap-tools/smbldap_bind.conf'
 183.182 +        PATTERN = re.compile('(slavePw|masterPw)="(.*)"', re.M)
 183.183 +        content = open(conf_file).read()
 183.184 +        content = re.sub(PATTERN, r'\1="%s"' % password, content)
 183.185 +        f = open(conf_file, 'w')
 183.186 +        f.write(content)
 183.187 +        f.close()
 183.188 +
 183.189 +    def get_base(self):
 183.190 +        """
 183.191 +        return samba conf for basedn
 183.192 +        look for 'ldap suffix' in the output of samba's ``testparm -s``
 183.193 +        """
 183.194 +
 183.195 +        try:
 183.196 +            ret, out, err = execute('testparm -s')
 183.197 +        except e:
 183.198 +            print e
 183.199 +            sys.exit(1)
 183.200 +
 183.201 +        smbconf = out.replace('\t','').split('\n')
 183.202 +
 183.203 +        for l in smbconf:
 183.204 +            if not 'ldap suffix = ' in l: continue
 183.205 +            key, value = l.split(' = ')
 183.206 +            
 183.207 +            if not value:
 183.208 +                raise InvalidValue
 183.209 +                sys.exit(1)
 183.210 +            else:
 183.211 +                return value
 183.212 +
 183.213 +    def show_conf(self):
 183.214 +        """
 183.215 +        show the configurazione of this server: uri, base, conf, rootdn, passwd
 183.216 +        """
 183.217 +        for i in ('uri', 'base', 'conf','rootdn', 'passwd'):
 183.218 +            print "%s: %s" % (i, getattr(self, i))
 183.219 +
 183.220 +        try:
 183.221 +            ret = self.bind()
 183.222 +        except Exception, e:
 183.223 +#            print "Error: could not bind", e
 183.224 +            raise 
 183.225 +
 183.226 +    def search(self, filterstr, *args, **kw):
 183.227 +        """
 183.228 +        perform a serach_s (syncronous) and return the result
 183.229 +        """
 183.230 +        return self.conn.search_s(self.base, SCOPE, filterstr, *args, **kw)
 183.231 +    
 183.232 +    def delete(self, dn):
 183.233 +        "delete an object"
 183.234 +        
 183.235 +        if self.dry_run:
 183.236 +            sys.stderr.write("DRY-RUN: else I'd delete %s\n" % dn)
 183.237 +        else:
 183.238 +            return self.conn.delete_s(dn)
 183.239 +    
 183.240 +    def get(self, filterstr, attrlist=None, null_ok=False, **kw):
 183.241 +        """
 183.242 +        search an object and raise a MultipleMatch error if more than one
 183.243 +        record is found. It also raise a MissingMatch if norecord is found and 
 183.244 +        'null_ok' is False (default)
 183.245 +        """
 183.246 +
 183.247 +        records = self.search(filterstr, attrlist=attrlist, **kw)
 183.248 +        if len(records) == 0:
 183.249 +            if null_ok == False:
 183.250 +                raise exc.MissingMatch('filter is: %s' % filterstr)
 183.251 +            else:
 183.252 +                return (None, None)
 183.253 +
 183.254 +        if len(records) == 1:
 183.255 +            return records[0]
 183.256 +        
 183.257 +        elif len(records) > 1:
 183.258 +            raise MultipleMatch(filterstr)
 183.259 +            
 183.260 +    def gets(self, filterstr, attrlist=None, null_ok=False, **kw):
 183.261 +        """search an object and NOT raise a MultipleMatch error if more than one
 183.262 +        record is found. It also raise a MissingMatch if norecord is found and 
 183.263 +        'null_ok' is False (default)"""
 183.264 +
 183.265 +        records = self.search(filterstr, attrlist=attrlist, **kw)
 183.266 +        return records
 183.267 +
 183.268 +    def modify(self, uid_or_dn, attr, newvalue,
 183.269 +               search_type='uid', quiet=False, add=False, rem=False):
 183.270 +        """
 183.271 +        modify an attribute by name or dn. add or remove (rem)
 183.272 +        """
 183.273 +
 183.274 +        if self.dry_run:
 183.275 +            print "DRY-RUN:change %s to %s in %s" % (uid_or_dn, attr,newvalue) 
 183.276 +            return
 183.277 +        
 183.278 +        dn = self.get_dn(uid_or_dn, search_type=search_type)
 183.279 +
 183.280 +        if newvalue == None:
 183.281 +            try:
 183.282 +                self.conn.modify_s(dn, [(ldap.MOD_DELETE, attr, None)])
 183.283 +            except ldap.NO_SUCH_ATTRIBUTE:
 183.284 +                pass
 183.285 +        else:
 183.286 +            if add:
 183.287 +                ## be quiet if adding a value, the value is already there
 183.288 +                try:
 183.289 +                    self.conn.modify_s(dn, [(ldap.MOD_ADD, attr, newvalue)])
 183.290 +                except ldap.TYPE_OR_VALUE_EXISTS, e:
 183.291 +                    pass
 183.292 +            if rem:
 183.293 +                try:
 183.294 +                    self.conn.modify_s(dn, [(ldap.MOD_ADD, attr, newvalue)])
 183.295 +                except ldap.TYPE_OR_VALUE_EXISTS, e:
 183.296 +                    pass
 183.297 +
 183.298 +            else:
 183.299 +                try:
 183.300 +                    self.conn.modify_s(dn, [(ldap.MOD_REPLACE, attr, newvalue)])
 183.301 +                except ldap.NO_SUCH_ATTRIBUTE, e:
 183.302 +                    if not quiet:
 183.303 +                        raise
 183.304 +                
 183.305 +    def get_dn(self, uid, search_type='uid'):
 183.306 +        """
 183.307 +        return a dn when given a uid (changeable with attribute). It searches
 183.308 +        adding base. If given a dn, returns it unchaged
 183.309 +        """
 183.310 +
 183.311 +        if uid.startswith("dn: ") or uid.startswith("cn="):
 183.312 +            return uid
 183.313 +
 183.314 +        dn, data = self.get("%s=%s" % (search_type, uid))
 183.315 +        return dn
 183.316 +        
 183.317 +    def backup(self):
 183.318 +        """save a slapcat.ldif file of the situation, suitable for restoring.
 183.319 +        The file is saved in /etc/isi/slapcat.ldif and is overwritte each call
 183.320 +        but is handled by a mercurial repository that is commited each time
 183.321 +        """
 183.322 +        if self.test_running:
 183.323 +            return
 183.324 +        out_file = defaults.BAK_LDAP_FILE
 183.325 +        execute("slapcat", None, out_file)
 183.326 +        ret_code, out, err = execute('hg add %s' % out_file, None, cwd='/etc')
 183.327 +        
 183.328 +        #ret_code, out, err = execute('hg status', None, cwd='/etc')
 183.329 +
 183.330 +        date = datetime.datetime.now().strftime("%H:%M %d/%m/%y")
 183.331 +        cmd = ['hg', 'commit', '-m' 'isi bk automatico %s' % date, out_file]
 183.332 +        ret_code, out, err = execute(cmd, cwd='/etc')
 183.333 +        if ret_code:
 183.334 +            raise ExecuteError(err)
 183.335 +# TODO: policies            
 183.336 +    def get_pwd_domain_policies(self, domain=None):
 183.337 +        """
 183.338 +        recupera le politiche di dominio
 183.339 +        """
 183.340 +        if not domain: domain = filesystem.samba_domain()
 183.341 +        plist = {
 183.342 +                'sambaPwdHistoryLength':0, 
 183.343 +                'sambaMinPwdLength':5, 
 183.344 +                'sambaMinPwdAge':0, 
 183.345 +                'sambaMaxPwdAge':-1, 
 183.346 +                'sambaLogonToChgPwd':0, 
 183.347 +                }
 183.348 +        pol = self.get('sambaDomainName=%s' % domain,plist.keys())
 183.349 +        plist['sambaPwdHistoryLength'] = int(pol[1]['sambaPwdHistoryLength'][0])
 183.350 +        plist['sambaMinPwdLength'] = int(pol[1]['sambaMinPwdLength'][0])
 183.351 +        plist['sambaMinPwdAge'] = int(pol[1]['sambaMinPwdAge'][0])
 183.352 +        plist['sambaMaxPwdAge'] = int(pol[1]['sambaMaxPwdAge'][0])
 183.353 +        plist['sambaLogonToChgPwd'] = int(pol[1]['sambaLogonToChgPwd'][0])
 183.354 +        return plist
 183.355 +
 183.356 +    def get_ugnums(self, domain):
 183.357 +        """
 183.358 +        get uidNumber and gidNumber for domain
 183.359 +        """
 183.360 +        nums = self.get('sambaDomainName=%s' % domain,['uidNumber','gidNumber'])
 183.361 +        uidNumber = int(nums[1]['uidNumber'][0])
 183.362 +        gidNumber = int(nums[1]['gidNumber'][0])
 183.363 +        return {'uidNumber':int(uidNumber), 'gidNumber':int(gidNumber)}
 183.364 +
 183.365 +    def set_ugnums(self, domain, uidNumber=None, gidNumber=None):
 183.366 +        """
 183.367 +        set uidNumber and gidNumber for domain
 183.368 +        """
 183.369 +        if uidNumber: self.modify(domain,'uidNumber',
 183.370 +                                  uidNumber,search_type='sambaDomainName')
 183.371 +        if gidNumber: self.modify(domain,'gidNumber',
 183.372 +                                  gidNumber,search_type='sambaDomainName')
 183.373 +
 183.374 +class Manager(object):
 183.375 +    def __init__(self, isiconn=None, verbose=False, web=False):
 183.376 +
 183.377 +        self.srv = isiconn or IsiConn(web=web)
 183.378 +        self.pumpkin_conn = models.get_conn(self.srv)
 183.379 +
 183.380 +        self.home_mode = None
 183.381 +        """home_mode may be rm or tar"""
 183.382 +        self.verbose = verbose
 183.383 +        self.sambaHome = None
 183.384 +        self.sambavers = filesystem.samba_version()
 183.385 +        self.logger = self.srv.logger
 183.386 +        self.groups = {}
 183.387 +        self.domain = self.get_samba_domain(filesystem.samba_domain())
 183.388 +### check
 183.389 +    def user_in_group(self, user, group):
 183.390 +        "test if user is in group"
 183.391 +
 183.392 +        filterstr = "(&(memberUid=%s)(cn=%s))" % (user, group)
 183.393 +        ret = self.srv.search(filterstr)
 183.394 +        return bool(ret)
 183.395 +    
 183.396 +    def user_exists(self, user):
 183.397 +        """test if user is a system user"""
 183.398 +
 183.399 +        filterstr = "(&(uid=%s)(objectClass=posixAccount))" % (user)
 183.400 +        dn, data = self.srv.get(filterstr, null_ok=True)
 183.401 +        return bool(dn)
 183.402 +        
 183.403 +    def group_exists(self, group):
 183.404 +        """test if group is a system group"""
 183.405 +        filterstr = "(&(cn=%s)(objectClass=posixGroup))" % (group)
 183.406 +        dn, data = self.srv.get(filterstr, null_ok=True)
 183.407 +        return bool(dn)
 183.408 +    
 183.409 +    def add_missing_groups(self, groups):
 183.410 +        """to be overloaded by isi-adduser for efficency """
 183.411 +        for group in groups:
 183.412 +            if group and not self.group_exists(group):
 183.413 +                self.add_group(group)
 183.414 +
 183.415 +    def add_classes(self, user, maingroup,  interactive,  groups):
 183.416 +        """ controlla esistenza gruppi dell'utente """
 183.417 +        if maingroup in ('alunni', 'esterni'):
 183.418 +            class_ = groups and groups[0] or None
 183.419 +            if not class_:
 183.420 +                return
 183.421 +            ## the first group, if exists is the class
 183.422 +            if maingroup == 'alunni':
 183.423 +                add_class_share([class_], course=False, interactive=interactive)
 183.424 +            elif maingroup == 'esterni':
 183.425 +
 183.426 +                add_class_share([class_], course=True, interactive=interactive)
 183.427 +
 183.428 +            return class_
 183.429 +    
 183.430 +    def test_password(self, uid, pwd):
 183.431 +        """
 183.432 +        controlla la validità delle credenziali
 183.433 +        """
 183.434 +        return self.srv.test_password(uid, pwd)
 183.435 +        
 183.436 +    def test_samba_password(self, uid, pwd, client=False):
 183.437 +        """
 183.438 +        controlla la validità delle credenziali
 183.439 +        """
 183.440 +        if not pwd:
 183.441 +            return False
 183.442 +        user = self.get_samba_user(uid)
 183.443 +        return user.test_samba_password(pwd, client=client)
 183.444 +
 183.445 +### get pumpkin objects
 183.446 +    def get_user(self, name, quiet=False):
 183.447 +        """
 183.448 +        Return a User object (pumpkin module)
 183.449 +        """
 183.450 +        user = models.get_user(name, self.pumpkin_conn)
 183.451 +        if not user and not quiet:
 183.452 +            raise exc.MissingMatch("User %s does not exists" % user)
 183.453 +        else:
 183.454 +            return user
 183.455 +        
 183.456 +    def get_samba_user(self, name, quiet=False):
 183.457 +        """
 183.458 +        Return a User object (pumpkin module)
 183.459 +        """
 183.460 +        user = models.get_samba_user(name, self.pumpkin_conn)
 183.461 +        if not user and not quiet:
 183.462 +            raise exc.MissingMatch("User %s does not exists" % user)
 183.463 +        else:
 183.464 +            return user
 183.465 +        
 183.466 +    def get_user_by_cf(self, cf):
 183.467 +        """
 183.468 +        Return a User object (pumpkin module)
 183.469 +        """
 183.470 +        return models.get_user_by_cf(cf, self.pumpkin_conn)
 183.471 +        
 183.472 +    def get_group(self, name, quiet=False):
 183.473 +        """
 183.474 +        Return a User object (pumpkin module)
 183.475 +        """
 183.476 +        try:
 183.477 +            return models.get_group(name, self.pumpkin_conn)
 183.478 +
 183.479 +        except exc.MissingMatch, e:
 183.480 +            if quiet:
 183.481 +                return
 183.482 +            raise exc.MissingMatch("Group %s does not exists" % name)
 183.483 +        
 183.484 +    def get_samba_group(self, name, quiet=False):
 183.485 +        """
 183.486 +        Return a User object (pumpkin module)
 183.487 +        """
 183.488 +        try:
 183.489 +            return models.get_samba_group(name, self.pumpkin_conn)
 183.490 +
 183.491 +        except exc.MissingMatch, e:
 183.492 +            if quiet:
 183.493 +                return
 183.494 +            raise exc.MissingMatch("Group %s does not exists" % name)
 183.495 +        
 183.496 +    def get_samba_domain(self, name):
 183.497 +        """
 183.498 +        Return a User object (pumpkin module)
 183.499 +        """
 183.500 +        return models.get_domain(name, self.pumpkin_conn)
 183.501 +        
 183.502 +### get
 183.503 +    def get_group_dn_by_name(self, name):
 183.504 +        """return the dn of a group reference by it's posix name"""
 183.505 +
 183.506 +        filterstr = "(&(cn=%s)(objectClass=posixGroup))" % name
 183.507 +        dn, data = self.srv.get(filterstr, attrlist=['cn'])
 183.508 +        return dn
 183.509 +    
 183.510 +    def get_user_dn_by_name(self, name):
 183.511 +        """return the dn of a user reference by it's posix name"""
 183.512 +        
 183.513 +        filterstr = "(&(uid=%s)(objectClass=posixAccount))" % name
 183.514 +        dn, data = self.srv.get(filterstr, attrlist=['cn'])
 183.515 +        return dn
 183.516 +    
 183.517 +    def get_home(self, user):
 183.518 +        """get homeDirectory of a user"""
 183.519 +        return self.get_ldap_field(user, 'homeDirectory')
 183.520 +
 183.521 +    def get_ldap_field(self, user, field):
 183.522 +        """get value of one ldap field"""
 183.523 +        filterstr = "(&(uid=%s)(objectClass=posixAccount))" % (user)
 183.524 +        dn, data = self.srv.get(filterstr, attrlist=[field])
 183.525 +        field = find_in(field, data.keys())
 183.526 +        if field: # in data:
 183.527 +            return data[field][0]
 183.528 +        else:
 183.529 +            return ""
 183.530 +
 183.531 +    def get_ldap_data(self, user,  attrlist):
 183.532 +        """get all data in attrlist"""
 183.533 +       
 183.534 +        filterstr = "(&(uid=%s)(objectClass=posixAccount))" % (user)
 183.535 +        dn, data = self.srv.get(filterstr, attrlist=attrlist)
 183.536 +        return data
 183.537 +    
 183.538 +    def get_user_groups(self, user):
 183.539 +        "return all posix group of a user"
 183.540 +
 183.541 +        filterstr = "(&(memberUid=%s)(objectClass=posixGroup))" % user
 183.542 +        
 183.543 +        ret = self.srv.search(filterstr, attrlist=['cn'])
 183.544 +        groups = []
 183.545 +        for dn, data in ret:
 183.546 +            groups += data['cn']
 183.547 +        return groups
 183.548 +    
 183.549 +    def get_domain(self):
 183.550 +        """get the sambaDomainName attribute of sambaDomain object"""
 183.551 +
 183.552 +        dn, data = self.srv.get("objectClass=sambaDomain")
 183.553 +        return data['sambaDomainName'][0]
 183.554 +    
 183.555 +    def get_attr(self, user, name):
 183.556 +        """return attribut 'name' of *user* 'user'. NOTE returns a list!! """
 183.557 +
 183.558 +        filterstr = "(&(uid=%s)(objectClass=posixAccount))" % (user)
 183.559 +        dn, data = self.srv.get(filterstr, [name])
 183.560 +        name = find_in(name, data.keys())
 183.561 +        if name: # in data:
 183.562 +            return data[name]
 183.563 +        else:
 183.564 +            return []
 183.565 +    
 183.566 +    def get_members(self, name,  checkuid=True):
 183.567 +        """return members of a group"""
 183.568 +        g = self.get_group(name)
 183.569 +        return g.members
 183.570 +        
 183.571 +    def get_computers(self):
 183.572 +        """return members of ou=Computers"""
 183.573 +
 183.574 +        filterstr = "(&(gidNumber=515)(objectClass=posixAccount))"
 183.575 +        computers = self.srv.gets(filterstr, attrlist=['uid'])
 183.576 +        return computers
 183.577 +    
 183.578 +### del
 183.579 +    def del_computer(self, uid):
 183.580 +        """ delete a joined computer"""
 183.581 +        # i nomi delle macchine windows terminano con un $
 183.582 +        if uid[-1] != '$': uid += '$'
 183.583 +        dn = self.get_user_dn_by_name(uid)
 183.584 +        if dn:
 183.585 +            self.srv.delete(dn)
 183.586 +            if self.verbose:
 183.587 +                sys.stdout.write("%s DELETED\n" % (uid))
 183.588 +      
 183.589 +    def del_member_from_group(self, uid, group, quiet=True):
 183.590 +        """delete membership. Don't complain if user is not in the group
 183.591 +        unless quiet=False"""
 183.592 +        
 183.593 +        dn = self.get_group_dn_by_name(group)
 183.594 +        if self.srv.dry_run:
 183.595 +            return
 183.596 +        try:
 183.597 +            self.srv.conn.modify_s(dn, [(ldap.MOD_DELETE, 'memberUid', uid)])
 183.598 +        except ldap.NO_SUCH_ATTRIBUTE:
 183.599 +            if not quiet:
 183.600 +                raise
 183.601 +    
 183.602 +    def del_user(self, name, quiet=False):
 183.603 +        """delete a user, all its membership and the personal group.
 183.604 +        If quiet=True does not complain even if the user does not exists"""
 183.605 +
 183.606 +        try:
 183.607 +            user = self.get_user(name)
 183.608 +        except exc.MissingMatch, e:
 183.609 +            if quiet:
 183.610 +                return
 183.611 +            else:
 183.612 +                raise exc.MissingMatch("User %s does not exists" % name)
 183.613 +        
 183.614 +        ### delete the user
 183.615 +        user.delete(home_mode=self.home_mode)
 183.616 +        self.logger.info("Deleting user " + user.logname)
 183.617 +
 183.618 +    def del_group(self, name, quiet=False):
 183.619 +        """delete a group
 183.620 +        If quiet=True does not complain even if the group does not exists"""
 183.621 +
 183.622 +        try:
 183.623 +            group = self.get_group(name)
 183.624 +        except exc.MissingMatch, e:
 183.625 +            if not quiet:
 183.626 +                raise exc.MissingMatch("Group %s does not exists" % name)
 183.627 +            else:
 183.628 +                return
 183.629 +            
 183.630 +        ### delete the user
 183.631 +        group.delete()
 183.632 +        self.logger.info("Deleting group " + group.name)
 183.633 +
 183.634 +        
 183.635 +### add
 183.636 +    def add_user(self, name, maingroup, no_filesystem=False, force_passwd_change=False,
 183.637 +                 interactive=False, run_alulink=True, **kw):
 183.638 +        """add a user with all 'normal' defaults
 183.639 +        The groups[0], if it exists is the class and will be set to
 183.640 +        departmentNumber attribute. This is used to connect the class.
 183.641 +        Interactive indicates a user is listening and can decide to add
 183.642 +        the class.
 183.643 +        """
 183.644 +
 183.645 +        cls = self.add_classes(name, maingroup, interactive, kw['groups'])
 183.646 +        self.add_missing_groups(kw['groups'])
 183.647 +        user = models.PosixUser(self.pumpkin_conn)
 183.648 +        user.set_parent('ou=People,dc=isi,dc=lan')
 183.649 +        user.logname = name
 183.650 +        user.shell = '/bin/bash'
 183.651 +        self.user_configure(user, maingroup, no_filesystem, force_passwd_change,
 183.652 +                            run_alulink=run_alulink, mode='Adding', **kw)
 183.653 +
 183.654 +        user = self.get_samba_user(name)
 183.655 +        
 183.656 +        if run_alulink and user.classe:
 183.657 +            filesystem.create_alulink((user.classe,), self)
 183.658 +
 183.659 +        return user
 183.660 +
 183.661 +    def add_samba_staff(self, user, invalidate_cache=True):
 183.662 +
 183.663 +        if invalidate_cache:
 183.664 +            execute('nscd -i passwd')
 183.665 +        ret_code, out, err = execute('smbpasswd -a -n %s' % user)
 183.666 +        if ret_code:
 183.667 +            self.logger.debug('smbpasswd failed: OUT: %s - ERR: %s' % (out, err))
 183.668 +
 183.669 +            raise Exception("Sambapasswd problems: %s - OUT: %s" % (err, out))
 183.670 +        user = self.get_samba_user(user)
 183.671 +        if not user:
 183.672 +            raise Exception("Samba user not created")
 183.673 +        user.drive = u'H:'
 183.674 +        user.logon = u'logon.bat'
 183.675 +        if self.sambaHome:
 183.676 +            user.sambaHomePath = ur'\\%s\%s\\.\\.profili\\WinXP' % (self.sambaHome, name)
 183.677 +        user.flags = u"[U          ]"
 183.678 +        user.save()
 183.679 +        return user
 183.680 +
 183.681 +    def modify_user(self, name, maingroup, no_filesystem=True, force_passwd_change=False,
 183.682 +                    interactive=False, run_alulink=True, **kw):
 183.683 +        """ modifica un utente esistente """
 183.684 +
 183.685 +        user = self.get_samba_user(name)
 183.686 +
 183.687 +        new_cls = self.add_classes(name, maingroup, interactive, kw['groups'])
 183.688 +        user.classe = new_cls
 183.689 +        
 183.690 +        self.add_missing_groups(kw['groups'])
 183.691 +        self.user_configure(user,  maingroup, no_filesystem, force_passwd_change,
 183.692 +                            run_alulink=run_alulink, mode='Modifying', **kw)
 183.693 +        return user
 183.694 +
 183.695 +    def user_configure(self, user, maingroup, no_filesystem, force_passwd_change, mode='Adding', **kw):
 183.696 +        """Crea l'utente
 183.697 +        :param user:  a models.PosixUser or models.SambaUser object
 183.698 +        :param maingroup: the maingroup it must belog to
 183.699 +        :param no_filesystem: (boolean) indicates it the homedir must be prepared
 183.700 +        :param kw: a dict as prepared by UserParser.get_opts() with
 183.701 +        """
 183.702 +        if maingroup not in self.groups:
 183.703 +            try:
 183.704 +                group = self.get_group(maingroup)
 183.705 +            except exc.MissingMatch:
 183.706 +                raise exc.MissingMainGroup("Maingroup %s is not defined" % maingroup, maingroup, user)
 183.707 +            self.groups[maingroup] = group
 183.708 +
 183.709 +        user.gid = self.groups[maingroup].gid
 183.710 +
 183.711 +        for key in user.__base_data__ + user.__extended_data__:
 183.712 +            value = kw.get(key, None)
 183.713 +            # change value or set to None an existent value but don't set to None a non-existent
 183.714 +            if value or getattr(user, key):
 183.715 +                setattr(user, key, value)
 183.716 +                
 183.717 +
 183.718 +        user.full_name  = u"%s %s" % (kw['first_name'], kw['last_name'])
 183.719 +
 183.720 +        if not user.uid:  # it's  a new one
 183.721 +            user.uid = self.domain.get_next_uid()
 183.722 +
 183.723 +        homedir = u"%s/%s/%s" % (defaults.GROUPS_PATH, maingroup, user.logname)
 183.724 +        user.home = homedir
 183.725 +
 183.726 +        user.save()
 183.727 +        self.logger.info('%s user %s' %(mode, user.logname))
 183.728 +        samba_user = self.add_samba_staff(user)
 183.729 +        # gestione password
 183.730 +        samba_user.set_password(kw['passwd'], force_passwd_change)
 183.731 +
 183.732 +        if not no_filesystem and not os.path.exists(homedir):             
 183.733 +            filesystem.home_create(user, homedir)
 183.734 +
 183.735 +        user_groups = set([maingroup] + kw['groups'] + defaults.EXTRA_GROUPS)
 183.736 +        user.set_groups(user_groups, self.groups)
 183.737 +    
 183.738 +    def parse_user_definition_string(self, string, action=True, interactive=False, home_mode='tar', **kw):
 183.739 +
 183.740 +        """split the user definition string and call user creation functions
 183.741 +        the (compact) format is in 7 fields, logname,last name,first name and 
 183.742 +        maingroup being the only mandatory ones. 
 183.743 +        The fields are separated by ';' and secondary groups are separated by ','
 183.744 +
 183.745 +        :param action: boolean. Take the action
 183.746 +        :param no_filesystem: opts.no_filesystem,
 183.747 +        :param update_user: if the user exists must be updated,
 183.748 +        :param update_passwd: opts.update_passwd,
 183.749 +        :param home_mode: 'tar' if not opts.home_zap or 'rm',
 183.750 +        :param force_passwd_change: opts.force_change_passwd
 183.751 +
 183.752 +
 183.753 +        logname;last;name;maingrp;other_grp1,othergrp2...;CF;PASS;list_ext_flds
 183.754 +        
 183.755 +        list_ext_flds: sex;address;city;cap;prov;tel
 183.756 +        """
 183.757 +        self.home_mode = home_mode
 183.758 +
 183.759 +        proxy = UserParser(self, string, interactive=interactive, **kw )
 183.760 +
 183.761 +        if action:
 183.762 +            return self.proxy_action(proxy, interactive=interactive)
 183.763 +
 183.764 +        return proxy
 183.765 +
 183.766 +    def proxy_action(self, proxy, interactive=True):
 183.767 +        """
 183.768 +        act on user_proxy according to action in it
 183.769 +        """
 183.770 +
 183.771 +        if proxy.action == 'add':
 183.772 +            return self.add_user(proxy.logname, proxy.maingroup, **proxy.get_opts())
 183.773 +
 183.774 +        elif proxy.action == 'delete':
 183.775 +            self.del_user(proxy.logname)
 183.776 +
 183.777 +        else:
 183.778 +            return self.modify_user(proxy.logname, proxy.maingroup, **proxy.get_opts())
 183.779 +
 183.780 +    def add_group(self, group_name, gid=None, quiet=True, system=False, invalidate_cache=True):
 183.781 +        """add a group
 183.782 +
 183.783 +        :param group_name: the name of the group
 183.784 +        :param gid: use gid (default is to get the next free number from Domain
 183.785 +        :param quiet: don't complain if it already exists, just retun it
 183.786 +        :param system: add a system group, possibile with same gid as existent
 183.787 +        :param invalidate_cache: if True (default) nscd -i group is called
 183.788 +        """
 183.789 +
 183.790 +        if not group_name:
 183.791 +            raise WrongParameters("Missing group in add_group")
 183.792 +
 183.793 +        try:
 183.794 +            ## check if it alreay exists
 183.795 +            g = self.get_group(group_name)
 183.796 +
 183.797 +            if quiet:
 183.798 +                return g
 183.799 +            else:
 183.800 +                raise exc.AlreadyExistingGroup("Group %s already exists" % group_name, group_name) 
 183.801 +
 183.802 +        except exc.MissingMatch:
 183.803 +            pass
 183.804 +
 183.805 +        ## opt -a adds SID
 183.806 +        if system:
 183.807 +            ret_code, out, err = execute("getent group %s" % group_name)
 183.808 +            if out: # plugdev:x:46:sandro
 183.809 +                group_name, pwd, gid, members = out.split(':')
 183.810 +            else:
 183.811 +                for gid in xrange(120, 150):
 183.812 +                    try:
 183.813 +                        models.get_group_by_gid(gid, self.pumpkin_conn)
 183.814 +                    except Exception:
 183.815 +                        break
 183.816 +                    
 183.817 +        self.logger.info("Adding group %s" % group_name)
 183.818 +            
 183.819 +        g = models.PosixGroup(self.pumpkin_conn)
 183.820 +        g.set_parent('ou=Groups,dc=isi,dc=lan')
 183.821 +        g.gid = gid and int(gid) or self.domain.get_next_gid()
 183.822 +        g.name = group_name
 183.823 +        g.save()
 183.824 +        if invalidate_cache:
 183.825 +            execute('nscd -i group')
 183.826 +        return g
 183.827 +
 183.828 +### tools
 183.829 +    
 183.830 +    def check_and_add(self, classes, courses):
 183.831 +        """if a class/course is missing, prompt for a confirm and create it"""
 183.832 +    
 183.833 +        ## classes
 183.834 +        missing_classes = []
 183.835 +        for grp in classes.keys():
 183.836 +            if grp not in get_classes():
 183.837 +                missing_classes += [grp]
 183.838 +        if missing_classes:
 183.839 +            interactive_add_classes(missing_classes)
 183.840 +            
 183.841 +        ## courses
 183.842 +        missing_courses = []
 183.843 +        for grp in courses.keys():
 183.844 +            if grp not in get_courses():
 183.845 +                missing_courses += [grp]
 183.846 +        if missing_courses:
 183.847 +            interactive_add_classes(missing_courses, opt='course')
 183.848 +   
 183.849 +        
 183.850 +    def read_file(self, file_name, interactive=True, run_alulink=True, **kw):
 183.851 +        """
 183.852 +        read an '.isi' file and add/delete/modify the user accordingly to specs in it
 183.853 +
 183.854 +        :param file_name: can be a file name or a file handler
 183.855 +        :param run_alulink: (boolean) run/don't run isi-alulink
 183.856 +        :param interactive: (boolean) ask/don't ask confirmation to create classes
 183.857 +        :param home_mode: (rm|tar|none) how should homes be removed
 183.858 +        :param no_filesystem: (boolean) don't touch filesystem (used in tests, run faster)
 183.859 +
 183.860 +        """
 183.861 +        main_groups, other_groups, classes, courses = set(), set(), set(), set()
 183.862 +        users = [] 
 183.863 +
 183.864 +        f = open(file_name) if isinstance(file_name, basestring) else file_name
 183.865 +        for line in f:
 183.866 +
 183.867 +            user_proxy = self.parse_user_definition_string(line, action=False,
 183.868 +                                                           run_alulink=False, **kw)
 183.869 +            users += [user_proxy]
 183.870 +
 183.871 +            if not user_proxy.action == 'delete':
 183.872 +                main_groups.add(user_proxy.maingroup)
 183.873 +                other_groups.update(set(user_proxy.groups))
 183.874 +
 183.875 +                if user_proxy.classe:
 183.876 +
 183.877 +                    if user_proxy.maingroup == 'alunni': # this is a class
 183.878 +                        classes.add(user_proxy.classe)
 183.879 +
 183.880 +                    elif user_proxy.maingroup == 'esterni':
 183.881 +                        courses.add(user_proxy.classe)
 183.882 +
 183.883 +
 183.884 +        wrong_groups  = main_groups.difference( set(get_main_groups()))
 183.885 +        if wrong_groups:
 183.886 +            raise exc.MissingMainGroup("Group not present in maingroups: %s" % wrong_groups, None, None)
 183.887 +
 183.888 +        self.add_missing_groups( other_groups )
 183.889 +        add_class_share(classes, course=False, interactive=interactive)
 183.890 +        add_class_share(courses, course=True,  interactive=interactive)
 183.891 +
 183.892 +        for proxy in users:
 183.893 +            try:
 183.894 +                self.proxy_action(proxy, interactive=False)
 183.895 +            except exc.MissingMatch, e:
 183.896 +                self.logger.warning(e)
 183.897 +
 183.898 +        if run_alulink:
 183.899 +            self.logger.info('Starting alulink for %s' % ','.join(list(classes.union(courses))))
 183.900 +            for cls in classes.union(courses):
 183.901 +                filesystem.create_alulink(classes, self)
 183.902 +        return len(users)
 183.903 +
 183.904 +    def check_file(self, file_name):
 183.905 +        """
 183.906 +        returna tuple of three lists of user to be added, deleted and modified according to
 183.907 +        content of file_name
 183.908 +
 183.909 +        :param file_name: a file in .isi format
 183.910 +        """
 183.911 +
 183.912 +        add, delete, modify = [], [], []
 183.913 +        users = [] 
 183.914 +
 183.915 +        f = open(file_name) if isinstance(file_name, basestring) else file_name
 183.916 +        for line in f:
 183.917 +
 183.918 +            user_proxy = self.parse_user_definition_string(line, action=False,)
 183.919 +                                                           
 183.920 +            if user_proxy.action == 'update':
 183.921 +                modify += [user_proxy]
 183.922 +
 183.923 +            elif user_proxy.action == 'delete':
 183.924 +                delete += [user_proxy]
 183.925 +
 183.926 +            elif user_proxy.action == 'add':
 183.927 +                add += [user_proxy]
 183.928 +                
 183.929 +        return add, delete, modify
 183.930 +    
 183.931 +    def pwd_must_change(self, name, gg=0):
 183.932 +        """ forza il rinnovo password per i membri di un gruppo 
 183.933 +        se gg > 0 fissa la data di scadenza a mktime()+gg
 183.934 +        """
 183.935 +        group = self.get_group(name)
 183.936 +        
 183.937 +        if gg:
 183.938 +            ggs = str(int(mktime(localtime()))+24*3600*gg)
 183.939 +        else:
 183.940 +            ggs = '0'
 183.941 +
 183.942 +        for uid in group.members:
 183.943 +            if self.verbose:
 183.944 +                print "elaboro %s" % uid
 183.945 +            if self.sambavers > "3.0.24":
 183.946 +                self.srv.modify(uid,'sambaPwdLastSet',ggs)
 183.947 +            else:
 183.948 +                self.srv.modify(uid,'sambaPwdMustChange',ggs)
 183.949 +
 183.950 +    def pwd_can_change(self, gruppo,  gg=-7):
 183.951 +        """ stabilisce da quando i membri del gruppo possono cambiare password """
 183.952 +        uu = self.get_members(gruppo)
 183.953 +        ggs = str(int(mktime(localtime()))+24*3600*gg)
 183.954 +        if uu:
 183.955 +            for uid in uu:
 183.956 +                if self.verbose:
 183.957 +                    print "elaboro %s" % uid
 183.958 +                self.srv.modify(uid,'sambaPwdCanChange',ggs)
 183.959 +                self.srv.modify(uid,'sambaPwdLastSet',ggs)
 183.960 +        else:
 183.961 +            raise exc.MissingOrVoidGroup
 183.962 +
 183.963 +    def pwd_when(self, gruppo, outf=None):
 183.964 +        """ date delle passwords """
 183.965 +        
 183.966 +        def print_msg(msg):
 183.967 +            if outf:
 183.968 +                outf.write(msg+'\n')
 183.969 +            else:
 183.970 +                print msg
 183.971 +        
 183.972 +        # legge le policies di dominio
 183.973 +        plist = self.srv.get_pwd_domain_policies()        
 183.974 +        
 183.975 +        uu = self.get_members(gruppo)
 183.976 +        if uu:
 183.977 +            print_msg('-'*75)
 183.978 +            print "POLITICHE DI DOMINIO"
 183.979 +            for k, v in plist.iteritems():
 183.980 +                print "%25s = %s" % (k, v)
 183.981 +#            print plist
 183.982 +            print_msg('-'*75)
 183.983 +            print_msg("%-15s %-15s %s %s" % 
 183.984 +                      ('UserId', 
 183.985 +                      'PwdLastSet', 
 183.986 +                      'PwdExpiration [days]',
 183.987 +                      'PwdCanChange'))
 183.988 +            print_msg('-'*75)
 183.989 +            for uid in uu:
 183.990 +                x1 = float(self.get_attr(uid, 'sambaPwdLastSet')[0])
 183.991 +                lsd = strftime('%Y-%m-%d',localtime(x1))
 183.992 +                
 183.993 +                if self.sambavers > "3.0.24":
 183.994 +                    if plist['sambaMaxPwdAge'] == -1:
 183.995 +                        x2 = 0
 183.996 +                    else:
 183.997 +                        x2 = x1 + plist['sambaMaxPwdAge']
 183.998 +                else:
 183.999 +                    x2 = float(self.get_attr(uid, 'sambaPwdMustChange')[0])
183.1000 +                
183.1001 +                x3 = float(self.get_attr(uid, 'sambaPwdCanChange')[0])
183.1002 +                if x2 > x1:
183.1003 +                    try:
183.1004 +                        exd = strftime('%Y-%m-%d',localtime(x2))
183.1005 +                        exg = "[%s]" % str(int((x2-x1)/3600/24))
183.1006 +                    except:
183.1007 +                        exd = "Never expire"
183.1008 +                        exg = ''
183.1009 +                else:
183.1010 +                    exg = ''
183.1011 +                    if self.sambavers > "3.0.24":
183.1012 +                        if plist['sambaMaxPwdAge'] == -1:
183.1013 +                            if x1>x2:
183.1014 +                                exd = "Never expire"
183.1015 +                            else:
183.1016 +                                exd = "Expired"
183.1017 +                            
183.1018 +                        else:    
183.1019 +                            exd = strftime('%Y-%m-%d',localtime(x2))
183.1020 +                    else:
183.1021 +                        exd = 'Expired'
183.1022 +                cch = strftime('%Y-%m-%d',localtime(x3))
183.1023 +                print_msg("%-15s %-15s %-10s %-10s %s" % 
183.1024 +                          (uid, lsd, exd, exg, cch))
183.1025 +        else:
183.1026 +            raise esc.MissingOrVoidGroup
183.1027 +
183.1028 +            
183.1029 +    def rename_user(self, old_uid, new_uid, cf):
183.1030 +        """ modifica il logname e quel che ne consegue """
183.1031 +        
183.1032 +        if self.user_exists(new_uid):
183.1033 +            raise exc.DuplicateUid('ERRORE: %s duplicato!!!' % new_uid) 
183.1034 +        
183.1035 +        if self.user_exists(old_uid):
183.1036 +            old_home = self.get_home(old_uid)
183.1037 +            old_dati = self.get_ldap_data(old_uid, ['cn','sn'])
183.1038 +            cn = old_dati['cn'][0]
183.1039 +            sn = old_dati['sn'][0]
183.1040 +            new_home = "%s/%s" % (os.path.dirname(old_home), new_uid)
183.1041 +            groups = self.get_user_groups(old_uid)
183.1042 +            if self.verbose:
183.1043 +                print "elaboro %s -> %s %s %s" % (old_uid,new_uid, new_home, cf)
183.1044 +            
183.1045 +            cmd = ['smbldap-usermod']
183.1046 +            
183.1047 +            cmd += ['-r', new_uid]
183.1048 +            cmd += ['-d', new_home]
183.1049 +            cmd += ['-G', ",".join(groups)]  
183.1050 +            
183.1051 +#            cmd += ['-N', cn ]  # cn
183.1052 +#            cmd += ['-S', sn ]   # sn
183.1053 +
183.1054 +            # FIXME: sambaHomePath con doppia 
183.1055 +#            if self.sambaHome:
183.1056 +#                cmd += ['-C',r'\\%s\%s\\.\\.profili\\WinXP'%(self.sambaHome,user)]
183.1057 +#                cmd+= ['-F', r'\\%s\%s\\.profili\\WinXP' % (self.sambaHome,user)]
183.1058 +
183.1059 +            cmd += [old_uid]
183.1060 +            ret_code, out, err = execute(cmd)
183.1061 +            if ret_code:
183.1062 +                raise ExecuteError("OUT: %s\nERR: %s" % (out, err))
183.1063 +            # smbldap-usermod non sembra modificare correttamente sn e cn in abbinamento all'opzione -r
183.1064 +    
183.1065 +            self.srv.modify(new_uid, 'cn', cn)
183.1066 +            self.srv.modify(new_uid, 'sn', sn)
183.1067 +            # rinomino home dir 
183.1068 +            os.rename(old_home, new_home)
183.1069 +            # cambio cf, se cf='' viene cancellato, se cf=None resta inalterato
183.1070 +            if not cf is None:
183.1071 +                self.srv.modify(new_uid, 'employeeNumber', cf)
183.1072 +
183.1073 +
183.1074 +### Definizione funzioni ###
183.1075 +
183.1076 +def find_parm_value(conf_file, parm):
183.1077 +    """trova il valore di un parametro in un file di conf or None"""
183.1078 +    content = open(conf_file).read()
183.1079 +    pat = '(.*%s.*?)=\s*"*\s*(.*)\s*"' % parm
183.1080 +    ret = re.search(pat, content)
183.1081 +    if ret:
183.1082 +        return ret.group(2)
183.1083 +    else:
183.1084 +        return None
183.1085 +
183.1086 +def find_in(x, ylist):
183.1087 +    ret = None
183.1088 +    for y in ylist:
183.1089 +        if x.lower() == y.lower():
183.1090 +            ret = y
183.1091 +            break
183.1092 +    return ret
183.1093 +
183.1094 +def get_main_groups():
183.1095 +    """
183.1096 +    return official list of maingroups, now os.listdir('/home/users')
183.1097 +    after performing a group existence check.
183.1098 +    """
183.1099 +
183.1100 +    srv = IsiConn(dn="", passwd="")
183.1101 +    isi_user = Manager(srv)
183.1102 +
183.1103 +    groups_list_raw = os.listdir(defaults.GROUPS_PATH)
183.1104 +    groups_list = [g for g in groups_list_raw if isi_user.group_exists(g) ]
183.1105 +
183.1106 +    return groups_list
183.1107 +
183.1108 +def get_classes(as_groups=False):
183.1109 +    """
183.1110 +    return official list of classes, now os.listdir('/home/shares/classi')
183.1111 +    after performing a group existence check.
183.1112 +    """
183.1113 +    srv = IsiConn(dn="", passwd="")    
183.1114 +    l = Manager(srv)
183.1115 +
183.1116 +    classes_list_raw = os.listdir(defaults.CLASSES_PATH)
183.1117 +    if as_groups:
183.1118 +        classes_list = [l.get_group(g) for g in classes_list_raw if l.group_exists(g) ]
183.1119 +    else:
183.1120 +        classes_list = [g for g in classes_list_raw if l.group_exists(g) ]
183.1121 +
183.1122 +    return classes_list
183.1123 +
183.1124 +
183.1125 +def get_courses():
183.1126 +    """
183.1127 +    return official list of courses, now os.listdir('/home/shares/courses')
183.1128 +    after performing a group existence check.
183.1129 +    """
183.1130 +
183.1131 +    srv = IsiConn(dn="", passwd="")
183.1132 +    isi_user = Manager(srv)
183.1133 +
183.1134 +    courses_list_raw = os.listdir(defaults.COURSES_PATH)
183.1135 +    courses_list = [g for g in courses_list_raw if isi_user.group_exists(g) ]
183.1136 +
183.1137 +    return courses_list
183.1138 +
183.1139 +def add_class_share(classes, course=False, interactive=True):
183.1140 +    """
183.1141 +    add classes if user confirms
183.1142 +
183.1143 +    :param course: boolean. Add a course not a class
183.1144 +    """
183.1145 +    logger = get_logger(web=True)
183.1146 +
183.1147 +    if course:
183.1148 +        CLASSES = get_courses()
183.1149 +    else:
183.1150 +        CLASSES = get_classes()
183.1151 +
183.1152 +    missing_classes = set(classes).difference(set(CLASSES))
183.1153 +    
183.1154 +    if missing_classes and interactive:
183.1155 +        msg = "Queste classi non sono definite:\n   %s\ndevo definirle? [S/n]\n"
183.1156 +        response = raw_input(msg % " ".join(list(missing_classes)))
183.1157 +        if response and response in 'nN':
183.1158 +            sys.stderr.write("Non aggiungo utenti in classi inesistenti. Esco\n")
183.1159 +            return False
183.1160 +
183.1161 +    if missing_classes:
183.1162 +        logger.info("Aggiungo le classi mancanti: %s" % missing_classes)
183.1163 +
183.1164 +    for cl in missing_classes:
183.1165 +        logger.info('Aggiungo classe: ' + cl)
183.1166 +        filesystem.create_class(cl, course=course, samba_reload=False, manager=None)
183.1167 +
183.1168 +    if missing_classes:
183.1169 +        execute('/etc/init.d/samba reload')
183.1170 +
183.1171 +def maingroup_byprefix(logname):
183.1172 +    '''cerca di determinare il maingroup dal logname'''
183.1173 +    #FIXME:la clausola or .... è dovuta a una mia necessità specifica
183.1174 +    main_group = ''
183.1175 +    if logname.startswith('a_') or logname.startswith('aa'):
183.1176 +        main_group = 'alunni' 
183.1177 +    if logname.startswith('e_') or logname.startswith('ee'):
183.1178 +        main_group = 'esterni' 
183.1179 +    if logname.startswith('d_') or logname.startswith('dd'):
183.1180 +        main_group = 'docenti' 
183.1181 +    if logname.startswith('ad_') or logname.startswith('ad'):
183.1182 +        main_group = 'admins' 
183.1183 +    return main_group
183.1184 +
183.1185 +
   184.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.2 +++ b/lib/isi/test.py	Mon Apr 26 11:16:23 2010 +0200
   184.3 @@ -0,0 +1,58 @@
   184.4 +import functions
   184.5 +import subprocess
   184.6 +import StringIO
   184.7 +
   184.8 +class InputStream(object):
   184.9 +    """ Simple Wrapper for File-like objects. [c]StringIO doesn't provide
  184.10 +        a readline function for use with generate_tokens.
  184.11 +        Using a iterator-like interface doesn't succeed, because the readline
  184.12 +        function isn't used in such a context. (see <python-lib>/tokenize.py)
  184.13 +    """
  184.14 +    def __init__(self, data):
  184.15 +        self.__data = [ '%s\n' % x for x in data.splitlines() ]
  184.16 +        self.__lcount = 0
  184.17 +        
  184.18 +    def readline(self):
  184.19 +        try:
  184.20 +            line = self.__data[self.__lcount]
  184.21 +            self.__lcount += 1
  184.22 +        except IndexError:
  184.23 +            line = ''
  184.24 +            self.__lcount = 0
  184.25 +        return line
  184.26 +    
  184.27 +    def fileno(self):
  184.28 +        return self.__lcount
  184.29 +
  184.30 +cmd = ['/home/sandro/sd/sandro_echo']
  184.31 +#cmd = ['sort']
  184.32 +def set_password(user, password):
  184.33 +    """set password fo user"""
  184.34 +
  184.35 +#p1 = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell='/bin/bash')
  184.36 +
  184.37 +    #Input = InputStream('%s\n%s' % (password, password))
  184.38 +    #Input = StringIO.StringIO('%s\n%s' % (password, password))
  184.39 +
  184.40 +    #p = subprocess.Popen(..., stdin=subprocess.PIPE)
  184.41 +    #p.stdin.write('%s\n%s' % (password, password))
  184.42 +    #p.stdin.close() # signal end of file
  184.43 +
  184.44 +    PWD = '<%s\na%s' % (password, password)
  184.45 +    #PWD = InputStream('%s\n%s' % (password, password))
  184.46 +    ret_code, out, err = functions.execute(cmd, stdin=PWD )
  184.47 +    return "OUTPUT: %s" % out
  184.48 +
  184.49 +
  184.50 +print set_password('abc', 'xyz')
  184.51 +
  184.52 +#p = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE)
  184.53 +#print p.communicate(input='uno\ndue\n')
  184.54 +
  184.55 +#p.stdin.write('uno\ndue\n')
  184.56 +#p.stdin.close()
  184.57 +#p.wait()
  184.58 +
  184.59 +
  184.60 +#print p.communicate()
  184.61 +
   185.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.2 +++ b/lib/isi/tests/runtest.py	Mon Apr 26 11:16:23 2010 +0200
   185.3 @@ -0,0 +1,16 @@
   185.4 +#!/usr/bin/env python
   185.5 +
   185.6 +import sys
   185.7 +import doctest
   185.8 +
   185.9 +sys.path.insert(0, "../../")
  185.10 +
  185.11 +files = (
  185.12 +    'srv.txt',
  185.13 +    'user.txt',
  185.14 +    )
  185.15 +for filename in files:
  185.16 +    doctest.testfile(filename)
  185.17 +
  185.18 +    
  185.19 +
   186.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.2 +++ b/lib/isi/tests/srv.txt	Mon Apr 26 11:16:23 2010 +0200
   186.3 @@ -0,0 +1,21 @@
   186.4 +# -*- mode: python  -*-
   186.5 +
   186.6 +This doctest only works if slapd is already working
   186.7 +
   186.8 +>>> from isi import IsiConn
   186.9 +>>> c = IsiConn()
  186.10 +>>> c.get_rootdn()
  186.11 +'cn=admin,dc=saraceno,dc=lan'
  186.12 +>>> c.get('cn=admin')[0]
  186.13 +'cn=admin,dc=saraceno,dc=lan'
  186.14 +
  186.15 +## simple way to check hat no more than one domain is defined:
  186.16 +## useless
  186.17 +>>> len(c.get("objectClass=sambaDomain"))
  186.18 +2
  186.19 +
  186.20 +>>> c.backup()
  186.21 +>>>
  186.22 +
  186.23 +
  186.24 +
   187.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   187.2 +++ b/lib/isi/tests/user.txt	Mon Apr 26 11:16:23 2010 +0200
   187.3 @@ -0,0 +1,38 @@
   187.4 +# -*- mode: python  -*-
   187.5 +
   187.6 +This doctest only works if slapd is already working
   187.7 +
   187.8 +>>> from isi import IsiConn, IsiUser
   187.9 +>>> c = IsiConn()
  187.10 +>>> l = IsiUser(c)
  187.11 +
  187.12 +    #print l.get_domain()
  187.13 +    #print l.get_group_dn_by_name('geo1a')
  187.14 +    #u, g  = ('a_spnclr93l50', 'geo1a')
  187.15 +    #print "%s is in group %s: %s" % (u, g, l.user_in_group(u, g))
  187.16 +
  187.17 +    #u, g  = ('aspnclr93l50', 'geo1a')
  187.18 +    #print "%s is in group %s: %s" % (u, g, l.user_in_group(u, g))
  187.19 +    #print l.get_user_dn_by_name(u)
  187.20 +    #print l.get_home(u)
  187.21 +    #u = 'a_dlcsfn92s05'
  187.22 +    #u = 
  187.23 +    #l.del_member_from_group(u, g)
  187.24 +    #print l.get_user_dn_by_name('a_cllfba93m07')
  187.25 +    #l.del_user('a_cllfba93m07', quiet=True)
  187.26 +    g = 'c4c1'
  187.27 +    print "alunni: %s, %s: %s" % (len(l.get_members('alunni')), g,
  187.28 +                                  len(l.get_members(g)))
  187.29 +    #print l.get_members(g)
  187.30 +    #l.del_users_of_group('alunni')
  187.31 +    #print l.get_members(g)
  187.32 +    #print l.get_attr('admancini', 'homeDirectory')[0]
  187.33 +    #print l.get_home('admancini')
  187.34 +    #l.del_user('admancini', quiet=True)
  187.35 +    #l.srv.backup()
  187.36 +    #l.del_users_of_group('alunni')
  187.37 +    #l.eliminate_member_from_group('a_spnclr93l50', 'geo1a')
  187.38 +    #u = 'a_trnlcu93h23'
  187.39 +    #print l.get_user_groups(u)
  187.40 +    #for i in l.get_members('geo1a'):
  187.41 +    #    l.user_in_group(i, 'geo1a')
   188.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.2 +++ b/setup.py	Mon Apr 26 11:16:23 2010 +0200
   188.3 @@ -0,0 +1,20 @@
   188.4 +#!/usr/bin/env python
   188.5 +
   188.6 +
   188.7 +from setuptools import setup, find_packages
   188.8 +import os
   188.9 +#from distutils.core import setup, find_packages
  188.10 +
  188.11 +setup(name='isi',
  188.12 +      version='0.2.4',
  188.13 +      description='Python module for reteisi',
  188.14 +      author='Alessandro Dentella',
  188.15 +      author_email='[email protected]',
  188.16 +      url='http://www.e-den.it/',
  188.17 +      package_dir={'':'lib'},
  188.18 +#     packages=find_packages('lib', exclude=['ez_setup', 'examples', 'tests']),
  188.19 +      packages=find_packages('lib', exclude='isi.egg-info'),
  188.20 +#      scripts=['bin/' + s for s in os.listdir('bin')]
  188.21 +      zip_safe=False,
  188.22 +     )
  188.23 +
   189.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.2 +++ b/tests/README	Mon Apr 26 11:16:23 2010 +0200
   189.3 @@ -0,0 +1,45 @@
   189.4 +Tests
   189.5 +=====
   189.6 +
   189.7 +
   189.8 +Questa cartella contiene alcuni test di verifica del corretto funzionamento
   189.9 +della libreria. Sono in due formati differenti:
  189.10 +
  189.11 +  * doctest
  189.12 +  * nosetests
  189.13 +
  189.14 +i doctest possono essere lanciati da qualunque macchina che abbia installato
  189.15 +python e dalla cartella stessa dei test con il comando: ./runtests.py
  189.16 +
  189.17 +I nosetest devono essere lanciati nella macchina virtuale. Nella loro
  189.18 +esecuzione cancellano e creano utenti, eliminano cartelle e fanno altre
  189.19 +operazioni che su un server reale creerebbero grossi scompensi.
  189.20 +
  189.21 +Copia dell'ultima versione
  189.22 +==========================
  189.23 +
  189.24 +Il filesystem netkit ha una versione dei pacchetti isi non costantemente
  189.25 +aggiornata. Per eseguire i test è necessario aggiornare:
  189.26 +
  189.27 +  * la libreria python isi
  189.28 +  * gli eseguibili isi-*
  189.29 +  * creare una cartella con i test in /tmp/
  189.30 +
  189.31 +Tutto questo può esere fatto con questi comandi::
  189.32 +
  189.33 +  rsync -a lib/isi [email protected]:/var/lib/python-support/python2.5/
  189.34 +  rsync -a usr/sbin [email protected]:/usr/
  189.35 +  rsync -a tests [email protected]:/tmp
  189.36 +
  189.37 +Ovviamente è suggeribile aggiornare all'ultima versione di sorgente
  189.38 +
  189.39 +
  189.40 +Lanciare i test
  189.41 +===============
  189.42 +
  189.43 +cd /tmp/tests
  189.44 +nosetests -v
  189.45 +
  189.46 +
  189.47 +
  189.48 +
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/tests/convert_test.py	Mon Apr 26 11:16:23 2010 +0200
   190.3 @@ -0,0 +1,195 @@
   190.4 +import os
   190.5 +import re
   190.6 +import isi
   190.7 +import glob
   190.8 +import datetime
   190.9 +import unittest
  190.10 +from dry.functions import execute
  190.11 +from nose import tools
  190.12 +import shutil
  190.13 +from isi import bulk_users
  190.14 +import logging
  190.15 +
  190.16 +
  190.17 +l = isi.Manager()
  190.18 +#l.logger.setLevel(logging.critical)
  190.19 +class Res: pass
  190.20 +res = Res()
  190.21 +
  190.22 +def setup():
  190.23 +    print "killing nscd"
  190.24 +    execute('killall nscd')
  190.25 +    execute('rm -Rf /home/users/alunni/*')
  190.26 +    execute('cp data/convert/sissi-tabcorsi /etc/isi')
  190.27 +    crea_classe('geo3a')
  190.28 +    crea_classe('ige3a')
  190.29 +    crea_classe('pro3a')
  190.30 +    
  190.31 +def crea_classe(classe):
  190.32 +    l.add_group(classe, quiet=True)
  190.33 +    path = '/home/shares/classi/%s' % classe
  190.34 +    if not os.path.exists(path):
  190.35 +        os.mkdir(path)
  190.36 +
  190.37 +class BulkUsers(unittest.TestCase):
  190.38 +
  190.39 +    def execute(self, cmd):
  190.40 +        ret_code, out, err = execute(cmd)
  190.41 +        assert ret_code == 0, "ret_code: %s: OUT=%s, ERR=%s" % (ret_code, out, err)
  190.42 +        return out, err
  190.43 +        
  190.44 +    def diff(self, this, other, ):
  190.45 +        """return a diff between self and other"""
  190.46 +
  190.47 +        import difflib
  190.48 +        diff = []
  190.49 +        
  190.50 +        for line in difflib.unified_diff([l for l in open(this).readlines()],
  190.51 +                                         [l for l in open(other).readlines()],
  190.52 +                                         this, other):
  190.53 +            diff += [line]
  190.54 +        return "".join(diff)
  190.55 +
  190.56 +    def are_files_equal(self, f1, f2):
  190.57 +        assert self.diff(f1, f2) == '', self.diff(f1, f2)
  190.58 +        
  190.59 +    def del_classe(self, classe):
  190.60 +        l.del_group(classe)
  190.61 +        execute('rm -Fr /home/shares/classi/%s' % classe)
  190.62 +        
  190.63 +    def prepare_01(self):
  190.64 +        for f in glob.glob('/root/users-*'):
  190.65 +            os.remove(f)
  190.66 +        l.get_group('alunni').delete_members(home_mode='rm')
  190.67 +
  190.68 +    ## Anno 0
  190.69 +    ## generazione FORMATO STANDARD
  190.70 +    def test_01a_alunni_anno0_std(self):
  190.71 +        self.prepare_01()
  190.72 +        res.b1 = bulk_users.BulkUsers('alunni', user_format='cf')
  190.73 +        res.b1.read_file('data/convert/sissi-0.csv', file_format='sissi')
  190.74 +
  190.75 +    def test_01b_col_map(self):
  190.76 +        assert bulk_users.SissiUser.cols['Corso'] == 2, 'Corso = %' % bulk_users.SissiUser.cols['Corso']
  190.77 +
  190.78 +    # esiste output
  190.79 +    def test_01b_generate_output(self):
  190.80 +        res.b1.as_isi(filename='/root/users-0-std.isi')
  190.81 +        assert os.path.exists('/root/users-0-std.isi')
  190.82 +        
  190.83 +    # e' corretto
  190.84 +    def test_01c_alunni_anno0_std(self):
  190.85 +        f1 = '/root/users-0-std.isi'
  190.86 +        f2 = 'data/convert/users-0-std.isi'
  190.87 +        self.are_files_equal(f1, f2)
  190.88 +        
  190.89 +    # FORMATO ESTESO
  190.90 +    def test_01d_alunni_anno0_std(self):
  190.91 +        res.b1.as_isi(filename='/root/users-0-extended.isi', extended=True)
  190.92 +        assert os.path.exists('/root/users-0-extended.isi')
  190.93 +        
  190.94 +    # e' corretto
  190.95 +    def test_01e_alunni_anno0_std_users_upd(self):
  190.96 +        f1 = '/root/users-0-extended.isi'
  190.97 +        f2 = 'data/convert/users-0-extended.isi'
  190.98 +        self.are_files_equal(f1, f2)
  190.99 +
 190.100 +    def test_01f_alunni_anno0_renamed(self):
 190.101 +        assert not res.b1.renamed
 190.102 +        
 190.103 +    def test_01g_alunni_anno0_deleted(self):
 190.104 +        assert not res.b1.get_users_to_be_removed()
 190.105 +
 190.106 +    ## logname con nome
 190.107 +    def test_01h_alunni_anno0_std(self):
 190.108 +        res.b1.user_format = 'name'
 190.109 +        res.b1.read_file('data/convert/sissi-0.csv', file_format='sissi')
 190.110 +        res.b1.as_isi(filename='/root/users-0-names.isi')
 190.111 +        assert os.path.exists('/root/users-0-names.isi')
 190.112 +        
 190.113 +    # e' corretto
 190.114 +    def test_01i_alunni_anno0_std_users_upd(self):
 190.115 +        f1 = '/root/users-0-names.isi'
 190.116 +        f2 = 'data/convert/users-0-names.isi'
 190.117 +        self.are_files_equal(f1, f2)
 190.118 +
 190.119 +    ## logname con nome - collisioni
 190.120 +    def test_01l_alunni_anno0_collisioni(self):
 190.121 +        res.b1 = bulk_users.BulkUsers('alunni', user_format='cf')
 190.122 +        res.b1.user_format = 'name'
 190.123 +        res.b1.read_file('data/convert/sissi-0-collisioni.csv', file_format='sissi')
 190.124 +        res.b1.as_isi(filename='/root/users-0-collisioni.isi')
 190.125 +        assert os.path.exists('/root/users-0-names.isi')
 190.126 +        
 190.127 +    # e' corretto
 190.128 +    def test_01m_alunni_anno0_std_users_upd(self):
 190.129 +        f1 = '/root/users-0-collisioni.isi'
 190.130 +        f2 = 'data/convert/users-0-collisioni.isi'
 190.131 +        self.are_files_equal(f1, f2)
 190.132 +
 190.133 +    
 190.134 +    ## da file .xls
 190.135 +    def test_01n_xls(self):
 190.136 +        xls = bulk_users.BulkUsers('alunni', user_format='cf')
 190.137 +        xls.read_file('data/convert/sissi-0.xls', file_format='sissi')
 190.138 +        assert len(xls.file_users) == 8
 190.139 +
 190.140 +    ## missing columns xls
 190.141 +    def test_01o_alunni_anno0_collisioni(self):
 190.142 +        res.b1 = bulk_users.BulkUsers('alunni', user_format='name')
 190.143 +        res.b1.user_format = 'name'
 190.144 +        res.b1.read_file('data/convert/sissi-0-col-select.xls', file_format='sissi')
 190.145 +        res.b1.as_isi(filename='/root/users-0-names-cols.isi')
 190.146 +        assert os.path.exists('/root/users-0-names-cols.isi')
 190.147 +        
 190.148 +    def test_01p_alunni_anno0_std_users_upd(self):
 190.149 +        f1 = '/root/users-0-names-cols.isi'
 190.150 +        f2 = 'data/convert/users-0-names.isi'
 190.151 +        self.are_files_equal(f1, f2)
 190.152 +
 190.153 +    def test_01q_alunni_anno0_collisioni(self):
 190.154 +        res.b1 = bulk_users.BulkUsers('alunni', user_format='id-name')
 190.155 +        res.b1.read_file('data/convert/sissi-0.csv', file_format='sissi')
 190.156 +        res.b1.as_isi(filename='/root/users-0-idnames.isi')
 190.157 +        assert os.path.exists('/root/users-0-idnames.isi')
 190.158 +        
 190.159 +    def test_01r_alunni_anno0_std_users_upd(self):
 190.160 +        f1 = '/root/users-0-idnames.isi'
 190.161 +        f2 = 'data/convert/users-0-idnames.isi'
 190.162 +        self.are_files_equal(f1, f2)
 190.163 +
 190.164 +    ## ANNO 1
 190.165 +    # genera alunni anno 0 con nomi (per avere collisioni)
 190.166 +    def prepara_02(self):
 190.167 +        l.get_group('alunni').delete_members()
 190.168 +        l.read_file('data/convert/users-0-names.isi', run_alulink=False, 
 190.169 +                    no_filesystem=True, interactive=False, default_passwd='PASSWORD')
 190.170 +
 190.171 +    def test_02a_alunni_anno1(self):
 190.172 +        self.prepara_02()
 190.173 +        # genera un db ldap da anno0
 190.174 +        res.b2 = bulk_users.BulkUsers('alunni', user_format='name')
 190.175 +        res.b2.read_file('data/convert/sissi-1.csv', file_format='sissi')
 190.176 +        
 190.177 +    # crea output standard
 190.178 +    def test_02b_alunni_standard(self):
 190.179 +        res.b2.as_isi('/root/users-1-names.isi')
 190.180 +        assert os.path.exists('/root/users-1-names.isi')
 190.181 +
 190.182 +    def test_02c_removed(self):
 190.183 +        assert res.b2.get_users_to_be_removed()
 190.184 +        delenda = list(res.b2.get_users_to_be_removed())[0]
 190.185 +        assert res.b2.users_dict[delenda.logname].cf == 'CRBMHL94A58I829C'
 190.186 +
 190.187 +    def test_02d_renamed(self):
 190.188 +        renamed = list(res.b2.renamed)[0]
 190.189 +        assert renamed.logname == 'michela.carboni02'
 190.190 +        assert renamed.cf == 'CRBLCU95E23A821X'
 190.191 +
 190.192 +    # e' corretto
 190.193 +    def test_02h_alunni_anno1_users(self):
 190.194 +        f1 = '/root/users-1-names.isi'
 190.195 +        f2 = 'data/convert/users-1-names.isi'
 190.196 +        self.are_files_equal(f1, f2)
 190.197 +            
 190.198 +        
   191.1 Binary file tests/data/convert/sissi-0-col-select.xls has changed
   192.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   192.2 +++ b/tests/data/convert/sissi-0-collisioni.csv	Mon Apr 26 11:16:23 2010 +0200
   192.3 @@ -0,0 +1,9 @@
   192.4 +Anno di corso;Sezione;Corso;Cognome;Nome;Data di nascita;Sesso;Comune di nascita;Prov. Nascita;Codice fiscale;Indirizzo;Comune di residenza;CAP;Prov. Residenza;Telefono 1;Telefono 2;Cognome padre;Nome padre;Cognome madre;Nome madre;Anno Sc.
   192.5 +3;A;PROGETTO CINQUE;CARBONI;LUCA;08/02/1992;M;MILANO;MI;CRBLCU95E23A829H;VIA GARIBALDI, 60;COLICO;23823;LC;0341/123456;;ACQUISTINI;GERVASO;ALIPRANDI;MARISA;2009
   192.6 +3;A;Indirizzo Giuridico Economico Aziendale;BERTOLDI;GIULIA;03/02/1993;F;MORBEGNO;SO;BRTGLI93B43F712B;VIA ROMA 103;TRAONA;23013;SO;0342/123456;888 123456; m;BERTOLDI;MARIO;GIGIONELLI;ANTONIA;2009
   192.7 +3;A;PROGETTO CINQUE;ANTONI;LUCIA;29/02/1991;F;MORBEGNO;SO;ANTLCU91B69F712X;VIA BRIGLIA, 150/A;MORBEGNO;23017;SO;0342/123456;;ANTONI;ALBERTO;MANNOIA;ZOE;2009
   192.8 +3;A;Indirizzo Giuridico Economico Aziendale;CARAPELLI;MARCO;18/02/1993;M;MORBEGNO;SO;CRPMRC93B18F712A;VIA RIBALDI, 4;COSIO VALTELLINO;23013;SO;0342 123456;M 999123456;CARAPELLI;GIUSEPPE;MARIOTTI;CRISTINA;2009
   192.9 +3;A;Indirizzo Giuridico Economico Aziendale;AMARETTI;NICOLA;08/01/1993;M;SONDRIO;SO;MRTNCL93A08I829X;VIA MARCHETTI, 20;ARDENNO;23014;SO;0342 123456;0342 654321 lavoro;AMARETTI;CARLO;FRANZINA;MARTA;2009
  192.10 +3;A;Programmatori Mercurio;CARBONI;LUCA;19/01/1993;F;MORBEGNO;SO;CRBLCU95E23A829G;VIA CARTIERA, 7;MANDELLO;23015;SO;0342 687521;335 5659780 p;TARGIOLI;ANDREA;AMBROSETTI;CARLA;2009
  192.11 +3;A;Indirizzo Giuridico Economico Aziendale;CARBONI;LUCA;23/01/1995;M;SONDRIO;SO;CRBLCU95E23A829F;Via LARIO, 32;MORBEGNO;23017;SO;0342/612620;333/5968693 m;CARBONI;MASSIMO;SELLA;SILVIA;2009
  192.12 +3;A;Indirizzo Giuridico Economico Aziendale;CARBONI;MICHELA;18/1/1994;F;SONDRIO;SO;CRBMHL94A58I829C;VIA ROCCA 5C;MORBEGNO;23017;SO;0342615240;P3406429865;CARBONI;MAURO;ARTONI;PAOLA;2009
   193.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.2 +++ b/tests/data/convert/sissi-0.csv	Mon Apr 26 11:16:23 2010 +0200
   193.3 @@ -0,0 +1,9 @@
   193.4 +Anno di corso;Sezione;Corso;Cognome;Nome;Data di nascita;Sesso;Comune di nascita;Prov. Nascita;Codice fiscale;Indirizzo;Comune di residenza;CAP;Prov. Residenza;Telefono 1;Telefono 2;Cognome padre;Nome padre;Cognome madre;Nome madre;Anno Sc.
   193.5 +3;A;PROGETTO CINQUE;ACQUISTINI;FRANCESCO;08/02/1992;M;MILANO;MI;CQSFRN92B08A745Z;VIA GARIBALDI, 60;COLICO;23823;LC;0341/123456;;ACQUISTINI;GERVASO;ALIPRANDI;MARISA;2009
   193.6 +3;A;Indirizzo Giuridico Economico Aziendale;BERTOLDI;GIULIA;03/02/1993;F;MORBEGNO;SO;BRTGLI93B43F712B;VIA ROMA 103;TRAONA;23013;SO;0342/123456;888 123456; m;BERTOLDI;MARIO;GIGIONELLI;ANTONIA;2009
   193.7 +3;A;PROGETTO CINQUE;ANTONI;LUCIA;29/02/1991;F;MORBEGNO;SO;ANTLCU91B69F712X;VIA BRIGLIA, 150/A;MORBEGNO;23017;SO;0342/123456;;ANTONI;ALBERTO;MANNOIA;ZOE;2009
   193.8 +3;A;Indirizzo Giuridico Economico Aziendale;CARAPELLI;MARCO;18/02/1993;M;MORBEGNO;SO;CRPMRC93B18F712A;VIA RIBALDI, 4;COSIO VALTELLINO;23013;SO;0342 123456;M 999123456;CARAPELLI;GIUSEPPE;MARIOTTI;CRISTINA;2009
   193.9 +3;A;Indirizzo Giuridico Economico Aziendale;AMARETTI;NICOLA;08/01/1993;M;SONDRIO;SO;MRTNCL93A08I829X;VIA MARCHETTI, 20;ARDENNO;23014;SO;0342 123456;0342 654321 lavoro;AMARETTI;CARLO;FRANZINA;MARTA;2009
  193.10 +3;A;Programmatori Mercurio;TARGIOLI;MARIELLA;19/01/1993;F;MORBEGNO;SO;TRGMRL93A59F712X;VIA CARTIERA, 7;MANDELLO;23015;SO;0342 687521;335 5659780 p;TARGIOLI;ANDREA;AMBROSETTI;CARLA;2009
  193.11 +3;A;Indirizzo Giuridico Economico Aziendale;CARBONI;LUCA;23/01/1995;M;SONDRIO;SO;CRBLCU95E23A829F;Via LARIO, 32;MORBEGNO;23017;SO;0342/612620;333/5968693 m;CARBONI;MASSIMO;SELLA;SILVIA;2009
  193.12 +3;A;Indirizzo Giuridico Economico Aziendale;CARBONI;MICHELA;18/1/1994;F;SONDRIO;SO;CRBMHL94A58I829C;VIA ROCCA 5C;MORBEGNO;23017;SO;0342615240;P3406429865;CARBONI;MAURO;ARTONI;PAOLA;2009
   194.1 Binary file tests/data/convert/sissi-0.xls has changed
   195.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   195.2 +++ b/tests/data/convert/sissi-1.csv	Mon Apr 26 11:16:23 2010 +0200
   195.3 @@ -0,0 +1,9 @@
   195.4 +Anno di corso;Sezione;Corso;Cognome;Nome;Data di nascita;Sesso;Comune di nascita;Prov. Nascita;Codice fiscale;Indirizzo;Comune di residenza;CAP;Prov. Residenza;Telefono 1;Telefono 2;Cognome padre;Nome padre;Cognome madre;Nome madre;Anno Sc.
   195.5 +3;A;PROGETTO CINQUE;ACQUISTINI;FRANCESCO;08/02/1992;M;MILANO;MI;CQSFRN92B08A745Z;VIA GARIBALDI, 60;COLICO;23823;LC;0341/123456;;ACQUISTINI;GERVASO;ALIPRANDI;MARISA;2009
   195.6 +3;A;Indirizzo Giuridico Economico Aziendale;BERTOLDI;GIULIA;03/02/1993;F;MORBEGNO;SO;BRTGLI93B43F712B;VIA ROMA 103;TRAONA;23013;SO;0342/123456;888 123456; m;BERTOLDI;MARIO;GIGIONELLI;ANTONIA;2009
   195.7 +3;A;PROGETTO CINQUE;ANTONI;LUCIA;29/02/1991;F;MORBEGNO;SO;ANTLCU91B69F712X;VIA BRIGLIA, 150/A;MORBEGNO;23017;SO;0342/123456;;ANTONI;ALBERTO;MANNOIA;ZOE;2009
   195.8 +3;A;Indirizzo Giuridico Economico Aziendale;CARAPELLI;MARCO;18/02/1993;M;MORBEGNO;SO;CRPMRC93B18F712A;VIA RIBALDI, 4;COSIO VALTELLINO;23013;SO;0342 123456;M 999123456;CARAPELLI;GIUSEPPE;MARIOTTI;CRISTINA;2009
   195.9 +3;A;Indirizzo Giuridico Economico Aziendale;AMARETTI;NICOLA;08/01/1993;M;SONDRIO;SO;MRTNCL93A08I829X;VIA MARCHETTI, 20;ARDENNO;23014;SO;0342 123456;0342 654321 lavoro;AMARETTI;CARLO;FRANZINA;MARTA;2009
  195.10 +3;A;Programmatori Mercurio;TARGIOLI;MARIELLA;19/01/1993;F;MORBEGNO;SO;TRGMRL93A59F712X;VIA CARTIERA, 7;MANDELLO;23015;SO;0342 687521;335 5659780 p;TARGIOLI;ANDREA;AMBROSETTI;CARLA;2009
  195.11 +3;A;Indirizzo Giuridico Economico Aziendale;CARBONI;LUCA;23/01/1995;M;SONDRIO;SO;CRBLCU95E23A829F;Via LARIO, 32;MORBEGNO;23017;SO;0342/612620;333/5968693 m;CARBONI;MASSIMO;SELLA;SILVIA;2009
  195.12 +3;A;Indirizzo Giuridico Economico Aziendale;CARBONI;MICHELA;18/1/1994;F;SONDRIO;SO;CRBLCU95E23A821X;VIA ROCCA 5C;MORBEGNO;23017;SO;0342615240;P3406429865;CARBONI;MAURO;ARTONI;PAOLA;2009
   196.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.2 +++ b/tests/data/convert/sissi-tabcorsi	Mon Apr 26 11:16:23 2010 +0200
   196.3 @@ -0,0 +1,5 @@
   196.4 +progetto cinque = geo
   196.5 +geometri        = geo
   196.6 +indirizzo giuridico economico aziendale = ige
   196.7 +programmatori mercurio = pro
   196.8 +
   197.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   197.2 +++ b/tests/data/convert/users-0-collisioni.isi	Mon Apr 26 11:16:23 2010 +0200
   197.3 @@ -0,0 +1,8 @@
   197.4 +luca.carboni;Carboni;Luca;alunni;geo3a;CRBLCU95E23A829H;
   197.5 +giulia.bertoldi;Bertoldi;Giulia;alunni;ige3a;BRTGLI93B43F712B;
   197.6 +lucia.antoni;Antoni;Lucia;alunni;geo3a;ANTLCU91B69F712X;
   197.7 +marco.carapelli;Carapelli;Marco;alunni;ige3a;CRPMRC93B18F712A;
   197.8 +nicola.amaretti;Amaretti;Nicola;alunni;ige3a;MRTNCL93A08I829X;
   197.9 +luca.carboni02;Carboni;Luca;alunni;pro3a;CRBLCU95E23A829G;
  197.10 +luca.carboni03;Carboni;Luca;alunni;ige3a;CRBLCU95E23A829F;
  197.11 +michela.carboni;Carboni;Michela;alunni;ige3a;CRBMHL94A58I829C;
   198.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   198.2 +++ b/tests/data/convert/users-0-extended.isi	Mon Apr 26 11:16:23 2010 +0200
   198.3 @@ -0,0 +1,8 @@
   198.4 +a_cqsfrn92b08;Acquistini;Francesco;alunni;geo3a;CQSFRN92B08A745Z;;M;VIA GARIBALDI, 60;;;23823;0341/123456
   198.5 +a_brtgli93b43;Bertoldi;Giulia;alunni;ige3a;BRTGLI93B43F712B;;F;VIA ROMA 103;;;23013;0342/123456
   198.6 +a_antlcu91b69;Antoni;Lucia;alunni;geo3a;ANTLCU91B69F712X;;F;VIA BRIGLIA, 150/A;;;23017;0342/123456
   198.7 +a_crpmrc93b18;Carapelli;Marco;alunni;ige3a;CRPMRC93B18F712A;;M;VIA RIBALDI, 4;;;23013;0342 123456
   198.8 +a_mrtncl93a08;Amaretti;Nicola;alunni;ige3a;MRTNCL93A08I829X;;M;VIA MARCHETTI, 20;;;23014;0342 123456
   198.9 +a_trgmrl93a59;Targioli;Mariella;alunni;pro3a;TRGMRL93A59F712X;;F;VIA CARTIERA, 7;;;23015;0342 687521
  198.10 +a_crblcu95e23;Carboni;Luca;alunni;ige3a;CRBLCU95E23A829F;;M;Via LARIO, 32;;;23017;0342/612620
  198.11 +a_crbmhl94a58;Carboni;Michela;alunni;ige3a;CRBMHL94A58I829C;;F;VIA ROCCA 5C;;;23017;0342615240
   199.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   199.2 +++ b/tests/data/convert/users-0-idnames.isi	Mon Apr 26 11:16:23 2010 +0200
   199.3 @@ -0,0 +1,8 @@
   199.4 +a_francesco.acquistini;Acquistini;Francesco;alunni;geo3a;CQSFRN92B08A745Z;
   199.5 +a_giulia.bertoldi;Bertoldi;Giulia;alunni;ige3a;BRTGLI93B43F712B;
   199.6 +a_lucia.antoni;Antoni;Lucia;alunni;geo3a;ANTLCU91B69F712X;
   199.7 +a_marco.carapelli;Carapelli;Marco;alunni;ige3a;CRPMRC93B18F712A;
   199.8 +a_nicola.amaretti;Amaretti;Nicola;alunni;ige3a;MRTNCL93A08I829X;
   199.9 +a_mariella.targioli;Targioli;Mariella;alunni;pro3a;TRGMRL93A59F712X;
  199.10 +a_luca.carboni;Carboni;Luca;alunni;ige3a;CRBLCU95E23A829F;
  199.11 +a_michela.carboni;Carboni;Michela;alunni;ige3a;CRBMHL94A58I829C;
   200.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.2 +++ b/tests/data/convert/users-0-names.isi	Mon Apr 26 11:16:23 2010 +0200
   200.3 @@ -0,0 +1,8 @@
   200.4 +francesco.acquistini;Acquistini;Francesco;alunni;geo3a;CQSFRN92B08A745Z;
   200.5 +giulia.bertoldi;Bertoldi;Giulia;alunni;ige3a;BRTGLI93B43F712B;
   200.6 +lucia.antoni;Antoni;Lucia;alunni;geo3a;ANTLCU91B69F712X;
   200.7 +marco.carapelli;Carapelli;Marco;alunni;ige3a;CRPMRC93B18F712A;
   200.8 +nicola.amaretti;Amaretti;Nicola;alunni;ige3a;MRTNCL93A08I829X;
   200.9 +mariella.targioli;Targioli;Mariella;alunni;pro3a;TRGMRL93A59F712X;
  200.10 +luca.carboni;Carboni;Luca;alunni;ige3a;CRBLCU95E23A829F;
  200.11 +michela.carboni;Carboni;Michela;alunni;ige3a;CRBMHL94A58I829C;
   201.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   201.2 +++ b/tests/data/convert/users-0-std.isi	Mon Apr 26 11:16:23 2010 +0200
   201.3 @@ -0,0 +1,8 @@
   201.4 +a_cqsfrn92b08;Acquistini;Francesco;alunni;geo3a;CQSFRN92B08A745Z;
   201.5 +a_brtgli93b43;Bertoldi;Giulia;alunni;ige3a;BRTGLI93B43F712B;
   201.6 +a_antlcu91b69;Antoni;Lucia;alunni;geo3a;ANTLCU91B69F712X;
   201.7 +a_crpmrc93b18;Carapelli;Marco;alunni;ige3a;CRPMRC93B18F712A;
   201.8 +a_mrtncl93a08;Amaretti;Nicola;alunni;ige3a;MRTNCL93A08I829X;
   201.9 +a_trgmrl93a59;Targioli;Mariella;alunni;pro3a;TRGMRL93A59F712X;
  201.10 +a_crblcu95e23;Carboni;Luca;alunni;ige3a;CRBLCU95E23A829F;
  201.11 +a_crbmhl94a58;Carboni;Michela;alunni;ige3a;CRBMHL94A58I829C;
   202.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   202.2 +++ b/tests/data/convert/users-1-names.isi	Mon Apr 26 11:16:23 2010 +0200
   202.3 @@ -0,0 +1,9 @@
   202.4 +francesco.acquistini;Acquistini;Francesco;alunni;geo3a;CQSFRN92B08A745Z;
   202.5 +giulia.bertoldi;Bertoldi;Giulia;alunni;ige3a;BRTGLI93B43F712B;
   202.6 +lucia.antoni;Antoni;Lucia;alunni;geo3a;ANTLCU91B69F712X;
   202.7 +marco.carapelli;Carapelli;Marco;alunni;ige3a;CRPMRC93B18F712A;
   202.8 +nicola.amaretti;Amaretti;Nicola;alunni;ige3a;MRTNCL93A08I829X;
   202.9 +mariella.targioli;Targioli;Mariella;alunni;pro3a;TRGMRL93A59F712X;
  202.10 +luca.carboni;Carboni;Luca;alunni;ige3a;CRBLCU95E23A829F;
  202.11 +michela.carboni02;Carboni;Michela;alunni;ige3a;CRBLCU95E23A821X;
  202.12 +-michela.carboni;Carboni;Michela;alunni;ige3a;CRBMHL94A58I829C;
   203.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   203.2 +++ b/tests/data/etc/dnsmasq.conf	Mon Apr 26 11:16:23 2010 +0200
   203.3 @@ -0,0 +1,102 @@
   203.4 +# -*- mode: conf -*-
   203.5 +# non inoltrare mai ai server dns esterni
   203.6 +# query senza nome dominio
   203.7 +domain-needed
   203.8 +
   203.9 +# Tutti i reverse lookup per la subnet privata
  203.10 +# non presenti in /etc/hosts o nei lease dhcp
  203.11 +# ottengono "host not found"
  203.12 +# invece di essere inoltrati ai dns esterni
  203.13 +bogus-priv
  203.14 +
  203.15 +# Filtra le ricorrenti richieste SOA, SRV e altre,
  203.16 +# provenienti da macchine windows
  203.17 +# serve in particolare a non attivare
  203.18 +# per sbaglio il link quando si
  203.19 +# hanno connessioni "on demand"
  203.20 +filterwin2k
  203.21 +
  203.22 +# server dns esterni di riferimento
  203.23 +# inserire i server dns uno per riga
  203.24 +# usati in questo caso i server di opendns.org
  203.25 +server=208.67.222.222 
  203.26 +server=208.67.220.220
  203.27 +
  203.28 +# aggiunge sempre il nome dominio al nome host
  203.29 +expand-hosts
  203.30 +
  203.31 +# nome del mio dominio
  203.32 +domain=isi.lan
  203.33 +
  203.34 +# Se si intende passare ai client un dominio differente
  203.35 +# dhcp-option=option:domain-name,isi.lan
  203.36 +
  203.37 +# range dei lease dhcp: indirizzo iniziale, indirizzo finale, netmask, durata del lease
  203.38 +dhcp-range=192.168.96.130,192.168.96.140,255.255.255.0,8h
  203.39 +
  203.40 +# Range dhcp per-tag
  203.41 +# ~~~~~~~~~~~~~~~~~~~
  203.42 +# E` anche possibile riservare un determinato range filtrando per TAG.
  203.43 +# I tag possono essere associati anche ad un'intera famiglia di indirizzi MAC
  203.44 +# Ciò risulta utilissimo, ad esempio, per limitare le macchine virtuali vmware
  203.45 +# ad un certo range.
  203.46 +#
  203.47 +# Settare il tag "macchinevmware" per le macchine con mac iniziante per
  203.48 +# 00:0c:29:*:*:* (gruppo di indirizzi mac riservati a vmware)
  203.49 +#
  203.50 +#   dhcp-mac=macchinevmware,00:0c:29:*:*:*
  203.51 +#
  203.52 +# Sintassi ::
  203.53 +#
  203.54 +#   dhcp-range=[[net:]network-id,]<start-addr>,<end-addr>[[,<net‐netmask>],<broadcast>][,<lease time>]
  203.55 +#
  203.56 +# Esempio ::
  203.57 +#
  203.58 +# dhcp-range=net:macchinevmware,192.168.150,160,255.255.255.0,8h
  203.59 +
  203.60 +
  203.61 +# Esempio di ip-reservation per client
  203.62 +#
  203.63 +# MAC address, indirizzo, nome host, tag(utile per associare a più server)
  203.64 +#
  203.65 +# dhcp-host=00:0c:29:c9:69:35,192.168.96.190,vm-ltsp01,net:ns1  # client1
  203.66 +# dhcp-host=00:0c:29:5e:69:b5,192.168.96.191,vm-ltsp02,net:ns2  # client2
  203.67 +#
  203.68 +# le associazioni vengono definite esternamente, vedi inclusioni a fine file.
  203.69 +# il file usato è /etc/isi/dns/dnsmasq/hosts.mac
  203.70 +
  203.71 +# dnsmasq supporta la maggior parte delle
  203.72 +# opzioni dhcp e bootp specificate in
  203.73 +# http://www.faqs.org/rfcs/rfc2132.html
  203.74 +# la sintassi e':
  203.75 +# dhcp-option=[numero relativo all'opzione],parametro
  203.76 +
  203.77 +# GATEWAY di default (3)
  203.78 +dhcp-option=3,192.168.96.1
  203.79 +
  203.80 +# DNS da passare ai client (6)
  203.81 +dhcp-option=6,192.168.96.254
  203.82 +
  203.83 +# WINS da passare ai client (44)
  203.84 +dhcp-option=44,192.168.96.253
  203.85 +#
  203.86 +# Il server dhcp sarà AUTORITATIVO.
  203.87 +dhcp-authoritative
  203.88 +cache-size=1024
  203.89 +### LOG 
  203.90 +# da usare per debug
  203.91 +# log-queries
  203.92 +
  203.93 +# Da abilitare *solo* in caso di debug, logga tutte le transazioni che avvengono
  203.94 +# tra servente DHCP e i client.
  203.95 +# 
  203.96 +# log-dhcp
  203.97 +
  203.98 +# Configurazione aggiuntiva per isi.
  203.99 +conf-dir=/etc/isi/dns/dnsmasq
 203.100 +addn-hosts=/etc/isi/dns/hosts
 203.101 +
 203.102 +# Per includere ulteriori configurazioni...
 203.103 +# conf-file=/etc/dnsmasq.more.conf
 203.104 +# conf-dir=/etc/dnsmasq.d
 203.105 +dhcp-boot=/ltsp/i386/nbi.img,ltsp-server,192.168.96.222
   204.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   204.2 +++ b/tests/data/etc/hosts	Mon Apr 26 11:16:23 2010 +0200
   204.3 @@ -0,0 +1,7 @@
   204.4 +127.0.0.1 localhost
   204.5 +127.0.1.1 ISI-PDC
   204.6 +192.168.96.222 srv-ltsp
   204.7 +192.168.96.210 ISI-PDC
   204.8 +192.168.96.22 www.tin.it
   204.9 +192.168.96.199 vm-client-ltsp1
  204.10 +192.168.96.44 srv-prova srv # questi sono dei commenti
   205.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   205.2 +++ b/tests/data/etc/hosts.mac	Mon Apr 26 11:16:23 2010 +0200
   205.3 @@ -0,0 +1,2 @@
   205.4 +dhcp-host=00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1
   205.5 +dhcp-host=00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2,net:ns1
   206.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   206.2 +++ b/tests/data/etc/isi/dns/dnsmasq/ltsp	Mon Apr 26 11:16:23 2010 +0200
   206.3 @@ -0,0 +1,27 @@
   206.4 +# le prossime sono quelle che servono
   206.5 +# in particolare ai thin client
   206.6 +# root-path (17)
   206.7 +# percorso dove montare la partizione root
   206.8 +dhcp-option=17,"/opt/ltsp/i386"
   206.9 +
  206.10 +# file di boot (percorso relativo alla root del server tftp),
  206.11 +# nome tftp server, ip tftp server
  206.12 +# l'indirizzo e il nome del server
  206.13 +# devono essere inseriti in /etc/hosts
  206.14 +dhcp-boot=/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222
  206.15 +
  206.16 +# file di boot (percorso relativo alla root del server tftp),
  206.17 +# nome tftp server, ip tftp server
  206.18 +# l'indirizzo e il nome del server
  206.19 +# devono essere inseriti in /etc/hosts
  206.20 +#dhcp-boot=/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222
  206.21 +
  206.22 +# PXE / Etherboot
  206.23 +dhcp-vendorclass=pxe,PXEClient 
  206.24 +dhcp-vendorclass=eth,Etherboot 
  206.25 +#    dhcp-option=vendor:PXEClient,1,0.0.0.0
  206.26 +dhcp-boot=net:pxe,/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222 
  206.27 +dhcp-boot=net:eth,/ltsp/i386/pxelinux.0,ltsp-server, 192.168.96.222
  206.28 +
  206.29 +# other
  206.30 +dhcp-boot=/ltsp/i386/nbi.img,ltsp-server,192.168.96.222
   207.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   207.2 +++ b/tests/data/leases	Mon Apr 26 11:16:23 2010 +0200
   207.3 @@ -0,0 +1,6 @@
   207.4 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
   207.5 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
   207.6 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
   207.7 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
   207.8 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
   207.9 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
   208.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   208.2 +++ b/tests/data/logon.conf	Mon Apr 26 11:16:23 2010 +0200
   208.3 @@ -0,0 +1,248 @@
   208.4 +# +-------------------------------------------------+
   208.5 +# � 2002-2005 ReteIsi / www.reteisi.org 
   208.6 +# +-------------------------------------------------+
   208.7 +# $Id: logon.conf,v 1.4 2021/09/02 17:23:43 max Exp $
   208.8 +
   208.9 +###-----------------------------------------------------------------------
  208.10 +### Le variabili dichiarate in questo file sono di due tipi
  208.11 +### quelle che iniziano con un _ sono variabili interne e servono
  208.12 +### ad abilitare (1) o disabilitare (0) la funzionalita`corrispondente
  208.13 +### oppure a passare variabili di configurazione specifiche di
  208.14 +### ISI-logon; le altre DEVONO corrispondere a voci di registro a cui 
  208.15 +### si vuole assegnare il valore scritto di seguito (es. 0x00000001).
  208.16 +### Per ottenere una differente impostazione per uno specifico gruppo
  208.17 +### basta specificare il gruppo come nell'esempio:
  208.18 +### Start__Page[alunni] = www.google.com
  208.19 +### Quando i nomi usati per le variabili sono quelli del registro di
  208.20 +### windows, se il nome della variabile di registro contiene uno
  208.21 +### spazio, sostituirlo con due _ (.Es "Start Page" = Start__Page)
  208.22 +
  208.23 +### sulle variabili prefissate con underscore in generale 
  208.24 +###    1 applica la restrizione
  208.25 +###    0 rimuove la restrizione
  208.26 +### il valore delle variabili di registro va espresso 
  208.27 +### coerentemente con il TIPO (se REG_DWORD, 0x......)
  208.28 +
  208.29 +### NOTA: Le variabili  sono *case sensitive*
  208.30 +###-----------------------------------------------------------------------
  208.31 +
  208.32 +### versione di logon.conf - DA INCREMENTARE AD OGNI MODIFICA di logon.conf 
  208.33 +### per attivare l'aggiornamento degli user.dat (agisce sui client win98)
  208.34 +
  208.35 +_Versione = 0;
  208.36 +
  208.37 +### DEBUG (0,1,2,3)
  208.38 +### 0 = nessun debug 
  208.39 +### 1 = solo console su video o su file (se valorizzato _DebugFile)
  208.40 +### 2 = su schermo (in box grafici: lungo, completo e noioso ;-)
  208.41 +### 3 = sul file locale DBG_macchina.TXT  nella HOME 
  208.42 +
  208.43 +
  208.44 +_DebugLevel = 1
  208.45 +
  208.46 +### opzioni aggiuntive se _DebugLevel=3
  208.47 +### _DebugShare		share samba in cui centralizzare 
  208.48 +### _DebugUsers		lista degli utenti da sottoporre a debug
  208.49 +### _DebugClients	lista dei clients da sottoporre a debug
  208.50 +
  208.51 +_DebugShare =
  208.52 +_DebugUsers =
  208.53 +_DebugClients=
  208.54 +
  208.55 +
  208.56 +### WinSet sezione 'start_page'
  208.57 +Start__Page          = www.google.it
  208.58 +Start__Page[admins]  = www.google.it
  208.59 +
  208.60 +### WinSet sezione 'proxy'
  208.61 +ProxyServer          = XXX.XXX.XXX:8128    # DansGuardian
  208.62 +ProxyServer[admins]  = XXX.XXX.XXX:3128    # Squid (FW permettendo)
  208.63 +ProxyOverride        = www.XXX.XXX,<local>
  208.64 +
  208.65 +### WinSet sezione 'no_profile' (solo XP)
  208.66 +ExcludeProfileDirs   = Impostazioni locali;Temporary Internet Files;Cronologia;Temp;Documenti;Cookies;SendTo
  208.67 +
  208.68 +### WinSet sezione 'document_folder'
  208.69 +Personal            = H:\Documenti
  208.70 +My__Picture         = 
  208.71 +My__Music			= 
  208.72 +My__Video           = 
  208.73 +
  208.74 +### WinSet sezione 'paranoia_folders' solo per win9x
  208.75 +### se _OkParanoia = 1 vengono ripuliti ad ogni logon il Desktop e il cestino di default.
  208.76 +_OkParanoia        = 0
  208.77 +
  208.78 +
  208.79 +### WinSet sezione 'iepasswordcache' - non salva le password digitate quando si accede a siti web
  208.80 +
  208.81 +_RestrictIEPasswordCaching = 0
  208.82 +
  208.83 +### WinSet sezione 'sync' (solo WinXP)
  208.84 +### per disabilitare la sincronizzazione delle cartelle non in linea
  208.85 +### � necessario porre a 1 la seguente variabile
  208.86 +_NoSync  = 1
  208.87 +
  208.88 +### WinSet sezione 'last-user' (WinXP)
  208.89 +### gli utenti normali non hanno permessi sufficenti
  208.90 +### gli amministratori (admins) invece possono
  208.91 +### questa situazione viene gestita eliminando
  208.92 +### il default
  208.93 +
  208.94 +_NoDispLastUser[admins]  = 0
  208.95 +
  208.96 +### WinPol9x sezione 'last-user' (Win9X solo con Tweakui installato)
  208.97 +_NoDispLastUser9X = 1
  208.98 +
  208.99 +### parametri validi per Win9x -  default molto restrittivo 
 208.100 +
 208.101 +### di seguito sono specifate tutte e solo le cartelle che possono essere messe in roaming
 208.102 +### separare le cartelle con un ; per default tutte le cartelle sono in roaming
 208.103 +
 208.104 +#_ProleDirs = AppData;Cache;Cookies;Desktop;Favorites;History;NetHood;Programs;Recent;Start Menu;Startup
 208.105 +_ProfileDirs = AppData;Temporary Internet Files;Cookies;Desktop;Favorites;History;NetHood;Programs;Recent;Start Menu;Startup
 208.106 +
 208.107 +### se le cartelle vengono messe in roaming possono anche essere rimappate sul server in modo
 208.108 +### da salvare i documenti durante la sessione ed evitare "traffico" all'uscita,
 208.109 +### se non si specifica alcun percorso vengono messe in roaming nel modo "classico" 
 208.110 +### con il salvataggio sul server all'uscita
 208.111 +
 208.112 +#esempi di percorsi:
 208.113 +#Desktop = H:\.profili\Win95\Desktop
 208.114 +#Cookies=H:\.profili\Win95\Cookies
 208.115 +#Favorites=H:\.profili\Win95\Favorites
 208.116 +
 208.117 +
 208.118 +### WinPol9x sezione 'access'
 208.119 +_RestrictLogon		    	= 1
 208.120 +_RestrictLogon[admins]      = 1
 208.121 +# valori di registro
 208.122 +UserProfiles                = 1 #0x00000001 # si vogliono i roaming profiles
 208.123 +UseHomeDirectory            = 1 #0x00000001 
 208.124 +MustBeValidated             = 1 #0x00000001 # si vuole l'autenticazione ldap
 208.125 +MustBeValidated[admins]     = 1 #0x00000000
 208.126 +LegalNoticeCaption          = XXX.XXX            
 208.127 +LegalNoticeText             = accesso riservato agli utenti autorizzati.
 208.128 +       
 208.129 +### WinPol9x sezione 'nocpan' - fa sparire dal pannello di controllo
 208.130 +_RestrictCpan               = 0
 208.131 +
 208.132 +### WinPol9x sezione 'appwiz' - fa sparire dal pannello di controllo
 208.133 +### l'applet Installa/Rimuovi applicazioni
 208.134 +_NoAppWiz               = 0
 208.135 +
 208.136 +### WinPol9x sezione 'nodrive' - fa sparire le periferiche dalle risorse del computer
 208.137 +_RestrictDrive              = 0
 208.138 +_RestrictDrive[admins]      = 0
 208.139 +
 208.140 +###WinPol9x sezione 'nodrivec' - fa sparire il disco C dalle risorse del computer
 208.141 +_RestrictDriveC             = 1
 208.142 +_RestrictDriveC[admins]     = 0
 208.143 +
 208.144 +### WinPol9x sezione 'nofind' - fa sparire la voce trova dal menu avvio
 208.145 +_RestrictFind               = 1
 208.146 +_RestrictFind[admins]       = 0
 208.147 +
 208.148 +### WinPol9x sezione 'nohistory' - cancella la cronologia
 208.149 +_RestrictHistory            = 0
 208.150 +
 208.151 +### WinPol9x sezione 'iecachedays' - se _SetIECache � settato a 1
 208.152 +### con la variabile successiva DaysToKeep � possibile impostare per
 208.153 +### quanti giorni restano nella cache le pagine web visitate
 208.154 +### Con DaysToKeep = 0x00000000 le pagine non vengono salvate
 208.155 +_SetIECache = 0
 208.156 +DaysToKeep = 0x00000000
 208.157 +
 208.158 +
 208.159 +
 208.160 +### WinPol9x sezione 'nosavesettings' - non salva i cambiamenti al Desktop all'uscita
 208.161 +_RestrictSaveSettings      = 0
 208.162 +
 208.163 +### WinPol9x sezione 'noactivedesktop' - disattiva l'Active Desktop
 208.164 +_RestrictActiveDesktop      = 0
 208.165 +
 208.166 +### WinPol9x sezione 'screen' -  abilita le restrizioni dello schermo
 208.167 +_RestrictScreen             = 1 
 208.168 +_RestrictScreen[admins]     = 0
 208.169 +
 208.170 +# opzioni restrizioni screen
 208.171 +NoDispAppearancePage        = 0 #0x00000000
 208.172 +NoDispBackgroundPage        = 0 #0x00000000
 208.173 +NoDispCPL                   = 0 #0x00000000
 208.174 +NoDispScrSavPage            = 0 #0x00000000
 208.175 +NoDispSettingsPage          = 1 #0x00000001
 208.176 +
 208.177 +# opzioni altre applet del pannello di controllo
 208.178 +NoAdminPage					= 1
 208.179 +NoConfigPage				= 1
 208.180 +NoDevMgrPage				= 1	
 208.181 +NoFileSysPage				= 1	
 208.182 +NoProfilePage				= 1
 208.183 +NoVirtMemPage				= 1
 208.184 +
 208.185 +### WinPol9x sezione 'net'    - Risorse di rete Propriet�          
 208.186 +_RestrictNet		        = 0
 208.187 +_RestrictNet[admins]        = 0
 208.188 +
 208.189 +### WinPol9x sezione 'passwd' = Pannello di controllo Password
 208.190 +_RestrictPasswd             = 1
 208.191 +_RestrictPasswd[admins]     = 0
 208.192 +
 208.193 +### WinPol9x sezione 'printer' - Impostazioni stampanti
 208.194 +_RestrictPrinter	    	= 1
 208.195 +_RestrictPrinter[admins]    = 0
 208.196 +
 208.197 +### WinPol9x sezione 'system'  - Restrizioni varie sul sistema     
 208.198 +_RestrictSystem             = 1
 208.199 +_RestrictSystem[admins]     = 0
 208.200 +
 208.201 +### WinPol9x sezione 'shell-run' - Start Esegui
 208.202 +_RestrictRun                = 0
 208.203 +_RestrictRun[admins]        = 0
 208.204 +
 208.205 +### WinPol9x sezione 'shell-noregtools' - tools per la modifica del registro
 208.206 +_RestrictRegTools           = 0
 208.207 +_RestrictRegTools[admins]   = 0
 208.208 +
 208.209 +### WinPol9x sezione 'shell-winoldapp' - vecchie applicazioni
 208.210 +_RestrictOldApp             = 0
 208.211 +_RestrictOldApp[admins]     = 0
 208.212 +
 208.213 +
 208.214 +### connessioni di rete  oltre a quelle attivate 
 208.215 +### automaticamente, che sono:
 208.216 +### H: -> homedir
 208.217 +### L: -> classe  (solo per gli alunni)
 208.218 +### la sintassi e'la seguente:
 208.219 +### NetFolder[unita'[:gruppo]] = nome della condivisione
 208.220 +###		esempio _NetFolder[U:admins]=util
 208.221 +
 208.222 +_NetFolder[W] = mioweb      
 208.223 +#_NetFolder[Z:admins] = zoftware
 208.224 +_NetFolder[Z] = software
 208.225 +_NetFolder[S] = area_alunni
 208.226 +_NetFolder[K:docenti] = classi
 208.227 +_NetFolder[K:admins] = classi
 208.228 +_NetFolder[X:admins] = dati
 208.229 +
 208.230 +### sincronizzazione orologio
 208.231 +
 208.232 +_NetTime      = 1
 208.233 +
 208.234 +### forzatura ambiente di default (desktop, menu avvio ecc.ecc.)
 208.235 +### la si ottiene copiando la seguente cartella
 208.236 +
 208.237 +### [netlogon]\env_$os_$gruppo\*  ->  C:\Windows\All Users  (Win9x)
 208.238 +### [netlogon]\env_$os_gruppo\*   ->  C:\Documents and Settings\All Users  (WinXP)
 208.239 +
 208.240 +### dove os = $ENV{OSCLIENT} e'la versione di windows che gira sul client 
 208.241 +### cioe'una delle seguenti: Win95,Win98,WinME,WinNT,Win2K,WinXP
 208.242 +
 208.243 +_EnvWin98           = 1
 208.244 +_EnvWin98[admins]   = 0     
 208.245 +
 208.246 +### ATTENZIONE: per WinXP,Win2K occorre che la cartella di destinazione sia
 208.247 +### scrivibile dagli utenti di dominio il che normalmente non e'; si
 208.248 +### consiglia di non attivare questa funzionalita, Se il client e'
 208.249 +### correttamente configurato si rivela sostanzialmente inutile
 208.250 +
 208.251 +_EnvWinXP           = 0
   209.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   209.2 +++ b/tests/data/users_misc.isi	Mon Apr 26 11:16:23 2010 +0200
   209.3 @@ -0,0 +1,4 @@
   209.4 +a_test;alunno;test;alunni;classe_test2;DNTLSN63D07z404a;isi
   209.5 +-a_test2;alunno;test;alunni;3b;DNTLSN63D07z404a;isi
   209.6 +d_test;doc;test;docenti;;DNTLSN63D07z404b;isi2
   209.7 +ad_test;adm;test;admins;;DNTLSN63D07z404c;isi2
   210.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   210.2 +++ b/tests/data/users_test.isi	Mon Apr 26 11:16:23 2010 +0200
   210.3 @@ -0,0 +1,7 @@
   210.4 +a_test;alunno;test;alunni;classe_test;DNTLSN63D07z404a;isi
   210.5 +a_test2;alunno;test;alunni;3b;DNTLSN63D07z404a;isi
   210.6 +d_test;doc;test;docenti;;DNTLSN63D07z404b;isi
   210.7 +ad_test;adm;test;admins;;DNTLSN63D07z404c;isi
   210.8 +at_test;ata;test;ata;;DNTLSN63D07z405;isi
   210.9 +s_test;doc;test;segreteria;;DNTLSN63D07z406;isi
  210.10 +e_test;doc;test;esterni;;DNTLSN63D07z407;isi
   211.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   211.2 +++ b/tests/data/var/lib/misc/dnsmasq.leases	Mon Apr 26 11:16:23 2010 +0200
   211.3 @@ -0,0 +1,2 @@
   211.4 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
   211.5 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
   212.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   212.2 +++ b/tests/dnsmasq.txt	Mon Apr 26 11:16:23 2010 +0200
   212.3 @@ -0,0 +1,107 @@
   212.4 +# -*- mode: python -*-
   212.5 +### test Hosts
   212.6 +
   212.7 +>>> import sys
   212.8 +>>> sys.path.insert(0, '..')
   212.9 +>>> from isi.conf import dnsmasq 
  212.10 +
  212.11 +>>> l = dnsmasq.Line('# comment')
  212.12 +>>> l.is_comment
  212.13 +True
  212.14 +
  212.15 +## Building a line from a string
  212.16 +>>> l = dnsmasq.Line('bogus-param')
  212.17 +Traceback (most recent call last):
  212.18 +...
  212.19 +UnknownParamName: Param is not valid: bogus-param
  212.20 +
  212.21 +>>> l = dnsmasq.Line('dhcp-authoritative')
  212.22 +>>> l.validate()
  212.23 +True
  212.24 +
  212.25 +>>> l = dnsmasq.Line('domain=isi.lan')
  212.26 +>>> l.param_name
  212.27 +'domain'
  212.28 +
  212.29 +>>> l = dnsmasq.Line('dhcp-range=192.168.96.130,192.168.96.140,255.255.255.0,8h')
  212.30 +>>> l.param_name
  212.31 +'dhcp-range'
  212.32 +
  212.33 +>>> l = dnsmasq.Line('dhcp-host=00:0c:29:c9:69:35,192.168.96.190,vm-ltsp01,net:ns1  # client1')
  212.34 +>>> l.param_name
  212.35 +'dhcp-host'
  212.36 +
  212.37 +>>> l = dnsmasq.Line('dhcp-option=3,192.168.96.1')
  212.38 +>>> l.param_name
  212.39 +'dhcp-option'
  212.40 +>>> l.value
  212.41 +'3,192.168.96.1'
  212.42 +
  212.43 +## Building a line from parameters
  212.44 +>>> print dnsmasq.Line(param_name='dhcp-range', value='192.168.96.130,192.168.96.140,255.255.255.0,8h')
  212.45 +dhcp-range=192.168.96.130,192.168.96.140,255.255.255.0,8h
  212.46 +
  212.47 +>>> print dnsmasq.Line(param_name='dhcp-authoritative')
  212.48 +dhcp-authoritative
  212.49 +
  212.50 +############
  212.51 +## Conf file
  212.52 +############
  212.53 +
  212.54 +>>> conf = dnsmasq.Conf('data/etc/dnsmasq.conf')
  212.55 +>>> len(conf.lines)
  212.56 +102
  212.57 +
  212.58 +>>> lines = conf.get_param(param_name='dhcp-authoritative')
  212.59 +>>> len(lines) 
  212.60 +1
  212.61 +
  212.62 +>>> l = conf.del_param('dhcp-authoritative')
  212.63 +>>> print l
  212.64 +dhcp-authoritative
  212.65 +
  212.66 +>>> conf2 = dnsmasq.Conf('data/etc/dnsmasq.conf')
  212.67 +>>> print conf2.diff(conf)
  212.68 +--- this.conf 
  212.69 ++++ other.conf 
  212.70 +@@ -81,7 +81,6 @@
  212.71 + dhcp-option=44,192.168.96.253
  212.72 + #
  212.73 + # Il server dhcp sarà AUTORITATIVO.
  212.74 +-dhcp-authoritative
  212.75 + cache-size=1024
  212.76 + ### LOG
  212.77 + # da usare per debug
  212.78 +<BLANKLINE>
  212.79 +
  212.80 +>>> conf = dnsmasq.Conf('data/etc/dnsmasq.conf')
  212.81 +>>> l = conf.del_param(param_name='server', value='208.67.222.222')
  212.82 +>>> print l
  212.83 +server=208.67.222.222
  212.84 +
  212.85 +>>> print conf2.diff(conf)
  212.86 +--- this.conf 
  212.87 ++++ other.conf 
  212.88 +@@ -19,7 +19,6 @@
  212.89 + # server dns esterni di riferimento
  212.90 + # inserire i server dns uno per riga
  212.91 + # usati in questo caso i server di opendns.org
  212.92 +-server=208.67.222.222
  212.93 + server=208.67.220.220
  212.94 +<BLANKLINE>
  212.95 + # aggiunge sempre il nome dominio al nome host
  212.96 +<BLANKLINE>
  212.97 +
  212.98 +>>> dnsmasq.get_ip('dhcp-option=6,192.168.96.254', '6')
  212.99 +'192.168.96.254'
 212.100 +
 212.101 +>>> dnsmasq.get_ip('dhcp-option=6,192.168.96.254,net:ns', '6', tag='ns')
 212.102 +'192.168.96.254'
 212.103 +
 212.104 +>>> dnsmasq.get_ip('dhcp-option=6,192.168.96.254,net:ns', '6', tag='ns2')
 212.105 +
 212.106 +>>> conf.get_option('gw')
 212.107 +'192.168.96.1'
 212.108 +
 212.109 +>>> sorted([x.hostname for x in dnsmasq.get_leases('data/leases') if x.hostname])
 212.110 +['colinux', 'vm-client-ltsp1', 'wdt']
   213.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   213.2 +++ b/tests/hosts.txt	Mon Apr 26 11:16:23 2010 +0200
   213.3 @@ -0,0 +1,84 @@
   213.4 +# -*- mode: python -*-
   213.5 +### test Hosts
   213.6 +
   213.7 +>>> import sys
   213.8 +>>> sys.path.insert(0, '..')
   213.9 +>>> from isi.conf import hosts
  213.10 +
  213.11 +## a Line from a line
  213.12 +>>> l = hosts.Line('127.0.0.1 localhost')
  213.13 +>>> l.param_name
  213.14 +'127.0.0.1'
  213.15 +
  213.16 +>>> l.value
  213.17 +'localhost'
  213.18 +
  213.19 +## a lien from values
  213.20 +>>> l = hosts.Line(param_name='127.0.0.1', value='localhost')
  213.21 +>>> print l
  213.22 +127.0.0.1 localhost
  213.23 +
  213.24 +>>> l = hosts.Line(param_name='127.0.0.300', value='localhost')
  213.25 +Traceback (most recent call last):
  213.26 +...
  213.27 +WrongIPError: 127.0.0.300 is not a valid IP
  213.28 +
  213.29 +
  213.30 +###########
  213.31 +## a file
  213.32 +###########
  213.33 +
  213.34 +>>> h = hosts.Hosts('data/etc/hosts')
  213.35 +>>> len(h.lines) == 7
  213.36 +True
  213.37 +
  213.38 +>>> lines = h.get_param(param_name='127.0.0.1')
  213.39 +>>> len(lines) 
  213.40 +1
  213.41 +
  213.42 +>>> lines = h.get_param(param_name='192.168.96.222', value='srv-ltsp')
  213.43 +>>> len(lines) 
  213.44 +1
  213.45 +
  213.46 +>>> lines[0].param_name
  213.47 +'192.168.96.222'
  213.48 +
  213.49 +>>> print h.set_param('192.168.96.222', value='srv-isi')
  213.50 +192.168.96.222 srv-isi
  213.51 +
  213.52 +## line number has not increased
  213.53 +>>> len(h.lines)
  213.54 +7
  213.55 +
  213.56 +>>> h1 = hosts.Hosts('data/etc/hosts')
  213.57 +>>> print h1.diff(h)
  213.58 +--- this.conf 
  213.59 ++++ other.conf 
  213.60 +@@ -1,6 +1,6 @@
  213.61 + 127.0.0.1 localhost
  213.62 + 127.0.1.1 ISI-PDC
  213.63 +-192.168.96.222 srv-ltsp
  213.64 ++192.168.96.222 srv-isi
  213.65 + 192.168.96.210 ISI-PDC
  213.66 + 192.168.96.22 www.tin.it
  213.67 + 192.168.96.199 vm-client-ltsp1
  213.68 +<BLANKLINE>
  213.69 +
  213.70 +>>> print h.set_param('192.168.96.254', value='gw')
  213.71 +192.168.96.254 gw
  213.72 +
  213.73 +>>> h1 = hosts.Hosts('data/etc/hosts')
  213.74 +>>> print h1.diff(h)
  213.75 +--- this.conf 
  213.76 ++++ other.conf 
  213.77 +@@ -1,7 +1,8 @@
  213.78 + 127.0.0.1 localhost
  213.79 + 127.0.1.1 ISI-PDC
  213.80 +-192.168.96.222 srv-ltsp
  213.81 ++192.168.96.222 srv-isi
  213.82 + 192.168.96.210 ISI-PDC
  213.83 + 192.168.96.22 www.tin.it
  213.84 + 192.168.96.199 vm-client-ltsp1
  213.85 + 192.168.96.44 srv-prova srv
  213.86 ++192.168.96.254 gw
  213.87 +<BLANKLINE>
   214.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   214.2 +++ b/tests/logon.txt	Mon Apr 26 11:16:23 2010 +0200
   214.3 @@ -0,0 +1,247 @@
   214.4 +# -*- mode: python -*-
   214.5 +
   214.6 +>>> from isi.conf import logon
   214.7 +
   214.8 +### Line
   214.9 +>>> line_dict = {'drive': None,
  214.10 +...             'final_comment': '',
  214.11 +...             'group': None,
  214.12 +...             'is_comment': False,
  214.13 +...             'line': 'Start__Page  = www.google.it',
  214.14 +...             'param_name': 'Start__Page',
  214.15 +...             'value': 'www.google.it'}            
  214.16 +
  214.17 +## parsing a simple line (w/o comment, w/o group)
  214.18 +>>> line = logon.Line('Start__Page  = www.google.it')
  214.19 +>>> vars(line) == line_dict
  214.20 +True
  214.21 +
  214.22 +## parsing a line with group & comment
  214.23 +>>> line = logon.Line('Start__Page[admins]  = www.google.it')
  214.24 +>>> line_dict.update({
  214.25 +...            'group' : 'admins',
  214.26 +...            'line': 'Start__Page[admins]  = www.google.it'
  214.27 +...            })
  214.28 +>>> vars(line) == line_dict
  214.29 +True
  214.30 +        
  214.31 +## parsing a line with final comment
  214.32 +>>> line = logon.Line('Start__Page[admins]  = www.google.it  # comment')
  214.33 +>>> line_dict.update({
  214.34 +...           'group' : 'admins',
  214.35 +...           'line': 'Start__Page[admins]  = www.google.it  # comment',
  214.36 +...           'final_comment' : '  # comment',
  214.37 +...           })
  214.38 +>>> vars(line) == line_dict
  214.39 +True
  214.40 +
  214.41 +## parsing a line with ";"
  214.42 +>>> line = logon.Line('ExcludeProfileDirs   = Impostazioni locali;Temporary Internet Files;Cronologia;Temp;Documenti;Cookies;SendTo')
  214.43 +>>> line.group is None
  214.44 +True
  214.45 +>>> print line.param_name
  214.46 +ExcludeProfileDirs
  214.47 +>>> print line.value
  214.48 +Impostazioni locali;Temporary Internet Files;Cronologia;Temp;Documenti;Cookies;SendTo
  214.49 +
  214.50 +## parsing a line with only driver
  214.51 +>>> line = logon.Line('_NetFolder[Z] = software')
  214.52 +>>> line.group is None
  214.53 +True
  214.54 +
  214.55 +>>> line.drive
  214.56 +'Z'
  214.57 +
  214.58 +## parsing a comment line
  214.59 +>>> line = logon.Line('#_NetFolder[Z] = software')
  214.60 +>>> line.is_comment
  214.61 +True
  214.62 +
  214.63 +>>> line = logon.Line(' # _NetFolder[Z] = software')
  214.64 +>>> line.is_comment
  214.65 +True
  214.66 +
  214.67 +## building a line w/o value
  214.68 +>>> line = logon.Line(param_name='Start__Page')
  214.69 +>>> print line 
  214.70 +Start__Page = 
  214.71 +
  214.72 +## building a line w/o group
  214.73 +>>> line = logon.Line(param_name='Start__Page', value='www.google.it', group=None)
  214.74 +>>> str(line) == 'Start__Page = www.google.it'
  214.75 +True
  214.76 +
  214.77 +## building a line with group
  214.78 +>>> line = logon.Line(param_name='Start__Page', value='www.google.it', group='admins')
  214.79 +>>> str(line) == 'Start__Page[admins] = www.google.it'
  214.80 +True
  214.81 +
  214.82 +## building a line with group
  214.83 +>>> line = logon.Line(param_name='Start__Page', group='alunni', value='facebook.it', )
  214.84 +>>> str(line) == 'Start__Page[alunni] = facebook.it'
  214.85 +True
  214.86 +
  214.87 +## building a line with drive
  214.88 +>>> line = logon.Line(param_name='_NetFolder', value='software', group='admins', drive='S')
  214.89 +>>> str(line) == '_NetFolder[S:admins] = software'
  214.90 +True
  214.91 +
  214.92 +## building a line from args
  214.93 +>>> line = logon.Line(param_name='_NetFolder', value='software', drive='S')
  214.94 +>>> str(line) == '_NetFolder[S] = software'
  214.95 +True
  214.96 +
  214.97 +### URL generation
  214.98 +>>> line = logon.Line(param_name='_NetFolder', value='software', drive='S')
  214.99 +>>> print line.url
 214.100 +/_NetFolder/?param_name=_NetFolder&drive=S
 214.101 +
 214.102 +>>> line = logon.Line(param_name='_NetFolder', value='software', group='docenti', drive='S')
 214.103 +>>> print line.url
 214.104 +/_NetFolder/?param_name=_NetFolder&group=docenti&drive=S
 214.105 +
 214.106 +>>> line = logon.Line(param_name='Start__Page', value='www.google.it', group='admins')
 214.107 +>>> print line.url
 214.108 +/Start__Page/?param_name=Start__Page&group=admins
 214.109 +
 214.110 +####################################
 214.111 +#### Logon: reading a conf file
 214.112 +####################################
 214.113 +
 214.114 +>>> conf = logon.Logon(text=logon.__doc__)
 214.115 +>>> sp = conf.get_param('Start__Page', 'admins')
 214.116 +>>> len(sp)
 214.117 +1
 214.118 +
 214.119 +## group=None: group is not defined
 214.120 +>>> sp = conf.get_param('Start__Page', group=None)
 214.121 +>>> for l in sp: print l
 214.122 +Start__Page = www.google.it  #
 214.123 +
 214.124 +## group=False: any group or group not defined
 214.125 +>>> c1 = logon.Logon(filename='data/logon.conf')
 214.126 +>>> sp = c1.get_param('Start__Page', group=False)
 214.127 +>>> for l in sp: print l
 214.128 +Start__Page = www.google.it
 214.129 +Start__Page[admins] = www.google.it
 214.130 +
 214.131 +>>> sp = c1.get_param('_NetFolder', drive='Z')
 214.132 +>>> for l in sp: print l
 214.133 +_NetFolder[Z] = software
 214.134 +
 214.135 +## DebugShare
 214.136 +>>> c1 = logon.Logon(filename='data/logon.conf')
 214.137 +>>> param = c1.get_param('_DebugUsers', group=False)
 214.138 +
 214.139 +
 214.140 +### change a Start__Page for admins
 214.141 +>>> c1 = logon.Logon(filename='data/logon.conf')
 214.142 +>>> c2 = logon.Logon(filename='data/logon.conf')
 214.143 +>>> param = c2.set_param('Start__Page', value='http://www.istruzione.it', group='admins')
 214.144 +>>> len(c1), len(c2)
 214.145 +(248, 248)
 214.146 +
 214.147 +>>> print c1.diff(c2, 'c1.conf', 'c2.conf')
 214.148 +--- c1.conf 
 214.149 ++++ c2.conf 
 214.150 +@@ -52,7 +52,7 @@
 214.151 +<BLANKLINE>
 214.152 + ### WinSet sezione 'start_page'
 214.153 + Start__Page = www.google.it
 214.154 +-Start__Page[admins] = www.google.it
 214.155 ++Start__Page[admins] = http://www.istruzione.it
 214.156 +<BLANKLINE>
 214.157 + ### WinSet sezione 'proxy'
 214.158 + ProxyServer = XXX.XXX.XXX:8128     # DansGuardian
 214.159 +<BLANKLINE>
 214.160 +
 214.161 +### add a Start__Page for docenti
 214.162 +>>> c1 = logon.Logon(filename='data/logon.conf')
 214.163 +>>> c2 = logon.Logon(filename='data/logon.conf')
 214.164 +>>> param = c2.set_param('Start__Page', value='http://www.istruzione.it', group='docenti')
 214.165 +>>> len(c1), len(c2)
 214.166 +(248, 249)
 214.167 +
 214.168 +>>> print c1.diff(c2, 'c1.conf', 'c2.conf')
 214.169 +--- c1.conf 
 214.170 ++++ c2.conf 
 214.171 +@@ -53,6 +53,7 @@
 214.172 + ### WinSet sezione 'start_page'
 214.173 + Start__Page = www.google.it
 214.174 + Start__Page[admins] = www.google.it
 214.175 ++Start__Page[docenti] = http://www.istruzione.it
 214.176 +<BLANKLINE>
 214.177 + ### WinSet sezione 'proxy'
 214.178 + ProxyServer = XXX.XXX.XXX:8128     # DansGuardian
 214.179 +<BLANKLINE>
 214.180 +
 214.181 +### add a _NetFolder for docenti
 214.182 +>>> c1 = logon.Logon(filename='data/logon.conf')
 214.183 +>>> c2 = logon.Logon(filename='data/logon.conf')
 214.184 +>>> param = c2.set_param('_NetFolder', value='software', group='docenti', drive="Z")
 214.185 +>>> len(c1), len(c2)
 214.186 +(248, 249)
 214.187 +
 214.188 +>>> print c1.diff(c2, 'c1.conf', 'c2.conf')
 214.189 +--- c1.conf 
 214.190 ++++ c2.conf 
 214.191 +@@ -223,6 +223,7 @@
 214.192 + _NetFolder[K:docenti] = classi
 214.193 + _NetFolder[K:admins] = classi
 214.194 + _NetFolder[X:admins] = dati
 214.195 ++_NetFolder[Z:docenti] = software
 214.196 +<BLANKLINE>
 214.197 + ### sincronizzazione orologio
 214.198 +<BLANKLINE>
 214.199 +<BLANKLINE>
 214.200 +
 214.201 +>>> c1 = logon.Logon(filename='data/logon.conf')
 214.202 +>>> c2 = logon.Logon(filename='data/logon.conf')
 214.203 +>>> param = c2.del_param('_NetTime')
 214.204 +>>> print c1.diff(c2, 'c1.conf', 'c2.conf')
 214.205 +--- c1.conf 
 214.206 ++++ c2.conf 
 214.207 +@@ -226,7 +226,6 @@
 214.208 +<BLANKLINE>
 214.209 + ### sincronizzazione orologio
 214.210 +<BLANKLINE>
 214.211 +-_NetTime = 1
 214.212 +<BLANKLINE>
 214.213 + ### forzatura ambiente di default (desktop, menu avvio ecc.ecc.)
 214.214 + ### la si ottiene copiando la seguente cartella
 214.215 +<BLANKLINE>
 214.216 +
 214.217 +>>> c1 = logon.Logon(filename='data/logon.conf')
 214.218 +>>> c2 = logon.Logon(filename='data/logon.conf')
 214.219 +>>> param = c2.del_param('_NetTime', value='1')
 214.220 +>>> print c1.diff(c2, 'c1.conf', 'c2.conf')
 214.221 +--- c1.conf 
 214.222 ++++ c2.conf 
 214.223 +@@ -226,7 +226,6 @@
 214.224 +<BLANKLINE>
 214.225 + ### sincronizzazione orologio
 214.226 +<BLANKLINE>
 214.227 +-_NetTime = 1
 214.228 +<BLANKLINE>
 214.229 + ### forzatura ambiente di default (desktop, menu avvio ecc.ecc.)
 214.230 + ### la si ottiene copiando la seguente cartella
 214.231 +<BLANKLINE>
 214.232 +
 214.233 +>>> param = c2.set_param('_NetTime', 1, group='admins')
 214.234 +>>> print c1.diff(c2, 'c1.conf', 'c2.conf')
 214.235 +--- c1.conf 
 214.236 ++++ c2.conf 
 214.237 +@@ -226,7 +226,6 @@
 214.238 +<BLANKLINE>
 214.239 + ### sincronizzazione orologio
 214.240 +<BLANKLINE>
 214.241 +-_NetTime = 1
 214.242 +<BLANKLINE>
 214.243 + ### forzatura ambiente di default (desktop, menu avvio ecc.ecc.)
 214.244 + ### la si ottiene copiando la seguente cartella
 214.245 +@@ -246,3 +245,4 @@
 214.246 + ### correttamente configurato si rivela sostanzialmente inutile
 214.247 +<BLANKLINE>
 214.248 + _EnvWinXP = 0
 214.249 ++_NetTime[admins] = 1
 214.250 +<BLANKLINE>
   215.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   215.2 +++ b/tests/mac.txt	Mon Apr 26 11:16:23 2010 +0200
   215.3 @@ -0,0 +1,108 @@
   215.4 +# -*- mode: python -*-
   215.5 +### test Mac
   215.6 +
   215.7 +>>> import sys
   215.8 +>>> sys.path.insert(0, '..')
   215.9 +>>> from isi.conf import mac, tools
  215.10 +
  215.11 +## a Line from a line
  215.12 +>>> l = mac.Line('dhcp-host=00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2 # comment')
  215.13 +>>> l.param_name
  215.14 +'dhcp-host'
  215.15 +
  215.16 +>>> l.value
  215.17 +'00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2'
  215.18 +
  215.19 +
  215.20 +## a lien from values
  215.21 +>>> l = mac.Line(param_name='dhcp-host', value='00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2')
  215.22 +>>> print l
  215.23 +dhcp-host=00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2
  215.24 +
  215.25 +>>> l.mac
  215.26 +'00:0c:29:c0:d7:9e'
  215.27 +
  215.28 +>>> l = mac.Line('dhcp-host=00:0c,192.168.96.198,vm-client-ltsp2 # comment')
  215.29 +Traceback (most recent call last):
  215.30 +...
  215.31 +WrongMACError: dhcp-host is not a valid MAC Address
  215.32 +
  215.33 +>>> l = mac.Line(param_name='dhcp-host', value='00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2')
  215.34 +>>> l.ip, l.hostname, l.tag
  215.35 +('192.168.96.198', 'vm-client-ltsp2', '')
  215.36 +
  215.37 +>>> l = mac.Line(param_name='dhcp-host', value='00:0c:29:c0:d7:9e,vm-client-ltsp2')
  215.38 +>>> l.ip, l.hostname, l.tag
  215.39 +('', 'vm-client-ltsp2', '')
  215.40 +
  215.41 +>>> l = mac.Line(param_name='dhcp-host', value='00:0c:29:c0:d7:9e,net:ns1')
  215.42 +>>> l.ip, l.hostname, l.tag
  215.43 +('', '', 'net:ns1')
  215.44 +
  215.45 +
  215.46 +>>> l = mac.Line(param_name='dhcp-host', value='00:0c:29:c0:d7:9e,192.168.1.1')
  215.47 +>>> l.ip, l.hostname, l.tag
  215.48 +('192.168.1.1', '', '')
  215.49 +
  215.50 +
  215.51 +###########
  215.52 +## a file
  215.53 +###########
  215.54 +
  215.55 +>>> h0 = mac.Mac('data/etc/hosts.mac')
  215.56 +>>> len(h0.lines)
  215.57 +2
  215.58 +
  215.59 +>>> lines = h0.get_param(param_name='dhcp-host')
  215.60 +>>> len(lines) 
  215.61 +2
  215.62 +
  215.63 +>>> lines = h0.get_param(param_name='dhcp-host', value='00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1')
  215.64 +>>> len(lines) 
  215.65 +1
  215.66 +
  215.67 +>>> h0.get_param(param_name='dhcp-host', mac='00:0c:29:10:a6:45')
  215.68 +[<dhcp-host 00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1>]
  215.69 +
  215.70 +>>> h0.get_param(param_name='dhcp-host', ip='192.168.96.199')
  215.71 +[<dhcp-host 00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1>]
  215.72 +
  215.73 +>>> h0.get_param(param_name='dhcp-host', tag='net:ns0')
  215.74 +[]
  215.75 +
  215.76 +>>> h0.get_param(param_name='dhcp-host', tag='net:ns1')
  215.77 +[<dhcp-host 00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2,net:ns1>]
  215.78 +
  215.79 +>>> lines[0].param_name
  215.80 +'dhcp-host'
  215.81 +
  215.82 +>>> h1 = mac.Mac('data/etc/hosts.mac')
  215.83 +>>> print h1.set_param('dhcp-host', value='00:0c:29:10:a6:46,192.168.96.200,vm-client-ltsp4')
  215.84 +dhcp-host=00:0c:29:10:a6:46,192.168.96.200,vm-client-ltsp4
  215.85 +
  215.86 +>>> print h0.diff(h1)
  215.87 +--- this.conf 
  215.88 ++++ other.conf 
  215.89 +@@ -1,2 +1,3 @@
  215.90 + dhcp-host=00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1
  215.91 + dhcp-host=00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2,net:ns1
  215.92 ++dhcp-host=00:0c:29:10:a6:46,192.168.96.200,vm-client-ltsp4
  215.93 +<BLANKLINE>
  215.94 +
  215.95 +## this should *change* the previous rather than adding as we cannot have 2 identical MACs
  215.96 +>>> h1 = mac.Mac('data/etc/hosts.mac')
  215.97 +>>> print h1.set_param('dhcp-host', value='00:0c:29:10:a6:45,192.168.96.190,vm-client-ltsp1')
  215.98 +dhcp-host=00:0c:29:10:a6:45,192.168.96.190,vm-client-ltsp1
  215.99 +
 215.100 +>>> print h0.diff(h1)
 215.101 +--- this.conf 
 215.102 ++++ other.conf 
 215.103 +@@ -1,2 +1,2 @@
 215.104 +-dhcp-host=00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1
 215.105 ++dhcp-host=00:0c:29:10:a6:45,192.168.96.190,vm-client-ltsp1
 215.106 + dhcp-host=00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2,net:ns1
 215.107 +<BLANKLINE>
 215.108 +
 215.109 +>>> tools.is_mac_address('00:0c:29:10:a6:46')
 215.110 +True
 215.111 +
   216.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   216.2 +++ b/tests/ntests.sh	Mon Apr 26 11:16:23 2010 +0200
   216.3 @@ -0,0 +1,4 @@
   216.4 +#!/bin/bash
   216.5 +
   216.6 +
   216.7 +nosetests --pdb-failure -v
   217.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   217.2 +++ b/tests/runtests.py	Mon Apr 26 11:16:23 2010 +0200
   217.3 @@ -0,0 +1,33 @@
   217.4 +#!/usr/bin/python
   217.5 +
   217.6 +import os
   217.7 +import sys
   217.8 +import doctest
   217.9 +import sys
  217.10 +
  217.11 +os.environ['LANG'] = 'C'
  217.12 +sys.path.insert(0, os.path.join(os.path.dirname(os.getcwd()), 'lib'))
  217.13 +
  217.14 +files = (
  217.15 +    'logon.txt',
  217.16 +    'hosts.txt',
  217.17 +    'dnsmasq.txt',
  217.18 +    'mac.txt',
  217.19 +    )
  217.20 +
  217.21 +if sys.argv[1:]:
  217.22 +    files = sys.argv[1:]
  217.23 +
  217.24 +for filename in files:
  217.25 +    print filename
  217.26 +    doctest.testfile(filename)
  217.27 +
  217.28 +
  217.29 +#nosetests --pdb-failure --with-doctest --doctest-extension=txt filename
  217.30 +#nosetests --pdb-failure 
  217.31 +    
  217.32 +
  217.33 +    
  217.34 +
  217.35 +    
  217.36 +
   218.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   218.2 +++ b/tests/user_isi_adduser.py	Mon Apr 26 11:16:23 2010 +0200
   218.3 @@ -0,0 +1,227 @@
   218.4 +import os
   218.5 +import re
   218.6 +import isi
   218.7 +import unittest
   218.8 +from dry.functions import execute
   218.9 +from nose import tools
  218.10 +import shutil
  218.11 +
  218.12 +def setup():
  218.13 +    print "killing nscd"
  218.14 +    execute('killall nscd')
  218.15 +    os.system('rm -Rf /home/users/docenti/*')
  218.16 +    l = isi.Manager()
  218.17 +    for name in ('d_test100', 'd_test101', 'd_test102'):
  218.18 +        try:
  218.19 +            l.del_user(name, )
  218.20 +        except isi.exc.MissingMatch:
  218.21 +            pass
  218.22 +
  218.23 +class AddDelUser(unittest.TestCase):
  218.24 +    __test__ = False
  218.25 +    #__test__ = True
  218.26 +    def setUp(self):
  218.27 +        self.conn = isi.IsiConn()
  218.28 +        self.l = isi.Manager(self.conn)
  218.29 +        self.l.home_mode = 'rm'
  218.30 +
  218.31 +    def execute(self, cmd):
  218.32 +        ret_code, out, err = execute(cmd)
  218.33 +        assert ret_code == 0, "ret_code: %s: OUT=%s, ERR=%s" % (ret_code, out, err)
  218.34 +        return out, err
  218.35 +        
  218.36 +    def execute_ko(self, cmd):
  218.37 +        ret_code, out, err = execute(cmd)
  218.38 +        assert ret_code != 0, "ret_code: %s: OUT=%s, ERR=%s" % (ret_code, out, err)
  218.39 +        return out, err
  218.40 +        
  218.41 +    def test_01a_del_user_group(self):
  218.42 +        ## clear any user from docenti
  218.43 +        self.execute('isi-deluser -g docenti --home rm')
  218.44 +        
  218.45 +    def test_01b_del_home(self):
  218.46 +        ## clear any user from docenti
  218.47 +        assert not os.path.exists('/home/users/docenti/d_test100')
  218.48 +        assert not os.path.exists('/home/users/docenti/d_test101')
  218.49 +        assert not os.path.exists('/home/users/docenti/d_test102')
  218.50 +        assert not os.path.exists('/home/users/docenti/d_test100.tgz')
  218.51 +        assert not os.path.exists('/home/users/docenti/d_test101.tgz')
  218.52 +        assert not os.path.exists('/home/users/docenti/d_test102.tgz')
  218.53 +        
  218.54 +    def test_02_isi_adduser(self):
  218.55 +        ## add d_test100
  218.56 +        self.execute(['isi-adduser', '-T', '-t', 'd_test100;docenti;isi'])
  218.57 +    
  218.58 +    def test_03_isi_groupcat(self):
  218.59 +        # verify it's in group docenti
  218.60 +        out, err = self.execute('isi-groupcat docenti')
  218.61 +        assert 'd_test100' in out.split()
  218.62 +    
  218.63 +    def test_03b_user_exists(self):
  218.64 +        assert self.l.user_exists('d_test100')
  218.65 +    
  218.66 +    def test_04_del_user(self):
  218.67 +        ## default: deletes the home directory, leaves the .tar.gz
  218.68 +        self.execute('isi-deluser d_test100')
  218.69 +        assert not os.path.exists('/home/users/docenti/d_test100')
  218.70 +        assert os.path.exists('/home/users/docenti/d_test100.tgz')
  218.71 +
  218.72 +    ## again isi-addusers but normal -s "string_definition"
  218.73 +    def test_05_isi_addusers(self):
  218.74 +        assert not self.l.user_exists('d_test101')
  218.75 +        assert not self.l.user_exists('d_test102')
  218.76 +        self.execute(['isi-adduser', '-T', '-s', "d_test101;Test;Docente;docenti;;CF1;isi"])
  218.77 +        self.execute(['isi-adduser', '-T', '-s', "d_test102;Test;Docente;docenti;;CF2;isi"])
  218.78 +
  218.79 +    def test_06_isi_groupcat(self):
  218.80 +        out, err = self.execute('isi-groupcat docenti')
  218.81 +        assert 'd_test101' in out.split()
  218.82 +    
  218.83 +    def test_07a_password_ok(self):
  218.84 +        assert self.l.test_password('d_test101', 'isi')
  218.85 +
  218.86 +    def test_07b_password_ko(self):
  218.87 +        assert not self.l.test_password('d_test101', 'isi_ko')
  218.88 +
  218.89 +    def test_08a_smb_password_ok(self):
  218.90 +        assert self.l.test_samba_password('d_test101', 'isi')
  218.91 +
  218.92 +    def test_08b_smb_password_ko(self):
  218.93 +        assert not self.l.test_samba_password('d_test101', 'isi_ko')
  218.94 +
  218.95 +    def test_08c_set_passwd(self):
  218.96 +        assert not self.l.test_password('d_test101', 'new_pwd')
  218.97 +        assert not self.l.test_samba_password('d_test101', 'new_pwd')
  218.98 +
  218.99 +    def test_09_groupcat_r(self):
 218.100 +        OUT = """d_test101;Test;Docente;docenti;;CF1;\nd_test102;Test;Docente;docenti;;CF2;\n"""
 218.101 +        
 218.102 +        out, err = self.execute('isi-groupcat -r docenti')
 218.103 +        assert OUT == out
 218.104 +
 218.105 +    def test_09a_del_no_home(self):
 218.106 +        self.execute('isi-deluser  --zap-home d_test101')
 218.107 +        assert not os.path.exists('/home/users/docenti/d_test101')
 218.108 +        assert not os.path.exists('/home/users/docenti/d_test101.tgz')
 218.109 +        
 218.110 +    def test_09b_del_leave_home(self):
 218.111 +        self.execute('isi-deluser  -H none d_test102')
 218.112 +        assert os.path.exists('/home/users/docenti/d_test102')
 218.113 +        
 218.114 +    ## again isi-addusers but normal -s "string_definition", using -p _cf
 218.115 +    def test_10a_isi_addusers_pass_cf(self):
 218.116 +        self.execute('rm -Rf /home/users/docenti/d_test102')
 218.117 +        self.execute(['isi-adduser', '-T', '--use-cf', '-s', "d_test101;Test;Docente;docenti;;DNTLSN63D07Z404Z;isi"])
 218.118 +        self.execute(['isi-adduser', '-T', '--use-cf', '-s', "d_test102;Test;Docente;docenti;;CCCNMN73F4ZP404Z;isi"])
 218.119 +
 218.120 +    def test_10b_password_cf(self):
 218.121 +        assert self.l.test_password('d_test101', 'Dntlsn63')
 218.122 +
 218.123 +    def test_10b_samba_password_cf(self):
 218.124 +        assert self.l.test_samba_password('d_test101', 'Dntlsn63')
 218.125 +
 218.126 +    def test_11a_isi_passwd(self):
 218.127 +        self.execute('isi-passwd -p isi2 d_test101')
 218.128 +
 218.129 +    def test_11b_test_passwd(self):
 218.130 +        assert self.l.test_password('d_test101', 'isi2')
 218.131 +        
 218.132 +    def test_11b_test_samba_passwd(self):
 218.133 +        assert self.l.test_samba_password('d_test101', 'isi2')
 218.134 +        
 218.135 +
 218.136 +class IsiUserFromFile(unittest.TestCase):
 218.137 +    __test__ = True
 218.138 +
 218.139 +    def setUp(self):
 218.140 +        self.conn = isi.IsiConn()
 218.141 +        self.l = isi.Manager(self.conn)
 218.142 +        self.l.home_mode = 'rm'
 218.143 +
 218.144 +    def execute(self, cmd):
 218.145 +        ret_code, out, err = execute(cmd)
 218.146 +        assert ret_code == 0, "ret_code: %s: OUT=%s, ERR=%s" % (ret_code, out, err)
 218.147 +        return out, err
 218.148 +        
 218.149 +    def test_00_delete(self):
 218.150 +        self.execute('isi-deluser -T -f data/users_test.isi -z')
 218.151 +
 218.152 +
 218.153 +    ## utenti da file - password in file
 218.154 +    def test_01a_isi_addusers_file(self):
 218.155 +        self.execute('isi-adduser -T -f data/users_test.isi --non-interactive')
 218.156 +        assert self.l.user_exists('a_test')
 218.157 +        
 218.158 +    def test_01a_passwd(self):
 218.159 +        assert self.l.test_password('a_test', 'isi')
 218.160 +
 218.161 +    def test_01b_samba_passwd(self):
 218.162 +        assert self.l.test_samba_password('a_test', 'isi', client=False)
 218.163 +
 218.164 +    def test_01c_isi_addusers_file(self):
 218.165 +        assert self.l.user_exists('a_test')
 218.166 +        
 218.167 +    def test_01d_update_samba_passwd(self):
 218.168 +        assert self.l.user_exists('a_test')
 218.169 +        self.execute('isi-adduser -T -f data/users_test.isi --default-passwd ok --update-passwd')
 218.170 +        assert self.l.test_samba_password('a_test', 'ok', client=False)
 218.171 +
 218.172 +    def test_13a_del_file(self):
 218.173 +        self.execute('isi-deluser -T -f data/users_test.isi -z')
 218.174 +
 218.175 +    def test_13b_del_home(self):
 218.176 +        assert not os.path.exists('/home/users/docenti/d_test')
 218.177 +        assert not os.path.exists('/home/users/docenti/d_test.tgz')
 218.178 +
 218.179 +    def test_13c_del_user(self):
 218.180 +        assert not self.l.user_exists('d_test')
 218.181 +        assert not self.l.user_exists('ad_test')
 218.182 +        assert not self.l.user_exists('at_test')
 218.183 +        
 218.184 +    ## utenti da file - password _cf
 218.185 +    def test_14a_isi_addusers_file(self):
 218.186 +        self.execute('isi-adduser -ZT --use-cf --default-passwd blabla -f data/users_test.isi')
 218.187 +        
 218.188 +    def test_14a_passwd(self):
 218.189 +        assert self.l.test_password('d_test', 'Dntlsn63')
 218.190 +        assert self.l.test_password('ad_test', 'Dntlsn63')
 218.191 +        assert self.l.test_password('at_test', 'Dntlsn63')
 218.192 +
 218.193 +    def test_14b_samba_passwd(self):
 218.194 +        assert self.l.test_samba_password('d_test', 'Dntlsn63')
 218.195 +        assert self.l.test_samba_password('ad_test', 'Dntlsn63')
 218.196 +        assert self.l.test_samba_password('at_test', 'Dntlsn63')
 218.197 +
 218.198 +    def test_15b_del_user(self):
 218.199 +        assert self.l.user_exists('d_test')
 218.200 +        assert self.l.user_exists('ad_test')
 218.201 +        assert self.l.user_exists('at_test')
 218.202 +
 218.203 +    def test_16a_modify(self):
 218.204 +        "fails becouse update is not allowed if not explicitly required"
 218.205 +        ret_code, out, err = execute('isi-adduser -T -f data/users_misc.isi -z -Z')        
 218.206 +        assert ret_code
 218.207 +
 218.208 +    def test_16b_modify(self):
 218.209 +        self.l.get_samba_user('ad_test').set_password('xxx')
 218.210 +        self.execute('isi-adduser -T -f data/users_misc.isi -z --update-user -Z')        
 218.211 +
 218.212 +    def test_16c_changed_group(self):
 218.213 +        assert self.l.user_in_group('a_test', 'classe_test2')
 218.214 +        
 218.215 +    def test_16d_changed_group2(self):
 218.216 +        assert not self.l.user_in_group('a_test', 'classe_test')
 218.217 +
 218.218 +    def test_16e_deleted(self):
 218.219 +        assert not self.l.user_exists('a_tests')
 218.220 +        assert not os.path.exists('/home/users/alunni/a_test2')
 218.221 +        assert not os.path.exists('/home/users/alunni/a_test2.tgz')
 218.222 +        
 218.223 +    def test_16f_unmodified(self):
 218.224 +        "update-user doesn't change password"
 218.225 +        assert self.l.user_exists('ad_test')
 218.226 +        assert not self.l.test_password('ad_test', 'isi2')
 218.227 +        assert self.l.test_password('ad_test', 'xxx')
 218.228 +
 218.229 +    def test_16g_del_file(self):
 218.230 +        self.execute('isi-deluser -T -f data/users_test.isi -z')
   219.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   219.2 +++ b/tests/user_lib_test.py	Mon Apr 26 11:16:23 2010 +0200
   219.3 @@ -0,0 +1,339 @@
   219.4 +import os
   219.5 +import re
   219.6 +import isi
   219.7 +import unittest
   219.8 +from dry.functions import execute
   219.9 +from nose import tools
  219.10 +import shutil
  219.11 +import logging
  219.12 +from isi.parser import UserParser
  219.13 +
  219.14 +def setup():
  219.15 +    global l
  219.16 +    conn = isi.IsiConn()
  219.17 +    l = isi.Manager()
  219.18 +    l.logger.setLevel(logging.critical)
  219.19 +    
  219.20 +    print "killing nscd"
  219.21 +    execute('killall nscd')
  219.22 +    execute('rm -Rf /home/users/docenti/*')
  219.23 +
  219.24 +class ParserUser(unittest.TestCase):
  219.25 +
  219.26 +#    __test__ = False
  219.27 +    __test__ = True
  219.28 +
  219.29 +    def setUp(self):
  219.30 +        self.opts = {
  219.31 +            'no_filesystem'       : None,
  219.32 +            'update_user'         : None,
  219.33 +            'update_passwd'       : None,
  219.34 +            'force_passwd_change' : None,
  219.35 +            'default_passwd'      : None,
  219.36 +            'use_cf'              : None,
  219.37 +            'passwd_random'       : None,
  219.38 +            'run_alulink'         : None,
  219.39 +            }
  219.40 +
  219.41 +    def test_00_del_user_group(self):
  219.42 +        ## clear any user from docenti
  219.43 +        docenti = l.get_group('docenti')
  219.44 +        docenti.delete_members(home_mode='rm')
  219.45 +
  219.46 +        docenti = l.get_group('alunni')
  219.47 +        docenti.delete_members(home_mode='rm')
  219.48 +
  219.49 +    def test_01a_action_add(self):
  219.50 +        proxy = UserParser(l, 'd_test;Docente;Test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.51 +        assert proxy.action == 'add'
  219.52 +
  219.53 +    def test_01b_action_del(self):
  219.54 +        proxy = UserParser(l, '-d_test;Docente;Test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.55 +        assert proxy.action == 'delete'
  219.56 +    
  219.57 +    @tools.raises(isi.exc.AlreadyExistingUser)
  219.58 +    def test_02a_action_update(self):
  219.59 +        ## create a user
  219.60 +        l.parse_user_definition_string("d_test;Test;Docente;docenti;;DNTLSN63D07;isi")
  219.61 +        proxy = UserParser(l, 'd_test;Docente;Test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.62 +
  219.63 +    def test_02a_action_update(self):
  219.64 +        l.parse_user_definition_string("d_test;Test;Docente;docenti;;DNTLSN63D07;isi")
  219.65 +        self.opts['update_user'] = True
  219.66 +        proxy = UserParser(l, 'd_test;Docente;Test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.67 +        assert proxy.action == 'update'
  219.68 +
  219.69 +    # attributi
  219.70 +    def test_03b_logname(self):
  219.71 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.72 +        assert proxy.logname == 'd_test1'
  219.73 +        
  219.74 +    def test_03c_first_name(self):
  219.75 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.76 +        assert proxy.first_name == 'Test'
  219.77 +        
  219.78 +    def test_03d_last_name(self):
  219.79 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.80 +        assert proxy.last_name == 'Docente'
  219.81 +
  219.82 +    def test_03e_maingrop(self):
  219.83 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.84 +        assert proxy.maingroup == 'docenti'
  219.85 +
  219.86 +    def test_03f_classe(self):
  219.87 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.88 +        assert proxy.classe == None
  219.89 +
  219.90 +    def test_03g_cf(self):
  219.91 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;dntlsn63d07;isi', **self.opts)
  219.92 +        assert proxy.cf == 'DNTLSN63D07'
  219.93 +
  219.94 +    def test_03g_password(self):
  219.95 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
  219.96 +        assert proxy.passwd == 'isi'
  219.97 +
  219.98 +    def test_03h_password_cf(self):
  219.99 +        self.opts['use_cf'] = True
 219.100 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07', **self.opts)
 219.101 +        assert proxy.passwd == 'Dntlsn63'
 219.102 +
 219.103 +    def test_03h_password_cf_password_present(self):
 219.104 +        self.opts['use_cf'] = True
 219.105 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
 219.106 +        assert proxy.passwd == 'Dntlsn63'
 219.107 +
 219.108 +    def test_03h_password_random(self):
 219.109 +        self.opts['passwd_random'] = True
 219.110 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
 219.111 +        ## well, at least is none of these...
 219.112 +        assert proxy.passwd not in ('Dntlsn63', 'isi', None)
 219.113 +    
 219.114 +    def test_04a_passwd_update_false(self):
 219.115 +        ## even if you have use_cf, since d_test is already present (=> action is update)
 219.116 +        ## passwd is not updated
 219.117 +        self.opts['use_cf'] = True
 219.118 +        self.opts['update_user'] = True
 219.119 +        self.opts['update_passwd'] = False
 219.120 +        proxy = UserParser(l, 'd_test;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
 219.121 +        ## well, at least is none of these...
 219.122 +        assert proxy.passwd == None
 219.123 +    
 219.124 +    def test_04b_passwd_update_true(self):
 219.125 +        ## even if you have use_cf, since d_test is already present (=> action is update)
 219.126 +        ## passwd is not updated
 219.127 +        self.opts['use_cf'] = True
 219.128 +        self.opts['update_user'] = True
 219.129 +        self.opts['update_passwd'] = True
 219.130 +        proxy = UserParser(l, 'd_test;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
 219.131 +        ## well, at least is none of these...
 219.132 +        assert proxy.passwd == 'Dntlsn63'
 219.133 +        
 219.134 +    def test_04c_cf_wins_over_default(self):
 219.135 +        self.opts['use_cf'] = True
 219.136 +        self.opts['default_passwd'] = 'ciao'
 219.137 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
 219.138 +        ## well, at least is none of these...
 219.139 +        assert proxy.passwd == 'Dntlsn63'
 219.140 +        
 219.141 +    def test_04d_default_passwd(self):
 219.142 +        self.opts['default_passwd'] = 'ciao'
 219.143 +        proxy = UserParser(l, 'd_test1;docente;test;docenti;;DNTLSN63D07;isi', **self.opts)
 219.144 +        ## well, at least is none of these...
 219.145 +        assert proxy.passwd == 'ciao'
 219.146 +
 219.147 +    # classe
 219.148 +    def test_05a_classe_in_proxy(self):
 219.149 +        """user class attributes gets correctly set"""
 219.150 +        self.opts.update({'default_passwd' : 'ciao', 'interactive' : False})
 219.151 +        proxy = UserParser(l, 'a_test;Alunno;test;alunni;classe_test;DNTLSN63D07;isi', **self.opts)
 219.152 +        ## well, at least is none of these...
 219.153 +        assert proxy.classe == 'classe_test'
 219.154 +
 219.155 +class Extended(unittest.TestCase):
 219.156 +
 219.157 +    def setUp(self):
 219.158 +        self.opts = {
 219.159 +            'no_filesystem'       : None,
 219.160 +            'update_user'         : None,
 219.161 +            'update_passwd'       : None,
 219.162 +            'force_passwd_change' : None,
 219.163 +            'default_passwd'      : None,
 219.164 +            'use_cf'              : None,
 219.165 +            'passwd_random'       : None,
 219.166 +            'run_alulink'         : None,
 219.167 +            }
 219.168 +
 219.169 +
 219.170 +    def test_06a_extended(self):
 219.171 +        l.del_user('a_test_ext', quiet=True)
 219.172 +        definition = "a_test_ext;carboni;michela;alunni;ige3a;crbmhl94a58i829c;XPWDX;f;" +\
 219.173 +                     "via rocca 5c;morbegno;23017;so;0342615240;p3406429865;18/1/1994;sondrio;" +\
 219.174 +                     "so;3;carboni;mauro;artoni;paola"
 219.175 +        self.opts.update({'default_passwd' : 'ciao', 'interactive' : False})
 219.176 +        self.proxy = UserParser(l, definition, **self.opts)
 219.177 +        assert self.proxy
 219.178 +        assert self.proxy.address == 'via rocca 5c'
 219.179 +        assert self.proxy.city == 'morbegno'
 219.180 +        assert self.proxy.zip == '23017'
 219.181 +        assert self.proxy.phone == '0342615240'
 219.182 +        assert self.proxy.sex == 'f'
 219.183 +
 219.184 +    def test_06b_extended_user(self):
 219.185 +        l.del_user('a_test_ext', quiet=True)
 219.186 +        definition = "a_test_ext;carboni;michela;alunni;ige3a;crbmhl94a58i829c;XPWDX;f;" +\
 219.187 +                     "via rocca 5c;morbegno;23017;so;0342615240;p3406429865;18/1/1994;sondrio;" +\
 219.188 +                     "so;3;carboni;mauro;artoni;paola"
 219.189 +        self.opts.update({'default_passwd' : 'ciao', 'interactive' : False})
 219.190 +        l.parse_user_definition_string(definition, force_passwd_change=False)
 219.191 +
 219.192 +    def test_06c_extended_user2(self):
 219.193 +        user = l.get_user('a_test_ext')
 219.194 +        assert user.sex == u'f'
 219.195 +        assert user.address == u'via rocca 5c'
 219.196 +        assert user.city == u'morbegno'
 219.197 +        assert user.zip_code == u'23017'
 219.198 +        assert user.phone == u'0342615240'
 219.199 +
 219.200 +
 219.201 +class ParserMethod(unittest.TestCase):
 219.202 +
 219.203 +    def setUp(self):
 219.204 +        self.conn = isi.IsiConn()
 219.205 +        l = isi.Manager(self.conn)
 219.206 +        self.conn.logger.setLevel(logging.critical)
 219.207 +        self.opts = {
 219.208 +            'no_filesystem'       : None,
 219.209 +            'update_user'         : None,
 219.210 +            'update_passwd'       : None,
 219.211 +            'force_passwd_change' : None,
 219.212 +            'default_passwd'      : None,
 219.213 +            'use_cf'              : None,
 219.214 +            'passwd_random'       : None,
 219.215 +            'run_alulink'         : None,
 219.216 +            }
 219.217 +
 219.218 +
 219.219 +    def test_01_del_user_group(self):
 219.220 +        ## clear any user from docenti
 219.221 +        docenti = l.get_group('docenti')
 219.222 +        docenti.delete_members(home_mode='rm')
 219.223 +        alunni = l.get_group('alunni')
 219.224 +        alunni.delete_members(home_mode='rm')
 219.225 +
 219.226 +    def test_10d_add_from_string(self):
 219.227 +        l.parse_user_definition_string("d_test111;Test;Docente;docenti;;DNTLSN63D07;isi", force_passwd_change=False)
 219.228 +
 219.229 +    def test_10e_path_exists(self):
 219.230 +        assert os.path.exists('/home/users/docenti/d_test111')
 219.231 +
 219.232 +    def test_10f_test_pass(self):
 219.233 +        assert l.test_password('d_test111', 'isi')
 219.234 +
 219.235 +    def test_10g_test_samba_pass(self):
 219.236 +        assert l.test_samba_password('d_test111', 'isi', client=False)
 219.237 +        assert l.test_samba_password('d_test111', 'isi', client=True)
 219.238 +
 219.239 +    def test_11d_add_from_string(self):
 219.240 +        l.parse_user_definition_string("d_test112;Test;Docente;docenti;;DNTLSN63D07;isi", force_passwd_change=True)
 219.241 +
 219.242 +    def test_11e_path_exists(self):
 219.243 +        assert os.path.exists('/home/users/docenti/d_test112')
 219.244 +
 219.245 +    def test_11f_test_pass(self):
 219.246 +        assert l.test_password('d_test112', 'isi')
 219.247 +
 219.248 +    def test_11g_test_samba_pass(self):
 219.249 +        assert l.test_samba_password('d_test112', 'isi', client=False)
 219.250 +        assert not l.test_samba_password('d_test112', 'isi', client=True)
 219.251 +
 219.252 +    def test_11h_force_passwd_change(self):
 219.253 +        user = l.get_samba_user('d_test112')
 219.254 +        assert user.sambaPwdLastSet == 0
 219.255 +
 219.256 +    def test_12d_add_from_string(self):
 219.257 +        l.parse_user_definition_string("d_test122;Test;Docente;docenti;;DNTLSN63D07;isi", use_cf=True)
 219.258 +
 219.259 +    def test_12e_path_exists(self):
 219.260 +        assert os.path.exists('/home/users/docenti/d_test122')
 219.261 +
 219.262 +    def test_12f_test_pass(self):
 219.263 +        assert l.test_password('d_test122', 'Dntlsn63')
 219.264 +
 219.265 +    def test_12g_samba_test_pass(self):
 219.266 +        assert l.test_samba_password('d_test122', 'Dntlsn63', client=False)
 219.267 +
 219.268 +    # classe
 219.269 +    def test_12h_classe_in_user(self):
 219.270 +        self.opts.update({'default_passwd' : 'ciao', 'interactive' : False})
 219.271 +        proxy = l.parse_user_definition_string('a_test;Alunno;test;alunni;classe_test;DNTLSN63D07;isi', **self.opts)
 219.272 +        a = l.get_user('a_test')
 219.273 +        assert a.classe == 'classe_test'
 219.274 +
 219.275 +    # delete
 219.276 +    def test_12j_delete_user_by_string(self):
 219.277 +        l.parse_user_definition_string("-d_test122;Test;Docente;docenti;;DNTLSN63D07;isi")
 219.278 +        assert not l.user_exists('d_test122')
 219.279 +
 219.280 +    def test_12j_deleted_home(self):
 219.281 +        assert not os.path.exists('/home/users/docenti/d_test122')
 219.282 +        
 219.283 +    def test_12k_tgz(self):
 219.284 +        assert os.path.exists('/home/users/docenti/d_test122.tgz')
 219.285 +        
 219.286 +    def test_12m_dn(self):
 219.287 +        a = l.get_user('a_test')
 219.288 +        assert a.dn == u'uid=a_test,ou=People,dc=isi,dc=lan'
 219.289 +
 219.290 +    def test_12n_deleted_from_group_when_deleted(self):
 219.291 +        l.del_user('a_test')
 219.292 +        assert not l.user_in_group('a_test', 'classe_test')
 219.293 +
 219.294 +    # delete zapping home
 219.295 +    def test_13h_delete_user_by_string(self):
 219.296 +        l.parse_user_definition_string("d_test123;Test;Docente;docenti;;DNTLSN63D07;isi")
 219.297 +        l.parse_user_definition_string("-d_test123;Test;Docente;docenti;;DNTLSN63D07;isi",
 219.298 +                                            home_mode='rm')
 219.299 +        assert not l.user_exists('d_test123')
 219.300 +
 219.301 +    def test_13i_deleted_home(self):
 219.302 +        assert not os.path.exists('/home/users/docenti/d_test123')
 219.303 +        
 219.304 +    def test_13j_tgz(self):
 219.305 +        assert not os.path.exists('/home/users/docenti/d_test123.tgz')
 219.306 +
 219.307 +    @tools.raises(isi.exc.MissingMainGroup)
 219.308 +    def test_14a_missing_maingroup(self):
 219.309 +        l.parse_user_definition_string("d_test124;Test;Docente;docente;;DNTLSN63D07;isi")
 219.310 +        
 219.311 +
 219.312 +class Modify(unittest.TestCase):
 219.313 +
 219.314 +    def preparazione_16(self):
 219.315 +        ## clear any user from docenti
 219.316 +        l.get_group('docenti').delete_members(home_mode='rm')
 219.317 +        l.get_group('alunni').delete_members(home_mode='rm')
 219.318 +        l.del_group('classe_test', quiet=True)
 219.319 +        l.del_group('classe_test2', quiet=True)
 219.320 +        
 219.321 +
 219.322 +    ## modifica
 219.323 +    def test_16b_add_alunno(self):
 219.324 +        self.preparazione_16()
 219.325 +        kw = {'interactive': False, 'update_user' : True}
 219.326 +        def_string  = "a_test;Test;Alunno;alunni;classe_test;DNTLSN63D07;isi"
 219.327 +        def_string2 = "a_test;Test;Alunno;alunni;classe_test2;DNTLSN63D07;isi"
 219.328 +
 219.329 +        u = l.parse_user_definition_string(def_string, **kw)
 219.330 +        assert l.user_in_group('a_test', 'classe_test')
 219.331 +        assert not l.user_in_group('a_test', 'classe_test2')
 219.332 +        u = l.parse_user_definition_string(def_string2, **kw)
 219.333 +        assert not l.user_in_group('a_test', 'classe_test')
 219.334 +        assert l.user_in_group('a_test', 'classe_test2')
 219.335 +
 219.336 +        
 219.337 +        
 219.338 +setup.__test__ = False
 219.339 +#Extended = False
 219.340 +#ParserUser.__test__ = False
 219.341 +#Modify.__test__ = False
 219.342 +#ParserMethod.__test__ = False
   220.1 Binary file usr/bin/crackcheck has changed
   221.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   221.2 +++ b/usr/bin/isi-gnome-menu	Mon Apr 26 11:16:23 2010 +0200
   221.3 @@ -0,0 +1,338 @@
   221.4 +#!/usr/bin/python
   221.5 +# -*- coding: utf-8 -*-
   221.6 +"""
   221.7 +Crea se non presente o modifica il file ``$UTENTE/.gtk-bookmarks``,
   221.8 +aggiungendo i riferimenti alle share ISI definite per l'utente
   221.9 +in ``/etc/isi/logon.conf``
  221.10 +
  221.11 +E' possibile lavorare su singoli utenti, gruppi o tutti gli utenti.
  221.12 +
  221.13 +Senza opzioni lavora sull'utente corrente. In un contesto LTSP cio'
  221.14 +permette, usando opportunamente ``$UTENTE/.xsessionrc``, di risettare
  221.15 +le share ad inizio sessione-grafica dell'utente.
  221.16 +
  221.17 +  usage: %prog [options] [user | group]
  221.18 +    -u, --user=user: lavora su un singolo utente
  221.19 +    -g, --group=group: lavora per un gruppo di utenti
  221.20 +    -a, --all: lavora su tutti gli utenti, ad eccezione di root
  221.21 +    -v, --verbose: modo verboso
  221.22 +"""
  221.23 +
  221.24 +import isi
  221.25 +
  221.26 +from dry import optionparse
  221.27 +from dry.functions import execute
  221.28 +
  221.29 +import ConfigParser
  221.30 +import os
  221.31 +import sys
  221.32 +import re
  221.33 +import commands
  221.34 +
  221.35 +### Classes Definition
  221.36 +class NoValidUser(Exception):
  221.37 +    def __init__(self):
  221.38 +        print 'Utente non valido'
  221.39 +        sys.exit(1)
  221.40 +        
  221.41 +class NoExistingIsiUser(Exception):
  221.42 +    def __init__(self):
  221.43 +        print 'Utente ISI inesistente'
  221.44 +
  221.45 +class RequireRootPrivileges(Exception):
  221.46 +    def __init__(self):
  221.47 +        print 'Privilegi di root richiesti'
  221.48 +        sys.exit(1)
  221.49 +        
  221.50 +class InputStream(object):
  221.51 +    """ 
  221.52 +    Simple Wrapper for File-like objects. [c]StringIO doesn't provide                               
  221.53 +    a readline function for use with generate_tokens.                
  221.54 +    Using a iterator-like interface doesn't succeed, because the readline
  221.55 +    function isn't used in such a context. (see <python-lib>/tokenize.py)
  221.56 +    """
  221.57 +    def __init__(self, filename=None, data=None):
  221.58 +        if filename:
  221.59 +            f = open(file)
  221.60 +            data = f.read()
  221.61 +            f.close()
  221.62 +        data = re.sub(':(.*=)', r'|\1', data)
  221.63 +        self.__data = [ '%s\n' % x for x in data.splitlines() ]
  221.64 +        self.__lcount = 0
  221.65 +
  221.66 +    def readline(self):
  221.67 +        try:
  221.68 +            line = self.__data[self.__lcount]
  221.69 +            self.__lcount += 1
  221.70 +        except IndexError:
  221.71 +            line = ''
  221.72 +            self.__lcount = 0
  221.73 +        line = re.sub(r'^ +', '', line)
  221.74 +        line = re.sub(r'^\t+', '', line)
  221.75 +        line = re.sub(r'#.*', '', line)
  221.76 +        return line
  221.77 +
  221.78 +class UserInfo(object):
  221.79 +    """
  221.80 +    UserInfo, an object to share user infos ...
  221.81 +    """
  221.82 +    def __init__(self, user):
  221.83 +        self.Manager = Manager
  221.84 +        self.user = user
  221.85 +        posix_user = self.Manager.get_user(user)
  221.86 +
  221.87 +        self.main_groups = MAIN_GROUPS
  221.88 +
  221.89 +        self.user_home = posix_user.home
  221.90 +        self.user_groups = [x.name for x in posix_user.get_my_groups()]
  221.91 +        self.user_maingroup = posix_user.maingroup
  221.92 +
  221.93 +        self.classe = posix_user.classe
  221.94 +        self.mioweb_path = '%s/public_html' % (posix_user.home)
  221.95 +
  221.96 +        self.links_cfg_path = '%s/.gtk-bookmarks' % posix_user.home
  221.97 +        self.logon_conf = '/etc/isi/logon.conf'
  221.98 +
  221.99 +
 221.100 +class SambaUserShare(object): 
 221.101 +    """
 221.102 +    samba
 221.103 +    """
 221.104 +    def __init__(self, UI):
 221.105 +        self.UI = UI
 221.106 +
 221.107 +    def _get_share_path(self, share):
 221.108 +        """
 221.109 +        Parse the "test_parm -s" samba command output putting share info (name and path)
 221.110 +        in a dict {share-name : share-path} .
 221.111 +        Returns the PATH of given share-name.
 221.112 +        """
 221.113 +        shares_path_dict = {}
 221.114 +        ret_code, sambaconf, err = execute('testparm -s')
 221.115 +        f = InputStream(data=sambaconf)
 221.116 +        parser = ConfigParser.ConfigParser()
 221.117 +        parser.readfp(f, 'cfg')
 221.118 +        sections = parser.sections()
 221.119 +
 221.120 +        for section in parser.sections():
 221.121 +            items = parser.items(section)
 221.122 +            #print items
 221.123 +            item_with_path = ([item[1] for item in items if 'path' in item])
 221.124 +            # filtering env variable elements                                                               
 221.125 +            if re.search('%', str(item_with_path)):
 221.126 +                continue
 221.127 +            for path in item_with_path:
 221.128 +                share_name = path.split('/')[-1]
 221.129 +                shares_path_dict[share_name] = path
 221.130 +
 221.131 +        try:
 221.132 +            return shares_path_dict[share]#share_path = shares_path_dict[share]
 221.133 +        except KeyError, e:
 221.134 +            print 'Impossibile trovare la share samba "%s".\
 221.135 +                   Lancia "isi-checkup"!' % (share)
 221.136 +#            print ' Le share samba attualmente attive sul tuo server sono le seguenti:'
 221.137 +#            for key in shares_path_dict.keys():
 221.138 +#                print '  ', key
 221.139 +
 221.140 +    def get_my_shares_path(self):
 221.141 +        """
 221.142 +        Parse "/etc/isi/logon.conf" and returns a list of shares's path that user should
 221.143 +        see in his/her own gnome menu.
 221.144 +        "/etc/isi/logon.conf" sample ::
 221.145 +        
 221.146 +            _NetFolder[T:docenti] = area_docenti
 221.147 +            _NetFolder[T:admins] = area_docenti
 221.148 +            
 221.149 +            _NetFolder[Z:docenti] = area_alunni
 221.150 +            _NetFolder[Z:admins] = area_alunni
 221.151 +            _NetFolder[Z:alunni] = area_alunni
 221.152 +            _NetFolder[U] = didattica
 221.153 +            #_NetFolder[W] = mio_web
 221.154 +
 221.155 +        """
 221.156 +        UI = self.UI
 221.157 +        user_maingroup = UI.user_groups[0]
 221.158 +     
 221.159 +        # FIXME Cambiare modo di prendere il gruppo principale
 221.160 +        # per admins user_maingroup[0] == 'Domain Admins', non 'admins'
 221.161 +        if user_maingroup == 'Domain Admins':
 221.162 +            user_maingroup = 'admins'
 221.163 +                          
 221.164 +        my_shares = []
 221.165 +        my_shares_path = []
 221.166 +        group_shares = {}
 221.167 +
 221.168 +        GROUP_RESTRICTION = re.compile(r'''
 221.169 +            ([^[]+)         # tutto fino alla quadra [
 221.170 +            (?:\[           # ?: non lo vogliamo in m.groups()
 221.171 +            (?:(?:[A-Z]:)?  # per NetFolder e ammessa sintassi: [S:admins]
 221.172 +            ([a-z]+)        # il gruppo principale
 221.173 +            )
 221.174 +            ])?
 221.175 +            ''', re.VERBOSE)
 221.176 +
 221.177 +        f = open(LOGON_CONF)
 221.178 +        for line in f.readlines():
 221.179 +        #debug
 221.180 +        #for line in __doc__.split('\n'):
 221.181 +            if  re.match('^$', line)    or \
 221.182 +                re.match('^\s*#', line) or \
 221.183 +                '_NetFolder' not in line:
 221.184 +                continue
 221.185 +
 221.186 +            m = re.search(GROUP_RESTRICTION, line)
 221.187 +            if m:
 221.188 +                smb_share_name = line.split('=')[1].strip()
 221.189 +                opt, group = m.groups()
 221.190 +                # Adding group's share name
 221.191 +                if not group in group_shares.keys():
 221.192 +                    group_shares[group] = [smb_share_name]
 221.193 +                else:
 221.194 +                    group_shares[group].append(smb_share_name)
 221.195 +
 221.196 +        #
 221.197 +        # ``group_shares`` content es.:
 221.198 +        #
 221.199 +        #   >>> print group_shares
 221.200 +        #    {None: ['software'], \
 221.201 +        #    'admins': ['classi', 'software', 'area_docenti', 'area_alunni', 'didattica'],\
 221.202 +        #    'alunni': ['area_alunni', 'didattica'], \
 221.203 +        #    'docenti': ['classi', 'area_docenti', 'area_alunni', 'didattica', 'area_educatori']}
 221.204 +        #
 221.205 +        if user_maingroup in group_shares.keys():
 221.206 +            my_shares = group_shares[user_maingroup]
 221.207 +
 221.208 +        # all-group shares
 221.209 +        if None in group_shares:
 221.210 +    	    my_shares += group_shares[None]
 221.211 +
 221.212 +        if UI.classe:
 221.213 +            my_shares += [UI.classe]
 221.214 +
 221.215 +        for share in my_shares:
 221.216 +            # settaggio manuale path di mio_web
 221.217 +            if share == 'mioweb':
 221.218 +                my_shares_path += [UI.mioweb_path]
 221.219 +            else:
 221.220 +                my_shares_path += [self._get_share_path(share)]
 221.221 +
 221.222 +        return my_shares_path
 221.223 +
 221.224 +class MenuManager(object):
 221.225 +    """
 221.226 +    Menu manager class, provides functions to manage user's menu
 221.227 +
 221.228 +    TODO
 221.229 +    replace _add_link function with _update_link function that
 221.230 +    removes share no longer defined for the user's group in
 221.231 +    logon.conf
 221.232 +    """
 221.233 +    def __init__(self, UI):
 221.234 +        self.UI = UI
 221.235 +        self.uri_list_old = []
 221.236 +        self.uri_list_new = []
 221.237 +
 221.238 +    def _check_link_existance(self, uri):
 221.239 +        """
 221.240 +        Returns  TRUE   if link exists
 221.241 +        Returns  FALSE  if link doesn't exist
 221.242 +        """
 221.243 +        if uri in self.uri_list_old:
 221.244 +            return True
 221.245 +        return False
 221.246 +
 221.247 +    def _add_link(self, uri):
 221.248 +        """
 221.249 +        Adds the link's uri given to the user's gnome menu
 221.250 +        """
 221.251 +        if VERBOSE:
 221.252 +            print 'ADDING\n "%s" to "%s"' % (uri, self.UI.links_cfg_path)
 221.253 +
 221.254 +        self.uri_list_new.append(uri)
 221.255 +
 221.256 +    def setup_menu_links(self):
 221.257 +        """
 221.258 +        Main function.
 221.259 +        Checks the link's uri presence in the user's gnome-menu config file and adds
 221.260 +        missing shares defined as needed by the user.
 221.261 +
 221.262 +        """
 221.263 +        S = SambaUserShare(self.UI)
 221.264 +        share_path_list = S.get_my_shares_path()
 221.265 +
 221.266 +#        print share_path_list
 221.267 +#        import ipdb; ipdb.set_trace()
 221.268 +
 221.269 +        if os.path.exists(self.UI.links_cfg_path):
 221.270 +            try:
 221.271 +                f = open(self.UI.links_cfg_path, 'r')
 221.272 +                self.uri_list_old = [ line.strip('\n') for line in f.readlines() if '://' in line ]
 221.273 +            except Exception, e:
 221.274 +                print e
 221.275 +
 221.276 +        for path in share_path_list:
 221.277 +            uri = 'file://%s' % path
 221.278 +            if self._check_link_existance(uri) == True:
 221.279 +                continue        
 221.280 +            self._add_link(uri)
 221.281 +
 221.282 +        uri_list = []
 221.283 +        uri_list = self.uri_list_old + self.uri_list_new
 221.284 +
 221.285 +        try:
 221.286 +            f = open(self.UI.links_cfg_path, 'w')
 221.287 +            f.writelines("\n".join(uri_list))
 221.288 +            f.close()
 221.289 +        except Exception, e:
 221.290 +            print 'Errore ', e
 221.291 +            
 221.292 +        # chown user
 221.293 +        ret, out, err = execute('chown %s %s' % (self.UI.user, self.UI.links_cfg_path))
 221.294 +
 221.295 +def work_on_user(user):
 221.296 +    if not Manager.user_exists(user):  raise NoExistingIsiUser
 221.297 +
 221.298 +    print 'working on %s ...' % user
 221.299 +
 221.300 +    UI = UserInfo(user)
 221.301 +    M = MenuManager(UI)
 221.302 +    M.setup_menu_links()
 221.303 +
 221.304 +def work_on_group(group):
 221.305 +    USERS = Manager.get_members(group)
 221.306 +    for user in USERS:
 221.307 +        work_on_user(user)
 221.308 +
 221.309 +def work_on_all():
 221.310 +    for group in MAIN_GROUPS:
 221.311 +        work_on_group(group)
 221.312 +
 221.313 +
 221.314 +opts, args = optionparse.parse(__doc__)
 221.315 +
 221.316 +LOGON_CONF = '/etc/isi/logon.conf'
 221.317 +
 221.318 +Manager = isi.Manager(isi.IsiConn(dn="", passwd=""))
 221.319 +MAIN_GROUPS = isi.srv.get_main_groups()
 221.320 +
 221.321 +#LOGNAME = os.getlogin() # Damn bugged method always returning root !?!?
 221.322 +LOGNAME = os.getenv('LOGNAME')  # env variable method
 221.323 +
 221.324 +USER = opts.user
 221.325 +GROUP = opts.group
 221.326 +VERBOSE = opts.verbose
 221.327 +
 221.328 +### Startup
 221.329 +if USER:
 221.330 +    work_on_user(USER)
 221.331 +elif GROUP:
 221.332 +    if LOGNAME != 'root':
 221.333 +        raise RequireRootPrivileges
 221.334 +    work_on_group(GROUP)
 221.335 +elif opts.all:
 221.336 +    if LOGNAME != 'root':
 221.337 +        raise RequireRootPrivileges
 221.338 +    work_on_all()
 221.339 +else:
 221.340 +    user = LOGNAME
 221.341 +    work_on_user(user)
   222.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   222.2 +++ b/usr/bin/isi-passwd	Mon Apr 26 11:16:23 2010 +0200
   222.3 @@ -0,0 +1,94 @@
   222.4 +#!/usr/bin/python
   222.5 +# -*- coding: utf-8 -*-
   222.6 +
   222.7 +# This program is free software; you can redistribute it and/or modify
   222.8 +# it under the terms of the GNU General Public License as published by
   222.9 +# the Free Software Foundation; either version 2, or (at your option)
  222.10 +# any later version.
  222.11 +
  222.12 +# AUTHORS: Sandro Dentella - Massimo Mancini
  222.13 +
  222.14 +"""
  222.15 +
  222.16 +opt -A  is not yet implemented
  222.17 +
  222.18 +  usage: %prog [options] user
  222.19 +    -N, --dry-run: don't touch the ldap db or filesystem 
  222.20 +    -w, --pwdroot: change root and slapd/samba password
  222.21 +    -A, --pwdslap: change only slapd/samba admin password
  222.22 +    -p, --passwd=password: use password
  222.23 +    -r, --random: assign a random password, print it in stdout
  222.24 +    -c, --codfis: password uguale ai primi 8 caratteri del codice fiscale con l'iniziale maiuscola
  222.25 +
  222.26 +"""
  222.27 +
  222.28 +import isi
  222.29 +import sys
  222.30 +# servono per identificare l'utente (vedi sotto)
  222.31 +# import os, pwd
  222.32 +import re
  222.33 +from dry import optionparse
  222.34 +from dry.functions import execute, ExecuteError
  222.35 +from isi.parser import new_password
  222.36 +from getpass import getpass
  222.37 +opts, args = optionparse.parse(__doc__)
  222.38 +
  222.39 +c = isi.IsiConn(dry_run=opts.dry_run)
  222.40 +l = isi.Manager(c)
  222.41 +c.backup()
  222.42 +
  222.43 +# per saper chi è l'utente loggato
  222.44 +# attuser = pwd.getpwuid(os.getuid())[0]
  222.45 +
  222.46 +
  222.47 +if opts.pwdroot or opts.pwdslap:
  222.48 +    msg=''
  222.49 +    if opts.pwdroot:
  222.50 +        opts.pwdslap = True
  222.51 +        msg = '/root'
  222.52 +    if opts.pwdslap:
  222.53 +        passwd1 = getpass('Nuova password samba/ldap%s: '% msg)
  222.54 +        passwd2 = getpass('Ripeti password samba/ldap%s: '% msg)
  222.55 +        if passwd1 == passwd2:
  222.56 +            try:
  222.57 +                c.set_rootdn_passwd(passwd1)
  222.58 +            except:
  222.59 +                sys.exit(1)
  222.60 +            if opts.pwdroot:        
  222.61 +                pwdr = "root:%s\n|" % passwd1
  222.62 +                ret_code, out, err = execute('chpasswd', stdin=pwdr )
  222.63 +                if ret_code:
  222.64 +                    print "ERRORE nel cambiare la password di root:%s" % err
  222.65 +                    msg=''
  222.66 +                    
  222.67 +            print "password slap/samba%s cambiata con successo" % msg       
  222.68 +        else:
  222.69 +            print "ERRORE: le password digitate non coincidono"
  222.70 +    sys.exit(0)
  222.71 +
  222.72 +
  222.73 +if not len(args) == 1:
  222.74 +    print >>sys.stderr, "Need a user to change the password"
  222.75 +    sys.exit(1)
  222.76 +else:
  222.77 +    user = args[0]
  222.78 +
  222.79 +
  222.80 +if l.user_exists(user):
  222.81 +    if opts.random:
  222.82 +        opts.passwd = new_password()
  222.83 +        print "the random password for user %s is: %s" % (user, opts.passwd)
  222.84 +    if opts.codfis:
  222.85 +        cf = l.get_attr(user, 'employeeNumber')[0]
  222.86 +        if cf: 
  222.87 +            opts.passwd = cf[0:8].title()
  222.88 +            print "the password for user %s is: %s " % (user, opts.passwd)
  222.89 +        else:
  222.90 +            print "ERRORE: codice fiscale mancante, inserire manualmente una password"
  222.91 +    if not opts.passwd:
  222.92 +        opts.passwd = raw_input('Nuova Password: ')
  222.93 +    user = l.get_samba_user(user)
  222.94 +    user.set_password(opts.passwd)
  222.95 +else:
  222.96 +    print >>sys.stderr, "No user '%s'" % user
  222.97 +    sys.exit(1)
   223.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   223.2 +++ b/usr/lib/cgi-bin/dglog.pl	Mon Apr 26 11:16:23 2010 +0200
   223.3 @@ -0,0 +1,827 @@
   223.4 +#!/usr/bin/perl
   223.5 +
   223.6 +###########################################################################
   223.7 +#
   223.8 +# Program  : Log Analyzer for DansGuardian
   223.9 +# Author   : Jimmy Myrick ([email protected])
  223.10 +# Version  : .1.1
  223.11 +# Released : July 6, 2021
  223.12 +# 
  223.13 +#    This program is free software; you can redistribute it and/or modify
  223.14 +#    it under the terms of the GNU General Public License as published by
  223.15 +#    the Free Software Foundation; either version 2 of the License, or
  223.16 +#    (at your option) any later version.
  223.17 +#
  223.18 +#    This program is distributed in the hope that it will be useful,
  223.19 +#    but WITHOUT ANY WARRANTY; without even the implied warranty of
  223.20 +#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  223.21 +#    GNU General Public License for more details.
  223.22 +#
  223.23 +# Heck, if you like it though and want to send me something, that's
  223.24 +# ok too.  
  223.25 +#
  223.26 +# Change history is available here for now:
  223.27 +#  http://www.tiger.org/technology/dg
  223.28 +#
  223.29 +###########################################################################
  223.30 +#
  223.31 +# Modified by: Massimo Mancini <[email protected]>
  223.32 +#         for: query ldap about user data 
  223.33 +#
  223.34 +###########################################################################
  223.35 +
  223.36 +###########################################################################
  223.37 +#
  223.38 +# Change to point to your DansGuardian log directory
  223.39 +# NOTE: The trailing / IS REQUIRED!!
  223.40 +#
  223.41 +###########################################################################
  223.42 +$logdir = '/var/log/dansguardian/';
  223.43 +do "/etc/isi/dglog.conf.pl";
  223.44 +
  223.45 +
  223.46 +###########################################################################
  223.47 +#
  223.48 +# Log filename.  Change this to match the prefix of your log files
  223.49 +# This defaults to access.log and should not have to be modified.
  223.50 +#
  223.51 +# Any logfiles in $logdir that match the prefix $logfile and are gzip'ed
  223.52 +# with a .gz extension will also be read.  The results will be printed in
  223.53 +# reverse chronological filename order.
  223.54 +#
  223.55 +# Example:
  223.56 +#  If you have the files:  access.log access.log.0.gz access.log.1.gz
  223.57 +#  where they are newest to oldest, then any matches in
  223.58 +#  access.log.1.gz will be printed first, followed by access.log.0.gz
  223.59 +#  and then access.log
  223.60 +#
  223.61 +# No sorting is done by the program and the results are displayed in logfile
  223.62 +# order.  If your results are out of sequence, check the filename/dates
  223.63 +# to be sure they are compressed and rotated properly.  If you use 
  223.64 +# the FreeBSD newsyslog.conf to rotate your logs, this will not be a
  223.65 +# problem.
  223.66 +#
  223.67 +###########################################################################
  223.68 +$logfile = 'access.log';
  223.69 +
  223.70 +
  223.71 +###########################################################################
  223.72 +#
  223.73 +# If you need the perl modules below, download and untar them to a directory.
  223.74 +# Then cd to the directory and enter the commands:
  223.75 +#  perl Makefile.PL; make; make test; make install 
  223.76 +#
  223.77 +# If you need more instructions, 
  223.78 +#  go here: http://www.cpan.org/modules/INSTALL.html
  223.79 +#
  223.80 +# Get it here: http://www.cpan.org/authors/id/LDS/CGI.pm-2.81.tar.gz
  223.81 +#
  223.82 +###########################################################################
  223.83 +use CGI;
  223.84 +
  223.85 +###########################################################################
  223.86 +#
  223.87 +# This is needed to do gzip'ed log files on the fly
  223.88 +# Get it here: http://www.cpan.org/authors/id/PMQS/Compress-Zlib-1.16.tar.gz
  223.89 +#
  223.90 +###########################################################################
  223.91 +use Compress::Zlib; 
  223.92 +
  223.93 +
  223.94 +###########################################################################
  223.95 +#
  223.96 +# This should determine where the program is called from automagically.
  223.97 +# If not, uncomment the first lane, change to your server name/path and
  223.98 +# comment the second line.  You can use Apache restrictions to block 
  223.99 +# access to this file if desired. 
 223.100 +#
 223.101 +###########################################################################
 223.102 +#$cgipath = 'http://your.server.com/cgi-bin/dglog/dglog.pl';
 223.103 +$cgipath = $ENV{SCRIPT_NAME};
 223.104 +
 223.105 +
 223.106 +###########################################################################
 223.107 +# LDAP
 223.108 +###########################################################################
 223.109 +
 223.110 +use Net::LDAP;
 223.111 +$OK_LDAP=1;
 223.112 +%usersfound=(); 
 223.113 +# $ldap_server ='<name|ip server_ldap>';
 223.114 +# $ldap_base   ='<dc=isi,dc=lan>';
 223.115 +# @ldap_fields=('gecos','departmentNumber');
 223.116 +$ldap = Net::LDAP->new($ldap_server) or ($OK_LDAP=0);
 223.117 +$ldap->bind if ($OK_LDAP);
 223.118 +
 223.119 +
 223.120 +###########################################################################
 223.121 +#
 223.122 +#    SHOULDN'T HAVE TO MODIFY ANYTHING BELOW THIS LINE
 223.123 +#
 223.124 +###########################################################################
 223.125 +
 223.126 +$q = new CGI;
 223.127 +
 223.128 +($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
 223.129 +$mon = $mon + 1;  # mon starts at 0 
 223.130 +$year = $year + 1900;  # year needs 1900 added
 223.131 +$pagename = 'Log Analyzer for DansGuardian';
 223.132 +
 223.133 +$a = $q->param('a');
 223.134 +
 223.135 +if ($a eq 'i') { # Inquiry into logs
 223.136 +
 223.137 +  # These are the values that can be sent by the user through the browser
 223.138 +  $sIP = "ALL";   # IP address 
 223.139 +  $sUN = "ALL";   # Username
 223.140 +  $sURL = "ALL"; # URL to show or trace a denied site - this is the URL to trace
 223.141 +  $sSD = "ALL";   # Complete start date
 223.142 +  $sSDY = "ALL";  # Start date year
 223.143 +  $sSDM = "ALL";  # Start date month
 223.144 +  $sSDD = "ALL";  # Start date day
 223.145 +  $sED = "ALL";   # Complete end date
 223.146 +  $sEDY = "ALL";  # End date year
 223.147 +  $sEDM = "ALL";  # End date month
 223.148 +  $sEDD = "ALL";  # End date day
 223.149 +  $sA = "ALL";    # Action
 223.150 +  $sSumCnt = "20";    # Number of summary sites to show
 223.151 +  $sSumDen = "off";    # Show denied summary? on/off
 223.152 +  $sSumAlw = "off";    # Show allowed summary? on/off
 223.153 +  $sL = "off"; # Turn URL's into links? on/off
 223.154 +  $sZ = "off"; # Examine gziped files? on/off
 223.155 +
 223.156 +  $sIP = &validateIP($q->param('sIP')) if $q->param('sIP') ne "";
 223.157 +  $sUN = $q->param('sUN') if $q->param('sUN') ne "";
 223.158 +  $sURL = $q->param('sURL') if $q->param('sURL') ne "";
 223.159 +
 223.160 +  if ($q->param('sSDY') ne "" &&
 223.161 +      $q->param('sSDM') ne "" &&
 223.162 +      $q->param('sSDD') ne "" &&
 223.163 +      $q->param('sEDY') ne "" &&
 223.164 +      $q->param('sEDM') ne "" &&
 223.165 +      $q->param('sEDD') ne "") {
 223.166 +
 223.167 +      $sSDY = $q->param('sSDY'); 
 223.168 +      $sSDM = $q->param('sSDM'); 
 223.169 +      $sSDD = $q->param('sSDD'); 
 223.170 +      $sEDY = $q->param('sEDY'); 
 223.171 +      $sEDM = $q->param('sEDM'); 
 223.172 +      $sEDD = $q->param('sEDD'); 
 223.173 +
 223.174 +      $sSD = $sSDY.'.'.$sSDM.'.'.$sSDD;
 223.175 +      $sSD = convertDate($sSD);
 223.176 +      $sED = $sEDY.'.'.$sEDM.'.'.$sEDD;
 223.177 +      $sED = convertDate($sED);
 223.178 +
 223.179 +      if ($sSD > $sED) {
 223.180 +        $msg = "End Date is greather than Start Date";
 223.181 +        &printMenu;
 223.182 +      }
 223.183 +  }
 223.184 +
 223.185 +  $sA = &validateAction($q->param('sA')) if $q->param('sA') ne "";  # Action
 223.186 + 
 223.187 +  $sSumCnt = &validateSummary($q->param('sSumCnt')) 
 223.188 +             if $q->param('sSumCnt') ne "";
 223.189 +  $sSumDen = $q->param('sSumDen') if $q->param('sSumDen') eq 'on';
 223.190 +  $sSumAlw = $q->param('sSumAlw') if $q->param('sSumAlw') eq 'on';
 223.191 +
 223.192 +  $sL = $q->param('sL') if $q->param('sL') eq 'on';
 223.193 +  $sZ = $q->param('sZ') if $q->param('sZ') eq 'on';
 223.194 +
 223.195 +
 223.196 +  # Need a few global variables to keep from passing back and forth a bunch
 223.197 +  $linesRead, $allowTotal, $blockTotal, $grandTotal = 0;
 223.198 +
 223.199 +  &searchLog;
 223.200 +
 223.201 +}
 223.202 +elsif ($a eq 'h') {
 223.203 +  &displayHelp;
 223.204 +}
 223.205 +else {
 223.206 +  &printMenu;
 223.207 +}
 223.208 +
 223.209 +#############
 223.210 +sub searchLog
 223.211 +#############
 223.212 +{
 223.213 +  my $first = 0;
 223.214 +
 223.215 +  &printHeader;
 223.216 +  print "<font face=arial,helvetica,sans-serif size=2>";
 223.217 +  print "Report information for:<br>
 223.218 +   Start Date: <b>$sSD</b> | End Date: <b>$sED</b> |
 223.219 +   Username : <b>$sUN</b> | IP: <b>$sIP</b> |
 223.220 +   Action: <b>$sA</b> | URL: <b>$sURL</b><hr></font>\n";
 223.221 +  print "<font face=arial,helvetica,sans-serif size=1>";
 223.222 +
 223.223 +  opendir(D, $logdir);
 223.224 +  @files = grep {/^$logfile/} readdir(D);
 223.225 +  @files = sort {$b cmp $a} @files;
 223.226 +  closedir(D);
 223.227 +
 223.228 +  foreach $file (@files) {
 223.229 +    if ($file =~ /\.gz/) {
 223.230 +      if ($sZ eq 'on') {
 223.231 +        if ($first == 0) {
 223.232 +          print "Ignoring gzip logfile(s) in $logdir: ";
 223.233 +          $first = 1;
 223.234 +        }
 223.235 +        print "$file | ";
 223.236 +        next;
 223.237 +      }
 223.238 +      $gz = gzopen($logdir.$file,r);
 223.239 +      if (!$gz) {
 223.240 +        $msg = "Cannot open $logdir$file. Check Permissions.";
 223.241 +        &printMenu;
 223.242 +      }
 223.243 +      while ($gz->gzreadline($line)) {
 223.244 +        &checkLine($line);
 223.245 +      }
 223.246 +      $gz->gzclose;
 223.247 +    } 
 223.248 +    else {
 223.249 +      print "<p>";
 223.250 +      unless (open(F,$logdir.$file)) {
 223.251 +        $msg = "Cannot open $logdir$file. Check Permissions.";
 223.252 +        &printMenu;
 223.253 +      }
 223.254 +      while ($line = <F>) {
 223.255 +        &checkLine($line);
 223.256 +      }
 223.257 +      close(F);
 223.258 +    }
 223.259 +  }
 223.260 +
 223.261 +  if ($sSumAlw eq "on" && $allowTotal != 0) {
 223.262 +    &showSummarySites($allowTotal,'ALLOWED',$sSumCnt,%topSites);
 223.263 +  }
 223.264 +  if ($sSumDen eq "on" && $blockTotal != 0) {
 223.265 +    &showSummarySites($blockTotal,'DENIED',$sSumCnt,%blockSites);
 223.266 +  }
 223.267 +
 223.268 +  print "<center><hr noshade size=1 width=50%>
 223.269 +         <font size=2>Total matches: $grandTotal |
 223.270 +         Total ALL Requests: $linesRead</font>
 223.271 +         <hr noshade size=1 width=50%></font>";
 223.272 +  print "<center><a href=$cgipath>Return to Menu</a></center>";
 223.273 +}
 223.274 +
 223.275 +#######################
 223.276 +sub ldap_getuserinfo {
 223.277 +#######################
 223.278 +
 223.279 +    $uid=shift;   
 223.280 +
 223.281 +    return "...no ldap!" if (!$OK_LDAP);
 223.282 +
 223.283 +    my $ret="",$gec,$dep,$flt,$ris,@info,$entry;
 223.284 +
 223.285 +    if (defined($usersfound{$uid})){
 223.286 +	$ret = $usersfound{$uid};
 223.287 +    }else{
 223.288 +
 223.289 +	$ris=$ldap->search( base   => $ldap_base,
 223.290 +			    filter => "uid=$uid",
 223.291 +			    attrs  => \@ldap_fields);
 223.292 +
 223.293 +	@info   = $ris->entries;
 223.294 +
 223.295 +	foreach $entry (@info) {
 223.296 +	    $gec = $entry->get_value($ldap_fields[0]);
 223.297 +	    $gec =~ s/,//g;
 223.298 +	    $dep = $entry->get_value($ldap_fields[1]);
 223.299 +	    $ret = uc("<strong> : $gec - $dep</strong>");
 223.300 +	}
 223.301 +	$usersfound{$uid}=$ret;
 223.302 +    }
 223.303 +    return $ret;
 223.304 +}
 223.305 +
 223.306 +
 223.307 +#############
 223.308 +sub checkLine
 223.309 +#############
 223.310 +{
 223.311 +  my ($line) = @_;
 223.312 +  $linesRead++;
 223.313 +
 223.314 +  # Print out a '.' every 1000 log file lines read. Keep browser connect alive
 223.315 +  if (($linesRead % 1000) == 0) {
 223.316 +    print " ";
 223.317 +  } 
 223.318 +  ($date,$time,$user,$ip,$url,$toeol) = split(/ /,$line,6);
 223.319 +
 223.320 +  # query ldap
 223.321 +  $user .= ldap_getuserinfo($user);
 223.322 +
 223.323 +
 223.324 +  # Rule out the easy matches first 
 223.325 +  return if ($sIP ne "ALL" && $sIP ne $ip);
 223.326 +  return if ($sUN ne "ALL" && $sUN ne $user);
 223.327 +
 223.328 +  # Don't do a date comparison unless we are told to
 223.329 +  if ($sSD ne "ALL" || $sED ne "ALL") {
 223.330 +    $dgDate = &convertDate($date);
 223.331 +    return if (!($dgDate ge $sSD && $dgDate le $sED));
 223.332 +  }
 223.333 +
 223.334 +  $url =~ /(\w+):\/\/([\w\.-]+)\/?(\S*)/;  
 223.335 +  $protocol = $1; # HTTP, FTP
 223.336 +  $baseurl = $2;  # domain part without http:// or ftp://
 223.337 +  return if ($sURL ne "ALL" && $sURL ne $baseurl);
 223.338 +  $toeol =~ /(\*.+\*)? ?(.+)? (\w+) (\d+)$/;
 223.339 +  $action = $1; # *DENIED# or *EXCEPTION* etc., if exists
 223.340 +  $reason = $2; # Reason for #1 if exists
 223.341 +  $method = $3; # method (GET POST)
 223.342 +  $size = $4;   # size
 223.343 +  if ($sA ne "ALL") { 
 223.344 +    return if ($sA eq "denAll" &&
 223.345 +      $action ne "*DENIED*");
 223.346 +    return if ($sA eq "excAll" &&
 223.347 +      $action ne "*EXCEPTION*");
 223.348 +    return if ($sA eq "denSite" && 
 223.349 +      !($reason =~ /^Banned site/));
 223.350 +    return if ($sA eq "denRegURL" && 
 223.351 +      !($reason =~ /^Banned Regular Expression URL/));
 223.352 +    return if ($sA eq "denPhrase" && 
 223.353 +      !($reason =~ /^Banned Phrase/));
 223.354 +    return if ($sA eq "denCombPhrase" && 
 223.355 +      !($reason =~ /^Banned combination phrase/));
 223.356 +    return if ($sA eq "denWeightPhrase" && 
 223.357 +      !($reason =~ /^Weighted phrase limit/));
 223.358 +    return if ($sA eq "denExt" && 
 223.359 +      !($reason =~ /^Banned extension/));
 223.360 +    return if ($sA eq "denMIME" && 
 223.361 +      !($reason =~ /^Banned MIME Type/));
 223.362 +    return if ($sA eq "denICRA" && 
 223.363 +      !($reason =~ /^ICRA/));
 223.364 +    return if ($sA eq "denBlanketIP" && 
 223.365 +      !($reason =~ /^Blanket IP Block/));
 223.366 +    return if ($sA eq "excSite" && 
 223.367 +      !($reason =~ /^Exception site/));
 223.368 +    return if ($sA eq "excPhrase" && 
 223.369 +      !($reason =~ /^Exception phrase/));
 223.370 +    return if ($sA eq "excCombPhrase" && 
 223.371 +      !($reason =~ /^Combination exception phrase/));
 223.372 +  }
 223.373 +
 223.374 +  # Need to do a count for grandTotal if allowed OR denied summary selected 
 223.375 +  if ($sSumAlw eq "on" || $sSumDen eq "on") {
 223.376 +    if ($action ne '*DENIED*') {
 223.377 +      $allowTotal++;
 223.378 +      $grandTotal++;
 223.379 +      # Don't waste memory if didn't want this, but need to count for grandTotal
 223.380 +      $topSites{$baseurl}++ if $sSumAlw eq "on";
 223.381 +    }
 223.382 +    else {
 223.383 +      $blockTotal++;
 223.384 +      $grandTotal++;
 223.385 +      # Don't waste memory if didn't want this, but need to count for grandTotal
 223.386 +      $blockSites{$baseurl}++ if $sSumDen eq "on";
 223.387 +    }
 223.388 +  }
 223.389 +  else {
 223.390 +    print "$date   $time   ";
 223.391 +    print "<a href=$cgipath?a=i&sSDY=$sSDY&sSDM=$sSDM&sSDD=$sSDD&sEDY=$sEDY&sEDM=$sEDM&sEDD=$sEDD&sIP=$ip&sZ=$sZ&sL=$sL>$ip</a> 
 223.392 +        $user<br>";
 223.393 +    if ($sL eq 'on') {
 223.394 +      print "<a href=\"$url\" target=_blank>$url</a> $method $size<br>";
 223.395 +    } else {
 223.396 +      print "$url $method $size<br>";
 223.397 +    }
 223.398 +    if ($action ne "" && $reason ne "") {
 223.399 +      print "<font color=red>$action : $reason</font><p>";
 223.400 +    } else {
 223.401 +      print "<p>";
 223.402 +    }
 223.403 +    $grandTotal++;
 223.404 +  }
 223.405 +}
 223.406 +
 223.407 +####################
 223.408 +sub showSummarySites {
 223.409 +####################
 223.410 +  my ($subTotal, $whatToShow, $topNum, %sites) = @_;
 223.411 +  my $count = 1;
 223.412 +
 223.413 +  print "<table border=0 cellpadding=2 cellspacing=2 align=center>
 223.414 +         <tr><th colspan=6>
 223.415 +         <b><center>
 223.416 +         <hr noshade width=50% size=1>
 223.417 +         Top $topNum $whatToShow Sites</b></td></tr>
 223.418 +         <hr noshade width=50% size=1>
 223.419 +         <tr><td align=center>Rank</td>
 223.420 +             <td align=center>URL</td>
 223.421 +             <td align=center>Count</td>
 223.422 +             <td align=right>\% of<br>$whatToShow</td>
 223.423 +             <td align=right>\% of<br>Total</td>
 223.424 +             <td align=center>Investigate</td></tr>";
 223.425 +
 223.426 +  foreach $key (sort {$sites{$b} <=> $sites{$a}} keys %sites) {
 223.427 +    if ($count <= $topNum) {
 223.428 +      print "<tr>
 223.429 +         <td align=right>$count.  </td>";
 223.430 +      print "<td align=right>";
 223.431 +      if ($sL eq 'on') {
 223.432 +        print "<a href=http://$key target=_blank>$key</a>";
 223.433 +      } else {
 223.434 +        print "$key";
 223.435 +      }
 223.436 +      print "</td><td align=right>$sites{$key}</td><td align=right>";
 223.437 +      printf("   %2.2f  ",($sites{$key}/$subTotal)*100);
 223.438 +      print "</td><td align=right>";
 223.439 +      printf("   %2.2f",($sites{$key}/$grandTotal)*100);
 223.440 +      print "</td>";
 223.441 +      print "<td align=center>
 223.442 +             <a href=$cgipath?a=i&sSDY=$sSDY&sSDM=$sSDM&sSDD=$sSDD&sEDY=$sEDY&sEDM=$sEDM&sEDD=$sEDD&sUN=$sUN&sIP=$sIP&sURL=$key&sZ=$sZ&sA=";
 223.443 +      if ($whatToShow eq "DENIED") { print "denAll"; } else { print ""; }
 223.444 +      print">Trace</a></td></tr>";
 223.445 +      $count++;
 223.446 +    }
 223.447 +    break;
 223.448 +  }
 223.449 +  print "<tr><td colspan=6 align=center>
 223.450 +         <hr noshade size=1 width=85% align=center>
 223.451 +         Total $whatToShow Requests (only top $topNum sites shown) : $subTotal
 223.452 +         <hr noshade size=1 width=85% align=center>
 223.453 +         </td></tr>";
 223.454 +  print "</table>
 223.455 +         <hr noshade width=100% size=1>";
 223.456 +}
 223.457 +
 223.458 +###################
 223.459 +sub validateSummary 
 223.460 +###################
 223.461 +{
 223.462 +  my ($count) = @_;
 223.463 +  if ($count < 0 || $count > 100) {
 223.464 +    $count = 20;
 223.465 +  }
 223.466 +  return($count);
 223.467 +}
 223.468 +
 223.469 +##############
 223.470 +sub validateIP 
 223.471 +##############
 223.472 +{
 223.473 +  my ($checkIP) = @_;
 223.474 +
 223.475 +  if ($checkIP eq 'ALL') {
 223.476 +    return('ALL');
 223.477 +  }
 223.478 +  elsif ($checkIP =~ /^((2([0-4]\d|5[0-5])|1?\d{1,2})(\.|$)){4}/) {
 223.479 +    return ($checkIP);
 223.480 +  }
 223.481 +  else {
 223.482 +    $msg = "Invalid IP address entered.";
 223.483 +    &printMenu;
 223.484 +  }
 223.485 +}
 223.486 +
 223.487 +##################
 223.488 +sub validateAction {
 223.489 +##################
 223.490 +  my ($action) = @_;
 223.491 +
 223.492 +  # Need to make the actions a hash and reference them that way
 223.493 +  # Make it easier to add/modify and can validate that way too
 223.494 +  # Maybe later.
 223.495 +  if ($action eq "none") { return ("ALL"); }
 223.496 +
 223.497 +  return ($action);
 223.498 +}
 223.499 +
 223.500 +###############
 223.501 +sub convertDate {
 223.502 +###############
 223.503 +  my ($workDate) = @_;
 223.504 +  ($year, $mon, $day) = split(/\./,$workDate);
 223.505 +
 223.506 +  if (length($mon) == 1) { $mon = '0'.$mon; }
 223.507 +  if (length($day) == 1) { $day = '0'.$day; }
 223.508 +  if (($mon ge "01" && $mon le "12") && ($day ge "01" && $day le "31") &&
 223.509 +      ($year ge "2000" && $year le "2035")) {
 223.510 +
 223.511 +      $goodDate = $year.$mon.$day;
 223.512 +      return ($goodDate);
 223.513 +  } else {
 223.514 +    $msg = "Invalid Date Detected";
 223.515 +    &printMenu;
 223.516 +  }
 223.517 +}
 223.518 +
 223.519 +###############
 223.520 +sub buildSelect
 223.521 +###############
 223.522 +{
 223.523 +  my ($start, $end, $type) = @_;
 223.524 +  my $x = 0;
 223.525 +  
 223.526 +##  print "<option value=\"\">--$type--";
 223.527 +  print "<option value=\"\">--ALL--";
 223.528 +  for ($x = $start; $x <= $end; $x++) {
 223.529 +    if ($type eq 'Year' && $x == $year) {
 223.530 +      print "<option value=$x selected>$x";
 223.531 +    }
 223.532 +    elsif ($type eq 'Month' && $x == $mon) {
 223.533 +      print "<option value=$x selected>$x";
 223.534 +    }
 223.535 +    elsif ($type eq 'Day' && $x == $mday) {
 223.536 +      print "<option value=$x selected>$x";
 223.537 +    }
 223.538 +    else {
 223.539 +      print "<option value=$x>$x";
 223.540 +    }
 223.541 +  }
 223.542 +}
 223.543 +
 223.544 +#############
 223.545 +sub printMenu
 223.546 +#############
 223.547 +{
 223.548 +  &printHeader;
 223.549 +  print "
 223.550 +    <table align=center bgcolor=ffffff border=1 cellpadding=3 cellspacing=1>\n";
 223.551 +  if ($msg ne "") {
 223.552 +    print "<tr><td colspan=3 bgcolor=c80000 align=center>
 223.553 +           <font face=arial,helvetica,sans-serif size=3><b>$msg</b>
 223.554 +           </font></tr>\n";
 223.555 +  }
 223.556 +  
 223.557 +  # Menu items header row
 223.558 +  print "
 223.559 +  <tr bgcolor=f0f0f0>
 223.560 +  <th width=40%>
 223.561 +    Parameter
 223.562 +  </th>
 223.563 +  <th width=40%>
 223.564 +    Value
 223.565 +  </th>
 223.566 +  <th width=20%>
 223.567 +    Description
 223.568 +  </th></tr>\n";
 223.569 +
 223.570 +  # Menu item for entering date ranges
 223.571 +  print "
 223.572 +  <tr><td align=left>
 223.573 +    Enter date range:
 223.574 +    <form action=$cgipath><input type=hidden name=a value=i>
 223.575 +    <br>
 223.576 +  </td>
 223.577 +  <td align=left>
 223.578 +    Start Date<br>
 223.579 +    <select name=sSDY>";
 223.580 +  &buildSelect(2002,2010,"Year");
 223.581 +  print "</select><select name=sSDM>";
 223.582 +  &buildSelect(01,12,"Month");
 223.583 +  print "</select><select name=sSDD>";
 223.584 +  &buildSelect(01,31,"Day");
 223.585 +  print "</select><br>
 223.586 +    End Date<br>
 223.587 +    <select name=sEDY>";
 223.588 +  &buildSelect(2002,2010,"Year");
 223.589 +  print "</select><select name=sEDM>";
 223.590 +  &buildSelect(01,12,"Month");
 223.591 +  print "</select><select name=sEDD>";
 223.592 +  &buildSelect(01,31,"Day");
 223.593 +  print "</select>
 223.594 +  </td>
 223.595 +  <td align=center>
 223.596 +    A start and end must be specified.
 223.597 +  </td></tr>\n";
 223.598 +
 223.599 +  # Menu item for IP viewing
 223.600 +  print "
 223.601 +  <tr><td align=left>
 223.602 +    Enter IP Address
 223.603 +  </td>
 223.604 +  <td align=left>
 223.605 +    <input name=sIP maxlength=15 size=20>
 223.606 +  </td>
 223.607 +  <td align=center>
 223.608 +    ex: 10.0.0.1<br>
 223.609 +  </td></tr>\n";
 223.610 +
 223.611 +  # Menu item for username viewing
 223.612 +  print "
 223.613 +  <tr><td align=left>
 223.614 +    Enter a Username
 223.615 +  </td>
 223.616 +  <td align=left>
 223.617 +    <input name=sUN maxlength=15 size=20>
 223.618 +  </td>
 223.619 +  <td align=center>
 223.620 +    (proxy auth must be enabled)<br>
 223.621 +  </td></tr>\n";
 223.622 +  
 223.623 +  # Menu item for URL viewing
 223.624 +  print "
 223.625 +  <tr><td align=left>
 223.626 +    Enter a URL (domain part only)
 223.627 +  </td>
 223.628 +  <td align=left>
 223.629 +    <input name=sURL maxlength=30 size=20>
 223.630 +  </td>
 223.631 +  <td align=center>
 223.632 +    Enter the www.domain.com part of a URL only<br>
 223.633 +  </td></tr>\n";
 223.634 +  
 223.635 +  # Menu item for ACTION
 223.636 +  print "
 223.637 +  <tr><td align=left>
 223.638 +    View activity by ACTION
 223.639 +  </td>
 223.640 +  <td align=left>
 223.641 +    <select name=sA>
 223.642 +    <option value=none>Show ALL
 223.643 +    <option value=none>---------------
 223.644 +    <option value=denAll>Show ALL Denied
 223.645 +    <option value=none>---------------
 223.646 +    <option value=excAll>Show ALL Exception
 223.647 +    <option value=none>---------------
 223.648 +    <option value=denSite>Banned Site
 223.649 +    <option value=denPhrase>Banned Phrase
 223.650 +    <option value=denRegURL>Banned Regular Expression URL
 223.651 +    <option value=denCombPhrase>Banned Combination Phrase
 223.652 +    <option value=denWeightPhrase>Weighted Phrase Limit
 223.653 +    <option value=denExt>Banned Extension
 223.654 +    <option value=denMIME>Banned MIME Type
 223.655 +    <option value=denICRA>ICRA Exceeded
 223.656 +    <option value=denBlanketIP>Blanket IP Block
 223.657 +    <option value=none>---------------
 223.658 +    <option value=excSite>Exception Site
 223.659 +    <option value=excPhrase>Exception Phrase
 223.660 +    <option value=excCombPhrase>Combination Exception Phrase
 223.661 +    </select>
 223.662 +   
 223.663 +  </td>
 223.664 +  <td align=center>
 223.665 +    Can only do one at a time.
 223.666 +  </td></tr>\n";
 223.667 +  
 223.668 +  # Menu item for selecting summary statistics
 223.669 +  print "
 223.670 +  <tr><td colspan=2 align=left>
 223.671 +    Show summary information for the top  
 223.672 +    <input maxlength=3 size=5 name=sSumCnt value=20> 
 223.673 +    <input type=checkbox name=sSumDen>DENIED 
 223.674 +    <input type=checkbox name=sSumAlw>ALLOWED
 223.675 +    sites
 223.676 +  </td>
 223.677 +  <td align=center>
 223.678 +    Will summarize the top sites for the criteria specified.
 223.679 +  </td></tr>\n";
 223.680 +
 223.681 +  print "
 223.682 +  <tr><td colspan=3 align=center>
 223.683 +   <table width=100% border=0 cellpadding=0 cellspacing=0 align=center>
 223.684 +    <tr><td>
 223.685 +     <input type=checkbox name=sL>Check to turn URL's in reports into links.<br>
 223.686 +     <input type=checkbox name=sZ>Check to <b>exclude</b> gzip log files.<br>
 223.687 +     <a href=$cgipath?a=h>View Usage Instructions</a><br>
 223.688 +    </td>
 223.689 +    <td align=center valign=middle>
 223.690 +     Click the \"Run Report\" Button to Start<p>
 223.691 +     <input type=submit value=\"Run Report\">   
 223.692 +     <input type=reset value=\"Reset Values\"><br>
 223.693 +    </td></tr>
 223.694 +   </table>
 223.695 +  </td></tr>\n";
 223.696 +
 223.697 +  print " </form> </td> </tr> </table> ";
 223.698 +  &printFooter;
 223.699 +  exit;
 223.700 +}
 223.701 +
 223.702 +###############
 223.703 +sub printHeader
 223.704 +###############
 223.705 +{
 223.706 + print $q->header;
 223.707 + print <<"(EOT)";
 223.708 + <HTML><HEAD>
 223.709 + <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
 223.710 + <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
 223.711 + <META HTTP-EQUIV="Expires" CONTENT="-1">
 223.712 + <TITLE>$pagename</TITLE>
 223.713 + <STYLE>
 223.714 + <!--
 223.715 +    TABLE       {margin-top: 0; padding-top: 0}
 223.716 +    TD  	{font-family: Serif; font-size: 10pt }
 223.717 +    TH  	{font-family: Serif; font-size: 12pt }
 223.718 + -->
 223.719 + </STYLE>
 223.720 + </HEAD>
 223.721 + <body bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#0000ff"
 223.722 + alink="#0000ff">
 223.723 + <center>
 223.724 + <table width="600" border="0" cellspacing="0" cellpadding="0">
 223.725 + <tr><th width=600 align=center>
 223.726 + <font size="4" color="#000000" face="arial">
 223.727 + <hr noshade size=1 width=90%>
 223.728 + $pagename 
 223.729 + <hr noshade size=1 width=90%>
 223.730 + </th></tr>
 223.731 + </table>
 223.732 + </center>
 223.733 +
 223.734 +(EOT)
 223.735 +}
 223.736 +
 223.737 +###############
 223.738 +sub printFooter
 223.739 +###############
 223.740 +{
 223.741 +  print <<"(EOT)";
 223.742 +  </BODY>
 223.743 +  </HTML>
 223.744 +(EOT)
 223.745 +}
 223.746 +
 223.747 +###############
 223.748 +sub displayHelp
 223.749 +###############
 223.750 +{
 223.751 +  &printHeader;
 223.752 +  print<<"(EOF)";
 223.753 +  <table width=75% border=1 cellpadding=2 cellspacing=0 align=center>
 223.754 +  <tr><th bgcolor=f0f0f0><font face=arial,helvetica,sans-serif size=4>
 223.755 +   Instructions
 223.756 +  </th></tr>
 223.757 +  <tr><td align=left><font face=arial,helvetica,sans-serif size=2>
 223.758 +  <b>Overview</b>
 223.759 +  <ul>
 223.760 +  This program will examine logs files created by DansGuardian filtering
 223.761 +  software (http://www.dansguardian.org).<p>
 223.762 +  Different search criteria can be specified.  The search criteria are
 223.763 +  cummulatvie (added together).  For example, specifying a date range
 223.764 +  and an IP address will only show entries that match BOTH criteria.  If
 223.765 +  you want to see all log entries, do not specify any criteria.
 223.766 +  <p>
 223.767 +  Presently, no sorting is done on the results.  This is to ensure a very
 223.768 +  fast search, use a small amount of memory, and "feed" the browser peridically with information
 223.769 +  so a timeout does not occur.  What this means is that your log files
 223.770 +  must be in chronological sequence on your system by name.  This will
 223.771 +  become important when using multiple log files is added.  This feature
 223.772 +  is not currently implemented.  Only the one file is examined now.
 223.773 +  </ul>
 223.774 +  </td></tr>
 223.775 +  <tr><td align=left><font face=arial,helvetica,sans-serif size=2>
 223.776 +  <b>Dates</b>
 223.777 +  <ul>
 223.778 +Select the range of dates to match.  If dates are used, <b>both</b> a start and end date must be selected.  Failure to select any part of a start or end date will result in no date range being used.  The dates will match greater than or equal to start date - less than or equal to end date. 
 223.779 +  </ul>
 223.780 +  </td></tr>
 223.781 +  <tr><td align=left><font face=arial,helvetica,sans-serif size=2>
 223.782 +  <b>IP Address</b>
 223.783 +  <ul>
 223.784 +  Enter a IPv4 address to match.  Example:  10.0.0.1
 223.785 +  </ul>
 223.786 +  </td></tr>
 223.787 +  <tr><td align=left><font face=arial,helvetica,sans-serif size=2>
 223.788 +  <b>Username</b>
 223.789 +  <ul>
 223.790 +  Enter a username to match.  Proxy auth must be enabled in DansGuardian for this to work.  If usernames are not shown when matching without any criteria, then proxy auth is most likely not enabled.  Refer to the appropriate instructions on how to do this.
 223.791 +  </ul>
 223.792 +  </td></tr>
 223.793 +  <tr><td align=left><font face=arial,helvetica,sans-serif size=2>
 223.794 +  <b>Action</b>
 223.795 +  <ul>
 223.796 +  Enter an action to match.  
 223.797 +  Use the drop-down list to select the ACTION to match.  The ACTIONs are the
 223.798 +  special case requests logged by DansGuardian.  To see ALL matches for
 223.799 +  DENIED and EXCEPTION, select "ALL DENIED" or "ALL EXCEPTIONS".  Only one
 223.800 +  ACTION can be viewed at a time and it shows most restrictive.  For example,
 223.801 +  if "Banned Site" is selected, then only DENIED requests that were DENIED because of a site being in a banned site list will be shown.  No other DENIED requests will be shown.
 223.802 +  </ul>
 223.803 +  </td></tr>
 223.804 +  <tr><td align=left><font face=arial,helvetica,sans-serif size=2>
 223.805 +  <b>Summary Information</b>
 223.806 +  <ul>
 223.807 +  Selecting these options will show a summary report for the number
 223.808 +  of sites entered.  The top 1 to 100 sites may be selected.
 223.809 +  <p>
 223.810 +  Once the summary screen appears, you may "investigate" why a site was
 223.811 +  denied/allowed and who/what machine was visiting the site.  Simply click
 223.812 +  on the "Trace" link under the "Investigate" column and the results will be
 223.813 +  shown.
 223.814 +  <p>
 223.815 +  Caution:  If you select to filter for only DENIED and check to show
 223.816 +  a summary for allowed, there will not be any results.  This is correct.
 223.817 +  If you don't see the results you expected, go back and check the
 223.818 +  criteria that was entered.
 223.819 +  <p>
 223.820 +  Turn URL's into links
 223.821 +  <ul>Checking this box will cause the URL's in the report to be clickable.
 223.822 +  </ul>
 223.823 +  </ul>
 223.824 +  </td></tr>
 223.825 +(EOF)
 223.826 +  print "<tr><td align=center><font face=arial,helvetica,sans=serif size=2>
 223.827 +  <a href=$cgipath>Return to $pagename</a></tr></td> 
 223.828 +  </table>\n";
 223.829 +}
 223.830 +
   224.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   224.2 +++ b/usr/lib/cgi-bin/listlogon.pl	Mon Apr 26 11:16:23 2010 +0200
   224.3 @@ -0,0 +1,251 @@
   224.4 +#!/usr/bin/perl -w
   224.5 +
   224.6 +# your httpd.conf should have something like this:
   224.7 +
   224.8 +# Alias /perl/  /real/path/to/perl-scripts/
   224.9 +
  224.10 +# <Location /perl>
  224.11 +# SetHandler  perl-script
  224.12 +# PerlHandler Apache::Registry
  224.13 +# PerlSendHeader On
  224.14 +# Options +ExecCGI
  224.15 +# </Location>
  224.16 +
  224.17 +my $cgipath = $ENV{SCRIPT_NAME};
  224.18 +my $qry     = $ENV{QUERY_STRING};
  224.19 +my $logonFile = "";
  224.20 +my $DOMAIN=`ldapsearch -xLLL sambaDomainName=* sambaDomainName | grep -v dn | sed 's/sambaDomainName: //'`;
  224.21 +
  224.22 +if (defined($qry)){
  224.23 +    my @aq=split(/&/,$qry);
  224.24 +    $aq[0] =~ s/logfile=//g;
  224.25 +    $logonFile=$aq[0];
  224.26 +    $aq[1] =~ s/ord=//g;
  224.27 +    $ordFile=$aq[1];
  224.28 +}
  224.29 +
  224.30 +if ($logonFile) {
  224.31 +    &vediLogonFile($logonFile,$ordFile);
  224.32 +}else{  
  224.33 +    &listaLogonFiles;
  224.34 +}
  224.35 +
  224.36 +
  224.37 +sub listaLogonFiles {
  224.38 +    my $logondir="/var/www/sambalogon";
  224.39 +    opendir(LD, $logondir) or die "Errore fatale: $!";
  224.40 +    my @allf = readdir LD;
  224.41 +    my @allfiles = sort {$b cmp $a} @allf;
  224.42 +    closedir LD;
  224.43 +    $form="
  224.44 +        <form action $cgipath method=\"GET\">
  224.45 +        <center>
  224.46 +        <table> 
  224.47 +    ";
  224.48 +        
  224.49 +    my $i=0;
  224.50 +    my $trclass;
  224.51 +    my $trjs;
  224.52 +    
  224.53 +    foreach $f (@allfiles) {
  224.54 +        
  224.55 +        next if ($f !~ m/logon-/);
  224.56 +        
  224.57 +        if ($i++ % 2) {
  224.58 +            $trclass="even";
  224.59 +        }else{
  224.60 +            $trclass="odd";
  224.61 +        }
  224.62 +        
  224.63 +        $trjs1=" onmouseover=\"this.className='surbrillance2'\" onmouseout=\"this.className='$trclass'\"";
  224.64 +        $trjs2=" onmousedown=\"document.location='listlogon.pl?logfile=$f&ord=time';\" ";
  224.65 +        
  224.66 +        $form .= "
  224.67 +            <tr class=$trclass $trjs1 $trjs2> 
  224.68 +                <td>$f<br></td>
  224.69 +            </tr>
  224.70 +        ";
  224.71 +    }   
  224.72 +    
  224.73 +    $form .= "
  224.74 +        </table></center></form>
  224.75 +    ";
  224.76 +    print "Content-type: text/html\n\n";
  224.77 +    &printHeader;
  224.78 +    print $form;
  224.79 +    #print "%ENV: <br>\n", map { "$_ = $ENV{$_} <br>\n" } keys %ENV;
  224.80 +    &printFooter;
  224.81 +}   
  224.82 +    
  224.83 +
  224.84 +sub vediLogonFile {
  224.85 +    my $lf = shift;
  224.86 +    my $ord= shift;
  224.87 +    my $logonFile="/var/www/sambalogon/$lf";
  224.88 +#   my $logonFile="/var/www/sambalogon/logon-051006";
  224.89 +    my $lst;
  224.90 +    my $r;
  224.91 +    my @ar;
  224.92 +    
  224.93 +    open(LL,"<$logonFile");
  224.94 +    my @aX=();
  224.95 +    my @aL=<LL>;
  224.96 +    my @aL1=();
  224.97 +    close LL;
  224.98 +    my $ot="↓";
  224.99 +    my $on="↓";
 224.100 +    if ($ord  eq 'id'){
 224.101 +        @aL1=sort { substr($a,15,10) cmp substr($b,15,10) } @aL;
 224.102 +        @aX=@aL1;
 224.103 +        $ot="";
 224.104 +    }else{
 224.105 +        @aX=@aL;
 224.106 +        $on="";
 224.107 +    }
 224.108 +
 224.109 +    
 224.110 +    
 224.111 +    my $trjs1=" onmouseover=\"this.className='surbrillance'\" onmouseout=\"this.className='normal'\"";
 224.112 +    my $trjs2=" onmousedown=\"document.location='listlogon.pl?logfile=$lf&ord=id';\" ";
 224.113 +    my $trjs3=" onmousedown=\"document.location='listlogon.pl?logfile=$lf&ord=time';\" ";
 224.114 +    
 224.115 +    $lst="$op<br>
 224.116 +    <center>
 224.117 +    <table>
 224.118 +    <th class='nobrd'>Data</th>
 224.119 +    <th class='nobrd' $trjs1 $trjs3>$ot Ora $ot</th>
 224.120 +    <th class='nobrd' $trjs1 $trjs2>$on UserID $on</th>
 224.121 +    <th class='nobrd'>Cognome</th>
 224.122 +    <th class='nobrd'>Nome</th>
 224.123 +    <th class='nobrd'>Classe</th>
 224.124 +    <th class='nobrd'>Quota</th>
 224.125 +    <th class='nobrd'>ClientID</th>
 224.126 +    <th class='nobrd'>op.su WLG</th>
 224.127 +    ";
 224.128 +    my $i=0;
 224.129 +    my $trclass;
 224.130 +    my $trjs;
 224.131 +
 224.132 +    foreach $l (@aX) {
 224.133 +        chop();
 224.134 +        @ar=split(/;/,$l);
 224.135 +        if ($ar[5] !~ m/INQUOTA/){
 224.136 +            $ar[5]="*"
 224.137 +        }else{
 224.138 +            $ar[5]="";
 224.139 +        }
 224.140 +        if ($i++ % 2) {
 224.141 +            $trclass="even";
 224.142 +        }else{
 224.143 +            $trclass="odd";
 224.144 +        }
 224.145 +        $trjs=" onmouseover=\"this.className='surbrillance'\" onmouseout=\"this.className='$trclass'\"";
 224.146 +        $sn=`ldapsearch -xLLL uid=$ar[2] sn | grep -w sn | sed 's/sn: //g'`;
 224.147 +        chop($sn);
 224.148 +        $cn=`ldapsearch -xLLL uid=$ar[2] cn | grep -w cn | sed 's/cn: //g'`;
 224.149 +        chop($cn);
 224.150 +        $lst .= "
 224.151 +        <tr class=$trclass $trjs> 
 224.152 +            <td>$ar[0]</td>
 224.153 +            <td >$ar[1]</td>
 224.154 +            <td>$ar[2]</td>
 224.155 +            <td>$sn</td>
 224.156 +            <td>$cn</td>
 224.157 +            <td>$ar[4]</td>
 224.158 +            <td align=\"center\">$ar[5]</td>
 224.159 +            <td>$ar[6]</td>
 224.160 +            <td>$ar[7]</td>
 224.161 +        </tr>
 224.162 +        ";
 224.163 +    }
 224.164 +
 224.165 +    $lst .= "
 224.166 +    </table>
 224.167 +    </center>
 224.168 +    ";
 224.169 +    
 224.170 +    print "Content-type: text/html\n\n";
 224.171 +    &printHeader;
 224.172 +    print $lst;
 224.173 +    &printFooter;
 224.174 +}
 224.175 +
 224.176 +sub printHeader {
 224.177 +print "
 224.178 +<HTML><HEAD>
 224.179 +<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">
 224.180 +<META HTTP-EQUIV=\"Cache-Control\" CONTENT=\"no-cache\">
 224.181 +<META HTTP-EQUIV=\"Expires\" CONTENT=\"-1\">
 224.182 +<TITLE>LISTA LOGON</TITLE>
 224.183 +<STYLE>
 224.184 +<!--
 224.185 +    TABLE       {margin-top: 0; padding-top: 0}
 224.186 +    TD          {font-family: Serif; font-size: 10pt }
 224.187 +    TH          {font-family: Serif; font-size: 12pt }
 224.188 +    
 224.189 +    th.surbrillance {
 224.190 +        background:#FFFF9A;
 224.191 +        cursor:pointer;
 224.192 +    }
 224.193 +    th.normal {
 224.194 +        background:#C1DCF0;
 224.195 +    }
 224.196 +    
 224.197 +    tr.even {
 224.198 +        background: #FAFDFF;
 224.199 +        color: #000;
 224.200 +        }
 224.201 +
 224.202 +    tr.odd {
 224.203 +        background: #E1E4E6;
 224.204 +        color: #000;
 224.205 +        }
 224.206 +
 224.207 +    tr.surbrillance {
 224.208 +        background:#FFFF9A;
 224.209 +        }
 224.210 +    tr.surbrillance2 {
 224.211 +        background:#FFFF9A;
 224.212 +        cursor:pointer;
 224.213 +        }
 224.214 +    th.nobrd {
 224.215 +        background: #C1DCF0;
 224.216 +        border-bottom: 0px solid #D5A085;
 224.217 +        border-top: 0px solid #D5A085;
 224.218 +        border-left: 0px solid #D5A085;
 224.219 +        border-right: 0px solid #D5A085;
 224.220 +        text-align: center;
 224.221 +    }
 224.222 + 
 224.223 +-->
 224.224 +</STYLE>
 224.225 +
 224.226 +</script>
 224.227 +
 224.228 +</HEAD>
 224.229 +<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#0000ff\" vlink=\"#0000ff\"
 224.230 +alink=\"#0000ff\">
 224.231 +<center>
 224.232 +<table width=\"600\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">
 224.233 +<tr><th width=\"600\" align=\"center\">
 224.234 +<font size=\"4\" color=\"#000000\" face=\"arial\">
 224.235 +<hr noshade size=1 width=90%>
 224.236 +ACCESSI AL DOMINIO SAMBA: $DOMAIN
 224.237 +<hr noshade size=1 width=90%>
 224.238 +</th></tr>
 224.239 +</table>
 224.240 +</center>
 224.241 +";
 224.242 +
 224.243 +}
 224.244 +
 224.245 +sub printFooter {
 224.246 +print "
 224.247 +</BODY>
 224.248 +</HTML>
 224.249 +";
 224.250 +}
 224.251 +
 224.252 +
 224.253 +
 224.254 +
   225.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   225.2 +++ b/usr/lib/isi/acl.conf	Mon Apr 26 11:16:23 2010 +0200
   225.3 @@ -0,0 +1,98 @@
   225.4 +## Ogni modifica a questo file verrà sovrascritta al cambio di release.
   225.5 +## modificare invece il file /etc/isi/acl-local.conf
   225.6 +
   225.7 +## i gruppi principali di default sono:
   225.8 +## admins alunni ata docenti esterni ospiti segreteria grtest
   225.9 +
  225.10 +[alunni]
  225.11 +  path = /home/users/alunni
  225.12 +  grp       = docenti
  225.13 +  u:        = rxw    # ogni permesso al proprietario
  225.14 +  g:docenti = rxw    # il gruppo docenti deve poter fare tutto
  225.15 +  g:admins  = rxw    # anche gli admins
  225.16 +  g:alunni  = ---    # nessun alunno ha diritti
  225.17 +  o         = ---    # nessun altro ha diritto di fare qualche cosa
  225.18 +  public_html = true
  225.19 +
  225.20 +
  225.21 +[docenti] 
  225.22 +  path = /home/users/docenti
  225.23 +  grp       = docenti
  225.24 +  u:        = rxw    # l'utente deve poter fare tutto
  225.25 +  g:        = ---    # il gruppo nulla (questo implica che nessun altro
  225.26 +                     # gruppo può per via della risemantizzazione delle
  225.27 +		             # groupship a "upper bound"
  225.28 +  o         = ---     
  225.29 +  public_html = true
  225.30 +
  225.31 +[ata]
  225.32 +  path = /home/users/ata
  225.33 +  grp  = ata
  225.34 +  copy = docenti
  225.35 +  public_html = true
  225.36 +
  225.37 +[admins]
  225.38 +  path = /home/users/admins
  225.39 +  grp       = admins
  225.40 +  copy = docenti
  225.41 +  g:admins  = ---		# gli admins non possono vedere altri admins
  225.42 +  public_html = true
  225.43 +
  225.44 +[segreteria]
  225.45 +  path = /home/users/segreteria
  225.46 +  grp       = segreteria
  225.47 +  copy = docenti
  225.48 +  g:segreteria = --- 
  225.49 +
  225.50 +[esterni]
  225.51 +  path = /home/users/esterni
  225.52 +  grp  = esterni
  225.53 +  copy = docenti
  225.54 +  g:esterni = --- 
  225.55 +  public_html = true
  225.56 +
  225.57 +[ospiti]
  225.58 +  path = /home/users/ospiti
  225.59 +  grp  = ospiti
  225.60 +  copy = docenti
  225.61 +  g:ospiti = --- # gli utenti di ospiti entrano nella propria home
  225.62 +  public_html = true
  225.63 +
  225.64 +[classi]
  225.65 +  path = /home/shares/classi
  225.66 +  g:docenti = rxw
  225.67 +  g:admins = rxw
  225.68 +  g:   = rxw			# ogni classe deve poter fare tutto in questa area
  225.69 +
  225.70 +[area_segreteria]
  225.71 +  path = /home/shares/area_segreteria
  225.72 +  grp = segreteria
  225.73 +  g:segreteria = rxw
  225.74 +  g:alunni     = ---
  225.75 +  o            = rx
  225.76 +
  225.77 +[area_materiali]
  225.78 +  path = /home/shares/area_materiali
  225.79 +  g:docenti = rxw
  225.80 +  g:admins = rxw
  225.81 +  o = rx
  225.82 +
  225.83 +[area_docenti]
  225.84 +  path = /home/shares/area_docenti
  225.85 +  g:docenti = rxw
  225.86 +  g:admins = rxw
  225.87 +  o = ---
  225.88 +
  225.89 +[area_alunni]
  225.90 +  path = /home/shares/area_alunni
  225.91 +  copy = alunni  # copia da /home/shares/classi le permission 
  225.92 +  g:alunni    = rxw    # e modifica questo
  225.93 +
  225.94 +[post_exec]
  225.95 +  file = /etc/isi/acl-post-exec.sh
  225.96 +  ## non modificate la riga seguente se non sapete cosa fate!!!
  225.97 +  cmd01  = setfacl --set u::7,g::5,o:0 /home/users/*
  225.98 +  cmd02  = setfacl --set u::7,g::5,o:5 /home/users/alunni /home/shares/classi
  225.99 +  cmd03  = chmod 600 /root
 225.100 +  cmd04  = isi-classe -N   # no samba
 225.101 +  cmd05  = isi-classe -C
 225.102 \ No newline at end of file
   226.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   226.2 +++ b/usr/lib/perl5/ISI/Conf.pm	Mon Apr 26 11:16:23 2010 +0200
   226.3 @@ -0,0 +1,95 @@
   226.4 +# +-------------------------------------------------+
   226.5 +# � 2002-2005 ReteIsi / www.reteisi.org 
   226.6 +# +-------------------------------------------------+
   226.7 +# $Id: Conf.pm,v 1.1.1.3 2021/10/09 04:34:58 max Exp $
   226.8 +
   226.9 +package ISI::Conf;
  226.10 +
  226.11 +use strict;
  226.12 +
  226.13 +
  226.14 +BEGIN {
  226.15 +    use Exporter   ();
  226.16 +    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
  226.17 +
  226.18 +    # set the version for version checking
  226.19 +    # if using RCS/CVS, this may be preferred
  226.20 +    $VERSION = sprintf "%d.%03d", q$Revision: 1.1.1.3 $ =~ /(\d+)/g;
  226.21 +
  226.22 +    @ISA         = qw(Exporter Autoload );
  226.23 +    @EXPORT      = qw(&ReadLdapConf );
  226.24 +#    @EXPORT_OK   = qw(%LdapConf);
  226.25 +
  226.26 +}
  226.27 +# our @EXPORT_OK;
  226.28 +# our %LdapConf;
  226.29 +# %LdapConf = ();
  226.30 +
  226.31 +sub ReadLdapConf () {
  226.32 +    # this function fills the hash %LdapConf w/ parameters needed for 
  226.33 +    # normal interaction w/ the LDAP db
  226.34 +    # base: 
  226.35 +    # root_bind_dn
  226.36 +    # slapd_pwd
  226.37 +    # host
  226.38 +	my %LdapConf=();
  226.39 +
  226.40 +    open CONF, "/etc/ldap/ldap.conf";
  226.41 +    while (<CONF>) {
  226.42 +	if ($_ =~ m/^\s*BASE\s*(\S+)/) {
  226.43 +	    $LdapConf{'BASE'} = $1;
  226.44 +	}
  226.45 +	if ($_ =~ m/^\s*HOST\s*(\S+)/) {
  226.46 +	    $LdapConf{'HOST'} = $1;
  226.47 +	}
  226.48 +    }
  226.49 +    close CONF;
  226.50 +    open CONF, "/etc/pam_ldap.conf";
  226.51 +    while (<CONF>) {
  226.52 +	if ($_ =~ m/^\s*rootbinddn\s*(\S+)/) {
  226.53 +	    $LdapConf{'ROOT_BIND_DN'} = $1;
  226.54 +	}
  226.55 +    }
  226.56 +    close CONF;
  226.57 +    
  226.58 +    $LdapConf{'PWD'} = `cat /etc/ldap.secret`;
  226.59 +    chomp $LdapConf{'PWD'};
  226.60 +
  226.61 +    return %LdapConf;
  226.62 +}
  226.63 +sub ReadFile {
  226.64 +    my $file = $_[0];
  226.65 +    my $delimiter="=";
  226.66 +    my %assoc_array;
  226.67 +    my $current_line;
  226.68 +    my @righe;
  226.69 +    my $riga;
  226.70 +    my @kv;
  226.71 +
  226.72 +    if ( -T $file) {
  226.73 +        if(!open(CONF,"<$file")) {
  226.74 +            return -1;
  226.75 +        }
  226.76 +    } else {
  226.77 +        #print "Inexistent file: $file\n" ;
  226.78 +        return 0 ;
  226.79 +    }
  226.80 +    
  226.81 +    @righe=<CONF>;
  226.82 +    foreach $riga (@righe) {
  226.83 +		chop($riga);
  226.84 +        @kv=split(/=/,$riga);
  226.85 +	next if (!$kv[1]);
  226.86 +	$kv[0]=~s/ //g ;
  226.87 +        $kv[1]=~s/\"//g ;
  226.88 +        if ( $kv[0] ne "") {
  226.89 +	    	$assoc_array{$kv[0]}=$kv[1];
  226.90 +        }
  226.91 +    }
  226.92 +    close(CONF);
  226.93 +    return %assoc_array;
  226.94 +}
  226.95 +
  226.96 +
  226.97 +1;
  226.98 +
   227.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   227.2 +++ b/usr/lib/perl5/ISI/MkPasswd.pm	Mon Apr 26 11:16:23 2010 +0200
   227.3 @@ -0,0 +1,315 @@
   227.4 +package ISI::MkPasswd;
   227.5 +
   227.6 +use 5.006001;
   227.7 +use strict;
   227.8 +use base qw(Exporter);
   227.9 +
  227.10 +use Carp qw(croak);
  227.11 +
  227.12 +# Defaults.
  227.13 +use constant LENGTH		=> 8;
  227.14 +use constant MINNUM		=> 1;
  227.15 +use constant MINLOWER	=> 2;
  227.16 +use constant MINUPPER	=> 2;
  227.17 +use constant MINSPECIAL	=> 0;
  227.18 +use constant DISTRIBUTE	=> "";
  227.19 +use constant FATAL		=> "";
  227.20 +
  227.21 +our %EXPORT_TAGS = (
  227.22 +	all	=> [ qw(mkpasswd) ],
  227.23 +);
  227.24 +our @EXPORT_OK = @{ $EXPORT_TAGS{all} };
  227.25 +our $VERSION = "0.02";
  227.26 +our $FATAL = "";
  227.27 +
  227.28 +my %keys = (
  227.29 +	dist	=> {
  227.30 +		lkeys	=> [ qw(q w e r t a s d f g z x c v b) ],
  227.31 +		rkeys	=> [ qw(y u i o p h j k l n m) ],
  227.32 +		lnums	=> [ qw(1 2 3 4 5 6) ],
  227.33 +		rnums	=> [ qw(7 8 9 0) ],
  227.34 +		lspec	=> [ qw(! @ $ %), "#" ],
  227.35 +		rspec	=> [
  227.36 +			qw(^ & * ( ) - = _ + [ ] { } \ | ; : ' " < > . ? /), ","
  227.37 +		],
  227.38 +	},
  227.39 +
  227.40 +	undist	=> {
  227.41 +		lkeys	=> [
  227.42 +			qw(a b c d e f g h i j k l m n o p q r s t u v w x y z)
  227.43 +		],
  227.44 +		rkeys	=> [
  227.45 +			qw(a b c d e f g h i j k l m n o p q r s t u v w x y z)
  227.46 +		],
  227.47 +		lnums	=> [ qw(0 1 2 3 4 5 6 7 8 9) ],
  227.48 +		rnums	=> [ qw(0 1 2 3 4 5 6 7 8 9) ],
  227.49 +		lspec	=> [
  227.50 +			qw(! @ $ % ~ ^ & * ( ) - = _ + [ ] { } \ | ; : ' " < > . ? /),
  227.51 +			"#", ","
  227.52 +		],
  227.53 +		rspec	=> [
  227.54 +			qw(! @ $ % ~ ^ & * ( ) - = _ + [ ] { } \ | ; : ' " < > . ? /),
  227.55 +			"#", ","
  227.56 +		],
  227.57 +	},
  227.58 +);
  227.59 +
  227.60 +sub mkpasswd {
  227.61 +	my $class	= shift if UNIVERSAL::isa $_[0], __PACKAGE__;
  227.62 +	my %args	= @_;
  227.63 +
  227.64 +	# Configuration.
  227.65 +	my $length		= defined $args{"-length"}     
  227.66 +		? $args{"-length"}
  227.67 +		: LENGTH;
  227.68 +	my $minnum		= defined $args{"-minnum"}
  227.69 +		? $args{"-minnum"}
  227.70 +		: MINNUM;
  227.71 +	my $minlower	= defined $args{"-minlower"}
  227.72 +		? $args{"-minlower"}
  227.73 +		: MINLOWER;
  227.74 +	my $minupper	= defined $args{"-minupper"}
  227.75 +		? $args{"-minupper"}
  227.76 +		: MINUPPER;
  227.77 +	my $minspecial	= defined $args{"-minspecial"}
  227.78 +		? $args{"-minspecial"}
  227.79 +		: MINSPECIAL;
  227.80 +	my $distribute	= defined $args{"-distribute"}
  227.81 +		? $args{"-distribute"}
  227.82 +		: DISTRIBUTE;
  227.83 +	my $fatal		= defined $args{"-fatal"}
  227.84 +		? $args{"-fatal"}
  227.85 +		: FATAL;
  227.86 +
  227.87 +	++$length;
  227.88 +	
  227.89 +	if ( $minnum + $minlower + $minupper + $minspecial > $length ) {
  227.90 +		if ( $fatal || $FATAL ) {
  227.91 +			croak "Impossible to generate $length-character password with "
  227.92 +					. "$minnum numbers, $minlower lowercase letters, "
  227.93 +					. "$minupper uppercase letters and $minspecial special "
  227.94 +					. "characters";
  227.95 +		} else {
  227.96 +			return;
  227.97 +		}
  227.98 +	}
  227.99 +
 227.100 +	# If there is any underspecification, use additional lowercase letters.
 227.101 +	$minlower = $length - ($minnum + $minupper + $minspecial);
 227.102 +
 227.103 +	# Choose left or right starting hand.
 227.104 +	my $initially_left = my $isleft = int rand 2;
 227.105 +
 227.106 +	# Select distribution of keys.
 227.107 +	my $lkeys = $distribute ? $keys{dist}{lkeys} : $keys{undist}{lkeys};
 227.108 +	my $rkeys = $distribute ? $keys{dist}{rkeys} : $keys{undist}{rkeys};
 227.109 +	my $lnums = $distribute ? $keys{dist}{lnums} : $keys{undist}{lnums};
 227.110 +	my $rnums = $distribute ? $keys{dist}{rnums} : $keys{undist}{rnums};
 227.111 +	my $lspec = $distribute ? $keys{dist}{lspec} : $keys{undist}{lspec};
 227.112 +	my $rspec = $distribute ? $keys{dist}{rspec} : $keys{undist}{rspec};
 227.113 +
 227.114 +	# Generate password.
 227.115 +
 227.116 +	my @lpass = (undef) x $length;	# password chars typed by left hand
 227.117 +	my @rpass = (undef) x $length;	# password chars typed by right hand
 227.118 +	my ($left, $right);
 227.119 +
 227.120 +	($left, $right) = &_psplit($minnum, \$isleft);
 227.121 +	for ( my $i = 0; $i < $left; $i++ ) {
 227.122 +		&_insert(\@lpass, $lnums->[rand @$lnums]);
 227.123 +	}
 227.124 +	for ( my $i = 0; $i < $right; $i++ ) {
 227.125 +		&_insert(\@rpass, $rnums->[rand @$rnums]);
 227.126 +	}
 227.127 +
 227.128 +	($left, $right) = &_psplit($minlower, \$isleft);
 227.129 +	for ( my $i = 0; $i < $left; $i++ ) {
 227.130 +		&_insert(\@lpass, $lkeys->[rand @$lkeys]);
 227.131 +	}
 227.132 +	for ( my $i = 0; $i < $right; $i++ ) {
 227.133 +		&_insert(\@rpass, $rkeys->[rand @$rkeys]);
 227.134 +	}
 227.135 +
 227.136 +	($left, $right) = &_psplit($minupper, \$isleft);
 227.137 +	for ( my $i = 0; $i < $left; $i++ ) {
 227.138 +		&_insert(\@lpass, uc $lkeys->[rand @$lkeys]);
 227.139 +	}
 227.140 +	for ( my $i = 0; $i < $right; $i++ ) {
 227.141 +		&_insert(\@rpass, uc $rkeys->[rand @$rkeys]);
 227.142 +	}
 227.143 +
 227.144 +	($left, $right) = &_psplit($minspecial, \$isleft);
 227.145 +	for ( my $i = 0; $i < $left; $i++ ) {
 227.146 +		&_insert(\@lpass, $lspec->[rand @$lspec]);
 227.147 +	}
 227.148 +	for ( my $i = 0; $i < $right; $i++ ) {
 227.149 +		&_insert(\@rpass, $rspec->[rand @$rspec]);
 227.150 +	}
 227.151 +
 227.152 +	# Merge results together.
 227.153 +	my $lpass = join "", map { defined $_ ? $_ : () } @lpass;
 227.154 +	my $rpass = join "", map { defined $_ ? $_ : () } @rpass;
 227.155 +
 227.156 +	return $initially_left ? "$lpass$rpass" : "$rpass$lpass";
 227.157 +}
 227.158 +
 227.159 +# Insert $char into password at a random position, thereby spreading the
 227.160 +# different kinds of characters throughout the password.
 227.161 +sub _insert {
 227.162 +	my $pass	= shift;	# ref = ARRAY
 227.163 +	my $char	= shift;
 227.164 +
 227.165 +	my $pos;
 227.166 +	do {
 227.167 +		$pos = int rand(1 + @$pass);
 227.168 +	} while ( defined $pass->[$pos] );
 227.169 +
 227.170 +	$pass->[$pos] = $char;
 227.171 +}
 227.172 +
 227.173 +# Given a size, distribute between left and right hands, taking into account
 227.174 +# where we left off.
 227.175 +sub _psplit {
 227.176 +	my $max		= shift;
 227.177 +	my $isleft	= shift;	# ref = SCALAR
 227.178 +
 227.179 +	my ($left, $right);
 227.180 +
 227.181 +	if ( $$isleft ) {
 227.182 +		$right = int($max / 2);
 227.183 +		$left = $max - $right;
 227.184 +		$$isleft = !($max % 2);
 227.185 +	} else {
 227.186 +		$left = int($max / 2);
 227.187 +		$right = $max - $left;
 227.188 +		$$isleft = !($max % 2);
 227.189 +	}
 227.190 +
 227.191 +	return ($left, $right);
 227.192 +}
 227.193 +
 227.194 +1;
 227.195 +
 227.196 +__END__
 227.197 +
 227.198 +=head1 NAME
 227.199 +
 227.200 +String::MkPasswd - random password generator
 227.201 +
 227.202 +=head1 SYNOPSIS
 227.203 +
 227.204 +  use String::MkPasswd qw(mkpasswd);
 227.205 +
 227.206 +  print mkpasswd();
 227.207 +
 227.208 +  # for the masochisticly paranoid...
 227.209 +  print mkpasswd(
 227.210 +      -length     => 27,
 227.211 +      -minnum     => 5,
 227.212 +      -minlower   => 1,   # minlower is increased if necessary
 227.213 +      -minupper   => 5,
 227.214 +      -minspecial => 5,
 227.215 +      -distribute => 1,
 227.216 +  );
 227.217 +
 227.218 +=head1 ABSTRACT
 227.219 +
 227.220 +This Perl library defines a single function, C<mkpasswd()>, to generate
 227.221 +random passwords.  The function is meant to be a simple way for
 227.222 +developers and system administrators to easily generate a relatively
 227.223 +secure password.
 227.224 +
 227.225 +=head1 DESCRIPTION
 227.226 +
 227.227 +The exportable C<mkpasswd()> function returns a single scalar: a random
 227.228 +password.  By default, this password is nine characters long with a
 227.229 +random distribution of four lower-case characters, two upper-case
 227.230 +characters, two digits, and one non-alphanumeric character.  These
 227.231 +parameters can be tuned by the user, as described in the L</"ARGUMENTS">
 227.232 +section.
 227.233 +
 227.234 +=head2 ARGUMENTS
 227.235 +
 227.236 +The C<mkpasswd()> function takes an optional hash of arguments.
 227.237 +
 227.238 +=over 4
 227.239 +
 227.240 +=item -length
 227.241 +
 227.242 +The total length of the password.  The default is 9.
 227.243 +
 227.244 +=item -minnum
 227.245 +
 227.246 +The minimum number of digits that will appear in the final password.
 227.247 +The default is 2.
 227.248 +
 227.249 +=item -minlower
 227.250 +
 227.251 +The minimum number of lower-case characters that will appear in the
 227.252 +final password.  The default is 2.
 227.253 +
 227.254 +=item -minupper
 227.255 +
 227.256 +The minimum number of upper-case characters that will appear in the
 227.257 +final password.  The default is 2.
 227.258 +
 227.259 +=item -minspecial
 227.260 +
 227.261 +The minimum number of non-alphanumeric characters that will appear in
 227.262 +the final password.  The default is 1.
 227.263 +
 227.264 +=item -distribute
 227.265 +
 227.266 +If set to a true value, password characters will be distributed between
 227.267 +the left- and right-hand sides of the keyboard.  This makes it more
 227.268 +difficult for an onlooker to see the password as it is typed.  The
 227.269 +default is false.
 227.270 +
 227.271 +=item -fatal
 227.272 +
 227.273 +If set to a true value, C<mkpasswd()> will L<Carp::croak()> rather than
 227.274 +return C<undef> on error.  The default is false.
 227.275 +
 227.276 +=back
 227.277 +
 227.278 +If B<-minnum>, B<-minlower>, B<-minupper>, and B<-minspecial> do not add
 227.279 +up to B<-length>, B<-minlower> will be increased to compensate.
 227.280 +However, if B<-minnum>, B<-minlower>, B<-minupper>, and B<-minspecial>
 227.281 +add up to more than B<-length>, then C<mkpasswd()> will return C<undef>.
 227.282 +See the section entitled L</"EXCEPTION HANDLING"> for how to change this
 227.283 +behavior.
 227.284 +
 227.285 +=head2 EXCEPTION HANDLING
 227.286 +
 227.287 +By default, C<mkpasswd()> will return C<undef> if it cannot generate a
 227.288 +password.  Some people are inclined to exception handling, so
 227.289 +B<String::MkPasswd> does its best to accomodate them.  If the variable
 227.290 +C<$String::MkPasswd::FATAL> is set to a true value, C<mkpasswd()> will
 227.291 +L<Carp::croak()> with an error instead of returning C<undef>.
 227.292 +
 227.293 +=head2 EXPORT
 227.294 +
 227.295 +None by default.  The C<mkpasswd()> method is exportable.
 227.296 +
 227.297 +=head1 SEE ALSO
 227.298 +
 227.299 +L<http://expect.nist.gov/#examples>, L<mkpasswd(1)>
 227.300 +
 227.301 +=head1 AKNOWLEDGEMENTS
 227.302 +
 227.303 +Don Libes of the National Institute of Standards and Technology, who
 227.304 +wrote the Expect example, L<mkpasswd(1)>.
 227.305 +
 227.306 +=head1 AUTHOR
 227.307 +
 227.308 +Chris Grau E<lt>[email protected]<gt>
 227.309 +
 227.310 +=head1 COPYRIGHT AND LICENSE
 227.311 +
 227.312 +Copyright (C) 2003-2004 by Chris Grau
 227.313 +
 227.314 +This library is free software; you can redistribute it and/or modify it
 227.315 +under the same terms as Perl itself, either Perl version 5.8.1 or, at
 227.316 +your option, any later version of Perl 5 you may have available.
 227.317 +
 227.318 +=cut
   228.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   228.2 +++ b/usr/lib/perl5/ISI/User.pm	Mon Apr 26 11:16:23 2010 +0200
   228.3 @@ -0,0 +1,152 @@
   228.4 +# +-------------------------------------------------+
   228.5 +# � 2002-2005 ReteIsi / www.reteisi.org 
   228.6 +# +-------------------------------------------------+
   228.7 +# $Id: User.pm,v 1.1.1.3 2021/10/09 04:34:58 max Exp $
   228.8 +
   228.9 +package ISI::User;
  228.10 +use Net::LDAP;
  228.11 +use ISI::Conf;
  228.12 +
  228.13 +use strict;
  228.14 +
  228.15 +BEGIN {
  228.16 +	use Exporter   ();
  228.17 +	our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
  228.18 +
  228.19 +	# set the version for version checking
  228.20 +	# if using RCS/CVS, this may be preferred
  228.21 +	$VERSION = sprintf "%d.%03d", q$Revision: 1.1.1.3 $ =~ /(\d+)/g;
  228.22 +
  228.23 +	@ISA         = qw(Exporter Autoload ISI::Conf Net::LDAP);
  228.24 +	@EXPORT      = qw(&FindUser &Bind);
  228.25 +
  228.26 +}
  228.27 +
  228.28 +my %CONF = &ReadLdapConf();
  228.29 +my $ldap;
  228.30 +
  228.31 +sub Bind() {
  228.32 +	my $ris;
  228.33 +
  228.34 +	$ldap =	Net::LDAP->new($CONF{'HOST'},
  228.35 +							port => 389,
  228.36 +							version => 3,
  228.37 +							timeout => 60)
  228.38 +			or die "ERRORE LDAP: non riesco a contattare il server ($@)";
  228.39 +	
  228.40 +	$ris  = $ldap->bind($CONF{'ROOT_BIND_DN'}, password=>$CONF{'PWD'});
  228.41 +	
  228.42 +	if ( $ris->is_error ) {
  228.43 +		print STDERR "ERRORE LDAP: bind autenticato non riuscito\n";
  228.44 +		exit;
  228.45 +	}
  228.46 +	return $ris;
  228.47 +}
  228.48 +
  228.49 +sub FindUser {
  228.50 +	# trova l'utente dato lo UID
  228.51 +	my $str = shift;
  228.52 +	my $campi = shift;
  228.53 +	my $txt ;
  228.54 +	my @fields;
  228.55 +	my $a;
  228.56 +	my $ris;
  228.57 +	my @info;
  228.58 +	my $filter = "(&(uid=$str)(objectClass=posixAccount))";
  228.59 +	if (defined($campi) ) {
  228.60 +		@fields = split /[,\s]/, $campi;
  228.61 +	} else {
  228.62 +	@fields = ('cn');
  228.63 +	}
  228.64 +	## creaiamo una referenza perche'  non possiamo mettere un array in
  228.65 +	## uno hash (valore della chiave attrs)
  228.66 +	$a = \@fields ;
  228.67 +	$ris = $ldap->search(
  228.68 +							filter => $filter,
  228.69 +							base   => $CONF{'BASE'},
  228.70 +							attrs  => $a);
  228.71 +	@info   = $ris->entries;
  228.72 +	$txt = "";
  228.73 +	foreach my $entry (@info) {
  228.74 +		foreach my $at (@fields) {
  228.75 +			$txt .= $entry->get_value($at)."\n";
  228.76 +		}
  228.77 +	}
  228.78 +	return $txt;
  228.79 +}
  228.80 +
  228.81 +
  228.82 +sub SearchUser {
  228.83 +	#trova l'utente in base a una condizione di filtro
  228.84 +	#il primo campo passato e' la chiave della risposta 
  228.85 +	my $flt = shift;
  228.86 +	my $campi  = shift;
  228.87 +	my $txt;
  228.88 +	my @fields;
  228.89 +	my $a;
  228.90 +	my $ris;
  228.91 +	my @info;
  228.92 +	my $filter = "(&($flt)(objectClass=posixAccount))";
  228.93 +	if (defined($campi) ) {
  228.94 +		@fields = split /[,\s]/, $campi;
  228.95 +	} else {
  228.96 +		@fields = ('cn');
  228.97 +	}
  228.98 +	## creaiamo una referenza perche'  non possiamo mettere un array in
  228.99 +	## uno hash (valore della chiave attrs)
 228.100 +	$a = \@fields ;
 228.101 +	$ris = $ldap->search(
 228.102 +							filter => $filter,
 228.103 +							base   => $CONF{'BASE'},
 228.104 +							attrs  => $a); 
 228.105 +	@info   = $ris->entries;
 228.106 +	$txt = "";
 228.107 +	foreach my $entry (@info) {
 228.108 +		foreach my $at (@fields) {
 228.109 +			$txt .= $entry->get_value($at)."\n";
 228.110 +		}
 228.111 +	}
 228.112 +	return $txt;
 228.113 +}
 228.114 +
 228.115 +sub SearchGroup {
 228.116 +	#trova l'utente in base a una condizione di filtro
 228.117 +	#il primo campo passato e' la chiave della risposta 
 228.118 +	my $flt = shift;
 228.119 +	my $campi  = shift;
 228.120 +	my $txt;
 228.121 +	my @fields;
 228.122 +	my $a;
 228.123 +	my $ris;
 228.124 +	my @info;
 228.125 +	my $filter = "(&($flt)(objectClass=posixGroup))";
 228.126 +	
 228.127 +	if (defined($campi) ) {
 228.128 +		@fields = split /[,\s]/, $campi;
 228.129 +	} else {
 228.130 +		@fields = ('cn');	my $ldap;
 228.131 +
 228.132 +	}
 228.133 +	## creaiamo una referenza perche'  non possiamo mettere un array in
 228.134 +	## uno hash (valore della chiave attrs)
 228.135 +	$a = \@fields ;
 228.136 +	$ris = $ldap->search(
 228.137 +							filter => $filter,
 228.138 +							base   => $CONF{'BASE'},
 228.139 +							attrs  => $a); 
 228.140 +	@info   = $ris->entries;
 228.141 +	$txt = "";
 228.142 +	foreach my $entry (@info) {
 228.143 +		foreach my $at (@fields) {
 228.144 +			$txt .= $entry->get_value($at)."\n";
 228.145 +		}
 228.146 +	}
 228.147 +	return $txt;
 228.148 +}
 228.149 +
 228.150 +1;
 228.151 +
 228.152 +
 228.153 +
 228.154 +
 228.155 +
   229.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   229.2 +++ b/usr/sbin/isi-addgroup	Mon Apr 26 11:16:23 2010 +0200
   229.3 @@ -0,0 +1,52 @@
   229.4 +#!/usr/bin/python
   229.5 +# -*- coding: utf-8 -*-
   229.6 +
   229.7 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   229.8 +#
   229.9 +#  This program is free software: you can redistribute it and/or modify
  229.10 +#  it under the terms of the GNU General Public License as published by
  229.11 +#  the Free Software Foundation, either version 3 of the License, or
  229.12 +#  (at your option) any later version.
  229.13 +#
  229.14 +#  This program is distributed in the hope that it will be useful,
  229.15 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  229.16 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  229.17 +#  GNU General Public License for more details.
  229.18 +#
  229.19 +#  You should have received a copy of the GNU General Public License
  229.20 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  229.21 +
  229.22 +
  229.23 +"""
  229.24 +Adds a group to ldap system
  229.25 +
  229.26 +  usage: %prog [options] group_name
  229.27 +    -g, --gid=GID: set gid GID
  229.28 +    -v, --verbose: be verbose
  229.29 +    -q, --quiet: be quiet if it already exists (exit with 0)
  229.30 +    -s, --system: add an ldap system group, possibly same gid as existent
  229.31 +"""
  229.32 +
  229.33 +import isi
  229.34 +import sys
  229.35 +import re
  229.36 +from dry import optionparse
  229.37 +from isi.models import PosixGroup
  229.38 +
  229.39 +#### PROGRAM
  229.40 +opts, args = optionparse.parse(__doc__)
  229.41 +
  229.42 +l = isi.Manager()
  229.43 +
  229.44 +
  229.45 +for group_name in args:
  229.46 +    try:
  229.47 +        l.add_group(group_name, quiet=opts.quiet, system=opts.system)
  229.48 +    except Exception:
  229.49 +        print "Already existing group '%s'" % l.get_group(group_name)
  229.50 +        
  229.51 +sys.exit(0)
  229.52 +
  229.53 +    
  229.54 +
  229.55 +
   230.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   230.2 +++ b/usr/sbin/isi-adduser	Mon Apr 26 11:16:23 2010 +0200
   230.3 @@ -0,0 +1,265 @@
   230.4 +#!/usr/bin/python
   230.5 +# -*- coding: utf-8 -*-
   230.6 +
   230.7 +# This program is free software; you can redistribute it and/or modify
   230.8 +# it under the terms of the GNU General Public License as published by
   230.9 +# the Free Software Foundation; either version 2, or (at your option)
  230.10 +# any later version.
  230.11 +
  230.12 +# AUTHORS: Sandro Dentella - Massimo Mancini
  230.13 +
  230.14 +"""
  230.15 +Utility per aggiugere utenti. Puo' essere usata sia interattivamente sia in
  230.16 +modo script leggendo da file (opzione -f) che passando la definizione dell'
  230.17 +alunno da riga di comando.
  230.18 +
  230.19 +Il formato della riga deve essere almeno:
  230.20 +
  230.21 +    logname;cognome;nome;gruppo_principale;classe;CF;password
  230.22 +
  230.23 +possono essere accodati altri campi rispettando il seguente formato:
  230.24 +
  230.25 +    sesso;indirizzo;cap;comune;provincia;telefono
  230.26 +
  230.27 +ogni campo puo' essere vuoto tranne logname e gruppo principale
  230.28 +la classe ha senso per alunni ed esterni e verra' usata per connettere la risorsa
  230.29 +Viene memorizzata in ldap come departmentNumber
  230.30 +
  230.31 +ATTENZIONE: se logname inizia con un - (meno) l'utente viene cancellato, in questo
  230.32 +caso l'opzione -z elimina la home dell'utente eliminato che altrimenti verra' 
  230.33 +semplicemente targizzata
  230.34 +
  230.35 +La forma [isi-adduser user gruppo] aggiunge l'utente al gruppo
  230.36 +
  230.37 +  usage: %prog [options] [ -f file_name ] 
  230.38 +    -N, --dry-run: non tocca il db ldap o il filesystem 
  230.39 +    -d, --debug: Mostra i comandi mentre li esegue
  230.40 +    -B, --force-change-passwd: forza cambio password all'accesso
  230.41 +    -f, --file=FILE: legge gli utenti da file (record standard)
  230.42 +    -F, --file-extended: legge gli utenti da file (record esteso)
  230.43 +    -v, --verbose: aumenta i messaggi
  230.44 +    -i, --interactive: modo interattivo (default se manca file)
  230.45 +    -I, --interactive-extended: modo interattivo con dati estesi
  230.46 +    -s, --string=str-definition: usa str-definition come definizione alunno
  230.47 +    -t, --test=str-def: come -s ma basta logname;gruppo;pwd
  230.48 +    -S, --show-conf: mostra la configurazione
  230.49 +    -x, --no-filesystem: non crea le cartelle
  230.50 +    -H, --home=host: crea home dir su host1,2 (necessita ssh con chiave)
  230.51 +    -c, --check: controlla se gli utenti sono tutti da aggiungere (opt di -f)
  230.52 +    -p, --default-passwd=xx: imposta la password di default
  230.53 +    -P, --passwd-random=pwd_lenght: password casuale di lunghezza pwd_lenght (min.5)
  230.54 +    -u, --update-user: gli utenti riconosciuti come esistenti saranno aggiornati. Non tocca la password
  230.55 +    -U, --update-passwd: come -u ma con aggiornamento della password
  230.56 +    -z, --home-zap: elimina le homedirs degli utenti cancellati
  230.57 +    -L, --noalulink: NON esegue isi-alulink dopo l'inserimento degli alunni
  230.58 +    -C, --use-cf: password costruita da cf (primi 8 caratteru, prima lettera maiuscola, come -p _cf)
  230.59 +    -T, --test-mode: running tests - don't backup (go faster)
  230.60 +    -Z, --non-interactive: non chiedere nulla, fai e basta (quindi crea le classi...)
  230.61 +
  230.62 +NOTA: se il campo password contiene PASSWORD, la password non viene gestita.
  230.63 +"""
  230.64 +
  230.65 +import isi
  230.66 +import sys
  230.67 +import re
  230.68 +import pexpect
  230.69 +from dry import optionparse
  230.70 +from dry.functions import execute, ExecuteError
  230.71 +from isi.filesystem import show_file
  230.72 +from isi import srv, exc, parser
  230.73 +from isi.conf import defaults 
  230.74 +
  230.75 +MSG_ERR01 = "ERRORE: gli utenti del gruppo %s devono essere membri di %s\n%s  come primo elemento del campo GRUPPI"
  230.76 +    
  230.77 +# TODO: ma siamo certi che IsiUserAdd serva?
  230.78 +class IsiUserAdd(isi.Manager):
  230.79 +    """ check all the group in one shot before starting. """
  230.80 +
  230.81 +    def check_groups_and_add(self, groups):
  230.82 +        """to be overloaded by isi-adduser for efficency """
  230.83 +        pass
  230.84 +
  230.85 +def test2string(test):
  230.86 +    logname, main_group, pwd = [x.strip() for x in re.split('[;,]', test)]
  230.87 +    main_group = srv.maingroup_byprefix(logname)
  230.88 +    return "%s;%s;%s;%s;;cf;%s" % (logname, main_group.title(), logname,
  230.89 +                                 main_group, pwd)
  230.90 +    
  230.91 +def go_interactive(isi_user):
  230.92 +    """prompt for interactive input of users to add"""
  230.93 +
  230.94 +    print "-"*70
  230.95 +    print "ISI-ADDUSER-MODO INTERATTIVO: user_ID vuoto = FINE\nAl posto dello USER_ID, puoi scrivere una stringa unica nel formato std:"
  230.96 +    if opts.interactive_extended:
  230.97 +        print "userID;cogn;nome;gruppo;gruppi;cf;pwd;sesso;indir;comune;cap;prov;tel"
  230.98 +        interactive_attrs = defaults.DATI_USER.split()
  230.99 +    else:
 230.100 +        print "userID;cognome;nome;gruppo;gruppi;cf;passwd\n"
 230.101 +        interactive_attrs = defaults.DATI_USER.split()[:7]
 230.102 +    print "-"*70
 230.103 +    
 230.104 +    data = []
 230.105 +    system_main_groups = srv.get_main_groups()
 230.106 +    for att in interactive_attrs:
 230.107 +        valdef = delim1 = delim2 = ""
 230.108 +        if att == 'GRUPPO':
 230.109 +            valdef = main_group
 230.110 +            delim1 = ' ['
 230.111 +            delim2 = ']'
 230.112 +            
 230.113 +        if att == 'PASSWORD':
 230.114 +            valdef = parser.new_password()
 230.115 +            delim1 = ' ['
 230.116 +            delim2 = ']'
 230.117 +            
 230.118 +        while True:
 230.119 +            returned_input = raw_input("%-20s:" % (att + delim1 + valdef + delim2))
 230.120 +            ## logname may be a string to split
 230.121 +            if len(re.split(";", returned_input)) > 1:
 230.122 +                return returned_input
 230.123 +            else:
 230.124 +                if att == 'USER_ID':
 230.125 +                    if not returned_input:
 230.126 +                        return None
 230.127 +                    elif isi_user.user_exists(returned_input):
 230.128 +                        print "ERRORE: utente esistente"
 230.129 +                        continue
 230.130 +                    main_group = srv.maingroup_byprefix(returned_input)
 230.131 +                elif att == 'GRUPPO':
 230.132 +                    if returned_input=='':
 230.133 +                        returned_input = valdef
 230.134 +                    elif returned_input not in system_main_groups:
 230.135 +                        print "ERRORE: il gruppo principale dichiarato non esiste"
 230.136 +                        continue
 230.137 +
 230.138 +                elif att == 'GRUPPI' and data[3] in 'alunni esterni':
 230.139 +                    if main_group == 'alunni':
 230.140 +                        xx = ('alunni','una classe', 'dichiarata')
 230.141 +                    else:
 230.142 +                        xx = ('esterni','un corso', 'dichiarato')
 230.143 +                    if returned_input=='':
 230.144 +                        print MSG_ERR01 % xx
 230.145 +                        continue
 230.146 +                            
 230.147 +                elif att == 'PASSWORD' and returned_input=='':
 230.148 +                    returned_input = valdef
 230.149 +                    
 230.150 +                data += [returned_input]
 230.151 +                break
 230.152 +
 230.153 +    return ';'.join(data)
 230.154 +
 230.155 +# def check_alulink(s):
 230.156 +#     if opts.noalulink: return
 230.157 +#     ss = s.split(';')
 230.158 +#     if ss[3] in ('alunni', 'esterni'):
 230.159 +#         classe = ss[4].split(',')[0]
 230.160 +#         if not classe in classi:
 230.161 +#             classi.append(classe)
 230.162 +
 230.163 +def handle_exceptions(e):
 230.164 +
 230.165 +    import traceback
 230.166 +
 230.167 +    if isinstance(e, exc.MissingMainGroup):
 230.168 +        if e.user:
 230.169 +            print "Missing Maingroup: '%s' while defining user '%s' (%s)" % (
 230.170 +                e.maingroup, e.user.logname, e.user.full_name)
 230.171 +        else:
 230.172 +            if not e.maingroup:
 230.173 +                print "Maingroup non definito: probabili problemi di formato file input"
 230.174 +            else:
 230.175 +                print "Missing Maingroup: '%s' " % (e.maingroup, )
 230.176 +        sys.exit(1)
 230.177 +    if isinstance(e, exc.AlreadyExistingUser):
 230.178 +        print "User '%s' si already defined" % e.logname
 230.179 +        sys.exit(1)
 230.180 +
 230.181 +    traceback.print_exc()
 230.182 +    sys.exit(1)
 230.183 +    
 230.184 +         
 230.185 +#### PROGRAM
 230.186 +logger = isi.get_logger()
 230.187 +logger.debug("Si comincia...")
 230.188 +opts, args = optionparse.parse(__doc__)
 230.189 +
 230.190 +if opts.home:
 230.191 +    l.sambaHome = opts.home
 230.192 +
 230.193 +if opts.file_extended:
 230.194 +    opts.file = opts.file_extended
 230.195 +    
 230.196 +if opts.update_passwd:
 230.197 +    ## update_passwd implies update_user
 230.198 +    opts.update_user = True
 230.199 +
 230.200 +conn = isi.IsiConn(dry_run=opts.dry_run)
 230.201 +
 230.202 +if opts.test_mode:
 230.203 +    conn.tests_running = True
 230.204 +
 230.205 +if opts.file:
 230.206 +    l = IsiUserAdd(conn, verbose=opts.verbose)
 230.207 +else:
 230.208 +    l = isi.Manager(conn, verbose=opts.verbose)
 230.209 +
 230.210 +### implement isi-adduser user group
 230.211 +if len(args) == 2:
 230.212 +    user_name, group_name = args
 230.213 +    print "Aggiungo utente al gruppo", group_name
 230.214 +    try:
 230.215 +        group = l.get_group(group_name)
 230.216 +    except MissingMatch:
 230.217 +        print "Il gruppo '%s' non esiste" % group_name
 230.218 +        sys,exit(1)
 230.219 +        
 230.220 +    
 230.221 +    group.add_member(user_name)
 230.222 +    execute('nscd -i group')
 230.223 +    sys.exit()
 230.224 +
 230.225 +if opts.show_conf:
 230.226 +    conn.show_conf()
 230.227 +    sys.exit(0)
 230.228 +
 230.229 +
 230.230 +conn.backup()
 230.231 +
 230.232 +kw = {
 230.233 +    'no_filesystem'       : opts.no_filesystem,
 230.234 +    'update_user'         : opts.update_user,
 230.235 +    'update_passwd'       : opts.update_passwd,
 230.236 +    'home_mode'           : 'tar' if not opts.home_zap else 'rm' ,
 230.237 +    'force_passwd_change' : opts.force_change_passwd,
 230.238 +    'default_passwd'      : opts.default_passwd,
 230.239 +    'use_cf'              : opts.use_cf,
 230.240 +    'passwd_random'       : opts.passwd_random,
 230.241 +    'run_alulink'         : not opts.noalulink,
 230.242 +    }
 230.243 +## check args
 230.244 +if not args:
 230.245 +    if opts.test:
 230.246 +        logger.debug(test2string(opts.test))
 230.247 +        opts.string = test2string(opts.test)
 230.248 +        
 230.249 +    if opts.string:
 230.250 +        try:
 230.251 +            l.parse_user_definition_string(opts.string, interactive=not opts.non_interactive, **kw)
 230.252 +        except Exception, e:
 230.253 +            handle_exceptions(e)
 230.254 +        
 230.255 +if opts.interactive or opts.interactive_extended:
 230.256 +    l.parse_user_definition_string(go_interactive(l),interactive=True, **kw)
 230.257 +
 230.258 +# read file
 230.259 +if opts.file:
 230.260 +    try:
 230.261 +        l.read_file(opts.file, interactive=not opts.non_interactive, **kw)
 230.262 +    except Exception, e:
 230.263 +        handle_exceptions(e)
 230.264 +
 230.265 +
 230.266 +
 230.267 +sys.exit(0)
 230.268 +
   231.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   231.2 +++ b/usr/sbin/isi-alulink	Mon Apr 26 11:16:23 2010 +0200
   231.3 @@ -0,0 +1,44 @@
   231.4 +#!/usr/bin/python
   231.5 +# -*- coding: utf-8 -*-
   231.6 +
   231.7 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   231.8 +#
   231.9 +#  This program is free software: you can redistribute it and/or modify
  231.10 +#  it under the terms of the GNU General Public License as published by
  231.11 +#  the Free Software Foundation, either version 3 of the License, or
  231.12 +#  (at your option) any later version.
  231.13 +#
  231.14 +#  This program is distributed in the hope that it will be useful,
  231.15 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  231.16 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  231.17 +#  GNU General Public License for more details.
  231.18 +#
  231.19 +#  You should have received a copy of the GNU General Public License
  231.20 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  231.21 +
  231.22 +
  231.23 +
  231.24 +u"""
  231.25 +Crea per ogni classe i link agli studenti. I link hanno sia il logname che il
  231.26 +nome/cognome completo per rendere facile capire chi siano.
  231.27 +
  231.28 +  usage: %prog [options] class | course
  231.29 +"""
  231.30 +
  231.31 +import sys
  231.32 +from isi import srv
  231.33 +from dry import optionparse
  231.34 +from isi import filesystem, Manager
  231.35 +
  231.36 +
  231.37 +#### PROGRAM
  231.38 +opts, args = optionparse.parse(__doc__)
  231.39 +
  231.40 +
  231.41 +if not args:
  231.42 +    args = srv.get_classes() + srv.get_courses()
  231.43 +    
  231.44 +filesystem.create_alulink(args, manager=Manager() )
  231.45 +
  231.46 +sys.exit(0)
  231.47 +
   232.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   232.2 +++ b/usr/sbin/isi-area	Mon Apr 26 11:16:23 2010 +0200
   232.3 @@ -0,0 +1,133 @@
   232.4 +#!/bin/bash
   232.5 +# +-------------------------------------------------+
   232.6 +#  (C) 2002-2008 ReteIsi / www.reteisi.org 
   232.7 +# +-------------------------------------------------+
   232.8 +# This program is free software; you can redistribute it and/or modify
   232.9 +# it under the terms of the GNU General Public License as published by
  232.10 +# the Free Software Foundation; either version 2, or (at your option)
  232.11 +# any later version.
  232.12 +# AUTORE: Massimo Mancini 2008 - [email protected]
  232.13 +
  232.14 +####### FUNCTIONS
  232.15 +function help () {
  232.16 +cat << FINE
  232.17 +Comando:     `basename $0`
  232.18 +
  232.19 +Sintassi:    `basename $0` [ -h ]  area gruppo 
  232.20 +
  232.21 +Descrizione:    Crea un'area condivisa:
  232.22 +
  232.23 +                1. la cartella /home/shares/area
  232.24 +                2. di proprietà del gruppo <gruppo>
  232.25 +                3. la share di area (se già non esiste in 
  232.26 +                   /etc/isi/samba/smb_aree.conf)
  232.27 +
  232.28 +Opzioni:        -h      help (Questa pagina di manuale)
  232.29 +                -p      NON applica le acl
  232.30 +                -N      non fa reload samba
  232.31 +                -v      verboso
  232.32 +FINE
  232.33 +exit 0
  232.34 +}
  232.35 +function esegui () {
  232.36 +    debug $*
  232.37 +    eval $*
  232.38 +}
  232.39 +function debug () {
  232.40 +    if [ "$VERBOSE" = 1 ] ; then
  232.41 +        echo $*
  232.42 +    fi
  232.43 +}
  232.44 +#function set_perms () {
  232.45 +#    chmod 755 /home/shares/$area
  232.46 +#    chown root.$grp_area /home/shares/classi
  232.47 +#}
  232.48 +function crea_area () {
  232.49 +    if [ ! -d /home/shares/$area ] ; then
  232.50 +        esegui mkdir /home/shares/$area
  232.51 +    fi
  232.52 +    esegui chgrp $grp_area /home/shares/$area
  232.53 +}
  232.54 +function crea_acl () {
  232.55 +    # controlla esistenza acl in /etc/isi/acl.conf e in /etc/isi/acl-local.conf
  232.56 +    # se non trova nulla crea le acl in /etc/isi/acl-local.conf
  232.57 +    # applica le acl
  232.58 +    local CONF_FILE1=/etc/isi/acl.conf
  232.59 +    local CONF_FILE2=/etc/isi/acl-local.conf
  232.60 +    local CREA_ACL=0
  232.61 +    if ! grep -q "\[$area\]" $CONF_FILE1 ; then
  232.62 +        if [ -f $CONF_FILE2 ] ; then 
  232.63 +            if ! grep -q "\[$area\]" $CONF_FILE2 ; then
  232.64 +                CREA_ACL=1
  232.65 +            fi
  232.66 +        else
  232.67 +            CREA_ACL=1
  232.68 +        fi
  232.69 +    fi
  232.70 +    if [ $CREA_ACL = 1 ] ; then
  232.71 +        cat <<EOF >> $CONF_FILE2
  232.72 +
  232.73 +[${area#/home/shares/}]
  232.74 +  path = /home/shares/$area
  232.75 +  grp = $grp_area
  232.76 +  g:$grp_area = rxw
  232.77 +  g:alunni     = ---
  232.78 +  o            = ---
  232.79 +EOF
  232.80 +        debug "ACL creata in $CONF_FILE2"
  232.81 +    fi
  232.82 +    if [ -z $NO_ACL ] ; then 
  232.83 +        debug "ATTENDI: applico acl..."
  232.84 +        isi-perms $area
  232.85 +    fi
  232.86 +}
  232.87 +function crea_share () {
  232.88 +local CONF_FILE=/etc/isi/samba/smb_aree.conf
  232.89 +
  232.90 +if ! grep -q "\[$area\]" $CONF_FILE ; then
  232.91 +    debug Creo la share $area
  232.92 +    cat <<EOF >> $CONF_FILE
  232.93 +
  232.94 +[${area#/home/shares/}]
  232.95 +comment = Area $area
  232.96 +path = /home/shares/$area
  232.97 +guest ok = no
  232.98 +writable = yes
  232.99 +browseable =yes
 232.100 +
 232.101 +EOF
 232.102 +    
 232.103 +fi
 232.104 +}
 232.105 +
 232.106 +
 232.107 +####### PROGRAM
 232.108 +
 232.109 +while getopts hvNp var
 232.110 +do
 232.111 +  case $var in
 232.112 +      h) clear; help; exit
 232.113 +      ;;
 232.114 +      v) VERBOSE=1
 232.115 +      ;;
 232.116 +      N) NO_SAMBA=1
 232.117 +      ;;
 232.118 +      p) NO_ACL=1
 232.119 +      ;;
 232.120 +  esac
 232.121 +done
 232.122 +shift ` expr $OPTIND - 1 `
 232.123 +
 232.124 +area="$1"
 232.125 +grp_area="$2"
 232.126 +
 232.127 +[ -z "$area" ] && help
 232.128 +[ -z "$grp_area" ] && help    
 232.129 +
 232.130 +crea_area
 232.131 +crea_share
 232.132 +crea_acl
 232.133 +
 232.134 +[ -z "$NO_SAMBA" ] && /etc/init.d/samba reload > /dev/null
 232.135 +
 232.136 +exit 0
   233.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   233.2 +++ b/usr/sbin/isi-changeattr	Mon Apr 26 11:16:23 2010 +0200
   233.3 @@ -0,0 +1,64 @@
   233.4 +#!/usr/bin/python
   233.5 +# -*- coding: utf-8 -*-
   233.6 +
   233.7 +# This program is free software; you can redistribute it and/or modify
   233.8 +# it under the terms of the GNU General Public License as published by
   233.9 +# the Free Software Foundation; either version 2, or (at your option)
  233.10 +# any later version.
  233.11 +
  233.12 +# AUTHORS: Sandro Dentella - Massimo Mancini
  233.13 +
  233.14 +"""
  233.15 +Change an attribute of ldap. If no value is provided, the attribute is deleted
  233.16 +
  233.17 +  usage: %prog [options] attribute value
  233.18 +    -N, --dry-run: don't touch the ldap db or filesystem 
  233.19 +    -d, --debug: Mostra i comandi mentre li esegue
  233.20 +    -g, --group=GROUP: change to all user of GROUP
  233.21 +    -u, --uid=UID: change for UID
  233.22 +    -v, --verbose: be verbose
  233.23 +"""
  233.24 +
  233.25 +import isi
  233.26 +import sys
  233.27 +import re
  233.28 +from dry import optionparse
  233.29 +
  233.30 +
  233.31 +#### PROGRAM
  233.32 +opts, args = optionparse.parse(__doc__)
  233.33 +
  233.34 +c = isi.IsiConn(dry_run=opts.dry_run)
  233.35 +l = isi.Manager(c)
  233.36 +c.backup()
  233.37 +
  233.38 +if not opts.group and not opts.uid:
  233.39 +    msg = "You must provide logname or group via -u or -g option\n"
  233.40 +    sys.stdout.write(msg)
  233.41 +    sys.exit(1)
  233.42 +
  233.43 +if opts.group:
  233.44 +    users = l.get_members(opts.group)
  233.45 +else:
  233.46 +    users = [opts.uid]
  233.47 +
  233.48 +
  233.49 +attribute = args[0]
  233.50 +try:
  233.51 +    value = args[1]
  233.52 +except:
  233.53 +    value = None
  233.54 +    
  233.55 +for uid in users:
  233.56 +    if opts.verbose:
  233.57 +        print uid
  233.58 +    try:
  233.59 +        c.modify(uid, attribute, value)
  233.60 +    except isi.MissingMatch:
  233.61 +        msg = "logname '%s' is missing\n" % uid
  233.62 +        sys.stdout.write(msg)
  233.63 +        sys.exit(1)
  233.64 +
  233.65 +sys.exit(0)
  233.66 +
  233.67 +    
   234.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   234.2 +++ b/usr/sbin/isi-classe	Mon Apr 26 11:16:23 2010 +0200
   234.3 @@ -0,0 +1,51 @@
   234.4 +#!/usr/bin/python
   234.5 +# -*- coding: utf-8 -*-
   234.6 +
   234.7 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   234.8 +#
   234.9 +#  This program is free software: you can redistribute it and/or modify
  234.10 +#  it under the terms of the GNU General Public License as published by
  234.11 +#  the Free Software Foundation, either version 3 of the License, or
  234.12 +#  (at your option) any later version.
  234.13 +#
  234.14 +#  This program is distributed in the hope that it will be useful,
  234.15 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  234.16 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  234.17 +#  GNU General Public License for more details.
  234.18 +#
  234.19 +#  You should have received a copy of the GNU General Public License
  234.20 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  234.21 +
  234.22 +
  234.23 +
  234.24 +u"""
  234.25 +crea una classe con tutto ciò che comporta:
  234.26 +   * il gruppo
  234.27 +   * la share di samba
  234.28 +
  234.29 +  usage: %prog [options] class | course
  234.30 +    -v, --verbose: be verbose
  234.31 +    -C, --course: create a course not a class
  234.32 +    -N, --no-samba-reload: don't reload samba (used when many classes are added)
  234.33 +"""
  234.34 +
  234.35 +import sys
  234.36 +from dry import optionparse
  234.37 +from isi import filesystem, srv
  234.38 +
  234.39 +#### PROGRAM
  234.40 +opts, args = optionparse.parse(__doc__)
  234.41 +
  234.42 +if args:
  234.43 +    classes = args
  234.44 +else:
  234.45 +    if opts.course:
  234.46 +        classes = srv.get_courses()
  234.47 +    else:
  234.48 +        classes = srv.get_classes()
  234.49 +
  234.50 +for class_ in classes:
  234.51 +    filesystem.create_class(class_, course=opts.course, samba_reload= not opts.no_samba_reload)
  234.52 +
  234.53 +sys.exit(0)
  234.54 +
   235.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   235.2 +++ b/usr/sbin/isi-computer	Mon Apr 26 11:16:23 2010 +0200
   235.3 @@ -0,0 +1,65 @@
   235.4 +#!/usr/bin/python
   235.5 +# -*- coding: utf-8 -*-
   235.6 +
   235.7 +# This program is free software; you can redistribute it and/or modify
   235.8 +# it under the terms of the GNU General Public License as published by
   235.9 +# the Free Software Foundation; either version 2, or (at your option)
  235.10 +# any later version.
  235.11 +
  235.12 +# AUTHORS: Massimo Mancini
  235.13 +
  235.14 +
  235.15 +"""
  235.16 +Senza opzioni restituisce la lista dei pc windows (join)
  235.17 +
  235.18 +  usage: %prog [options] [host_name|file]
  235.19 +    -d, --delete=delete: elimina un computer (annulla il join)
  235.20 +    -f, --file=file: elimina tutti i computer elencati nel file
  235.21 +    -v, --verbose: aumenta i messaggi a video
  235.22 +"""
  235.23 +
  235.24 +
  235.25 +import isi
  235.26 +import sys
  235.27 +from dry import optionparse
  235.28 +
  235.29 +def del_computer(hostname, error):
  235.30 +    """error is different is we delete one computer from the command line
  235.31 +    or from a file, when deleteing from a file it is normal that some pc
  235.32 +    may be non-existing"""
  235.33 +
  235.34 +    try:
  235.35 +        l.del_computer(hostname)
  235.36 +    except isi.MissingMatch, e:
  235.37 +        msg = " %s is not a joined machine on this Domain" % hostname
  235.38 +        sys.stderr.write("Error: %s\n" % msg)
  235.39 +        if error:
  235.40 +            sys.exit(error)
  235.41 +
  235.42 +opts, args = optionparse.parse(__doc__)
  235.43 +
  235.44 +hostname = None
  235.45 +filename = None
  235.46 +if opts.delete: hostname = opts.delete
  235.47 +if opts.file : filename = opts.file
  235.48 +l = isi.Manager(isi.IsiConn(), opts.verbose)
  235.49 +
  235.50 +if not (hostname or filename):
  235.51 +    computers = l.get_computers()
  235.52 +    if len(computers)==0:
  235.53 +        print "non trovo computer registrati sul dominio"
  235.54 +    else:
  235.55 +        for pc in computers:
  235.56 +            dn, data = pc
  235.57 +            print "%s" % data['uid'][0]
  235.58 +
  235.59 +else:
  235.60 +    if not hostname is None:
  235.61 +        del_computer(hostname,  error=1)
  235.62 +    if not filename is None:
  235.63 +        for host in open(filename):
  235.64 +            host = host[:-1]
  235.65 +            del_computer(host,  error=0)
  235.66 +            
  235.67 +    
  235.68 +sys.exit(0)
   236.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   236.2 +++ b/usr/sbin/isi-convert	Mon Apr 26 11:16:23 2010 +0200
   236.3 @@ -0,0 +1,97 @@
   236.4 +#!/usr/bin/python
   236.5 +# -*- coding: utf-8 -*-
   236.6 +
   236.7 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   236.8 +#
   236.9 +#  This program is free software: you can redistribute it and/or modify
  236.10 +#  it under the terms of the GNU General Public License as published by
  236.11 +#  the Free Software Foundation, either version 3 of the License, or
  236.12 +#  (at your option) any later version.
  236.13 +#
  236.14 +#  This program is distributed in the hope that it will be useful,
  236.15 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  236.16 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  236.17 +#  GNU General Public License for more details.
  236.18 +#
  236.19 +#  You should have received a copy of the GNU General Public License
  236.20 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  236.21 +
  236.22 +
  236.23 +
  236.24 +u"""
  236.25 +Importa gli utenti da formati differenti. Il file può essere in formato .csv
  236.26 +o .xls. Genera un file in formato .isi
  236.27 +
  236.28 +NOTA: non confondete il formato dei dati (la successione delle colonne) con il formato
  236.29 +      del file (.csv o .xls). 
  236.30 +
  236.31 +  usage: %prog [options] file
  236.32 +    -g, --group=GROUP: limit import for users (needed)
  236.33 +    -o, --output=FILE: produci l'output nel file FILE (default stdout)
  236.34 +    -r, --renamed: mostra quali utenti verrebbero rinominati
  236.35 +    -d, --deleted: mostra quali utenti verrebbero cancellati
  236.36 +    -e, --extended: usa il formato esteso
  236.37 +    -I, --id-name: usa d_nome.cognome per logname 
  236.38 +    -N, --name: usa nome.cognome per logname
  236.39 +    -p, --random-password: generate random password
  236.40 +    -F, --file-format=FORMAT: file format is FORMAT ('isi' or 'sissi')
  236.41 +    -C, --use-cf: usa CF per nome + identificativo maingroup  (default is in /etc/isi/defaults.py)
  236.42 +"""
  236.43 +
  236.44 +import os
  236.45 +import isi
  236.46 +import sys
  236.47 +from isi import bulk_users
  236.48 +import re
  236.49 +from dry import optionparse
  236.50 +
  236.51 +
  236.52 +#### PROGRAM
  236.53 +opts, args = optionparse.parse(__doc__)
  236.54 +
  236.55 +if len(args) <1:
  236.56 +    print "\nDevi indicare il file con gli utenti da importare!! \n" 
  236.57 +    sys.exit(1)
  236.58 +filename = args[0]
  236.59 +
  236.60 +if not os.path.exists(filename):
  236.61 +    print "File inesistente (%s)" % filename
  236.62 +    sys.exit(1)
  236.63 +
  236.64 +l = isi.Manager()
  236.65 +
  236.66 +if not opts.group:
  236.67 +    msg = "Devi indicare il gruppo con l'opzione -g\n"
  236.68 +    sys.stdout.write(msg)
  236.69 +    sys.exit(1)
  236.70 +
  236.71 +if not opts.file_format:
  236.72 +    opts.file_format = 'isi'
  236.73 +    
  236.74 +if opts.name:
  236.75 +    user_format = 'name'
  236.76 +elif opts.use_cf:
  236.77 +    user_format = 'cf'
  236.78 +elif opts.id_name:
  236.79 +    user_format = 'id-name'
  236.80 +else:
  236.81 +    user_format = None
  236.82 +    
  236.83 +bulk = bulk_users.BulkUsers(opts.group, user_format=user_format, 
  236.84 +                            random_password=opts.random_password)
  236.85 +bulk.read_file(filename, file_format=opts.file_format)
  236.86 +
  236.87 +if opts.renamed:
  236.88 +    output_text = bulk.renamed_as_text()
  236.89 +elif opts.deleted:
  236.90 +    output_text = bulk.deleted_as_text()
  236.91 +else:
  236.92 +    output_text = bulk.as_isi(extended=opts.extended)
  236.93 +
  236.94 +output_file = sys.stdout if not opts.output else open(opts.output, 'w')
  236.95 +output_file.write(output_text + '\n')
  236.96 +
  236.97 +
  236.98 +sys.exit(0)
  236.99 +
 236.100 +    
   237.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   237.2 +++ b/usr/sbin/isi-delprofilo	Mon Apr 26 11:16:23 2010 +0200
   237.3 @@ -0,0 +1,66 @@
   237.4 +#!/bin/bash
   237.5 +# +-------------------------------------------------+
   237.6 +#  (C) 2002-2008 ReteIsi / www.reteisi.org 
   237.7 +# +-------------------------------------------------+
   237.8 +# This program is free software; you can redistribute it and/or modify
   237.9 +# it under the terms of the GNU General Public License as published by
  237.10 +# the Free Software Foundation; either version 2, or (at your option)
  237.11 +# any later version.
  237.12 +# AUTORE: massimo mancini 2008 - [email protected]
  237.13 +
  237.14 +
  237.15 +function help () {
  237.16 +cat << FINE
  237.17 +Comando:    `basename $0`
  237.18 +
  237.19 +Sintassi:   `basename $0` [ -h ] 
  237.20 +            `basename $0` gruppo utente profilo
  237.21 +            
  237.22 +Descrizione: elimina il profilo windows di un utente    
  237.23 +            
  237.24 +Opzioni:    -h  help (Questa pagina di manuale)
  237.25 +            -v  verbose
  237.26 +
  237.27 +FINE
  237.28 +exit 0
  237.29 +}
  237.30 +
  237.31 +
  237.32 +####---------main-----------------
  237.33 +
  237.34 +VERBOSE=0
  237.35 +while getopts hv var
  237.36 +  do
  237.37 +  case $var in
  237.38 +      h) help; exit
  237.39 +      ;;
  237.40 +      v) VERBOSE=1
  237.41 +      ;;
  237.42 +  esac
  237.43 +done
  237.44 +shift ` expr $OPTIND - 1 `
  237.45 +
  237.46 +GRP=$1
  237.47 +USR=$2
  237.48 +WIN=$3
  237.49 +
  237.50 +[ -z $GRP ] && echo "MANCA IL GRUPPO!" && help
  237.51 +[ -z $USR ] && echo "MANCA L'UTENTE!" && help
  237.52 +[ -z $WIN ] && echo "MANCA IL PROFILO (WinXP|Win95|Win2K)" && help
  237.53 +
  237.54 +DIR="/home/users/$GRP/$USR"
  237.55 +PRF=$DIR/.profili/$WIN
  237.56 +DSK=$DIR/old_desktop/$WIN
  237.57 +
  237.58 +[ ! -d $DSK ] && mkdir -p $DSK
  237.59 +cp -a $PRF/Desktop/* $DSK
  237.60 +
  237.61 +if [ $GRP = "alunni" ]  ; then 
  237.62 +    chown -R $USR.docenti $DIR/old_desktop
  237.63 +else
  237.64 +    chown -R $USR.$GRP $DIR/old_desktop
  237.65 +fi    
  237.66 +[ $VERBOSE = 1 ] && echo "Desktop salvato in old_desktop"
  237.67 +rm -fr $PRF
  237.68 +[ $VERBOSE = 1 ] && echo "il profilo di $USR è stato eliminato"
  237.69 +
   238.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   238.2 +++ b/usr/sbin/isi-deluser	Mon Apr 26 11:16:23 2010 +0200
   238.3 @@ -0,0 +1,101 @@
   238.4 +#!/usr/bin/python
   238.5 +# -*- coding: utf-8 -*-
   238.6 +
   238.7 +# This program is free software; you can redistribute it and/or modify
   238.8 +# it under the terms of the GNU General Public License as published by
   238.9 +# the Free Software Foundation; either version 2, or (at your option)
  238.10 +# any later version.
  238.11 +
  238.12 +# AUTHORS: Sandro Dentella - Massimo Mancini
  238.13 +
  238.14 +"""
  238.15 +Delete a user. You may leave the home directry untouched (default) or
  238.16 +eliminate it or compress it
  238.17 +
  238.18 +  usage: %prog [options] [name]
  238.19 +    -N, --dry-run: don't touch the ldap 
  238.20 +    -g, --from-group=group: Eliminate all members from 'group'
  238.21 +    -z, --zap-home: Eliminate also the home dir (default is to create a tar.gz)
  238.22 +    -H, --home=rm|tar|none: rm, tar or ignore home dir
  238.23 +    -v, --verbose: be verbose
  238.24 +    -f, --from-file=filename: Loop on all users in file (one per line)
  238.25 +    -T, --test-mode: running tests - don't backup (go faster)
  238.26 +"""
  238.27 +
  238.28 +import isi
  238.29 +import sys
  238.30 +from dry import optionparse
  238.31 +opts, args = optionparse.parse(__doc__)
  238.32 +if opts.zap_home:
  238.33 +    opts.home = 'rm'
  238.34 +if not opts.home:
  238.35 +    opts.home = 'tar'
  238.36 +    
  238.37 +#import ipdb; ipdb.set_trace()
  238.38 +
  238.39 +conn = isi.IsiConn(dry_run=opts.dry_run)
  238.40 +l = isi.Manager(conn)
  238.41 +l.home_mode = opts.home
  238.42 +
  238.43 +if opts.test_mode:
  238.44 +    conn.tests_running = True
  238.45 +
  238.46 +conn.backup()
  238.47 +
  238.48 +def del_user(user, error):
  238.49 +    """error is different if we delete one user from the command line
  238.50 +    or from a file, when deleting from a file it is normal that some user
  238.51 +    may be non-existng"""
  238.52 +
  238.53 +    try:
  238.54 +        l.del_user(user)
  238.55 +    except isi.exc.MissingMatch, e:
  238.56 +        msg = "username %s is not a system user" % user
  238.57 +        sys.stderr.write("Error: %s\n" % msg)
  238.58 +        if error:
  238.59 +            sys.exit(error)
  238.60 +    
  238.61 +def get_user_from_file():
  238.62 +    """file may have single logname or complete lines. We pick the first
  238.63 +    after splittin with ';' """
  238.64 +    users = []
  238.65 +    for line in open(opts.from_file):
  238.66 +        line = line.rstrip('\n').replace(' ', '')
  238.67 +        if line:
  238.68 +            users += [line.split(';')[0]]
  238.69 +    return users
  238.70 +        
  238.71 +
  238.72 +## check args
  238.73 +if not len(args):
  238.74 +    if not opts.from_group and not opts.from_file:
  238.75 +        sys.stderr.write("Missing username\n")
  238.76 +        sys.exit(1)
  238.77 +
  238.78 +## if deleting a single user, raise an error if the user is missing
  238.79 +## if looping from a group just issue a warning if the user is missing
  238.80 +## but raise an error if the group is missing
  238.81 +
  238.82 +group = opts.from_group
  238.83 +
  238.84 +if group:   # GROUP
  238.85 +
  238.86 +    try:
  238.87 +        posix_group = l.get_group(group)
  238.88 +        posix_group.delete_members()
  238.89 +        sys.exit(0)
  238.90 +    except isi.exc.MissingMatch, e:
  238.91 +        msg = "group %s is not a system group" % group
  238.92 +        isi.srv.get_logger().warning(msg)
  238.93 +        sys.exit(1)
  238.94 +        
  238.95 +
  238.96 +elif opts.from_file:
  238.97 +    for user in get_user_from_file():
  238.98 +        if opts.verbose:
  238.99 +            print "elimino: %s" % user
 238.100 +        del_user(user, error=0)
 238.101 +else:        # USER
 238.102 +    del_user(args[0], error=1)
 238.103 +
 238.104 +sys.exit(0)
   239.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   239.2 +++ b/usr/sbin/isi-domain	Mon Apr 26 11:16:23 2010 +0200
   239.3 @@ -0,0 +1,628 @@
   239.4 +#!/bin/bash
   239.5 +# +-------------------------------------------------+
   239.6 +# (C) ReteIsi / www.reteisi.org 
   239.7 +# +-------------------------------------------------+
   239.8 +
   239.9 +# This program is free software; you can redistribute it and/or modify
  239.10 +# it under the terms of the GNU General Public License as published by
  239.11 +# the Free Software Foundation; either version 2, or (at your option)
  239.12 +# any later version.
  239.13 +#
  239.14 +#
  239.15 +# AUTORI: Sandro Dentella <[email protected]>
  239.16 +#         Massimo Mancini <[email protected]>
  239.17 +
  239.18 +function help () {
  239.19 +cat << FINE
  239.20 +Comando:     `basename $0`
  239.21 +
  239.22 +Sintassi:     `basename $0`[ -h ]
  239.23 +
  239.24 +Descrizione:    isi-domain dominio pdc-name pass
  239.25 +                 
  239.26 +                pass è la pass di root che viene utilizzata anche
  239.27 +                come pass amministrativa di slapd, questa può essere 
  239.28 +                in seguito cambiata con il comando: isi-passwd -A
  239.29 +                 
  239.30 +                Se il dominio in /etc/samba/smb.conf è ISI-DOMAIN, Si suppone 
  239.31 +                che non sia mai stato cambiato e viene rigenerato secrets.tdb
  239.32 +                Memorizza il nuovo SID nel file /etc/samba/domain.SID. 
  239.33 +                Se trova domain.SID chiede se si vuole usare quel SID.
  239.34 +                (la cosa serve ad evitare di dovere rifare il 
  239.35 +                join delle macchine.
  239.36 +
  239.37 +Opzioni:    -h  help (Questa pagina di manuale)
  239.38 +            -v  verbose
  239.39 +            -q  solo messaggi di errore
  239.40 +            -N  secrets.tdb verrà cancellato
  239.41 +            -R  cambia anche la password di root (come quella di admin ldap)
  239.42 +            -S  crea/aggiorna SOLO la struttura di default
  239.43 +            -s  NON crea/aggiorna la struttura di default
  239.44 +
  239.45 +NOTA: l'opzione -S crea/mantiene la struttura di default eventualmente descritta
  239.46 +nel file /etc/isi-def-stru che serve a ridefinire le seguenti variabili:
  239.47 +
  239.48 +    MAINGRPS="admins docenti segreteria ata alunni esterni ospiti"
  239.49 +    AREE="area_alunni area_docenti area_segreteria"
  239.50 +    CLASSI="classe_test"
  239.51 +    CORSI="corso_test"
  239.52 +
  239.53 +FINE
  239.54 +}
  239.55 +function _sintassi () {
  239.56 +    echo "Sintassi:   isi-startup [-N -A -D -S] NOME_DOMINIO NOME_PDC PASSWD"
  239.57 +    exit
  239.58 +}
  239.59 +function check_syntax () {
  239.60 +    eco y "check_syntax"
  239.61 +    [ -z "$DOMAIN" ] && _sintassi
  239.62 +    [ -z "$PDC_NAME" ] && _sintassi
  239.63 +    [ -z "$PASSWD" ] && _sintassi
  239.64 +}
  239.65 +function change_password () {
  239.66 +    eco "y change_password"
  239.67 +    ## sistema
  239.68 +    if [ $PWD_ROOT -eq 1 ]; then
  239.69 +        eco g "cambio password di root"
  239.70 +        echo "root:$PASSWD" |  chpasswd
  239.71 +    fi    
  239.72 +    ## smbtools
  239.73 +    eco g "admin passwd in /etc/smbldap-tools/smbldap_bind.conf"
  239.74 +    perl -pi -se '
  239.75 +              { $_ =~ s/(slavePw|masterPw)=.*/$1="$pwd"/ }
  239.76 +        ' -- -pwd=$PASSWD /etc/smbldap-tools/smbldap_bind.conf
  239.77 +
  239.78 +    ## admin ldap
  239.79 +    eco y "password admin ldap"
  239.80 +    local CRYPT_PASSWD=$(slappasswd -h "{CRYPT}" -s $PASSWD)
  239.81 +    eco g "ldapmodify $OPZ_MBIND"
  239.82 +    cat <<EOF |ldapmodify $OPZ_MBIND
  239.83 +dn: $RBDN
  239.84 +replace: userPassword
  239.85 +userPassword: $CRYPT_PASSWD
  239.86 +EOF
  239.87 +    ## samba: come raggiunere ldap
  239.88 +    eco g "reset password amministrativa di samba"
  239.89 +    smbpasswd -w $PASSWD
  239.90 +
  239.91 +    ## samba (root/Administrator)
  239.92 +    eco g "cambio passord di $DOMAIN_ADMIN"
  239.93 +#    echo -e "$PASSWD\n$PASSWD"|smbpasswd -s root 2>&1 |grep -v 'Failed to'
  239.94 +    echo -e "$PASSWD\n$PASSWD"|smbpasswd -s $DOMAIN_ADMIN 2>&1 |grep -v 'Failed to'
  239.95 +
  239.96 +    ## strumenti ldap*
  239.97 +    eco y "modifico /etc/*.secret"
  239.98 +    for f in ldap.secret  libnss-ldap.secret  pam_ldap.secret
  239.99 +    do
 239.100 +        if [ ! -L /etc/$f ] ; then 
 239.101 +            eco g "modifico $f"
 239.102 +            echo $PASSWD > /etc/$f
 239.103 +            chmod 600 /etc/$f
 239.104 +        fi
 239.105 +    done
 239.106 +
 239.107 +    ## reimposto le variabili connesse alla password
 239.108 +    LDAP_PWD=$PASSWD
 239.109 +    OPZ_SBIND="-xLLLD $RBDN -w $LDAP_PWD -h $HOST"
 239.110 +    OPZ_MBIND="-xD $RBDN -w $LDAP_PWD -h $HOST"
 239.111 +    
 239.112 +    [ $NEW = 1 ] && reset_secrets
 239.113 +
 239.114 +}
 239.115 +function reset_secrets () {
 239.116 +    eco y "reset /var/lib/samba/secrets.tdb"
 239.117 +    rm /var/lib/samba/secrets.tdb
 239.118 +    ## ora lo ricreiamo pulito
 239.119 +    smbpasswd -w $LDAP_PWD
 239.120 +}
 239.121 +function read_conf () {
 239.122 +    eco y "leggo la configurazione"
 239.123 +    DOM_PREC=$(egrep "workgroup *= *" /etc/samba/smb.conf | 
 239.124 +    sed 's/ *workgroup *= *//')
 239.125 +
 239.126 +    ## se ISI-DOMAIN suppongo di resettare secrets.tdb
 239.127 +    [ "$DOM_PREC" = "ISI-DOMAIN" ] && NEW=1
 239.128 +
 239.129 +    PDC_V=$(egrep "netbios name" /etc/samba/smb.conf | 
 239.130 +    sed 's/ *netbios name *= *//')
 239.131 +    [ -z "$PDC_V" ] && PDC_V=$(cat /etc/hostname)
 239.132 +
 239.133 +    ## solite variabili per ldap*
 239.134 +    if [ "$IS_UBUNTU" = 1 ] ; then
 239.135 +        RBDN=$(awk '/^ *rootbinddn/ {print $2$3$4$5}' /etc/ldap.conf )
 239.136 +        BASE=$(awk '/BASE/ {print $2 $3 $4 $5}' /etc/ldap/ldap.conf)
 239.137 +        HOST=$(awk '/HOST/ {print $2}' /etc/ldap/ldap.conf)
 239.138 +    else
 239.139 +        RBDN=$(awk '/^ *rootbinddn/ {print $2$3$4$5}' /etc/pam_ldap.conf )
 239.140 +        BASE=$(awk '/BASE/ {print $2 $3 $4 $5}' /etc/ldap/ldap.conf)
 239.141 +        HOST=$(awk '/HOST/ {print $2}' /etc/ldap/ldap.conf)
 239.142 +    fi
 239.143 +
 239.144 +    LDAP_PWD=$(cat /etc/ldap.secret)
 239.145 +
 239.146 +#    SID_OLD=$(net getlocalsid $DOM_PREC|sed 's/^SID for domain.* is: //')
 239.147 +
 239.148 +    # SID_OLD=$(net getdomainsid |grep "SID for domain" |sed 's/^SID for domain.* is: //')
 239.149 +    # SID_LOC=$(net getdomainsid |grep "SID for local" |sed 's/^SID for local.* is: //')
 239.150 +
 239.151 +    netbios_name=$(net getlocalsid|awk {'print $4'})
 239.152 +    SID_OLD=$(net getdomainsid|grep -v $netbios_name|awk {'print $NF'})
 239.153 +    SID_LOC=$(net getdomainsid|grep $netbios_name|awk {'print $NF'})
 239.154 +    
 239.155 +    if [ -z "$SID_LOC" ] ; then
 239.156 +        eco r "SID locale indefinito - provvedere"
 239.157 +        exit
 239.158 +    fi
 239.159 +    
 239.160 +    # amministrazione samba
 239.161 +    DOMAIN_ADMIN=$(getent group | grep :512: |awk -F":" '{print $4}'|awk -F"," '{print $1}')
 239.162 +    [ -z $DOMAIN_ADMIN ] && DOMAIN_ADMIN="Administrator"
 239.163 +    
 239.164 +    OPZ_SBIND="-xLLLD $RBDN -w $LDAP_PWD -h $HOST"
 239.165 +    OPZ_MBIND="-xD $RBDN -w $LDAP_PWD -h $HOST"
 239.166 +    if [ $VERBOSE = 1 ] ; then
 239.167 +        cat <<EOF
 239.168 +CONFIGURAZIONE ATTUALE:
 239.169 +DOMINIO........: $DOM_PREC
 239.170 +SID DOMINIO....: $SID_OLD
 239.171 +SID LOCALE.....: $SID_LOC
 239.172 +PDC............: $PDC_V
 239.173 +PWD LDAP.......: $LDAP_PWD
 239.174 +DOMAIN ADMIN...: $DOMAIN_ADMIN
 239.175 +EOF
 239.176 +    fi    
 239.177 +}
 239.178 +function new_sid (){
 239.179 +    eco y "generazione nuovo sid"
 239.180 +    if [ -f /etc/samba/domain.SID ] ; then
 239.181 +        read -p "Esiste un SID memorizzato. Vuoi usare questo (s/n)? " RISP
 239.182 +        N=$(expr match "$RISP" '[yYsS]')
 239.183 +        if [ $N -gt 0 ] ; then
 239.184 +            SID=$(cat /etc/samba/domain.SID)
 239.185 +        fi
 239.186 +    fi
 239.187 +    if [ -z "$SID" ] ; then
 239.188 +        SID=$(isi-gensid)
 239.189 +        echo $SID > /etc/samba/domain.SID
 239.190 +        eco v "nuovo sid salvato in /etc/samba/domain.SID - $SID"
 239.191 +    fi
 239.192 +}
 239.193 +function check_ldap_pwd () {
 239.194 +    eco y "check funzionamento ldap"
 239.195 +    if ! ldapsearch $OPZ_SBIND "objectclass=dcObject" 1>/dev/null ; then
 239.196 +        echo Non riesco a contattare il server ldap: password non valida 
 239.197 +        echo server non raggiungibile
 239.198 +    fi
 239.199 +}
 239.200 +function fix_PDC_name () {
 239.201 +    eco y "cambio nome PDC"
 239.202 +    ### non sostituisco solo nuovo con vecchio, nel caso
 239.203 +    #   sia stata fatta qualche modifica incompleta a mano
 239.204 +    ### fix server PDC per smbldap, isi/logon.bat isi/logonupd.bat
 239.205 +    perl -pi -se '
 239.206 +        {$_ =~ s/\\\\([^\\]+)\\/\\\\$pdc\\/g } 
 239.207 +    ' -- -pdc=$PDC_NAME /etc/smbldap-tools/smbldap.conf /etc/isi/logon{,upd}.bat
 239.208 +
 239.209 +    ### fix ultimo argomento /etc/isi/logon.bat
 239.210 +    perl -pi -se '
 239.211 +       {$_ =~ s/logon(upd)?.pl.*/logon$1.pl $pdc/}
 239.212 +    ' -- -pdc=$PDC_NAME /etc/isi/logon{,upd}.bat
 239.213 +    
 239.214 +    perl -pi -se '
 239.215 +        {if ($_ =~ /netbios *name/) {$_ = "    netbios name = $pdc\n"  }}
 239.216 +    ' -- -pdc=$PDC_NAME /etc/samba/smb.conf
 239.217 +
 239.218 +    echo $PDC_NAME > /etc/hostname
 239.219 +
 239.220 +}
 239.221 +function fix_DOMAIN_name () {
 239.222 +    eco y  "cambio nome dominio"
 239.223 +    # fix nome dominio
 239.224 +    perl -pi -se '
 239.225 +      {$_ =~ s/(sambaUnixIdPooldn="sambaDomainName=)([^,]*)(.*)/$1$dom$3/}
 239.226 +    ' -- -dom=$DOMAIN /etc/smbldap-tools/smbldap.conf
 239.227 +
 239.228 +    # modifica /etc/samba/smb.conf
 239.229 +    perl -pi -se '
 239.230 +        {$_ =~ s/.*workgroup.*/   workgroup = $dom/ }
 239.231 +    ' -- -dom=$DOMAIN /etc/samba/smb.conf
 239.232 +}
 239.233 +function fix_SID_in_smbldap_tools () {
 239.234 +    eco y "cambio SID in /etc/smbldap_tools/smbldap.conf"
 239.235 +     ### fix smbldap-tools
 239.236 +     perl -pi -se  '{if ($_ =~ /SID=/) {$_ = "SID=$SID\n"} }
 239.237 +     ' -- -SID=$SID /etc/smbldap-tools/smbldap.conf
 239.238 +}
 239.239 +
 239.240 +function get_max_IDs () {
 239.241 +# determina nextUID e nextGID e aggiunge i gruppi windows                                                                   
 239.242 +    S_UID=$(getent passwd |
 239.243 +        awk -F":" '$3 > 999 && $3 < 30000 {print $3}'| 
 239.244 +        sort -nr | head -n 1)
 239.245 +    S_GID=$(getent group |
 239.246 +        awk -F':' '$3 > 999 && $3 < 30000 {print $3}' |
 239.247 +        sort -nr | head -n 1)
 239.248 +
 239.249 +    [ -z "$S_UID" ] && S_UID=999
 239.250 +    [ -z "$S_GID" ] && S_GID=999
 239.251 +
 239.252 +    [ $S_UID -lt 1000 ] && S_UID=999;
 239.253 +    [ $S_GID -lt 1000 ] && S_GID=999;
 239.254 +
 239.255 +    S_UID=`expr $S_UID + 1`
 239.256 +    S_GID=`expr $S_GID + 1`
 239.257 +}
 239.258 +
 239.259 +function fix_LDAP_sambaDomainName () {
 239.260 +    local DN
 239.261 +    local LDAP_PASSWD=$(cat /etc/ldap.secret)
 239.262 +    ## Qui abbiamo un problema. Aggiungiamo la entry via ' net getlocalsid'
 239.263 +    ## dopo aver cambiato il nome in smb.conf.
 239.264 +    ## Questo crea una entry senza sambaUnixIdPool, quindi la modifichiamo
 239.265 +    OPTS=" -xD  $RBDN -w $LDAP_PASSWD "
 239.266 +
 239.267 +    ldapsearch -x -LLL $OPTS  sambaDomainName=$DOMAIN > /tmp/dom.ldif
 239.268 +    ## controlla esistenza gidNumber 
 239.269 +    if ! grep sambaUnixIdPool /tmp/dom.ldif >/dev/null; then
 239.270 +        get_max_IDs
 239.271 +        cat <<EOF | tee /tmp/modify.ldif| ldapmodify $OPTS 
 239.272 +dn: sambaDomainName=$DOMAIN,$BASE
 239.273 +changetype: modify
 239.274 +add: objectClass
 239.275 +objectClass: sambaUnixIdPool
 239.276 +-
 239.277 +add: uidNumber
 239.278 +uidNumber: $S_UID
 239.279 +-
 239.280 +add: gidNumber
 239.281 +gidNumber: $S_GID
 239.282 +EOF
 239.283 +
 239.284 +    fi
 239.285 +}
 239.286 +
 239.287 +
 239.288 +function set_debconf_vars () {
 239.289 +    eco y "setting variabili debconf"
 239.290 +    # aggiusta le var debconf
 239.291 +    . /usr/share/debconf/confmodule
 239.292 +    db_set shared/sambaPdcName    $PDC    || true
 239.293 +    db_set shared/sambaDomainName $DOMAIN || true
 239.294 +    db_set samba-common/workgroup $DOMAIN || true
 239.295 +    db_stop
 239.296 +}
 239.297 +function add_samba_at_boot () {
 239.298 +    eco j "add_samba_at_boot"
 239.299 +    ### update-rc
 239.300 +    update-rc.d samba defaults  # fallisce con file-rc
 239.301 +    [ -f /etc/runlevel.conf ] && \
 239.302 +        perl -pi -e '{if ($_ =~ /samba/) {$_ =~ s/\#//g  }}' /etc/runlevel.conf
 239.303 +
 239.304 +}
 239.305 +function eco() {
 239.306 +    ESC="\033["
 239.307 +    RED="${ESC}31;1m"
 239.308 +    GREEN="${ESC}32;1m"
 239.309 +    BLUE="${ESC}44;33;1m"
 239.310 +    YELLOW="${ESC}33;1m"
 239.311 +    NOR="${ESC}0m"
 239.312 +
 239.313 +    local col=$1
 239.314 +    shift
 239.315 +    case $col in
 239.316 +        g) COL=$GREEN
 239.317 +        ;;
 239.318 +        b) COL=$BLUE
 239.319 +        ;;
 239.320 +        y) COL=$YELLOW
 239.321 +        ;;
 239.322 +        r) COL=$RED
 239.323 +        ;;
 239.324 +        n) COL=$NOR
 239.325 +        ;;
 239.326 +    esac
 239.327 +    case $col in
 239.328 +        [gby]) [ $QUIET = 0 ] && echo -e ${COL}$*$NOR 
 239.329 +        ;;
 239.330 +        r) echo -e ${COL}$*$NOR 1>&2
 239.331 +        ;;
 239.332 +        n) [ $VERBOSE = 1 ] && echo $*
 239.333 +        ;;
 239.334 +    esac
 239.335 +}
 239.336 +
 239.337 +###------------ creazione struttura reteISI---------------------
 239.338 +# l'eventuale file di configurazione: /etc/isi/isi-def-stru.conf
 239.339 +# definisce: gruppi principali, struttura delle cartelle
 239.340 +
 239.341 +function crea_dir_grp (){
 239.342 +    DOVE=$1
 239.343 +    COSA=$2
 239.344 +    OKGR=$3
 239.345 +    for x in $COSA; do
 239.346 +        eco g "creo $DOVE/$x"
 239.347 +        mkdir -p $DOVE/$x > /dev/null
 239.348 +        [ $OKGR = 1 ] && isi-addgroup $x
 239.349 +    done
 239.350 +}
 239.351 +
 239.352 +function isi_default_stru(){
 239.353 +    # costanti
 239.354 +    GRP_SI=1
 239.355 +    GRP_NO=0
 239.356 +    UTENTI_IN="/home/users"
 239.357 +    SHARES_IN="/home/shares"
 239.358 +    FILE_DEF="/etc/isi/isi-def-stru.conf"
 239.359 +    # defaults (possono essere ridefiniti nel file di conf)
 239.360 +    MAINGRPS="admins docenti segreteria ata alunni esterni ospiti"
 239.361 +    AREE="area_alunni area_docenti area_segreteria"
 239.362 +    CLASSI="classe_test"
 239.363 +    CORSI="corso_test"
 239.364 +    
 239.365 +    [ -f $FILE_DEF ] && . $FILE_DEF
 239.366 +
 239.367 +    # crea gruppi principali e cartelle relative
 239.368 +    crea_dir_grp $UTENTI_IN $MAINGRPS $GRP_SI
 239.369 +    # crea classi/corsi
 239.370 +    for x in $CLASSI; do
 239.371 +        isi-classe $x
 239.372 +    done
 239.373 +    for x in $CORSI; do
 239.374 +        isi-classe -C $x
 239.375 +    done
 239.376 +    # crea aree
 239.377 +    for x in $AREE; do
 239.378 +        isi-area $x
 239.379 +    done
 239.380 +    isi-perms
 239.381 +}
 239.382 +
 239.383 +function slapd_stop () {
 239.384 +    eco y "fermo slapd"
 239.385 +    ## prima usiamo le buone maniere 
 239.386 +    /etc/init.d/slapd stop
 239.387 +    if pgrep -x slapd ; then 
 239.388 +        ## poi pero'  ci arrabbiamo...
 239.389 +        eco b "provo ad uccidere slapd con -9"
 239.390 +        skill -9 slapd
 239.391 +        if pgrep -x slapd; then
 239.392 +            eco r "slapd non muore neanche con kill -9;  esco"
 239.393 +            exit 1
 239.394 +        fi
 239.395 +    fi
 239.396 +}
 239.397 +function slapd_start () {
 239.398 +    local i=0
 239.399 +    eco y "avvio slapd"
 239.400 +    until [ "$(pidof slapd)" != "" ] ; do
 239.401 +        /etc/init.d/slapd start
 239.402 +        sleep 1
 239.403 +        i=$((i+1))
 239.404 +        if [ $i = 10 ] ; then
 239.405 +           eco r "slapd non parte!!!. Controllare."
 239.406 +           exit 1
 239.407 +        fi
 239.408 +    done
 239.409 +}
 239.410 +
 239.411 +function samba_stop () {
 239.412 +    eco y "fermo Samba"
 239.413 +    invoke-rc.d samba stop
 239.414 +    if [ "$(pidof smbd)" != "" ] ; then
 239.415 +       eco r "Samba non si spegne. Riavviare a mano."
 239.416 +       exit 1
 239.417 +    fi
 239.418 +}
 239.419 +function samba_start () {
 239.420 +    local i=0
 239.421 +    eco y "avvio Samba"
 239.422 +    until [ "$(pidof smbd)" != "" ] 
 239.423 +    do
 239.424 +        /etc/init.d/samba start
 239.425 +        sleep 1
 239.426 +        i=$((i+1))
 239.427 +        if [ $i = 10 ] ; then
 239.428 +           eco r "Samba non parte!!!. Controllare."
 239.429 +           exit 1
 239.430 +        fi
 239.431 +    done
 239.432 +}
 239.433 +function setting_sid () {
 239.434 +#    if [  "$SID" = "$SID_OLD" ] ; then 
 239.435 +#        eco y "hai usato il vecchio SID: $SID"
 239.436 +#    else
 239.437 +#        eco y "nuovo SID di dominio: $SID"
 239.438 +#        net setdomainsid $SID
 239.439 +#    fi    
 239.440 +    # risetta il SID del pdc
 239.441 +    eco y "setting domain SID: $SID"
 239.442 +    net setdomainsid $SID
 239.443 +    eco y "setting local SID: $SID_LOC"
 239.444 +    net setlocalsid $SID_LOC
 239.445 +    net getdomainsid
 239.446 +    
 239.447 +}
 239.448 +function domain_admin_permissions () {
 239.449 +    eco y "gestione permessi di Domain Admins e $DOMAIN_ADMIN ($1)"
 239.450 +    
 239.451 +    UP="$DOMAIN_ADMIN%$LDAP_PWD"
 239.452 +    P1=SeMachineAccountPrivilege
 239.453 +    P2=SeTakeOwnershipPrivilege
 239.454 +    P3=SeBackupPrivilege
 239.455 +    P4=SeRestorePrivilege
 239.456 +    P5=SeRemoteShutdownPrivilege
 239.457 +    P6=SePrintOperatorPrivilege
 239.458 +    P7=SeAddUsersPrivilege
 239.459 +    P8=SeDiskOperatorPrivilege
 239.460 +    
 239.461 +    net -U $UP rpc rights $1 "Domain Admins" $P1 $P2 $P3 $P4 $P5 $P6 $P7 $P8     
 239.462 +#    net -U $UP rpc rights $1 $DOMAIN_ADMIN $P1 $P2 $P3 $P4 $P5 $P6 $P7 $P8 
 239.463 +}
 239.464 +function slap_index_and_wins () {
 239.465 +    eco y "rigenero gli indici ldap"
 239.466 +    slapindex 2>/dev/null   # la redirezione elimina un warning
 239.467 +    chown openldap.openldap /var/lib/ldap/*
 239.468 +    eco y "elimino /var/lib/samba/wins.dat"
 239.469 +    rm /var/lib/samba/wins.dat
 239.470 +}
 239.471 +function slapcat_and_modify () {
 239.472 +    eco y "slapcat > $LDIF_OLD poi lo modifico in $LDIF_NEW"
 239.473 +
 239.474 +    slapcat > $LDIF_OLD
 239.475 +
 239.476 +    sed "s%$SID_OLD%$SID%gi" $LDIF_OLD | sed "s%$DOM_PREC%$DOMAIN%gi" > $LDIF_NEW
 239.477 +
 239.478 +    if [ "$SID_OLD" != "$SID" ] && grep -iqw $SID_OLD $LDIF_NEW ; then
 239.479 +        eco r "ERRORE: ridefinizione SID fallita"
 239.480 +        STOP_ON_ERROR=1
 239.481 +    fi
 239.482 +    if [ "$DOM_PREC" != "$DOMAIN" ] && grep -iqw $DOM_PREC $LDIF_NEW ; then
 239.483 +#        eco r $DOM_PREC
 239.484 +#        eco r $DOMAIN
 239.485 +#        exit
 239.486 +        eco r "ERRORE: ridefinizione DOMINIO fallita"
 239.487 +        STOP_ON_ERROR=1
 239.488 +    fi
 239.489 +}
 239.490 +function set_hostname (){
 239.491 +    OLD_HOSTNAME=$(hostname)
 239.492 +    ### squid
 239.493 +    FILE=/etc/squid.conf
 239.494 +    if [ -e "$FILE" ] ; then
 239.495 +        cp $FILE $FILE.2
 239.496 +        sed "s/^visible_hostname.*$/visible_hostname $PDC_NAME/" \
 239.497 +            < $FILE.2 > $FILE
 239.498 +        rm $FILE.2
 239.499 +    fi
 239.500 +    FILE=/etc/squid/squid.conf
 239.501 +    if [ -e "$FILE" ] ; then
 239.502 +        cp $FILE $FILE.2
 239.503 +        sed "s/^visible_hostname.*$/visible_hostname $PDC_NAME/" \
 239.504 +            < $FILE.2 > $FILE
 239.505 +        rm $FILE.2
 239.506 +    fi
 239.507 +    ### postfix
 239.508 +    [ -x /usr/sbin/postconf ] && postconf -e "myhostname = $PDC_NAME"
 239.509 +    ### /etc/hostname
 239.510 +    echo $PDC_NAME > /etc/hostname
 239.511 +    /etc/init.d/hostname.sh start > /dev/null
 239.512 +    ### /etc/mailname
 239.513 +    echo $PDC_NAME > /etc/mailname
 239.514 +    ### /etc/hosts
 239.515 +    FILE=/etc/hosts
 239.516 +    cp $FILE $FILE.2
 239.517 +    sed -i "s%argo-cd.argo.it%$PDC_NAME%" $FILE
 239.518 +    sed -i "s%$OLD_HOSTNAME%$PDC_NAME%" $FILE
 239.519 +    rm $FILE.2
 239.520 +    hostname $PDC_NAME    
 239.521 +}
 239.522 +
 239.523 +function invalid_nscd_cache(){
 239.524 +    # Invalido cache nscd
 239.525 +    [ ! -x /usr/sbin/nscd ] && return 1
 239.526 +    nscd -i passwd
 239.527 +    nscd -i group
 239.528 +
 239.529 +    return 0
 239.530 +}
 239.531 +
 239.532 +function clean_smb_cache(){
 239.533 +    rm -f /var/lib/samba/wins.dat
 239.534 +}
 239.535 +
 239.536 +### OPTS
 239.537 +STOP_ON_ERROR=0
 239.538 +NEW=0
 239.539 +PWD_ROOT=0
 239.540 +SOLO_DEFSTRU=0
 239.541 +NO_DEFSTRU=0
 239.542 +VERBOSE=0
 239.543 +QUIET=0
 239.544 +IS_UBUNTU=0
 239.545 +[ "$(lsb_release -is)" == "Ubuntu" ] && IS_UBUNTU=1
 239.546 +
 239.547 +while getopts hvqsSN var
 239.548 +do
 239.549 +  case $var in
 239.550 +      h) clear; help; exit
 239.551 +      ;;
 239.552 +      v) VERBOSE=1
 239.553 +      ;;
 239.554 +      q) QUIET=1
 239.555 +         VERBOSE=0
 239.556 +      ;;
 239.557 +      N) NEW=1
 239.558 +      ;;
 239.559 +      s) NO_DEFSTRU=1
 239.560 +      ;;
 239.561 +      S) SOLO_DEFSTRU=1
 239.562 +      ;;
 239.563 +      R) PWD_ROOT=1
 239.564 +  esac
 239.565 +done
 239.566 +shift `expr $OPTIND - 1 `
 239.567 +
 239.568 +DOMAIN=$(echo $1|tr '[a-z]' '[A-Z]')
 239.569 +PDC_NAME=$2
 239.570 +PASSWD=$3
 239.571 +
 239.572 +LDIF_OLD=/root/dbold.ldif
 239.573 +LDIF_NEW=/root/dbnew.ldif
 239.574 +
 239.575 +DOM_PREC=$(egrep "workgroup *= *" /etc/samba/smb.conf|sed 's/ *workgroup *= *//')
 239.576 +
 239.577 +
 239.578 +### PROGRAMMA
 239.579 +### controlla solo la struttura isi comprese le acl
 239.580 +[ "$SOLO_DEFSTRU" = 1 ] && isi_default_stru && exit 0
 239.581 +### ridefinizione dominio
 239.582 +check_syntax
 239.583 +read_conf
 239.584 +check_ldap_pwd
 239.585 +new_sid
 239.586 +domain_admin_permissions 'revoke'
 239.587 +samba_stop
 239.588 +slapd_stop
 239.589 +invalid_nscd_cache
 239.590 +### qui si modificano SID e DOMINIO
 239.591 +### se slapcat_and_modify fallisce STOP_ON_ERROR=1
 239.592 +slapcat_and_modify
 239.593 +if [ "$STOP_ON_ERROR" = 1 ]; then 
 239.594 +    slapd_start
 239.595 +    samba_start
 239.596 +    exit 1
 239.597 +else
 239.598 +    eco g "OK ridefinizione SID/DOMINIO"
 239.599 +fi    
 239.600 +### modifica i file di conf
 239.601 +set_hostname $PDC_NAME
 239.602 +hostname $PDC_NAME
 239.603 +fix_DOMAIN_name
 239.604 +fix_PDC_name 
 239.605 +fix_SID_in_smbldap_tools
 239.606 +### ricarica dbldap
 239.607 +eco y "carico dbldap corretto"
 239.608 +isi-slapd-reload -Rl $LDIF_NEW
 239.609 +slapd_start
 239.610 +samba_start
 239.611 +
 239.612 +### cambio la/le password
 239.613 +change_password
 239.614 +### risetto i sid che altrimenti risultano indefiniti
 239.615 +setting_sid
 239.616 +
 239.617 +samba_stop 
 239.618 +slapd_stop
 239.619 +invalid_nscd_cache
 239.620 +slap_index_and_wins      
 239.621 +slapd_start
 239.622 +fix_LDAP_sambaDomainName
 239.623 +samba_start
 239.624 +domain_admin_permissions 'grant'
 239.625 +samba_stop
 239.626 +clean_smb_cache
 239.627 +samba_start
 239.628 +set_debconf_vars
 239.629 +#isi-tools -N $DOMAIN > /dev/null
 239.630 +[ "$NO_DEFSTRU" = 1 ] || isi_default_stru
 239.631 +### FINE
   240.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   240.2 +++ b/usr/sbin/isi-gensid	Mon Apr 26 11:16:23 2010 +0200
   240.3 @@ -0,0 +1,11 @@
   240.4 +#!/usr/bin/python
   240.5 +# -*- coding: utf8 -*-
   240.6 +
   240.7 +""" calcola un domain SID """
   240.8 +import random
   240.9 +random.seed()
  240.10 +x1=str(random.randint(0,0xFFFFFFFF))
  240.11 +x2=str(random.randint(0,0xFFFFFFFF))
  240.12 +x3=str(random.randint(0,0xFFFFFFFF))
  240.13 +sid = 'S-1-5-21-%s-%s-%s' % (x1,x2,x3)
  240.14 +print sid
   241.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   241.2 +++ b/usr/sbin/isi-getattr	Mon Apr 26 11:16:23 2010 +0200
   241.3 @@ -0,0 +1,39 @@
   241.4 +#!/usr/bin/python
   241.5 +# -*- coding: utf-8 -*-
   241.6 +
   241.7 +# This program is free software; you can redistribute it and/or modify
   241.8 +# it under the terms of the GNU General Public License as published by
   241.9 +# the Free Software Foundation; either version 2, or (at your option)
  241.10 +# any later version.
  241.11 +
  241.12 +# AUTORE: massimo mancini 2008 - [email protected]
  241.13 +
  241.14 +"""
  241.15 +Restituisce un campo ldap dell'utente connettendosi al server ldap come 
  241.16 +amministratore ldap. Restituisce quindi anche i campi riservati.
  241.17 +
  241.18 +  usage: %prog user attributo_ldap
  241.19 +  
  241.20 +"""
  241.21 +
  241.22 +
  241.23 +import isi,sys
  241.24 +from dry import optionparse
  241.25 +
  241.26 +opts, args = optionparse.parse(__doc__)
  241.27 +
  241.28 +if len(args)<2:
  241.29 +    print "ERRORE: devi indicare utente e attributo"
  241.30 +    sys.exit()
  241.31 +else:
  241.32 +    user =  args[0]
  241.33 +    field = args[1]
  241.34 +
  241.35 +U = isi.Manager(isi.IsiConn())
  241.36 +    
  241.37 +if U.user_exists(user):
  241.38 +    print U.get_ldap_field(user, field)
  241.39 +else:
  241.40 +    print "utente inesistente: %s" % user
  241.41 +
  241.42 +
   242.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   242.2 +++ b/usr/sbin/isi-groupcat	Mon Apr 26 11:16:23 2010 +0200
   242.3 @@ -0,0 +1,47 @@
   242.4 +#!/usr/bin/python
   242.5 +# -*- coding: utf-8 -*-
   242.6 +
   242.7 +# This program is free software; you can redistribute it and/or modify
   242.8 +# it under the terms of the GNU General Public License as published by
   242.9 +# the Free Software Foundation; either version 2, or (at your option)
  242.10 +# any later version.
  242.11 +
  242.12 +# AUTHORS: Sandro Dentella - Massimo Mancini
  242.13 +
  242.14 +
  242.15 +"""
  242.16 +Return a list of all member of a group
  242.17 +
  242.18 +  usage: %prog [options] group_name
  242.19 +    -r, --record: return user's records standard part
  242.20 +    -R, --record-extended: return record extended
  242.21 +"""
  242.22 +
  242.23 +
  242.24 +import isi
  242.25 +import sys
  242.26 +from dry import optionparse
  242.27 +
  242.28 +opts, args = optionparse.parse(__doc__)
  242.29 +group_name = args[0]
  242.30 +
  242.31 +l = isi.Manager()
  242.32 +
  242.33 +if not len(args):
  242.34 +    sys.stderr.write("Missing group name\n")
  242.35 +    sys.exit(1)
  242.36 +
  242.37 +group = l.get_group(group_name)
  242.38 +
  242.39 +if not group:
  242.40 +    sys.stderr.write("No matching group: %s\n" % args[0])
  242.41 +    sys.exit(1)
  242.42 +    
  242.43 +
  242.44 +if opts.record or opts.record_extended:
  242.45 +    print group.as_isi_format(opts.record_extended)
  242.46 +        
  242.47 +else:
  242.48 +    print "\n".join(group.members)
  242.49 +
  242.50 +sys.exit(0)
   243.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   243.2 +++ b/usr/sbin/isi-perms	Mon Apr 26 11:16:23 2010 +0200
   243.3 @@ -0,0 +1,256 @@
   243.4 +#!/usr/bin/python
   243.5 +# -*- coding: utf-8 -*-
   243.6 +
   243.7 +# Copyright (C) 2006-2010, Sandro Dentella <[email protected]>
   243.8 +#
   243.9 +#  This program is free software: you can redistribute it and/or modify
  243.10 +#  it under the terms of the GNU General Public License as published by
  243.11 +#  the Free Software Foundation, either version 3 of the License, or
  243.12 +#  (at your option) any later version.
  243.13 +#
  243.14 +#  This program is distributed in the hope that it will be useful,
  243.15 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  243.16 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  243.17 +#  GNU General Public License for more details.
  243.18 +#
  243.19 +#  You should have received a copy of the GNU General Public License
  243.20 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  243.21 +
  243.22 +
  243.23 +"""
  243.24 +usage: %prog files [options] [ cartella ] [ cartella] ...
  243.25 +    -d, --debug: print debugging
  243.26 +    -n, --dry-run: don't execute commands really, just show
  243.27 +    -p, --nopostexec: don't execute postexec command
  243.28 +    -P, --nopreexec: don't execute preeexec command
  243.29 +    -b, --remove-all: as in setfacl (zeros precedent acl)
  243.30 +    -w, --write: write the conf file resulting from merge of 2 conf files (implies -n)
  243.31 +    -f, --file=FILE: use file as configuration file
  243.32 +"""
  243.33 +
  243.34 +import re
  243.35 +import os, sys
  243.36 +from dry import optionparse
  243.37 +from isi.filesystem import has_acl_support
  243.38 +import ConfigParser
  243.39 +import glob
  243.40 +
  243.41 +#import subprocess     #non disponibile in py2.3
  243.42 +
  243.43 +class ParsingPermError(Exception): pass
  243.44 +
  243.45 +class InputStream(object):
  243.46 +    """ Simple Wrapper for File-like objects. [c]StringIO doesn't provide
  243.47 +        a readline function for use with generate_tokens.
  243.48 +        Using a iterator-like interface doesn't succeed, because the readline
  243.49 +        function isn't used in such a context. (see <python-lib>/tokenize.py)
  243.50 +    """
  243.51 +    def __init__(self, file):
  243.52 +        f = open(file)
  243.53 +        data = f.read()
  243.54 +        data = re.sub(':(.*=)', r'|\1', data)
  243.55 +        f.close()
  243.56 +        self.__data = [ '%s\n' % x for x in data.splitlines() ]
  243.57 +        self.__lcount = 0
  243.58 +
  243.59 +    def readline(self):
  243.60 +        try:
  243.61 +            line = self.__data[self.__lcount]
  243.62 +            self.__lcount += 1
  243.63 +        except IndexError:
  243.64 +            line = ''
  243.65 +            self.__lcount = 0
  243.66 +        line = re.sub(r'^ +', '', line)
  243.67 +        line = re.sub(r'#.*', '', line)
  243.68 +        return line
  243.69 +
  243.70 +class Perm(object):
  243.71 +    def __init__(self, name=None, model=None):
  243.72 +        self.perm = {}
  243.73 +        self.name = name
  243.74 +        self.path = name
  243.75 +        if model:
  243.76 +            self.perm = model
  243.77 +        
  243.78 +    def set(self, perm):
  243.79 +        """add a key/value pair in self.perm dict. Each key/value correspond
  243.80 +        to a permission added to the setfacl command line
  243.81 +        """
  243.82 +        
  243.83 +        perm = perm.replace('|', ':')
  243.84 +        m = re.match('([gu]:[-\w.]*|[mo]):([-rxw]+)', perm)
  243.85 +        if m:
  243.86 +            self.perm[m.group(1)] = m.group(2)
  243.87 +        else:
  243.88 +            raise ParsingPermError('permission could not be parsed: %s' % perm)
  243.89 +            
  243.90 +    def create_perm_spec(self):
  243.91 +        """setfacl accepts many perms in the same line as in::
  243.92 +
  243.93 +           setfacl -R -d -m g:docenti:rxw,u::rxw,o:---  /home/sandro
  243.94 +        
  243.95 +        """
  243.96 +        
  243.97 +        P = ["%s:%s" % (k, self.perm[k]) for k in self.perm]
  243.98 +        return ",".join(P)
  243.99 +
 243.100 +    def show(self):
 243.101 +        """not used..."""
 243.102 +        print self.perm
 243.103 +        print self.create_perm_spec()
 243.104 +
 243.105 +    def read(self, items, mode=None):
 243.106 +        """implement 'copy' functions and set permissions"""
 243.107 +        
 243.108 +        for key, val in items:
 243.109 +            if key == 'copy':
 243.110 +                self.read(c.items(val), mode='copy')
 243.111 +
 243.112 +        for key, val in items:
 243.113 +            if key in ('grp', 'public_html', 'copy'):
 243.114 +                continue
 243.115 +            elif key == 'path':
 243.116 +                if not mode == 'copy':
 243.117 +                    self.path = val
 243.118 +            else:
 243.119 +                self.set("%s:%s" % (key, val))
 243.120 +
 243.121 +    def grp(self):
 243.122 +        """if a 'grp' option exists, execute it
 243.123 +        """
 243.124 +        if c.has_option(self.name, 'grp'):
 243.125 +            grp = c.get(self.name, 'grp')
 243.126 +            cmd = 'chgrp -R %s %s' % (grp, self.path)
 243.127 +            exec_cmd(cmd)
 243.128 +
 243.129 +        if c.has_option(self.name, 'public_html'):
 243.130 +            fix = c.get(self.name, 'public_html')
 243.131 +            if fix in ('yes', 'true', 1, 'si', '1'):
 243.132 +                self.public_html()
 243.133 +        
 243.134 +    def apply(self):
 243.135 +        for path in glob.glob(self.path):
 243.136 +            self.grp()
 243.137 +
 243.138 +            if opts.remove_all:
 243.139 +                b = 'b'
 243.140 +            else:
 243.141 +                b = ''
 243.142 +            cmd = "setfacl -R -d -%sm %s '%s'" % (b, self.create_perm_spec(),
 243.143 +                                                  path)
 243.144 +            exec_cmd(cmd)
 243.145 +            cmd2 = "setfacl -R -m %s '%s'" % (self.create_perm_spec(),
 243.146 +                                              path )
 243.147 +            exec_cmd(cmd2)
 243.148 +
 243.149 +    def public_html(self):
 243.150 +        """fixes public_html permissions"""
 243.151 +
 243.152 +        Dir = self.path
 243.153 +        cmd0 = "setfacl -m u:www-data:--x '%s' " % (Dir)
 243.154 +        cmd01 = "setfacl -m u:www-data:--x %s " % (Dir +'/*')
 243.155 +        cmd1 = "setfacl -R    -m u:www-data:rx %s/*/public_html" % Dir
 243.156 +        cmd2 = "setfacl -R -d -m u:www-data:rx %s/*/public_html" % Dir
 243.157 +
 243.158 +        if glob.glob("%s" % (Dir +'/*')):
 243.159 +            exec_cmd(cmd0)
 243.160 +        ## may be there are no public_html
 243.161 +        files = glob.glob("%s/*/public_html" % Dir)
 243.162 +        if files:
 243.163 +            exec_cmd(cmd1)
 243.164 +            exec_cmd(cmd2)
 243.165 +
 243.166 +def exec_cmd(cmd):
 243.167 +    ## debug
 243.168 +    if opts.debug:
 243.169 +        print >>sys.stderr, cmd
 243.170 +    ## exec
 243.171 +    if not opts.dry_run:
 243.172 +#     p = subprocess.Popen(cmd, shell=True)
 243.173 +#     p.wait()
 243.174 +        r, w, e = os.popen3(cmd)
 243.175 +        cmderr = e.readlines()
 243.176 +        w.close()
 243.177 +        e.close()
 243.178 +        if cmderr:
 243.179 +            print "COMANDO...:",cmd
 243.180 +            print "ERRORE....:",cmderr[0]
 243.181 +            #sys.exit(1)
 243.182 +            
 243.183 +def exec_section(section):
 243.184 +    if not section in c.sections():
 243.185 +        return
 243.186 +    if c.has_option(section, 'file'):
 243.187 +        file = c.get(section, 'file')
 243.188 +        if os.path.exists(file):
 243.189 +            exec_cmd("sh %s" % (file)) 
 243.190 +                    
 243.191 +    cmds = [cmd for cmd in c.options(section) if cmd.startswith('cmd')]
 243.192 +    cmds.sort
 243.193 +    for cmd in cmds:
 243.194 +        exec_cmd(c.get(section, cmd))
 243.195 +    
 243.196 +### Program
 243.197 +
 243.198 +# controlla immediatamente se /home è sotto acl, in caso contrario esce
 243.199 +# in condizioni normali trattasi di controllo superfluo, ma su una debian
 243.200 +# nuda e cruda...
 243.201 +
 243.202 +if not has_acl_support('/home'):
 243.203 +    print "ATTENZIONE: /home non supporta le ACLs - permessi non stabiliti"
 243.204 +    sys.exit(0)
 243.205 +
 243.206 +opts, args = optionparse.parse(__doc__)
 243.207 +if opts.write:
 243.208 +    opts.dry_run = True
 243.209 +
 243.210 +# ConfigParser parse g:group = rwx => g : 'group = rxw', so I parse acl.conf before
 243.211 +# ConfigParser. I also allow spaces in the beginning of the line
 243.212 +
 243.213 +
 243.214 +c = ConfigParser.ConfigParser()
 243.215 +
 243.216 +if opts.file:
 243.217 +    CONF_FILES = (opts.file)
 243.218 +else:
 243.219 +    CONF_FILES = ('/etc/isi/acl.conf', '/etc/isi/acl-local.conf')
 243.220 +
 243.221 +if opts.debug:
 243.222 +    print "reading file:", CONF_FILES
 243.223 +
 243.224 +for file_name in CONF_FILES:
 243.225 +    if os.path.exists(file_name):
 243.226 +        f = InputStream(file_name)
 243.227 +        c.readfp(f,'cfg')
 243.228 +
 243.229 +
 243.230 +if args:
 243.231 +    sections = args
 243.232 +else:
 243.233 +    sections = c.sections()
 243.234 +
 243.235 +if opts.debug:
 243.236 +    print "sections: ", sections
 243.237 +    
 243.238 +if not opts.nopreexec: exec_section('pre_exec')
 243.239 +
 243.240 +P = {}
 243.241 +for sec in sections:
 243.242 +    if sec in ('post_exec', 'pre_exec'):
 243.243 +        continue
 243.244 +    P[sec] = Perm(name=sec)
 243.245 +    P[sec].read(c.items(sec))
 243.246 +    P[sec].apply()
 243.247 +    
 243.248 +if not opts.nopostexec:
 243.249 +    exec_section('post_exec')
 243.250 +    
 243.251 +
 243.252 +if opts.write:
 243.253 +    f = open('/tmp/isi-perms.ini', 'w')
 243.254 +    c.write(f)
 243.255 +    f.close()
 243.256 +    f = open('/tmp/isi-perms.ini')
 243.257 +    txt = f.read()
 243.258 +    print txt
 243.259 +
   244.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   244.2 +++ b/usr/sbin/isi-quota	Mon Apr 26 11:16:23 2010 +0200
   244.3 @@ -0,0 +1,72 @@
   244.4 +#!/usr/bin/python
   244.5 +# -*- coding: utf-8 -*-
   244.6 +
   244.7 +# This program is free software; you can redistribute it and/or modify
   244.8 +# it under the terms of the GNU General Public License as published by
   244.9 +# the Free Software Foundation; either version 2, or (at your option)
  244.10 +# any later version.
  244.11 +
  244.12 +# AUTHORS: Massimo Mancini
  244.13 +
  244.14 +"""
  244.15 +ISI-QUOTA attribuisce la quota agli utenti di un gruppo   definito sull'albero
  244.16 +ldap e la somma di tutte le quote al gruppo stesso
  244.17 +
  244.18 +                filesystem = partizione quotata
  244.19 +                gruppo = utenti da quotare
  244.20 +                S1 = soft lim dello spazio disco
  244.21 +                S2 = hard lim dello spazio disco (deve essere > S1)
  244.22 +                F1 = soft lim del numero dei files (inode)
  244.23 +                F2 = soft lim del numero dei files (deve essere > F1)
  244.24 +                
  244.25 +limiti=0 equivale a nessuna quota
  244.26 +
  244.27 +  usage: %prog <filesystem> < gruppo> [ S1 ] [ S2 ] [ F1 ] [ F2 ]
  244.28 +
  244.29 +"""
  244.30 +
  244.31 +import isi
  244.32 +import sys, os
  244.33 +import re
  244.34 +import pexpect
  244.35 +from dry import optionparse
  244.36 +from dry.functions import execute, ExecuteError
  244.37 +from isi.filesystem import show_file
  244.38 +from isi.conf import defaults 
  244.39 +from isi.exc import QuotaError
  244.40 +
  244.41 +# defaults
  244.42 +s1 = defaults.QUOTA_S1
  244.43 +s2 = defaults.QUOTA_S2
  244.44 +f1 = defaults.QUOTA_F1
  244.45 +f2 = defaults.QUOTA_F2
  244.46 +rep_file = defaults.QUOTA_REP
  244.47 +
  244.48 +opts, args = optionparse.parse(__doc__)
  244.49 +
  244.50 +if len(args)==0: print "ERRORE: devi indicare perlomeno filesystem e gruppo" 
  244.51 +if len(args)==1: print "ERRORE: devi indicare il gruppo" 
  244.52 +if len(args)>=2: 
  244.53 +    fs  = args[0]
  244.54 +    gruppo = args[1]
  244.55 +    if len(args)>2: s1 = int(args[2])
  244.56 +    if len(args)>3: s2 = int(args[3])
  244.57 +    if len(args)>4: f1 = int(args[4])
  244.58 +    if len(args)>5: f2 = int(args[5])
  244.59 +    if s1==0: print "disco: alert limit disabilitato"
  244.60 +    if s2==0: print "disco: space limit disabilitato"
  244.61 +    if f1==0: print "file : alert limit disabilitato"
  244.62 +    if f2==0: print "file : maxnr limit disabilitato"
  244.63 +
  244.64 +manager = isi.Manager()
  244.65 +try:
  244.66 +    group = manager.get_group(gruppo)
  244.67 +    group.set_quota(fs, s1, s2, f1, f2)
  244.68 +    if os.path.isfile(rep_file):
  244.69 +        show_file(rep_file)
  244.70 +    else:
  244.71 +        print "ERRORE nella creazione del file %s" % rep_file
  244.72 +except QuotaError, e:
  244.73 +    print "\nERRORE QUOTA:\n%s" % e
  244.74 +    
  244.75 +
   245.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   245.2 +++ b/usr/sbin/isi-setup	Mon Apr 26 11:16:23 2010 +0200
   245.3 @@ -0,0 +1,1356 @@
   245.4 +#!/bin/bash
   245.5 +# +-------------------------------------------------+
   245.6 +# (C) ReteIsi / www.reteisi.org 
   245.7 +# +-------------------------------------------------+
   245.8 +
   245.9 +# This program is free software; you can redistribute it and/or modify
  245.10 +# it under the terms of the GNU General Public License as published by
  245.11 +# the Free Software Foundation; either version 2, or (at your option)
  245.12 +# any later version.
  245.13 +#
  245.14 +#
  245.15 +# AUTORI:   Massimo Mancini <[email protected]>
  245.16 +#           Sandro Dentella <[email protected]>, 
  245.17 +
  245.18 +# installa un sistema reteISI (slapd+samba+struttura delle cartelle)
  245.19 +# 
  245.20 +
  245.21 +### controlla le dipendenze e installa i pacchetti mancanti
  245.22 +
  245.23 +#set -e
  245.24 +
  245.25 +function check_hg_etc () {
  245.26 +    local PWD
  245.27 +    eco y "controllo che /etc sia sotto mercurial"
  245.28 +    if [ -d /etc/.hg ] ; then
  245.29 +        eco g "mercurial OK"
  245.30 +    else
  245.31 +        eco g "preparo il repository hg per /etc"
  245.32 +        PWD=$(pwd)
  245.33 +        cd /etc
  245.34 +        hg -q init
  245.35 +        hg -q add *
  245.36 +        hg -q commit -m "init repo"
  245.37 +        chmod 600 .hg
  245.38 +        cd $PWD
  245.39 +    fi
  245.40 +}
  245.41 +function new_sid (){
  245.42 +    eco y "generazione nuovi sid"
  245.43 +    SID=$(isi-gensid)
  245.44 +    SID_PDC=$(isi-gensid)
  245.45 +    if [ -f /etc/samba/domain.SID ] ; then
  245.46 +        read -p "Esiste un SID memorizzato per il DOMINIO . Vuoi usare questo (s/n)? " RISP
  245.47 +        N=$(expr match "$RISP" '[yYsS]')
  245.48 +        if [ "$N" -gt 0 ] ; then
  245.49 +            SID=$(cat /etc/samba/domain.SID)
  245.50 +        fi
  245.51 +    fi
  245.52 +    if [ -f /etc/samba/pdc.SID ] ; then
  245.53 +        read -p "Esiste un SID memorizzato per il PDC. Vuoi usare questo (s/n)? " RISP
  245.54 +        N=$(expr match "$RISP" '[yYsS]')
  245.55 +        if [ "$N" -gt 0 ] ; then
  245.56 +            SID=$(cat /etc/samba/domain.SID)
  245.57 +        fi
  245.58 +    fi
  245.59 +    echo $SID > /etc/samba/domain.SID
  245.60 +    echo $SID_PDC > /etc/samba/pdc.SID
  245.61 +    eco g "sid di $DOMAIN_NAME salvato in /etc/samba/domain.SID - $SID"
  245.62 +    eco g "sid di $PDC_NAME  salvato in /etc/samba/pdc.SID - $SID_PDC"
  245.63 +    
  245.64 +}
  245.65 +function setting_sid () {
  245.66 +    eco y "setting SIDs"
  245.67 +    net setdomainsid $SID
  245.68 +    net setlocalsid $SID_PDC
  245.69 +} 
  245.70 +function read_defaults(){
  245.71 +# i dati seguenti possono essere ridefiniti 
  245.72 +# nel file seguente
  245.73 +    FILE_DEF="/etc/isi/isi-setup.conf"
  245.74 +    # distro target
  245.75 +    [ $IS_UBUNTU = 0 ] && DIST='lenny' 
  245.76 +    [ $IS_UBUNTU = 1 ] && DIST='lenny' 
  245.77 +    # pacchetti
  245.78 +    PKGS_COMMON='mercurial nscd at acl quota tofrodos procinfo reiserfsprogs xfsprogs slapd libnss-ldap libpam-ldap  libnet-ldap-perl samba smbldap-tools migrationtools db4.2-util python-ldap python-dry python-urwid python-isi win-perl isi'
  245.79 +    PKGS_UBUNTU=" cracklib2 "
  245.80 +    PKGS_DEBIAN=" libcrack2 "
  245.81 +    # costanti
  245.82 +    UTENTI_IN="/home/users"
  245.83 +    SHARES_IN="/home/shares"
  245.84 +    CLASSI_IN="$SHARES_IN/classi"
  245.85 +    CORSI_IN="$SHARES_IN/corsi"
  245.86 +    PROFILE_DIR=".profili"
  245.87 +    # defaults (possono essere ridefiniti nel file di conf)
  245.88 +    MAINGRPS="admins,docenti,segreteria,ata,alunni,esterni,ospiti"
  245.89 +    AREE="area_alunni,area_docenti,area_segreteria,software"
  245.90 +    CLASSI="classe_test"
  245.91 +    CORSI="corso_test"   
  245.92 +    DC1=$(echo $DNS_DOMAIN | awk -F"." '{print $1}')
  245.93 +    DC2=$(echo $DNS_DOMAIN | awk -F"." '{print $2}')
  245.94 +    BASE_DN="dc=$DC1,dc=$DC2"
  245.95 +    SERVER_LDAP=127.0.0.1
  245.96 +    ROOT_BIND_DN="cn=admin,$BASE_DN"
  245.97 +    URI_LDAP="ldap://$SERVER_LDAP"
  245.98 +    SIZELIMIT=5000
  245.99 +    # smbldap-populate uid e gid iniziali
 245.100 +#    SMBLDAP_LDIF='/etc/isi/smbldap_ini.ldif'
 245.101 +#    DOMAIN_ADMIN="Administrator"
 245.102 +    U_MIN=1000
 245.103 +    U_MAX=30000
 245.104 +    G_MIN=1000
 245.105 +    G_MAX=30000
 245.106 +    # variabili in /etc/samba/smb.conf e ambiente samba
 245.107 +    SAMBA_STRING="SERVER ISI"
 245.108 +    SAMBA_IFACE="eth0"
 245.109 +    SAMBA_ADD_MACHINE_SCRIPT="/usr/sbin/smbldap-useradd -w "
 245.110 +#    [ "$USO_PDBEDIT" = 0 ] && SAMBA_ADD_MACHINE_SCRIPT="/usr/sbin/smbldap-useradd -w "
 245.111 +#    [ "$USO_PDBEDIT" = 1 ] && SAMBA_ADD_MACHINE_SCRIPT="/usr/bin/pdbedit -a -m -u"
 245.112 +
 245.113 +    [ "$USE_CONF" = 1 -a -f "$FILE_DEF" ] && . $FILE_DEF
 245.114 +
 245.115 +    [ "$IS_UBUNTU" = 0 ] && PKGS="$PKGS_DEBIAN $PKGS_COMMON"
 245.116 +    [ "$IS_UBUNTU" = 1 ] && PKGS="$PKGS_UBUNTU $PKGS_COMMON"
 245.117 +    
 245.118 +    if [ ! "$SERVER_LDAP" = "localhost" -a ! "$SERVER_LDAP"  = "127.0.0.1" ] ; then
 245.119 +        eco r "SLAPD NON LOCALE: $SERVER_LDAP, configurazione interrotta"
 245.120 +        exit 0
 245.121 +    fi
 245.122 +    if [ "$DUMP_CONF" = 1 ] ; then
 245.123 +        [ ! -d /etc/isi ] && mkdir /etc/isi
 245.124 +        cat <<DUMPEOF > /etc/isi/isi-setup.conf
 245.125 +#### DEFAULTs FILE per ISI-SETUP
 245.126 +# distribuzione
 245.127 +DIST=$DIST
 245.128 +PKGS="$PKGS_COMMON"
 245.129 +PKGS_UBUNTU="$PKGS_UBUNTU"
 245.130 +PKGS_DEBIAN="$PKGS_DEBIAN"
 245.131 +# struttura ISI
 245.132 +UTENTI_IN="$UTENTI_IN"
 245.133 +SHARES_IN="$SHARES_IN"
 245.134 +MAINGRPS="$MAINGRPS"
 245.135 +AREE="$AREE"
 245.136 +CLASSI="$CLASSI"
 245.137 +CORSI="$CORSI"
 245.138 +# dati dominio 
 245.139 +SID="$SID"
 245.140 +SID_PDC="$SID_PDC"
 245.141 +DOMAIN_NAME="$DOMAIN_NAME"
 245.142 +PDC_NAME="$PDC_NAME"
 245.143 +ORG_NAME="$ORG_NAME"
 245.144 +DOMAIN_ADMIN="$DOMAIN_ADMIN"
 245.145 +# dati ldap
 245.146 +SERVER_LDAP="$SERVER_LDAP"
 245.147 +DNS_DOMAIN="$DNS_DOMAIN"
 245.148 +BASE_DN="$BASE_DN"
 245.149 +ROOT_BIND_DN="$ROOT_BIND_DN"
 245.150 +URI_LDAP="$URI_LDAP"
 245.151 +LDAP_PWD="$LDAP_PWD"
 245.152 +U_MIN=$U_MIN
 245.153 +U_MAX=$U_MAX
 245.154 +G_MIN=$G_MIN
 245.155 +G_MAX=$G_MAX
 245.156 +# parametri samba
 245.157 +SAMBA_STRING="$SAMBA_STRING"
 245.158 +SAMBA_IFACE="$SAMBA_IFACE"
 245.159 +SAMBA_ADD_MACHINE_SCRIPT="$SAMBA_ADD_MACHINE_SCRIPT"
 245.160 +DUMPEOF
 245.161 +        chmod 600 /etc/isi/isi-setup.conf
 245.162 +        eco g "defaults salvati in /etc/isi/isi-setup.conf"
 245.163 +    [ "$SOLO_DUMP_CONF" = 1 ] && exit
 245.164 +    fi
 245.165 +}
 245.166 +
 245.167 +function eco() {
 245.168 +    ESC="\033["
 245.169 +    RED="${ESC}31;1m"
 245.170 +    GREEN="${ESC}32;1m"
 245.171 +    BLUE="${ESC}44;33;1m"
 245.172 +    YELLOW="${ESC}33;1m"
 245.173 +    NOR="${ESC}0m"
 245.174 +
 245.175 +    local col=$1
 245.176 +    shift
 245.177 +    case $col in
 245.178 +        g) COL=$GREEN
 245.179 +        ;;
 245.180 +        b) COL=$BLUE
 245.181 +        ;;
 245.182 +        y) COL=$YELLOW
 245.183 +        ;;
 245.184 +        r) COL=$RED
 245.185 +        ;;
 245.186 +        n) COL=$NOR
 245.187 +        ;;
 245.188 +    esac
 245.189 +    case $col in
 245.190 +        [gby]) [ $QUIET = 0 ] && echo -e ${COL}$*$NOR 
 245.191 +        ;;
 245.192 +        r) echo -e ${COL}$*$NOR 1>&2
 245.193 +        ;;
 245.194 +        n) [ $VERBOSE = 1 ] && echo $*
 245.195 +        ;;
 245.196 +    esac
 245.197 +}
 245.198 +
 245.199 +function crea_dir (){
 245.200 +    DOVE=$1
 245.201 +    COSA=$(echo $2 | sed 's/,/ /g')
 245.202 +    for x in $COSA; do
 245.203 +        if [ ! -d "$DOVE/$x" ] ; then
 245.204 +            eco n "creo $DOVE/$x"
 245.205 +            mkdir -p $DOVE/$x
 245.206 +        fi
 245.207 +    done
 245.208 +}
 245.209 +
 245.210 +function isi_default_stru(){
 245.211 +    eco y 'Preparazione filesystem ISI'
 245.212 +    # crea cartelle relative gruppi principali 
 245.213 +    crea_dir $UTENTI_IN $MAINGRPS
 245.214 +    # crea cartelle classi/corsi
 245.215 +    crea_dir $CLASSI_IN $CLASSI
 245.216 +    crea_dir $CORSI_IN $CORSI
 245.217 +    # crea cartelle aree
 245.218 +    crea_dir $SHARES_IN $AREE
 245.219 +    ### copia grub4dos nella share software
 245.220 +    if [ -d /home/shares/software ] && [ ! -d /home/shares/software/grub4dos ]; then
 245.221 +	cp -a /usr/share/doc/isi/grub4dos /home/shares/software
 245.222 +	find /home/shares/software -name \*gz -exec gunzip {} \;
 245.223 +    fi
 245.224 +    ### /etc/skel
 245.225 +    for d in .profili public_html Documenti ; do
 245.226 +        [ -d /etc.skel/$d ] || mkdir -p /etc/skel/$d
 245.227 +    done
 245.228 +    ### i file in /etc/isi saranno installati dal pacchetto isi
 245.229 +    if [ "$STANDARD_SETUP" = 1 ] ; then 
 245.230 +        [ ! -d /etc/isi ] && mkdir /etc/isi
 245.231 +        cp -a /usr/share/doc/isi/etc/isi/* /etc/isi/
 245.232 +        # link simbolico a /usr/lib/isi/acl.conf
 245.233 +        [ -L /etc/isi/acl.conf ] && rm /etc/isi/acl.conf 
 245.234 +        ln -s /usr/lib/isi/acl.conf /etc/isi/acl.conf
 245.235 +        ### check isi-logon
 245.236 +        if [ -f /etc/isi/logon.conf.gz ] ; then
 245.237 +            [ -f /etc/isi/logon.conf ] && rm /etc/isi/logon.conf
 245.238 +            gunzip /etc/isi/logon.conf.gz
 245.239 +        fi
 245.240 +        for f in logon.conf logon.pl logonupd.pl ; do
 245.241 +            ff="/usr/share/WinActivePerl/$f"
 245.242 +            [ -f "$ff" ] && rm $ff
 245.243 +            ln -s /etc/isi/$f $ff
 245.244 +        done
 245.245 +    fi
 245.246 +    # aggiorna PDC_NAME in logon.bat logonupd.bat
 245.247 +    OLD_PDC=$(grep "\\\\" /etc/isi/logon.bat | awk -F"\\" '{print $3}')
 245.248 +    if [ "$OLD_PDC" != "$PDC_NAME" ] ; then 
 245.249 +        sed -i "s%$OLD_PDC%$PDC_NAME%g" /etc/isi/logon.bat
 245.250 +        sed -i "s%$OLD_PDC%$PDC_NAME%g" /etc/isi/logonupd.bat
 245.251 +    fi
 245.252 +}
 245.253 +function _checkapt (){
 245.254 +    FILE="$1"
 245.255 +    REPO="$2"
 245.256 +    DIST="$3"
 245.257 +    RAMI="$4"
 245.258 +    local OPZ
 245.259 +    if ! egrep -q "[\s\t]*$REPO[\s\t]*$DIST[\s\t]*$RAMI" /etc/apt/sources.list ; then
 245.260 +        sed -i "s/^.*\($REPO.*\)/#\1/" /etc/apt/sources.list
 245.261 +        echo "deb http://$REPO $DIST $RAMI" >> /etc/apt/sources.list
 245.262 +    [ "$VERBOSE" = 1 ] && OPZ='' || OPZ='-q'
 245.263 +        wget $OPZ http://$REPO/dists/$DIST/public.key -O- | apt-key add - >/dev/null
 245.264 +    fi
 245.265 +    if  grep -q $REPO /etc/apt/sources.list ; then
 245.266 +        eco g "FONTE APT OK: deb http://$REPO $DIST $RAMI"
 245.267 +    else
 245.268 +        eco r "ERRORE: manca la fonte $REPO" 
 245.269 +        exit 1
 245.270 +    fi
 245.271 +}
 245.272 +
 245.273 +function checkapt () {
 245.274 +    local op
 245.275 +    [ "$APT_UPD" = 0 ] && return
 245.276 +    eco y 'FASE 1: controllo e update delle fonti APT'
 245.277 +    _checkapt 'reteisi' 'apt.argolinux.org' $DIST 'main'
 245.278 +    _checkapt 'reteisi' 'apt.reteisi.org' $DIST 'isi'
 245.279 +    [ "$VERBOSE" = 0 ] && op="-qq" || op=""
 245.280 +    apt-get update $op
 245.281 +}
 245.282 +
 245.283 +function _checkpkg (){
 245.284 +    local op
 245.285 +    if [ "$IS_UBUNTU" = 1 ] ; then
 245.286 +        if grep -wq $1 /tmp/PKGS_NO_UBUNTU &>/dev/null; then 
 245.287 +            return 0
 245.288 +        fi
 245.289 +    fi
 245.290 +    
 245.291 +    [ "$APT_UPD" = 0 ] && return
 245.292 +    op="-y --force-yes"
 245.293 +    [ "$VERBOSE" = 0 ] && op="$op -qq"
 245.294 +    if dpkg -l $1 2>/dev/null | grep -q ii ; then
 245.295 +       eco g "PRESENTE: $1"
 245.296 +    else
 245.297 +       eco r "MANCANTE: $1 - installo...ATTENDI..."
 245.298 +       apt-get install $1 $op
 245.299 +       if dpkg -l $1 2>/dev/null | grep -q ii ; then
 245.300 +           eco g "INSTALLATO: $1"
 245.301 +       else
 245.302 +           eco r "IMPOSSIBILE installare $1"
 245.303 +           ERR_PKG="$ERR_PKG $1"
 245.304 +       fi
 245.305 +    fi
 245.306 +}
 245.307 +
 245.308 +function check_packages () {
 245.309 +    ERR_PKG=""
 245.310 +    eco y 'FASE 2: controllo e/o installazione pacchetti'
 245.311 +    eco y "CONTROLLO: pacchetti"
 245.312 +    for p in $PKGS_COMMON ; do
 245.313 +        _checkpkg $p
 245.314 +    done
 245.315 +    if [ -z "$ERR_PKG" ] ; then
 245.316 +        eco v "pacchetti OK"
 245.317 +    else
 245.318 +        eco r "ERRORE FATALE - mancano pacchetti critici:\n\t$ERR_PKG" 
 245.319 +        exit 1
 245.320 +    fi
 245.321 +}
 245.322 +
 245.323 +function prep_debconf () {
 245.324 +    # ATTENZIONE qui si utilizza la tecnica del preseed. 
 245.325 +    # È obbligatorio che tra il tipo della variabile debconf e il suo valore 
 245.326 +    # ci sia ESATTAMENTE UNO SPAZIO.
 245.327 +    
 245.328 +    [ "$APT_UPD" = 0 ] && return
 245.329 +    eco y 'Preparazione variabili debconf (APT_UPD=$APT_UPD)'  
 245.330 +    apt-get install debconf-utils -qq
 245.331 +    
 245.332 +    export DEBIAN_FRONTEND=noninteractive
 245.333 +    export DEBIAN_PRIORITY=critical
 245.334 +    
 245.335 +    cat <<PRESEED>> /tmp/isi.preseed
 245.336 +# LDAP root account password:
 245.337 +libpam-ldap libpam-ldap/rootbindpw password $LDAP_PWD
 245.338 +# LDAP root account password:
 245.339 +libnss-ldap libnss-ldap/rootbindpw password $LDAP_PWD
 245.340 +# Encrypted admin password:
 245.341 +slapd slapd/internal/adminpw password $LDAP_PWD
 245.342 +# Administrator password:
 245.343 +slapd slapd/password1 password $LDAP_PWD
 245.344 +# Confirm password:
 245.345 +slapd slapd/password2 password $LDAP_PWD
 245.346 +# Password for database login account:
 245.347 +libpam-ldap libpam-ldap/bindpw password    
 245.348 +# Password for database login account:
 245.349 +libnss-ldap libnss-ldap/bindpw password    
 245.350 +# Does the LDAP database require login?
 245.351 +libnss-ldap libnss-ldap/dblogin boolean false
 245.352 +# Password mismatch
 245.353 +slapd slapd/password_mismatch note    
 245.354 +# Retry configuration?
 245.355 +slapd slapd/invalid_config boolean true
 245.356 +# Organization name:
 245.357 +slapd   shared/organization string $ORG_NAME
 245.358 +# Automatically update libnss-ldap's configuration file?
 245.359 +libnss-ldap libnss-ldap/override boolean true
 245.360 +# How do you want to run Samba?
 245.361 +# Choices: daemons, inetd
 245.362 +samba samba/run_mode select daemons
 245.363 +# Distinguished name of the search base:
 245.364 +libnss-ldap shared/ldapns/base-dn string $BASE_DN
 245.365 +libpam-ldap shared/ldapns/base-dn string $BASE_DN
 245.366 +# LDAP server Uniform Resource Identifier:
 245.367 +libnss-ldap shared/ldapns/ldap-server string $URI_LDAP
 245.368 +libpam-ldap shared/ldapns/ldap-server string $URI_LDAP
 245.369 +# Use password encryption?
 245.370 +samba-common samba-common/encrypt_passwords boolean true
 245.371 +# Local crypt to use when changing passwords.
 245.372 +# Choices: clear, crypt, nds, ad, exop, md5
 245.373 +libpam-ldap libpam-ldap/pam_password select crypt
 245.374 +# Modify smb.conf to use WINS settings from DHCP?
 245.375 +samba-common samba-common/dhcp boolean false
 245.376 +# Unprivileged database user:
 245.377 +libpam-ldap libpam-ldap/binddn  string  cn=proxyuser,dc=example,dc=net
 245.378 +# Make the configuration file readable/writeable by its owner only?
 245.379 +libnss-ldap libnss-ldap/confperm boolean true
 245.380 +# Workgroup/Domain Name:
 245.381 +samba-common samba-common/workgroup string $DOMAIN_NAME
 245.382 +# LDAP account for root:
 245.383 +libpam-ldap libpam-ldap/rootbinddn string $ROOT_BIND_DN
 245.384 +# LDAP account for root:
 245.385 +libnss-ldap libnss-ldap/rootbinddn string $ROOT_BIND_DN
 245.386 +# Make local root Database admin.
 245.387 +libpam-ldap libpam-ldap/dbrootlogin boolean false
 245.388 +# Database backend to use:
 245.389 +# Choices: BDB, HDB
 245.390 +slapd slapd/backend   select HDB
 245.391 +# Dump databases to file on upgrade:
 245.392 +# Choices: always, when needed, never
 245.393 +slapd slapd/dump_database select when needed
 245.394 +# Allow LDAPv2 protocol?
 245.395 +slapd slapd/allow_ldap_v2 boolean false
 245.396 +# Make debconf change your config?
 245.397 +libpam-ldap libpam-ldap/override boolean true
 245.398 +# Omit OpenLDAP server configuration?
 245.399 +slapd slapd/no_configuration boolean false
 245.400 +# LDAP version to use:
 245.401 +# Choices: 3, 2
 245.402 +libnss-ldap shared/ldapns/ldap_version select 3
 245.403 +libpam-ldap shared/ldapns/ldap_version select 3
 245.404 +# Does the LDAP database require login?
 245.405 +libpam-ldap libpam-ldap/dblogin boolean false
 245.406 +# Abort installation after depmod error?
 245.407 +# Move old database?
 245.408 +slapd   slapd/move_old_database boolean true
 245.409 +# Unprivileged database user:
 245.410 +libnss-ldap libnss-ldap/binddn string cn=proxyuser,dc=example,dc=net
 245.411 +# Back up current database and create a new one?
 245.412 +slapd slapd/suffix_change boolean false
 245.413 +# Create samba password database, /var/lib/samba/passdb.tdb?
 245.414 +samba samba/generate_smbpasswd boolean true
 245.415 +## nsswitch.conf not managed automatically
 245.416 +#libnss-ldap libnss-ldap/nsswitch note    
 245.417 +# Directory to use for dumped databases:
 245.418 +slapd slapd/dump_database_destdir string /var/backups/slapd-VERSION
 245.419 +# Do you want the database to be removed when slapd is purged?
 245.420 +slapd slapd/purge_database boolean false
 245.421 +# DNS domain name:
 245.422 +slapd slapd/domain string $DNS_DOMAIN
 245.423 +# Configure smb.conf automatically?
 245.424 +samba-common samba-common/do_debconf boolean true
 245.425 +PRESEED
 245.426 +
 245.427 +    debconf-set-selections /tmp/isi.preseed
 245.428 +    rm  /tmp/isi.preseed
 245.429 +}
 245.430 +
 245.431 +function set_in_conf_file() {
 245.432 +    VAR=$1
 245.433 +    VALUE=$2
 245.434 +    SEP_REG="[ \t]"
 245.435 +    SEP=" "
 245.436 +    eco n "setting in $CONF_FILE - $VAR  $VALUE" 
 245.437 +    # 1^ case: var is not in file: just add it
 245.438 +    # 2^ case: VAR is in file
 245.439 +    if ! grep -q $VAR $CONF_FILE  ; then
 245.440 +        echo ${VAR}${SEP}${VALUE} >> $CONF_FILE
 245.441 +    else
 245.442 +        sed -i "s%^[ #]*$VAR$SEP_REG.*%$VAR$SEP$VALUE%" $CONF_FILE
 245.443 +    fi
 245.444 +return
 245.445 +}
 245.446 +function uncomment () {
 245.447 +    VAR=$1
 245.448 +    VAL=$2
 245.449 +    # comment all other poss=ible $1 not commented
 245.450 +    sed -i "s/^.*\($VAR.*\)/#\1/" $CONF_FILE
 245.451 +    # uncomment  $1 $2
 245.452 +    sed -i "s/^.*\($VAR *$VAL\)/\1/" $CONF_FILE
 245.453 +}
 245.454 +function stop_services (){
 245.455 +#    [ $QUIET = 0 ]  && /etc/init.d/slapd stop \
 245.456 +#                    || /etc/init.d/slapd stop >/dev/null
 245.457 +
 245.458 +    #invoke-rc.d slapd stop
 245.459 +    /etc/init.d/slapd stop
 245.460 +    until [ "$(pidof slapd)" = "" ] ; do
 245.461 +        sleep 1
 245.462 +        if [ "$(pidof slapd)" != "" ] ; then 
 245.463 +            eco r "riprovo a fermare slapd"
 245.464 +            #invoke-rc.d slapd stop
 245.465 +            /etc/init.d/slapd stop
 245.466 +        else
 245.467 +            break
 245.468 +        fi
 245.469 +        i=$((i+1))
 245.470 +        if [ "$i" = 10 ] ; then
 245.471 +           eco r "slapd non si ferma !!! - ERRORE FATALE"
 245.472 +           exit 1
 245.473 +        fi
 245.474 +    done
 245.475 +
 245.476 +    #invoke-rc.d samba stop
 245.477 +    /etc/init.d/samba stop
 245.478 +    until [ "$(pidof slapd)" = "" ] ; do
 245.479 +        sleep 1
 245.480 +        if [ "$(pidof slapd)" != "" ] ; then 
 245.481 +            eco r "riprovo a fermare samba"
 245.482 +            #invoke-rc.d samba stop
 245.483 +            /etc/init.d/samba stop
 245.484 +        else
 245.485 +            break
 245.486 +        fi
 245.487 +        i=$((i+1))
 245.488 +        if [ "$i" = 10 ] ; then
 245.489 +           eco r "samba non si ferma !!! - ERRORE FATALE"
 245.490 +           exit 1
 245.491 +        fi
 245.492 +    done
 245.493 +
 245.494 +    
 245.495 +#    if [ $PIDSLAP != "" ] ; then 
 245.496 +#        eco r 'ERRORE: slapd non si ferma!!! - provo kill -9'
 245.497 +#        exit 1
 245.498 +#    fi
 245.499 +#    [ $QUIET = 0 ]  && /etc/init.d/samba stop \
 245.500 +#                    || /etc/init.d/samba stop >/dev/null
 245.501 +#    PIDS=$(pidof smbd)
 245.502 +#    PIDN=$(pidof nmbd)
 245.503 +#    until  [ $PIDS != "" -o $PIDN != "" ] ; do
 245.504 +#        eco r 'ERRORE: samba non si ferma!!! provo kill -9'
 245.505 +#        kill -9 PIDS
 245.506 +#        kill -9 PIDN
 245.507 +#        PIDS=$(pidof smbd)
 245.508 +#        PIDN=$(pidof nmbd)
 245.509 +#    done
 245.510 +}
 245.511 +function start_services (){
 245.512 +    [ "$QUIET" = 0 ] && /etc/init.d/slapd start \
 245.513 +                    || /etc/init.d/slapd start >/dev/null
 245.514 +    
 245.515 +    PID1=$(pgrep -c slapd)
 245.516 +    if [ "$PID1" = 0 ] ; then 
 245.517 +        eco r 'ERRORE: slapd non parte!!!'
 245.518 +        exit 1
 245.519 +    else
 245.520 +    [ "$QUIET" = 0 ] && /etc/init.d/samba start \
 245.521 +                    || /etc/init.d/samba start >/dev/null
 245.522 +        PID1=$(pgrep -c smbd)
 245.523 +        PID2=$(pgrep -c nmbd)
 245.524 +        if [ "$PID1" = 0  -o "$PID2" = 0 ] ; then
 245.525 +            eco r 'ERRORE: samba non parte!!!'
 245.526 +            exit 1
 245.527 +        fi
 245.528 +    fi
 245.529 +    eco g "slapd/samba correttamente avviati"
 245.530 +}
 245.531 +function check_secrets (){
 245.532 +    eco y "setting /etc/ldap.secret"
 245.533 +    rm -f /etc/libnss-ldap.secret
 245.534 +    rm -f /etc/pam_ldap.secret
 245.535 +    echo $LDAP_PWD > /etc/ldap.secret
 245.536 +    chmod 600 /etc/ldap.secret
 245.537 +    ln -s /etc/ldap.secret /etc/libnss-ldap.secret
 245.538 +    ln -s /etc/ldap.secret /etc/pam_ldap.secret
 245.539 +}
 245.540 +function setting_ldap (){
 245.541 +    eco y "setting conf ldap"
 245.542 +    if [ "$IS_UBUNTU" = 0 ] ; then  #lenny/etch
 245.543 +        ### conf of /etc/ldap/ldap.conf
 245.544 +        CONF_FILE="/etc/ldap/ldap.conf"
 245.545 +        set_in_conf_file "BASE" "$BASE_DN"
 245.546 +        set_in_conf_file "URI"  "$URI_LDAP"
 245.547 +        set_in_conf_file "HOST" "$SERVER_LDAP"
 245.548 +        set_in_conf_file "SIZELIMIT" "$SIZELIMIT"
 245.549 +
 245.550 +        # defaults for libnss
 245.551 +        CONF_FILE="/etc/libnss-ldap.conf"
 245.552 +        if [ -e "$CONF_FILE" ] ; then
 245.553 +            set_in_conf_file "base" "$BASE_DN"
 245.554 +            set_in_conf_file "host" "$SERVER_LDAP"
 245.555 +            set_in_conf_file "ldap_version" "3"
 245.556 +            set_in_conf_file "rootbinddn" "$ROOT_BIND_DN"
 245.557 +            if [[ "$(expr match $URI_LDAP ldaps?://)" -gt 7 ]]; then
 245.558 +                set_in_conf_file "uri" "$URI_LDAP"
 245.559 +            fi
 245.560 +            uncomment "pam_password" "exop"
 245.561 +            XX=$(egrep "^[^#]*uri ldapi:///" $CONF_FILE)
 245.562 +            [ -z "$XX" ] || sed -i "s%^.*$XX%\#$XX%g" $CONF_FILE
 245.563 +        fi
 245.564 +
 245.565 +        # defaults for libpam_ldap
 245.566 +        CONF_FILE="/etc/pam_ldap.conf"
 245.567 +        if [ -e "$CONF_FILE" ] ; then
 245.568 +            set_in_conf_file "base" "$BASE_DN"
 245.569 +            set_in_conf_file "host" "$SERVER_LDAP"
 245.570 +            set_in_conf_file "ldap_version" "3"
 245.571 +            set_in_conf_file "rootbinddn" "$ROOT_BIND_DN"
 245.572 +            uncomment "pam_password" "exop"
 245.573 +            XX=$(egrep "^[^#]*uri ldapi:///" $CONF_FILE)
 245.574 +            [ -z "$XX" ] || sed -i "s%^.*$XX%\#$XX%g" $CONF_FILE
 245.575 +        fi
 245.576 +    else  #ubuntu
 245.577 +        ### conf of /etc/ldap/ldap.conf
 245.578 +        CONF_FILE="/etc/ldap/ldap.conf"
 245.579 +        set_in_conf_file "BASE" "$BASE_DN"
 245.580 +        set_in_conf_file "URI"  "$URI_LDAP"
 245.581 +        set_in_conf_file "HOST" "$SERVER_LDAP"
 245.582 +        set_in_conf_file "SIZELIMIT" "$SIZELIMIT"
 245.583 +
 245.584 +        CONF_FILE="/etc/ldap.conf"
 245.585 +        if [ -e "$CONF_FILE" ] ; then
 245.586 +            set_in_conf_file "base" "$BASE_DN"
 245.587 +            set_in_conf_file "host" "$SERVER_LDAP"
 245.588 +            set_in_conf_file "ldap_version" "3"
 245.589 +            set_in_conf_file "rootbinddn" "$ROOT_BIND_DN"
 245.590 +            uncomment "pam_password" "exop"
 245.591 +	fi
 245.592 +
 245.593 +        # defaults for ldap.conf
 245.594 +        CONF_FILE="/etc/ldap.conf"
 245.595 +        if [ -e "$CONF_FILE" ] ; then
 245.596 +            set_in_conf_file "base" "$BASE_DN"
 245.597 +            set_in_conf_file "host" "$SERVER_LDAP"
 245.598 +            set_in_conf_file "ldap_version" "3"
 245.599 +            set_in_conf_file "rootbinddn" "$ROOT_BIND_DN"
 245.600 +            if [[ "$(expr match $URI_LDAP ldaps?://)" -gt 7 ]]; then
 245.601 +                set_in_conf_file "uri" "$URI_LDAP"
 245.602 +            fi
 245.603 +            uncomment "pam_password" "exop"
 245.604 +            XX=$(egrep "^[^#]*uri ldapi:///" $CONF_FILE)
 245.605 +            [ -z "$XX" ] || sed -i "s%^.*$XX%\#$XX%g" $CONF_FILE
 245.606 +        fi
 245.607 +    fi
 245.608 +}
 245.609 +
 245.610 +function slap_add_indexes () {
 245.611 +    # adding slapd indexes only if they are not yet there
 245.612 +    if ! grep -q "eq,subinitial" /etc/ldap/slapd.conf ; then
 245.613 +        cp /etc/ldap/slapd.conf /tmp/slapd.conf
 245.614 +        eco y "Adding indexed to /etc/ldap/slapd.conf"
 245.615 +        awk ' {print}
 245.616 +            $1 == "index" && $2 == "objectClass" {
 245.617 +            print "index    uid,uidNumber,gidNumber,memberUid   eq"
 245.618 +            print "index    cn,sn                               eq,subinitial"
 245.619 +            print "index    sambaSID                            eq"
 245.620 +            print "index    sambaPrimaryGroupSID                eq"
 245.621 +            print "index    sambaDomainName                     eq"
 245.622 +            print "index    DisplayName                         eq"
 245.623 +            print "index    sambaGroupType                      eq"
 245.624 +            print "index    sambaSIDList                        eq"
 245.625 +            print "index    uniqueMember                        eq"
 245.626 +            }'  /tmp/slapd.conf > /etc/ldap/slapd.conf
 245.627 +        rm /tmp/slapd.conf
 245.628 +    fi
 245.629 +    if ! grep -q "sambaPwdMustChange" /etc/ldap/slapd.conf ; then
 245.630 +        cp /etc/ldap/slapd.conf /tmp/slapd.conf
 245.631 +        eco y "special access to pass* fields"
 245.632 +        awk ' $3 == "attrs=userPassword" {
 245.633 +            $0="access to attrs=userPassword, sambaNTPassword, sambaLMPassword, sambaPwdLastSet,sambaPwdMustChange, employeeNumber"
 245.634 +            }
 245.635 +            {print}'  /tmp/slapd.conf > /etc/ldap/slapd.conf
 245.636 +        rm /tmp/slapd.conf
 245.637 +    fi
 245.638 +}
 245.639 +function slap_add_samba_schema () {
 245.640 +    #[ -f /etc/ldap/schema/samba.schema ] && return
 245.641 +    SCHEMA=/usr/share/doc/isi/etc/samba/samba.schema.gz
 245.642 +    if [ -f "$SCHEMA" ] ; then 
 245.643 +        zcat $SCHEMA > /etc/ldap/schema/samba.schema
 245.644 +        eco n "Adding samba.schema to /etc/ldap/slapd.conf"
 245.645 +        if ! grep -q "/etc/ldap/schema/samba.schema" /etc/ldap/slapd.conf ; then 
 245.646 +            cp /etc/ldap/slapd.conf /tmp/slapd.conf
 245.647 +            awk ' {print}   
 245.648 +                /inetorgperson/ {print "include\t\t/etc/ldap/schema/samba.schema"}
 245.649 +                '  /tmp/slapd.conf > /etc/ldap/slapd.conf
 245.650 +            rm /tmp/slapd.conf
 245.651 +        fi
 245.652 +    else
 245.653 +        eco r "ERRORE FATALE: manca samba.schema" 
 245.654 +        exit 1
 245.655 +    fi    
 245.656 +}
 245.657 +function check_nsswitch() {  
 245.658 +    eco y "setting /etc/nsswitch.conf"
 245.659 +    # password group shadow
 245.660 +    for string in passwd group shadow; do
 245.661 +        if ! egrep -q "$string.*ldap" /etc/nsswitch.conf ; then
 245.662 +            eco n "Adding 'ldap' to /etc/nsswitch.conf for $string"
 245.663 +            cp /etc/nsswitch.conf /tmp
 245.664 +            awk '{if($1 ~ string) {print string"\t files ldap"}
 245.665 +                else print
 245.666 +                }' string=$string: /tmp/nsswitch.conf > /etc/nsswitch.conf
 245.667 +        fi
 245.668 +    done
 245.669 +}
 245.670 +function check_pam() {
 245.671 +    # password group shadow
 245.672 +    eco y "setting pam"
 245.673 +    local PWD
 245.674 +    PWD=$(pwd)
 245.675 +    cd /etc/pam.d
 245.676 +
 245.677 +    for file in account auth password session; do
 245.678 +        file=common-$file
 245.679 +        [ ! -e "$file" ] && continue
 245.680 +        if ! grep pam_ldap.so $file > /dev/null ; then
 245.681 +            eco n "Adding sufficient pam_ldap.so to /etc/pam.d/$file"
 245.682 +            cp $file /tmp
 245.683 +            awk '$3 == "pam_unix.so" {print $1"\t sufficient pam_ldap.so"
 245.684 +                if ($1 == "auth" && $0 !~ /first_pass/) {
 245.685 +                    $0=$0" use_first_pass"
 245.686 +                }
 245.687 +            }
 245.688 +            {print}' /tmp/$file > $file
 245.689 +            rm -f /tmp/$file
 245.690 +        fi
 245.691 +    done
 245.692 +    # force smbd to reload pam setting
 245.693 +    /etc/init.d/ssh reload 1> /dev/null 2>&1 
 245.694 +    #killall -HUP smbd 2> /dev/null ||true
 245.695 +    cd $PWD
 245.696 +}
 245.697 +function crea_smb_conf () {
 245.698 +    eco y "configuro Samba"
 245.699 +    # utmp logfile
 245.700 +    mkdir -p /var/log/samba/utmp
 245.701 +    mkdir -p /var/log/samba/wtmp
 245.702 +    touch /var/log/samba/utmp/utmpx
 245.703 +    touch /var/log/samba/wtmp/wtmpx
 245.704 +    # cancella eventuale wins.dat
 245.705 +    [ -f /var/lib/samba/wins.dat ] && rm /var/lib/samba/wins.dat
 245.706 +    # /etc/samba/smb.conf
 245.707 +    cat <<EOF > /etc/samba/smb.conf
 245.708 +[global]
 245.709 +   workgroup = $DOMAIN_NAME
 245.710 +   netbios name = $PDC_NAME
 245.711 +   server string = %h $SERVER_STRING
 245.712 +   dns proxy = No
 245.713 +   bind interfaces only = Yes
 245.714 +   interfaces = lo, $SAMBA_IFACE
 245.715 +   smb ports = 139
 245.716 +#   invalid users = root
 245.717 +#   admin users = root,@admins
 245.718 +#   printer admin = @lpadmin
 245.719 +
 245.720 +### registra i logon via samba
 245.721 +   utmp = Yes
 245.722 +   utmp directory = /var/log/samba/utmp
 245.723 +   wtmp directory = /var/log/samba/wtmp
 245.724 +
 245.725 +### evita l'apertura di notepad con un file desktop.ini
 245.726 +   hide files = /desktop.ini/ntuser.ini/NTUSER.*/
 245.727 +
 245.728 +### conserva i permessi e i privilegi dei file dell'utente
 245.729 +   inherit acls = yes
 245.730 +   inherit owner = yes
 245.731 +
 245.732 +   log file = /var/log/samba/log.%m
 245.733 +   max log size = 1000
 245.734 +   syslog = 0
 245.735 +   log level = 1
 245.736 +
 245.737 +   security = user
 245.738 +   encrypt passwords = true
 245.739 +   passdb backend = ldapsam:ldap://$SERVER_LDAP/
 245.740 +   obey pam restrictions = no
 245.741 +   deadtime = 15
 245.742 +   browseable = no
 245.743 +
 245.744 +   wins support = Yes
 245.745 +   name resolve order = lmhosts host wins bcast
 245.746 +
 245.747 +   local master = yes
 245.748 +   domain master = Yes
 245.749 +   preferred master = Yes
 245.750 +   os level = 254
 245.751 +   domain logons = Yes
 245.752 +
 245.753 +#   map system = yes
 245.754 +#   map archive = yes
 245.755 +#   map hidden = yes
 245.756 +
 245.757 +   unix password sync = no
 245.758 +   enable privileges = yes
 245.759 +   passwd program = /usr/sbin/smbldap-passwd %u
 245.760 +   passwd chat = *New*password* %n\n *Retype*new*password* %n\n
 245.761 +   socket options = TCP_NODELAY, SO_KEEPALIVE
 245.762 +
 245.763 +   load printers = yes
 245.764 +   printing = cups
 245.765 +   printcap name = cups
 245.766 +
 245.767 +   ldap ssl = no
 245.768 +   ldap passwd sync = yes
 245.769 +   ldap machine suffix = ou=Computers
 245.770 +   ldap idmap suffix = ou=Idmaps
 245.771 +   ldap group suffix = ou=Groups
 245.772 +   ldap user suffix = ou=People
 245.773 +   ldap suffix = $BASE_DN
 245.774 +   ldap delete dn = Yes
 245.775 +   ldap admin dn = $ROOT_BIND_DN
 245.776 +
 245.777 +   logon home = \\\\%N\\%U\\.\\\\.profili\\%a
 245.778 +   logon drive = H:
 245.779 +   logon path = \\\\%N\\%U\\.profili\\%a
 245.780 +   logon script = logon.bat
 245.781 +
 245.782 +   add machine script = $SAMBA_ADD_MACHINE_SCRIPT "%m"
 245.783 +   set primary group script = /usr/sbin/smbldap-usermod -g "%g" "%u"
 245.784 +   delete user from group script = /usr/sbin/smbldap-groupmod -x "%u" "%g"
 245.785 +   add user to group script = /usr/sbin/smbldap-groupmod -m "%u" "%g"
 245.786 +   delete group script = /usr/sbin/smbldap-groupdel "%g"
 245.787 +   add group script = /usr/sbin/smbldap-groupadd -p "%g"
 245.788 +   delete user script = /usr/sbin/smbldap-userdel "%u"
 245.789 +   add user script = /usr/sbin/smbldap-useradd -m "%u"
 245.790 +   
 245.791 +   check password script = /usr/bin/crackcheck -s
 245.792 +   
 245.793 +   panic action = /usr/share/samba/panic-action %d
 245.794 +
 245.795 +[homes]
 245.796 +   comment = ISI-homes (NON MODIFICARE QUESTA RIGA)
 245.797 +   browseable = no
 245.798 +   writable = yes
 245.799 +   guest ok = no
 245.800 +   veto files = /public_html/
 245.801 +
 245.802 +[printers]
 245.803 +   comment = All Printers
 245.804 +   browseable = no
 245.805 +   path = /tmp
 245.806 +   printable = yes
 245.807 +   public = no
 245.808 +   writable = no
 245.809 +   create mode = 0700
 245.810 +
 245.811 +[print$]
 245.812 +   comment = Printer Drivers
 245.813 +   path = /var/lib/samba/printers
 245.814 +   browseable = yes
 245.815 +   read only = yes
 245.816 +   guest ok = no
 245.817 +   write list = @lpadmin, root
 245.818 +
 245.819 +include = /etc/isi/samba/smb_servizi.conf
 245.820 +#include = /etc/isi/samba/smb_maingrps.conf
 245.821 +include = /etc/isi/samba/smb_classi.conf
 245.822 +include = /etc/isi/samba/smb_corsi.conf
 245.823 +include = /etc/isi/samba/smb_aree.conf
 245.824 +
 245.825 +[perl]
 245.826 +   path = /usr/share/WinActivePerl
 245.827 +   comment = Per Windows Binaries
 245.828 +   public = yes
 245.829 +   writable = no
 245.830 +   guest ok = yes
 245.831 +   browseable = no
 245.832 +
 245.833 +
 245.834 +[netlogon]
 245.835 +    comment = ISI-NetLogon (NON MODIFICARE QUESTA RIGA)
 245.836 +    path = /home/samba/netlogon
 245.837 +    guest ok = yes
 245.838 +    browseable = no
 245.839 +    create mask = 0644
 245.840 +    directory mask = 0755
 245.841 +    writable = yes
 245.842 +    root preexec=/usr/sbin/setlogonvar '%U' '%G' '%m'
 245.843 +    root postexec=/usr/sbin/rmlogonvar '%m'
 245.844 +
 245.845 +#[profiles]
 245.846 +#   comment = cartelle profili utente
 245.847 +#   path = $UTENTI_IN/%g/%u/$PROFILE_DIR%a
 245.848 +#   read only = No
 245.849 +#   create mask = 0660
 245.850 +#   directory mask = 2770
 245.851 +#   browseable = No
 245.852 +#   guest ok = Yes
 245.853 +#   profile acls = Yes
 245.854 +#   csc policy = disable
 245.855 +#   # next line is a great way to secure the profiles
 245.856 +#   force user = %U
 245.857 +
 245.858 +EOF
 245.859 +
 245.860 +    # /home/samba/netlogon
 245.861 +    [ -d /home/samba/netlogon ] || mkdir -p /home/samba/netlogon
 245.862 +    # crea la dir per la registrazionre dei login via samba
 245.863 +    [ -d /var/www/sambalogon ] || mkdir -p /var/www/sambalogon
 245.864 +    # crea link simbolici a logon*.bat
 245.865 +    for f in logon.bat logonupd.bat ; do
 245.866 +        [ -e /home/samba/netlogon/$f ] && rm /home/samba/netlogon/$f
 245.867 +        ln -s /etc/isi/$f /home/samba/netlogon/$f
 245.868 +    done
 245.869 +}
 245.870 +function add_env_folder () {
 245.871 +    # aggiunge le cartelle d'ambiente env_WinXX_gruppo
 245.872 +    # con WinXX = Win98 e WinXP
 245.873 +    local PROGRAM_DIR=/usr/share/doc/isi/logon/WinMenuAvvio/Programmi
 245.874 +    eco y "creo le cartelle /home/samba/netlogon/ENV..."
 245.875 +    GRUPPI=$(echo $MAINGRPS|sed 's/,/ /g')
 245.876 +    for grp in $GRUPPI ; do
 245.877 +        for os in Win98 WinXP ; do
 245.878 +            DIRENV=/home/samba/netlogon/env_$os\_$grp
 245.879 +            if [ ! -d "$DIRENV" ] ; then  
 245.880 +                mkdir -p $DIRENV/Desktop
 245.881 +                mkdir -p $DIRENV/Menu\ Avvio
 245.882 +                # regalino: link all'applet CambiaPassword del controlpanel
 245.883 +                if [ "$os" = "Win98" ] ; then
 245.884 +                    cp /usr/share/doc/isi/logon/WinDesktop/Cambia* \
 245.885 +                        $DIRENV/Desktop
 245.886 +		    if [ -d $PROGRAM_DIR ] ; then
 245.887 +			cp -a /usr/share/doc/isi/logon/WinMenuAvvio/Programmi \
 245.888 +                            $DIRENV/Menu\ Avvio
 245.889 +		    fi
 245.890 +                fi
 245.891 +                chmod -R 775 $DIRENV
 245.892 +            fi
 245.893 +        done
 245.894 +    done
 245.895 +    chown -R root.admins /home/samba/netlogon/env* || echo admins non ancora presente...
 245.896 +
 245.897 +}
 245.898 +
 245.899 +function fix_ldap_sambaAlgorithmicRidBase () {
 245.900 +
 245.901 +    ## Qui abbiamo un problema. smbldap-populate non crea (!!!)
 245.902 +    ## sambaAlgorithmicRidBase
 245.903 +
 245.904 +    OPTS=" -D  $ROOT_BIND_DN -w $LDAP_PWD "
 245.905 +    ldapsearch -xLLL $OPTS  "(sambaDomainName=$DOMAIN_NAME)" > /tmp/dom.ldif
 245.906 +    ## controlla esistenza gidNumber
 245.907 +    if ! grep sambaAlgorithmicRidBase /tmp/dom.ldif >/dev/null; then
 245.908 +        eco y "fix sambaAlgorithmicRidBase: 1000"
 245.909 +        cat <<EOF > /tmp/dom.ldif
 245.910 +dn: sambaDomainName=$DOMAIN_NAME,$BASE_DN
 245.911 +changetype: modify
 245.912 +add: sambaAlgorithmicRidBase
 245.913 +sambaAlgorithmicRidBase: 1000
 245.914 +EOF
 245.915 +        ldapmodify -x $OPTS -f /tmp/dom.ldif
 245.916 +    fi
 245.917 +}
 245.918 +
 245.919 +function conf_populate {
 245.920 +    eco y "popolo ldap con i gruppi predefiniti Windows"
 245.921 +    S_UID=$(getent passwd | \
 245.922 +        awk -F":" -v umin=$U_MIN -v umax=$U_MAX \
 245.923 +            '$3 >= umin && $3 <= umax {print $3}'| \
 245.924 +        sort -nr | head -n 1)
 245.925 +    S_GID=$(getent group | \
 245.926 +        awk -F':' -v gmin=$G_MIN -v gmax=$G_MAX \
 245.927 +            '$3 >= gmin && $3 <= gmax {print $3}' | \
 245.928 +        sort -nr | head -n 1)
 245.929 +
 245.930 +    [ -z "$S_UID" ] && S_UID=$U_MIN
 245.931 +    [ -z "$S_GID" ] && S_GID=$G_MIN
 245.932 +    
 245.933 +    [ "$S_UID" -lt "$U_MIN" ] && S_UID=$U_MIN
 245.934 +    [ "$S_GID" -lt "$G_MIN" ] && S_GID=$G_MIN
 245.935 +
 245.936 +    [ "$S_UID" -gt "$U_MIN" ] && S_UID=`expr $S_UID + 1`
 245.937 +    [ "$S_GID" -gt "$G_MIN" ] && S_GID=`expr $S_GID + 1`
 245.938 +
 245.939 +    if [ "$DOMAIN_ADMIN" = "root" ] ; then
 245.940 +        POPOPZ="-u $S_UID -g $S_GID"
 245.941 +    else
 245.942 +        A_UID=$S_UID
 245.943 +        S_UID=`expr $S_UID + 1`
 245.944 +        POPOPZ="-u $S_UID -g $S_GID -a $DOMAIN_ADMIN -k $A_UID -m 512"
 245.945 +    fi
 245.946 +    PWD2="$LDAP_PWD\n$LDAP_PWD\n"
 245.947 +    
 245.948 +    if [ "$QUIET" = 1 ] ; then
 245.949 +        echo -e $PWD2 | smbldap-populate $POPOPZ > /dev/null
 245.950 +    else
 245.951 +        echo -e $PWD2 | smbldap-populate $POPOPZ
 245.952 +    fi  
 245.953 +    ### controllo allineamento uid/gid 
 245.954 +#    isi-tools -N $DOMAIN_NAME > /dev/null
 245.955 +}
 245.956 +function grant_permission_to_domain_admin () {
 245.957 +    eco y "assegno i privilegi amministrativi a Domain Admins e $DOMAIN_ADMIN"
 245.958 +    ### ATTENZIONE: anche senza questo il join e' impossibile!
 245.959 +    ### smbldap-populate aggiunge Adminstrator con loginShell=/bin/false
 245.960 +    ### questo impedisce il join: xp risponde "Utente non trovato"
 245.961 +
 245.962 +#    isi-changeattr -u $DOMAIN_ADMIN loginShell "/bin/bash"
 245.963 +#    ADMIN_HOME=$(isi-getattr Administrator homeDirectory)
 245.964 +#    [ -d $ADMIN_HOME ] || mkdir -p $ADMIN_HOME
 245.965 +
 245.966 +    ### sembra necessaria anche la ripetizione su Administrator
 245.967 +    
 245.968 +    UP="$DOMAIN_ADMIN%$LDAP_PWD"
 245.969 +    P1=SeMachineAccountPrivilege
 245.970 +    P2=SeTakeOwnershipPrivilege
 245.971 +    P3=SeBackupPrivilege
 245.972 +    P4=SeRestorePrivilege
 245.973 +    P5=SeRemoteShutdownPrivilege
 245.974 +    P6=SePrintOperatorPrivilege
 245.975 +    P7=SeAddUsersPrivilege
 245.976 +    P8=SeDiskOperatorPrivilege
 245.977 +    
 245.978 +    net -U $UP rpc rights grant "Domain Admins" $P1 $P2 $P3 $P4 $P5 $P6 $P7 $P8 
 245.979 +#    net -U $UP rpc rights grant $DOMAIN_ADMIN $P1 $P2 $P3 $P4 $P5 $P6 $P7 $P8 
 245.980 +
 245.981 +    if [ "$ADMIN_IS_NORMAL_USER" = 1 ] ; then 
 245.982 +        eco g "rendo $DOMAIN_ADMIN un utente normale"
 245.983 +        isi-changeattr -u $DOMAIN_ADMIN loginShell "/bin/bash"
 245.984 +        ADMIN_HOME=$UTENTI_IN/admins/$DOMAIN_ADMIN
 245.985 +        [ -d "$ADMIN_HOME" ] || mkdir -p $ADMIN_HOME
 245.986 +        isi-changeattr -u $DOMAIN_ADMIN homeDirectory "$ADMIN_HOME"
 245.987 +        cp -a /etc/skel/* $ADMIN_HOME
 245.988 +        [ -d "$ADMIN_HOME/.profili" ] || mkdir $ADMIN_HOME/.profili
 245.989 +        isi-adduser $DOMAIN_ADMIN admins
 245.990 +        chown -R $DOMAIN_ADMIN $ADMIN_HOME
 245.991 +    fi    
 245.992 +}
 245.993 +
 245.994 +function crea_smbldap_conf_file(){
 245.995 +cat <<CONF1 > /etc/smbldap-tools/smbldap.conf
 245.996 +SID="$SID"
 245.997 +slaveLDAP="$SERVER_LDAP"
 245.998 +slavePort="389"
 245.999 +masterLDAP="$SERVER_LDAP"
245.1000 +masterPort="389"
245.1001 +ldapTLS="0"
245.1002 +suffix="$BASE_DN"
245.1003 +usersdn="ou=People,$BASE_DN"
245.1004 +computersdn="ou=Computers,$BASE_DN"
245.1005 +groupsdn="ou=Groups,$BASE_DN"
245.1006 +idmapdn="ou=Idmap,$BASE_DN"
245.1007 +sambaUnixIdPooldn="sambaDomainName=$DOMAIN_NAME,$BASE_DN"
245.1008 +scope="sub"
245.1009 +hash_encrypt="SSHA"
245.1010 +crypt_salt_format="%s"
245.1011 +userLoginShell="/bin/bash"
245.1012 +userHome="/home/%U"
245.1013 +userGecos="System User"
245.1014 +defaultUserGid="513"
245.1015 +defaultComputerGid="515"
245.1016 +skeletonDir="/etc/skel"
245.1017 +defaultMaxPasswordAge="99"
245.1018 +userSmbHome=""
245.1019 +userProfile=""
245.1020 +userHomeDrive=""
245.1021 +mailDomain="$DNS_DOMAIN
245.1022 +with_smbpasswd="0"
245.1023 +smbpasswd="/usr/bin/smbpasswd"
245.1024 +defaultComputerGid0="515"
245.1025 +CONF1
245.1026 +
245.1027 +cat <<CONF2 > /etc/smbldap-tools/smbldap_bind.conf
245.1028 +slaveDN="$ROOT_BIND_DN"
245.1029 +slavePw="$LDAP_PWD"
245.1030 +masterDN="$ROOT_BIND_DN"
245.1031 +masterPw="$LDAP_PWD"
245.1032 +CONF2
245.1033 +}
245.1034 +
245.1035 +function reset_samba_secretdb (){
245.1036 +    eco y "riscrivo /var/lib/samba/secret.tdb"
245.1037 +    [ -f /var/lib/samba/secret.tdb ] && rm /var/lib/samba/secret.tdb
245.1038 +    [ "$QUIET" = 0 ] && smbpasswd -w $LDAP_PWD
245.1039 +    [ "$QUIET" = 1 ] && smbpasswd -w $LDAP_PWD > /dev/null
245.1040 +}
245.1041 +
245.1042 +function crea_gruppi_isi (){
245.1043 +    GRUPPI=$(echo "$MAINGRPS,$CLASSI,$CORSI,nowww" | sed 's/,/ /g')
245.1044 +    eco y "crea gruppi principali isi $GRUPPI"
245.1045 +    isi-addgroup --quiet $GRUPPI
245.1046 +    isi-addgroup --system --quiet plugdev audio
245.1047 +}
245.1048 +
245.1049 +
245.1050 +function check_acl_quota () {
245.1051 +
245.1052 +    [ "$ACL_IN_FSTAB" = 0 -a "$QUOTA_IN_FSTAB" = 0 ] && return
245.1053 +
245.1054 +    home=$(grep -w "/home" /etc/fstab)
245.1055 +    
245.1056 +    if [ -z "$home" ] ; then
245.1057 +        home=$(grep -w "/" /etc/fstab)
245.1058 +    fi
245.1059 +
245.1060 +    dv=$(echo $home| awk '{print $1}')
245.1061 +    mp=$(echo $home| awk '{print $2}')
245.1062 +    fs=$(echo $home| awk '{print $3}')
245.1063 +    op=$(echo $home| awk '{print $4}')
245.1064 +    z1=$(echo $home| awk '{print $5}')
245.1065 +    z2=$(echo $home| awk '{print $6}')
245.1066 +    
245.1067 +    if [ "$fs" != "xfs" ] ; then
245.1068 +        if [ "$ACL_IN_FSTAB" = 1 ] ; then 
245.1069 +            if ! echo $op | grep -q acl ; then op="$op,acl" ; fi
245.1070 +        fi    
245.1071 +    fi
245.1072 +    if [ "$QUOTA_IN_FSTAB" = 1 ] ; then     
245.1073 +        if  ! echo $op | grep -q usrquota ; then op="$op,usrquota" ; fi
245.1074 +        if  ! echo $op | grep -q grpquota ; then op="$op,grpquota" ; fi
245.1075 +    fi
245.1076 +    
245.1077 +    home2="$dv $mp $fs $op $z1 $z2"
245.1078 +    sed -i "s%^.*$home%$home2%" /etc/fstab
245.1079 +    
245.1080 +    if ! grep -q "$home2" /etc/fstab ; then
245.1081 +        eco r "problemi acl/quota in /etc/fstab - correggere manualmente"
245.1082 +    else
245.1083 +        if [ "$REMOUNT_HOME" = 1 ] ; then 
245.1084 +            eco v "check acl/quota ok - remount $mp"
245.1085 +            if ! mount $mp -o remount ; then
245.1086 +                eco r "ERRORE: remount $mp fallito"
245.1087 +            else
245.1088 +                #TODO: attivazione quota
245.1089 +                if grep -q usrquota /etc/fstab ; then 
245.1090 +            [ "$QUIET" = 0 ] && /etc/init.d/quota restart
245.1091 +            [ "$QUIET" = 1 ] && /etc/init.d/quota restart > /dev/null
245.1092 +                    RETVAL=$?
245.1093 +                    if [ "$RETVAL" != "0" ] ; then
245.1094 +                        eco r "ATTENZIONE: problemi con la quota (retval = $RETVAL)"
245.1095 +                    fi
245.1096 +                fi
245.1097 +            fi
245.1098 +        fi   
245.1099 +    fi
245.1100 +}
245.1101 +
245.1102 +function slap_index () {
245.1103 +    eco y "rigenero gli indici ldap"
245.1104 +    slapindex 2>/dev/null   # la redirezione elimina un warning
245.1105 +    chown openldap.openldap /var/lib/ldap/*
245.1106 +}
245.1107 +function fine(){
245.1108 +    [ "$QUIET" = 1 ] && return
245.1109 +    echo -e $YELLOW
245.1110 +    cat <<FINE
245.1111 +$BORDO
245.1112 +L'installazione del software ReteISI è terminata. Dati installazione:
245.1113 +DOMINIO............= $DOMAIN_NAME
245.1114 +NOME PDC...........= $PDC_NAME
245.1115 +PWD ADMIN LDAP.....= $LDAP_PWD
245.1116 +ORGANIZZAZIONE.....= $ORG_NAME
245.1117 +DOMINIO DNS........= $DNS_DOMAIN
245.1118 +SID................= $SID  
245.1119 +SID_PDC............: $SID_PDC 
245.1120 +$BORDO
245.1121 +Puoi cambiare dominio ldap/samba con il comando:
245.1122 +        isi-domain DOMINIO PDC PASSWORD
245.1123 +$BORDO
245.1124 +FINE
245.1125 +    echo -e $NOR
245.1126 +}
245.1127 +function slapd_reconfigure (){
245.1128 +    if grep -q $BASE_DN /etc/ldap/slapd.conf ; then
245.1129 +        return 
245.1130 +    fi
245.1131 +    eco y "riconfigurazione slapd"
245.1132 +    APT_UPD=1 
245.1133 +    prep_debconf
245.1134 +    [ "$QUIET" = 0 ] && dpkg-reconfigure slapd
245.1135 +    [ "$QUIET" = 1 ] && dpkg-reconfigure slapd > /dev/null
245.1136 +}
245.1137 +function change_hostname (){
245.1138 +    OLD_HOSTNAME=$(hostname)
245.1139 +    ### squid
245.1140 +    FILE=/etc/squid.conf
245.1141 +    if [ -e "$FILE" ] ; then
245.1142 +        cp $FILE $FILE.2
245.1143 +        sed "s/^visible_hostname.*$/visible_hostname $PDC_NAME/" \
245.1144 +            < $FILE.2 > $FILE
245.1145 +        rm $FILE.2
245.1146 +    fi
245.1147 +    FILE=/etc/squid/squid.conf
245.1148 +    if [ -e "$FILE" ] ; then
245.1149 +        cp $FILE $FILE.2
245.1150 +        sed "s/^visible_hostname.*$/visible_hostname $PDC_NAME/" \
245.1151 +            < $FILE.2 > $FILE
245.1152 +        rm $FILE.2
245.1153 +    fi
245.1154 +    ### postfix
245.1155 +    [ -x /usr/sbin/postconf ] && postconf -e "myhostname = $PDC_NAME"
245.1156 +    ### /etc/hostname
245.1157 +    echo $PDC_NAME > /etc/hostname
245.1158 +    /etc/init.d/hostname.sh start > /dev/null
245.1159 +    ### /etc/mailname
245.1160 +    echo $PDC_NAME > /etc/mailname
245.1161 +    ### /etc/hosts
245.1162 +    FILE=/etc/hosts
245.1163 +    cp $FILE $FILE.2
245.1164 +    sed -i "s%argo-cd.argo.it%$PDC_NAME%" $FILE
245.1165 +    rm $FILE.2
245.1166 +    hostname $PDC_NAME    
245.1167 +}
245.1168 +
245.1169 +function set_nscd_conf_file(){
245.1170 +    eco y "setting conf /etc/nscd.conf"
245.1171 +    if [ -f /etc/nscd.conf ] ; then
245.1172 +        ### conf of        CONF_FILE="/etc/nscd.conf"
245.1173 +    perl -i -p -e '{$_ =~ s/(persistent\s+(group|passwd|hosts|services).*)yes/$1no/;}' /etc/nscd.conf
245.1174 +    fi
245.1175 +}
245.1176 +###------------main()
245.1177 +function main(){
245.1178 +    /etc/init.d/nscd stop > /dev/null
245.1179 +    read_defaults           #legge i defaults (esce se SOLO_DUMP_CONF=1)
245.1180 +    prep_debconf            # prepara risposte debconf
245.1181 +    checkapt                # controlla  le fonti apt
245.1182 +    check_packages          # controlla i pacchetti
245.1183 +    stop_services
245.1184 +    slapd_reconfigure       # eventuale riconfigurazione di slapd
245.1185 +    stop_services           # stop slapd e samba
245.1186 +    isi_default_stru        # crea le cartelle ISI e i file di conf
245.1187 +    check_secrets           # check /etc/*.secret
245.1188 +    check_nsswitch          # configura nsswitch per ldap
245.1189 +    check_pam               # configura pam per ldap
245.1190 +    setting_ldap            # slapd e connessi (conf.preliminare)
245.1191 +    crea_smbldap_conf_file  # conf samba tools
245.1192 +    crea_smb_conf
245.1193 +    change_hostname
245.1194 +    slap_add_samba_schema
245.1195 +    start_services
245.1196 +    conf_populate           # popola l'albero ldap
245.1197 +    reset_samba_secretdb    # smbpasswd -w
245.1198 +    fix_ldap_sambaAlgorithmicRidBase
245.1199 +    setting_sid             # net set domain/local sids
245.1200 +    stop_services           # stop slapd e samba
245.1201 +    slap_add_indexes        # aggiunge indici sul SID ecc.ecc.    
245.1202 +    slap_index              # rigenera gli indici ldap
245.1203 +    set_nscd_conf_file      # Setta persistent a NO
245.1204 +    check_acl_quota         # controlla /etc/fstab per acl e quota su /home
245.1205 +    start_services          # start slapd/samba
245.1206 +    crea_gruppi_isi         # crea i gruppi main, classi e corsi
245.1207 +    add_env_folder          # creo le cartelle /home/samba/netlogon/env*
245.1208 +    grant_permission_to_domain_admin
245.1209 +    stop_services           # stop slapd e samba
245.1210 +    start_services          # start slapd/samba
245.1211 +    /etc/init.d/nscd start >/dev/null
245.1212 +    fine
245.1213 +}
245.1214 +function help (){
245.1215 +cat <<EOF
245.1216 +$BORDO
245.1217 +ISI-SETUP installa ed esegue la configurazione di base di un PDC ldap/samba 
245.1218 +configurato secondo il modello ISI (http://www.reteisi.org).
245.1219 +
245.1220 +USO: isi-setup [opzioni] [dominio_win] [pdc] [password] [org] [dns_base_ldap]
245.1221 +
245.1222 +OPZIONI:    -h  questo help
245.1223 +            -v  verbose - aumenta il numero di messaggi a video
245.1224 +            -s  script_mode - non chiede conferma prima di continuare
245.1225 +            -d  salva la configurazione in /etc/isi/isi-setup.conf
245.1226 +            -D  salva come sopra ed ESCE
245.1227 +            -c  utlizza /etc/isi/isi-setup.conf come file di conf.
245.1228 +            -q  solo messaggi di errore
245.1229 +            -S  NON esegue il setup standard, non tocca la conf che trova
245.1230 +            -U  NON esegue aggiornamento variabili debconf e pacchetti
245.1231 +            -A  NON controlla /etc/fstab per le acl
245.1232 +            -T  NON controlla /etc/fstab per la quota
245.1233 +            -R  NON esegue il remount di /home (inutile se espresse -AT)
245.1234 +            -a  NON rende l'amministratore di dominio un utente ordinario (nessuna shell, nessuna home) 
245.1235 +
245.1236 +* DEFAULTS:   org = ISI_ORG, dns_base_ldap = isi.lan
245.1237 +* Ad eventuali domande rispondere premendo ENTER
245.1238 +* ISI-SETUP ridirige errori e warning su STDERR
245.1239 +* Soppressione e logging dei messaggi si ottengono ridirigendo l'output.
245.1240 +$BORDO                
245.1241 +EOF
245.1242 +}
245.1243 +### ----------------- inizio -----------------------
245.1244 +# dominio di default
245.1245 +DOMAIN_NAME='ISI-DOMAIN'
245.1246 +PDC_NAME='ISI-PDC'
245.1247 +LDAP_PWD='reteisi'   
245.1248 +ORG_NAME='ISI-ORG'
245.1249 +DNS_DOMAIN='isi.lan'
245.1250 +#SID="S-1-5-21-2385007630-1092215365-3723864586"
245.1251 +#SID_PDC="S-1-5-21-2385007630-1092215365-3723864586"
245.1252 +DOMAIN_ADMIN="administrator"
245.1253 +ERR_PKG=""
245.1254 +QUIET=0
245.1255 +SETUP_LOG=""
245.1256 +VERBOSE=0
245.1257 +APT_UPD=1
245.1258 +DUMP_CONF=0
245.1259 +USE_CONF=0
245.1260 +STANDARD_SETUP=1
245.1261 +ACL_IN_FSTAB=1
245.1262 +QUOTA_IN_FSTAB=1
245.1263 +REMOUNT_HOME=1
245.1264 +SOLO_DUMP_CONF=0
245.1265 +#USO_PDBEDIT=0
245.1266 +ADMIN_IS_NORMAL_USER=1
245.1267 +IS_UBUNTU=0
245.1268 +[ "$(lsb_release -is)" == "Ubuntu" ] && IS_UBUNTU=1
245.1269 +
245.1270 +BORDO='=========================================================================='
245.1271 +while getopts hvqsdDcsqlUATRa: var 
245.1272 +do
245.1273 +case $var in
245.1274 +    h) help; exit
245.1275 +    ;;
245.1276 +    #FIXME: quiet
245.1277 +    q)  QUIET=1
245.1278 +        VERBOSE=0
245.1279 +    ;;
245.1280 +    v)  VERBOSE=1
245.1281 +    ;;
245.1282 +    s)  SCRIPT_MODE=1
245.1283 +    ;;
245.1284 +    d)  DUMP_CONF=1
245.1285 +    ;;
245.1286 +    D)  SOLO_DUMP_CONF=1
245.1287 +        DUMP_CONF=1
245.1288 +    ;;
245.1289 +    c)  USE_CONF=1
245.1290 +    ;;
245.1291 +    S)  STANDARD_SETUP=0
245.1292 +    ;;
245.1293 +    U)  APT_UPD=0
245.1294 +    ;;
245.1295 +    A)  ACL_IN_FSTAB=0
245.1296 +    ;;
245.1297 +    T)  QUOTA_IN_FSTAB=0
245.1298 +    ;;
245.1299 +    R)  REMOUNT_HOME=1
245.1300 +    ;;
245.1301 +#    j)  USO_PDBEDIT=1
245.1302 +#    ;;
245.1303 +    a)  DOMAIN_ADMIN=$OPTARG
245.1304 +        ADMIN_IS_NORMAL_USER=0
245.1305 +    ;;
245.1306 +esac
245.1307 +done
245.1308 +shift ` expr $OPTIND - 1 `
245.1309 +
245.1310 +#clear screen
245.1311 +
245.1312 +[ -z $1 ] || DOMAIN_NAME=$1
245.1313 +[ -z $2 ] || PDC_NAME=$2
245.1314 +[ -z $3 ] || LDAP_PWD=$3
245.1315 +[ -z $4 ] || ORG_NAME=$4
245.1316 +[ -z $5 ] || DNS_DOMAIN=$5
245.1317 +
245.1318 +check_hg_etc            # controlla che /etc sia sotto mercurial
245.1319 +new_sid                 # genera nuovi SIDs
245.1320 +
245.1321 +if [ "$QUIET" = 1 -a "$SCRIPT_MODE" = 0 ] ; then
245.1322 +    cat <<EOF
245.1323 +$BORDO    
245.1324 +Definisco il dominio Samba/Ldap:
245.1325 +DOMINIO....................: $DOMAIN_NAME
245.1326 +NOME PDC...................: $PDC_NAME
245.1327 +DOMAIN_ADMINISTRATOR.......: $DOMAIN_ADMIN
245.1328 +PWD ADMIN LDAP.............: $LDAP_PWD
245.1329 +ORGANIZZAZIONE.............: $ORG_NAME
245.1330 +DOMINIO DNS................: $DNS_DOMAIN
245.1331 +SID........................: $SID
245.1332 +SID_PDC....................: $SID_PDC    
245.1333 +$BORDO
245.1334 +eseguo con le seguenti opzioni: 
245.1335 +QUIET..................(-q): $QUIET
245.1336 +VERBOSE................(-v): $VERBOSE
245.1337 +DUMP_CONF..............(-d): $DUMP_CONF
245.1338 +SOLO_DUMP_CONF.........(-D): $SOLO_DUMP_CONF
245.1339 +USE_CONF...............(-c): $USE_CONF
245.1340 +APT_UPD................(-U): $APT_UPD
245.1341 +STANDARD_SETUP.........(-S): $STANDARD_SETUP    
245.1342 +ACL_IN_FSTAB...........(-A): $ACL_IN_FSTAB    
245.1343 +QUOTA_IN_FSTAB.........(-Q): $QUOTA_IN_FSTAB    
245.1344 +REMOUNT_HOME...........(-R): $REMOUNT_HOME    
245.1345 +ADMIN_IS_NORMAL_USER...(-a): $ADMIN_IS_NORMAL_USER ($DOMAIN_ADMIN)
245.1346 +$BORDO
245.1347 +EOF
245.1348 +    read -p "Continuo N/s ? " RISP 
245.1349 +    N=$(expr match "$RISP" '[yYsS]')
245.1350 +    [ "$N" -gt 0 ] && main
245.1351 +else
245.1352 +    main
245.1353 +fi    
245.1354 +
245.1355 +
245.1356 +
245.1357 +
245.1358 +
245.1359 +
   246.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   246.2 +++ b/usr/sbin/isi-slapd-reload	Mon Apr 26 11:16:23 2010 +0200
   246.3 @@ -0,0 +1,129 @@
   246.4 +#!/bin/bash
   246.5 +
   246.6 +# Copyright (C) 2008, Sandro Dentella <[email protected]>
   246.7 +#
   246.8 +#  This program is free software: you can redistribute it and/or modify
   246.9 +#  it under the terms of the GNU General Public License as published by
  246.10 +#  the Free Software Foundation, either version 3 of the License, or
  246.11 +#  (at your option) any later version.
  246.12 +#
  246.13 +#  This program is distributed in the hope that it will be useful,
  246.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  246.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  246.16 +#  GNU General Public License for more details.
  246.17 +#
  246.18 +#  You should have received a copy of the GNU General Public License
  246.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  246.20 +
  246.21 +
  246.22 +function mk_temp_conf () {
  246.23 +    TMP_DIR=$(mktemp -dt ldap.XXXXXX )
  246.24 +    perl -s -pe '{$_ =~ s!^\s*(directory\s).*!\1"$TMP_DIR/ldap"! ;}' -- \
  246.25 +    -TMP_DIR=$TMP_DIR /etc/ldap/slapd.conf > $TMP_DIR/slapd.conf
  246.26 +    mkdir $TMP_DIR/ldap
  246.27 +    echo using $TMP_DIR/ldap
  246.28 +    cp /var/lib/ldap/DB_CONFIG $TMP_DIR/ldap
  246.29 +}
  246.30 +
  246.31 +function slap_add () {
  246.32 +    if [ -z "$LDIF_FILE" ] ; then
  246.33 +        LDIF_FILE=$TMP_DIR/slapcat.ldif
  246.34 +        slapcat > $LDIF_FILE
  246.35 +    fi
  246.36 +    slapadd $VERBOSE -f $TMP_DIR/slapd.conf -l $LDIF_FILE
  246.37 +    if grep -q openldap /etc/passwd ; then
  246.38 +        chown -R openldap.openldap $TMP_DIR/ldap
  246.39 +    fi
  246.40 +}
  246.41 +function check_root () {
  246.42 +    if [ $(id -u) -gt 0 ]  ; then
  246.43 +        echo you must be root
  246.44 +        exit 1
  246.45 +    fi
  246.46 +}
  246.47 +function backup_var_lib_ldap () {
  246.48 +    if [ -d /var/lib/ldap ] ; then
  246.49 +        BK_FILE=$TMP_DIR/ldapbak-$(date '+%y%m%d').tgz
  246.50 +        tar -czf $BK_FILE -C /var/lib/ ldap
  246.51 +        mv --backup=numbered $BK_FILE /root
  246.52 +    fi
  246.53 +}
  246.54 +
  246.55 +function stop_for_sure_or_exit () {
  246.56 +    ## prima usiamo le buone maniere 
  246.57 +    
  246.58 +    /etc/init.d/slapd stop
  246.59 +    if pgrep -x slapd ; then 
  246.60 +        ## poi pero'  ci arrabbiamo...
  246.61 +        my_echo "provo ad uccidere slapd con -9"
  246.62 +        skill -9 slapd
  246.63 +        if pgrep -x slapd; then
  246.64 +            echo "slapd non muore neanche con kill -9;  esco"
  246.65 +            exit 1
  246.66 +        fi
  246.67 +    fi
  246.68 +}
  246.69 +function mv_start () {
  246.70 +    if [ -e /var/lib/ldap ] ; then
  246.71 +        mv /var/lib/ldap $TMP_DIR/ldap_bk
  246.72 +    fi
  246.73 +    mv $TMP_DIR/ldap /var/lib/ldap
  246.74 +    /etc/init.d/slapd start
  246.75 +    if ! pgrep slapd ; then
  246.76 +        echo "slapd non parte..."
  246.77 +    fi
  246.78 +    
  246.79 +}
  246.80 +function my_echo() {
  246.81 +    if [ ! "QUIET" = 1 ] ; then
  246.82 +        echo $*
  246.83 +    fi
  246.84 +}
  246.85 +function help () {
  246.86 +cat << FINE
  246.87 +Comando:     `basename $0`
  246.88 +
  246.89 +Sintassi:    `basename $0` [ -h ]
  246.90 +
  246.91 +Descrizione:    Ricrea uno slapd a partire da slapcat della configurazione in 
  246.92 +                atto o di una passata in argomento
  246.93 +
  246.94 +Opzioni:    -h  help (Questa pagina di manuale)
  246.95 +            -l  ldif_file usa 'ldif_file' come contenuto del db ldap
  246.96 +            -R  make it the Real slapd  process
  246.97 +                spegni slapd, sposta la cartella e riparti
  246.98 +  
  246.99 +FINE
 246.100 +}
 246.101 +
 246.102 +
 246.103 +while getopts vRqhl: var
 246.104 +do
 246.105 +  case $var in
 246.106 +      h) clear; help; exit
 246.107 +      ;;
 246.108 +      l) LDIF_FILE=$OPTARG
 246.109 +      ;;
 246.110 +      R) REAL=1
 246.111 +      ;;
 246.112 +      q) QUIET=1
 246.113 +      ;;
 246.114 +      v) VERBOSE="-v"
 246.115 +      ;;
 246.116 +  esac
 246.117 +done
 246.118 +shift ` expr $OPTIND - 1 `
 246.119 +
 246.120 +
 246.121 +check_root
 246.122 +mk_temp_conf
 246.123 +slap_add
 246.124 +
 246.125 +if [ "$REAL" = 1 ] ; then
 246.126 +    stop_for_sure_or_exit
 246.127 +    backup_var_lib_ldap
 246.128 +    mv_start
 246.129 +else
 246.130 +  my_echo "il processo slapd non e' stato toccato perche' non hai usato opt -R"
 246.131 +  echo "Dati in $TMP_DIR/ldap"
 246.132 +fi
   247.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   247.2 +++ b/usr/sbin/isi-tools	Mon Apr 26 11:16:23 2010 +0200
   247.3 @@ -0,0 +1,435 @@
   247.4 +#!/usr/bin/python
   247.5 +# -*- coding: utf-8 -*-
   247.6 +
   247.7 +# This program is free software; you can redistribute it and/or modify
   247.8 +# it under the terms of the GNU General Public License as published by
   247.9 +# the Free Software Foundation; either version 2, or (at your option)
  247.10 +# any later version.
  247.11 +
  247.12 +# AUTHORS: Sandro Dentella - Massimo Mancini
  247.13 +
  247.14 +
  247.15 +"""
  247.16 +ISI-INFO effettua una serie di controlli e restituisce elenchi di utenti
  247.17 +  usage: %prog [options] [users_file_name|group_name|domain]
  247.18 +    -c, --classes: lista la composizione delle classi contenute nel file utenti passato
  247.19 +    -f, --field-ldap=field_ldap: lista la valorizzazione del campo ldap per gli utenti del gruppo indicato
  247.20 +    -p, --pwd-changed: restituisce gli utenti che hanno cambiato la password rispetto a quella definita nel file utenti
  247.21 +    -P, --pwd-nochanged: restituisce gli utenti che NON hanno cambiato la password rispetto a quella definita nel file utenti
  247.22 +    -B, --pwd-mustchange: costringe al rinnovo password tutti i membri di un gruppo
  247.23 +    -b, --pwd-mustchange-days=pwd_mustchange_days: fissa la data di scadenza password per i membri del gruppo a oggi + i giorni indicati
  247.24 +    -W, --pwd-when: mostra le date di last set e scadenza delle password
  247.25 +    -A, --pwd-canchange-days=pwd_canchange_days: fissa la data a partire dalla quale gli utenti del gruppo possono modificare la password, per impedire il cambio data indicare un numero positivo di giorni
  247.26 +    -n, --numbers-get: mostra i successivi uidNumber e gidNumber per il dominio samba indicato
  247.27 +    -N, --numbers-set: come -n ma corregge l'errore trovato
  247.28 +    -r, --rename-user=rename_user: formato vecchio_logname,nuovo_logname,[cf] (separatore virgola)
  247.29 +    -R, --rename-user-file=rename_user_file: cambia i logname contenuti nel file, formato come sopra
  247.30 +    -X, --force: non interrompe l'azione in caso di errore (in abbinamento con -R)
  247.31 +    -o, --output=out_file: scrive il risultato in un file
  247.32 +    -v, --verbose: aumenta i messaggi a video
  247.33 +    -j, --adjust: rimemorizza cn,sn,givenName,gecos,displayName per ogni utente nel file
  247.34 +
  247.35 +NOTA:   le opzioni -c -p -n|N  non sono cumulabili\n l'opzione -o funziona solo con -c -f -p
  247.36 +"""
  247.37 +
  247.38 +import isi
  247.39 +import sys, os
  247.40 +import re
  247.41 +import pexpect
  247.42 +from dry import optionparse
  247.43 +from dry.functions import execute, ExecuteError
  247.44 +from isi.filesystem import show_file
  247.45 +#from isi.srv import get_main_groups, interactive_add_classes, \
  247.46 +#     get_classes, get_courses,  new_passwd, maingroup_byprefix, \
  247.47 +#     MultipleErrors, WrongLineFormat,  WrongOperation
  247.48 +from isi.conf.defaults import *
  247.49 +from isi.srv import MissingMatch
  247.50 +from time import mktime, localtime
  247.51 +
  247.52 +class IsiTool(object):
  247.53 +    def __init__(self, users_file=None, campo_ldap=None, 
  247.54 +                gruppo=None, domain=None,  out_file=None,
  247.55 +                pwd_canchange_days=-7, pwd_mustchange_days=0,
  247.56 +                verbose=False):
  247.57 +        self.users_file = users_file
  247.58 +        self.campo_ldap = campo_ldap
  247.59 +        self.gruppo = gruppo
  247.60 +        self.domain = domain
  247.61 +        self.pwd_canchange_days = pwd_canchange_days
  247.62 +        self.pwd_mustchange_days = pwd_mustchange_days
  247.63 +        self.verbose=verbose
  247.64 +        self.C = isi.IsiConn()
  247.65 +        self.U = isi.Manager(self.C)
  247.66 +        self.outf = None
  247.67 +        self.rename_user_line = None
  247.68 +        self.rename_user_file = None
  247.69 +        ret = False
  247.70 +        if out_file:
  247.71 +            ret = True
  247.72 +            if os.path.isfile(out_file):
  247.73 +                ret = raw_input("il file %s ESISTE! lo sovrascrivo (S/n)? " %
  247.74 +                                 out_file)
  247.75 +                if not ret: ret = 's'
  247.76 +                if ret in 'sS':
  247.77 +                    ret = True
  247.78 +                else:
  247.79 +                    ret = False
  247.80 +                    print "stampo su stdout...\n"
  247.81 +        if ret:
  247.82 +            self.outf = open(out_file, 'w')
  247.83 +            
  247.84 +    
  247.85 +    def show(self, msg):
  247.86 +        if self.outf:
  247.87 +            self.outf.write(msg+'\n')
  247.88 +        else:
  247.89 +            print msg
  247.90 +            
  247.91 +    def show_file(self):
  247.92 +        if self.outf: show_file(out_file)
  247.93 +
  247.94 +            
  247.95 +    def close_outf(self):
  247.96 +        if self.outf: self.outf.close()
  247.97 +    
  247.98 +    def print_classi_corsi(self, cosa, dict):
  247.99 +        nt = 0
 247.100 +        for k, v in dict.iteritems():
 247.101 +            self.show("-"*70)
 247.102 +            self.show("%s %s" % (cosa, k))
 247.103 +            self.show("-"*70)
 247.104 +            n = 0
 247.105 +            v.sort()
 247.106 +            for u in v:
 247.107 +                n += 1
 247.108 +                self.show("%s %s" % (n, u))
 247.109 +            nt += n
 247.110 +        self.show("-"*70)
 247.111 +        if cosa == 'CLASSE':
 247.112 +            self.show("trovate %s classi e %s alunni" % (len(dict), nt))
 247.113 +        else:    
 247.114 +            self.show("trovati %s corsi e %s corsisti" % (len(dict), nt))
 247.115 +        self.show("-"*70)
 247.116 +    
 247.117 +    def info_classi(self):
 247.118 +        classi = {} 
 247.119 +        corsi = {}
 247.120 +        try:
 247.121 +            uf = open(self.users_file)
 247.122 +            for line in uf:
 247.123 +                campi = line.split(';')
 247.124 +                # salta i record con meno di 5 campi (classe = campo6)
 247.125 +                if len(campi)<5 : continue
 247.126 +                mgrp = campi[3]
 247.127 +                if self.U.user_exists(campi[0]):
 247.128 +                    u = (campi[1], campi[2], campi[0], '')
 247.129 +                else:
 247.130 +                    u = (campi[1], campi[2], campi[0], 'INESISTENTE')
 247.131 +                    
 247.132 +                s = "%-15s %-15s %s %s" % u
 247.133 +
 247.134 +                if mgrp in ('alunni'):
 247.135 +                    classe = campi[4].split(',')[0]
 247.136 +                    if classi.has_key(classe):
 247.137 +                        classi[classe].append(s)
 247.138 +                    else:
 247.139 +                        classi[classe] = [s]
 247.140 +                if mgrp in ('esterni'):
 247.141 +                    corso = campi[4].split(',')[0]
 247.142 +                    if corsi.has_key(corso):
 247.143 +                        corsi[corso].append(s)
 247.144 +                    else:
 247.145 +                        corsi[corso] = [s]
 247.146 +            self.print_classi_corsi('CLASSE', classi)
 247.147 +            self.print_classi_corsi('CORSO', corsi)
 247.148 +                    
 247.149 +        except IOError, e:
 247.150 +            print e
 247.151 +            print "ERRORE: il file %s non esiste" % self.users_file
 247.152 +        
 247.153 +        self.close_outf()
 247.154 +
 247.155 +    def adjust_user(self):
 247.156 +        """ corregge cn,sn,gecos,givenNam,displayName """
 247.157 +        try:
 247.158 +            uf = open(self.users_file)
 247.159 +            rext = False
 247.160 +            for line in uf:
 247.161 +                campi = line.split(';')
 247.162 +                if len(campi)<7 : continue
 247.163 +                user = campi[0]
 247.164 +                cogn = campi[1]
 247.165 +                nome = campi[2]
 247.166 +                if len(campi)>7: # record esteso
 247.167 +                   rext = True
 247.168 +                    
 247.169 +                if self.verbose:
 247.170 +                    print "elaboro %s - %s %s " % (user, cogn, nome)
 247.171 +                gecos = cn = "%s %s" % (nome.title(), cogn.title())
 247.172 +                sn = cogn.title()
 247.173 +                givenName = nome.title()
 247.174 +                displayName = "%s %s" % (cogn.upper(), nome.title())
 247.175 +                self.U.srv.modify(user,'cn',cn)
 247.176 +                self.U.srv.modify(user,'sn',sn)
 247.177 +                self.U.srv.modify(user,'gecos',gecos)
 247.178 +                self.U.srv.modify(user,'givenName',givenName)
 247.179 +                self.U.srv.modify(user,'displayName',displayName)
 247.180 +                    
 247.181 +        except IOError, e:
 247.182 +            print e
 247.183 +            print "ERRORE: il file %s non esiste" % self.users_file
 247.184 +        
 247.185 +
 247.186 +    def info_field(self):
 247.187 +        uu = self.U.get_members(self.gruppo)
 247.188 +        if uu:
 247.189 +            self.show("-"*70)
 247.190 +            self.show("Valore del campo ldap [%s] per i membri del gruppo [%s]" % \
 247.191 +                    (self.campo_ldap, self.gruppo))
 247.192 +            self.show("-"*70)
 247.193 +            for u in uu:
 247.194 +#                d = self.U.get_attr(u, self.campo_ldap)[0]
 247.195 +                d = self.U.get_ldap_field(u, self.campo_ldap)
 247.196 +                if d:
 247.197 +                    self.show("%-14s %s = %s" % (u, self.campo_ldap, d))
 247.198 +                else:
 247.199 +                    self.show("%s %s = %s" % (u, self.campo_ldap, 'NON DEFINITO'))
 247.200 +            self.show("-"*70)
 247.201 +        else:
 247.202 +            print "GRUPPO INESISTENTE O VUOTO"
 247.203 +        self.close_outf()
 247.204 +    
 247.205 +    def info_pwds(self, pwd_changed):
 247.206 +        try:
 247.207 +            uf = open(self.users_file)
 247.208 +            for line in uf:
 247.209 +                campi = line.split(';')
 247.210 +                if len(campi)<7 : continue
 247.211 +                uid = campi[0]
 247.212 +                pwd = campi[6]
 247.213 +                if self.U.user_exists(uid):
 247.214 +                    dn = self.U.get_user_dn_by_name(uid)
 247.215 +                    cmd = "ldapsearch -xLLLD %s -w %s uid=%s %s" % \
 247.216 +                        (dn, pwd, uid, uid)
 247.217 +                    r, o, e = execute(cmd)
 247.218 +                    if pwd_changed and e:
 247.219 +                        self.show("%-15s  PWD CAMBIATA" % uid )
 247.220 +                    if not pwd_changed and not e:
 247.221 +                        self.show("%-15s  PWD NON CAMBIATA" % uid )
 247.222 +
 247.223 +                    
 247.224 +        except IOError, e:
 247.225 +            print e
 247.226 +            print "ERRORE: il file %s non esiste" % self.users_file
 247.227 +        
 247.228 +        self.close_outf()
 247.229 +
 247.230 +    def info_nums(self, okset=False):
 247.231 +        """ restituisce o setta uidNumber gidNumber """
 247.232 +        
 247.233 +        def maxnum(cmd, nmax):
 247.234 +            r, o, e = execute(cmd)
 247.235 +            ll = o.split('\n')
 247.236 +            n = 0
 247.237 +            for l in ll:
 247.238 +                u = l.split(':')
 247.239 +#                if len(u)>3 and int(u[2]) >= UID_MIN and int(u[2]) <= UID_MAX:
 247.240 +                if len(u)>3 and int(u[2]) <= nmax:
 247.241 +                    n = max(n, int(u[2]))
 247.242 +            return n
 247.243 +            
 247.244 +        nums = self.C.get_ugnums(self.domain)
 247.245 +        gidNumber = nums['gidNumber']
 247.246 +        uidNumber = nums['uidNumber']
 247.247 +        gid = maxnum("getent group" , GID_MAX)
 247.248 +        uid = maxnum("getent passwd", UID_MAX )
 247.249 +        print "-"*70
 247.250 +        print "ULTIMI NUMERI   - gidNumber:%s\tuidNumber:%s\n" % (gid, uid)
 247.251 +        print "PROSSIMI NUMERI - gidNumber:%s\tuidNumber:%s\n" % \
 247.252 +            (gidNumber,uidNumber)
 247.253 +
 247.254 +        if not okset and (gid > gidNumber-1 or uid > uidNumber-1):
 247.255 +            print "ATTENZIONE: è necessario allineare i numeri, usa l'opzione -N"
 247.256 +
 247.257 +        print "-"*70
 247.258 +
 247.259 +        if okset:
 247.260 +            gidNumber = max(gidNumber, GID_MIN)
 247.261 +            uidNumber = max(uidNumber, UID_MIN)
 247.262 +            if gid > gidNumber - 1: gidNumber = gid + 1
 247.263 +            if uid > uidNumber - 1: uidNumber = uid + 1
 247.264 +            if gidNumber <= GID_MAX and uidNumber <= UID_MAX:
 247.265 +                self.C.set_ugnums(self.domain, gidNumber=str(gidNumber))
 247.266 +                self.C.set_ugnums(self.domain, uidNumber=str(uidNumber))
 247.267 +                print "DOPO L'ALLINEAMENTO:"
 247.268 +                print "ULTIMI NUMERI   - gidNumber:%s\tuidNumber:%s\n" % (gid, uid)
 247.269 +                print "PROSSIMI NUMERI - gidNumber:%s\tuidNumber:%s\n" % \
 247.270 +                    (gidNumber,uidNumber)
 247.271 +                print "-"*70
 247.272 +            else:
 247.273 +                print "ALLINEAMENTO IMPOSSIBILE - NUMERI FUORI RANGE"
 247.274 +
 247.275 +    def pwd_must_change(self):
 247.276 +        """ forza al rinnovo password i membri di un gruppo """
 247.277 +        try:
 247.278 +            self.U.verbose = self.verbose
 247.279 +            self.U.pwd_must_change(self.gruppo, self.pwd_mustchange_days)
 247.280 +        except:
 247.281 +            print "GRUPPO INESISTENTE O VUOTO"
 247.282 +        
 247.283 +    def pwd_can_change(self):
 247.284 +        """ abilita disabilita il cambio password """
 247.285 +        try:
 247.286 +            self.U.verbose = self.verbose
 247.287 +            self.U.pwd_can_change(self.gruppo, self.pwd_canchange_days)
 247.288 +        except:
 247.289 +            print "GRUPPO INESISTENTE O VUOTO"
 247.290 +
 247.291 +    def pwd_expire(self):
 247.292 +        """ fissa la data di scadenza della password """
 247.293 +        try:
 247.294 +            self.U.verbose = self.verbose
 247.295 +            self.U.pwd_expire(self.gruppo, self.pwd_expire)
 247.296 +        except:
 247.297 +            print "GRUPPO INESISTENTE O VUOTO"
 247.298 +            
 247.299 +    def pwd_when(self):
 247.300 +        """ last set end expire dates of passwords"""
 247.301 +        try:
 247.302 +            self.U.pwd_when(self.gruppo, outf=self.outf)
 247.303 +            self.close_outf()
 247.304 +
 247.305 +        except: 
 247.306 +            raise
 247.307 +            print "GRUPPO INESISTENTE O VUOTO"      
 247.308 +      
 247.309 +    def rename_user(self):
 247.310 +        """ modifica il logname e quel che ne segue """
 247.311 +        def logch(line):
 247.312 +            ll = line.split(',')
 247.313 +            # se manca il codice fiscale... così il formato è corretto
 247.314 +            if len(ll)==2: ll.append(None)
 247.315 +            
 247.316 +            old_l, new_l, cf = ll
 247.317 +            self.U.verbose = self.verbose
 247.318 +            self.U.rename_user(old_l, new_l, cf)
 247.319 +        
 247.320 +        if self.rename_user_file:
 247.321 +            # controlla che non ci siano new_id esistenti
 247.322 +            err = False
 247.323 +            collisioni=[]
 247.324 +            fcoll = open('/tmp/collisioni', 'w')
 247.325 +            for line in open(self.rename_user_file):
 247.326 +                line = line.rstrip('\n').replace(' ', '')
 247.327 +                if not ',' in line: 
 247.328 +                    if len(line)>0:
 247.329 +                        print "ERRORE: %s" % line
 247.330 +                        fcoll.write("ERRORE: %s\n" % line)
 247.331 +                    continue
 247.332 +                u = line.split(',')
 247.333 +                if self.U.user_exists(u[1]):
 247.334 +                    print "COLLISIONE CON UTENTE ESISTENTE: %s" % u[1]
 247.335 +                    collisioni.append(u[:2])
 247.336 +                    fcoll.write("%s\n" % line)
 247.337 +                    err = True
 247.338 +            fcoll.close()
 247.339 +            if not err or opts.force:
 247.340 +                for line in open(self.rename_user_file):
 247.341 +                    line = line.rstrip('\n').replace(' ', '') 
 247.342 +                    if not ',' in line: continue
 247.343 +                    u = line.split(',')
 247.344 +                    if not u[:2] in collisioni:
 247.345 +                        try:
 247.346 +                            logch(line)
 247.347 +                        except MissingMatch, e:
 247.348 +                            print "ERRORE (MissingMatch): %s - %s " % (line,e)
 247.349 +            else:
 247.350 +                print "IMPOSSIBILE PROCEDERE: errori e/o collisioni uid vecchi/nuovi"
 247.351 +            if len(collisioni)>0:
 247.352 +                print "errori e collisioni registrati in /tmp/collisioni"
 247.353 +        elif self.rename_user_line:
 247.354 +                logch(self.rename_user_line)
 247.355 +    
 247.356 +#### PROGRAM
 247.357 +
 247.358 +# defaults
 247.359 +users_file = domain = gruppo = out_file = None
 247.360 +can_change = 1
 247.361 +
 247.362 +opts, args = optionparse.parse(__doc__)
 247.363 +
 247.364 +# -o file 
 247.365 +if opts.output: out_file = opts.output
 247.366 +
 247.367 +if opts.classes or opts.pwd_changed or opts.pwd_nochanged or opts.adjust: 
 247.368 +    if len(args)==0:
 247.369 +        print "ERRORE: devi dirmi il nome del file utenti da utilizzare"
 247.370 +    else:
 247.371 +        users_file = args[0]
 247.372 +    
 247.373 +
 247.374 +if opts.numbers_get or opts.numbers_set: 
 247.375 +    if len(args)==0:
 247.376 +        print "ERRORE: devi dirmi il nome del dominio samba"
 247.377 +    else:
 247.378 +        domain = args[0]
 247.379 +
 247.380 +if opts.field_ldap or opts.pwd_mustchange or \
 247.381 +    opts.pwd_canchange_days or opts.pwd_mustchange_days or opts.pwd_when: 
 247.382 +    if len(args)==0:
 247.383 +        print "ERRORE: devi dirmi il nome di un gruppo"
 247.384 +    else:
 247.385 +        gruppo = args[0]
 247.386 +
 247.387 +
 247.388 +tool = IsiTool(users_file=users_file, 
 247.389 +               domain=domain, 
 247.390 +               gruppo=gruppo, 
 247.391 +               campo_ldap=opts.field_ldap, 
 247.392 +               out_file=out_file, 
 247.393 +               pwd_canchange_days=opts.pwd_canchange_days, 
 247.394 +               pwd_mustchange_days=opts.pwd_mustchange_days, 
 247.395 +               verbose=opts.verbose)    
 247.396 +
 247.397 +if opts.classes:
 247.398 +    tool.info_classi() # -c 
 247.399 +
 247.400 +if opts.field_ldap and gruppo: 
 247.401 +    tool.info_field() # -f 
 247.402 +
 247.403 +if opts.pwd_changed:
 247.404 +    tool.info_pwds(True) # -p 
 247.405 +
 247.406 +if opts.pwd_nochanged:
 247.407 +    tool.info_pwds(False) # -P
 247.408 +
 247.409 +if opts.pwd_mustchange: 
 247.410 +    tool.pwd_must_change() # -B
 247.411 +    
 247.412 +if opts.pwd_mustchange_days: 
 247.413 +    tool.pwd_mustchange_days = int(opts.pwd_mustchange_days)
 247.414 +    tool.pwd_must_change() # -E expiredata
 247.415 +    
 247.416 +if opts.pwd_canchange_days: 
 247.417 +    tool.pwd_canchange_days = int(opts.pwd_canchange_days)
 247.418 +    tool.pwd_can_change() # -A 0|1
 247.419 +
 247.420 +if opts.pwd_when: 
 247.421 +    tool.pwd_when() # -W
 247.422 +   
 247.423 +if opts.numbers_get: 
 247.424 +    tool.info_nums(False) #  -n
 247.425 +    
 247.426 +if opts.numbers_set: 
 247.427 +    tool.info_nums(True)  #  -N
 247.428 +
 247.429 +if opts.rename_user or opts.rename_user_file: 
 247.430 +    tool.rename_user_line =  opts.rename_user
 247.431 +    tool.rename_user_file =  opts.rename_user_file
 247.432 +    tool.rename_user()  #  -r|-R
 247.433 +    
 247.434 +if opts.adjust: 
 247.435 +    tool.adjust_user()  #  -j
 247.436 +
 247.437 +tool.show_file()
 247.438 +
   248.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   248.2 +++ b/usr/sbin/isi-users	Mon Apr 26 11:16:23 2010 +0200
   248.3 @@ -0,0 +1,2047 @@
   248.4 +#!/usr/bin/python
   248.5 +# -*- coding: utf-8 -*-
   248.6 +
   248.7 +# This program is free software; you can redistribute it and/or modify
   248.8 +# it under the terms of the GNU General Public License as published by
   248.9 +# the Free Software Foundation; either version 2, or (at your option)
  248.10 +# any later version.
  248.11 +
  248.12 +# AUTHORS: Sandro Dentella - Massimo Mancini
  248.13 +
  248.14 +
  248.15 +import os, sys, re, random, string
  248.16 +import urwid.curses_display, urwid
  248.17 +import ldap,time
  248.18 +import isi
  248.19 +from isi.srv import new_passwd
  248.20 +from dry.functions import execute, ExecuteError
  248.21 +
  248.22 +USERS_FILE = '/root/users_last_update'
  248.23 +HOME_IN    = '/home/users'
  248.24 +PROFILO={
  248.25 +            '9x': 'Win95', 
  248.26 +            'xp': 'WinXP', 
  248.27 +            '2k': 'Win2K', 
  248.28 +         }
  248.29 +
  248.30 +CMD = "ls -l /bin/sh|awk '{print $10}'"
  248.31 +r, w, e = os.popen3(CMD)
  248.32 +ws = w.readlines()
  248.33 +es = e.readlines()
  248.34 +w.close()
  248.35 +e.close()
  248.36 +IS_DASH = (ws[0].find('dash')>= 0)
  248.37 +
  248.38 +blank = urwid.AttrWrap(urwid.Text(""),'body')
  248.39 +sep   = urwid.Divider('-')
  248.40 +
  248.41 +
  248.42 +# FILECONF file di configurazione dello script
  248.43 +FILECONF="/etc/isi/userpy.conf"
  248.44 +
  248.45 +
  248.46 +class dictNoComplain(dict):
  248.47 +    """ il dizionario che non solleva eccezioni nel 
  248.48 +    caso di chiave inesistente """
  248.49 +    valore = None
  248.50 +    def __getitem__(self,key):
  248.51 +        if not self.has_key(key) or self.get(key) == None:
  248.52 +            return ''
  248.53 +        else:
  248.54 +            return self.get(key)
  248.55 +
  248.56 +class isildap:
  248.57 +    configparm={}
  248.58 +    l       = None
  248.59 +    members = None
  248.60 +    memdata = None
  248.61 +    campildap = (
  248.62 +        'dn','cn','sn','uid','gecos','givenName',
  248.63 +        'displayName','employeeNumber','employeeType',
  248.64 +        'postOfficeBox','postalCode','homePhone',
  248.65 +        'postalAddress','departmentNumber','homeDirectory','gidNumber'
  248.66 +        )
  248.67 +
  248.68 +    datiuser  = None
  248.69 +    err = None
  248.70 +
  248.71 +    def __init__(self,gruppo=None,u='',p=''):
  248.72 +        """ crea una connessione ldap, passando u e p, vengono testate 
  248.73 +        le credenziali """       
  248.74 +
  248.75 +        self.l = isi.Manager(isi.IsiConn())
  248.76 +
  248.77 +        if gruppo:
  248.78 +#            self.l.delisildap_groupmembers 
  248.79 +            self.isildap_groupmembers(gruppo)
  248.80 +            self.isildap_loadmemdata()
  248.81 +        else:
  248.82 +            print "ERRORE: manca il gruppo"
  248.83 +            sys.exit()
  248.84 +    
  248.85 +    def isildap_groupmembers(self,group):
  248.86 +        self.members = self.l.get_members(group)
  248.87 +
  248.88 +    def isildap_userdata(self,uid):
  248.89 +        ret=dictNoComplain()
  248.90 +        result_data = self.l.get_ldap_data(uid, self.campildap)
  248.91 +        for k in result_data.keys():
  248.92 +            ret[k]=result_data[k][0]
  248.93 +        return ret
  248.94 +        
  248.95 +    def isildap_loadmemdata(self):
  248.96 +        self.memdata=dictNoComplain()
  248.97 +        print 'loading users...',
  248.98 +        for uid in self.members:
  248.99 +            self.memdata[uid]=self.isildap_userdata(uid)
 248.100 +        print   
 248.101 +        
 248.102 +    def isildap_printmemdata(self):
 248.103 +        for u,d in self.memdata.iteritems():
 248.104 +            print '\t',string.ljust(u,20)
 248.105 +            for k,v in d.iteritems():
 248.106 +                print '\t\t',string.ljust(k,20),v
 248.107 +
 248.108 +    def isildap_isuser(self,uid):
 248.109 +        return self.l.user_exists(uid)
 248.110 +        
 248.111 +
 248.112 +class orderedDict(dict):
 248.113 +    """ 
 248.114 +    dizionario ordinato: aggiunge la proprieta` self.ordKeys 
 248.115 +    che contiene la lista delle chiavi secondo l'ordine di caricamento
 248.116 +    del dizionario  
 248.117 +    il dizionario non solleva eccezioni nel caso di chiave inesistente
 248.118 +    """
 248.119 +    ordKeys = []
 248.120 +    to_order = None
 248.121 +    valore = None
 248.122 +    def __init__(self,to_order=None):
 248.123 +        self.ordKeys=[]
 248.124 +        return None
 248.125 +
 248.126 +    def __getitem__(self,key):
 248.127 +        if not self.has_key(key) or self.get(key) == None:
 248.128 +            return ''
 248.129 +        else:
 248.130 +            return self.get(key)
 248.131 +
 248.132 +    def __setitem__(self,k,v):
 248.133 +        if not self.has_key(k) or self.get(k) == None:
 248.134 +            self.ordKeys.append(k)
 248.135 +            self.setdefault(k,v)
 248.136 +            if self.to_order:
 248.137 +                self.ordKeys.sort()
 248.138 +        return None
 248.139 +    
 248.140 +class VEdit(urwid.Edit):
 248.141 +    """ Edit widget con nome e validazione """
 248.142 +    def __init__(self, 
 248.143 +                 name='', 
 248.144 +                 condition='.*',
 248.145 +                 maxlen=None,
 248.146 +                 msgerr='',
 248.147 +                 msghlp='',
 248.148 +                 caption='', 
 248.149 +                 edit_text='', 
 248.150 +                 multiline=False, 
 248.151 +                 align='left', 
 248.152 +                 wrap='space', 
 248.153 +                 allow_tab=False, 
 248.154 +                 edit_pos=None,
 248.155 +                 layout=None):
 248.156 +        
 248.157 +        urwid.Edit.__init__(self,caption,edit_text,multiline,align,wrap,
 248.158 +                            allow_tab,edit_pos,layout)
 248.159 +            
 248.160 +        self.name      = name
 248.161 +        self.rex       = re.compile(condition)
 248.162 +        self.maxlen    = maxlen
 248.163 +        self.msgerr    = msgerr
 248.164 +        self.msghlp    = msghlp
 248.165 +        #self.edit_text = edit_text
 248.166 +        #self.multiline = multiline
 248.167 +        #self.allow_tab = allow_tab
 248.168 +        self.set_caption( caption )
 248.169 +        #self.layout    = layout
 248.170 +
 248.171 +        if edit_pos is None:
 248.172 +            self.edit_pos = len(edit_text)
 248.173 +        else:
 248.174 +            self.set_edit_pos(edit_pos)
 248.175 +        
 248.176 +        self.highlight = None
 248.177 +        self.pref_col_maxcol = None, None
 248.178 +        self._shift_view_to_cursor = 0
 248.179 +
 248.180 +    def RaiseMaxLen(self):
 248.181 +        if self.maxlen:
 248.182 +            return len(self.edit_text) >= self.maxlen
 248.183 +        else:
 248.184 +            return False
 248.185 +    
 248.186 +    def validate(self):
 248.187 +        return self.rex.match(self.edit_text)
 248.188 +    
 248.189 +    def vuota(self,end=0):
 248.190 +        self.set_edit_text(self.get_edit_text()[:end])
 248.191 +        self.set_edit_pos(end) 
 248.192 +        
 248.193 +
 248.194 +class SelText(urwid.Text):
 248.195 +    
 248.196 +    def selectable(self): return True
 248.197 +
 248.198 +    def keypress(self,(maxcol,),key):
 248.199 +        """Handle editing keystrokes, return others."""
 248.200 +        #self.set_text(('focus',self.get_text()[0]))
 248.201 +        return key
 248.202 +
 248.203 +class NamedWrap(urwid.AttrWrap):
 248.204 +    name = None
 248.205 +    def __init__(self, name, w, attr, focus_attr=None):
 248.206 +        self.name = name
 248.207 +        self.w = w
 248.208 +        self.attr = attr
 248.209 +        self.focus_attr = focus_attr
 248.210 +
 248.211 +    def get_name(self):
 248.212 +        return self.name
 248.213 +
 248.214 +class SelTextWalker(urwid.SimpleListWalker):
 248.215 +           
 248.216 +    def rows(self, (maxcol,), focus=False ):
 248.217 +        """Return the number of rows required for this widget."""
 248.218 +        return len(self.contents)
 248.219 +
 248.220 +    def render(self,(maxcol,), focus=False):
 248.221 +        for t in self.contents:
 248.222 +            return t[0].render()
 248.223 +
 248.224 +class HelpColumn(urwid.BoxWidget):
 248.225 +    help_text = [
 248.226 +        [ " Chiudi Help  : ", ('key', "AltH") ],
 248.227 +        [ " Abbandona    : ", ('key', "AltX") ],
 248.228 +        "-" ,
 248.229 +        [ " Nuovo utente : ",('key', "AltN | F8")],
 248.230 +        "",
 248.231 +        [ " Canc.da lista: ",('key', "Canc (Delete)")],
 248.232 +#        [ " Canc.da ldap : ",('key', "AltCanc")],
 248.233 +        [ " Canc.da ldap : ",('key', "F9")],
 248.234 +        "",
 248.235 +        [ " Salva attuale: ",('key', "AltS")],
 248.236 +        [ " Salva ed esce: ",('key', "AltF")],
 248.237 +        "-",
 248.238 +        [ " Mov.campi    : ", ('key', "Su Giù Ds Sn PgSù PgGiù" )],
 248.239 +        [ " Mov.colonne  : " ,('key', "Sn Ds AltSn AltDs")],
 248.240 +        [ " Ok campo     : " ,('key', "Enter Tab")],
 248.241 +        [ " Canc.campo   : ",('key', "CtrlK")],
 248.242 +        [ " Annulla edit : ",('key', "ESC")],
 248.243 +        "-",
 248.244 +        [ " Rilegge LDAP : ",('key', "AltR")],
 248.245 +        [ " Ricarica GRP : ",('key', "AltG")],
 248.246 +        "-",
 248.247 +        [ " Cambia passwd: ",('key', "AltP")],
 248.248 +        [ " Cambia quota : ",('key', "AltQ")],
 248.249 +        '-',
 248.250 +        [ " Canc.prof.XP : ",('key', "AltJ")],
 248.251 +        [ " Canc.prof.2K : ",('key', "AltL")],
 248.252 +        [ " Canc.prof.9x : ",('key', "AltI")],
 248.253 +        '-',
 248.254 +        [ ('buttnf'," CODICE COLORE ")],
 248.255 +        [ ('focuserr',"   utente con dati errati")],
 248.256 +        [ ('focuscha',"   utente con dati modificati")],
 248.257 +        [ ('focusnew',"   nuovo utente")],
 248.258 +        [ ('focuspwd',"   utente con passwd modificata")],
 248.259 +        [ ('focusdel',"   utente eliminato da LDAP")],
 248.260 +        [ ('focus',   "   utente ldap senza errori")],
 248.261 +        [ ('focus',   " ? utente senza quota")],
 248.262 +        [ ('focus',   " + utente fuori quota")],
 248.263 +        '-',
 248.264 +        ["* L'aggiornamento LDAP viene eseguito solo terminando con AltF\n* La modifica delle password ordinata digitando AltP è invece immediata"],
 248.265 +        ]
 248.266 +                
 248.267 +    def __init__(self):
 248.268 +        self.head = urwid.AttrWrap(
 248.269 +            urwid.Text(["ISI-USER HELP"],'center'),'header')
 248.270 +        self.foot = urwid.AttrWrap( 
 248.271 +                urwid.Text(["continua...Sù/Giù scorre"],'center'), 'footer' )
 248.272 +        self.items = [self.rigah(x) for x in self.help_text]
 248.273 +        self.listbox = urwid.ListBox( self.items )
 248.274 +        self.body = urwid.AttrWrap( self.listbox, 'help' )
 248.275 +        self.frame = urwid.Frame( self.body, header=self.head)
 248.276 +        
 248.277 +    def rigah(self,x):
 248.278 +        align = 'left'
 248.279 +        if x == '-':
 248.280 +            return sep
 248.281 +        else:
 248.282 +            return urwid.Text(x,align)
 248.283 +    
 248.284 +    def render( self, (maxcol, maxrow), **opts ):
 248.285 +        head_rows = self.head.rows( (maxcol,) )
 248.286 +        if "bottom" in self.listbox.ends_visible( 
 248.287 +                (maxcol, maxrow-head_rows) ):
 248.288 +                self.frame.footer = None
 248.289 +        else:
 248.290 +            self.frame.footer = self.foot
 248.291 +        return self.frame.render( (maxcol, maxrow), ** opts )
 248.292 +        
 248.293 +    def keypress( self, size, key ):
 248.294 +        return self.frame.keypress( size, key )
 248.295 +
 248.296 +class AuthPassColumn(urwid.BoxWidget):
 248.297 +    help_text = [
 248.298 +        "-" ,
 248.299 +        [ " Admin password: "],
 248.300 +        "-",
 248.301 +        [ '#ATTENZIONE: la password digitata non viene visualizzata'], 
 248.302 +        ]
 248.303 +                
 248.304 +    def __init__(self):
 248.305 +        self.head = urwid.AttrWrap(
 248.306 +            urwid.Text(["ISI-USER PASSWORD"],'center'),'header')
 248.307 +        self.foot = urwid.AttrWrap( 
 248.308 +                urwid.Text(["continua...Su/Giu scorre"],'center'), 'footer' )
 248.309 +        self.items = [self.rigah(x) for x in self.help_text]
 248.310 +        self.listbox = urwid.ListBox( self.items )
 248.311 +        self.listbox.set_focus(1)
 248.312 +        self.body = urwid.AttrWrap( self.listbox, 'help' )
 248.313 +        self.frame = urwid.Frame( self.body, header=self.head)
 248.314 +        
 248.315 +    def rigah(self,x):
 248.316 +        align = 'left'
 248.317 +        x1 = string.replace(x[0],'#','')
 248.318 +        if x == '-':
 248.319 +            return sep
 248.320 +        elif x1 != x[0]:
 248.321 +            return urwid.AttrWrap(urwid.Text(x1,'left'),'help')
 248.322 +        else:
 248.323 +            return urwid.AttrWrap(urwid.Edit(('editcp',x)),'passwd')
 248.324 +    
 248.325 +    def render( self, (maxcol, maxrow), **opts ):
 248.326 +        head_rows = self.head.rows( (maxcol,) )
 248.327 +        if "bottom" in self.listbox.ends_visible( 
 248.328 +                (maxcol, maxrow-head_rows) ):
 248.329 +                self.frame.footer = None
 248.330 +        else:
 248.331 +            self.frame.footer = self.foot
 248.332 +        return self.frame.render( (maxcol, maxrow), ** opts )
 248.333 +        
 248.334 +    def keypress( self, size, key ):
 248.335 +        return self.frame.keypress( size, key )
 248.336 +
 248.337 +class ConfirmColumn(urwid.BoxWidget):
 248.338 +    help_text = [
 248.339 +                ["-" ,
 248.340 +                [ " Confermi S/N ? "],
 248.341 +                "-",
 248.342 +                [ "#ATTENZIONE: ci sono modifiche non salvate - CONFERMARE l'uscita dal programma"], 
 248.343 +                ], 
 248.344 +                ["-" ,
 248.345 +                [ " Confermi S/N ? "],
 248.346 +                "-",
 248.347 +                [ "#ATTENZIONE: stai ordinando la cancellazione di un profilo remoto WINDOWS, il desktop sarà salvato nella cartella HOME/old_desktop"], 
 248.348 +                ], 
 248.349 +        ]
 248.350 +    titolo = [
 248.351 +              "ISI-USER: USCITA", 
 248.352 +              "ISI-USER: ELIM.PROFILO", 
 248.353 +            ]
 248.354 +                
 248.355 +    def __init__(self):
 248.356 +        self.head = None
 248.357 +        self.items = None
 248.358 +        self.listbox = None
 248.359 +        self.body = None
 248.360 +        self.frame = None
 248.361 +        self.load_msg(0)
 248.362 +        self.foot = urwid.AttrWrap( 
 248.363 +                urwid.Text(["continua...Su/Giu scorre"],'center'), 'footer' )
 248.364 +        
 248.365 +
 248.366 +    def load_msg(self, n=0, s=None):
 248.367 +        if not s is None:
 248.368 +            tit = "%s [%s]" % (self.titolo[n], s)
 248.369 +        else:
 248.370 +            tit = self.titolo[n]
 248.371 +        self.head = urwid.AttrWrap(
 248.372 +            urwid.Text([tit],'center'),'header')
 248.373 +        self.items = [self.rigah(x) for x in self.help_text[n]]
 248.374 +        self.listbox = urwid.ListBox( self.items )
 248.375 +        self.listbox.set_focus(1)
 248.376 +        self.body = urwid.AttrWrap( self.listbox, 'help' )
 248.377 +        self.frame = urwid.Frame( self.body, header=self.head)
 248.378 +#        self.frame._invalidate()
 248.379 +        
 248.380 +    def vuota(self):
 248.381 +        for w in self.items:
 248.382 +            if hasattr(w,'edit_text'):
 248.383 +                w.set_edit_text('')
 248.384 +                w.set_edit_pos(0)
 248.385 +        
 248.386 +    def rigah(self,x):
 248.387 +        align = 'left'
 248.388 +        x1 = string.replace(x[0],'#','')
 248.389 +        if x == '-':
 248.390 +            return sep
 248.391 +        elif x1 != x[0]:
 248.392 +            return urwid.AttrWrap(urwid.Text(x1,'left'),'help')
 248.393 +        else:
 248.394 +            return urwid.AttrWrap(urwid.Edit(('editcp',x)),'focus')
 248.395 +    
 248.396 +    def render( self, (maxcol, maxrow), **opts ):
 248.397 +        head_rows = self.head.rows( (maxcol,) )
 248.398 +        if "bottom" in self.listbox.ends_visible( 
 248.399 +                (maxcol, maxrow-head_rows) ):
 248.400 +                self.frame.footer = None
 248.401 +        else:
 248.402 +            self.frame.footer = self.foot
 248.403 +        return self.frame.render( (maxcol, maxrow), ** opts )
 248.404 +        
 248.405 +    def keypress( self, size, key ):
 248.406 +        return self.frame.keypress( size, key )
 248.407 +
 248.408 +class authSudo:
 248.409 +    authChi = dictNoComplain()
 248.410 +    adminUsr = None
 248.411 +    adminGid = None
 248.412 +    adminGrp = None
 248.413 +    gruppo = None
 248.414 +    ru = None
 248.415 +    rg = None
 248.416 +    
 248.417 +    def __init__(self,gruppo):
 248.418 +        self.gruppo = gruppo
 248.419 +        #FILECONF="/etc/isi/userpy.conf"
 248.420 +        if os.environ.has_key('SUDO_USER'):
 248.421 +            self.adminUsr = os.environ['SUDO_USER']
 248.422 +            self.adminGid = os.environ['SUDO_GID']
 248.423 +            r,w,e = os.popen3("getent group | grep "+str(self.adminGid))
 248.424 +            self.adminGrp = '@'+string.split(w.readlines()[0],':',1)[0]
 248.425 +            x=w.readlines()
 248.426 +            w.close()
 248.427 +            e.close()
 248.428 +        else:
 248.429 +            self.adminUsr = os.environ['USER']
 248.430 +            self.adminGrp = 'root'
 248.431 +            
 248.432 +        upat = r'\b' + self.adminUsr + r'\b'
 248.433 +        gpat = self.adminGrp + r'\b'
 248.434 +        self.ru = re.compile(upat)
 248.435 +        self.rg = re.compile(gpat)
 248.436 +
 248.437 +        if os.access(FILECONF,os.R_OK):
 248.438 +            f = open(FILECONF,"r")
 248.439 +            x = f.readlines()
 248.440 +            f.close()
 248.441 +            xr = re.compile(r'^\s*(.+)\s*=\s*(.+)\s*$')
 248.442 +            xm = re.compile(r'^(\w+)@(\w*)\s*$')
 248.443 +            cr = re.compile(r'^\s*#')
 248.444 +            for l in x:
 248.445 +                if cr.match(l): continue
 248.446 +                xl = xr.match(l)
 248.447 +                if xl:
 248.448 +                    gg = xl.group(1)
 248.449 +                    uu = xl.group(2)
 248.450 +                    self.authChi[gg] = uu
 248.451 +                    xx = xm.match(gg)
 248.452 +                    if xx:
 248.453 +                        gM = xx.group(1)
 248.454 +                        gS = xx.group(2)
 248.455 +                        #print '|'+gS+'|'
 248.456 +                        if (gS):
 248.457 +                            self.authChi[gS] = uu
 248.458 +                        else:
 248.459 +                            self.authChi[gM] = uu
 248.460 +                        
 248.461 +    
 248.462 +    def main(self):
 248.463 +        
 248.464 +        if not os.access("/etc/smbldap-tools/smbldap_bind.conf",os.R_OK):
 248.465 +            print "\n============================================================="
 248.466 +            print "ERRORE: impossibile usare questa utility su questo sistema"
 248.467 +            print "        smbldap-tools non correttamente installato o"
 248.468 +            print "        permessi insufficienti - rivolgersi all'Amministratore"
 248.469 +            print "============================================================="
 248.470 +            sys.exit()
 248.471 +        elif self.adminUsr == 'root':
 248.472 +            return
 248.473 +        elif self.gruppo:
 248.474 +            #print '###',gruppo,self.authChi[gruppo]
 248.475 +            if not (self.ru.search(self.authChi[gruppo]) or \
 248.476 +                                self.rg.search(self.authChi[gruppo])):
 248.477 +                print "\n=============================================="
 248.478 +                print "ACCESSO VIETATO - gruppo richiesto: "+gruppo
 248.479 +                print "  "+self.adminUsr+self.adminGrp+" non ha i privilegi necessari"
 248.480 +                print "  rivolgersi all'Amministratore"
 248.481 +                print "=============================================="
 248.482 +                sys.exit()
 248.483 +        else:
 248.484 +            print "\n=============================================="
 248.485 +            print "ACCESSO SENZA INDICAZIONE DEL GRUPPO VIETATO:"
 248.486 +            print "  uso consentito al solo personale autorizzato"
 248.487 +            print "  rivolgersi all'Amministratore"
 248.488 +            print "=============================================="
 248.489 +            sys.exit()
 248.490 +    
 248.491 +        
 248.492 +
 248.493 +class User:
 248.494 +    """ crea un oggetto utente 
 248.495 +    le condizioni possibili sui campi sono espresse via regexp:
 248.496 +    campo obbligatorio '.+'
 248.497 +    campo facoltativo  '.*'
 248.498 +    """
 248.499 +
 248.500 +    CampiUtente = orderedDict()
 248.501 +    #defaults
 248.502 +    USERID_MINLEN = 5
 248.503 +    USERID_MAXLEN = 15
 248.504 +    USERPW_MINLEN = 8
 248.505 +    USERPW_MAXLEN = 14
 248.506 +    CLASSE_MAXLEN = 6
 248.507 +    
 248.508 +    PREFIX_ADMINS = "ad_"
 248.509 +    PREFIX_ALUNNI = "a_"
 248.510 +    PREFIX_ATA    = "t_"
 248.511 +    PREFIX_DOCENTI= "d_"
 248.512 +    PREFIX_ESTERNI= "e_"
 248.513 +    PREFIX_OSPITI = "o_"
 248.514 +
 248.515 +    # lettura parametri dal file di conf.
 248.516 +    if os.access(FILECONF,os.R_OK):
 248.517 +        f = open(FILECONF,"r")
 248.518 +        x = f.readlines()
 248.519 +        f.close()
 248.520 +        cr = re.compile(r'^\s*#')
 248.521 +        for l in x:
 248.522 +            if cr.match(l): continue
 248.523 +            ll=string.replace(l,'\n','')
 248.524 +            ll=string.replace(l,' ','')
 248.525 +            param = string.split(ll,'=')
 248.526 +            #print param
 248.527 +            if param[0] == 'USERID_MINLEN':
 248.528 +                USERID_MINLEN = int(param[1])
 248.529 +            if param[0] == 'USERID_MAXLEN':
 248.530 +                USERID_MAXLEN = int(param[1])
 248.531 +            if param[0] == 'USERPW_MINLEN':
 248.532 +                USERPW_MINLEN = int(param[1])
 248.533 +            if param[0] == 'USERPW_MAXLEN':
 248.534 +                USERPW_MAXLEN = int(param[1])
 248.535 +            if param[0] == 'CLASSE_MAXLEN':
 248.536 +                CLASSE_MAXLEN = int(param[1])
 248.537 +            if param[0] == 'PREFIX_ADMINS':
 248.538 +                PREFIX_ADMINS = param[1]
 248.539 +            if param[0] == 'PREFIX_ALUNNI':
 248.540 +                PREFIX_ALUNNI = param[1]
 248.541 +            if param[0] == 'PREFIX_ATA':
 248.542 +                PREFIX_ATA    = param[1]
 248.543 +            if param[0] == 'PREFIX_DOCENTI':
 248.544 +                PREFIX_DOCENTI= param[1]
 248.545 +            if param[0] == 'PREFIX_ESTERNI':
 248.546 +                PREFIX_ESTERNI = param[1]
 248.547 +            if param[0] == 'PREFIX_OSPITI':
 248.548 +                PREFIX_OSPITI = param[1]
 248.549 +
 248.550 +    CampiUtente['userMGrp']    = {
 248.551 +        'caption':"Gruppo princ.",
 248.552 +        'required':True,
 248.553 +        'condition':'^.+$',
 248.554 +        'default':'=alunni',
 248.555 +        'visible':True,
 248.556 +        'maxlen':None,
 248.557 +        'msgerr':'CAMPO OBBLIGATORIO',
 248.558 +        'msghlp':'inserire il gruppo principale'
 248.559 +        }
 248.560 +
 248.561 +    CampiUtente['userID']      = {
 248.562 +        'caption':"UserID",
 248.563 +        'required':True,
 248.564 +        'condition':'^[a-z_0-9\.]{'+str(USERID_MINLEN)+','+str(USERID_MAXLEN)+'}$',
 248.565 +        'default':'',
 248.566 +        'visible':True,
 248.567 +        'maxlen':USERID_MAXLEN,
 248.568 +        'msgerr':'CAMPO OBBLIGATORIO ('+str(USERID_MINLEN)+'-'+\
 248.569 +                                      str(USERID_MAXLEN)+' car.)',
 248.570 +        'msghlp':'inserisci il nome utente'
 248.571 +        }
 248.572 +    
 248.573 +    CampiUtente['userPass']    = {
 248.574 +        'caption':"Password",
 248.575 +        'required':True,
 248.576 +        'condition':'^.{'+str(USERPW_MINLEN)+','+str(USERPW_MAXLEN)+'}$',
 248.577 +        'default':'',
 248.578 +        'visible':True,
 248.579 +        'maxlen':USERPW_MAXLEN,
 248.580 +        'msgerr':'OBBL.se nuovo utente ('+str(USERPW_MINLEN)+'-'+\
 248.581 +                                        str(USERPW_MAXLEN)+')',
 248.582 +        'msghlp':'cambia la pass al volo con AltP'
 248.583 +        }
 248.584 +    
 248.585 +
 248.586 +    CampiUtente['userCognome'] = {
 248.587 +        'caption':"Cognome",
 248.588 +        'required':True,
 248.589 +        'condition':'^[a-z\' A-Z]{2,25}$',
 248.590 +        'default':'',
 248.591 +        'visible':True,
 248.592 +        'maxlen':None,
 248.593 +        'msgerr':'CAMPO OBBLIGATORIO',
 248.594 +        'msghlp':'inserisci il Cognome'
 248.595 +        }
 248.596 +
 248.597 +    CampiUtente['userNome']    = {
 248.598 +        'caption':"Nome",
 248.599 +        'required':None,
 248.600 +        'condition':'^[a-z A-Z]*$',
 248.601 +        'default':'',
 248.602 +        'visible':True,
 248.603 +        'maxlen':None,
 248.604 +        'msgerr':'',
 248.605 +        'msghlp':'inserisci il Nome'
 248.606 +        }
 248.607 +
 248.608 +    CampiUtente['userCF']      = {
 248.609 +        'caption':"Cod.fiscale",
 248.610 +        'required':None,
 248.611 +        'condition':'^[a-zA-Z]{6,6}[0-9]{2,2}[a-zA-Z]{1,1}[0-9]{2,2}[a-zA-Z]{1}[0-9]{3,3}[a-zA-Z]{1,1}|^$',
 248.612 +        'default':'',
 248.613 +        'visible':True,
 248.614 +        'maxlen':None,
 248.615 +        'msgerr':'formato errato',
 248.616 +        'msghlp':'inserisci il codice fiscale'
 248.617 +        }
 248.618 +    
 248.619 +    CampiUtente['userClasse']  = {
 248.620 +        'caption':"Classe",
 248.621 +        'required':None,
 248.622 +        'condition':'^.*$',
 248.623 +        'default':'=',
 248.624 +        'visible':True,
 248.625 +        'maxlen':CLASSE_MAXLEN,
 248.626 +        'msgerr':'',
 248.627 +        'msghlp':'obbligatorio se alunno'
 248.628 +        }
 248.629 +
 248.630 +    CampiUtente['userAGrp']    = {
 248.631 +        'caption':"Altri gruppi",
 248.632 +        'required':None,
 248.633 +        'condition':'^.*$',
 248.634 +        'default':'',
 248.635 +        'visible':True,
 248.636 +        'maxlen':None,
 248.637 +        'msgerr':'',
 248.638 +        'msghlp':'separa i gruppi con la virgola'
 248.639 +        }
 248.640 +
 248.641 +    CampiUtente['userSex']     = {
 248.642 +        'caption':"Sesso",
 248.643 +        'required':None,
 248.644 +        'condition':'^[mMfF]?$',
 248.645 +        'default':'',
 248.646 +        'visible':True,
 248.647 +        'maxlen':1,
 248.648 +        'msgerr':'valori ammessi: vuoto mMfF',
 248.649 +        'msghlp':'inserisci M o F'
 248.650 +        }
 248.651 +
 248.652 +    
 248.653 +    CampiUtente['userNatoil']  = {
 248.654 +        'caption':"Nato il",
 248.655 +        'required':None,
 248.656 +        'condition':'^.*$',
 248.657 +        'default':'',
 248.658 +        'visible':False,
 248.659 +        'maxlen':None,
 248.660 +        'msgerr':'',
 248.661 +        'msghlp':'inserisci la data di nascita'
 248.662 +        }
 248.663 +
 248.664 +    CampiUtente['userNatoa']   = {
 248.665 +        'caption':"Nato a",
 248.666 +        'required':None,
 248.667 +        'condition':'^.*$',
 248.668 +        'default':'',
 248.669 +        'visible':False,
 248.670 +        'maxlen':None,
 248.671 +        'msgerr':'',
 248.672 +        'msghlp':'inserisci il luogo di nascita'
 248.673 +        }
 248.674 +
 248.675 +    CampiUtente['userNatoPr']  = {
 248.676 +        'caption':"Prov.nascita",
 248.677 +        'required':None,
 248.678 +        'condition':'.*',
 248.679 +        'default':'',
 248.680 +        'visible':False,
 248.681 +        'maxlen':2,
 248.682 +        'msgerr':'',
 248.683 +        'msghlp':'inserisci la provincia di nascita'
 248.684 +        }
 248.685 +
 248.686 +    CampiUtente['userNatoSt']  = {
 248.687 +        'caption':"Stato",
 248.688 +        'required':None,
 248.689 +        'condition':'^.*$',
 248.690 +        'default':'',
 248.691 +        'visible':False,
 248.692 +        'maxlen':None,
 248.693 +        'msgerr':'',
 248.694 +        'msghlp':'inserisci lo stato di nascita'
 248.695 +        }
 248.696 +
 248.697 +    CampiUtente['userInd']     = {
 248.698 +        'caption':"Indirizzo",
 248.699 +        'required':None,
 248.700 +        'condition':'^.*$',
 248.701 +        'default':'',
 248.702 +        'visible':True,
 248.703 +        'maxlen':None,
 248.704 +        'msgerr':'',
 248.705 +        'msghlp':"inserisci l'indirizzo"
 248.706 +        }
 248.707 +
 248.708 +    CampiUtente['userCap']     = {
 248.709 +        'caption':"Cap",
 248.710 +        'required':None,
 248.711 +        'condition':'^[0-9]{5,5}$|^$',
 248.712 +        'default':'',
 248.713 +        'visible':True,
 248.714 +        'maxlen':5,
 248.715 +        'msgerr':'formato errato',
 248.716 +        'msghlp':'inserisci il C.A.P.'
 248.717 +        }
 248.718 +
 248.719 +    CampiUtente['userCitta']   = {
 248.720 +        'caption':"Citta",
 248.721 +        'required':None,
 248.722 +        'condition':'^.*$',
 248.723 +        'default':'',
 248.724 +        'visible':True,
 248.725 +        'maxlen':None,
 248.726 +        'msgerr':'',
 248.727 +        'msghlp':'luogo di residenza'
 248.728 +        }
 248.729 +
 248.730 +    CampiUtente['userProv']    = {
 248.731 +        'caption':"Provincia",
 248.732 +        'required':None,
 248.733 +        'condition':'^.*$',
 248.734 +        'default':'',
 248.735 +        'visible':True,
 248.736 +        'maxlen':None,
 248.737 +        'msgerr':'',
 248.738 +        'msghlp':'provinca di residenza'
 248.739 +        }
 248.740 +
 248.741 +    CampiUtente['userTel1']    = {
 248.742 +        'caption':"Telefono1",
 248.743 +        'required':None,
 248.744 +        'condition':'^.*$',
 248.745 +        'default':'',
 248.746 +        'visible':True,
 248.747 +        'maxlen':None,
 248.748 +        'msgerr':'',
 248.749 +        'msghlp':'telefono di casa'
 248.750 +        }
 248.751 +
 248.752 +    CampiUtente['userTel2']    = {
 248.753 +        'caption':"Telefono2",
 248.754 +        'required':None,
 248.755 +        'condition':'^.*$',
 248.756 +        'default':'',
 248.757 +        'visible':False,
 248.758 +        'maxlen':None,
 248.759 +        'msgerr':'',
 248.760 +        'msghlp':'altro telefono'
 248.761 +        }
 248.762 +
 248.763 +    CampiUtente['userEmail']  = {
 248.764 +        'caption':"E-mail",
 248.765 +        'required':None,
 248.766 +        'condition':'^.+@.+^|^$',
 248.767 +        'default':'',
 248.768 +        'visible':False,
 248.769 +        'maxlen':None,
 248.770 +        'msgerr':'indirizzo e-mail non valido',
 248.771 +        'msghlp':'inserisci un indirizzo email valido'
 248.772 +        }
 248.773 +
 248.774 +    CampiUtente['userPadreC']  = {
 248.775 +        'caption':"Cognome padre",
 248.776 +        'required':None,
 248.777 +        'condition':'^.*$',
 248.778 +        'default':'',
 248.779 +        'visible':False,
 248.780 +        'maxlen':None,
 248.781 +        'msgerr':'',
 248.782 +        'msghlp':'inserisci il cognome del padre'
 248.783 +        }
 248.784 +
 248.785 +    CampiUtente['userPadreN']  = {
 248.786 +        'caption':"Nome padre",
 248.787 +        'required':None,
 248.788 +        'condition':'^.*$',
 248.789 +        'default':'',
 248.790 +        'visible':False,
 248.791 +        'maxlen':None,
 248.792 +        'msgerr':'',
 248.793 +        'msghlp':'inserisci il nome del padre'
 248.794 +        }
 248.795 +
 248.796 +    CampiUtente['userMadreC']  = {
 248.797 +        'caption':"Cognome madre",
 248.798 +        'required':None,
 248.799 +        'condition':'.*',
 248.800 +        'default':'',
 248.801 +        'visible':False,
 248.802 +        'maxlen':None,
 248.803 +        'msgerr':'',
 248.804 +        'msghlp':'inserisci il cognome della madre'
 248.805 +        }
 248.806 +
 248.807 +    CampiUtente['userMadreN']  = {
 248.808 +        'caption':"Nome madre",
 248.809 +        'required':None,
 248.810 +        'condition':'^.*$',
 248.811 +        'default':'',
 248.812 +        'visible':False,
 248.813 +        'maxlen':None,
 248.814 +        'msgerr':'',
 248.815 +        'msghlp':'inserisci il nome della madre'
 248.816 +        }
 248.817 +
 248.818 +    CampiQuota = orderedDict()
 248.819 +
 248.820 +    CampiQuota['quota_sl']    = {
 248.821 +        'caption':"Allarme a (in kb)",
 248.822 +        'required':None,
 248.823 +        'condition':'^[0-9]*$',
 248.824 +        'default':'0',
 248.825 +        'visible':True,
 248.826 +        'maxlen':None,
 248.827 +        'msgerr':'',
 248.828 +        'msghlp':'soglia di allarme spazio insufficiente'
 248.829 +        }
 248.830 +
 248.831 +    CampiQuota['quota_hl']      = {
 248.832 +        'caption':"Limite max.(in kb)",
 248.833 +        'required':None,
 248.834 +        'condition':'^[0-9]*$',
 248.835 +        'default':'0',
 248.836 +        'visible':True,
 248.837 +        'maxlen':None,
 248.838 +        'msgerr':'',
 248.839 +        'msghlp':'soglia invalicabile - spazio totale'
 248.840 +        }
 248.841 +    
 248.842 +    PrefixID = dictNoComplain()
 248.843 +    
 248.844 +    PrefixID['alunni' ] = PREFIX_ALUNNI
 248.845 +    PrefixID['admins' ] = PREFIX_ADMINS
 248.846 +    PrefixID['ata'    ] = PREFIX_ATA
 248.847 +    PrefixID['docenti'] = PREFIX_DOCENTI
 248.848 +    PrefixID['esterni'] = PREFIX_ESTERNI 
 248.849 +    PrefixID['ospiti' ] = PREFIX_OSPITI
 248.850 +            
 248.851 +    # sequenza campi compatibile solo con gli scripts isi*
 248.852 +    TracRec = ('userID','userCognome','userNome','userMGrp',
 248.853 +                'userAGrp','userCF','userPass','userSex',
 248.854 +                'userInd','userCitta','userCap','userProv','userTel1')
 248.855 +
 248.856 +# tracciato record potenziale (SISSI)
 248.857 +#    TracRec = ('userID','userCognome','userNome','userMGrp',
 248.858 +#                'userAGrp','userCF','userPass','userSex',
 248.859 +#                'userInd','userCitta','userCap','userProv','userTel1',
 248.860 +#                'userTel2','userNatoil','userNatoa','userNatoPr','userNatoSt',
 248.861 +#                'userPadreC','userPadreN','userMadreC','userMadreN')
 248.862 +    
 248.863 +    newUser = None  # si tratta di un nuovo utente ?
 248.864 +    newPass = None  # password cambiata ?
 248.865 +    changed = None  # dati modificati?
 248.866 +    novalid = None  # i dati contengono errori?
 248.867 +    delUser = None  # l'utente deve essere eliminato da ldap?
 248.868 +    
 248.869 +    Campi = orderedDict()
 248.870 +    for campo in CampiUtente.ordKeys:
 248.871 +        if CampiUtente[campo]['visible']:
 248.872 +            if CampiUtente[campo]['required']:
 248.873 +                ob = ' *: '
 248.874 +            else:
 248.875 +                ob = '  : '
 248.876 +            caption = string.rjust(CampiUtente[campo]['caption'],20)+ob
 248.877 +            Campi[campo] = VEdit(campo,
 248.878 +                                 CampiUtente[campo]['condition'],
 248.879 +                                 CampiUtente[campo]['maxlen'],
 248.880 +                                 CampiUtente[campo]['msgerr'],
 248.881 +                                 CampiUtente[campo]['msghlp'],
 248.882 +                                 ('editcp',caption),
 248.883 +                                 string.lstrip(CampiUtente[campo]['default'],'='))
 248.884 +
 248.885 +    Quota = orderedDict()
 248.886 +    for campo in CampiQuota.ordKeys:
 248.887 +        if CampiQuota[campo]['visible']:
 248.888 +            if CampiQuota[campo]['required']:
 248.889 +                ob = ' *: '
 248.890 +            else:
 248.891 +                ob = '  : '
 248.892 +            caption = string.rjust(CampiQuota[campo]['caption'],20)+ob
 248.893 +            Quota[campo] = VEdit(campo,
 248.894 +                                    CampiQuota[campo]['condition'],
 248.895 +                                    CampiQuota[campo]['maxlen'],
 248.896 +                                    CampiQuota[campo]['msgerr'],
 248.897 +                                    CampiQuota[campo]['msghlp'],
 248.898 +                                    ('editcp',caption),
 248.899 +                                    string.lstrip(CampiQuota[campo]['default'],'='))
 248.900 +
 248.901 +    Quota['h1'] = sep
 248.902 +    Quota['h2'] = urwid.Text('Quota in kilobytes (50000 = 50Mb)\nAltQ - assegna la quota\nESC  - rinuncia')
 248.903 +    
 248.904 +    def __init__(self):         
 248.905 +        self.items=[] # campi editabili frame di sinistra
 248.906 +        self.itemq=[] # campi quota
 248.907 +        for c in self.Campi.ordKeys:
 248.908 +            self.items.append(urwid.AttrWrap(self.Campi[c],'editbx','editfc'))
 248.909 +
 248.910 +        for c in self.Quota.ordKeys:
 248.911 +            if c in ('h1','h2'):
 248.912 +                self.itemq.append(urwid.AttrWrap(self.Quota[c],'help'))
 248.913 +            else:
 248.914 +                self.itemq.append(urwid.AttrWrap(self.Quota[c],'editbx','editfc'))
 248.915 +    
 248.916 +    def get_campo(self,nome):
 248.917 +        v = ''
 248.918 +        if nome in ('quota_sl','quota_hl'):
 248.919 +            if self.CampiQuota[nome]['visible']:
 248.920 +                v = self.Quota[nome].get_edit_text()
 248.921 +        else:   
 248.922 +            if self.CampiUtente[nome]['visible']:
 248.923 +                v = self.Campi[nome].get_edit_text()
 248.924 +        return v
 248.925 +        
 248.926 +    def get_default(self,nome):
 248.927 +        if nome in ('quota_sl','quota_hl'):
 248.928 +            return self.CampiQuot[nome]['default']
 248.929 +        else:   
 248.930 +            return self.CampiUtente[nome]['default']
 248.931 +
 248.932 +    def set_campo(self,nome,valore):
 248.933 +        if nome in ('quota_sl','quota_hl'):
 248.934 +            if self.CampiQuota[nome]['visible']:
 248.935 +                self.Quota[nome].set_edit_text(valore)
 248.936 +        else:   
 248.937 +            if self.CampiUtente[nome]['visible']:
 248.938 +                self.Campi[nome].set_edit_text(valore)
 248.939 +
 248.940 +    def is_visible(self,nome):
 248.941 +        if nome in ('quota_sl','quota_hl'):
 248.942 +            return self.CampiQuot[nome]['visible']
 248.943 +        else:   
 248.944 +            return self.CampiUtente[nome]['visible']
 248.945 +    
 248.946 +
 248.947 +class AddUser:
 248.948 +    palette = [
 248.949 +        ('body'    , 'black'     , 'light gray', 'standout'),
 248.950 +        ('reverse' , 'light gray', 'dark blue'),
 248.951 +        ('header'  , 'yellow'    , 'dark blue', 'bold'),
 248.952 +        ('footer'  , 'yellow'    , 'dark blue', 'bold'),
 248.953 +        ('focus'   , 'black'     , 'light gray', 'standout'),
 248.954 +        ('focusnew', 'dark blue' , 'light gray', 'standout'),
 248.955 +        ('focuserr', 'dark red'  , 'light gray', 'standout'),
 248.956 +        ('focusdel', 'yellow'    , 'dark red', 'standout'),
 248.957 +        ('focuspwd', 'yellow'    , 'light gray', 'standout'),
 248.958 +        ('focuscha', 'white',      'light gray', 'standout'),
 248.959 +        ('selfocus', 'yellow'    , 'dark magenta',\
 248.960 +                                    ('bold','standout','underline')),
 248.961 +        ('title'   , 'dark red'  , 'light gray',('standout','underline')),
 248.962 +        ('help'    , 'dark blue' , 'light gray', 'standout'),
 248.963 +        ('helpnote', 'dark red'  , 'light gray'),
 248.964 +        ('passwd'  , 'dark red'  , 'dark red'),
 248.965 +        ('key'     , 'yellow'    , 'light gray', ('standout','underline')),
 248.966 +        ('editfc'  , 'white'     , 'black', 'bold'),
 248.967 +        ('editbx'  , 'light gray', 'black'),
 248.968 +        ('editcp'  , 'black'     , 'light gray', 'standout'),
 248.969 +        ('errorcp' , 'dark red'  , 'light gray', 'standout'),
 248.970 +        ('alert'   , 'yellow'    , 'dark red', 'standout'),
 248.971 +        ('newuser' , 'dark red'  , 'light gray', 'standout'),
 248.972 +        ('bright'  , 'dark gray' , 'light gray', ('bold','standout')),
 248.973 +        ('error'   , 'white'     , 'black', ('bold','standout')),
 248.974 +        ('buttn'   , 'black'     , 'dark cyan'),
 248.975 +        ('buttnf'  , 'white'     , 'dark blue','bold'),
 248.976 +        ]
 248.977 +
 248.978 +    htxt1 = urwid.Text("ISI-USERS [AltH-help]")
 248.979 +    ftxt1 = urwid.Text("")
 248.980 +    head1 = urwid.AttrWrap( htxt1, 'header' )
 248.981 +    foot0 = urwid.AttrWrap( ftxt1, 'alert' )
 248.982 +    foot1 = urwid.AttrWrap( ftxt1, 'footer' )
 248.983 +
 248.984 +    htxt2 = urwid.Text("Lista utenti gruppo:")
 248.985 +    ftxt2 = urwid.Text("")
 248.986 +    head2 = urwid.AttrWrap( htxt2, 'header' )
 248.987 +    foot2 = urwid.AttrWrap( ftxt2, 'footer' )
 248.988 +
 248.989 +    htxt4 = urwid.Text("QUOTA DISCO")
 248.990 +    ftxt4 = urwid.Text("")
 248.991 +    head4 = urwid.AttrWrap( htxt4, 'header' )
 248.992 +    foot4 = urwid.AttrWrap( ftxt4, 'footer' )
 248.993 +
 248.994 +    AttUser = User()
 248.995 +    AttUid  = None
 248.996 +
 248.997 +    #inserisco separatori tra campi, preparo frame di sinistra 
 248.998 +    AttUser.items.insert(0,blank)
 248.999 +    AttUser.items.insert(2,sep)    
248.1000 +    AttUser.items.insert(5,sep)    
248.1001 +    AttUser.items.insert(11,sep)    
248.1002 +    AttUser.items.insert(17,sep)  
248.1003 +    AttUser.items.append(sep)
248.1004 +    AttUser.items.append(blank)
248.1005 +
248.1006 +    num_items=len(AttUser.items)
248.1007 +    num_user = 0
248.1008 +
248.1009 +    AttUser.itemq.insert(0,blank)
248.1010 +
248.1011 +    usersRecords = {}
248.1012 +    usersImmessi = {}
248.1013 +    usersQuota   = {}
248.1014 +    usersInOrd   = []
248.1015 +    
248.1016 +    LBoxF     = urwid.ListBox(AttUser.items)
248.1017 +    LBoxQ     = urwid.ListBox(AttUser.itemq)
248.1018 +    
248.1019 +    ListaID  = [sep]
248.1020 +    LBoxL    = urwid.ListBox(ListaID)
248.1021 +    LBoxH    = HelpColumn()
248.1022 +    LBoxP    = AuthPassColumn()
248.1023 +    LBoxC    = ConfirmColumn()
248.1024 +
248.1025 +    oShow = 0
248.1026 +    FC = urwid.Frame(LBoxF,head1, foot1)
248.1027 +    FL = [  urwid.Frame(LBoxL,head2,foot2), LBoxH, LBoxP, LBoxC, 
248.1028 +            urwid.Frame(LBoxQ,head4,foot4) ]
248.1029 +
248.1030 +    oC2 = (
248.1031 +        urwid.Overlay(FL[0],FL[1],'left',('relative',100),'top',('relative',100)),
248.1032 +        urwid.Overlay(FL[1],FL[0],'left',('relative',100),'top',('relative',100)),
248.1033 +        urwid.Overlay(FL[2],FL[0],'left',('relative',100),'top',('relative',100)),
248.1034 +        urwid.Overlay(FL[3],FL[0],'left',('relative',100),'top',('relative',100)),
248.1035 +        urwid.Overlay(FL[4],FL[0],'left',('relative',100),'top',('relative',100))
248.1036 +        )
248.1037 +
248.1038 +    # FIXME: per il momento interfaccio la libreria attraverso gli oggetti 
248.1039 +    # già esistenti nella vecchia versione di isi-users
248.1040 +    # LDAPCON conterrà la connessione ad ldap, LDAPCON.l è l'oggetto isi.Manager
248.1041 +    # che mette a disposizione tutte le funzioni di libreria
248.1042 +    
248.1043 +    LDAPCON  = None
248.1044 +    changed  = None
248.1045 +    user_exist = None
248.1046 +    auth = None
248.1047 +    op_pwd = None
248.1048 +    op_fine = None
248.1049 +    alulink = []
248.1050 +    size= None
248.1051 +    gruppo = None
248.1052 +    ldapLoadErr = None
248.1053 +    cancProfilo = None
248.1054 +    
248.1055 +    def __init__(self,gruppo=None): 
248.1056 +        """autorizza l'utente e carica utenti del gruppo"""
248.1057 +        
248.1058 +        self.auth = authSudo(gruppo)
248.1059 +        self.auth.main()
248.1060 +        self.gruppo=gruppo
248.1061 +        
248.1062 +        if gruppo:
248.1063 +            self.htxt2.set_text('Gruppo: '+self.gruppo+' | admin: '+ \
248.1064 +                                self.auth.adminUsr+self.auth.adminGrp)
248.1065 +            self.LDAPCON = isildap(gruppo)
248.1066 +            # carica tutti gli utenti del gruppo
248.1067 +            self.load_fromldap()
248.1068 +            
248.1069 +            
248.1070 +        self.user_exist = False 
248.1071 +        self.okalert = False
248.1072 +
248.1073 +        if self.usersInOrd:
248.1074 +            self.ncol=1
248.1075 +        else:
248.1076 +            self.ncol=0
248.1077 +
248.1078 +        self.col_list = [   ('weight',45,self.FC),
248.1079 +                            ('weight',30,self.oC2[self.oShow])
248.1080 +                        ]
248.1081 +
248.1082 +        self.columns = urwid.Columns( self.col_list, 1 )
248.1083 +        self.columns.set_focus_column( self.ncol )
248.1084 +        self.top = urwid.AttrWrap( self.columns, 'body' )
248.1085 +
248.1086 +        
248.1087 +    def main(self):
248.1088 +        self.ui = urwid.curses_display.Screen()
248.1089 +        self.ui.register_palette(self.palette)
248.1090 +        self.ui.run_wrapper( self.run )
248.1091 +        return self.num_user        
248.1092 +
248.1093 +    def run(self):
248.1094 +        self.ui.set_mouse_tracking()
248.1095 +        while True:
248.1096 +            self.size = self.ui.get_cols_rows()     
248.1097 +            if not self.ldapLoadErr is None:
248.1098 +                self.alert('DATI/UTENTI INESISTENTI:\n'+self.ldapLoadErr)
248.1099 +                self.ldapLoadErr = None
248.1100 +
248.1101 +            if not self.AttUser.get_campo('userPass'):
248.1102 +                self.AttUser.set_campo('userPass',new_passwd(8))
248.1103 +
248.1104 +            Altro   = None
248.1105 +            NoValid = None
248.1106 +            k       = None
248.1107 +            
248.1108 +            changeshow = None
248.1109 +            self.num_user = len(self.usersImmessi)
248.1110 +    
248.1111 +            while True:         
248.1112 +                if Altro: break
248.1113 +                
248.1114 +                if changeshow:
248.1115 +                    changeshow = None
248.1116 +                    self.col_list = [   ('weight',45,self.FC),
248.1117 +                                        ('weight',30,self.FL[self.oShow])
248.1118 +                                    ]
248.1119 +                    self.columns = urwid.Columns( self.col_list, 1 )
248.1120 +                    self.columns.set_focus_column( self.ncol )
248.1121 +                    self.top = urwid.AttrWrap( self.columns, 'body' )
248.1122 +
248.1123 +                self.ncol = self.columns.get_focus_column()
248.1124 +                c,p = self.LBoxF.get_focus()            
248.1125 +                if not hasattr(c,'validate'):
248.1126 +                    self.LBoxF.set_focus(1)
248.1127 +                    c,p = self.LBoxF.get_focus()            
248.1128 +                    
248.1129 +                if self.ncol == 0:      
248.1130 +                    if NoValid:
248.1131 +                        self.stato(c,'err')
248.1132 +                    else:   
248.1133 +                        self.stato(c,'hlp')
248.1134 +                else:
248.1135 +                    self.cambiaDatiUser()
248.1136 +                    self.aggiorna_form()
248.1137 +                    
248.1138 +                self.draw_screen( self.size)
248.1139 +
248.1140 +                NoValid = None
248.1141 +                keys    = None
248.1142 +
248.1143 +                while not keys:
248.1144 +                    keys = self.ui.get_input()      
248.1145 +                    for k in keys:
248.1146 +                        if urwid.is_mouse_event(k):
248.1147 +                            event, button, col, row = k
248.1148 +                            self.top.mouse_event( self.size,event, button, col, row,focus=True )
248.1149 +                            continue
248.1150 +                            
248.1151 +                        if k == "window resize":
248.1152 +                            self.size = self.ui.get_cols_rows()
248.1153 +                            continue
248.1154 +                        
248.1155 +                        if self.cancProfilo:
248.1156 +                            if self.oShow == 3 and k in ('s','S'):
248.1157 +                                k = self.cancProfilo
248.1158 +                                changeshow = True
248.1159 +                                self.oShow=0
248.1160 +                            elif self.oShow == 3 and k in ('n','N'):
248.1161 +                                self.cancProfilo = None
248.1162 +#                                self.LBoxC.vuota() #probabilmente inutile
248.1163 +                                changeshow = True
248.1164 +                                self.oShow=0
248.1165 +                                k=''
248.1166 +                        else:
248.1167 +                            if self.oShow == 3 and k in ('s','S'):
248.1168 +                                self.num_user = 0
248.1169 +                                return
248.1170 +                            elif self.oShow == 3 and k in ('n','N'):
248.1171 +#                                self.LBoxC.vuota() #probabilmente inutile
248.1172 +                                changeshow = True
248.1173 +                                self.oShow=0
248.1174 +                                k=''
248.1175 +                            elif self.oShow == 3:
248.1176 +                                k=''
248.1177 +                            else:
248.1178 +                                pass
248.1179 +
248.1180 +                        if k in ('meta x','meta X'):
248.1181 +                            if self.ncol == 0:
248.1182 +                                self.cambiaDatiUser()
248.1183 +                            if len(self.usersRecords) > 0:
248.1184 +                                self.LBoxC.load_msg(0)
248.1185 +                                changeshow = True
248.1186 +                                self.oShow = 3
248.1187 +                                self.ncol=1
248.1188 +                                k = ''
248.1189 +                            else:   
248.1190 +                                self.num_user = 0
248.1191 +                                return 
248.1192 +
248.1193 +                        if k in ('left','meta left') and self.oShow == 2:
248.1194 +                            k = '' 
248.1195 +                            
248.1196 +                        if k == 'esc':
248.1197 +                            if self.ncol == 0 and len(self.usersImmessi)>0:
248.1198 +                                self.alert('')
248.1199 +                                self.AttUser.changed = False
248.1200 +                                k='meta right'
248.1201 +                            if self.oShow == 2:
248.1202 +                                self.alert('')
248.1203 +                                changeshow = True
248.1204 +                                self.oShow = 0
248.1205 +                                self.op_pwd = None
248.1206 +                                self.op_fine = None
248.1207 +                            elif self.oShow == 4:
248.1208 +                                self.alert('')
248.1209 +                                changeshow = True
248.1210 +                                self.oShow = 0
248.1211 +                                
248.1212 +                        if k in ('meta s','meta S'):
248.1213 +                            if self.ncol == 0 and self.checkPrivileges():
248.1214 +                                self.AttUser.changed = True
248.1215 +                                self.AddRecord()
248.1216 +                                k='meta right'
248.1217 +
248.1218 +                        if k in ('meta r','meta R'): #ricarica da ldap
248.1219 +                            self.reloadFromLdap()
248.1220 +                            break   
248.1221 +                        if k in ('meta g','meta G'): #ricarica da ldap
248.1222 +                            self.load_fromldap()
248.1223 +                        #---------------------------------------------------
248.1224 +                        if k in ('meta h','meta H'):
248.1225 +                            changeshow = True
248.1226 +                            if self.oShow == 1: 
248.1227 +                                self.oShow=0
248.1228 +                            else:
248.1229 +                                self.oShow=1
248.1230 +
248.1231 +                        elif k in ('meta q','meta Q'):
248.1232 +                            changeshow = True
248.1233 +                            if self.oShow == 4: 
248.1234 +                                q = [ self.AttUser.get_campo('quota_sl'), 
248.1235 +                                      self.AttUser.get_campo('quota_hl') ]
248.1236 +                                self.set_quota(self.AttUid,q)
248.1237 +                                self.oShow=0
248.1238 +                            else:
248.1239 +                                q = self.get_quota(self.AttUid)
248.1240 +                                self.AttUser.set_campo('quota_sl',q[1])
248.1241 +                                self.AttUser.set_campo('quota_hl',q[2])
248.1242 +                                self.LBoxQ.set_focus(1)
248.1243 +                                self.oShow=4
248.1244 +
248.1245 +                        elif k in ('meta i','meta I'): # cancella profilo Win9x
248.1246 +                            if self.cancProfilo is None:
248.1247 +                                self.cancProfilo = k
248.1248 +                                self.LBoxC.load_msg(1, '9x')
248.1249 +                                changeshow = True
248.1250 +                                self.oShow = 3
248.1251 +#                                self.ncol=1
248.1252 +                            else:
248.1253 +                                self.elimina_profilo(PROFILO['9x'])
248.1254 +                            k = ''
248.1255 +                            
248.1256 +                        elif k in ('meta j','meta J'): # cancella profilo WinXP
248.1257 +                            if self.cancProfilo is None:
248.1258 +                                self.cancProfilo = k
248.1259 +                                self.LBoxC.load_msg(1, 'xp')
248.1260 +                                changeshow = True
248.1261 +                                self.oShow = 3
248.1262 +#                                self.ncol=1
248.1263 +                            else:
248.1264 +                                self.elimina_profilo(PROFILO['xp'])
248.1265 +                            k = ''
248.1266 +
248.1267 +                        elif k in ('meta l','meta L'): # cancella profilo WinXP
248.1268 +                            if self.cancProfilo is None:
248.1269 +                                self.cancProfilo = k
248.1270 +                                self.LBoxC.load_msg(1, '2k')
248.1271 +                                changeshow = True
248.1272 +                                self.oShow = 3
248.1273 +#                                self.ncol=1
248.1274 +                            else:
248.1275 +                                self.elimina_profilo(PROFILO['2k'])
248.1276 +                            k = ''
248.1277 + 
248.1278 +                        elif k in ('ctrl k','ctrl K'):
248.1279 +                            if self.ncol == 0:
248.1280 +                                c.vuota(c.edit_pos)
248.1281 +                                self.AttUser.changed = True
248.1282 +
248.1283 +                        elif k in ('meta p','meta P'): # CAMBIA PASSWORD
248.1284 +                            k=''
248.1285 +                            if self.ncol == 0:
248.1286 +                                if not self.AttUser.get_campo('userPass'):
248.1287 +                                    self.LBoxF.set_focus(4)
248.1288 +                                elif self.auth.adminUsr == 'root':
248.1289 +                                    if self.cambiaPass():
248.1290 +                                        self.AttUser.set_campo('userPass','')
248.1291 +                                        self.op_pwd =  None
248.1292 +                                else:   
248.1293 +                                    changeshow = True
248.1294 +                                    self.op_pwd = True
248.1295 +                                    if self.oShow == 2: 
248.1296 +                                        self.oShow=0
248.1297 +                                    else:
248.1298 +                                        self.oShow=2
248.1299 +                                        self.ncol=1
248.1300 +
248.1301 +                        elif k in ('enter','tab'): # attivo solo sulla colonna 0
248.1302 +                            if self.ncol == 0 and \
248.1303 +                                self.checkPrivileges() and self.oShow<2:
248.1304 +                                self.is_new_user(self.AttUser.get_campo('userID'))
248.1305 +                                if c.name == 'userPass' and \
248.1306 +                                    self.user_exist and not c.get_edit_text():
248.1307 +                                    k = 'down'
248.1308 +                                elif c.validate(): 
248.1309 +                                    k = 'down'
248.1310 +                                    self.IDPrefix(c)
248.1311 +                                else:   
248.1312 +                                    NoValid = True
248.1313 +                                    self.columns.set_focus_column(self.ncol-1)
248.1314 +                            elif self.oShow == 2:
248.1315 +                                if self.op_pwd:
248.1316 +                                    if self.cambiaPass():
248.1317 +                                        self.AttUser.set_campo('userPass','')
248.1318 +                                        changeshow = True
248.1319 +                                        self.oShow = 0
248.1320 +                                        self.op_pwd =  None
248.1321 +                                elif self.op_fine:
248.1322 +                                    self.UsersFile()
248.1323 +                                    self.updateLdap()
248.1324 +                                    return
248.1325 +                            elif self.oShow == 4:                               
248.1326 +                                k = 'down'
248.1327 +                            elif self.ncol==1 and self.oShow==0:
248.1328 +                                pass
248.1329 +
248.1330 +                        elif k in ('up','down','page up','page down'):
248.1331 +                            if self.ncol == 0:
248.1332 +                                if not c.validate():
248.1333 +                                    if c.name == 'userPass' and \
248.1334 +                                        self.user_exist and not c.edit_text:
248.1335 +                                        pass
248.1336 +                                    else:
248.1337 +                                        c.set_caption(('errorcp',c.caption))
248.1338 +                                else:
248.1339 +                                    c.set_caption(('editcp',c.caption))
248.1340 +
248.1341 +                                self.is_new_user(self.AttUser.get_campo('userID'))
248.1342 +                                self.IDPrefix(c)
248.1343 +                            else:
248.1344 +                                self.alert('')
248.1345 +                                
248.1346 +                        elif k in ('right','left'):
248.1347 +                            pass
248.1348 +
248.1349 +                        elif k == 'meta left':
248.1350 +                            if self.ncol > 0:
248.1351 +                                self.columns.set_focus_column(self.ncol-1)
248.1352 +                            k = ''
248.1353 +
248.1354 +                        elif k == 'meta right':
248.1355 +                            if self.ncol == 0 and self.checkPrivileges():
248.1356 +                                self.cambiaDatiUser()
248.1357 +                                self.columns.set_focus_column(1)
248.1358 +                            k = ''
248.1359 +                        
248.1360 +                        elif k == 'f9':        #ex 'meta delete':
248.1361 +                            if self.ncol == 1:
248.1362 +                                if self.AttUser.delUser:
248.1363 +                                    self.AttUser.delUser = False
248.1364 +                                    self.AttUser.changed = True
248.1365 +                                else:   
248.1366 +                                    self.AttUser.delUser = True
248.1367 +                                self.AddRecord()
248.1368 +
248.1369 +                        elif k == 'delete':
248.1370 +                            if self.ncol == 1:
248.1371 +                                if self.oShow == 0:
248.1372 +                                    k = self.DeleteUser()
248.1373 +                                    if k == 'left':
248.1374 +                                        self.vuota()
248.1375 +                                        self.LBoxF.set_focus(1)
248.1376 +                                        self.num_user = 0
248.1377 +                                        Altro = True
248.1378 +                                        self.AttUser.changed = False
248.1379 +                                elif self.oShow == 4:
248.1380 +                                    pass
248.1381 +                            else:
248.1382 +                                self.AttUser.changed = True
248.1383 +
248.1384 +                        elif k == 'backspace':
248.1385 +                            if self.oShow ==0 and self.ncol == 0:
248.1386 +                                self.AttUser.changed = True
248.1387 +                            
248.1388 +                        elif k in ('meta f','meta F'): # registra 
248.1389 +                            if self.ncol == 0:
248.1390 +                                self.cambiaDatiUser()
248.1391 +                            if len(self.usersRecords) == 0:
248.1392 +                                self.alert('nessun aggiornamento necessario')
248.1393 +                            else:   
248.1394 +                                if self.ncol==0 and not self.checkPrivileges():
248.1395 +                                    k = ''
248.1396 +                                else:   
248.1397 +                                    if self.auth.adminUsr == 'root':
248.1398 +                                        self.UsersFile()
248.1399 +                                        self.updateLdap()
248.1400 +                                        return
248.1401 +                                    else:
248.1402 +                                        changeshow = True
248.1403 +                                        self.op_fine = True
248.1404 +                                        if self.oShow == 2: 
248.1405 +                                            self.oShow=0
248.1406 +                                        else:
248.1407 +                                            self.oShow=2
248.1408 +                                            self.ncol=1
248.1409 +
248.1410 +                        elif k in ('f8','meta n','meta N') : # altro record
248.1411 +                            if self.ncol == 0:
248.1412 +                                if self.ValidateAll() and \
248.1413 +                                        self.checkPrivileges():
248.1414 +                                    self.AddRecord()
248.1415 +                                    self.vuota()
248.1416 +                                    self.AttUser.changed =  False
248.1417 +                                    self.LBoxF.set_focus(1)
248.1418 +                                    Altro = True
248.1419 +                                else:
248.1420 +                                    NoValid=True
248.1421 +                                    k = ''
248.1422 +                            else:
248.1423 +                                self.vuota()
248.1424 +                                self.LBoxF.set_focus(1)
248.1425 +                                Altro = True
248.1426 +                                self.ncol = self.columns.set_focus_column(0)
248.1427 +
248.1428 +                        elif not k in ('delete','left','right','backspace'):
248.1429 +                            if self.ncol == 0:
248.1430 +                                if c.RaiseMaxLen(): 
248.1431 +                                    k=''
248.1432 +                                else:
248.1433 +                                    self.AttUser.changed = True
248.1434 +#                        self.alert(keys)
248.1435 +                        if k: self.top.keypress( self.size, k )
248.1436 +                    
248.1437 +#-------------------------------------------------------------------------  
248.1438 +    def elimina_profilo(self, pwin):
248.1439 +        """ elimina profilo windows"""
248.1440 +        self.alert('%s - elimino profilo %s, attendi...' % (self.AttUid, pwin))
248.1441 +        self.cancProfilo = None
248.1442 +        if not self.checkPrivileges(): return
248.1443 +        maingrp = self.AttUser.get_campo('userMGrp')
248.1444 +        home = "%s/%s/%s" % (HOME_IN, maingrp, self.AttUid)
248.1445 +        profilo = "%s/%s/%s/.profili/%s" % \
248.1446 +                (HOME_IN, maingrp, self.AttUid, pwin)
248.1447 +        if os.path.isdir(profilo):
248.1448 +            try:
248.1449 +                cmd = "isi-delprofilo %s %s %s" % (maingrp, self.AttUid, pwin)
248.1450 +                r, o, e = execute(cmd)
248.1451 +                self.alert('%s - profilo %s eliminato' % (self.AttUid, pwin))
248.1452 +            except ExecuteError, e:
248.1453 +                self.alert("ERRORE: %s"  % e)
248.1454 +        else:
248.1455 +            self.alert('%s - profilo %s inesistente' % (self.AttUid, pwin))
248.1456 +
248.1457 +    def aggiorna_form(self):        
248.1458 +        """ il try serve per la compatibità con la versione etch """
248.1459 +        i=0
248.1460 +        try:
248.1461 +            for i in range(len(self.AttUser.items)):
248.1462 +                self.AttUser.items[i]._invalidate()
248.1463 +        except:
248.1464 +            pass
248.1465 +
248.1466 +    def draw_screen(self, size):
248.1467 +        """ disegna la schermata """
248.1468 +        canvas = self.top.render( size, focus=True )
248.1469 +        self.ui.draw_screen( size, canvas )
248.1470 +    
248.1471 +    def IDPrefix(self,c):
248.1472 +        """ prefissa userID dipendentemente dal gruppo principale """
248.1473 +        if c.name == 'userMGrp' and self.AttUser.get_campo('userID') =='':
248.1474 +            self.AttUser.set_campo('userID',self.AttUser.PrefixID[c.edit_text])
248.1475 +
248.1476 +    def cambiaDatiUser(self):
248.1477 +        """ sincronizza lista utente e form dati """
248.1478 +        if self.checkPrivileges() and self.AttUser.changed:
248.1479 +            if self.user_exist or self.ValidateAll(): self.AddRecord()
248.1480 +        self.ReloadDatiUser()
248.1481 +        alertmsg=''
248.1482 +        if self.AttUser.newUser:
248.1483 +            alertmsg += 'NEW'
248.1484 +        if self.AttUser.newPass:
248.1485 +            alertmsg += '|PWD'
248.1486 +        if self.AttUser.changed:
248.1487 +            alertmsg += '|MOD'
248.1488 +        if self.AttUser.delUser:
248.1489 +            alertmsg = ' ELIMINATO '
248.1490 +        self.AttUid = self.AttUser.get_campo('userID')
248.1491 +
248.1492 +        self.is_new_user(self.AttUid)
248.1493 +        x = 'UT:'+string.ljust(str(self.num_user),4) +'|'+ \
248.1494 +          string.ljust(self.AttUid,13) +'|'
248.1495 +        self.ftxt2.set_text([x,('key',alertmsg)] )  
248.1496 +
248.1497 +    def alert(self,msg):
248.1498 +        """ visualizza un messaggio sotto i campi"""
248.1499 +        n = len(self.AttUser.items)-1
248.1500 +        if msg:
248.1501 +            self.AttUser.items[n]=\
248.1502 +                urwid.AttrWrap(urwid.Text(msg,'center'),'alert')
248.1503 +        else:
248.1504 +            self.AttUser.items[n]=\
248.1505 +                urwid.AttrWrap(urwid.Text(msg,'center'),'body')
248.1506 +        try:
248.1507 +            self.AttUser.items[n]._invalidate()
248.1508 +        except:
248.1509 +            pass
248.1510 +        self.draw_screen( self.size )
248.1511 +
248.1512 +    def topalert(self,msg,align='center'):
248.1513 +        """ visualizza un messaggio sopra i campi """
248.1514 +        if msg:
248.1515 +            self.AttUser.items[0] = \
248.1516 +                urwid.AttrWrap(urwid.Text(msg,align),'focuspwd')
248.1517 +        else:
248.1518 +            self.AttUser.items[0] = blank
248.1519 +        self.AttUser.items[0]._invalidate()
248.1520 +        self.draw_screen( self.size )
248.1521 +
248.1522 +    def stato(self,c,tmsg):
248.1523 +        """ aggiorna la riga di stato """
248.1524 +
248.1525 +        if self.AttUser.changed:
248.1526 +            ch = '*'
248.1527 +        else:
248.1528 +            ch = ' '
248.1529 +        
248.1530 +        if tmsg == 'err':
248.1531 +            color = 'error'
248.1532 +            msg = ch+'|'+c.msgerr
248.1533 +            allinea = 'center'
248.1534 +        elif tmsg == 'hlp':
248.1535 +            color = 'footer'
248.1536 +            msg = ch+'|'+c.msghlp
248.1537 +            allinea = 'left'
248.1538 +        else:
248.1539 +            pass
248.1540 +            
248.1541 +        self.ftxt1.set_align_mode(allinea)
248.1542 +        self.ftxt1.set_text((color,msg))
248.1543 +
248.1544 +        
248.1545 +    def ValidateAll(self):  
248.1546 +        """ valida tutti i campi della maschera """
248.1547 +        ret = True
248.1548 +        self.AttUser.novalid = False
248.1549 +        i = 0
248.1550 +        for c in self.AttUser.items: 
248.1551 +            if hasattr(c,'validate'):
248.1552 +                if c.validate(): 
248.1553 +                    c.set_caption(('editcp',c.caption))
248.1554 +                else:
248.1555 +                    if c.name == 'userPass' and not \
248.1556 +                        self.AttUser.newUser and not c.edit_text:
248.1557 +                        ret = True
248.1558 +                    elif c.name == 'userClasse' and not \
248.1559 +                            c.edit_text and \
248.1560 +                            string.lower(self.AttUser.get_campo('userMGrp'))=='alunni':
248.1561 +                        ret = False
248.1562 +                    else:
248.1563 +                        self.LBoxF.set_focus(i)
248.1564 +                        c.set_caption(('errorcp',c.caption))
248.1565 +                        ret = False
248.1566 +            
248.1567 +        i += 1
248.1568 +        
248.1569 +        if not ret:
248.1570 +            self.AttUser.novalid = True
248.1571 +            
248.1572 +        return ret
248.1573 +
248.1574 +    def checkPrivileges(self):
248.1575 +        """ controlla che l'admin abbia i privilegi sui gruppi dichiarati"""
248.1576 +        ret = True
248.1577 +        err = ''
248.1578 +        if self.auth.adminUsr == 'root':
248.1579 +            pass
248.1580 +        else:
248.1581 +            gM = self.auth.authChi[self.AttUser.get_campo('userMGrp')]
248.1582 +        
248.1583 +            gC = self.auth.authChi[self.AttUser.get_campo('userClasse')]
248.1584 +
248.1585 +            if not (self.auth.ru.search(gM+'@'+gC) or \
248.1586 +                        self.auth.rg.search(gM+'@'+gC)):
248.1587 +                err += ' '+self.AttUser.get_campo('userClasse')
248.1588 +                ret = False
248.1589 +            
248.1590 +            gg = string.split(self.AttUser.get_campo('userAGrp'),',')
248.1591 +            for g in gg:
248.1592 +                if g:
248.1593 +                    gx = self.auth.authChi[g]
248.1594 +                    if not (self.auth.ru.search(gM+'@'+gx) or \
248.1595 +                                self.auth.rg.search(gM+'@'+gx)):
248.1596 +                        err += ' '+g
248.1597 +                        ret = False
248.1598 +        if not ret:
248.1599 +            self.alert('OPERAZIONE VIETATA:\nimpossibile assegnare utenti a gruppi ['+ \
248.1600 +                       err+'] su cui non si hanno privilegi')       
248.1601 +        return ret  
248.1602 +    
248.1603 +    def vuota(self):
248.1604 +        """ 
248.1605 +        vuota tutti campi 
248.1606 +        rispetta i default e se il default inizia con =
248.1607 +        ripropone (non cancella) il valore attuale
248.1608 +        """
248.1609 +        rex=re.compile('^=')
248.1610 +        for c in self.AttUser.Campi.keys():
248.1611 +            vd=self.AttUser.get_default(c)
248.1612 +            if not rex.match(vd):
248.1613 +                self.AttUser.set_campo(c,string.lstrip(vd,'='))
248.1614 +        self.AttUser.changed = False
248.1615 +        self.AttUser.newPass = False
248.1616 +        self.AttUser.newUser = False
248.1617 +        self.AttUser.novalid = False
248.1618 +        
248.1619 +
248.1620 +    def DeleteUser(self):
248.1621 +        """ cancella l'utente dalla lista della seconda colonna """
248.1622 +        uid = self.AttUser.get_campo('userID')
248.1623 +        cog = self.AttUser.get_campo('userCognome')
248.1624 +        nom = self.AttUser.get_campo('userNome')
248.1625 +
248.1626 +        cn  = string.ljust(cog,10) +' '+ nom
248.1627 +        cni = self.usersInOrd.index(cn+uid)
248.1628 +
248.1629 +        del self.usersInOrd[cni]
248.1630 +        del self.ListaID[cni]
248.1631 +        del self.usersImmessi[uid]
248.1632 +        
248.1633 +        if self.usersRecords.has_key(uid):
248.1634 +            del self.usersRecords[uid]
248.1635 +        
248.1636 +        self.num_user -= 1
248.1637 +
248.1638 +        ll=len(self.usersInOrd) 
248.1639 +        if cni == ll:
248.1640 +            cni -= 1
248.1641 +        
248.1642 +        if ll>0:
248.1643 +#            self.ListaUt.set_focus(cni)
248.1644 +            self.LBoxL.set_focus(cni)
248.1645 +            self.ReloadDatiUser()
248.1646 +            return ''
248.1647 +        else:
248.1648 +            self.vuota()
248.1649 +            return 'left'
248.1650 +    
248.1651 +    def reloadFromLdap(self):   
248.1652 +        """ rilegge il record ldap """
248.1653 +        uid = self.AttUser.get_campo('userID')
248.1654 +        cog = self.AttUser.get_campo('userCognome')
248.1655 +        nom = self.AttUser.get_campo('userNome')
248.1656 +
248.1657 +        cn  = string.ljust(cog,10) +' '+ nom
248.1658 +        try:
248.1659 +            cni = self.usersInOrd.index(cn+uid)
248.1660 +
248.1661 +            del self.usersInOrd[cni]
248.1662 +            del self.ListaID[cni]
248.1663 +            del self.usersImmessi[uid]
248.1664 +        
248.1665 +            if self.usersRecords.has_key(uid):
248.1666 +                del self.usersRecords[uid]
248.1667 +            self.AttUser.changed = False
248.1668 +            self.load_fromldap(uid)
248.1669 +        except:
248.1670 +            self.alert('nessun utente in lista')
248.1671 +
248.1672 +    def ReloadDatiUser(self):
248.1673 +        """ rilegge i dati caricati """
248.1674 +        if len(self.usersInOrd)>0:
248.1675 +#            w,p = self.ListaUt.get_focus()
248.1676 +            w,p = self.LBoxL.get_focus()
248.1677 +            if hasattr(w,'name') and self.usersImmessi.has_key(w.name):
248.1678 +#                self.alert(w.name)
248.1679 +                uc = self.usersImmessi[w.name]
248.1680 +                for c,txt in uc.iteritems():
248.1681 +                    if c == 'changed':
248.1682 +                        self.AttUser.changed = uc['changed']
248.1683 +                    elif c == 'newPass':
248.1684 +                        self.AttUser.newPass = uc['newPass']
248.1685 +                    elif c == 'newUser':
248.1686 +                        self.AttUser.newUser = uc['newUser']
248.1687 +                    elif c == 'novalid':
248.1688 +                        self.AttUser.novalid = uc['novalid']
248.1689 +                    elif c == 'delUser':
248.1690 +                        self.AttUser.delUser = uc['delUser']
248.1691 +                    else:
248.1692 +                        self.AttUser.set_campo(c,txt)
248.1693 +                        
248.1694 +            if not self.ValidateAll():
248.1695 +                self.ftxt1.set_align_mode('center')
248.1696 +                self.ftxt1.set_text(('error','errore nei dati'))
248.1697 +            else:
248.1698 +                uid = self.AttUser.get_campo('userID')
248.1699 +                if self.usersQuota[uid][1]:
248.1700 +                    x ='QUOTA| L1:'+string.ljust(self.usersQuota[uid][1],8)+ \
248.1701 +                      '| L2:'+ string.ljust(self.usersQuota[uid][2],8)+ \
248.1702 +                      '| DSK:'+string.ljust(self.usersQuota[uid][0],8)
248.1703 +                else:
248.1704 +                    x = 'QUOTA non assegnata'
248.1705 +                self.ftxt1.set_align_mode('left')
248.1706 +                self.ftxt1.set_text(('footer',x))
248.1707 +                
248.1708 +
248.1709 +    def AddRecord(self,Force=None):
248.1710 +        """ aggiorna/aggiunge il record dell'utente in memoria """
248.1711 +        uid = self.AttUser.get_campo('userID')
248.1712 +        cog = self.AttUser.get_campo('userCognome')
248.1713 +        nom = self.AttUser.get_campo('userNome')
248.1714 +        self.usersQuota[uid] = self.get_quota(uid)
248.1715 +        
248.1716 +        # ?=quota sconosciuta +=quota superata spazio=quota ok
248.1717 +        quo = '?'
248.1718 +        if self.usersQuota[uid][1] or self.usersQuota[uid][2]:
248.1719 +            quo = ' '
248.1720 +        try:
248.1721 +            i=string.index(self.usersQuota[uid][0],'*')         
248.1722 +            quo = '+'
248.1723 +        except:
248.1724 +            pass
248.1725 +        
248.1726 +        cn  = string.ljust(cog,10) + ' ' + nom
248.1727 +        r   = string.ljust(uid,15) + quo + cn
248.1728 +
248.1729 +        self.ValidateAll()
248.1730 +        if not self.usersImmessi.has_key(uid):
248.1731 +            self.usersInOrd.append(cn+uid)
248.1732 +            self.usersInOrd.sort()
248.1733 +            k = self.usersInOrd.index(cn+uid)
248.1734 +            if Force: # in questo caso si tratta di utente esistente
248.1735 +                if not self.AttUser.novalid:
248.1736 +                    if self.AttUser.newPass:
248.1737 +                        x = NamedWrap(uid,SelText(r,'left','clip'),\
248.1738 +                            'focuspwd','selfocus')
248.1739 +                    else:
248.1740 +                        x = NamedWrap(uid,SelText(r,'left','clip'),\
248.1741 +                            'focus','selfocus')
248.1742 +                else:   
248.1743 +                    x = NamedWrap(uid,SelText(r,'left','clip'),'focuserr',\
248.1744 +                        'selfocus')
248.1745 +            else:
248.1746 +                x = NamedWrap(uid,SelText(r,'left','clip'),'focusnew',\
248.1747 +                    'selfocus')
248.1748 +                
248.1749 +            
248.1750 +            if k > len(self.ListaID):
248.1751 +                self.ListaID.append(x)
248.1752 +            else:
248.1753 +                self.ListaID.insert(k,x)
248.1754 +                
248.1755 +        else:
248.1756 +            for nw in self.ListaID:
248.1757 +                if hasattr(nw,'name') and nw.get_name() == uid:
248.1758 +                    nw.w.set_text(r)
248.1759 +                    if self.AttUser.delUser:
248.1760 +                        nw.attr='focusdel'
248.1761 +                    elif self.AttUser.newUser:
248.1762 +                        nw.attr='focusnew'
248.1763 +                    elif self.AttUser.newPass:
248.1764 +                        nw.attr='focuspwd'
248.1765 +                    elif self.AttUser.novalid:
248.1766 +                        nw.attr='focuserr'
248.1767 +                    elif self.AttUser.changed:
248.1768 +                        nw.attr='focuscha'
248.1769 +                    else:
248.1770 +                        nw.attr='focus'
248.1771 +
248.1772 +        self.usersImmessi[uid] = {}
248.1773 +        for c in self.AttUser.Campi.ordKeys:
248.1774 +            self.usersImmessi[uid][c] = self.AttUser.get_campo(c)
248.1775 +        self.usersImmessi[uid]['newUser'] = self.AttUser.newUser
248.1776 +        self.usersImmessi[uid]['newPass'] = self.AttUser.newPass
248.1777 +        self.usersImmessi[uid]['changed'] = self.AttUser.changed
248.1778 +        self.usersImmessi[uid]['delUser'] = self.AttUser.delUser
248.1779 +        if self.AttUser.newUser:
248.1780 +            self.alulinkClasse(self.usersImmessi[uid]['userClasse'])
248.1781 +        elif self.usersImmessi[uid]['userClasse'] != \
248.1782 +             self.LDAPCON.memdata[uid]['departmentNumber']:
248.1783 +            self.alulinkClasse(self.usersImmessi[uid]['userClasse'])
248.1784 +            self.alulinkClasse(self.LDAPCON.memdata[uid]['departmentNumber'])
248.1785 +        self.UserRecord(uid)
248.1786 +
248.1787 +    def alulinkClasse(self,classe):
248.1788 +        """ determina quali classi debbono essere alulinkate """
248.1789 +        try:
248.1790 +            self.alulink.index(classe)
248.1791 +        except: 
248.1792 +            self.alulink.append(classe)
248.1793 +            cc=""
248.1794 +            for c in self.alulink:
248.1795 +                cc+=c+' '
248.1796 +            self.alert('alulink: '+cc)
248.1797 +
248.1798 +    def UserRecord(self,uid):
248.1799 +        """ costruisce il record utente """
248.1800 +        rec = None
248.1801 +        xxx = self.AttUser.get_campo('userAGrp')
248.1802 +        yyy = self.AttUser.get_campo('userClasse')
248.1803 +        if yyy:
248.1804 +            if xxx:
248.1805 +                xxx1 = yyy + ',' + xxx
248.1806 +            else:
248.1807 +                xxx1 = yyy
248.1808 +            self.AttUser.set_campo('userAGrp',xxx1) 
248.1809 +
248.1810 +        if not self.AttUser.get_campo('userPass'):
248.1811 +            self.AttUser.set_campo('userPass','_UNCHANGED_')
248.1812 +            
248.1813 +        if self.AttUser.changed or self.AttUser.delUser:
248.1814 +            rec = ";".join(["%s" % self.AttUser.get_campo(c) \
248.1815 +                                for c in self.AttUser.TracRec])
248.1816 +            if self.AttUser.delUser:
248.1817 +                rec = '-'+rec
248.1818 +        else:
248.1819 +            pass
248.1820 +        if rec:
248.1821 +            self.usersRecords[uid] = rec
248.1822 +        self.AttUser.set_campo('userAGrp',xxx)  
248.1823 +#        self.alert(rec)
248.1824 +
248.1825 +    def UsersFile(self):
248.1826 +        """ salva su file i record immessi """
248.1827 +        f = open(USERS_FILE,'w')
248.1828 +        self.num_user=0
248.1829 +        for u,rec in self.usersRecords.iteritems():     
248.1830 +            self.num_user += 1
248.1831 +            f.write(rec + '\n')
248.1832 +        f.close
248.1833 +
248.1834 +    def cambiaPass(self):
248.1835 +        """ attiva la procedura di cambio password """
248.1836 +        ret = False
248.1837 +        if not self.auth.adminUsr == 'root':
248.1838 +            p  = self.LBoxP.items[1].get_edit_text()
248.1839 +            if not p:
248.1840 +                self.alert('ERRORE: password vuota\nriprova o premi ESC')
248.1841 +                self.LBoxP.items[1].set_edit_text('')
248.1842 +                self.LBoxP.items[1].set_edit_pos(0)
248.1843 +                self.columns.set_focus_column(1)
248.1844 +                return ret
248.1845 +            dn = self.LDAPCON.l.srv.get_dn(self.auth.adminUsr)
248.1846 +            try:
248.1847 +                self.LDAPCON.l.srv.bind(dn=dn,passwd=p)
248.1848 +            except:                      
248.1849 +                self.alert('ERRORE: credenziali errate\nriprova o premi ESC')
248.1850 +                self.LBoxP.items[1].set_edit_text('')
248.1851 +                self.LBoxP.items[1].set_edit_pos(0)
248.1852 +                self.columns.set_focus_column(1)
248.1853 +                del pl
248.1854 +                return ret
248.1855 +                
248.1856 +        wu = self.AttUser.Campi['userID']
248.1857 +        wp = self.AttUser.Campi['userPass']
248.1858 +        if wu.validate() and wp.validate() and not self.AttUser.newUser:
248.1859 +            p = wp.get_edit_text()
248.1860 +            u = wu.get_edit_text()
248.1861 +            if IS_DASH:
248.1862 +                CMD = 'echo "' + p + '\\n' + p + '\\n' + \
248.1863 +                    '" | smbldap-passwd '+ u
248.1864 +            
248.1865 +            else:
248.1866 +                CMD = 'echo -e "' + p + '\\n' + p + '\\n' + \
248.1867 +                    '" | smbldap-passwd '+ u
248.1868 +            
248.1869 +            r, w, e = os.popen3(CMD)
248.1870 +            cmderr = w.readlines()
248.1871 +            w.close()
248.1872 +            e.close()
248.1873 +            
248.1874 +            if len(cmderr)>3:
248.1875 +                self.alert('ERRORE NEL CAMBIAMENTO DELLA PASSWORD\n'+cmderr[3])
248.1876 +            else:   
248.1877 +                self.alert('PASSWORD CAMBIATA')
248.1878 +                self.AttUser.newPass = True
248.1879 +                self.AddRecord()
248.1880 +                ret = True
248.1881 +                
248.1882 +        else:
248.1883 +            self.alert('IMPOSSIBILE CAMBIARE LA PASSWORD\nutente e/o password non validi')
248.1884 +        return ret      
248.1885 +
248.1886 +
248.1887 +    def load_fromldap(self,uid=None):
248.1888 +        """ 
248.1889 +        trasferisce i dati ldap come se fossero acquisiti manualmente
248.1890 +        e li aggiunge alle liste interne
248.1891 +        campildap = (
248.1892 +        'dn','cn','sn','uid','gecos','givenName',
248.1893 +        'displayName','employeeNumber','employeeType',
248.1894 +        'postOfficeBox','postalCode','homePhone',
248.1895 +        'postalAddress','departmentNumber','homeDirectory,gidNumber'
248.1896 +        )
248.1897 +        """
248.1898 +        for u,d in self.LDAPCON.memdata.iteritems():            
248.1899 +            if uid == None:
248.1900 +                pass
248.1901 +            elif u != uid:
248.1902 +                continue
248.1903 +            try:
248.1904 +                user_id = string.strip(d['uid'])
248.1905 +                
248.1906 +                # recupera il maingroup MGrp
248.1907 +                all_groups = self.LDAPCON.l.get_user_groups(user_id)
248.1908 +                MGrp = all_groups[0]                        # gruppo principale
248.1909 +                CGrp = string.strip(d['departmentNumber'])  # classe
248.1910 +                if CGrp:
248.1911 +                    all_groups.remove(CGrp)                     # altri gruppi
248.1912 +                AGrp = ",".join(all_groups[1:])
248.1913 +                self.AttUser.set_campo('userMGrp',MGrp)
248.1914 +                self.AttUser.set_campo('userID',user_id)
248.1915 +                self.AttUser.set_campo('userPass','')
248.1916 +                self.AttUser.set_campo('userCognome',string.strip(d['sn']))
248.1917 +                self.AttUser.set_campo('userNome',string.strip(d['givenName']))
248.1918 +                self.AttUser.set_campo('userClasse',CGrp)
248.1919 +                self.AttUser.set_campo('userAGrp',AGrp)
248.1920 +                self.AttUser.set_campo('userSex',\
248.1921 +                                        string.strip(d['employeeType']))
248.1922 +                self.AttUser.set_campo('userCF',\
248.1923 +                                        string.strip(d['employeeNumber']))
248.1924 +                self.AttUser.set_campo('userNatoil','')
248.1925 +                self.AttUser.set_campo('userNatoa','')
248.1926 +                self.AttUser.set_campo('userNatoPr','')
248.1927 +                self.AttUser.set_campo('userNatoSt','')
248.1928 +                self.AttUser.set_campo('userInd',\
248.1929 +                                        string.strip(d['postalAddress']))
248.1930 +                self.AttUser.set_campo('userCap',string.strip(d['postalCode']))
248.1931 +                
248.1932 +                rp = re.compile('^(.*)\((.*)\)')
248.1933 +                cp = rp.match(d['postOfficeBox'])
248.1934 +                if cp:
248.1935 +                    self.AttUser.set_campo('userCitta',\
248.1936 +                                           string.strip(cp.group(1)))
248.1937 +                    self.AttUser.set_campo('userProv',string.strip(cp.group(2)))
248.1938 +                else:
248.1939 +                    self.AttUser.set_campo('userCitta',string.strip(d['postOfficeBox']))
248.1940 +                    self.AttUser.set_campo('userProv','')
248.1941 +
248.1942 +                self.AttUser.set_campo('userTel1',string.strip(d['homePhone']))
248.1943 +                self.AttUser.set_campo('userTel2','')
248.1944 +                self.AttUser.set_campo('userEmail','')
248.1945 +                self.AttUser.set_campo('userPadreC','')
248.1946 +                self.AttUser.set_campo('userPadreN','')
248.1947 +                self.AttUser.set_campo('userMadreC','')
248.1948 +                self.AttUser.set_campo('userMadreN','')
248.1949 +                self.AttUser.changed = False
248.1950 +                self.AttUser.novalid = False
248.1951 +                self.AttUser.newPass = False
248.1952 +                self.AttUser.newUser = False
248.1953 +                self.AddRecord(True)
248.1954 +            except:
248.1955 +                if self.ldapLoadErr is None:
248.1956 +                    self.ldapLoadErr = u
248.1957 +                else:   
248.1958 +                    self.ldapLoadErr += ", "+u
248.1959 +
248.1960 +            if uid == None:
248.1961 +                pass
248.1962 +            elif u == uid:
248.1963 +                break
248.1964 +        
248.1965 +        
248.1966 +    def is_new_user(self,uid):
248.1967 +        """ verifica se l'utente esiste su ldap """
248.1968 +        if not(self.LDAPCON):
248.1969 +            sys.exit()
248.1970 +        else:
248.1971 +            if self.LDAPCON.isildap_isuser(uid):
248.1972 +                self.user_exist = True
248.1973 +                self.AttUser.newUser = False
248.1974 +                self.AttUser.items[0] = blank
248.1975 +            else:
248.1976 +                self.user_exist = False 
248.1977 +                self.AttUser.newUser = True
248.1978 +                self.AttUser.items[0] = \
248.1979 +                    urwid.AttrWrap(urwid.Text("Nuovo utente",'right'),'newuser')
248.1980 +                if not self.gruppo is None:
248.1981 +                    mg = string.lower(self.AttUser.get_campo('userMGrp'))
248.1982 +                    if (mg =='alunni' or mg == 'esterni') and not \
248.1983 +                        mg == self.gruppo:
248.1984 +                        self.AttUser.set_campo('userClasse',self.gruppo)
248.1985 +
248.1986 +    def updateLdap(self):
248.1987 +        """ aggiorna ldap """
248.1988 +        self.alert('ATTENDI: aggiornamento ldap in corso...')
248.1989 +        self.LDAPCON.l.read_file(USERS_FILE) # non si passano opzioni
248.1990 +            
248.1991 +    def load_quota(self):
248.1992 +        for u,d in self.usersImmessi.iteritems():
248.1993 +            self.usersQuota[u] = self.get_quota(u)
248.1994 +            
248.1995 +    def get_quota(self,uid):
248.1996 +        ret = ['','','']
248.1997 +        # if necessario per evitare che la ricerca della quota
248.1998 +        # di un utente non ancora aggiunto a ldap e quindi inesistente
248.1999 +        # invalidi la cache nscd
248.2000 +        if self.LDAPCON.isildap_isuser(uid):
248.2001 +            CMD = 'quota ' + uid+' | grep -v File'
248.2002 +            r, w, e = os.popen3(CMD)
248.2003 +            x = w.readlines()
248.2004 +            w.close()
248.2005 +            e.close()
248.2006 +            lx=len(x)
248.2007 +            if lx>1:        
248.2008 +                if lx==2:
248.2009 +                    qr = string.split(x[lx-1])[1:4]
248.2010 +                else:   
248.2011 +                    qr = string.split(x[lx-1])[0:3]
248.2012 +                ret = qr    
248.2013 +        return ret  
248.2014 +        
248.2015 +    
248.2016 +    def set_quota(self,uid,lim):
248.2017 +        if int(lim[0])>0 and int(lim[1]) and not (
248.2018 +            lim[0] == self.usersQuota[uid][1] and 
248.2019 +            lim[1] == self.usersQuota[uid][2]):
248.2020 +            CMD = 'setquota ' + uid + ' ' + str(lim[0]) + ' ' +\
248.2021 +                str(lim[1]) + ' 0 0 -a'
248.2022 +            r, w, e = os.popen3(CMD)
248.2023 +            x = w.readlines()       
248.2024 +            w.close()
248.2025 +            e.close()
248.2026 +            self.alert('setting...\n'+CMD)
248.2027 +            time.sleep(2)
248.2028 +            self.alert('')
248.2029 +            q = self.get_quota(uid)
248.2030 +            if not (q[1] == lim[0] and q[2] == lim[1]):
248.2031 +                self.alert('IMPOSSIBILE ASSEGNARE LA QUOTA\n'+q[1]+'='+\
248.2032 +                            lim[0]+'|'+q[2]+'='+lim[1])
248.2033 +            else:
248.2034 +                self.usersQuota[uid] = q
248.2035 +            
248.2036 +#########################################################
248.2037 +
248.2038 +    
248.2039 +gruppo = None
248.2040 +if not len(sys.argv) == 2:
248.2041 +    print "USO: isi-users <gruppo>"
248.2042 +    sys.exit(1)
248.2043 +else:
248.2044 +    gruppo = sys.argv[1]
248.2045 +
248.2046 +n=AddUser(gruppo).main()
248.2047 +print "---------------------------------------------------"
248.2048 +print "salvati "+str(n)+" records in %s Good bye!" % USERS_FILE
248.2049 +print "---------------------------------------------------"
248.2050 +sys.exit(0)
   249.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   249.2 +++ b/usr/sbin/isi-wlg	Mon Apr 26 11:16:23 2010 +0200
   249.3 @@ -0,0 +1,329 @@
   249.4 +#!/usr/bin/python
   249.5 +# -*- coding: utf-8 -*-
   249.6 +
   249.7 +# This program is free software; you can redistribute it and/or modify
   249.8 +# it under the terms of the GNU General Public License as published by
   249.9 +# the Free Software Foundation; either version 2, or (at your option)
  249.10 +# any later version.
  249.11 +
  249.12 +# AUTHOR: Massimo Mancini
  249.13 +
  249.14 +"""
  249.15 +ISI-WINDOWS_LOCAL_GROUP (WLG)
  249.16 +isi-wlg -aggiunge o cancella un utente/gruppo di dominio a/da un gruppo locale 
  249.17 +          WinXP (Administrators, Power Users o altro)
  249.18 +        -cambia la password dell'Administrator del client XP
  249.19 +
  249.20 +  usage: %prog <options>
  249.21 +    -a, --add-user=add_user: utente/gruppo da aggiungere al gruppo locale XP nel formato DOMINIO\\NOME (due controbarre)
  249.22 +    -x, --canc-user=canc_user: utente/gruppo da eliminare dal gruppo locale XP
  249.23 +    -g, --local-group=local_group: agisce sul gruppo locale XP indicato
  249.24 +    -l, --labinfo=labinfo: nome dell'aula descritta in /etc/isi/labinfo.secret
  249.25 +    -P, --newlocalpwd: cambia la password all'Administrator locale XP
  249.26 +    -S, --host=host: workstation windows su cui agire (incompatibile con -l)
  249.27 +    -U, --hostadmin=hostadmin: account amministrativo sull'host nel formatp user%pwd
  249.28 +    -A, --admindom: richiede le credenziali di un amministratore di dominio
  249.29 +    -M, --maplab=maplab: <nome,range_ip> nel formato nmap; ricerca i client e compila il file di conf dell'aula [nome]
  249.30 +
  249.31 +NOTA1: esprimendo l'opzione -A le operazioni verranno svolte dall'amministratore 
  249.32 +di dominio, prescindendo quindi dalle credenziali dichiarate nel file di conf.
  249.33 +"""
  249.34 +
  249.35 +import isi
  249.36 +import sys,  os,  getpass
  249.37 +import re
  249.38 +from dry import optionparse
  249.39 +from dry.functions import execute, ExecuteError
  249.40 +
  249.41 +####-----------------------------------------COSTANTI
  249.42 +
  249.43 +# file di conf dei laboratori
  249.44 +INFOLABS="/etc/isi/labinfo.secret"
  249.45 +BORDO="-"*70    
  249.46 +# parametri
  249.47 +adc = None # amministratore di dominio%password
  249.48 +acw = None # amministratore client%password
  249.49 +pwd = None # nuova password amministrativa locale (XP)
  249.50 +wlg = None # gruppo locale windows
  249.51 +usr = None # utente o gruppo da aggiungere
  249.52 +wks = None # workstation windows
  249.53 +adc = None # credenziali amministratore di dominio
  249.54 +aula = None # eventuale aula
  249.55 +
  249.56 +# net command
  249.57 +# NETADD/DEL = net rpc group addmem|delmem wlg usr -S wks -U account_admin
  249.58 +NETADD = "net rpc group addmem %s %s -S %s -U %s"
  249.59 +NETDEL = "net rpc group delmem %s %s -S %s -U %s"
  249.60 +
  249.61 +# NETPWD = net rpc password Administrator NUOVA_PASSWORD -S wks -U account_admin
  249.62 +NETPWD = "net rpc password %s %s -S %s -U %s"
  249.63 +
  249.64 +# NETMAP = nmap -O -sS range_ip
  249.65 +NETMAP = "nmap -O -sS %s"
  249.66 +
  249.67 +
  249.68 +####----------------------------------------- FUNCTIONS
  249.69 +def crea_aula(nome, o):
  249.70 +    aula = "[%s]\n" % nome
  249.71 +    ll = [aula]
  249.72 +    print BORDO
  249.73 +    print aula
  249.74 +    for line in o.split('\n'):
  249.75 +        if line.startswith('Interesting'):
  249.76 +            print "###",line
  249.77 +            hh = line.split(' ')
  249.78 +            if len(hh)>4:
  249.79 +                host_name = hh[3]
  249.80 +                host_ip   = hh[4].replace('(', '').replace(')', '')
  249.81 +            else:
  249.82 +                host_name = 'SENZA_NOME_CHECK_DNS'
  249.83 +                host_ip   = hh[3].replace('(', '').replace(')', '')
  249.84 +                
  249.85 +        if line.startswith('Running'):
  249.86 +            host_os   = line.split(':')[1].strip()
  249.87 +            if 'Windows XP' in host_os:
  249.88 +                ll.append(host_name+'\n')
  249.89 +                print "aggiunto: %s %s %s" % (host_ip,  host_name,  host_os)
  249.90 +            else:
  249.91 +                print "scartato: %s %s %s" % (host_ip,  host_name,  host_os)
  249.92 +    if len(ll)>1:
  249.93 +        print BORDO            
  249.94 +        fl = open(INFOLABS, 'a')
  249.95 +        fl.writelines(ll)
  249.96 +        fl.close()
  249.97 +    else:
  249.98 +        alert('ATTENZIONE: aula %s non aggiunta a %s' % (nome, INFOLABS))
  249.99 +                
 249.100 +def ask_for_new_local_password():
 249.101 +    print "NUOVE CREDENZIALI AMMINISTRATIVE SUL CLIENT:"
 249.102 +    while True:
 249.103 +        ret = getpass.getpass('Nuova  password: ')
 249.104 +        re2 = getpass.getpass('Ripeti password: ')
 249.105 +        if ret == re2: 
 249.106 +            break
 249.107 +        else:
 249.108 +            print "le password non coincidono!!!"
 249.109 +    return ret
 249.110 +    
 249.111 +def ask_for_domain_admin():
 249.112 +    if opts.admindom: 
 249.113 +        print "CREDENZIALI DI UN AMMINISTRATORE DI DOMINIO"
 249.114 +        ad_nome = raw_input("Login (administrator): ")
 249.115 +        ad_pass = getpass.getpass('Password: ')
 249.116 +        if not ad_nome: 
 249.117 +            ret = 'administrator%'+ad_pass
 249.118 +        else:
 249.119 +            ret = ad_nome+'%'+ad_pass
 249.120 +    return ret
 249.121 +
 249.122 +def alert(msg):
 249.123 +    print "%s\n%s\n%s\n" % (BORDO, msg, BORDO)
 249.124 +    
 249.125 +def setting_pwd(net_cmd, usr, pwd, wks,  adc,  aula ):
 249.126 +    """ setting delle password amministrative dei client"""
 249.127 +    #questa op.deve ridefinire la descrizione dell'aula    
 249.128 +    #intestazione della sezione nel file di configurazione
 249.129 +    #se l'operazione ordinata e' su tutta l'aula
 249.130 +    wks_new = []
 249.131 +    if aula: 
 249.132 +        if adc:
 249.133 +            wks_new.append([aula+usr+"%"+pwd])
 249.134 +    for w in wks:
 249.135 +        # se viene passato administrator%password di dominio
 249.136 +        if adc: 
 249.137 +            adm = adc
 249.138 +        else:
 249.139 +            adm = "%s/%s" % (w[0], w[1])
 249.140 +            
 249.141 +        cmd = net_cmd % (usr, pwd, w[0], adm)
 249.142 +        print "elaboro %s su %s..." % (usr, w[0]), 
 249.143 +        r, o, e = execute(cmd)
 249.144 +        if e:
 249.145 +            err = e.split(':')
 249.146 +            if len(err)>1:
 249.147 +                esito = err[1].strip(' ')
 249.148 +            else:
 249.149 +                esito = e
 249.150 +        else: 
 249.151 +            esito = 'OK'
 249.152 +        if adc:           
 249.153 +            wks_new.append([w[0], '', esito]) 
 249.154 +        else:
 249.155 +            wks_new.append([w[0], usr+'%'+pwd, esito]) 
 249.156 +        print esito
 249.157 +        
 249.158 +    # adesso deve rimettere a posto il file di configurazione
 249.159 +    # ci sono due casi: aula o singola macchina
 249.160 +    #FIXME
 249.161 +    fl = open(INFOLABS, 'r')
 249.162 +    ll = []
 249.163 +    aula_trovata = False
 249.164 +    #TODO: tenere conto che su qualche macchina il comando potrebbe non funzionare
 249.165 +    for line in fl:
 249.166 +        line = line.strip(' ')
 249.167 +        if aula and line.startswith(aula):
 249.168 +            aula_trovata = True
 249.169 +            for w in wks_new: ll.append(w[0]+'\n')
 249.170 +        else:
 249.171 +            if aula_trovata and line.startswith('['): # next aula
 249.172 +                aula_trovata = False
 249.173 +            if aula_trovata:
 249.174 +                # salta tutte le righe relative all'aula
 249.175 +                pass
 249.176 +            else:
 249.177 +                if not aula and line.startswith(wks[0][0]):
 249.178 +                    line = "%s;%s\n" % (wks[0][0],usr+'%'+pwd)
 249.179 +                ll.append(line)
 249.180 +    fl.close()
 249.181 +    fl = open(INFOLABS, 'w')
 249.182 +    # il file di conf e' riscritto (ogni riga e' gia' terminata da \n)
 249.183 +    fl.writelines(ll)
 249.184 +    fl.close()
 249.185 +    
 249.186 +    
 249.187 +def setting_wlg(net_cmd, wlg, usr, wks,  adc ): 
 249.188 +    """ modifica la composizione di un gruppo locale"""
 249.189 +    for w in wks:
 249.190 +        # se viene passato l'amministratore di dominio....
 249.191 +        if adc: adm = adc
 249.192 +        else:   adm = "%s/%s" % (w[0], w[1])
 249.193 +        cmd = net_cmd % (wlg, usr, w[0], adm)
 249.194 +        print "elaboro %s su %s..." % (usr, w[0]), 
 249.195 +        r, o, e = execute(cmd)
 249.196 +        if e:
 249.197 +            err = e.split(':')
 249.198 +            if len(err)>1: print err[1].strip(' ')
 249.199 +            else:          print e
 249.200 +        else:              print "OK!"
 249.201 + 
 249.202 +def mapping_lab(maplab):
 249.203 +    if not os.path.isfile('usr/bin/nmap'):
 249.204 +        alert('ERRORE: nmap mancante (apt-get install nmap)')
 249.205 +    else:
 249.206 +        try:
 249.207 +            nome, range_ip = maplab.split(',')
 249.208 +            cmd = 'grep %s %s' % (nome, INFOLABS)
 249.209 +            r, o, e = execute(cmd)
 249.210 +            if not o: # se grep non trova nulla
 249.211 +                cmd = NETMAP % range_ip
 249.212 +                r, o, e = execute(cmd)
 249.213 +                if e:
 249.214 +                    print "ERRORE %s" % e
 249.215 +                else:
 249.216 +                    crea_aula(nome, o)
 249.217 +            else:
 249.218 +                alert('ERRORE: aula già definita, cambiare nome')
 249.219 +        except e:
 249.220 +            alert("ERRORE: errore di formato in %s %s" % (maplab, e))
 249.221 +def read_aula_description(aula):
 249.222 +    wks = []
 249.223 +    admin_account = None
 249.224 +    is_aula = False
 249.225 +    fl = open(INFOLABS, 'r')
 249.226 +    for line in fl:
 249.227 +        line = line.strip('\n')
 249.228 +        line = line.strip(' ')
 249.229 +        if len(line)>0 and not line.startswith('#'):
 249.230 +            if is_aula and not line.startswith('['):
 249.231 +                ww = line.split(';')
 249.232 +                if len(ww)==1:
 249.233 +                    if admin_account: 
 249.234 +                        ww.append(admin_account)
 249.235 +                    else:
 249.236 +                        ww.append('ACCOUNT_AMMINISTRATIVO_MANCANTE')
 249.237 +                wks.append(ww)
 249.238 +            if aula in line:
 249.239 +                is_aula = True
 249.240 +                aa = line.split(']')
 249.241 +                if len(aa)>1: admin_account = aa[1]
 249.242 +            elif "[" in line: is_aula = False
 249.243 +    fl.close()
 249.244 +    return wks
 249.245 +
 249.246 +####----------------------------------------- PROGRAM
 249.247 +opts, args = optionparse.parse(__doc__)
 249.248 +
 249.249 +if opts.local_group:    wlg = opts.local_group
 249.250 +
 249.251 +if opts.maplab:
 249.252 +    mapping_lab(opts.maplab)
 249.253 +    sys.exit()
 249.254 +
 249.255 +if opts.newlocalpwd:    
 249.256 +    # questa richiesta e' prioritaria e alternativa alle altre
 249.257 +    net_cmd = NETPWD
 249.258 +    net_msg = 'Cambio la password amministrativa locale'
 249.259 +    usr = "Administrator"
 249.260 +elif opts.add_user: 
 249.261 +    net_cmd = NETADD
 249.262 +    net_msg = 'AGGIUNGO [%s] al gruppo locale [%s]'  
 249.263 +    usr = opts.add_user
 249.264 +elif opts.canc_user: 
 249.265 +    net_cmd = NETDEL
 249.266 +    net_msg = 'ELIMINO [%s] dal gruppo locale [%s]'
 249.267 +    usr = opts.canc_user
 249.268 +else:
 249.269 +    if not opts.newlocalpwd:
 249.270 +        alert("ERRORE: devi specificare -a UTENTE  oppure  -x UTENTE")
 249.271 +    else:
 249.272 +        alert("ERRORE: non hai richiesto nessuna operazione [-a|-x|-P]!!!")
 249.273 +    print __doc__
 249.274 +    sys.exit()
 249.275 + 
 249.276 +if opts.host and opts.labinfo:
 249.277 +    alert("ERRORE: le opzioni -l e -S sono incompatibili")
 249.278 +    print __doc__
 249.279 +    sys.exit()
 249.280 +    
 249.281 +if opts.host: 
 249.282 +    if opts.hostadmin:
 249.283 +        wks = [[opts.host, opts.hostadmin]]
 249.284 +    elif opts.admindom:
 249.285 +        wks = [[opts.host, 'DOMAIN_ADMIN']]
 249.286 +
 249.287 +if opts.labinfo:
 249.288 +    if os.path.isfile(INFOLABS):
 249.289 +        aula = "[%s]" % opts.labinfo
 249.290 +        wks = read_aula_description(aula)
 249.291 +        if len(wks) == 0:
 249.292 +            alert("ERRORE: descrizione aula %s mancante in %s" % (aula, INFOLABS))
 249.293 +            sys.exit()                    
 249.294 +    else:
 249.295 +        alert("ERRORE: file di conf. dei laboratori mancante (%s)" % INFOLABS)
 249.296 +        sys.exit()
 249.297 +        
 249.298 +err = []
 249.299 +
 249.300 +if not opts.newlocalpwd and wlg is None: 
 249.301 +    err.append("   gruppo locale non dichiarato")
 249.302 +if usr is None: 
 249.303 +    err.append("   utente o gruppo da aggiungere mancante")
 249.304 +if wks is None: 
 249.305 +    err.append("   macchina bersaglio non dichiarata o credenziali mancanti")
 249.306 +    
 249.307 +if len(err) == 0:
 249.308 +    print BORDO
 249.309 +    if opts.newlocalpwd: print "CAMBIO PASSWORD AMMINISTRATIVA"
 249.310 +    else:                print (net_msg % (usr, wlg))
 249.311 +    if opts.labinfo:     print "delle macchine dell'aula %s:" % opts.labinfo
 249.312 +    else:                print 'delle macchine:'
 249.313 +    for w in wks:
 249.314 +        if "MANCANTE" in w[1]: print "   %s %s" % (w[0], w[1])
 249.315 +        else:                  print "   %s" % w[0]
 249.316 +    print BORDO
 249.317 +    ret=raw_input('Confermi (s/n)?')
 249.318 +    if ret and ret in 'sS':
 249.319 +        if opts.admindom: adc = ask_for_domain_admin()
 249.320 +        if opts.newlocalpwd: 
 249.321 +            pwd = ask_for_new_local_password()
 249.322 +            setting_pwd(net_cmd, usr, pwd, wks, adc,  aula)
 249.323 +        else:        
 249.324 +            setting_wlg(net_cmd, wlg, usr, wks,  adc)
 249.325 +    else:
 249.326 +        alert("operazione NON effettuata")
 249.327 +else:
 249.328 +    print "Elaborazione impossibile.\nERRORI:"
 249.329 +    for e in err: print e
 249.330 +
 249.331 +print BORDO
 249.332 +    
   250.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   250.2 +++ b/usr/sbin/rmlogonvar	Mon Apr 26 11:16:23 2010 +0200
   250.3 @@ -0,0 +1,10 @@
   250.4 +#!/bin/bash
   250.5 +
   250.6 +# +-------------------------------------------------+
   250.7 +# � 2002-2005 ReteIsi / www.reteisi.org 
   250.8 +# +-------------------------------------------------+
   250.9 +# $Id: rmlogonvar 43 2021-10-30 07:35:24Z max $
  250.10 +
  250.11 +
  250.12 +VARDIR="/home/samba/netlogon"
  250.13 +rm $VARDIR/logonvar_$1
   251.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   251.2 +++ b/usr/sbin/setlogonvar	Mon Apr 26 11:16:23 2010 +0200
   251.3 @@ -0,0 +1,48 @@
   251.4 +#!/bin/bash
   251.5 +
   251.6 +# +-------------------------------------------------+
   251.7 +# © 2002-2008 ReteIsi / www.reteisi.org
   251.8 +# +-------------------------------------------------+
   251.9 +# This program is free software; you can redistribute it and/or modify
  251.10 +# it under the terms of the GNU General Public License as published by
  251.11 +# the Free Software Foundation; either version 2, or (at your option)
  251.12 +# any later version.
  251.13 +
  251.14 +# AUTHOR: Massimo Mancini
  251.15 +
  251.16 +# E' possibile aggiungere l'utente che si logga
  251.17 +# o la sua classe ad un gruppo locale windows (WLG)
  251.18 +# il WLG di destinazione e' gestito dal file di conf
  251.19 +# /etc/isi/wlg.secret
  251.20 +
  251.21 +USR=$1
  251.22 +GRP=$2
  251.23 +CLI=$3
  251.24 +
  251.25 +VARDIR="/home/samba/netlogon"
  251.26 +WWWDIR="/var/www/sambalogon"
  251.27 +VARFILE=$VARDIR/logonvar_$CLI
  251.28 +
  251.29 +if [ -f $VARFILE ] ; then
  251.30 +        if ! egrep -q "^$1," $VARFILE ; then
  251.31 +                rm $VARFILE
  251.32 +        fi
  251.33 +fi
  251.34 +
  251.35 +if [ ! -f $VARFILE ] ; then
  251.36 +        classe=$(isi-getattr $USR departmentNumber)
  251.37 +
  251.38 +        # WindowsLocalGroups
  251.39 +        WLG=$(setlogonwlg $USR $CLI $classe)
  251.40 +
  251.41 +        quotasup=$(quota $USR | grep \*)
  251.42 +        DT=$(date +%y%m%d)
  251.43 +        D1=$(date +%y-%m-%d)
  251.44 +        TM=$(date +%H:%M)
  251.45 +        [ -z $quotasup ] && quotasup="INQUOTA" || quotasup="FUORIQUOTA"
  251.46 +
  251.47 +        CHI="$USR,$GRP,$classe,$quotasup"
  251.48 +        CHI_QUANDO="$D1;$TM;$1;$GRP;$classe;$quotasup;$CLI;$WLG"
  251.49 +        echo $CHI > $VARFILE
  251.50 +        echo $CHI_QUANDO >> $WWWDIR/logon-$DT
  251.51 +fi
   252.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   252.2 +++ b/usr/sbin/setlogonwlg	Mon Apr 26 11:16:23 2010 +0200
   252.3 @@ -0,0 +1,73 @@
   252.4 +#!/bin/bash
   252.5 +
   252.6 +# This program is free software; you can redistribute it and/or modify
   252.7 +# it under the terms of the GNU General Public License as published by
   252.8 +# the Free Software Foundation; either version 2, or (at your option)
   252.9 +# any later version.
  252.10 +
  252.11 +# AUTHORS: Massimo Mancini
  252.12 +#
  252.13 +# SCOPO:aggiungere|eliminare un utente o un gruppo a|da un gruppo locale
  252.14 +#   sul client windows da cui si sta effettuando il logon
  252.15 +
  252.16 +
  252.17 +function get_var (){
  252.18 +    STATO=$(echo $1 | awk -F":" '{print $1}')
  252.19 +    WLG=$(echo $1 | awk -F":" '{print $3}')
  252.20 +    WKS=$(echo $1 | awk -F":" '{print $4}')
  252.21 +    PWD=$(echo $1 | awk -F":" '{print $5}')
  252.22 +}
  252.23 +
  252.24 +function wlg_op_on () {
  252.25 +    local USR
  252.26 +    [ -z $1 ] && return
  252.27 +    USR=$1
  252.28 +    OPR=""
  252.29 +    STATO=''
  252.30 +    WLG=''
  252.31 +    WKS=''
  252.32 +    PWD=''
  252.33 +    DENY=$(egrep -i "^DENY.*:$USR:" $SECRET)
  252.34 +    if [ -z $DENY ] ; then
  252.35 +        ALLOW=$(egrep -i "^ALLOW.*:$USR:" $SECRET)
  252.36 +        if [ ! -z $ALLOW ]; then
  252.37 +            OPR='addmem'
  252.38 +            get_var $ALLOW
  252.39 +        fi
  252.40 +    else
  252.41 +        OPR='delmem'
  252.42 +        get_var $DENY
  252.43 +    fi
  252.44 +
  252.45 +    if [ -z $USR ] || [ -z $CLI ] || [ -z $OPR ] || [ -z $WLG ] || [ -z $WKS ] || [ -z $PWD ] ; then
  252.46 +        ret=""
  252.47 +    else
  252.48 +        # check sulla macchina dell'utente
  252.49 +        if ! echo $CLI | egrep -q $WKS; then
  252.50 +            ret="no_on_this_host"
  252.51 +        else
  252.52 +            ERR=$(net rpc group $OPR $WLG $USR -U "$CLI/$PWD" -S $CLI 2>&1)
  252.53 +            [ "$?" = "0" ] && ret="$OPR:$WLG:$USR" || ret="$ERR"
  252.54 +        fi  
  252.55 +    fi      
  252.56 +    echo $ret
  252.57 +}
  252.58 +
  252.59 +###### ------------program--------------------
  252.60 +
  252.61 +USR=$1  # utente
  252.62 +CLI=$2  # client windows (nomehost)
  252.63 +GRP=$3  # gruppo di dominio (tipicamente una classe) - può non esserci
  252.64 +
  252.65 +# file di configurazione
  252.66 +SECRET="/etc/isi/wlg.secret" 
  252.67 +if [ -f $SECRET ] ; then
  252.68 +    ret=""
  252.69 +    ret_u=$(wlg_op_on $USR)
  252.70 +    ret_g=$(wlg_op_on $GRP)
  252.71 +    ret="$ret_u $ret_g" 
  252.72 +else
  252.73 +    ret="no_/etc/wlg.secret"
  252.74 +fi      
  252.75 +echo $ret
  252.76 +
   253.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   253.2 +++ b/usr/share/WinActivePerl/lib/ISI/Logon.pm	Mon Apr 26 11:16:23 2010 +0200
   253.3 @@ -0,0 +1,1461 @@
   253.4 +# +-------------------------------------------------+
   253.5 +# � 2002-2005 ReteIsi / www.reteisi.org 
   253.6 +# +-------------------------------------------------+
   253.7 +# $Id: Logon.pm 250 2021-09-24 16:00:13Z max $
   253.8 +
   253.9 +### DEFINIZIONE PACKAGE
  253.10 +# Copyright: Sandro Dentella - Massimo Mancini, Marco Vaninetti Aug 2004-2005
  253.11 +# This program is free software; you can redistribute it and/or modify
  253.12 +# it under the terms of the GNU General Public License as published by
  253.13 +# the Free Software Foundation; either version 2, or (at your option)
  253.14 +# any later version.
  253.15 +
  253.16 +package ISI::Logon;
  253.17 +
  253.18 +BEGIN {
  253.19 +    use Exporter   ();
  253.20 +    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
  253.21 +
  253.22 +    # set the version for version checking
  253.23 +    # if using RCS/CVS, this may be preferred
  253.24 +    $VERSION = sprintf "%d.%03d", q$Revision: 250 $ =~ /(\d+)/g;
  253.25 +
  253.26 +    @ISA         = qw(Exporter Autoload Win32::TieRegistry);
  253.27 +    @EXPORT      = qw(&version &ReadConf &OsName &WinPol9x &opgruppo 
  253.28 +            &IsWin9x &GetInfoLogon &WinMsgBox &WinSet &DbgClose);
  253.29 +}
  253.30 +
  253.31 +### INIZIO CODICE
  253.32 +
  253.33 +use WIN32; 
  253.34 +use Win32::TieRegistry; $Registry->Delimiter("/");
  253.35 +
  253.36 +#use strict;
  253.37 +$DBG = 0 ;  # attiva modo DEBUG
  253.38 +
  253.39 +$OUTPUT="";
  253.40 +@CMD=(); 
  253.41 +
  253.42 +@DscType=qw(REG_NONE REG_SZ REG_EXPAND_SZ REG_BINARY REG_DWORD);
  253.43 +%ValType=(REG_NONE      => 0,
  253.44 +        REG_SZ        => 1,
  253.45 +        REG_EXPAND_SZ => 2,
  253.46 +        REG_BINARY    => 3,
  253.47 +        REG_DWORD     => 4);
  253.48 +
  253.49 +
  253.50 +### CHIAVI DI REGISTRO
  253.51 +# Formato descrizione array chiavi di registro: 
  253.52 +
  253.53 +# @nome = ( keyroot;,
  253.54 +#           ValueName=ValueType:default);
  253.55 +
  253.56 +# l'idea e` che per produrre un certo settaggio di registro
  253.57 +# ci si limita alla conf della chiave senza  ulteriori interventi sul codice
  253.58 +# Tenere presente che per attivare certe funzioni  occorre definire 
  253.59 +# delle chiavi con certi valori ma per disabilitarle occorre cancellare
  253.60 +# la chiave che contiene quelle variabili (DELKEY) o cancellare solo
  253.61 +# le variabili (values) contenuti nella chiave (DELVAL); 
  253.62 +# in altri casi l'on/off della  funzionalita` di ottiene settando a 0 o a 1 la
  253.63 +# variabile corrispondente
  253.64 +
  253.65 +
  253.66 +
  253.67 +### nome netbios del client 
  253.68 +#$K_CLIENTNAME = "LMachine/System/CurrentControlSet/Services/VxD/VNETSUP/";
  253.69 +
  253.70 +
  253.71 +### WinSet IE - start page
  253.72 +@K_IEMAIN     = ("CUser/Software/Microsoft/Internet Explorer/Main/",
  253.73 +                "Start__Page=REG_SZ:");
  253.74 +
  253.75 +### WinSet - proxy
  253.76 +@K_INTNETSET  = ("CUser/Software/Microsoft/Windows/CurrentVersion/Internet Settings/",
  253.77 +                "ProxyEnable=REG_DWORD:0x00000001",
  253.78 +                "EnableAutodial=REG_DWORD:0x00000000",
  253.79 +                "EnableHttp1_1=REG_DWORD:0x00000001",
  253.80 +                "ProxyHttp1.1=REG_DWORD:0x00000001",
  253.81 +                "ProxyOverride=REG_SZ:<local>",
  253.82 +                "ProxyServer=REG_SZ:");
  253.83 +
  253.84 +### WinSet - profile
  253.85 +@K_NOPROFILE  = ("CUser/Software/Microsoft/Windows NT/CurrentVersion/Winlogon/",
  253.86 +        "ExcludeProfileDirs=REG_SZ:''");
  253.87 +
  253.88 +### WinSet - no_local_profile (Disable Local Caching of Domain User Profiles)
  253.89 +@K_NOLOCALPROFILE1 = ("LMachine/Software/Microsoft/Windows NT/CurrentVersion/Winlogon/",
  253.90 +        "DeleteRoamingCache=REG_DWORD:0x00000001");
  253.91 +
  253.92 +@K_NOLOCALPROFILE2 = ("LMachine/Software/Policies/Microsoft/Windows/",
  253.93 +        "DeleteRoamingCache=REG_DWORD:0x00000001");
  253.94 +
  253.95 +### WinSet - document_folder (_CDOC viene decodificato in C:\Documenti)
  253.96 +@K_DOCFOLDER1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
  253.97 +        "Personal=REG_SZ:_CDOC",
  253.98 +        "My__Picture=REG_SZ:_CDOC\Immagini",
  253.99 +        "My__Music=REG_SZ:_CDOC\Musica",
 253.100 +        "My__Video=REG_SZ:_CDOC\Video");
 253.101 +
 253.102 +@K_DOCFOLDER2 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/Shell Folders/",
 253.103 +        "Personal=REG_SZ:_CDOC",
 253.104 +        "My__Picture=REG_SZ:_CDOC\Immagini",
 253.105 +        "My__Music=REG_SZ:_CDOC\Musica",
 253.106 +        "My__Video=REG_SZ:_CDOC\Video");
 253.107 +
 253.108 +
 253.109 +# WinSet - last-user (winXP)
 253.110 +@K_LASTUSR_ON = ("LMachine/Software/Microsoft/Windows/CurrentVersion/policies/system/",
 253.111 +        "dontdisplaylastusername=REG_DWORD:0x00000000");
 253.112 +
 253.113 +@K_LASTUSR_OFF= ("LMachine/Software/Microsoft/Windows/CurrentVersion/policies/system/",
 253.114 +        "dontdisplaylastusername=REG_DWORD:0x00000001");
 253.115 +
 253.116 +### WinPol - last-user (win9X, al momento funziona solo se � installato Tweakui)
 253.117 +@K_LASTUSER_OFF = ("LMachine/Software/Microsoft/Windows/CurrentVersion/Winlogon/",
 253.118 +        "DontDisplayLastUserName=REG_SZ:1");
 253.119 +@K_LASTUSER_ON = ("LMachine/Software/Microsoft/Windows/CurrentVersion/Winlogon/",
 253.120 +        "DontDisplayLastUserName=REG_SZ:0");
 253.121 +
 253.122 +### WinSet - sync
 253.123 +@K_SYNC_ON  = ("CUser/Software/Microsoft/Windows/CurrentVersion/NetCache/",
 253.124 +        "SyncAtLogoff=REG_DWORD:0x00000001",
 253.125 +        "SyncAtLogon=REG_DWORD:0x00000001");
 253.126 +@K_SYNC_OFF  = ("CUser/Software/Microsoft/Windows/CurrentVersion/NetCache/",
 253.127 +        "SyncAtLogoff=REG_DWORD:0x00000000",
 253.128 +        "SyncAtLogon=REG_DWORD:0x00000000");
 253.129 +
 253.130 +### winset  sezione 'iepasswordcache'  
 253.131 +
 253.132 +@K_IEPASSWORDCACHING_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Internet Settings/",
 253.133 +        "DisablePasswordCaching=REG_DWORD:0x00000001");
 253.134 +
 253.135 +@K_IEPASSWORDCACHING_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Internet Settings/",
 253.136 +        "DisablePasswordCaching=REG_DWORD:0x00000001");
 253.137 +
 253.138 +        
 253.139 +### winset  sezione 'autorun'  
 253.140 +
 253.141 +@K_AUTORUN_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.142 +        "NoDriveTypeAutoRun=REG_DWORD:0x91");
 253.143 +        
 253.144 +# policies win98  sezione 'clearpol' - elimina gruppodll e altre restrizioni (non settabile)
 253.145 +@K_CLEAR_D1   = ("LMachine/Network/Logon/",
 253.146 +        "PolicyHandler=REG_SZ:''");
 253.147 +
 253.148 +@K_CLEAR_D2   = ("LMachine/System/CurrentControlSet/Services/MSNP32/NetworkProvider/",
 253.149 +        "GroupFcn=REG_SZ:''");
 253.150 +
 253.151 +@K_CLEAR_D3   = ("LMachine/System/CurrentControlSet/Services/NWNP32/");
 253.152 +
 253.153 +@K_CLEAR_A1   = ("LMachine/Software/Microsoft/Windows/CurrentVersion/Setup/OptionalComponents/GroupPol/",
 253.154 +        "INF=REG_SZ:grouppol.inf",
 253.155 +        "Installed=REG_SZ:0",
 253.156 +        "Section=REG_SZ:Group_Pol");
 253.157 +        
 253.158 +# policies win98  sezione 'pwdcaching' - elimina la cache delle password (non settabile)
 253.159 +@K_PWDCACHING   = ("LMachine/Software/Microsoft/Windows/CurrentVersion/Policies/Network/",
 253.160 +        "DisablePwdCaching=REG_DWORD:1");
 253.161 +        
 253.162 +
 253.163 +# policies win98  sezione 'shell_run'
 253.164 +@K_NOCPAN1_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/RestrictRun/");
 253.165 +@K_NOCPAN1_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/RestrictRun/");
 253.166 +
 253.167 +# policies win98  sezione 'nosetfolder'
 253.168 +@K_NOCPAN2_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.169 +        "NoSetFolders=REG_DWORD:0x00000001");
 253.170 +@K_NOCPAN2_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.171 +        "NoSetFolders=REG_DWORD:0x00000001");
 253.172 +        
 253.173 +### policies win98  sezione 'nodrive'
 253.174 +@K_NODRIVE_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.175 +        "NoDrives=REG_DWORD:67108863");
 253.176 +@K_NODRIVE_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.177 +        "NoDrives=REG_DWORD:67108863");
 253.178 +        
 253.179 +### policies win98  sezione 'nodrivec'
 253.180 +@K_NODRIVEC_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.181 +        "NoDrives=REG_BINARY:04,00,0,00");
 253.182 +@K_NODRIVEC_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.183 +        "NoDrives=REG_BINARY:04,00,0,00");
 253.184 +            
 253.185 +### policies win98  sezione 'nofind'
 253.186 +@K_NOFIND_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.187 +        "NoFind=REG_DWORD:0x00000001");
 253.188 +@K_NOFIND_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.189 +        "NoFind=REG_DWORD:0x00000001");
 253.190 +        
 253.191 +### policies win98  sezione 'nohistory'
 253.192 +@K_NOHISTORY1_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.193 +        "ClearRecentDocsOnExit=REG_BINARY:01,00,00,00");
 253.194 +@K_NOHISTORY1_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.195 +        "ClearRecentDocsOnExit=REG_BINARY:01,00,00,00");
 253.196 +@K_NOHISTORY2_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.197 +        "NoRecentDocsHistory=REG_BINARY:01,00,00,00");
 253.198 +@K_NOHISTORY2_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.199 +        "NoRecentDocsHistory=REG_BINARY:01,00,00,00");
 253.200 +        
 253.201 +### policies win98  sezione 'noactivedesktop'
 253.202 +@K_NOACTIVED_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.203 +        "NoActiveDesktop=REG_BINARY:01,00,00,00",
 253.204 +        "NoActiveDesktopChanges=REG_BINARY:01,00,00,00",
 253.205 +        "NoSetActiveDesktop=REG_BINARY:01,00,00,00");
 253.206 +@K_NOACTIVED_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.207 +        "NoActiveDesktop=REG_BINARY:01,00,00,00",
 253.208 +        "NoActiveDesktopChanges=REG_BINARY:01,00,00,00",
 253.209 +        "NoSetActiveDesktop=REG_BINARY:01,00,00,00");
 253.210 +        
 253.211 +# policies win98  sezione 'access'
 253.212 +@K_NETLOGON1   = ("LMachine/Network/Logon/",
 253.213 +        "UserProfiles=REG_DWORD:1",
 253.214 +        "UseHomeDirectory=REG_DWORD:1",
 253.215 +        "MustBeValidated=REG_DWORD:1");
 253.216 +
 253.217 +@K_NETLOGON2   = ("LMachine/Software/Microsoft/Windows/CurrentVersion/Winlogon/",
 253.218 +        "LegalNoticeCaption=REG_SZ:Avvertenza",
 253.219 +        "LegalNoticeText=REG_SZ:Accesso riservato agli utenti autorizzati.");
 253.220 +
 253.221 +
 253.222 +### policies win98  sezione 'net' - ON setting, OFF DELKEY
 253.223 +@K_NONET_DU   = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Network/",
 253.224 +                "NoNetSetup=REG_DWORD:0x00000001",
 253.225 +                "NoNetSetupIDPage=REG_DWORD:0x00000001",
 253.226 +                "NoNetSetupSecurityPage=REG_DWORD:0x00000001");
 253.227 +            
 253.228 +@K_NONET_CU   = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Network/",
 253.229 +                "NoNetSetup=REG_DWORD:0x00000001",
 253.230 +                "NoNetSetupIDPage=REG_DWORD:0x00000001",
 253.231 +                "NoNetSetupSecurityPage=REG_DWORD:0x00000001");
 253.232 +
 253.233 +### policies win98  sezione 'screen' - ON setting, OFF DELVAL
 253.234 +@K_SCREEN_DU  = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/System/",
 253.235 +        "NoDispAppearancePage=REG_DWORD:0x00000000",
 253.236 +        "NoDispBackgroundPage=REG_DWORD:0x00000000",
 253.237 +        "NoDispCPL=REG_DWORD:0x00000000",
 253.238 +        "NoDispScrSavPage=REG_DWORD:0x00000000",
 253.239 +        "NoDispSettingsPage=REG_DWORD:0x00000001");
 253.240 +
 253.241 +@K_SCREEN_CU  = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/System/",
 253.242 +        "NoDispAppearancePage=REG_DWORD:0x00000000",
 253.243 +        "NoDispBackgroundPage=REG_DWORD:0x00000000",
 253.244 +        "NoDispCPL=REG_DWORD:0x00000000",
 253.245 +        "NoDispScrSavPage=REG_DWORD:0x00000000",
 253.246 +        "NoDispSettingsPage=REG_DWORD:0x00000001");
 253.247 +
 253.248 +### policies win98  sezione 'printer' - ON setting, OFF DELVAL
 253.249 +@K_NOSTP_DU   = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.250 +                "NoAddPrinter=REG_DWORD:0x00000001",
 253.251 +                "NoDeletePrinter=REG_DWORD:0x00000001",
 253.252 +                "NoPrinterTabs=REG_DWORD:0x00000001");
 253.253 +
 253.254 +@K_NOSTP_CU   = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.255 +                "NoAddPrinter=REG_DWORD:0x00000001",
 253.256 +                "NoDeletePrinter=REG_DWORD:0x:00000001",
 253.257 +                "NoPrinterTabs=REG_DWORD:0x00000001");
 253.258 +
 253.259 +### policies win98  sezione 'passwd'  - ON setting, OFF DELVAL
 253.260 +@K_CHPWD_DU    = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/System/",
 253.261 +        "NoAdminPage=REG_DWORD:0x00000001",
 253.262 +        "NoProfilePage=REG_DWORD:0x00000001");
 253.263 +
 253.264 +@K_CHPWD_CU    = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/System/",
 253.265 +        "NoAdminPage=REG_DVWORD:0x00000001",
 253.266 +        "NoProfilePage=REG_DWORD:0x00000001");
 253.267 +
 253.268 +### policies win98  sezione 'system'  - ON setting, OFF DELVAL
 253.269 +@K_SYS_DU      = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/System/",
 253.270 +        "NoConfigPage=REG_DWORD:0x00000001",
 253.271 +        "NoDevMgrPage=REG_DWORD:0x00000001",
 253.272 +        "NoFileSysPage=REG_DWORD:0x00000001",
 253.273 +        "NoVirtMemPage=REG_DWORD:0x00000001");
 253.274 +
 253.275 +@K_SYS_CU      = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/System/",
 253.276 +        "NoConfigPage=REG_DWORD:0x00000001",
 253.277 +        "NoDevMgrPage=REG_DWORD:0x00000001",
 253.278 +        "NoFileSysPage=REG_DWORD:0x00000001",
 253.279 +        "NoVirtMemPage=REG_DWORD:0x00000001");
 253.280 +
 253.281 +### policies win98  sezione 'shell-esegui'  - ON setting, OFF DELVAL
 253.282 +@K_SHRUN_DU    = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.283 +        "NoRun=REG_DWORD:0x00000001");
 253.284 +
 253.285 +@K_SHRUN_CU    = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.286 +        "NoRun=REG_DWORD:0x00000001");
 253.287 +
 253.288 +### policies win98  sezione 'shell-noregtools'  - ON setting, OFF DELVAL
 253.289 +
 253.290 +@K_SHRTOOLS_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/System/",
 253.291 +        "DisableRegistryTools=REG_DWORD:0x00000001");
 253.292 +
 253.293 +@K_SHRTOOLS_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/System/",
 253.294 +        "DisableRegistryTools=REG_DWORD:0x00000001");
 253.295 +
 253.296 +### policies win98  sezione 'shell-winoldapp'  - ON setting, OFF DELVAL
 253.297 +
 253.298 +@K_SHOLDAPP_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/WinOldApp/",
 253.299 +        "Disabled=REG_DWORD:0x00000001",
 253.300 +        "NoRealMode=REG_DWORD:0x00000001");
 253.301 +
 253.302 +@K_SHOLDAPP_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/WinOldApp/",
 253.303 +        "Disabled=REG_DWORD:0x00000001",
 253.304 +        "NoRealMode=REG_DWORD:0x00000001");
 253.305 +
 253.306 +### policies win98  sezione 'nosavesettings'  - ON setting, OFF DELVAL
 253.307 +
 253.308 +@K_NOSAVESETTINGS_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.309 +        "NoSaveSettings=REG_BINARY:01,00,00,00");
 253.310 +
 253.311 +@K_NOSAVESETTINGS_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer/",
 253.312 +        "NoSaveSettings=REG_BINARY:01,00,00,00");
 253.313 +        
 253.314 +### policies win98  sezione 'iecachedays'  
 253.315 +
 253.316 +@K_IECACHEDAYS_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/Internet Settings/Url History",
 253.317 +        "DaysToKeep=REG_DWORD:0x00000000");
 253.318 +
 253.319 +@K_IECACHEDAYS_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/Internet Settings/Url History/",
 253.320 +        "DaysToKeep=REG_DWORD:0x00000000"); 
 253.321 +
 253.322 +
 253.323 +            
 253.324 +### policies win98  sezione 'profiledirs' - vengono settati tutti i percorsi di default 
 253.325 +@K_ALLPROFILEDIRS = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.326 +        "AppData=REG_SZ:_DUPROF\\Application Data",
 253.327 +        "Cache=REG_SZ:_DUPROF\\Temporary Internet Files",
 253.328 +        "Cookies=REG_SZ:_DUPROF\\Cookies",
 253.329 +        "Desktop=REG_SZ:_DUPROF\\Desktop",
 253.330 +        "Favorites=REG_SZ:_DUPROF\\Preferiti",
 253.331 +        "History=REG_SZ:_DUPROF\\Cronologia",
 253.332 +        "NetHood=REG_SZ:_DUPROF\\Risorse di rete",
 253.333 +        "Programs=REG_SZ:_DUPROF\\Menu Avvio\\Programmi",
 253.334 +        "Recent=REG_SZ:_DUPROF\\Recent",
 253.335 +        "Start Menu=REG_SZ:_DUPROF\\Menu Avvio",
 253.336 +        "Startup=REG_SZ:_DUPROF\\Menu Avvio\\Programmi\\Esecuzione automatica");
 253.337 +
 253.338 +### policies win98 sezione 'updateprofiledirs' - vengono impostate le cartelle in roaming
 253.339 +
 253.340 +@F_APPDATA_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/AppData/",
 253.341 +        "CentralFile=REG_SZ:Application Data",
 253.342 +        "LocalFile=REG_SZ:Application Data","Name=REG_SZ:\*.\*",
 253.343 +        "DefaultDir=REG_SZ:\*windir\\Application Data",
 253.344 +        "MustBeRelative=REG_DWORD:1",
 253.345 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.346 +        "RegValue=REG_SZ:AppData");
 253.347 +    
 253.348 +@F_APPDATA_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/AppData/",
 253.349 +        "CentralFile=REG_SZ:Application Data",
 253.350 +        "LocalFile=REG_SZ:Application Data",
 253.351 +        "Name=REG_SZ:\*.\*",
 253.352 +        "DefaultDir=REG_SZ:\*windir\\Application Data",
 253.353 +        "MustBeRelative=REG_DWORD:1",
 253.354 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.355 +        "RegValue=REG_SZ:AppData");
 253.356 +
 253.357 +@F_APPDATA1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.358 +        "AppData=REG_SZ:_CUPROF\\Application Data");
 253.359 +
 253.360 +@F_CACHE_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Cache/",
 253.361 +        "CentralFile=REG_SZ:Temporary Internet Files",
 253.362 +        "LocalFile=REG_SZ:Temporary Internet Files",
 253.363 +        "Name=REG_SZ:",
 253.364 +        "MustBeRelative=REG_DWORD:1",
 253.365 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.366 +        "RegValue=REG_SZ:Cache");
 253.367 +
 253.368 +@F_CACHE_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Cache/",
 253.369 +        "CentralFile=REG_SZ:Temporary Internet Files",
 253.370 +        "LocalFile=REG_SZ:Temporary Internet Files",
 253.371 +        "Name=REG_SZ:",
 253.372 +        "MustBeRelative=REG_DWORD:1",
 253.373 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.374 +        "RegValue=REG_SZ:Cache");
 253.375 +
 253.376 +@F_CACHE1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.377 +        "Cache=REG_SZ:_CUPROF\\Temporary Internet Files");
 253.378 +
 253.379 +@F_COOKIES_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Cookies/",
 253.380 +        "CentralFile=REG_SZ:Cookies",
 253.381 +        "DefaultDir=REG_SZ:\*windir\\Cookies",
 253.382 +        "LocalFile=REG_SZ:Cookies",
 253.383 +        "Name=REG_SZ:\*.\*",
 253.384 +        "MustBeRelative=REG_DWORD:1",
 253.385 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.386 +        "RegValue=REG_SZ:Cookies");
 253.387 +
 253.388 +@F_COOKIES_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Cookies/",
 253.389 +        "CentralFile=REG_SZ:Cookies",
 253.390 +        "DefaultDir=REG_SZ:\*windir\\Cookies",
 253.391 +        "LocalFile=REG_SZ:Cookies",
 253.392 +        "Name=REG_SZ:\*.\*",
 253.393 +        "MustBeRelative=REG_DWORD:1",
 253.394 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.395 +        "RegValue=REG_SZ:Cookies");
 253.396 +
 253.397 +@F_COOKIES1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.398 +        "Cookies=REG_SZ:_CUPROF\\Cookies");
 253.399 +
 253.400 +@F_DESKTOP_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Desktop/",
 253.401 +        "CentralFile=REG_SZ:Desktop",
 253.402 +        "LocalFile=REG_SZ:Desktop",
 253.403 +        "Name=REG_SZ:\*.\*",
 253.404 +        "MustBeRelative=REG_DWORD:1",
 253.405 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.406 +        "RegValue=REG_SZ:Desktop");
 253.407 +
 253.408 +@F_DESKTOP_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Desktop/",
 253.409 +        "CentralFile=REG_SZ:Desktop",
 253.410 +        "LocalFile=REG_SZ:Desktop",
 253.411 +        "Name=REG_SZ:\*.\*",
 253.412 +        "MustBeRelative=REG_DWORD:1",
 253.413 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.414 +        "RegValue=REG_SZ:Desktop");
 253.415 +
 253.416 +@F_DESKTOP1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.417 +        "Desktop=REG_SZ:_CUPROF\\Desktop");
 253.418 +
 253.419 +@F_FAVORITES_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Favorites/",
 253.420 +        "CentralFile=REG_SZ:Preferiti",
 253.421 +        "LocalFile=REG_SZ:Preferiti",
 253.422 +        "Name=REG_SZ:\*.\*",
 253.423 +        "MustBeRelative=REG_DWORD:1",
 253.424 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.425 +        "RegValue=REG_SZ:Favorites");
 253.426 +
 253.427 +@F_FAVORITES_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Favorites/",
 253.428 +        "CentralFile=REG_SZ:Preferiti",
 253.429 +        "LocalFile=REG_SZ:Preferiti",
 253.430 +        "Name=REG_SZ:\*.\*",
 253.431 +        "MustBeRelative=REG_DWORD:1",
 253.432 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.433 +        "RegValue=REG_SZ:Favorites");
 253.434 +
 253.435 +@F_FAVORITES1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.436 +        "Favorites=REG_SZ:_CUPROF\\Favorites");
 253.437 +
 253.438 +@F_HISTORY_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/History/",
 253.439 +        "CentralFile=REG_SZ:Cronologia",
 253.440 +        "LocalFile=REG_SZ:Cronologia",
 253.441 +        "Name=REG_SZ:\*.\*",
 253.442 +        "DefaultDir=REG_SZ:\*windir\\Cronologia",
 253.443 +        "MustBeRelative=REG_DWORD:1",
 253.444 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.445 +        "RegValue=REG_SZ:History");
 253.446 +
 253.447 +@F_HISTORY_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/History/",
 253.448 +        "CentralFile=REG_SZ:Cronologia",
 253.449 +        "LocalFile=REG_SZ:Cronologia",
 253.450 +        "Name=REG_SZ:\*.\*",
 253.451 +        "DefaultDir=REG_SZ:\*windir\\Cronologia",
 253.452 +        "MustBeRelative=REG_DWORD:1",
 253.453 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.454 +        "RegValue=REG_SZ:History");
 253.455 +
 253.456 +@F_HISTORY1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.457 +        "History=REG_SZ:_CUPROF\\Cronologia");
 253.458 +
 253.459 +@F_NETHOOD_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/NetHood/",
 253.460 +        "CentralFile=REG_SZ:Risorse di Rete",
 253.461 +        "LocalFile=REG_SZ:Risorse di Rete",
 253.462 +        "Name=REG_SZ:\*.\*",
 253.463 +        "MustBeRelative=REG_DWORD:1",
 253.464 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.465 +        "RegValue=REG_SZ:NetHood");
 253.466 +
 253.467 +@F_NETHOOD_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/NetHood/",
 253.468 +        "CentralFile=REG_SZ:Risorse di Rete",
 253.469 +        "LocalFile=REG_SZ:Risorse di Rete",
 253.470 +        "Name=REG_SZ:\*.\*",
 253.471 +        "MustBeRelative=REG_DWORD:1",
 253.472 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.473 +        "RegValue=REG_SZ:NetHood");
 253.474 +
 253.475 +@F_NETHOOD1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.476 +        "NetHood=REG_SZ:_CUPROF\\NetHood");
 253.477 +
 253.478 +@F_RECENT_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Recent/",
 253.479 +        "CentralFile=REG_SZ:Recent",
 253.480 +        "LocalFile=REG_SZ:Recent",
 253.481 +        "Name=REG_SZ:\*.\*",
 253.482 +        "MustBeRelative=REG_DWORD:1",
 253.483 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.484 +        "RegValue=REG_SZ:Recent"); 
 253.485 +
 253.486 +@F_RECENT_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Recent/",
 253.487 +        "CentralFile=REG_SZ:Recent",
 253.488 +        "LocalFile=REG_SZ:Recent",
 253.489 +        "Name=REG_SZ:\*.\*",
 253.490 +        "MustBeRelative=REG_DWORD:1",
 253.491 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.492 +        "RegValue=REG_SZ:Recent"); 
 253.493 +
 253.494 +@F_RECENT1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.495 +        "Recent=REG_SZ:_CUPROF\\Recent");
 253.496 +
 253.497 +@F_START_MENU_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Start Menu/",
 253.498 +        "CentralFile=REG_SZ:Menu Avvio",
 253.499 +        "LocalFile=REG_SZ:Menu Avvio",
 253.500 +        "Name=REG_SZ:\*.lnk,\*.pif,\*.url",
 253.501 +        "MustBeRelative=REG_DWORD:1",
 253.502 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.503 +        "RegValue=REG_SZ:Start Menu");
 253.504 +
 253.505 +@F_START_MENU_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Start Menu/",
 253.506 +        "CentralFile=REG_SZ:Menu Avvio",
 253.507 +        "LocalFile=REG_SZ:Menu Avvio",
 253.508 +        "Name=REG_SZ:\*.lnk,\*.pif,\*.url",
 253.509 +        "MustBeRelative=REG_DWORD:1",
 253.510 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.511 +        "RegValue=REG_SZ:Start Menu");   
 253.512 +
 253.513 +@F_START_MENU1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.514 +        "Start Menu=REG_SZ:_CUPROF\\Menu Avvio");
 253.515 +
 253.516 +@F_PROGRAMS_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/SecondaryProfileReconciliation/Programs/",
 253.517 +        "CentralFile=REG_SZ:Programmi",
 253.518 +        "LocalFile=REG_SZ:Menu Avvio\\Programmi",
 253.519 +        "Name=REG_SZ:\*.lnk,\*.pif,\*.url",
 253.520 +        "MustBeRelative=REG_DWORD:1",
 253.521 +        "ParentKey=REG_SZ:Start Menu",
 253.522 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.523 +        "RegValue=REG_SZ:Programs");
 253.524 +
 253.525 +@F_PROGRAMS_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Programs/",
 253.526 +        "CentralFile=REG_SZ:Programmi",
 253.527 +        "LocalFile=REG_SZ:Menu Avvio\\Programmi",
 253.528 +        "Name=REG_SZ:\*.lnk,\*.pif,\*.url",
 253.529 +        "MustBeRelative=REG_DWORD:1",
 253.530 +        "ParentKey=REG_SZ:Start Menu",
 253.531 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.532 +        "RegValue=REG_SZ:Programs");    
 253.533 +
 253.534 +@F_PROGRAMS1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.535 +        "Startup=REG_SZ:_CUPROF\\Programmi");
 253.536 +
 253.537 +@F_STARTUP_CU = ("CUser/Software/Microsoft/Windows/CurrentVersion/SecondaryProfileReconciliation/Startup/",
 253.538 +        "CentralFile=REG_SZ:Esecuzione Automatica",
 253.539 +        "LocalFile=REG_SZ:Menu Avvio\\Programmi\\Esecuzione Automatica",
 253.540 +        "Name=REG_SZ:\*.lnk,\*.pif,\*.url",
 253.541 +        "MustBeRelative=REG_DWORD:1",
 253.542 +        "ParentKey=REG_SZ:Start Menu",
 253.543 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.544 +        "RegValue=REG_SZ:Startup");
 253.545 +
 253.546 +@F_STARTUP_DU = ("Users/.DEFAULT/Software/Microsoft/Windows/CurrentVersion/ProfileReconciliation/Startup/",
 253.547 +        "CentralFile=REG_SZ:Esecuzione Automatica",
 253.548 +        "LocalFile=REG_SZ:Menu Avvio\\Programmi\\Esecuzione Automatica",
 253.549 +        "Name=REG_SZ:\*.lnk,\*.pif,\*.url",
 253.550 +        "MustBeRelative=REG_DWORD:1",
 253.551 +        "ParentKey=REG_SZ:Start Menu",
 253.552 +        "RegKey=REG_SZ:Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
 253.553 +        "RegValue=REG_SZ:Startup");         
 253.554 +
 253.555 +@F_STARTUP1 = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/User Shell Folders/",
 253.556 +        "Startup=REG_SZ:_CUPROF\\Menu Avvio\\Programmi\\Esecuzione automatica");
 253.557 +
 253.558 +### policies win98 sezione 'updatecontrol' - viene preparato RunOnce per eseguire aggiorna.bat
 253.559 +@K_UPDATE = ("LMachine/Software/Microsoft/Windows/CurrentVersion/RunOnce/",
 253.560 +        "LogonUpd=REG_SZ:_DIRLOGON\\logonupd.bat");
 253.561 +
 253.562 +@K_LABELHOME    = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/MountPoints2/_NETUSEHOME/",
 253.563 +        "_LabelFromDesktopINI=REG_SZ:HOME");
 253.564 +@K_LABELCLASSE  = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/MountPoints2/_NETUSECLASSE/",
 253.565 +        "_LabelFromDesktopINI=REG_SZ:MIA_CLASSE");
 253.566 +@K_LABELSCAMBIO = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/MountPoints2/_NETUSESCAMBIO/",
 253.567 +        "_LabelFromDesktopINI=REG_SZ:SCAMBIO");
 253.568 +@K_LABELMIOWEB  = ("CUser/Software/Microsoft/Windows/CurrentVersion/Explorer/MountPoints2/_NETUSEMIOWEB/",
 253.569 +        "_LabelFromDesktopINI=REG_SZ:MIO_WEB");
 253.570 +
 253.571 +
 253.572 +sub version {
 253.573 +    &debug ("Version: 0.9x\n");
 253.574 +}
 253.575 +
 253.576 +sub opgruppo {
 253.577 +    my $opdef = shift;    
 253.578 +    my $group = shift;
 253.579 +    my $opvar = shift;
 253.580 +    my $OkRestrict = $opdef ;
 253.581 +    
 253.582 +    $OkRestrict=$$opvar{''}     if ((defined($$opvar{''})));
 253.583 +    $OkRestrict=$$opvar{$group} if ((defined($$opvar{$group})));
 253.584 +
 253.585 +#    &WinMsgBox ("$opvar [ $group ]  = $OkRestrict\n",0,"OPGRUPPO") if ($DBG);
 253.586 +    my $msg = "$opvar"."[".$group."]  = $OkRestrict\n";
 253.587 +    &debug ($msg,0,"OPGRUPPO");
 253.588 +
 253.589 +    return $OkRestrict;
 253.590 +}
 253.591 +sub ReadConf {
 253.592 +    my $fname=shift;    #nome del file di conf
 253.593 +    my $okupd=shift;    #se 1 ReadConf e` chiamata da logonupd.pl   
 253.594 +    my $file = "$ENV{LOGONSERVER}\\perl\\$fname";
 253.595 +    my $dbgf="";
 253.596 +    my $posdbgf="";
 253.597 +    my $dbgshare;
 253.598 +    my $dbgclien;
 253.599 +    my $dbgusers;
 253.600 +
 253.601 +    open CONF, $file || die "ERRORE $f NON ESISTE";
 253.602 +
 253.603 +    my $msg="";
 253.604 +    my $x, $i=0;
 253.605 +    while (<CONF>) {
 253.606 +        
 253.607 +        # elimina fine riga e commenti 
 253.608 +        chop($_);  s/\#.*// ;  next if ($_ eq "");
 253.609 +        
 253.610 +        # qui non sono riuscito a trovare una regexp
 253.611 +        # che facesse il lavoro dell'if in colpo solo
 253.612 +        # la creazione implicita delle variabili
 253.613 +        # ci risparmia un sacco di codice
 253.614 +        
 253.615 +        if (m/.*\[.*/) {
 253.616 +            m/(.*)\[(.*)\]\s*=\s*(.*)/i ;
 253.617 +            $msg .= "1=$1, 2=$2 , 3=$3 , 4=$4 , 5=$5\n" ; #if ($i>20); 
 253.618 +            $x=$1;            
 253.619 +            $$x{$2}=$3;                    
 253.620 +        }else{
 253.621 +            m/(\S*)\s*=\s*(.*)/i ;
 253.622 +            $msg .= "1=$1, 2=$2 , 3=$3 , 4=$4 , 5=$5\n" ; #if ($i>20); 
 253.623 +            $x=$1;
 253.624 +            $$x{''}=$2;                         
 253.625 +        }
 253.626 +    $i++;
 253.627 +    }   
 253.628 +    close CONF;
 253.629 +
 253.630 +    # DBG diverso da zero solo se _DebugLevel > 1
 253.631 +    $DBG      = &opgruppo(0,$ENV{MAINGROUP},'_DebugLevel');
 253.632 +    $dbgshare = &opgruppo(0,$ENV{MAINGROUP},'_DebugShare');
 253.633 +    $dbgusers = &opgruppo(0,$ENV{MAINGROUP},'_DebugUsers');
 253.634 +    $dbgclien = &opgruppo(0,$ENV{MAINGROUP},'_DebugClients');
 253.635 +
 253.636 +    if ($DBG == 3 && $dbgusers){
 253.637 +        $DBG=0 if ($dbgusers !~ m/$ENV{USERNAME}/i);
 253.638 +        WinMsgBox("DEBUG_LEVEL=$DBG per gli utenti: $dbgusers") if ($DBG);
 253.639 +    }   
 253.640 +    if ($DBG == 3 && $dbgclien){
 253.641 +        $DBG=0 if ($dbgclien !~ m/$ENV{NETBIOSNAME}/i);
 253.642 +        WinMsgBox("DEBUG_LEVEL=$DBG per i clients: $dbgclien") if ($DBG);
 253.643 +    }   
 253.644 +    
 253.645 +    if ($DBG == 0) {        #nessun debug
 253.646 +        $OUTPUT="";
 253.647 +    
 253.648 +    }elsif ($DBG == 1){     #debug su conole
 253.649 +        $OUTPUT="";
 253.650 +    
 253.651 +    }elsif ($DBG == 2){     #debug via WinMsgBox
 253.652 +        $OUTPUT="";
 253.653 +    
 253.654 +    }elsif ($DBG == 3){     #debug su file in homes
 253.655 +        $OUTPUT = "FILE";
 253.656 +        if ($dbgshare){
 253.657 +            $dbgf=$ENV{LOGONSERVER}."\\".$dbgshare."\\DBG_".$ENV{NETBIOSNAME}.".TXT";
 253.658 +        }else{
 253.659 +            $dbgf=$ENV{LOGONSERVER}."\\".$ENV{USERNAME}."\\DBG_".$ENV{NETBIOSNAME}.".TXT";
 253.660 +        }   
 253.661 +    
 253.662 +#   }elsif ($DBG == 4){     #debug su file in [netlogon]
 253.663 +#       $OUTPUT = "FILE";
 253.664 +#       $dbgf=$ENV{LOGONSERVER}."\\dbglogon\\DBG_".$ENV{NETBIOSNAME}.".TXT";
 253.665 +
 253.666 +    }else{
 253.667 +        WinMsgBox("_DebugLevel = $DBG, i valori ammessi sono 0,1,2,3\ndebug disabilitato",0,"ERRORE IN LOGON.CONF");
 253.668 +        $DBG=0;$OUTPUT=""
 253.669 +    }
 253.670 +    
 253.671 +    if ($OUTPUT =~ m/FILE/ ){
 253.672 +        my $opf;
 253.673 +        if ($okupd){
 253.674 +            $opf='>>';
 253.675 +        }else{
 253.676 +            $opf='>';
 253.677 +        }   
 253.678 +        if (!open(OUT,"$opf $dbgf")){
 253.679 +            WinMsgBox("non riesco ad aprire $dbgf",0,"ERRORE DEBUG");
 253.680 +        }else{
 253.681 +            WinMsgBox("ho aperto $dbgf [$opf]",0,"FILE DEBUG");
 253.682 +            print OUT "###------INIZIO DEBUG [$opf]------\n";
 253.683 +        }
 253.684 +    }
 253.685 +        
 253.686 +    print "DEBUG_LEVEL=$DBG  DEBUG_FILE=$dbgf \n";
 253.687 +    
 253.688 +    &ListENV if ($DBG);
 253.689 +    &debug("Leggo $file per gruppo $ENV{MAINGROUP}");
 253.690 +    &debug($msg,0,"CONFIGURAZIONE") if ($msg ne "");
 253.691 +    
 253.692 +}
 253.693 +sub DbgClose {close OUT;}
 253.694 +
 253.695 +sub OsName {
 253.696 +    my $os=Win32::GetOSName();   
 253.697 +    $os=~ s/\/\.Net//;
 253.698 +    return $os;
 253.699 +}
 253.700 +sub GetInfoLogon {   
 253.701 +    # recupera username e maingroup eliminando le 
 253.702 +    # differenze fra le versioni di windows
 253.703 +    # necessita di uno script aggiuntivo lanciato
 253.704 +    # da samba con direttiva root preexec (setlogonvar)
 253.705 +    # setlogonvar contiene uid,maingrp,classe
 253.706 +    # POSSIBILE SVILUPPO: recuperare maingrp, classe
 253.707 +    # direttamente da ldap....
 253.708 +    # ma lo uid va comunque passato via file
 253.709 +    
 253.710 +    my $srv = shift;   
 253.711 +    my $r, $f;   
 253.712 +
 253.713 +    $ENV{NETBIOSNAME}=Win32::NodeName;
 253.714 +    $ENV{OSCLIENT}=&OsName();    
 253.715 +
 253.716 +    if (&IsWin9x) {
 253.717 +        chomp($srv);
 253.718 +        $ENV{LOGONSERVER}     = "\\\\$srv";
 253.719 +        $ENV{USERNAME}        = Win32::LoginName();
 253.720 +        $ENV{ALLUSERSPROFILE} = "C:\\Windows\\All Users";
 253.721 +    }
 253.722 +
 253.723 +    # non e` affatto detto che Win32::LogonName() funzioni !!!
 253.724 +    
 253.725 +#   chdir "$ENV{LOGONSERVER}\\perl";
 253.726 +    
 253.727 +#   $f="$ENV{LOGONSERVER}\\perl\\logonvar_$ENV{NETBIOSNAME}"; 
 253.728 +    
 253.729 +    $f="$ENV{LOGONSERVER}\\netlogon\\logonvar_$ENV{NETBIOSNAME}"; 
 253.730 +    open UI,$f;while (<UI>){$r=$_;} close UI ; #unlink($f);
 253.731 +    chop($r); @info=split(/,/,$r);
 253.732 +    
 253.733 +    $ENV{USERNAME}= $info[0] if (!$ENV{USERNAME});    
 253.734 +    $ENV{MAINGROUP}= $info[1];
 253.735 +    $ENV{CLASSE}=$info[2];    
 253.736 +    $ENV{QUOTA}=$info[3];
 253.737 +
 253.738 +    WinMsgBox("ATTENZIONE: spazio disco insufficente!!!\nse non liberi spazio non potrai salvare nuovi file.",0,"QUOTA DISCO SUPERATA")  if ($ENV{QUOTA} =~ m/FUORIQUOTA/);
 253.739 +}
 253.740 +sub WinMsgBox {
 253.741 +    my $msg=shift;
 253.742 +    my $flags=shift;
 253.743 +    my $title=shift;
 253.744 +    Win32::MsgBox($msg,$flags,$title);
 253.745 +}
 253.746 +sub debug {
 253.747 +    ### _DebugLevel = 0 nessun messaggio
 253.748 +    ###             = 1 solo messaggi di console 
 253.749 +    ###             = 2 con WinMsgBox
 253.750 +    ###             = 3 messaggi in un file locale in HOMES
 253.751 +    ###             = 4 messaggi in file remoto in /home/samba/netlogon
 253.752 +    my $msg = shift ;
 253.753 +    my $lvl = shift ;
 253.754 +    # A title is accepted as 3^ argument
 253.755 +    my $title = shift ;
 253.756 +    
 253.757 +    return if ($DBG == 0);
 253.758 +    
 253.759 +
 253.760 +    if ($DBG =~ m/[134]/ ) {
 253.761 +        if ($OUTPUT == 'FILE') {
 253.762 +            print OUT "$title\n";
 253.763 +            print OUT "$msg\n";
 253.764 +        } else {
 253.765 +            print "$title\n";
 253.766 +            print "$msg\n";
 253.767 +        }
 253.768 +    }
 253.769 +    if ($DBG  == 2 ) {
 253.770 +        Win32::MsgBox($msg, 0, $title) ;
 253.771 +    }
 253.772 +}
 253.773 +sub ListENV {
 253.774 +    my $key, $msg="";
 253.775 +    &debug(Win32::LoginName(),0,'Win32::LoginName') ;
 253.776 +    foreach $key (sort keys %ENV) {
 253.777 +        $msg .= "$key = $ENV{$key}\n";
 253.778 +    }
 253.779 +    &debug($msg,0,'VARIABILI ENV');
 253.780 +}
 253.781 +sub IsWin9x {
 253.782 +    return ($ENV{OSCLIENT} =~ m/Win95|Win98|WinME/i)   
 253.783 +}
 253.784 +sub WinSet {
 253.785 +    my $op=shift;
 253.786 +    my $nomute=shift;
 253.787 +    if ($OUTPUT){
 253.788 +        print OUT "#### SETTING $op\n" if ($nomute);
 253.789 +    }else{
 253.790 +        print "#### SETTING $op\n" if ($nomute);
 253.791 +    }
 253.792 +    my $group = $ENV{MAINGROUP};
 253.793 +
 253.794 +    if ($op eq 'start_page') {
 253.795 +        &SetKeyVal(\@K_IEMAIN,$group,"EXPLORER");
 253.796 +
 253.797 +    }elsif ($op eq 'proxy'){
 253.798 +        &SetKeyVal(\@K_INTNETSET,$group,"PROXY");
 253.799 +
 253.800 +    }elsif ($op eq 'no_profile') {
 253.801 +        return if (&IsWin9x) ; # win9x  non supportato
 253.802 +        &SetKeyVal(\@K_NOPROFILE,$group,"NO_PROFILE");
 253.803 +    
 253.804 +    }elsif ($op eq 'no_local_profile') {
 253.805 +        return if (&IsWin9x) ; # win9x  non supportato
 253.806 +        &SetKeyVal(\@K_NOLOCALPROFILE1,$group,"NOLOCALPROFILE1");
 253.807 +        &SetKeyVal(\@K_NOLOCALPROFILE2,$group,"NOLOCALPROFILE2");
 253.808 +
 253.809 +    }elsif ($op eq 'last_user') {
 253.810 +        return if (&IsWin9x) ; # win9x  supportato in modo diverso
 253.811 +        my $OkRestrict = &opgruppo(undef,$group,'_NoDispLastUser');
 253.812 +        if (defined($OkRestrict)){
 253.813 +            &SetKeyVal(\@K_LASTUSR_OFF,$group,"NODISP_LASTUSER") if ($OkRestrict);
 253.814 +            &SetKeyVal(\@K_LASTUSR_ON, $group,"NODISP_LASTUSER") if (!$OkRestrict);
 253.815 +        }
 253.816 +    
 253.817 +    }elsif ($op eq 'sync') {
 253.818 +        return if (&IsWin9x) ; # win9x  non supportato
 253.819 +        my $OkRestrict = &opgruppo(undef,$group,'_NoSync');
 253.820 +        if (defined($OkRestrict)){
 253.821 +            &SetKeyVal(\@K_SYNC_OFF,$group,"NOSYNC") if ($OkRestrict);
 253.822 +            &SetKeyVal(\@K_SYNC_ON, $group,"NOSYNC") if (!$OkRestrict);
 253.823 +        }
 253.824 +        
 253.825 +    }elsif ($op eq 'iepasswordcache') {
 253.826 +        &ApplicaPol('_RestrictIEPasswordCaching',\@K_IEPASSWORDCACHING_DU,\@K_IEPASSWORDCACHING_CU,$op,'DELVAL',$setDU);
 253.827 +
 253.828 +    }elsif ($op eq 'autorun') {
 253.829 +        &SetKeyVal(\@K_AUTORUN_CU,$group,"AUTORUN");
 253.830 +    
 253.831 +    }elsif ($op eq 'document_folder') {
 253.832 +        &SetKeyVal(\@K_DOCFOLDER1,$group,"DOC_FOLDER1");
 253.833 +        &SetKeyVal(\@K_DOCFOLDER2,$group,"DOC_FOLDER2");
 253.834 +        
 253.835 +    }elsif ($op eq 'net_use') {
 253.836 +        &net_use();
 253.837 +
 253.838 +    }elsif ($op eq 'set_printers') {
 253.839 +        &set_printers();
 253.840 +
 253.841 +    }elsif ($op eq 'net_time') {
 253.842 +        &net_time();
 253.843 +
 253.844 +    }elsif ($op eq 'std_env') {
 253.845 +        &standard_env();
 253.846 +
 253.847 +    }else{
 253.848 +    
 253.849 +        &debug('ERRORE IN /etc/isi/logon.conf (WinSet): '.$op,0,"OPZIONE SCONOSCIUTA");
 253.850 +    }
 253.851 +}
 253.852 +sub WinPol9x {
 253.853 +    # Win9xPol dovrebbe emulare CONFIG.POL
 253.854 +
 253.855 +    my $pol=shift;
 253.856 +    my $nomute=shift;
 253.857 +    my $setDU=shift;   #per logon2.bat
 253.858 +    
 253.859 +    if ($OUTPUT){
 253.860 +        print OUT "#### SETTING $pol\n" if ($nomute);
 253.861 +    }else{  
 253.862 +        print "#### SETTING $pol\n" if ($nomute);
 253.863 +    }   
 253.864 +
 253.865 +    my $key,$val;
 253.866 +
 253.867 +    return if (!&IsWin9x);
 253.868 +    #print $OUTPUT "sto simulando CONFIG.POL sezione $pol\n" if ($DBG);   
 253.869 +
 253.870 +    # modo di cancellazione vuoto significa che per eliminare la restrizione
 253.871 +    # si agisce su /etc/isi/logon.conf cambiando il valore delle variabili
 253.872 +    
 253.873 +    
 253.874 +    if ($pol eq 'clearpol'){   
 253.875 +        &DelKeyVal(\@K_CLEAR_D1,'DELVAL',"ELIMINO GRUPPOL 1");
 253.876 +        &DelKeyVal(\@K_CLEAR_D2,'DELVAL',"ELIMINO GRUPPOL 2");
 253.877 +        &DelKeyVal(\@K_CLEAR_D3,'DELKEY',"ELIMINO GRUPPOL 3");
 253.878 +        &SetKeyVal(\@K_CLEAR_A1,"","ELIMINO GRUPPOL 4");
 253.879 +    
 253.880 +    }elsif ($pol eq 'access'){ 
 253.881 +        &ApplicaPol('_RestrictLogon','',\@K_NETLOGON1,$pol,'DELVAL','');              
 253.882 +        &ApplicaPol('_RestrictLogon','',\@K_NETLOGON2,$pol,'DELVAL','');     
 253.883 +    
 253.884 +    }elsif ($pol eq 'pwdcaching'){ 
 253.885 +        &SetKeyVal(\@K_PWDCACHING,"","NO PASSWORD CACHING");  
 253.886 +
 253.887 +    }elsif ($pol eq 'last_user') {
 253.888 +        &SetKeyVal(\@K_LASTUSER_OFF,"","NO_DISP_LASTUSER") if($_NoDispLastUser9X{''} eq 1);
 253.889 +        &SetKeyVal(\@K_LASTUSER_ON,"","NO_DISP_LASTUSER")  if($_NoDispLastUser9X{''} eq 0);       
 253.890 +    
 253.891 +    }elsif ($pol eq 'nocpan'){   
 253.892 +        &ApplicaPol('_RestrictCpan',\@K_NOCPAN1_DU,\@K_NOCPAN1_CU,$pol,'DELKEY',$setDU);    
 253.893 +        &ApplicaPol('_RestrictCpan',\@K_NOCPAN2_DU,\@K_NOCPAN2_CU,$pol,'DELVAL',$setDU);   
 253.894 +    
 253.895 +    }elsif ($pol eq 'appwiz'){
 253.896 +        &AppWiz('_NoAppWiz',$pol);
 253.897 +    
 253.898 +    }elsif ($pol eq 'nodrive'){
 253.899 +        &ApplicaPol('_RestrictDrive',\@K_NOHYSTORY_DU,\@K_NOHYSTORY_CU,$pol,'DELVAL',$setDU);
 253.900 +    
 253.901 +    }elsif ($pol eq 'nodrivec'){
 253.902 +        &ApplicaPol('_RestrictDriveC',\@K_NODRIVEC_DU,\@K_NODRIVEC_CU,$pol,'DELVAL',$setDU);
 253.903 +
 253.904 +    }elsif ($pol eq 'nohistory'){
 253.905 +        &ApplicaPol('_RestrictHistory',\@K_NOHISTORY1_DU,\@K_NOHISTORY1_CU,$pol,'DELVAL',$setDU);
 253.906 +        &ApplicaPol('_RestrictHistory',\@K_NOHISTORY2_DU,\@K_NOHISTORY2_CU,$pol,'DELVAL',$setDU);
 253.907 +    
 253.908 +    }elsif ($pol eq 'iecachedays'){
 253.909 +        if($_SetIECache{''} eq 1){
 253.910 +            &SetKeyVal(\@K_IECACHEDAYS_CU,"","IE CACHE DAYS");
 253.911 +            &SetKeyVal(\@K_IECACHEDAYS_DU,"","IE CACHE DAYS");
 253.912 +        }
 253.913 +                            
 253.914 +    }elsif ($pol eq 'noactivedesktop'){
 253.915 +        &ApplicaPol('_RestrictActiveDesktop',\@K_NOACTIVED_DU,\@K_NOACTIVED_CU,$pol,'DELVAL',$setDU);
 253.916 +    
 253.917 +    }elsif ($pol eq 'nofind'){
 253.918 +        &ApplicaPol('_RestrictFind',\@K_NOFIND_DU,\@K_NOFIND_CU,$pol,'DELVAL',$setDU);      
 253.919 +    
 253.920 +    }elsif ($pol eq 'paranoia'){
 253.921 +        my $OkRestrict = &opgruppo(0,$ENV{MAINGROUP},'_OkParanoia');
 253.922 +        if($OkRestrict){
 253.923 +            @CMD=();            
 253.924 +            push(@CMD,"deltree /y C:\\Windows\\Desktop\\\*.\*");
 253.925 +            &esegui;
 253.926 +            @CMD=();            
 253.927 +            push(@CMD,"deltree /y C:\\Recycled\\\*.\* ");
 253.928 +            &esegui;
 253.929 +        }
 253.930 +    
 253.931 +    }elsif ($pol eq 'screen'){
 253.932 +        &ApplicaPol('_RestrictScreen',\@K_SCREEN_DU,\@K_SCREEN_CU,$pol,'DELVAL',$setDU);            
 253.933 +    
 253.934 +    }elsif ($pol eq 'net'){
 253.935 +        &ApplicaPol('_RestrictNet',\@K_NONET_DU,\@K_NONET_CU,$pol,'DELKEY',$setDU);              
 253.936 +
 253.937 +    }elsif ($pol eq 'passwd'){
 253.938 +        &ApplicaPol('_RestrictPasswd',\@K_CHPWD_DU,\@K_CHPWD_CU,$pol,'DELVAL',$setDU);
 253.939 +
 253.940 +    }elsif ($pol eq 'printer'){
 253.941 +        &ApplicaPol('_RestrictPrinter',\@K_NOSTP_DU,\@K_NOSTP_CU,$pol,'DELVAL',$setDU);
 253.942 +
 253.943 +    }elsif ($pol eq 'system'){
 253.944 +        &ApplicaPol('_RestrictSystem',\@K_SYS_DU,\@K_SYS_CU,$pol,'DELVAL',$setDU);
 253.945 +
 253.946 +    }elsif ($pol eq 'shell_run'){
 253.947 +        &ApplicaPol('_RestrictRun',\@K_SHRUN_DU,\@K_SHRUN_CU,$pol,'DELVAL',$setDU);
 253.948 +
 253.949 +    }elsif ($pol eq 'shell_noregtools'){
 253.950 +        &ApplicaPol('_RestrictRegTools',\@K_SHRTOOLS_DU,\@K_SHRTOOLS_CU,$pol,'DELVAL',$setDU);
 253.951 +
 253.952 +    }elsif ($pol eq 'shell_winoldapp'){
 253.953 +        &ApplicaPol('_RestrictOldApp',\@K_SHOLDAPP_DU,\@K_SHOLDAPP_CU,$pol,'DELVAL',$setDU);
 253.954 +
 253.955 +    }elsif ($pol eq 'nosavesettings'){
 253.956 +    &ApplicaPol('_RestrictSaveSettings',\@K_NOSAVESETTINGS_DU,\@K_NOSAVESETTINGS_CU,$pol,'DELVAL',$setDU);
 253.957 +    
 253.958 +    }elsif ($pol eq 'profiledirs'){
 253.959 +        &SetKeyVal(\@K_ALLPROFILEDIRS,'DELVAL',"TUTTE LE CARTELLE A DEFAULT");
 253.960 +    
 253.961 +    }elsif ($pol eq 'updateprofiledirs'){
 253.962 +        
 253.963 +        #metto tutti i percorsi a valori di default
 253.964 +        
 253.965 +        &SetKeyVal(\@K_ALLPROFILEDIRS,'DELVAL',"TUTTE LE CARTELLE A DEFAULT");
 253.966 +        
 253.967 +        #Tolgo tutte le cartelle dal roaming sia per l'utente che per il DEFAULT user
 253.968 +        
 253.969 +        &DelKeyVal(\@F_APPDATA_CU,"DELKEY","CARTELLA APPDATA");
 253.970 +        &DelKeyVal(\@F_CACHE_CU,"DELKEY","CARTELLA CACHE"); 
 253.971 +        &DelKeyVal(\@F_COOKIES_CU,"DELKEY","CARTELLA COOKIES"); 
 253.972 +        &DelKeyVal(\@F_DESKTOP_CU,"DELKEY","CARTELLA DESKTOP"); 
 253.973 +        &DelKeyVal(\@F_HISTORY_CU,"DELKEY","CARTELLA CRONOLOGIA");
 253.974 +        &DelKeyVal(\@F_NETHOOD_CU,"DELKEY","CARTELLA RISORSE DI RETE");
 253.975 +        &DelKeyVal(\@F_PROGRAMS_CU,"DELKEY","CARTELLA MENU PROGRAMMI");
 253.976 +        &DelKeyVal(\@F_RECENT_CU,"DELKEY","CARTELLA RECENTI");
 253.977 +        &DelKeyVal(\@F_START_MENU_CU,"DELKEY","CARTELLA MENU AVVIO");
 253.978 +        &DelKeyVal(\@F_STARTUP_CU,"DELKEY","CARTELLA ESECUZIONE AUTOMATICA");
 253.979 +        &DelKeyVal(\@F_APPDATA_DU,"DELKEY","CARTELLA APPDATA");
 253.980 +        &DelKeyVal(\@F_CACHE_DU,"DELKEY","CARTELLA CACHE"); 
 253.981 +        &DelKeyVal(\@F_COOKIES_DU,"DELKEY","CARTELLA COOKIES"); ##m1#a_test#.profili#WinXP
 253.982 +        &DelKeyVal(\@F_DESKTOP_DU,"DELKEY","CARTELLA DESKTOP"); 
 253.983 +        &DelKeyVal(\@F_HISTORY_DU,"DELKEY","CARTELLA CRONOLOGIA");
 253.984 +        &DelKeyVal(\@F_NETHOOD_DU,"DELKEY","CARTELLA RISORSE DI RETE");
 253.985 +        &DelKeyVal(\@F_PROGRAMS_DU,"DELKEY","CARTELLA MENU PROGRAMMI");
 253.986 +        &DelKeyVal(\@F_RECENT_DU,"DELKEY","CARTELLA RECENTI");
 253.987 +        &DelKeyVal(\@F_START_MENU_DU,"DELKEY","CARTELLA MENU AVVIO");
 253.988 +        &DelKeyVal(\@F_STARTUP_DU,"DELKEY","CARTELLA ESECUZIONE AUTOMATICA");
 253.989 +        
 253.990 +        #Metto in roaming solo le cartelle selezionate in logon.conf e setto i percorsi di queste.
 253.991 +        #Se i percorsi non sono specificati in logon.conf, vengono usati i valori di default per i roaming profiles
 253.992 +        #Vengono anche precisate quali devono essere le cartelle in roaming per i nuovi utenti (DEFAULT USER)
 253.993 +        
 253.994 +        my $ProfileDirs = &opgruppo(1,$group,'_ProfileDirs');
 253.995 +        @dirs=split(/;/,$ProfileDirs);
 253.996 +        for (my $k=0 ;$k<@dirs ;$k++){
 253.997 +            if ($dirs[$k] eq 'AppData'){
 253.998 +                &SetKeyVal(\@F_APPDATA_CU,"","CARTELLA APPDATA"); 
 253.999 +                &SetKeyVal(\@F_APPDATA_DU,"","CARTELLA APPDATA"); 
253.1000 +                &SetKeyVal(\@F_APPDATA1,"","CARTELLA APPDATA");  
253.1001 +            } elsif ($dirs[$k] eq 'Cache') {
253.1002 +                &SetKeyVal(\@F_CACHE_CU,"","CARTELLA CACHE"); 
253.1003 +                &SetKeyVal(\@F_CACHE_DU,"","CARTELLA CACHE"); 
253.1004 +                &SetKeyVal(\@F_CACHE1,"","CARTELLA CACHE"); 
253.1005 +            } elsif ($dirs[$k] eq 'Cookies') {
253.1006 +                &SetKeyVal(\@F_COOKIES_CU,"","CARTELLA COOKIES"); 
253.1007 +                &SetKeyVal(\@F_COOKIES_DU,"","CARTELLA COOKIES"); 
253.1008 +                &SetKeyVal(\@F_COOKIES1,"","CARTELLA COOKIES"); 
253.1009 +            } elsif ($dirs[$k] eq 'Desktop') {
253.1010 +                &SetKeyVal(\@F_DESKTOP_CU,"","CARTELLA DESKTOP"); 
253.1011 +                &SetKeyVal(\@F_DESKTOP_DU,"","CARTELLA DESKTOP"); 
253.1012 +                &SetKeyVal(\@F_DESKTOP1,"","CARTELLA DESKTOP"); 
253.1013 +            } elsif ($dirs[$k] eq 'Favorites') {
253.1014 +                &SetKeyVal(\@F_FAVORITES_CU,"","CARTELLA PREFERITI"); 
253.1015 +                &SetKeyVal(\@F_FAVORITES_DU,"","CARTELLA PREFERITI"); 
253.1016 +                &SetKeyVal(\@F_FAVORITES1,"","CARTELLA PREFERITI"); 
253.1017 +            } elsif ($dirs[$k] eq 'History') {
253.1018 +                &SetKeyVal(\@F_HISTORY_CU,"","CARTELLA CRONOLOGIA");
253.1019 +                &SetKeyVal(\@F_HISTORY_DU,"","CARTELLA CRONOLOGIA");
253.1020 +                &SetKeyVal(\@F_HISTORY1,"","CARTELLA CRONOLOGIA");
253.1021 +            } elsif ($dirs[$k] eq 'NetHood') {
253.1022 +                &SetKeyVal(\@F_NETHOOD_CU,"","CARTELLA RISORSE DI RETE");
253.1023 +                &SetKeyVal(\@F_NETHOOD_DU,"","CARTELLA RISORSE DI RETE");
253.1024 +                &SetKeyVal(\@F_NETHOOD1,"","CARTELLA RISORSE DI RETE");
253.1025 +            } elsif ($dirs[$k] eq 'Programs') {
253.1026 +                &SetKeyVal(\@F_PROGRAMS_CU,"","CARTELLA MENU PROGRAMMI");
253.1027 +                &SetKeyVal(\@F_PROGRAMS_DU,"","CARTELLA MENU PROGRAMMI");
253.1028 +                &SetKeyVal(\@F_PROGRAMS1,"","CARTELLA MENU PROGRAMMI");
253.1029 +            } elsif ($dirs[$k] eq 'Recent') {
253.1030 +                &SetKeyVal(\@F_RECENT_CU,"","CARTELLA RECENTI");
253.1031 +                &SetKeyVal(\@F_RECENT_DU,"","CARTELLA RECENTI");
253.1032 +                &SetKeyVal(\@F_RECENT1,"","CARTELLA RECENTI");
253.1033 +            } elsif ($dirs[$k] eq 'Start Menu') {
253.1034 +                &SetKeyVal(\@F_START_MENU_CU,"","CARTELLA MENU AVVIO");
253.1035 +                &SetKeyVal(\@F_START_MENU_DU,"","CARTELLA MENU AVVIO");
253.1036 +                &SetKeyVal(\@F_START_MENU1,"","CARTELLA MENU AVVIO");
253.1037 +            } elsif ($dirs[$k] eq 'Startup') {
253.1038 +                &SetKeyVal(\@F_STARTUP_CU,"","CARTELLA ESECUZIONE AUTOMATICA");
253.1039 +                &SetKeyVal(\@F_STARTUP_DU,"","CARTELLA ESECUZIONE AUTOMATICA");
253.1040 +                &SetKeyVal(\@F_STARTUP1,"","CARTELLA ESECUZIONE AUTOMATICA");
253.1041 +            }   
253.1042 +        }
253.1043 +        $newvers= $_Versione{''};
253.1044 +        chop $newvers;
253.1045 +        my $file = "H:\\.profili\\Win95\\Versione";
253.1046 +        open (OUTV, ">$file");
253.1047 +        print OUTV "$newvers\n";
253.1048 +        close OUTV;
253.1049 +        exec ("RUNDLL32 SHELL32.DLL,SHExitWindowsEx 0");
253.1050 +    
253.1051 +    }elsif ($pol eq 'updatecontrol'){ 
253.1052 +        
253.1053 +        #controlliamo se il profilo � da aggiornare
253.1054 +        #se la risposta �  affermativa prepariamo RunOnce
253.1055 +        
253.1056 +        $newvers= $_Versione{''};
253.1057 +        my $file = "H:\\.profili\\Win95\\Versione";
253.1058 +        if(!-e $file){
253.1059 +            &SetKeyVal(\@K_UPDATE,"","MANCA IL FILE: PREPARO AGGIORNAMENTO");  
253.1060 +            WinMsgBox("ATTENZIONE: alla fine di queste operazioni\nsar� necessario ripetere il login",0,"PRIMA CONFIGURAZIONE");
253.1061 +        }else{
253.1062 +            open (FILE, $file);
253.1063 +            $oldvers= $_;
253.1064 +            while (<FILE>) {
253.1065 +                $oldvers = $_;
253.1066 +            }
253.1067 +            close FILE;
253.1068 +            chop($oldvers);
253.1069 +            chop($newvers); 
253.1070 +            if ($newvers ne $oldvers) {
253.1071 +                &SetKeyVal(\@K_UPDATE,"","VERSIONE SBAGLIATA: PREPARO AGGIORNAMENTO");
253.1072 +                WinMsgBox("ATTENZIONE: alla fine di queste operazioni\nsar� necessario ripetere il login",0,"AGGIORNAMENTO DELLA CONFIGURAZIONE");
253.1073 +            }
253.1074 +        }
253.1075 +            
253.1076 +    }elsif ($pol eq 'startupdate'){ 
253.1077 +        $datfile = "C:\\WINDOWS\\profiles\\$ENV{USERNAME}\\user.dat";
253.1078 +        if(!-e $datfile){
253.1079 +            # inutile aggiornare, l'utente non ha scaricato il suo profilo! usciamo da aggiorna.pl
253.1080 +            exit;
253.1081 +        } 
253.1082 +    }else{
253.1083 +        &debug('ERRORE IN /etc/isi/logon.conf (WinPol9x): $pol',0,"OPZIONE SCONOSCIUTA");
253.1084 +    }
253.1085 +}
253.1086 +sub AppWiz {
253.1087 +    my $opvar = shift; # var di /etc/isi/logon.conf
253.1088 +    my $tit   = shift; # titolo
253.1089 +    my $group = $ENV{MAINGROUP};
253.1090 +    my $OkRestrict = &opgruppo(1,$group,$opvar);
253.1091 +    my $src="$ENV{LOGONSERVER}\\perl\\win98\\Appwiz.cpl";
253.1092 +    my $dst="C:\\WINDOWS\\SYSTEM\\Appwiz.cpl";
253.1093 +    if ($OkRestrict){
253.1094 +        &debug("del $dst",0,"STO PER ESEGUIRE...") ;
253.1095 +        @CMD=();            
253.1096 +        push(@CMD,"del $dst");
253.1097 +        &esegui;
253.1098 +    }else{
253.1099 +        if ($x){
253.1100 +            WinMsgBox("ERRORE: impossibile ripristinare Appwiz",0,"AGGIORNAMENTO DELLA CONFIGURAZIONE");
253.1101 +        }else{          
253.1102 +            &debug("copy $src $dst",0,"STO PER ESEGUIRE...") ;
253.1103 +            @CMD=();            
253.1104 +            push(@CMD,"copy $src $dst");
253.1105 +            &esegui;
253.1106 +        }
253.1107 +    } 
253.1108 +}
253.1109 +
253.1110 +sub ApplicaPol {
253.1111 +    my $opvar = shift; # var di /etc/isi/logon.conf
253.1112 +    my $aDU   = shift; # chiavi default user
253.1113 +    my $aCU   = shift; # chiavi current user
253.1114 +    my $tit   = shift; # titolo
253.1115 +    my $opDel = shift; # modo di cancellazione 
253.1116 +    my $setDU = shift; # per logon2.bat in Esecuzione Automatica
253.1117 +    
253.1118 +    my $group=$ENV{MAINGROUP};
253.1119 +    my $OkRestrict = &opgruppo(1,$group,$opvar);
253.1120 +
253.1121 +    &Restrict($OkRestrict,$aDU,$group,"$tit\_DU",$opDel) if ($setDU);   
253.1122 +    &Restrict($OkRestrict,$aCU,$group,"$tit\_CU",$opDel);
253.1123 +}
253.1124 +sub Restrict {
253.1125 +    $ok=shift;
253.1126 +    $refreg=shift;
253.1127 +    $group=shift;
253.1128 +    $titolo=shift;
253.1129 +    $opcanc=shift;
253.1130 +    if ($ok) { 
253.1131 +        &SetKeyVal($refreg,$group,$titolo);        
253.1132 +    }elsif ($opcanc){
253.1133 +        &DelKeyVal($refreg,$opcanc,$titolo);        
253.1134 +    }
253.1135 +}  
253.1136 +sub DelKeyVal {
253.1137 +    $r=shift;
253.1138 +    $op=shift;
253.1139 +    $titolo=shift;
253.1140 +    my $v,$rvar,$key,$kroot,$kvar;       
253.1141 +    my @kv = @$r,$oldv,$oldop;
253.1142 +    my $msg="";
253.1143 +    
253.1144 +    $kroot = $kv[0];
253.1145 +
253.1146 +    if (!defined($Registry->{$kroot})){return;}
253.1147 +    
253.1148 +    # opzioni possibili DELKEY | DELVAL
253.1149 +    if     ($op eq 'DELKEY') {        
253.1150 +        delete $Registry->{$kroot};
253.1151 +        $msg .= "DELKEY $kroot \n" ;    
253.1152 +    }elsif ($op eq 'DELVAL') { 
253.1153 +
253.1154 +        $msg .= "ELIMINO I VALORI SOTTO (FastDelete=$oldopt):\n$kroot\n" ;                      
253.1155 +
253.1156 +        $key = $Registry->{$kroot}; 
253.1157 +        $oldopt=$key->FastDelete( 1 );
253.1158 +
253.1159 +        # elimina key var
253.1160 +        for (my $j=1;$j<@kv;$j++){       
253.1161 +            @rvar=split(/=|:/,$kv[$j]);
253.1162 +            $kvar=$rvar[0];
253.1163 +            $kvar=~s/\_{2}/ /g;
253.1164 +            if (defined($key->{$kvar})) {
253.1165 +                $oldv=delete $key->{$kvar};
253.1166 +                $msg .= "DELVAR $kvar = $oldv\n" ;
253.1167 +            }
253.1168 +        }
253.1169 +    }
253.1170 +    &debug($msg,0,"ELIMINO VOCE DI REGISTRO: $titolo") ;
253.1171 +}
253.1172 +#--------------
253.1173 +sub SetKeyVal {
253.1174 +    
253.1175 +    # setting del valore delle variabili in una chiave di registro
253.1176 +    # se la chiave non esiste viene creata
253.1177 +    
253.1178 +    $r=shift;
253.1179 +    $group=shift;
253.1180 +    $pol=shift;
253.1181 +    
253.1182 +    my $v,$rvar,$key,$kroot,$kvar,$cvar,$kdef;   
253.1183 +    my $vval,$vtype,$NOERR;
253.1184 +    
253.1185 +    my @kv = @$r;
253.1186 +    my $msg="";
253.1187 +    
253.1188 +    if ($DBG){
253.1189 +        $msg .= "#------ voci di registro -------\n";
253.1190 +        #stranamente lo statement while ($k) non funziona....
253.1191 +        for (my $k=0 ;$k<@kv ;$k++){
253.1192 +            $msg .= "$k) $kv[$k] \n";
253.1193 +        }   
253.1194 +        $msg .= "#-------------valori -----------\n";
253.1195 +    }
253.1196 +    
253.1197 +    $kroot = $kv[0];  
253.1198 +
253.1199 +    # setting delle label delle connessioni H: L: S: W:
253.1200 +    if ($pol eq "LABELHOME"){    
253.1201 +        
253.1202 +        my $pdc=$ENV{LOGONSERVER}; $pdc =~ s/\\//g;
253.1203 +        # per tener conto della tecnica della // o di /./
253.1204 +#       my $unit1="##".$pdc."#".$ENV{USERNAME}."#.profili#".$ENV{OSCLIENT};    
253.1205 +        my $unit2="##".$pdc."#".$ENV{USERNAME};    
253.1206 +#       $kroot =~ s/_NETUSEHOME/$unit1/g ;
253.1207 +        $kroot =~ s/_NETUSEHOME/$unit2/i ;
253.1208 +        #&WinMsgBox($kroot,0,$pol);
253.1209 +        
253.1210 +    }
253.1211 +
253.1212 +    if ($pol eq "LABELCLASSE" && $ENV{MAINGROUP}=~m/alunni|esterni/i){    
253.1213 +        
253.1214 +        my $pdc=$ENV{LOGONSERVER}; $pdc =~ s/\\//g;
253.1215 +        my $unita="##".$pdc."#".$ENV{CLASSE};    
253.1216 +        $kroot =~ s/_NETUSECLASSE/$unita/i ;
253.1217 +        #&WinMsgBox($kroot,0,$pol);
253.1218 +        
253.1219 +    }
253.1220 +
253.1221 +    if ($pol eq "LABELSCAMBIO"){    
253.1222 +        
253.1223 +        my $pdc=$ENV{LOGONSERVER}; $pdc =~ s/\\//g;
253.1224 +        my $unita="##".$pdc."#scambio";    
253.1225 +        $kroot =~ s/_NETUSESCAMBIO/$unita/i ;
253.1226 +        #&WinMsgBox($kroot,0,$pol);
253.1227 +        
253.1228 +    }
253.1229 +    if ($pol eq "LABELMIOWEB"){    
253.1230 +        
253.1231 +        my $pdc=$ENV{LOGONSERVER}; $pdc =~ s/\\//g;
253.1232 +        my $unita="##".$pdc."#mioweb";    
253.1233 +        $kroot =~ s/_NETUSEMIOWEB/$unita/i ;
253.1234 +        #&WinMsgBox($kroot,0,$pol);
253.1235 +        
253.1236 +    }
253.1237 +
253.1238 +
253.1239 +    $key = $Registry->{$kroot};
253.1240 +    
253.1241 +    if (!defined($key)){
253.1242 +        if (!IsWin9x && $kroot){ # !~ m/^CUser/i){
253.1243 +            debug "OP.INTERROTTA - NON TROVO: $kroot\n";
253.1244 +            return;
253.1245 +        }
253.1246 +        $key=$Registry->{$kroot}={};        
253.1247 +        $msg .= "CREO : $kroot\n" ;
253.1248 +    }    
253.1249 +
253.1250 +    #&dispOptions($key,$kroot);
253.1251 +
253.1252 +    #$key->SetOptions(DWordsToHex=>1);
253.1253 +                    
253.1254 +    $msg .= "ROOT = $kroot\n";
253.1255 +    
253.1256 +    # key var
253.1257 +    for (my $j=1;$j<@kv;$j++){       
253.1258 +
253.1259 +        @rvar=split(/=|:/,$kv[$j]);
253.1260 +        $kvar=$cvar=$rvar[0];
253.1261 +        $kvar =~ s/\_{2}/ /g;
253.1262 +        $ktyp=$rvar[1];
253.1263 +        $kdef=$rvar[2];
253.1264 +            
253.1265 +        if (defined($$cvar{$group})){
253.1266 +            $v=$$cvar{$group};         # esiste il valore per il gruppo
253.1267 +        }elsif (defined($$cvar{''})){
253.1268 +            $v=$$cvar{''};             # default definito
253.1269 +        }else{
253.1270 +            $v = $kdef;                  # default di sistema
253.1271 +            $v =~ s/_CDOC/C\:Documenti/g  if ($kdef =~ '_CDOC');
253.1272 +            $v =~ s/_HDOC/H\:Documenti/g  if ($kdef =~ '_HDOC');
253.1273 +            $v ="H:\Documenti" if ($kdef eq '_HDOC');
253.1274 +            my $user = $ENV{USERNAME};
253.1275 +            $v =~ s/_CUPROF/C:\\WINDOWS\\Profiles\\$user/g  if ($kdef =~ '_CUPROF');
253.1276 +            $v =~ s/_DUPROF/C:\\WINDOWS/g  if ($kdef =~ '_DUPROF');
253.1277 +            my $perldir="$ENV{LOGONSERVER}\\perl";
253.1278 +            $v =~ s/_DIRPERL/$perldir/g  if ($kdef =~ '_DIRPERL');
253.1279 +            my $dirlogon="$ENV{LOGONSERVER}\\netlogon";
253.1280 +            $v =~ s/_DIRLOGON/$dirlogon/g  if ($kdef =~ '_DIRLOGON');
253.1281 +        }    
253.1282 +        
253.1283 +        ($vval,$vtype)=$key->GetValue($kvar);
253.1284 +        
253.1285 +        if (!defined($key->{$kvar})){
253.1286 +            $vtype=$ValType{$ktyp};
253.1287 +            $msg .= "ADDVAR: $kvar = $ktyp:$v\n" ;            
253.1288 +        }
253.1289 +        
253.1290 +        if ($vtype == $ValType{REG_SZ}){           
253.1291 +            $msg .= "$j) $kvar \t  $vval -> $v \t(".$DscType[$vtype].")\n" ;            
253.1292 +        }
253.1293 +
253.1294 +        if ($vtype == $ValType{REG_DWORD}){          
253.1295 +            $msg .= "$j) $kvar \t  $vval -> $v \t(".$DscType[$vtype].")\n" ;         
253.1296 +        }
253.1297 +
253.1298 +        if ($vtype == $ValType{REG_BINARY}){       
253.1299 +            $msg .= "$j) $kvar \t".unpack("L",$vval)." -> $v \t(" . $DscType[$vtype] . ")\n" ;
253.1300 +        }
253.1301 +
253.1302 +        $msg .= "     SETVALUE: $kvar , $v , $DscType[$vtype]\n" ;
253.1303 +        
253.1304 +    # forzo la costruzione del valore esadecimale perche' non sembra avvenire
253.1305 +    # automaticamente come documentato, con l'occasione evito la necessita` di indicare
253.1306 +    # il valore come 0x.....
253.1307 +
253.1308 +        if ($vtype == $ValType{REG_DWORD}){          
253.1309 +            if ($v =~ m/^0x/) {
253.1310 +                $v=pack('L',substr($v,3));
253.1311 +            }else{
253.1312 +                $v=pack('L',$v);
253.1313 +            }
253.1314 +        }
253.1315 +    
253.1316 +        if ($vtype == $ValType{REG_BINARY}){
253.1317 +            $v=pack('C4',$v);
253.1318 +        }
253.1319 +        $NOERR=$key->SetValue($kvar , $v , $DscType[$vtype]);
253.1320 +        &debug("$kroot\n$kvar = $v\t\t$DscType[$vtype]\n",0,"ERRORE DI REGISTRO") if (!$NOERR);
253.1321 +    }   
253.1322 +    $msg .= "#-------------------------------\n" ;
253.1323 +    &debug($msg,0,"RegSettings: $pol        gruppo: $group") ;
253.1324 +}        
253.1325 +sub dispOptions{
253.1326 +    my $key=shift;   
253.1327 +    my $kroot=shift;
253.1328 +    my %opt,$k,$v,$msg="";
253.1329 +
253.1330 +    debug("$pol: $kroot");
253.1331 +    $key->GetOptions(\%opt);
253.1332 +    while (($k,$v)=each(%opt)){
253.1333 +        $msg .= "$k = $v\n";
253.1334 +    }
253.1335 +    &debug($msg,0,"REG OPTIONS");
253.1336 +}
253.1337 +sub net_use {
253.1338 +
253.1339 +    @CMD=();
253.1340 +    $group=$ENV{MAINGROUP};
253.1341 +    my $option="";
253.1342 +    my $share;
253.1343 +    my $g;
253.1344 +    my $udsk;
253.1345 +
253.1346 +    if (&IsWin9x){
253.1347 +        push(@CMD,"ECHO NET USE H: /HOME") ;
253.1348 +        push(@CMD,"NET USE H: /HOME");
253.1349 +    }
253.1350 +    
253.1351 +    $option="/PERSISTENT:NO" if (!&IsWin9x);
253.1352 +    if ($ENV{CLASSE}){
253.1353 +        push(@CMD,"ECHO NET USE L: $ENV{LOGONSERVER}\\$ENV{CLASSE} $option") ;
253.1354 +        push(@CMD,"NET USE L: $ENV{LOGONSERVER}\\$ENV{CLASSE} $option");
253.1355 +    }
253.1356 +    
253.1357 +    while (($u,$s)=each(%_NetFolder)){
253.1358 +    
253.1359 +        # vecchia sintassi _NetFolder[S]=share,gruppo
253.1360 +        ($share,$g)=split(/,/,$s);
253.1361 +        
253.1362 +        # nuova sintassi _NetFolder[S:gruppo]=share
253.1363 +        # se ERRONEAMENTE (o per vedere che succede) si scrivesse
253.1364 +        # _NetFolder[S:gruppo1]=share,gruppo2 allora vincerebbe
253.1365 +        # gruppo1, ma non ci sarebbe il mascheramento generato dalla 
253.1366 +        # vecchia sintassi
253.1367 +        ($udsk,$g)=split(/:/,$u);
253.1368 +        
253.1369 +        if ($group eq $g || $g eq ""){
253.1370 +            push(@CMD,"ECHO NET USE $udsk: $ENV{LOGONSERVER}\\$share $option") ;
253.1371 +            push(@CMD,"NET USE $udsk: $ENV{LOGONSERVER}\\$share $option");
253.1372 +        }
253.1373 +    }
253.1374 +
253.1375 +    &esegui;
253.1376 +    
253.1377 +    if (! &IsWin9x){
253.1378 +        &SetKeyVal(\@K_LABELHOME,"",   "LABELHOME");
253.1379 +        &SetKeyVal(\@K_LABELCLASSE,"", "LABELCLASSE");
253.1380 +        &SetKeyVal(\@K_LABELSCAMBIO,"","LABELSCAMBIO");
253.1381 +        &SetKeyVal(\@K_LABELMIOWEB,"", "LABELMIOWEB");
253.1382 +    }   
253.1383 +}
253.1384 +sub set_printers {
253.1385 +
253.1386 +    @CMD=();
253.1387 +    $group=$ENV{MAINGROUP};
253.1388 +    my $option="";
253.1389 +    my $share;
253.1390 +    my $g;
253.1391 +    my $udsk;
253.1392 +    my $my_printers;
253.1393 +    while (($g,$share)=each(%UserPrinter)) {
253.1394 +	$my_printers .= "$share ($g)";
253.1395 +    }
253.1396 +    push(@CMD,"ECHO Ci sono1 $group". $my_printers) ;
253.1397 +    
253.1398 +    if (! &IsWin9x){
253.1399 +      push(@CMD,"ECHO Ci sono2") ;
253.1400 +      while (($g,$share)=each(%UserPrinter)) {
253.1401 +
253.1402 +	  if ($group eq $g || $g eq ""){
253.1403 +	      push(@CMD,"ECHO RunDLL32 PrintUI.DLL,PrintUIEntry /dn /n $share /q") ;
253.1404 +	      push(@CMD,"ECHO RunDLL32 PrintUI.DLL,PrintUIEntry /in /n $share /q") ;
253.1405 +	      push(@CMD,"RunDLL32 PrintUI.DLL,PrintUIEntry /dn /n $ENV{LOGONSERVER}\\$share /q");
253.1406 +	      push(@CMD,"RunDLL32 PrintUI.DLL,PrintUIEntry /in /n $ENV{LOGONSERVER}\\$share /q");
253.1407 +	  }
253.1408 +      }
253.1409 +      if ($group eq 'admins' || $group eq 'Domain Admins') {
253.1410 +          while (($g,$share)=each(%PcPrinter)) {
253.1411 +	      push(@CMD,"ECHO RunDLL32 PrintUI.DLL,PrintUIEntry /gd /n $share /q") ;
253.1412 +	      push(@CMD,"ECHO RunDLL32 PrintUI.DLL,PrintUIEntry /ga /n $share /q") ;
253.1413 +	      push(@CMD,"RunDLL32 PrintUI.DLL,PrintUIEntry /gd /n $ENV{LOGONSERVER}\\$share /q");
253.1414 +	      push(@CMD,"RunDLL32 PrintUI.DLL,PrintUIEntry /ga /n $ENV{LOGONSERVER}\\$share /q");
253.1415 +	  }
253.1416 +      }
253.1417 +    }   
253.1418 +
253.1419 +    &esegui;
253.1420 +    
253.1421 +}
253.1422 +sub net_time {
253.1423 +    my $Ok=&opgruppo(1,$ENV{MAINGROUP},'_NetTime');
253.1424 +    if ($Ok){
253.1425 +        @CMD=();
253.1426 +        push(@CMD,"NET TIME $ENV{LOGONSERVER} /SET /YES");
253.1427 +        &esegui;
253.1428 +    }
253.1429 +}
253.1430 +sub standard_env {
253.1431 +
253.1432 +    my $group = $ENV{MAINGROUP};
253.1433 +    my $os    = $ENV{OSCLIENT};
253.1434 +    my $Ok=&opgruppo(0,$group,"_Env".$os);
253.1435 +    
253.1436 +    &debug("$group  $os  $Ok ",0,"PRIMA DI  ESEGUIRE......") ;
253.1437 +
253.1438 +    if ($Ok){
253.1439 +        my $src =  "$ENV{LOGONSERVER}\\netlogon\\env_".$os."_".$group;
253.1440 +        my $dst;
253.1441 +        if (&IsWin9x) {
253.1442 +            $dst =  "$ENV{ALLUSERSPROFILE}";
253.1443 +        }else{
253.1444 +            $dst =  "$ENV{ALLUSERSPROFILE}";
253.1445 +        }
253.1446 +        &debug("xcopy $src  $dst  /S /Y /C /I /Q /R",0,
253.1447 +        "STO PER ESEGUIRE......") ;
253.1448 +        @CMD=();            
253.1449 +        push(@CMD,"xcopy $src \"$dst\"  /S /Y /C /I /Q /R");
253.1450 +        &esegui;
253.1451 +    }
253.1452 +}
253.1453 +sub esegui  {
253.1454 +    my $success, $msg="",$msgerr=""; 
253.1455 +    
253.1456 +    foreach (@CMD) {    
253.1457 +        $success = system($_) ;
253.1458 +        $msg .= "$_ ( $success )\n" ;       
253.1459 +    }
253.1460 +    &debug($msg,0,'COMANDI ESEGUITI');
253.1461 +    return $success;
253.1462 +}
253.1463 +
253.1464 +1;
   254.1 Binary file usr/share/WinActivePerl/win98/Appwiz.cpl has changed
   255.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   255.2 +++ b/usr/share/doc/isi/acl.conf	Mon Apr 26 11:16:23 2010 +0200
   255.3 @@ -0,0 +1,17 @@
   255.4 +[/home/alunni]
   255.5 +  g:docenti = rxw
   255.6 +  g:ata     = rxw
   255.7 +  o         = ---
   255.8 +
   255.9 +[/home/docenti]
  255.10 +  o         = ---
  255.11 +
  255.12 +[/home/area_scambio]
  255.13 +  copy = /home/classi 
  255.14 +  g:alunni    = rx-
  255.15 +
  255.16 +[/home/classi]
  255.17 +  g:docenti  = rxw
  255.18 +  g:ata      = rxw
  255.19 +  o          = r--
  255.20 +
   256.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   256.2 +++ b/usr/share/doc/isi/etc/isi/acl-local.conf	Mon Apr 26 11:16:23 2010 +0200
   256.3 @@ -0,0 +1,1 @@
   256.4 +### acl-local.conf - personalizza/sovrascrive acl.conf
   257.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   257.2 +++ b/usr/share/doc/isi/etc/isi/defaults.py	Mon Apr 26 11:16:23 2010 +0200
   257.3 @@ -0,0 +1,80 @@
   257.4 +#!/usr/bin/python
   257.5 +# -*- coding: utf-8 -*-
   257.6 +
   257.7 +# This program is free software; you can redistribute it and/or modify
   257.8 +# it under the terms of the GNU General Public License as published by
   257.9 +# the Free Software Foundation; either version 2, or (at your option)
  257.10 +# any later version.
  257.11 +
  257.12 +
  257.13 +# AUTHORS: Sandro Dentella - Massimo Mancini
  257.14 +
  257.15 +"""
  257.16 +These defaults will be overwritten by values in /etc/isi/defaults.py
  257.17 +"""
  257.18 +import os
  257.19 +# struttura della /home
  257.20 +GROUPS_PATH = '/home/users'
  257.21 +CLASSES_PATH = '/home/shares/classi'
  257.22 +COURSES_PATH = '/home/shares/corsi'
  257.23 +
  257.24 +# gruppi a cui vanno assegnati gli utenti se si vuole che possano
  257.25 +# usare chiavette e audio dei client linux
  257.26 +#EXTRA_GROUPS = []
  257.27 +EXTRA_GROUPS = ['plugdev','audio', 'fuse']
  257.28 +
  257.29 +        
  257.30 +# usato da isi2-adduser per l'imput interattivo
  257.31 +DATI_USER = "USER_ID COGNOME NOME GRUPPO GRUPPI COD.FISC. PASSWORD SESSO INDIRIZZO COMUNE CAP PROVINCIA TELEFONO"    
  257.32 +
  257.33 +# configurazione del logger
  257.34 +LOG_FILE = '/var/log/users_error.log'
  257.35 +LOG_MODE = 'w'
  257.36 +LOG_FORMAT = '%(asctime)s %(name)-8s %(levelname)-8s %(message)s'
  257.37 +LOG_DATE_FORMAT='%y-%m-%d %H:%M'
  257.38 +
  257.39 +# configurazione del backup ldap
  257.40 +BAK_LDAP_FILE = '/etc/isi/slapcat.ldif'
  257.41 +
  257.42 +# QUOTA
  257.43 +QUOTA_S1 = 0
  257.44 +QUOTA_S2 = 0
  257.45 +QUOTA_F1 = 0
  257.46 +QUOTA_F2 = 0
  257.47 +QUOTA_REP = '/tmp/repquota.txt'
  257.48 +
  257.49 +# PERMESSI DI DEFAULT SU HOME E FILE (indipendenti da acl)
  257.50 +# alunni ed esterni
  257.51 +PERMS_HOME_ALU = '2770'
  257.52 +PERMS_FILE_ALU = '660'
  257.53 +# tutti gli altri
  257.54 +PERMS_HOME_ALL = '2700'
  257.55 +PERMS_FILE_ALL = '600'
  257.56 +
  257.57 +# NUMERI INIZIALI LDAP
  257.58 +UID_MIN = 1000
  257.59 +GID_MIN = 1000
  257.60 +UID_MAX = 30000
  257.61 +GID_MAX = 30000
  257.62 +
  257.63 +## User's logname format
  257.64 +
  257.65 +GROUP_IDS = {
  257.66 +    'alunni'     : 'a',
  257.67 +    'docenti'    : 'd',
  257.68 +    'admins'     : 'ad',
  257.69 +    'esterni'    : 'e',
  257.70 +    'segreteria' : 's',
  257.71 +    'ata'        : 'at',
  257.72 +    }
  257.73 +
  257.74 +USER_FORMAT = {
  257.75 +    'default' : u'%(group_id)s_%(cf).8s',
  257.76 +    'docenti' : u'%(first_name)s.%(last_name)s',
  257.77 +    }
  257.78 +
  257.79 +CLASSE_FORMAT = u"%(corso)s%(anno_corso)s%(sezione)s" 
  257.80 +
  257.81 +if os.path.exists('/etc/isi/defaults.py'):
  257.82 +    execfile('/etc/isi/defaults.py')
  257.83 +
   258.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   258.2 +++ b/usr/share/doc/isi/etc/isi/labinfo.secret	Mon Apr 26 11:16:23 2010 +0200
   258.3 @@ -0,0 +1,24 @@
   258.4 +### /etc/isi/labinfo.secret
   258.5 +### file di configurazione delle aule di informatica
   258.6 +### viene usato da isi-wlg per la manipolazione dei gruppi locali
   258.7 +### dei client windows (xp) dell'aula stessa
   258.8 +### e modificato isi-wlg nel caso di cambio della password amministrativa
   258.9 +### del client
  258.10 +### FORMATO LINEA: nomehostXP;Administrator_locale%password
  258.11 +### Esempi (replicare decommentando):
  258.12 +
  258.13 +### con credenziali amministrative individuali
  258.14 +#[aula1]
  258.15 +#pc01;administrator%password1
  258.16 +#pc02;administrator%password2
  258.17 +
  258.18 +
  258.19 +### con credenziali amministrative uniche
  258.20 +#[aula2]administrator%password
  258.21 +#pc01
  258.22 +#pc02
  258.23 +
  258.24 +### con credenziali amministrative miste
  258.25 +#[aula1]administrator%password
  258.26 +#pc01
  258.27 +#pc02;administrator%password2
   259.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   259.2 +++ b/usr/share/doc/isi/etc/isi/logon.bat	Mon Apr 26 11:16:23 2010 +0200
   259.3 @@ -0,0 +1,3 @@
   259.4 +:: ##### LOGON.BAT creato da ISI-LOGON #####
   259.5 +@ECHO OFF
   259.6 +\\ISI-PDC\perl\bin\perl \\ISI-PDC\perl\logon.pl ISI-PDC
   260.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   260.2 +++ b/usr/share/doc/isi/etc/isi/logon.conf	Mon Apr 26 11:16:23 2010 +0200
   260.3 @@ -0,0 +1,265 @@
   260.4 +# +-------------------------------------------------+
   260.5 +# � 2002-2005 ReteIsi / www.reteisi.org 
   260.6 +# +-------------------------------------------------+
   260.7 +# $Id: logon.conf 160 2021-09-02 17:23:43Z max $
   260.8 +
   260.9 +###-----------------------------------------------------------------------
  260.10 +### Le variabili dichiarate in questo file sono di due tipi
  260.11 +### quelle che iniziano con un _ sono variabili interne e servono
  260.12 +### ad abilitare (1) o disabilitare (0) la funzionalita`corrispondente
  260.13 +### oppure a passare variabili di configurazione specifiche di
  260.14 +### ISI-logon; le altre DEVONO corrispondere a voci di registro a cui 
  260.15 +### si vuole assegnare il valore scritto di seguito (es. 0x00000001).
  260.16 +### Per ottenere una differente impostazione per uno specifico gruppo
  260.17 +### basta specificare il gruppo come nell'esempio:
  260.18 +### Start__Page[alunni] = www.google.com
  260.19 +### Quando i nomi usati per le variabili sono quelli del registro di
  260.20 +### windows, se il nome della variabile di registro contiene uno
  260.21 +### spazio, sostituirlo con due _ (.Es "Start Page" = Start__Page)
  260.22 +
  260.23 +### sulle variabili prefissate con underscore in generale 
  260.24 +###    1 applica la restrizione
  260.25 +###    0 rimuove la restrizione
  260.26 +### il valore delle variabili di registro va espresso 
  260.27 +### coerentemente con il TIPO (se REG_DWORD, 0x......)
  260.28 +
  260.29 +### NOTA: Le variabili  sono *case sensitive*
  260.30 +###-----------------------------------------------------------------------
  260.31 +
  260.32 +### versione di logon.conf - DA INCREMENTARE AD OGNI MODIFICA di logon.conf 
  260.33 +### per attivare l'aggiornamento degli user.dat (agisce sui client win98)
  260.34 +
  260.35 +_Versione = 0;
  260.36 +
  260.37 +### DEBUG (0,1,2,3)
  260.38 +### 0 = nessun debug 
  260.39 +### 1 = solo console su video o su file (se valorizzato _DebugFile)
  260.40 +### 2 = su schermo (in box grafici: lungo, completo e noioso ;-)
  260.41 +### 3 = sul file locale DBG_macchina.TXT  nella HOME 
  260.42 +
  260.43 +
  260.44 +_DebugLevel = 1
  260.45 +
  260.46 +### opzioni aggiuntive se _DebugLevel=3
  260.47 +### _DebugShare		share samba in cui centralizzare 
  260.48 +### _DebugUsers		lista degli utenti da sottoporre a debug
  260.49 +### _DebugClients	lista dei clients da sottoporre a debug
  260.50 +
  260.51 +# _DebugShare =
  260.52 +# _DebugUsers =
  260.53 +# _DebugClients=
  260.54 +
  260.55 +
  260.56 +### WinSet sezione 'start_page'
  260.57 +Start__Page          = www.google.it
  260.58 +Start__Page[admins]  = www.google.it
  260.59 +
  260.60 +### WinSet sezione 'proxy'
  260.61 +ProxyServer          = XXX.XXX.XXX:8128    # DansGuardian
  260.62 +ProxyServer[admins]  = XXX.XXX.XXX:3128    # Squid (FW permettendo)
  260.63 +ProxyOverride        = www.XXX.XXX,<local>
  260.64 +
  260.65 +### WinSet sezione 'no_profile' (solo XP)
  260.66 +ExcludeProfileDirs   = Impostazioni locali;Temporary Internet Files;Cronologia;Temp;Documenti;Cookies;SendTo
  260.67 +
  260.68 +### WinSet sezione 'no_local_profile' (solo XP)
  260.69 +DeleteRoamingCache  = 1
  260.70 +
  260.71 +### WinSet sezione 'document_folder'
  260.72 +Personal            = H:\Documenti
  260.73 +My__Picture         = 
  260.74 +My__Music			= 
  260.75 +My__Video           = 
  260.76 +
  260.77 +### WinSet sezione 'paranoia_folders' solo per win9x
  260.78 +### se _OkParanoia = 1 vengono ripuliti ad ogni logon il Desktop e il cestino di default.
  260.79 +_OkParanoia        = 0
  260.80 +
  260.81 +
  260.82 +### WinSet sezione 'iepasswordcache' - non salva le password digitate quando si accede a siti web
  260.83 +
  260.84 +_RestrictIEPasswordCaching = 0
  260.85 +
  260.86 +### WinSet sezione 'sync' (solo WinXP)
  260.87 +### per disabilitare la sincronizzazione delle cartelle non in linea
  260.88 +### è necessario porre a 1 la seguente variabile
  260.89 +_NoSync  = 1
  260.90 +
  260.91 +
  260.92 +### WinSet sezione 'autorun' (PER IL MOMENTO NON FUNZIONA!!!!_
  260.93 +### valori possibili: 
  260.94 +###     0x91 = abilita autorun
  260.95 +###     0x95 = disabilita autorun da USB lo mantiene per i CD
  260.96 +###     0xB5 = disabilita completamente l'autorun
  260.97 +NoDriveTypeAutorun = 0xB5
  260.98 +
  260.99 +### WinSet sezione 'last-user' (WinXP)
 260.100 +### gli utenti normali non hanno permessi sufficenti
 260.101 +### gli amministratori (admins) invece possono
 260.102 +### questa situazione viene gestita eliminando
 260.103 +### il default
 260.104 +
 260.105 +_NoDispLastUser[admins]  = 0
 260.106 +
 260.107 +### WinPol9x sezione 'last-user' (Win9X solo con Tweakui installato)
 260.108 +_NoDispLastUser9X = 1
 260.109 +
 260.110 +### parametri validi per Win9x -  default molto restrittivo 
 260.111 +
 260.112 +### di seguito sono specifate tutte e solo le cartelle che possono essere messe in roaming
 260.113 +### separare le cartelle con un ; per default tutte le cartelle sono in roaming
 260.114 +
 260.115 +#_ProleDirs = AppData;Cache;Cookies;Desktop;Favorites;History;NetHood;Programs;Recent;Start Menu;Startup
 260.116 +_ProfileDirs = AppData;Temporary Internet Files;Cookies;Desktop;Favorites;History;NetHood;Programs;Recent;Start Menu;Startup
 260.117 +
 260.118 +### se le cartelle vengono messe in roaming possono anche essere rimappate sul server in modo
 260.119 +### da salvare i documenti durante la sessione ed evitare "traffico" all'uscita,
 260.120 +### se non si specifica alcun percorso vengono messe in roaming nel modo "classico" 
 260.121 +### con il salvataggio sul server all'uscita
 260.122 +
 260.123 +#esempi di percorsi:
 260.124 +#Desktop = H:\.profili\Win95\Desktop
 260.125 +#Cookies=H:\.profili\Win95\Cookies
 260.126 +#Favorites=H:\.profili\Win95\Favorites
 260.127 +
 260.128 +
 260.129 +### WinPol9x sezione 'access'
 260.130 +_RestrictLogon		    	= 1
 260.131 +_RestrictLogon[admins]      = 1
 260.132 +# valori di registro
 260.133 +UserProfiles                = 1 #0x00000001 # si vogliono i roaming profiles
 260.134 +UseHomeDirectory            = 1 #0x00000001 
 260.135 +MustBeValidated             = 1 #0x00000001 # si vuole l'autenticazione ldap
 260.136 +MustBeValidated[admins]     = 1 #0x00000000
 260.137 +LegalNoticeCaption          = XXX.XXX            
 260.138 +LegalNoticeText             = accesso riservato agli utenti autorizzati.
 260.139 +       
 260.140 +### WinPol9x sezione 'nocpan' - fa sparire dal pannello di controllo
 260.141 +_RestrictCpan               = 0
 260.142 +
 260.143 +### WinPol9x sezione 'appwiz' - fa sparire dal pannello di controllo
 260.144 +### l'applet Installa/Rimuovi applicazioni
 260.145 +_NoAppWiz               = 0
 260.146 +
 260.147 +### WinPol9x sezione 'nodrive' - fa sparire le periferiche dalle risorse del computer
 260.148 +_RestrictDrive              = 0
 260.149 +_RestrictDrive[admins]      = 0
 260.150 +
 260.151 +###WinPol9x sezione 'nodrivec' - fa sparire il disco C dalle risorse del computer
 260.152 +_RestrictDriveC             = 1
 260.153 +_RestrictDriveC[admins]     = 0
 260.154 +
 260.155 +### WinPol9x sezione 'nofind' - fa sparire la voce trova dal menu avvio
 260.156 +_RestrictFind               = 1
 260.157 +_RestrictFind[admins]       = 0
 260.158 +
 260.159 +### WinPol9x sezione 'nohistory' - cancella la cronologia
 260.160 +_RestrictHistory            = 0
 260.161 +
 260.162 +### WinPol9x sezione 'iecachedays' - se _SetIECache è settato a 1
 260.163 +### con la variabile successiva DaysToKeep è possibile impostare per
 260.164 +### quanti giorni restano nella cache le pagine web visitate
 260.165 +### Con DaysToKeep = 0x00000000 le pagine non vengono salvate
 260.166 +_SetIECache = 0
 260.167 +DaysToKeep = 0x00000000
 260.168 +
 260.169 +
 260.170 +
 260.171 +### WinPol9x sezione 'nosavesettings' - non salva i cambiamenti al Desktop all'uscita
 260.172 +_RestrictSaveSettings      = 0
 260.173 +
 260.174 +### WinPol9x sezione 'noactivedesktop' - disattiva l'Active Desktop
 260.175 +_RestrictActiveDesktop      = 0
 260.176 +
 260.177 +### WinPol9x sezione 'screen' -  abilita le restrizioni dello schermo
 260.178 +_RestrictScreen             = 1 
 260.179 +_RestrictScreen[admins]     = 0
 260.180 +
 260.181 +# opzioni restrizioni screen
 260.182 +NoDispAppearancePage        = 0 #0x00000000
 260.183 +NoDispBackgroundPage        = 0 #0x00000000
 260.184 +NoDispCPL                   = 0 #0x00000000
 260.185 +NoDispScrSavPage            = 0 #0x00000000
 260.186 +NoDispSettingsPage          = 1 #0x00000001
 260.187 +
 260.188 +# opzioni altre applet del pannello di controllo
 260.189 +NoAdminPage					= 1
 260.190 +NoConfigPage				= 1
 260.191 +NoDevMgrPage				= 1	
 260.192 +NoFileSysPage				= 1	
 260.193 +NoProfilePage				= 1
 260.194 +NoVirtMemPage				= 1
 260.195 +
 260.196 +### WinPol9x sezione 'net'    - Risorse di rete Proprietà          
 260.197 +_RestrictNet		        = 0
 260.198 +_RestrictNet[admins]        = 0
 260.199 +
 260.200 +### WinPol9x sezione 'passwd' = Pannello di controllo Password
 260.201 +_RestrictPasswd             = 1
 260.202 +_RestrictPasswd[admins]     = 0
 260.203 +
 260.204 +### WinPol9x sezione 'printer' - Impostazioni stampanti
 260.205 +_RestrictPrinter	    	= 1
 260.206 +_RestrictPrinter[admins]    = 0
 260.207 +
 260.208 +### WinPol9x sezione 'system'  - Restrizioni varie sul sistema     
 260.209 +_RestrictSystem             = 1
 260.210 +_RestrictSystem[admins]     = 0
 260.211 +
 260.212 +### WinPol9x sezione 'shell-run' - Start Esegui
 260.213 +_RestrictRun                = 0
 260.214 +_RestrictRun[admins]        = 0
 260.215 +
 260.216 +### WinPol9x sezione 'shell-noregtools' - tools per la modifica del registro
 260.217 +_RestrictRegTools           = 0
 260.218 +_RestrictRegTools[admins]   = 0
 260.219 +
 260.220 +### WinPol9x sezione 'shell-winoldapp' - vecchie applicazioni
 260.221 +_RestrictOldApp             = 0
 260.222 +_RestrictOldApp[admins]     = 0
 260.223 +
 260.224 +
 260.225 +### connessioni di rete  oltre a quelle attivate 
 260.226 +### automaticamente, che sono:
 260.227 +### H: -> homedir
 260.228 +### L: -> classe  (solo per gli alunni)
 260.229 +### la sintassi e'la seguente:
 260.230 +### NetFolder[unita'[:gruppo]] = nome della condivisione
 260.231 +###		esempio _NetFolder[U:admins]=util
 260.232 +
 260.233 +_NetFolder[W:alunni] = mioweb      
 260.234 +_NetFolder[S:admins] = software
 260.235 +_NetFolder[Y:Domain Admins] = software
 260.236 +_NetFolder[Y:docenti] = software
 260.237 +_NetFolder[U] = area_alunni
 260.238 +_NetFolder[T:docenti] = area_docenti
 260.239 +_NetFolder[T:docenti] = area_segreteria
 260.240 +_NetFolder[K:docenti] = classi
 260.241 +_NetFolder[K:admins] = classi
 260.242 +_NetFolder[X:admins] = dati
 260.243 +
 260.244 +### sincronizzazione orologio
 260.245 +
 260.246 +_NetTime      = 1
 260.247 +
 260.248 +### forzatura ambiente di default (desktop, menu avvio ecc.ecc.)
 260.249 +### la si ottiene copiando la seguente cartella
 260.250 +
 260.251 +### [netlogon]\env_$os_$gruppo\*  ->  C:\Windows\All Users  (Win9x)
 260.252 +### [netlogon]\env_$os_gruppo\*   ->  C:\Documents and Settings\All Users  (WinXP)
 260.253 +
 260.254 +### dove os = $ENV{OSCLIENT} e'la versione di windows che gira sul client 
 260.255 +### cioe'una delle seguenti: Win95,Win98,WinME,WinNT,Win2K,WinXP
 260.256 +
 260.257 +_EnvWin98           = 1
 260.258 +_EnvWin98[admins]   = 0     
 260.259 +
 260.260 +### ATTENZIONE: per WinXP,Win2K occorre che la cartella di destinazione sia
 260.261 +### scrivibile dagli utenti di dominio il che normalmente non e'; si
 260.262 +### consiglia di non attivare questa funzionalità che, se il client è
 260.263 +### correttamente configurato si rivela sostanzialmente inutile
 260.264 +
 260.265 +_EnvWinXP           = 0
 260.266 +
 260.267 +
 260.268 +
   261.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   261.2 +++ b/usr/share/doc/isi/etc/isi/logon.pl	Mon Apr 26 11:16:23 2010 +0200
   261.3 @@ -0,0 +1,115 @@
   261.4 +#!/usr/bin/perl
   261.5 +
   261.6 +# +-------------------------------------------------+
   261.7 +# � 2002-2005 ReteIsi / www.reteisi.org 
   261.8 +# +-------------------------------------------------+
   261.9 +# $Id: logon.pl,v 1.2 2021/09/02 17:23:43 max Exp $
  261.10 +
  261.11 +use ISI::Logon ;
  261.12 +
  261.13 +# logon.bat richiama logon.pl passandogli
  261.14 +# il nome netbios del server che deve essere
  261.15 +# definito a mano, questo se vogliamo
  261.16 +# che tutte le versioni di windows
  261.17 +# si comportino allo stesso modo
  261.18 +# tutte le variabili necessarie sono contenute
  261.19 +# nell'hash %ENV
  261.20 +
  261.21 +my $srv = shift;
  261.22 +
  261.23 +my $DBG = 1; # attivazione modalita` DEBUG (messaggistica in finestra DOS, comoda!)
  261.24 +my $SDU = 1; # setting Users/.DEFAULT
  261.25 +
  261.26 +#$group = shift;
  261.27 +
  261.28 +&GetInfoLogon($srv);
  261.29 +
  261.30 +&ReadConf("logon.conf",0);
  261.31 +
  261.32 +$DBG=&opgruppo(1,$ENV{MAINGROUP},'_DebugLevel');
  261.33 +
  261.34 +print "NOME SERVER  = $ENV{LOGONSERVER}\n" if ($DBG);
  261.35 +print "VER.OS CLIENT= $ENV{OSCLIENT} \n"   if ($DBG);
  261.36 +print "NOME CLIENT  = $ENV{NETBIOSNAME}\n" if ($DBG);
  261.37 +print "UTENTE       = $ENV{USERNAME}\n"    if ($DBG);
  261.38 +print "GRUPPO MAIN  = $ENV{MAINGROUP}\n"   if ($DBG);
  261.39 +
  261.40 +
  261.41 +### policies x win9x - sostituisce CONFIG.POL
  261.42 +### primo passaggio
  261.43 +
  261.44 +
  261.45 +
  261.46 +&WinPol9x('clearpol',$DBG);
  261.47 +&WinPol9x('access',$DBG);
  261.48 +&WinPol9x('pwdcaching',$DBG);
  261.49 +&WinPol9x('nocpan',$DBG);
  261.50 +&WinPol9x('appwiz',$DBG);
  261.51 +&WinPol9x('nodrive',$DBG);
  261.52 +&WinPol9x('nodrivec',$DBG);
  261.53 +&WinPol9x('noactivedesktop',$DBG);
  261.54 +&WinPol9x('nohistory',$DBG);
  261.55 +&WinPol9x('nosavesettings',$DBG);
  261.56 +&WinPol9x('paranoia',$DBG);
  261.57 +&WinPol9x('nofind',$DBG);
  261.58 +&WinPol9x('last_user',$DBG);
  261.59 +&WinPol9x('screen',$DBG);
  261.60 +&WinPol9x('net',$DBG);
  261.61 +&WinPol9x('passwd',$DBG);
  261.62 +&WinPol9x('printer',$DBG);
  261.63 +&WinPol9x('system',$DBG);
  261.64 +&WinPol9x('shell_run',$DBG);
  261.65 +&WinPol9x('shell_noregtools',$DBG);
  261.66 +&WinPol9x('shell_winoldapp',$DBG);
  261.67 +&WinPol9x('iecachedays',$DBG);
  261.68 +
  261.69 +### visualizzazione nome ultimo utente
  261.70 +
  261.71 +&WinSet('last_user',$DBG);
  261.72 +
  261.73 +### setting browser (IE) 
  261.74 +
  261.75 +&WinSet('start_page',$DBG);
  261.76 +&WinSet('proxy',$DBG);
  261.77 +&WinSet('no_profile',$DBG);
  261.78 +&WinSet('no_local_profile',$DBG);
  261.79 +&WinSet('sync',$DBG);
  261.80 +&WinSet('autorun',$DBG);
  261.81 +&WinSet('document_folder',$DBG);
  261.82 +&WinSet('iepasswordcache',$DBG);
  261.83 +
  261.84 +### connessione cartelle di rete
  261.85 +
  261.86 +&WinSet('net_use',$DBG);
  261.87 +
  261.88 +### controllo se l'utente ha il profilo aggiornato
  261.89 +### eventualmente attivo l'aggiornamento  con lo script logonupd.pl
  261.90 +&WinPol9x('updatecontrol',$DBG);
  261.91 +
  261.92 +### sincronizzazione dell'orologio
  261.93 +
  261.94 +&WinSet('net_time',$DBG);
  261.95 +&WinSet('set_printer',$DBG);
  261.96 +
  261.97 +### predisposizione ambiente client standard
  261.98 +
  261.99 +&WinSet('std_env',$DBG);
 261.100 +
 261.101 +&DbgClose();
 261.102 +
 261.103 +###-------fine-----------------
 261.104 +
 261.105 +
 261.106 +
 261.107 +
 261.108 +
 261.109 +
 261.110 +
 261.111 +
 261.112 +
 261.113 +
 261.114 +
 261.115 +
 261.116 +
 261.117 +
 261.118 +
   262.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   262.2 +++ b/usr/share/doc/isi/etc/isi/logonupd.bat	Mon Apr 26 11:16:23 2010 +0200
   262.3 @@ -0,0 +1,3 @@
   262.4 +:: ##### LOGON.BAT creato da ISI-LOGON #####
   262.5 +@ECHO OFF
   262.6 +\\ISI-PDC\perl\bin\perl \\ISI-PDC\perl\logonupd.pl ISI-PDC
   263.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   263.2 +++ b/usr/share/doc/isi/etc/isi/logonupd.pl	Mon Apr 26 11:16:23 2010 +0200
   263.3 @@ -0,0 +1,86 @@
   263.4 +#!/usr/bin/perl
   263.5 +
   263.6 +# +-------------------------------------------------+
   263.7 +# � 2002-2005 ReteIsi / www.reteisi.org 
   263.8 +# +-------------------------------------------------+
   263.9 +# $Id: logonupd.pl,v 1.1.1.2 2021/10/30 07:35:24 max Exp $
  263.10 +
  263.11 +use ISI::Logon ;
  263.12 +
  263.13 +# logon.bat richiama logon.pl passandogli
  263.14 +# il nome netbios del server che deve essere
  263.15 +# definito a mano, questo se vogliamo
  263.16 +# che tutte le versioni di windows
  263.17 +# si comportino allo stesso modo
  263.18 +# tutte le variabili necessarie sono contenute
  263.19 +# nell'hash %ENV
  263.20 +
  263.21 +my $srv = shift;
  263.22 +
  263.23 +my $DBG = 1; # attivazione modalita` DEBUG (messaggistica in finestra DOS, comoda!)
  263.24 +my $SDU = 0; # setting Users/.DEFAULT
  263.25 +
  263.26 +#$group = shift;
  263.27 +
  263.28 +&GetInfoLogon($srv);
  263.29 +
  263.30 +&ReadConf("logon.conf",1);
  263.31 +
  263.32 +$DBG=&opgruppo(1,$ENV{MAINGROUP},'_DebugLevel');
  263.33 +
  263.34 +print "NOME SERVER  = $ENV{LOGONSERVER}\n" if ($DBG);
  263.35 +print "VER.OS CLIENT= $ENV{OSCLIENT} \n"   if ($DBG);
  263.36 +print "NOME CLIENT  = $ENV{NETBIOSNAME}\n" if ($DBG);
  263.37 +print "UTENTE       = $ENV{USERNAME}\n"    if ($DBG);
  263.38 +print "GRUPPO MAIN  = $ENV{MAINGROUP}\n"   if ($DBG);
  263.39 +
  263.40 +
  263.41 +### policies x win9x - sostituisce CONFIG.POL
  263.42 +### secondo passaggio (commentate le istruzioni da non ripetere)
  263.43 +
  263.44 +&WinPol9x('startupdate',$DBG);
  263.45 +
  263.46 +&WinPol9x('clearpol',$DBG);
  263.47 +&WinPol9x('access',$DBG);
  263.48 +#&WinPol9x('pwdcaching',$DBG);
  263.49 +&WinPol9x('nocpan',$DBG);
  263.50 +&WinPol9x('nodrive',$DBG);
  263.51 +&WinPol9x('nodrivec',$DBG);
  263.52 +&WinPol9x('noactivedesktop',$DBG);
  263.53 +&WinPol9x('nohistory',$DBG);
  263.54 +&WinPol9x('nosavesettings',$DBG);
  263.55 +#&WinPol9x('paranoia',$DBG);
  263.56 +&WinPol9x('nofind',$DBG);
  263.57 +&WinPol9x('last_user',$DBG);
  263.58 +&WinPol9x('screen',$DBG);
  263.59 +&WinPol9x('net',$DBG);
  263.60 +&WinPol9x('passwd',$DBG);
  263.61 +&WinPol9x('printer',$DBG);
  263.62 +&WinPol9x('system',$DBG);
  263.63 +&WinPol9x('shell_run',$DBG);
  263.64 +&WinPol9x('shell_noregtools',$DBG);
  263.65 +&WinPol9x('shell_winoldapp',$DBG);
  263.66 +&WinPol9x('iecachedays',$DBG);
  263.67 +#&WinSet('start_page',$DBG);
  263.68 +#&WinSet('proxy',$DBG);
  263.69 +#&WinSet('no_profile',$DBG);
  263.70 +#&WinSet('sync',$DBG);
  263.71 +&WinSet('document_folder',$DBG);
  263.72 +&WinSet('iepasswordcache',$DBG);
  263.73 +&WinPol9x('profiledirs',$DBG);
  263.74 +&WinPol9x('updateprofiledirs',$DBG);
  263.75 +
  263.76 +&DbgClose();
  263.77 +
  263.78 +
  263.79 +
  263.80 +
  263.81 +
  263.82 +
  263.83 +
  263.84 +
  263.85 +
  263.86 +
  263.87 +
  263.88 +
  263.89 +
   264.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   264.2 +++ b/usr/share/doc/isi/etc/isi/samba/smb_aree.conf	Mon Apr 26 11:16:23 2010 +0200
   264.3 @@ -0,0 +1,26 @@
   264.4 +[area_alunni]
   264.5 +    comment = cartella pubblica di scambio
   264.6 +    path = /home/shares/area_alunni
   264.7 +    read only = No
   264.8 +    directory mask = 0777
   264.9 +
  264.10 +[area_segreteria]
  264.11 +    path = /home/shares/area_segreteria
  264.12 +    comment = cartella per comunicazioni segreteria
  264.13 +    read only = No
  264.14 +    directory mask = 0770
  264.15 +
  264.16 +[area_docenti]
  264.17 +    path = /home/shares/area_docenti
  264.18 +    comment = cartella per scambio fra docenti
  264.19 +    read only = No
  264.20 +    directory mask = 0770
  264.21 +
  264.22 +
  264.23 +[area_riservata]
  264.24 +	comment = Area area_riservata
  264.25 +	path = /home/shares/area_riservata
  264.26 +	guest ok = no
  264.27 +	writable = yes
  264.28 +	browseable =yes
  264.29 +
   265.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   265.2 +++ b/usr/share/doc/isi/etc/isi/samba/smb_classi.conf	Mon Apr 26 11:16:23 2010 +0200
   265.3 @@ -0,0 +1,17 @@
   265.4 +# classi SAMBA - generate con Webmin-ISI-Classi il 08.05.2021
   265.5 +
   265.6 +[classi]
   265.7 +comment = cartella classi
   265.8 +path = /home/shares/classi
   265.9 +guest ok = no
  265.10 +writable = yes
  265.11 +browseable = yes
  265.12 +
  265.13 +
  265.14 +[classe_test]
  265.15 +comment = Classe Test
  265.16 +path = /home/shares/classi/classe_test
  265.17 +guest ok = no
  265.18 +writable = yes
  265.19 +browseable = no
  265.20 +
   266.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   266.2 +++ b/usr/share/doc/isi/etc/isi/samba/smb_corsi.conf	Mon Apr 26 11:16:23 2010 +0200
   266.3 @@ -0,0 +1,16 @@
   266.4 +# corsi SAMBA - reteisi
   266.5 +
   266.6 +[corsi]
   266.7 +comment = cartella corsi
   266.8 +path = /home/shares/corsi
   266.9 +guest ok = no
  266.10 +writable = yes
  266.11 +browseable =yes
  266.12 +
  266.13 +[corso_test]
  266.14 +comment = cartella di classe del corso
  266.15 +path = /home/shares/corsi/corso_test
  266.16 +guest ok = no
  266.17 +writable = yes
  266.18 +browseable =no
  266.19 +
   267.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   267.2 +++ b/usr/share/doc/isi/etc/isi/samba/smb_homes.conf	Mon Apr 26 11:16:23 2010 +0200
   267.3 @@ -0,0 +1,11 @@
   267.4 +# aree SAMBA - modello HOME distribuito da reteisi
   267.5 +
   267.6 +[homes]
   267.7 +   comment = ISI-homes (NON MODIFICARE QUESTA RIGA)
   267.8 +   browseable = no
   267.9 +   writable = yes
  267.10 +   guest ok = no
  267.11 +   veto files = /public_html/
  267.12 +
  267.13 +
  267.14 +
   268.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   268.2 +++ b/usr/share/doc/isi/etc/isi/samba/smb_maingrps.conf	Mon Apr 26 11:16:23 2010 +0200
   268.3 @@ -0,0 +1,66 @@
   268.4 +### share SAMBA - reteisi
   268.5 +
   268.6 +[admins]
   268.7 +comment = cartella di gruppo
   268.8 +path = /home/users/admins
   268.9 +guest ok = no
  268.10 +writable = yes
  268.11 +browseable = no
  268.12 +valid users = root,@admins
  268.13 +
  268.14 +[alunni]
  268.15 +comment = cartella di gruppo
  268.16 +path = /home/users/alunni
  268.17 +guest ok = no
  268.18 +writable = yes
  268.19 +browseable = yes
  268.20 +valid users = root,@admins,@alunni,@docenti
  268.21 +
  268.22 +[ata]
  268.23 +comment = cartella di gruppo
  268.24 +path = /home/users/ata
  268.25 +guest ok = no
  268.26 +writable = yes
  268.27 +browseable = yes
  268.28 +valid users = root,@admins,@ata
  268.29 +
  268.30 +[docenti]
  268.31 +comment = cartella di gruppo
  268.32 +path = /home/users/docenti
  268.33 +guest ok = no
  268.34 +writable = yes
  268.35 +browseable = yes
  268.36 +valid users = root,@admins,@docenti
  268.37 +
  268.38 +[esterni]
  268.39 +comment = cartella di gruppo
  268.40 +path = /home/users/esterni
  268.41 +guest ok = no
  268.42 +writable = yes
  268.43 +browseable = yes
  268.44 +valid users = root,@admins,@esterni,@docenti
  268.45 +
  268.46 +[segreteria]
  268.47 +comment = cartella di gruppo
  268.48 +path = /home/users/segreteria
  268.49 +guest ok = no
  268.50 +writable = yes
  268.51 +browseable = yes
  268.52 +valid users = root,@admins,@segreteria
  268.53 +
  268.54 +[ospiti]
  268.55 +comment = cartella di gruppo
  268.56 +path = /home/users/ospiti
  268.57 +guest ok = no
  268.58 +writable = yes
  268.59 +browseable = yes
  268.60 +valid users = root,@admins,@ospiti
  268.61 +
  268.62 +[gruppo-test]
  268.63 +comment = cartella di gruppo
  268.64 +path = /home/users/grtest
  268.65 +guest ok = no
  268.66 +writable = yes
  268.67 +browseable = yes
  268.68 +valid users = root,@admins,@grtest,@docenti
  268.69 +
   269.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   269.2 +++ b/usr/share/doc/isi/etc/isi/samba/smb_servizi.conf	Mon Apr 26 11:16:23 2010 +0200
   269.3 @@ -0,0 +1,31 @@
   269.4 +[preside]
   269.5 +   comment = Home del preside
   269.6 +   path = /home/users/admins/preside
   269.7 +   browseable = no
   269.8 +   writable = yes
   269.9 +   guest ok = no
  269.10 +   create mask = 0600
  269.11 +   directory mask = 0700
  269.12 +   valid users = preside
  269.13 +
  269.14 +[mioweb]
  269.15 +   comment = web directories
  269.16 +   path = /home/users/%G/%u/public_html
  269.17 +   browseable = no
  269.18 +   writable = yes
  269.19 +   guest ok = no
  269.20 +   force create mode = 0644
  269.21 +   force directory mode = 0711
  269.22 +
  269.23 +[software]
  269.24 +   comment = cartella applicazioni
  269.25 +   path = /home/shares/software
  269.26 +   read only = No
  269.27 +   directory mask = 0777
  269.28 +
  269.29 +[dati]
  269.30 +   comment = /home del server
  269.31 +   path = /home
  269.32 +   read only = No
  269.33 +   browseable = no
  269.34 +
   270.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   270.2 +++ b/usr/share/doc/isi/etc/isi/save-config/isi.list	Mon Apr 26 11:16:23 2010 +0200
   270.3 @@ -0,0 +1,9 @@
   270.4 +# file di configurazione per save-config
   270.5 +# salvataggio configurazione isi
   270.6 +# deve essere copiato in /etc/save-config/files/isi.list
   270.7 +
   270.8 +/etc/smbldap-tools/
   270.9 +/etc/isi
  270.10 +/home/samba
  270.11 +/var/ldap
  270.12 +/var/lib/samba
   271.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   271.2 +++ b/usr/share/doc/isi/etc/isi/sissi-tabcorsi	Mon Apr 26 11:16:23 2010 +0200
   271.3 @@ -0,0 +1,7 @@
   271.4 +# tabella di traduzione nome corsi SISSI -> classi isi
   271.5 +# formato: corso_sissi = classe_isi
   271.6 +# Esempio (per un ITCG):
   271.7 +#   progetto cinque = geo
   271.8 +#   geometri        = geo
   271.9 +#   indirizzo giuridico economico aziendale = ige
  271.10 +#   progetto mercurio = pro
   272.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   272.2 +++ b/usr/share/doc/isi/etc/isi/userid-come	Mon Apr 26 11:16:23 2010 +0200
   272.3 @@ -0,0 +1,29 @@
   272.4 +# REGOLA PER LA COSTRUZIONE DELLO USERID
   272.5 +# si tratta in pratica di un frammento i codice 
   272.6 +# perl che viene interpretato al volo e che puo'
   272.7 +# essere modificato dall'utente senza toccare lo script
   272.8 +# principale isi-prepusers
   272.9 +# le righe precedute dal segno # sono commenti e possono
  272.10 +# essere inserite dovunque
  272.11 +# le variabili in MAISCOLO sono da considerare note e 
  272.12 +# gia' valorizzate con i dati utente. 
  272.13 +# Esse sono $COGNOME, $NOME, $CODFISC, $NATOIL
  272.14 +# la data di nascita e' restituita nel formato yymmgg
  272.15 +
  272.16 +# la regola di default e'
  272.17 +# 
  272.18 +#          $UID="a_".substr($CODFISC,0,11)
  272.19 +#
  272.20 +# ed e' quella assunta quando questo file non contiene 
  272.21 +# istruzioni eseguibili ( o non esiste, o e vuoto, o tutte
  272.22 +# le righe sono commentate.
  272.23 +
  272.24 +# esempio 1 = primi 4 caratteri del cognome 
  272.25 +# $UID=substr($COGNOME,0,4);
  272.26 +
  272.27 +# esempio 2 = primi 3 caratteri del cognome + primi 3 del nome 
  272.28 +# $UID=substr($COGNOME,0,3).substr($NOME,0,3);
  272.29 +
  272.30 +# esempio 3 = primi 3 car.cognome + primi 3 del nome + data di nascita
  272.31 +# $UID = substr($COGNOME,0,3).substr($NOME,0,3).$NATOIL;
  272.32 +
   273.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   273.2 +++ b/usr/share/doc/isi/etc/isi/userpy.conf	Mon Apr 26 11:16:23 2010 +0200
   273.3 @@ -0,0 +1,42 @@
   273.4 +######################################################################
   273.5 +# ISI_USERS
   273.6 +# file di configurazione dei permessi di accesso dei dati utenti
   273.7 +#
   273.8 +# SINTASSI 1:
   273.9 +#	gruppo_princ@gruppo_sec = admin1, admin2,  @gruppo1, @gruppo2 ...
  273.10 +#
  273.11 +# SINTASSI 2:
  273.12 +#	gruppo_princ@ = admin1, admin2,  @gruppo1, @gruppo2 ...
  273.13 +#
  273.14 +# 	le righe che iniziano con un # sono commenti e non saranno 
  273.15 +#	interpretate
  273.16 +#	la sintassi 2 assegna privilegi di root a tutti gli utenti del
  273.17 +#	gruppo principale
  273.18 +# 
  273.19 +# NOTA BENE:
  273.20 +#	affinche' gli utenti dichiarati amministratori di quella
  273.21 +#	particolare risorsa possano effettivamente operare, occorre
  273.22 +#	che isi-users sia chiamato via sudo, esempio:
  273.23 +#
  273.24 +#		$ sudo isi-users classe
  273.25 +#
  273.26 +#	il che comporta la corretta configurazione del file /ets/sudoers
  273.27 +#	vedi esempio in /usr/share/doc/isi-ldap3/sudo/sudoers	
  273.28 +######################################################################
  273.29 +# lunghezze min, max di userID, password e nome classe
  273.30 +USERID_MINLEN = 5
  273.31 +USERID_MAXLEN = 15
  273.32 +USERPW_MINLEN = 8
  273.33 +USERPW_MAXLEN = 14
  273.34 +CLASSE_MAXLEN = 6
  273.35 +
  273.36 +PREFIX_ADMINS = "ad_"
  273.37 +PREFIX_ALUNNI = "a_"
  273.38 +PREFIX_ATA    = "t_"
  273.39 +PREFIX_DOCENTI= "d_"
  273.40 +PREFIX_ESTERNI= "e_"
  273.41 +PREFIX_OSPITI = "o_"
  273.42 +
  273.43 +# -----------------------------------------------------
  273.44 +# da qui in poi l'assegnazione dei privilegi sui gruppi
  273.45 +# -----------------------------------------------------
   274.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   274.2 +++ b/usr/share/doc/isi/etc/isi/wlg.secret	Mon Apr 26 11:16:23 2010 +0200
   274.3 @@ -0,0 +1,23 @@
   274.4 +### WLG.SECRET: file di configurazione di setlogonwlg per la gestione
   274.5 +### dei gruppi locali su client XP durante la fase di logon
   274.6 +
   274.7 +### NOTA IMPORTANTE: proteggere questo file con chmod 600
   274.8 +### per evitare di esporre le password amministrative dei client
   274.9 +
  274.10 +### FORMATO (separatore :)
  274.11 +### campo1) stato: ALLOW|DENY la precedenza è DENY
  274.12 +### campo2) user|gruppo da aggiungere o da cancellare dal gruppo locale
  274.13 +### campo3) gruppo locale windows
  274.14 +### campo4) espressione regolare per il nome host del client windows
  274.15 +### campo5) credenziali amministrative del client
  274.16 +
  274.17 +### per disabilitare una direttiva basta commentarla
  274.18 +### per abilitare una direttiva presente basta decommentarla
  274.19 +### la direttiva DEVE cominciare a inizio riga, non solo ammessi spazi
  274.20 +
  274.21 +#DENY:aatest:Administrators:^xp:Administrator%password
  274.22 +#DENY:classe_test:Administrators:^xp:Administrator%password
  274.23 +
  274.24 +#ALLOW:aatest:Administrators:^xp:Administrator%password
  274.25 +#ALLOW:classe_test:Administrators:^xp:Administrator%password
  274.26 +
   275.1 Binary file usr/share/doc/isi/etc/samba/samba.schema.gz has changed
   276.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   276.2 +++ b/usr/share/doc/isi/etc/samba/smb.conf	Mon Apr 26 11:16:23 2010 +0200
   276.3 @@ -0,0 +1,158 @@
   276.4 +##################################################
   276.5 +# FILE DI CONFIGURAZIONE PER PDC SAMBA3.2
   276.6 +##################################################
   276.7 +[global]
   276.8 +   workgroup = ISI-DOMAIN
   276.9 +   netbios name = ISI-PDC
  276.10 +   server string = %h
  276.11 +   dns proxy = No
  276.12 +   bind interfaces only = Yes
  276.13 +   interfaces = lo, eth0
  276.14 +   smb ports = 139
  276.15 +
  276.16 +#   invalid users = root
  276.17 +#   admin users = root,@admins
  276.18 +#   printer admin = @lpadmin
  276.19 +
  276.20 +### registra i logon via samba: ATTENZIONE le cartelle vanno create
  276.21 +#   utmp = Yes
  276.22 +#   utmp directory = /var/log/samba/utmp
  276.23 +#   wtmp directory = /var/log/samba/wtmp
  276.24 +
  276.25 +### evita l'apertura di notepad con un file desktop.ini
  276.26 +   hide files = /desktop.ini/ntuser.ini/NTUSER.*/
  276.27 +
  276.28 +### conserva i permessi e i privilegi dei file dell'utente
  276.29 +   inherit acls = yes
  276.30 +   inherit owner = yes
  276.31 +
  276.32 +   log file = /var/log/samba/log.%m
  276.33 +   max log size = 1000
  276.34 +   syslog = 0
  276.35 +   log level = 0
  276.36 +
  276.37 +   security = user
  276.38 +   encrypt passwords = true
  276.39 +   passdb backend = ldapsam:ldap://127.0.0.1/
  276.40 +   obey pam restrictions = no
  276.41 +   deadtime = 15
  276.42 +   browseable = no
  276.43 +
  276.44 +   wins support = Yes
  276.45 +   name resolve order = lmhosts host wins bcast
  276.46 +
  276.47 +   local master = yes
  276.48 +   domain master = Yes
  276.49 +   preferred master = Yes
  276.50 +   os level = 254
  276.51 +   domain logons = Yes
  276.52 +   
  276.53 +#   map system = yes
  276.54 +#   map archive = yes
  276.55 +#   map hidden = yes
  276.56 +
  276.57 +   unix password sync = no
  276.58 +   enable privileges = yes
  276.59 +   passwd program = /usr/sbin/smbldap-passwd %u
  276.60 +   passwd chat = *New*password* %n\n *Retype*new*password* %n\n
  276.61 +   socket options = TCP_NODELAY, SO_KEEPALIVE
  276.62 +
  276.63 +   load printers = yes
  276.64 +   printing = cups
  276.65 +   printcap name = cups
  276.66 +
  276.67 +   ldap ssl = no
  276.68 +   ldap passwd sync = yes
  276.69 +   ldap machine suffix = ou=Computers
  276.70 +   ldap idmap suffix = ou=Idmaps
  276.71 +   ldap group suffix = ou=Groups
  276.72 +   ldap user suffix = ou=People
  276.73 +   ldap suffix = dc=isi,dc=lan
  276.74 +   ldap delete dn = Yes
  276.75 +   ldap admin dn = cn=admin,dc=isi,dc=lan
  276.76 +
  276.77 +   logon home = \\%N\%U\.\\.profili\%a
  276.78 +   logon drive = H:
  276.79 +   logon path = \\%N\%U\.profili\%a
  276.80 +   logon script = logon.bat
  276.81 +
  276.82 +   add machine script = /usr/sbin/smbldap-useradd -w "%m"
  276.83 +   set primary group script = /usr/sbin/smbldap-usermod -g "%g" "%u"
  276.84 +   delete user from group script = /usr/sbin/smbldap-groupmod -x "%u" "%g"
  276.85 +   add user to group script = /usr/sbin/smbldap-groupmod -m "%u" "%g"
  276.86 +   delete group script = /usr/sbin/smbldap-groupdel "%g"
  276.87 +   add group script = /usr/sbin/smbldap-groupadd -p "%g"
  276.88 +   delete user script = /usr/sbin/smbldap-userdel "%u"
  276.89 +   add user script = /usr/sbin/smbldap-useradd -m "%u"
  276.90 +   check password script = /usr/bin/crackcheck -s
  276.91 +
  276.92 +   panic action = /usr/share/samba/panic-action %d
  276.93 +   check password script = /usr/bin/crackcheck -s
  276.94 +
  276.95 +[homes]
  276.96 +   comment = ISI-homes (NON MODIFICARE QUESTA RIGA)
  276.97 +   browseable = no
  276.98 +   writable = yes
  276.99 +   guest ok = no
 276.100 +   veto files = /public_html/
 276.101 +
 276.102 +[printers]
 276.103 +   comment = All Printers
 276.104 +   browseable = no
 276.105 +   path = /tmp
 276.106 +   printable = yes
 276.107 +   public = no
 276.108 +   writable = no
 276.109 +   create mode = 0700
 276.110 +
 276.111 +[print$]
 276.112 +   comment = Printer Drivers
 276.113 +   path = /var/lib/samba/printers
 276.114 +   browseable = yes
 276.115 +   read only = yes
 276.116 +   guest ok = no
 276.117 +   write list = @lpadmin, root
 276.118 +
 276.119 +#### ATTENZIONE: configurare i file da includere secondo necessità
 276.120 +#include = /etc/isi/samba/smb_servizi.conf
 276.121 +#include = /etc/isi/samba/smb_maingrps.conf
 276.122 +#include = /etc/isi/samba/smb_classi.conf
 276.123 +#include = /etc/isi/samba/smb_corsi.conf
 276.124 +#include = /etc/isi/samba/smb_aree.conf
 276.125 +
 276.126 +[perl]
 276.127 +   path = /usr/share/WinActivePerl
 276.128 +   comment = Per Windows Binaries
 276.129 +   public = yes
 276.130 +   writable = no
 276.131 +   guest ok = yes
 276.132 +   browseable = no
 276.133 +   
 276.134 +[netlogon]
 276.135 +    comment = ISI-NetLogon (NON MODIFICARE QUESTA RIGA)
 276.136 +    path = /home/samba/netlogon
 276.137 +    guest ok = yes
 276.138 +    browseable = no
 276.139 +    create mask = 0644
 276.140 +    directory mask = 0755
 276.141 +    writable = yes
 276.142 +    root preexec=/usr/sbin/setlogonvar '%U' '%G' '%m'
 276.143 +    root postexec=/usr/sbin/rmlogonvar '%m'
 276.144 +
 276.145 +### la share seguente è opzionale, decommentare se si vuole una condivisione
 276.146 +### per indirizzare velocemente il profilo
 276.147 +
 276.148 +#[profiles]
 276.149 +#   comment = cartelle profili utente
 276.150 +#   path = /home/users/%g/%u/.profili/%a
 276.151 +#   path = /home/users/profili
 276.152 +#   read only = No
 276.153 +#   create mask = 0660
 276.154 +#   directory mask = 2770
 276.155 +#   browseable = No
 276.156 +#   guest ok = Yes
 276.157 +#   profile acls = Yes
 276.158 +#   csc policy = disable
 276.159 +#   # next line is a great way to secure the profiles
 276.160 +#   force user = %U
 276.161 +
   277.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   277.2 +++ b/usr/share/doc/isi/etc/skel/.Xdefaults	Mon Apr 26 11:16:23 2010 +0200
   277.3 @@ -0,0 +1,48 @@
   277.4 +! *background:	linen
   277.5 +*background:	gray85
   277.6 +!*Background:	gray85
   277.7 +*foreground:	gray22
   277.8 +Emacs.font: 6x13
   277.9 +Emacs.pane.menubar.font: 6x13
  277.10 +Emacs*menu*font: 6x13
  277.11 +Emacs.geometry: 80x55
  277.12 +! Emacs.font: -b&h-lucidatypewriter-medium-r-*-*-12-120-75-75-m-*-*-*
  277.13 +Emacs.background: gray78
  277.14 +Emacs.font-lock-reference-face.attributeForeground: forestgreen
  277.15 +Emacs.font-lock-string-face.attributeForeground: slateblue4
  277.16 +!Emacs.font-lock-function-name-face.attributeFont: 7x13bold
  277.17 +!Emacs.font-lock-function-name-face.attributeFont: lucidasans-bold-14
  277.18 +!Emacs.font-lock-function-name-face.attributeForeground: salmon
  277.19 +
  277.20 +XTerm*VT100.Background: gray85
  277.21 +XTerm*VT100.Foreground: gray15
  277.22 +XTerm*SaveLines: 1000
  277.23 +Galeon*geometry: 600x600+0+0
  277.24 +Netscape.TopLevelShell.geometry: =700x550+0+0
  277.25 +Mozilla.TopLevelShell.geometry: =700x550+0+0
  277.26 +Galeon.TopLevelShell.geometry: =700x550+0+0
  277.27 +
  277.28 +*customization:	-color
  277.29 +*VT100*colorBDMode: on
  277.30 +
  277.31 +*XTerm*color0: 	 gray20
  277.32 +*VT100*color1: 	 IndianRed
  277.33 +!*VT100*color2:  green3
  277.34 +*VT100*color2: 	 aquamarine3
  277.35 +*VT100*color3: 	 pink4
  277.36 +*VT100*color4: 	 lightblue4
  277.37 +*VT100*color5: 	 magenta3
  277.38 +!*VT100*color6:  cyan3
  277.39 +*VT100*color6:   thistle
  277.40 +*VT100*color7: 	 lightyellow3
  277.41 +*VT100*color8: 	 gray30
  277.42 +*VT100*color9: 	 Red
  277.43 +*VT100*color10:  aquamarine4
  277.44 +*VT100*color11:  yellow2
  277.45 +*VT100*color12:  blue
  277.46 +*VT100*color13:  magenta
  277.47 +!*VT100*color14: cyan
  277.48 +*VT100*color14:  navy
  277.49 +!*VT100*color15: lightyellow3
  277.50 +*VT100*colorUL:  Brown
  277.51 +*VT100*colorBD:  navy
   278.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   278.2 +++ b/usr/share/doc/isi/etc/skel/.alias	Mon Apr 26 11:16:23 2010 +0200
   278.3 @@ -0,0 +1,6 @@
   278.4 +# $Id: .alias 23 2021-10-15 17:05:08Z root $
   278.5 +# Luis Francisco Gonz�lez <[email protected]> based on that of Vadik Vygonets
   278.6 +# Please check /usr/doc/tcsh/examples/alias to see other possible values.
   278.7 +alias	ls	'ls --color=auto'
   278.8 +alias	md	mkdir
   278.9 +alias	rd	rmdir
   279.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   279.2 +++ b/usr/share/doc/isi/etc/skel/.bash_profile	Mon Apr 26 11:16:23 2010 +0200
   279.3 @@ -0,0 +1,24 @@
   279.4 +# ~/.bash_profile: executed by bash(1) for login shells.
   279.5 +# see /usr/share/doc/bash/examples/startup-files for examples.
   279.6 +# the files are located in the bash-doc package.
   279.7 +
   279.8 +# the default umask is set in /etc/login.defs
   279.9 +#umask 022
  279.10 +
  279.11 +# the rest of this file is commented out.
  279.12 +
  279.13 +# include .bashrc if it exists
  279.14 +
  279.15 +#if [ -f ~/.bashrc ]; then
  279.16 +#    source ~/.bashrc
  279.17 +#fi
  279.18 +
  279.19 +# set PATH so it includes user's private bin if it exists
  279.20 +#if [ -d ~/bin ] ; then
  279.21 +#    PATH=~/bin:"${PATH}"
  279.22 +#fi
  279.23 +
  279.24 +# do the same with MANPATH
  279.25 +#if [ -d ~/man ]; then
  279.26 +#    MANPATH=~/man:"${MANPATH}"
  279.27 +#fi
   280.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   280.2 +++ b/usr/share/doc/isi/etc/skel/.bashrc	Mon Apr 26 11:16:23 2010 +0200
   280.3 @@ -0,0 +1,41 @@
   280.4 +# ~/.bashrc: executed by bash(1) for non-login shells.
   280.5 +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
   280.6 +# for examples
   280.7 +
   280.8 +# If running interactively, then:
   280.9 +if [ "$PS1" ]; then
  280.10 +
  280.11 +    # don't put duplicate lines in the history. See bash(1) for more options
  280.12 +    # export HISTCONTROL=ignoredups
  280.13 +
  280.14 +    # enable color support of ls and also add handy aliases
  280.15 +    if [ "$TERM" != "dumb" ]; then
  280.16 +	eval `dircolors -b`
  280.17 +	alias ls='ls --color=auto'
  280.18 +	#alias dir='ls --color=auto --format=vertical'
  280.19 +	#alias vdir='ls --color=auto --format=long'
  280.20 +    fi
  280.21 +
  280.22 +    # some more ls aliases
  280.23 +    #alias ll='ls -l'
  280.24 +    #alias la='ls -A'
  280.25 +    #alias l='ls -CF'
  280.26 +
  280.27 +    # set a fancy prompt
  280.28 +    PS1='\u@\h:\w\$ '
  280.29 +
  280.30 +    # If this is an xterm set the title to user@host:dir
  280.31 +    #case $TERM in
  280.32 +    #xterm*)
  280.33 +    #    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
  280.34 +    #    ;;
  280.35 +    #*)
  280.36 +    #    ;;
  280.37 +    #esac
  280.38 +
  280.39 +    # enable programmable completion features (you don't need to enable
  280.40 +    # this, if it's already enabled in /etc/bash.bashrc).
  280.41 +    #if [ -f /etc/bash_completion ]; then
  280.42 +    #  . /etc/bash_completion
  280.43 +    #fi
  280.44 +fi
   281.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   281.2 +++ b/usr/share/doc/isi/etc/skel/.bashrc-sd	Mon Apr 26 11:16:23 2010 +0200
   281.3 @@ -0,0 +1,38 @@
   281.4 +# ~/.bashrc: executed by bash(1) for non-login shells.
   281.5 +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
   281.6 +# for examples
   281.7 +
   281.8 +# If running interactively, then:
   281.9 +if [ "$PS1" ]; then
  281.10 +
  281.11 +    # don't put duplicate lines in the history. See bash(1) for more options
  281.12 +    # export HISTCONTROL=ignoredups
  281.13 +
  281.14 +    # enable color support of ls and also add handy aliases
  281.15 +    eval `dircolors -b`
  281.16 +    alias ls='ls --color=auto'
  281.17 +    #alias dir='ls --color=auto --format=vertical'
  281.18 +    #alias vdir='ls --color=auto --format=long'
  281.19 +
  281.20 +    # some more ls aliases
  281.21 +    #alias ll='ls -l'
  281.22 +    #alias la='ls -A'
  281.23 +    #alias l='ls -CF'
  281.24 +
  281.25 +    # set a fancy prompt
  281.26 +    PS1='\u@\h:\w\$ '
  281.27 +
  281.28 +    # If this is an xterm set the title to user@host:dir
  281.29 +    #case $TERM in
  281.30 +    #xterm*)
  281.31 +    #    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
  281.32 +    #    ;;
  281.33 +    #*)
  281.34 +    #    ;;
  281.35 +    #esac
  281.36 +
  281.37 +fi
  281.38 +
  281.39 +[ -f /etc/bash.bashrc ] && . /etc/bash.bashrc
  281.40 +
  281.41 +
   282.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   282.2 +++ b/usr/share/doc/isi/etc/skel/.cshrc	Mon Apr 26 11:16:23 2010 +0200
   282.3 @@ -0,0 +1,13 @@
   282.4 +# $Id: .cshrc 23 2021-10-15 17:05:08Z root $
   282.5 +# Luis Francisco Gonz�lez <[email protected]> based on that of Vadik Vygonets
   282.6 +# Please check /usr/doc/tcsh/examples/cshrc to see other possible values.
   282.7 +if ( $?prompt ) then
   282.8 +  set autoexpand
   282.9 +  set autolist
  282.10 +  set cdpath = ( ~ )
  282.11 +  set pushdtohome
  282.12 +
  282.13 +# Load aliases from ~/.alias
  282.14 +  if ( -e ~/.alias )	source ~/.alias
  282.15 +
  282.16 +endif
   283.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   283.2 +++ b/usr/share/doc/isi/etc/skel/.emacs	Mon Apr 26 11:16:23 2010 +0200
   283.3 @@ -0,0 +1,395 @@
   283.4 +;; FIRST:   Do:  M-x outline-minor-mode
   283.5 +;; SECOND:  try M-h too see the index of the file! (outline-minor-mode)
   283.6 +; I don't know why it beahaves oddly if you force it w/ -*- line
   283.7 +
   283.8 +;;;; dir where to load  & REMAPPING HELP!!! (C-h is to eat backword!!!)
   283.9 +;; we add a dir where lo took for files when loading 
  283.10 +(setq load-path (cons "~/.emacsdir" load-path))
  283.11 +(setq default-major-mode 'text-mode)
  283.12 +
  283.13 +;;;; Just for emacs21
  283.14 +(if (string-equal "21" (substring (emacs-version) 10 12))
  283.15 +    (progn
  283.16 +      (blink-cursor-mode 0)
  283.17 +      ;; Insert newline when you press `C-n' (next-line)
  283.18 +      ;; at the end of the buffer
  283.19 +      (setq next-line-add-newlines t)
  283.20 +      ;; Turn on image viewing
  283.21 +      (auto-image-file-mode t)
  283.22 +      ;; Turn on menu bar (this bar has text)
  283.23 +      ;; (Use numeric argument to turn on)
  283.24 +      (menu-bar-mode 1)
  283.25 +      ;; Turn off tool bar (this bar has icons)
  283.26 +      ;; (Use numeric argument to turn on)
  283.27 +      (tool-bar-mode nil)
  283.28 +      ;; Turn off tooltip mode for tool bar
  283.29 +      ;; (This mode causes icon explanations to pop up)
  283.30 +      ;; (Use numeric argument to turn on)
  283.31 +      (tooltip-mode nil)
  283.32 +      ;; If tooltips turned on, make tips appear promptly
  283.33 +      (setq tooltip-delay 0.1)  ; default is one second
  283.34 +       ))
  283.35 +
  283.36 +
  283.37 +; (hscroll-global-mode nil)
  283.38 +;;;; hilighting & fill
  283.39 +;(server-start nil)
  283.40 +;;(load-file "~/.emacs.elc")
  283.41 +;; this remaps C-h -> C-xh
  283.42 +(global-set-key "\C-xh" 'help-command) ;; overrides mark-whole-buffer
  283.43 +(global-unset-key "\C-h" ) 
  283.44 +; non perdere l' ultimo bit dell' input
  283.45 +;(set-input-mode nil nil 1)
  283.46 +;;;; look & feel: decoration & hiligting
  283.47 +;; maximum decoration in hilighting
  283.48 +    (setq font-lock-maximum-decoration t)
  283.49 +    (global-font-lock-mode t)
  283.50 +; auto-copress will correcly deal w/ tar.gz files (gunzip then tar t)
  283.51 +    (auto-compression-mode nil)
  283.52 +;; autofill si ferma alla colonna 77
  283.53 +    (setq-default fill-column 76)
  283.54 +;;;; Scrolling 1 row at a time
  283.55 +   (global-set-key "\C-z"  (lambda () (interactive) (scroll-up 1)))
  283.56 +   (global-set-key "\M-z"  (lambda () (interactive) (scroll-up -1)))
  283.57 +   (global-set-key "\C-h" 'delete-backward-char)
  283.58 +;; C-u kill backward
  283.59 +  (global-set-key "\C-cu" [?\C-  ?\C-a ?\C-w])
  283.60 +;;;; Paren
  283.61 +   (require 'paren)
  283.62 +   (show-paren-mode 1)
  283.63 +;;;; kill & yank / search & replace
  283.64 +;; search & replace
  283.65 +    (global-set-key "\C-cr" 'query-replace-regexp)
  283.66 +;;;; Font-Lock Mode - Add color to text moden
  283.67 +; Here I add some colors for text mode (my default)
  283.68 + (defvar text-font-lock-keywords
  283.69 +   (eval-when-compile
  283.70 +       (list
  283.71 +	;;
  283.72 +	;; Function name declarations.
  283.73 +;	'("\\<\\(proc\\|AA\-\\)\\>[ \t]*\\(\\sw+\\)?\\(.*\\)"
  283.74 +	'("^\\(#.*|\\)[ \t]*\\([A-z(){}._]+\\)?\\(.*\\)"
  283.75 +	  (1 font-lock-comment-face) (2 font-lock-function-name-face nil t)
  283.76 +	  (3 font-lock-keyword-face nil t))
  283.77 +     '("^\\s-*\\([-]\\S-*\\) +\\(\\sw+\\)" (1 font-lock-warning-face) 
  283.78 +       (2 font-lock-keyword-face nil t))
  283.79 +     ; bold face for *words*
  283.80 +     '("\\s-\\(\\*[^*]+\\*\\)\\s-" . font-lock-string-face) 
  283.81 +     ; italic face for _words*
  283.82 +     '("\\s-\\(\\_[^*]+\\*\\)\\s-" . font-lock-comment-face) 
  283.83 +     ; title row for menu.lst in grub...
  283.84 +     '("^\\(title \\)\\(.*\\)" 
  283.85 +	  (1 font-lock-comment-face) (2 font-lock-function-name-face nil t))
  283.86 +     ;; NOTE: it is important the order of the lines defining color match
  283.87 +     ; the next colors a line beginning w/ >% but > is redefined below
  283.88 +     '("^\\(\\s-*>\\s-*>.*\\|%[^\n]*\\)" . font-lock-type-face) 
  283.89 +     ; the next colors a  line beginning w/ >>
  283.90 +     '("^\\(\\s-*>[^>\n]+\\)" . font-lock-comment-face) 
  283.91 +     '("^\\([.']H +\\w+\\) \\(.+\\)" (1 font-lock-keyword-face) 
  283.92 +       (2 font-lock-function-name-face nil t))
  283.93 +       ))
  283.94 +   "Default expressions to highlight in text mode.")
  283.95 +
  283.96 + (add-hook 'text-mode-hook
  283.97 +  (function (lambda ()
  283.98 +              (make-local-variable 'font-lock-defaults)
  283.99 +              (setq font-lock-defaults 
 283.100 +		 '(text-font-lock-keywords nil nil ))
 283.101 +;  questo pare non servire... (?: . "w") (?_ . "w") 
 283.102 +	      ; copiato senza capire gran che' da tcl-mode
 283.103 +;	      (set-syntax-table (copy-syntax-table))
 283.104 +	      (modify-syntax-entry ?# "<")
 283.105 +;	      (modify-syntax-entry ?\n ">")
 283.106 +	      (modify-syntax-entry ?| ">")
 283.107 +	      (modify-syntax-entry ?\n ">")
 283.108 +)))
 283.109 + (add-hook 'tex-mode-hook
 283.110 +  (function (lambda ()
 283.111 +              (make-local-variable 'font-lock-defaults)
 283.112 +              (setq font-lock-defaults nil)
 283.113 +)))
 283.114 +
 283.115 +
 283.116 +;;;; Outline & related bind - use add-hooks for tcl, text, python, sh
 283.117 +    (set-variable (quote outline-minor-mode-prefix) (quote "\C-ch"))
 283.118 +    (require 'outline)
 283.119 +;;     (require 'allout)
 283.120 +;;     (outline-init t)
 283.121 +    (require 'foldout)
 283.122 +;    (outline-minor-mode t)
 283.123 +;    (require 'out-xtra)
 283.124 +;    (make-local-variable (quote outline-regexp))
 283.125 +;    (global-set-key "\C-chi" 'make-indirect-buffer)
 283.126 +;    (global-set-key "\C-chj" 'show-entry)
 283.127 +;    (global-set-key "\C-chb" 'show-branches)
 283.128 +;    (global-set-key "\C-chh" 'hide-sublevels)
 283.129 +    (global-set-key "\M-h" 'hide-sublevels)
 283.130 +    (global-set-key "\M-j" 'show-subtree)
 283.131 +    (global-set-key "\M-k" 'hide-subtree)
 283.132 +;    (global-set-key "\C-chk" 'hide-leaves)
 283.133 +;    (global-set-key "\C-ch2" 'make-indirect-buffer)
 283.134 +;    (global-set-key "\C-cht" 'hide-body)
 283.135 +;    (global-set-key "\C-cht" 'hide-body)
 283.136 +    (add-hook 'tcl-mode-hook
 283.137 +              (function
 283.138 +                (lambda ()
 283.139 +		  (turn-on-follow-mode)
 283.140 +		 (outline-minor-mode t)
 283.141 +;		 (hscroll-mode t)
 283.142 +                 (make-local-variable (quote outline-regexp))
 283.143 +                 (setq outline-level 'outline-level)
 283.144 +                 (set-variable (quote outline-regexp) 
 283.145 + 	         (quote "proc\\|####?\\|# - #\\| +###\\|    for\\|    if ")))))
 283.146 +    (add-hook 'python-mode-hook
 283.147 +              (function
 283.148 +                (lambda ()
 283.149 +;		  (turn-on-follow-mode)
 283.150 +		 (outline-minor-mode t)
 283.151 +;		 (hscroll-mode t)
 283.152 +                 (make-local-variable (quote outline-regexp))
 283.153 +                 (set-variable (quote outline-regexp) 
 283.154 + 	         (quote " *def ..\\|####?\\|# - #\\|class")))))
 283.155 +    (add-hook 'text-mode-hook
 283.156 +              (function
 283.157 +                (lambda ()
 283.158 +		  (turn-on-follow-mode)
 283.159 +		 (outline-minor-mode t)
 283.160 +;                 (set-variable (quote comment-start) (quote "# "))
 283.161 +		 (set (make-local-variable 'comment-start) "# ")
 283.162 +		 (set (make-local-variable 'comment-start-skip) "# *")
 283.163 +                 (make-local-variable (quote outline-regexp))
 283.164 +                 (set-variable (quote outline-regexp) (quote "\\.H *[0-9]")))))
 283.165 +    (add-hook 'sh-mode-hook
 283.166 +              (function
 283.167 +                (lambda ()
 283.168 +		  (turn-on-follow-mode)
 283.169 +		 (outline-minor-mode t)
 283.170 +                 (setq outline-level 'sh-outline-level)
 283.171 +                 (make-local-variable (quote outline-regexp))
 283.172 +                 (set-variable (quote outline-regexp) 
 283.173 +			       (quote "### \\|func\\|.*()")))))
 283.174 +     (add-hook 'lisp-mode-hook
 283.175 +               (function
 283.176 +                 (lambda ()
 283.177 + 		 (outline-minor-mode t))))
 283.178 +;                  (make-local-variable (quote outline-regexp)))))
 283.179 +
 283.180 +
 283.181 +
 283.182 +;;;; functions
 283.183 +;; this function forces all pattern of outline-regexp of a function to behave 
 283.184 +;; the same way, independent of thei length. Use it in cnjunction w/
 283.185 +; -*- outline-regexp: "## # \\|.*()" -*-
 283.186 +;; and all functions will be part of the "index" toghether w/ all the lines 
 283.187 +;; that have ## # at the beginning 
 283.188 +(defun sh-outline-level () 1)
 283.189 +
 283.190 +;; sst C-cs
 283.191 +;; I repeat it twice so that colors get ok... this seem to depend on outline 
 283.192 +;; mode being requested by the -*- line at beginning!!! 
 283.193 +(fset 'sd-sost
 283.194 +   [?\C-a ?\C-  ?\M-f escape ?1 escape ?| ?s ?s ?t return])
 283.195 +; (fset 'sd-sost
 283.196 +;    [?\C-a ?\C-  ?\M-f escape ?1 escape ?| ?s ?s ?t return])
 283.197 +  (global-set-key "\C-cs" 'sd-sost)
 283.198 +;;;; EDIFF
 283.199 +  (global-set-key "\C-cer" 'ediff-revision)
 283.200 +  (global-set-key "\C-cef" 'ediff-files)
 283.201 +  (global-set-key "\C-ceb" 'ediff-buffers)
 283.202 +  (global-set-key "\C-cem" 'ediff-merge)
 283.203 +  (global-set-key "\C-ced" 'ediff-directories)
 283.204 +  ; the following position the control-frame for ediff 5 pixel lower than default
 283.205 +  (set-variable (quote ediff-control-frame-upward-shift) -5)
 283.206 +;;;; Comment region
 283.207 +  (global-set-key "\C-cc" 'comment-region)
 283.208 +  (global-set-key "\C-cU" [escape ?- ?1 ?\C-c ?c])
 283.209 +  ;  (global-set-key "\C-cu" '(comment-region -1))
 283.210 +;;;; Text-mode - definig paragraph
 283.211 +(add-hook 'text-mode-hook
 283.212 +   (function
 283.213 +    (lambda ()
 283.214 +     (set-variable (quote paragraph-start) "[ 	]*$\\|^\\|^[ 	]*-"))))
 283.215 +
 283.216 +;;;; TAGS
 283.217 +  (global-set-key "\C-ctv" 'visit-tags-table)
 283.218 +  (global-set-key "\C-ctr" 'tags-reset-tags-tables)
 283.219 +  (global-set-key "\C-cts" 'tags-search)
 283.220 +  (global-set-key "\C-ctq" 'tags-query-replace)
 283.221 +  (global-set-key "\C-cta" 'tags-apropos)
 283.222 +;;;; MULE & iso-accent 
 283.223 +;; Sistemiamo MULE (internazionalizzazione)
 283.224 +  (standard-display-european t)
 283.225 +;  (set-input-mode nil nil 1)
 283.226 +  (load-library "iso-insert")
 283.227 +  (load-library "iso-acc")
 283.228 +  (add-hook 'text-mode-hook 'iso-accents-mode)
 283.229 +  ; Con la segg istruzione evito che // diventi �
 283.230 +;  (iso-accents-customize "french")
 283.231 +;  (iso-accents-customize "spanish")
 283.232 +  ;; non voglio che "a venga modificato: rinuncio anche alla dieresi: Tant pis
 283.233 +(setq iso-accents-enable '(?' ?` ?^  ?~ ))
 283.234 +;;;; Ispell (if .emacsdir is there)
 283.235 +(if (file-exists-p "~/.emacsdir") 
 283.236 +    (progn
 283.237 +      (require 'ispell)
 283.238 +      (load-library "ispell-patch.el")
 283.239 +    ; (setq ispell-dictionary-alist
 283.240 +    ;      (append ispell-dictionary-alist
 283.241 +    ;       '(("italian"
 283.242 +    ;          "[A-Za-z]"
 283.243 +    ;          "[^A-Za-z]"
 283.244 +    ;           "[---']" t nil "~list" iso-8859-1))))
 283.245 +
 283.246 +      (global-set-key "\C-cir" 'ispell-region) 
 283.247 +      (global-set-key "\C-cib" 'ispell-buffer) 
 283.248 +      (global-set-key "\C-cim" 'ispell-minor-mode) 
 283.249 +      (global-set-key "\C-cid" 'ispell-change-dictionary)
 283.250 +      (global-set-key "\C-x\C-t" 'write-region) 
 283.251 +      (set-default 'ispell-local-dictionary "italian-ge")))
 283.252 +
 283.253 +;;;; Misc: comint, repeat, goto...
 283.254 +    (add-hook 'text-mode-hook 'turn-on-auto-fill)
 283.255 +    ;; questo in origine e` C-x ESC ESC
 283.256 +    (global-set-key "\C-cx" 'repeat-complex-command)
 283.257 +    (global-set-key "\C-c " 'comint-dynamic-complete)  
 283.258 +    (global-set-key "\C-\M-g" 'goto-line)  
 283.259 +    (put 'downcase-region 'disabled nil)
 283.260 +
 283.261 +    (setq auto-mode-alist
 283.262 +	    (cons '("\\.py$" . python-mode) auto-mode-alist))
 283.263 +    (setq interpreter-mode-alist
 283.264 +	  (cons '("python" . python-mode)
 283.265 +		  interpreter-mode-alist))
 283.266 +    (autoload 'python-mode "python-mode" "Python editing mode." t)
 283.267 +    ;; psgml
 283.268 +    (autoload 'sgml-mode "psgml" "Major mode to edit SGML files." t)
 283.269 +    (autoload 'xml-mode "psgml" "Major mode to edit XML files." t)
 283.270 +
 283.271 +
 283.272 +;;;; Desktop
 283.273 +  (load "desktop")
 283.274 +  (desktop-load-default)
 283.275 +  ;      (desktop-read)
 283.276 +;;;; ps-printing
 283.277 +  (setq ps-print-color-p t)
 283.278 +  ;; (setq ps-paper-type "a4")
 283.279 +  (set-variable (quote ps-paper-type) (quote a4))
 283.280 +  (setq ps-lpr-command "lpr")
 283.281 +  (setq ps-lpr-switches '("-Pfile"))
 283.282 +  (setq ps-bold-faces '(times))
 283.283 +  (setq ps-zebra-stripes t)
 283.284 +  (setq ps-build-face-reference t)
 283.285 +  (setq ps-zebra-stripe-height 4)
 283.286 +  (setq ps-line-number nil)
 283.287 +  (global-set-key "\C-cpb" 'ps-print-buffer-with-faces)
 283.288 +  (global-set-key "\C-cpr" 'ps-print-region-with-faces)
 283.289 +  (global-set-key "\C-cpxd" 'ps-despool)
 283.290 +  ;(global-set-key '(control f22) 'ps-despool)
 283.291 +;;;; Latex & dvi
 283.292 +   (setq tex-dvi-view-command "tkdvi")
 283.293 +   ;(setq latex-run-command "lx -q")
 283.294 +   (setq latex-run-command "latex")
 283.295 +   ;;(setq tex-directory "./")
 283.296 +;;;; custom set faces
 283.297 +(custom-set-faces
 283.298 +  ;; custom-set-faces was added by Custom -- don't edit or cut/paste it!
 283.299 +  ;; Your init file should contain only one such instance.
 283.300 + '(sh-heredoc-face ((((class color) (background light)) (:background "darkseagreen" :foreground "Navy")))))
 283.301 +
 283.302 +
 283.303 +
 283.304 +;;;; GNU Server
 283.305 +(if (file-exists-p ".emacsdir/gnuserv")
 283.306 +    (progn
 283.307 +      (gnuserv-start)
 283.308 +      (global-set-key "\C-x\C-c" 'gnuserv-edit)))
 283.309 +;(require 'preview)
 283.310 +;;;; msb-mode - fancy buffer menu
 283.311 +(msb-mode)
 283.312 +(defconst msb--sd-many-menus  
 283.313 +  '(((and (boundp 'server-buffer-clients)
 283.314 +	  server-buffer-clients
 283.315 +	  'multi)
 283.316 +     1010
 283.317 +     "Clients (%d)")
 283.318 +    ((and (boundp 'vc-mode) vc-mode 'multi)
 283.319 +     1020
 283.320 +     "Version Control (%d)")
 283.321 +    ((and buffer-file-name
 283.322 +	  (buffer-modified-p)
 283.323 +	  'multi)
 283.324 +     1030
 283.325 +     "Changed files (%d)")
 283.326 +    ((and (get-buffer-process (current-buffer))
 283.327 +	  'multi)
 283.328 +     1040
 283.329 +     "Processes (%d)")
 283.330 +    ((and msb-display-invisible-buffers-p
 283.331 +	  (msb-invisible-buffer-p)
 283.332 +	  'multi)
 283.333 +     1090
 283.334 +     "Invisible buffers (%d)")
 283.335 +    ((eq major-mode 'dired-mode)
 283.336 +     2010
 283.337 +     "Dired (%d)"
 283.338 +     ;; Note this different menu-handler
 283.339 +     msb-dired-item-handler
 283.340 +     ;; Also note this item-sorter
 283.341 +     msb-sort-by-directory)
 283.342 +    ((eq major-mode 'Man-mode)
 283.343 +     5030
 283.344 +     "Manuals (%d)")
 283.345 +    ((eq major-mode 'w3-mode)
 283.346 +     5020
 283.347 +     "WWW (%d)")
 283.348 +    ((or (memq major-mode
 283.349 +	       '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode))
 283.350 +	 (memq major-mode '(mh-letter-mode mh-show-mode mh-folder-mode))
 283.351 +	 (memq major-mode '(gnus-summary-mode message-mode gnus-group-mode
 283.352 +			    gnus-article-mode score-mode
 283.353 +			    gnus-browse-killed-mode)))
 283.354 +     5010
 283.355 +     "Mail (%d)")
 283.356 +    ;; Catchup for all non-file buffers
 283.357 +    ((and (not buffer-file-name)
 283.358 +	  'no-multi)
 283.359 +     5099
 283.360 +     "Other non-file buffers (%d)")
 283.361 +    ((and (string-match "/\\.[^/]*$" buffer-file-name)
 283.362 +	  'multi)
 283.363 +     1080
 283.364 +     "Hidden Files (%d)")
 283.365 +    ((eq major-mode 'tcl-mode)
 283.366 +     1071
 283.367 +     "Tcl Files (%d)")
 283.368 +    ((memq major-mode '(c-mode c++-mode))
 283.369 +     3010
 283.370 +     "C/C++ Files (%d)")
 283.371 +    ((eq major-mode 'emacs-lisp-mode)
 283.372 +     3020
 283.373 +     "Elisp Files (%d)")
 283.374 +    ((eq major-mode 'sh-mode)
 283.375 +     3021
 283.376 +     "Shell Files (%d)")
 283.377 +    ((eq major-mode 'awk-mode)
 283.378 +     3022
 283.379 +     "Awk Files (%d)")
 283.380 +    ((eq major-mode 'latex-mode)
 283.381 +     3030
 283.382 +     "LaTex Files (%d)")
 283.383 +    ((eq major-mode 'nroff-mode)
 283.384 +     3031
 283.385 +     "Nroff Files (%d)")
 283.386 +    ((eq major-mode 'text-mode)
 283.387 +     3032
 283.388 +     "Text Files (%d)")
 283.389 +    ('no-multi
 283.390 +     3099
 283.391 +     "Other files (%d)")))
 283.392 +(custom-set-variables
 283.393 +  ;; custom-set-variables was added by Custom -- don't edit or cut/paste it!
 283.394 +  ;; Your init file should contain only one such instance.
 283.395 + '(case-fold-search t)
 283.396 + '(msb-display-most-recently-used 25)
 283.397 + '(msb-max-menu-items 25)
 283.398 + '(msb-menu-cond msb--sd-many-menus))
   284.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   284.2 +++ b/usr/share/doc/isi/etc/skel/.xsession-sd	Mon Apr 26 11:16:23 2010 +0200
   284.3 @@ -0,0 +1,61 @@
   284.4 +#!/bin/sh 
   284.5 +
   284.6 +# Merge in defaults and keymaps
   284.7 +
   284.8 +# killall Xvnc
   284.9 +# sleep 2
  284.10 +# if [ "`pidof Xvnc`" = "" ]
  284.11 +# then
  284.12 +# 	/usr/bin/X11/Xvnc :1 -desktop X -httpd /usr/local/vnc/classes \
  284.13 +# 		-alwaysshared \
  284.14 +# 		-auth /.Xauthority -geometry 1024x768 \
  284.15 +# 		-depth 24 -rfbwait 120000 -rfbauth /.vnc/passwd \
  284.16 +# 		-rfbport 5901 &
  284.17 +# 	sleep 5
  284.18 +# fi
  284.19 +
  284.20 +userresources=$HOME/.Xresources
  284.21 +usermodmap=$HOME/.Xmodmap
  284.22 +sysmodmap=/etc/X11/Xmodmap
  284.23 + 
  284.24 +if [ -f "$sysmodmap" ]; then xmodmap $sysmodmap; fi
  284.25 +if [ -f "$userresources" ]; then xrdb -merge $userresources; fi
  284.26 +if [ -f "$usermodmap" ]; then xmodmap $usermodmap; fi
  284.27 +
  284.28 +# turn mousekeys on and expiry (timeout) off
  284.29 +if [ -f /usr/X11R6/bin/xkbse ] ; then
  284.30 +    xkbset m
  284.31 +    xkbset exp =m
  284.32 +    xmodmap -e "keycode 113 = Pointer_Button2"
  284.33 +    xmodmap -e "keycode 109 = Pointer_Button3" 
  284.34 +    xmodmap -e "keycode 117 = Pointer_Button3"
  284.35 +fi
  284.36 +# this uses accessx
  284.37 +# /home/local/bin/ax +mousekeys
  284.38 +
  284.39 +xmodmap -e "remove Lock = Caps_Lock"
  284.40 +xmodmap -e "keycode 66 = grave asciitilde"
  284.41 +
  284.42 +PATH=$PATH:/usr/local/bin/X11
  284.43 +MANPATH=`manpath`
  284.44 +export MANPATH PATH
  284.45 +
  284.46 +#xauth extract - $DISPLAY | rsh remotehost /usr/bin/X11/xauth merge -
  284.47 +
  284.48 +xterm -geometry 80x43+1024+0 -T login -n login -ls -exec bash &
  284.49 +xterm -geometry 80x43+1024+1536 -T Sotto -ls -exec bash &
  284.50 +xterm -geometry 80x43+2048+1536 -T Sotto -ls -exec bash &
  284.51 +
  284.52 +# touch /tmp/ps
  284.53 +# gv -geometry 1016x745+1024+768 /tmp/ps &
  284.54 +
  284.55 +xload -geometry 157x66+776+0 &
  284.56 +rclock -bg gray90 -geometry 71x70-0+67 &
  284.57 +xsysinfo -geometry 157x85+776+66  &
  284.58 +
  284.59 +xhost +bluff
  284.60 +
  284.61 +xsetroot -solid  rgb:828f/43d9/43d9   
  284.62 +fvwm2 -f ~/.fvwm2rc 
  284.63 +
  284.64 +#startkde
   285.1 Binary file usr/share/doc/isi/etc/skel/public_html/immagini/bg_intro.jpg has changed
   286.1 Binary file usr/share/doc/isi/etc/skel/public_html/immagini/folder.png has changed
   287.1 Binary file usr/share/doc/isi/etc/skel/public_html/immagini/logo5.gif has changed
   288.1 Binary file usr/share/doc/isi/etc/skel/public_html/immagini/tux.gif has changed
   289.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   289.2 +++ b/usr/share/doc/isi/etc/skel/public_html/index.html	Mon Apr 26 11:16:23 2010 +0200
   289.3 @@ -0,0 +1,99 @@
   289.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
   289.5 +<html>
   289.6 +<head>
   289.7 +  <meta http-equiv="content-type"
   289.8 + content="text/html; charset=ISO-8859-1">
   289.9 +  <title>index</title>
  289.10 +</head>
  289.11 +<body
  289.12 + style="background-image: url(file:///etc/skel/public_html/immagini/bg_intro.jpg);">
  289.13 +<div style="text-align: center;"><big><big>Questa è la HOME PAGE
  289.14 +del tuo web personale <br>
  289.15 +</big></big><br>
  289.16 +Essa si trova nella sottocartella speciale (invisibile da windows) <span
  289.17 + style="font-weight: bold;">public_html</span> della tua home
  289.18 +directory. <br>
  289.19 +Per raggiungerla da qualunque macchina della rete basta utilizzare un
  289.20 +browser e puntarlo all´indirizzo:<br>
  289.21 +<big style="font-weight: bold; color: rgb(255, 0, 0);"><br>
  289.22 +http://url_server/~nome_utente/index.html</big><br>
  289.23 +Il carattere<big><big><big> <span style="color: rgb(255, 0, 0);">~</span>
  289.24 +</big></big></big>(tilde) si ottiene sulle tastiere italiane delle
  289.25 +macchine windows digitando la combinazione <br>
  289.26 +<span style="font-weight: bold;">Alt126</span><br>
  289.27 +(il numero 126 va composto sul tastierino numerico tenendo premuto il
  289.28 +tasto ALT)<br>
  289.29 +<br>
  289.30 +Sei libero di modificarla come ti pare e di aggiungere tutte le pagine
  289.31 +che vuoi ma dovrai rispettare strettamente le seguenti <a
  289.32 + href="file:///avvertenze.html">avvertenze</a>.<br>
  289.33 +<br>
  289.34 +Puoi costruire pagine statiche HTML o dinamiche in PHP.  Per
  289.35 +facilitarti le cose, nella tua cartella personale, ti è stata
  289.36 +preparata la seguente
  289.37 +struttura che e' raggiungibile direttamente da <span
  289.38 + style="font-weight: bold;">Risorse_del_computer, mioweb </span>ed e'
  289.39 +vista come disco <span style="font-weight: bold;">W</span>.<br>
  289.40 +Per pubblicare le tue pagine web ti basta quindi salvarle su <span
  289.41 + style="font-weight: bold;">W:</span><br>
  289.42 +<br>
  289.43 +<table
  289.44 + style="text-align: left; margin-left: auto; margin-right: auto; width: 80%;"
  289.45 + border="1" cellspacing="2" cellpadding="2">
  289.46 +  <tbody>
  289.47 +    <tr>
  289.48 +      <td
  289.49 + style="width: 25px; vertical-align: middle; text-align: center;"><img
  289.50 + src="immagini/folder.png" alt="public_html"
  289.51 + style="width: 22px; height: 19px;"><br>
  289.52 +      </td>
  289.53 +      <td
  289.54 + style="width: 25px; vertical-align: middle; text-align: center;"><br>
  289.55 +      </td>
  289.56 +      <td
  289.57 + style="vertical-align: middle; text-align: center; width: 60px;">public_html</td>
  289.58 +      <td style="vertical-align: top; width: 350px;">la directory
  289.59 +radice del tuo sito
  289.60 +personale (invisibile da windows) <span style="font-weight: bold;"></span><br>
  289.61 +      </td>
  289.62 +    </tr>
  289.63 +    <tr>
  289.64 +      <td style="vertical-align: middle; text-align: center;"><br>
  289.65 +      </td>
  289.66 +      <td
  289.67 + style="width: 25px; vertical-align: middle; text-align: center;"><img
  289.68 + style="width: 22px; height: 19px;" alt="public_html"
  289.69 + src="immagini/folder.png"></td>
  289.70 +      <td
  289.71 + style="vertical-align: middle; text-align: center; width: 60px;">immagini<br>
  289.72 +      </td>
  289.73 +      <td style="vertical-align: top; width: 350px;">tutte le immagini
  289.74 +del sito<br>
  289.75 +      </td>
  289.76 +    </tr>
  289.77 +    <tr>
  289.78 +      <td style="vertical-align: middle; text-align: center;"><br>
  289.79 +      </td>
  289.80 +      <td
  289.81 + style="width: 25px; vertical-align: middle; text-align: center;"><img
  289.82 + style="width: 22px; height: 19px;" alt="public_html"
  289.83 + src="immagini/folder.png"></td>
  289.84 +      <td
  289.85 + style="vertical-align: middle; text-align: center; width: 60px;">templates<br>
  289.86 +      </td>
  289.87 +      <td style="vertical-align: top; width: 350px;">tutti i templates
  289.88 +(al momento
  289.89 +è vuota)<br>
  289.90 +      </td>
  289.91 +    </tr>
  289.92 +  </tbody>
  289.93 +</table>
  289.94 +<br>
  289.95 +Buon divertimento!<br>
  289.96 +<big><big><img src="immagini/tux.gif" alt="tux"
  289.97 + style="width: 76px; height: 102px;"></big></big><br>
  289.98 +<br>
  289.99 +</div>
 289.100 +<br>
 289.101 +</body>
 289.102 +</html>
   290.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   290.2 +++ b/usr/share/doc/isi/etc/smbldap-tools/smbldap.conf	Mon Apr 26 11:16:23 2010 +0200
   290.3 @@ -0,0 +1,193 @@
   290.4 +# $Source$
   290.5 +# $Id: smbldap.conf 23 2021-10-15 17:05:08Z root $
   290.6 +#
   290.7 +# smbldap-tools.conf : Q & D configuration file for smbldap-tools
   290.8 +
   290.9 +#  This code was developped by IDEALX (http://IDEALX.org/) and
  290.10 +#  contributors (their names can be found in the CONTRIBUTORS file).
  290.11 +#
  290.12 +#                 Copyright (C) 2001-2002 IDEALX
  290.13 +#
  290.14 +#  This program is free software; you can redistribute it and/or
  290.15 +#  modify it under the terms of the GNU General Public License
  290.16 +#  as published by the Free Software Foundation; either version 2
  290.17 +#  of the License, or (at your option) any later version.
  290.18 +#
  290.19 +#  This program is distributed in the hope that it will be useful,
  290.20 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  290.21 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  290.22 +#  GNU General Public License for more details.
  290.23 +#
  290.24 +#  You should have received a copy of the GNU General Public License
  290.25 +#  along with this program; if not, write to the Free Software
  290.26 +#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  290.27 +#  USA.
  290.28 +
  290.29 +#  Purpose :
  290.30 +#       . be the configuration file for all smbldap-tools scripts
  290.31 +
  290.32 +##############################################################################
  290.33 +#
  290.34 +# General Configuration
  290.35 +#
  290.36 +##############################################################################
  290.37 +
  290.38 +# Put your own SID
  290.39 +# to obtain this number do: net getlocalsid
  290.40 +SID="S-1-5-21-3440555123-2170259995-2169184781"
  290.41 +##############################################################################
  290.42 +#
  290.43 +# LDAP Configuration
  290.44 +#
  290.45 +##############################################################################
  290.46 +
  290.47 +# Notes: to use to dual ldap servers backend for Samba, you must patch
  290.48 +# Samba with the dual-head patch from IDEALX. If not using this patch
  290.49 +# just use the same server for slaveLDAP and masterLDAP.
  290.50 +# Those two servers declarations can also be used when you have 
  290.51 +# . one master LDAP server where all writing operations must be done
  290.52 +# . one slave LDAP server where all reading operations must be done
  290.53 +#   (typically a replication directory)
  290.54 +
  290.55 +# Ex: slaveLDAP=127.0.0.1
  290.56 +slaveLDAP="127.0.0.1"
  290.57 +slavePort="389"
  290.58 +
  290.59 +# Master LDAP : needed for write operations
  290.60 +# Ex: masterLDAP=127.0.0.1
  290.61 +masterLDAP="127.0.0.1"
  290.62 +masterPort="389"
  290.63 +
  290.64 +# Use TLS for LDAP
  290.65 +# If set to 1, this option will use start_tls for connection
  290.66 +# (you should also used the port 389)
  290.67 +ldapTLS="0"
  290.68 +
  290.69 +# How to verify the server's certificate (none, optional or require)
  290.70 +# see "man Net::LDAP" in start_tls section for more details
  290.71 +#verify="require"
  290.72 +
  290.73 +# CA certificate
  290.74 +# see "man Net::LDAP" in start_tls section for more details
  290.75 +#cafile="/etc/smbldap-tools/ca.pem"
  290.76 +
  290.77 +# certificate to use to connect to the ldap server
  290.78 +# see "man Net::LDAP" in start_tls section for more details
  290.79 +#clientcert="/etc/smbldap-tools/smbldap-tools.pem"
  290.80 +
  290.81 +# key certificate to use to connect to the ldap server
  290.82 +# see "man Net::LDAP" in start_tls section for more details
  290.83 +#clientkey="/etc/smbldap-tools/smbldap-tools.key"
  290.84 +
  290.85 +# LDAP Suffix
  290.86 +# Ex: suffix=dc=IDEALX,dc=ORG
  290.87 +suffix="dc=isi,dc=lan"
  290.88 +
  290.89 +# Where are stored Users
  290.90 +# Ex: usersdn="ou=People,dc=IDEALX,dc=ORG"
  290.91 +usersdn="ou=People,dc=isi,dc=lan"
  290.92 +
  290.93 +# Where are stored Computers
  290.94 +# Ex: computersdn="ou=Computers,dc=IDEALX,dc=ORG"
  290.95 +computersdn="ou=Computers,dc=isi,dc=lan"
  290.96 +
  290.97 +# Where are stored Groups
  290.98 +# Ex groupsdn="ou=Groups,dc=IDEALX,dc=ORG"
  290.99 +groupsdn="ou=Groups,dc=isi,dc=lan"
 290.100 +
 290.101 +# Where are stored Idmap entries (used if samba is a domain member server)
 290.102 +# Ex groupsdn="ou=Idmap,dc=IDEALX,dc=ORG"
 290.103 +idmapdn="ou=Idmap,dc=isi,dc=lan"
 290.104 +
 290.105 +# Where to store next uidNumber and gidNumber available
 290.106 +#sambaUnixIdPooldn="cn=NextFreeUnixId,${suffix}"
 290.107 +sambaUnixIdPooldn="sambaDomainName=ISI-DOMAIN,dc=isi,dc=lan"
 290.108 +
 290.109 +# Default scope Used
 290.110 +scope="sub"
 290.111 +
 290.112 +# Unix password encryption (CRYPT, MD5, SMD5, SSHA, SHA)
 290.113 +hash_encrypt="SSHA"
 290.114 +
 290.115 +# if hash_encrypt is set to CRYPT, you may set a salt format.
 290.116 +# default is "%s", but many systems will generate MD5 hashed
 290.117 +# passwords if you use "$1$%.8s". This parameter is optional!
 290.118 +crypt_salt_format="%s"
 290.119 +
 290.120 +##############################################################################
 290.121 +# 
 290.122 +# Unix Accounts Configuration
 290.123 +# 
 290.124 +##############################################################################
 290.125 +
 290.126 +# Login defs
 290.127 +# Default Login Shell
 290.128 +# Ex: userLoginShell="/bin/bash"
 290.129 +userLoginShell="/bin/bash"
 290.130 +
 290.131 +# Home directory
 290.132 +# Ex: userHome="/home/%U"
 290.133 +userHome="/home/%U"
 290.134 +
 290.135 +# Gecos
 290.136 +userGecos="System User"
 290.137 +
 290.138 +# Default User (POSIX and Samba) GID
 290.139 +defaultUserGid="513"
 290.140 +
 290.141 +# Default Computer (Samba) GID
 290.142 +defaultComputerGid="515"
 290.143 +
 290.144 +# Skel dir
 290.145 +skeletonDir="/etc/skel"
 290.146 +
 290.147 +# Default password validation time (time in days) Comment the next line if
 290.148 +# you don't want password to be enable for defaultMaxPasswordAge days (be
 290.149 +# careful to the sambaPwdMustChange attribute's value)
 290.150 +defaultMaxPasswordAge="99"
 290.151 +
 290.152 +##############################################################################
 290.153 +#
 290.154 +# SAMBA Configuration
 290.155 +#
 290.156 +##############################################################################
 290.157 +
 290.158 +# The UNC path to home drives location (%U username substitution)
 290.159 +# Ex: \\My-PDC-netbios-name\homes\%U
 290.160 +# Just set it to a null string if you want to use the smb.conf 'logon home'
 290.161 +# directive and/or disable roaming profiles
 290.162 +userSmbHome="\\ISI-PDC\%U"
 290.163 +
 290.164 +# The UNC path to profiles locations (%U username substitution)
 290.165 +# Ex: \\My-PDC-netbios-name\profiles\%U
 290.166 +# Just set it to a null string if you want to use the smb.conf 'logon path'
 290.167 +# directive and/or disable roaming profiles
 290.168 +userProfile="\\ISI-PDC\profiles"
 290.169 +
 290.170 +# The default Home Drive Letter mapping
 290.171 +# (will be automatically mapped at logon time if home directory exist)
 290.172 +# Ex: H: for H:
 290.173 +userHomeDrive="H:"
 290.174 +
 290.175 +# The default user netlogon script name (%U username substitution)
 290.176 +# if not used, will be automatically username.cmd
 290.177 +# make sure script file is edited under dos
 290.178 +# Ex: %U.cmd
 290.179 +# userScript="startup.cmd" # make sure script file is edited under dos
 290.180 +# userScript="%U.cmd"
 290.181 +
 290.182 +# Domain appended to the users "mail"-attribute
 290.183 +# when smbldap-useradd -M is used
 290.184 +mailDomain="isi.lan"
 290.185 +
 290.186 +##############################################################################
 290.187 +#
 290.188 +# SMBLDAP-TOOLS Configuration (default are ok for a RedHat)
 290.189 +#
 290.190 +##############################################################################
 290.191 +
 290.192 +# Allows not to use smbpasswd (if with_smbpasswd == 0 in smbldap_conf.pm) but
 290.193 +# prefer Crypt::SmbHash library
 290.194 +with_smbpasswd="0"
 290.195 +smbpasswd="/usr/bin/smbpasswd"
 290.196 +defaultComputerGid0="515"
   291.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   291.2 +++ b/usr/share/doc/isi/etc/smbldap-tools/smbldap_bind.conf	Mon Apr 26 11:16:23 2010 +0200
   291.3 @@ -0,0 +1,12 @@
   291.4 +############################
   291.5 +# Credential Configuration #
   291.6 +############################
   291.7 +# Notes: you can specify two differents configuration if you use a
   291.8 +# master ldap for writing access and a slave ldap server for reading access
   291.9 +# By default, we will use the same DN (so it will work for standard Samba
  291.10 +# release)
  291.11 +slaveDN="cn=admin,dc=isi,dc=lan"
  291.12 +slavePw="xxx"
  291.13 +masterDN="cn=admin,dc=isi,dc=lan"
  291.14 +masterPw="xxx"
  291.15 +
   292.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   292.2 +++ b/usr/share/doc/isi/etc/sudoers.isi	Mon Apr 26 11:16:23 2010 +0200
   292.3 @@ -0,0 +1,21 @@
   292.4 +# sudoers file.
   292.5 +#
   292.6 +# This file MUST be edited with the 'visudo' command as root.
   292.7 +#
   292.8 +# See the sudoers man page for the details on how to write a sudoers file.
   292.9 +#
  292.10 +
  292.11 +# Host alias specification
  292.12 +
  292.13 +# User alias specification
  292.14 +User_Alias   UPYAUTH = admin1, admin2 
  292.15 +
  292.16 +# Cmnd alias specification
  292.17 +
  292.18 +Cmnd_Alias UPY = /usr/sbin/isi-users
  292.19 +
  292.20 +# User privilege specification
  292.21 +root    ALL=(ALL) ALL
  292.22 +UPYAUTH ALL=(ALL) NOPASSWD: UPY
  292.23 +
  292.24 +
   293.1 Binary file usr/share/doc/isi/grub4dos/win98/c/boot/grub/gpxe.iso has changed
   294.1 Binary file usr/share/doc/isi/grub4dos/win98/c/grldr has changed
   295.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   295.2 +++ b/usr/share/doc/isi/grub4dos/win98/c/menu.lst	Mon Apr 26 11:16:23 2010 +0200
   295.3 @@ -0,0 +1,15 @@
   295.4 +color blue/white white/green white/blue white/blue
   295.5 +timeout 10
   295.6 +
   295.7 +title gPXE (LTSP)
   295.8 +find --set-root /boot/grub/gpxe.iso
   295.9 +map /boot/grub/gpxe.iso (0xff) || map --mem /boot/grub/gpxe.iso (0xff)
  295.10 +map --hook
  295.11 +chainloader (0xff)
  295.12 +
  295.13 +title Windows 9x/Me
  295.14 +find --set-root /io.sys
  295.15 +chainloader /io.sys
  295.16 +
  295.17 +title halt
  295.18 +halt
   296.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   296.2 +++ b/usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/COPYING	Mon Apr 26 11:16:23 2010 +0200
   296.3 @@ -0,0 +1,340 @@
   296.4 +		    GNU GENERAL PUBLIC LICENSE
   296.5 +		       Version 2, June 1991
   296.6 +
   296.7 + Copyright (C) 1989, 1991 Free Software Foundation, Inc.
   296.8 +     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   296.9 + Everyone is permitted to copy and distribute verbatim copies
  296.10 + of this license document, but changing it is not allowed.
  296.11 +
  296.12 +			    Preamble
  296.13 +
  296.14 +  The licenses for most software are designed to take away your
  296.15 +freedom to share and change it.  By contrast, the GNU General Public
  296.16 +License is intended to guarantee your freedom to share and change free
  296.17 +software--to make sure the software is free for all its users.  This
  296.18 +General Public License applies to most of the Free Software
  296.19 +Foundation's software and to any other program whose authors commit to
  296.20 +using it.  (Some other Free Software Foundation software is covered by
  296.21 +the GNU Library General Public License instead.)  You can apply it to
  296.22 +your programs, too.
  296.23 +
  296.24 +  When we speak of free software, we are referring to freedom, not
  296.25 +price.  Our General Public Licenses are designed to make sure that you
  296.26 +have the freedom to distribute copies of free software (and charge for
  296.27 +this service if you wish), that you receive source code or can get it
  296.28 +if you want it, that you can change the software or use pieces of it
  296.29 +in new free programs; and that you know you can do these things.
  296.30 +
  296.31 +  To protect your rights, we need to make restrictions that forbid
  296.32 +anyone to deny you these rights or to ask you to surrender the rights.
  296.33 +These restrictions translate to certain responsibilities for you if you
  296.34 +distribute copies of the software, or if you modify it.
  296.35 +
  296.36 +  For example, if you distribute copies of such a program, whether
  296.37 +gratis or for a fee, you must give the recipients all the rights that
  296.38 +you have.  You must make sure that they, too, receive or can get the
  296.39 +source code.  And you must show them these terms so they know their
  296.40 +rights.
  296.41 +
  296.42 +  We protect your rights with two steps: (1) copyright the software, and
  296.43 +(2) offer you this license which gives you legal permission to copy,
  296.44 +distribute and/or modify the software.
  296.45 +
  296.46 +  Also, for each author's protection and ours, we want to make certain
  296.47 +that everyone understands that there is no warranty for this free
  296.48 +software.  If the software is modified by someone else and passed on, we
  296.49 +want its recipients to know that what they have is not the original, so
  296.50 +that any problems introduced by others will not reflect on the original
  296.51 +authors' reputations.
  296.52 +
  296.53 +  Finally, any free program is threatened constantly by software
  296.54 +patents.  We wish to avoid the danger that redistributors of a free
  296.55 +program will individually obtain patent licenses, in effect making the
  296.56 +program proprietary.  To prevent this, we have made it clear that any
  296.57 +patent must be licensed for everyone's free use or not licensed at all.
  296.58 +
  296.59 +  The precise terms and conditions for copying, distribution and
  296.60 +modification follow.
  296.61 +
  296.62 +		    GNU GENERAL PUBLIC LICENSE
  296.63 +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  296.64 +
  296.65 +  0. This License applies to any program or other work which contains
  296.66 +a notice placed by the copyright holder saying it may be distributed
  296.67 +under the terms of this General Public License.  The "Program", below,
  296.68 +refers to any such program or work, and a "work based on the Program"
  296.69 +means either the Program or any derivative work under copyright law:
  296.70 +that is to say, a work containing the Program or a portion of it,
  296.71 +either verbatim or with modifications and/or translated into another
  296.72 +language.  (Hereinafter, translation is included without limitation in
  296.73 +the term "modification".)  Each licensee is addressed as "you".
  296.74 +
  296.75 +Activities other than copying, distribution and modification are not
  296.76 +covered by this License; they are outside its scope.  The act of
  296.77 +running the Program is not restricted, and the output from the Program
  296.78 +is covered only if its contents constitute a work based on the
  296.79 +Program (independent of having been made by running the Program).
  296.80 +Whether that is true depends on what the Program does.
  296.81 +
  296.82 +  1. You may copy and distribute verbatim copies of the Program's
  296.83 +source code as you receive it, in any medium, provided that you
  296.84 +conspicuously and appropriately publish on each copy an appropriate
  296.85 +copyright notice and disclaimer of warranty; keep intact all the
  296.86 +notices that refer to this License and to the absence of any warranty;
  296.87 +and give any other recipients of the Program a copy of this License
  296.88 +along with the Program.
  296.89 +
  296.90 +You may charge a fee for the physical act of transferring a copy, and
  296.91 +you may at your option offer warranty protection in exchange for a fee.
  296.92 +
  296.93 +  2. You may modify your copy or copies of the Program or any portion
  296.94 +of it, thus forming a work based on the Program, and copy and
  296.95 +distribute such modifications or work under the terms of Section 1
  296.96 +above, provided that you also meet all of these conditions:
  296.97 +
  296.98 +    a) You must cause the modified files to carry prominent notices
  296.99 +    stating that you changed the files and the date of any change.
 296.100 +
 296.101 +    b) You must cause any work that you distribute or publish, that in
 296.102 +    whole or in part contains or is derived from the Program or any
 296.103 +    part thereof, to be licensed as a whole at no charge to all third
 296.104 +    parties under the terms of this License.
 296.105 +
 296.106 +    c) If the modified program normally reads commands interactively
 296.107 +    when run, you must cause it, when started running for such
 296.108 +    interactive use in the most ordinary way, to print or display an
 296.109 +    announcement including an appropriate copyright notice and a
 296.110 +    notice that there is no warranty (or else, saying that you provide
 296.111 +    a warranty) and that users may redistribute the program under
 296.112 +    these conditions, and telling the user how to view a copy of this
 296.113 +    License.  (Exception: if the Program itself is interactive but
 296.114 +    does not normally print such an announcement, your work based on
 296.115 +    the Program is not required to print an announcement.)
 296.116 +
 296.117 +These requirements apply to the modified work as a whole.  If
 296.118 +identifiable sections of that work are not derived from the Program,
 296.119 +and can be reasonably considered independent and separate works in
 296.120 +themselves, then this License, and its terms, do not apply to those
 296.121 +sections when you distribute them as separate works.  But when you
 296.122 +distribute the same sections as part of a whole which is a work based
 296.123 +on the Program, the distribution of the whole must be on the terms of
 296.124 +this License, whose permissions for other licensees extend to the
 296.125 +entire whole, and thus to each and every part regardless of who wrote it.
 296.126 +
 296.127 +Thus, it is not the intent of this section to claim rights or contest
 296.128 +your rights to work written entirely by you; rather, the intent is to
 296.129 +exercise the right to control the distribution of derivative or
 296.130 +collective works based on the Program.
 296.131 +
 296.132 +In addition, mere aggregation of another work not based on the Program
 296.133 +with the Program (or with a work based on the Program) on a volume of
 296.134 +a storage or distribution medium does not bring the other work under
 296.135 +the scope of this License.
 296.136 +
 296.137 +  3. You may copy and distribute the Program (or a work based on it,
 296.138 +under Section 2) in object code or executable form under the terms of
 296.139 +Sections 1 and 2 above provided that you also do one of the following:
 296.140 +
 296.141 +    a) Accompany it with the complete corresponding machine-readable
 296.142 +    source code, which must be distributed under the terms of Sections
 296.143 +    1 and 2 above on a medium customarily used for software interchange; or,
 296.144 +
 296.145 +    b) Accompany it with a written offer, valid for at least three
 296.146 +    years, to give any third party, for a charge no more than your
 296.147 +    cost of physically performing source distribution, a complete
 296.148 +    machine-readable copy of the corresponding source code, to be
 296.149 +    distributed under the terms of Sections 1 and 2 above on a medium
 296.150 +    customarily used for software interchange; or,
 296.151 +
 296.152 +    c) Accompany it with the information you received as to the offer
 296.153 +    to distribute corresponding source code.  (This alternative is
 296.154 +    allowed only for noncommercial distribution and only if you
 296.155 +    received the program in object code or executable form with such
 296.156 +    an offer, in accord with Subsection b above.)
 296.157 +
 296.158 +The source code for a work means the preferred form of the work for
 296.159 +making modifications to it.  For an executable work, complete source
 296.160 +code means all the source code for all modules it contains, plus any
 296.161 +associated interface definition files, plus the scripts used to
 296.162 +control compilation and installation of the executable.  However, as a
 296.163 +special exception, the source code distributed need not include
 296.164 +anything that is normally distributed (in either source or binary
 296.165 +form) with the major components (compiler, kernel, and so on) of the
 296.166 +operating system on which the executable runs, unless that component
 296.167 +itself accompanies the executable.
 296.168 +
 296.169 +If distribution of executable or object code is made by offering
 296.170 +access to copy from a designated place, then offering equivalent
 296.171 +access to copy the source code from the same place counts as
 296.172 +distribution of the source code, even though third parties are not
 296.173 +compelled to copy the source along with the object code.
 296.174 +
 296.175 +  4. You may not copy, modify, sublicense, or distribute the Program
 296.176 +except as expressly provided under this License.  Any attempt
 296.177 +otherwise to copy, modify, sublicense or distribute the Program is
 296.178 +void, and will automatically terminate your rights under this License.
 296.179 +However, parties who have received copies, or rights, from you under
 296.180 +this License will not have their licenses terminated so long as such
 296.181 +parties remain in full compliance.
 296.182 +
 296.183 +  5. You are not required to accept this License, since you have not
 296.184 +signed it.  However, nothing else grants you permission to modify or
 296.185 +distribute the Program or its derivative works.  These actions are
 296.186 +prohibited by law if you do not accept this License.  Therefore, by
 296.187 +modifying or distributing the Program (or any work based on the
 296.188 +Program), you indicate your acceptance of this License to do so, and
 296.189 +all its terms and conditions for copying, distributing or modifying
 296.190 +the Program or works based on it.
 296.191 +
 296.192 +  6. Each time you redistribute the Program (or any work based on the
 296.193 +Program), the recipient automatically receives a license from the
 296.194 +original licensor to copy, distribute or modify the Program subject to
 296.195 +these terms and conditions.  You may not impose any further
 296.196 +restrictions on the recipients' exercise of the rights granted herein.
 296.197 +You are not responsible for enforcing compliance by third parties to
 296.198 +this License.
 296.199 +
 296.200 +  7. If, as a consequence of a court judgment or allegation of patent
 296.201 +infringement or for any other reason (not limited to patent issues),
 296.202 +conditions are imposed on you (whether by court order, agreement or
 296.203 +otherwise) that contradict the conditions of this License, they do not
 296.204 +excuse you from the conditions of this License.  If you cannot
 296.205 +distribute so as to satisfy simultaneously your obligations under this
 296.206 +License and any other pertinent obligations, then as a consequence you
 296.207 +may not distribute the Program at all.  For example, if a patent
 296.208 +license would not permit royalty-free redistribution of the Program by
 296.209 +all those who receive copies directly or indirectly through you, then
 296.210 +the only way you could satisfy both it and this License would be to
 296.211 +refrain entirely from distribution of the Program.
 296.212 +
 296.213 +If any portion of this section is held invalid or unenforceable under
 296.214 +any particular circumstance, the balance of the section is intended to
 296.215 +apply and the section as a whole is intended to apply in other
 296.216 +circumstances.
 296.217 +
 296.218 +It is not the purpose of this section to induce you to infringe any
 296.219 +patents or other property right claims or to contest validity of any
 296.220 +such claims; this section has the sole purpose of protecting the
 296.221 +integrity of the free software distribution system, which is
 296.222 +implemented by public license practices.  Many people have made
 296.223 +generous contributions to the wide range of software distributed
 296.224 +through that system in reliance on consistent application of that
 296.225 +system; it is up to the author/donor to decide if he or she is willing
 296.226 +to distribute software through any other system and a licensee cannot
 296.227 +impose that choice.
 296.228 +
 296.229 +This section is intended to make thoroughly clear what is believed to
 296.230 +be a consequence of the rest of this License.
 296.231 +
 296.232 +  8. If the distribution and/or use of the Program is restricted in
 296.233 +certain countries either by patents or by copyrighted interfaces, the
 296.234 +original copyright holder who places the Program under this License
 296.235 +may add an explicit geographical distribution limitation excluding
 296.236 +those countries, so that distribution is permitted only in or among
 296.237 +countries not thus excluded.  In such case, this License incorporates
 296.238 +the limitation as if written in the body of this License.
 296.239 +
 296.240 +  9. The Free Software Foundation may publish revised and/or new versions
 296.241 +of the General Public License from time to time.  Such new versions will
 296.242 +be similar in spirit to the present version, but may differ in detail to
 296.243 +address new problems or concerns.
 296.244 +
 296.245 +Each version is given a distinguishing version number.  If the Program
 296.246 +specifies a version number of this License which applies to it and "any
 296.247 +later version", you have the option of following the terms and conditions
 296.248 +either of that version or of any later version published by the Free
 296.249 +Software Foundation.  If the Program does not specify a version number of
 296.250 +this License, you may choose any version ever published by the Free Software
 296.251 +Foundation.
 296.252 +
 296.253 +  10. If you wish to incorporate parts of the Program into other free
 296.254 +programs whose distribution conditions are different, write to the author
 296.255 +to ask for permission.  For software which is copyrighted by the Free
 296.256 +Software Foundation, write to the Free Software Foundation; we sometimes
 296.257 +make exceptions for this.  Our decision will be guided by the two goals
 296.258 +of preserving the free status of all derivatives of our free software and
 296.259 +of promoting the sharing and reuse of software generally.
 296.260 +
 296.261 +			    NO WARRANTY
 296.262 +
 296.263 +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 296.264 +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
 296.265 +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 296.266 +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 296.267 +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 296.268 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 296.269 +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 296.270 +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 296.271 +REPAIR OR CORRECTION.
 296.272 +
 296.273 +  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 296.274 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 296.275 +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 296.276 +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 296.277 +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 296.278 +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 296.279 +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 296.280 +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 296.281 +POSSIBILITY OF SUCH DAMAGES.
 296.282 +
 296.283 +		     END OF TERMS AND CONDITIONS
 296.284 +
 296.285 +	    How to Apply These Terms to Your New Programs
 296.286 +
 296.287 +  If you develop a new program, and you want it to be of the greatest
 296.288 +possible use to the public, the best way to achieve this is to make it
 296.289 +free software which everyone can redistribute and change under these terms.
 296.290 +
 296.291 +  To do so, attach the following notices to the program.  It is safest
 296.292 +to attach them to the start of each source file to most effectively
 296.293 +convey the exclusion of warranty; and each file should have at least
 296.294 +the "copyright" line and a pointer to where the full notice is found.
 296.295 +
 296.296 +    <one line to give the program's name and a brief idea of what it does.>
 296.297 +    Copyright (C) 19yy  <name of author>
 296.298 +
 296.299 +    This program is free software; you can redistribute it and/or modify
 296.300 +    it under the terms of the GNU General Public License as published by
 296.301 +    the Free Software Foundation; either version 2 of the License, or
 296.302 +    (at your option) any later version.
 296.303 +
 296.304 +    This program is distributed in the hope that it will be useful,
 296.305 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 296.306 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 296.307 +    GNU General Public License for more details.
 296.308 +
 296.309 +    You should have received a copy of the GNU General Public License
 296.310 +    along with this program; if not, write to the Free Software
 296.311 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 296.312 +
 296.313 +
 296.314 +Also add information on how to contact you by electronic and paper mail.
 296.315 +
 296.316 +If the program is interactive, make it output a short notice like this
 296.317 +when it starts in an interactive mode:
 296.318 +
 296.319 +    Gnomovision version 69, Copyright (C) 19yy name of author
 296.320 +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 296.321 +    This is free software, and you are welcome to redistribute it
 296.322 +    under certain conditions; type `show c' for details.
 296.323 +
 296.324 +The hypothetical commands `show w' and `show c' should show the appropriate
 296.325 +parts of the General Public License.  Of course, the commands you use may
 296.326 +be called something other than `show w' and `show c'; they could even be
 296.327 +mouse-clicks or menu items--whatever suits your program.
 296.328 +
 296.329 +You should also get your employer (if you work as a programmer) or your
 296.330 +school, if any, to sign a "copyright disclaimer" for the program, if
 296.331 +necessary.  Here is a sample; alter the names:
 296.332 +
 296.333 +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 296.334 +  `Gnomovision' (which makes passes at compilers) written by James Hacker.
 296.335 +
 296.336 +  <signature of Ty Coon>, 1 April 2022
 296.337 +  Ty Coon, President of Vice
 296.338 +
 296.339 +This General Public License does not permit incorporating your program into
 296.340 +proprietary programs.  If your program is a subroutine library, you may
 296.341 +consider it more useful to permit linking proprietary applications with the
 296.342 +library.  If this is what you want to do, use the GNU Library General
 296.343 +Public License instead of this License.
   297.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   297.2 +++ b/usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/ChangeLog_GRUB4DOS.txt	Mon Apr 26 11:16:23 2010 +0200
   297.3 @@ -0,0 +1,572 @@
   297.4 +2009-03-31(r66) 0.4.4 official release.
   297.5 +2009-03-28 removed the problematic global variable "i"; reduced one open-file step for configfile on cdrom.
   297.6 +2009-03-27 fixed memory overlap issue on "map --rehook".
   297.7 +2009-03-25 disabled the search for DEFAULT file on cdrom(in cmain, stage2.c).
   297.8 +2009-03-24 fixed problem of WRITE/DD on modifying internal variables. added dd options for user-defined buffer.
   297.9 +2009-03-21 bug fix: turned errorcheck on in run_script and enter_cmdline.
  297.10 +2009-03-20(r65) fixed `configfile not working in menu init command group'.
  297.11 +2009-03-19 trying to fix problem of `configfile running slowly'.
  297.12 +2009-03-18 fixed problem of `geometry-tune too slow' on vmware.
  297.13 +2009-03-17 fixed endless loop problem while running "configfile (md)4+8".
  297.14 +2009-03-15 added new option --sync for geometry command.
  297.15 +2009-03-14 added new option --tune for geometry command.
  297.16 +2009-03-12 rearranged preset-menu items.
  297.17 +2009-03-11 changed geometry-tune code(aim to solve problem on vmware).
  297.18 +2009-03-07 fixed a bug(in grldrstart.S) brought in since 2009-02-05.
  297.19 +2009-03-03 fixed memory overflow issue with (rd). canceled restrictions on some disk write commands.
  297.20 +2009-02-26 fixed geometry-tune issue(reportedly with Virtual PC).
  297.21 +2009-02-21 changes made according to Simon's hiddenmenu patches.
  297.22 +2009-02-20 documented the command line needed for chainloading stage2 of grub legacy.
  297.23 +2009-02-19 now a range of drives can be unmapped.
  297.24 +2009-02-18 possibility to run another menu.lst after gfxmenu.
  297.25 +2009-02-17 fix graphics display issue generated last time.
  297.26 +2009-02-15 improved color command to set color for help text and heading line.
  297.27 +2009-02-13 fix problems booting Linux when there are mappings.
  297.28 +2009-02-11 added ext4 support(in fsys_ext2fs.c).
  297.29 +2009-02-09 isolinux.bin(version 3.73) gets chainloaded again.
  297.30 +2009-02-08 Move some variables to a known address. The read command returns value at addess.
  297.31 +2009-02-03 New initrd syntax loading multiple cpio files for Linux 2.6 kernels.
  297.32 +2009-01-30 Supported per-menu-item help text.
  297.33 +2009-01-28 Fixed printf issue. Allowed non-block files to be written with dd and write.
  297.34 +2009-01-24 New syntax of WRITE support writing string to file.
  297.35 +2009-01-16(r64) Added gfxmenu support
  297.36 +2009-01-09 New commands dd and uuid. fixed a bug in disk emulation.
  297.37 +2008-12-30 Work around for BIOSes lacking INT15/E820 support.
  297.38 +2008-12-29(r63) Now the preset menu holds the highest priority. MSYS/MinGW support.
  297.39 +2008-12-24 Added "detect" sub-command for the "pxe" command.
  297.40 +2008-12-21 Fixed several bootlace bugs when running under DOS.
  297.41 +2008-12-20 bootlace is now able to create triple MBR.
  297.42 +2008-12-19 fixed problem of Disk Read Error on the last track.
  297.43 +2008-12-16 under DOS bootlace can use a parameter file for its command-line arguments.
  297.44 +2008-12-12 added a new option --chs-no-tune for bootlace.com.
  297.45 +2008-12-07 workaround for buggy no-emulation-mode cdrom BIOSes.
  297.46 +2008-12-04 fixed ext3 inode size issue on bootlace. fixed partition table check issue on bootlace.
  297.47 +2008-12-03 cut off the MENU_BUF. removed the TESTLOAD command. added TITLES array.
  297.48 +2008-12-01 added new program badgrub.exe. changed syntax of the find command.
  297.49 +2008-11-19(r62) enable interrupt when DELAY. avoid disabling CPU cache in a20_test(a20.inc).
  297.50 +2008-11-18p added STIs to better respond hardware interrupt(a20.inc, asm.S).
  297.51 +2008-11-18 changed DELAY code(a20.inc). added JMPs in unreal mode for RAM disk emulation(asm.S).
  297.52 +2008-11-15 loosened the check of the first FAT entry(fsys_fat.c). avoid using OUT instruction in DELAY(a20.inc).
  297.53 +2008-11-11(r61) added --ignore-cd option for the find command.
  297.54 +2008-11-08 read the boot file to determin the pxe block size. avoid running pxe_detect for non-pxe booting.
  297.55 +2008-11-02 added a new option --mbr-no-bpb for bootlace.com.
  297.56 +2008-11-01 changed PXE_MIN_BLKSIZE and PXE_MAX_BLKSIZE. allowed FAT cluster size larger than 32K.
  297.57 +2008-10-26 fixed pxe block size issue.
  297.58 +2008-10-21 fixed cylinder issue in int13/ah=8. Fixed stack conflict in bootlace.
  297.59 +2008-10-17 added command line options --serial-number=SN and --restore-mbr to bootlace.
  297.60 +2008-10-12 fixed a bug in fsys_fat.c causing FAT32 mount failure.
  297.61 +2008-10-03 cancelled unnecessary initialisations for the root device.
  297.62 +2008-10-02 improved int15 probing in probe_int.
  297.63 +2008-10-01 before booting GRLDR, give the user a chance to boot previous mbr.
  297.64 +2008-09-30 fixed a big bug in set_bootdev causing extra rawread executed and the geometry messed up.
  297.65 +2008-09-29 fixed a big bug in get_diskinfo causing duplicate geometry calculation for each IO request on floppy.
  297.66 +2008-09-27 fixed a new bug intrduced recently in get_diskinfo.
  297.67 +2008-09-25 fixed an issue of uninitialised current_term in boot.c, causing the failure of the kernel command in graphics mode.
  297.68 +2008-09-24 fixed the issue of "$BITMAP should be non-resident when in attribute list" in fsys_ntfs.c.
  297.69 +2008-09-23 fixed virtual cdrom sector read issue(64K at a time) for a non-mem mapping.
  297.70 +2008-09-21 added a new command "tpm --init".
  297.71 +2008-09-21 fixed memory conflicts between graphics mode and linux kernel.
  297.72 +2008-09-20 fixed a serious problem in grldrstart causing boot failure on FAT.
  297.73 +2008-09-19 fixed a new bug intrduced last in get_diskinfo.
  297.74 +2008-09-15 fixed a problem when different action occurs on a drive between chs and lba.
  297.75 +2008-09-13 fixed a problem of reentering int13 handler from a virtual device on a real cdrom device driven by the builtin cdrom driver.
  297.76 +2008-09-12 fixed an issue of whole cdrom mapping.
  297.77 +2008-09-09 fixed virtual cdrom sector read issue when it is not a mem-mapping.
  297.78 +2008-09-07 title delimitors(or comments) can be used in menu now.
  297.79 +2008-08-27 save stack space occupation by the int13_handler.
  297.80 +2008-08-26 fixed a bug relevant to iso emulation, causing disk read error.
  297.81 +2008-08-24 save stack space occupation by the int13_handler.
  297.82 +2008-08-14 enlarged stage2 stack space.
  297.83 +2008-08-13 fixed again the bug on the root command.
  297.84 +2008-08-12 fixed int5 in probe_int.
  297.85 +2008-08-10 added a new command checkrange; fixed a bug on the root command.
  297.86 +2008-08-08 added builtin stack for int13_handler to avoid stack overflow.
  297.87 +2008-08-06 fixed a suspicious problem on the SCRATCH buffer in get_diskinfo.
  297.88 +2008-08-04 fixed again error handling problem about operator && and ||; added STIs to better respond hardware interrupt.
  297.89 +2008-08-03 fixed error handling problem about operator && and ||; grldr.mbr structure change; other small alterations.
  297.90 +2008-07-28 added STIs to better respond hardware interrupt or to feed watchdog.
  297.91 +2008-07-10(r60) let KEY_UP(KEY_DOWN) loop to the last(first) menu entry.
  297.92 +2008-07-06 added backup_int13 and restore_int13 for a buggy usb bios f24a ver 1.00parttbl on compaq v5235tu(reporter: uleak). turn a20 debug on for memdrives.
  297.93 +2008-06-28 fixed ext3-inode-size issue in grldr boot sector and bootlace.inc.
  297.94 +2008-06-26 fixed int4C-4F in probe_int for Lenovo A6900.
  297.95 +2008-06-24 fixed "256-byte ext3 inode size" issue in fsys_ext2fs.c.
  297.96 +2008-06-23 added command ls.
  297.97 +2008-06-22 disabled safe_int13 code for a buggy usb bios f24a ver 1.00parttbl on compaq v5235tu(reporter: uleak).
  297.98 +2008-06-21 add A20 debug code to help locate a20 failure.
  297.99 +2008-06-18 A20 test begins. Update version number to 0.4.4.
 297.100 +2008-06-12 Let HIDE and UNHIDE respond with a message.
 297.101 +2008-06-10 Let ROOT show correct filesystem info.
 297.102 +2008-06-07 Let MAKEACTIVE and GEOMETRY show active partitions.
 297.103 +2008-06-01 commented out the terminal-switching code in run_menu.
 297.104 +2008-05-31 changed asm.S to avoid clearing out bss for the configfile command.
 297.105 +2008-05-27 initialize saved_videomode/font8x16 for working across configfile.
 297.106 +2008-05-25 fixed int76 in probe_int for a Tongfang.
 297.107 +2008-05-22 fixed an issue of CPU cache wrongly disabled in GRUB.EXE for long.
 297.108 +2008-05-21 fixed an issue of stack-overflow in real_get_cmdline.
 297.109 +2008-05-17 enable the geometry_tune code for test only.
 297.110 +2008-05-14 fix int5 and int8 in probe_int.
 297.111 +2008-05-06 adjustment on probe_int for "pxe keep".
 297.112 +2008-05-03 fixed problem on the commands setup and install.
 297.113 +2008-05-02(r59) add new command checktime.
 297.114 +2008-05-01 fixes on int vector probing, A20 control, configfile, find, etc.
 297.115 +2008-03-14(r58) commented out the geometry-tune code. other fixes.
 297.116 +2008-01-01(r57): mini build support
 297.117 +2007-12-25(r56): created the test branch
 297.118 +2007-12-25(r55) removed commands uppermem, ioprobe, impsprobe and displayapm.
 297.119 +2007-12-14 test 3 of the geometry-tune.
 297.120 +2007-12-10 cleanups on chainloader and errorcheck.
 297.121 +2007-12-05 fixed a bug in ntfs file system module.
 297.122 +2007-12-04 fixes on gzipped (rd) image support.
 297.123 +2007-12-02 int13 emulation workaround for buggy BIOSes('Disk read error').
 297.124 +2007-11-23 implemented cdrom emulation.
 297.125 +2007-10-15(r54) version 0.4.3
 297.126 +2007-10-08 implemented chainloading isolinux.
 297.127 +2007-10-04 changed drive number of (md) to 0xffff.
 297.128 +2007-10-02 reduced output messages for "debug off".
 297.129 +2007-09-27 added a new map option of --a20-keep-on.
 297.130 +2007-09-26 a workaround for buggy USB floppy BIOSes(hang at INT13/AH=48h).
 297.131 +2007-08-27(r53) new notation () standing for the current root device.
 297.132 +2007-08-26 new feature of root prefix for support of relative path.
 297.133 +2007-08-25 fixed one more possible issue on A20.
 297.134 +2007-08-24 fixed another possible issue on A20 for memdrives.
 297.135 +2007-08-23 fixed a possible issue on A20 for memdrives.
 297.136 +2007-08-21 expand memdrive size according to the probed CHS.
 297.137 +2007-08-17 test A20 control for memory mapped disks.
 297.138 +
 297.139 +	Updated code for hmload.
 297.140 +	Fixed a major problem of endless loop on enumeration of partitions.
 297.141 +	Fixed an issue in probe_mbr.
 297.142 +	Fixed a bug on compressed NTFS volume.
 297.143 +	Fixed a problem in probe_int by capturing int10.
 297.144 +
 297.145 +2007-07-25 version 0.4.3pre2
 297.146 +
 297.147 +	Added a new command OUTLINE, and a new option --duce for GRUB.EXE.
 297.148 +	Changed PARTNEW syntax. Fixed a problem of OPEN_PARTITION.
 297.149 +	The arguments of PARTTYPE have changed to be optional.
 297.150 +	
 297.151 +	A Fault-Recovery-Handler was imposed on probe_int to fight against
 297.152 +	some very serious BIOS bugs(reportedly of DELL machines).
 297.153 +
 297.154 +	The DEBUG command syntax was changed for verbosity control.
 297.155 +
 297.156 +2007-06-22 version 0.4.3pre1
 297.157 +
 297.158 +	Fixed two problems on GRUB.EXE: preset_menu and FreeDOS related.
 297.159 +	Added a new command `hiddenflag'; Added BPB in GRLDR.MBR; Ignored the
 297.160 +	partition-ID check in filesystem modules; other fixes.
 297.161 +
 297.162 +	PXE and NTFS fixes.
 297.163 +	Fixed a bug in probe_int for GRUB.EXE running in VM86 mode.
 297.164 +	Rewrite fsys_ntfs.c
 297.165 +	Fixed probe_int and init_pic in GRUB.EXE. Reduced warnings in bios.c.
 297.166 +	Added PXE support.
 297.167 +	NTFS code update for bootlace. Fixed timing functions.
 297.168 +	fix a bug in get_diskinfo; protect the MBR of an in-situ-mapped drive.
 297.169 +	Insert-key to debug on startup; polish graphics. NTFS boot record fix.
 297.170 +	Bugfixes on STAGE2_SIZE, arrow keys, and handling `&&'/`||' in menu.
 297.171 +	Move preset menu to the end/tail of pre_stage2.
 297.172 +	Numeric keys to select menu entry; fixed a bug of int13 harddrives.
 297.173 +	Code clean-ups on build script and keycode translation. 
 297.174 +	F11/F12 hotkey handling.
 297.175 +	Added builtin NTFS boot sectors into GRLDR.
 297.176 +	Added 3 commands is64bit, errnum and errorcheck.
 297.177 +	Applied Robert Millan's patch of check_64bit.
 297.178 +	Implemented two syntactic operators `&&' and `||'.
 297.179 +	Added a new option --in-situ for the map command.
 297.180 +
 297.181 +	Fixed an auto-probe-int problem of GRUB.EXE under "EMM386 noems".
 297.182 +
 297.183 +	Workaround for buggy VirtualPC on a issue of floppy-emulation-mode
 297.184 +	bootable CDROM.
 297.185 +
 297.186 +2006-12-28 version 0.4.2
 297.187 +
 297.188 +	Fixed a bug hidden deeply in memcheck.
 297.189 +	Fixed a bug hidden deeply in get_diskinfo.
 297.190 +	Fixed a bug in load_image.
 297.191 +	GRLDR(as a no-emulation-mode bootable CDROM image) was adapted to
 297.192 +	cope with some buggy BIOSes(e.g., VirtualPC).
 297.193 +	Added LBA-to-CHS geometry translation(in int13_handler) to simulate
 297.194 +	LBA(EBIOS)-enabled drives on CHS-only drives.
 297.195 +	Added a new feature of Unconditional Command-line Entrance.
 297.196 +	Applied Beverly Brown's patch to load_initrd.
 297.197 +	Added two new options to the map command to better serve Win9x.
 297.198 +	The default config file search path for GRUB.EXE was changed to
 297.199 +	(DOS file) .\menu.lst and then (DOS file) \menu.lst and then
 297.200 +	(GRUB file) /menu.lst.
 297.201 +	Other bug fixes.
 297.202 +
 297.203 +2006-10-24 version 0.4.2pre11
 297.204 +
 297.205 +	Made a workaround for buggy USB-bootable board QDI 848E.
 297.206 +	Made a workaround for buggy 965 board with SATA CDROM connected.
 297.207 +
 297.208 +2006-10-07 version 0.4.2pre10
 297.209 +
 297.210 +	Fixed a problem in GRUB shell which causes failure in grub-install.
 297.211 +	Enabled GRUB.EXE to run under FreeDOS with memdrives in use.
 297.212 +	Implemented an auto-probe mechanism to support all kinds of DOSes.
 297.213 +
 297.214 +2006-09-19 version 0.4.2pre9
 297.215 +
 297.216 +	Resolved several problems:
 297.217 +	1. (about kexec)Dropped the problematic kexec-tools-1.101-patch.
 297.218 +	2. (about stack)Adjusted code in C files to use less stack.
 297.219 +	3. (about cdrom)Fixed a few bugs in the cdrom driver. 
 297.220 +
 297.221 +2006-08-29 version 0.4.2pre8
 297.222 +
 297.223 +	Added a new command `setvbe'.
 297.224 +	Dropped the obsolete EZ-BIOS(with signature `AERMH') support.
 297.225 +	Fixed a bug in parsing Rock-Ridge extension.
 297.226 +	No-emulation-mode Bootable CD can be chainloaded now.
 297.227 +	Some work was done to improve remote/diskless boot.
 297.228 +	Fixed one more USB/Floppy EBIOS problem(in get_diskinfo).
 297.229 +	Merged protected mode stack into real mode stack at 0x2000.
 297.230 +	Code clean-up.
 297.231 +
 297.232 +2006-07-31 version 0.4.2pre7
 297.233 +
 297.234 +	Imported ATAPI CDROM driver from Smart Boot Manager.
 297.235 +
 297.236 +	Dropped the previous implementation of SCDROM/BIOSCDROM.
 297.237 +
 297.238 +	Fixed a USB/Floppy EBIOS problem that could cause media access failure
 297.239 +	or even hang the machine when using USB storage devices.
 297.240 +
 297.241 +	Fixed a bug in BOOTLACE.COM that had improperly set the LBA indicator
 297.242 +	byte(which is at offset 0x02 of the boot sector).
 297.243 +
 297.244 +	Fixed a bug in GRLDR that caused failure in finding the associated
 297.245 +	MENU.LST config-file(which should be in the same directory as GRLDR).
 297.246 +
 297.247 +2006-06-18 version 0.4.2pre6
 297.248 +
 297.249 +	Dropped the obsolete EZD disk map support.
 297.250 +	Fixed several bugs that may hang or slow the qemu virtual machine.
 297.251 +	Fixed a bug that causes the pause command not to respond any key-press.
 297.252 +	Fixed a bug that causes a command to accidentally fail if in a menu.
 297.253 +	Fixed a bug that causes the menu not to work once a cdrom had booted.
 297.254 +
 297.255 +2006-06-05 version 0.4.2pre5
 297.256 +
 297.257 +	Added a static-linked binary executable file GRUB(a Linux utility).
 297.258 +
 297.259 +	Fixed a gateA20 problem related to memdrive emulation.
 297.260 +
 297.261 +	Boot GRUB.EXE directly off Windows9x/Me(experimental; might hang).
 297.262 +
 297.263 +2006-04-03 version 0.4.2pre4
 297.264 +
 297.265 +	Made GRUB.EXE run under EMM386.
 297.266 +	Fixed a bug in splashimage_func().
 297.267 +	Made `ignore error' constant and removed the `--ignore-error' option,
 297.268 +	and renamed the option `--seconds=T' to `--wait=T' for savedefault.
 297.269 +	The sample menu.lst was modified accordingly.
 297.270 +
 297.271 +2006-03-28 version 0.4.2pre3
 297.272 +
 297.273 +	New syntax for the `default' and `savedefault' commands was
 297.274 +	implemented.
 297.275 +
 297.276 +	Changed `int' to `unsigned long' for filemax, filepos and fsmax, and
 297.277 +	modified all fsys_*.c files in order to open large files(2GB or
 297.278 +	longer).
 297.279 +
 297.280 +2006-03-09 version 0.4.2pre2
 297.281 +
 297.282 +	The directory `boot/grub/' was removed from the release tree(GRUB4DOS
 297.283 +	does not use the stage files at boot time). The default config file for
 297.284 +	GRUB.EXE was changed to (hd0,0)/menu.lst(but preset_menu still locates
 297.285 +	(hd0,0)/boot/grub/menu.lst when (hd0,0)/menu.lst does not exist).
 297.286 +
 297.287 +	Added DOS command-line options --bypass, --time-out=T and --hot-key=K
 297.288 +	for GRUB.EXE.
 297.289 +
 297.290 +2006-02-24 version 0.4.2pre1
 297.291 +	gcc-4 support by VirusCamp.
 297.292 +	
 297.293 +	Limited support for returning to DOS from GRUB.EXE.
 297.294 +	
 297.295 +	Implemented a new feature that GRUB.EXE can be used as a DOS device
 297.296 +	driver and be started in CONFIG.SYS with a DEVICE line.
 297.297 +	
 297.298 +	Better IODELAY was made for initialization of PIC to fix the
 297.299 +	keyboard-not-responding problem when running through KEXEC.
 297.300 +
 297.301 +	Better A20 gate control was made to help fix various problems on the
 297.302 +	boot of grub.
 297.303 +	
 297.304 +2005-12-14 version 0.4.1
 297.305 +	Fixed a partition enumeration bug(in disk_io.c). Fixed a bug of mapping
 297.306 +	partitions to harddrives(in builtins.c). Fixed a bug that causes
 297.307 +	failure when `find --set-root' on a CD-ROM device(in builtins.c). Added
 297.308 +	a new feature of directly chainloading ntldr and some dos kernels.
 297.309 +
 297.310 +2005-11-14 version 0.4.1pre32
 297.311 +	Fixed more bugs.
 297.312 +
 297.313 +2005-11-02 version 0.4.1pre31
 297.314 +	A few bugs were fixed.
 297.315 +
 297.316 +2005-10-23 version 0.4.1pre30
 297.317 +	A bug about "bootlace.com --floppy" was fixed.
 297.318 +
 297.319 +2005-10-18 version 0.4.1pre29
 297.320 +	Added ram disk device (rd) to access, typically, the initrd image.
 297.321 +	Added many new command-line options for bootlace.com to install GRLDR
 297.322 +	boot record onto the boot sector of a floppy. A few bugs about
 297.323 +	"map --mem" were fixed. Another bug about finding grldr in NTFS was
 297.324 +	also fixed. It may cause the machine to hang up when there is no ntfs
 297.325 +	boot record in the boot area of the NTFS partition.
 297.326 +
 297.327 +2005-09-25 version 0.4.1pre28
 297.328 +	Commandline option --config-file="FILENAME_OR_RAW_COMMANDS" was added
 297.329 +	for GRUB.EXE where GRUB.EXE is treated as a Linux kernel.
 297.330 +	Fixed a bug which causes installation failure when BOOTLACE.COM is
 297.331 +	used for large disks.
 297.332 +
 297.333 +2005-09-21 version 0.4.1pre27
 297.334 +	Added a patch to the kexec-tools-1.101. Kexec might fail to load
 297.335 +	grub.exe without this patch.
 297.336 +
 297.337 +2005-09-14 version 0.4.1pre26
 297.338 +	Fixed a bug for the DOS part of BOOTLACE.COM
 297.339 +
 297.340 +2005-09-11 version 0.4.1pre25
 297.341 +	GRUB4LIN has merged into GRUB.EXE; A new command-line option
 297.342 +	--read-only was added for BOOTLACE.COM; A few bug fixes.
 297.343 +	
 297.344 +2005-09-01 version 0.4.1pre24
 297.345 +	BOOTLACE.COM runs under both DOS and Linux.
 297.346 +
 297.347 +2005-08-27 version 0.4.1pre23
 297.348 +	Added a utility BOOTLACE.COM for installing grldr bootstrap code to MBR
 297.349 +
 297.350 +2005-07-30 version 0.4.1pre22
 297.351 +	Added bootstrap file GRLDR.MBR for launching grldr from MBR.
 297.352 +
 297.353 +2005-07-24 version 0.4.1pre21
 297.354 +	Added Windows NT 4.0 support(actually fixed a bug reported by Stefan
 297.355 +	Baur). For other new features, see README.txt.
 297.356 +
 297.357 +2005-07-20 version 0.4.1pre20
 297.358 +	Added ext2/ext3 boot record code for loading grldr from the beginning
 297.359 +	sector of a floppy or a partition. 
 297.360 +
 297.361 +2005-05-25 version 0.4.1pre5
 297.362 +	GRUB commands can be embedded into the command line of GRUB.EXE
 297.363 +
 297.364 +2005-05-20 version 0.4.1pre4
 297.365 +	Bug fixes: When the system has no floppies, some operations,
 297.366 +	e.g., the find command, will hang the machine.
 297.367 +
 297.368 +2005-05-17 version 0.4.1pre3
 297.369 +	Search for cdrom_drive from drive 0x88 to drive 0xff
 297.370 +
 297.371 +2005-05-11 version 0.4.1pre2
 297.372 +	Our base is now upgraded to GNU GRUB 0.97.
 297.373 +
 297.374 +2005-04-25 version 0.4.1pre
 297.375 +	Fixed a bug reported by Gilles van Ruymbeke
 297.376 +	<[email protected]> <[email protected]>:
 297.377 +	
 297.378 +	The map_func improperly opened the emulation image for 3 times, that
 297.379 +	might slow down the load speed heavily, especially for gzipped files.
 297.380 +
 297.381 +2005-04-15 version 0.4.0
 297.382 +	Add /boot/grub/menu.lst in preset menu. This is final.
 297.383 +
 297.384 +2005-04-07 version 0.4.0pre7
 297.385 +	config_file takes precedence over preset_menu.
 297.386 +
 297.387 +2005-04-06 version 0.4.0pre6
 297.388 +	GRLDR can be used with no-emulation-mode bootable CD-ROM.
 297.389 +
 297.390 +2005-03-09 version 0.4.0pre4
 297.391 +	Now preset menu find /menu.lst, no longer support /boot/grub/menu.lst
 297.392 +
 297.393 +	Partition images can emulate a partition (hd?,0) with --mem option.
 297.394 +
 297.395 +2005-03-02 version 0.4.0pre3
 297.396 +	GRLDR startup code search all partitions in all harddrives for GRLDR.
 297.397 +
 297.398 +	chainloader can boot images larger than 512 bytes, and can load image
 297.399 +	to a different location than 0000:7C00.
 297.400 +
 297.401 +2005-02-06 version 0.4.0pre
 297.402 +	Switched to GNU GRUB 0.96
 297.403 +	The --mem option of MAP command was added for memdrive emulation.
 297.404 +
 297.405 +	Also announced 0.2.0 final.
 297.406 +
 297.407 +2004-10-23 version 0.2.0pre13
 297.408 +	GRUB.EXE runs in DOSBOX.
 297.409 +	GRUB4LIN is introduced to boot off LINUX.
 297.410 +	Fixed a bug reported by windrv: NTFS check contiguity failure
 297.411 +	Rearranged the patches.
 297.412 +
 297.413 +2004-08-31 version 0.2.0pre12
 297.414 +	Fixed a bug reported by szwp: cannot load GRLDR on partition that is
 297.415 +	not CHS-accessible.
 297.416 +
 297.417 +	Fixed a bug reported by windrv: take too much time to check contiguity
 297.418 +
 297.419 +2004-08-15 version 0.2.0pre11
 297.420 +	Mark the scdrom module as experimental.
 297.421 +
 297.422 +2004-07-13 version 0.2.0pre9
 297.423 +	Merged GNU GRUB 0.95
 297.424 +
 297.425 +	BOOTGRUB removed. Use BOOT.INI line C:\GRLDR="Start GRUB" instead.
 297.426 +
 297.427 +	Patches from Gandalf: NTFS and ATAPI CDROM support(also thanks to
 297.428 +	Tobias Svensson <[email protected]>)
 297.429 +
 297.430 +	Patches from Chris Semler <[email protected]>: findroot
 297.431 +
 297.432 +2004-04-12 version 0.2.0pre6
 297.433 +	Now GRUB.EXE can be used in CONFIG.SYS this way:
 297.434 +
 297.435 +	shell=C:\some\where\grub.exe --config-file=(hd0,0)/boot/grub/menu.lst
 297.436 +
 297.437 +	or
 297.438 +
 297.439 +	shell=C:\some\where\grub.exe
 297.440 +
 297.441 +	No other changes.
 297.442 +
 297.443 +2004-04-09 version 0.2.0pre5
 297.444 +	Now BOOTGRUB contains 4 sectors, i.e., 2048 bytes. Optionally, you may
 297.445 +	copy the 2nd, 3rd and 4th sectors of BOOTGRUB to the three sectors that
 297.446 +	immediately follow the MBR. Also Optionally, you may copy 446 bytes
 297.447 +	from the very beginning of BOOTGRUB to the very beginning of MBR. In
 297.448 +	this way, the GRLDR can be started out of MBR, without the presence of
 297.449 +	NTLDR.
 297.450 +
 297.451 +	CAUTION: Don't copy 512 bytes to MBR. The partition table should not
 297.452 +	be overwritten. The partition table is in the end of MBR. If you make
 297.453 +	a mistake, you will lose your whole system!!
 297.454 +
 297.455 +2004-02-18 version 0.2.0pre4
 297.456 +	Arbitrary-size floppy and hard disk emulation finally implemented.
 297.457 +	GRUB for NTLDR is included. See README file.
 297.458 +	Splash image version is available in the SPLASH directory.
 297.459 +	
 297.460 +2003-09-23 version 0.1.4 -- development unstable release
 297.461 +	Unfortunately 0.1.3 has an ugly bug. Fixed.
 297.462 +
 297.463 +2003-09-01 version 0.1.3 -- development unstable release
 297.464 +	Rewrite the code for guessing FreeDOS int vectors. Hopefully it works
 297.465 +	for all the future versions of FreeDOS :-)
 297.466 +
 297.467 +2003-08-25 version 0.1.2 -- development unstable release
 297.468 +	Fixed a small bug that affects the read of the emulated floppy sectors.
 297.469 +	
 297.470 +	Added some files (including the menu.lst file) for installing GRUB to
 297.471 +	MBR from DOS. Usage:
 297.472 +
 297.473 +	Copy the boot directory to C:\ ; You must do this on Windows, NOT dos,
 297.474 +	because DOS cannot deal with the long filenames.
 297.475 +
 297.476 +	Run grub to access the menu.lst file in C:\boot\grub ; Of cause on DOS.
 297.477 +
 297.478 +	When menu occurs, select a proper menu item for installing GRUB to MBR.
 297.479 +
 297.480 +	If the menu does not appear, you should get the "grub>" prompt. At the
 297.481 +	prompt, type the following commands:
 297.482 +
 297.483 +	grub> configfile (hd0,1)/boot/grub/menu.lst
 297.484 +	grub> configfile (hd0,2)/boot/grub/menu.lst
 297.485 +	grub> configfile (hd0,3)/boot/grub/menu.lst
 297.486 +
 297.487 +	Then, the menu should occur.
 297.488 +	
 297.489 +2003-06-29 version 0.1.0.1 -- development unstable release
 297.490 +	Do some cleanups on 0.1.0, no important changes.
 297.491 +	BTW, it seems that the 0.1.0 is quite stable :-)
 297.492 +	
 297.493 +2003-06-29 version 0.0.8
 297.494 +	Restore mapped int13 to the unmapped state while grub is invoked
 297.495 +	after a previously performed drive map operation.
 297.496 +
 297.497 +2003-05-29 version 0.1.0 -- development unstable release
 297.498 +	Floppy 1.44M drive emulation are OK. GOOD!!!! Usage:
 297.499 +	
 297.500 +	# boot Windows 98 SE
 297.501 +	map (hd1,0)/dos98se.img (fd0)
 297.502 +	chainloader (hd1,0)/dos98se.img
 297.503 +	rootnoverify (fd0)
 297.504 +	boot
 297.505 +	
 297.506 +	Another example:
 297.507 +
 297.508 +	# boot Mandrake hard disk installer
 297.509 +	map (hd0,0)/hd.img (fd0)
 297.510 +	chainloader (hd0,0)/hd.img
 297.511 +	rootnoverify (fd0)
 297.512 +	boot
 297.513 +
 297.514 +	Note that the floppy image file must size 1440KB, i.e., 1474560 bytes.
 297.515 +	_AND_ also, the file must consist of one contiguous disk area, no
 297.516 +	holes, no fragments. Use GRUB's blocklist command to determine whether
 297.517 +	or not an image file is contiguous. It is known that a 1440KB-file is
 297.518 +	always non-contiguous if it resides in an ext2 filesystem. But you may
 297.519 +	get a 1440KB contiguous file with an FAT32 partition(vfat filesystem).
 297.520 +
 297.521 +	Floppy(and hard disk) with arbitrary sizes will be emulated in the
 297.522 +	future.
 297.523 +
 297.524 +2003-05-06 version 0.0.7
 297.525 +
 297.526 +		Fixed a huge bug!! Read the following carefully!
 297.527 +	
 297.528 +	Using the drive map command(just as many distributions currently do)
 297.529 +	
 297.530 +			map TO_DRIVE FROM_DRIVE
 297.531 +	
 297.532 +	to boot your system could seriously _damage_ your hard disk data,
 297.533 +	
 297.534 +	totally and thoroughly!! This bug has just been fixed in 0.0.7 :-)
 297.535 +	
 297.536 +	This bug is not specific to grub_for_dos, but caused by the original
 297.537 +	
 297.538 +	grub-0.93 release. So do _NOT_ use map command any more until my fix is
 297.539 +
 297.540 +	accepted by GRUB maintainers or a similar fix is made by other
 297.541 +	
 297.542 +	people. For now, do _NOT_ use map command in any kind of Linux
 297.543 +	
 297.544 +	distributions such as Red Hat or Mandrake or any others.
 297.545 +
 297.546 +		Because GRUB_FOR_DOS-0.0.7 already applied the fix, so it
 297.547 +	
 297.548 +	should be safe to use the map command.
 297.549 +
 297.550 +		Another small bug was also fixed in grub_for_dos-0.0.7 :-)
 297.551 +
 297.552 +2003-04-29 version 0.0.6
 297.553 +	Runs also on MS-DOS 3.30. No other changes.
 297.554 +
 297.555 +2003-04-26 version 0.0.5
 297.556 +	Runs on MS-DOS 4.0, 5.0, 6.0, 6.20, 6.21, 6.22, 7.0, 7.10, 8.0 and
 297.557 +	FreeDOS(build 2029). GOOD!!
 297.558 +
 297.559 +2003-04-20 version 0.0.4
 297.560 +	Running on FreeDOS(build 2029), GOOD!! (But currently GRUB.EXE only
 297.561 +	has limited FreeDOS support, maybe unstable.)
 297.562 +
 297.563 +	Add a "Guess DOS Version" feature. The program now exit to DOS when
 297.564 +	guess failed. The previous versions of GRUB.EXE always hang when
 297.565 +	running on an unsupported DOS version.
 297.566 +	
 297.567 +2003-04-13 version 0.0.3
 297.568 +	The option "--config-file=FILE" was added.
 297.569 +	
 297.570 +2003-04-11 version 0.0.2
 297.571 +	Also runs on MS-DOS 8.0 (i.e., the DOS with WinMe/2000/XP), GOOD!!
 297.572 +	The GRUB.PIF file included, so GRUB.EXE can be started from Windows 9x
 297.573 +
 297.574 +2003-04-10 version 0.0.1
 297.575 +	Runs on MS-DOS 7.10(Win98)
   298.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   298.2 +++ b/usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/README_GRUB4DOS.txt	Mon Apr 26 11:16:23 2010 +0200
   298.3 @@ -0,0 +1,3864 @@
   298.4 +Please refer to http://grub4dos.sourceforge.net/wiki/ for DOCs on GRUB4DOS.
   298.5 +
   298.6 +Main project page:	https://gna.org/projects/grub4dos/
   298.7 +
   298.8 +Download site:		http://download.gna.org/grub4dos/
   298.9 +Download site:		http://grub4dos.sourceforge.net/
  298.10 +Download site:		http://sarovar.org/projects/grub4dos/
  298.11 +Download site:		http://grub4dos.nufans.net/
  298.12 +Download site:		http://sites.google.com/site/grubdos/
  298.13 +Download site:		ftp://grub4dos.sarovar.org/pub/grub4dos/
  298.14 +
  298.15 +Get the latest source code by using anonymous svn in this way:
  298.16 +
  298.17 +	svn co svn://svn.gna.org/svn/grub4dos/trunk grub4dos
  298.18 +
  298.19 +or in this way:
  298.20 +
  298.21 +	svn co http://svn.gna.org/svn/grub4dos/trunk grub4dos
  298.22 +
  298.23 +View the source code online with your web browser at:
  298.24 +
  298.25 +	http://svn.gna.org/viewcvs/grub4dos/trunk/
  298.26 +
  298.27 +GRUB4DOS mailing list:
  298.28 +
  298.29 +	[email protected]
  298.30 +
  298.31 +Subscription page:
  298.32 +
  298.33 +	https://mail.gna.org/listinfo/grub4dos-devel/
  298.34 +
  298.35 +Discussion forum(Official technical support site):
  298.36 +
  298.37 +	http://www.boot-land.net/forums/index.php?showforum=66
  298.38 +
  298.39 +------------------------------------------------------------------------------
  298.40 +
  298.41 +Usage:
  298.42 +		GRUB [--bypass] [--time-out=T] [--hot-key=K] [--config-file=FILE]
  298.43 +		
  298.44 +		The FILE, for example, can be (hd0,0)/menu.lst
  298.45 +		
  298.46 +		In CONFIG.SYS, the line looks like:
  298.47 +		
  298.48 +			install=c:\some\where\grub.exe --config-file=FILE
  298.49 +		
  298.50 +		If no options present, GRUB.EXE simply uses
  298.51 +		
  298.52 +			(hd0,0)/menu.lst
  298.53 +		
  298.54 +		as the configure file, if it exists. (Notice! We finally
  298.55 +		changed the default file from (hd0,0)/boot/grub/menu.lst to
  298.56 +		(hd0,0)/menu.lst) (Changed 2006-12-23. See Update 3 below.)
  298.57 +		
  298.58 +		The partition (hd0,0) can be of a Windows partition or a Linux
  298.59 +		partition, or any other partition type supported by GRUB.
  298.60 +
  298.61 +		Only GRUB-style filename is acceptable here for FILE. A DOS
  298.62 +		filename won't work(it is certain we should use GRUB-style
  298.63 +		filenames because DOS-filenames won't access a file in a
  298.64 +		Linux ext2 partition for example).(See Update 2 below)
  298.65 +
  298.66 +		Update: FILE can be the contents of a menu. Use semi-colon
  298.67 +		to delimitate the embedded commands here in FILE. The FILE
  298.68 +		can be enclosed with a pair of double-quotes. For example:
  298.69 +
  298.70 +			GRUB --config-file="root (hd0,0);chainloader +1"
  298.71 +
  298.72 +		This command will boot the system in (hd0,0).
  298.73 +
  298.74 +		Another example:
  298.75 +
  298.76 +			GRUB --config-file="reboot"
  298.77 +
  298.78 +		This command will reboot the machine.
  298.79 +
  298.80 +		One more example:
  298.81 +
  298.82 +			GRUB --config-file="halt"
  298.83 +
  298.84 +		This command will halt the machine.
  298.85 +
  298.86 +		if --bypass is specified, GRUB will exit to DOS when
  298.87 +		timeout reached.
  298.88 +
  298.89 +		The option `--time-out=T' specifies the timeout value in
  298.90 +		seconds. T defaults to 5 if --bypass is specified and defaults
  298.91 +		to 0 if --bypass is not specified.
  298.92 +
  298.93 +		The default hot key value is 0x3920(for space bar). If this
  298.94 +		key is pressed, GRUB will boot normally. If another key is
  298.95 +		pressed, GRUB will terminate immediately and return back to
  298.96 +		DOS. See "int 16 keyboard scan codes" below.
  298.97 +
  298.98 +		Each option can be specified only once at most.
  298.99 +
 298.100 +		Update 2: DOS filenames have been supported(patched by John
 298.101 +		Cobb). If the beginning two characters of FILE are "#@", then
 298.102 +		the rest of FILE is taken as a DOS filename. Example:
 298.103 +
 298.104 +			GRUB --config-file="#@c:\menu.lst"
 298.105 +
 298.106 +		Only the beginning 4KB of the DOS file will be used. The file
 298.107 +		should be an uncompressed text file.
 298.108 +
 298.109 +		Note: You may also use the `direct DOS file access' with the
 298.110 +		SHELL or INSTALL line in CONFIG.SYS, but should not use it
 298.111 +		with the DEVICE line. The DOS document said that a DOS device
 298.112 +		driver should not call the `open file' DOS call.
 298.113 +
 298.114 +		Update 3(2021-12-23): By default, GRUB.EXE will locate its
 298.115 +		config file in the following order:
 298.116 +
 298.117 +			(DOS file) .\menu.lst, the MENU.LST in the current dir.
 298.118 +
 298.119 +			(DOS file) \menu.lst, the MENU.LST in the root dir of
 298.120 +						the current drive.
 298.121 +			(GRUB file) /menu.lst, the MENU.LST in the root dir of
 298.122 +						the boot device.
 298.123 +
 298.124 +		The default boot device is still (hd0,0).
 298.125 +
 298.126 +
 298.127 +--------------------------------------------------------
 298.128 +
 298.129 +Update 1:	Version 0.2.0 also brings out a new thing, GRUB for NTLDR,
 298.130 +		which could be used to boot into GRUB from the boot menu
 298.131 +		of Windows NT/2000/XP. Copy GRLDR to the root directory of
 298.132 +		drive C: of Windows NT/2000/XP and append to C:\BOOT.INI
 298.133 +		this line:
 298.134 +
 298.135 +			C:\GRLDR="Start GRUB"
 298.136 +
 298.137 +		That will be done. The GRLDR should be in the same directory
 298.138 +		as BOOT.INI and NTLDR. Note that BOOT.INI is usually hidden
 298.139 +		and you must unhide it before you can see it. The filename
 298.140 +		GRLDR shouldn't be changed. If GRLDR is in a NTFS partition,
 298.141 +		it should be copied to the root directory of another non-NTFS
 298.142 +		partition(and likewise should the menu.lst file be). If GRLDR
 298.143 +		is compressed, e.g., in a NTFS partition, it will not work.
 298.144 +
 298.145 +		Even if the drive letter of this disk has been changed to
 298.146 +		other than C by the Windows device manager, it seems you still
 298.147 +		have to use the letter C here in BOOT.INI, otherwise, NTLDR
 298.148 +		will fail to locate the GRLDR file.
 298.149 +
 298.150 +		And what's more, if you are booting NTLDR from a floppy, you
 298.151 +		will have to write the GRLDR line in A:\BOOT.INI like this:
 298.152 +
 298.153 +			C:\GRLDR="Start GRUB"
 298.154 +
 298.155 +		and shouldn't use the letter A like this:
 298.156 +
 298.157 +			A:\GRLDR="Start GRUB"
 298.158 +
 298.159 +		(Note that in the case when BOOT.INI is on floppy A, the
 298.160 +		notation "C:\GRLDR" actually refer to the file A:\GRLDR).
 298.161 +
 298.162 +
 298.163 +Update 2:	GRUB for Linux is also introduced along with 0.2.0. You can
 298.164 +		boot grub using a linux loader KEXEC, LILO, SYSLINUX or another
 298.165 +		GRUB. (GRUB4LIN has merged into GRUB.EXE)
 298.166 +
 298.167 +		To boot GRUB off Linux, use this pair of commands:
 298.168 +
 298.169 +			kexec -l grub.exe
 298.170 +			kexec -e
 298.171 +
 298.172 +		To boot GRUB via GRUB, use commands like the following:
 298.173 +
 298.174 +			kernel (hd0,0)/grub.exe
 298.175 +			boot
 298.176 +
 298.177 +		To boot GRUB via LILO, use these lines in lilo.conf:
 298.178 +
 298.179 +			image=/boot/grub.exe
 298.180 +			label=grub.exe
 298.181 +
 298.182 +		To boot GRUB via SYSLINUX, use these lines in syslinux.cfg:
 298.183 +
 298.184 +			label grub.exe
 298.185 +				kernel grub.exe
 298.186 +
 298.187 +		LOADLIN may encounter problems when loading grub.exe, because
 298.188 +		grub.exe requires some unchanged original BIOS interrupt
 298.189 +		vectors, but DOS has destroyed them, and loadlin does not
 298.190 +		recover them before it transfers control to grub.exe.
 298.191 +		
 298.192 +Update 3:	Beginning at version 0.4.0, GRUB for DOS supports memdrives.
 298.193 +		Example:
 298.194 +
 298.195 +			# boot into a floppy image
 298.196 +			map --mem (hd0,0)/floppy.img (fd0)
 298.197 +			map --hook
 298.198 +			chainloader (fd0)+1
 298.199 +			rootnoverify (fd0)
 298.200 +			map --floppies=1
 298.201 +			boot
 298.202 +
 298.203 +		Because the image will be copied to a memory area, the image
 298.204 +		itself can be non-contiguous and even gzipped.
 298.205 +
 298.206 +		Another Example:
 298.207 +
 298.208 +			map --mem=-2880 (hd0,0)/floppy.img (fd0)
 298.209 +
 298.210 +		This memdrive (fd0) will occupy at least 1440 KB of memory.
 298.211 +		This is useful when the size of a 1.44M-floppy image is less
 298.212 +		than 1440 KB.
 298.213 +
 298.214 +		One more example:
 298.215 +
 298.216 +			map --mem --read-only (hd0,0)/hd.img (hd1)
 298.217 +
 298.218 +		This memdrive is a hard drive, and read-only. That means you
 298.219 +		will not be able to write data to the memdrive (hd1).
 298.220 +
 298.221 +		You can use many memdrives and many ordinary virtual emulated
 298.222 +		disk-based drives at the same time.
 298.223 +
 298.224 +		If the BIOS does not support int15/EAX=e820h, you will not be
 298.225 +		able to use any memdrives.
 298.226 +
 298.227 +Update 4:	For memdrive emulation, a single-partition image can be used
 298.228 +		instead of a whole-harddrive image. Example:
 298.229 +
 298.230 +			map --mem (hd0,7)/win98.img (hd0)
 298.231 +			map --hook
 298.232 +			chainloader (hd0)+1
 298.233 +			rootnoverify (hd0)
 298.234 +			map --harddrives=1
 298.235 +			boot
 298.236 +
 298.237 +		Here win98.img is a partition image without the leading MBR
 298.238 +		and partition table in it. Surely GRUB for DOS will build an
 298.239 +		MBR and partition table for the memdrive (hd0).
 298.240 +
 298.241 +Update 5:	Now GRLDR can be used as a no-emulation-mode bootable CD-ROM
 298.242 +		boot image. Example for Linux users:
 298.243 +
 298.244 +			mkdir iso_root
 298.245 +			cp grldr iso_root
 298.246 +			mkisofs -R -b grldr -no-emul-boot -boot-load-seg 0x1000 -o bootable.iso iso_root
 298.247 +
 298.248 +		As an alternative, grldr can also be used the same way as
 298.249 +		stage2_eltorito. The -boot-info-table option is allowed but you
 298.250 +		can omit it:
 298.251 +
 298.252 +			mkdir iso_root
 298.253 +			cp grldr iso_root
 298.254 +			mkisofs -R -b grldr -no-emul-boot -boot-load-size 4 -o grldr.iso iso_root
 298.255 +
 298.256 +		Also note that the bootable.iso above must be created with the
 298.257 +		-boot-load-seg 0xHHHH option where HHHH is greater than or
 298.258 +		equal to 1000(hex). If HHHH < 1000(hex), QEMU will hang. This
 298.259 +		is a bug in QEMU. The grldr.iso can be created with or without
 298.260 +		-boot-load-seg 0xHHHH option.
 298.261 +
 298.262 +		The menu.lst file should be placed in the root dir of the CD.
 298.263 +
 298.264 +Update 6:	The Chinese special build is in the "chinese" subdirectory.
 298.265 +		(patched by Gandalf, 2021-06-27)
 298.266 +
 298.267 +		The Chinese special build also has scdrom builtin.
 298.268 +		(update: scdrom has been dropped since 2021-07-20)
 298.269 +
 298.270 +Update 7:	Added memory drive (md). Like (nd) for network drive and (cd)
 298.271 +		for CD-ROM drive, a new drive (md) is implemented for accessing
 298.272 +		the whole memory as a disk drive. (md) only works for systems
 298.273 +		with BIOS int15/EAX=E820h support.
 298.274 +
 298.275 +		The cat command now has a few new options: --hex for hexdump,
 298.276 +		and --locate=STRING for string search in file.
 298.277 +
 298.278 +		Typical examples:
 298.279 +
 298.280 +			cat --hex (hd0)+1
 298.281 +
 298.282 +		It will display the MBR sector in hex form.
 298.283 +
 298.284 +			cat --hex (md)+2
 298.285 +
 298.286 +		It will display 1KB of your memory(in fact, it is the real-mode
 298.287 +		IDT table), also in hexdump form.
 298.288 +		
 298.289 +			cat --hex (md)0x800+1
 298.290 +
 298.291 +		It will display 1 sector of your extended memory.
 298.292 +
 298.293 +			cat --hex (hd0,0)+1
 298.294 +
 298.295 +		It will display the first sector of partition (hd0,0). Usually
 298.296 +		this sector contains the boot record of an operating system.
 298.297 +
 298.298 +Update 8:	Added ram drive (rd). The (md) device accesses the memory
 298.299 +		starting at physical address 0. But (rd) accesses memory
 298.300 +		starting at any base address. The base and length of the ram
 298.301 +		drive can be specified through the map command. "help map" for
 298.302 +		details. You can even specify the BIOS drive number used for
 298.303 +		the (rd) drive, e.g., map --ram-drive=0xf0. The default drive
 298.304 +		number for (rd) is 0x7F which is a floppy. If (rd) is a hard
 298.305 +		drive image, you should change the drive number to a value
 298.306 +		greater than or equal to 0x80(but should avoid using 0xffff,
 298.307 +		because 0xffff is for the (md) device).
 298.308 +
 298.309 +		The notation (rd)+1 always represents the file which contains
 298.310 +		all the bytes stored in (rd).
 298.311 +
 298.312 +Update 9:	Directly boot NTLDR of WinNT/2K/XP and IO.SYS of Win9x/ME and
 298.313 +		KERNEL.SYS of FreeDOS. Examples:
 298.314 +
 298.315 +			chainloader --edx=0xPPYY (hd0,0)/ntldr
 298.316 +			boot
 298.317 +
 298.318 +			chainloader --edx=0xYY (hd0,0)/io.sys
 298.319 +			boot
 298.320 +
 298.321 +			chainloader --ebx=0xYY (hd0,0)/kernel.sys
 298.322 +			boot
 298.323 +
 298.324 +		Hex YY specifies the boot drive number, and hex PP specifies
 298.325 +		the boot partition number of NTLDR. If the boot drive is
 298.326 +		floppy, PP should be the hex value ff, i.e., decimal 255.
 298.327 +
 298.328 +		For KERNEL.SYS of FreeDOS, the --edx won't work,
 298.329 +		use --ebx please.
 298.330 +
 298.331 +		The option --edx ( --ebx ) can be omitted if the file is in
 298.332 +		its normal place. But in some cases, those options are needed.
 298.333 +
 298.334 +		If, e.g., the ntldr file is in an ext2 partition called
 298.335 +		(hd2,8) while you want it to think of the Windows partition
 298.336 +		(hd0,7) as the boot partition, then --edx is required:
 298.337 +
 298.338 +			chainloader --edx=0x0780 (hd2,8)/ntldr
 298.339 +
 298.340 +		For DOS kernels(i.e., IO.SYS and KERNEL.SYS), the boot
 298.341 +		partition number is meaningless, so you only need to specify
 298.342 +		the correct boot drive number YY(but specifying the boot
 298.343 +		partition number is harmless).
 298.344 +
 298.345 +		The above PPYY can also be specified by using a root or
 298.346 +		rootnoverify command after the chainloader command. Examples:
 298.347 +
 298.348 +			chainloader (hd2,6)/kernel.sys
 298.349 +			rootnoverify (hd0)	<-------- YY=80
 298.350 +			boot
 298.351 +
 298.352 +			chainloader (hd0,0)/ntldr
 298.353 +			rootnoverify (hd0,5)	<-------- YY=80, PP=05
 298.354 +			boot
 298.355 +
 298.356 +		Tip: CMLDR (the ComMand LoaDeR, which is used to load the
 298.357 +		Windows Fault Recovery Console) can be chainloaded as well
 298.358 +		as NTLDR.
 298.359 +
 298.360 +		Bean has successfully decompressed and booted IO.SYS of WinME.
 298.361 +		Thanks for the great job!
 298.362 +
 298.363 +Update 10:	isolinux.bin (version 3.73) can be chainloaded as with build
 298.364 +		2009-02-09.
 298.365 +
 298.366 +			chainloader (cd)/isolinux.bin
 298.367 +
 298.368 +		isolinux.bin must reside in a real or virtual cdrom.
 298.369 +
 298.370 +Update 11:	stage2 of Grub Legacy can be chainloaded in this way:
 298.371 +
 298.372 +			chainloader --force --load-segment=0 --load-offset=0x8000 --boot-cs=0 --boot-ip=0x8200 (...)/.../stage2
 298.373 +
 298.374 +--------------------------------------------------------
 298.375 +
 298.376 +	There is no full documentation in English at present. Here are some
 298.377 +	examples showing the usage of disk emulation commands:
 298.378 +
 298.379 +1.	Emulates HD partition C: as floppy drive A: and boot win98 from C:
 298.380 +
 298.381 +		map --read-only (hd0,0)+1 (fd0)
 298.382 +		chainloader (hd0,0)+1
 298.383 +		rootnoverify (hd0)
 298.384 +		boot
 298.385 +
 298.386 +	In the above example, (hd0,0) is drive C: with win98 on it. After win98
 298.387 +	boot complete, you will find that A: contains all files of C:, and if
 298.388 +	you delete files in A:, the files in C: will also disappear.
 298.389 +
 298.390 +	At the map command line, the notation (hdm,n)+1 is interpreted to
 298.391 +	represent the whole partition (hdm,n), not just the first sector of the
 298.392 +	partition.
 298.393 +
 298.394 +2.	Emulates HD partition C: as floppy drive A: and boot win98 from A:
 298.395 +
 298.396 +		map --read-only (hd0,0)+1 (fd0)
 298.397 +		map --hook
 298.398 +		chainloader (fd0)+1
 298.399 +		rootnoverify (fd0)
 298.400 +		map --floppies=1
 298.401 +		boot
 298.402 +
 298.403 +	After the "map --hook" command, the emulation takes effect instantly
 298.404 +	even in the GRUB command line.
 298.405 +	
 298.406 +	Note that the (fd0) in "chainloader (fd0)+1" is the emulated virtual
 298.407 +	floppy A:, not the real floppy diskette(because map is hooked now).
 298.408 +
 298.409 +
 298.410 +3.	Emulates an image file as floppy drive A: and boot win98 from C:
 298.411 +
 298.412 +		map --read-only (hd0,0)/floppy.img (fd0)
 298.413 +		chainloader (hd0,0)+1
 298.414 +		rootnoverify (hd0)
 298.415 +		map --floppies=1
 298.416 +		map --harddrives=1
 298.417 +		boot
 298.418 +
 298.419 +4.	Emulates an HD partition as the first hard disk and boot DOS from it:
 298.420 +
 298.421 +		map --read-only (hd2,6)+1 (hd0)
 298.422 +		map --hook
 298.423 +		chainloader (hd0,0)+1
 298.424 +		rootnoverify (hd0)
 298.425 +		map --harddrives=1
 298.426 +		boot
 298.427 +
 298.428 +	In this example, (hd2,6)+1 represents an extended logical DOS partition
 298.429 +	of the third BIOS hard disk (hd2).
 298.430 +
 298.431 +	If a DOS partition is used to emulate a hard disk, GRUB for DOS will
 298.432 +	first try to locate the partition table, usually 63 sectors ahead of
 298.433 +	the DOS partition. GRUB for DOS will refuse the emulation if the
 298.434 +	partition table is not there.
 298.435 +
 298.436 +5.	Emulates an image file as the first hard disk and boot DOS from it:
 298.437 +
 298.438 +		map --read-only (hd0,0)/harddisk.img (hd0)
 298.439 +		chainloader --load-length=512 (hd0,0)/harddisk.img
 298.440 +		rootnoverify (hd0)
 298.441 +		map --harddrives=1
 298.442 +		boot
 298.443 +
 298.444 +	If an image file is used to emulate a hard disk, the image file must
 298.445 +	contain an MBR. In other word, the first sector of HARDDISK.IMG must
 298.446 +	contain the partition table of the emulated virtual hard disk.
 298.447 +
 298.448 +Note:	Counters for floppies and harddrives in the BIOS Data Area remain
 298.449 +	unchanged during the mapping. You should manually set them to proper
 298.450 +	values with `map --floppies=' and/or `map --harddrives=', especially,
 298.451 +	e.g., when there is no real floppy drive attached to the mother board.
 298.452 +	If not doing so, DOS might fail to start.
 298.453 +
 298.454 +	`map --status' can report the values. Note also that `map --floppies='
 298.455 +	and `map --harddrives=' can be used independently without the
 298.456 +	appearance of mappings.
 298.457 +
 298.458 +	0.4.2 has introduced a new variable, memdisk_raw, to simulate the
 298.459 +	memdisk-like raw mode. If the BIOS has no int15/87h, or if it has
 298.460 +	buggy int15/87h support, you should set this variable before any
 298.461 +	memdrives are used. Here is an example:
 298.462 +
 298.463 +		map --memdisk-raw=1
 298.464 +		map --mem (hd0,0)/floppy.img (fd0)
 298.465 +		map --hook
 298.466 +		chainloader (fd0)+1
 298.467 +		rootnoverify (fd0)
 298.468 +		boot
 298.469 +
 298.470 +	If you encountered a memdrive failure without using
 298.471 +	map --memdisk-raw=1, you should have a try with `map --memdisk-raw=1'.
 298.472 +
 298.473 +	If you `map --memdisk-raw=0' later, you should afterwards do a
 298.474 +	`map --unhook'(and followed by a `map --hook' if needed).
 298.475 +
 298.476 +	Update: memdisk_raw now defaults to 1. You should `map --memdisk-raw=0'
 298.477 +	if you want to use int15/87h to access memdrives.
 298.478 +
 298.479 +--------------------------------------------------------
 298.480 +	
 298.481 +	Floppies/harddisks of any size can be emulated with GRUB for DOS 0.2.0.
 298.482 +	
 298.483 +	Image file must be contiguous, or else GRUB for DOS will refuse it.
 298.484 +
 298.485 +	The `blocklist' command can list fragments or pieces of a file.
 298.486 +
 298.487 +	Type "help map" at the GRUB prompt to get a brief description of the
 298.488 +	command.
 298.489 +
 298.490 +	The form 
 298.491 +	
 298.492 +		map ... (fd?)
 298.493 +	
 298.494 +	is a floppy emulation, and the form
 298.495 +	
 298.496 +		map ... (hd?)
 298.497 +	
 298.498 +	is a hard disk emulation.
 298.499 +
 298.500 +	When a HARD DISK emulation is used, better not start Windows for
 298.501 +	security reasons. Windows may even destroy all data and all information
 298.502 +	on all your real hard disks!!!!!!!!
 298.503 +	
 298.504 +	Update for --mem: when --mem is used, it seems rather safe even after
 298.505 +	entering Windows. Win98 can operate the memdrive normally.
 298.506 +
 298.507 +	Windows NT/2000/XP does not recognize the emulated drives no matter
 298.508 +	whether the --mem option is present.
 298.509 +
 298.510 +
 298.511 +
 298.512 +******************************************************************************
 298.513 +***   Explanation of the grldr-bootable floppies or harddisk partitions    ***
 298.514 +******************************************************************************
 298.515 +
 298.516 +1. Ext2 Boot Sector/Boot Record Layout (for loading grldr)
 298.517 +------------------------------------------------------------------------------
 298.518 +An EXT2/EXT3 volume can be GRUB-bootable. Copy grldr and an optional menu.lst
 298.519 +to the root dir of the EXT2/EXT3 volume, and build the boot sector based on the
 298.520 +fifth sector of grldr(some fields need to be changed as detailed in the
 298.521 +following table). And then the EXT2/EXT3 volume is GRUB-bootable.
 298.522 +
 298.523 +Update:	bootlace.com is a DOS/Linux utility that can install the GRLDR boot
 298.524 +record onto the first sector of an EXT2/EXT3 volume.
 298.525 +
 298.526 +Offset	Length	Description
 298.527 +======	======	==============================================================
 298.528 +00h	2	Machine code for short jump over the data.
 298.529 +
 298.530 +02h	1	LBA indicator. Valid values are 0x02 for CHS mode, or 0x42 for
 298.531 +		LBA mode.
 298.532 +
 298.533 +		If the BIOS int13 supports LBA, this byte can be safely set to
 298.534 +		0x42.
 298.535 +
 298.536 +		Some USB BIOSes might have bugs when using CHS mode, so the
 298.537 +		format program should set this byte to 0x42. It seems that
 298.538 +		(generally) all USB BIOSes have LBA support.
 298.539 +
 298.540 +		If the format program does not know whether the BIOS has LBA
 298.541 +		support, it may operate this way:
 298.542 +
 298.543 +		if (partition_start + total_sectors_in_partition) exceeds the
 298.544 +		CHS addressing ability(especially when it is greater than
 298.545 +		1024*256*63), the caller should set this byte to 0x42,
 298.546 +		otherwise, set to 0x02.
 298.547 +
 298.548 +		Note that Windows98 uses the value 0x0e as the LBA indicator.
 298.549 +
 298.550 +		Update: this byte of LBA indicator is ignored. The boot
 298.551 +		record can probe the LBA support of BIOS.
 298.552 +
 298.553 +03h	10	OEM name string (of OS which formatted the disk).
 298.554 +		Update: this field is now used for error message of "I/O error"
 298.555 +
 298.556 +0Dh	1	Sectors per block. Valid values are 2, 4, 8, 16 and 32.
 298.557 +
 298.558 +0Eh	2	Bytes per block. Valid values are 0x400, 0x800, 0x1000, 0x2000
 298.559 +		and 0x4000.
 298.560 +
 298.561 +10h	4	Pointers in pointers-per-block blocks, that is, number of
 298.562 +		blocks covered by a double-indirect block.
 298.563 +
 298.564 +		Valid values are 0x10000, 0x40000, 0x100000, 0x400000 and
 298.565 +		0x1000000.
 298.566 +
 298.567 +14h	4	Pointers per block, that is, number of blocks covered by an
 298.568 +		indirect block.
 298.569 +
 298.570 +		Valid values are 0x100, 0x200, 0x400, 0x800, 0x1000.
 298.571 +
 298.572 +18h	2	Sectors per track.
 298.573 +
 298.574 +1Ah	2	Number of heads/sides.
 298.575 +
 298.576 +1Ch	4	Number of hidden sectors (those preceding the boot sector).
 298.577 +
 298.578 +		Also referred to as the starting sector of the partition.
 298.579 +
 298.580 +		For floppies, it should be 0.
 298.581 +
 298.582 +20h	4	Total number of sectors in the filesystem(or in the partition).
 298.583 +
 298.584 +24h	1	BIOS drive number of the boot device.
 298.585 +
 298.586 +		Actually this byte is ignored for read. The boot code will
 298.587 +		write DL onto this byte. The BIOS or the caller should set
 298.588 +		drive number in DL.
 298.589 +
 298.590 +		We assume all BIOSes pass correct drive number in DL.
 298.591 +		Buggy BIOSes are not supported!!
 298.592 +
 298.593 +25h	1	Partition number of this partition on the boot drive.
 298.594 +
 298.595 +		0, 1, 2, 3 are primary partitions.
 298.596 +		4, 5, 6, ... are logical partitions in the extended partition.
 298.597 +
 298.598 +		0xff is for whole drive. So for floppies, it should be 0xff.
 298.599 +
 298.600 +26h	2	inode size in bytes. (Notice! We use the formerly reserved
 298.601 +		word here for inode size!)
 298.602 +
 298.603 +28h	4	Number of inodes per group.
 298.604 +
 298.605 +		Normally a 1.44M floppy has only one group, and the total
 298.606 +		number of inodes is 184. So the value should be	184 or
 298.607 +		greater.
 298.608 +
 298.609 +2Ch	4	The block number for group descriptors.
 298.610 +
 298.611 +		Valid values are 2 for 1024-byte blocks, and 1 otherwise.
 298.612 +
 298.613 +		The value here is equal to (s_first_data_block + 1).
 298.614 +
 298.615 +30h	1	code for "cld"(0xFC).
 298.616 +
 298.617 +31h	2	code for "xor ax,ax"(0x31, 0xC0).
 298.618 +
 298.619 +33h	1	code for "nop"(0x90) or "cwd"(0x99)
 298.620 +
 298.621 +34h	458	The rest of the machine code.
 298.622 +
 298.623 +1FEh	2	Boot Signature AA55h.
 298.624 +
 298.625 +
 298.626 +2. FAT12/FAT16 Boot Sector/Boot Record Layout (for loading grldr)
 298.627 +------------------------------------------------------------------------------
 298.628 +A FAT12/16 volume can be GRUB-bootable. Copy grldr and an optional menu.lst to
 298.629 +the root dir of the FAT12/16 volume, and build the boot sector based on the
 298.630 +fourth sector of grldr(some fields need to be changed as detailed in the
 298.631 +following table). And then the FAT12/16 volume is GRUB-bootable.
 298.632 +
 298.633 +Update:	bootlace.com is a DOS/Linux utility that can install the GRLDR boot
 298.634 +record onto the boot sector of an FAT12/16 volume.
 298.635 +
 298.636 +Offset	Length	Description
 298.637 +======	======	==============================================================
 298.638 +00h	2	Machine code for short jump over the data.
 298.639 +
 298.640 +02h	1	LBA indicator. Valid values are 0x90 for CHS mode, or 0x0e for
 298.641 +		LBA mode.
 298.642 +
 298.643 +		If the BIOS int13 supports LBA, this byte can be safely set to
 298.644 +		0x0e.
 298.645 +
 298.646 +		Some USB BIOSes might have bugs when using CHS mode, so the
 298.647 +		format program should set this byte to 0x0e. It seems that
 298.648 +		(generally) all USB BIOSes have LBA support.
 298.649 +
 298.650 +		If the format program does not know whether the BIOS has LBA
 298.651 +		support, it may operate this way:
 298.652 +
 298.653 +		if (partition_start + total_sectors_in_partition) exceeds the
 298.654 +		CHS addressing ability(especially when it is greater than
 298.655 +		1024*256*63), the caller should set this byte to 0x0e,
 298.656 +		otherwise, set to 0x90.
 298.657 +
 298.658 +		Update: this byte of LBA indicator is ignored. The boot
 298.659 +		record can probe the LBA support of BIOS.
 298.660 +
 298.661 +		Update(2021-07-31): Though GRLDR won't use this LBA-indicator
 298.662 +		byte, Windows 98 uses it. Usually this byte should be 0x90 for
 298.663 +		CHS mode(especially for floppies). If this byte is not set
 298.664 +		properly, Windows 98 will not recognize the floppy or
 298.665 +		partition. This problem was reported by neiljoy. Many thanks!
 298.666 +
 298.667 +03h	8	OEM name string (of OS which formatted the disk).
 298.668 +
 298.669 +0Bh	2	Bytes per sector. Must be 512.
 298.670 +
 298.671 +0Dh	1	Sectors per cluster. Valid values are 1, 2, 4, 8, 16, 32, 64
 298.672 +		and 128. But a cluster size larger than 32K should not occur.
 298.673 +
 298.674 +0Eh	2	Reserved sectors(number of sectors before the first FAT,
 298.675 +		including the boot sector), usually 1.
 298.676 +
 298.677 +10h	1	Number of FATs(nearly always 2).
 298.678 +
 298.679 +11h	2	Maximum number of root directory entries.
 298.680 +
 298.681 +13h	2	Total number of sectors (for small disks only, if the disk is
 298.682 +		too big this is set to 0 and offset 20h is used instead).
 298.683 +
 298.684 +15h	1	Media descriptor byte, pretty meaningless now (see below).
 298.685 +
 298.686 +16h	2	Sectors per FAT.
 298.687 +
 298.688 +18h	2	Sectors per track.
 298.689 +
 298.690 +1Ah	2	Total number of heads/sides.
 298.691 +
 298.692 +1Ch	4	Number of hidden sectors (those preceding the boot sector).
 298.693 +
 298.694 +		Also referred to as the starting sector of the partition.
 298.695 +
 298.696 +		For floppies, it should be 0.
 298.697 +
 298.698 +20h	4	Total number of sectors for large disks.
 298.699 +
 298.700 +24h	1	BIOS drive number of the boot device.
 298.701 +
 298.702 +		Actually this byte is ignored for read. The boot code will
 298.703 +		write DL onto this byte. The BIOS or the caller should set
 298.704 +		drive number in DL.
 298.705 +
 298.706 +		We assume all BIOSes pass correct drive number in DL.
 298.707 +		Buggy BIOSes are not supported!!
 298.708 +
 298.709 +25h	1	Partition number of this filesystem in the boot drive.
 298.710 +
 298.711 +		This byte is ignored for read. The boot code will write
 298.712 +		partition number onto this byte. See offset 41h below.
 298.713 +
 298.714 +26h	1	Signature (must be 28h or 29h to be recognised by NT).
 298.715 +
 298.716 +27h	4	Volume serial number.
 298.717 +
 298.718 +2Bh	11	Volume label.
 298.719 +
 298.720 +36h	8	File system ID. "FAT12   ", "FAT16   " or "FAT     ".
 298.721 +
 298.722 +3Eh	1	code for "cli".
 298.723 +
 298.724 +3Fh	1	code for "cld".
 298.725 +
 298.726 +40h	1	code for "mov dh, imm8".
 298.727 +
 298.728 +41h	1	Partition number of this partition on the boot drive.
 298.729 +
 298.730 +		0, 1, 2, 3 are primary partitions.
 298.731 +		4, 5, 6, ... are logical partitions in the extended partition.
 298.732 +
 298.733 +		0xff is for whole drive. So for floppies, it should be 0xff.
 298.734 +
 298.735 +42h	442	The rest of the machine code.
 298.736 +
 298.737 +1FCh	4	Boot Signature AA550000h. (Win9x uses 4 bytes as magic value)
 298.738 +
 298.739 +
 298.740 +3. FAT32 Boot Sector/Boot Record Layout (for loading grldr)
 298.741 +------------------------------------------------------------------------------
 298.742 +A FAT32 volume can be GRUB-bootable. Copy grldr and an optional menu.lst to
 298.743 +the root dir of the FAT32 volume, and build the boot sector based on the
 298.744 +third sector of grldr(some fields need to be changed as detailed in the
 298.745 +following table). And then the FAT32 volume is GRUB-bootable.
 298.746 +
 298.747 +Update:	bootlace.com is a DOS/Linux utility that can install the GRLDR boot
 298.748 +record onto the boot sector of an FAT32 volume.
 298.749 +
 298.750 +Offset	Length	Description
 298.751 +======	======	==============================================================
 298.752 +00h	2	Machine code for short jump over the data.
 298.753 +
 298.754 +02h	1	LBA indicator. Valid values are 0x90 for CHS mode, or 0x0e for
 298.755 +		LBA mode.
 298.756 +
 298.757 +		If the BIOS int13 supports LBA, this byte can be safely set to
 298.758 +		0x0e.
 298.759 +
 298.760 +		Some USB BIOSes might have bugs when using CHS mode, so the
 298.761 +		format program should set this byte to 0x0e. It seems that
 298.762 +		(generally) all USB BIOSes have LBA support.
 298.763 +
 298.764 +		If the format program does not know whether the BIOS has LBA
 298.765 +		support, it may operate this way:
 298.766 +
 298.767 +		if (partition_start + total_sectors_in_partition) exceeds the
 298.768 +		CHS addressing ability(especially when it is greater than
 298.769 +		1024*256*63), the caller should set this byte to 0x0e,
 298.770 +		otherwise, set to 0x90.
 298.771 +
 298.772 +		Update: this byte of LBA indicator is ignored. The boot
 298.773 +		record can probe the LBA support of BIOS.
 298.774 +
 298.775 +		Update(2021-07-31): Though GRLDR won't use this LBA-indicator
 298.776 +		byte, Windows 98 uses it. Usually this byte should be 0x90 for
 298.777 +		CHS mode(especially for floppies). If this byte is not set
 298.778 +		properly, Windows 98 will not recognize the floppy or
 298.779 +		partition. This problem was reported by neiljoy. Many thanks!
 298.780 +
 298.781 +03h	8	OEM name string (of OS which formatted the disk).
 298.782 +
 298.783 +0Bh	2	Bytes per sector. Must be 512.
 298.784 +
 298.785 +0Dh	1	Sectors per cluster. Valid values are 1, 2, 4, 8, 16, 32, 64
 298.786 +		and 128. But a cluster size larger than 32K should not occur.
 298.787 +
 298.788 +0Eh	2	Reserved sectors(number of sectors before the first FAT,
 298.789 +		including the boot sector), usually 1.
 298.790 +
 298.791 +10h	1	Number of FATs(nearly always 2).
 298.792 +
 298.793 +11h	2	(Maximum number of root directory entries)Must be 0.
 298.794 +
 298.795 +13h	2	(Total number of sectors for small disks only)Must be 0.
 298.796 +
 298.797 +15h	1	Media descriptor byte, pretty meaningless now (see below).
 298.798 +
 298.799 +16h	2	(Sectors per FAT)Must be 0.
 298.800 +
 298.801 +18h	2	Sectors per track.
 298.802 +
 298.803 +1Ah	2	Total number of heads/sides.
 298.804 +
 298.805 +1Ch	4	Number of hidden sectors (those preceding the boot sector).
 298.806 +
 298.807 +		Also referred to as the starting sector of the partition.
 298.808 +
 298.809 +		For floppies, it should be 0.
 298.810 +
 298.811 +20h	4	Total number of sectors for large disks.
 298.812 +
 298.813 +24h	4	FAT32 sectors per FAT.
 298.814 +
 298.815 +28h	2	If bit 7 is clear then all FATs are updated, otherwise bits
 298.816 +		0-3 give the current active FAT, all other bits are reserved.
 298.817 +
 298.818 +2Ah	2	High byte is major revision number, low byte is minor revision
 298.819 +		number, currently both are 0.
 298.820 +
 298.821 +2Ch	4	Root directory starting cluster.
 298.822 +
 298.823 +30h	2	File system information sector.
 298.824 +
 298.825 +32h	2	If non-zero this gives the sector which holds a copy of the
 298.826 +		boot record, usually 6.
 298.827 +
 298.828 +34h	12	Reserved, set to 0.
 298.829 +
 298.830 +40h	1	BIOS drive number of the boot device.
 298.831 +
 298.832 +		80h is first HDD, 00h is first FDD.
 298.833 +
 298.834 +		Actually this byte is ignored for read. The boot code will
 298.835 +		write DL onto this byte. The BIOS or the caller should set
 298.836 +		drive number in DL.
 298.837 +
 298.838 +		We assume all BIOSes pass correct drive number in DL.
 298.839 +		Buggy BIOSes are not supported!!
 298.840 +
 298.841 +41h	1	Partition number of this filesystem in the boot drive.
 298.842 +
 298.843 +		This byte is ignored for read. The boot code will write
 298.844 +		partition number onto this byte. See offset 5Dh below.
 298.845 +
 298.846 +42h	1	Signature (must be 28h or 29h to be recognised by NT).
 298.847 +
 298.848 +43h	4	Volume serial number.
 298.849 +
 298.850 +47h	11	Volume label.
 298.851 +
 298.852 +52h	8	File system ID. "FAT32   ".
 298.853 +
 298.854 +5Ah	1	opcode for "cli".
 298.855 +
 298.856 +5Bh	1	opcode for "cld".
 298.857 +
 298.858 +5Ch	1	opcode for "mov dh, imm8".
 298.859 +
 298.860 +5Dh	1	Partition number of this partition on the boot drive.
 298.861 +
 298.862 +		0, 1, 2, 3 are primary partitions.
 298.863 +		4, 5, 6, ... are logical partitions in the extended partition.
 298.864 +
 298.865 +		0xff is for whole drive. So for floppies, it should be 0xff.
 298.866 +
 298.867 +5Eh	414	The rest of the machine code.
 298.868 +
 298.869 +1FCh	4	Boot Signature AA550000h. (Win9x uses 4 bytes as magic value)
 298.870 +
 298.871 +
 298.872 +4. NTFS Boot Sector/Boot Record Layout (for loading grldr)
 298.873 +------------------------------------------------------------------------------
 298.874 +An NTFS volume can be GRUB-bootable. Copy grldr and an optional menu.lst to
 298.875 +the root dir of the NTFS volume, and build the boot sector based on the
 298.876 +6th-9th sectors of grldr(some fields need to be changed as detailed in the
 298.877 +following table). And then the NTFS volume is GRUB-bootable.
 298.878 +
 298.879 +Update:	bootlace.com is a DOS/Linux utility that can install the GRLDR boot
 298.880 +record onto the leading 4 sectors of an NTFS volume.
 298.881 +
 298.882 +Offset	Length	Description
 298.883 +======	======	==============================================================
 298.884 +00h	2	Machine code for short jump over the data.
 298.885 +
 298.886 +02h	1	LBA indicator. Valid values are 0x90 for CHS mode, or 0x0e for
 298.887 +		LBA mode.
 298.888 +
 298.889 +		If the BIOS int13 supports LBA, this byte can be safely set to
 298.890 +		0x0e.
 298.891 +
 298.892 +		Some USB BIOSes might have bugs when using CHS mode, so the
 298.893 +		format program should set this byte to 0x0e. It seems that
 298.894 +		(generally) all USB BIOSes have LBA support.
 298.895 +
 298.896 +		If the format program does not know whether the BIOS has LBA
 298.897 +		support, it may operate this way:
 298.898 +
 298.899 +		if (partition_start + total_sectors_in_partition) exceeds the
 298.900 +		CHS addressing ability(especially when it is greater than
 298.901 +		1024*256*63), the caller should set this byte to 0x0e,
 298.902 +		otherwise, set to 0x90.
 298.903 +
 298.904 +		Update: this byte of LBA indicator is ignored. The boot
 298.905 +		record can probe the LBA support of BIOS.
 298.906 +
 298.907 +		Update(2021-07-31): Though GRLDR won't use this LBA-indicator
 298.908 +		byte, Windows 98 uses it. Usually this byte should be 0x90 for
 298.909 +		CHS mode(especially for floppies). If this byte is not set
 298.910 +		properly, Windows 98 will not recognize the floppy or
 298.911 +		partition. This problem was reported by neiljoy. Many thanks!
 298.912 +
 298.913 +03h	8	OEM name string (of OS which formatted the disk).
 298.914 +
 298.915 +0Bh	2	Bytes per sector. Must be 512.
 298.916 +
 298.917 +0Dh	1	Sectors per cluster. Valid values are 1, 2, 4, 8, 16, 32, 64
 298.918 +		and 128. But a cluster size larger than 32K should not occur.
 298.919 +
 298.920 +0Eh	2	(Reserved sectors)Unused.
 298.921 +
 298.922 +10h	1	(Number of FATs)Must be 0.
 298.923 +
 298.924 +11h	2	(Maximum number of root directory entries)Must be 0.
 298.925 +
 298.926 +13h	2	(Total number of sectors for small disks only)Must be 0.
 298.927 +
 298.928 +15h	1	Media descriptor byte, pretty meaningless now (see below).
 298.929 +
 298.930 +16h	2	(Sectors per FAT)Must be 0.
 298.931 +
 298.932 +18h	2	Sectors per track.
 298.933 +
 298.934 +1Ah	2	Total number of heads/sides.
 298.935 +
 298.936 +1Ch	4	Number of hidden sectors (those preceding the boot sector).
 298.937 +
 298.938 +		Also referred to as the starting sector of the partition.
 298.939 +
 298.940 +		For floppies, it should be 0.
 298.941 +
 298.942 +20h	4	(Total number of sectors for large disks)Must be 0.
 298.943 +
 298.944 +24h	4	(FAT32 sectors per FAT) - Usually 80 00 80 00, A value of
 298.945 +		80 00 00 00 has been seen on a USB thumb drive which is
 298.946 +		formatted with NTFS under Windows XP. Note this is removable
 298.947 +		media and is not partitioned, the drive as a whole is NTFS
 298.948 +		formatted.
 298.949 +
 298.950 +28h	8	Number of sectors in the volume.
 298.951 +
 298.952 +30h	8	LCN of VCN 0 of the $MFT.
 298.953 +
 298.954 +38h	8	LCN of VCN 0 of the $MFTMirr.
 298.955 +
 298.956 +40h	4	Clusters per MFT Record.
 298.957 +
 298.958 +44h	4	Clusters per Index Record.
 298.959 +
 298.960 +48h	8	Volume serial number.
 298.961 +
 298.962 +50h	4	Checksum, usually 0.
 298.963 +
 298.964 +54h	1	opcode for "cli".
 298.965 +
 298.966 +55h	1	opcode for "cld".
 298.967 +
 298.968 +56h	1	opcode for "mov dh, imm8".
 298.969 +
 298.970 +57h	1	Partition number of this partition on the boot drive.
 298.971 +
 298.972 +		0, 1, 2, 3 are primary partitions.
 298.973 +		4, 5, 6, ... are logical partitions in the extended partition.
 298.974 +
 298.975 +		0xff is for whole drive. So for floppies, it should be 0xff.
 298.976 +
 298.977 +58h	420	The rest of the machine code in the first sector.
 298.978 +
 298.979 +1FCh	4	Boot Signature AA550000h. (Win9x uses 4 bytes as magic value)
 298.980 +
 298.981 +200h	1536	The rest of the machine code in the last 3 sectors.
 298.982 +
 298.983 +------------------------------------------------------------------------------
 298.984 +
 298.985 +Appendix A: File System Information Sector of FAT32(not used by grldr)
 298.986 +
 298.987 +Offset	Length	Description
 298.988 +======	======	==============================================================
 298.989 +0h	4	Leading Signature 41615252h.
 298.990 +
 298.991 +4h	480	Reserved, set to 0.
 298.992 +
 298.993 +1E4h	4	FSI structure signature 61417272h.
 298.994 +
 298.995 +1E8h	4	Contains the last known count of free clusters, if this is
 298.996 +		equal to FFFFFFFFh, then the count is unknown.
 298.997 +
 298.998 +1ECh	4	Cluster number at which you should begin a search for a free
 298.999 +		cluster, if this is equal to FFFFFFFFh then the field has not
298.1000 +		been set.
298.1001 +
298.1002 +1F0h	12	Reserved, set to 0.
298.1003 +
298.1004 +1FCh	4	Trailing Signature AA550000h.
298.1005 +
298.1006 +------------------------------------------------------------------------------
298.1007 +
298.1008 +Appendix B: Media Descriptor Byte(not used by grldr)
298.1009 +
298.1010 +The Media descriptor byte is meaningless because of the duplications, F0h for
298.1011 +example.
298.1012 +
298.1013 +Byte	Type of disk	Sectors	Heads	Tracks	Capacity
298.1014 +----	------------	-------	-----	------	--------
298.1015 +FFh	5 1/4"		8	2	40	320KB
298.1016 +FEh	5 1/4"		8	1	40	160KB
298.1017 +FDh	5 1/4"		9	2	40	360KB
298.1018 +FCh	5 1/4"		9	1	40	180KB
298.1019 +FBh	both		9	2	80	640KB
298.1020 +FAh	both		9	1	80	320KB
298.1021 +F9h	5 1/4"		15	2	80	1200KB
298.1022 +F9h	3 1/2"		9	2	80	720KB
298.1023 +F0h	3 1/2"		18 	2	80	1440KB
298.1024 +F0h	3 1/2"		36 	2	80	2880KB
298.1025 +F8h	hard disk	NA	NA	NA	NA
298.1026 +
298.1027 +******************************************************************************
298.1028 +***   grldr.mbr - How to write it to Master Boot Track of the hard disk    ***
298.1029 +******************************************************************************
298.1030 +
298.1031 +grldr.mbr contains code that can be used as Master Boot Record. The code is
298.1032 +responsible for searching all partitions for grldr and when found, loading it.
298.1033 +Currently supported partition types are: FAT12/FAT16/FAT32, NTFS, EXT2/EXT3.
298.1034 +Logical partitions in the extended partition are supported, provided that the
298.1035 +extended partition type is Microsoft-compatible. In fact, the Linux extended
298.1036 +partition type(0x85) is not fully tested for the search mechanism.
298.1037 +
298.1038 +How to write GRLDR.MBR to the Master Boot Track of a hard disk?
298.1039 +
298.1040 +First, read the Windows disk signature and partition information bytes
298.1041 +(72 bytes in total, from offset 0x01b8 to 0x01ff of the MBR sector), and put
298.1042 +them on the same range from offset 0x01b8 to 0x01ff of the beginning sector of
298.1043 +GRLDR.MBR.
298.1044 +
298.1045 +Optionally, if the MBR in the hard disk is a single sector MBR created by
298.1046 +Microsoft FDISK, it may be copied onto the second sector of GRLDR.MBR.
298.1047 +
298.1048 +The second sector of GRLDR.MBR is called "previous MBR". When GRLDR not found,
298.1049 +"previous MBR" will be started.
298.1050 +
298.1051 +No other steps needed, after all necessary changes stated above have been made,
298.1052 +now simply write GRLDR.MBR on to the Master Boot Track. That's all.
298.1053 +
298.1054 +Note: The Master Boot Track means the first track of the hard drive.
298.1055 +
298.1056 +Note: The bootstrap code of GRLDR.MBR only finds GRLDR file in the root dir of
298.1057 +a partition. You'd better place menu.lst file accompanying with GRLDR(i.e., in
298.1058 +the same root dir of the same partition as GRLDR).
298.1059 +
298.1060 +The filename "grldr" in an ext2 partition must be in lower case letters, and
298.1061 +the file type of grldr must be plain regular. Other types, e.g., a symbolic
298.1062 +link, won't work.
298.1063 +
298.1064 +Update:	bootlace.com is a DOS/Linux utility for installing grldr.mbr to MBR.
298.1065 +The whole grldr.mbr is embedded in the body of the bootlace.com utility, so
298.1066 +bootlace.com can be used independently. See below.
298.1067 +
298.1068 +******************************************************************************
298.1069 +***               grldr.mbr - Details about the control bytes              ***
298.1070 +******************************************************************************
298.1071 +
298.1072 +Six bytes can be used to control the boot process of GRLDR.MBR.
298.1073 +
298.1074 +Offset	Length	Description
298.1075 +======	======	==============================================================
298.1076 +02h	1	bit0=1: disable the search for GRLDR on floppy
298.1077 +		bit0=0: enable the search for GRLDR on floppy
298.1078 +
298.1079 +		bit1=1: disable the boot of PREVIOUS MBR with invalid
298.1080 +			partition table(usually an OS boot sector)
298.1081 +		bit1=0: enable the boot of PREVIOUS MBR with invalid
298.1082 +			partition table(usually an OS boot sector)
298.1083 +
298.1084 +		bit2=1: disable the feature of unconditional entrance to
298.1085 +			the command-line(See below `--duce')
298.1086 +		bit2=0: enable the feature of unconditional entrance to
298.1087 +			the command-line(See below `--duce')
298.1088 +
298.1089 +		bit3=1: disable geometry tune(See below `--chs-no-tune')
298.1090 +		bit3=0: enable geometry tune(See below `--chs-no-tune')
298.1091 +
298.1092 +		bit4 - bit6: reserved
298.1093 +
298.1094 +		bit7=1: try to boot PREVIOUS MBR after the search for GRLDR
298.1095 +		bit7=0: try to boot PREVIOUS MBR before the search for GRLDR
298.1096 +
298.1097 +03h	1	timeout in seconds to wait for a key press. 0xff stands for
298.1098 +		waiting all the time(endless).
298.1099 +
298.1100 +04h	2	hot-key code. high byte is scan code, low byte is ASCII code.
298.1101 +		the default value is 0x3920, which stands for the space bar.
298.1102 +		if this key is pressed, GRUB will be started prior to the boot
298.1103 +		of previous MBR. See "int 16 keyboard scan codes" below.
298.1104 +
298.1105 +06h	1	preferred boot drive number, 0xff for no-drive
298.1106 +07h	1	preferred partition number, 0xff for whole drive
298.1107 +
298.1108 +		if the preferred boot drive number is 0xff, the order of the
298.1109 +		search for GRLDR will be:
298.1110 +
298.1111 +			(hd0,0), (hd0,1), ..., (hd0,L),(L=max partition number) 
298.1112 +			(hd1,0), (hd1,1), ..., (hd1,M),(M=max partition number)
298.1113 +			... ... ... ... ... ... ... ... 
298.1114 +			(hdX,0), (hdX,1), ..., (hdX,N),(N=max partition number)
298.1115 +						       (X=max harddrive number)
298.1116 +			(fd0)
298.1117 +
298.1118 +		otherwise, if the preferred boot drive number is Y(not equal to
298.1119 +		0xff) and the preferred partition number is K, then the order of
298.1120 +		the search for GRLDR will be:
298.1121 +
298.1122 +			(Y) if K=0xff; or (Y,K) otherwise
298.1123 +			(hd0,0), (hd0,1), ..., (hd0,L),(L=max partition number) 
298.1124 +			(hd1,0), (hd1,1), ..., (hd1,M),(M=max partition number)
298.1125 +			... ... ... ... ... ... ... ... 
298.1126 +			(hdX,0), (hdX,1), ..., (hdX,N),(N=max partition number)
298.1127 +						       (X=max harddrive number)
298.1128 +			(fd0)
298.1129 +
298.1130 +		Note: if Y < 0x80, then (Y) is floppy, else (Y) is harddrive,
298.1131 +		      and (Y,K) is partition number K on harddrive (Y).
298.1132 +
298.1133 +
298.1134 +******************************************************************************
298.1135 +***        bootlace.com - Install GRLDR.MBR bootstrap code to MBR          ***
298.1136 +******************************************************************************
298.1137 +
298.1138 +BOOTLACE.COM installs GRLDR.MBR boot record to the MBR of a harddrive or of a
298.1139 +harddrive image file, or to the boot sector of a floppy or a floppy image.
298.1140 +
298.1141 +Usage:
298.1142 +
298.1143 +	bootlace.com  [OPTIONS]  DEVICE_OR_FILE
298.1144 +
298.1145 +OPTIONS:
298.1146 +
298.1147 +	--read-only		do everything except the actual write to the
298.1148 +				specified DEVICE_OR_FILE.
298.1149 +
298.1150 +	--restore-mbr		restore the previous mbr.
298.1151 +
298.1152 +	--mbr-no-bpb		do not copy BPB in the boot sector of the
298.1153 +				leading FAT partition to MBR.
298.1154 +
298.1155 +	--no-backup-mbr		do not copy the old MBR to the second sector of
298.1156 +				DEVICE_OR_FILE.
298.1157 +
298.1158 +	--force-backup-mbr	force the copy of old MBR to the second sector
298.1159 +				of DEVICE_OR_FILE.
298.1160 +
298.1161 +	--mbr-enable-floppy	enable the search for GRLDR on floppy.
298.1162 +
298.1163 +	--mbr-disable-floppy	disable the search for GRLDR on floppy.
298.1164 +
298.1165 +	--mbr-enable-osbr	enable the boot of PREVIOUS MBR with invalid
298.1166 +				partition table(usually an OS boot sector).
298.1167 +
298.1168 +	--mbr-disable-osbr	disable the boot of PREVIOUS MBR with invalid
298.1169 +				partition table(usually an OS boot sector).
298.1170 +
298.1171 +	--duce			disable the feature of unconditional entrance
298.1172 +	                        to the command-line.
298.1173 +
298.1174 +				Normally one can unconditionally get the
298.1175 +				command-line console by a keypress of `C',
298.1176 +				bypassing all config-files(including the
298.1177 +				preset-menu). This is a security hole. So we
298.1178 +				need this option to disable the feature.
298.1179 +
298.1180 +				DUCE is for Disable Unconditional Command-line
298.1181 +				Entrance.
298.1182 +
298.1183 +	--chs-no-tune		disable the feature of geometry tune.
298.1184 +
298.1185 +	--boot-prevmbr-first	try to boot PREVIOUS MBR before the search for
298.1186 +				GRLDR.
298.1187 +
298.1188 +	--boot-prevmbr-last	try to boot PREVIOUS MBR after the search for
298.1189 +				GRLDR.
298.1190 +
298.1191 +	--preferred-drive=D	preferred boot drive number, 0 <= D < 255.
298.1192 +
298.1193 +	--preferred-partition=P	preferred partition number, 0 <= P < 255.
298.1194 +
298.1195 +	--serial-number=SN	setup a new serial number for the hard drive.
298.1196 +				SN must be non-zero.
298.1197 +
298.1198 +	--time-out=T		wait T seconds before booting PREVIOUS MBR. if
298.1199 +				T is 0xff, wait forever. The default is 5.
298.1200 +	
298.1201 +	--hot-key=K		if the desired key K is pressed, start GRUB
298.1202 +				before booting PREVIOUS MBR. K is a word
298.1203 +				value, just as the value in AX register
298.1204 +				returned from int16/AH=1. The high byte is the
298.1205 +				scan code and the low byte is ASCII code. The
298.1206 +				default is 0x3920 for space bar. See "int 16
298.1207 +				keyboard scan codes" below.
298.1208 +
298.1209 +	--floppy		if DEVICE_OR_FILE is floppy, use this option.
298.1210 +
298.1211 +	--floppy=N		if DEVICE_OR_FILE is a partition on a hard
298.1212 +				drive, use this option. N is used to specify
298.1213 +				the partition number: 0,1,2 and 3 for the
298.1214 +				primary partitions, and 4,5,6,... for the
298.1215 +				logical partitions.
298.1216 +
298.1217 +	--sectors-per-track=S	specifies sectors per track for --floppy.
298.1218 +				1 <= S <= 63, default is 63.
298.1219 +
298.1220 +	--heads=H		specifies number of heads for --floppy.
298.1221 +				1 <= H <= 256, default is 255.
298.1222 +
298.1223 +	--start-sector=B	specifies hidden sectors for --floppy=N.
298.1224 +
298.1225 +	--total-sectors=C	specifies total sectors for --floppy.
298.1226 +				default is 0.
298.1227 +
298.1228 +	--lba			use lba mode for --floppy. If the floppy BIOS
298.1229 +				has LBA support, you can specify --lba here.
298.1230 +				It is assumed that all floppy BIOSes have CHS
298.1231 +				support. So you would rather specify --chs.
298.1232 +				If neither --chs nor --lba is specified, then
298.1233 +				the LBA indicator(i.e., the third byte of the
298.1234 +				boot sector) will not be touched.
298.1235 +
298.1236 +	--chs			use chs mode for --floppy. You should specify
298.1237 +				--chs if the floppy BIOS does not support LBA.
298.1238 +				We assume all floppy BIOSes have CHS support.
298.1239 +				So it is likely you want to specify --chs.
298.1240 +				If neither --chs nor --lba is specified, then
298.1241 +				the LBA indicator(i.e., the third byte of the
298.1242 +				boot sector) will not be touched.
298.1243 +
298.1244 +	--fat12			FAT12 is allowed to be installed for --floppy.
298.1245 +
298.1246 +	--fat16			FAT16 is allowed to be installed for --floppy.
298.1247 +
298.1248 +	--fat32			FAT32 is allowed to be installed for --floppy.
298.1249 +
298.1250 +	--vfat			FAT12/16/32 are allowed to be installed for
298.1251 +				--floppy.
298.1252 +
298.1253 +	--ntfs			NTFS is allowed to be installed for --floppy.
298.1254 +
298.1255 +	--ext2			EXT2 is allowed to be installed for --floppy.
298.1256 +
298.1257 +	--install-partition=I	Install the boot record onto the boot area of
298.1258 +				partition number I of the specified hard drive
298.1259 +				or harddrive image DEVICE_OR_FILE.
298.1260 +
298.1261 +DEVICE_OR_FILE:	Filename of the device or the image file. For DOS, a BIOS drive
298.1262 +number(hex 0xHH or decimal DDD) can be used to access the drive. BIOS drive
298.1263 +number 0 is for the first floppy, 1 is for the second floppy; 0x80 is for the
298.1264 +first hard drive, 0x81 is for the second hard drive, etc.
298.1265 +
298.1266 +Note: BOOTLACE.COM writes only the boot code to MBR. The boot code needs to
298.1267 +load GRLDR as the second(and last) stage of the GRUB boot process. Therefore
298.1268 +GRLDR should be copied to the root directory of one of the supported
298.1269 +partitions, either before or after a successful execution of BOOTLACE.COM.
298.1270 +Currently only partitions with filesystem type of FAT12, FAT16, FAT32, NTFS,
298.1271 +EXT2 or EXT3 are supported.
298.1272 +
298.1273 +Note 2: If DEVICE_OR_FILE is a harddisk device or a harddisk image file, it
298.1274 +must contain a valid partition table, otherwise, BOOTLACE.COM will fail. If
298.1275 +DEVICE_OR_FILE is a floppy device or a floppy image file, then it must contain
298.1276 +a supported filesystem(i.e., either of FAT12/FAT16/FAT32/NTFS/EXT2/EXT3).
298.1277 +
298.1278 +Note 3: If DEVICE_OR_FILE is a floppy device or a floppy image file, and it
298.1279 +was formated EXT2/EXT3, then you should specify --sectors-per-track and
298.1280 +--heads explicitly.
298.1281 +
298.1282 +
298.1283 +Important!! If you install GRLDR Boot Record to a floppy or a partition, the
298.1284 +floppy or partition will boot solely grldr, and your original
298.1285 +IO.SYS(DOS/Win9x/Me) and NTLDR(WinNT/2K/XP) will become unbootable. This is
298.1286 +because the original boot record of the floppy or partition was overwritten.
298.1287 +There is no such problem when installing GRLDR Boot Record onto the MBR.
298.1288 +Update: Some NTLDR/IO.SYS/KERNEL.SYS files can be directly chainloaded in the
298.1289 +latest GRUB4DOS.
298.1290 +
298.1291 +Tip: If the filename begins in a dash(-) or a digit, you may prefix a dirname
298.1292 +(./) or (.\) to it.
298.1293 +
298.1294 +Examples:
298.1295 +
298.1296 +	Installing GRLDR boot code to MBR under Linux:
298.1297 +
298.1298 +		bootlace.com  /dev/hda
298.1299 +
298.1300 +	Installing GRLDR boot code to MBR under DOS:
298.1301 +
298.1302 +		bootlace.com  0x80
298.1303 +
298.1304 +	Installing GRLDR boot code to a harddisk image under DOS or Linux:
298.1305 +
298.1306 +		bootlace.com  hd.img
298.1307 +
298.1308 +	Installing GRLDR boot code to floppy under Linux:
298.1309 +
298.1310 +		bootlace.com  --floppy --chs /dev/fd0
298.1311 +
298.1312 +	Installing GRLDR boot code to floppy under DOS:
298.1313 +
298.1314 +		bootlace.com  --floppy --chs 0x00
298.1315 +
298.1316 +	Installing GRLDR boot code to a floppy image under DOS or Linux:
298.1317 +
298.1318 +		bootlace.com  --floppy --chs floppy.img
298.1319 +
298.1320 +BOOTLACE.COM cannot function well under Windows NT/2000/XP/2003. It is expected
298.1321 +(and designed) to run under DOS/Win9x and Linux. Update: For image FILES,
298.1322 +bootlace.com function well under Windows NT/2000/XP/2003. For devices,
298.1323 +bootlace.com will not work under Windows NT/2000/XP/2003 because bootlace.com
298.1324 +is a DOS utility and Windows NT/2000/XP/2003 does not allow bootlace.com to
298.1325 +access devices.
298.1326 +
298.1327 +******************************************************************************
298.1328 +***        kexec-tools should be patched for the 1.101 release             ***
298.1329 +******************************************************************************
298.1330 +
298.1331 +The file kexec-tools-1.101-patch is a patch to the kexec-tools-1.101 release.
298.1332 +Kexec might fail to load grub.exe without this patch.
298.1333 +
298.1334 +The home page of kexec-tools is:
298.1335 +
298.1336 +	http://www.xmission.com/~ebiederm/files/kexec/
298.1337 +
298.1338 +Note: The Linux kernel should be KEXEC enabled before kexec can be run.
298.1339 +
298.1340 +			!! Important Update !!
298.1341 +
298.1342 +The patch `kexec-tools-1.101-patch' is not needed now and has been deleted.
298.1343 +Even worse, it fails in `kexec -l grub.exe --initrd=imgfile'. So please
298.1344 +do not use it any more.
298.1345 +
298.1346 +******************************************************************************
298.1347 +***           Direct transition to DOS/Win9x from within Linux             ***
298.1348 +******************************************************************************
298.1349 +
298.1350 +By using kexec, we can easily boot into DOS/Win9x from a running Linux system.
298.1351 +
298.1352 +If WIN98.IMG is a bootable hard-disk image, do as follows:
298.1353 +
298.1354 +kexec -l grub.exe --initrd=WIN98.IMG --command-line="--config-file=map (rd) (hd0); map --hook; chainloader (hd0)+1; rootnoverify (hd0)"
298.1355 +
298.1356 +kexec -e
298.1357 +
298.1358 +If DOS.IMG is a bootable floppy image, do this way:
298.1359 +
298.1360 +kexec -l grub.exe --initrd=DOS.IMG --command-line="--config-file=map (rd) (fd0); map --hook; chainloader (fd0)+1; rootnoverify (fd0)"
298.1361 +
298.1362 +kexec -e
298.1363 +
298.1364 +Note that in this manner, we can boot DOS/Win9x without using a real DOS/Win9x
298.1365 +disk. We need no FAT partition but an image file.
298.1366 +
298.1367 +We have noticed that Linux itself can act as a big boot manager by using kexec
298.1368 +and grub.exe. This may be convenient to developers who write installation or
298.1369 +bootstrap or initialization programs.
298.1370 +
298.1371 +Certainly, grub.exe and the bootable disk image can also be loaded by a running
298.1372 +GRUB or LILO or syslinux. Examples:
298.1373 +
298.1374 +1. Loaded by GRUB:
298.1375 +
298.1376 +	kernel (hd0,0)/grub.exe --config-file="map (rd) (fd0); map --hook; chainloader (fd0)+1; rootnoverify (fd0)"
298.1377 +	initrd (hd0,0)/DOS.IMG
298.1378 +	boot
298.1379 +
298.1380 +2. Loaded by LILO:
298.1381 +
298.1382 +	image=/boot/grub.exe
298.1383 +		label=grub.exe
298.1384 +		initrd=/boot/DOS.IMG
298.1385 +		append="--config-file=map (rd) (fd0); map --hook; chainloader (fd0)+1; rootnoverify (fd0)"
298.1386 +
298.1387 +3. Loaded by SYSLINUX:
298.1388 +
298.1389 +	label grub.exe
298.1390 +		kernel grub.exe
298.1391 +		append initrd=DOS.IMG --config-file="map (rd) (fd0); map --hook; chainloader (fd0)+1; rootnoverify (fd0)"
298.1392 +
298.1393 +Note: If the above `map (rd) (...)' failed, you may use `map (rd)+1 (...)'
298.1394 +instead and try again.
298.1395 +
298.1396 +******************************************************************************
298.1397 +***               Keyboard BIOS Scan Code/ASCII code tables                ***
298.1398 +******************************************************************************
298.1399 +
298.1400 +Keyboard bios scan code and ascii character code tables can be obtained from
298.1401 +the web by, for example, googling for "3920 372A 4A2D 4E2B 352F". Here are 2
298.1402 +main results:
298.1403 +
298.1404 +1. From "http://heim.ifi.uio.no/~stanisls/helppc/scan_codes.html":
298.1405 +
298.1406 +INT 16 - Keyboard Scan Codes
298.1407 +
298.1408 +       Key	 Normal    Shifted   w/Ctrl    w/Alt
298.1409 +
298.1410 +	A	  1E61	    1E41      1E01	1E00
298.1411 +	B	  3062	    3042      3002	3000
298.1412 +	C	  2E63	    2E43      2E03	2E00
298.1413 +	D	  2064	    2044      2004	2000
298.1414 +	E	  1265	    1245      1205	1200
298.1415 +	F	  2166	    2146      2106	2100
298.1416 +	G	  2267	    2247      2207	2200
298.1417 +	H	  2368	    2348      2308	2300
298.1418 +	I	  1769	    1749      1709	1700
298.1419 +	J	  246A	    244A      240A	2400
298.1420 +	K	  256B	    254B      250B	2500
298.1421 +	L	  266C	    264C      260C	2600
298.1422 +	M	  326D	    324D      320D	3200
298.1423 +	N	  316E	    314E      310E	3100
298.1424 +	O	  186F	    184F      180F	1800
298.1425 +	P	  1970	    1950      1910	1900
298.1426 +	Q	  1071	    1051      1011	1000
298.1427 +	R	  1372	    1352      1312	1300
298.1428 +	S	  1F73	    1F53      1F13	1F00
298.1429 +	T	  1474	    1454      1414	1400
298.1430 +	U	  1675	    1655      1615	1600
298.1431 +	V	  2F76	    2F56      2F16	2F00
298.1432 +	W	  1177	    1157      1117	1100
298.1433 +	X	  2D78	    2D58      2D18	2D00
298.1434 +	Y	  1579	    1559      1519	1500
298.1435 +	Z	  2C7A	    2C5A      2C1A	2C00
298.1436 +
298.1437 +       Key	 Normal    Shifted   w/Ctrl    w/Alt
298.1438 +
298.1439 +	1	  0231	    0221		7800
298.1440 +	2	  0332	    0340      0300	7900
298.1441 +	3	  0433	    0423		7A00
298.1442 +	4	  0534	    0524		7B00
298.1443 +	5	  0635	    0625		7C00
298.1444 +	6	  0736	    075E      071E	7D00
298.1445 +	7	  0837	    0826		7E00
298.1446 +	8	  0938	    092A		7F00
298.1447 +	9	  0A39	    0A28		8000
298.1448 +	0	  0B30	    0B29		8100
298.1449 +
298.1450 +       Key	 Normal    Shifted   w/Ctrl    w/Alt
298.1451 +
298.1452 +	-	  0C2D	    0C5F      0C1F	8200
298.1453 +	=	  0D3D	    0D2B		8300
298.1454 +	[	  1A5B	    1A7B      1A1B	1A00
298.1455 +	]	  1B5D	    1B7D      1B1D	1B00
298.1456 +	;	  273B	    273A		2700
298.1457 +	'	  2827	    2822
298.1458 +	`	  2960	    297E
298.1459 +	\	  2B5C	    2B7C      2B1C	2600 (same as Alt L)
298.1460 +	,	  332C	    333C
298.1461 +	.	  342E	    343E
298.1462 +	/	  352F	    353F
298.1463 +
298.1464 +	Key	 Normal    Shifted   w/Ctrl    w/Alt
298.1465 +
298.1466 +	F1	  3B00	    5400      5E00	6800
298.1467 +	F2	  3C00	    5500      5F00	6900
298.1468 +	F3	  3D00	    5600      6000	6A00
298.1469 +	F4	  3E00	    5700      6100	6B00
298.1470 +	F5	  3F00	    5800      6200	6C00
298.1471 +	F6	  4000	    5900      6300	6D00
298.1472 +	F7	  4100	    5A00      6400	6E00
298.1473 +	F8	  4200	    5B00      6500	6F00
298.1474 +	F9	  4300	    5C00      6600	7000
298.1475 +	F10	  4400	    5D00      6700	7100
298.1476 +	F11	  8500	    8700      8900	8B00
298.1477 +	F12	  8600	    8800      8A00	8C00
298.1478 +
298.1479 +	Key	    Normal    Shifted	w/Ctrl	  w/Alt
298.1480 +
298.1481 +	BackSpace    0E08      0E08	 0E7F	  0E00
298.1482 +	Del	     5300      532E	 9300	  A300
298.1483 +	Down Arrow   5000      5032	 9100	  A000
298.1484 +	End	     4F00      4F31	 7500	  9F00
298.1485 +	Enter	     1C0D      1C0D	 1C0A	  A600
298.1486 +	Esc	     011B      011B	 011B	  0100
298.1487 +	Home	     4700      4737	 7700	  9700
298.1488 +	Ins	     5200      5230	 9200	  A200
298.1489 +	Keypad 5		4C35	 8F00
298.1490 +	Keypad *     372A		 9600	  3700
298.1491 +	Keypad -     4A2D      4A2D	 8E00	  4A00
298.1492 +	Keypad +     4E2B      4E2B		  4E00
298.1493 +	Keypad /     352F      352F	 9500	  A400
298.1494 +	Left Arrow   4B00      4B34	 7300	  9B00
298.1495 +	PgDn	     5100      5133	 7600	  A100
298.1496 +	PgUp	     4900      4939	 8400	  9900
298.1497 +	PrtSc				 7200
298.1498 +	Right Arrow  4D00      4D36	 7400	  9D00
298.1499 +	SpaceBar     3920      3920	 3920	  3920
298.1500 +	Tab	     0F09      0F00	 9400	  A500
298.1501 +	Up Arrow     4800      4838	 8D00	  9800
298.1502 +
298.1503 +
298.1504 +- Some key combinations are not available on all systems.  The PS/2
298.1505 +  includes many that aren't available on the PC, XT and AT.
298.1506 +- To retrieve the character from a scan code logical AND the word
298.1507 +  with 0x00FF.
298.1508 +- see  INT 16  MAKE CODES
298.1509 +
298.1510 +
298.1511 +
298.1512 +2. From "http://www.hoppie.nl/ivan/keycodes.txt":
298.1513 +
298.1514 +
298.1515 +
298.1516 +     Keystroke                  Keypress code
298.1517 +--------------------------------------------------
298.1518 +     Esc                        011B
298.1519 +     1                          0231
298.1520 +     2                          0332
298.1521 +     3                          0433
298.1522 +     4                          0534
298.1523 +     5                          0635
298.1524 +     6                          0736
298.1525 +     7                          0837
298.1526 +     8                          0938
298.1527 +     9                          0A39
298.1528 +     0                          0B30
298.1529 +     -                          0C2D
298.1530 +     =                          0D3D
298.1531 +     Backspace                  0E08
298.1532 +     Tab                        0F09
298.1533 +     q                          1071
298.1534 +     w                          1177
298.1535 +     e                          1265
298.1536 +     r                          1372
298.1537 +     t                          1474
298.1538 +     y                          1579
298.1539 +     u                          1675
298.1540 +     i                          1769
298.1541 +     o                          186F
298.1542 +     p                          1970
298.1543 +     [                          1A5B
298.1544 +     ]                          1B5D
298.1545 +     Enter                      1C0D
298.1546 +     Ctrl                         **
298.1547 +     a                          1E61
298.1548 +     s                          1F73
298.1549 +     d                          2064
298.1550 +     f                          2166
298.1551 +     g                          2267
298.1552 +     h                          2368
298.1553 +     j                          246A
298.1554 +     k                          256B
298.1555 +     l                          266C
298.1556 +     ;                          273B
298.1557 +     '                          2827
298.1558 +     `                          2960
298.1559 +     Shift                        **
298.1560 +     \                          2B5C
298.1561 +     z                          2C7A
298.1562 +     x                          2D78
298.1563 +     c                          2E63
298.1564 +     v                          2F76
298.1565 +     b                          3062
298.1566 +     n                          316E
298.1567 +     m                          326D
298.1568 +     ,                          332C
298.1569 +     .                          342E
298.1570 +     /                          352F
298.1571 +     Gray *                     372A
298.1572 +     Alt                          **
298.1573 +     Space                      3920
298.1574 +     Caps Lock                    **
298.1575 +     F1                         3B00
298.1576 +     F2                         3C00
298.1577 +     F3                         3D00
298.1578 +     F4                         3E00
298.1579 +     F5                         3F00
298.1580 +     F6                         4000
298.1581 +     F7                         4100
298.1582 +     F8                         4200
298.1583 +     F9                         4300
298.1584 +     F10                        4400
298.1585 +     F11                        8500
298.1586 +     F12                        8600
298.1587 +     Num Lock                     **
298.1588 +     Scroll Lock                  **
298.1589 +     White Home                 4700
298.1590 +     White Up Arrow             4800
298.1591 +     White PgUp                 4900
298.1592 +     Gray -                     4A2D
298.1593 +     White Left Arrow           4B00
298.1594 +     Center Key                 4C00
298.1595 +     White Right Arrow          4D00
298.1596 +     Gray +                     4E2B
298.1597 +     White End                  4F00
298.1598 +     White Down Arrow           5000
298.1599 +     White PgDn                 5100
298.1600 +     White Ins                  5200
298.1601 +     White Del                  5300
298.1602 +     SysReq                       **
298.1603 +     Key 45 [1]                 565C
298.1604 +     Enter (number keypad)      1C0D
298.1605 +     Gray /                     352F
298.1606 +     PrtSc                        **
298.1607 +     Pause                        **
298.1608 +     Gray Home                  4700
298.1609 +     Gray Up Arrow              4800
298.1610 +     Gray Page Up               4900
298.1611 +     Gray Left Arrow            4B00
298.1612 +     Gray Right Arrow           4D00
298.1613 +     Gray End                   4F00
298.1614 +     Gray Down Arrow            5000
298.1615 +     Gray Page Down             5100
298.1616 +     Gray Insert                5200
298.1617 +     Gray Delete                5300
298.1618 +
298.1619 +     Shift Esc                  011B
298.1620 +     !                          0221
298.1621 +     @                          0340
298.1622 +     #                          0423
298.1623 +     $                          0524
298.1624 +     %                          0625
298.1625 +     ^                          075E
298.1626 +     &                          0826
298.1627 +     * (white)                  092A
298.1628 +     (                          0A28
298.1629 +     )                          0B29
298.1630 +     _                          0C5F
298.1631 +     + (white)                  0D2B
298.1632 +     Shift Backspace            0E08
298.1633 +     Shift Tab (Backtab)        0F00
298.1634 +     Q                          1051
298.1635 +     W                          1157
298.1636 +     E                          1245
298.1637 +     R                          1352
298.1638 +     T                          1454
298.1639 +     Y                          1559
298.1640 +     U                          1655
298.1641 +     I                          1749
298.1642 +     O                          184F
298.1643 +     P                          1950
298.1644 +     {                          1A7B
298.1645 +     }                          1B7D
298.1646 +     Shift Enter                1C0D
298.1647 +     Shift Ctrl                   **
298.1648 +     A                          1E41
298.1649 +     S                          1F53
298.1650 +     D                          2044
298.1651 +     F                          2146
298.1652 +     G                          2247
298.1653 +     H                          2348
298.1654 +     J                          244A
298.1655 +     K                          254B
298.1656 +     L                          264C
298.1657 +     :                          273A
298.1658 +     "                          2822
298.1659 +     ~                          297E
298.1660 +     |                          2B7C
298.1661 +     Z                          2C5A
298.1662 +     X                          2D58
298.1663 +     C                          2E43
298.1664 +     V                          2F56
298.1665 +     B                          3042
298.1666 +     N                          314E
298.1667 +     M                          324D
298.1668 +     <                          333C
298.1669 +     >                          343E
298.1670 +     ?                          353F
298.1671 +     Shift Gray *               372A
298.1672 +     Shift Alt                    **
298.1673 +     Shift Space                3920
298.1674 +     Shift Caps Lock              **
298.1675 +     Shift F1                   5400
298.1676 +     Shift F2                   5500
298.1677 +     Shift F3                   5600
298.1678 +     Shift F4                   5700
298.1679 +     Shift F5                   5800
298.1680 +     Shift F6                   5900
298.1681 +     Shift F7                   5A00
298.1682 +     Shift F8                   5B00
298.1683 +     Shift F9                   5C00
298.1684 +     Shift F10                  5D00
298.1685 +     Shift F11                  8700
298.1686 +     Shift F12                  8800
298.1687 +     Shift Num Lock               **
298.1688 +     Shift Scroll Lock            **
298.1689 +     Shift 7 (number pad)       4737
298.1690 +     Shift 8 (number pad)       4838
298.1691 +     Shift 9 (number pad)       4939
298.1692 +     Shift Gray -               4A2D
298.1693 +     Shift 4 (number pad)       4B34
298.1694 +     Shift 5 (number pad)       4C35
298.1695 +     Shift 6 (number pad)       4D36
298.1696 +     Shift Gray +               4E2B
298.1697 +     Shift 1 (number pad)       4F31
298.1698 +     Shift 2 (number pad)       5032
298.1699 +     Shift 3 (number pad)       5133
298.1700 +     Shift 0 (number pad)       5230
298.1701 +     Shift . (number pad)       532E
298.1702 +     Shift SysReq                 **
298.1703 +     Shift Key 45 [1]           567C
298.1704 +     Shift Enter (number pad)   1C0D
298.1705 +     Shift Gray /               352F
298.1706 +     Shift PrtSc                  **
298.1707 +     Shift Pause                  **
298.1708 +     Shift Gray Home            4700
298.1709 +     Shift Gray Up Arrow        4800
298.1710 +     Shift Gray Page Up         4900
298.1711 +     Shift Gray Left Arrow      4B00
298.1712 +     Shift Gray Right Arrow     4D00
298.1713 +     Shift Gray End             4F00
298.1714 +     Shift Gray Down Arrow      5000
298.1715 +     Shift Gray Page Down       5100
298.1716 +     Shift Gray Insert          5200
298.1717 +     Shift Gray Delete          5300
298.1718 +
298.1719 +     Ctrl Esc                   011B
298.1720 +     Ctrl 1                       --
298.1721 +     Ctrl 2 (NUL)               0300
298.1722 +     Ctrl 3                       --
298.1723 +     Ctrl 4                       --
298.1724 +     Ctrl 5                       --
298.1725 +     Ctrl 6 (RS)                071E
298.1726 +     Ctrl 7                       --
298.1727 +     Ctrl 8                       --
298.1728 +     Ctrl 9                       --
298.1729 +     Ctrl 0                       --
298.1730 +     Ctrl -                     0C1F
298.1731 +     Ctrl =                       --
298.1732 +     Ctrl Backspace (DEL)       0E7F
298.1733 +     Ctrl Tab                   9400
298.1734 +     Ctrl q (DC1)               1011
298.1735 +     Ctrl w (ETB)               1117
298.1736 +     Ctrl e (ENQ)               1205
298.1737 +     Ctrl r (DC2)               1312
298.1738 +     Ctrl t (DC4)               1414
298.1739 +     Ctrl y (EM)                1519
298.1740 +     Ctrl u (NAK)               1615
298.1741 +     Ctrl i (HT)                1709
298.1742 +     Ctrl o (SI)                180F
298.1743 +     Ctrl p (DEL)               1910
298.1744 +     Ctrl [ (ESC)               1A1B
298.1745 +     Ctrl ] (GS)                1B1D
298.1746 +     Ctrl Enter (LF)            1C0A
298.1747 +     Ctrl a (SOH)               1E01
298.1748 +     Ctrl s (DC3)               1F13
298.1749 +     Ctrl d (EOT)               2004
298.1750 +     Ctrl f (ACK)               2106
298.1751 +     Ctrl g (BEL)               2207
298.1752 +     Ctrl h (Backspace)         2308
298.1753 +     Ctrl j (LF)                240A
298.1754 +     Ctrl k (VT)                250B
298.1755 +     Ctrl l (FF)                260C
298.1756 +     Ctrl ;                       --
298.1757 +     Ctrl '                       --
298.1758 +     Ctrl `                       --
298.1759 +     Ctrl Shift                   **
298.1760 +     Ctrl \ (FS)                2B1C
298.1761 +     Ctrl z (SUB)               2C1A
298.1762 +     Ctrl x (CAN)               2D18
298.1763 +     Ctrl c (ETX)               2E03
298.1764 +     Ctrl v (SYN)               2F16
298.1765 +     Ctrl b (STX)               3002
298.1766 +     Ctrl n (SO)                310E
298.1767 +     Ctrl m (CR)                320D
298.1768 +     Ctrl ,                       --
298.1769 +     Ctrl .                       --
298.1770 +     Ctrl /                       --
298.1771 +     Ctrl Gray *                9600
298.1772 +     Ctrl Alt                     **
298.1773 +     Ctrl Space                 3920
298.1774 +     Ctrl Caps Lock               --
298.1775 +     Ctrl F1                    5E00
298.1776 +     Ctrl F2                    5F00
298.1777 +     Ctrl F3                    6000
298.1778 +     Ctrl F4                    6100
298.1779 +     Ctrl F5                    6200
298.1780 +     Ctrl F6                    6300
298.1781 +     Ctrl F7                    6400
298.1782 +     Ctrl F8                    6500
298.1783 +     Ctrl F9                    6600
298.1784 +     Ctrl F10                   6700
298.1785 +     Ctrl F11                   8900
298.1786 +     Ctrl F12                   8A00
298.1787 +     Ctrl Num Lock                --
298.1788 +     Ctrl Scroll Lock             --
298.1789 +     Ctrl White Home            7700
298.1790 +     Ctrl White Up Arrow        8D00
298.1791 +     Ctrl White PgUp            8400
298.1792 +     Ctrl Gray -                8E00
298.1793 +     Ctrl White Left Arrow      7300
298.1794 +     Ctrl 5 (number pad)        8F00
298.1795 +     Ctrl White Right Arrow     7400
298.1796 +     Ctrl Gray +                9000
298.1797 +     Ctrl White End             7500
298.1798 +     Ctrl White Down Arrow      9100
298.1799 +     Ctrl White PgDn            7600
298.1800 +     Ctrl White Ins             9200
298.1801 +     Ctrl White Del             9300
298.1802 +     Ctrl SysReq                  **
298.1803 +     Ctrl Key 45 [1]            --  
298.1804 +     Ctrl Enter (number pad)    1C0A
298.1805 +     Ctrl / (number pad)        9500
298.1806 +     Ctrl PrtSc                 7200
298.1807 +     Ctrl Break                 0000
298.1808 +     Ctrl Gray Home             7700
298.1809 +     Ctrl Gray Up Arrow         8DE0
298.1810 +     Ctrl Gray Page Up          8400
298.1811 +     Ctrl Gray Left Arrow       7300
298.1812 +     Ctrl Gray Right Arrow      7400
298.1813 +     Ctrl Gray End              7500
298.1814 +     Ctrl Gray Down Arrow       91E0
298.1815 +     Ctrl Gray Page Down        7600
298.1816 +     Ctrl Gray Insert           92E0
298.1817 +     Ctrl Gray Delete           93E0
298.1818 +
298.1819 +     Alt Esc                    0100
298.1820 +     Alt 1                      7800
298.1821 +     Alt 2                      7900
298.1822 +     Alt 3                      7A00
298.1823 +     Alt 4                      7B00
298.1824 +     Alt 5                      7C00
298.1825 +     Alt 6                      7D00
298.1826 +     Alt 7                      7E00
298.1827 +     Alt 8                      7F00
298.1828 +     Alt 9                      8000
298.1829 +     Alt 0                      8100
298.1830 +     Alt -                      8200
298.1831 +     Alt =                      8300
298.1832 +     Alt Backspace              0E00
298.1833 +     Alt Tab                    A500
298.1834 +     Alt q                      1000
298.1835 +     Alt w                      1100
298.1836 +     Alt e                      1200
298.1837 +     Alt r                      1300
298.1838 +     Alt t                      1400
298.1839 +     Alt y                      1500
298.1840 +     Alt u                      1600
298.1841 +     Alt i                      1700
298.1842 +     Alt o                      1800
298.1843 +     Alt p                      1900
298.1844 +     Alt [                      1A00
298.1845 +     Alt ]                      1B00
298.1846 +     Alt Enter                  1C00
298.1847 +     Alt Ctrl                     **
298.1848 +     Alt a                      1E00
298.1849 +     Alt s                      1F00
298.1850 +     Alt d                      2000
298.1851 +     Alt f                      2100
298.1852 +     Alt g                      2200
298.1853 +     Alt h                      2300
298.1854 +     Alt j                      2400
298.1855 +     Alt k                      2500
298.1856 +     Alt l                      2600
298.1857 +     Alt ;                      2700
298.1858 +     Alt '                      2800
298.1859 +     Alt `                      2900
298.1860 +     Alt Shift                    **
298.1861 +     Alt \                      2B00
298.1862 +     Alt z                      2C00
298.1863 +     Alt x                      2D00
298.1864 +     Alt c                      2E00
298.1865 +     Alt v                      2F00
298.1866 +     Alt b                      3000
298.1867 +     Alt n                      3100
298.1868 +     Alt m                      3200
298.1869 +     Alt ,                      3300
298.1870 +     Alt .                      3400
298.1871 +     Alt /                      3500
298.1872 +     Alt Gray *                 3700
298.1873 +     Alt Space                  3920
298.1874 +     Alt Caps Lock                **
298.1875 +     Alt F1                     6800
298.1876 +     Alt F2                     6900
298.1877 +     Alt F3                     6A00
298.1878 +     Alt F4                     6B00
298.1879 +     Alt F5                     6C00
298.1880 +     Alt F6                     6D00
298.1881 +     Alt F7                     6E00
298.1882 +     Alt F8                     6F00
298.1883 +     Alt F9                     7000
298.1884 +     Alt F10                    7100
298.1885 +     Alt F11                    8B00
298.1886 +     Alt F12                    8C00
298.1887 +     Alt Num Lock                 **
298.1888 +     Alt Scroll Lock              **
298.1889 +     Alt Gray -                 4A00
298.1890 +     Alt Gray +                 4E00
298.1891 +     Alt 7 (number pad)           # 
298.1892 +     Alt 8 (number pad)           # 
298.1893 +     Alt 9 (number pad)           # 
298.1894 +     Alt 4 (number pad)           # 
298.1895 +     Alt 5 (number pad)           # 
298.1896 +     Alt 6 (number pad)           # 
298.1897 +     Alt 1 (number pad)           # 
298.1898 +     Alt 2 (number pad)           # 
298.1899 +     Alt 3 (number pad)           # 
298.1900 +     Alt Del                      --
298.1901 +     Alt SysReq                   **
298.1902 +     Alt Key 45 [1]               --
298.1903 +     Alt Enter (number pad)     A600
298.1904 +     Alt / (number pad)         A400
298.1905 +     Alt PrtSc                    **
298.1906 +     Alt Pause                    **
298.1907 +     Alt Gray Home              9700
298.1908 +     Alt Gray Up Arrow          9800
298.1909 +     Alt Gray Page Up           9900
298.1910 +     Alt Gray Left Arrow        9B00
298.1911 +     Alt Gray Right Arrow       9D00
298.1912 +     Alt Gray End               9F00
298.1913 +     Alt Gray Down Arrow        A000
298.1914 +     Alt Gray Page Down         A100
298.1915 +     Alt Gray Insert            A200
298.1916 +     Alt Gray Delete            A300
298.1917 +
298.1918 +  -------------------------------------------------------------------------
298.1919 +
298.1920 +Footnotes
298.1921 +
298.1922 +        [1]   In the United States, the 101/102-key keyboard is shipped
298.1923 +              with 101 keys. Overseas versions have an additional key
298.1924 +              sandwiched between the left Shift key and the Z key. This
298.1925 +              additional key is identified by IBM (and in this table) as
298.1926 +              "Key 45."
298.1927 +
298.1928 +        [**]  Keys and key combinations marked ** are used by the ROM BIOS
298.1929 +              but do not put values into the keyboard buffer.
298.1930 +
298.1931 +        [--]  Keys and key combinations marked -- are ignored by the ROM
298.1932 +              BIOS.
298.1933 +
298.1934 +
298.1935 +
298.1936 +
298.1937 +3. From "http://heim.ifi.uio.no/~stanisls/helppc/make_codes.html":
298.1938 +
298.1939 +
298.1940 +INT 9 - Hardware Keyboard Make/Break Codes
298.1941 +
298.1942 +	Key	     Make  Break		Key    Make  Break
298.1943 +
298.1944 +	Backspace     0E    8E			F1	3B    BB
298.1945 +	Caps Lock     3A    BA			F2	3C    BC
298.1946 +	Enter	      1C    9C			F3	3D    BD
298.1947 +	Esc	      01    81			F4	3E    BE
298.1948 +	Left Alt      38    B8			F7	41    C1
298.1949 +	Left Ctrl     1D    9D			F5	3F    BF
298.1950 +	Left Shift    2A    AA			F6	40    C0
298.1951 +	Num Lock      45    C5			F8	42    C2
298.1952 +	Right Shift   36    B6			F9	43    C3
298.1953 +	Scroll Lock   46    C6			F10	44    C4
298.1954 +	Space	      39    B9			F11	57    D7
298.1955 +	Sys Req (AT)  54    D4			F12	58    D8
298.1956 +	Tab	      0F    8F
298.1957 +
298.1958 +		    Keypad Keys		       Make   Break
298.1959 +
298.1960 +		    Keypad 0  (Ins)		52	D2
298.1961 +		    Keypad 1  (End) 		4F	CF
298.1962 +		    Keypad 2  (Down arrow)	50	D0
298.1963 +		    Keypad 3  (PgDn)		51	D1
298.1964 +		    Keypad 4  (Left arrow)	4B	CB
298.1965 +		    Keypad 5			4C	CC
298.1966 +		    Keypad 6  (Right arrow)	4D	CD
298.1967 +		    Keypad 7  (Home)		47	C7
298.1968 +		    Keypad 8  (Up arrow)	48	C8
298.1969 +		    Keypad 9  (PgUp)		49	C9
298.1970 +		    Keypad .  (Del) 		53	D3
298.1971 +		    Keypad *  (PrtSc)		37	B7
298.1972 +		    Keypad -			4A	CA
298.1973 +		    Keypad +			4E	CE
298.1974 +
298.1975 +	       Key    Make  Break	       Key    Make  Break
298.1976 +
298.1977 +		A      1E    9E 		N      31    B1
298.1978 +		B      30    B0 		O      18    98
298.1979 +		C      2E    AE 		P      19    99
298.1980 +		D      20    A0 		Q      10    90
298.1981 +		E      12    92 		R      13    93
298.1982 +		F      21    A1 		S      1F    9F
298.1983 +		G      22    A2 		T      14    94
298.1984 +		H      23    A3 		U      16    96
298.1985 +		I      17    97 		V      2F    AF
298.1986 +		J      24    A4 		W      11    91
298.1987 +		K      25    A5 		X      2D    AD
298.1988 +		L      26    A6 		Y      15    95
298.1989 +		M      32    B2 		Z      2C    AC
298.1990 +
298.1991 +	       Key    Make  Break	       Key    Make  Break
298.1992 +
298.1993 +		1      02    82 		-      0C    8C
298.1994 +		2      03    83 		=      0D    8D
298.1995 +		3      04    84 		[      1A    9A
298.1996 +		4      05    85 		]      1B    9B
298.1997 +		5      06    86 		;      27    A7
298.1998 +		6      07    87 		'      28    A8
298.1999 +		7      08    88 		`      29    A9
298.2000 +		8      09    89 		\      2B    AB
298.2001 +		9      0A    8A 		,      33    B3
298.2002 +		0      0B    8B 		.      34    B4
298.2003 +						/      35    B5
298.2004 +
298.2005 +
298.2006 +Enhanced Keyboard Keys (101/102 keys)
298.2007 +
298.2008 +	Control Keys		  Make		  Break
298.2009 +
298.2010 +	Alt-PrtSc (SysReq)	  54		  D4
298.2011 +	Ctrl-PrtSc		  E0 37 	  E0 B7
298.2012 +	Enter			  E0 1C 	  E0 9C
298.2013 +	PrtSc			  E0 2A E0 37	  E0 B7 E0 AA
298.2014 +	Right Alt		  E0 38 	  E0 B8
298.2015 +	Right Ctrl		  E0 1D 	  E0 9D
298.2016 +	Shift-PrtSc		  E0 37 	  E0 B7
298.2017 +	/			  E0 35 	  E0 B5
298.2018 +	Pause			  E1 1D 45 E1 9D C5  (not typematic)
298.2019 +	Ctrl-Pause (Ctrl-Break)   E0 46 E0 C6	     (not typematic)
298.2020 +
298.2021 +	- Keys marked as "not typematic" generate one stream of bytes
298.2022 +	  without corresponding break scan code bytes (actually the
298.2023 +	  break codes are part of the make code).
298.2024 +
298.2025 +
298.2026 +			Normal Mode or
298.2027 +			Shift w/Numlock
298.2028 +	Key		 Make	 Break	   |----- Numlock on ------.
298.2029 +					      Make	    Break
298.2030 +	Del		 E0 53	 E0 D3	   E0 2A E0 53	 E0 D3 E0 AA
298.2031 +	Down arrow	 E0 50	 E0 D0	   E0 2A E0 50	 E0 D0 E0 AA
298.2032 +	End		 E0 4F	 E0 CF	   E0 2A E0 4F	 E0 CF E0 AA
298.2033 +	Home		 E0 47	 E0 C7	   E0 2A E0 47	 E0 C7 E0 AA
298.2034 +	Ins		 E0 52	 E0 D2	   E0 2A E0 52	 E0 D2 E0 AA
298.2035 +	Left arrow	 E0 4B	 E0 CB	   E0 2A E0 4B	 E0 CB E0 AA
298.2036 +	PgDn		 E0 51	 E0 D1	   E0 2A E0 51	 E0 D1 E0 AA
298.2037 +	PgUp		 E0 49	 E0 C9	   E0 2A E0 49	 E0 C9 E0 AA
298.2038 +	Right arrow	 E0 4D	 E0 CD	   E0 2A E0 4D	 E0 CD E0 AA
298.2039 +	Up arrow	 E0 48	 E0 C8	   E0 2A E0 48	 E0 C8 E0 AA
298.2040 +
298.2041 +	Key	      |--Left Shift Pressed--.	  |--Right Shift Pressed--.
298.2042 +			 Make	       Break	      Make	    Break
298.2043 +	Del	      E0 AA E0 53   E0 D3 E0 2A    E0 B6 E0 53	 E0 D3 E0 36
298.2044 +	Down arrow    E0 AA E0 50   E0 D0 E0 2A    E0 B6 E0 50	 E0 D0 E0 36
298.2045 +	End	      E0 AA E0 4F   E0 CF E0 2A    E0 B6 E0 4F	 E0 CF E0 36
298.2046 +	Home	      E0 AA E0 47   E0 C7 E0 2A    E0 B6 E0 47	 E0 C7 E0 36
298.2047 +	Ins	      E0 AA E0 52   E0 D2 E0 2A    E0 B6 E0 52	 E0 D2 E0 36
298.2048 +	Left arrow    E0 AA E0 4B   E0 CB E0 2A    E0 B6 E0 4B	 E0 CB E0 36
298.2049 +	PgDn	      E0 AA E0 51   E0 D1 E0 2A    E0 B6 E0 51	 E0 D1 E0 36
298.2050 +	PgUp	      E0 AA E0 49   E0 C9 E0 2A    E0 B6 E0 49	 E0 C9 E0 36
298.2051 +	Right arrow   E0 AA E0 4D   E0 CD E0 2A    E0 B6 E0 4D	 E0 CD E0 36
298.2052 +	Up arrow      E0 AA E0 48   E0 C8 E0 2A    E0 B6 E0 48	 E0 C8 E0 36
298.2053 +	/	      E0 AA E0 35   E0 B5 E0 2A    E0 B6 E0 35	 E0 B5 E0 36
298.2054 +
298.2055 +
298.2056 +	- The PS/2 models have three make/break scan code sets.  The first
298.2057 +	  set matches the PC & XT make/break scan code set and is the one
298.2058 +	  listed here.	Scan code sets are selected by writing the value F0
298.2059 +	  to the keyboard via the 8042 (port 60h).  The following is a brief
298.2060 +	  description of the scan code sets (see the PS/2 Technical Reference
298.2061 +	  manuals for more information on scan code sets 2 and 3):
298.2062 +
298.2063 +	/  set 1, each key has a base scan code.  Some keys generate
298.2064 +	   extra scan codes to generate artificial shift states.  This
298.2065 +	   is similar to the standard scan code set used on the PC and XT.
298.2066 +	/  set 2, each key sends one make scan code and two break scan
298.2067 +	   codes bytes (F0 followed by the make code).	This scan code
298.2068 +	   set is available on the IBM AT also.
298.2069 +	/  set 3, each key sends one make scan code and two break scan
298.2070 +	   codes bytes (F0 followed by the make code) and no keys are
298.2071 +	   altered by Shift/Alt/Ctrl keys.
298.2072 +	/  typematic scan codes are the same as the make scan code
298.2073 +
298.2074 +	- Some Tandy 1000's do not handle Alt key combinations when multiple
298.2075 +	  shift keys are pressed.  The Alt-Shift-H combination loses the Alt.
298.2076 +	- extended keys like (F11, F12) can only be read with systems that
298.2077 +	  have extended keyboard BIOS support (or INT 9 extensions);  to
298.2078 +	  read these special keys on these systems INT 16,10 must be used
298.2079 +
298.2080 +
298.2081 +******************************************************************************
298.2082 +***                         GRLDR  Error messages                          ***
298.2083 +******************************************************************************
298.2084 +
298.2085 +1. Missing MBR-helper.
298.2086 +
298.2087 +	The helper function in the sectors that immediately follow the MBR is
298.2088 +	not present, or it has been erased by a virus or by Windows XP/Vista.
298.2089 +
298.2090 +	Run the bootlace.com utility to fix the problem.
298.2091 +
298.2092 +2. Buggy BIOS!
298.2093 +
298.2094 +	Your BIOS is too buggy. It even has no support for INT13/AH=8.
298.2095 +
298.2096 +	No solution except flashing your BIOS. Buggy BIOSes will encounter
298.2097 +	more and more problems with grub4dos in the future.
298.2098 +
298.2099 +3. This partition is NTFS but with unknown boot record. Please install
298.2100 +Microsoft NTFS boot sectors to this partition correctly, or create an
298.2101 +FAT12/16/32 partition and place the same copy of GRLDR and MENU.LST there.
298.2102 +
298.2103 +	The boot record was changed or erased by Microsoft Windows XP Service
298.2104 +	Pack 2.
298.2105 +
298.2106 +	You may install the old boot record introduced with the	original clean
298.2107 +	Windows 2K/XP. As another solution, you may create an FAT partition
298.2108 +	for your system, and copy GRLDR and your MENU.LST to its root dir.
298.2109 +
298.2110 +	While the startup code of grldr might fail to load GRLDR in NTFS
298.2111 +	partitions, it always successfully loads GRLDR in FAT partitions(and
298.2112 +	even in ext2/ext3 partitions).
298.2113 +
298.2114 +	Note that NTLDR only loads the startup code of grldr(i.e., the leading
298.2115 +	16 sectors of grldr), not the whole grldr file.
298.2116 +
298.2117 +	Thus, C:\GRLDR must exist(here C: can be NTFS), since it is used for
298.2118 +	BOOT.INI and NTLDR. If C: is NTFS, X:\GRLDR should exist as well,
298.2119 +	where X: stands for a certain FAT partition.
298.2120 +
298.2121 +
298.2122 +******************************************************************************
298.2123 +***                             Known BIOS bugs                            ***
298.2124 +******************************************************************************
298.2125 +
298.2126 +1. Some newer Dell machines have no int13/AH=43h support. You may encounter
298.2127 +	failure when trying to write-access an emulated disk.
298.2128 +
298.2129 +	Note: This bug is serious! The old "root+setup" installation method
298.2130 +	(in real mode grub environment) uses INT13 to write the first sector
298.2131 +	of stage2. It will fail for the buggy DELL machine when stage2 is
298.2132 +	accessed with LBA mode.
298.2133 +
298.2134 +2. Some buggy BIOSes won't boot bootable.iso(See above).(qemu can boot it fine)
298.2135 +
298.2136 +3. Some newer Dell machines violently destroyed the interrupt vectors for
298.2137 +	hardware IRQs and will hang the machine when running GRUB.EXE
298.2138 +	from DOS. You may try again with BADGRUB.EXE.
298.2139 +
298.2140 +4. Reports say some BIOSes will function abnormally after GRUB.EXE is started
298.2141 +	by kexec of Linux. Some machines reportedly hang. Some others
298.2142 +	reportedly cannot access USB drives.
298.2143 +
298.2144 +
298.2145 +******************************************************************************
298.2146 +***                             Known Problems                             ***
298.2147 +******************************************************************************
298.2148 +
298.2149 +1.	Running GRUB.EXE from a DOS box of Windows 9x/Me could hang the
298.2150 +	machine, especially for some systems with USB support. You may
298.2151 +	encounter the same problem when running GRUB.EXE through KEXEC under
298.2152 +	Linux.
298.2153 +
298.2154 +Note:	You don't have to run GRUB.EXE from protected mode of Win9x, which
298.2155 +	could hang the machine; Instead, you usually want to run GRUB.EXE
298.2156 +	after you have done a "Restart the computer in MS-DOS mode", which
298.2157 +	is safe enough.
298.2158 +
298.2159 +2.	The default chainloader action will keep A20 on. Some buggy DOS XMS
298.2160 +	memory managers could hang the machine. You may use the --disable-a20
298.2161 +	option in the chainloader line and try again. Anyway, you should avoid
298.2162 +	using those buggy memory managers.
298.2163 +
298.2164 +3.	THTF BIOS L4S5M Ver 1.1a(dated 2022-1-10) has a buggy int15 which
298.2165 +	causes hang at the boot of a multi boot kernel(memdisk for example).
298.2166 +
298.2167 +4.	A Chinese DOS system software, the TechWay SCS, will not work with
298.2168 +	newer versions of GRUB.EXE. In general, TSRs that take antitracking
298.2169 +	measures will not work with GRUB.EXE any more.
298.2170 +
298.2171 +
298.2172 +******************************************************************************
298.2173 +***        List of binary files and their corresponding source files       ***
298.2174 +******************************************************************************
298.2175 +
298.2176 +binary file	main source file	other included source or binary files
298.2177 +-------------   ----------------	-------------------------------------
298.2178 +
298.2179 +bootlace.com	bootlacestart.S		bootlace.inc, grldrstart.S
298.2180 +
298.2181 +grldr		grldrstart.S		pre_stage2(binary, See note below)
298.2182 +
298.2183 +grldr.mbr	mbrstart.S		grldrstart.S
298.2184 +
298.2185 +grub.exe	dosstart.S		pre_stage2(binary, See note below)
298.2186 +
298.2187 +hmload.com	hmloadstart.S
298.2188 +
298.2189 +-----------------------------------------------------------------------------
298.2190 +
298.2191 +Note: pre_stage2 is the main body of GNU GRUB and it is simply appended to
298.2192 +grldrstart/dosstart in binary format to form our grldr/grub.exe.
298.2193 +
298.2194 +Note: The GRUB file(WITHOUT .EXE suffix) is a static-linked ELF executable
298.2195 +program for Linux, normally called the GRUB Shell. The GRUB Shell is a boot-
298.2196 +manager, but not a boot-loader(the "boot" command won't work in GRUB Shell). 
298.2197 +GRUB.EXE(with KEXEC) can be used as a bootloader running directly under Linux.
298.2198 +
298.2199 +******************************************************************************
298.2200 +***             Memory Layout for Quiting to DOS from GRUB.EXE             ***
298.2201 +******************************************************************************
298.2202 +
298.2203 +The quit command is implemented to return to DOS in the instance that GRUB.EXE
298.2204 +is started off DOS.
298.2205 +
298.2206 +1. Before GRUB.EXE transfers control to pre_stage2, it will copy 640KB of
298.2207 +conventional memory to physical address 0x200000(i.e., 2MB), and write 4 long
298.2208 +integers immediately follows the backup copy of the conventional memory:
298.2209 +	At 0x2A0000:	0x50554B42, it is the "BKUP" signature.
298.2210 +
298.2211 +	At 0x2A0004:	Gate A20 status under DOS: non-zero means A20 on;
298.2212 +			zero means A20 off. Update: A20 always on, see below.
298.2213 +
298.2214 +	At 0x2A0008:	high word is boot-CS, low word is boot-IP. The quit
298.2215 +			command uses this entry point to return to DOS.
298.2216 +
298.2217 +	At 0x2A000C:	CheckSum: the sum of all long integers in the memory
298.2218 +			range from 0x200000 to 0x2A000F is 0.
298.2219 +
298.2220 +2. If the above memory structure is corrupted by a grub command, the quit
298.2221 +command will issue an error message and refuse to exit from grub.
298.2222 +
298.2223 +3. Because GRUB may corrupt extended memory, you should better avoid using
298.2224 +extended memory under DOS before running GRUB.EXE.
298.2225 +
298.2226 +4. Gate A20 will be enabled by GRUB.EXE. Hopefully this would hurt nothing.
298.2227 +
298.2228 +
298.2229 +******************************************************************************
298.2230 +***             Memory usage in conventional/low memory area               ***
298.2231 +******************************************************************************
298.2232 +
298.2233 +1. boot.c, fsys_reiserfs.c: 8K below 0x68000.
298.2234 +
298.2235 +2. fsys_ext2fs.c, fsys_minix.c: 1K below 0x68000.
298.2236 +
298.2237 +3. fsys_jfs.c: 4K + 256 bytes below 0x68000.
298.2238 +
298.2239 +4. fsys_reiserfs.c: 202 bytes at 0x600.
298.2240 +
298.2241 +5. fsys_xfs.c: 188 bytes at 0x600.
298.2242 +
298.2243 +6. fsys_xfs.c: (logical block size) bytes below 0x68000.
298.2244 +
298.2245 +7. geometry tune: 0x50000 - 0x5ffff.
298.2246 +
298.2247 +******************************************************************************
298.2248 +***                Command-line Length about GRUB.EXE                      ***
298.2249 +******************************************************************************
298.2250 +
298.2251 +GRUB.EXE now can be started in CONFIG.SYS with the **DEVICE** command:
298.2252 +
298.2253 +	DEVICE=grub.exe [--config-file="FILENAME_OR_COMMANDS"]
298.2254 +
298.2255 +1. If GRUB.EXE is invoked with DEVICE command and FILENAME_OR_COMMANDS is a
298.2256 +collection of some GRUB commands separated by semi-colon, then the length of
298.2257 +FILENAME_OR_COMMANDS can be nearly 4KB ----Supprise? But true!  MS-DOS 7+
298.2258 +even allows a much longer line, but 4KB seems enough for our use of GRUB.EXE.
298.2259 +This is very useful when we want to embed a big menu into the command line.
298.2260 +Note that GRLDR hasn't yet supported any command-line arguments.
298.2261 +
298.2262 +2. If GRUB.EXE is invoked with INSTALL command, the option length has a limit
298.2263 +of 80 characters(including the leading "--config-file=" part). An overflow may
298.2264 +hang up MS-DOS immediately.
298.2265 +
298.2266 +3. If GRUB.EXE is invoked with SHELL command, the option length has a limit of
298.2267 +126 characters(including the leading "--config-file=" part). Overflow won't
298.2268 +hang up MS-DOS, but the line will be cut short. This limit is the same as that
298.2269 +in the console-DOS-prompt or in a BAT file.
298.2270 +
298.2271 +4. The DOS editor EDIT does not allow to create a line of 4KB long. So use
298.2272 +another editor, for example, vi for Linux, please.
298.2273 +
298.2274 +5. The DEVICE=GRUB.EXE line can be used together with other DEVICE commands
298.2275 +such as DEVICE=HIMEM.SYS and DEVICE=EMM386.EXE. The GRUB.EXE line should
298.2276 +occur before the EMM386.EXE line in order to avoid the rejection by EMM386.
298.2277 +Update: Since 0.4.2, GRUB.EXE works well even after EMM386.EXE is loaded.
298.2278 +
298.2279 +6. In any case mentioned above, you can return back to DOS by quit command.
298.2280 +
298.2281 +7. Memory usage about command-line menu: The 4KB command-line menu starts at
298.2282 +physical address 0x0800 and ends at 0x17FF.
298.2283 +
298.2284 +******************************************************************************
298.2285 +***          New Syntax for the DEFAULT/SAVEDEFAULT Commands               ***
298.2286 +******************************************************************************
298.2287 +
298.2288 +In addition to the original usage of "default NUM" and "default saved", now
298.2289 +there is a new usage of "default FILE", like this:
298.2290 +
298.2291 +		default (hd0,0)/default
298.2292 +
298.2293 +Note that FILE must have a valid DEFAULT file format. A sample DEFAULT file
298.2294 +is included in the release. You may copy it to wherever you like, but you
298.2295 +should avoid modifying its content manually. The DEFAULT file may be used
298.2296 +in this way:
298.2297 +
298.2298 +(1) First, you should copy a default file with valid format to somewhere in
298.2299 +your operating system.
298.2300 +
298.2301 +(2) Secondly, you should use the "default FILE" command of GRUB to announce
298.2302 +the use of FILE as our new default file for being written by "savedefault".
298.2303 +
298.2304 +(3) Then, you may use "savedefault" command to save the desired entry number
298.2305 +into this new default file.
298.2306 +
298.2307 +(4) OK, at next boot, you may read the saved entry number by using the same
298.2308 +"default FILE" command as mentioned in above (2).
298.2309 +
298.2310 +And the SAVEDEFAULT command now accept an options `--wait=T', like this:
298.2311 +
298.2312 +		savedefault --wait=5
298.2313 +
298.2314 +If `--wait=T' is specified and T is non-zero, savedefault will prompt
298.2315 +the user with a message just before it writes to disk. The write operation
298.2316 +will be cancelled in T seconds if the `Y' key was not pressed.
298.2317 +
298.2318 +Here is a sample menu.lst file:
298.2319 +
298.2320 +#--------------------begin menu.lst---------------------------------------
298.2321 +color black/cyan yellow/cyan
298.2322 +timeout 30
298.2323 +default /default
298.2324 +
298.2325 +title find and load NTLDR of Windows NT/2K/XP
298.2326 +find --set-root /ntldr
298.2327 +chainloader /ntldr
298.2328 +savedefault --wait=2
298.2329 +
298.2330 +title find and load CMLDR, the Recovery Console of Windows NT/2K/XP
298.2331 +fallback 2
298.2332 +find --set-root /cmldr
298.2333 +chainloader /cmldr
298.2334 +#####################################################################
298.2335 +# write string "cmdcons" to memory 0000:7C03 in 2 steps:
298.2336 +#####################################################################
298.2337 +# step 1. Write 4 chars "cmdc" at 0000:7C03
298.2338 +write 0x7C03 0x63646D63
298.2339 +# step 2. Write 3 chars "ons" and an ending null at 0000:7C07
298.2340 +write 0x7C07 0x00736E6F
298.2341 +savedefault --wait=2
298.2342 +
298.2343 +title find and load IO.SYS of Windows 9x/Me
298.2344 +find --set-root /io.sys
298.2345 +chainloader /io.sys
298.2346 +savedefault --wait=2
298.2347 +
298.2348 +title floppy (fd0)
298.2349 +chainloader (fd0)+1
298.2350 +rootnoverify (fd0)
298.2351 +savedefault --wait=2
298.2352 +
298.2353 +title find and boot Linux with menu.lst already installed
298.2354 +find --set-root /sbin/init
298.2355 +savedefault --wait=2
298.2356 +configfile /boot/grub/menu.lst
298.2357 +
298.2358 +title find and boot Mandriva with menu.lst already installed
298.2359 +find --set-root /etc/mandriva-release
298.2360 +savedefault --wait=2
298.2361 +configfile /boot/grub/menu.lst
298.2362 +
298.2363 +title back to dos
298.2364 +savedefault --wait=2
298.2365 +quit
298.2366 +
298.2367 +title commandline
298.2368 +savedefault --wait=2
298.2369 +commandline
298.2370 +
298.2371 +title reboot
298.2372 +savedefault --wait=2
298.2373 +reboot
298.2374 +
298.2375 +title halt
298.2376 +savedefault --wait=2
298.2377 +halt
298.2378 +#--------------------end menu.lst---------------------------------------
298.2379 +
298.2380 +Note 1:	The file DEFAULT must exist and have a proper format as stated above.
298.2381 +	Or else, the default/savedefault commands won't function well.
298.2382 +
298.2383 +Note 2:	The file DEFAULT which is in the same dir as a certain MENU.LST file
298.2384 +	is called associated with the MENU.LST file.
298.2385 +
298.2386 +Note 3:	The associated DEFAULT file will take effect automatically if there
298.2387 +	are no `default' commands present.
298.2388 +
298.2389 +Note 4:	Just before a menu file gains control(e.g., it is the associated
298.2390 +	MENU.LST of a GRLDR file, or it was specified via
298.2391 +	`grub.exe --config-file=(DEVICE)/PATH/YOUR_MENU_FILE', or it was
298.2392 +	specified by the `configfile' command of grub), its associated
298.2393 +	DEFAULT file will be used if present, until an explicit `default'
298.2394 +	command is encountered.
298.2395 +
298.2396 +******************************************************************************
298.2397 +***                   The New `cdrom' Command Syntax                       ***
298.2398 +******************************************************************************
298.2399 +
298.2400 +1. Initialize the ATAPI CDROM devices:
298.2401 +
298.2402 +	grub> cdrom --init
298.2403 +
298.2404 +   This will display the number of atapi cdroms found: atapi_dev_count
298.2405 +
298.2406 +2. Stop the ATAPI CDROM devices:
298.2407 +
298.2408 +	grub> cdrom --stop
298.2409 +
298.2410 +   This will set atapi_dev_count to 0.
298.2411 +
298.2412 +3. Add IO ports for searching the atapi cdrom devices. For example:
298.2413 +
298.2414 +	grub> cdrom --add-io-ports=0x03F601F0
298.2415 +
298.2416 +After running `cdrom --init' and `map --hook', the cdroms can be accessed
298.2417 +through devices (cd0), (cd1), ...
298.2418 +
298.2419 +Note 1: If the system does not fully support the ATAPI CD-ROM specifications,
298.2420 +	you will encounter failure when trying to access the (cdX) devices.
298.2421 +
298.2422 +Note 2: After doing a `cdrom --stop', you should do a `map --unhook'. Of
298.2423 +	course you may `map --hook' again if there are mapped drives.
298.2424 +
298.2425 +Note 3: After adding IO ports, you should do a `map --unhook' followed by a
298.2426 +	`cdrom --init' and then followed by a `map --hook'.
298.2427 +
298.2428 +	By default, these ports are used for searching cdroms(so they needn't
298.2429 +	be added):
298.2430 +
298.2431 +		0x03F601F0, 0x03760170, 0x02F600F0,
298.2432 +		0x03860180, 0x6F006B00, 0x77007300.
298.2433 +
298.2434 +Note 4: The BIOS might have offered a cdrom interface. It would be (cd). After
298.2435 +	`cdrom --init' and `map --hook', we might have our (cd0), (cd1), ...
298.2436 +	available. It is likely that one of them could access the same media
298.2437 +	as the BIOS-offered (cd).
298.2438 +
298.2439 +Note 5: You may access the (cd) and (cdX)'es in the blocklist way. Example:
298.2440 +
298.2441 +		cat --hex (cd0)16+2
298.2442 +
298.2443 +	The cdrom sectors are big sectors with a size of 2048 bytes.
298.2444 +
298.2445 +Note 6:	The iso9660 filesystem driver has Rock-Ridge extension support, but
298.2446 +	has no Joliet extension support. So you may encounter failure when
298.2447 +	you attempt to read files on a Joliet CD.
298.2448 +
298.2449 +Note 7: The (cd) or (cdX)'es can be booted now. Examples:
298.2450 +
298.2451 +		chainloader (cd)
298.2452 +		boot
298.2453 +
298.2454 +		chainloader (cd0)
298.2455 +		boot
298.2456 +
298.2457 +		chainloader (cd1)
298.2458 +		boot
298.2459 +
298.2460 +	You should already have access to the CD sectors before you can
298.2461 +	chainload it.
298.2462 +
298.2463 +******************************************************************************
298.2464 +***                   About the New `setvbe' Command                       ***
298.2465 +******************************************************************************
298.2466 +
298.2467 +Gerardo Richarte contributed the `setvbe' code and the following comment:
298.2468 +
298.2469 +	New command is `setvbe', and can be used to change the video mode
298.2470 +	before executing the kernel.
298.2471 +
298.2472 +	For example, you can do
298.2473 +
298.2474 +		setvbe 1024x768x32
298.2475 +
298.2476 +	this will scan the list of available modes and set it, and
298.2477 +	automatically append a `video=' option to each subsequent kernel
298.2478 +	command-line. The appended `video=' option is like this:
298.2479 +
298.2480 +		video=1024x768x32@0xf0000000,4096
298.2481 +
298.2482 +	where 0xf0000000 is the video framebuffer address as reported by vbe,
298.2483 +	and 4096 is the size of a scanline in bytes (also as reported by vbe).
298.2484 +
298.2485 +	This is really useful if you want to give some graphics support to your
298.2486 +	OS, but you don't want to implement any video functionality other than
298.2487 +	writing a pixel to video memory.
298.2488 +
298.2489 +
298.2490 +******************************************************************************
298.2491 +***                   About the DOS utility `hmload'                       ***
298.2492 +******************************************************************************
298.2493 +
298.2494 +This program was written by John Cobb (Queen Mary, University of London).
298.2495 +
298.2496 +John Cobb's note:
298.2497 +
298.2498 +	To make use of the ram drive feature I wrote a program `hmload' to load
298.2499 +	an arbitrary file to an arbitrary address in high memory. The program
298.2500 +	is not very sophisticated and relies on XMS to turn on the A20 line.
298.2501 +	(Also one must be very careful to steer clear of any areas of memory
298.2502 +	already in use).
298.2503 +
298.2504 +	Under Linux we generated a disk image `dskimg' (with the kernel and
298.2505 +	Initrd and a partition table).
298.2506 +
298.2507 +	Using this our boot procedure looked something like this:
298.2508 +
298.2509 +	hmload -fdskimg -a128
298.2510 +	fixrb
298.2511 +	<unload network drivers>
298.2512 +	grub
298.2513 +
298.2514 +		map --ram-drive=0x81
298.2515 +		map --rd-base=0x8000000
298.2516 +		map --rd-size=0x400000
298.2517 +		root (rd,0)
298.2518 +		kernel /kernel root=/dev/ram0 rw ip=bootp ramdisk_size=32768 ...
298.2519 +		initrd /initrd
298.2520 +		boot
298.2521 +
298.2522 +See http://sysdocs.stu.qmul.ac.uk/sysdocs/Comment/GrubForDOS/ for details.
298.2523 +
298.2524 +Update 2007-12-05:
298.2525 +
298.2526 +	Now the MAP command can handle gzipped (rd) image. One can use this
298.2527 +	feature with the hmload utility. For example,
298.2528 +
298.2529 +	step 1. Load the gzipped image under DOS at a relatively low address:
298.2530 +
298.2531 +		hmload -fdskimg.gz -a16
298.2532 +
298.2533 +	step 2. Unload network drivers.
298.2534 +
298.2535 +	step 3. Run GRUB.EXE.
298.2536 +
298.2537 +	step 4. At the grub prompt, run these commands:
298.2538 +
298.2539 +		map --rd-base=0x1000000	# set rd-base address to be 16M
298.2540 +		map --rd-size=<the accurate size of dskimg.gz in bytes>
298.2541 +		map (rd)+1 (hd0)	# This will decompress (rd) and place
298.2542 +					# the decompressed image at the top end
298.2543 +					# of the extended memory. The (rd)+1
298.2544 +					# here has special meaning and stands
298.2545 +					# for the whole (rd) device. You must
298.2546 +					# use (rd)+1 instead of (rd).
298.2547 +		map --hook
298.2548 +		root (hd0,0)
298.2549 +		kernel /kernel root=/dev/ram0 rw ip=bootp ramdisk_size=32768 ...
298.2550 +		initrd /initrd
298.2551 +		map --unhook
298.2552 +		map (hd0) (hd0)		# Delete the map; this is needed.
298.2553 +		boot
298.2554 +
298.2555 +
298.2556 +******************************************************************************
298.2557 +***                      Notes on the use of stack                         ***
298.2558 +******************************************************************************
298.2559 +
298.2560 +The protected-mode and real-mode stack are merged at physical address 0x2000.
298.2561 +
298.2562 +All functions should use at most 2K stack space(0x1800-0x2000). So each
298.2563 +subfunction should use as little stack as possible to avoid stack-overflow.
298.2564 +
298.2565 +Don't use recursive functions because they could expend too much stack space.
298.2566 +
298.2567 +The original protected mode stack at 0x68000(expand-down) is free now and can
298.2568 +be reused for any purposes.
298.2569 +
298.2570 +
298.2571 +******************************************************************************
298.2572 +***                  A bug was found in the CDROM driver                   ***
298.2573 +******************************************************************************
298.2574 +
298.2575 +It seems the cdrom must be connected as the master device of an IDE controller.
298.2576 +
298.2577 +If cdrom is slave, the driver will fail to read the cdrom sectors. Hope someone
298.2578 +
298.2579 +could fix this problem.
298.2580 +
298.2581 +
298.2582 +******************************************************************************
298.2583 +***                        BIOS and the (cd) drive                         ***
298.2584 +******************************************************************************
298.2585 +
298.2586 +When BIOS boots a no-emulation-mode bootable CD-ROM, it allocates a BIOS drive
298.2587 +number to the CD. If the boot image of the CD-ROM is grldr or stage2_eltorito,
298.2588 +then GRUB can access the CD-ROM media through the drive number allocated by
298.2589 +BIOS. The device name of the CD-ROM is (cd).
298.2590 +
298.2591 +BIOS can allocate a BIOS drive number to a no-emulation-mode CDROM even when
298.2592 +the CDROM is not bootable. QEMU has done so. At boot time, GRUB4DOS will
298.2593 +search drives 0x80-0xFF for a possible no-emulation-mode CDROM drive allocated
298.2594 +by BIOS. So if BIOS offered a CDROM interface of int13 EBIOS functions 41h-4Eh,
298.2595 +then the (cd) device will be automatically available in GRUB4DOS.
298.2596 +
298.2597 +
298.2598 +******************************************************************************
298.2599 +***              The way of disk emulation changed greatly                 ***
298.2600 +******************************************************************************
298.2601 +
298.2602 +The way of disk emulation has changed greatly since 0.4.2 final. Please don't
298.2603 +mix newer versions with older versions when disk emulation features are used.
298.2604 +
298.2605 +The newer versions won't automatically unhook emulations established in a
298.2606 +previous grub4dos environment. The GRUB.EXE of an older version will
298.2607 +automatically dismiss emulations established earlier, before transferring
298.2608 +control to the main grub program(i.e., pre_stage2).
298.2609 +
298.2610 +
298.2611 +******************************************************************************
298.2612 +***            FreeDOS EMM386 v2.26 (2021-08-27) VCPI problem              ***
298.2613 +******************************************************************************
298.2614 +
298.2615 +The VCPI function "AX=DE0Ch - Switch From Protected Mode to V86 Mode" of
298.2616 +FreeDOS EMM386 v2.26 was not implemented properly(it always hangs). As an
298.2617 +alternative, you can use Microsoft's EMM386 instead.
298.2618 +
298.2619 +Even while emm386 is running, grub.exe can be started. But if you try to quit
298.2620 +to DOS from grub4dos by using the `quit' command, the VCPI function DE0C will
298.2621 +be called. If EMM386 is of Microsoft, everything goes ok. If EMM386 is of
298.2622 +FreeDOS, the machine will hang.
298.2623 +
298.2624 +
298.2625 +******************************************************************************
298.2626 +***                 New options for map were added                         ***
298.2627 +******************************************************************************
298.2628 +
298.2629 +Along with 0.4.2 final, there are two new options for the map command. They
298.2630 +are --safe-mbr-hook=SMH and --int13-scheme=SCH. Both are related with disk
298.2631 +emulation for use(as smoothly as possible) in the Win9x environment.
298.2632 +
298.2633 +SMH can take either of the two values 0 and 1. By default, SMH is 1. If you
298.2634 +encountered problems of disk emulation under Win9x, you may insert a line of
298.2635 +
298.2636 +	map --safe-mbr-hook=0
298.2637 +
298.2638 +before the `boot' command and try again.
298.2639 +
298.2640 +Also SCH may take either 0 or 1 at present. By default, SCH is 1. If you
298.2641 +encountered disk emulation problems under Win9x, you may insert a line of
298.2642 +
298.2643 +	map --int13-scheme=0
298.2644 +
298.2645 +before the `boot' command and try again.
298.2646 +
298.2647 +Note by the way. Like --safe-mbr-hook and --int13-scheme, the MAP command has
298.2648 +a few other options that are used for setting global variables. They are here:
298.2649 +
298.2650 +	map --floppies=M
298.2651 +
298.2652 +M can be 0, 1, or 2. MAP will set a proper value at 0040:0010 by using M.
298.2653 +
298.2654 +	map --harddrives=N
298.2655 +
298.2656 +N can be between 0 and 127(inclusive). MAP will set 0040:0075 to N.
298.2657 +
298.2658 +	map --memdisk-raw=RAW
298.2659 +
298.2660 +RAW default to 1. If RAW=0, `int15/ah=87h' will be used to access memdrives.
298.2661 +
298.2662 +	map --ram-drive=RD
298.2663 +
298.2664 +RD default to 0x7F which is a floppy. If the RAM DRIVE is a hard drive image
298.2665 +(with partition table in the first sector), you should set RD >= 0x80 and RD
298.2666 +< 0xFF.
298.2667 +
298.2668 +	map --rd-base=ADDR
298.2669 +
298.2670 +	map --rd-size=SIZE
298.2671 +
298.2672 +ADDR specifies the physical base address of the ramdisk image. SIZE specifies
298.2673 +the size in bytes of the ramdisk image. ADDR default to 0. SIZE is also default
298.2674 +to 0, but a size of 0 means 4GB, not a zero-long disk. The RAM DRIVE can be
298.2675 +accessed in the GRUB environment using the (rd) device.
298.2676 +
298.2677 +
298.2678 +******************************************************************************
298.2679 +***                   About the new map option --in-situ                   ***
298.2680 +******************************************************************************
298.2681 +
298.2682 +--in-situ is used with hard drive images or hardrive partitions. With an
298.2683 +in-situ map, we can typically use a logical partition as a primary partition.
298.2684 +
298.2685 +In-situ map is a whole drive map. It only virtualize the partition table and
298.2686 +the number of hidden sectors in the BPB of the DOS Boot Record.
298.2687 +
298.2688 +While disk emulation may encounter various problems with win9x, the in-situ map
298.2689 +works fine with win9x.
298.2690 +
298.2691 +Note that --in-situ will not change the real partition table.
298.2692 +
298.2693 +Example:
298.2694 +
298.2695 +	map --in-situ (hd0,4)+1 (hd0)
298.2696 +
298.2697 +
298.2698 +******************************************************************************
298.2699 +***                      The PARTNEW Command Syntax                        ***
298.2700 +******************************************************************************
298.2701 +
298.2702 +Besides the mappings in the above section, you may instead choose to create a
298.2703 +new primary partition with the PARTNEW command. PARTNEW can generate a primary
298.2704 +partition entry (in the partition table) for a logical partition.
298.2705 +
298.2706 +For example,
298.2707 +
298.2708 +	partnew (hd0,3) 0x07 (hd0,4)+1
298.2709 +
298.2710 +where the file (hd0,4)+1 stands for the whole partition (hd0,4). This command
298.2711 +will create a new primary partition (hd0,3) whose type is 0x07 and whose
298.2712 +contents/data is the same as that of the logical partition (hd0,4).
298.2713 +
298.2714 +Just like a whole logical partition, a contiguous partition image file can
298.2715 +also be used with PARTNEW:
298.2716 +
298.2717 +	partnew (hd0,3) 0x00 (hd0,0)/my_partition.img
298.2718 +
298.2719 +The type 0x00 indicates a type-auto-detection of the image MY_PARTITION.IMG.
298.2720 +The above command will create a new primary partition (hd0,3) with a proper
298.2721 +type and with contents/data being exactly that of the contiguous file
298.2722 +(hd0,0)/my_partition.img.
298.2723 +
298.2724 +PARTNEW will automatically correct the "hidden sectors" in the BPB and the
298.2725 +modification will be permanent. And PARTNEW modifies the partition table
298.2726 +permanently.
298.2727 +
298.2728 +In addition to creating new partition entries, PARTNEW can also be used to
298.2729 +delete(erase, or wipe) a primary partition entry. For example,
298.2730 +
298.2731 +	partnew (hd0,3) 0 0 0
298.2732 +
298.2733 +which will empty the last entry in the partition table in MBR. Generally,
298.2734 +you should use the form of "partnew PARTITION 0 0 0" to erase the entry.
298.2735 +Note that only the entry would be erased, and the data stored in the partition
298.2736 +will not be touched.
298.2737 +
298.2738 +******************************************************************************
298.2739 +***              Newly implemented operators `&&' and `||'                 ***
298.2740 +******************************************************************************
298.2741 +
298.2742 +This implementation is very simple. It does not handle operator nesting.
298.2743 +
298.2744 +Usage of `&&':
298.2745 +
298.2746 +	command1 && command2
298.2747 +
298.2748 +Description:
298.2749 +
298.2750 +	If command1 returns true, then command2 will be executed.
298.2751 +
298.2752 +Usage of `||':
298.2753 +
298.2754 +	command1 || command2
298.2755 +
298.2756 +Description:
298.2757 +
298.2758 +	If command1 returns false, then command2 will be executed.
298.2759 +
298.2760 +Examples:
298.2761 +
298.2762 +	is64bit && default 0
298.2763 +	is64bit || default 1
298.2764 +
298.2765 +******************************************************************************
298.2766 +***          Three new commands is64bit, errnum and errorcheck             ***
298.2767 +******************************************************************************
298.2768 +
298.2769 +is64bit and errnum retrieve the value of is64bit and errnum respectively.
298.2770 +
298.2771 +errorcheck controls whether or not the error will be handled. By default,
298.2772 +errorcheck is on, and menu script execution will stop on error. If errorcheck
298.2773 +is off, the script will continue to execute upto a boot command. A boot command
298.2774 +will turn the errorcheck on.
298.2775 +
298.2776 +
298.2777 +******************************************************************************
298.2778 +***              Use numeric keys to select a menu entry                   ***
298.2779 +******************************************************************************
298.2780 +
298.2781 +If, for example, you intend to goto entry #25, you may press 2 followed by 5.
298.2782 +
298.2783 +
298.2784 +******************************************************************************
298.2785 +***           Use the INSERT key to debug step by step at startup          ***
298.2786 +******************************************************************************
298.2787 +
298.2788 +Some buggy machines could fail to enter grub4dos environment. They might hang
298.2789 +or reboot unexpectedly. Press INSERT as quickly as possible on startup, and
298.2790 +you can get a chance to single-step the boot process and see how far it can
298.2791 +go, and then report bugs.
298.2792 +
298.2793 +
298.2794 +******************************************************************************
298.2795 +***             The debug command syntax has been changed                  ***
298.2796 +******************************************************************************
298.2797 +
298.2798 +The DEBUG command now can be used to control the verbosity of command output:
298.2799 +
298.2800 +		debug [ on | off | normal | status | INTEGER ]
298.2801 +
298.2802 +0 or off for silent
298.2803 +1 or normal for normal
298.2804 +2 to 0x7FFFFFFF or on for verbose
298.2805 +
298.2806 +
298.2807 +******************************************************************************
298.2808 +***                     GRUB4DOS and Windows Vista                         ***
298.2809 +******************************************************************************
298.2810 +
298.2811 +First, use the following command to create a boot entry:
298.2812 +
298.2813 +	bcdedit /create /d "GRUB for DOS" /application bootsector
298.2814 +
298.2815 +The result will look like this:
298.2816 +
298.2817 +The entry {05d33150-3fde-11dc-a457-00021cf82fb0} was successfully created.
298.2818 +
298.2819 +The long string {05d33150-3fde-11dc-a457-00021cf82fb0} is the id for this
298.2820 +entry.
298.2821 +
298.2822 +Then, use the following commands to set boot parameters:
298.2823 +
298.2824 +	bcdedit /set {id} device boot
298.2825 +	bcdedit /set {id} path \grldr.mbr
298.2826 +	bcdedit /displayorder {id} /addlast
298.2827 +
298.2828 +Please replace {id} with the actual id returned from the previous command.
298.2829 +
298.2830 +Finally, copy GRLDR.MBR to C:\ or wherever your boot drive is, and copy GRLDR
298.2831 +and menu.lst to the root directory of any FAT16/FAT32/EXT2/NTFS partition.
298.2832 +
298.2833 +Note: A boot partition should be the active primary partition with BOOTMGR
298.2834 +      inside. The `device boot' indicates grldr.mbr should be in the boot
298.2835 +      partition.
298.2836 +
298.2837 +Lianjiang has written down a script to automate the tasks:
298.2838 +
298.2839 +	@echo off
298.2840 +	rem by lianjiang
298.2841 +	cls
298.2842 +	echo.
298.2843 +	echo   Please run as administrator
298.2844 +	echo.
298.2845 +	pause
298.2846 +	set gname=GRUB for DOS
298.2847 +	set vid=
298.2848 +	set timeout=5
298.2849 +	bcdedit >bcdtemp.txt
298.2850 +	type bcdtemp.txt | find "\grldr.mbr" >nul && echo. && echo  BCD entry existing, no need to install. && pause && goto exit
298.2851 +	bcdedit  /export "Bcd_Backup" >nul
298.2852 +	bcdedit  /create /d "%gname%" /application bootsector >vid.ini
298.2853 +	for,/f,"tokens=2 delims={",%%i,In (vid.ini) Do (
298.2854 +                  set vida=%%i
298.2855 +	)
298.2856 +	for,/f,"tokens=1 delims=}",%%i,In ("%vida%") Do (
298.2857 +                  set vid={%%i}
298.2858 +	)
298.2859 +	echo %vid%>vid.ini
298.2860 +	bcdedit  /set %vid% device boot >nul
298.2861 +	bcdedit  /set %vid% path \grldr.mbr >nul
298.2862 +	bcdedit  /displayorder %vid% /addlast >nul
298.2863 +	bcdedit  /timeout  %timeout% >nul
298.2864 +	if exist grldr.mbr copy grldr.mbr %systemdrive%\ /y && goto exit
298.2865 +	echo.
298.2866 +	echo   Please copy grldr.mbr to %systemdrive%\
298.2867 +	echo.
298.2868 +	pause
298.2869 +	:exit
298.2870 +	del bcdtemp.txt >nul
298.2871 +-------------------------------------------------------------------
298.2872 +Update: Fujianabc pointed out that
298.2873 +
298.2874 +	bcdedit  /set %vid% device boot >nul
298.2875 +
298.2876 +should be changed to
298.2877 +
298.2878 +	bcdedit  /set %vid% device partition=%SystemDrive% >nul
298.2879 +-------------------------------------------------------------------
298.2880 +
298.2881 +You still need to copy grldr yourself.
298.2882 +
298.2883 +Notice: It's possible to modify the BCD entry from a different OS, you just
298.2884 +need to specify the location of BCD:
298.2885 +
298.2886 +	bcdedit /store D:\boot\BCD ...
298.2887 +
298.2888 +Notice: These commands need elevated privileges, they should be used inside
298.2889 +cmd.exe which is started with "Run as administrator".
298.2890 +
298.2891 +Notice: People has reported that some version of Vista doesn't support
298.2892 +creating file in C:\ with no extension, even with administrator privileges.
298.2893 +This means grldr can't be placed in C:\. You can solve this by either copy
298.2894 +grldr to another partition, or rename grldr to something like grub.bin. Please
298.2895 +see the following section on how to do this.
298.2896 +
298.2897 +
298.2898 +******************************************************************************
298.2899 +***                      How to rename grldr                               ***
298.2900 +******************************************************************************
298.2901 +
298.2902 +grldr and grldr.mbr use internal boot file name to decide which file to load,
298.2903 +so if you want to change the name, you must also change the embeded setting.
298.2904 +You can do this with the help of grubinst, which can be downloaded at:
298.2905 +
298.2906 +http://download.gna.org/grubutil/
298.2907 +
298.2908 +grubinst can generate customized grldr.mbr:
298.2909 +
298.2910 +	grubinst -o -b=mygrldr C:\mygrldr.mbr
298.2911 +
298.2912 +grubinst can also edit existing grldr/grldr.mbr:
298.2913 +
298.2914 +	grubinst -e -b=mygrldr C:\mygrldr
298.2915 +
298.2916 +	grubinst -e -b=mygrldr C:\mygrldr.mbr
298.2917 +
298.2918 +In this case, you must use a grubinst that is compatible with the version of
298.2919 +grub4dos, otherwise the edit will fail.
298.2920 +
298.2921 +So, in order to load mygrldr instead of grldr, you can use one of the
298.2922 +following methods:
298.2923 +
298.2924 +1. Use customized grldr.mbr to load mygrldr. In this case, you need to change
298.2925 +the embeded boot file name in grldr.mbr. The name of grldr.mbr can be changed
298.2926 +at will.
298.2927 +
298.2928 +2. Use mygrldr directly. In this case, you need to change the embeded boot
298.2929 +file name in mygrldr to match its new name.
298.2930 +
298.2931 +Notice: The boot file name must conform to the 8.3 naming convention.
298.2932 +
298.2933 +
298.2934 +******************************************************************************
298.2935 +***                          PXE device                                    ***
298.2936 +******************************************************************************
298.2937 +
298.2938 +If PXE service is found at startup, GRUB4DOS will create a virtual device
298.2939 +(pd), through which files from the tftp server can be accessed. You can setup
298.2940 +a diskless boot environment using the following steps:
298.2941 +
298.2942 +Client side
298.2943 +
298.2944 +You need to boot from PXE ROM.
298.2945 +
298.2946 +Server side
298.2947 +
298.2948 +You need to configure a dhcp server and a tftp server. In the dhcp server, use
298.2949 +grldr as boot file.
298.2950 +
298.2951 +You may also want to load a different menu.lst for different client. GRUB4DOS
298.2952 +will scan the following location for configuration file:
298.2953 +
298.2954 +	[/mybootdir]/menu.lst/01-88-99-AA-BB-CC-DD
298.2955 +	[/mybootdir]/menu.lst/C000025B
298.2956 +	[/mybootdir]/menu.lst/C000025
298.2957 +	[/mybootdir]/menu.lst/C00002
298.2958 +	[/mybootdir]/menu.lst/C0000
298.2959 +	[/mybootdir]/menu.lst/C000
298.2960 +	[/mybootdir]/menu.lst/C00
298.2961 +	[/mybootdir]/menu.lst/C0
298.2962 +	[/mybootdir]/menu.lst/C
298.2963 +	[/mybootdir]/menu.lst/default
298.2964 +
298.2965 +Here, we assume the network card mac for the client machine is
298.2966 +88:99:AA:BB:CC:DD, and the ip address is 192.0.2.91 (C000025B). /mybootdir is
298.2967 +the directory of the boot file, for example, if boot file is /tftp/grldr, then
298.2968 +mybootdir=tftp.
298.2969 +
298.2970 +If none of the above files is present, grldr will use its embeded menu.lst.
298.2971 +
298.2972 +This is a menu.lst to illstrate how to use files from the tftp server.
298.2973 +
298.2974 +	title Create ramdisk using map
298.2975 +	map --mem (pd)/floppy.img (fd0)
298.2976 +	map --hook
298.2977 +	rootnoverify (fd0)
298.2978 +	chainloader (fd0)+1
298.2979 +
298.2980 +	title Create ramdisk using memdisk
298.2981 +	kernel (pd)/memdisk
298.2982 +	initrd (pd)/floppy.img
298.2983 +
298.2984 +You can see that the menu.lst is very similar to normal disk boot, you just
298.2985 +need to replace device like (hd0,0) with (pd).
298.2986 +
298.2987 +There are some differences between disk device and pxe device:
298.2988 +
298.2989 +1. You can't list files in the pxe device.
298.2990 +
298.2991 +2. The blocklist command will not work with a file in the pxe device.
298.2992 +
298.2993 +3. You must use --mem option if you want to map a file in the pxe device.
298.2994 +
298.2995 +When you use chainloader to load file from the pxe device, there is a option
298.2996 +you can use:
298.2997 +
298.2998 +	chainloader --raw (pd)/BOOT_FILE
298.2999 +
298.3000 +Option --raw works just like --force, but it load file in one go. This can
298.3001 +improve performance in some situation.
298.3002 +
298.3003 +You can use the pxe command to control the pxe device.
298.3004 +
298.3005 +1. pxe
298.3006 +
298.3007 +	If used without any parameter, pxe command will display current
298.3008 +	settings.
298.3009 +
298.3010 +2. pxe blksize N
298.3011 +
298.3012 +	Set the packet size for tftp transmission. Minimum value is 512,
298.3013 +	maximum value is 1432. This parameter is used primarily for very old
298.3014 +	tftp server where packet larger than 512 byte is not supported.
298.3015 +
298.3016 +3. pxe basedir /dir
298.3017 +
298.3018 +	Set the base directory for files in the tftp server. If
298.3019 +
298.3020 +		pxe basedir /tftp
298.3021 +
298.3022 +	then all files in the pxe device is related to directory /tftp, for
298.3023 +	example, (pd)/aa.img correspond to /tftp/aa.img in the server.
298.3024 +
298.3025 +	The default value of base directory is the directory of the boot file,
298.3026 +	for example, if boot file is /tftp/grldr, then default base directory
298.3027 +	is /tftp.
298.3028 +
298.3029 +4. pxe keep
298.3030 +
298.3031 +	Keep the PXE stack. The default behaviour of GRUB4DOS is to unload
298.3032 +	the PXE stack just before it exits.
298.3033 +
298.3034 +5. pxe unload
298.3035 +
298.3036 +	Unload the PXE stack immediately.
298.3037 +
298.3038 +
298.3039 +
298.3040 +******************************************************************************
298.3041 +***                  New Feature of Relative Path Support                  ***
298.3042 +******************************************************************************
298.3043 +
298.3044 +Use the `root' or `rootnoverify' command to specify the `working directory'.
298.3045 +
298.3046 +For example:
298.3047 +
298.3048 +		root  (hd0,0)/boot/grub
298.3049 +
298.3050 +This specifies that the working dir is (hd0,0)/boot/grub. So all subsequent
298.3051 +filenames of the form "/..." will actually refer to (hd0,0)/boot/grub/...
298.3052 +
298.3053 +That is to say:
298.3054 +
298.3055 +		cat  /menu.lst
298.3056 +
298.3057 +will be equivalent to
298.3058 +
298.3059 +		cat  (hd0,0)/boot/grub/menu.lst
298.3060 +
298.3061 +
298.3062 +
298.3063 +******************************************************************************
298.3064 +***                 Notation For The Current Root Device                   ***
298.3065 +******************************************************************************
298.3066 +
298.3067 +
298.3068 +The notation `()' can be used to access the current root device. You may use
298.3069 +`find --set-root ...' to set the current root device, but the find command
298.3070 +does not set the `working dir' of the root device. In this case you should
298.3071 +use `()' to set the working dir after the find command:
298.3072 +
298.3073 +		root  ()/boot/grub
298.3074 +
298.3075 +Update 2008-05-01:
298.3076 +
298.3077 +	FIND can also set the `working directory' now. For example:
298.3078 +
298.3079 +		find  --set-root=/tmp  /boot/grub/menu.lst
298.3080 +
298.3081 +	It is equivalent to this pair of commands:
298.3082 +
298.3083 +		find  --set-root  /boot/grub/menu.lst
298.3084 +		root  ()/tmp
298.3085 +
298.3086 +
298.3087 +******************************************************************************
298.3088 +***                   The new map option --a20-keep-on                     ***
298.3089 +******************************************************************************
298.3090 +
298.3091 +
298.3092 +Along with 0.4.3 final, map has a new option --a20-keep-on which is related to
298.3093 +A20 control after a memdrive sector access. Usage:
298.3094 +
298.3095 +	map --a20-keep-on=0
298.3096 +
298.3097 +It should be used before the "map --hook" command.
298.3098 +
298.3099 +By default, A20 will be always on after an RAM INT13 sector access. If
298.3100 +"map --a20-keep-on=0" is used, the A20 status after the INT13 call will be the
298.3101 +same as that before the INT13 call.
298.3102 +
298.3103 +
298.3104 +******************************************************************************
298.3105 +***                  The CDROM emulation (virtualization)                  ***
298.3106 +******************************************************************************
298.3107 +
298.3108 +The CDROM emulation is sometimes called ISO emulation. Here is an example:
298.3109 +
298.3110 +	map  (hd0,0)/myiso.iso  (hd32)
298.3111 +	map  --hook
298.3112 +	chainloader  (hd32)
298.3113 +	boot
298.3114 +
298.3115 +if myiso.iso is not contiguous and you have enough memory, add a --mem option:
298.3116 +
298.3117 +	map  --mem  (hd0,0)/myiso.iso  (hd32)
298.3118 +	map  --hook
298.3119 +	chainloader  (hd32)
298.3120 +	boot
298.3121 +
298.3122 +Note: (hd32) is a grub drive number equivalent to (0xA0). If a virtual drive is
298.3123 +specified with a drive number greater than or equal to 0xA0, then it will be
298.3124 +treated as a cdrom (i.e., with 2048-byte big sectors).
298.3125 +
298.3126 +Like normal disk emulations, the CDROM emulation also (mainly) works with
298.3127 +real-mode OSes. After a protected-mode OS kernel (such as
298.3128 +WinNT/2K/XP/VISTA/LINUX) gains control, the OS would have no ability to access
298.3129 +the virtual CDROM through BIOS int13.
298.3130 +
298.3131 +DOS/Win9x users may google for ELTORITO.SYS and use it in CONFIG.SYS as a
298.3132 +device driver for the virtual cdrom.
298.3133 +
298.3134 +Example usage of eltorito.sys in CONFIG.SYS:
298.3135 +
298.3136 +	device=eltorito.sys /D:oemcd001
298.3137 +
298.3138 +Corresponding MSCDEX command which can be placed in AUTOEXEC.BAT:
298.3139 +
298.3140 +	MSCDEX /D:oemcd001 /L:D
298.3141 +
298.3142 +
298.3143 +Due to some bugs found in eltorito.sys, the driver could fail to load. If you
298.3144 +encounter such problems, then you may replace (hd32) with (0xFF) for the
298.3145 +virtual cdrom drive number and try again.
298.3146 +
298.3147 +
298.3148 +******************************************************************************
298.3149 +***                  The New Command CHECKRANGE                            ***
298.3150 +******************************************************************************
298.3151 +
298.3152 +Checkrange checks whether or not the return value of a command is in the
298.3153 +specified range or ranges.
298.3154 +
298.3155 +Usage:		checkrange  RANGE  COMMAND
298.3156 +
298.3157 +Here are some examples for RANGE:
298.3158 +
298.3159 +	3 is a range containing only the number 3
298.3160 +	3:3 is equivalent to 3
298.3161 +	3:8 is a range containing the numbers 3, 4, 5, 6, 7, 8
298.3162 +	3,4,5,6,7,8 is equivalent to 3:8
298.3163 +	3:5,6:8 is also equivalent to 3:8
298.3164 +	3,4:7,8 is also equivalent to 3:8
298.3165 +
298.3166 +Note: You should not insert spaces into a range.
298.3167 +
298.3168 +Here is an example showing where the checkrange can be used:
298.3169 +
298.3170 +	checkrange 0x05,0x0F,0x85 parttype (hd0,1) || hide (hd0,1)
298.3171 +
298.3172 +which means: if (hd0,1) is not an extended partition, then hide it.
298.3173 +
298.3174 +
298.3175 +******************************************************************************
298.3176 +***                       The New Command TPM                              ***
298.3177 +******************************************************************************
298.3178 +
298.3179 +The "tpm --init" uses 512-byte data at 0000:7C00 as buffer to initialise TPM.
298.3180 +
298.3181 +Before you boot VISTA's BOOTMGR, you might have to use the "tpm --init"
298.3182 +command on some machines. Normally you want to issue the "tpm --init" command
298.3183 +after a CHAINLOADER command.
298.3184 +
298.3185 +
298.3186 +******************************************************************************
298.3187 +***               Delimitors or comments between titles                    ***
298.3188 +******************************************************************************
298.3189 +
298.3190 +It is possible to use titles as delimitors or comments. A title(or menu item)
298.3191 +is called unbootable if all of its menu commands are not boot-sensitive.
298.3192 +
298.3193 +The following commands are boot-sensitive(and others are not boot-sensitive):
298.3194 +
298.3195 +	boot
298.3196 +	bootp
298.3197 +	chainloader
298.3198 +	configfile
298.3199 +	embed
298.3200 +	commandline
298.3201 +	halt
298.3202 +	install
298.3203 +	kernel
298.3204 +	pxe
298.3205 +	quit
298.3206 +	reboot
298.3207 +	setup
298.3208 +
298.3209 +An unbootable title will be skipped when the user presses the Up Arrow or Down
298.3210 +Arrow keys. Even the unbootable menu item can get accessed(and executed) by
298.3211 +using the Left Arrow and/or Right Arrow keys. Examples:
298.3212 +
298.3213 +	title This is an UNBOOTABLE entry(so this line is also a comment)
298.3214 +		pause --wait=0 This title is a comment. Nothing to do.
298.3215 +		pause --wait=0 You can use non-boot-sensitive commands here
298.3216 +		pause --wait=0 of any kind and as many as you would like.
298.3217 +		help
298.3218 +		help root
298.3219 +		help chainloader
298.3220 +		help parttype
298.3221 +		clear
298.3222 +	title ------------------------------------------------------------
298.3223 +		pause --wait=0 This title is a delimitor. Nothing to do.
298.3224 +		pause --wait=0 You can use non-boot-sensitive commands here
298.3225 +		pause --wait=0 of any kind and as many as you would like.
298.3226 +		clear
298.3227 +		help
298.3228 +		help boot
298.3229 +	title ============================================================
298.3230 +		pause --wait=0 This title is a delimitor. Nothing to do.
298.3231 +		pause --wait=0 You can use non-boot-sensitive commands here
298.3232 +		pause --wait=0 of any kind and as many as you would like.
298.3233 +		help
298.3234 +		clear
298.3235 +		help pause
298.3236 +	title ************************************************************
298.3237 +		pause --wait=0 This title is a delimitor. Nothing to do.
298.3238 +		pause --wait=0 You can use non-boot-sensitive commands here
298.3239 +		pause --wait=0 of any kind and as many as you would like.
298.3240 +		help kernel
298.3241 +		help
298.3242 +		clear
298.3243 +
298.3244 +Note: An unbootable menu item must contain at least one command. If there
298.3245 +are no commands for a title, the title will be simply discarded and disappear.
298.3246 +
298.3247 +
298.3248 +******************************************************************************
298.3249 +***                           Bifurcate drives                             ***
298.3250 +******************************************************************************
298.3251 +
298.3252 +Some machines apply different actions to a drive between CHS and LBA mode.
298.3253 +When you read sectors using standard BIOS call int13/AH=02h, you might find
298.3254 +out the drive is a floppy. But when you read sectors using extended BIOS
298.3255 +call(EBIOS) int13/AH=42h, you could know the drive is a cdrom. Such a drive
298.3256 +is called bifurcate.
298.3257 +
298.3258 +A bifurcate drive can have two drive numbers: one is the normal BIOS drive
298.3259 +number between 00 and FF in hexa, and this drive uses only CHS mode disk
298.3260 +access(standard BIOS int13/AH=02h); the other is the normal BIOS drive number
298.3261 +(Bitwise) OR'ed by 0x100(i.e., 256 in decimal), and this drive uses only
298.3262 +LBA mode disk access(EBIOS int13/AH=42h). For example, if the drive 0x00
298.3263 +(i.e., the first floppy) is bifurcate, then the drive (0x00) uses CHS mode
298.3264 +to access its sectors, and the drive (0x100) uses LBA (meaning EBIOS) mode
298.3265 +to access its sectors.
298.3266 +
298.3267 +The geometry command can report the disk access mode for bifurcate drives as
298.3268 +BIF instead of the conventional CHS or LBA.
298.3269 +
298.3270 +Known bifurcate drives. Virtual PC and some real machines are found to create
298.3271 +a bifurcate floppy drive when they boot from a floppy-emulation mode bootable
298.3272 +cdrom. The "geometry (fd0)" will show
298.3273 +
298.3274 +	drive 0x00(BIF): C/H/S=...Sector Count/Size=.../512
298.3275 +
298.3276 +and "geometry (0x100)" will show
298.3277 +
298.3278 +	drive 0x100(BIF): C/H/S=...Sector Count/Size=.../2048
298.3279 +
298.3280 +Actually (0x100) can access the whole cdrom, you may "ls (0x100)/" and find
298.3281 +your files on the cdrom(not the files inside the booted floppy image). Of
298.3282 +course "ls (fd0)/" will list the files inside the booted floppy image.
298.3283 +
298.3284 +Note that only some (real or virtual) machines have this action, others
298.3285 +will not produce bifurcate drives.
298.3286 +
298.3287 +
298.3288 +******************************************************************************
298.3289 +***                       GRLDR as PXE boot file                           ***
298.3290 +******************************************************************************
298.3291 +
298.3292 +GRLDR can be used as the PXE boot file on a remote/network server. The (pd)
298.3293 +device is used to access files on the server. When GRLDR is booted through
298.3294 +network, it will use its preset menu as the config file. However, you may use
298.3295 +a "pxe detect" command, which acts the same way as PXELINUX:
298.3296 +
298.3297 +    * First, it will search for the config file using the hardware type (using
298.3298 +      its ARP type code) and address, all in hexadecimal with dash separators;
298.3299 +      for example, for an Ethernet (ARP type 1) with address 88:99:AA:BB:CC:DD
298.3300 +      it would search for the filename 01-88-99-AA-BB-CC-DD. 
298.3301 +
298.3302 +    * Next, it will search for the config file using its own IP address in
298.3303 +      upper case hexadecimal, e.g. 192.0.2.91 -> C000025B. If that file is not
298.3304 +      found, it will remove one hex digit and try again. At last, it will try
298.3305 +      looking for a file named default (in lower case). As an example, if the
298.3306 +      boot file name is /mybootdir/grldr, the Ethernet MAC address is
298.3307 +      88:99:AA:BB:CC:DD and the IP address 192.0.2.91, it will try following
298.3308 +      files (in that order): 
298.3309 +
298.3310 +       /mybootdir/menu.lst/01-88-99-AA-BB-CC-DD
298.3311 +       /mybootdir/menu.lst/C000025B
298.3312 +       /mybootdir/menu.lst/C000025
298.3313 +       /mybootdir/menu.lst/C00002
298.3314 +       /mybootdir/menu.lst/C0000
298.3315 +       /mybootdir/menu.lst/C000
298.3316 +       /mybootdir/menu.lst/C00
298.3317 +       /mybootdir/menu.lst/C0
298.3318 +       /mybootdir/menu.lst/C
298.3319 +       /mybootdir/menu.lst/default
298.3320 +
298.3321 +You cannot directly map an image file on (pd). You must map it in memory using
298.3322 +the --mem option. For example,
298.3323 +
298.3324 +	map --mem (pd)/images/floppy.img (fd0)
298.3325 +	map --hook
298.3326 +	chainloader (fd0)+1
298.3327 +	rootnoverify (fd0)
298.3328 +	boot
298.3329 +
298.3330 +One more example,
298.3331 +
298.3332 +	map --mem (pd)/images/cdimage.iso (0xff)
298.3333 +	map --hook
298.3334 +	chainloader (0xff)
298.3335 +	boot
298.3336 +
298.3337 +
298.3338 +******************************************************************************
298.3339 +***                       New program badgrub.exe                          ***
298.3340 +******************************************************************************
298.3341 +
298.3342 +The new program badgrub.exe is intended to serve 'bad' machines(typically some
298.3343 +DELL models) that cannot run the normal grub.exe.
298.3344 +
298.3345 +
298.3346 +******************************************************************************
298.3347 +***                           Conditional find                             ***
298.3348 +******************************************************************************
298.3349 +
298.3350 +The new find syntax allows to find a device conditionally.
298.3351 +
298.3352 +	find [OPTIONS] [FILENAME] [CONDITION]
298.3353 +
298.3354 +CONDITION is a normal grub command which returns TRUE or FALSE.
298.3355 +
298.3356 +	Example 1:
298.3357 +
298.3358 +		find
298.3359 +
298.3360 +	This will list all partitions, all floppies and the (cd).
298.3361 +
298.3362 +	Example 2:
298.3363 +
298.3364 +		find +1
298.3365 +
298.3366 +	This will list all devices with a known filesystem.
298.3367 +
298.3368 +	Example 3:
298.3369 +
298.3370 +		find checkrange 0xAF parttype
298.3371 +
298.3372 +	This will list all partitions with ID=0xAF.
298.3373 +
298.3374 +	Example 4:
298.3375 +
298.3376 +		find /ntldr checkrange 0x07 parttype
298.3377 +
298.3378 +	This will list all partitions with ID=0x07 and existing /ntldr.
298.3379 +
298.3380 +
298.3381 +
298.3382 +******************************************************************************
298.3383 +***                    How to build grldr boot images                      ***
298.3384 +******************************************************************************
298.3385 +
298.3386 +1. build 1.44M floppy image ext2grldr.img
298.3387 +
298.3388 +	dd if=/dev/zero of=ext2grldr.img bs=512 count=2880
298.3389 +	mke2fs ext2grldr.img
298.3390 +	mkdir ext2tmp
298.3391 +	mount -o loop ext2grldr.img ext2tmp
298.3392 +	cp default ext2tmp
298.3393 +	cp menu.lst ext2tmp
298.3394 +	cp grldr ext2tmp
298.3395 +	umount ext2tmp
298.3396 +	bootlace.com --floppy --chs --sectors-per-track=18 --heads=2 --start-sector=0 --total-sectors=2880 ext2grldr.img
298.3397 +
298.3398 +2. build 1.44M floppy image fat12grldr.img
298.3399 +
298.3400 +	dd if=/dev/zero of=fat12grldr.img bs=512 count=2880
298.3401 +	mkdosfs fat12grldr.img
298.3402 +	mkdir fat12tmp
298.3403 +	mount -o loop fat12grldr.img fat12tmp
298.3404 +	cp default fat12tmp
298.3405 +	cp menu.lst fat12tmp
298.3406 +	cp grldr fat12tmp
298.3407 +	umount fat12tmp
298.3408 +	bootlace.com --floppy --chs fat12grldr.img
298.3409 +
298.3410 +3. build iso9660 CDROM image grldr.iso
298.3411 +
298.3412 +	mkdir iso_root
298.3413 +	cp grldr iso_root
298.3414 +	cp menu.lst iso_root
298.3415 +	mkisofs -R -b grldr -no-emul-boot -boot-load-size 4 -o grldr.iso iso_root
298.3416 +
298.3417 +
298.3418 +******************************************************************************
298.3419 +***           Use bootlace.com to install partition boot record            ***
298.3420 +******************************************************************************
298.3421 +
298.3422 +Since bootlace.com has not implemented the --install-partition option, you
298.3423 +need to use the already implemented --floppy=PartitionNumber option instead.
298.3424 +
298.3425 +Hear is a way you might want to follow:
298.3426 +
298.3427 +Step 1. Get the boot sectors of the partition and save to a file MYPART.TMP.
298.3428 +	For NTFS, you need to get the beginning 16 sectors. For other type of
298.3429 +	filesystems, you only need to get one sector, but getting more sectors
298.3430 +	is also ok.
298.3431 +
298.3432 +Step 2. Run this:
298.3433 +
298.3434 +	bootlace.com --floppy=Y --sectors-per-track=S --heads=H --start-sector=B --total-sectors=C --vfat --ext2 --ntfs MYPART.TMP
298.3435 +
298.3436 +	where we suppose MYPART.TMP is for (hdX,Y) and the partition number Y
298.3437 +	should be specified as in the --floppy=Y option.
298.3438 +
298.3439 +	Note that for FAT12/16/32/NTFS partitions, you can omit these options:
298.3440 +
298.3441 +		 --sectors-per-track, --heads, --start-sector, --total-sectors,
298.3442 +		 --vfat and --ext2.
298.3443 +
298.3444 +	For NTFS partitions, you must specify --ntfs option.
298.3445 +
298.3446 +	For ext2 partitions, you can omit --vfat, --ntfs and --ext2 options,
298.3447 +	but other options should be specified.
298.3448 +
298.3449 +Step 3. Put MYPART.TMP back on to the boot sector(s) of your original partition
298.3450 +	(hdX,Y).
298.3451 +
298.3452 +
298.3453 +Note: Only a few file systems(FAT12/16/32/NTFS/ext2/ext3) are supported by now.
298.3454 +
298.3455 +Note2: Under Linux you may directly write the partition. That is to say, Step
298.3456 +	1 and Step 3 are not needed. Simply use its device name instead of
298.3457 +	MYPART.TMP.
298.3458 +
298.3459 +Note3: grubinst has the feature of installing grldr boot code onto a
298.3460 +	partition boot area.
298.3461 +
298.3462 +******************************************************************************
298.3463 +***                Use a single key to select menu item                    ***
298.3464 +******************************************************************************
298.3465 +
298.3466 +Some machines have a simplified keyboard. The keyborad might have only the
298.3467 +number keys 0 .. 9 plus a few other keys. When the menu displayed, the user
298.3468 +can strike a key for 8 times. When the menu handler detects the continuous
298.3469 +single keypress, it will assume the user want to use this key to select a menu
298.3470 +item and boot. This single key will act as the RIGHT-ARROW key for the user to
298.3471 +select a menu item. And 5 seconds later after the user stops the keypress,
298.3472 +the selected menu item will automatically boot. Any normal keys can be used as
298.3473 +a single key for this purpose, except for a few functional keys like b, e,
298.3474 +Enter, etc. Once another key is pressed, the feature of Single-Key-Selection
298.3475 +will disappear immediately.
298.3476 +
298.3477 +
298.3478 +******************************************************************************
298.3479 +***             Parameter file for bootlace running under DOS              ***
298.3480 +******************************************************************************
298.3481 +
298.3482 +You may move all or part of the command-line arguments into a file. The file
298.3483 +can have multi lines. Just like SPACEs and TABs, the CRs and LFs can also
298.3484 +delimit the commandline arguments in the parameter file.
298.3485 +
298.3486 +Example:
298.3487 +
298.3488 +		bootlace < my_parafile
298.3489 +		bootlace --read-only my_mbr < my_other_options
298.3490 +
298.3491 +Note:	Pipes do not work. You have to use the input-redirection operator(<).
298.3492 +
298.3493 +
298.3494 +******************************************************************************
298.3495 +***                  Use bootlace to create a triple MBR                   ***
298.3496 +******************************************************************************
298.3497 +
298.3498 +This is typically used for USB drives, though it also works with hard drives.
298.3499 +
298.3500 +Steps to create triple MBR:
298.3501 +
298.3502 +1. Do a fresh FDISK to create a FAT12/16/32 partition starting at sector 95
298.3503 +(in LBA, that is, the begginning sector(MBR) is sector 0).
298.3504 +
298.3505 +2. Install grldr boot sector onto the boot sector of this partition. See
298.3506 +section "Use bootlace.com to install partition boot record" above.
298.3507 +
298.3508 +3. Get 96 sectors of the drive starting at sector 0(MBR), and save to file
298.3509 +MYMBR96.TMP.
298.3510 +
298.3511 +4. Run bootlace.com:
298.3512 +
298.3513 +	bootlace.com MYMBR96.TMP
298.3514 +
298.3515 +5. Put MYMBR96.TMP back onto the drive starting at MBR(sector 0).
298.3516 +
298.3517 +Note: If the drive already has a triple MBR, then bootlace will cancel it
298.3518 +and restore the original partition layout.
298.3519 +
298.3520 +
298.3521 +******************************************************************************
298.3522 +***                    Use 'pxe detect' in preset-menu                     ***
298.3523 +******************************************************************************
298.3524 +
298.3525 +Now the "pxe" command has a new subcommand "detect":
298.3526 +
298.3527 +		pxe detect [BLOCK_SIZE] [MENU_FILE]
298.3528 +
298.3529 +BLOCK_SIZE specifies the block size for PXE. If it is not specified or it is
298.3530 +0, then grub4dos will go through a probing process and get a proper value
298.3531 +for data transfer.
298.3532 +
298.3533 +MENU_FILE specifies the config file on the PXE server. If omitted, a standard
298.3534 +config file in the menu.lst sub-dir will gain control. For a description on
298.3535 +the config files in the menu.lst sub-dir, please refer to the section
298.3536 +"GRLDR as PXE boot file" above.
298.3537 +If MENU_FILE starts in a "/", then the MENU_FILE on the PXE server will gain
298.3538 +control, else(if MENU_FILE does not start in a "/") no menu will be executed.
298.3539 +
298.3540 +Normally you want to use a "pxe blksize ..." or a "pxe detect ..." command
298.3541 +before you access the (pd) device, since the default blocksize of 512 might
298.3542 +not work on your system.
298.3543 +
298.3544 +
298.3545 +******************************************************************************
298.3546 +***                    Use 'configfile' in preset-menu                     ***
298.3547 +******************************************************************************
298.3548 +
298.3549 +Now the preset menu holds the highest priority. It will gain control prior to
298.3550 +the menu.lst on the boot device. If a 'configfile' command(without specifying
298.3551 +any file as the parameter) occurs in the menu init command group of the preset
298.3552 +menu, then control will go to the menu.lst on the boot device.
298.3553 +
298.3554 +Note: You should better not use "configfile ANOTHER_MENU" frequently in your
298.3555 +menu.lst file, because it could create infinite loop and thus hang your
298.3556 +computer.
298.3557 +
298.3558 +
298.3559 +******************************************************************************
298.3560 +***                    New command 'dd' to copy files                      ***
298.3561 +******************************************************************************
298.3562 +
298.3563 +Usage:
298.3564 +
298.3565 +dd if=IF of=OF [bs=BS] [count=C] [skip=IN] [seek=OUT] [buf=ADDR] [buflen=SIZE]
298.3566 +
298.3567 +Copy file IF to OF. BS is blocksize in bytes, default to 512. C is blocks to
298.3568 +copy, default is total blocks in IF. IN specifies number of blocks to skip
298.3569 +when read, default is 0. OUT specifies number of blocks to skip when write,
298.3570 +default is 0. Skipped blocks are not touched. Both IF and OF must exist.
298.3571 +
298.3572 +Both IF and OF must have a leading device name, i.e.,  of the form `(...)'.
298.3573 +You may use `()' for the current root device.
298.3574 +
298.3575 +dd can neither enlarge nor reduce the size of OF, the leftover tail of IF
298.3576 +will be discarded. OF cannot be a gzipped file. If IF is a gzipped file,
298.3577 +it will be decompressed automatically when copying.
298.3578 +
298.3579 +dd is dangerous, use at your own risk. To be on the safe side, you should
298.3580 +only use dd to write a file in memory.
298.3581 +
298.3582 +In some cases when writing a file in a NTFS volume, dd might fail.
298.3583 +
298.3584 +If you attempt to write a device or a block file that is not in memory by
298.3585 +starting dd in a menu, you will safely be refused :-) (Update: no restrictions
298.3586 +now)
298.3587 +
298.3588 +Update: New options are implemented for user defined buffer. By default,
298.3589 +the buffer is at address 0x50000, and length is 0x10000(=64KB). You cannot
298.3590 +specify ADDR to be lower than 0x100000(=1MB). Besides, you must specify SIZE
298.3591 +larger than 0x10000(=64KB). Normally you want ADDR >= 0x1000000(=16MB), and
298.3592 +SIZE also >= 16MB. A large SIZE could speed up the progression of dd.
298.3593 +
298.3594 +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
298.3595 +!!!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!!
298.3596 +!!!!    Caution! Both IF and OF can be a device name which stands for     !!!!
298.3597 +!!!!    all the sectors on the device. Take utmost care!                  !!!!
298.3598 +!!!!______________________________________________________________________!!!!
298.3599 +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
298.3600 +
298.3601 +
298.3602 +******************************************************************************
298.3603 +***              New command 'uuid' to identify partitions                 ***
298.3604 +******************************************************************************
298.3605 +
298.3606 +Usage:
298.3607 +
298.3608 +	uuid [DEVICE] [UUID]
298.3609 +
298.3610 +If DEVICE is not specified, search for filesystem with UUID in all partitions
298.3611 +and set the partition containing the filesystem as new root (if UUID is
298.3612 +specified), or just list uuid's of all filesystems on all devices (if UUID is
298.3613 +not specified). If DEVICE is specified, return true or false according to
298.3614 +whether or not the DEVICE matches the specified UUID (if UUID is specified),
298.3615 +or just list the uuid of DEVICE (if UUID is not specified).
298.3616 +
298.3617 +Example 1:
298.3618 +
298.3619 +	find --set-root uuid () 7f95820f-5e33-4e6c-8f50-0760bf06d79c
298.3620 +
298.3621 +which will find a partition with uuid=7f95820f-5e33-4e6c-8f50-0760bf06d79c
298.3622 +and set the partition as root if found.
298.3623 +
298.3624 +Example 2:
298.3625 +
298.3626 +	uuid ()
298.3627 +
298.3628 +which will print the uuid of the current root device.
298.3629 +
298.3630 +
298.3631 +******************************************************************************
298.3632 +***                     gfxmenu support in grub4dos                        ***
298.3633 +******************************************************************************
298.3634 +
298.3635 +Gfxmenu support has been added to grub4dos. To use it, you must first find the
298.3636 +message file you need, then load it in menu.lst with command like this:
298.3637 +
298.3638 +	gfxmenu /message
298.3639 +
298.3640 +This should be a gloabl command, that is, not inside any menu item. Also, it
298.3641 +can only be used in configure file, running it in console mode does not work.
298.3642 +
298.3643 +gfxmenu does not work in conjunction with the password feature.
298.3644 +
298.3645 +There are two major format of message file. Old format is created with gfxboot
298.3646 +3.2.* or older (size of message file is normally about 150K), while new format
298.3647 +is created with gfxboot 3.3.* and later (size of message file is normally above
298.3648 +300K). Both format are supported in grub4dos.
298.3649 +
298.3650 +
298.3651 +******************************************************************************
298.3652 +***           Use 'write' to write a string into a device or file          ***
298.3653 +******************************************************************************
298.3654 +
298.3655 +Usage:
298.3656 +
298.3657 +	write [--offset=SKIP] ADDR_OR_FILE INTEGER_OR_STRING
298.3658 +
298.3659 +SKIP is an integer and defaults to 0.
298.3660 +
298.3661 +If ADDR_OR_FILE is an integer, then it is treated as a memory address, and
298.3662 +INTEGER_OR_STRING must be an integer value. The integer INTEGER_OR_STRING
298.3663 +will be written to address (ADDR_OR_FILE + SKIP).
298.3664 +
298.3665 +If ADDR_OR_FILE is a device or a file, then INTEGER_OR_STRING is treated as
298.3666 +a string which will be written to ADDR_OR_FILE at offset SKIP (in bytes).
298.3667 +
298.3668 +The string is quoted with nothing, that is, neither with the single quote
298.3669 +char(') nor with the double quote char(").
298.3670 +
298.3671 +Space char must be quoted with back slash(\). (Update: need not now)
298.3672 +
298.3673 +Single quote char(') and double quote char(") are not interpreted specially
298.3674 +and can be used directly in the string.
298.3675 +
298.3676 +Some C-style quote sequences are interpreted as follows:
298.3677 +
298.3678 +	\NNN	character with octal value NNN (1 to 3 digits)
298.3679 +
298.3680 +	\\	backslash
298.3681 +
298.3682 +	\a	alert (BEL)
298.3683 +
298.3684 +	\b	backspace
298.3685 +
298.3686 +	\f	form feed
298.3687 +
298.3688 +	\n	new line
298.3689 +
298.3690 +	\r	carriage return
298.3691 +
298.3692 +	\t	horizontal tab
298.3693 +
298.3694 +	\v	vertical tab
298.3695 +
298.3696 +	\xHH	byte with hexadecimal value HH (1 to 2 digits)
298.3697 +
298.3698 +Just like dd, the write can neither enlarge nor reduce the size of the
298.3699 +destination file, the leftover tail of the string will be discarded.
298.3700 +The destination file cannot be a gzipped file.
298.3701 +
298.3702 +Again like dd, the write command is also dangerous, use at your own risk.
298.3703 +And to be on the safe side, you should only write to memory files.
298.3704 +
298.3705 +In some cases when writing a file in a NTFS volume, the write might fail.
298.3706 +
298.3707 +If you attempt to write a device or a block file that is not in memory by
298.3708 +using write in a menu, you will safely be refused :-) (Update: no restrictions
298.3709 +now)
298.3710 +
298.3711 +
298.3712 +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
298.3713 +!!!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!!
298.3714 +!!!!    Caution! The file to write can be a device name which stands      !!!!
298.3715 +!!!!    for all the sectors on the device. Take utmost care!              !!!!
298.3716 +!!!!______________________________________________________________________!!!!
298.3717 +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
298.3718 +
298.3719 +
298.3720 +******************************************************************************
298.3721 +***                 Item-by-item help text for menu entries                ***
298.3722 +******************************************************************************
298.3723 +
298.3724 +
298.3725 +The help message at the bottom of the screen will vary as you choose the menu.
298.3726 +
298.3727 +You may append your help text to the title line. The help text must begin
298.3728 +with "\n", for example:
298.3729 +
298.3730 +	title This is the title\nThis is the help text.\nAnd this is the 2nd line of the help text.
298.3731 +
298.3732 +Some C-style quote sequences are interpreted as stated in the section above.
298.3733 +
298.3734 +
298.3735 +******************************************************************************
298.3736 +***        initrd can load multiple cpio files for Linux 2.6 kernels       ***
298.3737 +******************************************************************************
298.3738 +
298.3739 +Usage:
298.3740 +
298.3741 +	initrd FILE [FILE ...]
298.3742 +
298.3743 +Note 1: You should not load more than one oldstyle disk images in this way,
298.3744 +because this is not supported by Linux kernel.
298.3745 +
298.3746 +Note 2: The FILEs should be specified in the same order as with syslinux.
298.3747 +
298.3748 +******************************************************************************
298.3749 +***            access some internel variables at a fixed location          ***
298.3750 +******************************************************************************
298.3751 +
298.3752 +Address		Length		Description
298.3753 +=========	========	==============================================
298.3754 +0000:8208	4 (DWORD)	install_partition (the boot partition)
298.3755 +0000:8280	4 (DWORD)	boot_drive (the boot drive)
298.3756 +0000:8284	4 (DWORD)	pxe_yip (your ip)
298.3757 +0000:8288	4 (DWORD)	pxe_sip (server ip)
298.3758 +0000:828C	4 (DWORD)	pxe_gip (gateway ip)
298.3759 +0000:8290	8 (QWORD)	filesize (file size by last "cat --length=0")
298.3760 +0000:8298	4 (DWORD)	saved_mem_upper (extended memory size in KB)
298.3761 +0000:829C	4 (DWORD)	saved_partition (current root partition)
298.3762 +0000:82A0	4 (DWORD)	saved_drive (current root drive)
298.3763 +0000:82A4	4 (DWORD)	no_decompression (no auto gunzip)
298.3764 +
298.3765 +Note 1: Filesize can be initialised/modified by using "cat --length=0 FILE".
298.3766 +Note 2: You should not write these variables by hand(should read only).
298.3767 +Note 3: You may use 1K at 6000:0000 for your own varibles(See note 4).
298.3768 +Note 4: The read command now returns the integer value at the given address.
298.3769 +Note 5: Grub4dos does not have the variable expansion feature. You can only
298.3770 +	use integer variables. You need not declare them, but use the memory
298.3771 +	address directly. Usually you want to use variables as a logical
298.3772 +	value or in a command for conditional test, e.g., of this form:
298.3773 +		 "checkrange RANGE read ADDR"
298.3774 +Note 6: no_decompression, saved_drive and saved_partition are writable.
298.3775 +
298.3776 +
298.3777 +******************************************************************************
298.3778 +***            possibility to run another menu.lst after gfxmenu           ***
298.3779 +******************************************************************************
298.3780 +
298.3781 +Notice the use of CONFIGFILE after GFXMENU in the following example:
298.3782 +
298.3783 +	# The menu.lst file for gfxmenu
298.3784 +	default=0
298.3785 +	timeout=5
298.3786 +	gfxmenu /message
298.3787 +	configfile /another.lst
298.3788 +	title 0..........
298.3789 +	................
298.3790 +	title 1..........
298.3791 +	................
298.3792 +	title 2..........
298.3793 +	................
298.3794 +	# End of menu.lst
298.3795 +
298.3796 +	# Begin another.lst
298.3797 +	default=0
298.3798 +	timeout=5
298.3799 +	title 0..........
298.3800 +	................
298.3801 +	title 1..........
298.3802 +	................
298.3803 +	title 2..........
298.3804 +	................
298.3805 +	# End of another.lst
298.3806 +
298.3807 +This will try gfxmenu command first. On exit(or on failure) control will go
298.3808 +to another.lst file.
298.3809 +
298.3810 +
298.3811 +******************************************************************************
298.3812 +***                   a range of drives can be unmapped                    ***
298.3813 +******************************************************************************
298.3814 +
298.3815 +Usage:
298.3816 +
298.3817 +	map --unmap=RANGE
298.3818 +
298.3819 +RANGE is a range of BIOS drive numbers to be unmapped. BIOS drive number 0
298.3820 +is for the first floppy, 1 is for the second floppy; 0x80 is for the first
298.3821 +hard drive, 0x81 is for the second hard drive, etc; virtual cdrom (hd32)
298.3822 +corresponds to BIOS drive number 0xA0, (hd33) corresponds to 0xA1, etc.
298.3823 +
298.3824 +For description on RANGE, please refer to section `The New Command CHECKRANGE'
298.3825 +above.
298.3826 +
298.3827 +Example 1:
298.3828 +
298.3829 +	map --unmap=0,0x80,0xff
298.3830 +
298.3831 +This will unmap virtual floppy (fd0), virtual hard drive (hd0) and virtual
298.3832 +cdrom (0xff).
298.3833 +
298.3834 +Example 2:
298.3835 +
298.3836 +	map --unmap=0:0xff
298.3837 +
298.3838 +This will unmap all virtual floppies, all virtual hard drives and all virtual
298.3839 +cdroms.
298.3840 +
298.3841 +Note 1: Normally a `map' command will add an item in the drive map table for
298.3842 +	a virtual drive. But `--unmap' means items in the drive map table
298.3843 +	(for the specified virtual drives) will be deleted.
298.3844 +Note 2:	The --unhook option only breaks the INT13 hook(to the inerrupt
298.3845 +	vector table). It will not affect the drive map table. And later on
298.3846 +	execution of a `boot' command, the INT13 disk emulation routine will
298.3847 +	automatically get hooked(to the interrupt vector table) when needed
298.3848 +	(e.g., the drive map table is non-empty) even if it has been unhooked.
298.3849 +Note 3: Usually you want to do a `map --rehook' after you have changed the
298.3850 +	drive map table.
298.3851 +
298.3852 +
298.3853 +******************************************************************************
298.3854 +***                         geometry tune and sync                         ***
298.3855 +******************************************************************************
298.3856 +
298.3857 +When a USB storage device is connected to a (or another) machine, the geometry
298.3858 +in the partition table or in the BPB of the volume could be invalid, and the
298.3859 +machine could hang at boot time. So you need to find out the correct geometry
298.3860 +for the drive (use `geometry --tune'), and then update the geometry in
298.3861 +partition table and BPB of the drive(use `geometry --sync').
298.3862 +
298.3863 +The above steps are required if you are going to boot DOS, because DOS
298.3864 +requires the right geometry in the partition table and BPB. Windows/Linux may
298.3865 +also require it, since the boot process could run in real-mode.
298.3866 +
298.3867 +
   299.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/badgrub.exe has changed
   300.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/bootlace.com has changed
   301.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/chinese/badgrub.exe has changed
   302.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/chinese/grldr has changed
   303.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/chinese/grub.exe has changed
   304.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   304.2 +++ b/usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/config.sys	Mon Apr 26 11:16:23 2010 +0200
   304.3 @@ -0,0 +1,6 @@
   304.4 +rem load grub.exe before emm386.exe
   304.5 +device=grub.exe --bypass --time-out=5 --config-file="color black/cyan yellow/cyan;timeout 60;default 0;title find and load NTLDR of Windows NT/2K/XP;find --set-root /ntldr;chainloader /ntldr;title find and load CMLDR, the Recovery Console of Windows NT/2K/XP;find --set-root /cmldr;chainloader /cmldr;write 0x7C03 0x63646D63;write 0x7C07 0x00736E6F;title find and load IO.SYS of Windows 9x/Me;find --set-root /io.sys;chainloader /io.sys;title floppy (fd0);chainloader (fd0)+1;rootnoverify (fd0);title find and boot Linux with menu.lst already installed;find --set-root /sbin/init;configfile /boot/grub/menu.lst;title find and boot Mandriva with menu.lst already installed;find --set-root /etc/mandriva-release;configfile /boot/grub/menu.lst;title back to dos;quit;title commandline;commandline;title reboot;reboot;title halt;halt;"
   304.6 +
   304.7 +device=c:\windows\himem.sys
   304.8 +device=c:\windows\emm386.exe
   304.9 +
   305.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   305.2 +++ b/usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/default	Mon Apr 26 11:16:23 2010 +0200
   305.3 @@ -0,0 +1,46 @@
   305.4 +       
   305.5 +#
   305.6 +#
   305.7 +#
   305.8 +#
   305.9 +#
  305.10 +#
  305.11 +#
  305.12 +#
  305.13 +#
  305.14 +#
  305.15 +# !!!!!!! The file size is 2048 bytes. Don't change the file size !!!!!!!
  305.16 +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.17 +# XXXXXXXXXXXXXXXXXXXXX
  305.18 +# WARNING: If you want to edit this file directly, do not remove any line
  305.19 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.20 +# XXXXXXXXXXXXXXXXXXXXX
  305.21 +# WARNING: If you want to edit this file directly, do not remove any line
  305.22 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.23 +# XXXXXXXXXXXXXXXXXXXXX
  305.24 +# WARNING: If you want to edit this file directly, do not remove any line
  305.25 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.26 +# XXXXXXXXXXXXXXXXXXXXX
  305.27 +# WARNING: If you want to edit this file directly, do not remove any line
  305.28 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.29 +# XXXXXXXXXXXXXXXXXXXXX
  305.30 +# WARNING: If you want to edit this file directly, do not remove any line
  305.31 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.32 +# XXXXXXXXXXXXXXXXXXXXX
  305.33 +# WARNING: If you want to edit this file directly, do not remove any line
  305.34 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.35 +# XXXXXXXXXXXXXXXXXXXXX
  305.36 +# WARNING: If you want to edit this file directly, do not remove any line
  305.37 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.38 +# XXXXXXXXXXXXXXXXXXXXX
  305.39 +# WARNING: If you want to edit this file directly, do not remove any line
  305.40 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.41 +# XXXXXXXXXXXXXXXXXXXXX
  305.42 +# WARNING: If you want to edit this file directly, do not remove any line
  305.43 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.44 +# XXXXXXXXXXXXXXXXXXXXX
  305.45 +# WARNING: If you want to edit this file directly, do not remove any line
  305.46 +# from this file, including this warning. XXXXXXXXXXXXXXXXXXXXXXXXXXX
  305.47 +# XXXXXXXXXXXXXXXXXXXXX
  305.48 +# !!!!!!! The file size is 2048 bytes. Don't change the file size !!!!!!!
  305.49 +# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
   306.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/grldr has changed
   307.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/grldr.mbr has changed
   308.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/grub.exe has changed
   309.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/grub.pif has changed
   310.1 Binary file usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/hmload.com has changed
   311.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   311.2 +++ b/usr/share/doc/isi/grub4dos/win98/grub4dos-0.4.4/menu.lst	Mon Apr 26 11:16:23 2010 +0200
   311.3 @@ -0,0 +1,96 @@
   311.4 +# This is a sample menu.lst file. You should make some changes to it.
   311.5 +# The old install method of booting via the stage-files has been removed.
   311.6 +# Please install GRLDR boot strap code to MBR with the bootlace.com
   311.7 +# utility under DOS/Win9x or Linux.
   311.8 +
   311.9 +color blue/green yellow/red white/magenta white/magenta
  311.10 +timeout 30
  311.11 +default /default
  311.12 +
  311.13 +title find and load NTLDR of Windows NT/2K/XP
  311.14 +fallback 1
  311.15 +find --set-root --ignore-floppies /ntldr
  311.16 +chainloader /ntldr
  311.17 +savedefault --wait=2
  311.18 +
  311.19 +title find and load BOOTMGR of Windows VISTA
  311.20 +fallback 2
  311.21 +find --set-root --ignore-floppies /bootmgr
  311.22 +chainloader /bootmgr
  311.23 +savedefault --wait=2
  311.24 +
  311.25 +title find and load CMLDR, the Recovery Console of Windows NT/2K/XP
  311.26 +fallback 3
  311.27 +find --set-root --ignore-floppies /cmldr
  311.28 +chainloader /cmldr
  311.29 +#####################################################################
  311.30 +# write string "cmdcons" to memory 0000:7C03 in 2 steps:
  311.31 +#####################################################################
  311.32 +# step 1. Write 4 chars "cmdc" at 0000:7C03
  311.33 +write 0x7C03 0x63646D63
  311.34 +# step 2. Write 3 chars "ons" and an ending null at 0000:7C07
  311.35 +write 0x7C07 0x00736E6F
  311.36 +savedefault --wait=2
  311.37 +
  311.38 +title find and load IO.SYS of Windows 9x/Me
  311.39 +fallback 4
  311.40 +find --set-root /io.sys
  311.41 +chainloader /io.sys
  311.42 +savedefault --wait=2
  311.43 +
  311.44 +title find and boot 0PE.ISO
  311.45 +fallback 5
  311.46 +find --set-root /0PE/0PE.ISO
  311.47 +map /0PE/0PE.ISO (0xff) || map --mem /0PE/0PE.ISO (0xff)
  311.48 +map --hook
  311.49 +chainloader (0xff)
  311.50 +savedefault --wait=2
  311.51 +
  311.52 +title find and boot MicroPE.ISO
  311.53 +fallback 6
  311.54 +find --set-root /boot/MicroPE.ISO
  311.55 +map /boot/MicroPE.ISO (0xff) || map --mem /boot/MicroPE.ISO (0xff)
  311.56 +map --hook
  311.57 +chainloader (0xff)
  311.58 +savedefault --wait=2
  311.59 +
  311.60 +title Parted Magic ISO
  311.61 +fallback 7
  311.62 +find --set-root /pmagic.iso
  311.63 +map /pmagic.iso (0xff) || map --mem /pmagic.iso (0xff)
  311.64 +map --hook
  311.65 +chainloader (0xff)
  311.66 +savedefault --wait=2
  311.67 +
  311.68 +title Ultimate Boot CD ISO
  311.69 +fallback 8
  311.70 +find --set-root /ubcd.iso
  311.71 +map /ubcd.iso (0xff) || map --mem /ubcd.iso (0xff)
  311.72 +map --hook
  311.73 +chainloader (0xff)
  311.74 +savedefault --wait=2
  311.75 +
  311.76 +title commandline
  311.77 +commandline
  311.78 +
  311.79 +title floppy (fd0)
  311.80 +chainloader (fd0)+1
  311.81 +rootnoverify (fd0)
  311.82 +
  311.83 +title back to dos
  311.84 +quit
  311.85 +
  311.86 +title reboot
  311.87 +reboot
  311.88 +
  311.89 +title halt
  311.90 +halt
  311.91 +
  311.92 +title MAXDOS.IMG
  311.93 +find --set-root --ignore-floppies /boot/MAXDOS.IMG
  311.94 +map --mem /boot/MAXDOS.IMG (fd0)
  311.95 +map --hook
  311.96 +chainloader (fd0)+1
  311.97 +rootnoverify (fd0)
  311.98 +
  311.99 +
   312.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   312.2 +++ b/usr/share/doc/isi/grub4dos/win98/installa_grub.bat.bat	Mon Apr 26 11:16:23 2010 +0200
   312.3 @@ -0,0 +1,15 @@
   312.4 +@echo off
   312.5 +
   312.6 +:: DISCO=0x80 : MBR del primo disco
   312.7 +:: DISCO=0x81 : MBR del secondo disco
   312.8 +
   312.9 +SET BOOTLACE=grub4dos-0.4.4\bootlace.com
  312.10 +SET DISCO=0x80
  312.11 +
  312.12 +echo Installo grub nel MBR del disco %DISCO% ...
  312.13 +%BOOTLACE% %DISCO%
  312.14 +
  312.15 +echo Copio i file necessari ...
  312.16 +xcopy /E /Y /Q c\* c:\
  312.17 +
  312.18 +exit
   313.1 Binary file usr/share/doc/isi/grub4dos/xp/c/boot/grub/gpxe.iso has changed
   314.1 Binary file usr/share/doc/isi/grub4dos/xp/c/grldr has changed
   315.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   315.2 +++ b/usr/share/doc/isi/grub4dos/xp/c/menu.lst	Mon Apr 26 11:16:23 2010 +0200
   315.3 @@ -0,0 +1,16 @@
   315.4 +color blue/white white/green white/blue white/blue 
   315.5 +timeout 10
   315.6 +default 0
   315.7 +
   315.8 +title Linux (LTSP via gPXE)
   315.9 +find --set-root /boot/grub/gpxe.iso
  315.10 +map /boot/grub/gpxe.iso (0xff) || map --mem /boot/grub/gpxe.iso (0xff)
  315.11 +map --hook
  315.12 +chainloader (0xff)
  315.13 +
  315.14 +title Windows XP/2K/NT
  315.15 +find --set-root --ignore-floppies /ntldr
  315.16 +chainloader /ntldr
  315.17 +
  315.18 +title halt
  315.19 +halt
   316.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   316.2 +++ b/usr/share/doc/isi/grub4dos/xp/grubinst/COPYING	Mon Apr 26 11:16:23 2010 +0200
   316.3 @@ -0,0 +1,674 @@
   316.4 +                    GNU GENERAL PUBLIC LICENSE
   316.5 +                       Version 3, 29 June 2021
   316.6 +
   316.7 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
   316.8 + Everyone is permitted to copy and distribute verbatim copies
   316.9 + of this license document, but changing it is not allowed.
  316.10 +
  316.11 +                            Preamble
  316.12 +
  316.13 +  The GNU General Public License is a free, copyleft license for
  316.14 +software and other kinds of works.
  316.15 +
  316.16 +  The licenses for most software and other practical works are designed
  316.17 +to take away your freedom to share and change the works.  By contrast,
  316.18 +the GNU General Public License is intended to guarantee your freedom to
  316.19 +share and change all versions of a program--to make sure it remains free
  316.20 +software for all its users.  We, the Free Software Foundation, use the
  316.21 +GNU General Public License for most of our software; it applies also to
  316.22 +any other work released this way by its authors.  You can apply it to
  316.23 +your programs, too.
  316.24 +
  316.25 +  When we speak of free software, we are referring to freedom, not
  316.26 +price.  Our General Public Licenses are designed to make sure that you
  316.27 +have the freedom to distribute copies of free software (and charge for
  316.28 +them if you wish), that you receive source code or can get it if you
  316.29 +want it, that you can change the software or use pieces of it in new
  316.30 +free programs, and that you know you can do these things.
  316.31 +
  316.32 +  To protect your rights, we need to prevent others from denying you
  316.33 +these rights or asking you to surrender the rights.  Therefore, you have
  316.34 +certain responsibilities if you distribute copies of the software, or if
  316.35 +you modify it: responsibilities to respect the freedom of others.
  316.36 +
  316.37 +  For example, if you distribute copies of such a program, whether
  316.38 +gratis or for a fee, you must pass on to the recipients the same
  316.39 +freedoms that you received.  You must make sure that they, too, receive
  316.40 +or can get the source code.  And you must show them these terms so they
  316.41 +know their rights.
  316.42 +
  316.43 +  Developers that use the GNU GPL protect your rights with two steps:
  316.44 +(1) assert copyright on the software, and (2) offer you this License
  316.45 +giving you legal permission to copy, distribute and/or modify it.
  316.46 +
  316.47 +  For the developers' and authors' protection, the GPL clearly explains
  316.48 +that there is no warranty for this free software.  For both users' and
  316.49 +authors' sake, the GPL requires that modified versions be marked as
  316.50 +changed, so that their problems will not be attributed erroneously to
  316.51 +authors of previous versions.
  316.52 +
  316.53 +  Some devices are designed to deny users access to install or run
  316.54 +modified versions of the software inside them, although the manufacturer
  316.55 +can do so.  This is fundamentally incompatible with the aim of
  316.56 +protecting users' freedom to change the software.  The systematic
  316.57 +pattern of such abuse occurs in the area of products for individuals to
  316.58 +use, which is precisely where it is most unacceptable.  Therefore, we
  316.59 +have designed this version of the GPL to prohibit the practice for those
  316.60 +products.  If such problems arise substantially in other domains, we
  316.61 +stand ready to extend this provision to those domains in future versions
  316.62 +of the GPL, as needed to protect the freedom of users.
  316.63 +
  316.64 +  Finally, every program is threatened constantly by software patents.
  316.65 +States should not allow patents to restrict development and use of
  316.66 +software on general-purpose computers, but in those that do, we wish to
  316.67 +avoid the special danger that patents applied to a free program could
  316.68 +make it effectively proprietary.  To prevent this, the GPL assures that
  316.69 +patents cannot be used to render the program non-free.
  316.70 +
  316.71 +  The precise terms and conditions for copying, distribution and
  316.72 +modification follow.
  316.73 +
  316.74 +                       TERMS AND CONDITIONS
  316.75 +
  316.76 +  0. Definitions.
  316.77 +
  316.78 +  "This License" refers to version 3 of the GNU General Public License.
  316.79 +
  316.80 +  "Copyright" also means copyright-like laws that apply to other kinds of
  316.81 +works, such as semiconductor masks.
  316.82 +
  316.83 +  "The Program" refers to any copyrightable work licensed under this
  316.84 +License.  Each licensee is addressed as "you".  "Licensees" and
  316.85 +"recipients" may be individuals or organizations.
  316.86 +
  316.87 +  To "modify" a work means to copy from or adapt all or part of the work
  316.88 +in a fashion requiring copyright permission, other than the making of an
  316.89 +exact copy.  The resulting work is called a "modified version" of the
  316.90 +earlier work or a work "based on" the earlier work.
  316.91 +
  316.92 +  A "covered work" means either the unmodified Program or a work based
  316.93 +on the Program.
  316.94 +
  316.95 +  To "propagate" a work means to do anything with it that, without
  316.96 +permission, would make you directly or secondarily liable for
  316.97 +infringement under applicable copyright law, except executing it on a
  316.98 +computer or modifying a private copy.  Propagation includes copying,
  316.99 +distribution (with or without modification), making available to the
 316.100 +public, and in some countries other activities as well.
 316.101 +
 316.102 +  To "convey" a work means any kind of propagation that enables other
 316.103 +parties to make or receive copies.  Mere interaction with a user through
 316.104 +a computer network, with no transfer of a copy, is not conveying.
 316.105 +
 316.106 +  An interactive user interface displays "Appropriate Legal Notices"
 316.107 +to the extent that it includes a convenient and prominently visible
 316.108 +feature that (1) displays an appropriate copyright notice, and (2)
 316.109 +tells the user that there is no warranty for the work (except to the
 316.110 +extent that warranties are provided), that licensees may convey the
 316.111 +work under this License, and how to view a copy of this License.  If
 316.112 +the interface presents a list of user commands or options, such as a
 316.113 +menu, a prominent item in the list meets this criterion.
 316.114 +
 316.115 +  1. Source Code.
 316.116 +
 316.117 +  The "source code" for a work means the preferred form of the work
 316.118 +for making modifications to it.  "Object code" means any non-source
 316.119 +form of a work.
 316.120 +
 316.121 +  A "Standard Interface" means an interface that either is an official
 316.122 +standard defined by a recognized standards body, or, in the case of
 316.123 +interfaces specified for a particular programming language, one that
 316.124 +is widely used among developers working in that language.
 316.125 +
 316.126 +  The "System Libraries" of an executable work include anything, other
 316.127 +than the work as a whole, that (a) is included in the normal form of
 316.128 +packaging a Major Component, but which is not part of that Major
 316.129 +Component, and (b) serves only to enable use of the work with that
 316.130 +Major Component, or to implement a Standard Interface for which an
 316.131 +implementation is available to the public in source code form.  A
 316.132 +"Major Component", in this context, means a major essential component
 316.133 +(kernel, window system, and so on) of the specific operating system
 316.134 +(if any) on which the executable work runs, or a compiler used to
 316.135 +produce the work, or an object code interpreter used to run it.
 316.136 +
 316.137 +  The "Corresponding Source" for a work in object code form means all
 316.138 +the source code needed to generate, install, and (for an executable
 316.139 +work) run the object code and to modify the work, including scripts to
 316.140 +control those activities.  However, it does not include the work's
 316.141 +System Libraries, or general-purpose tools or generally available free
 316.142 +programs which are used unmodified in performing those activities but
 316.143 +which are not part of the work.  For example, Corresponding Source
 316.144 +includes interface definition files associated with source files for
 316.145 +the work, and the source code for shared libraries and dynamically
 316.146 +linked subprograms that the work is specifically designed to require,
 316.147 +such as by intimate data communication or control flow between those
 316.148 +subprograms and other parts of the work.
 316.149 +
 316.150 +  The Corresponding Source need not include anything that users
 316.151 +can regenerate automatically from other parts of the Corresponding
 316.152 +Source.
 316.153 +
 316.154 +  The Corresponding Source for a work in source code form is that
 316.155 +same work.
 316.156 +
 316.157 +  2. Basic Permissions.
 316.158 +
 316.159 +  All rights granted under this License are granted for the term of
 316.160 +copyright on the Program, and are irrevocable provided the stated
 316.161 +conditions are met.  This License explicitly affirms your unlimited
 316.162 +permission to run the unmodified Program.  The output from running a
 316.163 +covered work is covered by this License only if the output, given its
 316.164 +content, constitutes a covered work.  This License acknowledges your
 316.165 +rights of fair use or other equivalent, as provided by copyright law.
 316.166 +
 316.167 +  You may make, run and propagate covered works that you do not
 316.168 +convey, without conditions so long as your license otherwise remains
 316.169 +in force.  You may convey covered works to others for the sole purpose
 316.170 +of having them make modifications exclusively for you, or provide you
 316.171 +with facilities for running those works, provided that you comply with
 316.172 +the terms of this License in conveying all material for which you do
 316.173 +not control copyright.  Those thus making or running the covered works
 316.174 +for you must do so exclusively on your behalf, under your direction
 316.175 +and control, on terms that prohibit them from making any copies of
 316.176 +your copyrighted material outside their relationship with you.
 316.177 +
 316.178 +  Conveying under any other circumstances is permitted solely under
 316.179 +the conditions stated below.  Sublicensing is not allowed; section 10
 316.180 +makes it unnecessary.
 316.181 +
 316.182 +  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 316.183 +
 316.184 +  No covered work shall be deemed part of an effective technological
 316.185 +measure under any applicable law fulfilling obligations under article
 316.186 +11 of the WIPO copyright treaty adopted on 20 December 1996, or
 316.187 +similar laws prohibiting or restricting circumvention of such
 316.188 +measures.
 316.189 +
 316.190 +  When you convey a covered work, you waive any legal power to forbid
 316.191 +circumvention of technological measures to the extent such circumvention
 316.192 +is effected by exercising rights under this License with respect to
 316.193 +the covered work, and you disclaim any intention to limit operation or
 316.194 +modification of the work as a means of enforcing, against the work's
 316.195 +users, your or third parties' legal rights to forbid circumvention of
 316.196 +technological measures.
 316.197 +
 316.198 +  4. Conveying Verbatim Copies.
 316.199 +
 316.200 +  You may convey verbatim copies of the Program's source code as you
 316.201 +receive it, in any medium, provided that you conspicuously and
 316.202 +appropriately publish on each copy an appropriate copyright notice;
 316.203 +keep intact all notices stating that this License and any
 316.204 +non-permissive terms added in accord with section 7 apply to the code;
 316.205 +keep intact all notices of the absence of any warranty; and give all
 316.206 +recipients a copy of this License along with the Program.
 316.207 +
 316.208 +  You may charge any price or no price for each copy that you convey,
 316.209 +and you may offer support or warranty protection for a fee.
 316.210 +
 316.211 +  5. Conveying Modified Source Versions.
 316.212 +
 316.213 +  You may convey a work based on the Program, or the modifications to
 316.214 +produce it from the Program, in the form of source code under the
 316.215 +terms of section 4, provided that you also meet all of these conditions:
 316.216 +
 316.217 +    a) The work must carry prominent notices stating that you modified
 316.218 +    it, and giving a relevant date.
 316.219 +
 316.220 +    b) The work must carry prominent notices stating that it is
 316.221 +    released under this License and any conditions added under section
 316.222 +    7.  This requirement modifies the requirement in section 4 to
 316.223 +    "keep intact all notices".
 316.224 +
 316.225 +    c) You must license the entire work, as a whole, under this
 316.226 +    License to anyone who comes into possession of a copy.  This
 316.227 +    License will therefore apply, along with any applicable section 7
 316.228 +    additional terms, to the whole of the work, and all its parts,
 316.229 +    regardless of how they are packaged.  This License gives no
 316.230 +    permission to license the work in any other way, but it does not
 316.231 +    invalidate such permission if you have separately received it.
 316.232 +
 316.233 +    d) If the work has interactive user interfaces, each must display
 316.234 +    Appropriate Legal Notices; however, if the Program has interactive
 316.235 +    interfaces that do not display Appropriate Legal Notices, your
 316.236 +    work need not make them do so.
 316.237 +
 316.238 +  A compilation of a covered work with other separate and independent
 316.239 +works, which are not by their nature extensions of the covered work,
 316.240 +and which are not combined with it such as to form a larger program,
 316.241 +in or on a volume of a storage or distribution medium, is called an
 316.242 +"aggregate" if the compilation and its resulting copyright are not
 316.243 +used to limit the access or legal rights of the compilation's users
 316.244 +beyond what the individual works permit.  Inclusion of a covered work
 316.245 +in an aggregate does not cause this License to apply to the other
 316.246 +parts of the aggregate.
 316.247 +
 316.248 +  6. Conveying Non-Source Forms.
 316.249 +
 316.250 +  You may convey a covered work in object code form under the terms
 316.251 +of sections 4 and 5, provided that you also convey the
 316.252 +machine-readable Corresponding Source under the terms of this License,
 316.253 +in one of these ways:
 316.254 +
 316.255 +    a) Convey the object code in, or embodied in, a physical product
 316.256 +    (including a physical distribution medium), accompanied by the
 316.257 +    Corresponding Source fixed on a durable physical medium
 316.258 +    customarily used for software interchange.
 316.259 +
 316.260 +    b) Convey the object code in, or embodied in, a physical product
 316.261 +    (including a physical distribution medium), accompanied by a
 316.262 +    written offer, valid for at least three years and valid for as
 316.263 +    long as you offer spare parts or customer support for that product
 316.264 +    model, to give anyone who possesses the object code either (1) a
 316.265 +    copy of the Corresponding Source for all the software in the
 316.266 +    product that is covered by this License, on a durable physical
 316.267 +    medium customarily used for software interchange, for a price no
 316.268 +    more than your reasonable cost of physically performing this
 316.269 +    conveying of source, or (2) access to copy the
 316.270 +    Corresponding Source from a network server at no charge.
 316.271 +
 316.272 +    c) Convey individual copies of the object code with a copy of the
 316.273 +    written offer to provide the Corresponding Source.  This
 316.274 +    alternative is allowed only occasionally and noncommercially, and
 316.275 +    only if you received the object code with such an offer, in accord
 316.276 +    with subsection 6b.
 316.277 +
 316.278 +    d) Convey the object code by offering access from a designated
 316.279 +    place (gratis or for a charge), and offer equivalent access to the
 316.280 +    Corresponding Source in the same way through the same place at no
 316.281 +    further charge.  You need not require recipients to copy the
 316.282 +    Corresponding Source along with the object code.  If the place to
 316.283 +    copy the object code is a network server, the Corresponding Source
 316.284 +    may be on a different server (operated by you or a third party)
 316.285 +    that supports equivalent copying facilities, provided you maintain
 316.286 +    clear directions next to the object code saying where to find the
 316.287 +    Corresponding Source.  Regardless of what server hosts the
 316.288 +    Corresponding Source, you remain obligated to ensure that it is
 316.289 +    available for as long as needed to satisfy these requirements.
 316.290 +
 316.291 +    e) Convey the object code using peer-to-peer transmission, provided
 316.292 +    you inform other peers where the object code and Corresponding
 316.293 +    Source of the work are being offered to the general public at no
 316.294 +    charge under subsection 6d.
 316.295 +
 316.296 +  A separable portion of the object code, whose source code is excluded
 316.297 +from the Corresponding Source as a System Library, need not be
 316.298 +included in conveying the object code work.
 316.299 +
 316.300 +  A "User Product" is either (1) a "consumer product", which means any
 316.301 +tangible personal property which is normally used for personal, family,
 316.302 +or household purposes, or (2) anything designed or sold for incorporation
 316.303 +into a dwelling.  In determining whether a product is a consumer product,
 316.304 +doubtful cases shall be resolved in favor of coverage.  For a particular
 316.305 +product received by a particular user, "normally used" refers to a
 316.306 +typical or common use of that class of product, regardless of the status
 316.307 +of the particular user or of the way in which the particular user
 316.308 +actually uses, or expects or is expected to use, the product.  A product
 316.309 +is a consumer product regardless of whether the product has substantial
 316.310 +commercial, industrial or non-consumer uses, unless such uses represent
 316.311 +the only significant mode of use of the product.
 316.312 +
 316.313 +  "Installation Information" for a User Product means any methods,
 316.314 +procedures, authorization keys, or other information required to install
 316.315 +and execute modified versions of a covered work in that User Product from
 316.316 +a modified version of its Corresponding Source.  The information must
 316.317 +suffice to ensure that the continued functioning of the modified object
 316.318 +code is in no case prevented or interfered with solely because
 316.319 +modification has been made.
 316.320 +
 316.321 +  If you convey an object code work under this section in, or with, or
 316.322 +specifically for use in, a User Product, and the conveying occurs as
 316.323 +part of a transaction in which the right of possession and use of the
 316.324 +User Product is transferred to the recipient in perpetuity or for a
 316.325 +fixed term (regardless of how the transaction is characterized), the
 316.326 +Corresponding Source conveyed under this section must be accompanied
 316.327 +by the Installation Information.  But this requirement does not apply
 316.328 +if neither you nor any third party retains the ability to install
 316.329 +modified object code on the User Product (for example, the work has
 316.330 +been installed in ROM).
 316.331 +
 316.332 +  The requirement to provide Installation Information does not include a
 316.333 +requirement to continue to provide support service, warranty, or updates
 316.334 +for a work that has been modified or installed by the recipient, or for
 316.335 +the User Product in which it has been modified or installed.  Access to a
 316.336 +network may be denied when the modification itself materially and
 316.337 +adversely affects the operation of the network or violates the rules and
 316.338 +protocols for communication across the network.
 316.339 +
 316.340 +  Corresponding Source conveyed, and Installation Information provided,
 316.341 +in accord with this section must be in a format that is publicly
 316.342 +documented (and with an implementation available to the public in
 316.343 +source code form), and must require no special password or key for
 316.344 +unpacking, reading or copying.
 316.345 +
 316.346 +  7. Additional Terms.
 316.347 +
 316.348 +  "Additional permissions" are terms that supplement the terms of this
 316.349 +License by making exceptions from one or more of its conditions.
 316.350 +Additional permissions that are applicable to the entire Program shall
 316.351 +be treated as though they were included in this License, to the extent
 316.352 +that they are valid under applicable law.  If additional permissions
 316.353 +apply only to part of the Program, that part may be used separately
 316.354 +under those permissions, but the entire Program remains governed by
 316.355 +this License without regard to the additional permissions.
 316.356 +
 316.357 +  When you convey a copy of a covered work, you may at your option
 316.358 +remove any additional permissions from that copy, or from any part of
 316.359 +it.  (Additional permissions may be written to require their own
 316.360 +removal in certain cases when you modify the work.)  You may place
 316.361 +additional permissions on material, added by you to a covered work,
 316.362 +for which you have or can give appropriate copyright permission.
 316.363 +
 316.364 +  Notwithstanding any other provision of this License, for material you
 316.365 +add to a covered work, you may (if authorized by the copyright holders of
 316.366 +that material) supplement the terms of this License with terms:
 316.367 +
 316.368 +    a) Disclaiming warranty or limiting liability differently from the
 316.369 +    terms of sections 15 and 16 of this License; or
 316.370 +
 316.371 +    b) Requiring preservation of specified reasonable legal notices or
 316.372 +    author attributions in that material or in the Appropriate Legal
 316.373 +    Notices displayed by works containing it; or
 316.374 +
 316.375 +    c) Prohibiting misrepresentation of the origin of that material, or
 316.376 +    requiring that modified versions of such material be marked in
 316.377 +    reasonable ways as different from the original version; or
 316.378 +
 316.379 +    d) Limiting the use for publicity purposes of names of licensors or
 316.380 +    authors of the material; or
 316.381 +
 316.382 +    e) Declining to grant rights under trademark law for use of some
 316.383 +    trade names, trademarks, or service marks; or
 316.384 +
 316.385 +    f) Requiring indemnification of licensors and authors of that
 316.386 +    material by anyone who conveys the material (or modified versions of
 316.387 +    it) with contractual assumptions of liability to the recipient, for
 316.388 +    any liability that these contractual assumptions directly impose on
 316.389 +    those licensors and authors.
 316.390 +
 316.391 +  All other non-permissive additional terms are considered "further
 316.392 +restrictions" within the meaning of section 10.  If the Program as you
 316.393 +received it, or any part of it, contains a notice stating that it is
 316.394 +governed by this License along with a term that is a further
 316.395 +restriction, you may remove that term.  If a license document contains
 316.396 +a further restriction but permits relicensing or conveying under this
 316.397 +License, you may add to a covered work material governed by the terms
 316.398 +of that license document, provided that the further restriction does
 316.399 +not survive such relicensing or conveying.
 316.400 +
 316.401 +  If you add terms to a covered work in accord with this section, you
 316.402 +must place, in the relevant source files, a statement of the
 316.403 +additional terms that apply to those files, or a notice indicating
 316.404 +where to find the applicable terms.
 316.405 +
 316.406 +  Additional terms, permissive or non-permissive, may be stated in the
 316.407 +form of a separately written license, or stated as exceptions;
 316.408 +the above requirements apply either way.
 316.409 +
 316.410 +  8. Termination.
 316.411 +
 316.412 +  You may not propagate or modify a covered work except as expressly
 316.413 +provided under this License.  Any attempt otherwise to propagate or
 316.414 +modify it is void, and will automatically terminate your rights under
 316.415 +this License (including any patent licenses granted under the third
 316.416 +paragraph of section 11).
 316.417 +
 316.418 +  However, if you cease all violation of this License, then your
 316.419 +license from a particular copyright holder is reinstated (a)
 316.420 +provisionally, unless and until the copyright holder explicitly and
 316.421 +finally terminates your license, and (b) permanently, if the copyright
 316.422 +holder fails to notify you of the violation by some reasonable means
 316.423 +prior to 60 days after the cessation.
 316.424 +
 316.425 +  Moreover, your license from a particular copyright holder is
 316.426 +reinstated permanently if the copyright holder notifies you of the
 316.427 +violation by some reasonable means, this is the first time you have
 316.428 +received notice of violation of this License (for any work) from that
 316.429 +copyright holder, and you cure the violation prior to 30 days after
 316.430 +your receipt of the notice.
 316.431 +
 316.432 +  Termination of your rights under this section does not terminate the
 316.433 +licenses of parties who have received copies or rights from you under
 316.434 +this License.  If your rights have been terminated and not permanently
 316.435 +reinstated, you do not qualify to receive new licenses for the same
 316.436 +material under section 10.
 316.437 +
 316.438 +  9. Acceptance Not Required for Having Copies.
 316.439 +
 316.440 +  You are not required to accept this License in order to receive or
 316.441 +run a copy of the Program.  Ancillary propagation of a covered work
 316.442 +occurring solely as a consequence of using peer-to-peer transmission
 316.443 +to receive a copy likewise does not require acceptance.  However,
 316.444 +nothing other than this License grants you permission to propagate or
 316.445 +modify any covered work.  These actions infringe copyright if you do
 316.446 +not accept this License.  Therefore, by modifying or propagating a
 316.447 +covered work, you indicate your acceptance of this License to do so.
 316.448 +
 316.449 +  10. Automatic Licensing of Downstream Recipients.
 316.450 +
 316.451 +  Each time you convey a covered work, the recipient automatically
 316.452 +receives a license from the original licensors, to run, modify and
 316.453 +propagate that work, subject to this License.  You are not responsible
 316.454 +for enforcing compliance by third parties with this License.
 316.455 +
 316.456 +  An "entity transaction" is a transaction transferring control of an
 316.457 +organization, or substantially all assets of one, or subdividing an
 316.458 +organization, or merging organizations.  If propagation of a covered
 316.459 +work results from an entity transaction, each party to that
 316.460 +transaction who receives a copy of the work also receives whatever
 316.461 +licenses to the work the party's predecessor in interest had or could
 316.462 +give under the previous paragraph, plus a right to possession of the
 316.463 +Corresponding Source of the work from the predecessor in interest, if
 316.464 +the predecessor has it or can get it with reasonable efforts.
 316.465 +
 316.466 +  You may not impose any further restrictions on the exercise of the
 316.467 +rights granted or affirmed under this License.  For example, you may
 316.468 +not impose a license fee, royalty, or other charge for exercise of
 316.469 +rights granted under this License, and you may not initiate litigation
 316.470 +(including a cross-claim or counterclaim in a lawsuit) alleging that
 316.471 +any patent claim is infringed by making, using, selling, offering for
 316.472 +sale, or importing the Program or any portion of it.
 316.473 +
 316.474 +  11. Patents.
 316.475 +
 316.476 +  A "contributor" is a copyright holder who authorizes use under this
 316.477 +License of the Program or a work on which the Program is based.  The
 316.478 +work thus licensed is called the contributor's "contributor version".
 316.479 +
 316.480 +  A contributor's "essential patent claims" are all patent claims
 316.481 +owned or controlled by the contributor, whether already acquired or
 316.482 +hereafter acquired, that would be infringed by some manner, permitted
 316.483 +by this License, of making, using, or selling its contributor version,
 316.484 +but do not include claims that would be infringed only as a
 316.485 +consequence of further modification of the contributor version.  For
 316.486 +purposes of this definition, "control" includes the right to grant
 316.487 +patent sublicenses in a manner consistent with the requirements of
 316.488 +this License.
 316.489 +
 316.490 +  Each contributor grants you a non-exclusive, worldwide, royalty-free
 316.491 +patent license under the contributor's essential patent claims, to
 316.492 +make, use, sell, offer for sale, import and otherwise run, modify and
 316.493 +propagate the contents of its contributor version.
 316.494 +
 316.495 +  In the following three paragraphs, a "patent license" is any express
 316.496 +agreement or commitment, however denominated, not to enforce a patent
 316.497 +(such as an express permission to practice a patent or covenant not to
 316.498 +sue for patent infringement).  To "grant" such a patent license to a
 316.499 +party means to make such an agreement or commitment not to enforce a
 316.500 +patent against the party.
 316.501 +
 316.502 +  If you convey a covered work, knowingly relying on a patent license,
 316.503 +and the Corresponding Source of the work is not available for anyone
 316.504 +to copy, free of charge and under the terms of this License, through a
 316.505 +publicly available network server or other readily accessible means,
 316.506 +then you must either (1) cause the Corresponding Source to be so
 316.507 +available, or (2) arrange to deprive yourself of the benefit of the
 316.508 +patent license for this particular work, or (3) arrange, in a manner
 316.509 +consistent with the requirements of this License, to extend the patent
 316.510 +license to downstream recipients.  "Knowingly relying" means you have
 316.511 +actual knowledge that, but for the patent license, your conveying the
 316.512 +covered work in a country, or your recipient's use of the covered work
 316.513 +in a country, would infringe one or more identifiable patents in that
 316.514 +country that you have reason to believe are valid.
 316.515 +
 316.516 +  If, pursuant to or in connection with a single transaction or
 316.517 +arrangement, you convey, or propagate by procuring conveyance of, a
 316.518 +covered work, and grant a patent license to some of the parties
 316.519 +receiving the covered work authorizing them to use, propagate, modify
 316.520 +or convey a specific copy of the covered work, then the patent license
 316.521 +you grant is automatically extended to all recipients of the covered
 316.522 +work and works based on it.
 316.523 +
 316.524 +  A patent license is "discriminatory" if it does not include within
 316.525 +the scope of its coverage, prohibits the exercise of, or is
 316.526 +conditioned on the non-exercise of one or more of the rights that are
 316.527 +specifically granted under this License.  You may not convey a covered
 316.528 +work if you are a party to an arrangement with a third party that is
 316.529 +in the business of distributing software, under which you make payment
 316.530 +to the third party based on the extent of your activity of conveying
 316.531 +the work, and under which the third party grants, to any of the
 316.532 +parties who would receive the covered work from you, a discriminatory
 316.533 +patent license (a) in connection with copies of the covered work
 316.534 +conveyed by you (or copies made from those copies), or (b) primarily
 316.535 +for and in connection with specific products or compilations that
 316.536 +contain the covered work, unless you entered into that arrangement,
 316.537 +or that patent license was granted, prior to 28 March 2007.
 316.538 +
 316.539 +  Nothing in this License shall be construed as excluding or limiting
 316.540 +any implied license or other defenses to infringement that may
 316.541 +otherwise be available to you under applicable patent law.
 316.542 +
 316.543 +  12. No Surrender of Others' Freedom.
 316.544 +
 316.545 +  If conditions are imposed on you (whether by court order, agreement or
 316.546 +otherwise) that contradict the conditions of this License, they do not
 316.547 +excuse you from the conditions of this License.  If you cannot convey a
 316.548 +covered work so as to satisfy simultaneously your obligations under this
 316.549 +License and any other pertinent obligations, then as a consequence you may
 316.550 +not convey it at all.  For example, if you agree to terms that obligate you
 316.551 +to collect a royalty for further conveying from those to whom you convey
 316.552 +the Program, the only way you could satisfy both those terms and this
 316.553 +License would be to refrain entirely from conveying the Program.
 316.554 +
 316.555 +  13. Use with the GNU Affero General Public License.
 316.556 +
 316.557 +  Notwithstanding any other provision of this License, you have
 316.558 +permission to link or combine any covered work with a work licensed
 316.559 +under version 3 of the GNU Affero General Public License into a single
 316.560 +combined work, and to convey the resulting work.  The terms of this
 316.561 +License will continue to apply to the part which is the covered work,
 316.562 +but the special requirements of the GNU Affero General Public License,
 316.563 +section 13, concerning interaction through a network will apply to the
 316.564 +combination as such.
 316.565 +
 316.566 +  14. Revised Versions of this License.
 316.567 +
 316.568 +  The Free Software Foundation may publish revised and/or new versions of
 316.569 +the GNU General Public License from time to time.  Such new versions will
 316.570 +be similar in spirit to the present version, but may differ in detail to
 316.571 +address new problems or concerns.
 316.572 +
 316.573 +  Each version is given a distinguishing version number.  If the
 316.574 +Program specifies that a certain numbered version of the GNU General
 316.575 +Public License "or any later version" applies to it, you have the
 316.576 +option of following the terms and conditions either of that numbered
 316.577 +version or of any later version published by the Free Software
 316.578 +Foundation.  If the Program does not specify a version number of the
 316.579 +GNU General Public License, you may choose any version ever published
 316.580 +by the Free Software Foundation.
 316.581 +
 316.582 +  If the Program specifies that a proxy can decide which future
 316.583 +versions of the GNU General Public License can be used, that proxy's
 316.584 +public statement of acceptance of a version permanently authorizes you
 316.585 +to choose that version for the Program.
 316.586 +
 316.587 +  Later license versions may give you additional or different
 316.588 +permissions.  However, no additional obligations are imposed on any
 316.589 +author or copyright holder as a result of your choosing to follow a
 316.590 +later version.
 316.591 +
 316.592 +  15. Disclaimer of Warranty.
 316.593 +
 316.594 +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
 316.595 +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
 316.596 +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
 316.597 +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 316.598 +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 316.599 +PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
 316.600 +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
 316.601 +ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 316.602 +
 316.603 +  16. Limitation of Liability.
 316.604 +
 316.605 +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 316.606 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
 316.607 +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
 316.608 +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
 316.609 +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
 316.610 +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
 316.611 +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
 316.612 +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
 316.613 +SUCH DAMAGES.
 316.614 +
 316.615 +  17. Interpretation of Sections 15 and 16.
 316.616 +
 316.617 +  If the disclaimer of warranty and limitation of liability provided
 316.618 +above cannot be given local legal effect according to their terms,
 316.619 +reviewing courts shall apply local law that most closely approximates
 316.620 +an absolute waiver of all civil liability in connection with the
 316.621 +Program, unless a warranty or assumption of liability accompanies a
 316.622 +copy of the Program in return for a fee.
 316.623 +
 316.624 +                     END OF TERMS AND CONDITIONS
 316.625 +
 316.626 +            How to Apply These Terms to Your New Programs
 316.627 +
 316.628 +  If you develop a new program, and you want it to be of the greatest
 316.629 +possible use to the public, the best way to achieve this is to make it
 316.630 +free software which everyone can redistribute and change under these terms.
 316.631 +
 316.632 +  To do so, attach the following notices to the program.  It is safest
 316.633 +to attach them to the start of each source file to most effectively
 316.634 +state the exclusion of warranty; and each file should have at least
 316.635 +the "copyright" line and a pointer to where the full notice is found.
 316.636 +
 316.637 +    <one line to give the program's name and a brief idea of what it does.>
 316.638 +    Copyright (C) <year>  <name of author>
 316.639 +
 316.640 +    This program is free software: you can redistribute it and/or modify
 316.641 +    it under the terms of the GNU General Public License as published by
 316.642 +    the Free Software Foundation, either version 3 of the License, or
 316.643 +    (at your option) any later version.
 316.644 +
 316.645 +    This program is distributed in the hope that it will be useful,
 316.646 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
 316.647 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 316.648 +    GNU General Public License for more details.
 316.649 +
 316.650 +    You should have received a copy of the GNU General Public License
 316.651 +    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 316.652 +
 316.653 +Also add information on how to contact you by electronic and paper mail.
 316.654 +
 316.655 +  If the program does terminal interaction, make it output a short
 316.656 +notice like this when it starts in an interactive mode:
 316.657 +
 316.658 +    <program>  Copyright (C) <year>  <name of author>
 316.659 +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 316.660 +    This is free software, and you are welcome to redistribute it
 316.661 +    under certain conditions; type `show c' for details.
 316.662 +
 316.663 +The hypothetical commands `show w' and `show c' should show the appropriate
 316.664 +parts of the General Public License.  Of course, your program's commands
 316.665 +might be different; for a GUI interface, you would use an "about box".
 316.666 +
 316.667 +  You should also get your employer (if you work as a programmer) or school,
 316.668 +if any, to sign a "copyright disclaimer" for the program, if necessary.
 316.669 +For more information on this, and how to apply and follow the GNU GPL, see
 316.670 +<http://www.gnu.org/licenses/>.
 316.671 +
 316.672 +  The GNU General Public License does not permit incorporating your program
 316.673 +into proprietary programs.  If your program is a subroutine library, you
 316.674 +may consider it more useful to permit linking proprietary applications with
 316.675 +the library.  If this is what you want to do, use the GNU Lesser General
 316.676 +Public License instead of this License.  But first, please read
 316.677 +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
   317.1 Binary file usr/share/doc/isi/grub4dos/xp/grubinst/grubinst.exe has changed
   318.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   318.2 +++ b/usr/share/doc/isi/grub4dos/xp/grubinst/grubinst_gui.chs	Mon Apr 26 11:16:23 2010 +0200
   318.3 @@ -0,0 +1,44 @@
   318.4 +100=�豸
   318.5 +101=����
   318.6 +103=ˢ��
   318.7 +104=�ļ�
   318.8 +106=���
   318.9 +107=�����б�
  318.10 +109=ˢ��
  318.11 +110=���������Ƕ���GRLDR.MBR
  318.12 +
  318.13 +120=ѡ��
  318.14 +121=ֻ��ģʽ
  318.15 +122=�����ϸ��Ϣ
  318.16 +123=������ԭ��MBR
  318.17 +124=����ʱ����������
  318.18 +125=������ԭ��MBR
  318.19 +126=��������ԭ��MBR
  318.20 +127=Grub�ڶ���
  318.21 +128=����ӳ��
  318.22 +129=�ȴ�ʱ��
  318.23 +131=�ȼ�
  318.24 +133=װ�ض�
  318.25 +135=�����ļ�
  318.26 +137=�������
  318.27 +
  318.28 +140=�ָ�
  318.29 +141=�����ļ�
  318.30 +143=���
  318.31 +144=���ļ��лָ�
  318.32 +145=��ԭ��MBR�лָ�
  318.33 +
  318.34 +160=����
  318.35 +161=��װ
  318.36 +162=�˳�
  318.37 +
  318.38 +500=Grub4Dos ��װ����
  318.39 +501=û��ָ�������ļ�
  318.40 +502=������������
  318.41 +503=�ļ�������Ϊ��
  318.42 +504=û��ָ���豸����
  318.43 +505=���к�̨�������
  318.44 +506=�����ļ��Ƿ�
  318.45 +507=��������
  318.46 +508=����ʹ���豸��
  318.47 +509=�Ƿ��������������Ȼϣ����װ����ʹ��--skip-mbr-testѡ��
  318.48 \ No newline at end of file
   319.1 Binary file usr/share/doc/isi/grub4dos/xp/grubinst/grubinst_gui.exe has changed
   320.1 Binary file usr/share/doc/isi/grub4dos/xp/grubinst/grubmenu.exe has changed
   321.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   321.2 +++ b/usr/share/doc/isi/grub4dos/xp/grubinst/readme.txt	Mon Apr 26 11:16:23 2010 +0200
   321.3 @@ -0,0 +1,42 @@
   321.4 +1. Introdution
   321.5 +
   321.6 +This utility is used to install GRUB4DOS boot code to the MBR or partition
   321.7 +boot sector of hard disk or image file.
   321.8 +
   321.9 +grubinst.exe is a console mode program. It mimics the behavior of the DOS/Linux
  321.10 +utility bootlace.com from TinyBit's GRUB4DOS package. But unlike bootlace.com,
  321.11 +grubinst is writen completely in C and can be compiled to run in OSs like
  321.12 +Windows NT/2K/XP, Linux and FreeBSD.
  321.13 +
  321.14 +grubinst_gui.exe is a GUI frontend to grubinst.exe. It provides a friendly
  321.15 +interface to users who are not familiar whith the command line environment.
  321.16 +Currently, grubinst_gui.exe only runs in Windows OSs.
  321.17 +
  321.18 +Please note that these utilities only install MBR, it DOES NOT copy GRLDR to
  321.19 +your partition or configure menu.lst, neither does it modify boot.ini to enable
  321.20 +booting from the NT boot manager. To know more about such things, please refers
  321.21 +to readme file from the GRUB4DOS package.
  321.22 +
  321.23 +Also note that the current version of grubinst doesn't support modify the MBR
  321.24 +of hard disk in Windows 95/98/ME. For those OSs, bootlace.com should be used
  321.25 +instead.
  321.26 +
  321.27 +2. Documents
  321.28 +
  321.29 +Documents have been moved to the grub4dos homepage at sourceforge.net:
  321.30 +
  321.31 +http://grub4dos.sourceforge.net
  321.32 +
  321.33 +3. Useful links
  321.34 +
  321.35 +http://grub4dos.sourceforge.net/
  321.36 +grubinst and wingrub homepage
  321.37 +
  321.38 +http://grub4dos.jot.com/
  321.39 +Latest GRUB4DOS package by TinyBit
  321.40 +
  321.41 +http://www.znpc.net/bbs
  321.42 +Chinese forum on GRUB4DOS
  321.43 +
  321.44 +http://grub.linuxeden.com/
  321.45 +Misc information by TinyBit, also in chinese
   322.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   322.2 +++ b/usr/share/doc/isi/grub4dos/xp/installa_grub_personalizzata.bat.bat	Mon Apr 26 11:16:23 2010 +0200
   322.3 @@ -0,0 +1,11 @@
   322.4 +@echo off
   322.5 +
   322.6 +SET GRUBINSTGUI=grubinst\grubinst_gui
   322.7 +
   322.8 +echo Copio i file necessari ...
   322.9 +xcopy /E /Y /Q c\* c:\
  322.10 +
  322.11 +echo Lancio installazione personalizzata di GRUB nel MBR ...
  322.12 +%GRUBINSTGUI%
  322.13 +
  322.14 +exit
   323.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   323.2 +++ b/usr/share/doc/isi/grub4dos/xp/installa_grub_standard.bat.bat	Mon Apr 26 11:16:23 2010 +0200
   323.3 @@ -0,0 +1,12 @@
   323.4 +@echo off
   323.5 +
   323.6 +SET GRUBINST=grubinst\grubinst.exe
   323.7 +
   323.8 +echo Copio i file necessari ...
   323.9 +xcopy /E /Y /Q c\* c:\
  323.10 +
  323.11 +echo Lancio installazione di GRUB nel MBR ...
  323.12 +%GRUBINST% (hd0)
  323.13 +
  323.14 +pause
  323.15 +exit
   324.1 Binary file usr/share/doc/isi/logon/WinDesktop/Cambia Password.lnk has changed
   325.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   325.2 +++ b/usr/share/doc/isi/logon/logon.bat	Mon Apr 26 11:16:23 2010 +0200
   325.3 @@ -0,0 +1,22 @@
   325.4 +# +-------------------------------------------------+
   325.5 +# � 2002-2005 ReteIsi / www.reteisi.org 
   325.6 +# +-------------------------------------------------+
   325.7 +# $Id: logon.bat 3 2021-10-08 15:21:15Z root $
   325.8 +
   325.9 +:: LOGON.BAT-----------------------------------------------
  325.10 +:: attenzione WIN98 non consente un logon.bat con parametri
  325.11 +:: e non fornisce la variabile d'ambiente %LOGONSERVER%
  325.12 +:: per cui e' necessario arrangiarsi....
  325.13 +:: --------------------------------------------------------
  325.14 +
  325.15 +@echo off
  325.16 +set SRV=XXX
  325.17 +\\%SRV%\perl\bin\perl \\%SRV%\perl\logon.pl %SRV% 
  325.18 +
  325.19 +:: %LOGONSERVER%\perl\bin\perl %LOGONSERVER%\perl\logon.pl %1 
  325.20 +
  325.21 +:: pause
  325.22 +exit
  325.23 +
  325.24 +
  325.25 +
   326.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   326.2 +++ b/usr/share/doc/isi/logon/logonupd.bat	Mon Apr 26 11:16:23 2010 +0200
   326.3 @@ -0,0 +1,15 @@
   326.4 +# +-------------------------------------------------+
   326.5 +# � 2002-2005 ReteIsi / www.reteisi.org 
   326.6 +# +-------------------------------------------------+
   326.7 +# $Id: logonupd.bat 3 2021-10-08 15:21:15Z root $
   326.8 +
   326.9 +:: LOGON.BAT-----------------------------------------------
  326.10 +:: attenzione WIN98 non consente un logon.bat con parametri
  326.11 +:: e non fornisce la variabile d'ambiente %LOGONSERVER%
  326.12 +:: per cui e' necessario arrangiarsi....
  326.13 +:: --------------------------------------------------------
  326.14 +
  326.15 +@echo off
  326.16 +set SRV=XXX
  326.17 +\\%SRV%\perl\bin\perl \\%SRV%\perl\logonupd.pl %SRV% 
  326.18 +exit
   327.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   327.2 +++ b/usr/share/doc/isi/logon/logonupd.pl	Mon Apr 26 11:16:23 2010 +0200
   327.3 @@ -0,0 +1,86 @@
   327.4 +#!/usr/bin/perl
   327.5 +
   327.6 +# +-------------------------------------------------+
   327.7 +# � 2002-2005 ReteIsi / www.reteisi.org 
   327.8 +# +-------------------------------------------------+
   327.9 +# $Id: logonupd.pl 43 2021-10-30 07:35:24Z max $
  327.10 +
  327.11 +use ISI::Logon ;
  327.12 +
  327.13 +# logon.bat richiama logon.pl passandogli
  327.14 +# il nome netbios del server che deve essere
  327.15 +# definito a mano, questo se vogliamo
  327.16 +# che tutte le versioni di windows
  327.17 +# si comportino allo stesso modo
  327.18 +# tutte le variabili necessarie sono contenute
  327.19 +# nell'hash %ENV
  327.20 +
  327.21 +my $srv = shift;
  327.22 +
  327.23 +my $DBG = 1; # attivazione modalita` DEBUG (messaggistica in finestra DOS, comoda!)
  327.24 +my $SDU = 0; # setting Users/.DEFAULT
  327.25 +
  327.26 +#$group = shift;
  327.27 +
  327.28 +&GetInfoLogon($srv);
  327.29 +
  327.30 +&ReadConf("logon.conf",1);
  327.31 +
  327.32 +$DBG=&opgruppo(1,$ENV{MAINGROUP},'_DebugLevel');
  327.33 +
  327.34 +print "NOME SERVER  = $ENV{LOGONSERVER}\n" if ($DBG);
  327.35 +print "VER.OS CLIENT= $ENV{OSCLIENT} \n"   if ($DBG);
  327.36 +print "NOME CLIENT  = $ENV{NETBIOSNAME}\n" if ($DBG);
  327.37 +print "UTENTE       = $ENV{USERNAME}\n"    if ($DBG);
  327.38 +print "GRUPPO MAIN  = $ENV{MAINGROUP}\n"   if ($DBG);
  327.39 +
  327.40 +
  327.41 +### policies x win9x - sostituisce CONFIG.POL
  327.42 +### secondo passaggio (commentate le istruzioni da non ripetere)
  327.43 +
  327.44 +&WinPol9x('startupdate',$DBG);
  327.45 +
  327.46 +&WinPol9x('clearpol',$DBG);
  327.47 +&WinPol9x('access',$DBG);
  327.48 +#&WinPol9x('pwdcaching',$DBG);
  327.49 +&WinPol9x('nocpan',$DBG);
  327.50 +&WinPol9x('nodrive',$DBG);
  327.51 +&WinPol9x('nodrivec',$DBG);
  327.52 +&WinPol9x('noactivedesktop',$DBG);
  327.53 +&WinPol9x('nohistory',$DBG);
  327.54 +&WinPol9x('nosavesettings',$DBG);
  327.55 +#&WinPol9x('paranoia',$DBG);
  327.56 +&WinPol9x('nofind',$DBG);
  327.57 +&WinPol9x('last_user',$DBG);
  327.58 +&WinPol9x('screen',$DBG);
  327.59 +&WinPol9x('net',$DBG);
  327.60 +&WinPol9x('passwd',$DBG);
  327.61 +&WinPol9x('printer',$DBG);
  327.62 +&WinPol9x('system',$DBG);
  327.63 +&WinPol9x('shell_run',$DBG);
  327.64 +&WinPol9x('shell_noregtools',$DBG);
  327.65 +&WinPol9x('shell_winoldapp',$DBG);
  327.66 +&WinPol9x('iecachedays',$DBG);
  327.67 +#&WinSet('start_page',$DBG);
  327.68 +#&WinSet('proxy',$DBG);
  327.69 +#&WinSet('no_profile',$DBG);
  327.70 +#&WinSet('sync',$DBG);
  327.71 +&WinSet('document_folder',$DBG);
  327.72 +&WinSet('iepasswordcache',$DBG);
  327.73 +&WinPol9x('profiledirs',$DBG);
  327.74 +&WinPol9x('updateprofiledirs',$DBG);
  327.75 +
  327.76 +&DbgClose();
  327.77 +
  327.78 +
  327.79 +
  327.80 +
  327.81 +
  327.82 +
  327.83 +
  327.84 +
  327.85 +
  327.86 +
  327.87 +
  327.88 +
  327.89 +
   328.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   328.2 +++ b/usr/share/isi-checkup/isi.conf	Mon Apr 26 11:16:23 2010 +0200
   328.3 @@ -0,0 +1,91 @@
   328.4 +010_disk_space.py
   328.5 +011_need_file_hostname.py
   328.6 +012_need_file_hosts.py
   328.7 +013_need_file_resolve.conf.py
   328.8 +014_need_file_interfaces.py
   328.9 +015_localhost.py
  328.10 +016_need_file_runlevel.conf.py
  328.11 +112_dhcp3-server_run_on_boot.py
  328.12 +113_need_file_dhcpd.conf.py
  328.13 +114_slapd_run_on_boot.py
  328.14 +115_need_file_ldap.secret.py
  328.15 +120_netbiosIsHostname.py
  328.16 +121_squid_run_on_boot.py
  328.17 +122_need_file_squid.conf.py
  328.18 +123_squid_parmExist.py
  328.19 +125_dansguardian_run_on_boot.py
  328.20 +126_postfix_run_on_boot.py
  328.21 +127_postfixcheck.py
  328.22 +128_nscd_run_on_boot.py
  328.23 +129_need_file_nscd.conf.py
  328.24 +131_ssh_run_on_boot.py
  328.25 +133_samba_run_on_boot.py
  328.26 +134_need_file_smb.conf.py
  328.27 +135_need_file_dansguardian.conf.py
  328.28 +137_bind9_run_on_boot.py
  328.29 +201_need_dir_home.py
  328.30 +202_need_dir_users.py
  328.31 +203_need_dir_alunni.py
  328.32 +204_need_dir_docenti.py
  328.33 +205_need_dir_admins.py
  328.34 +206_need_dir_ata.py
  328.35 +207_need_dir_esterni.py
  328.36 +208_need_dir_ospiti.py
  328.37 +209_need_dir_segreteria.py
  328.38 +220_need_dir_shares.py
  328.39 +225_need_dir_classi.py
  328.40 +226_need_dir_area_alunni.py
  328.41 +227_need_dir_area_docenti.py
  328.42 +228_need_dir_area_segreteria.py
  328.43 +229_need_dir_corsi.py
  328.44 +230_ldap_same_secret.py
  328.45 +231_need_file_libnss-ldap.secret.py
  328.46 +232_need_file_pam_ldap.secret.py
  328.47 +233_need_file_slapd_conf.py
  328.48 +342_nscd_no_persistent.py
  328.49 +250_need_file_logon.conf.py
  328.50 +251_need_file_logon.bat.py
  328.51 +252_need_file_acl.conf.py
  328.52 +253_need_file_sshd_config.py
  328.53 +254_need_file_named.conf.py
  328.54 +260_need_process_slapd.py
  328.55 +261_need_process_sshd.py
  328.56 +262_need_process_dhcpd3.py
  328.57 +263_need_process_smbd.py
  328.58 +264_need_process_nmbd.py
  328.59 +265_need_process_squid.py
  328.60 +266_need_process_dansguardian.py
  328.61 +267_need_process_master.py
  328.62 +268_need_process_named.py
  328.63 +269_need_process_nscd.py
  328.64 +271_samba_share_homes.py
  328.65 +272_samba_share_netlogon.py
  328.66 +273_samba_share_software.py
  328.67 +274_samba_share_dati.py
  328.68 +275_samba_share_classi.py
  328.69 +276_samba_share_corsi.py
  328.70 +277_samba_share_perl.py
  328.71 +278_samba_share_printers.py
  328.72 +279_samba_share_area_alunni.py
  328.73 +280_samba_share_area_docenti.py
  328.74 +281_samba_share_area_segreteria.py
  328.75 +300_samba_shares_paths.py
  328.76 +301_class_path_name.py
  328.77 +307_ldap_connect.py
  328.78 +308_user_exists_administrator.py
  328.79 +309_administrator_credential.py
  328.80 +310_DomainAdmins_group_priv.py
  328.81 +320_ldap_sizelimit.py
  328.82 +321_checkgunum.sh
  328.83 +325_smbldap_homePath.py
  328.84 +330_group_exists_docenti.py
  328.85 +331_group_exists_alunni.py
  328.86 +332_group_exists_admins.py
  328.87 +333_group_exists_ata.py
  328.88 +334_group_exists_esterni.py
  328.89 +335_group_exists_ospiti.py
  328.90 +336_group_exists_segreteria.py
  328.91 +340_logon-bat.py
  328.92 +341_logonupd-bat.py
  328.93 +342_nscd_no_persistent.py
  328.94 +502_check_permission_rwx.sh
   329.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   329.2 +++ b/usr/share/isi-checkup/lib/checkup.py	Mon Apr 26 11:16:23 2010 +0200
   329.3 @@ -0,0 +1,572 @@
   329.4 +"""
   329.5 +Prototype class for a test
   329.6 +
   329.7 +"""
   329.8 +import re
   329.9 +import os
  329.10 +import sys
  329.11 +from dry.functions import execute
  329.12 +import isi
  329.13 +
  329.14 +class TestError(Exception): pass
  329.15 +
  329.16 +class IsiTest(object):
  329.17 +    """If a user is passed as argument, the user is set as an instance
  329.18 +    attribute. This way a test can use it (and presumably limit tests to that
  329.19 +    user 
  329.20 +    """
  329.21 +    skip = ()
  329.22 +    skip_range = ('0', '0')
  329.23 +    run = False
  329.24 +    _name = None
  329.25 +    
  329.26 +    def __init__(self, user=None):
  329.27 +        self.user = user
  329.28 +
  329.29 +    def set_name(self, value):
  329.30 +        self._name = value
  329.31 +
  329.32 +    def get_name(self):
  329.33 +        if not self._name:
  329.34 +            return '%s' % self.__class__.__name__
  329.35 +        return self._name
  329.36 +    
  329.37 +    name = property(get_name, set_name)
  329.38 +    
  329.39 +    def report(self):
  329.40 +        pass
  329.41 +    
  329.42 +    def __str__(self):
  329.43 +        return "%s" % self.name
  329.44 +
  329.45 +class InputStream(object):
  329.46 +    """ Simple Wrapper for File-like objects. [c]StringIO doesn't provide
  329.47 +        a readline function for use with generate_tokens.
  329.48 +        Using a iterator-like interface doesn't succeed, because the readline
  329.49 +        function isn't used in such a context. (see <python-lib>/tokenize.py)
  329.50 +    """
  329.51 +    def __init__(self, filename=None, data=None):
  329.52 +        if filename:
  329.53 +            f = open(file)
  329.54 +            data = f.read()
  329.55 +            f.close()
  329.56 +        data = re.sub(':(.*=)', r'|\1', data)
  329.57 +        self.__data = [ '%s\n' % x for x in data.splitlines() ]
  329.58 +        self.__lcount = 0
  329.59 +
  329.60 +    def readline(self):
  329.61 +        try:
  329.62 +            line = self.__data[self.__lcount]
  329.63 +            self.__lcount += 1
  329.64 +        except IndexError:
  329.65 +            line = ''
  329.66 +            self.__lcount = 0
  329.67 +        line = re.sub(r'^ +', '', line)
  329.68 +        line = re.sub(r'^\t+', '', line)
  329.69 +        line = re.sub(r'#.*', '', line)
  329.70 +        return line
  329.71 +
  329.72 +class IsiTestProcess(IsiTest):
  329.73 +    PROCESS_NAME = None
  329.74 +
  329.75 +    def __init__(self, user=None):
  329.76 +        self.missing = []    
  329.77 +
  329.78 +    def test_needed_process(self):
  329.79 +        process = self.PROCESS_NAME
  329.80 +        cmd = "pgrep %s" % process
  329.81 +        ret_code, out, err = execute(cmd)
  329.82 +        if not ret_code:
  329.83 +            return True
  329.84 +        self.missing += [process]
  329.85 +            
  329.86 +    def report(self):
  329.87 +        if self.missing:
  329.88 +            print 'Processo non in esecuzione:', ",".join(self.missing)
  329.89 +#             for process in self.missing:
  329.90 +#                 print '    ', process
  329.91 +                
  329.92 +    def __str__(self):
  329.93 +        return "test process: %s" % (self.PROCESS_NAME)
  329.94 +
  329.95 +class IsiTestFile(IsiTest):
  329.96 +    FILE_NAME = None
  329.97 +
  329.98 +    def __init__(self, user=None):
  329.99 +        self.missing = []
 329.100 +
 329.101 +    def test_needed_file(self):
 329.102 +        filename = self.FILE_NAME
 329.103 +        try:
 329.104 +            open(filename)
 329.105 +        except IOError:
 329.106 +            readable = False
 329.107 +        else:
 329.108 +            readable = True
 329.109 +
 329.110 +        if os.path.isfile(filename) and readable:
 329.111 +            return True
 329.112 +        else:
 329.113 +            self.missing += [filename]
 329.114 +            return False
 329.115 +        
 329.116 +    def report(self):
 329.117 +        if self.missing:
 329.118 +            for filename in self.missing:
 329.119 +                print 'File non presente: "%s"' % filename
 329.120 +        
 329.121 +    def __str__(self):
 329.122 +        return "test file: %s" % (self.FILE_NAME)
 329.123 +
 329.124 +class IsiTestDir(IsiTest):
 329.125 +    DIR_NAME = None
 329.126 +
 329.127 +    def __init__(self, user=None):
 329.128 +        self.missing = []
 329.129 +
 329.130 +    def test_needed_dir(self):
 329.131 +        directory = self.DIR_NAME
 329.132 +        if os.path.isdir(directory):
 329.133 +            return True
 329.134 +        self.missing += [directory]
 329.135 +
 329.136 +    def report(self):
 329.137 +        if self.missing:
 329.138 +            print 'Directory non presente :\n'
 329.139 +            for directory in self.missing:
 329.140 +                print '    ', directory
 329.141 +
 329.142 +    def __str__(self):
 329.143 +        return "test dir: %s" % (self.DIR_NAME)
 329.144 +
 329.145 +class IsiTestSambaShare(IsiTest):
 329.146 +    SAMBA_SHARE_NAME = None
 329.147 +
 329.148 +    def __init__(self, user=None):
 329.149 +        self.missing = []
 329.150 +        
 329.151 +    def get_samba_share(self):
 329.152 +        """ Returns System Samba Shares """
 329.153 +
 329.154 +        smb_conf_dir = '/etc/isi/samba'
 329.155 +        smb_conf_files = [ "%s/%s" % (smb_conf_dir, f) \
 329.156 +                           for f in os.listdir(smb_conf_dir) if f.endswith('.conf') ]
 329.157 +        smb_conf_files.insert(0,'/etc/samba/smb.conf')
 329.158 +        shares = []
 329.159 +
 329.160 +        for conf_file in smb_conf_files:
 329.161 +            try:
 329.162 +                f = open(conf_file)
 329.163 +            except TestError:
 329.164 +                pass
 329.165 +            for line in f.readlines():
 329.166 +                m = re.search('^\[(.*)\].*',line)
 329.167 +                if m:
 329.168 +                    share = m.group(1)
 329.169 +                    shares.append(share)
 329.170 +#        ret_code, out, err = execute(cmd)
 329.171 +#        print out, err
 329.172 +#         for samba_share in out.split():
 329.173 +#             if samba_share.startswith('Disk'):
 329.174 +#                 return samba_share.split('|')[1]
 329.175 +        return shares
 329.176 +
 329.177 +    def test_samba_share(self):
 329.178 +        samba_shares = self.get_samba_share()
 329.179 +        share = self.SAMBA_SHARE_NAME
 329.180 +        if share in  samba_shares:
 329.181 +            return True
 329.182 +        self.missing += [share]
 329.183 +
 329.184 +    def report(self):
 329.185 +        if self.missing:
 329.186 +            print 'Samba Share non definita:\n' 
 329.187 +            for share in self.missing:
 329.188 +                print '    ', share
 329.189 +            
 329.190 +    def __str__(self):
 329.191 +        return "test share: %s" % (self.SAMBA_SHARE_NAME)
 329.192 +
 329.193 +class BootProcess(IsiTest):
 329.194 +    """
 329.195 +    Formato /etc/runlevel.conf
 329.196 +    
 329.197 +    # <sort> <off-> <on-levels>     <command>
 329.198 +    01      -       S               /etc/init.d/glibc.sh
 329.199 +    02      -       S               /etc/init.d/mountkernfs.sh
 329.200 +    20      0,1,6   2,3,4,5         /etc/init.d/inetd
 329.201 +    10      -       2,3,4,5         /etc/init.d/sysklogd
 329.202 +    90      0,1,6   -               /etc/init.d/sysklogd
 329.203 +    """
 329.204 +    #process = "slapd ssh dhcp3-server samba squid dansguardian postfix bind9"
 329.205 +    INIT_SCRIPTS = None
 329.206 +    
 329.207 +    def __init__(self, user=None):
 329.208 +        self.NOT_BOOTING = []
 329.209 +
 329.210 +    def using_runlevel_conf(self):
 329.211 +        """ return True if using runlevel.conf """
 329.212 +        cmd = 'grep runlevel.conf /etc/init.d/rcS'
 329.213 +        ret_code, out, err = execute(cmd)
 329.214 +        
 329.215 +        if ret_code:
 329.216 +            return False
 329.217 +        #elif os.path.isfile('/etc/runlevel.conf'):
 329.218 +        #    return True
 329.219 +        return True
 329.220 +
 329.221 +    def get_sys_runlevel_default(self):
 329.222 +        """ returns default system boot runlevel """
 329.223 +        f = open('/etc/inittab')
 329.224 +        for line in f:
 329.225 +            m = re.search('^id:(?P<runlevel>.*):initdefault:$',line)
 329.226 +            if not m: continue
 329.227 +            m = m.groupdict()
 329.228 +            runlevel = m['runlevel']
 329.229 +        return runlevel
 329.230 +
 329.231 +    def get_sys_runlevel(self):
 329.232 +        """ returns actual runlevel """
 329.233 +        ret_code, out, err = execute('runlevel')
 329.234 +        n, runlevel = out.split()
 329.235 +        return runlevel
 329.236 +
 329.237 +    def init_d_booting(self, process):
 329.238 +        """
 329.239 +        checks in /etc/init.d/rc*.d/
 329.240 +        ============================
 329.241 +        Returns True if process is configured to run at boot
 329.242 +        """
 329.243 +        sys_runlevel = self.get_sys_runlevel()
 329.244 +        path = '/etc/rc%s.d' % sys_runlevel
 329.245 +        boot_process = [s[3:] for s in os.listdir(path) if s.startswith('S')]
 329.246 +        if process in boot_process:
 329.247 +            return True
 329.248 +        else:
 329.249 +            return False
 329.250 +
 329.251 +    def runlevel_conf_booting(self, process):
 329.252 +        """
 329.253 +        checks in /etc/runlevel.conf
 329.254 +        ============================
 329.255 +        Test if a process is configured to run at boot
 329.256 +        """
 329.257 +        filename = "/etc/runlevel.conf"
 329.258 +        sys_runlevel = self.get_sys_runlevel()
 329.259 +        runlevel = open(filename).read().split('\n')
 329.260 +        commented = []
 329.261 +        found = False
 329.262 +        
 329.263 +        for line in runlevel:
 329.264 +            if re.search('/etc/init.d/%s' % process, line):
 329.265 +                if re.search('\s*#', line):
 329.266 +                    commented += line
 329.267 +                else:
 329.268 +                    level, stop, start, path = line.split()
 329.269 +                    if sys_runlevel in start:
 329.270 +                        found = True
 329.271 +        if found:
 329.272 +            return True
 329.273 +        return False
 329.274 +
 329.275 +    def test_will_boot(self):
 329.276 +        """ Test if a process is properly configured to automatically boot """
 329.277 +        process = self.INIT_SCRIPTS
 329.278 +
 329.279 +        if self.using_runlevel_conf():
 329.280 +            if self.runlevel_conf_booting(process):
 329.281 +                return True
 329.282 +            self.NOT_BOOTING += [process]
 329.283 +        else:
 329.284 +            if self.init_d_booting(process):
 329.285 +                return True
 329.286 +            self.NOT_BOOTING += [process]
 329.287 +
 329.288 +    def report(self):
 329.289 +        if self.NOT_BOOTING:
 329.290 +            for process in self.NOT_BOOTING:
 329.291 +                print "Servizio non configurato per partire al boot: %s" % process
 329.292 +
 329.293 +    def __str__(self):
 329.294 +                return "test process: %s" % (self.INIT_SCRIPTS)
 329.295 +
 329.296 +
 329.297 +class SambaGroupPrivs(IsiTest):
 329.298 +    """
 329.299 +    Checks if a particular group has needed privs
 329.300 +    
 329.301 +    Privilege definition
 329.302 +    ====================
 329.303 +
 329.304 +    SeMachineAccountPrivilege  Add machines to domain
 329.305 +    SeTakeOwnershipPrivilege  Take ownership of files or other objects
 329.306 +    SeBackupPrivilege  Back up files and directories
 329.307 +    SeRestorePrivilege  Restore files and directories
 329.308 +    SeRemoteShutdownPrivilege  Force shutdown from a remote system
 329.309 +    SePrintOperatorPrivilege  Manage printers
 329.310 +    SeAddUsersPrivilege  Add users and groups to the domain
 329.311 +    SeDiskOperatorPrivilege  Manage disk shares
 329.312 +    """
 329.313 +
 329.314 +    NEEDED_PRIV_LIST = None
 329.315 +    GROUP = None
 329.316 +    AUTH_USER = None
 329.317 +    AUTH_PW = None
 329.318 +
 329.319 +    def __init__(self, user=None):
 329.320 +        if not self.NEEDED_PRIV_LIST:
 329.321 +            self.NEEDED_PRIV_LIST = ['SeMachineAccountPrivilege',
 329.322 +                                     'SeTakeOwnershipPrivilege',
 329.323 +                                     'SeBackupPrivilege',
 329.324 +                                     'SeRestorePrivilege',
 329.325 +                                     'SeRemoteShutdownPrivilege',
 329.326 +                                     'SePrintOperatorPrivilege',
 329.327 +                                     'SeAddUsersPrivilege',
 329.328 +                                     'SeDiskOperatorPrivilege',
 329.329 +                                     ]
 329.330 +        self.miss_priv = []
 329.331 +        self.err = None
 329.332 +
 329.333 +    def test_net_group_privs(self):
 329.334 +        cmd = ['net', 'rpc', 'rights', 'list', '%s' % self.GROUP,\
 329.335 +               '-U', '%s%%%s' % (self.AUTH_USER, self.AUTH_PW)]
 329.336 +        ret_code, out, err = execute(cmd)
 329.337 +
 329.338 +        if 'NT_STATUS_LOGON_FAILURE' in err:
 329.339 +            self.err = err
 329.340 +            return False
 329.341 +            
 329.342 +        LOAD_PRIV_LIST = out
 329.343 +
 329.344 +        for priv in self.NEEDED_PRIV_LIST:
 329.345 +            if not priv in LOAD_PRIV_LIST:
 329.346 +                self.miss_priv += [priv]
 329.347 +                continue
 329.348 +        if not self.miss_priv:
 329.349 +            return True
 329.350 +        return False
 329.351 +
 329.352 +    def report(self):
 329.353 +        if self.miss_priv and not self.err:
 329.354 +            print 'Privilegi mancanti al gruppo "%s" :' % self.GROUP
 329.355 +            for priv in self.miss_priv:
 329.356 +                print '    ', priv
 329.357 +        if self.err:
 329.358 +            print 'Errori durante esecuzione comando\n    ', self.err
 329.359 +
 329.360 +    def __str__(self):
 329.361 +                return "test privilege for: %s" % (self.GROUP)
 329.362 +
 329.363 +class IsiLdapTest(IsiTest):
 329.364 +    TEST_NAME = None
 329.365 +
 329.366 +    def __init__(self, user=None):
 329.367 +        self.user = user
 329.368 +        self.srv  =  isi.IsiConn()
 329.369 +        self.isi_user = isi.Manager(self.srv)
 329.370 +
 329.371 +    def __str__(self):
 329.372 +        return "%s" % self.TEST_NAME
 329.373 +        
 329.374 +class IsiTestGroup(IsiLdapTest):
 329.375 +    GROUP = None
 329.376 +
 329.377 +    def __init__(self, user=None):
 329.378 +        self.user = user
 329.379 +        self.srv  =  isi.IsiConn()
 329.380 +        self.isi_user = isi.Manager(self.srv)
 329.381 +
 329.382 +    def test_group_exists(self):
 329.383 +        return self.isi_user.group_exists(self.GROUP)
 329.384 +
 329.385 +    def __str__(self):
 329.386 +        return "test Group Existence: %s" % (self.GROUP)
 329.387 +
 329.388 +class IsiTestUserExist(IsiLdapTest):
 329.389 +    USER = None
 329.390 +    
 329.391 +    def __init__(self, user=None):
 329.392 +        self.user = user
 329.393 +        self.srv  =  isi.IsiConn()
 329.394 +        self.isi_user = isi.Manager(self.srv)
 329.395 +
 329.396 +    def test_user_exists(self):
 329.397 +        return self.isi_user.user_exists(self.USER)
 329.398 +
 329.399 +    def __str__(self):
 329.400 +        return "test User Existence: %s" % (self.USER)
 329.401 +
 329.402 +### Inizio Colorize
 329.403 +# Color definition for the Colorize Class. Add below your colors =)
 329.404 +COLORS = {
 329.405 +          'BOLD_BLACK' : '39,48,1',
 329.406 +          'BOLD_RED' : '31,48,1',
 329.407 +          'BOLD_GREEN' : '32,48,1',
 329.408 +          'BOLD_YELLOW' : '33,48,1',
 329.409 +          'BOLD_RED' : '31,48,1',
 329.410 +          'BOLD_BLUE' : '34,48,1',
 329.411 +          'BOLD_VIOLET' : '35,48,1',
 329.412 +          'BOLD_CIANO' : '36,48,1',
 329.413 +
 329.414 +          'BLACK' : '30,30,2',
 329.415 +          'GREEN' : '30,32,2',
 329.416 +          'OCRA' : '30,33,2',
 329.417 +          'BLUE' : '30,34,2',
 329.418 +          'VIOLET' : '30,35,2',
 329.419 +          'CIANO' : '30,36,2',
 329.420 +          'GREY' : '30,37,2',
 329.421 +
 329.422 +          'GRAY_LIGHT' : '37,48,1',
 329.423 +          }
 329.424 +
 329.425 +class Colorize(object):
 329.426 +    """
 329.427 +    Returns Colorized versions of the same message
 329.428 +    for every color defined.
 329.429 +
 329.430 +    Example:
 329.431 +
 329.432 +    message = 'hey wazzupp??'    
 329.433 +
 329.434 +    c = Colorize()
 329.435 +    c.set_msg(message)
 329.436 +    print c.GREEN    # prints the message using green color
 329.437 +
 329.438 +    OR
 329.439 +    
 329.440 +    c = Colorize(message)
 329.441 +    print c.GREEN    # prints the message using green color
 329.442 +
 329.443 +    You can get a list of available color using the self.list_colors() method.
 329.444 +    It may be useful with ipython.
 329.445 +
 329.446 +    Example:
 329.447 +    Colorize().list_colors()
 329.448 +    
 329.449 +    """
 329.450 +
 329.451 +    def __init__(self, msg=None):
 329.452 +        """ Constructor """
 329.453 +        if msg:
 329.454 +            self.set_msg(msg)
 329.455 +
 329.456 +    def get_ansi(self, code):
 329.457 +        """ Returns the Ansi Code of the color"""
 329.458 +        x, y, z = code.split(',')
 329.459 +        ESC = '\033[' 
 329.460 +        return '%s;%s;%s;%sm' % (ESC, x, y, z)
 329.461 +
 329.462 +    def set_msg(self, msg=None):
 329.463 +        """ Store given message in color's attributes"""
 329.464 +        NOR = '\033[0m'
 329.465 +
 329.466 +        for key in COLORS.iterkeys():
 329.467 +            value = COLORS[key]
 329.468 +            value_ansi = self.get_ansi(value)
 329.469 +            setattr(self, '%s' % key, '%s%s%s' % (value_ansi, msg, NOR))
 329.470 +
 329.471 +    def list_colors(self):
 329.472 +        """ print colorized list of available colors """
 329.473 +
 329.474 +        NOR = '\033[0m'
 329.475 +
 329.476 +        print '\n   Available colors'
 329.477 +
 329.478 +        for key in COLORS.iterkeys():
 329.479 +            value = COLORS[key]
 329.480 +            value_ansi = self.get_ansi(value)
 329.481 +            print '%s####  %11s (code: %s) ####%s' % (value_ansi, key, value, NOR)
 329.482 +
 329.483 +    def write_color_list(self, filename=None):
 329.484 +        """
 329.485 +        1) prints out "all" ansi color available
 329.486 +        
 329.487 +        2) writes all ansi color available in "file". If not "file" argument given
 329.488 +
 329.489 +        It'll write to /tmp/ansi_colors
 329.490 +        You can browse colors using "less -R @file"
 329.491 +
 329.492 +        Note: this method may overload old machines. Generated file size will be
 329.493 +              about 712 Kb
 329.494 +        """
 329.495 +
 329.496 +        NOR = '\033[0m'
 329.497 +
 329.498 +        if not filename:
 329.499 +            f = open("/tmp/ansi_colors", "w")
 329.500 +        else:
 329.501 +            try:
 329.502 +                f = open(filename, "w")
 329.503 +            except Exception:
 329.504 +                print "Error opening: %s" % filename
 329.505 +
 329.506 +        range_x = range(1,12)
 329.507 +        range_x += range(29,49)
 329.508 +        range_y = range(1,40)
 329.509 +        range_z = range(1,10)
 329.510 +        
 329.511 +        for z in range_z:
 329.512 +            for y in range_y:
 329.513 +                for x in range_x:
 329.514 +                    code = '%s,%s,%s' % (x, y, z)
 329.515 +                    msg = 'Browse colors using "less -R /tmp/colori"'
 329.516 +                    output = '\033[%s;%s;%sm (%s) %s %s' % \
 329.517 +                             (x, y, z, code, msg, NOR)
 329.518 +                    print output
 329.519 +                    f.writelines('%s\n' % output)
 329.520 +        f.close()  
 329.521 +
 329.522 +        
 329.523 +#### DEMO - begin ####
 329.524 +
 329.525 +# prova test_needed_process
 329.526 +# x = IsiTestProcess()
 329.527 +# x.PROCESS_NAME='ssx'
 329.528 +# x.PROCESS_NAME='ssh'
 329.529 +# x.test_needed_process()
 329.530 +# x.report()
 329.531 +
 329.532 +# # prova test_needed_file
 329.533 +# x = IsiTestFile()
 329.534 +# x.FILE_NAME = '/etc/ldap.secret'
 329.535 +# x.FILE_NAME = '/etc/xxxxx'
 329.536 +# x.test_needed_file()
 329.537 +# x.report()
 329.538 +
 329.539 +# # prova test_needed_dir
 329.540 +# x = IsiTestDir()
 329.541 +# x.DIR_NAME = '/home/shares/area_docenti'
 329.542 +# x.DIR_NAME = '/home/shares/area_docuuuu'
 329.543 +# x.test_needed_dir()
 329.544 +# x.report()
 329.545 +
 329.546 +# prova test_samba_share
 329.547 +# x = IsiTestSambaShare()
 329.548 +# x.SAMBA_SHARE_NAME = 'xnetlogon'
 329.549 +# x.test_samba_share()
 329.550 +# x.report()
 329.551 +
 329.552 +# prova test_boot_process
 329.553 +# x = BootProcess()
 329.554 +# x.INIT_SCRIPTS = 'sshx'
 329.555 +# x.test_will_boot()
 329.556 +# x.report()
 329.557 +
 329.558 +
 329.559 +#prova test_net_group_privs
 329.560 +# x = SambaGroupPrivs()
 329.561 +# x.NEEDED_PRIV_LIST = ['SeMachineAccountPrivilege','asdasd']
 329.562 +# x.GROUP = 'Domain Admins'
 329.563 +# x.AUTH_USER = 'administrator'
 329.564 +# x.AUTH_PW = ''
 329.565 +# x.test_net_group_privs()
 329.566 +# x.report()
 329.567 +
 329.568 +# # prova classe Colorize
 329.569 +# c = Colorize()
 329.570 +# message = 'Messaggio di prova'
 329.571 +# c.set_msg(message)
 329.572 +# print c.GREEN    # prints the message using green color
 329.573 +
 329.574 +#### DEMO - end ####
 329.575 +
   330.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   330.2 +++ b/usr/share/isi-checkup/lib/colorize.py	Mon Apr 26 11:16:23 2010 +0200
   330.3 @@ -0,0 +1,153 @@
   330.4 +#!/usr/bin/python
   330.5 +"""
   330.6 +
   330.7 +Simone Castellazzi <[email protected]>
   330.8 +
   330.9 +Description
  330.10 +===========
  330.11 +
  330.12 +
  330.13 +TODO:
  330.14 +
  330.15 +??
  330.16 +msg.title.D_GREEN
  330.17 +msg.title.L_GREEN
  330.18 +"""
  330.19 +
  330.20 +# Color definition. Add below your colors =)
  330.21 +COLORS = {
  330.22 +          'BOLD_BLACK' : '39,48,1',
  330.23 +          'BOLD_RED' : '31,48,1',
  330.24 +          'BOLD_GREEN' : '32,48,1',
  330.25 +          'BOLD_YELLOW' : '33,48,1',
  330.26 +          'BOLD_RED' : '31,48,1',
  330.27 +          'BOLD_BLUE' : '34,48,1',
  330.28 +          'BOLD_VIOLET' : '35,48,1',
  330.29 +          'BOLD_CIANO' : '36,48,1',
  330.30 +
  330.31 +          'BOLD_RED_U' : '31,4,1',
  330.32 +          'BOLD_GREEN_U' : '32,4,1',
  330.33 +          'BOLD_BLUE_U' : '34,4,1',
  330.34 +              
  330.35 +          'BLACK' : '30,30,2',
  330.36 +          'GREEN' : '30,32,2',
  330.37 +          'OCRA' : '30,33,2',
  330.38 +          'BLUE' : '30,34,2',
  330.39 +          'VIOLET' : '30,35,2',
  330.40 +          'CIANO' : '30,36,2',
  330.41 +          'GREY' : '30,37,2',
  330.42 +
  330.43 +          'GRAY_LIGHT' : '37,48,1',
  330.44 +
  330.45 +          'WHITE_BLUE' : '7,34,3',
  330.46 +          'WHITE_RED' : '7,31,3',
  330.47 +          'WHITE_OCRA' : '7,33,3',
  330.48 +          'WHITE_VIOLA' : '7,35,2',
  330.49 +          'YELLOW' : '1,33,1',
  330.50 +
  330.51 +          'RED_U' : '31,19,4',
  330.52 +          'GREEN_U' : '32,19,4',
  330.53 +          'YELLOW_U' : '33,19,4',
  330.54 +          'BLUE_U' : '34,19,4',
  330.55 +          'VIOLA_U' : '35,19,4',
  330.56 +          'CIANO_U' : '36,19,4',
  330.57 +
  330.58 +          }
  330.59 +
  330.60 +class Colorize(object):
  330.61 +    """
  330.62 +    Returns Colorized versions of the same message
  330.63 +    for every color defined.
  330.64 +
  330.65 +    Example:
  330.66 +
  330.67 +    message = 'hey wazzupp??'    
  330.68 +
  330.69 +    c = Colorize()
  330.70 +    c.set_msg(message)
  330.71 +    print c.GREEN    # prints the message using green color
  330.72 +
  330.73 +    OR
  330.74 +    
  330.75 +    c = Colorize(message)
  330.76 +    print c.GREEN    # prints the message using green color
  330.77 +
  330.78 +    You can get a list of available color using the self.list_colors() method.
  330.79 +    It may be useful with ipython.
  330.80 +
  330.81 +    Example:
  330.82 +    Colorize().list_colors()
  330.83 +    
  330.84 +    """
  330.85 +
  330.86 +    def __init__(self, msg=None):
  330.87 +        """ Constructor """
  330.88 +        if msg:
  330.89 +            self.set_msg(msg)
  330.90 +
  330.91 +    def get_ansi(self, code):
  330.92 +        """ Returns the Ansi Code of the color"""
  330.93 +        x, y, z = code.split(',')
  330.94 +        ESC = '\033[' 
  330.95 +        return '%s;%s;%s;%sm' % (ESC, x, y, z)
  330.96 +
  330.97 +    def set_msg(self, msg=None):
  330.98 +        """ Store given message in color's attributes"""
  330.99 +        NOR = '\033[0m'
 330.100 +
 330.101 +        for key in COLORS.iterkeys():
 330.102 +            value = COLORS[key]
 330.103 +            value_ansi = self.get_ansi(value)
 330.104 +            setattr(self, '%s' % key, '%s%s%s' % (value_ansi, msg, NOR))
 330.105 +
 330.106 +    def list_colors(self):
 330.107 +        """ print colorized list of available colors """
 330.108 +
 330.109 +        NOR = '\033[0m'
 330.110 +
 330.111 +        print '\n   Available colors'
 330.112 +
 330.113 +        for key in COLORS.iterkeys():
 330.114 +            value = COLORS[key]
 330.115 +            value_ansi = self.get_ansi(value)
 330.116 +            print '%s####  %11s (code: %s) ####%s' % (value_ansi, key, value, NOR)
 330.117 +
 330.118 +    def write_color_list(self, filename=None):
 330.119 +        """
 330.120 +        1) prints out "all" ansi color available
 330.121 +        
 330.122 +        2) writes all ansi color available in "file". If not "file" argument given
 330.123 +
 330.124 +        It'll write to /tmp/ansi_colors
 330.125 +        You can browse colors using "less -R @file"
 330.126 +
 330.127 +        Note: this method may overload old machines. Generated file size will be
 330.128 +              about 712 Kb
 330.129 +        """
 330.130 +
 330.131 +        NOR = '\033[0m'
 330.132 +
 330.133 +        if not filename:
 330.134 +            f = open("/tmp/ansi_colors", "w")
 330.135 +        else:
 330.136 +            try:
 330.137 +                f = open(filename, "w")
 330.138 +            except Exception:
 330.139 +                print "Error opening: %s" % filename
 330.140 +
 330.141 +        range_x = range(1,12)
 330.142 +        range_x += range(29,49)
 330.143 +        range_y = range(1,40)
 330.144 +        range_z = range(1,10)
 330.145 +        
 330.146 +        for z in range_z:
 330.147 +            for y in range_y:
 330.148 +                for x in range_x:
 330.149 +                    code = '%s,%s,%s' % (x, y, z)
 330.150 +                    msg = 'Browse colors using "less -R /tmp/colori"'
 330.151 +                    output = '\033[%s;%s;%sm (%s) %s %s' % \
 330.152 +                             (x, y, z, code, msg, NOR)
 330.153 +                    print output
 330.154 +                    f.writelines('%s\n' % output)
 330.155 +        f.close()  
 330.156 +
   331.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   331.2 +++ b/usr/share/isi-checkup/tests/010_disk_space.py	Mon Apr 26 11:16:23 2010 +0200
   331.3 @@ -0,0 +1,114 @@
   331.4 +#!/usr/bin/python
   331.5 +"""
   331.6 +Filesystem            Size  Used Avail Use% Mounted on
   331.7 +/dev/md3              2.5G  1.3G  1.3G  100% /
   331.8 +tmpfs                 507M     0  507M   0% /lib/init/rw
   331.9 +udev                   10M   80K   10M   1% /dev
  331.10 +tmpfs                 507M  4.0K  507M   1% /dev/shm
  331.11 +/dev/md0               23M   19M  2.6M  97% /boot
  331.12 +/dev/md4              178G   27G  151G  55% /home
  331.13 +/dev/md5              178G   27G  151G  55% /test
  331.14 +"""
  331.15 +
  331.16 +import re
  331.17 +from dry.functions import execute
  331.18 +import sys
  331.19 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
  331.20 +from checkup import IsiTest, TestError
  331.21 +
  331.22 +class T_diskspace(IsiTest):
  331.23 +    run = True
  331.24 +    skip = ""
  331.25 +    name = 'disk_space'
  331.26 +    WARNING = False
  331.27 +    ERROR = False
  331.28 +
  331.29 +    def __init__(self, user=None):
  331.30 +        pass
  331.31 +
  331.32 +    def test_diskspace(self):
  331.33 +
  331.34 +        level_warn = 90
  331.35 +        level_error = 95
  331.36 +        dev = {}
  331.37 + 
  331.38 +        ret_code, out, err = execute('df -h')
  331.39 + 
  331.40 +        out = out.split("\n")
  331.41 +        out.sort(reverse = True)
  331.42 +
  331.43 +        for line in out:
  331.44 +            if line.startswith('/dev/'):
  331.45 +                line = re.split(" +", line)
  331.46 +                """
  331.47 +                modello contenuto "line"
  331.48 +                ['/dev/md3', '2.5G', '1.3G', '1.3G', '51%', '/']
  331.49 +                ['/dev/md0', '23M', '19M', '2.6M', '94%', '/boot']
  331.50 +                ['/dev/md4', '178G', '27G', '151G', '15%', '/home']
  331.51 +                """
  331.52 +                k = line[0]
  331.53 +                v = [ int(line[4].strip('%s')), line[5] ]
  331.54 +                dev[k] = v
  331.55 +
  331.56 +        for k, v in dev.items():
  331.57 +            self.mnt = k
  331.58 +            self.dev = v[1]
  331.59 +            self.usage = v[0]
  331.60 +            
  331.61 +            if self.usage >= level_error:
  331.62 +                self.ERROR = True
  331.63 +            elif self.usage >= level_warn:
  331.64 +                self.WARNING = True
  331.65 +            else:
  331.66 +                return True
  331.67 +
  331.68 +    def report(self):
  331.69 +        if self.WARNING:
  331.70 +            print "    WARNING\t %s \t %s \t occupato al %s%%" % (self.dev, self.mnt, self.usage)
  331.71 +        if self.ERROR:
  331.72 +            print "    *ERROR*\t %s \t %s \t occupato al %s%%" % (self.dev, self.mnt, self.usage)
  331.73 +
  331.74 +    def __str__(self):
  331.75 +        return "test %s" % (self.name)
  331.76 +
  331.77 +
  331.78 +
  331.79 +
  331.80 +
  331.81 +
  331.82 +
  331.83 +
  331.84 +
  331.85 +
  331.86 +
  331.87 +
  331.88 +
  331.89 +
  331.90 +
  331.91 +
  331.92 +
  331.93 +
  331.94 +
  331.95 +
  331.96 +
  331.97 +
  331.98 +
  331.99 +
 331.100 +
 331.101 +
 331.102 +
 331.103 +
 331.104 +
 331.105 +
 331.106 +
 331.107 +
 331.108 +
 331.109 +
 331.110 +
 331.111 +
 331.112 +
 331.113 +
 331.114 +
 331.115 +
 331.116 +
 331.117 +
   332.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   332.2 +++ b/usr/share/isi-checkup/tests/011_need_file_hostname.py	Mon Apr 26 11:16:23 2010 +0200
   332.3 @@ -0,0 +1,7 @@
   332.4 +from checkup import IsiTestFile
   332.5 +
   332.6 +class FileHostname(IsiTestFile):
   332.7 +    run = True
   332.8 +    skip = ""
   332.9 +    FILE_NAME = '/etc/hostname'
  332.10 +
   333.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   333.2 +++ b/usr/share/isi-checkup/tests/012_need_file_hosts.py	Mon Apr 26 11:16:23 2010 +0200
   333.3 @@ -0,0 +1,7 @@
   333.4 +from checkup import IsiTestFile
   333.5 +
   333.6 +class FileHosts(IsiTestFile):
   333.7 +    run = True
   333.8 +    skip = ""
   333.9 +    FILE_NAME = '/etc/hosts'
  333.10 +
   334.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   334.2 +++ b/usr/share/isi-checkup/tests/013_need_file_resolve.conf.py	Mon Apr 26 11:16:23 2010 +0200
   334.3 @@ -0,0 +1,7 @@
   334.4 +from checkup import IsiTestFile
   334.5 +
   334.6 +class FileResolvConf(IsiTestFile):
   334.7 +    run = True
   334.8 +    skip = ""
   334.9 +    FILE_NAME = '/etc/resolv.conf'
  334.10 +
   335.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   335.2 +++ b/usr/share/isi-checkup/tests/014_need_file_interfaces.py	Mon Apr 26 11:16:23 2010 +0200
   335.3 @@ -0,0 +1,7 @@
   335.4 +from checkup import IsiTestFile
   335.5 +
   335.6 +class FileInterfaces(IsiTestFile):
   335.7 +    run = True
   335.8 +    skip = "260 261 262 263 264 265 266 267 268"
   335.9 +    FILE_NAME = '/etc/network/interfaces'
  335.10 +
   336.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   336.2 +++ b/usr/share/isi-checkup/tests/015_localhost.py	Mon Apr 26 11:16:23 2010 +0200
   336.3 @@ -0,0 +1,104 @@
   336.4 +#/usr/bin/python
   336.5 +"""
   336.6 +127.0.0.1 localhost
   336.7 +127.0.1.1 dream0ne
   336.8 +
   336.9 +###############################
  336.10 +# Network Dreamnet
  336.11 +###############################
  336.12 +192.168.1.100 pa-zulu
  336.13 +192.168.1.102 pa-nb
  336.14 +192.168.1.10 hp1320
  336.15 +###############################
  336.16 +
  336.17 +# The following lines are desirable for IPv6 capable hosts
  336.18 +::1 ip6-localhost ip6-loopback
  336.19 +fe00::0 ip6-localnet
  336.20 +ff00::0 ip6-mcastprefix
  336.21 +ff02::1 ip6-allnodes
  336.22 +ff02::2 ip6-allrouters
  336.23 +ff02::3 ip6-allhosts
  336.24 +
  336.25 +"""
  336.26 +from checkup import IsiTest
  336.27 +import re
  336.28 +
  336.29 +errors = []
  336.30 +
  336.31 +class check_localhost(IsiTest):
  336.32 +    """ Checks configuration of the"/etc/hosts" file """
  336.33 +    run = True
  336.34 +    skip = ""
  336.35 +    name = 'localhost'
  336.36 +    errors = []
  336.37 +
  336.38 +    def read_etc_hosts(self):
  336.39 +        """
  336.40 +        Parse /etc/hosts and returns dictionary
  336.41 +
  336.42 +        es.
  336.43 +        key, value = ip, ['host1','...']
  336.44 +        """
  336.45 +        hosts = {}
  336.46 +        #for line in __doc__.split('\n'): # per test
  336.47 +        f = open('/etc/hosts')
  336.48 +        for line in f.readlines():
  336.49 +            if re.search('^$', line): continue
  336.50 +            if re.match('^\s*#.*$', line): continue
  336.51 +            line = line.strip('\n').split()
  336.52 +            ip = line[0]
  336.53 +            hostnames = line[1:]
  336.54 +            hosts[ip] = hostnames
  336.55 +
  336.56 +        return hosts
  336.57 +
  336.58 +    def read_etc_hostname(self):
  336.59 +        """ returns hostname """
  336.60 +        f = open('/etc/hostname')
  336.61 +        for line in f.readlines():    
  336.62 +        #for line in __doc__.split('\n'):
  336.63 +            if re.search('^$', line): continue
  336.64 +            if re.match('^\s*#.*$', line): continue
  336.65 +            return line.strip()
  336.66 +
  336.67 +    def test_localhost(self):
  336.68 +        """ Perform series of test on /etc/hosts """
  336.69 +        etc_hosts = self.read_etc_hosts()
  336.70 +        etc_hostname = self.read_etc_hostname()
  336.71 +        errors = []
  336.72 +        
  336.73 +        # check if 127.0.0.1 is NOT defined
  336.74 +        if not etc_hosts.has_key('127.0.0.1'):
  336.75 +            errors.append("127.0.0.1 non definito.")
  336.76 +        else:
  336.77 +            # check if 127.0.0.1 is NOT associated to at least one host
  336.78 +            if not etc_hosts['127.0.0.1']:
  336.79 +                errors.append("127.0.0.1 non e' associato a nessun hostname.")
  336.80 +            # check if 127.0.0.1 is associated to *localhost*
  336.81 +            if not 'localhost' in etc_hosts['127.0.0.1']:
  336.82 +                errors.append("127.0.0.1 non e' associato a 'localhost'.")
  336.83 +            # check if '/etc/hostname' is associated *lo*
  336.84 +            if not etc_hostname in etc_hosts['127.0.0.1']:
  336.85 +                if etc_hosts.has_key('127.0.1.1') and etc_hostname in etc_hosts['127.0.1.1']:
  336.86 +                    pass
  336.87 +                else:
  336.88 +                    errors.append("hostname di sistema %s non associato all'interfaccia 'lo'." % etc_hostname)
  336.89 +            # check for multiple definition of 127.0.0.1 or 127.0.1.1
  336.90 +            if etc_hosts.keys().count("127.0.0.1") > 1 or \
  336.91 +               etc_hosts.keys().count("127.0.0.1") > 1:
  336.92 +                errors.append("127.0.0.1 e' ripetuto piu' volte all'interno del file.")
  336.93 +
  336.94 +        if errors:
  336.95 +            self.errors = errors
  336.96 +            return False
  336.97 +        return True
  336.98 +
  336.99 +    def report(self):
 336.100 +        if self.errors:
 336.101 +            print 'Errori di configurazione in \"/etc/hosts\" :'
 336.102 +            for e in self.errors:
 336.103 +                print '- ', e
 336.104 +        
 336.105 +    def __str__(self):
 336.106 +        return "test %s" % (self.name)
 336.107 +
   337.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   337.2 +++ b/usr/share/isi-checkup/tests/016_need_file_runlevel.conf.py	Mon Apr 26 11:16:23 2010 +0200
   337.3 @@ -0,0 +1,26 @@
   337.4 +from checkup import IsiTest, BootProcess
   337.5 +import os
   337.6 +
   337.7 +class FileRunlevelConf(IsiTest):
   337.8 +    run = True
   337.9 +    name = "FileRunlevelConfExist"
  337.10 +    file_missing = False
  337.11 +
  337.12 +    run = True
  337.13 +    file_missing = False
  337.14 +
  337.15 +    def __init__(self, user=None):
  337.16 +        self.runlevel_conf = BootProcess().using_runlevel_conf()
  337.17 +
  337.18 +    def test_RunlevelConfExist(self):
  337.19 +        if not self.runlevel_conf:
  337.20 +            # Returns True if not using runlevel.conf (lenny)
  337.21 +            return True
  337.22 +        if not os.path.isfile('/etc/runlevel.conf'):
  337.23 +            self.file_missing = True
  337.24 +            return False
  337.25 +        return True
  337.26 +
  337.27 +    def report(self):
  337.28 +        if self.file_missing:
  337.29 +            print "/etc/runlevel.conf non trovato"
   338.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   338.2 +++ b/usr/share/isi-checkup/tests/112_dhcp3-server_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   338.3 @@ -0,0 +1,6 @@
   338.4 +from checkup import BootProcess
   338.5 +
   338.6 +class BootProcessDhcp3Server(BootProcess):
   338.7 +    skip = "113 262"
   338.8 +    run = True
   338.9 +    INIT_SCRIPTS = 'dhcp3-server'
   339.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   339.2 +++ b/usr/share/isi-checkup/tests/113_need_file_dhcpd.conf.py	Mon Apr 26 11:16:23 2010 +0200
   339.3 @@ -0,0 +1,7 @@
   339.4 +from checkup import IsiTestFile
   339.5 +
   339.6 +class FileDhcpdConf(IsiTestFile):
   339.7 +    skip = "262"
   339.8 +    run = True
   339.9 +    FILE_NAME = '/etc/dhcp3/dhcpd.conf'
  339.10 +
   340.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   340.2 +++ b/usr/share/isi-checkup/tests/114_slapd_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   340.3 @@ -0,0 +1,6 @@
   340.4 +from checkup import BootProcess
   340.5 +
   340.6 +class BootProcessSlapd(BootProcess):
   340.7 +    run = True
   340.8 +    skip = "115 230 231 232 233 260 307 308 309 310 325 320 321 325 330 331 332 333 334 335 336"
   340.9 +    INIT_SCRIPTS = 'slapd'
   341.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   341.2 +++ b/usr/share/isi-checkup/tests/115_need_file_ldap.secret.py	Mon Apr 26 11:16:23 2010 +0200
   341.3 @@ -0,0 +1,7 @@
   341.4 +from checkup import IsiTestFile
   341.5 +
   341.6 +class FileLdapSecret(IsiTestFile):
   341.7 +    run = True
   341.8 +    skip = "230 231 232 260 325 320 307 308 309 320 325 330 331 332 333 334 335 336"
   341.9 +    FILE_NAME = '/etc/ldap.secret'
  341.10 +
   342.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   342.2 +++ b/usr/share/isi-checkup/tests/120_netbiosIsHostname.py	Mon Apr 26 11:16:23 2010 +0200
   342.3 @@ -0,0 +1,51 @@
   342.4 +#!/usr/bin/python
   342.5 +
   342.6 +from checkup import IsiTest
   342.7 +import re
   342.8 +
   342.9 +class HostnameIsNetbiosName(IsiTest):
  342.10 +    """
  342.11 +    Tests if hostname configured in /etc/hostname is
  342.12 +    the netbios name configured in /etc/samba/smb.conf
  342.13 +    """
  342.14 +    name = 'localhost = netbios name'
  342.15 +    run = True
  342.16 +    skip = ''
  342.17 +    check_failed = False
  342.18 +    
  342.19 +    def get_netbios_name(self):
  342.20 +        """ returns netbios_name configured in /etc/samba/smb.conf """
  342.21 +        f = open('/etc/samba/smb.conf')
  342.22 +        for line in f.readlines():
  342.23 +            m = re.match('^\s*netbios name\s*=\s*(.+)\s*$', line)
  342.24 +            if m:        
  342.25 +                netbios_name = m.groups()[0]
  342.26 +                return netbios_name
  342.27 +
  342.28 +    def get_hostname(self):
  342.29 +        """ returns hostname configured in /etc/hostname """
  342.30 +        f = open('/etc/hostname')
  342.31 +        for line in f.readlines():    
  342.32 +        #for line in __doc__.split('\n'):
  342.33 +            if re.search('^$', line): continue
  342.34 +            if re.match('^\s*#.*$', line): continue
  342.35 +            return line.strip()
  342.36 +
  342.37 +    def test_hostname_is_netbiosname(self):
  342.38 +        """ returns True if netbios_name == hostname """
  342.39 +        netbios_name = self.get_netbios_name()
  342.40 +        hostname = self.get_hostname()
  342.41 +        if netbios_name == hostname :
  342.42 +            return True
  342.43 +        else:
  342.44 +            self.check_failed = True
  342.45 +            return False
  342.46 +    
  342.47 +    def report(self):
  342.48 +        if self.check_failed:
  342.49 +            print "\nIl nome host della macchina configurato in '/etc/hostname'\n"\
  342.50 +                 +"non coincide con il nome netbios configurato in '/etc/samba/smb.conf'."
  342.51 +
  342.52 +    def __str__(self):
  342.53 +        return "test %s" % (self.name)
  342.54 +
   343.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   343.2 +++ b/usr/share/isi-checkup/tests/121_squid_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   343.3 @@ -0,0 +1,6 @@
   343.4 +from checkup import BootProcess
   343.5 +
   343.6 +class BootProcessSquid(BootProcess):
   343.7 +    skip = "122 123 265"
   343.8 +    run = True
   343.9 +    INIT_SCRIPTS = 'squid'
   344.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   344.2 +++ b/usr/share/isi-checkup/tests/122_need_file_squid.conf.py	Mon Apr 26 11:16:23 2010 +0200
   344.3 @@ -0,0 +1,7 @@
   344.4 +from checkup import IsiTestFile
   344.5 +
   344.6 +class FileSquidConf(IsiTestFile):
   344.7 +    run = True
   344.8 +    skip = "123 265"
   344.9 +    FILE_NAME = '/etc/squid/squid.conf'
  344.10 +
   345.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   345.2 +++ b/usr/share/isi-checkup/tests/123_squid_parmExist.py	Mon Apr 26 11:16:23 2010 +0200
   345.3 @@ -0,0 +1,60 @@
   345.4 +#!/usr/bin/python
   345.5 +'''
   345.6 +squid-log.py
   345.7 +
   345.8 +Test che verifica che alcuni parametri siano presenti
   345.9 +in /etc/squid/squid.conf.
  345.10 +'''
  345.11 +
  345.12 +import sys
  345.13 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
  345.14 +import os
  345.15 +import re
  345.16 +from checkup import IsiTest
  345.17 +
  345.18 +class TestSquidLog(IsiTest):
  345.19 +    run = True
  345.20 +    name = 'squid_parmExist'
  345.21 +    def __init__(self, user=None):
  345.22 +
  345.23 +        self.squid_config = "/etc/squid/squid.conf"
  345.24 +
  345.25 +        self.parmExist = 'access_log http_port'.split()
  345.26 +        self.missing = []
  345.27 +            
  345.28 +    def parm_exist(self, parm):
  345.29 +        '''
  345.30 +        Se il parametro non esiste ritorna False
  345.31 +        Se non esiste il file /etc/squid/squid.conf ritorna False
  345.32 +        '''
  345.33 +        if not os.path.isfile(self.squid_config):
  345.34 +            return False
  345.35 +                            
  345.36 +        f = open(self.squid_config)
  345.37 +        for line in f:
  345.38 +            if not parm in line:
  345.39 +                continue
  345.40 +            if re.match('\s*%s\s+.+\s*' % parm, line):
  345.41 +                return True
  345.42 +        return False
  345.43 +    def test_squid_parmExist(self):
  345.44 +        for parm in self.parmExist:
  345.45 +            if self.parm_exist(parm):
  345.46 +                continue
  345.47 +            self.missing += [parm]
  345.48 +        if not self.missing:
  345.49 +            return True
  345.50 +        
  345.51 +    def report(self):
  345.52 +        if self.missing:
  345.53 +            print 'squid.conf: Parametri assenti'
  345.54 +            print '-----------------------------'
  345.55 +            for i in self.missing:
  345.56 +                print '    %s' % i
  345.57 +
  345.58 +    def __str__(self):
  345.59 +            return "test %s" % (self.name)
  345.60 +            
  345.61 +
  345.62 +
  345.63 +
   346.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   346.2 +++ b/usr/share/isi-checkup/tests/125_dansguardian_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   346.3 @@ -0,0 +1,6 @@
   346.4 +from checkup import BootProcess
   346.5 +
   346.6 +class BootProcessDansguardian(BootProcess):
   346.7 +    run = True
   346.8 +    skip = "135 266"
   346.9 +    INIT_SCRIPTS = 'dansguardian'
   347.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   347.2 +++ b/usr/share/isi-checkup/tests/126_postfix_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   347.3 @@ -0,0 +1,6 @@
   347.4 +from checkup import BootProcess
   347.5 +
   347.6 +class BootProcessPostfix(BootProcess):
   347.7 +    run = True
   347.8 +    skip = "127 267"
   347.9 +    INIT_SCRIPTS = 'postfix'
   348.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   348.2 +++ b/usr/share/isi-checkup/tests/127_postfixcheck.py	Mon Apr 26 11:16:23 2010 +0200
   348.3 @@ -0,0 +1,27 @@
   348.4 +#!/bin/bin/python
   348.5 +
   348.6 +import re
   348.7 +from dry.functions import execute
   348.8 +import sys
   348.9 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
  348.10 +from checkup import IsiTest, TestError
  348.11 +
  348.12 +class CheckPostfix(IsiTest):
  348.13 +    run = True
  348.14 +    ERROR = False
  348.15 +
  348.16 +    def test_check_postfix(self):
  348.17 +        cmd = 'postfix check'
  348.18 +        ret_code, out, self.err = execute(cmd)
  348.19 +
  348.20 +        if not ret_code:
  348.21 +            return True
  348.22 +        self.ERROR = True
  348.23 +
  348.24 +    def report(self):
  348.25 +        if self.ERROR:
  348.26 +            print ' "postfix check" ha restituito errori:\n%s' % self.err
  348.27 +
  348.28 +    def __str__(self):
  348.29 +            return "test %s" % (self.name)
  348.30 +            
  348.31 \ No newline at end of file
   349.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   349.2 +++ b/usr/share/isi-checkup/tests/128_nscd_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   349.3 @@ -0,0 +1,6 @@
   349.4 +from checkup import BootProcess
   349.5 +
   349.6 +class BootProcessNscd(BootProcess):
   349.7 +    skip = "129 269 342"
   349.8 +    run = True
   349.9 +    INIT_SCRIPTS = 'nscd'
   350.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   350.2 +++ b/usr/share/isi-checkup/tests/129_need_file_nscd.conf.py	Mon Apr 26 11:16:23 2010 +0200
   350.3 @@ -0,0 +1,7 @@
   350.4 +from checkup import IsiTestFile
   350.5 +
   350.6 +class FileNscdConf(IsiTestFile):
   350.7 +    run = True
   350.8 +    skip = "342"
   350.9 +    FILE_NAME = '/etc/nscd.conf'
  350.10 +
   351.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   351.2 +++ b/usr/share/isi-checkup/tests/131_ssh_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   351.3 @@ -0,0 +1,6 @@
   351.4 +from checkup import BootProcess
   351.5 +
   351.6 +class BootProcessSsh(BootProcess):
   351.7 +    run = True
   351.8 +    skip = "253 261"
   351.9 +    INIT_SCRIPTS = 'ssh'
   352.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   352.2 +++ b/usr/share/isi-checkup/tests/133_samba_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   352.3 @@ -0,0 +1,6 @@
   352.4 +from checkup import BootProcess
   352.5 +
   352.6 +class BootProcessSamba(BootProcess):
   352.7 +    run = True
   352.8 +    skip = "134 220 225 226 227 228 229 249 250 251 263 264 271 272 273 274 275 276 277 278 279 280 281 300 301 310 325 321 340 341 343"
   352.9 +    INIT_SCRIPTS = 'samba'
   353.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   353.2 +++ b/usr/share/isi-checkup/tests/134_need_file_smb.conf.py	Mon Apr 26 11:16:23 2010 +0200
   353.3 @@ -0,0 +1,7 @@
   353.4 +from checkup import IsiTestFile
   353.5 +
   353.6 +class FileSmbConf(IsiTestFile):
   353.7 +    run = True
   353.8 +    skip = "263 264 271 272 273 274 275 276 277 278 279 280 281 300 310 325"
   353.9 +    FILE_NAME = '/etc/samba/smb.conf'
  353.10 +
   354.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   354.2 +++ b/usr/share/isi-checkup/tests/135_need_file_dansguardian.conf.py	Mon Apr 26 11:16:23 2010 +0200
   354.3 @@ -0,0 +1,7 @@
   354.4 +from checkup import IsiTestFile
   354.5 +
   354.6 +class FileDansguardianConf(IsiTestFile):
   354.7 +    run = True
   354.8 +    skip = "266"
   354.9 +    FILE_NAME = '/etc/dansguardian/dansguardian.conf'
  354.10 +
   355.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   355.2 +++ b/usr/share/isi-checkup/tests/137_bind9_run_on_boot.py	Mon Apr 26 11:16:23 2010 +0200
   355.3 @@ -0,0 +1,6 @@
   355.4 +from checkup import BootProcess
   355.5 +
   355.6 +class BootProcessBind9(BootProcess):
   355.7 +    run = True
   355.8 +    skip = "254 268"
   355.9 +    INIT_SCRIPTS = 'bind9'
   356.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   356.2 +++ b/usr/share/isi-checkup/tests/201_need_dir_home.py	Mon Apr 26 11:16:23 2010 +0200
   356.3 @@ -0,0 +1,7 @@
   356.4 +from checkup import IsiTestDir
   356.5 +
   356.6 +class DirHome(IsiTestDir):
   356.7 +    run = True
   356.8 +    skip = "202 203 204 205 206 207 208 209 220 225 226 227 228 229 301 502 501"
   356.9 +    DIR_NAME = '/home'
  356.10 +
   357.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   357.2 +++ b/usr/share/isi-checkup/tests/202_need_dir_users.py	Mon Apr 26 11:16:23 2010 +0200
   357.3 @@ -0,0 +1,7 @@
   357.4 +from checkup import IsiTestDir
   357.5 +
   357.6 +class DirHomeUsers(IsiTestDir):
   357.7 +    run = True
   357.8 +    skip = "203 204 205 206 207 208 209"
   357.9 +    DIR_NAME = '/home/users'
  357.10 +
   358.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   358.2 +++ b/usr/share/isi-checkup/tests/203_need_dir_alunni.py	Mon Apr 26 11:16:23 2010 +0200
   358.3 @@ -0,0 +1,6 @@
   358.4 +from checkup import IsiTestDir
   358.5 +
   358.6 +class DirHomeUsersAlunni(IsiTestDir):
   358.7 +    run = True
   358.8 +    DIR_NAME = '/home/users/alunni'
   358.9 +
   359.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   359.2 +++ b/usr/share/isi-checkup/tests/204_need_dir_docenti.py	Mon Apr 26 11:16:23 2010 +0200
   359.3 @@ -0,0 +1,5 @@
   359.4 +from checkup import IsiTestDir
   359.5 +
   359.6 +class DirHomeUsersDocenti(IsiTestDir):
   359.7 +    run = True
   359.8 +    DIR_NAME = '/home/users/docenti'
   360.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   360.2 +++ b/usr/share/isi-checkup/tests/205_need_dir_admins.py	Mon Apr 26 11:16:23 2010 +0200
   360.3 @@ -0,0 +1,5 @@
   360.4 +from checkup import IsiTestDir
   360.5 +
   360.6 +class DirHomeUsersAdmins(IsiTestDir):
   360.7 +	run = True
   360.8 +	DIR_NAME = '/home/users/admins'
   361.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   361.2 +++ b/usr/share/isi-checkup/tests/206_need_dir_ata.py	Mon Apr 26 11:16:23 2010 +0200
   361.3 @@ -0,0 +1,5 @@
   361.4 +from checkup import IsiTestDir
   361.5 +
   361.6 +class DirHomeUsersAta(IsiTestDir):
   361.7 +	run = True
   361.8 +	DIR_NAME = '/home/users/ata'
   362.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   362.2 +++ b/usr/share/isi-checkup/tests/207_need_dir_esterni.py	Mon Apr 26 11:16:23 2010 +0200
   362.3 @@ -0,0 +1,5 @@
   362.4 +from checkup import IsiTestDir
   362.5 +
   362.6 +class DirHomeUsersEsterni(IsiTestDir):
   362.7 +	run = True
   362.8 +	DIR_NAME = '/home/users/esterni'
   363.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   363.2 +++ b/usr/share/isi-checkup/tests/208_need_dir_ospiti.py	Mon Apr 26 11:16:23 2010 +0200
   363.3 @@ -0,0 +1,5 @@
   363.4 +from checkup import IsiTestDir
   363.5 +
   363.6 +class DirHomeUsersOspiti(IsiTestDir):
   363.7 +	run = True
   363.8 +	DIR_NAME = '/home/users/ospiti'
   364.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   364.2 +++ b/usr/share/isi-checkup/tests/209_need_dir_segreteria.py	Mon Apr 26 11:16:23 2010 +0200
   364.3 @@ -0,0 +1,5 @@
   364.4 +from checkup import IsiTestDir
   364.5 +
   364.6 +class DirHomeUsersSegreteria(IsiTestDir):
   364.7 +	run = True
   364.8 +	DIR_NAME = '/home/users/segreteria'
   365.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   365.2 +++ b/usr/share/isi-checkup/tests/220_need_dir_shares.py	Mon Apr 26 11:16:23 2010 +0200
   365.3 @@ -0,0 +1,7 @@
   365.4 +from checkup import IsiTestDir
   365.5 +
   365.6 +class DirHomeShares(IsiTestDir):
   365.7 +    run = True
   365.8 +    skip = "301"
   365.9 +    DIR_NAME = '/home/shares'
  365.10 +
   366.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   366.2 +++ b/usr/share/isi-checkup/tests/225_need_dir_classi.py	Mon Apr 26 11:16:23 2010 +0200
   366.3 @@ -0,0 +1,7 @@
   366.4 +from checkup import IsiTestDir
   366.5 +
   366.6 +class DirHomeSharesClassi(IsiTestDir):
   366.7 +    run = True
   366.8 +    skip = "301"
   366.9 +    DIR_NAME = '/home/shares/classi'
  366.10 +
   367.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   367.2 +++ b/usr/share/isi-checkup/tests/226_need_dir_area_alunni.py	Mon Apr 26 11:16:23 2010 +0200
   367.3 @@ -0,0 +1,6 @@
   367.4 +from checkup import IsiTestDir
   367.5 +
   367.6 +class DirHomeSharesAreaAlunni(IsiTestDir):
   367.7 +    run = True
   367.8 +    DIR_NAME = '/home/shares/area_alunni'
   367.9 +
   368.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   368.2 +++ b/usr/share/isi-checkup/tests/227_need_dir_area_docenti.py	Mon Apr 26 11:16:23 2010 +0200
   368.3 @@ -0,0 +1,6 @@
   368.4 +from checkup import IsiTestDir
   368.5 +
   368.6 +class DirHomeSharesAreaDocenti(IsiTestDir):
   368.7 +    run = True
   368.8 +    DIR_NAME = '/home/shares/area_docenti'
   368.9 +
   369.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   369.2 +++ b/usr/share/isi-checkup/tests/228_need_dir_area_segreteria.py	Mon Apr 26 11:16:23 2010 +0200
   369.3 @@ -0,0 +1,6 @@
   369.4 +from checkup import IsiTestDir
   369.5 +
   369.6 +class DirHomeSharesAreaSegreteria(IsiTestDir):
   369.7 +    run = True
   369.8 +    DIR_NAME = '/home/shares/area_segreteria'
   369.9 +
   370.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   370.2 +++ b/usr/share/isi-checkup/tests/229_need_dir_corsi.py	Mon Apr 26 11:16:23 2010 +0200
   370.3 @@ -0,0 +1,7 @@
   370.4 +from checkup import IsiTestDir
   370.5 +
   370.6 +class DirHomeSharesCorsi(IsiTestDir):
   370.7 +    run = True
   370.8 +    skip = "301"
   370.9 +    DIR_NAME = '/home/shares/corsi'
  370.10 +
   371.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   371.2 +++ b/usr/share/isi-checkup/tests/230_ldap_same_secret.py	Mon Apr 26 11:16:23 2010 +0200
   371.3 @@ -0,0 +1,32 @@
   371.4 +#!/usr/bin/python
   371.5 +
   371.6 +import sys,os
   371.7 +import re
   371.8 +
   371.9 +from checkup import IsiTest
  371.10 +
  371.11 +class TestSamePw(IsiTest):
  371.12 +    run = True
  371.13 +    skip = "260"
  371.14 +    differences = False
  371.15 +    def __init__(self, user=None):
  371.16 +        pass
  371.17 +    
  371.18 +    def test_checkPw(self):
  371.19 +	self.pwLdap = open("/etc/ldap.secret"       ).readline().strip()
  371.20 +	self.pwNss  = open("/etc/libnss-ldap.secret").readline().strip()
  371.21 +	self.pwPam  = open("/etc/pam_ldap.secret"   ).readline().strip()
  371.22 +	
  371.23 +	if (self.pwLdap == self.pwNss == self.pwPam): return True
  371.24 +
  371.25 +        self.differences = True
  371.26 +
  371.27 +    def report(self):
  371.28 +        if self.differences:
  371.29 +            print " Password dei files ldap.secret differenti:"
  371.30 +            print "        /etc/ldap.secret : "+self.pwLdap
  371.31 +            print " /etc/libnss-ldap.secret : "+self.pwNss
  371.32 +            print "    /etc/pam_ldap.secret : "+self.pwPam
  371.33 +        
  371.34 +    def __str__(self):
  371.35 +            return "test %s" % (self.name)
   372.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   372.2 +++ b/usr/share/isi-checkup/tests/231_need_file_libnss-ldap.secret.py	Mon Apr 26 11:16:23 2010 +0200
   372.3 @@ -0,0 +1,7 @@
   372.4 +from checkup import IsiTestFile
   372.5 +
   372.6 +class FileLibNssLdapSecret(IsiTestFile):
   372.7 +    run = True
   372.8 +    skip = "232 260 325 320 307 308 309 320 325 330 331 332 333 334 335 336"
   372.9 +    FILE_NAME = '/etc/libnss-ldap.secret'
  372.10 +
   373.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   373.2 +++ b/usr/share/isi-checkup/tests/232_need_file_pam_ldap.secret.py	Mon Apr 26 11:16:23 2010 +0200
   373.3 @@ -0,0 +1,6 @@
   373.4 +from checkup import IsiTestFile
   373.5 +
   373.6 +class FilePamLdapSecret(IsiTestFile):
   373.7 +    run = True
   373.8 +    FILE_NAME = '/etc/pam_ldap.secret'
   373.9 +
   374.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   374.2 +++ b/usr/share/isi-checkup/tests/233_need_file_slapd_conf.py	Mon Apr 26 11:16:23 2010 +0200
   374.3 @@ -0,0 +1,7 @@
   374.4 +from checkup import IsiTestFile
   374.5 +
   374.6 +class FileSlapdConf(IsiTestFile):
   374.7 +    run = True
   374.8 +    skip = "260 325 320 307 308 309 320 325 330 331 332 333 334 335 336"
   374.9 +    FILE_NAME = "/etc/ldap/slapd.conf"
  374.10 +
   375.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   375.2 +++ b/usr/share/isi-checkup/tests/250_need_file_logon.conf.py	Mon Apr 26 11:16:23 2010 +0200
   375.3 @@ -0,0 +1,6 @@
   375.4 +from checkup import IsiTestFile
   375.5 +
   375.6 +class FileLogonConf(IsiTestFile):
   375.7 +    run = True
   375.8 +    FILE_NAME = '/etc/isi/logon.conf'
   375.9 +
   376.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   376.2 +++ b/usr/share/isi-checkup/tests/251_need_file_logon.bat.py	Mon Apr 26 11:16:23 2010 +0200
   376.3 @@ -0,0 +1,6 @@
   376.4 +from checkup import IsiTestFile
   376.5 +
   376.6 +class FileLogonBat(IsiTestFile):
   376.7 +    run = True
   376.8 +    FILE_NAME = '/etc/isi/logon.bat'
   376.9 +
   377.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   377.2 +++ b/usr/share/isi-checkup/tests/252_need_file_acl.conf.py	Mon Apr 26 11:16:23 2010 +0200
   377.3 @@ -0,0 +1,6 @@
   377.4 +from checkup import IsiTestFile
   377.5 +
   377.6 +class FileAclConf(IsiTestFile):
   377.7 +    run = True
   377.8 +    FILE_NAME = '/etc/isi/acl.conf'
   377.9 +
   378.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   378.2 +++ b/usr/share/isi-checkup/tests/253_need_file_sshd_config.py	Mon Apr 26 11:16:23 2010 +0200
   378.3 @@ -0,0 +1,7 @@
   378.4 +from checkup import IsiTestFile
   378.5 +
   378.6 +class FileSshdConfig(IsiTestFile):
   378.7 +    run = True
   378.8 +    skip = "261"
   378.9 +    FILE_NAME = '/etc/ssh/sshd_config'
  378.10 +
   379.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   379.2 +++ b/usr/share/isi-checkup/tests/254_need_file_named.conf.py	Mon Apr 26 11:16:23 2010 +0200
   379.3 @@ -0,0 +1,7 @@
   379.4 +from checkup import IsiTestFile
   379.5 +
   379.6 +class FileNamedConf(IsiTestFile):
   379.7 +    run = True
   379.8 +    skip = "268"
   379.9 +    FILE_NAME = '/etc/bind/named.conf'
  379.10 +
   380.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   380.2 +++ b/usr/share/isi-checkup/tests/260_need_process_slapd.py	Mon Apr 26 11:16:23 2010 +0200
   380.3 @@ -0,0 +1,6 @@
   380.4 +from checkup import IsiTestProcess
   380.5 +
   380.6 +class ProcessSlapd(IsiTestProcess):
   380.7 +    run = True
   380.8 +    skip = '260 261 262 263 264 265 266 267 268 269 271 272 273 274 275 276 277 278 279 280 281 300 301 307 310'    
   380.9 +    PROCESS_NAME='slapd'
   381.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   381.2 +++ b/usr/share/isi-checkup/tests/261_need_process_sshd.py	Mon Apr 26 11:16:23 2010 +0200
   381.3 @@ -0,0 +1,5 @@
   381.4 +from checkup import IsiTestProcess
   381.5 +
   381.6 +class ProcessSshd(IsiTestProcess):
   381.7 +    run = True
   381.8 +    PROCESS_NAME='sshd'
   382.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   382.2 +++ b/usr/share/isi-checkup/tests/262_need_process_dhcpd3.py	Mon Apr 26 11:16:23 2010 +0200
   382.3 @@ -0,0 +1,5 @@
   382.4 +from checkup import IsiTestProcess
   382.5 +
   382.6 +class ProcessDhcpd3(IsiTestProcess):
   382.7 +    run = True
   382.8 +    PROCESS_NAME='dhcpd3'
   383.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   383.2 +++ b/usr/share/isi-checkup/tests/263_need_process_smbd.py	Mon Apr 26 11:16:23 2010 +0200
   383.3 @@ -0,0 +1,5 @@
   383.4 +from checkup import IsiTestProcess
   383.5 +
   383.6 +class ProcessSmbd(IsiTestProcess):
   383.7 +    run = True
   383.8 +    PROCESS_NAME='smbd'
   384.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   384.2 +++ b/usr/share/isi-checkup/tests/264_need_process_nmbd.py	Mon Apr 26 11:16:23 2010 +0200
   384.3 @@ -0,0 +1,5 @@
   384.4 +from checkup import IsiTestProcess
   384.5 +
   384.6 +class ProcessNmbd(IsiTestProcess):
   384.7 +    run = True
   384.8 +    PROCESS_NAME='nmbd'
   385.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   385.2 +++ b/usr/share/isi-checkup/tests/265_need_process_squid.py	Mon Apr 26 11:16:23 2010 +0200
   385.3 @@ -0,0 +1,5 @@
   385.4 +from checkup import IsiTestProcess
   385.5 +
   385.6 +class ProcessSquid(IsiTestProcess):
   385.7 +    run = True
   385.8 +    PROCESS_NAME='squid'
   386.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   386.2 +++ b/usr/share/isi-checkup/tests/266_need_process_dansguardian.py	Mon Apr 26 11:16:23 2010 +0200
   386.3 @@ -0,0 +1,5 @@
   386.4 +from checkup import IsiTestProcess
   386.5 +
   386.6 +class ProcessDansguardian(IsiTestProcess):
   386.7 +    run = True
   386.8 +    PROCESS_NAME='dansguardian'
   387.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   387.2 +++ b/usr/share/isi-checkup/tests/267_need_process_master.py	Mon Apr 26 11:16:23 2010 +0200
   387.3 @@ -0,0 +1,5 @@
   387.4 +from checkup import IsiTestProcess
   387.5 +
   387.6 +class ProcessPostfix(IsiTestProcess):
   387.7 +    run = True
   387.8 +    PROCESS_NAME='master'
   388.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   388.2 +++ b/usr/share/isi-checkup/tests/268_need_process_named.py	Mon Apr 26 11:16:23 2010 +0200
   388.3 @@ -0,0 +1,5 @@
   388.4 +from checkup import IsiTestProcess
   388.5 +
   388.6 +class ProcessBind9(IsiTestProcess):
   388.7 +    run = True
   388.8 +    PROCESS_NAME='named'
   389.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   389.2 +++ b/usr/share/isi-checkup/tests/269_need_process_nscd.py	Mon Apr 26 11:16:23 2010 +0200
   389.3 @@ -0,0 +1,5 @@
   389.4 +from checkup import IsiTestProcess
   389.5 +
   389.6 +class ProcessNscd(IsiTestProcess):
   389.7 +    run = True
   389.8 +    PROCESS_NAME='nscd'
   390.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   390.2 +++ b/usr/share/isi-checkup/tests/271_samba_share_homes.py	Mon Apr 26 11:16:23 2010 +0200
   390.3 @@ -0,0 +1,6 @@
   390.4 +from checkup import IsiTestSambaShare
   390.5 +
   390.6 +class ShareHomes(IsiTestSambaShare):
   390.7 +    run = True
   390.8 +    SAMBA_SHARE_NAME = 'homes'
   390.9 +
   391.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   391.2 +++ b/usr/share/isi-checkup/tests/272_samba_share_netlogon.py	Mon Apr 26 11:16:23 2010 +0200
   391.3 @@ -0,0 +1,6 @@
   391.4 +from checkup import IsiTestSambaShare
   391.5 +
   391.6 +class ShareNetlogon(IsiTestSambaShare):
   391.7 +    run = True
   391.8 +    SAMBA_SHARE_NAME = 'netlogon'
   391.9 +
   392.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   392.2 +++ b/usr/share/isi-checkup/tests/273_samba_share_software.py	Mon Apr 26 11:16:23 2010 +0200
   392.3 @@ -0,0 +1,6 @@
   392.4 +from checkup import IsiTestSambaShare
   392.5 +
   392.6 +class ShareSoftware(IsiTestSambaShare):
   392.7 +    run = True
   392.8 +    SAMBA_SHARE_NAME = 'software'
   392.9 +
   393.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   393.2 +++ b/usr/share/isi-checkup/tests/274_samba_share_dati.py	Mon Apr 26 11:16:23 2010 +0200
   393.3 @@ -0,0 +1,6 @@
   393.4 +from checkup import IsiTestSambaShare
   393.5 +
   393.6 +class ShareDati(IsiTestSambaShare):
   393.7 +    run = True
   393.8 +    SAMBA_SHARE_NAME = 'dati'
   393.9 +
   394.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   394.2 +++ b/usr/share/isi-checkup/tests/275_samba_share_classi.py	Mon Apr 26 11:16:23 2010 +0200
   394.3 @@ -0,0 +1,6 @@
   394.4 +from checkup import IsiTestSambaShare
   394.5 +
   394.6 +class ShareClassi(IsiTestSambaShare):
   394.7 +    run = True
   394.8 +    SAMBA_SHARE_NAME = 'classi'
   394.9 +
   395.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   395.2 +++ b/usr/share/isi-checkup/tests/276_samba_share_corsi.py	Mon Apr 26 11:16:23 2010 +0200
   395.3 @@ -0,0 +1,6 @@
   395.4 +from checkup import IsiTestSambaShare
   395.5 +
   395.6 +class ShareCorsi(IsiTestSambaShare):
   395.7 +    run = True
   395.8 +    SAMBA_SHARE_NAME = 'corsi'
   395.9 +
   396.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   396.2 +++ b/usr/share/isi-checkup/tests/277_samba_share_perl.py	Mon Apr 26 11:16:23 2010 +0200
   396.3 @@ -0,0 +1,6 @@
   396.4 +from checkup import IsiTestSambaShare
   396.5 +
   396.6 +class SharePerl(IsiTestSambaShare):
   396.7 +    run = True
   396.8 +    SAMBA_SHARE_NAME = 'perl'
   396.9 +
   397.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   397.2 +++ b/usr/share/isi-checkup/tests/278_samba_share_printers.py	Mon Apr 26 11:16:23 2010 +0200
   397.3 @@ -0,0 +1,6 @@
   397.4 +from checkup import IsiTestSambaShare
   397.5 +
   397.6 +class SharePrinters(IsiTestSambaShare):
   397.7 +    run = True
   397.8 +    SAMBA_SHARE_NAME = 'printers'
   397.9 +
   398.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   398.2 +++ b/usr/share/isi-checkup/tests/279_samba_share_area_alunni.py	Mon Apr 26 11:16:23 2010 +0200
   398.3 @@ -0,0 +1,6 @@
   398.4 +from checkup import IsiTestSambaShare
   398.5 +
   398.6 +class ShareAreaAlunni(IsiTestSambaShare):
   398.7 +    run = True
   398.8 +    SAMBA_SHARE_NAME = 'area_alunni'
   398.9 +
   399.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   399.2 +++ b/usr/share/isi-checkup/tests/280_samba_share_area_docenti.py	Mon Apr 26 11:16:23 2010 +0200
   399.3 @@ -0,0 +1,6 @@
   399.4 +from checkup import IsiTestSambaShare
   399.5 +
   399.6 +class ShareAreaDocenti(IsiTestSambaShare):
   399.7 +    run = True
   399.8 +    SAMBA_SHARE_NAME = 'area_docenti'
   399.9 +
   400.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   400.2 +++ b/usr/share/isi-checkup/tests/281_samba_share_area_segreteria.py	Mon Apr 26 11:16:23 2010 +0200
   400.3 @@ -0,0 +1,13 @@
   400.4 +from checkup import IsiTestSambaShare
   400.5 +
   400.6 +class ShareAreaSegreteria(IsiTestSambaShare):
   400.7 +    run = True
   400.8 +    SAMBA_SHARE_NAME = 'area_segreteria'
   400.9 +
  400.10 +
  400.11 +
  400.12 +
  400.13 +
  400.14 +
  400.15 +
  400.16 +
   401.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   401.2 +++ b/usr/share/isi-checkup/tests/300_samba_shares_paths.py	Mon Apr 26 11:16:23 2010 +0200
   401.3 @@ -0,0 +1,56 @@
   401.4 +#!/usr/bin/python
   401.5 +import sys
   401.6 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
   401.7 +from checkup import IsiTest, InputStream
   401.8 +
   401.9 +from dry.functions import execute
  401.10 +import re
  401.11 +import ConfigParser
  401.12 +import os
  401.13 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
  401.14 +from checkup import IsiTest, TestError
  401.15 +
  401.16 +class SharesHavePath(IsiTest):
  401.17 +    run = True
  401.18 +
  401.19 +    def __init__(self, user=None):
  401.20 +        ret_code, sambaconf, err = execute('testparm -s')
  401.21 +        f = InputStream(data=sambaconf)
  401.22 +        self.parser = ConfigParser.ConfigParser()
  401.23 +        self.parser.readfp(f, 'cfg')
  401.24 +        self.sections = self.parser.sections()
  401.25 +        self.missing = []
  401.26 +
  401.27 +    def get_share_paths(self):
  401.28 +        """ Returns samba shares paths """
  401.29 +        sharePaths = []
  401.30 +        for section in self.parser.sections():
  401.31 +            items = self.parser.items(section)
  401.32 +            item_with_path = ([item[1] for item in items\
  401.33 +                               if 'path' in item])
  401.34 +            # filtering env variable elements
  401.35 +            if re.search('%', str(item_with_path)): continue
  401.36 +            sharePaths += item_with_path
  401.37 +        return sharePaths
  401.38 +
  401.39 +    def test_share_paths_exist(self):
  401.40 +        """ check if defined samba share paths exist """
  401.41 +        share_paths = self.get_share_paths()
  401.42 +        for path in share_paths:
  401.43 +            if os.path.isdir(path): continue
  401.44 +            self.missing += [path]
  401.45 +        if not self.missing:
  401.46 +            return True
  401.47 +        return False
  401.48 +            
  401.49 +    def report(self):
  401.50 +        if self.missing:
  401.51 +            #msg = 'PATH richiesti da shares definite assenti\n'
  401.52 +            #msg += '-'*len(msg)
  401.53 +            #print msg
  401.54 +            print 'PATH richiesti da shares definite assenti'
  401.55 +            for share in self.missing:
  401.56 +                print "    ", share
  401.57 +
  401.58 +    def __str__(self):
  401.59 +            return "test %s" % (self.name)
   402.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   402.2 +++ b/usr/share/isi-checkup/tests/301_class_path_name.py	Mon Apr 26 11:16:23 2010 +0200
   402.3 @@ -0,0 +1,75 @@
   402.4 +#!/usr/bin/python
   402.5 +import sys
   402.6 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
   402.7 +from checkup import IsiTest, InputStream
   402.8 +
   402.9 +from dry.functions import execute
  402.10 +import re
  402.11 +import ConfigParser
  402.12 +import os
  402.13 +#from isi.srv import CLASSES, COURSES
  402.14 +from isi import srv 
  402.15 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
  402.16 +from checkup import IsiTest, TestError
  402.17 +CLASSES = srv.get_classes()
  402.18 +COURSES = srv.get_courses()
  402.19 +
  402.20 +class SharesHavePath(IsiTest):
  402.21 +    run = True
  402.22 +
  402.23 +    def __init__(self, user=None):
  402.24 +        ret_code, sambaconf, err = execute('testparm -s')
  402.25 +        f = InputStream(data=sambaconf)
  402.26 +        self.parser = ConfigParser.ConfigParser()
  402.27 +        self.parser.readfp(f, 'cfg')
  402.28 +        self.sections = self.parser.sections()
  402.29 +
  402.30 +        self.bad_classes = []
  402.31 +        self.bad_courses = []
  402.32 +
  402.33 +    def get_share_paths_last(self):
  402.34 +        """ Returns samba shares paths """
  402.35 +        share_paths_last = []
  402.36 +        for section in self.parser.sections():
  402.37 +            items = self.parser.items(section)
  402.38 +            item_with_path = ([item[1] for item in items\
  402.39 +                               if 'path' in item])
  402.40 +            # filtering env variable elements with '%' character
  402.41 +            if re.search('%', str(item_with_path)): continue
  402.42 +
  402.43 +            # get last last path name element
  402.44 +            item_without_path = [ el.split('/')[-1] for el in item_with_path]
  402.45 +            share_paths_last += item_without_path
  402.46 +
  402.47 +        return share_paths_last
  402.48 +    
  402.49 +    def test_class_path_name(self):
  402.50 +        """
  402.51 +        Checks if the defined "CLASS/COURSE NAME" is the last element of the
  402.52 +        defined "PATH NAME"
  402.53 +        """
  402.54 +        share_paths_name = self.get_share_paths_last()
  402.55 +
  402.56 +        for CLASS in CLASSES:
  402.57 +            if CLASS not in share_paths_name:
  402.58 +                self.bad_classes += [CLASS]
  402.59 +                
  402.60 +        for COURSE in COURSES:
  402.61 +            if not COURSE in share_paths_name:
  402.62 +                self.bad_courses += [COURSE]
  402.63 +
  402.64 +        if not self.bad_courses or self.bad_classes:
  402.65 +            return True
  402.66 +        
  402.67 +    def report(self):
  402.68 +        if self.bad_classes:
  402.69 +            print 'Le segg. CLASSI hanno nomi samba non coincidenti con il PATH:'
  402.70 +            for bad_class in self.bad_classes:
  402.71 +                print "    ", bad_class
  402.72 +        if self.bad_courses:
  402.73 +            print 'I segg. CORSI hanno nomi samba non coincidenti con il PATH:'
  402.74 +            for bad_course in self.bad_courses:
  402.75 +                print "    ", bad_course
  402.76 +
  402.77 +    def __str__(self):
  402.78 +            return "test %s" % (self.name)
   403.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   403.2 +++ b/usr/share/isi-checkup/tests/307_ldap_connect.py	Mon Apr 26 11:16:23 2010 +0200
   403.3 @@ -0,0 +1,14 @@
   403.4 +from checkup import IsiTest
   403.5 +from ldap import INVALID_CREDENTIALS
   403.6 +import isi
   403.7 +
   403.8 +class LdapConnect(IsiTest):
   403.9 +    skip = "308 309 330 331 332 333 334 335 336 501"
  403.10 +    run = True
  403.11 +    
  403.12 +    def test_slapd_conn_parameter(self):
  403.13 +        try:
  403.14 +            self.srv  =  isi.IsiConn()
  403.15 +            return True
  403.16 +        except INVALID_CREDENTIALS:
  403.17 +            return False
   404.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   404.2 +++ b/usr/share/isi-checkup/tests/308_user_exists_administrator.py	Mon Apr 26 11:16:23 2010 +0200
   404.3 @@ -0,0 +1,6 @@
   404.4 +from checkup import IsiTestUserExist
   404.5 +
   404.6 +class UserAdministrator(IsiTestUserExist):
   404.7 +    run = True
   404.8 +    USER = 'administrator'
   404.9 +    skip = '309 310'
   405.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   405.2 +++ b/usr/share/isi-checkup/tests/309_administrator_credential.py	Mon Apr 26 11:16:23 2010 +0200
   405.3 @@ -0,0 +1,39 @@
   405.4 +import isi
   405.5 +import os
   405.6 +from checkup import IsiTest
   405.7 +I = isi.IsiConn()
   405.8 +
   405.9 +class CheckAdministratorCredential(IsiTest):
  405.10 +    """
  405.11 +    Checks if administrator password == /etc/ldap.secret
  405.12 +    or
  405.13 +    administrator password == /etc/administrator.secret
  405.14 +    """
  405.15 +    name = 'Check Administrator Credential'
  405.16 +    run = True
  405.17 +    skip = '310'
  405.18 +    MATCH = False
  405.19 +    
  405.20 +    def __init__(self, user=None):
  405.21 +        if os.path.isfile('/etc/administrator.secret'):
  405.22 +            self.AUTH_PW = open('/etc/administrator.secret').read().strip()
  405.23 +        else:
  405.24 +            self.AUTH_PW = open('/etc/ldap.secret').read().strip()
  405.25 +        
  405.26 +    def test_administrator_credential(self):
  405.27 +        if I.test_password('administrator', self.AUTH_PW):
  405.28 +            self.MATCH = True
  405.29 +            return True
  405.30 +        else:
  405.31 +            return False
  405.32 +    
  405.33 +
  405.34 +    def report(self):
  405.35 +        if not self.MATCH:
  405.36 +            print "\nLa password di 'administrator' differisce da quella trovata in \n"+\
  405.37 +                  "/etc/ldap.secret. Non e' un errore ma alcuni test necessitano di \n"+\
  405.38 +                  "conoscere la password di 'administrator'.\n"+\
  405.39 +                  "Inseriscila in '/etc/administrator.secret'\n"
  405.40 +             
  405.41 +    def __str__(self):
  405.42 +        return "test %s" % (self.name)
   406.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   406.2 +++ b/usr/share/isi-checkup/tests/310_DomainAdmins_group_priv.py	Mon Apr 26 11:16:23 2010 +0200
   406.3 @@ -0,0 +1,37 @@
   406.4 +import os
   406.5 +from checkup import SambaGroupPrivs
   406.6 +
   406.7 +class DomainAdminsPrivs(SambaGroupPrivs):
   406.8 +    """
   406.9 +    Checks if a particular group has needed privs
  406.10 +    
  406.11 +    Privilege definition
  406.12 +    ====================
  406.13 +
  406.14 +    SeMachineAccountPrivilege  Add machines to domain
  406.15 +    SeTakeOwnershipPrivilege  Take ownership of files or other objects
  406.16 +    SeBackupPrivilege  Back up files and directories
  406.17 +    SeRestorePrivilege  Restore files and directories
  406.18 +    SeRemoteShutdownPrivilege  Force shutdown from a remote system
  406.19 +    SePrintOperatorPrivilege  Manage printers
  406.20 +    SeAddUsersPrivilege  Add users and groups to the domain
  406.21 +    SeDiskOperatorPrivilege  Manage disk shares
  406.22 +    """
  406.23 +    run = True
  406.24 +    
  406.25 +    NEEDED_PRIV_LIST = ['SeMachineAccountPrivilege',
  406.26 +                        'SeTakeOwnershipPrivilege',
  406.27 +                        'SeBackupPrivilege',
  406.28 +                        'SeRestorePrivilege',
  406.29 +                        'SeRemoteShutdownPrivilege',
  406.30 +                        'SePrintOperatorPrivilege',
  406.31 +                        'SeAddUsersPrivilege',
  406.32 +                        'SeDiskOperatorPrivilege',]
  406.33 +    GROUP = 'Domain Admins'
  406.34 +    AUTH_USER = 'administrator'
  406.35 +
  406.36 +    if os.path.isfile('/etc/administrator.secret'):
  406.37 +        AUTH_PW = open('/etc/administrator.secret').read().strip()
  406.38 +    else:
  406.39 +        AUTH_PW = open('/etc/ldap.secret').read().strip()
  406.40 +
   407.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   407.2 +++ b/usr/share/isi-checkup/tests/320_ldap_sizelimit.py	Mon Apr 26 11:16:23 2010 +0200
   407.3 @@ -0,0 +1,53 @@
   407.4 +import re
   407.5 +from dry.functions import execute
   407.6 +import sys
   407.7 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
   407.8 +from checkup import IsiTest, TestError
   407.9 +
  407.10 +class LdapSizelimit(IsiTest):
  407.11 +    """ Checks if ldap < 1500 """
  407.12 +    run = True
  407.13 +    
  407.14 +    def __init__(self, user=None):
  407.15 +        self.LOW_SIZELIMIT = False
  407.16 +        
  407.17 +    def get_ldap_sizelimit(self):
  407.18 +        pattern = '^\S*sizelimit\S*(?P<sizelimit>.+)'
  407.19 +        f = open('/etc/ldap/slapd.conf')
  407.20 +        for line in f.readlines():
  407.21 +            m = re.match(pattern, line)
  407.22 +            if m:
  407.23 +                m = m.groupdict()
  407.24 +                sizelimit = m['sizelimit']
  407.25 +                return int(sizelimit)
  407.26 +
  407.27 +    def test_ldap_lowSizelimit(self):
  407.28 +        self.SIZE_LIMIT = self.get_ldap_sizelimit()
  407.29 +        if not self.SIZE_LIMIT < 1500:
  407.30 +            return True
  407.31 +        self.LOW_SIZELIMIT = True
  407.32 +
  407.33 +    def report(self):
  407.34 +        if self.LOW_SIZELIMIT:
  407.35 +            print 'Parametro ldap "sizelimit" inferiore a 1500'
  407.36 +            print '    sizelimit : ', self.SIZE_LIMIT
  407.37 +
  407.38 +    def __str__(self):
  407.39 +            return "test %s" % (self.name)
  407.40 +
  407.41 +
  407.42 +
  407.43 +
  407.44 +
  407.45 +
  407.46 +
  407.47 +
  407.48 +
  407.49 +
  407.50 +
  407.51 +
  407.52 +
  407.53 +
  407.54 +
  407.55 +
  407.56 +
   408.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   408.2 +++ b/usr/share/isi-checkup/tests/321_checkgunum.sh	Mon Apr 26 11:16:23 2010 +0200
   408.3 @@ -0,0 +1,25 @@
   408.4 +#!/bin/bash
   408.5 +
   408.6 +domain=$(grep 'workgroup' /etc/samba/smb.conf | awk {'print $3'})
   408.7 +
   408.8 +uidNumber=$(ldapsearch -xLLL sambaDomainName=$domain dn uidNumber | grep uid)
   408.9 +gidNumber=$(ldapsearch -xLLL sambaDomainName=$domain dn gidNumber | grep gid)
  408.10 +
  408.11 +if [ -z "$uidNumber" ]; then
  408.12 +
  408.13 +    if [ -z "$gidNumber" ]; then
  408.14 +        echo 'Campi ldap uidNumber e gidNumber assenti !!!'
  408.15 +        exit 1
  408.16 +    else
  408.17 +        echo 'Campo ldap uidNumber assente !!!'
  408.18 +        exit 1
  408.19 +    fi
  408.20 +else
  408.21 +    if [ -z "$gidNumber" ]; then
  408.22 +        echo 'Campo ldap gidNumber assente !!!'
  408.23 +        exit 1
  408.24 +    fi
  408.25 +fi
  408.26 +
  408.27 +exit 0
  408.28 +
   409.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   409.2 +++ b/usr/share/isi-checkup/tests/325_smbldap_homePath.py	Mon Apr 26 11:16:23 2010 +0200
   409.3 @@ -0,0 +1,97 @@
   409.4 +#!/usr/bin/python
   409.5 +"""
   409.6 +SID="S-1-5-21-3099135007-616077390-1994049917"
   409.7 +slaveLDAP="127.0.0.1"
   409.8 +slavePort="389"
   409.9 +masterLDAP="127.0.0.1"
  409.10 +masterPort="389"
  409.11 +ldapTLS="0"
  409.12 +suffix="dc=isi,dc=lan"
  409.13 +usersdn="ou=People,dc=isi,dc=lan"
  409.14 +computersdn="ou=Computers,dc=isi,dc=lan"
  409.15 +groupsdn="ou=Groups,dc=isi,dc=lan"
  409.16 +idmapdn="ou=Idmap,dc=isi,dc=lan"
  409.17 +sambaUnixIdPooldn="sambaDomainName=ITIS-RIVA,dc=isi,dc=lan"
  409.18 +scope="sub"
  409.19 +hash_encrypt="SSHA"
  409.20 +crypt_salt_format="%s"
  409.21 +userLoginShell="/bin/bash"
  409.22 +userHome="/home/%U"
  409.23 +userGecos="System User"
  409.24 +defaultUserGid="513"
  409.25 +defaultComputerGid="515"
  409.26 +skeletonDir="/etc/skel"
  409.27 +defaultMaxPasswordAge="99"
  409.28 +userSmbHome="\\ISI-PDC\%U"
  409.29 +userProfile="\\ISI-PDC\profiles"
  409.30 +userHomeDrive="H:"
  409.31 +mailDomain="isi.lan"
  409.32 +with_smbpasswd="0"
  409.33 +smbpasswd="/usr/bin/smbpasswd"
  409.34 +SID for domain SARGO is: S-1-5-21-1479175027-3375466229-471917732
  409.35 +"""
  409.36 +
  409.37 +import re
  409.38 +from dry.functions import execute
  409.39 +import sys
  409.40 +sys.path.insert(0, '/usr/share/isi-checkup/lib')
  409.41 +from checkup import IsiTest, TestError
  409.42 +
  409.43 +class Smbldap_homePath(IsiTest):
  409.44 +    run = True
  409.45 +    name = 'smbldap_homePath'
  409.46 +
  409.47 +    paramToFind = 'userSmbHome userProfile'
  409.48 +    paramFound = {}
  409.49 +
  409.50 +    def __init__(self, user=None):
  409.51 +                pass
  409.52 +
  409.53 +    def parse_smbldap_conf(self):
  409.54 +        """
  409.55 +        return /etc/smbldap-tools/smbldap.conf par
  409.56 +
  409.57 +        TODO: affinare regexp (matcha grossolanamente)
  409.58 +        """
  409.59 +        cfg_parsed = {}
  409.60 +        f = open('/etc/smbldap-tools/smbldap.conf')
  409.61 +
  409.62 +        pattern = '^\s*(?P<key>.+)\s*=+\s*(?P<value>.+)\s*$'
  409.63 +        for line in f.readlines():
  409.64 +        #for line in __doc__.split('\n'):
  409.65 +            if re.match('^\s*$', line):
  409.66 +                continue
  409.67 +            m = re.search(pattern, line)
  409.68 +            if m:
  409.69 +                key = m.group('key')
  409.70 +                value = m.group('value')
  409.71 +
  409.72 +                cfg_parsed[key] = value
  409.73 +
  409.74 +        return cfg_parsed
  409.75 +    
  409.76 +    def findParam(self):
  409.77 +        cfg = self.parse_smbldap_conf()
  409.78 +
  409.79 +        for key in self.paramToFind.split():
  409.80 +            if cfg.has_key(key) and cfg[key].strip('"\''):
  409.81 +                self.paramFound[key] = cfg[key]
  409.82 +
  409.83 +        return self.paramFound
  409.84 +
  409.85 +    def test_smbldap_homePath(self):
  409.86 +        if not self.findParam():
  409.87 +            return True
  409.88 +        return False
  409.89 +
  409.90 +    def report(self):
  409.91 +        if self.paramFound:
  409.92 +            paramFound = self.paramFound
  409.93 +            print "WARNING  '/etc/smbldap-tools/smbldap.conf'"+\
  409.94 +                  "presenta i seguenti campi obsoleti:\n"
  409.95 +            for key in paramFound.keys():
  409.96 +                print "%s = %s" % (key, paramFound[key])
  409.97 +
  409.98 +    def __str__(self):
  409.99 +        return "test %s" % (self.name)
 409.100 +                                                
   410.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   410.2 +++ b/usr/share/isi-checkup/tests/330_group_exists_docenti.py	Mon Apr 26 11:16:23 2010 +0200
   410.3 @@ -0,0 +1,5 @@
   410.4 +from checkup import IsiTestGroup
   410.5 +
   410.6 +class GroupDocenti(IsiTestGroup):
   410.7 +    GROUP = 'docenti'
   410.8 +    run = True
   411.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   411.2 +++ b/usr/share/isi-checkup/tests/331_group_exists_alunni.py	Mon Apr 26 11:16:23 2010 +0200
   411.3 @@ -0,0 +1,5 @@
   411.4 +from checkup import IsiTestGroup
   411.5 +
   411.6 +class GroupDocenti(IsiTestGroup):
   411.7 +    GROUP = 'alunni'
   411.8 +    run = True
   412.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   412.2 +++ b/usr/share/isi-checkup/tests/332_group_exists_admins.py	Mon Apr 26 11:16:23 2010 +0200
   412.3 @@ -0,0 +1,5 @@
   412.4 +from checkup import IsiTestGroup
   412.5 +
   412.6 +class GroupDocenti(IsiTestGroup):
   412.7 +    GROUP = 'admins'
   412.8 +    run = True
   413.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   413.2 +++ b/usr/share/isi-checkup/tests/333_group_exists_ata.py	Mon Apr 26 11:16:23 2010 +0200
   413.3 @@ -0,0 +1,5 @@
   413.4 +from checkup import IsiTestGroup
   413.5 +
   413.6 +class GroupDocenti(IsiTestGroup):
   413.7 +    GROUP = 'ata'
   413.8 +    run = True
   414.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   414.2 +++ b/usr/share/isi-checkup/tests/334_group_exists_esterni.py	Mon Apr 26 11:16:23 2010 +0200
   414.3 @@ -0,0 +1,5 @@
   414.4 +from checkup import IsiTestGroup
   414.5 +
   414.6 +class GroupDocenti(IsiTestGroup):
   414.7 +    GROUP = 'esterni'
   414.8 +    run = True
   415.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   415.2 +++ b/usr/share/isi-checkup/tests/335_group_exists_ospiti.py	Mon Apr 26 11:16:23 2010 +0200
   415.3 @@ -0,0 +1,5 @@
   415.4 +from checkup import IsiTestGroup
   415.5 +
   415.6 +class GroupDocenti(IsiTestGroup):
   415.7 +    GROUP = 'ospiti'
   415.8 +    run = True
   416.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   416.2 +++ b/usr/share/isi-checkup/tests/336_group_exists_segreteria.py	Mon Apr 26 11:16:23 2010 +0200
   416.3 @@ -0,0 +1,5 @@
   416.4 +from checkup import IsiTestGroup
   416.5 +
   416.6 +class GroupDocenti(IsiTestGroup):
   416.7 +    GROUP = 'segreteria'
   416.8 +    run = True
   417.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   417.2 +++ b/usr/share/isi-checkup/tests/340_logon-bat.py	Mon Apr 26 11:16:23 2010 +0200
   417.3 @@ -0,0 +1,66 @@
   417.4 +from checkup import IsiTest
   417.5 +import re
   417.6 +
   417.7 +class LogonBat(IsiTest):
   417.8 +    name = 'logon_bat'
   417.9 +    skip = ''
  417.10 +    run = True  
  417.11 +        
  417.12 +    def __init__(self, user=None):
  417.13 +        self.no_match = False
  417.14 +        self.netbios_name = self.get_netbios_name()
  417.15 +
  417.16 +    def get_netbios_name(self):
  417.17 +        """Returns the netbios name configured in smb.conf"""
  417.18 +
  417.19 +        exclude_match = '^\s*#|^\s*;|^$'
  417.20 +        match = '^\s*(?P<key>netbios name)\s*=\s*(?P<value>.+)$'
  417.21 +
  417.22 +        try:
  417.23 +            f = open('/etc/samba/smb.conf').read().split('\n')
  417.24 +        except Exception:
  417.25 +            pass
  417.26 +
  417.27 +        for line in f:
  417.28 +            if re.search(exclude_match, line):
  417.29 +                continue 
  417.30 +            m = re.search(match, line)
  417.31 +            if m:
  417.32 +                return m.group('value')
  417.33 +
  417.34 +    def test_logon_bat(self):
  417.35 +        """
  417.36 +        Checks if the netbios name is missing in /etc/isi/logon.conf
  417.37 +        """
  417.38 +        netbios_name = self.get_netbios_name()
  417.39 +        share_perl = '\\\\%s\\perl\\bin\\perl' % netbios_name
  417.40 +        share_logon_pl = '\\\\%s\\perl\\logon.pl' % netbios_name
  417.41 +        self.cfg_expected =  " ".join([share_perl, share_logon_pl, netbios_name])
  417.42 +
  417.43 +        try:
  417.44 +            f = open('/etc/isi/logon.bat').read().split('\n') 
  417.45 +        except Exception:
  417.46 +            pass
  417.47 +        for line in f:
  417.48 +            if not re.search('^\s*\\\\', line):
  417.49 +                continue
  417.50 +            self.line = line
  417.51 +
  417.52 +            for element in line.split():
  417.53 +                if element != share_perl and\
  417.54 +                   element != share_logon_pl and\
  417.55 +                   element != netbios_name:
  417.56 +                   self.no_match = True
  417.57 +                   
  417.58 +        if self.no_match:
  417.59 +            return False
  417.60 +        return True
  417.61 +
  417.62 +    def report(self):
  417.63 +        if self.no_match:
  417.64 +            print 'Configurazione di "/etc/isi/logon.bat" non coerente'
  417.65 +            print '    attuale: %s' % self.line    
  417.66 +            print '     attesa: %s' % self.cfg_expected        
  417.67 +
  417.68 +    def __str__(self):
  417.69 +        return "test %s" % (self.name)
   418.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   418.2 +++ b/usr/share/isi-checkup/tests/341_logonupd-bat.py	Mon Apr 26 11:16:23 2010 +0200
   418.3 @@ -0,0 +1,66 @@
   418.4 +from checkup import IsiTest
   418.5 +import re
   418.6 +
   418.7 +class LogonupdBat(IsiTest):
   418.8 +    name = 'logonupd_bat'
   418.9 +    skip = ''
  418.10 +    run = True  
  418.11 +        
  418.12 +    def __init__(self, user=None):
  418.13 +        self.no_match = False
  418.14 +        self.netbios_name = self.get_netbios_name()
  418.15 +
  418.16 +    def get_netbios_name(self):
  418.17 +        """Returns the netbios name configured in smb.conf"""
  418.18 +
  418.19 +        exclude_match = '^\s*#|^\s*;|^$'
  418.20 +        match = '^\s*(?P<key>netbios name)\s*=\s*(?P<value>.+)$'
  418.21 +
  418.22 +        try:
  418.23 +            f = open('/etc/samba/smb.conf').read().split('\n')
  418.24 +        except Exception:
  418.25 +            pass
  418.26 +
  418.27 +        for line in f:
  418.28 +            if re.search(exclude_match, line):
  418.29 +                continue 
  418.30 +            m = re.search(match, line)
  418.31 +            if m:
  418.32 +                return m.group('value')
  418.33 +
  418.34 +    def test_logonupd_bat(self):
  418.35 +        """
  418.36 +        Checks if the netbios name is missing in /etc/isi/logonupd.conf
  418.37 +        """
  418.38 +        netbios_name = self.get_netbios_name()
  418.39 +        share_perl = '\\\\%s\\perl\\bin\\perl' % netbios_name
  418.40 +        share_logonupd_pl = '\\\\%s\\perl\\logonupd.pl' % netbios_name
  418.41 +        self.cfg_expected =  " ".join([share_perl, share_logonupd_pl, netbios_name])
  418.42 +
  418.43 +        try:
  418.44 +            f = open('/etc/isi/logonupd.bat').read().split('\n') 
  418.45 +        except Exception:
  418.46 +            pass
  418.47 +        for line in f:
  418.48 +            if not re.search('^\s*\\\\', line):
  418.49 +                continue
  418.50 +            self.line = line
  418.51 +
  418.52 +            for element in line.split():
  418.53 +                if element != share_perl and\
  418.54 +                   element != share_logonupd_pl and\
  418.55 +                   element != netbios_name:
  418.56 +                   self.no_match = True
  418.57 +                   
  418.58 +        if self.no_match:
  418.59 +            return False
  418.60 +        return True
  418.61 +
  418.62 +    def report(self):
  418.63 +        if self.no_match:
  418.64 +            print 'Configurazione di "/etc/isi/logonupd.bat" non coerente'
  418.65 +            print '    attuale: %s' % self.line    
  418.66 +            print '     attesa: %s' % self.cfg_expected        
  418.67 +
  418.68 +    def __str__(self):
  418.69 +        return "test %s" % (self.name)
   419.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   419.2 +++ b/usr/share/isi-checkup/tests/342_nscd_no_persistent.py	Mon Apr 26 11:16:23 2010 +0200
   419.3 @@ -0,0 +1,45 @@
   419.4 +#!/usr/bin/python
   419.5 +
   419.6 +from checkup import IsiTest
   419.7 +import re
   419.8 +import os
   419.9 +
  419.10 +class nscd_persistent(IsiTest):
  419.11 +    run = True
  419.12 +    name = 'check nscd persistent'
  419.13 +    bad_services = []       
  419.14 +    
  419.15 +    def check_persistent(self):
  419.16 +        """ 
  419.17 +        Returns bad_services list of services found 
  419.18 +        or bad_services=None.
  419.19 +        """
  419.20 +        f = open('/etc/nscd.conf').read()
  419.21 +        
  419.22 +        for line in f.split('\n'):
  419.23 +            if re.match('^\s*#', line):
  419.24 +                continue
  419.25 +            if not 'persistent' in line:
  419.26 +                continue
  419.27 +            persistent, service, active = line.split()
  419.28 +            if active == 'yes':
  419.29 +                self.bad_services += [service]
  419.30 +                
  419.31 +        return self.bad_services
  419.32 +            
  419.33 +    def test_nscd_persistent(self):
  419.34 +        if os.path.isfile('/etc/nscd.conf'):
  419.35 +            if not self.check_persistent():
  419.36 +                return True
  419.37 +            else:
  419.38 +                return False
  419.39 +
  419.40 +    def report(self):
  419.41 +        if self.bad_services:
  419.42 +            print '\nDisattiva in /etc/nscd.conf:'
  419.43 +            for service in self.bad_services:
  419.44 +                print "persistent    %s\tyes" % service
  419.45 +
  419.46 +    def __str__(self):
  419.47 +        return "test %s" % (self.name)
  419.48 +
   420.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   420.2 +++ b/usr/share/isi-checkup/tests/501_firefoxCfg.py	Mon Apr 26 11:16:23 2010 +0200
   420.3 @@ -0,0 +1,168 @@
   420.4 +#!/usr/bin/python
   420.5 +'''
   420.6 +firefoxCfg.py
   420.7 +
   420.8 +Test che verifica che proxy e porta dei profili_firefox utente corrispondano
   420.9 +a quelli del server impostati in /etc/isi/logon.conf
  420.10 +
  420.11 +Accetta in ingresso un utente.
  420.12 +
  420.13 +TODO
  420.14 +- fixare ciclo su tutti gli utenti
  420.15 +- controllare che utente richiesto Esista...
  420.16 +- migliorare estetica output =)
  420.17 +- Cambio nomi variabili
  420.18 +'''
  420.19 +
  420.20 +import os
  420.21 +import re
  420.22 +import isi
  420.23 +from isi.checkup import IsiTest
  420.24 +from dry.functions import execute
  420.25 +
  420.26 +# MAIN
  420.27 +class TestFirefox(IsiTest):
  420.28 +    def __init__(self, user=None):
  420.29 +
  420.30 +        logonConfFile = "/etc/isi/logon.conf"
  420.31 +        self.fireConfSite = "/.profili/WinXP/Dati applicazioni/Mozilla/" + \
  420.32 +                       "Firefox/Profiles/isi.default/prefs.js"
  420.33 +        self.user = user
  420.34 +        self.no_profile = {}
  420.35 +        self.wrong_profile = {}
  420.36 +        self.logonConf_Parsed = self.logonParser(logonConfFile)
  420.37 +
  420.38 +        if self.user:
  420.39 +            ret_code, self.maingroup, err = execute('id -gn ' + self.user)
  420.40 +            self.maingroup
  420.41 +        
  420.42 +    def logonParser(self, logonConfFile):
  420.43 +        '''
  420.44 +        #Return a dictionary with logon.conf's ProxyServer section
  420.45 +        #Eg.
  420.46 +        ProxyServer = 192.168.1.150:8128
  420.47 +        ProxyServer[admins] = 192.168.1.150:3128
  420.48 +        ProxyServer[alunni] = 192.168.1.150:8128
  420.49 +
  420.50 +        #return {None: '8128', 'admins': '3128', 'alunni': '8128'}
  420.51 +        '''    
  420.52 +
  420.53 +        fParsed = {}
  420.54 +        f = open(logonConfFile)
  420.55 +        
  420.56 +        PAT = re.compile(r'''   
  420.57 +            (?:https?://)?            # http://
  420.58 +            (?P<host>[^:/]+)          # localhost  o 192.168.1.254
  420.59 +            :(?P<port>\d+)            # porta
  420.60 +            ''', re.VERBOSE)
  420.61 +
  420.62 +        GROUP_RESTRICTION = re.compile(r'''
  420.63 +             ([^[]+)         # tutto fino alla quadra [
  420.64 +             (?:\[           # ?: non lo vogliamo in m.groups()
  420.65 +             (?:(?:[A-Z]:)?  # per NetFolder e ammessa sintassi: [S:admins]
  420.66 +             ([a-z]+)        # il gruppo principale 
  420.67 +             )              
  420.68 +             ])?
  420.69 +        ''', re.VERBOSE)
  420.70 +            
  420.71 +        for line in f:
  420.72 +            if re.match('^\s*#', line):  # comments
  420.73 +                continue
  420.74 +            #print '-%s-' % line
  420.75 +            m = re.match(PAT, line)
  420.76 +            if m:
  420.77 +                key, val = m.groups()
  420.78 +                m2 = re.search(GROUP_RESTRICTION, key)
  420.79 +                if m2:
  420.80 +                    opt, maingroup = m2.groups()
  420.81 +                    proxy_ip = key.split('=')[1].strip()
  420.82 +                    fParsed[maingroup] = [proxy_ip, val]
  420.83 +        return fParsed
  420.84 +
  420.85 +
  420.86 +    def firefoxParser(self, fireConfFile):
  420.87 +        '''
  420.88 +        Return a dictionary with prefs.js options
  420.89 +        '''
  420.90 +
  420.91 +        fParsed = {}
  420.92 +        f = open(fireConfFile)        
  420.93 +        for line in f:
  420.94 +            if not 'user_pref("' in line:
  420.95 +                continue
  420.96 +            m = re.match('.*user_pref.(.*?).;', line)
  420.97 +            key, value = m.group(1).split(", ")
  420.98 +            fParsed[key.strip('\"')] = value.strip('\"')
  420.99 +
 420.100 +        return fParsed
 420.101 +
 420.102 +    def check_profile(self, user=None, group=None):
 420.103 +        '''
 420.104 +        Verifica che proxy e porta dei profili_firefox utente corrispondano
 420.105 +        a quelli del server impostati in /etc/isi/logon.conf
 420.106 +        '''
 420.107 +
 420.108 +        logon_conf = self.logonConf_Parsed
 420.109 +
 420.110 +        # Si usi la configurazione per il gruppo, se specificata in "logon.conf"
 420.111 +        if group in logon_conf:
 420.112 +            proxyServer = logon_conf[group]
 420.113 +        else:
 420.114 +            proxyServer = logon_conf[None]
 420.115 +
 420.116 +        u = isi.Manager(isi.IsiConn())
 420.117 +        
 420.118 +        #Cerca profilo utente
 420.119 +        ret_code, fireConfFile, err = execute('find %s -name prefs.js' % u.get_home(user))
 420.120 +        fireConfFile = fireConfFile.strip()
 420.121 +        
 420.122 +        if not os.path.isfile(fireConfFile): # no firefox_profile?
 420.123 +            self.no_profile[user] = group
 420.124 +        else:
 420.125 +            # Leggo il profilo_firefox utente
 420.126 +            firefox_profile = self.firefoxParser(fireConfFile)
 420.127 +            
 420.128 +            # (profilo_firefox utente) === (configurazione proxy logon.conf) ?
 420.129 +            proxy_user = firefox_profile['network.proxy.http']
 420.130 +            proxyPort_user = firefox_profile['network.proxy.http_port']
 420.131 +
 420.132 +            if proxy_user == proxyServer[0]:
 420.133 +                #self.wrong_profile[user] = [group, proxy_user]
 420.134 +                pass
 420.135 +            if proxyPort_user == proxyServer[1]:
 420.136 +                pass
 420.137 +                #self.wrong_profile[user] += [proxyPort_user]
 420.138 +
 420.139 +            
 420.140 +    def test_firefoxCfg(self):
 420.141 +
 420.142 +        # DEBUG\
 420.143 +        self.user = 'o_test'
 420.144 +        self.maingroup = 'alunni'
 420.145 +        # DEBUG/
 420.146 +        
 420.147 +        if self.user:  
 420.148 +            self.check_profile(self.user, self.maingroup)
 420.149 +        else:			
 420.150 +        # Se non fornito utente, ciclo su quelli presenti in ogni gruppo ISI
 420.151 +            groups = isi.get_main_groups()
 420.152 +            u = isi.Manager(isi.IsiConn())
 420.153 +            for group in groups:
 420.154 +                for user in u.get_members(group):
 420.155 +                    self.check_profile(user, group)
 420.156 +
 420.157 +    def report(self):
 420.158 +        if self.no_profile:
 420.159 +            print "\nUtenti senza profilo Firefox"
 420.160 +            print "----------------------------"
 420.161 +            for el in self.no_profile:
 420.162 +                print "    ", el
 420.163 +
 420.164 +        if self.wrong_profile:
 420.165 +            print "\nUtenti con profilo Firefox incoerente"
 420.166 +            print "-------------------------------------"
 420.167 +            for el in self.wrong_profile.keys():
 420.168 +                gruppo = self.wrong_profile[el][0]
 420.169 +                wrong_proxy = self.wrong_profile[el][1]
 420.170 +                wrong_proxy_port = self.wrong_profile[el][2]
 420.171 +                print "    (%s)%s - %s:%s" % (gruppo, el, wrong_proxy, wrong_proxy_port)
   421.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   421.2 +++ b/usr/share/isi-checkup/tests/502_check_permission_rwx.sh	Mon Apr 26 11:16:23 2010 +0200
   421.3 @@ -0,0 +1,235 @@
   421.4 +#!/bin/bash
   421.5 +
   421.6 +# includo 
   421.7 +# source /etc/isi/checkup/tests-available/default/check_rwx.config
   421.8 +
   421.9 +# Directory contenute nella home da testare per i relativi permessi (R,W,X)
  421.10 +homedirsR='public_html'
  421.11 +homedirsW='public_html'
  421.12 +homedirsX='public_html'
  421.13 +
  421.14 +# Aree dei gruppi
  421.15 +aree_docenti='/home/shares/area_docenti'
  421.16 +aree_alunni='/home/shares/area_alunni'
  421.17 +aree_segreteria='/home/shares/area_segreteria'
  421.18 +
  421.19 +
  421.20 +tmpFile=".$RANDOM.isicheckup"
  421.21 +errNumber=0
  421.22 +findDepth=3 # arriva fino a .profili/WinXP
  421.23 +
  421.24 +### Definizione Funzioni ###
  421.25 +
  421.26 +function checkW(){
  421.27 +    local utente=$1
  421.28 +    local gruppo=$2
  421.29 +    local aree=$3
  421.30 +    local errNumber=0
  421.31 +    if su $utente -c "find /home/users/$gruppo/$utente -maxdepth $findDepth -type d -exec touch {}/$tmpFile \; "; then
  421.32 +        find /home/users/$gruppo/$utente -maxdepth $findDepth -type d -exec rm -f {}/*.isicheckup \;
  421.33 +    else
  421.34 +        let errNumber++
  421.35 +        echo -e "W> !! ($gruppo)$utente non scrive in ~$utente/.profili/*"
  421.36 +    fi
  421.37 +            
  421.38 +    for homedirW in $homedirsW; do
  421.39 +        if su $utente -c "touch ~$utente/$homedirW/$tmpFile >/dev/null"; then
  421.40 +            eval rm -f ~$utente/$homedirW/$tmpFile
  421.41 +            #echo -e "W> ($gruppo)$utente scrive in $homedirW"
  421.42 +        else
  421.43 +            echo -e "W> !! ($gruppo)$utente non scrive in $homedirW"
  421.44 +            let errNumber++
  421.45 +        fi
  421.46 +    done    
  421.47 +    for area in $aree;do
  421.48 +        if su $utente -c "touch $area/$tmpFile >/dev/null"; then
  421.49 +            rm -f $area/$tmpFile
  421.50 +            #echo -e "W> ($gruppo)$utente scrive in $area"
  421.51 +        else
  421.52 +            echo -e "W> !! ($gruppo)$utente non scrive in $area"
  421.53 +            let errNumber++
  421.54 +        fi
  421.55 +    done    	
  421.56 +    if [ "$errNumber" != "0" ]; then
  421.57 +        return 1  
  421.58 +    else
  421.59 +        return 0 
  421.60 +    fi
  421.61 +}    
  421.62 +
  421.63 +function checkR(){
  421.64 +    local utente=$1
  421.65 +    local gruppo=$2    
  421.66 +    local aree=$3
  421.67 +    local errNumber=0
  421.68 +    if su $utente -c "find /home/users/$gruppo/$utente -maxdepth $findDepth >/dev/null"; then
  421.69 +        echo -n
  421.70 +    else
  421.71 +        let errNumber++
  421.72 +        echo -e "R> !! ($gruppo)$utente non legge in ~$utente/.profili/*"
  421.73 +    fi
  421.74 +
  421.75 +    for homedirR in $homedirsR; do
  421.76 +        if su $utente -c "ls ~$utente/$homedirR >/dev/null"; then
  421.77 +            #echo -e "R> ($gruppo)$utente legge in ~$utente/$homedirR"
  421.78 +            echo -n
  421.79 +        else
  421.80 +            echo -e "R> !! ($gruppo)$utente non legge in ~$utente/$homedirR"
  421.81 +            let errNumber++
  421.82 +        fi
  421.83 +    done    
  421.84 +    for area in $aree; do
  421.85 +        if su $utente -c "ls $area >/dev/null"; then
  421.86 +            #echo -e "R> ($gruppo)$utente legge in $area"
  421.87 +            echo -n
  421.88 +        else
  421.89 +            echo -e "R> !! ($gruppo)$utente non legge in $area"
  421.90 +            let errNumber++
  421.91 +        fi
  421.92 +    done    
  421.93 +    if [ "$errNumber" != "0" ]; then
  421.94 +        return 1  
  421.95 +    else
  421.96 +        return 0 
  421.97 +    fi
  421.98 +}    
  421.99 +
 421.100 +function checkX(){
 421.101 +    local utente=$1
 421.102 +    local gruppo=$2    
 421.103 +    local aree=$3
 421.104 +    local errNumber=0
 421.105 +
 421.106 +    if su $utente -c "find /home/users/$gruppo/$utente -maxdepth $findDepth\
 421.107 +     -type d -exec ls {} >/dev/null \; "; then
 421.108 +        echo -n
 421.109 +    else
 421.110 +        echo -e "X> !! ($gruppo)$utente non attraversa ~$user/.profili/*"
 421.111 +        let errNumber++
 421.112 +    fi
 421.113 +
 421.114 +    for homedirX in $homedirsX; do
 421.115 +        if su $utente -c "cd ~ && cd ~$utente/$homedirX >/dev/null" ; then
 421.116 +            #echo -e "X> ($gruppo)$utente attraversa ~$utente/$homedirX"
 421.117 +            echo -n
 421.118 +        else
 421.119 +            echo -e "X> !! ($gruppo)$utente non attraversa ~$utente/$homedirX"
 421.120 +            let errNumber++
 421.121 +        fi
 421.122 +    done    
 421.123 +    for area in $aree;do
 421.124 +        if su $utente -c "cd $area" ; then
 421.125 +            #echo -e "X> ($gruppo)$utente attraversa $area"
 421.126 +            echo -n
 421.127 +        else
 421.128 +            echo -e "X> !! ($gruppo)$utente non attraversa $area"
 421.129 +            let errNumber++
 421.130 +        fi
 421.131 +    done    	
 421.132 +    if [ "$errNumber" != "0" ]; then
 421.133 +        return 1  
 421.134 +    else
 421.135 +        return 0 
 421.136 +    fi
 421.137 +}    
 421.138 +    
 421.139 +
 421.140 +function everybody(){
 421.141 +
 421.142 +    local errNumber=0
 421.143 +
 421.144 +    for gruppo in $(ls /home/users);do
 421.145 +	if isi-groupcat $gruppo 1> /dev/null 2> /dev/null; then
 421.146 +            for utenti in $(isi-groupcat $gruppo);do
 421.147 +                for utente in $utenti;do
 421.148 +        
 421.149 +                    # aree = $aree_gruppo        
 421.150 +            	    if [ $gruppo == 'docenti' ]; then
 421.151 +                        aree=$aree_docenti
 421.152 +                    elif [ $gruppo == 'alunni' ]; then
 421.153 +                        aree=$aree_alunni
 421.154 +                    elif [ $gruppo == 'segreteria' ]; then
 421.155 +                        aree=$aree_segreteria
 421.156 +	  	    else
 421.157 +		        aree='/tmp'
 421.158 +                    fi
 421.159 +        
 421.160 +                    # lancio le funzioni di controllo RWX  
 421.161 +                    if ! checkW $utente $gruppo $aree; then
 421.162 +                        let errNumber++
 421.163 +                    fi 
 421.164 +                    if ! checkX $utente $gruppo $aree; then
 421.165 +                        let errNumber++
 421.166 +                    fi 
 421.167 +                    if ! checkR $utente $gruppo $aree; then
 421.168 +                        let errNumber++
 421.169 +                    fi
 421.170 +
 421.171 +                 done
 421.172 +	
 421.173 +   	    # clean tmpFile residui :-/
 421.174 +	    find /home/users/$gruppo -iname *.isicheckup -exec rm {} \;
 421.175 +            done
 421.176 +        fi
 421.177 +    done
 421.178 +    if [ "$errNumber" != "0" ]; then
 421.179 +        return 1  
 421.180 +    else
 421.181 +        return 0 
 421.182 +    fi
 421.183 +}
 421.184 +
 421.185 +### Main ###
 421.186 +
 421.187 +# Evito ``find: cannot get current directory: Permission denied``
 421.188 +cd /tmp
 421.189 +
 421.190 +#se fornito argomento in ingresso (utente)
 421.191 +if [[ -z "$1" ]]; then
 421.192 +    if ! everybody; then
 421.193 +        exit 1
 421.194 +    else
 421.195 +	echo "Permessi corretti"
 421.196 +        exit 0
 421.197 +    fi
 421.198 +else    
 421.199 +    utente=$1
 421.200 +    gruppo=$(ldapsearch -xLLL uid=$utente | grep homeD | awk -F"/" '{ print $4 }')
 421.201 +    
 421.202 +    if [ -z "$gruppo" ]; then
 421.203 +	echo -e "\n    \"$utente\" non e' un utente del dominio"
 421.204 +    	exit 1
 421.205 +    fi
 421.206 +    
 421.207 +    # aree = $aree_gruppo        
 421.208 +    if [ $gruppo == 'docenti' ]; then
 421.209 +        aree=$aree_docenti
 421.210 +    elif [ $gruppo == 'alunni' ]; then
 421.211 +        aree=$aree_alunni
 421.212 +    elif [ $gruppo == 'segreteria' ]; then
 421.213 +        aree=$aree_segreteria
 421.214 +    else
 421.215 +        aree='/tmp'
 421.216 +    fi
 421.217 +
 421.218 +    if ! checkW $utente $gruppo $aree; then
 421.219 +        let errNumber++
 421.220 +    fi 
 421.221 +    if ! checkX $utente $gruppo $aree; then
 421.222 +        let errNumber++
 421.223 +    fi 
 421.224 +    if ! checkR $utente $gruppo $aree; then
 421.225 +        let errNumber++
 421.226 +    fi 
 421.227 +
 421.228 +    # clean tmpFile residui :-/
 421.229 +    find /home/users/$gruppo/$utente -iname *.isicheckup -exec rm {} \;
 421.230 +
 421.231 +
 421.232 +    if [ "$errNumber" != "0" ]; then
 421.233 +        exit 1  
 421.234 +    else
 421.235 +	echo "Permessi corretti"
 421.236 +        exit 0 
 421.237 +    fi
 421.238 +fi
   422.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   422.2 +++ b/usr/share/isi-checkup/tests/STRUTTURA.txt	Mon Apr 26 11:16:23 2010 +0200
   422.3 @@ -0,0 +1,92 @@
   422.4 +  0 - 100   boot
   422.5 +101 - 200   servizi   # servisi possibili ma non necessari
   422.6 +201 - 400   reteisi   # servizi necesari a reteisi
   422.7 +501 - 700   user
   422.8 +
   422.9 +
  422.10 +010 disk_space
  422.11 +011 need_file_hostname
  422.12 +012 need_file_hosts
  422.13 +013 need_file_resolve.conf
  422.14 +014 need_file_interfaces
  422.15 +015 localhost
  422.16 +016 need_file_runlevel.conf
  422.17 +020 ip
  422.18 +021 mii-tool # test che ci sia la connessione
  422.19 +
  422.20 +110  bind9
  422.21 +111  ssh
  422.22 +112  dhcp3-server
  422.23 +   113 need_file_dhcpd.conf
  422.24 +
  422.25 +113  S_ldap_secret.py
  422.26 +   115  slapd
  422.27 +   116  S_sameSecrets.sh
  422.28 +
  422.29 +
  422.30 +116  samba
  422.31 +117  nmbd
  422.32 +   118 need_file_smb.conf
  422.33 +   119 S_netbiosIsHostname.sh
  422.34 +
  422.35 +120  squid
  422.36 +   121 need_file_squid.conf
  422.37 +   122 S_squid_parmExist.py
  422.38 +
  422.39 +
  422.40 +123  dansguardian
  422.41 +  124  need_file_dansguardian.conf
  422.42 +
  422.43 +125  postfix
  422.44 +  126  S_postfixcheck.sh
  422.45 +
  422.46 +201  need_dir_home
  422.47 +   201  need_dir_users
  422.48 +      205 need_dir_alunni
  422.49 +      206 need_dir_docenti
  422.50 +      207 need_dir_admins
  422.51 +
  422.52 +   220  need_dir_shares
  422.53 +      225 need_dir_classi
  422.54 +      226 need_dir_area_alunni
  422.55 +      227 need_dir_area_docenti
  422.56 +
  422.57 +
  422.58 +   230 need_file_ldap.secret
  422.59 +   231 need_file_libnss-ldap.secret
  422.60 +   232 need_file_pam_ldap.secret
  422.61 +
  422.62 +250   need_file_logon.conf
  422.63 +251   need_file_logon.bat
  422.64 +252   need_file_acl.conf
  422.65 +
  422.66 +260 need_process_slapd
  422.67 +261 need_process_sshd
  422.68 +262 need_process_dhcpd3
  422.69 +263 need_process_smbd
  422.70 +264 need_process_nmbd
  422.71 +265 need_process_squid
  422.72 +266 need_process_dansguardian
  422.73 +267 need_process_master
  422.74 +268 need_process_named
  422.75 +
  422.76 +270
  422.77 +271   samba_share_homes
  422.78 +272   samba_share_netlogon
  422.79 +273   samba_share_software
  422.80 +274   samba_share_dati
  422.81 +275   samba_share_classi
  422.82 +276   samba_share_corsi
  422.83 +277   samba_share_perl
  422.84 +278   samba_share_printers
  422.85 +279   samba_share_area_alunni
  422.86 +280   samba_share_area_docenti
  422.87 +281   samba_share_area_segreteria
  422.88 +
  422.89 +330   group_exist_docenti
  422.90 +331   group_exist_alunni
  422.91 +332   group_exist_admins
  422.92 +
  422.93 +501    T_firefoxCfg.py
  422.94 +502    U_check_rwx2.sh
  422.95 +503    U_check_rwx.sh
   423.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   423.2 +++ b/web/.hgignore	Mon Apr 26 11:16:23 2010 +0200
   423.3 @@ -0,0 +1,7 @@
   423.4 +mako_modules
   423.5 +static/js/OLD
   423.6 +static/img-old
   423.7 +static/css/ui/themes/base
   423.8 +static/css/ui/themes/ui*
   423.9 +static
  423.10 +local_settings.py
   424.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   424.2 +++ b/web/data/boot	Mon Apr 26 11:16:23 2010 +0200
   424.3 @@ -0,0 +1,27 @@
   424.4 +# le prossime sono quelle che servono
   424.5 +# in particolare ai thin client
   424.6 +# root-path (17)
   424.7 +# percorso dove montare la partizione root
   424.8 +dhcp-option=17,"/opt/ltsp/i386"
   424.9 +
  424.10 +# file di boot (percorso relativo alla root del server tftp),
  424.11 +# nome tftp server, ip tftp server
  424.12 +# l'indirizzo e il nome del server
  424.13 +# devono essere inseriti in /etc/hosts
  424.14 +dhcp-boot=/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222
  424.15 +
  424.16 +# file di boot (percorso relativo alla root del server tftp),
  424.17 +# nome tftp server, ip tftp server
  424.18 +# l'indirizzo e il nome del server
  424.19 +# devono essere inseriti in /etc/hosts
  424.20 +#dhcp-boot=/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222
  424.21 +
  424.22 +# PXE / Etherboot
  424.23 +dhcp-vendorclass=pxe,PXEClient
  424.24 +dhcp-vendorclass=eth,Etherboot
  424.25 +#    dhcp-option=vendor:PXEClient,1,0.0.0.0
  424.26 +dhcp-boot=net:pxe,/ltsp/i386/pxelinux.0,ltsp-server,192.168.96.222
  424.27 +dhcp-boot=net:eth,/ltsp/i386/pxelinux.0,ltsp-server, 192.168.96.222
  424.28 +
  424.29 +# other
  424.30 +dhcp-boot=/ltsp/i386/nbi.img,ltsp-server,192.168.96.222
  424.31 \ No newline at end of file
   425.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   425.2 +++ b/web/data/dnsmasq.conf	Mon Apr 26 11:16:23 2010 +0200
   425.3 @@ -0,0 +1,101 @@
   425.4 +# -*- mode: conf -*-
   425.5 +# non inoltrare mai ai server dns esterni
   425.6 +# query senza nome dominio
   425.7 +domain-needed
   425.8 +
   425.9 +# Tutti i reverse lookup per la subnet privata
  425.10 +# non presenti in /etc/hosts o nei lease dhcp
  425.11 +# ottengono "host not found"
  425.12 +# invece di essere inoltrati ai dns esterni
  425.13 +bogus-priv
  425.14 +
  425.15 +# Filtra le ricorrenti richieste SOA, SRV e altre,
  425.16 +# provenienti da macchine windows
  425.17 +# serve in particolare a non attivare
  425.18 +# per sbaglio il link quando si
  425.19 +# hanno connessioni "on demand"
  425.20 +filterwin2k
  425.21 +
  425.22 +# server dns esterni di riferimento
  425.23 +# inserire i server dns uno per riga
  425.24 +# usati in questo caso i server di opendns.org
  425.25 +server=208.67.220.220
  425.26 +server=208.67.220.220
  425.27 +
  425.28 +# aggiunge sempre il nome dominio al nome host
  425.29 +expand-hosts
  425.30 +
  425.31 +# nome del mio dominio
  425.32 +domain=vega.it
  425.33 +
  425.34 +# Se si intende passare ai client un dominio differente
  425.35 +# dhcp-option=option:domain-name,isi.lan
  425.36 +
  425.37 +# range dei lease dhcp: indirizzo iniziale, indirizzo finale, netmask, durata del lease
  425.38 +dhcp-range=192.168.96.130,192.168.96.140,255.255.255.0,8h
  425.39 +
  425.40 +# Range dhcp per-tag
  425.41 +# ~~~~~~~~~~~~~~~~~~~
  425.42 +# E` anche possibile riservare un determinato range filtrando per TAG.
  425.43 +# I tag possono essere associati anche ad un'intera famiglia di indirizzi MAC
  425.44 +# Ciò risulta utilissimo, ad esempio, per limitare le macchine virtuali vmware
  425.45 +# ad un certo range.
  425.46 +#
  425.47 +# Settare il tag "macchinevmware" per le macchine con mac iniziante per
  425.48 +# 00:0c:29:*:*:* (gruppo di indirizzi mac riservati a vmware)
  425.49 +#
  425.50 +#   dhcp-mac=macchinevmware,00:0c:29:*:*:*
  425.51 +#
  425.52 +# Sintassi ::
  425.53 +#
  425.54 +#   dhcp-range=[[net:]network-id,]<start-addr>,<end-addr>[[,<net‐netmask>],<broadcast>][,<lease time>]
  425.55 +#
  425.56 +# Esempio ::
  425.57 +#
  425.58 +# dhcp-range=net:macchinevmware,192.168.150,160,255.255.255.0,8h
  425.59 +
  425.60 +
  425.61 +# Esempio di ip-reservation per client
  425.62 +#
  425.63 +# MAC address, indirizzo, nome host, tag(utile per associare a più server)
  425.64 +#
  425.65 +# dhcp-host=00:0c:29:c9:69:35,192.168.96.190,vm-ltsp01,net:ns1  # client1
  425.66 +# dhcp-host=00:0c:29:5e:69:b5,192.168.96.191,vm-ltsp02,net:ns2  # client2
  425.67 +#
  425.68 +# le associazioni vengono definite esternamente, vedi inclusioni a fine file.
  425.69 +# il file usato è /etc/isi/dns/dnsmasq/hosts.mac
  425.70 +
  425.71 +# dnsmasq supporta la maggior parte delle
  425.72 +# opzioni dhcp e bootp specificate in
  425.73 +# http://www.faqs.org/rfcs/rfc2132.html
  425.74 +# la sintassi e':
  425.75 +# dhcp-option=[numero relativo all'opzione],parametro
  425.76 +
  425.77 +# GATEWAY di default (3)
  425.78 +dhcp-option=44,192.168.96.253
  425.79 +
  425.80 +# DNS da passare ai client (6)
  425.81 +dhcp-option=6,192.168.96.254
  425.82 +
  425.83 +# WINS da passare ai client (44)
  425.84 +dhcp-option=44,192.168.96.253
  425.85 +#
  425.86 +# Il server dhcp sarà AUTORITATIVO.
  425.87 +dhcp-authoritative
  425.88 +cache-size=1024
  425.89 +### LOG
  425.90 +# da usare per debug
  425.91 +# log-queries
  425.92 +
  425.93 +# Da abilitare *solo* in caso di debug, logga tutte le transazioni che avvengono
  425.94 +# tra servente DHCP e i client.
  425.95 +#
  425.96 +# log-dhcp
  425.97 +
  425.98 +# Configurazione aggiuntiva per isi.
  425.99 +conf-dir=/etc/isi/dns/dnsmasq
 425.100 +addn-hosts=/etc/isi/dns/hosts
 425.101 +
 425.102 +# Per includere ulteriori configurazioni...
 425.103 +# conf-file=/etc/dnsmasq.more.conf
 425.104 +# conf-dir=/etc/dnsmasq.d
 425.105 \ No newline at end of file
   426.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   426.2 +++ b/web/data/hosts	Mon Apr 26 11:16:23 2010 +0200
   426.3 @@ -0,0 +1,9 @@
   426.4 +127.0.0.1 localhost
   426.5 +127.0.1.1 ISI-PDC
   426.6 +192.168.96.222 srv-ltsp
   426.7 +192.168.96.22 www.tin.it
   426.8 +192.168.96.199 vm-client-ltsp1
   426.9 +192.168.96.44 srv-prova srv
  426.10 +192.168.5.44 srv-test
  426.11 +11.11.1.1 bluffo
  426.12 +5.5.5.5 sandro
  426.13 \ No newline at end of file
   427.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   427.2 +++ b/web/data/hosts.mac	Mon Apr 26 11:16:23 2010 +0200
   427.3 @@ -0,0 +1,3 @@
   427.4 +dhcp-host=00:0c:29:10:a6:45,192.168.96.199,vm-client-ltsp1
   427.5 +dhcp-host=00:0c:29:c0:d7:9e,192.168.96.198,vm-client-ltsp2,net:ns1
   427.6 +dhcp-host=00:0c:29:10:a6:48,192.168.5.55
   427.7 \ No newline at end of file
   428.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   428.2 +++ b/web/data/leases	Mon Apr 26 11:16:23 2010 +0200
   428.3 @@ -0,0 +1,54 @@
   428.4 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
   428.5 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
   428.6 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
   428.7 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
   428.8 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
   428.9 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  428.10 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  428.11 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  428.12 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  428.13 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  428.14 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  428.15 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  428.16 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  428.17 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  428.18 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  428.19 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  428.20 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  428.21 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  428.22 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  428.23 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  428.24 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  428.25 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  428.26 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  428.27 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  428.28 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  428.29 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  428.30 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  428.31 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  428.32 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  428.33 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  428.34 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  428.35 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  428.36 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  428.37 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  428.38 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  428.39 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  428.40 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  428.41 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  428.42 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  428.43 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  428.44 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  428.45 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  428.46 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  428.47 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  428.48 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  428.49 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  428.50 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  428.51 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
  428.52 +946689575 00:00:00:00:00:05 192.168.1.155 wdt 01:00:00:00:00:00:05
  428.53 +946689522 00:00:00:00:00:04 192.168.1.237 * 01:00:00:00:00:00:04
  428.54 +946689351 00:0f:b0:3a:b5:0b 192.168.1.208 colinux *
  428.55 +946689493 02:0f:b0:3a:b5:0b 192.168.1.199 * 01:02:0f:b0:3a:b5:0b
  428.56 +1259870930 00:0c:29:f5:6f:69 192.168.96.135 * *
  428.57 +1259870915 00:0c:29:10:a6:45 192.168.96.199 vm-client-ltsp1 *
   429.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   429.2 +++ b/web/data/smb.conf	Mon Apr 26 11:16:23 2010 +0200
   429.3 @@ -0,0 +1,300 @@
   429.4 +# -*- outline-regexp: "####\\|\\[..." -*-
   429.5 +#
   429.6 +#### preamble
   429.7 +# Sample configuration file for the ISI project (www.reteisi.org)
   429.8 +# derived from samba sample conf for Debian adding LDAP conf for smbdldap-tools
   429.9 +#
  429.10 +#
  429.11 +# This is the main Samba configuration file. You should read the
  429.12 +# smb.conf(5) manual page in order to understand the options listed
  429.13 +# here. Samba has a huge number of configurable options most of which 
  429.14 +# are not shown in this example
  429.15 +#
  429.16 +# Any line which starts with a ; (semi-colon) or a # (hash) 
  429.17 +# is a comment and is ignored. In this example we will use a #
  429.18 +# for commentary and a ; for parts of the config file that you
  429.19 +# may wish to enable
  429.20 +#
  429.21 +# NOTE: Whenever you modify this file you should run the command
  429.22 +# "testparm" to check that you have not many any basic syntactic 
  429.23 +# errors. 
  429.24 +#
  429.25 +
  429.26 +#======================= Global Settings =======================
  429.27 +
  429.28 +[global]
  429.29 +
  429.30 +## Browsing/Identification/Domain ###
  429.31 +
  429.32 +   workgroup = FOSSATIINTERNI
  429.33 +    netbios name = srv-fossati
  429.34 +   domain master = Yes
  429.35 +   local master = Yes
  429.36 +   preferred master = Yes
  429.37 +   os level = 200
  429.38 +   domain logons = Yes
  429.39 +   deadtime = 15
  429.40 +   security = user
  429.41 +   enable privileges = yes
  429.42 +   admin users = root # , @admins
  429.43 +
  429.44 +   logon home = \\%N\%U\.\\.profili\%a
  429.45 +   logon path = \\%N\%U\.profili\%a
  429.46 +   logon script = logon.bat
  429.47 +
  429.48 +#   logon home = \\%N\%U\.\.profili%a
  429.49 +   logon drive = H:
  429.50 +#   logon path = \\%L\profiles
  429.51 +
  429.52 +
  429.53 +# server string is the equivalent of the NT Description field
  429.54 +   server string = %h server (Samba %v)
  429.55 +
  429.56 +# Windows Internet Name Serving Support Section:
  429.57 +# WINS Support - Tells the NMBD component of Samba to enable its WINS Server
  429.58 +  wins support = Yes
  429.59 +
  429.60 +# WINS Server - Tells the NMBD components of Samba to be a WINS Client
  429.61 +# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
  429.62 +;   wins server = w.x.y.z
  429.63 +
  429.64 +# This will prevent nmbd to search for NetBIOS names through DNS.
  429.65 +   dns proxy = no
  429.66 +
  429.67 +# What naming service and in what order should we use to resolve host names
  429.68 +# to IP addresses
  429.69 +   name resolve order = lmhosts host wins bcast
  429.70 +
  429.71 +
  429.72 +#### LDAP  #############
  429.73 +   passdb backend = ldapsam:ldap://127.0.0.1
  429.74 +   obey pam restrictions = no
  429.75 +   passwd program = /usr/sbin/smbldap-passwd %u
  429.76 +   passwd chat = *New*password* %n\n *Retype*new*password* %n\n
  429.77 +   ldap ssl = no
  429.78 +   ldap passwd sync = yes
  429.79 +   ldap machine suffix = ou=Computers
  429.80 +   ldap idmap suffix = ou=Idmaps
  429.81 +   ldap group suffix = ou=Groups
  429.82 +   ldap user suffix = ou=People
  429.83 +   ldap suffix = dc=isi,dc=lan
  429.84 +   ldap delete dn = Yes
  429.85 +   ldap admin dn = cn=admin,dc=isi,dc=lan
  429.86 +
  429.87 +   add machine script = /usr/sbin/smbldap-useradd -w "%m"
  429.88 +   set primary group script = /usr/sbin/smbldap-usermod -g "%g" "%u"
  429.89 +   delete user from group script = /usr/sbin/smbldap-groupmod -x "%u" "%g"
  429.90 +   add user to group script = /usr/sbin/smbldap-groupmod -m "%u" "%g"
  429.91 +   delete group script = /usr/sbin/smbldap-groupdel "%g"
  429.92 +   add group script = /usr/sbin/smbldap-groupadd -p "%g"
  429.93 +   delete user script = /usr/sbin/smbldap-userdel "%u"
  429.94 +   add user script = /usr/sbin/smbldap-useradd -m "%u"
  429.95 +
  429.96 +#### Debugging/Accounting ####
  429.97 +
  429.98 +# This tells Samba to use a separate log file for each machine
  429.99 +# that connects
 429.100 +   log file = /var/log/samba/log.%m
 429.101 +   log level = 3
 429.102 +
 429.103 +# Put a capping on the size of the log files (in Kb).
 429.104 +   max log size = 1000
 429.105 +
 429.106 +# If you want Samba to only log through syslog then set the following
 429.107 +# parameter to 'yes'.
 429.108 +;   syslog only = no
 429.109 +
 429.110 +# We want Samba to log a minimum amount of information to syslog. Everything
 429.111 +# should go to /var/log/samba/log.{smbd,nmbd} instead. If you want to log
 429.112 +# through syslog you should set the following parameter to something higher.
 429.113 +   syslog = 0
 429.114 +
 429.115 +# Do something sensible when Samba crashes: mail the admin a backtrace
 429.116 +   panic action = /usr/share/samba/panic-action %d
 429.117 +
 429.118 +
 429.119 +#### Authentication #######
 429.120 +
 429.121 +# "security = user" is always a good idea. This will require a Unix account
 429.122 +# in this server for every user accessing the server. See
 429.123 +# /usr/share/doc/samba-doc/htmldocs/ServerType.html in the samba-doc
 429.124 +# package for details.
 429.125 +;   security = user
 429.126 +
 429.127 +# You may wish to use password encryption.  See the section on
 429.128 +# 'encrypt passwords' in the smb.conf(5) manpage before enabling.
 429.129 +   encrypt passwords = true
 429.130 +
 429.131 +# If you are using encrypted passwords, Samba will need to know what
 429.132 +# password database type you are using.  
 429.133 +## these settings are 'overloaded' by ldap configuration
 429.134 +;   passdb backend = tdbsam guest
 429.135 +;   obey pam restrictions = yes
 429.136 +;   guest account = nobody
 429.137 +;   invalid users = root
 429.138 +
 429.139 +# This boolean parameter controls whether Samba attempts to sync the Unix
 429.140 +# password with the SMB password when the encrypted SMB password in the
 429.141 +# passdb is changed.
 429.142 +;   unix password sync = no
 429.143 +
 429.144 +# For Unix password sync to work on a Debian GNU/Linux system, the following
 429.145 +# parameters must be set (thanks to Augustin Luton <[email protected]> for
 429.146 +# sending the correct chat script for the passwd program in Debian Potato).
 429.147 +;   passwd program = /usr/bin/passwd %u
 429.148 +;   passwd chat = *Enter\snew\sUNIX\spassword:* %n\n *Retype\snew\sUNIX\spassword:* %n\n .
 429.149 +
 429.150 +# This boolean controls whether PAM will be used for password changes
 429.151 +# when requested by an SMB client instead of the program listed in
 429.152 +# 'passwd program'. The default is 'no'.
 429.153 +;   pam password change = no
 429.154 +
 429.155 +
 429.156 +#### Printing ##########
 429.157 +
 429.158 +# If you want to automatically load your printer list rather
 429.159 +# than setting them up individually then you'll need this
 429.160 +;   load printers = yes
 429.161 +
 429.162 +# lpr(ng) printing. You may wish to override the location of the
 429.163 +# printcap file
 429.164 +;   printing = bsd
 429.165 +;   printcap name = /etc/printcap
 429.166 +
 429.167 +# CUPS printing.  See also the cupsaddsmb(8) manpage in the
 429.168 +# cupsys-client package.
 429.169 +;   printing = cups
 429.170 +;   printcap name = cups
 429.171 +
 429.172 +# When using [print$], root is implicitly a 'printer admin', but you can
 429.173 +# also give this right to other users to add drivers and set printer
 429.174 +# properties
 429.175 +;   printer admin = @ntadmin
 429.176 +
 429.177 +
 429.178 +#### File sharing ########
 429.179 +
 429.180 +# Name mangling options
 429.181 +;   preserve case = yes
 429.182 +;   short preserve case = yes
 429.183 +
 429.184 +
 429.185 +#### Misc ############
 429.186 +
 429.187 +# Using the following line enables you to customise your configuration
 429.188 +# of the machine that is connecting
 429.189 +;   include = /home/samba/etc/smb.conf.%m
 429.190 +
 429.191 +# Most people will find that this option gives better performance.
 429.192 +# See smb.conf(5) and /usr/share/doc/samba-doc/htmldocs/speed.html
 429.193 +# for details
 429.194 +# You may want to add the following on a Linux system:
 429.195 +#         SO_RCVBUF=8192 SO_SNDBUF=8192
 429.196 +   socket options = TCP_NODELAY
 429.197 +
 429.198 +# The following parameter is useful only if you have the linpopup package
 429.199 +# installed. The samba maintainer and the linpopup maintainer are
 429.200 +# working to ease installation and configuration of linpopup and samba.
 429.201 +;   message command = /bin/sh -c '/usr/bin/linpopup "%f" "%m" %s; rm %s' &
 429.202 +
 429.203 +# Domain Master specifies Samba to be the Domain Master Browser. If this
 429.204 +# machine will be configured as a BDC (a secondary logon server), you
 429.205 +# must set this to 'no'; otherwise, the default behavior is recommended.
 429.206 +;   domain master = auto
 429.207 +
 429.208 +# Some defaults for winbind (make sure you're not using the ranges
 429.209 +# for something else.)
 429.210 +;   idmap uid = 10000-20000
 429.211 +;   idmap gid = 10000-20000
 429.212 +;   template shell = /bin/bash
 429.213 +
 429.214 +#======================= Share Definitions =======================
 429.215 +
 429.216 +[homes]
 429.217 +   comment = ISI-homes (NON MODIFICARE QUESTA RIGA)
 429.218 +   browseable = no
 429.219 +   writable = yes
 429.220 +   guest ok = no
 429.221 +   #veto files = /public_html/
 429.222 +
 429.223 +[netlogon]
 429.224 +    comment = ISI-NetLogon (NON MODIFICARE QUESTA RIGA)
 429.225 +    path = /home/samba/netlogon
 429.226 +    guest ok = yes
 429.227 +    browseable = no
 429.228 +    create mask = 0644
 429.229 +    directory mask = 0755
 429.230 +    writable = yes
 429.231 +    root preexec=/usr/sbin/setlogonvar '%U' '%G' '%m'
 429.232 +    root postexec=/usr/sbin/rmlogonvar '%m'
 429.233 +
 429.234 +[perl]
 429.235 +   path = /usr/share/WinActivePerl
 429.236 +   comment = Per Windows Binaries
 429.237 +   public = yes
 429.238 +   writable = no
 429.239 +   guest ok = yes
 429.240 +   browseable = no
 429.241 +
 429.242 +[printers]
 429.243 +   comment = All Printers
 429.244 +   browseable = no
 429.245 +   path = /tmp
 429.246 +   printable = yes
 429.247 +   public = no
 429.248 +   writable = no
 429.249 +   create mode = 0700
 429.250 +
 429.251 +# Windows clients look for this share name as a source of downloadable
 429.252 +# printer drivers
 429.253 +
 429.254 +[print$]
 429.255 +   comment = Printer Drivers
 429.256 +   path = /var/lib/samba/printers
 429.257 +   browseable = yes
 429.258 +   read only = yes
 429.259 +   guest ok = no
 429.260 +# Uncomment to allow remote administration of Windows print drivers.
 429.261 +# Replace 'ntadmin' with the name of the group your admin users are
 429.262 +# members of.
 429.263 +;   write list = root, @ntadmin
 429.264 +
 429.265 +# A sample share for sharing your CD-ROM with others.
 429.266 +;[cdrom]
 429.267 +;   comment = Samba server's CD-ROM
 429.268 +;   writable = no
 429.269 +;   locking = no
 429.270 +;   path = /cdrom
 429.271 +;   public = yes
 429.272 +
 429.273 +# The next two parameters show how to auto-mount a CD-ROM when the
 429.274 +#	cdrom share is accesed. For this to work /etc/fstab must contain
 429.275 +#	an entry like this:
 429.276 +#
 429.277 +#       /dev/scd0   /cdrom  iso9660 defaults,noauto,ro,user   0 0
 429.278 +#
 429.279 +# The CD-ROM gets unmounted automatically after the connection to the
 429.280 +#
 429.281 +# If you don't want to use auto-mounting/unmounting make sure the CD
 429.282 +#	is mounted on /cdrom
 429.283 +#
 429.284 +;   preexec = /bin/mount /cdrom
 429.285 +;   postexec = /bin/umount /cdrom
 429.286 +
 429.287 +[gestionale]
 429.288 +   comment = software gestionale
 429.289 +   path = /home/shares/software/gestionale/lib
 429.290 +   browseable = yes
 429.291 +   writable = yes
 429.292 +
 429.293 +
 429.294 +#### includes
 429.295 +include = /etc/isi/samba/smb_servizi.conf
 429.296 +include = /etc/isi/samba/smb_maingrps.conf
 429.297 +include = /etc/isi/samba/smb_classi.conf
 429.298 +include = /etc/isi/samba/smb_corsi.conf
 429.299 +include = /etc/isi/samba/smb_aree.conf
 429.300 +
 429.301 +#### The End  *;-)
 429.302 +## DEBCONF CONFIGURED by isi-ldap3
 429.303 +
   430.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   430.2 +++ b/web/dnsmasq/dns_form.py	Mon Apr 26 11:16:23 2010 +0200
   430.3 @@ -0,0 +1,218 @@
   430.4 +# -*- coding: utf-8 -*-
   430.5 +
   430.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   430.7 +#
   430.8 +#  This program is free software: you can redistribute it and/or modify
   430.9 +#  it under the terms of the GNU General Public License as published by
  430.10 +#  the Free Software Foundation, either version 3 of the License, or
  430.11 +#  (at your option) any later version.
  430.12 +#
  430.13 +#  This program is distributed in the hope that it will be useful,
  430.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  430.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  430.16 +#  GNU General Public License for more details.
  430.17 +#
  430.18 +#  You should have received a copy of the GNU General Public License
  430.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  430.20 +
  430.21 +
  430.22 +"""
  430.23 +# GATEWAY di default (3)
  430.24 +dhcp-option=3,192.168.96.1
  430.25 +
  430.26 +# DNS da passare ai client (6)
  430.27 +dhcp-option=6,192.168.96.254
  430.28 +
  430.29 +# WINS da passare ai client (44)
  430.30 +dhcp-option=44,192.168.96.253
  430.31 +"""
  430.32 +
  430.33 +from django import forms
  430.34 +from django.forms import util
  430.35 +from django.conf import settings
  430.36 +from isi.conf import dnsmasq, tools, hosts, mac
  430.37 +from django.contrib import messages
  430.38 +from isiweb.logger import logger
  430.39 +
  430.40 +
  430.41 +SIMPLE_PARAMS = ['domain-needed', 'bogus-priv', 'filterwin2k', 'expand-hosts', 'dhcp-authoritative']
  430.42 +PARAMS = ['server', 'domain', 'dhcp-range', 'dhcp-host', 'dhcp-option', 'cache-size', 'conf-dir',
  430.43 +          'addn-hosts', 'conf-file', 'conf-dir']
  430.44 +
  430.45 +auth_tip = u"""dhcp_autoritative|Deve essere 'True' per il corretto funzionamento di ReteISI.
  430.46 +    Indica se -in presenza di altri dhcp server- questo deve comunicare la sua priorità.
  430.47 +    Avere più dhcp server nella stessa rete porta normalmente a guai ed è quindi sconsigliato"""
  430.48 +
  430.49 +tips = {
  430.50 +    'gw' : 'Gateway /Router|Il default gateway passato dal dhcp',
  430.51 +    'domain' : 'Domain|il dominio internet passato dal dhcp',
  430.52 +    'wins' : 'Wins Server|Il winserver usato dai client per la risoluzione delle risorse Windows',
  430.53 +    'dhcp_authoritative' : auth_tip,
  430.54 +    'dns' : "Dns|Il server dns per i client (deve puntare a questa versione di dnsmasq",
  430.55 +    'server' : u"Server|DNS esterni cui verranno inoltrate le domande dns per le quali questo server dnsmasq non è autoritativo",
  430.56 +    }
  430.57 +
  430.58 +def get_data(filename):
  430.59 +
  430.60 +    data = {}
  430.61 +    conf = dnsmasq.Conf(filename)
  430.62 +    
  430.63 +    data['server'] = " ".join([l.value for l in conf.get_param('server')])
  430.64 +    data['domain'] = conf.get_param('domain')[0].value
  430.65 +    data['dhcp_authoritative'] = bool(conf.get_param('domain'))
  430.66 +    data['gw'] = conf.get_option('gw')
  430.67 +    data['wins'] = conf.get_option('wins')
  430.68 +    data['dns'] = conf.get_option('dns')
  430.69 +    data['dhcp_range'] = conf.get_param('dhcp-range')[0].value
  430.70 +
  430.71 +    return data
  430.72 +
  430.73 +class DnsForm(forms.Form):
  430.74 +
  430.75 +#     domain_needed = forms.BooleanField()
  430.76 +#     bogus_priv = forms.BooleanField()
  430.77 +#     filterwin2k = forms.BooleanField()
  430.78 +#     expand_hosts = forms.BooleanField()
  430.79 +    dhcp_authoritative = forms.BooleanField(help_text=auth_tip, required=False)
  430.80 +
  430.81 +    server = forms.CharField(max_length=100,help_text=tips['server'])
  430.82 +    domain = forms.CharField(max_length=100,)
  430.83 +#    chache_size = forms.CharField(max_length=10,)
  430.84 +#    conf_dir = forms.CharField(max_length=10,)
  430.85 +
  430.86 +    dns = forms.IPAddressField()
  430.87 +    gw = forms.IPAddressField()    
  430.88 +    wins = forms.IPAddressField()
  430.89 +    dhcp_range = forms.CharField(max_length=150, help_text="start_ip, end_ip, metmask, time:\n192.168.1.100,192.168.1.200,255.255.255.0,8h")
  430.90 +
  430.91 +    def clean_server(self):
  430.92 +
  430.93 +        servers = self.cleaned_data['server'].split()
  430.94 +        for srv in servers:
  430.95 +            if not tools.is_ip_address(srv):
  430.96 +                raise util.ValidationError(u"%s non è un IP valido" % srv)
  430.97 +        return servers
  430.98 +
  430.99 +    def save(self):
 430.100 +        
 430.101 +        conf = dnsmasq.Conf(settings.DNSMASQ_CONF)
 430.102 +        for srv in self.cleaned_data['server']:
 430.103 +            conf.set_param('server', value=srv)
 430.104 +
 430.105 +        conf.set_param('domain', self.cleaned_data['domain'])
 430.106 +        conf.set_param('dhcp-range', self.cleaned_data['dhcp_range'])
 430.107 +        conf.set_option('gw', self.cleaned_data['gw'])
 430.108 +        conf.set_option('dns', self.cleaned_data['dns'])
 430.109 +        conf.set_option('wins', self.cleaned_data['wins'])
 430.110 +        ## impongo dhcp-autoritative
 430.111 +        conf.set_param('dhcp-authoritative')
 430.112 +
 430.113 +        conf.save()
 430.114 +
 430.115 +
 430.116 +
 430.117 +class HostForm(forms.Form):
 430.118 +
 430.119 +    ip = forms.IPAddressField(help_text="Inserire l'IP della macchina di cui si vuole impostare la risoluzione")
 430.120 +    hostname = forms.CharField(max_length=100, help_text="Inserire il nome della macchina (possibili anche alias)")
 430.121 +
 430.122 +    def save(self):
 430.123 +
 430.124 +        conf = hosts.Hosts(settings.HOSTS_CONF)
 430.125 +        conf.set_param(self.cleaned_data['ip'], self.cleaned_data['hostname'])
 430.126 +        conf.save()
 430.127 +
 430.128 +OPTIONS = (
 430.129 +    ('dhcp-boot',)*2,
 430.130 +    ('dhcp-option',)*2,
 430.131 +    ('dhcp-vendorclass',)*2,
 430.132 +    )
 430.133 +     
 430.134 +class BootLineForm(forms.Form):
 430.135 +
 430.136 +    index = forms.IntegerField()
 430.137 +    param_name = forms.ChoiceField(help_text="Nome del parametro", choices=OPTIONS)
 430.138 +    value = forms.CharField(max_length=100, required=False,
 430.139 +                            help_text="|Opzione completa di boot per sintassi dnsmasq")
 430.140 +    tag = forms.CharField(max_length=20, required=False,
 430.141 +                          help_text="Tag dnsmasq|Es.: fat_ns1, thin_srv2")
 430.142 +    image = forms.CharField(max_length=40, required=False, initial='/ltsp/i386/pxelinux.0',
 430.143 +                            help_text="Image|Deve esistere la corrispondente immagine/chroot. Questo parameto decide se fat/thin")
 430.144 +    server = forms.IPAddressField(required=False,
 430.145 +                                  help_text="Server|Inserire nome server (se correttamente risolto) o IP")
 430.146 +
 430.147 +    def clean(self):
 430.148 +        value = self.cleaned_data.get('value')
 430.149 +        tag = self.cleaned_data.get('tag')
 430.150 +        image = self.cleaned_data.get('image') or '/ltsp/i386/pxelinux.0'
 430.151 +        server  = self.cleaned_data.get('server')
 430.152 +
 430.153 +        if not value:
 430.154 +            if not tag or not ip_server:
 430.155 +                raise util.ValidationError(u'Devi scrivere tag e ip del server')
 430.156 +            self.cleaned_data['value'] = "net:%s,%s,%s" % (tag, image, server)
 430.157 +        return self.cleaned_data
 430.158 +
 430.159 +    def save(self):
 430.160 +        param_name = self.cleaned_data.get('param_name')
 430.161 +        value = self.cleaned_data.get('value')
 430.162 +        index = self.cleaned_data.get('index')
 430.163 +        
 430.164 +
 430.165 +        conf = dnsmasq.Conf(settings.BOOT_CONF)
 430.166 +        line = dnsmasq.Line(param_name=param_name, value=value)
 430.167 +        conf.lines.insert(index + 1, line)
 430.168 +        conf.save()
 430.169 +
 430.170 +    def update(self):
 430.171 +        param_name = self.cleaned_data.get('param_name')
 430.172 +        value = self.cleaned_data.get('value')
 430.173 +        index = self.cleaned_data.get('index')
 430.174 +
 430.175 +        conf = dnsmasq.Conf(settings.BOOT_CONF)
 430.176 +        line = dnsmasq.Line(param_name=param_name, value=value)
 430.177 +        conf.lines[index] = line
 430.178 +        conf.save()
 430.179 +
 430.180 +class MacForm(forms.Form):
 430.181 +
 430.182 +    mac = forms.CharField(help_text="MAC|Inserire il MACe della macchina di cui si vuole impostare il valore")
 430.183 +    ip = forms.IPAddressField(help_text="IP|Inserire l'IP della macchina di cui si vuole impostare la risoluzione",
 430.184 +                              required=False)
 430.185 +    value = forms.CharField(max_length=100, required=False,
 430.186 +                            help_text="Value|Inserire il nome della macchina (possibili anche alias)")
 430.187 +    tag = forms.CharField(max_length=20, required=False, help_text="Tag dnsmasq (net:)|Es. fat_ns1, thin_srv2. Deve esistere una corrispondente boot-option")
 430.188 +
 430.189 +    
 430.190 +    def clean_mac(self):
 430.191 +
 430.192 +        mac = self.cleaned_data['mac']
 430.193 +        if tools.is_mac_address(mac):
 430.194 +            return mac
 430.195 +        raise util.ValidationError(u"'%s' non è un mac address" % mac)
 430.196 +
 430.197 +    def clean_tag(self):
 430.198 +
 430.199 +        if self.cleaned_data['tag']:
 430.200 +            return "net:%s" % self.cleaned_data['tag']
 430.201 +        return None
 430.202 +
 430.203 +    def clean(self):
 430.204 +        tag = self.cleaned_data.get('tag')
 430.205 +        mac = self.cleaned_data.get('mac')
 430.206 +        ip  = self.cleaned_data.get('ip')
 430.207 +
 430.208 +        if not self.cleaned_data.get('value'):
 430.209 +            if not ip and not tag:
 430.210 +                raise util.ValidationError("Occorre definire almeno o l'IP o il tag")
 430.211 +            self.cleaned_data['value'] = ",".join([x for x in (mac, ip, tag) if x])
 430.212 +
 430.213 +        return self.cleaned_data
 430.214 +        
 430.215 +    def save(self):
 430.216 +        conf = mac.Mac(settings.MAC_CONF)
 430.217 +        line = conf.set_param('dhcp-host', self.cleaned_data['value'])
 430.218 +        conf.save()
 430.219 +        logger.debug("Added %s" % line)
 430.220 +        return line
 430.221 +
   431.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   431.2 +++ b/web/dnsmasq/models.py	Mon Apr 26 11:16:23 2010 +0200
   431.3 @@ -0,0 +1,3 @@
   431.4 +from django.db import models
   431.5 +
   431.6 +# Create your models here.
   432.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   432.2 +++ b/web/dnsmasq/templates/dnsmasq/boot_form.mako	Mon Apr 26 11:16:23 2010 +0200
   432.3 @@ -0,0 +1,24 @@
   432.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   432.5 +
   432.6 +<%def name="title()">Configurazione boot</%def>
   432.7 +
   432.8 +<%def name="layout()">
   432.9 +
  432.10 +param_name
  432.11 +h=index=$!?index
  432.12 +value
  432.13 +tag
  432.14 +image
  432.15 +server
  432.16 +--
  432.17 +s=Salva
  432.18 +
  432.19 +</%def>
  432.20 +
  432.21 +${jun.show_form_errors(form)}
  432.22 +${forms.mako_create_nform(context, layout, form, style='-')}
  432.23 +
  432.24 +
  432.25 +<script type="text/javascript" >
  432.26 +  $('td label[title]').cluetip({splitTitle: '|'});
  432.27 +</script>
   433.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   433.2 +++ b/web/dnsmasq/templates/dnsmasq/dnsmasq_form.mako	Mon Apr 26 11:16:23 2010 +0200
   433.3 @@ -0,0 +1,26 @@
   433.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   433.5 +
   433.6 +<%def name="title()">Configurazione dhcp </%def>
   433.7 +
   433.8 +<%def name="layout()">
   433.9 +
  433.10 +server:100
  433.11 +domain
  433.12 +## dhcp_authoritative
  433.13 +gw
  433.14 +wins
  433.15 +dns
  433.16 +dhcp_range
  433.17 +--
  433.18 +s=Aggiorna
  433.19 +
  433.20 +</%def>
  433.21 +${jun.show_form_errors(form)}
  433.22 +${forms.mako_create_nform(context, layout, form, style='-')}
  433.23 +
  433.24 +
  433.25 +<script type="text/javascript" >
  433.26 +$(document).ready(function () {
  433.27 +  $('td label[title]').cluetip({splitTitle: '|'});
  433.28 +});
  433.29 +</script>
   434.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   434.2 +++ b/web/dnsmasq/templates/dnsmasq/dnsmasq_list.mako	Mon Apr 26 11:16:23 2010 +0200
   434.3 @@ -0,0 +1,263 @@
   434.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   434.5 +
   434.6 +<%def name="dhcp()">
   434.7 +
   434.8 +
   434.9 +<div style="margin-bottom: 40px">
  434.10 +<form action="/dnsmasq/restart/">
  434.11 +  <input type="submit" class="submit ui-button ui-widget" value="Riavvia DnsMasq" name="Riavvia">
  434.12 +</form>
  434.13 +</div>
  434.14 +
  434.15 +<p>
  434.16 +Questi parametri verranno usati per 
  434.17 +    <table>
  434.18 +    <thead>
  434.19 +    <tr>
  434.20 +      <th>Parametro</th>
  434.21 +      <th>Valore</th>
  434.22 +    </tr>
  434.23 +    </thead>	
  434.24 +    <tbody>
  434.25 +      
  434.26 +    % for key, value in dnsdata.iteritems():
  434.27 +       <tr>
  434.28 +	 <td class="title" title="${tips.get(key, '')}"><b>${key.title()}:</b></td>  
  434.29 +	 <td>${value}</td>  
  434.30 +       </tr>
  434.31 +    % endfor
  434.32 +
  434.33 +    </tbody>
  434.34 +    </table>
  434.35 +
  434.36 +  <div class="actions">
  434.37 +    ${jun.popup_link('/dnsmasq/set_dhcp/?'+ '&popup', txt="Modifica la configurazione", icon='edit')}
  434.38 +  </div> <!--  actions -->
  434.39 +
  434.40 +</%def>
  434.41 +
  434.42 +<%def name="mac()">
  434.43 +    <table>
  434.44 +    <thead>
  434.45 +    <tr>
  434.46 +      <th></th>
  434.47 +      <th>Parametro</th>
  434.48 +      <th>Valore</th>
  434.49 +    </tr>
  434.50 +    </thead>	
  434.51 +    <tbody>
  434.52 +    % for mac, value in macs:
  434.53 +       <tr>
  434.54 +	 <td>${jun.popup_link('/dnsmasq/mac/del/%s/?' % mac+ "&popup", icon='del')}</td>  
  434.55 +	 <td><b>${mac}</b></td>  
  434.56 +	 <td>${value}</td>  
  434.57 +       </tr>
  434.58 +    % endfor
  434.59 +
  434.60 +    </tbody>
  434.61 +    </table>
  434.62 +
  434.63 +  <div class="actions">
  434.64 +    ${jun.popup_link('/dnsmasq/mac/add/?'+ "&popup", icon='add', txt='Aggiungi un abbinamento mac/ip')}
  434.65 +  </div> <!--  actions -->
  434.66 +
  434.67 +</%def>
  434.68 +<%def name="leases_tab()">
  434.69 +    <table class="tbldata">
  434.70 +    <thead>
  434.71 +    <tr>
  434.72 +      <th>Mac</th>
  434.73 +      <th>IP</th>
  434.74 +      <th>Hostname</th>
  434.75 +      <th>Client ID</th>
  434.76 +    </tr>
  434.77 +    </thead>	
  434.78 +    <tbody>
  434.79 +    % for lease in leases:
  434.80 +       <tr>
  434.81 +	 <td>${lease.mac}</td>  
  434.82 +	 <td>${lease.ip}</td>  
  434.83 +	 <td>${lease.hostname or ''}</td>  
  434.84 +	 <td>${lease.client_id or ''}</td>  
  434.85 +       </tr>
  434.86 +    % endfor
  434.87 +
  434.88 +    </tbody>
  434.89 +    </table>
  434.90 +</%def>
  434.91 +
  434.92 +<%def name="boot()">
  434.93 +  
  434.94 +  <div class="ui-state-error" style="padding: 15px;">In questa sezione è  importante l'ordine dei parametri</div>
  434.95 +  
  434.96 +  Qui potete aggiungere server e corrispondenze fra server, tag e immagini
  434.97 +  da caricare.
  434.98 +
  434.99 +    <table class="">
 434.100 +    <thead>
 434.101 +    <tr>
 434.102 +      <th>Option</th>
 434.103 +      <th>Value</th>
 434.104 +      <th>Azione</th>
 434.105 +    </tr>
 434.106 +    </thead>	
 434.107 +    <tbody>
 434.108 +    % for line in [x for x in boot_conf.lines if not x.is_comment]:
 434.109 +       <tr>
 434.110 +	 <td>${line.param_name}</td>  
 434.111 +	 <td>${line.value}</td>  
 434.112 +	 <td>
 434.113 +     ${jun.popup_link('/dnsmasq/boot/add/%s/?popup'% boot_conf.lines.index(line), icon='add')}
 434.114 +     ${jun.popup_link('/dnsmasq/boot/del/%s/?popup'% boot_conf.lines.index(line), icon='del')}
 434.115 +     ${jun.popup_link('/dnsmasq/boot/edit/%s/?popup'% boot_conf.lines.index(line), icon='edit')}
 434.116 +      </td>  
 434.117 +       </tr>
 434.118 +    % endfor
 434.119 +
 434.120 +    </tbody>
 434.121 +    </table>
 434.122 +</%def>
 434.123 +
 434.124 +
 434.125 +<%def name="sezione(sez)">
 434.126 +  <div id="${sez}" class="tab">
 434.127 +    % if sez == 'dhcp':
 434.128 +       ${self.dhcp()}
 434.129 +    % elif sez == 'dns':
 434.130 +       ${self.dns()}
 434.131 +    % elif sez == 'mac':
 434.132 +       ${self.mac()}
 434.133 +    % elif sez == 'boot':
 434.134 +       ${self.boot()}
 434.135 +    % else:
 434.136 +       ${self.leases_tab()}
 434.137 +    % endif
 434.138 +  </div>
 434.139 +</%def>
 434.140 +
 434.141 +<div id="tabs">
 434.142 +  <ul > 
 434.143 +       <li><a href="#dhcp">dhcp</a></li>
 434.144 +       <li><a href="#dns">dns</a></li>
 434.145 +       <li><a href="#mac">mac</a></li>
 434.146 +       <li><a href="#boot">boot/ltsp</a></li>
 434.147 +       <li><a href="#leases">leases</a></li>
 434.148 +  </ul>
 434.149 +  %for sez in ('dhcp',  'dns', 'mac', 'boot','leases'):
 434.150 +      ${self.sezione(sez)}
 434.151 +  %endfor
 434.152 +  
 434.153 +</div> <!-- tabs -->
 434.154 +
 434.155 +<script type="text/javascript" >
 434.156 +$(document).ready(function () {
 434.157 +
 434.158 +  $('#tabs').tabs();
 434.159 +  $('#tabs li > a').click(function () {document.location.hash = this.href; });  
 434.160 +  $('td.title').cluetip({splitTitle: '|'});
 434.161 +##  $('td.title').cluetip({splitTitle: '|', sticky: true, closePosition: 'title', arrows: true });
 434.162 +
 434.163 +  $('.toggle').click(function(){
 434.164 +     $('.advanced').toggle();
 434.165 +   });
 434.166 +
 434.167 +  $('.tbldata').dataTable( {
 434.168 +##             "aaSorting": [[0,'asc'],],
 434.169 +             "bPaginate": false,
 434.170 +		"bLengthChange": 25,
 434.171 +		"bFilter": true,
 434.172 +		"bSort": true,
 434.173 +		"bInfo": true,
 434.174 +                 "sDom": 'ft',
 434.175 +
 434.176 +                "bJQueryUI": false,
 434.177 +		"bAutoWidth": true }
 434.178 +  );
 434.179 +
 434.180 +
 434.181 +});
 434.182 +</script>
 434.183 +
 434.184 +<%def name="dns()">
 434.185 +    <table class="tbldata">
 434.186 +    <thead>
 434.187 +    <tr>
 434.188 +      <th></th>
 434.189 +      <th>Parametro</th>
 434.190 +      <th>Valore</th>
 434.191 +    </tr>
 434.192 +    </thead>	
 434.193 +    <tbody>
 434.194 +    % for ip, name in hosts:
 434.195 +       <tr>
 434.196 +	 <td>${jun.popup_link('/dnsmasq/host/del/%s/?&popup' % ip, icon='del')}</td>  
 434.197 +	 <td>${ip}</td>  
 434.198 +	 <td>${name}</td>  
 434.199 +       </tr>
 434.200 +    % endfor
 434.201 +
 434.202 +    </tbody>
 434.203 +    </table>
 434.204 +
 434.205 +  <div class="actions">
 434.206 +##    <a href="/dnsmasq/host/add/?" class="dialog-form" title="Aggiungi host">Aggiungi un host con ajax</a>
 434.207 +    ${jun.popup_link('/dnsmasq/host/add/?'+ "&popup", icon='add', txt='Aggiungi un host')}
 434.208 +  </div> <!--  actions -->
 434.209 +</%def>
 434.210 +
 434.211 +<%def name="ajax_form()">
 434.212 +<script type="text/javascript" >
 434.213 +$(document).ready(dialogForms);
 434.214 +
 434.215 +function dialogForms1() {
 434.216 +  $('a.dialog-form').click(function() {
 434.217 +    var a = $(this);
 434.218 +    $.get(a.attr('href'),function(resp){
 434.219 +      var dialog = $('<div>').attr('id','formDialog').html(resp);
 434.220 +      $('body').append(dialog);
 434.221 +      dialog.find(':submit').hide();
 434.222 +      dialog.dialog({
 434.223 +        title: a.attr('title') ? a.attr('title') : '',
 434.224 +        modal: true,
 434.225 +        autoOpen: false,
 434.226 +        buttons: {
 434.227 +          'Save': function() {submitFormWithAjax($(this).find('form'));},
 434.228 +          'Cancel': function() {$(this).dialog('close');}
 434.229 +        },
 434.230 +        close: function() {$(this).remove();},
 434.231 +        width: 'auto'
 434.232 +      });
 434.233 +    }, 'html');
 434.234 +    return false;
 434.235 +  });
 434.236 +}
 434.237 +
 434.238 +function dialogForms() {
 434.239 +  $('a.dialog-form').click(function() {
 434.240 +    var a = $(this);
 434.241 +    $('#ajdialog').load(a.attr('href') + 'nt=1').dialog({
 434.242 +        title: a.attr('title') ? a.attr('title') : '',
 434.243 +        modal: true,
 434.244 +        buttons: {
 434.245 +          'Save': function() {submitFormWithAjax($(this).find('form'));},
 434.246 +          'Cancel': function() {$(this).dialog('close');}
 434.247 +        },
 434.248 +        close: function() {$(this).remove();},
 434.249 +        width: 'auto'
 434.250 +      });
 434.251 +    return false;
 434.252 +  });
 434.253 +}
 434.254 +
 434.255 +function submitFormWithAjax(form) {
 434.256 +  form = $(form);
 434.257 +  $.post(form.baseURI, function (resp) {
 434.258 +     $('#ajdialog').html(resp)
 434.259 +  }).serialize();
 434.260 +  return false;
 434.261 +} 
 434.262 +</script>
 434.263 +</%def>
 434.264 +## ${self.ajax_submit()}
 434.265 +
 434.266 +<div id="ajdialog"></div>
   435.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   435.2 +++ b/web/dnsmasq/templates/dnsmasq/host_form.mako	Mon Apr 26 11:16:23 2010 +0200
   435.3 @@ -0,0 +1,21 @@
   435.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   435.5 +
   435.6 +<%def name="title()">Configurazione dhcp </%def>
   435.7 +
   435.8 +<%def name="layout()">
   435.9 +
  435.10 +hostname
  435.11 +ip
  435.12 +--
  435.13 +s=Aggiungi
  435.14 +
  435.15 +</%def>
  435.16 +
  435.17 +<style>
  435.18 +http://localhost:8000/static/css/ui/themes/isi/ui.theme.css
  435.19 +</style>
  435.20 +##<h2>${title()}</h2>
  435.21 +  ${jun.show_form_errors(form)}
  435.22 +  ${forms.mako_create_nform(context, layout, form, action="/dnsmasq/host/add/?nt=1", style='-')}
  435.23 +
  435.24 +
   436.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   436.2 +++ b/web/dnsmasq/templates/dnsmasq/mac_form.mako	Mon Apr 26 11:16:23 2010 +0200
   436.3 @@ -0,0 +1,39 @@
   436.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   436.5 +
   436.6 +<%def name="title()">Configurazione dhcp </%def>
   436.7 +
   436.8 +<%def name="layout()">
   436.9 +
  436.10 +mac
  436.11 +ip
  436.12 +tag
  436.13 +value
  436.14 +--
  436.15 +s=Aggiungi
  436.16 +
  436.17 +</%def>
  436.18 +
  436.19 +In questa pagina si possono aggiungere degli abbinamenti fra un MAC address
  436.20 +ed una opzione di boot.
  436.21 +
  436.22 +Il MAC address ha una forma così: <tt>00:0c:29:10:a6:45</tt> ed identifica
  436.23 +in modo univo una scheda di rete e quindi in generale un client.
  436.24 +
  436.25 +Si può aggiungere un tag, ovvero un identificatore che verrà usato dal dhcp
  436.26 +  per decidere quale immagine inviare al client se richiede (tramite
  436.27 +  PXE/gPXE) una immagine per partire come thin/fat client.
  436.28 +
  436.29 +Il tag è una stringa qualunque, ma deve esserci una corrispondente opzione
  436.30 +  di boot perché venga presa in considerazione (altrimenti il default, se
  436.31 +  definito viene usato). Tag sensati hanno una indicazione dell'immagine
  436.32 +  (fat/thin) e del server (srv1/srv2...)
  436.33 +
  436.34 +
  436.35 +##<h2>${title()}</h2>
  436.36 +  ${jun.show_form_errors(form)}
  436.37 +  ${forms.mako_create_nform(context, layout, form, style='-')}
  436.38 +
  436.39 +
  436.40 +<script type="text/javascript" >
  436.41 +  $('td label[title]').cluetip({splitTitle: '|'});
  436.42 +</script>
   437.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   437.2 +++ b/web/dnsmasq/tests.py	Mon Apr 26 11:16:23 2010 +0200
   437.3 @@ -0,0 +1,23 @@
   437.4 +"""
   437.5 +This file demonstrates two different styles of tests (one doctest and one
   437.6 +unittest). These will both pass when you run "manage.py test".
   437.7 +
   437.8 +Replace these with more appropriate tests for your application.
   437.9 +"""
  437.10 +
  437.11 +from django.test import TestCase
  437.12 +
  437.13 +class SimpleTest(TestCase):
  437.14 +    def test_basic_addition(self):
  437.15 +        """
  437.16 +        Tests that 1 + 1 always equals 2.
  437.17 +        """
  437.18 +        self.failUnlessEqual(1 + 1, 2)
  437.19 +
  437.20 +__test__ = {"doctest": """
  437.21 +Another way to test that 1 + 1 is equal to 2.
  437.22 +
  437.23 +>>> 1 + 1 == 2
  437.24 +True
  437.25 +"""}
  437.26 +
   438.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   438.2 +++ b/web/dnsmasq/urls.py	Mon Apr 26 11:16:23 2010 +0200
   438.3 @@ -0,0 +1,17 @@
   438.4 +from django.conf.urls.defaults import *
   438.5 +
   438.6 +urlpatterns = patterns('isiweb.dnsmasq.views',
   438.7 +    (r'^conf/', 'show_conf'),
   438.8 +    (r'^restart/', 'restart'),
   438.9 +    (r'^set_dhcp/', 'set_dhcp'),
  438.10 +    (r'^host/add/', 'add_host'),
  438.11 +    (r'^mac/add/', 'add_mac'),
  438.12 +    (r'^host/del/(?P<ip>[0-9.]+)/', 'del_host'),
  438.13 +    (r'^mac/del/(?P<mac_address>[0-9a-fA-F:.]+)/', 'del_mac'),
  438.14 +    (r'^boot/add/(?P<index>[0-9]+)/', 'add_boot_param'),
  438.15 +    (r'^boot/del/(?P<index>[0-9]+)/', 'del_boot_param'),
  438.16 +    (r'^boot/edit/(?P<index>[0-9]+)/', 'edit_boot_param'),
  438.17 +
  438.18 +#     (r'^pc/add/', 'add_pc'),
  438.19 +#     (r'^pc/del/', 'del_pc'),
  438.20 +)
   439.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   439.2 +++ b/web/dnsmasq/views.py	Mon Apr 26 11:16:23 2010 +0200
   439.3 @@ -0,0 +1,218 @@
   439.4 +# -*- coding: utf-8 -*-
   439.5 +
   439.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   439.7 +#
   439.8 +#  This program is free software: you can redistribute it and/or modify
   439.9 +#  it under the terms of the GNU General Public License as published by
  439.10 +#  the Free Software Foundation, either version 3 of the License, or
  439.11 +#  (at your option) any later version.
  439.12 +#
  439.13 +#  This program is distributed in the hope that it will be useful,
  439.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  439.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  439.16 +#  GNU General Public License for more details.
  439.17 +#
  439.18 +#  You should have received a copy of the GNU General Public License
  439.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  439.20 +
  439.21 +
  439.22 +from django.template import RequestContext
  439.23 +from django.http import HttpResponseRedirect
  439.24 +from django.conf import settings
  439.25 +from vov.views.decorators import login_required
  439.26 +from vov.views import mgeneric
  439.27 +from django.views import generic
  439.28 +from vov.template import mako_loader
  439.29 +from isi.conf import logon, hosts, mac, dnsmasq
  439.30 +from django.contrib import messages
  439.31 +import dns_form
  439.32 +from django.contrib import messages
  439.33 +from dry.functions import execute
  439.34 +import isi
  439.35 +
  439.36 +logger = isi.srv.get_logger(web=True)
  439.37 +    
  439.38 +@login_required
  439.39 +def show_conf(request):
  439.40 +
  439.41 +    data = dns_form.get_data(settings.DNSMASQ_CONF)
  439.42 +
  439.43 +    host_conf = hosts.Hosts(settings.HOSTS_CONF)
  439.44 +    host_list = [(l.param_name, l.value) for l in host_conf.lines if not l.is_comment]
  439.45 +
  439.46 +    mac_conf = mac.Mac(settings.MAC_CONF)
  439.47 +    mac_list = [(l.mac, l.value.replace(l.mac + ',', '')) for l in mac_conf.get_param('dhcp-host')]
  439.48 +
  439.49 +    leases = dnsmasq.get_leases(settings.LEASES_FILE)
  439.50 +    boot_conf = dnsmasq.Conf(settings.BOOT_CONF)
  439.51 +
  439.52 +    context = {
  439.53 +        'dnsdata' : data,
  439.54 +        'hosts' : host_list,
  439.55 +        'macs' : mac_list,
  439.56 +        'leases' : leases,
  439.57 +        'boot_conf' : boot_conf,
  439.58 +        'tips' : dns_form.tips,
  439.59 +        }
  439.60 +    return mako_loader.render_to_response('dnsmasq/dnsmasq_list.mako', context,
  439.61 +                                   context_instance=RequestContext(request),)
  439.62 +
  439.63 +@login_required
  439.64 +def set_dhcp(request):
  439.65 +    
  439.66 +    if request.method == 'POST': # If the form has been submitted...
  439.67 +        form = dns_form.DnsForm(request.POST) # A form bound to the POST data
  439.68 +        if form.is_valid(): # All validation rules pass
  439.69 +            form.save()
  439.70 +            messages.success(request, 'Dhcp aggiornato')
  439.71 +            return HttpResponseRedirect('/views/close_popup/') 
  439.72 +    else:
  439.73 +        data = dns_form.get_data(settings.DNSMASQ_CONF)
  439.74 +        form = dns_form.DnsForm(initial=data) # An unbound form
  439.75 +
  439.76 +    context = {'form' : form,}
  439.77 +
  439.78 +    return mako_loader.render_to_response('dnsmasq/dnsmasq_form.mako', context,
  439.79 +                                   context_instance=RequestContext(request),)
  439.80 +
  439.81 +@login_required
  439.82 +def add_host(request):
  439.83 +    
  439.84 +    if request.method == 'POST': # If the form has been submitted...
  439.85 +        form = dns_form.HostForm(request.POST) # A form bound to the POST data
  439.86 +        if form.is_valid(): # All validation rules pass
  439.87 +            form.save()
  439.88 +            messages.success(request, 'Host aggiornato')
  439.89 +            return HttpResponseRedirect('/views/close_popup/') 
  439.90 +    else:
  439.91 +        form = dns_form.HostForm() # An unbound form
  439.92 +
  439.93 +    context = {'form' : form,}
  439.94 +
  439.95 +    return mako_loader.render_to_response('dnsmasq/host_form.mako', context,
  439.96 +                                   context_instance=RequestContext(request),)
  439.97 +
  439.98 +@login_required
  439.99 +def add_mac(request):
 439.100 +    
 439.101 +    if request.method == 'POST': # If the form has been submitted...
 439.102 +        form = dns_form.MacForm(request.POST) # A form bound to the POST data
 439.103 +        if form.is_valid(): # All validation rules pass
 439.104 +            line = form.save()
 439.105 +            messages.success(request, "Added %s" % line)
 439.106 +            return HttpResponseRedirect('/views/close_popup/') 
 439.107 +    else:
 439.108 +        form = dns_form.MacForm() # An unbound form
 439.109 +
 439.110 +    context = {'form' : form,}
 439.111 +
 439.112 +    return mako_loader.render_to_response('dnsmasq/mac_form.mako', context,
 439.113 +                                   context_instance=RequestContext(request),)
 439.114 +
 439.115 +class IP(mgeneric.Obj):
 439.116 +
 439.117 +    def __init__(self, request, ip):
 439.118 +
 439.119 +        self.ip = self.value = ip
 439.120 +        self.conf = hosts.Hosts(settings.HOSTS_CONF)
 439.121 +
 439.122 +    def delete(self):
 439.123 +        self.conf.del_param(self.ip)
 439.124 +        self.conf.save()
 439.125 +        self.message = 'Eliminato host: ' + self.ip
 439.126 +        logger.debug('Eliminato host %s' % self.ip)
 439.127 +
 439.128 +
 439.129 +class Mac(mgeneric.Obj):
 439.130 +
 439.131 +    def __init__(self, request, mac_address):
 439.132 +
 439.133 +        self.mac = self.value = mac_address
 439.134 +        self.conf = mac.Mac(settings.HOSTS_CONF)
 439.135 +
 439.136 +    def delete(self):
 439.137 +        self.conf.del_param(self.mac)
 439.138 +        self.conf.save()
 439.139 +        self.message = 'Eliminato mac: ' + self.mac
 439.140 +        logger.debug('Eliminato mac %s' % self.mac)
 439.141 +
 439.142 +class BootParam(mgeneric.Obj):
 439.143 +
 439.144 +    def __init__(self, request, index):
 439.145 +
 439.146 +        self.index  = index
 439.147 +        self.conf = dnsmasq.Conf(settings.BOOT_CONF)
 439.148 +        self.value = unicode(self.conf.lines[index])
 439.149 +        
 439.150 +    def delete(self):
 439.151 +        line = self.conf.lines.pop(self.index)
 439.152 +        self.conf.save()
 439.153 +        self.message = 'Eliminato parametro: %s' % line
 439.154 +        logger.debug('Eliminato parametro: %s' % line)
 439.155 +
 439.156 +@login_required
 439.157 +def del_host(request, ip):
 439.158 +
 439.159 +    obj = IP(request, ip)
 439.160 +    return mgeneric.delete_non_model(request, obj=obj, )
 439.161 +
 439.162 +@login_required
 439.163 +def del_mac(request, mac_address):
 439.164 +
 439.165 +    obj = Mac(request, mac_address)
 439.166 +    return mgeneric.delete_non_model(request, obj=obj, )
 439.167 +
 439.168 +@login_required
 439.169 +def del_boot_param(request, index):
 439.170 +
 439.171 +    obj = BootParam(request, int(index))
 439.172 +    return mgeneric.delete_non_model(request, obj=obj, )
 439.173 +
 439.174 +
 439.175 +########  boot #######
 439.176 +@login_required
 439.177 +def add_boot_param(request, index):
 439.178 +    
 439.179 +    if request.method == 'POST': # If the form has been submitted...
 439.180 +        form = dns_form.BootLineForm(request.POST) # A form bound to the POST data
 439.181 +        if form.is_valid(): # All validation rules pass
 439.182 +            form.save()
 439.183 +            messages.success(request, 'Aggiunto parametro di boot')
 439.184 +            return HttpResponseRedirect('/views/close_popup/') 
 439.185 +    else:
 439.186 +        form = dns_form.BootLineForm() # An unbound form
 439.187 +
 439.188 +    context = {'form' : form, 'index' : index}
 439.189 +
 439.190 +    return mako_loader.render_to_response('dnsmasq/boot_form.mako', context,
 439.191 +                                   context_instance=RequestContext(request),)
 439.192 +
 439.193 +@login_required
 439.194 +def edit_boot_param(request, index):
 439.195 +    
 439.196 +
 439.197 +    if request.method == 'POST': # If the form has been submitted...
 439.198 +        form = dns_form.BootLineForm(request.POST) # A form bound to the POST data
 439.199 +        if form.is_valid(): # All validation rules pass
 439.200 +            form.update()
 439.201 +            messages.success(request, 'Aggiunto parametro di boot')
 439.202 +            return HttpResponseRedirect('/views/close_popup/') 
 439.203 +    else:
 439.204 +        boot_conf = dnsmasq.Conf(settings.BOOT_CONF)
 439.205 +        data = vars(boot_conf.lines[int(index)])
 439.206 +        form = dns_form.BootLineForm(initial=data) # An unbound form
 439.207 +
 439.208 +    context = {'form' : form, 'index': index}
 439.209 +
 439.210 +    return mako_loader.render_to_response('dnsmasq/boot_form.mako', context,
 439.211 +                                   context_instance=RequestContext(request),)
 439.212 +
 439.213 +@login_required
 439.214 +def restart(request):
 439.215 +    ret_code, out, err = execute('/etc/init.d/dnsmasq restart')
 439.216 +    if not ret_code:
 439.217 +        messages.success(request, "Dnsmasq server riavviato correttamente")
 439.218 +    else:
 439.219 +        messages.error(request, "Errore nel riavvio del server: %s" % err)
 439.220 +    
 439.221 +    return HttpResponseRedirect('/dnsmasq/conf/')
   440.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   440.2 +++ b/web/ldap-auth.py	Mon Apr 26 11:16:23 2010 +0200
   440.3 @@ -0,0 +1,48 @@
   440.4 +from django.conf import settings
   440.5 +from django.contrib.auth.models import User, check_password
   440.6 +import isi
   440.7 +
   440.8 +
   440.9 +class LDAPBackend(object):
  440.10 +    """
  440.11 +    Authenticate against ldap users
  440.12 +    """
  440.13 +    def authenticate(self, username=None, password=None):
  440.14 +
  440.15 +        l = isi.Manager()
  440.16 +        
  440.17 +        try:
  440.18 +            if username == 'admin':
  440.19 +                ## needed for the first access
  440.20 +                login_valid = True
  440.21 +                pwd_valid = password == l.srv.passwd
  440.22 +            else:
  440.23 +                login_valid = l.user_in_group(username, 'admins') or l.user_in_group(username, 'docenti')
  440.24 +                pwd_valid = l.test_password(username, password)
  440.25 +
  440.26 +            if login_valid and pwd_valid:
  440.27 +                try:
  440.28 +                    user = User.objects.get(username=username)
  440.29 +                except User.DoesNotExist:
  440.30 +                    # Create a new user. Note that we can set password
  440.31 +                    # to anything, because it won't be checked; the password
  440.32 +                    # from settings.py will.
  440.33 +                    
  440.34 +                    user = User(username=username, password='get from ldap')
  440.35 +                    if username == 'admin' or 'admins' in l.get_user(username).get_my_groups(as_plain_list=True):
  440.36 +                        user.is_staff = True
  440.37 +                    else:
  440.38 +                        user.is_staff = False
  440.39 +                    user.is_superuser = True
  440.40 +                    user.save()
  440.41 +                return user
  440.42 +        except isi.exc.MissingMatch, e:
  440.43 +            return None
  440.44 +        return None
  440.45 +
  440.46 +    def get_user(self, user_id):
  440.47 +        try:
  440.48 +            return User.objects.get(pk=user_id)
  440.49 +        except User.DoesNotExist:
  440.50 +            return None
  440.51 +
   441.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   441.2 +++ b/web/manage.py	Mon Apr 26 11:16:23 2010 +0200
   441.3 @@ -0,0 +1,11 @@
   441.4 +#!/usr/bin/env python
   441.5 +from django.core.management import execute_manager
   441.6 +try:
   441.7 +    import settings # Assumed to be in the same directory.
   441.8 +except ImportError:
   441.9 +    import sys
  441.10 +    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
  441.11 +    sys.exit(1)
  441.12 +
  441.13 +if __name__ == "__main__":
  441.14 +    execute_manager(settings)
   442.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   442.2 +++ b/web/modwsgi.py	Mon Apr 26 11:16:23 2010 +0200
   442.3 @@ -0,0 +1,8 @@
   442.4 +import os
   442.5 +os.environ['DJANGO_SETTINGS_MODULE'] = 'isiweb.settings'
   442.6 +
   442.7 +import django.core.handlers.wsgi
   442.8 +
   442.9 +application = django.core.handlers.wsgi.WSGIHandler()
  442.10 +
  442.11 +
   443.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   443.2 +++ b/web/navigazione/models.py	Mon Apr 26 11:16:23 2010 +0200
   443.3 @@ -0,0 +1,3 @@
   443.4 +from django.db import models
   443.5 +
   443.6 +# Create your models here.
   444.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   444.2 +++ b/web/navigazione/templates/navigazione/show_conf.mako	Mon Apr 26 11:16:23 2010 +0200
   444.3 @@ -0,0 +1,68 @@
   444.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   444.5 +
   444.6 +<div id="tabs">
   444.7 +  <ul > 
   444.8 +     %for sez in ('classi', ):
   444.9 +           <li><a href="#${sez}">${sez}</a></li>
  444.10 +     %endfor
  444.11 +  </ul>
  444.12 +  
  444.13 +
  444.14 +
  444.15 +  <div id="classi" class="tab">
  444.16 +
  444.17 +    <div class="azioni">
  444.18 +      <table>
  444.19 +      <theader>
  444.20 +        <tr>
  444.21 +	 <th>classe</th>
  444.22 +	 <th>bloccata?</th>
  444.23 +	 <th></th>
  444.24 +      </theader>
  444.25 +      <tbody>
  444.26 +       %for c in classes:
  444.27 +        <tr>
  444.28 +          <td>${c}</td>
  444.29 +	   % if c.get_www():
  444.30 +	      <td>SI</td>
  444.31 +              <td><a href='/navigazione/allow/${c.name}'>permetti</a></td>
  444.32 +           % else:
  444.33 +	      <td>NO</td>
  444.34 +              <td><a href='/navigazione/block/${c.name}'>inibisci</a></td>
  444.35 +           % endif
  444.36 +        </tr>
  444.37 +       %endfor
  444.38 +      </tbody>
  444.39 +      </table>
  444.40 +
  444.41 +
  444.42 +    </div> <!-- azioni  -->
  444.43 +  </div> <!-- dominio -->
  444.44 +
  444.45 +##   <div id="aule" class="tab">
  444.46 +##     <div class="azioni">
  444.47 +##       <a href="/samba/conf/save/">Inibisci un'aula <img src="/static/img/icon_changelink.gif"></>
  444.48 +##     </div> <!-- azioni  -->
  444.49 +##   </div> <!-- aule  -->
  444.50 +## 
  444.51 +</div> <!-- tabs -->
  444.52 +
  444.53 +####  script & style
  444.54 +<script>
  444.55 +$(document).ready(function () {
  444.56 +
  444.57 +  $('#tabs').tabs();
  444.58 +  $('td.title').cluetip({splitTitle: '|'});
  444.59 +##  $('td.title').cluetip({splitTitle: '|', sticky: true, closePosition: 'title', arrows: true });
  444.60 +
  444.61 +});
  444.62 +</script>
  444.63 +
  444.64 +<style>
  444.65 +table.data {
  444.66 +   margin-top: 30px
  444.67 +}
  444.68 +table.data th {
  444.69 +   text-align: left
  444.70 +}
  444.71 +</style>
   445.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   445.2 +++ b/web/navigazione/tests.py	Mon Apr 26 11:16:23 2010 +0200
   445.3 @@ -0,0 +1,23 @@
   445.4 +"""
   445.5 +This file demonstrates two different styles of tests (one doctest and one
   445.6 +unittest). These will both pass when you run "manage.py test".
   445.7 +
   445.8 +Replace these with more appropriate tests for your application.
   445.9 +"""
  445.10 +
  445.11 +from django.test import TestCase
  445.12 +
  445.13 +class SimpleTest(TestCase):
  445.14 +    def test_basic_addition(self):
  445.15 +        """
  445.16 +        Tests that 1 + 1 always equals 2.
  445.17 +        """
  445.18 +        self.failUnlessEqual(1 + 1, 2)
  445.19 +
  445.20 +__test__ = {"doctest": """
  445.21 +Another way to test that 1 + 1 is equal to 2.
  445.22 +
  445.23 +>>> 1 + 1 == 2
  445.24 +True
  445.25 +"""}
  445.26 +
   446.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   446.2 +++ b/web/navigazione/urls.py	Mon Apr 26 11:16:23 2010 +0200
   446.3 @@ -0,0 +1,7 @@
   446.4 +from django.conf.urls.defaults import *
   446.5 +
   446.6 +urlpatterns = patterns('isiweb.navigazione.views',
   446.7 +    (r'^block/(?P<group_name>.*)/$', 'block'),
   446.8 +    (r'^allow/(?P<group_name>.*)/$', 'allow'),
   446.9 +    (r'^conf/$', 'show_conf'),
  446.10 +)
   447.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   447.2 +++ b/web/navigazione/views.py	Mon Apr 26 11:16:23 2010 +0200
   447.3 @@ -0,0 +1,38 @@
   447.4 +from django.template import RequestContext
   447.5 +from django.http import HttpResponseRedirect
   447.6 +from django.conf import settings
   447.7 +from vov.views.decorators import login_required
   447.8 +from django.views import generic
   447.9 +from vov.template import mako_loader
  447.10 +from isi.conf import logon
  447.11 +import isi
  447.12 +from django.contrib import messages
  447.13 +
  447.14 +l = isi.Manager()
  447.15 +
  447.16 +@login_required
  447.17 +def show_conf(request):
  447.18 +
  447.19 +    context = {
  447.20 +        'classes' : isi.srv.get_classes(as_groups=True)
  447.21 +    }
  447.22 +        
  447.23 +    return mako_loader.render_to_response('navigazione/show_conf.mako', context,
  447.24 +                                   context_instance=RequestContext(request),)
  447.25 +
  447.26 +@login_required
  447.27 +def block(request, group_name):
  447.28 +
  447.29 +    group = l.get_group(group_name)
  447.30 +    group.set_www(False)
  447.31 +    isi.get_logger(web=True).info("User %s has blocked class %s" % (request.user, group_name))
  447.32 +    return HttpResponseRedirect('/navigazione/conf/')
  447.33 +    
  447.34 +@login_required
  447.35 +def allow(request, group_name):
  447.36 +
  447.37 +    group = l.get_group(group_name)
  447.38 +    group.set_www(True)
  447.39 +    isi.get_logger().info("User %s has permitted www to class %s" % (request.user, group_name))
  447.40 +    return HttpResponseRedirect('/navigazione/conf/')
  447.41 +    
   448.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   448.2 +++ b/web/samba/models.py	Mon Apr 26 11:16:23 2010 +0200
   448.3 @@ -0,0 +1,3 @@
   448.4 +from django.db import models
   448.5 +
   448.6 +# Create your models here.
   449.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   449.2 +++ b/web/samba/samba_form.py	Mon Apr 26 11:16:23 2010 +0200
   449.3 @@ -0,0 +1,80 @@
   449.4 +"""
   449.5 +[global]
   449.6 +
   449.7 +## Browsing/Identification/Domain ###
   449.8 +
   449.9 +   workgroup = FOSSATIINTERNI
  449.10 +    netbios name = srv-fossati
  449.11 +   domain master = Yes
  449.12 +   local master = Yes
  449.13 +   preferred master = Yes
  449.14 +
  449.15 +"""
  449.16 +
  449.17 +from django import forms
  449.18 +from django.conf import settings
  449.19 +from dry.functions import execute, ExecuteError
  449.20 +import isi
  449.21 +import re
  449.22 +
  449.23 +logger = isi.srv.get_logger(web=True)
  449.24 +
  449.25 +class SambaForm(forms.Form):
  449.26 +
  449.27 +    domain_name = forms.CharField(label='Dominio', max_length=30, required=True)
  449.28 +    netbios_name  = forms.CharField(label="Nome netbios", max_length=30, required=True)
  449.29 +    root_password =  forms.CharField(widget=forms.PasswordInput(render_value=False)) 
  449.30 +    password = forms.CharField(widget=forms.PasswordInput(render_value=False)) 
  449.31 +
  449.32 +    def clean_prev_password(self):
  449.33 +
  449.34 +        password = self.cleaned_data['root_password']
  449.35 +        return password
  449.36 +
  449.37 +    def save(self):
  449.38 +        domain = self.cleaned_data['domain_name']
  449.39 +        srv_name = self.cleaned_data['netbios_name']
  449.40 +        root_password = self.cleaned_data['root_password']
  449.41 +        password = self.cleaned_data['password']
  449.42 +        cmd = ['/usr/sbin/isi-domain', '-Qq', domain, srv_name, password]
  449.43 +        ret_code, out, err = execute(cmd)
  449.44 +        if not ret_code:
  449.45 +            logger.debug("/usr/sbin/isi-domain %s %s %s" % (domain, srv_name, '...'))
  449.46 +            self.message = "<br>".join(out.split('\n'))
  449.47 +        else:
  449.48 +            raise ExecuteError("isi-domain ha problemi: error: %s output: %s" % (err, out))
  449.49 +        
  449.50 +
  449.51 +                              
  449.52 +class DomainInfo(object):
  449.53 +
  449.54 +    domain_name = ''
  449.55 +    netbios_name = ''
  449.56 +    domain_pat = re.compile('\s*workgroup\s*=\s*(?P<domain>[\w_-]+)', re.I)
  449.57 +    netbios_name_pat = re.compile('\s*netbios name\s*=\s*(?P<name>[\w_-]+)', re.I)
  449.58 +
  449.59 +    def __init__(self, conf=None):
  449.60 +
  449.61 +        if conf:
  449.62 +            for line in conf.split('\n'):
  449.63 +                self.parse_line(line)
  449.64 +        else:
  449.65 +            f = open(settings.SAMBA_FILE)
  449.66 +            for line in f:
  449.67 +                self.parse_line(line)
  449.68 +            f.close()
  449.69 +
  449.70 +
  449.71 +    def parse_line(self, line):
  449.72 +        m = self.domain_pat.match(line) 
  449.73 +        if m:
  449.74 +            self.domain_name = m.group('domain')
  449.75 +
  449.76 +        m = self.netbios_name_pat.match(line) 
  449.77 +        if m:
  449.78 +            self.netbios_name = m.group('name')
  449.79 +                
  449.80 +if __name__ == '__main__':
  449.81 +
  449.82 +    d=DomainInfo(__doc__)
  449.83 +    vars(d)
   450.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   450.2 +++ b/web/samba/templates/samba/samba_form.mako	Mon Apr 26 11:16:23 2010 +0200
   450.3 @@ -0,0 +1,31 @@
   450.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   450.5 +
   450.6 +
   450.7 +<h1> Configurazione Samba</h1>
   450.8 +
   450.9 +<%def name="layout()">
  450.10 +
  450.11 +domain_name
  450.12 +netbios_name
  450.13 +root_password
  450.14 +password
  450.15 +--
  450.16 +s=salva
  450.17 +
  450.18 +</%def>
  450.19 +
  450.20 +${jun.show_form_errors(form)}
  450.21 +${forms.mako_create_nform(context, layout, form, style='-')}
  450.22 +
  450.23 +
  450.24 +<style>
  450.25 +table.data {
  450.26 +   margin-top: 30px
  450.27 +}
  450.28 +table.data th {
  450.29 +   text-align: left
  450.30 +}
  450.31 +.data td {
  450.32 +   padding-right: 30px
  450.33 +}
  450.34 +</style>
   451.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   451.2 +++ b/web/samba/templates/samba/show_conf.mako	Mon Apr 26 11:16:23 2010 +0200
   451.3 @@ -0,0 +1,96 @@
   451.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   451.5 +
   451.6 +<div id="tabs">
   451.7 +  <ul > 
   451.8 +     %for sez in ('dominio',  'stampanti', 'shares' ):
   451.9 +           <li><a href="#${sez}">${sez}</a></li>
  451.10 +     %endfor
  451.11 +  </ul>
  451.12 +  
  451.13 +
  451.14 +
  451.15 +  <div id="dominio" class="tab">
  451.16 +
  451.17 +    <table class="data">
  451.18 +    <tr>
  451.19 +      <th><b>Dominio:</b></th>  <td>${domain.domain_name}</td>
  451.20 +    </tr>
  451.21 +    <tr>
  451.22 +      <th><b>Netbios Name:</b></th>  <td>${domain.netbios_name}</td>
  451.23 +    </tr>
  451.24 +    <tr>
  451.25 +      <th><b>Password:</b></th>  <td> ... ssht...</td>
  451.26 +    </tr>
  451.27 +    </table>
  451.28 +    <div class="azioni">
  451.29 +      ${jun.popup_link("/samba/conf/save/?popup", txt='Modifica la configurazione', icon='edit')}
  451.30 +    </div> <!-- azioni  -->
  451.31 +  </div> <!-- dominio -->
  451.32 +
  451.33 +  <div id="stampanti" class="tab">
  451.34 +      
  451.35 +      Si consiglia la lettura del laboratorio netkit sulla configurazione
  451.36 +      delle <a href="/docs/allegati/netkit/stampanti/README.html">stampanti</a>
  451.37 +
  451.38 +      % if isinstance(printers, Exception):
  451.39 +          <div class="ui-state-error" style="margin: 15px; padding: 10px">
  451.40 +             Il seguente errore non influenza il funzionamento del sistema ma
  451.41 +             quello della interfaccia web!<br>
  451.42 +             ${printers.message}
  451.43 +          </div>
  451.44 +      % else:
  451.45 +	 <table>
  451.46 +	   <tr>
  451.47 +	      <th>name</th> <th>driver</th> <th>printername</th> <th>comment</th>
  451.48 +	   </tr>
  451.49 +	  % for p in printers:
  451.50 +	   <tr>
  451.51 +	      <td>${p.sharename}</td> <td>${p.drivername}</td> <td>${p.printername}</td> <td>${p.comment}</td>
  451.52 +	   </tr>
  451.53 +	  % endfor            
  451.54 +	 </table>
  451.55 +      % endif
  451.56 +  </div>
  451.57 +
  451.58 +  <div id="shares" class="tab">
  451.59 +      <h3>shares definite</h3>
  451.60 +      Le seguenti shares sono definite in /etc/samba/smb.conf o file inclusi
  451.61 +      (es.: /etc/isi/samba/smb_*):
  451.62 +
  451.63 +     <table>
  451.64 +     <tr>
  451.65 +       <th>share</th>  <th>path</th>
  451.66 +     </tr>
  451.67 +     % for share, path in shares:
  451.68 +     <tr>
  451.69 +       <td>${share}</td>  <td>${path}</td>
  451.70 +     </tr>
  451.71 +     % endfor
  451.72 +     </table>
  451.73 +       
  451.74 +  </div>
  451.75 +
  451.76 +</div> <!-- tabs -->
  451.77 +
  451.78 +####  script & style
  451.79 +<script type="text/javascript">
  451.80 +$(document).ready(function () {
  451.81 +
  451.82 +  $('#tabs').tabs();
  451.83 +  $('td.title').cluetip({splitTitle: '|'});
  451.84 +##  $('td.title').cluetip({splitTitle: '|', sticky: true, closePosition: 'title', arrows: true });
  451.85 +
  451.86 +});
  451.87 +</script>
  451.88 +
  451.89 +<style type="text/css">
  451.90 +table.data {
  451.91 +   margin-top: 30px
  451.92 +}
  451.93 +table.data th {
  451.94 +   text-align: left
  451.95 +}
  451.96 +.data td {
  451.97 +   padding-left: 30px
  451.98 +}
  451.99 +</style>
   452.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   452.2 +++ b/web/samba/tests.py	Mon Apr 26 11:16:23 2010 +0200
   452.3 @@ -0,0 +1,23 @@
   452.4 +"""
   452.5 +This file demonstrates two different styles of tests (one doctest and one
   452.6 +unittest). These will both pass when you run "manage.py test".
   452.7 +
   452.8 +Replace these with more appropriate tests for your application.
   452.9 +"""
  452.10 +
  452.11 +from django.test import TestCase
  452.12 +
  452.13 +class SimpleTest(TestCase):
  452.14 +    def test_basic_addition(self):
  452.15 +        """
  452.16 +        Tests that 1 + 1 always equals 2.
  452.17 +        """
  452.18 +        self.failUnlessEqual(1 + 1, 2)
  452.19 +
  452.20 +__test__ = {"doctest": """
  452.21 +Another way to test that 1 + 1 is equal to 2.
  452.22 +
  452.23 +>>> 1 + 1 == 2
  452.24 +True
  452.25 +"""}
  452.26 +
   453.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   453.2 +++ b/web/samba/urls.py	Mon Apr 26 11:16:23 2010 +0200
   453.3 @@ -0,0 +1,6 @@
   453.4 +from django.conf.urls.defaults import *
   453.5 +
   453.6 +urlpatterns = patterns('isiweb.samba.views',
   453.7 +    (r'^conf/save/$', 'save_conf'),
   453.8 +    (r'^conf/$', 'show_conf'),
   453.9 +)
   454.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   454.2 +++ b/web/samba/views.py	Mon Apr 26 11:16:23 2010 +0200
   454.3 @@ -0,0 +1,48 @@
   454.4 +from django.template import RequestContext
   454.5 +from django.http import HttpResponseRedirect
   454.6 +from django.conf import settings
   454.7 +from vov.views.decorators import login_required
   454.8 +from django.views import generic
   454.9 +from vov.template import mako_loader
  454.10 +from isi import exc
  454.11 +from isi.conf import logon, misc
  454.12 +from django.contrib import messages
  454.13 +from samba_form import SambaForm, DomainInfo
  454.14 +
  454.15 +class Domain(object): pass
  454.16 +
  454.17 +@login_required
  454.18 +def show_conf(request):
  454.19 +
  454.20 +    try:
  454.21 +        printers = misc.get_printers_with_rpcclient()
  454.22 +    except (exc.ExecuteError, exc.AuthenticationError), e:
  454.23 +        printers = e
  454.24 +
  454.25 +    context = {
  454.26 +        'domain'  : DomainInfo(),
  454.27 +        'shares'  : misc.get_shares(all=True, descr=False),
  454.28 +        'printers': printers,
  454.29 +        }
  454.30 +    return mako_loader.render_to_response('samba/show_conf.mako', context,
  454.31 +                                   context_instance=RequestContext(request),)
  454.32 +
  454.33 +@login_required
  454.34 +def save_conf(request):
  454.35 +    
  454.36 +    if request.method == 'POST': # If the form has been submitted...
  454.37 +        form = SambaForm(request.POST) # A form bound to the POST data
  454.38 +        if form.is_valid(): # All validation rules pass
  454.39 +            form.save()
  454.40 +            messages.success(request, 'Dominio impostato:<br>%s' % form.message)
  454.41 +            return HttpResponseRedirect('/views/close_popup/') 
  454.42 +    else:
  454.43 +        domain = DomainInfo()
  454.44 +        print vars(domain)
  454.45 +        form = SambaForm(initial=vars(domain)) # An unbound form
  454.46 +
  454.47 +    context = {'form' : form,
  454.48 +               }
  454.49 +
  454.50 +    return mako_loader.render_to_response('samba/samba_form.mako', context,
  454.51 +                                   context_instance=RequestContext(request),)
   455.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   455.2 +++ b/web/settings.py	Mon Apr 26 11:16:23 2010 +0200
   455.3 @@ -0,0 +1,127 @@
   455.4 +import os
   455.5 +import sys
   455.6 +import vov
   455.7 +from vov.functions.conf import *
   455.8 +
   455.9 +CWD = os.path.dirname(__file__)
  455.10 +set_cwd(CWD)
  455.11 +from vov.conf.settings import *
  455.12 +from local_settings import *
  455.13 +
  455.14 +# Django settings for isiweb project.
  455.15 +
  455.16 +DEBUG = True
  455.17 +TEMPLATE_DEBUG = DEBUG
  455.18 +PRJ_DIR = CWD
  455.19 +CWD = PRJ_DIR
  455.20 +ADMINS = (
  455.21 +    # ('Your Name', '[email protected]'),
  455.22 +)
  455.23 +
  455.24 +MANAGERS = ADMINS
  455.25 +
  455.26 +DATABASES = {
  455.27 +    'default': {
  455.28 +        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
  455.29 +        'NAME': CWD + '/isi.db',                      # Or path to database file if using sqlite3.
  455.30 +        'USER': '',                      # Not used with sqlite3.
  455.31 +        'PASSWORD': '',                  # Not used with sqlite3.
  455.32 +        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
  455.33 +        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
  455.34 +    }
  455.35 +}
  455.36 +AUTHENTICATION_BACKENDS = ('isiweb.ldap-auth.LDAPBackend',)
  455.37 +
  455.38 +# Local time zone for this installation. Choices can be found here:
  455.39 +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
  455.40 +# although not all choices may be available on all operating systems.
  455.41 +# If running in a Windows environment this must be set to the same as your
  455.42 +# system time zone.
  455.43 +TIME_ZONE = 'Europe/Rome'
  455.44 +
  455.45 +# Language code for this installation. All choices can be found here:
  455.46 +# http://www.i18nguy.com/unicode/language-identifiers.html
  455.47 +LANGUAGE_CODE = 'it_it'
  455.48 +
  455.49 +SITE_ID = 1
  455.50 +
  455.51 +# If you set this to False, Django will make some optimizations so as not
  455.52 +# to load the internationalization machinery.
  455.53 +USE_I18N = True
  455.54 +
  455.55 +# Absolute path to the directory that holds media.
  455.56 +# Example: "/home/media/media.lawrence.com/"
  455.57 +MEDIA_ROOT = PRJ_DIR + '/static'
  455.58 +
  455.59 +# URL that handles the media served from MEDIA_ROOT. Make sure to use a
  455.60 +# trailing slash if there is a path component (optional in other cases).
  455.61 +# Examples: "http://media.lawrence.com", "http://example.com/media/"
  455.62 +MEDIA_URL = '/static'
  455.63 +
  455.64 +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
  455.65 +# trailing slash.
  455.66 +# Examples: "http://foo.com/media/", "/media/".
  455.67 +ADMIN_MEDIA_PREFIX = '/media/'
  455.68 +
  455.69 +# Make this unique, and don't share it with anybody.
  455.70 +SECRET_KEY = 'oguf-tkekbeatknmy=3m5v!w9@rr(xl5)%l09+m+=lpndx0&2w'
  455.71 +
  455.72 +# List of callables that know how to import templates from various sources.
  455.73 +# TEMPLATE_LOADERS = (
  455.74 +#     'django.template.loaders.filesystem.load_template_source',
  455.75 +#     'django.template.loaders.app_directories.load_template_source',
  455.76 +#     'django.template.loaders.filesystem.Loader',
  455.77 +#     'django.template.loaders.app_directories.Loader',
  455.78 +# #     'django.template.loaders.eggs.Loader',
  455.79 +# )
  455.80 +
  455.81 +# MIDDLEWARE_CLASSES = (
  455.82 +#     'django.middleware.common.CommonMiddleware',
  455.83 +#     'django.contrib.sessions.middleware.SessionMiddleware',
  455.84 +#     'django.middleware.csrf.CsrfViewMiddleware',
  455.85 +#     'django.contrib.auth.middleware.AuthenticationMiddleware',
  455.86 +#     'django.contrib.messages.middleware.MessageMiddleware',
  455.87 +# )
  455.88 +
  455.89 +ROOT_URLCONF = 'isiweb.urls'
  455.90 +
  455.91 +
  455.92 +INSTALLED_APPS = (
  455.93 +    'django.contrib.auth',
  455.94 +    'django.contrib.contenttypes',
  455.95 +    'django.contrib.sessions',
  455.96 +    'django.contrib.sites',
  455.97 +    'django.contrib.admin',
  455.98 +    'django.contrib.messages',
  455.99 +    'vov.sys',
 455.100 +    'vov.registration',
 455.101 +    'isiweb.logon',
 455.102 +    'isiweb.users',
 455.103 +    'isiweb.samba',
 455.104 +    'isiweb.dnsmasq',
 455.105 +    'isiweb.navigazione',
 455.106 +)
 455.107 +
 455.108 +TEMPLATE_CONTEXT_PROCESSORS = (
 455.109 +    'django.core.context_processors.auth',
 455.110 +    'django.core.context_processors.debug',
 455.111 +    'django.core.context_processors.i18n',
 455.112 +    'django.core.context_processors.request',
 455.113 +)
 455.114 +
 455.115 +
 455.116 +DATE_FORMAT="d/m/Y"
 455.117 +TIME_FORMAT="G:i"
 455.118 +DATETIME_FORMAT="d/m/Y G:i"
 455.119 +
 455.120 +
 455.121 +
 455.122 +MAKO_FILTERS = None
 455.123 +
 455.124 +LOGON_FILE = '/etc/isi/logon.conf'
 455.125 +SAMBA_FILE = '/etc/samba/smb.conf'
 455.126 +DNSMASQ_CONF = '/etc/dnsmasq.conf'
 455.127 +HOSTS_CONF = '/etc/hosts'
 455.128 +MAC_CONF = '/etc/isi/dnsmasq/hosts.mac'
 455.129 +LEASES_FILE = '/var/lib/misc/dnsmasq.leases'
 455.130 +BOOT_CONF = '/etc/isi/dnsmasq/boot'
   456.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   456.2 +++ b/web/static/css/bt.css	Mon Apr 26 11:16:23 2010 +0200
   456.3 @@ -0,0 +1,23 @@
   456.4 +.tooltip {
   456.5 +color:#000000;
   456.6 +font-family:Arial,sans-serif;
   456.7 +font-size:11px;
   456.8 +font-size-adjust:none;
   456.9 +font-stretch:normal;
  456.10 +font-style:normal;
  456.11 +font-variant:normal;
  456.12 +font-weight:lighter;
  456.13 +line-height:1.3;
  456.14 +text-align:center;
  456.15 +text-decoration:none;
  456.16 +width:200px;
  456.17 +}
  456.18 +.tooltip span.top {
  456.19 +background:transparent url(/static/img/bt.gif) no-repeat scroll center top;
  456.20 +padding:30px 8px 0pt;
  456.21 +}
  456.22 +.tooltip b.bottom {
  456.23 +background:transparent url(/static/img/bt.gif) no-repeat scroll center bottom;
  456.24 +color:#548912;
  456.25 +padding:3px 8px 15px;
  456.26 +}
  456.27 \ No newline at end of file
   457.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   457.2 +++ b/web/static/css/cluetip.css	Mon Apr 26 11:16:23 2010 +0200
   457.3 @@ -0,0 +1,211 @@
   457.4 +/* global */
   457.5 +#cluetip-close img {
   457.6 +    border: 0
   457.7 +    }
   457.8 +#cluetip-title {
   457.9 +    overflow: hidden
  457.10 +    }
  457.11 +#cluetip-title #cluetip-close {
  457.12 +    float: right;
  457.13 +    position: relative
  457.14 +    }
  457.15 +#cluetip-waitimage {
  457.16 +    width: 43px;
  457.17 +    height: 11px;
  457.18 +    position: absolute;
  457.19 +    background-image: url(images/wait.gif)
  457.20 +    }
  457.21 +.cluetip-arrows {
  457.22 +    display: none;
  457.23 +    position: absolute;
  457.24 +    top: 0;
  457.25 +    left: -11px;
  457.26 +    height: 22px;
  457.27 +    width: 11px;
  457.28 +    background-repeat: no-repeat;
  457.29 +    background-position: 0 0
  457.30 +    }
  457.31 +#cluetip-extra {
  457.32 +    display: none
  457.33 +    }
  457.34 +/***************************************
  457.35 +   =cluetipClass: 'default' 
  457.36 +-------------------------------------- */
  457.37 +.cluetip-default {
  457.38 +    background-color: #ddf1c1
  457.39 +    }
  457.40 +.cluetip-default #cluetip-outer {
  457.41 +    position: relative;
  457.42 +    margin: 0;
  457.43 +    background-color: #ddf1c1
  457.44 +    }
  457.45 +.cluetip-default h3#cluetip-title {
  457.46 +    margin: 0 0 5px;
  457.47 +    padding: 8px 10px 4px;
  457.48 +    font-size: 1.1em;
  457.49 +    font-weight: normal;
  457.50 +    background-color: #437353;
  457.51 +    color: #fff
  457.52 +    }
  457.53 +.cluetip-default #cluetip-title a {
  457.54 +    color: #ddf1c1;
  457.55 +    font-size: 0.95em
  457.56 +    }
  457.57 +.cluetip-default #cluetip-inner {
  457.58 +    padding: 10px
  457.59 +    }
  457.60 +.cluetip-default div#cluetip-close {
  457.61 +    text-align: right;
  457.62 +    margin: 0 5px 5px;
  457.63 +    color: #900
  457.64 +    }
  457.65 +/* default arrows */
  457.66 +.clue-right-default .cluetip-arrows {
  457.67 +    background-image: url(images/darrowleft.gif)
  457.68 +    }
  457.69 +.clue-left-default .cluetip-arrows {
  457.70 +    background-image: url(images/darrowright.gif);
  457.71 +    left: 100%;
  457.72 +    margin-right: -11px
  457.73 +    }
  457.74 +.clue-top-default .cluetip-arrows {
  457.75 +    background-image: url(images/darrowdown.gif);
  457.76 +    top: 100%;
  457.77 +    left: 50%;
  457.78 +    margin-left: -11px;
  457.79 +    height: 11px;
  457.80 +    width: 22px
  457.81 +    }
  457.82 +.clue-bottom-default .cluetip-arrows {
  457.83 +    background-image: url(images/darrowup.gif);
  457.84 +    top: -11px;
  457.85 +    left: 50%;
  457.86 +    margin-left: -11px;
  457.87 +    height: 11px;
  457.88 +    width: 22px
  457.89 +    }
  457.90 +/***************************************
  457.91 +   =cluetipClass: 'jtip'
  457.92 +-------------------------------------- */
  457.93 +.cluetip-jtip {
  457.94 +    background-color: transparent
  457.95 +    }
  457.96 +.cluetip-jtip #cluetip-outer {
  457.97 +    border: 2px solid #ccc;
  457.98 +    position: relative;
  457.99 +    background-color: #fff
 457.100 +    }
 457.101 +.cluetip-jtip h3#cluetip-title {
 457.102 +    margin: 0 0 5px;
 457.103 +    padding: 2px 5px;
 457.104 +    font-size: 16px;
 457.105 +    font-weight: normal;
 457.106 +    background-color: #ccc;
 457.107 +    color: #333
 457.108 +    }
 457.109 +.cluetip-jtip #cluetip-inner {
 457.110 +    padding: 0 5px 5px;
 457.111 +    display: inline-block
 457.112 +    }
 457.113 +.cluetip-jtip div#cluetip-close {
 457.114 +    text-align: right;
 457.115 +    margin: 0 5px 5px;
 457.116 +    color: #900
 457.117 +    }
 457.118 +/* jtip arrows */
 457.119 +.clue-right-jtip .cluetip-arrows {
 457.120 +    background-image: url(images/arrowleft.gif)
 457.121 +    }
 457.122 +.clue-left-jtip .cluetip-arrows {
 457.123 +    background-image: url(images/arrowright.gif);
 457.124 +    left: 100%;
 457.125 +    margin-right: -11px
 457.126 +    }
 457.127 +.clue-top-jtip .cluetip-arrows {
 457.128 +    background-image: url(images/arrowdown.gif);
 457.129 +    top: 100%;
 457.130 +    left: 50%;
 457.131 +    margin-left: -11px;
 457.132 +    height: 11px;
 457.133 +    width: 22px
 457.134 +    }
 457.135 +.clue-bottom-jtip .cluetip-arrows {
 457.136 +    background-image: url(images/arrowup.gif);
 457.137 +    top: -11px;
 457.138 +    left: 50%;
 457.139 +    margin-left: -11px;
 457.140 +    height: 11px;
 457.141 +    width: 22px
 457.142 +    }
 457.143 +/***************************************
 457.144 +   =cluetipClass: 'rounded'
 457.145 +-------------------------------------- */
 457.146 +.cluetip-rounded {
 457.147 +    background: transparent url(images/bl.gif) no-repeat 0 100%;
 457.148 +    margin-top: 10px;
 457.149 +    margin-left: 12px
 457.150 +    }
 457.151 +.cluetip-rounded #cluetip-outer {
 457.152 +    background: transparent url(images/tl.gif) no-repeat 0 0;
 457.153 +    margin-top: -12px
 457.154 +    }
 457.155 +.cluetip-rounded #cluetip-title {
 457.156 +    background-color: transparent;
 457.157 +    padding: 12px 12px 0;
 457.158 +    margin: 0 -12px 0 0;
 457.159 +    position: relative
 457.160 +    }
 457.161 +.cluetip-rounded #cluetip-extra {
 457.162 +    position: absolute;
 457.163 +    display: block;
 457.164 +    background: transparent url(images/tr.gif) no-repeat 100% 0;
 457.165 +    top: 0;
 457.166 +    right: 0;
 457.167 +    width: 12px;
 457.168 +    height: 30px;
 457.169 +    margin: -12px -12px 0 0
 457.170 +    }
 457.171 +.cluetip-rounded #cluetip-inner {
 457.172 +    background: url(images/br.gif) no-repeat 100% 100%;
 457.173 +    padding: 5px 12px 12px;
 457.174 +    margin: -18px -12px 0 0;
 457.175 +    position: relative
 457.176 +    }
 457.177 +.cluetip-rounded div#cluetip-close {
 457.178 +    text-align: right;
 457.179 +    margin: 0 5px 5px;
 457.180 +    color: #009;
 457.181 +    background: transparent
 457.182 +    }
 457.183 +.cluetip-rounded div#cluetip-close a {
 457.184 +    color: #777
 457.185 +    }
 457.186 +/* rounded arrows */
 457.187 +.clue-right-rounded .cluetip-arrows {
 457.188 +    background-image: url(images/rarrowleft.gif)
 457.189 +    }
 457.190 +.clue-left-rounded .cluetip-arrows {
 457.191 +    background-image: url(images/rarrowright.gif);
 457.192 +    left: 100%;
 457.193 +    margin-left: 12px
 457.194 +    }
 457.195 +.clue-top-rounded .cluetip-arrows {
 457.196 +    background-image: url(images/rarrowdown.gif);
 457.197 +    top: 100%;
 457.198 +    left: 50%;
 457.199 +    margin-left: -11px;
 457.200 +    height: 11px;
 457.201 +    width: 22px
 457.202 +    }
 457.203 +.clue-bottom-rounded .cluetip-arrows {
 457.204 +    background-image: url(images/rarrowup.gif);
 457.205 +    top: -23px;
 457.206 +    left: 50%;
 457.207 +    margin-left: -11px;
 457.208 +    height: 11px;
 457.209 +    width: 22px
 457.210 +    }
 457.211 +/* stupid IE6 HasLayout hack */
 457.212 +.cluetip-rounded #cluetip-title, .cluetip-rounded #cluetip-inner {
 457.213 +    zoom: 1
 457.214 +    }
   458.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   458.2 +++ b/web/static/css/demo_page.css	Mon Apr 26 11:16:23 2010 +0200
   458.3 @@ -0,0 +1,93 @@
   458.4 +
   458.5 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   458.6 + * General page setup
   458.7 + */
   458.8 +#dt_example {
   458.9 +	font: 80%/1.45em "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
  458.10 +	margin: 0;
  458.11 +	padding: 0;
  458.12 +	color: #333;
  458.13 +	background-color: #fff;
  458.14 +}
  458.15 +
  458.16 +
  458.17 +#dt_example #container {
  458.18 +	width: 800px;
  458.19 +	margin: 30px auto;
  458.20 +	padding: 0;
  458.21 +}
  458.22 +
  458.23 +
  458.24 +#dt_example #footer {
  458.25 +	margin: 50px auto 0 auto;
  458.26 +	padding: 0;
  458.27 +}
  458.28 +
  458.29 +#dt_example #demo {
  458.30 +	margin: 30px auto 0 auto;
  458.31 +}
  458.32 +
  458.33 +#dt_example .demo_jui {
  458.34 +	margin: 30px auto 0 auto;
  458.35 +}
  458.36 +
  458.37 +#dt_example .big {
  458.38 +	font-size: 1.3em;
  458.39 +	font-weight: bold;
  458.40 +	line-height: 1.6em;
  458.41 +	color: #4E6CA3;
  458.42 +}
  458.43 +
  458.44 +#dt_example .spacer {
  458.45 +	height: 20px;
  458.46 +	clear: both;
  458.47 +}
  458.48 +
  458.49 +#dt_example .clear {
  458.50 +	clear: both;
  458.51 +}
  458.52 +
  458.53 +#dt_example pre {
  458.54 +	padding: 15px;
  458.55 +	background-color: #F5F5F5;
  458.56 +	border: 1px solid #CCCCCC;
  458.57 +}
  458.58 +
  458.59 +#dt_example h1 {
  458.60 +	margin-top: 2em;
  458.61 +	font-size: 1.3em;
  458.62 +	font-weight: normal;
  458.63 +	line-height: 1.6em;
  458.64 +	color: #4E6CA3;
  458.65 +	border-bottom: 1px solid #B0BED9;
  458.66 +	clear: both;
  458.67 +}
  458.68 +
  458.69 +#dt_example h2 {
  458.70 +	font-size: 1.2em;
  458.71 +	font-weight: normal;
  458.72 +	line-height: 1.6em;
  458.73 +	color: #4E6CA3;
  458.74 +	clear: both;
  458.75 +}
  458.76 +
  458.77 +#dt_example a {
  458.78 +	color: #0063DC;
  458.79 +	text-decoration: none;
  458.80 +}
  458.81 +
  458.82 +#dt_example a:hover {
  458.83 +	text-decoration: underline;
  458.84 +}
  458.85 +
  458.86 +#dt_example ul {
  458.87 +	color: #B0BED9;
  458.88 +}
  458.89 +
  458.90 +.css_right {
  458.91 +	float: right;
  458.92 +}
  458.93 +
  458.94 +.css_left {
  458.95 +	float: left;
  458.96 +}
  458.97 \ No newline at end of file
   459.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   459.2 +++ b/web/static/css/demo_table.css	Mon Apr 26 11:16:23 2010 +0200
   459.3 @@ -0,0 +1,493 @@
   459.4 +/*
   459.5 + *  File:         demo_table.css
   459.6 + *  CVS:          $Id$
   459.7 + *  Description:  CSS descriptions for DataTables demo pages
   459.8 + *  Author:       Allan Jardine
   459.9 + *  Created:      Tue May 12 06:47:22 BST 2009
  459.10 + *  Modified:     $Date$ by $Author$
  459.11 + *  Language:     CSS
  459.12 + *  Project:      DataTables
  459.13 + *
  459.14 + *  Copyright 2009 Allan Jardine. All Rights Reserved.
  459.15 + *
  459.16 + * ***************************************************************************
  459.17 + * DESCRIPTION
  459.18 + *
  459.19 + * The styles given here are suitable for the demos that are used with the standard DataTables
  459.20 + * distribution (see www.datatables.net). You will most likely wish to modify these styles to
  459.21 + * meet the layout requirements of your site.
  459.22 + *
  459.23 + * Common issues:
  459.24 + *   'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is
  459.25 + *     no conflict between the two pagination types. If you want to use full_numbers pagination
  459.26 + *     ensure that you either have "example_alt_pagination" as a body class name, or better yet,
  459.27 + *     modify that selector.
  459.28 + *   Note that the path used for Images is relative. All images are by default located in
  459.29 + *     ../images/ - relative to this CSS file.
  459.30 + */
  459.31 +
  459.32 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  459.33 + * DataTables features
  459.34 + */
  459.35 +
  459.36 +.dataTables_wrapper {
  459.37 +	position: relative;
  459.38 +	min-height: 302px;
  459.39 +	clear: both;
  459.40 +	_height: 302px;
  459.41 +	zoom: 1; /* Feeling sorry for IE */
  459.42 +}
  459.43 +
  459.44 +.dataTables_processing {
  459.45 +	position: absolute;
  459.46 +	top: 50%;
  459.47 +	left: 50%;
  459.48 +	width: 250px;
  459.49 +	height: 30px;
  459.50 +	margin-left: -125px;
  459.51 +	margin-top: -15px;
  459.52 +	padding: 14px 0 2px 0;
  459.53 +	border: 1px solid #ddd;
  459.54 +	text-align: center;
  459.55 +	color: #999;
  459.56 +	font-size: 14px;
  459.57 +	background-color: white;
  459.58 +}
  459.59 +
  459.60 +.dataTables_length {
  459.61 +	width: 40%;
  459.62 +	float: left;
  459.63 +}
  459.64 +
  459.65 +.dataTables_filter {
  459.66 +	width: 50%;
  459.67 +	float: right;
  459.68 +	text-align: right;
  459.69 +}
  459.70 +
  459.71 +.dataTables_info {
  459.72 +	width: 60%;
  459.73 +	float: left;
  459.74 +}
  459.75 +
  459.76 +.dataTables_paginate {
  459.77 +	width: 44px;
  459.78 +	* width: 50px;
  459.79 +	float: right;
  459.80 +	text-align: right;
  459.81 +}
  459.82 +
  459.83 +/* Pagination nested */
  459.84 +.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next {
  459.85 +	height: 19px;
  459.86 +	width: 19px;
  459.87 +	margin-left: 3px;
  459.88 +	float: left;
  459.89 +}
  459.90 +
  459.91 +.paginate_disabled_previous {
  459.92 +	background-image: url('../images/back_disabled.jpg');
  459.93 +}
  459.94 +
  459.95 +.paginate_enabled_previous {
  459.96 +	background-image: url('../images/back_enabled.jpg');
  459.97 +}
  459.98 +
  459.99 +.paginate_disabled_next {
 459.100 +	background-image: url('../images/forward_disabled.jpg');
 459.101 +}
 459.102 +
 459.103 +.paginate_enabled_next {
 459.104 +	background-image: url('../images/forward_enabled.jpg');
 459.105 +}
 459.106 +
 459.107 +
 459.108 +
 459.109 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 459.110 + * DataTables display
 459.111 + */
 459.112 +table.display {
 459.113 +	margin: 0 auto;
 459.114 +	width: 100%;
 459.115 +	clear: both;
 459.116 +}
 459.117 +
 459.118 +table.display thead th {
 459.119 +	padding: 3px 18px 3px 10px;
 459.120 +	border-bottom: 1px solid black;
 459.121 +	font-weight: bold;
 459.122 +	cursor: pointer;
 459.123 +	* cursor: hand;
 459.124 +}
 459.125 +
 459.126 +table.display tfoot th {
 459.127 +	padding: 3px 10px;
 459.128 +	border-top: 1px solid black;
 459.129 +	font-weight: bold;
 459.130 +}
 459.131 +
 459.132 +table.display tr.heading2 td {
 459.133 +	border-bottom: 1px solid #aaa;
 459.134 +}
 459.135 +
 459.136 +table.display td {
 459.137 +	padding: 3px 10px;
 459.138 +}
 459.139 +
 459.140 +table.display td.center {
 459.141 +	text-align: center;
 459.142 +}
 459.143 +
 459.144 +
 459.145 +
 459.146 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 459.147 + * DataTables sorting
 459.148 + */
 459.149 +
 459.150 +.sorting_asc {
 459.151 +	background: url('../images/sort_asc.png') no-repeat center right;
 459.152 +}
 459.153 +
 459.154 +.sorting_desc {
 459.155 +	background: url('../images/sort_desc.png') no-repeat center right;
 459.156 +}
 459.157 +
 459.158 +.sorting {
 459.159 +	background: url('../images/sort_both.png') no-repeat center right;
 459.160 +}
 459.161 +
 459.162 +.sorting_asc_disabled {
 459.163 +	background: url('../images/sort_asc_disabled.png') no-repeat center right;
 459.164 +}
 459.165 +
 459.166 +.sorting_desc_disabled {
 459.167 +	background: url('../images/sort_desc_disabled.png') no-repeat center right;
 459.168 +}
 459.169 +
 459.170 +
 459.171 +
 459.172 +
 459.173 +
 459.174 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 459.175 + * DataTables row classes
 459.176 + */
 459.177 +table.display tr.odd.gradeA {
 459.178 +	background-color: #ddffdd;
 459.179 +}
 459.180 +
 459.181 +table.display tr.even.gradeA {
 459.182 +	background-color: #eeffee;
 459.183 +}
 459.184 +
 459.185 +table.display tr.odd.gradeA {
 459.186 +	background-color: #ddffdd;
 459.187 +}
 459.188 +
 459.189 +table.display tr.even.gradeA {
 459.190 +	background-color: #eeffee;
 459.191 +}
 459.192 +
 459.193 +table.display tr.odd.gradeC {
 459.194 +	background-color: #ddddff;
 459.195 +}
 459.196 +
 459.197 +table.display tr.even.gradeC {
 459.198 +	background-color: #eeeeff;
 459.199 +}
 459.200 +
 459.201 +table.display tr.odd.gradeX {
 459.202 +	background-color: #ffdddd;
 459.203 +}
 459.204 +
 459.205 +table.display tr.even.gradeX {
 459.206 +	background-color: #ffeeee;
 459.207 +}
 459.208 +
 459.209 +table.display tr.odd.gradeU {
 459.210 +	background-color: #ddd;
 459.211 +}
 459.212 +
 459.213 +table.display tr.even.gradeU {
 459.214 +	background-color: #eee;
 459.215 +}
 459.216 +
 459.217 +
 459.218 +tr.odd {
 459.219 +	background-color: #E2E4FF;
 459.220 +}
 459.221 +
 459.222 +tr.even {
 459.223 +	background-color: white;
 459.224 +}
 459.225 +
 459.226 +
 459.227 +
 459.228 +
 459.229 +
 459.230 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 459.231 + * Misc
 459.232 + */
 459.233 +.top, .bottom {
 459.234 +	padding: 15px;
 459.235 +	background-color: #F5F5F5;
 459.236 +	border: 1px solid #CCCCCC;
 459.237 +}
 459.238 +
 459.239 +.top .dataTables_info {
 459.240 +	float: none;
 459.241 +}
 459.242 +
 459.243 +.clear {
 459.244 +	clear: both;
 459.245 +}
 459.246 +
 459.247 +.dataTables_empty {
 459.248 +	text-align: center;
 459.249 +}
 459.250 +
 459.251 +tfoot input {
 459.252 +	margin: 0.5em 0;
 459.253 +	width: 100%;
 459.254 +	color: #444;
 459.255 +}
 459.256 +
 459.257 +tfoot input.search_init {
 459.258 +	color: #999;
 459.259 +}
 459.260 +
 459.261 +td.group {
 459.262 +	background-color: #d1cfd0;
 459.263 +	border-bottom: 2px solid #A19B9E;
 459.264 +	border-top: 2px solid #A19B9E;
 459.265 +}
 459.266 +
 459.267 +td.details {
 459.268 +	background-color: #d1cfd0;
 459.269 +	border: 2px solid #A19B9E;
 459.270 +}
 459.271 +
 459.272 +
 459.273 +.example_alt_pagination div.dataTables_info {
 459.274 +	width: 40%;
 459.275 +}
 459.276 +
 459.277 +.paging_full_numbers {
 459.278 +	width: 400px;
 459.279 +	height: 22px;
 459.280 +	line-height: 22px;
 459.281 +}
 459.282 +
 459.283 +.paging_full_numbers span.paginate_button,
 459.284 + 	.paging_full_numbers span.paginate_active {
 459.285 +	border: 1px solid #aaa;
 459.286 +	-webkit-border-radius: 5px;
 459.287 +	-moz-border-radius: 5px;
 459.288 +	padding: 2px 5px;
 459.289 +	margin: 0 3px;
 459.290 +	cursor: pointer;
 459.291 +	*cursor: hand;
 459.292 +}
 459.293 +
 459.294 +.paging_full_numbers span.paginate_button {
 459.295 +	background-color: #ddd;
 459.296 +}
 459.297 +
 459.298 +.paging_full_numbers span.paginate_button:hover {
 459.299 +	background-color: #ccc;
 459.300 +}
 459.301 +
 459.302 +.paging_full_numbers span.paginate_active {
 459.303 +	background-color: #99B3FF;
 459.304 +}
 459.305 +
 459.306 +table.display tr.even.row_selected td {
 459.307 +	background-color: #B0BED9;
 459.308 +}
 459.309 +
 459.310 +table.display tr.odd.row_selected td {
 459.311 +	background-color: #9FAFD1;
 459.312 +}
 459.313 +
 459.314 +
 459.315 +/*
 459.316 + * Sorting classes for columns
 459.317 + */
 459.318 +/* For the standard odd/even */
 459.319 +tr.odd td.sorting_1 {
 459.320 +	background-color: #D3D6FF;
 459.321 +}
 459.322 +
 459.323 +tr.odd td.sorting_2 {
 459.324 +	background-color: #DADCFF;
 459.325 +}
 459.326 +
 459.327 +tr.odd td.sorting_3 {
 459.328 +	background-color: #E0E2FF;
 459.329 +}
 459.330 +
 459.331 +tr.even td.sorting_1 {
 459.332 +	background-color: #EAEBFF;
 459.333 +}
 459.334 +
 459.335 +tr.even td.sorting_2 {
 459.336 +	background-color: #F2F3FF;
 459.337 +}
 459.338 +
 459.339 +tr.even td.sorting_3 {
 459.340 +	background-color: #F9F9FF;
 459.341 +}
 459.342 +
 459.343 +
 459.344 +/* For the Conditional-CSS grading rows */
 459.345 +/*
 459.346 + 	Colour calculations (based off the main row colours)
 459.347 +  Level 1:
 459.348 +		dd > c4
 459.349 +		ee > d5
 459.350 +	Level 2:
 459.351 +	  dd > d1
 459.352 +	  ee > e2
 459.353 + */
 459.354 +tr.odd.gradeA td.sorting_1 {
 459.355 +	background-color: #c4ffc4;
 459.356 +}
 459.357 +
 459.358 +tr.odd.gradeA td.sorting_2 {
 459.359 +	background-color: #d1ffd1;
 459.360 +}
 459.361 +
 459.362 +tr.odd.gradeA td.sorting_3 {
 459.363 +	background-color: #d1ffd1;
 459.364 +}
 459.365 +
 459.366 +tr.even.gradeA td.sorting_1 {
 459.367 +	background-color: #d5ffd5;
 459.368 +}
 459.369 +
 459.370 +tr.even.gradeA td.sorting_2 {
 459.371 +	background-color: #e2ffe2;
 459.372 +}
 459.373 +
 459.374 +tr.even.gradeA td.sorting_3 {
 459.375 +	background-color: #e2ffe2;
 459.376 +}
 459.377 +
 459.378 +tr.odd.gradeC td.sorting_1 {
 459.379 +	background-color: #c4c4ff;
 459.380 +}
 459.381 +
 459.382 +tr.odd.gradeC td.sorting_2 {
 459.383 +	background-color: #d1d1ff;
 459.384 +}
 459.385 +
 459.386 +tr.odd.gradeC td.sorting_3 {
 459.387 +	background-color: #d1d1ff;
 459.388 +}
 459.389 +
 459.390 +tr.even.gradeC td.sorting_1 {
 459.391 +	background-color: #d5d5ff;
 459.392 +}
 459.393 +
 459.394 +tr.even.gradeC td.sorting_2 {
 459.395 +	background-color: #e2e2ff;
 459.396 +}
 459.397 +
 459.398 +tr.even.gradeC td.sorting_3 {
 459.399 +	background-color: #e2e2ff;
 459.400 +}
 459.401 +
 459.402 +tr.odd.gradeX td.sorting_1 {
 459.403 +	background-color: #ffc4c4;
 459.404 +}
 459.405 +
 459.406 +tr.odd.gradeX td.sorting_2 {
 459.407 +	background-color: #ffd1d1;
 459.408 +}
 459.409 +
 459.410 +tr.odd.gradeX td.sorting_3 {
 459.411 +	background-color: #ffd1d1;
 459.412 +}
 459.413 +
 459.414 +tr.even.gradeX td.sorting_1 {
 459.415 +	background-color: #ffd5d5;
 459.416 +}
 459.417 +
 459.418 +tr.even.gradeX td.sorting_2 {
 459.419 +	background-color: #ffe2e2;
 459.420 +}
 459.421 +
 459.422 +tr.even.gradeX td.sorting_3 {
 459.423 +	background-color: #ffe2e2;
 459.424 +}
 459.425 +
 459.426 +tr.odd.gradeU td.sorting_1 {
 459.427 +	background-color: #c4c4c4;
 459.428 +}
 459.429 +
 459.430 +tr.odd.gradeU td.sorting_2 {
 459.431 +	background-color: #d1d1d1;
 459.432 +}
 459.433 +
 459.434 +tr.odd.gradeU td.sorting_3 {
 459.435 +	background-color: #d1d1d1;
 459.436 +}
 459.437 +
 459.438 +tr.even.gradeU td.sorting_1 {
 459.439 +	background-color: #d5d5d5;
 459.440 +}
 459.441 +
 459.442 +tr.even.gradeU td.sorting_2 {
 459.443 +	background-color: #e2e2e2;
 459.444 +}
 459.445 +
 459.446 +tr.even.gradeU td.sorting_3 {
 459.447 +	background-color: #e2e2e2;
 459.448 +}
 459.449 +
 459.450 +
 459.451 +/*
 459.452 + * Row highlighting example
 459.453 + */
 459.454 +.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted {
 459.455 +	background-color: #ECFFB3;
 459.456 +}
 459.457 +
 459.458 +.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted {
 459.459 +	background-color: #E6FF99;
 459.460 +}
 459.461 +
 459.462 +
 459.463 +/*
 459.464 + * KeyTable
 459.465 + */
 459.466 +table.KeyTable td {
 459.467 +	border: 3px solid transparent;
 459.468 +}
 459.469 +
 459.470 +table.KeyTable td.focus {
 459.471 +	border: 3px solid #3366FF;
 459.472 +}
 459.473 +
 459.474 +table.display tr.gradeA {
 459.475 +	background-color: #eeffee;
 459.476 +}
 459.477 +
 459.478 +table.display tr.gradeC {
 459.479 +	background-color: #ddddff;
 459.480 +}
 459.481 +
 459.482 +table.display tr.gradeX {
 459.483 +	background-color: #ffdddd;
 459.484 +}
 459.485 +
 459.486 +table.display tr.gradeU {
 459.487 +	background-color: #ddd;
 459.488 +}
 459.489 +
 459.490 +div.box {
 459.491 +	height: 100px;
 459.492 +	padding: 10px;
 459.493 +	overflow: auto;
 459.494 +	border: 1px solid #8080FF;
 459.495 +	background-color: #E5E5FF;
 459.496 +}
   460.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   460.2 +++ b/web/static/css/demo_table_jui.css	Mon Apr 26 11:16:23 2010 +0200
   460.3 @@ -0,0 +1,476 @@
   460.4 +/*
   460.5 + *  File:         demo_table_jui.css
   460.6 + *  CVS:          $Id$
   460.7 + *  Description:  CSS descriptions for DataTables demo pages
   460.8 + *  Author:       Allan Jardine
   460.9 + *  Created:      Tue May 12 06:47:22 BST 2009
  460.10 + *  Modified:     $Date$ by $Author$
  460.11 + *  Language:     CSS
  460.12 + *  Project:      DataTables
  460.13 + *
  460.14 + *  Copyright 2009 Allan Jardine. All Rights Reserved.
  460.15 + *
  460.16 + * ***************************************************************************
  460.17 + * DESCRIPTION
  460.18 + *
  460.19 + * The styles given here are suitable for the demos that are used with the standard DataTables
  460.20 + * distribution (see www.datatables.net). You will most likely wish to modify these styles to
  460.21 + * meet the layout requirements of your site.
  460.22 + *
  460.23 + * Common issues:
  460.24 + *   'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is
  460.25 + *     no conflict between the two pagination types. If you want to use full_numbers pagination
  460.26 + *     ensure that you either have "example_alt_pagination" as a body class name, or better yet,
  460.27 + *     modify that selector.
  460.28 + *   Note that the path used for Images is relative. All images are by default located in
  460.29 + *     ../images/ - relative to this CSS file.
  460.30 + */
  460.31 +
  460.32 +
  460.33 +/*
  460.34 + * jQuery UI specific styling
  460.35 + */
  460.36 +
  460.37 +.paging_two_button .fg-button {
  460.38 +	float: left;
  460.39 +	cursor: pointer;
  460.40 +	* cursor: hand;
  460.41 +}
  460.42 +
  460.43 +.paging_full_numbers .fg-button {
  460.44 +	padding: 2px 6px;
  460.45 +	cursor: pointer;
  460.46 +	* cursor: hand;
  460.47 +}
  460.48 +
  460.49 +.paging_full_numbers {
  460.50 +	width: 350px !important;
  460.51 +}
  460.52 +
  460.53 +.fg-toolbar {
  460.54 +	padding: 5px;
  460.55 +}
  460.56 +
  460.57 +.dataTables_paginate {
  460.58 +	width: auto;
  460.59 +}
  460.60 +
  460.61 +table.display thead th {
  460.62 +	padding: 3px 0px 3px 10px;
  460.63 +	cursor: pointer;
  460.64 +	* cursor: hand;
  460.65 +}
  460.66 +
  460.67 +
  460.68 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  460.69 + *
  460.70 + * Everything below this line is the same as demo_table.css. This file is
  460.71 + * required for 'cleanliness' of the markup
  460.72 + *
  460.73 + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  460.74 +
  460.75 +
  460.76 +
  460.77 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  460.78 + * DataTables features
  460.79 + */
  460.80 +
  460.81 +.dataTables_wrapper {
  460.82 +	position: relative;
  460.83 +	min-height: 302px;
  460.84 +	_height: 302px;
  460.85 +	clear: both;
  460.86 +}
  460.87 +
  460.88 +.dataTables_processing {
  460.89 +	position: absolute;
  460.90 +	top: 0px;
  460.91 +	left: 50%;
  460.92 +	width: 250px;
  460.93 +	margin-left: -125px;
  460.94 +	border: 1px solid #ddd;
  460.95 +	text-align: center;
  460.96 +	color: #999;
  460.97 +	font-size: 11px;
  460.98 +	padding: 2px 0;
  460.99 +}
 460.100 +
 460.101 +.dataTables_length {
 460.102 +	width: 40%;
 460.103 +	float: left;
 460.104 +}
 460.105 +
 460.106 +.dataTables_filter {
 460.107 +	width: 50%;
 460.108 +	float: right;
 460.109 +	text-align: right;
 460.110 +}
 460.111 +
 460.112 +.dataTables_info {
 460.113 +	width: 50%;
 460.114 +	float: left;
 460.115 +}
 460.116 +
 460.117 +.dataTables_paginate {
 460.118 +	float: right;
 460.119 +	text-align: right;
 460.120 +}
 460.121 +
 460.122 +/* Pagination nested */
 460.123 +.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next {
 460.124 +	height: 19px;
 460.125 +	width: 19px;
 460.126 +	margin-left: 3px;
 460.127 +	float: left;
 460.128 +}
 460.129 +
 460.130 +.paginate_disabled_previous {
 460.131 +	background-image: url('../images/back_disabled.jpg');
 460.132 +}
 460.133 +
 460.134 +.paginate_enabled_previous {
 460.135 +	background-image: url('../images/back_enabled.jpg');
 460.136 +}
 460.137 +
 460.138 +.paginate_disabled_next {
 460.139 +	background-image: url('../images/forward_disabled.jpg');
 460.140 +}
 460.141 +
 460.142 +.paginate_enabled_next {
 460.143 +	background-image: url('../images/forward_enabled.jpg');
 460.144 +}
 460.145 +
 460.146 +
 460.147 +
 460.148 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 460.149 + * DataTables display
 460.150 + */
 460.151 +table.display {
 460.152 +	margin: 0 auto;
 460.153 +	width: 100%;
 460.154 +	clear: both;
 460.155 +}
 460.156 +
 460.157 +table.display tfoot th {
 460.158 +	padding: 3px 10px;
 460.159 +	border-top: 1px solid black;
 460.160 +	font-weight: bold;
 460.161 +}
 460.162 +
 460.163 +table.display tr.heading2 td {
 460.164 +	border-bottom: 1px solid #aaa;
 460.165 +}
 460.166 +
 460.167 +table.display td {
 460.168 +	padding: 3px 10px;
 460.169 +}
 460.170 +
 460.171 +table.display td.center {
 460.172 +	text-align: center;
 460.173 +}
 460.174 +
 460.175 +
 460.176 +
 460.177 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 460.178 + * DataTables sorting
 460.179 + */
 460.180 +
 460.181 +.sorting_asc {
 460.182 +	background: url('../images/sort_asc.jpg') no-repeat center right;
 460.183 +}
 460.184 +
 460.185 +.sorting_desc {
 460.186 +	background: url('../images/sort_desc.jpg') no-repeat center right;
 460.187 +}
 460.188 +
 460.189 +.sorting {
 460.190 +	background: url('../images/sort_both.jpg') no-repeat center right;
 460.191 +}
 460.192 +
 460.193 +
 460.194 +
 460.195 +
 460.196 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 460.197 + * DataTables row classes
 460.198 + */
 460.199 +table.display tr.odd.gradeA {
 460.200 +	background-color: #ddffdd;
 460.201 +}
 460.202 +
 460.203 +table.display tr.even.gradeA {
 460.204 +	background-color: #eeffee;
 460.205 +}
 460.206 +
 460.207 +
 460.208 +
 460.209 +
 460.210 +table.display tr.odd.gradeA {
 460.211 +	background-color: #ddffdd;
 460.212 +}
 460.213 +
 460.214 +table.display tr.even.gradeA {
 460.215 +	background-color: #eeffee;
 460.216 +}
 460.217 +
 460.218 +table.display tr.odd.gradeC {
 460.219 +	background-color: #ddddff;
 460.220 +}
 460.221 +
 460.222 +table.display tr.even.gradeC {
 460.223 +	background-color: #eeeeff;
 460.224 +}
 460.225 +
 460.226 +table.display tr.odd.gradeX {
 460.227 +	background-color: #ffdddd;
 460.228 +}
 460.229 +
 460.230 +table.display tr.even.gradeX {
 460.231 +	background-color: #ffeeee;
 460.232 +}
 460.233 +
 460.234 +table.display tr.odd.gradeU {
 460.235 +	background-color: #ddd;
 460.236 +}
 460.237 +
 460.238 +table.display tr.even.gradeU {
 460.239 +	background-color: #eee;
 460.240 +}
 460.241 +
 460.242 +
 460.243 +tr.odd {
 460.244 +	background-color: #E2E4FF;
 460.245 +}
 460.246 +
 460.247 +tr.even {
 460.248 +	background-color: white;
 460.249 +}
 460.250 +
 460.251 +
 460.252 +
 460.253 +
 460.254 +
 460.255 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 460.256 + * Misc
 460.257 + */
 460.258 +.top, .bottom {
 460.259 +	padding: 15px;
 460.260 +	background-color: #F5F5F5;
 460.261 +	border: 1px solid #CCCCCC;
 460.262 +}
 460.263 +
 460.264 +.top .dataTables_info {
 460.265 +	float: none;
 460.266 +}
 460.267 +
 460.268 +.clear {
 460.269 +	clear: both;
 460.270 +}
 460.271 +
 460.272 +.dataTables_empty {
 460.273 +	text-align: center;
 460.274 +}
 460.275 +
 460.276 +tfoot input {
 460.277 +	margin: 0.5em 0;
 460.278 +	width: 100%;
 460.279 +	color: #444;
 460.280 +}
 460.281 +
 460.282 +tfoot input.search_init {
 460.283 +	color: #999;
 460.284 +}
 460.285 +
 460.286 +td.group {
 460.287 +	background-color: #d1cfd0;
 460.288 +	border-bottom: 2px solid #A19B9E;
 460.289 +	border-top: 2px solid #A19B9E;
 460.290 +}
 460.291 +
 460.292 +td.details {
 460.293 +	background-color: #d1cfd0;
 460.294 +	border: 2px solid #A19B9E;
 460.295 +}
 460.296 +
 460.297 +
 460.298 +.example_alt_pagination div.dataTables_info {
 460.299 +	width: 40%;
 460.300 +}
 460.301 +
 460.302 +.paging_full_numbers span.paginate_button,
 460.303 + 	.paging_full_numbers span.paginate_active {
 460.304 +	border: 1px solid #aaa;
 460.305 +	-webkit-border-radius: 5px;
 460.306 +	-moz-border-radius: 5px;
 460.307 +	padding: 2px 5px;
 460.308 +	margin: 0 3px;
 460.309 +	cursor: pointer;
 460.310 +	*cursor: hand;
 460.311 +}
 460.312 +
 460.313 +.paging_full_numbers span.paginate_button {
 460.314 +	background-color: #ddd;
 460.315 +}
 460.316 +
 460.317 +.paging_full_numbers span.paginate_button:hover {
 460.318 +	background-color: #ccc;
 460.319 +}
 460.320 +
 460.321 +.paging_full_numbers span.paginate_active {
 460.322 +	background-color: #99B3FF;
 460.323 +}
 460.324 +
 460.325 +table.display tr.even.row_selected td {
 460.326 +	background-color: #B0BED9;
 460.327 +}
 460.328 +
 460.329 +table.display tr.odd.row_selected td {
 460.330 +	background-color: #9FAFD1;
 460.331 +}
 460.332 +
 460.333 +
 460.334 +/*
 460.335 + * Sorting classes for columns
 460.336 + */
 460.337 +/* For the standard odd/even */
 460.338 +tr.odd td.sorting_1 {
 460.339 +	background-color: #D3D6FF;
 460.340 +}
 460.341 +
 460.342 +tr.odd td.sorting_2 {
 460.343 +	background-color: #DADCFF;
 460.344 +}
 460.345 +
 460.346 +tr.odd td.sorting_3 {
 460.347 +	background-color: #E0E2FF;
 460.348 +}
 460.349 +
 460.350 +tr.even td.sorting_1 {
 460.351 +	background-color: #EAEBFF;
 460.352 +}
 460.353 +
 460.354 +tr.even td.sorting_2 {
 460.355 +	background-color: #F2F3FF;
 460.356 +}
 460.357 +
 460.358 +tr.even td.sorting_3 {
 460.359 +	background-color: #F9F9FF;
 460.360 +}
 460.361 +
 460.362 +
 460.363 +/* For the Conditional-CSS grading rows */
 460.364 +/*
 460.365 + 	Colour calculations (based off the main row colours)
 460.366 +  Level 1:
 460.367 +		dd > c4
 460.368 +		ee > d5
 460.369 +	Level 2:
 460.370 +	  dd > d1
 460.371 +	  ee > e2
 460.372 + */
 460.373 +tr.odd.gradeA td.sorting_1 {
 460.374 +	background-color: #c4ffc4;
 460.375 +}
 460.376 +
 460.377 +tr.odd.gradeA td.sorting_2 {
 460.378 +	background-color: #d1ffd1;
 460.379 +}
 460.380 +
 460.381 +tr.odd.gradeA td.sorting_3 {
 460.382 +	background-color: #d1ffd1;
 460.383 +}
 460.384 +
 460.385 +tr.even.gradeA td.sorting_1 {
 460.386 +	background-color: #d5ffd5;
 460.387 +}
 460.388 +
 460.389 +tr.even.gradeA td.sorting_2 {
 460.390 +	background-color: #e2ffe2;
 460.391 +}
 460.392 +
 460.393 +tr.even.gradeA td.sorting_3 {
 460.394 +	background-color: #e2ffe2;
 460.395 +}
 460.396 +
 460.397 +tr.odd.gradeC td.sorting_1 {
 460.398 +	background-color: #c4c4ff;
 460.399 +}
 460.400 +
 460.401 +tr.odd.gradeC td.sorting_2 {
 460.402 +	background-color: #d1d1ff;
 460.403 +}
 460.404 +
 460.405 +tr.odd.gradeC td.sorting_3 {
 460.406 +	background-color: #d1d1ff;
 460.407 +}
 460.408 +
 460.409 +tr.even.gradeC td.sorting_1 {
 460.410 +	background-color: #d5d5ff;
 460.411 +}
 460.412 +
 460.413 +tr.even.gradeC td.sorting_2 {
 460.414 +	background-color: #e2e2ff;
 460.415 +}
 460.416 +
 460.417 +tr.even.gradeC td.sorting_3 {
 460.418 +	background-color: #e2e2ff;
 460.419 +}
 460.420 +
 460.421 +tr.odd.gradeX td.sorting_1 {
 460.422 +	background-color: #ffc4c4;
 460.423 +}
 460.424 +
 460.425 +tr.odd.gradeX td.sorting_2 {
 460.426 +	background-color: #ffd1d1;
 460.427 +}
 460.428 +
 460.429 +tr.odd.gradeX td.sorting_3 {
 460.430 +	background-color: #ffd1d1;
 460.431 +}
 460.432 +
 460.433 +tr.even.gradeX td.sorting_1 {
 460.434 +	background-color: #ffd5d5;
 460.435 +}
 460.436 +
 460.437 +tr.even.gradeX td.sorting_2 {
 460.438 +	background-color: #ffe2e2;
 460.439 +}
 460.440 +
 460.441 +tr.even.gradeX td.sorting_3 {
 460.442 +	background-color: #ffe2e2;
 460.443 +}
 460.444 +
 460.445 +tr.odd.gradeU td.sorting_1 {
 460.446 +	background-color: #c4c4c4;
 460.447 +}
 460.448 +
 460.449 +tr.odd.gradeU td.sorting_2 {
 460.450 +	background-color: #d1d1d1;
 460.451 +}
 460.452 +
 460.453 +tr.odd.gradeU td.sorting_3 {
 460.454 +	background-color: #d1d1d1;
 460.455 +}
 460.456 +
 460.457 +tr.even.gradeU td.sorting_1 {
 460.458 +	background-color: #d5d5d5;
 460.459 +}
 460.460 +
 460.461 +tr.even.gradeU td.sorting_2 {
 460.462 +	background-color: #e2e2e2;
 460.463 +}
 460.464 +
 460.465 +tr.even.gradeU td.sorting_3 {
 460.466 +	background-color: #e2e2e2;
 460.467 +}
 460.468 +
 460.469 +
 460.470 +/*
 460.471 + * Row highlighting example
 460.472 + */
 460.473 +.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted {
 460.474 +	background-color: #ECFFB3;
 460.475 +}
 460.476 +
 460.477 +.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted {
 460.478 +	background-color: #E6FF99;
 460.479 +}
 460.480 \ No newline at end of file
   461.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   461.2 +++ b/web/static/css/global.css	Mon Apr 26 11:16:23 2010 +0200
   461.3 @@ -0,0 +1,316 @@
   461.4 +* {
   461.5 +    margin: 0;
   461.6 +    padding: 0
   461.7 +    }
   461.8 +/* LAYOUT COLOR */
   461.9 +body {
  461.10 +    background-color: #FFFFFF;
  461.11 +    }
  461.12 +#container {
  461.13 +    background-color: #fff
  461.14 +    }
  461.15 +#header {
  461.16 +    background-color:#F2F7FB;
  461.17 +}
  461.18 +#footer {
  461.19 +    background: #DDDDDD;
  461.20 +    border-top: 1px solid #999999
  461.21 +    }
  461.22 +/* END LAYOUT COLOR */
  461.23 +p { 
  461.24 +    line-height: 1.2em;
  461.25 +}
  461.26 +h1, h2 {
  461.27 +    font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
  461.28 +    font-weight: normal
  461.29 +    }
  461.30 +h1 {
  461.31 +    font-size: 197%
  461.32 +    }
  461.33 +h2 {
  461.34 +    font-size: 167%;
  461.35 +    margin: 0px
  461.36 +    }
  461.37 +h3 {
  461.38 +    margin-bottom: 1em;
  461.39 +    text-transform: uppercase;
  461.40 +    font-size: 100%
  461.41 +    }
  461.42 +ul, ol {
  461.43 +    /*margin-bottom: 1.5em;*/
  461.44 +    line-height: 1.6em;
  461.45 +    }
  461.46 +p {}
  461.47 +ol {}
  461.48 +ul li {
  461.49 +    list-style: none
  461.50 +    }
  461.51 +td, th {
  461.52 +    line-height: 10px;
  461.53 +    font-size: 90%;
  461.54 +    vertical-align: middle;
  461.55 +    padding: 1px 5px;
  461.56 +    }
  461.57 +a {
  461.58 +    text-decoration: none;
  461.59 +    color: #666666
  461.60 +    }
  461.61 +a:hover, a:active {
  461.62 +    /*text-decoration: none;*/
  461.63 +    color: #1777B1
  461.64 +    }
  461.65 +.hide {
  461.66 +    display: none
  461.67 +    }
  461.68 +/*
  461.69 +a:visited {
  461.70 +    color: #666666;
  461.71 +}*/
  461.72 +img {
  461.73 +    border: none
  461.74 +    }
  461.75 +img.left {
  461.76 +    float: left;
  461.77 +    margin: 0 20px 10px 0
  461.78 +    }
  461.79 +img.right {
  461.80 +    float: right;
  461.81 +    margin: 0 0 10px 20px
  461.82 +    }
  461.83 +input[type="text"], input[type="password"], textarea, select, .vTextField, .x-form-text, textarea.x-form-field {
  461.84 +    border: 1px solid #999999;
  461.85 +    background: #FFFFFF;
  461.86 +    margin-right: 0px;
  461.87 +    margin-left: 0px;
  461.88 +    padding: 2px 3px 0pt
  461.89 +    }
  461.90 +input[type="submit"], input[type="button"], input[type="reset"], .submit-row input {
  461.91 +    background: white;
  461.92 +    border-color: #DDDDDD #aaa #aaa #ddd;
  461.93 +    border-style: solid;
  461.94 +    border-width: 1px;
  461.95 +    color: black;
  461.96 +    padding: 3px
  461.97 +    }
  461.98 +select {
  461.99 +    padding: 0px
 461.100 +    }
 461.101 +th {
 461.102 +    font-weight: bold;
 461.103 +    text-align: center
 461.104 +    }
 461.105 +
 461.106 +/* LOGIN */
 461.107 +#form_login {
 461.108 +    margin:0px auto;    
 461.109 +    width: 250px;
 461.110 +}
 461.111 +
 461.112 +    
 461.113 +/* Finestra ancora sezioni */
 461.114 +.x-hidden {
 461.115 +    left: -10000px;
 461.116 +    position: absolute;
 461.117 +    top: -10000px;
 461.118 +    visibility: hidden
 461.119 +    }
 461.120 +.x-window-body a {
 461.121 +    font-size: 11px;
 461.122 +    font-weight: bold;
 461.123 +    padding: 3px;
 461.124 +    margin-bottom: 3px
 461.125 +    }
 461.126 +/* Login */
 461.127 +.vTextField, .vPasswordField {
 461.128 +    margin-bottom: 7px
 461.129 +    }
 461.130 +#login label {
 461.131 +    width: 80px;
 461.132 +    float: left
 461.133 +    }
 461.134 +.errors {
 461.135 +    background: #FFFFCC url(/static/img/icon_error.gif) no-repeat scroll 5px 10px;
 461.136 +    border: 1px solid red;
 461.137 +    color: red;
 461.138 +    display: block;
 461.139 +    font-size: 14px !important;
 461.140 +    margin: 0px 0px 10px;
 461.141 +    padding: 4px 5px 4px 5px;
 461.142 +    width: 100%
 461.143 +    }
 461.144 +.errors h2 {
 461.145 +    margin-left: 20px
 461.146 +    }    
 461.147 +/* Logo */
 461.148 +#logo {
 461.149 +    background: transparent url(/static/img/logo.gif) no-repeat scroll 0px 0px;
 461.150 +    width:150px;
 461.151 +    height:60px;    
 461.152 +    float: left
 461.153 +    }
 461.154 +    
 461.155 +#logo h1, #logo h2 {
 461.156 +    float: left
 461.157 +    }
 461.158 +    
 461.159 +#logo a {
 461.160 +    text-decoration: none;
 461.161 +    color: #000000
 461.162 +    }
 461.163 +/* Search
 461.164 +#user-tools {
 461.165 +    float: right;
 461.166 +    width: 300px;
 461.167 +    margin-top: 70px;
 461.168 +    text-align: right
 461.169 +    }
 461.170 +*/
 461.171 +
 461.172 +#user-tools {
 461.173 +    float: right;
 461.174 +    width: 300px;
 461.175 +    text-align: right
 461.176 +}
 461.177 +        
 461.178 +/* Table List */
 461.179 +.list_table {
 461.180 +    width: 100%
 461.181 +    }
 461.182 +.list_table td, .list_table th {
 461.183 +    border-bottom: 1px solid #EEEEEE;
 461.184 +    font-family: "Lucida Grande", Verdana, Arial, sans-serif;
 461.185 +    font-size: 90%;
 461.186 +    line-height: 10px;
 461.187 +    padding: 5px;
 461.188 +    vertical-align: middle
 461.189 +    }
 461.190 +.title_nav {
 461.191 +    margin-bottom: 15px
 461.192 +    }
 461.193 +/* table form */
 461.194 +form fieldset {
 461.195 +    border: 1px solid #D7E5F2;
 461.196 +    background-color: #F9FBFD;
 461.197 +    margin-top: 10px;
 461.198 +    padding-top: 10px;
 461.199 +    padding-right: 10px
 461.200 +    }
 461.201 +.form fieldset {
 461.202 +    padding: 20px
 461.203 +    }
 461.204 +form legend, .form legend {
 461.205 +    border: 1px solid #D7E5F2;
 461.206 +    color: #2266AA;
 461.207 +    font-size: 90%;
 461.208 +    font-weight: bold;
 461.209 +    margin: 0pt 20px;
 461.210 +    padding: 3px
 461.211 +    }
 461.212 +form legend a, .form legend a {
 461.213 +    color: #2266AA
 461.214 +    }
 461.215 +form table {
 461.216 +    color: #000000;
 461.217 +    width: 100%;
 461.218 +    border: 1px solid #D7E5F2;
 461.219 +    border-collapse: collapse
 461.220 +    }
 461.221 +.form table {
 461.222 +    border: 0px solid #EEEEEE
 461.223 +    }
 461.224 +form td, form th {
 461.225 +    padding-left: 4px;
 461.226 +    color: #000000;
 461.227 +    text-align: left;
 461.228 +    margin-right: 0px;
 461.229 +    padding: 7px
 461.230 +    }
 461.231 +.form td, .form th {
 461.232 +    padding-left: 4px;
 461.233 +    color: #000000;
 461.234 +    text-align: left;
 461.235 +    padding: 10px;
 461.236 +    border-bottom: 0px solid #EEEEEE
 461.237 +    }
 461.238 +form textarea, .form textarea {
 461.239 +    height: 97%;
 461.240 +    vertical-align: top;
 461.241 +    width: 100%
 461.242 +    }
 461.243 +form label, .form label {
 461.244 +    font-size: 11px;
 461.245 +    color: #666666;
 461.246 +    /*font-variant : small-caps;*/
 461.247 +    text-transform: uppercase
 461.248 +    }
 461.249 +form label.required, .form label.required {
 461.250 +    font-weight: bold;
 461.251 +    /* font-variant : small-caps;*/
 461.252 +    text-transform: uppercase
 461.253 +    }
 461.254 +.label_header {
 461.255 +    font-size: 13px;
 461.256 +    /*font-variant: small-caps;*/
 461.257 +    font-weight: bold;
 461.258 +    text-transform: uppercase
 461.259 +    }
 461.260 +/* Footer */
 461.261 +#footer p {
 461.262 +    margin: 5px;
 461.263 +    text-align: right;
 461.264 +    font-size: 85%
 461.265 +    }
 461.266 +/* EXT Grid */
 461.267 +.x-grid3-hd-row td, .x-grid3-row td {
 461.268 +    padding: 0px
 461.269 +    }
 461.270 +.x-panel-bbar .x-toolbar table {
 461.271 +    width: 350px
 461.272 +    }
 461.273 +.x-grid3-header {
 461.274 +    border-bottom: 1px solid #999999
 461.275 +    }
 461.276 +.x-panel-header {
 461.277 +    background: #D7E5F2;
 461.278 +    border: 1px solid #999999
 461.279 +    }
 461.280 +.x-panel-body {
 461.281 +    border-width: 0px 1px 1px 1px;
 461.282 +    border-style: solid;
 461.283 +    border-color: #999999
 461.284 +    }
 461.285 +.x-panel-bbar .x-toolbar table td {
 461.286 +    padding: 0px
 461.287 +    }
 461.288 +/* Summary Table */
 461.289 +.x-grid3-summary-row {
 461.290 +    background: #F1F2F4 none repeat scroll 0% 50%;
 461.291 +    border-left: 1px solid #FFFFFF;
 461.292 +    border-right: 1px solid #FFFFFF;
 461.293 +    color: #333333
 461.294 +    }
 461.295 +.x-grid3-summary-row .x-grid3-cell-inner {
 461.296 +    font-weight: bold;
 461.297 +    padding-bottom: 4px
 461.298 +    }
 461.299 +.x-grid3-row td, .x-grid3-summary-row td {
 461.300 +    padding-left: 0px;
 461.301 +    padding-right: 0px
 461.302 +    }
 461.303 +/* Icon Button */
 461.304 +.icon_add {
 461.305 +    background-image: url(/static/img/add.gif) !important
 461.306 +    }
 461.307 +.icon_print {
 461.308 +    background-image: url(/static/img/print.gif) !important
 461.309 +    }
 461.310 +/* LEGENDA */
 461.311 +.legenda {
 461.312 +    font-size: 10px;
 461.313 +    text-align: right
 461.314 +    }
 461.315 +
 461.316 +/* HELP TEXT */
 461.317 +.help_text {
 461.318 +    border-bottom:2px dashed orange;
 461.319 +}
   462.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   462.2 +++ b/web/static/css/html4css1.css	Mon Apr 26 11:16:23 2010 +0200
   462.3 @@ -0,0 +1,338 @@
   462.4 +/*
   462.5 +:Author: David Goodger
   462.6 +:Contact: [email protected]
   462.7 +:Date: $Date: 2021-12-18 01:56:14 +0100 (Sun, 18 Dec 2021) $
   462.8 +:Revision: $Revision: 4224 $
   462.9 +:Copyright: This stylesheet has been placed in the public domain.
  462.10 +
  462.11 +Default cascading style sheet for the HTML output of Docutils.
  462.12 +
  462.13 +See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
  462.14 +customize this style sheet.
  462.15 +*/
  462.16 +/* used to remove borders from tables and images */
  462.17 +.borderless, table.borderless td, table.borderless th {
  462.18 +    border: 0
  462.19 +    }
  462.20 +table.borderless td, table.borderless th {
  462.21 +    /* Override padding for "table.docutils td" with "! important".
  462.22 +         The right padding separates the table cells. */
  462.23 +    padding: 0 0.5em 0 0 !important
  462.24 +    }
  462.25 +.first {
  462.26 +    /* Override more specific margin styles with "! important". */
  462.27 +    margin-top: 0 !important
  462.28 +    }
  462.29 +.last, .with-subtitle {
  462.30 +    margin-bottom: 0 !important
  462.31 +    }
  462.32 +.hidden {
  462.33 +    display: none
  462.34 +    }
  462.35 +a.toc-backref {
  462.36 +    text-decoration: none;
  462.37 +    color: #ba4a18
  462.38 +    }
  462.39 +blockquote.epigraph {
  462.40 +    margin: 2em 5em
  462.41 +    }
  462.42 +dl.docutils dd {
  462.43 +    margin-bottom: 0.5em
  462.44 +    }
  462.45 +/* Uncomment (and remove this text!) to get bold-faced definition list terms
  462.46 +dl.docutils dt {
  462.47 +  font-weight: bold ;}
  462.48 +*/
  462.49 +div.abstract {
  462.50 +    margin: 2em 5em
  462.51 +    }
  462.52 +div.abstract p.topic-title {
  462.53 +    font-weight: bold;
  462.54 +    text-align: center
  462.55 +    }
  462.56 +div.admonition, div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning {
  462.57 +    margin: 2em;
  462.58 +    border: medium outset;
  462.59 +    padding: 1em
  462.60 +    }
  462.61 +div.admonition p.admonition-title, div.hint p.admonition-title, div.important p.admonition-title, div.note p.admonition-title, div.tip p.admonition-title {
  462.62 +    font-weight: bold;
  462.63 +    font-family: sans-serif
  462.64 +    }
  462.65 +div.attention p.admonition-title, div.caution p.admonition-title, div.danger p.admonition-title, div.error p.admonition-title, div.warning p.admonition-title {
  462.66 +    color: #ff0000;
  462.67 +    font-weight: bold;
  462.68 +    font-family: sans-serif
  462.69 +    }
  462.70 +/* Uncomment (and remove this text!) to get reduced vertical space in
  462.71 +   compound paragraphs.
  462.72 +div.compound .compound-first, div.compound .compound-middle {
  462.73 +  margin-bottom: 0.5em ;}
  462.74 +
  462.75 +div.compound .compound-last, div.compound .compound-middle {
  462.76 +  margin-top: 0.5em ;}
  462.77 +*/
  462.78 +/* div.dedication { */
  462.79 +/*     margin: 2em 5em; */
  462.80 +/*     text-align: center; */
  462.81 +/*     font-style: italic */
  462.82 +/*     } */
  462.83 +/* div.dedication p.topic-title { */
  462.84 +/*     font-weight: bold; */
  462.85 +/*     font-style: normal */
  462.86 +/*     } */
  462.87 +/* div.figure { */
  462.88 +/*     margin-left: 2em; */
  462.89 +/*     margin-right: 2em */
  462.90 +/*     } */
  462.91 +/* div.footer, div.header { */
  462.92 +/*     clear: both; */
  462.93 +/*     font-size: smaller */
  462.94 +/*     } */
  462.95 +/* div.line-block { */
  462.96 +/*     display: block; */
  462.97 +/*     margin-top: 1em; */
  462.98 +/*     margin-bottom: 1em */
  462.99 +/*     } */
 462.100 +/* div.line-block div.line-block { */
 462.101 +/*     margin-top: 0; */
 462.102 +/*     margin-bottom: 0; */
 462.103 +/*     margin-left: 1.5em */
 462.104 +/*     } */
 462.105 +/* div.sidebar_orig { */
 462.106 +/*     margin-left: 1em; */
 462.107 +/*     border: medium outset; */
 462.108 +/*     padding: 1em; */
 462.109 +/*     background-color: #ffffee; */
 462.110 +/*     width: 40%; */
 462.111 +/*     float: right; */
 462.112 +/*     clear: right */
 462.113 +/*     } */
 462.114 +div.sidebar {
 462.115 +    margin-left: 1em;
 462.116 +    margin-top: 1em;
 462.117 +    border: 1px solid orange;
 462.118 +    padding: 1em;
 462.119 +    background-color: #FFFFCC;
 462.120 +    width: 40%;
 462.121 +    float: right;
 462.122 +    clear: right;
 462.123 +    margin-bottom: 20px
 462.124 +    }
 462.125 +div.sidebar p.rubric {
 462.126 +    font-family: sans-serif;
 462.127 +    font-size: medium
 462.128 +    }
 462.129 +div.system-messages {
 462.130 +    margin: 5em
 462.131 +    }
 462.132 +div.system-messages h1 {
 462.133 +    color: #ff0000
 462.134 +    }
 462.135 +div.system-message {
 462.136 +    border: medium outset;
 462.137 +    padding: 1em
 462.138 +    }
 462.139 +div.system-message p.system-message-title {
 462.140 +    color: #ff0000;
 462.141 +    font-weight: bold
 462.142 +    }
 462.143 +div.topic {
 462.144 +    margin: 0em
 462.145 +    }
 462.146 +h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
 462.147 +    margin-top: 0.4em
 462.148 +    }
 462.149 +h1.title {
 462.150 +    text-align: center
 462.151 +    }
 462.152 +h2.subtitle {
 462.153 +    text-align: center
 462.154 +    }
 462.155 +hr.docutils {
 462.156 +    width: 75%
 462.157 +    }
 462.158 +img.align-left {
 462.159 +    clear: left
 462.160 +    }
 462.161 +img.align-right {
 462.162 +    clear: right
 462.163 +    }
 462.164 +#main_content ul {
 462.165 +    margin: 0pt;
 462.166 +    padding: 0pt 0pt 0pt 0.5em
 462.167 +    }
 462.168 +#main_content li {
 462.169 +    list-style-type: square;
 462.170 +    margin-left: 2em;
 462.171 +    padding: 3px 0px 0px;
 462.172 +/*     font-family: arial, "Lucida Grande", verdana, sans-serif; */
 462.173 +/*     font-size: 12px */
 462.174 +    }
 462.175 +ul.simple li a:hover {
 462.176 +    background-color: red;
 462.177 +    color: white
 462.178 +    }
 462.179 +ol.arabic {
 462.180 +    list-style: decimal
 462.181 +    }
 462.182 +ol.loweralpha {
 462.183 +    list-style: lower-alpha
 462.184 +    }
 462.185 +ol.upperalpha {
 462.186 +    list-style: upper-alpha
 462.187 +    }
 462.188 +ol.lowerroman {
 462.189 +    list-style: lower-roman
 462.190 +    }
 462.191 +ol.upperroman {
 462.192 +    list-style: upper-roman
 462.193 +    }
 462.194 +/* p.attribution { */
 462.195 +/*     text-align: right; */
 462.196 +/*     margin-left: 50% */
 462.197 +/*     } */
 462.198 +/* p.caption { */
 462.199 +/*     font-style: italic */
 462.200 +/*     } */
 462.201 +/* p.credits { */
 462.202 +/*     font-style: italic; */
 462.203 +/*     font-size: smaller */
 462.204 +/*     } */
 462.205 +/* p.label { */
 462.206 +/*     white-space: nowrap */
 462.207 +/*     } */
 462.208 +/* p.rubric { */
 462.209 +/*     font-weight: bold; */
 462.210 +/*     font-size: larger; */
 462.211 +/*     color: #b03060; */
 462.212 +/*     text-align: center */
 462.213 +/*     } */
 462.214 +/* p.sidebar-title { */
 462.215 +/*     font-family: sans-serif; */
 462.216 +/*     font-weight: bold; */
 462.217 +/*     font-size: larger */
 462.218 +/*     } */
 462.219 +/* p.sidebar-subtitle { */
 462.220 +/*     font-family: sans-serif; */
 462.221 +/*     font-weight: bold */
 462.222 +/*     } */
 462.223 +/* p.topic-title { */
 462.224 +/*     font-size: 22px */
 462.225 +/*     } */
 462.226 +/* p.topic-title a { */
 462.227 +/*     color: #AA0000 */
 462.228 +/*     } */
 462.229 +pre.address {
 462.230 +    margin-bottom: 0;
 462.231 +    margin-top: 0;
 462.232 +    font-family: serif;
 462.233 +    font-size: 100%
 462.234 +    }
 462.235 +pre.literal-block, pre.doctest-block {
 462.236 +    margin-left: 2em;
 462.237 +    margin-right: 2em;
 462.238 +    background-color: #eeeeee;
 462.239 +    border: 1px solid #A0A0A0;
 462.240 +    color: #000000;
 462.241 +    clear: right
 462.242 +    }
 462.243 +span.classifier {
 462.244 +    font-family: sans-serif;
 462.245 +    font-style: oblique
 462.246 +    }
 462.247 +span.classifier-delimiter {
 462.248 +    font-family: sans-serif;
 462.249 +    font-weight: bold
 462.250 +    }
 462.251 +span.interpreted {
 462.252 +    font-family: sans-serif
 462.253 +    }
 462.254 +span.option {
 462.255 +    white-space: nowrap
 462.256 +    }
 462.257 +span.pre {
 462.258 +    white-space: pre;
 462.259 +    color: #ff00
 462.260 +    }
 462.261 +span.problematic {
 462.262 +    color: #ff0000
 462.263 +    }
 462.264 +span.section-subtitle {
 462.265 +    /* font-size relative to parent (h1..h6 element) */
 462.266 +    font-size: 80%
 462.267 +    }
 462.268 +table.citation {
 462.269 +    border-left: solid 1px gray;
 462.270 +    margin-left: 1px
 462.271 +    }
 462.272 +table.docinfo {
 462.273 +    margin: 2em 4em
 462.274 +    }
 462.275 +table.docutils {
 462.276 +    margin-top: 2.5em;
 462.277 +    margin-bottom: 2.5em
 462.278 +    }
 462.279 +table.footnote {
 462.280 +    border-left: solid 1px black;
 462.281 +    margin-left: 1px
 462.282 +    }
 462.283 +table.docutils td, table.docutils th, table.docinfo td, table.docinfo th {
 462.284 +    padding-left: 0.5em;
 462.285 +    padding-right: 0.5em;
 462.286 +    vertical-align: top;
 462.287 +    line-height: 18px;
 462.288 +    font-size: 110%
 462.289 +    }
 462.290 +table.docutils th {
 462.291 +    color: red
 462.292 +    }
 462.293 +table.docutils th.field-name, table.docinfo th.docinfo-name {
 462.294 +    font-weight: bold;
 462.295 +    text-align: left;
 462.296 +    white-space: nowrap;
 462.297 +    padding-left: 0
 462.298 +    }
 462.299 +h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
 462.300 +    font-size: 100%
 462.301 +    }
 462.302 +tt.docutils {
 462.303 +    /*   background-color: #eeeeee ; */
 462.304 +    }
 462.305 +ul.auto-toc {
 462.306 +    list-style-type: none
 462.307 +    }
 462.308 +.section {
 462.309 +    margin-top: 20px
 462.310 +    }
 462.311 +.section h1, .section h2 {
 462.312 +    border-style: solid;
 462.313 +    border-width: 0pt 0pt 1px;
 462.314 +    border-color: #E2DCC8
 462.315 +    }
 462.316 +.section h1 {
 462.317 +    font-size: 180%;
 462.318 +    font-weight: bold;
 462.319 +    background-color: #FDFAF3
 462.320 +    }
 462.321 +.section h2 {
 462.322 +    font-size: 150%
 462.323 +    }
 462.324 +.section h1 a, .section h2 a {
 462.325 +    color: #AA0000
 462.326 +    }
 462.327 +/* .section p { */
 462.328 +/*     margin-top: 20px; */
 462.329 +/*     font-family: arial, "Lucida Grande", verdana, sans-serif; */
 462.330 +/*     font-size: 120%; */
 462.331 +/*     line-height: 1.4em; */
 462.332 +/*     color: #333333 */
 462.333 +/*     } */
 462.334 +/* /\* thunder *\/ */
 462.335 +span.pre {
 462.336 +    background-color: #FFFFFF;
 462.337 +    color: navy;
 462.338 +    font-size: 110%;
 462.339 +    font-weight: bold;
 462.340 +    white-space: pre
 462.341 +    }
   463.1 Binary file web/static/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png has changed
   464.1 Binary file web/static/css/images/ui-bg_diagonals-thick_20_666666_40x40.png has changed
   465.1 Binary file web/static/css/images/ui-bg_flat_10_000000_40x100.png has changed
   466.1 Binary file web/static/css/images/ui-bg_glass_100_f6f6f6_1x400.png has changed
   467.1 Binary file web/static/css/images/ui-bg_glass_100_fdf5ce_1x400.png has changed
   468.1 Binary file web/static/css/images/ui-bg_glass_65_ffffff_1x400.png has changed
   469.1 Binary file web/static/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png has changed
   470.1 Binary file web/static/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png has changed
   471.1 Binary file web/static/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png has changed
   472.1 Binary file web/static/css/images/ui-icons_222222_256x240.png has changed
   473.1 Binary file web/static/css/images/ui-icons_228ef1_256x240.png has changed
   474.1 Binary file web/static/css/images/ui-icons_ef8c08_256x240.png has changed
   475.1 Binary file web/static/css/images/ui-icons_ffd27a_256x240.png has changed
   476.1 Binary file web/static/css/images/ui-icons_ffffff_256x240.png has changed
   477.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   477.2 +++ b/web/static/css/jquery-ui-1.7.2.custom.css	Mon Apr 26 11:16:23 2010 +0200
   477.3 @@ -0,0 +1,406 @@
   477.4 +/*
   477.5 +* jQuery UI CSS Framework
   477.6 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
   477.7 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
   477.8 +*/
   477.9 +
  477.10 +/* Layout helpers
  477.11 +----------------------------------*/
  477.12 +.ui-helper-hidden { display: none; }
  477.13 +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
  477.14 +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
  477.15 +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  477.16 +.ui-helper-clearfix { display: inline-block; }
  477.17 +/* required comment for clearfix to work in Opera \*/
  477.18 +* html .ui-helper-clearfix { height:1%; }
  477.19 +.ui-helper-clearfix { display:block; }
  477.20 +/* end clearfix */
  477.21 +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
  477.22 +
  477.23 +
  477.24 +/* Interaction Cues
  477.25 +----------------------------------*/
  477.26 +.ui-state-disabled { cursor: default !important; }
  477.27 +
  477.28 +
  477.29 +/* Icons
  477.30 +----------------------------------*/
  477.31 +
  477.32 +/* states and images */
  477.33 +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
  477.34 +
  477.35 +
  477.36 +/* Misc visuals
  477.37 +----------------------------------*/
  477.38 +
  477.39 +/* Overlays */
  477.40 +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
  477.41 +
  477.42 +
  477.43 +
  477.44 +/*
  477.45 +* jQuery UI CSS Framework
  477.46 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
  477.47 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
  477.48 +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
  477.49 +*/
  477.50 +
  477.51 +
  477.52 +/* Component containers
  477.53 +----------------------------------*/
  477.54 +.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
  477.55 +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
  477.56 +.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
  477.57 +.ui-widget-content a { color: #333333; }
  477.58 +.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
  477.59 +.ui-widget-header a { color: #ffffff; }
  477.60 +
  477.61 +/* Interaction states
  477.62 +----------------------------------*/
  477.63 +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; outline: none; }
  477.64 +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; outline: none; }
  477.65 +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; outline: none; }
  477.66 +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; outline: none; }
  477.67 +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; outline: none; }
  477.68 +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; outline: none; text-decoration: none; }
  477.69 +
  477.70 +/* Interaction Cues
  477.71 +----------------------------------*/
  477.72 +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
  477.73 +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
  477.74 +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
  477.75 +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #ffffff; }
  477.76 +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #ffffff; }
  477.77 +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
  477.78 +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
  477.79 +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
  477.80 +
  477.81 +/* Icons
  477.82 +----------------------------------*/
  477.83 +
  477.84 +/* states and images */
  477.85 +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
  477.86 +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  477.87 +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
  477.88 +.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
  477.89 +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
  477.90 +.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
  477.91 +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
  477.92 +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
  477.93 +
  477.94 +/* positioning */
  477.95 +.ui-icon-carat-1-n { background-position: 0 0; }
  477.96 +.ui-icon-carat-1-ne { background-position: -16px 0; }
  477.97 +.ui-icon-carat-1-e { background-position: -32px 0; }
  477.98 +.ui-icon-carat-1-se { background-position: -48px 0; }
  477.99 +.ui-icon-carat-1-s { background-position: -64px 0; }
 477.100 +.ui-icon-carat-1-sw { background-position: -80px 0; }
 477.101 +.ui-icon-carat-1-w { background-position: -96px 0; }
 477.102 +.ui-icon-carat-1-nw { background-position: -112px 0; }
 477.103 +.ui-icon-carat-2-n-s { background-position: -128px 0; }
 477.104 +.ui-icon-carat-2-e-w { background-position: -144px 0; }
 477.105 +.ui-icon-triangle-1-n { background-position: 0 -16px; }
 477.106 +.ui-icon-triangle-1-ne { background-position: -16px -16px; }
 477.107 +.ui-icon-triangle-1-e { background-position: -32px -16px; }
 477.108 +.ui-icon-triangle-1-se { background-position: -48px -16px; }
 477.109 +.ui-icon-triangle-1-s { background-position: -64px -16px; }
 477.110 +.ui-icon-triangle-1-sw { background-position: -80px -16px; }
 477.111 +.ui-icon-triangle-1-w { background-position: -96px -16px; }
 477.112 +.ui-icon-triangle-1-nw { background-position: -112px -16px; }
 477.113 +.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
 477.114 +.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
 477.115 +.ui-icon-arrow-1-n { background-position: 0 -32px; }
 477.116 +.ui-icon-arrow-1-ne { background-position: -16px -32px; }
 477.117 +.ui-icon-arrow-1-e { background-position: -32px -32px; }
 477.118 +.ui-icon-arrow-1-se { background-position: -48px -32px; }
 477.119 +.ui-icon-arrow-1-s { background-position: -64px -32px; }
 477.120 +.ui-icon-arrow-1-sw { background-position: -80px -32px; }
 477.121 +.ui-icon-arrow-1-w { background-position: -96px -32px; }
 477.122 +.ui-icon-arrow-1-nw { background-position: -112px -32px; }
 477.123 +.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
 477.124 +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
 477.125 +.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
 477.126 +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
 477.127 +.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
 477.128 +.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
 477.129 +.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
 477.130 +.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
 477.131 +.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
 477.132 +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
 477.133 +.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
 477.134 +.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
 477.135 +.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
 477.136 +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
 477.137 +.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
 477.138 +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
 477.139 +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
 477.140 +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
 477.141 +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
 477.142 +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
 477.143 +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
 477.144 +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
 477.145 +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
 477.146 +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
 477.147 +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
 477.148 +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
 477.149 +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
 477.150 +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
 477.151 +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
 477.152 +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
 477.153 +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
 477.154 +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
 477.155 +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
 477.156 +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
 477.157 +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
 477.158 +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
 477.159 +.ui-icon-arrow-4 { background-position: 0 -80px; }
 477.160 +.ui-icon-arrow-4-diag { background-position: -16px -80px; }
 477.161 +.ui-icon-extlink { background-position: -32px -80px; }
 477.162 +.ui-icon-newwin { background-position: -48px -80px; }
 477.163 +.ui-icon-refresh { background-position: -64px -80px; }
 477.164 +.ui-icon-shuffle { background-position: -80px -80px; }
 477.165 +.ui-icon-transfer-e-w { background-position: -96px -80px; }
 477.166 +.ui-icon-transferthick-e-w { background-position: -112px -80px; }
 477.167 +.ui-icon-folder-collapsed { background-position: 0 -96px; }
 477.168 +.ui-icon-folder-open { background-position: -16px -96px; }
 477.169 +.ui-icon-document { background-position: -32px -96px; }
 477.170 +.ui-icon-document-b { background-position: -48px -96px; }
 477.171 +.ui-icon-note { background-position: -64px -96px; }
 477.172 +.ui-icon-mail-closed { background-position: -80px -96px; }
 477.173 +.ui-icon-mail-open { background-position: -96px -96px; }
 477.174 +.ui-icon-suitcase { background-position: -112px -96px; }
 477.175 +.ui-icon-comment { background-position: -128px -96px; }
 477.176 +.ui-icon-person { background-position: -144px -96px; }
 477.177 +.ui-icon-print { background-position: -160px -96px; }
 477.178 +.ui-icon-trash { background-position: -176px -96px; }
 477.179 +.ui-icon-locked { background-position: -192px -96px; }
 477.180 +.ui-icon-unlocked { background-position: -208px -96px; }
 477.181 +.ui-icon-bookmark { background-position: -224px -96px; }
 477.182 +.ui-icon-tag { background-position: -240px -96px; }
 477.183 +.ui-icon-home { background-position: 0 -112px; }
 477.184 +.ui-icon-flag { background-position: -16px -112px; }
 477.185 +.ui-icon-calendar { background-position: -32px -112px; }
 477.186 +.ui-icon-cart { background-position: -48px -112px; }
 477.187 +.ui-icon-pencil { background-position: -64px -112px; }
 477.188 +.ui-icon-clock { background-position: -80px -112px; }
 477.189 +.ui-icon-disk { background-position: -96px -112px; }
 477.190 +.ui-icon-calculator { background-position: -112px -112px; }
 477.191 +.ui-icon-zoomin { background-position: -128px -112px; }
 477.192 +.ui-icon-zoomout { background-position: -144px -112px; }
 477.193 +.ui-icon-search { background-position: -160px -112px; }
 477.194 +.ui-icon-wrench { background-position: -176px -112px; }
 477.195 +.ui-icon-gear { background-position: -192px -112px; }
 477.196 +.ui-icon-heart { background-position: -208px -112px; }
 477.197 +.ui-icon-star { background-position: -224px -112px; }
 477.198 +.ui-icon-link { background-position: -240px -112px; }
 477.199 +.ui-icon-cancel { background-position: 0 -128px; }
 477.200 +.ui-icon-plus { background-position: -16px -128px; }
 477.201 +.ui-icon-plusthick { background-position: -32px -128px; }
 477.202 +.ui-icon-minus { background-position: -48px -128px; }
 477.203 +.ui-icon-minusthick { background-position: -64px -128px; }
 477.204 +.ui-icon-close { background-position: -80px -128px; }
 477.205 +.ui-icon-closethick { background-position: -96px -128px; }
 477.206 +.ui-icon-key { background-position: -112px -128px; }
 477.207 +.ui-icon-lightbulb { background-position: -128px -128px; }
 477.208 +.ui-icon-scissors { background-position: -144px -128px; }
 477.209 +.ui-icon-clipboard { background-position: -160px -128px; }
 477.210 +.ui-icon-copy { background-position: -176px -128px; }
 477.211 +.ui-icon-contact { background-position: -192px -128px; }
 477.212 +.ui-icon-image { background-position: -208px -128px; }
 477.213 +.ui-icon-video { background-position: -224px -128px; }
 477.214 +.ui-icon-script { background-position: -240px -128px; }
 477.215 +.ui-icon-alert { background-position: 0 -144px; }
 477.216 +.ui-icon-info { background-position: -16px -144px; }
 477.217 +.ui-icon-notice { background-position: -32px -144px; }
 477.218 +.ui-icon-help { background-position: -48px -144px; }
 477.219 +.ui-icon-check { background-position: -64px -144px; }
 477.220 +.ui-icon-bullet { background-position: -80px -144px; }
 477.221 +.ui-icon-radio-off { background-position: -96px -144px; }
 477.222 +.ui-icon-radio-on { background-position: -112px -144px; }
 477.223 +.ui-icon-pin-w { background-position: -128px -144px; }
 477.224 +.ui-icon-pin-s { background-position: -144px -144px; }
 477.225 +.ui-icon-play { background-position: 0 -160px; }
 477.226 +.ui-icon-pause { background-position: -16px -160px; }
 477.227 +.ui-icon-seek-next { background-position: -32px -160px; }
 477.228 +.ui-icon-seek-prev { background-position: -48px -160px; }
 477.229 +.ui-icon-seek-end { background-position: -64px -160px; }
 477.230 +.ui-icon-seek-first { background-position: -80px -160px; }
 477.231 +.ui-icon-stop { background-position: -96px -160px; }
 477.232 +.ui-icon-eject { background-position: -112px -160px; }
 477.233 +.ui-icon-volume-off { background-position: -128px -160px; }
 477.234 +.ui-icon-volume-on { background-position: -144px -160px; }
 477.235 +.ui-icon-power { background-position: 0 -176px; }
 477.236 +.ui-icon-signal-diag { background-position: -16px -176px; }
 477.237 +.ui-icon-signal { background-position: -32px -176px; }
 477.238 +.ui-icon-battery-0 { background-position: -48px -176px; }
 477.239 +.ui-icon-battery-1 { background-position: -64px -176px; }
 477.240 +.ui-icon-battery-2 { background-position: -80px -176px; }
 477.241 +.ui-icon-battery-3 { background-position: -96px -176px; }
 477.242 +.ui-icon-circle-plus { background-position: 0 -192px; }
 477.243 +.ui-icon-circle-minus { background-position: -16px -192px; }
 477.244 +.ui-icon-circle-close { background-position: -32px -192px; }
 477.245 +.ui-icon-circle-triangle-e { background-position: -48px -192px; }
 477.246 +.ui-icon-circle-triangle-s { background-position: -64px -192px; }
 477.247 +.ui-icon-circle-triangle-w { background-position: -80px -192px; }
 477.248 +.ui-icon-circle-triangle-n { background-position: -96px -192px; }
 477.249 +.ui-icon-circle-arrow-e { background-position: -112px -192px; }
 477.250 +.ui-icon-circle-arrow-s { background-position: -128px -192px; }
 477.251 +.ui-icon-circle-arrow-w { background-position: -144px -192px; }
 477.252 +.ui-icon-circle-arrow-n { background-position: -160px -192px; }
 477.253 +.ui-icon-circle-zoomin { background-position: -176px -192px; }
 477.254 +.ui-icon-circle-zoomout { background-position: -192px -192px; }
 477.255 +.ui-icon-circle-check { background-position: -208px -192px; }
 477.256 +.ui-icon-circlesmall-plus { background-position: 0 -208px; }
 477.257 +.ui-icon-circlesmall-minus { background-position: -16px -208px; }
 477.258 +.ui-icon-circlesmall-close { background-position: -32px -208px; }
 477.259 +.ui-icon-squaresmall-plus { background-position: -48px -208px; }
 477.260 +.ui-icon-squaresmall-minus { background-position: -64px -208px; }
 477.261 +.ui-icon-squaresmall-close { background-position: -80px -208px; }
 477.262 +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
 477.263 +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
 477.264 +.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
 477.265 +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
 477.266 +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
 477.267 +.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
 477.268 +
 477.269 +
 477.270 +/* Misc visuals
 477.271 +----------------------------------*/
 477.272 +
 477.273 +/* Corner radius */
 477.274 +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }
 477.275 +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
 477.276 +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
 477.277 +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 477.278 +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
 477.279 +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 477.280 +.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 477.281 +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
 477.282 +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
 477.283 +
 477.284 +/* Overlays */
 477.285 +.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
 477.286 +.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; }/* Accordion
 477.287 +----------------------------------*/
 477.288 +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
 477.289 +.ui-accordion .ui-accordion-li-fix { display: inline; }
 477.290 +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
 477.291 +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
 477.292 +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
 477.293 +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
 477.294 +.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
 477.295 +----------------------------------*/
 477.296 +.ui-datepicker { width: 17em; padding: .2em .2em 0; }
 477.297 +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
 477.298 +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
 477.299 +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
 477.300 +.ui-datepicker .ui-datepicker-prev { left:2px; }
 477.301 +.ui-datepicker .ui-datepicker-next { right:2px; }
 477.302 +.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
 477.303 +.ui-datepicker .ui-datepicker-next-hover { right:1px; }
 477.304 +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
 477.305 +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
 477.306 +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
 477.307 +.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
 477.308 +.ui-datepicker select.ui-datepicker-month, 
 477.309 +.ui-datepicker select.ui-datepicker-year { width: 49%;}
 477.310 +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
 477.311 +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
 477.312 +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
 477.313 +.ui-datepicker td { border: 0; padding: 1px; }
 477.314 +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
 477.315 +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
 477.316 +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
 477.317 +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
 477.318 +
 477.319 +/* with multiple calendars */
 477.320 +.ui-datepicker.ui-datepicker-multi { width:auto; }
 477.321 +.ui-datepicker-multi .ui-datepicker-group { float:left; }
 477.322 +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
 477.323 +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
 477.324 +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
 477.325 +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
 477.326 +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
 477.327 +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
 477.328 +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
 477.329 +.ui-datepicker-row-break { clear:both; width:100%; }
 477.330 +
 477.331 +/* RTL support */
 477.332 +.ui-datepicker-rtl { direction: rtl; }
 477.333 +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
 477.334 +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
 477.335 +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
 477.336 +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
 477.337 +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
 477.338 +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
 477.339 +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
 477.340 +.ui-datepicker-rtl .ui-datepicker-group { float:right; }
 477.341 +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
 477.342 +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
 477.343 +
 477.344 +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
 477.345 +.ui-datepicker-cover {
 477.346 +    display: none; /*sorry for IE5*/
 477.347 +    display/**/: block; /*sorry for IE5*/
 477.348 +    position: absolute; /*must have*/
 477.349 +    z-index: -1; /*must have*/
 477.350 +    filter: mask(); /*must have*/
 477.351 +    top: -4px; /*must have*/
 477.352 +    left: -4px; /*must have*/
 477.353 +    width: 200px; /*must have*/
 477.354 +    height: 200px; /*must have*/
 477.355 +}/* Dialog
 477.356 +----------------------------------*/
 477.357 +.ui-dialog { position: relative; padding: .2em; width: 300px; }
 477.358 +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
 477.359 +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
 477.360 +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
 477.361 +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
 477.362 +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
 477.363 +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
 477.364 +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
 477.365 +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
 477.366 +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
 477.367 +.ui-draggable .ui-dialog-titlebar { cursor: move; }
 477.368 +/* Progressbar
 477.369 +----------------------------------*/
 477.370 +.ui-progressbar { height:2em; text-align: left; }
 477.371 +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
 477.372 +----------------------------------*/
 477.373 +.ui-resizable { position: relative;}
 477.374 +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
 477.375 +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
 477.376 +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
 477.377 +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
 477.378 +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
 477.379 +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
 477.380 +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
 477.381 +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
 477.382 +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
 477.383 +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
 477.384 +----------------------------------*/
 477.385 +.ui-slider { position: relative; text-align: left; }
 477.386 +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
 477.387 +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
 477.388 +
 477.389 +.ui-slider-horizontal { height: .8em; }
 477.390 +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
 477.391 +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
 477.392 +.ui-slider-horizontal .ui-slider-range-min { left: 0; }
 477.393 +.ui-slider-horizontal .ui-slider-range-max { right: 0; }
 477.394 +
 477.395 +.ui-slider-vertical { width: .8em; height: 100px; }
 477.396 +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
 477.397 +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
 477.398 +.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
 477.399 +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
 477.400 +----------------------------------*/
 477.401 +.ui-tabs { padding: .2em; zoom: 1; }
 477.402 +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
 477.403 +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
 477.404 +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
 477.405 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
 477.406 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
 477.407 +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
 477.408 +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
 477.409 +.ui-tabs .ui-tabs-hide { display: none !important; }
   478.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   478.2 +++ b/web/static/css/layout.css	Mon Apr 26 11:16:23 2010 +0200
   478.3 @@ -0,0 +1,80 @@
   478.4 +html,body{margin:0; padding: 0;height: 100%}
   478.5 +div#container{position: relative; height:100%}
   478.6 +body>div#container{height: auto; min-height: 100%}
   478.7 +div#content{padding: 0 1.5em 5em}
   478.8 +div#footer{position:absolute;bottom: 0;width: 100%}
   478.9 +
  478.10 +
  478.11 +body {
  478.12 +    font-family: Verdana, Arial, Helvetica, sans-serif;
  478.13 +    font-size: 90%;
  478.14 +	margin: 0em;
  478.15 +	padding: 0em;    
  478.16 +}
  478.17 +
  478.18 +#container {
  478.19 +	margin: 0em;
  478.20 +	padding: 0em;
  478.21 +	width: 100%;
  478.22 +}
  478.23 +
  478.24 +#header {
  478.25 +    min-width:860px;
  478.26 +    padding: 5px 20px 0 30px;
  478.27 +}
  478.28 +
  478.29 +#main_menu {
  478.30 +    min-width:900px;
  478.31 +}
  478.32 +
  478.33 +#page {
  478.34 +    padding : 30px 20px 0 30px;
  478.35 +    width: 95%;
  478.36 +    min-width: 840px;
  478.37 +}
  478.38 +
  478.39 +#breadcrumbs {
  478.40 +    margin-left: 20px;
  478.41 +}
  478.42 +
  478.43 +#navigation_menu {
  478.44 +    float: left;
  478.45 +    width:200px;
  478.46 +    min-width:200px;
  478.47 +    margin: 0;
  478.48 +    padding: 0;
  478.49 +}
  478.50 +
  478.51 +#content {
  478.52 +    margin-left: 20px;    
  478.53 +    display: table;
  478.54 +}
  478.55 +
  478.56 +.main_content {
  478.57 +    min-width: 600px;
  478.58 +    margin: 10px 50px 50px 10px
  478.59 +}
  478.60 +
  478.61 +.ui-tabs-panel { 
  478.62 +    padding-bottom: 20px
  478.63 + }
  478.64 +
  478.65 +.ui-widget-content { 
  478.66 +    min-height: 350px;
  478.67 +    padding: 0px 0px 0px 0px;
  478.68 +    margin: 0px 0px 10px 0px
  478.69 + }
  478.70 +
  478.71 +.azioni { 
  478.72 +    margin: 20px 0 20px 0
  478.73 + }
  478.74 +
  478.75 +#footer {
  478.76 +    height: 30px;
  478.77 +    margin: 30px 0 20px 0;
  478.78 +    bottom:0px;
  478.79 +    left:0px;
  478.80 +    right:0px;   
  478.81 +    min-width:900px; 
  478.82 +}
  478.83 +
   479.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   479.2 +++ b/web/static/css/local.css	Mon Apr 26 11:16:23 2010 +0200
   479.3 @@ -0,0 +1,133 @@
   479.4 +@import url(local.global.css);
   479.5 +@import url(local.menu.css);
   479.6 +#header {
   479.7 +    background-color: #fefefc;
   479.8 +    height: 68px
   479.9 +    }
  479.10 +#user-tools {
  479.11 +    margin-top: 45px
  479.12 +    }
  479.13 +#content {
  479.14 +    display: table
  479.15 +    }
  479.16 +#navigation_menu {
  479.17 +    min-width: 150px;
  479.18 +    width: 150px
  479.19 +    }
  479.20 +td, th {
  479.21 +    font-size: 100%;
  479.22 +    line-height: 16px;
  479.23 +    padding: 3px;
  479.24 +    vertical-align: middle
  479.25 +    }
  479.26 +.row1 {
  479.27 +    background-color: #f6f6f6
  479.28 +    }
  479.29 +fieldset.form {
  479.30 +    background-color: #f6f6f6
  479.31 +    }
  479.32 +#main_content a:link, a:visited {
  479.33 +    color: #6922c6;
  479.34 +    text-decoration: none
  479.35 +    }
  479.36 +#main_content a:hover {
  479.37 +    color: blue
  479.38 +    }
  479.39 +#main_content h2, #content h2 {
  479.40 +    color: #6922c6;
  479.41 +    border-style: solid;
  479.42 +    border-width: 0pt 0pt 1px;
  479.43 +    margin: 4px 0 4px 8px
  479.44 +    }
  479.45 +.x-menu {
  479.46 +    border-bottom: 1px solid #645e28
  479.47 +    }
  479.48 +ul.simple li a:hover {
  479.49 +    background-color: transparent;
  479.50 +    color: white
  479.51 +    }
  479.52 +blockquote {
  479.53 +    border-left: 0px;
  479.54 +    margin-left: 30;
  479.55 +    margin-right: 30
  479.56 +    }
  479.57 +.highlight pre {
  479.58 +    background-color: #efefef
  479.59 +    }
  479.60 +.section p {
  479.61 +    color: #333333;
  479.62 +    /*     font-size:110%; */
  479.63 +    line-height: 1.2em;
  479.64 +    margin-top: 10px
  479.65 +    }
  479.66 +pre.literal-block {
  479.67 +    background: #EFEFEF none repeat scroll 10% 0%;
  479.68 +    border: 1px solid #AAAAAA;
  479.69 +    margin: 5pt 10px;
  479.70 +    padding: 6px 8px
  479.71 +    }
  479.72 +li em {
  479.73 +    font-style: bold
  479.74 +    }
  479.75 +
  479.76 +div.rss_logo a {
  479.77 +    background-color:#FF6600;
  479.78 +    border-color:#FCC7A5 rgb(125, 51, 2) rgb(62, 26, 1) rgb(255, 149, 78);
  479.79 +    border-style:solid;
  479.80 +    border-width:1px;
  479.81 +    color:#FFFFFF;
  479.82 +    font-family:sans-serif;
  479.83 +    font-size:10px;
  479.84 +    font-weight:bold;
  479.85 +    line-height:10px;
  479.86 +    padding:3px 6px;
  479.87 +    text-align:center;
  479.88 +    text-decoration:none;
  479.89 +}
  479.90 +
  479.91 +.actions { 
  479.92 +    margin: 20px 0 20px 0
  479.93 +}
  479.94 +.ui-helper-reset {
  479.95 +    line-height:0.9
  479.96 +}
  479.97 +form table { 
  479.98 +    width: 100%
  479.99 +}
 479.100 +form { 
 479.101 +    width: 100%
 479.102 +}
 479.103 +
 479.104 +table td {
 479.105 +    padding: 0 30px 0 30px
 479.106 +}
 479.107 +table.horizontal th {
 479.108 +    padding:0 30px;
 479.109 +    text-align:right;
 479.110 +    vertical-align:text-top;
 479.111 +}
 479.112 +.dataTables_length {
 479.113 +    ##  float:left;
 479.114 +    width:40%;
 479.115 +}
 479.116 +.dataTables_filter {
 479.117 +    ##float:right;
 479.118 +    text-align:right;
 479.119 +    ##width:50%;
 479.120 +    margin: 0 0 20px;
 479.121 +}
 479.122 +.dataTables_info {
 479.123 +    ##float:left;
 479.124 +    width:60%;
 479.125 +}
 479.126 +.dataTables_paginate {
 479.127 +    float:right;
 479.128 +    text-align:right;
 479.129 +    width:44px;
 479.130 +}
 479.131 +table {
 479.132 +    border-bottom:1px solid #DDDDDD;
 479.133 +    border-top:1px solid #DDDDDD;
 479.134 +    margin:15px 0;
 479.135 +    padding:10px 0;
 479.136 +}
   480.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   480.2 +++ b/web/static/css/local.global.css	Mon Apr 26 11:16:23 2010 +0200
   480.3 @@ -0,0 +1,319 @@
   480.4 +* {
   480.5 +    margin: 0;
   480.6 +    padding: 0
   480.7 +    }
   480.8 +/* LAYOUT COLOR */
   480.9 +body {
  480.10 +    background-color: #fcfefc;
  480.11 +/*     color: #666666 */
  480.12 +    }
  480.13 +/* Logo */
  480.14 +#logo {
  480.15 +    background: transparent url(/static/img/logo.png) no-repeat scroll 0px 0px;
  480.16 +    width: 250px;
  480.17 +    height: 90px;
  480.18 +    float: left
  480.19 +    }
  480.20 +#logo h1, #logo h2 {
  480.21 +    float: left
  480.22 +    }
  480.23 +#container {
  480.24 +    background-color: #fff
  480.25 +    }
  480.26 +#header {
  480.27 +    background-color: #fdfaf3;
  480.28 +    /*     border-bottom: 1px solid #645e28 */
  480.29 +    }
  480.30 +#footer {
  480.31 +    background: #cae960;
  480.32 +    border-top: 1px solid #999999
  480.33 +    }
  480.34 +li, dt, dd { 
  480.35 +    font-size:  100%; 
  480.36 +    line-height: none;
  480.37 +}
  480.38 +/* END LAYOUT COLOR */
  480.39 +h1, h2, h3, h4 {
  480.40 +    font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
  480.41 +    font-weight: normal
  480.42 +    }
  480.43 +h1 {
  480.44 +    font-size: 197%
  480.45 +    }
  480.46 +h2 {
  480.47 +    font-size: 167%;
  480.48 +    margin: 0px
  480.49 +    }
  480.50 +h3 {
  480.51 +    margin: 1em 0 0.5em;
  480.52 +    text-transform: none;
  480.53 +    font-size: 130%;
  480.54 +    color: #000000;
  480.55 +    font-weight: bold
  480.56 +    }
  480.57 +p, ul, ol {
  480.58 +    /*margin-bottom: 1.5em;*/
  480.59 +/*     line-height: 1.6em */
  480.60 +    }
  480.61 +ul li {
  480.62 +    list-style: none
  480.63 +    }
  480.64 +td, th {
  480.65 +    line-height: 10px;
  480.66 +    font-size: 90%;
  480.67 +    vertical-align: middle
  480.68 +    }
  480.69 +a {
  480.70 +    text-decoration: none;
  480.71 +    color: #666666
  480.72 +    }
  480.73 +a:hover, a:active {
  480.74 +    /*text-decoration: none;*/
  480.75 +    color: #6921cd
  480.76 +    }
  480.77 +.hide {
  480.78 +    display: none
  480.79 +    }
  480.80 +/*
  480.81 +a:visited {
  480.82 +    color: #666666;
  480.83 +}*/
  480.84 +img {
  480.85 +    border: none
  480.86 +    }
  480.87 +img.left {
  480.88 +    float: left;
  480.89 +    margin: 0 20px 10px 0
  480.90 +    }
  480.91 +img.right {
  480.92 +    float: right;
  480.93 +    margin: 0 0 10px 20px
  480.94 +    }
  480.95 +input[type="text"], input[type="password"], textarea, select, .vTextField, .x-form-text, textarea.x-form-field {
  480.96 +    border: 1px solid #999999;
  480.97 +    font: Verdana, Geneva, Arial, Helvetica, sans-serif;
  480.98 +    background: #FFFFFF;
  480.99 +    color: #102132;
 480.100 +    margin-right: 0px;
 480.101 +    margin-left: 0px;
 480.102 +    padding: 2px 3px 0pt
 480.103 +    }
 480.104 +input[type="submit"], input[type="button"], input[type="reset"], .submit-row input {
 480.105 +    background: white;
 480.106 +    border-color: #DDDDDD #aaa #aaa #ddd;
 480.107 +    border-style: solid;
 480.108 +    border-width: 1px;
 480.109 +    color: black;
 480.110 +    padding: 3px
 480.111 +    }
 480.112 +select {
 480.113 +    padding: 0px 0px 0px 4px
 480.114 +    }
 480.115 +th {
 480.116 +    font-weight: bold;
 480.117 +    text-align: center
 480.118 +    }
 480.119 +/* Finestra ancora sezioni */
 480.120 +.x-hidden {
 480.121 +    left: -10000px;
 480.122 +    position: absolute;
 480.123 +    top: -10000px;
 480.124 +    visibility: hidden
 480.125 +    }
 480.126 +.x-window-body a {
 480.127 +    font-size: 11px;
 480.128 +    font-weight: bold;
 480.129 +    padding: 3px;
 480.130 +    margin-bottom: 3px
 480.131 +    }
 480.132 +/* Login */
 480.133 +.vTextField, .vPasswordField {
 480.134 +    margin-bottom: 7px
 480.135 +    }
 480.136 +#login label {
 480.137 +    width: 80px;
 480.138 +    float: left
 480.139 +    }
 480.140 +.errors {
 480.141 +    background: #FFFFCC url(/static/img/icon_error.gif) no-repeat scroll 5px 0.3em;
 480.142 +    border: 1px solid red;
 480.143 +    color: #d9d;
 480.144 +    display: block;
 480.145 +    font-size: 14px !important;
 480.146 +    margin: 0px 0px 10px;
 480.147 +    padding: 4px 5px 4px 5px;
 480.148 +    width: 100%
 480.149 +    }
 480.150 +/* Logo */
 480.151 +#logo {
 480.152 +    float: left
 480.153 +    }
 480.154 +#logo h1, #logo h2 {
 480.155 +    float: left
 480.156 +    }
 480.157 +#logo h1 {
 480.158 +    padding-top: 40px;
 480.159 +    text-transform: lowercase;
 480.160 +    font-size: 34px;
 480.161 +    font-weight: normal
 480.162 +    }
 480.163 +#logo h2 {
 480.164 +    padding: 63px 0 0 3px;
 480.165 +    text-transform: none;
 480.166 +    font-family: Verdana, Arial, Helvetica, sans-serif;
 480.167 +    font-size: 9px
 480.168 +    }
 480.169 +#logo a {
 480.170 +    text-decoration: none;
 480.171 +    color: #000000
 480.172 +    }
 480.173 +/* Search */
 480.174 +#user-tools {
 480.175 +    float: right;
 480.176 +    width: 350px;
 480.177 +    margin-top: 70px;
 480.178 +    text-align: right
 480.179 +    }
 480.180 +/* Table List */
 480.181 +.list_table {
 480.182 +    width: 100%
 480.183 +    }
 480.184 +.list_table td, .list_table th {
 480.185 +    border-bottom: 1px solid #EEEEEE;
 480.186 +    font-family: "Lucida Grande", Verdana, Arial, sans-serif;
 480.187 +    font-size: 90%;
 480.188 +    line-height: 10px;
 480.189 +    padding: 5px;
 480.190 +    vertical-align: middle
 480.191 +    }
 480.192 +.title_nav {
 480.193 +    margin-bottom: 15px
 480.194 +    }
 480.195 +/* table form */
 480.196 +form fieldset {
 480.197 +    border: 1px solid #da27d8;
 480.198 +    background-color: #f6f6f6;
 480.199 +    margin-top: 10px;
 480.200 +    padding-top: 10px;
 480.201 +    padding-right: 10px
 480.202 +    }
 480.203 +.form fieldset {
 480.204 +    padding: 20px
 480.205 +    }
 480.206 +form legend, .form legend {
 480.207 +    border: 1px solid #da27d8;
 480.208 +    background-color: #f6f6f6;
 480.209 +    color: #253221;
 480.210 +    font-size: 90%;
 480.211 +    font-weight: bold;
 480.212 +    margin: 0pt 20px;
 480.213 +    padding: 3px
 480.214 +    }
 480.215 +form legend a, .form legend a {
 480.216 +    color: #253221
 480.217 +    }
 480.218 +form table {
 480.219 +    background-color: #f6f6f6;
 480.220 +    color: #253221;
 480.221 +    width: 100%;
 480.222 +    border: 1px solid #da27d8;
 480.223 +    border-collapse: collapse
 480.224 +    }
 480.225 +.form table {
 480.226 +    border: 0px solid #645e28
 480.227 +    }
 480.228 +form td {
 480.229 +    padding-left: 4px;
 480.230 +    background-color: #f6f6f6;
 480.231 +    color: #253221;
 480.232 +    text-align: left;
 480.233 +    margin-right: 0px;
 480.234 +    padding: 7px
 480.235 +    }
 480.236 +.form td {
 480.237 +    padding-left: 4px;
 480.238 +    color: #253221;
 480.239 +    text-align: left;
 480.240 +    padding: 4px;
 480.241 +    border-bottom: 0px solid #f6f6f6
 480.242 +    }
 480.243 +form textarea, .form textarea {
 480.244 +    height: 97%;
 480.245 +    vertical-align: top;
 480.246 +    width: 100%
 480.247 +    }
 480.248 +form label, .form label {
 480.249 +    font-size: 11px;
 480.250 +    color: #666666;
 480.251 +    /*font-variant : small-caps;*/
 480.252 +    text-transform: none
 480.253 +    }
 480.254 +form label.required, .form label.required {
 480.255 +    font-weight: bold;
 480.256 +    /* font-variant : small-caps;*/
 480.257 +    text-transform: none
 480.258 +    }
 480.259 +.label_header {
 480.260 +    font-size: 13px;
 480.261 +    /*font-variant: small-caps;*/
 480.262 +    font-weight: bold;
 480.263 +    text-transform: none
 480.264 +    }
 480.265 +/* Footer */
 480.266 +#footer p {
 480.267 +    margin: 5px;
 480.268 +    text-align: right;
 480.269 +    font-size: 85%
 480.270 +    }
 480.271 +/* EXT Grid */
 480.272 +.x-grid3-hd-row td, .x-grid3-row td {
 480.273 +    padding: 0px
 480.274 +    }
 480.275 +.x-panel-bbar .x-toolbar table {
 480.276 +    width: 350px
 480.277 +    }
 480.278 +.x-grid3-header {
 480.279 +    border-bottom: 1px solid #999999
 480.280 +    }
 480.281 +.x-panel-header {
 480.282 +    background: #78b1c5;
 480.283 +    border: 1px solid #999999
 480.284 +    }
 480.285 +.x-panel-body {
 480.286 +    border-width: 0px 1px 1px 1px;
 480.287 +    border-style: solid;
 480.288 +    border-color: #999999
 480.289 +    }
 480.290 +.x-panel-bbar .x-toolbar table td {
 480.291 +    padding: 0px
 480.292 +    }
 480.293 +/* Summary Table */
 480.294 +.x-grid3-summary-row {
 480.295 +    background: #F1F2F4 none repeat scroll 0% 50%;
 480.296 +    border-left: 1px solid #FFFFFF;
 480.297 +    border-right: 1px solid #FFFFFF;
 480.298 +    color: #333333
 480.299 +    }
 480.300 +.x-grid3-summary-row .x-grid3-cell-inner {
 480.301 +    font-weight: bold;
 480.302 +    padding-bottom: 4px
 480.303 +    }
 480.304 +.x-grid3-row td, .x-grid3-summary-row td {
 480.305 +    padding-left: 0px;
 480.306 +    padding-right: 0px
 480.307 +    }
 480.308 +/* Icon Button */
 480.309 +.icon_add {
 480.310 +    background-image: url(/static/img/add.gif) !important
 480.311 +    }
 480.312 +.icon_print {
 480.313 +    background-image: url(/static/img/print.gif) !important
 480.314 +    }
 480.315 +/* LEGENDA */
 480.316 +.legenda {
 480.317 +    font-size: 10px;
 480.318 +    text-align: right
 480.319 +    }
 480.320 +.errorlist 4li { 
 480.321 +    background-color: red
 480.322 + }
   481.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   481.2 +++ b/web/static/css/local.menu.css	Mon Apr 26 11:16:23 2010 +0200
   481.3 @@ -0,0 +1,153 @@
   481.4 +/* Modifico l'header in base al tipo di menu che viusalizzo */
   481.5 +#bottomheader {
   481.6 +    background: #cae960 none repeat scroll 0% 50%;
   481.7 +    clear: both;
   481.8 +    height: 2px;
   481.9 +    line-height: 8px;
  481.10 +    padding: 0pt;
  481.11 +    width: 100%;
  481.12 +    margin-top: -8px;
  481.13 +    margin-left: 0px
  481.14 +    }
  481.15 +#main_menu {
  481.16 +    bottom: 0px;
  481.17 +    margin-top: -2px;
  481.18 +    padding: 0pt 0pt 0pt 100px;
  481.19 +    position: relative
  481.20 +    }
  481.21 +/* Menu */
  481.22 +.horizontal_menu ul {
  481.23 +    list-style-type: none;
  481.24 +    margin: 0pt;
  481.25 +    padding: 0pt;
  481.26 +    z-index: 100
  481.27 +    }
  481.28 +/* All' li principale metto un altezza piu piccola e il fon a bold */
  481.29 +.horizontal_menu .mainli {
  481.30 +    line-height: 13px;
  481.31 +    font-weight: bold
  481.32 +    }
  481.33 +/* settaggi x tt le voci di menu */
  481.34 +.horizontal_menu ul li {
  481.35 +    display: inline;
  481.36 +    float: left;
  481.37 +    line-height: 21px;
  481.38 +    padding: 0px;
  481.39 +    position: relative;
  481.40 +    margin-right: 4px;
  481.41 +    font-weight: normal
  481.42 +    }
  481.43 +.horizontal_menu ul li a {
  481.44 +    color: #ffffff;
  481.45 +    display: block;
  481.46 +    padding: 1px 8px;
  481.47 +    text-decoration: none
  481.48 +    }
  481.49 +/* Colore dei sottomenu quando ci passo sopra */
  481.50 +.horizontal_menu .mainli ul li a:hover {
  481.51 +    background-color: #e6fc1e
  481.52 +    }
  481.53 +
  481.54 +.horizontal_menu  ul li a.active {
  481.55 +    background-color: #e6fc1e
  481.56 +    }
  481.57 +
  481.58 +/* Settaggi per menu principale, quello sempre visibile */
  481.59 +.horizontal_menu .mainfoldericon {
  481.60 +    background: #cae960 url(/static/img/color_tabs_left.gif) no-repeat left top;
  481.61 +    float: left;
  481.62 +    color: #15428b;
  481.63 +    padding: 0 0 1px 3px;
  481.64 +    text-decoration: none;
  481.65 +    letter-spacing: 1px
  481.66 +    }
  481.67 +.horizontal_menu .mainfoldericon span {
  481.68 +    float: left;
  481.69 +    display: block;
  481.70 +    background: transparent url(/static/img/color_tabs_right.gif) no-repeat right top;
  481.71 +    padding: 4px 9px 2px 6px
  481.72 +    }
  481.73 +/* Colore del menu principale quando ci passo sopra */
  481.74 +.horizontal_menu ul li a:hover {
  481.75 +    background-color: #e6fc1e
  481.76 +    }
  481.77 +/* Settaggi vari per corretta visualizzazione sottomenu */
  481.78 +.horizontal_menu ul li ul {
  481.79 +    display: block;
  481.80 +    left: 0pt;
  481.81 +    position: absolute;
  481.82 +    top: 1em;
  481.83 +    visibility: hidden;
  481.84 +    float: none
  481.85 +    }
  481.86 +.horizontal_menu ul li ul li {
  481.87 +    display: list-item;
  481.88 +    float: none
  481.89 +    }
  481.90 +.horizontal_menu ul li ul li ul {
  481.91 +    left: 159px;
  481.92 +    top: 0pt
  481.93 +    }
  481.94 +/* settaggi dei sottomenu */
  481.95 +.horizontal_menu ul li ul li a {
  481.96 +    background: #cae960;
  481.97 +    border-width: 1px 1px 0px 1px;
  481.98 +    border-color: #cae960;
  481.99 +    display: block;
 481.100 +    color: #333333;
 481.101 +    padding: 1px 5px 1px 7px;
 481.102 +    text-decoration: none;
 481.103 +    width: 160px
 481.104 +    }
 481.105 +/* ai meu che hanno dei sottomenu aggiungo la frecceta rossa a destra */
 481.106 +.horizontal_menu .subfoldericon {
 481.107 +    background-image: url(/static/img/arrow-right-blu.gif);
 481.108 +    background-position: right;
 481.109 +    background-repeat: no-repeat
 481.110 +    }
 481.111 +/* .horizontal_menu .mainfoldericon {
 481.112 +    background:#F0F0F0 url(/static/img/arrow-down-red.gif) no-repeat scroll right center;
 481.113 +}*/
 481.114 +.horizontal_menu li#active a {
 481.115 +    background-color: #FFFFFF;
 481.116 +    color: #000000
 481.117 +    }
 481.118 +* html p#iepara {
 481.119 +    padding-top: 1em
 481.120 +    }
 481.121 +* html .horizontal_menu ul li {
 481.122 +    float: left;
 481.123 +    height: 1%
 481.124 +    }
 481.125 +* html .horizontal_menu ul li a {
 481.126 +    height: 1%
 481.127 +    }
 481.128 +/* Navigation Menu */
 481.129 +#navigation_menu ul li {
 481.130 +    padding-left: 10px;
 481.131 +    background: url(/static/img/img16.gif) no-repeat 0px 10px;
 481.132 +    font-size: 11px;
 481.133 +    margin-bottom: 0em;
 481.134 +    line-height: 20px
 481.135 +    }
 481.136 +/* Menu di sx */
 481.137 +.box-blue {
 481.138 +    /*background: url(/static/img/img13.gif) repeat-x;*/
 481.139 +    border: 1px solid #999999
 481.140 +    }
 481.141 +.box-blue .section {
 481.142 +    /*background: url(/static/img/img15.gif) no-repeat right top;*/
 481.143 +    background-color: #cae960;
 481.144 +    border-bottom: 1px solid #999999;
 481.145 +    font-size: 100%;
 481.146 +    color: #15428B
 481.147 +    }
 481.148 +.box-blue .section b {
 481.149 +    display: block;
 481.150 +    height: 23px;
 481.151 +    padding: 7px 0 0 10px;
 481.152 +    /*background: url(/static/img/img14.gif) no-repeat;*/
 481.153 +    }
 481.154 +.box-blue .content {
 481.155 +    padding: 7px
 481.156 +    }
   482.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   482.2 +++ b/web/static/css/main.css	Mon Apr 26 11:16:23 2010 +0200
   482.3 @@ -0,0 +1,3 @@
   482.4 +@import url('layout.css');
   482.5 +@import url('global.css');
   482.6 +@import url('menu.css');
   483.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   483.2 +++ b/web/static/css/menu.css	Mon Apr 26 11:16:23 2010 +0200
   483.3 @@ -0,0 +1,166 @@
   483.4 +/* Modifico l'header in base al tipo di menu che viusalizzo */
   483.5 +#main_menu {
   483.6 +    bottom:0px;
   483.7 +    margin-top:10px;
   483.8 +    position:relative;
   483.9 +}
  483.10 +
  483.11 +/* Menu */
  483.12 +.horizontal_menu ul {
  483.13 +    list-style-type:none;
  483.14 +    margin:0pt;
  483.15 +    padding:0pt;
  483.16 +    z-index:100;
  483.17 +}
  483.18 +
  483.19 +/* All' li principale metto un altezza piu piccola e il fon a bold */
  483.20 +.horizontal_menu .mainli {
  483.21 +    line-height:13px;
  483.22 +    font-weight:bold;
  483.23 +}
  483.24 +
  483.25 +/* settaggi x tt le voci di menu */
  483.26 +.horizontal_menu ul li {
  483.27 +    display:inline;
  483.28 +    float:left;
  483.29 +    line-height:21px;
  483.30 +    padding:0px;
  483.31 +    position:relative;
  483.32 +    margin-right: 4px;
  483.33 +    font-weight:normal;
  483.34 +}
  483.35 +
  483.36 +.horizontal_menu ul li a {
  483.37 +    color: #ffffff;
  483.38 +    display:block;
  483.39 +    padding:1px 8px;
  483.40 +    text-decoration:none;
  483.41 +}
  483.42 +
  483.43 +/* Colore dei sottomenu quando ci passo sopra */
  483.44 +.horizontal_menu .mainli ul li a:hover {
  483.45 +    background-color: #D7E5F2;
  483.46 +}
  483.47 +
  483.48 +/* Settaggi per menu principale, quello sempre visibile */
  483.49 +.horizontal_menu .mainfoldericon {
  483.50 +    background: #344682 url(/static/img/color_tabs_left.gif) no-repeat left top;
  483.51 +    float:left;
  483.52 +    color: white;
  483.53 +    padding:0 0 1px 3px;
  483.54 +    text-decoration:none;
  483.55 +    letter-spacing: 1px;
  483.56 +}
  483.57 +
  483.58 +.horizontal_menu .mainfoldericon span {
  483.59 +    float:left;
  483.60 +    display:block;
  483.61 +    background: transparent url(/static/img/color_tabs_right.gif) no-repeat right top;
  483.62 +    padding:4px 9px 2px 6px;
  483.63 +}
  483.64 +
  483.65 +/* Colore del menu principale quando ci passo sopra */
  483.66 +.horizontal_menu ul li a:hover {
  483.67 +    background-color: #3562A6;
  483.68 +}
  483.69 +
  483.70 +.horizontal_menu ul li a.active {
  483.71 +    background-color: #3562A6;
  483.72 +}
  483.73 +
  483.74 +/* Settaggi vari per corretta visualizzazione sottomenu */ 
  483.75 +.horizontal_menu ul li ul {
  483.76 +    display:block;
  483.77 +    left:0pt;
  483.78 +    position:absolute;
  483.79 +    top:1em;
  483.80 +    visibility:hidden;
  483.81 +    float:none;
  483.82 +}
  483.83 +
  483.84 +.horizontal_menu ul li ul li {
  483.85 +    display:list-item;
  483.86 +    float:none;
  483.87 +}
  483.88 +
  483.89 +.horizontal_menu ul li ul li ul {
  483.90 +    left:159px;
  483.91 +    top:0pt;
  483.92 +}
  483.93 +
  483.94 +/* settaggi dei sottomenu */
  483.95 +.horizontal_menu ul li ul li a {
  483.96 +    background:#F0F0F0;
  483.97 +    border:1px solid #CCCCCC; 
  483.98 +    display:block;
  483.99 +    color: #333333;
 483.100 +    padding:1px 5px 1px 7px;
 483.101 +    text-decoration:none;
 483.102 +    width:160px;
 483.103 +}
 483.104 +
 483.105 +/* ai meu che hanno dei sottomenu aggiungo la frecceta rossa a destra */
 483.106 +.horizontal_menu .subfoldericon {
 483.107 +    background-image: url(/static/img/arrow-right-blu.gif);
 483.108 +    background-position: right;
 483.109 +    background-repeat:no-repeat;
 483.110 +}
 483.111 +
 483.112 +/* .horizontal_menu .mainfoldericon {
 483.113 +    background:#F0F0F0 url(/static/img/arrow-down-red.gif) no-repeat scroll right center;
 483.114 +}*/
 483.115 +
 483.116 +.horizontal_menu li#active a {
 483.117 +    background-color:#FFFFFF;
 483.118 +    color:#000000;
 483.119 +}
 483.120 +
 483.121 +* html p#iepara {
 483.122 +    padding-top:1em;
 483.123 +}
 483.124 +
 483.125 +* html .horizontal_menu ul li {
 483.126 +    float:left;
 483.127 +    height:1%;
 483.128 +}
 483.129 +
 483.130 +* html .horizontal_menu ul li a {
 483.131 +    height:1%;
 483.132 +}
 483.133 +
 483.134 +/* Navigation Menu */
 483.135 +
 483.136 +#navigation_menu ul li {
 483.137 +	padding-left: 10px;
 483.138 +	background: url(/static/img/img16.gif) no-repeat 0px 10px;
 483.139 +    font-size:11px;
 483.140 +    margin-bottom:0em;
 483.141 +    line-height:20px;
 483.142 +}
 483.143 +
 483.144 +
 483.145 +/* Menu di sx */
 483.146 +
 483.147 +.box-blue {
 483.148 +    /*background: url(/static/img/img13.gif) repeat-x;*/
 483.149 +    border: 1px solid #999999;
 483.150 +}
 483.151 +
 483.152 +.box-blue .section {
 483.153 +    /*background: url(/static/img/img15.gif) no-repeat right top;*/
 483.154 +    background-color:#D7E5F2;
 483.155 +    border-bottom :1px solid #999999;
 483.156 +    font-size: 100%;
 483.157 +    color: #15428B;
 483.158 +}
 483.159 +
 483.160 +.box-blue .section b {
 483.161 +    display: block;
 483.162 +    height: 23px;
 483.163 +    padding: 7px 0 0 10px;
 483.164 +    /*background: url(/static/img/img14.gif) no-repeat;*/
 483.165 +}
 483.166 +
 483.167 +.box-blue .content {
 483.168 +    padding: 7px;
 483.169 +}
   484.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   484.2 +++ b/web/static/css/menu_ext.css	Mon Apr 26 11:16:23 2010 +0200
   484.3 @@ -0,0 +1,171 @@
   484.4 +/* Modifico l'header in base al tipo di menu che viusalizzo */
   484.5 +#header {
   484.6 +    border-bottom: 1px solid #718BB7
   484.7 +}
   484.8 +
   484.9 +/* Menu */
  484.10 +.x-menu {
  484.11 +    background:#F0F0F0 url(/static/img/menu.gif) repeat-y scroll 0%;
  484.12 +    padding:0px;
  484.13 +}
  484.14 +
  484.15 +.x-menu a.x-menu-item {
  484.16 +    color:#233D6D;    
  484.17 +}
  484.18 +
  484.19 +.x-menu-item-active {
  484.20 +    background:#C3DAF9 none repeat scroll 0%;
  484.21 +    border:1px solid #8BB8F3;
  484.22 +    color:#233D6D;
  484.23 +    padding:0px;
  484.24 +}
  484.25 +
  484.26 +.x-menubar {
  484.27 +    background-color:#DEECFD !important;
  484.28 +    padding:0px 0px 0px 40px;
  484.29 +}
  484.30 +
  484.31 +.x-horizontal-menubar {
  484.32 +    border-left:0px none;
  484.33 +    border-right:0px none;
  484.34 +    border-top:0px none;
  484.35 +    /* width:100%!important; */
  484.36 +    overflow:hidden;
  484.37 +}
  484.38 +.x-menubar .x-menu-list {
  484.39 +    border:0px none;
  484.40 +}
  484.41 +.x-horizontal-menubar .x-menu-list {
  484.42 +    margin-left:0px;
  484.43 +    height:100%;
  484.44 +}
  484.45 +.x-horizontal-menubar .x-menu-list .x-menu-list-item {
  484.46 +    text-decoration:none;
  484.47 +    padding:0px 10px 0px 2px;
  484.48 +    display:block;
  484.49 +    float:left;
  484.50 +    background-image: none;
  484.51 +}
  484.52 +.x-menubar .x-menu-list .x-menu-list-item {
  484.53 +    border:1px solid #deecfd; /* transparent  gives black border in IE? */;
  484.54 +}
  484.55 +.x-menubar .x-menu-list .x-menu-item-active {
  484.56 +    border: 1px solid #8BB8F3;
  484.57 +    background: #C3DAF9 none repeat scroll 0%;
  484.58 +}
  484.59 +.x-menubar .x-menu-activated .x-menu-item-active {
  484.60 +    background-color: #F0F0F0;
  484.61 +}
  484.62 +.x-horizontal-menubar .x-menu-list .x-menu-single-item .x-menu-item {
  484.63 +    background: transparent;
  484.64 +    padding-right:15px;
  484.65 +}               
  484.66 +.x-horizontal-menubar .x-menu-list .x-menu-item-arrow .x-menu-item {
  484.67 +    background: transparent url(/static/img/menubar-parent.gif) no-repeat scroll right 0.6em;
  484.68 +}
  484.69 +.x-menubar .x-menu-list .x-menu-list-item .x-menu-item .x-menu-item-icon {
  484.70 +    display:none;
  484.71 +}
  484.72 +
  484.73 +
  484.74 +/* Navigation Menu */
  484.75 +
  484.76 +#navigation_menu ul li {
  484.77 +	padding-left: 10px;
  484.78 +	background: url(/static/img/img16.gif) no-repeat 0px 10px;
  484.79 +    font-size:11px;
  484.80 +    margin-bottom:0em;
  484.81 +    line-height:20px;
  484.82 +}
  484.83 +
  484.84 +
  484.85 +/* Menu di sx */
  484.86 +
  484.87 +.box-blue {
  484.88 +    /*background: url(/static/img/img13.gif) repeat-x;*/
  484.89 +    border: 1px solid #999999;
  484.90 +}
  484.91 +
  484.92 +.box-blue .section {
  484.93 +    /*background: url(/static/img/img15.gif) no-repeat right top;*/
  484.94 +    background-color:#D7E5F2;
  484.95 +    border-bottom :1px solid #999999;
  484.96 +    font-size: 100%;
  484.97 +    color: #15428B;
  484.98 +}
  484.99 +
 484.100 +.box-blue .section b {
 484.101 +    display: block;
 484.102 +    height: 23px;
 484.103 +    padding: 7px 0 0 10px;
 484.104 +    /*background: url(/static/img/img14.gif) no-repeat;*/
 484.105 +}
 484.106 +
 484.107 +.box-blue .content {
 484.108 +    padding: 7px;
 484.109 +}
 484.110 +
 484.111 +
 484.112 +/* Horizontal menu NON EXT */
 484.113 +#horizontal_menu {
 484.114 +	height: 30px;
 484.115 +    margin-bottom:30px;
 484.116 +    padding-left:40px;
 484.117 +}
 484.118 +
 484.119 +#horizontal_menu ul {
 484.120 +	margin: 0;
 484.121 +	list-style: none;
 484.122 +	line-height: normal;
 484.123 +}
 484.124 +
 484.125 +#horizontal_menu li {
 484.126 +	display: block;
 484.127 +	float: left;
 484.128 +	margin-right: 6px;
 484.129 +	padding: 0;
 484.130 +	/*background: #FFFFFF;*/
 484.131 +    background: #D7E5F2;
 484.132 +    border-left:1px solid #718BB7;
 484.133 +    border-bottom:1px solid #718BB7;
 484.134 +    border-right:1px solid #718BB7;
 484.135 +}
 484.136 +
 484.137 +#horizontal_menu a {
 484.138 +	display: block;
 484.139 +	float: left;
 484.140 +	/*background: url(/static/images/img07.gif) no-repeat;*/
 484.141 +	text-decoration: none;
 484.142 +    color: #666666;
 484.143 +	height: 23px;
 484.144 +	padding: 7px 20px 0 20px;
 484.145 +	cursor: hand;  
 484.146 +    font-weight:bold;  
 484.147 +}
 484.148 +
 484.149 +#horizontal_menu a:hover {
 484.150 +	color: #1777B1;
 484.151 +}
 484.152 +
 484.153 +/*
 484.154 +#menu b {
 484.155 +	display: block;
 484.156 +	float: left;
 484.157 +	height: 23px;
 484.158 +	padding: 7px 20px 0 20px;
 484.159 +	background: url(/static/images/img08.gif) no-repeat right top;
 484.160 +	cursor: hand;	
 484.161 +}*/
 484.162 +
 484.163 +#horizontal_menu li#active {
 484.164 +	/*background: #CFCECE url(/static/images/img04.gif) repeat-x;*/
 484.165 +    border-left:1px solid #718BB7;
 484.166 +    border-bottom:1px solid #718BB7;
 484.167 +    border-right:1px solid #718BB7;        
 484.168 +}
 484.169 +
 484.170 +#horizontal_menu li#active a {
 484.171 +	/*background: url(/static/images/img06.gif) no-repeat right top;*/
 484.172 +	color: #000000;
 484.173 +    background-color:#FFFFFF;    
 484.174 +}
   485.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   485.2 +++ b/web/static/css/print.css	Mon Apr 26 11:16:23 2010 +0200
   485.3 @@ -0,0 +1,48 @@
   485.4 +#navigation_menu{display: none;}
   485.5 +#navigation_filter{display: none;}
   485.6 +body {
   485.7 +    background: white;
   485.8 +    color: black;
   485.9 +    font-size: 6px;
  485.10 +}
  485.11 +#content{
  485.12 +     font-family: Verdana,Arial,sans-serif;
  485.13 +     font-weight: normal; border: none;
  485.14 +     margin: 10px; padding: 10px;
  485.15 +     background: transparent;
  485.16 +     font-size: 6px;
  485.17 + }
  485.18 +
  485.19 +a:link,a:visited {
  485.20 +    font-weight: bold;
  485.21 +    text-decoration: underline;
  485.22 +}
  485.23 +
  485.24 +img{display: none;}
  485.25 +.title_nav{display: none;}
  485.26 +#page_navigator{display: none;}
  485.27 +
  485.28 +
  485.29 +.table_grid{
  485.30 +    border: 1px solid;
  485.31 +    width: 100%;
  485.32 +}
  485.33 +.tr_grid_head{
  485.34 +    font-weight: bold;
  485.35 +    text-align: center;
  485.36 +}
  485.37 +.td_grid_head{
  485.38 +}
  485.39 +.tr_grid{
  485.40 +}
  485.41 +.row1{
  485.42 +    background: #E5E5E5;
  485.43 +}
  485.44 +.row2{
  485.45 +    background: #EEEEEE;
  485.46 +}
  485.47 +.td_grid_label{
  485.48 +    font-weight: bold;
  485.49 +}
  485.50 +.td_grid_value{
  485.51 +}
  485.52 \ No newline at end of file
   486.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   486.2 +++ b/web/static/css/rst.css	Mon Apr 26 11:16:23 2010 +0200
   486.3 @@ -0,0 +1,67 @@
   486.4 +.highlight pre { 
   486.5 +    margin:10px; 
   486.6 +    background: #dbdfda; 
   486.7 +    padding: 10px 10px;
   486.8 +    border: 1px solid #aaa;
   486.9 +}
  486.10 +.highlight{ background: #ffffff; margin:10px; background: #ffffff; padding: 10px 10px;}
  486.11 +.highlight .c { color: #008800; font-style: italic ;} /* Comment */
  486.12 +.highlight .err { border: 1px solid #FF0000 ;} /* Error */
  486.13 +.highlight .k { color: #aa22ff; font-weight: 600 ;} /* Keyword */
  486.14 +.highlight .o { color: #666666 ;} /* Operator */
  486.15 +.highlight .cm { color: #008800; font-style: italic ;} /* Comment.Multiline */
  486.16 +.highlight .cp { color: #008800 ;} /* Comment.Preproc */
  486.17 +.highlight .c1 { color: #008800; font-style: italic ;} /* Comment.Single */
  486.18 +.highlight .cs { color: #008800; font-weight: bold ;} /* Comment.Special */
  486.19 +.highlight .gd { color: #a00000 ;} /* Generic.Deleted */
  486.20 +.highlight .ge { font-style: italic ;} /* Generic.Emph */
  486.21 +.highlight .gr { color: #ff0000 ;} /* Generic.Error */
  486.22 +.highlight .gh { color: #000080; font-weight: bold ;} /* Generic.Heading */
  486.23 +.highlight .gi { color: #00a000 ;} /* Generic.Inserted */
  486.24 +.highlight .go { color: #808080 ;} /* Generic.Output */
  486.25 +.highlight .gp { color: #000080; font-weight: bold ;} /* Generic.Prompt */
  486.26 +.highlight .gs { font-weight: bold ;} /* Generic.Strong */
  486.27 +.highlight .gu { color: #800080; font-weight: bold ;} /* Generic.Subheading */
  486.28 +.highlight .gt { color: #0040d0 ;} /* Generic.Traceback */
  486.29 +.highlight .kc { color: #aa22ff; font-weight: bold ;} /* Keyword.Constant */
  486.30 +.highlight .kd { color: #aa22ff; font-weight: bold ;} /* Keyword.Declaration */
  486.31 +.highlight .kp { color: #aa22ff ;} /* Keyword.Pseudo */
  486.32 +.highlight .kr { color: #aa22ff; font-weight: bold ;} /* Keyword.Reserved */
  486.33 +.highlight .kt { color: #aa22ff; font-weight: bold ;} /* Keyword.Type */
  486.34 +.highlight .m { color: #666666 ;} /* Literal.Number */
  486.35 +.highlight .n { color: #222 ;} /* Literal.Number */
  486.36 +.highlight .s { color: #bb4444 ;} /* Literal.String */
  486.37 +.highlight .na { color: #bb4444 ;} /* Name.Attribute */
  486.38 +.highlight .nb { color: #aa22ff ;} /* Name.Builtin */
  486.39 +.highlight .nc { color: #008000 ;} /* Name.Class */
  486.40 +.highlight .no { color: #880000 ;} /* Name.Constant */
  486.41 +.highlight .nd { color: #aa22ff ;} /* Name.Decorator */
  486.42 +.highlight .ni { color: #999999; font-weight: bold ;} /* Name.Entity */
  486.43 +.highlight .ne { color: #d2413a; font-weight: bold ;} /* Name.Exception */
  486.44 +.highlight .nf { color: #0000ff ;} /* Name.Function */
  486.45 +.highlight .nl { color: #a0a000 ;} /* Name.Label */
  486.46 +.highlight .nn { color: #0000ff; font-weight: bold ;} /* Name.Namespace */
  486.47 +.highlight .nt { color: #008000; font-weight: bold ;} /* Name.Tag */
  486.48 +.highlight .nv { color: #b8860b ;} /* Name.Variable */
  486.49 +.highlight .ow { color: #aa22ff; font-weight: bold ;} /* Operator.Word */
  486.50 +.highlight .mf { color: #666666 ;} /* Literal.Number.Float */
  486.51 +.highlight .mh { color: #666666 ;} /* Literal.Number.Hex */
  486.52 +.highlight .mi { color: #666666 ;} /* Literal.Number.Integer */
  486.53 +.highlight .mo { color: #666666 ;} /* Literal.Number.Oct */
  486.54 +.highlight .sb { color: #bb4444 ;} /* Literal.String.Backtick */
  486.55 +.highlight .sc { color: #bb4444 ;} /* Literal.String.Char */
  486.56 +.highlight .sd { color: #bb4444; font-style: italic ;} /* Literal.String.Doc */
  486.57 +.highlight .s2 { color: #bb4444 ;} /* Literal.String.Double */
  486.58 +.highlight .se { color: #bb6622; font-weight: bold ;} /* Literal.String.Escape */
  486.59 +.highlight .sh { color: #bb4444 ;} /* Literal.String.Heredoc */
  486.60 +.highlight .si { color: #bb6688; font-weight: bold ;} /* Literal.String.Interpol */
  486.61 +.highlight .sx { color: #008000 ;} /* Literal.String.Other */
  486.62 +.highlight .sr { color: #bb6688 ;} /* Literal.String.Regex */
  486.63 +.highlight .s1 { color: #bb4444 ;} /* Literal.String.Single */
  486.64 +.highlight .ss { color: #b8860b ;} /* Literal.String.Symbol */
  486.65 +.highlight .bp { color: #aa22ff ;} /* Name.Builtin.Pseudo */
  486.66 +.highlight .vc { color: #b8860b ;} /* Name.Variable.Class */
  486.67 +.highlight .vg { color: #b8860b ;} /* Name.Variable.Global */
  486.68 +.highlight .vi { color: #b8860b ;} /* Name.Variable.Instance */
  486.69 +.highlight .il { color: #666666 ;} /* Literal.Number.Integer.Long */
  486.70 +.highlight span:hover { background: #ffff99 ;}
  486.71 \ No newline at end of file
   487.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   487.2 +++ b/web/static/css/tabs-no-images.css	Mon Apr 26 11:16:23 2010 +0200
   487.3 @@ -0,0 +1,62 @@
   487.4 +
   487.5 +/* root element for tabs  */
   487.6 +ul.css-tabs {  
   487.7 +	margin:0 !important; 
   487.8 +	padding:0;
   487.9 +	height:30px;
  487.10 +	border-bottom:1px solid #666;	 	
  487.11 +}
  487.12 +
  487.13 +/* single tab */
  487.14 +ul.css-tabs li {  
  487.15 +	float:left;	 
  487.16 +	padding:0; 
  487.17 +	margin:0;  
  487.18 +	list-style-type:none;	
  487.19 +}
  487.20 +
  487.21 +/* link inside the tab. uses a background image */
  487.22 +ul.css-tabs a { 
  487.23 +	float:left;
  487.24 +	font-size:13px;
  487.25 +	display:block;
  487.26 +	padding:5px 30px;	
  487.27 +	text-decoration:none;
  487.28 +	border:1px solid #666;	
  487.29 +	border-bottom:0px;
  487.30 +	height:18px;
  487.31 +	background-color:#efefef;
  487.32 +	color:#777;
  487.33 +	margin-right:2px;
  487.34 +	-moz-border-radius-topleft: 4px;
  487.35 +	-moz-border-radius-topright:4px;
  487.36 +	position:relative;
  487.37 +	top:1px;	
  487.38 +}
  487.39 +
  487.40 +ul.css-tabs a:hover {
  487.41 +	background-color:#F7F7F7;
  487.42 +	color:#333;
  487.43 +}
  487.44 +	
  487.45 +/* selected tab */
  487.46 +ul.css-tabs a.current {
  487.47 +	background-color:#ddd;
  487.48 +	border-bottom:2px solid #ddd;	
  487.49 +	color:#000;	
  487.50 +	cursor:default;
  487.51 +}
  487.52 +
  487.53 +	
  487.54 +/* tab pane */
  487.55 +div.css-panes div {
  487.56 +	display:none;
  487.57 +	border:1px solid #666;
  487.58 +	border-width:0 1px 1px 1px;
  487.59 +	min-height:150px;
  487.60 +	padding:15px 20px;
  487.61 +	background-color:#ddd;	
  487.62 +}
  487.63 +
  487.64 +
  487.65 +
   488.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   488.2 +++ b/web/static/css/tabs.css	Mon Apr 26 11:16:23 2010 +0200
   488.3 @@ -0,0 +1,111 @@
   488.4 +
   488.5 +/* root element for tabs  */
   488.6 +ul.tabs { 
   488.7 +	list-style:none; 
   488.8 +	margin:0 !important; 
   488.9 +	padding:0;
  488.10 +	height:30px;
  488.11 +	border-bottom:1px solid #666;	
  488.12 +}
  488.13 +
  488.14 +/* single tab */
  488.15 +ul.tabs li { 
  488.16 +	float:left;	 
  488.17 +	text-indent:0;
  488.18 +	padding:0;
  488.19 +	margin:0 !important;
  488.20 +	list-style-image:none !important; 
  488.21 +}
  488.22 +
  488.23 +/* link inside the tab. uses a background image */
  488.24 +ul.tabs a { 
  488.25 +	background: url(/static/img/tabs.png) no-repeat -420px 0;
  488.26 +	font-size:11px;
  488.27 +	display:block;
  488.28 +	height: 30px;  
  488.29 +	line-height:30px;
  488.30 +	width: 111px;
  488.31 +	text-align:center;	
  488.32 +	text-decoration:none;
  488.33 +	color:#000;
  488.34 +	padding:0px;
  488.35 +	margin:0px;	
  488.36 +	position:relative;
  488.37 +	top:1px;
  488.38 +}
  488.39 +
  488.40 +ul.tabs a:active {
  488.41 +	outline:none;		
  488.42 +}
  488.43 +
  488.44 +/* when mouse enters the tab move the background image */
  488.45 +ul.tabs a:hover {
  488.46 +	background-position: -420px -31px;	
  488.47 +	color:#fff;	
  488.48 +}
  488.49 +
  488.50 +/* active tab uses a class name "current". it's highlight is also done by moving the background image. */
  488.51 +ul.tabs a.current, ul.tabs a.current:hover, ul.tabs li.current a {
  488.52 +	background-position: -420px -62px;		
  488.53 +	cursor:default !important; 
  488.54 +	color:#000 !important;
  488.55 +}
  488.56 +
  488.57 +/* Different widths for tabs: use a class name: w1, w2, w3 or w2 */
  488.58 +
  488.59 +
  488.60 +/* width 1 */
  488.61 +ul.tabs a.w1 			{ background-position: -519px 0; width:134px; }
  488.62 +ul.tabs a.w1:hover 	{ background-position: -519px -31px; }
  488.63 +ul.tabs a.w1.current { background-position: -519px -62px; }
  488.64 +
  488.65 +/* width 2 */
  488.66 +ul.tabs a.w2 			{ background-position: -366px -0px; width:154px; }
  488.67 +ul.tabs a.w2:hover 	{ background-position: -366px -31px; }
  488.68 +ul.tabs a.w2.current { background-position: -366px -62px; }
  488.69 +
  488.70 +
  488.71 +/* width 3 */
  488.72 +ul.tabs a.w3 			{ background-position: -193px -0px; width:174px; }
  488.73 +ul.tabs a.w3:hover 	{ background-position: -193px -31px; }
  488.74 +ul.tabs a.w3.current { background-position: -193px -62px; }
  488.75 +
  488.76 +/* width 4 */
  488.77 +ul.tabs a.w4 			{ background-position: -0px -0px; width:194px; }
  488.78 +ul.tabs a.w4:hover 	{ background-position: -0px -31px; }
  488.79 +ul.tabs a.w4.current { background-position: -0px -62px; }
  488.80 +
  488.81 +
  488.82 +/* initially all panes are hidden */ 
  488.83 +div.panes div.pane {
  488.84 +	display:none;		
  488.85 +}
  488.86 +
  488.87 +
  488.88 +h4.toggle {
  488.89 +  margin-top: 30px    
  488.90 +}
  488.91 +dev.advanced {
  488.92 +    border-style: none;
  488.93 +}
  488.94 +
  488.95 +/* tab pane styling */
  488.96 +div.panes div {
  488.97 +  display:none;		
  488.98 +  padding:15px 10px;
  488.99 +  border:0px solid #999;
 488.100 +  border-top:0;
 488.101 +  font-size:14px;
 488.102 +  background-color:#fff;
 488.103 +}
 488.104 +
 488.105 +.tooltip {  
 488.106 +    display:none;  
 488.107 +    background:transparent url(/static/img/black_arrow.png);  
 488.108 +    font-size:12px;  
 488.109 +    height:165px;  
 488.110 +    width:268px;  
 488.111 +    color:#000;    
 488.112 +    padding: 20px;   
 488.113 +} 
 488.114 +
   489.1 Binary file web/static/css/ui/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png has changed
   490.1 Binary file web/static/css/ui/themes/base/images/ui-bg_flat_75_ffffff_40x100.png has changed
   491.1 Binary file web/static/css/ui/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png has changed
   492.1 Binary file web/static/css/ui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png has changed
   493.1 Binary file web/static/css/ui/themes/base/images/ui-bg_glass_75_dadada_1x400.png has changed
   494.1 Binary file web/static/css/ui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png has changed
   495.1 Binary file web/static/css/ui/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png has changed
   496.1 Binary file web/static/css/ui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png has changed
   497.1 Binary file web/static/css/ui/themes/base/images/ui-icons_222222_256x240.png has changed
   498.1 Binary file web/static/css/ui/themes/base/images/ui-icons_2e83ff_256x240.png has changed
   499.1 Binary file web/static/css/ui/themes/base/images/ui-icons_454545_256x240.png has changed
   500.1 Binary file web/static/css/ui/themes/base/images/ui-icons_888888_256x240.png has changed
   501.1 Binary file web/static/css/ui/themes/base/images/ui-icons_cd0a0a_256x240.png has changed
   502.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   502.2 +++ b/web/static/css/ui/themes/base/ui.accordion.css	Mon Apr 26 11:16:23 2010 +0200
   502.3 @@ -0,0 +1,9 @@
   502.4 +/* Accordion
   502.5 +----------------------------------*/
   502.6 +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
   502.7 +.ui-accordion .ui-accordion-li-fix { display: inline; }
   502.8 +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
   502.9 +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
  502.10 +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
  502.11 +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
  502.12 +.ui-accordion .ui-accordion-content-active { display: block; }
  502.13 \ No newline at end of file
   503.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   503.2 +++ b/web/static/css/ui/themes/base/ui.all.css	Mon Apr 26 11:16:23 2010 +0200
   503.3 @@ -0,0 +1,2 @@
   503.4 +@import "ui.base.css";
   503.5 +@import "ui.theme.css";
   504.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   504.2 +++ b/web/static/css/ui/themes/base/ui.base.css	Mon Apr 26 11:16:23 2010 +0200
   504.3 @@ -0,0 +1,8 @@
   504.4 +@import url("ui.core.css");
   504.5 +@import url("ui.resizable.css");
   504.6 +@import url("ui.accordion.css");
   504.7 +@import url("ui.dialog.css");
   504.8 +@import url("ui.slider.css");
   504.9 +@import url("ui.tabs.css");
  504.10 +@import url("ui.datepicker.css");
  504.11 +@import url("ui.progressbar.css");
  504.12 \ No newline at end of file
   505.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   505.2 +++ b/web/static/css/ui/themes/base/ui.core.css	Mon Apr 26 11:16:23 2010 +0200
   505.3 @@ -0,0 +1,37 @@
   505.4 +/*
   505.5 +* jQuery UI CSS Framework
   505.6 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
   505.7 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
   505.8 +*/
   505.9 +
  505.10 +/* Layout helpers
  505.11 +----------------------------------*/
  505.12 +.ui-helper-hidden { display: none; }
  505.13 +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
  505.14 +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
  505.15 +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  505.16 +.ui-helper-clearfix { display: inline-block; }
  505.17 +/* required comment for clearfix to work in Opera \*/
  505.18 +* html .ui-helper-clearfix { height:1%; }
  505.19 +.ui-helper-clearfix { display:block; }
  505.20 +/* end clearfix */
  505.21 +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
  505.22 +
  505.23 +
  505.24 +/* Interaction Cues
  505.25 +----------------------------------*/
  505.26 +.ui-state-disabled { cursor: default !important; }
  505.27 +
  505.28 +
  505.29 +/* Icons
  505.30 +----------------------------------*/
  505.31 +
  505.32 +/* states and images */
  505.33 +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
  505.34 +
  505.35 +
  505.36 +/* Misc visuals
  505.37 +----------------------------------*/
  505.38 +
  505.39 +/* Overlays */
  505.40 +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
  505.41 \ No newline at end of file
   506.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   506.2 +++ b/web/static/css/ui/themes/base/ui.datepicker.css	Mon Apr 26 11:16:23 2010 +0200
   506.3 @@ -0,0 +1,62 @@
   506.4 +/* Datepicker
   506.5 +----------------------------------*/
   506.6 +.ui-datepicker { width: 17em; padding: .2em .2em 0; }
   506.7 +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
   506.8 +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
   506.9 +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
  506.10 +.ui-datepicker .ui-datepicker-prev { left:2px; }
  506.11 +.ui-datepicker .ui-datepicker-next { right:2px; }
  506.12 +.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
  506.13 +.ui-datepicker .ui-datepicker-next-hover { right:1px; }
  506.14 +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
  506.15 +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
  506.16 +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
  506.17 +.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
  506.18 +.ui-datepicker select.ui-datepicker-month, 
  506.19 +.ui-datepicker select.ui-datepicker-year { width: 49%;}
  506.20 +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
  506.21 +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
  506.22 +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
  506.23 +.ui-datepicker td { border: 0; padding: 1px; }
  506.24 +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
  506.25 +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
  506.26 +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
  506.27 +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
  506.28 +
  506.29 +/* with multiple calendars */
  506.30 +.ui-datepicker.ui-datepicker-multi { width:auto; }
  506.31 +.ui-datepicker-multi .ui-datepicker-group { float:left; }
  506.32 +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
  506.33 +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
  506.34 +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
  506.35 +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
  506.36 +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
  506.37 +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
  506.38 +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
  506.39 +.ui-datepicker-row-break { clear:both; width:100%; }
  506.40 +
  506.41 +/* RTL support */
  506.42 +.ui-datepicker-rtl { direction: rtl; }
  506.43 +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
  506.44 +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
  506.45 +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
  506.46 +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
  506.47 +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
  506.48 +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
  506.49 +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
  506.50 +.ui-datepicker-rtl .ui-datepicker-group { float:right; }
  506.51 +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
  506.52 +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
  506.53 +
  506.54 +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
  506.55 +.ui-datepicker-cover {
  506.56 +    display: none; /*sorry for IE5*/
  506.57 +    display/**/: block; /*sorry for IE5*/
  506.58 +    position: absolute; /*must have*/
  506.59 +    z-index: -1; /*must have*/
  506.60 +    filter: mask(); /*must have*/
  506.61 +    top: -4px; /*must have*/
  506.62 +    left: -4px; /*must have*/
  506.63 +    width: 200px; /*must have*/
  506.64 +    height: 200px; /*must have*/
  506.65 +}
  506.66 \ No newline at end of file
   507.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   507.2 +++ b/web/static/css/ui/themes/base/ui.progressbar.css	Mon Apr 26 11:16:23 2010 +0200
   507.3 @@ -0,0 +1,4 @@
   507.4 +/* Progressbar
   507.5 +----------------------------------*/
   507.6 +.ui-progressbar { height:2em; text-align: left; }
   507.7 +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
   507.8 \ No newline at end of file
   508.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   508.2 +++ b/web/static/css/ui/themes/base/ui.resizable.css	Mon Apr 26 11:16:23 2010 +0200
   508.3 @@ -0,0 +1,13 @@
   508.4 +/* Resizable
   508.5 +----------------------------------*/
   508.6 +.ui-resizable { position: relative;}
   508.7 +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
   508.8 +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
   508.9 +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
  508.10 +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
  508.11 +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
  508.12 +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
  508.13 +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
  508.14 +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
  508.15 +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
  508.16 +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
  508.17 \ No newline at end of file
   509.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   509.2 +++ b/web/static/css/ui/themes/base/ui.slider.css	Mon Apr 26 11:16:23 2010 +0200
   509.3 @@ -0,0 +1,17 @@
   509.4 +/* Slider
   509.5 +----------------------------------*/
   509.6 +.ui-slider { position: relative; text-align: left; }
   509.7 +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
   509.8 +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
   509.9 +
  509.10 +.ui-slider-horizontal { height: .8em; }
  509.11 +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
  509.12 +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
  509.13 +.ui-slider-horizontal .ui-slider-range-min { left: 0; }
  509.14 +.ui-slider-horizontal .ui-slider-range-max { right: 0; }
  509.15 +
  509.16 +.ui-slider-vertical { width: .8em; height: 100px; }
  509.17 +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
  509.18 +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
  509.19 +.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
  509.20 +.ui-slider-vertical .ui-slider-range-max { top: 0; }
  509.21 \ No newline at end of file
   510.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   510.2 +++ b/web/static/css/ui/themes/base/ui.tabs.css	Mon Apr 26 11:16:23 2010 +0200
   510.3 @@ -0,0 +1,11 @@
   510.4 +/* Tabs
   510.5 +----------------------------------*/
   510.6 +.ui-tabs { padding: .2em; zoom: 1; }
   510.7 +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
   510.8 +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
   510.9 +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
  510.10 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
  510.11 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
  510.12 +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
  510.13 +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
  510.14 +.ui-tabs .ui-tabs-hide { display: none !important; }
   511.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   511.2 +++ b/web/static/css/ui/themes/base/ui.theme.css	Mon Apr 26 11:16:23 2010 +0200
   511.3 @@ -0,0 +1,245 @@
   511.4 +
   511.5 +
   511.6 +/*
   511.7 +* jQuery UI CSS Framework
   511.8 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
   511.9 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
  511.10 +* To view and modify this theme, visit http://jqueryui.com/themeroller/
  511.11 +*/
  511.12 +
  511.13 +
  511.14 +/* Component containers
  511.15 +----------------------------------*/
  511.16 +.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
  511.17 +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
  511.18 +.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
  511.19 +.ui-widget-content a { color: #222222/*{fcContent}*/; }
  511.20 +.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
  511.21 +.ui-widget-header a { color: #222222/*{fcHeader}*/; }
  511.22 +
  511.23 +/* Interaction states
  511.24 +----------------------------------*/
  511.25 +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; outline: none; }
  511.26 +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; outline: none; }
  511.27 +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; outline: none; }
  511.28 +.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; outline: none; }
  511.29 +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; outline: none; }
  511.30 +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; outline: none; text-decoration: none; }
  511.31 +
  511.32 +/* Interaction Cues
  511.33 +----------------------------------*/
  511.34 +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
  511.35 +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
  511.36 +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
  511.37 +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
  511.38 +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
  511.39 +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
  511.40 +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
  511.41 +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
  511.42 +
  511.43 +/* Icons
  511.44 +----------------------------------*/
  511.45 +
  511.46 +/* states and images */
  511.47 +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
  511.48 +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
  511.49 +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
  511.50 +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
  511.51 +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
  511.52 +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
  511.53 +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
  511.54 +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
  511.55 +
  511.56 +/* positioning */
  511.57 +.ui-icon-carat-1-n { background-position: 0 0; }
  511.58 +.ui-icon-carat-1-ne { background-position: -16px 0; }
  511.59 +.ui-icon-carat-1-e { background-position: -32px 0; }
  511.60 +.ui-icon-carat-1-se { background-position: -48px 0; }
  511.61 +.ui-icon-carat-1-s { background-position: -64px 0; }
  511.62 +.ui-icon-carat-1-sw { background-position: -80px 0; }
  511.63 +.ui-icon-carat-1-w { background-position: -96px 0; }
  511.64 +.ui-icon-carat-1-nw { background-position: -112px 0; }
  511.65 +.ui-icon-carat-2-n-s { background-position: -128px 0; }
  511.66 +.ui-icon-carat-2-e-w { background-position: -144px 0; }
  511.67 +.ui-icon-triangle-1-n { background-position: 0 -16px; }
  511.68 +.ui-icon-triangle-1-ne { background-position: -16px -16px; }
  511.69 +.ui-icon-triangle-1-e { background-position: -32px -16px; }
  511.70 +.ui-icon-triangle-1-se { background-position: -48px -16px; }
  511.71 +.ui-icon-triangle-1-s { background-position: -64px -16px; }
  511.72 +.ui-icon-triangle-1-sw { background-position: -80px -16px; }
  511.73 +.ui-icon-triangle-1-w { background-position: -96px -16px; }
  511.74 +.ui-icon-triangle-1-nw { background-position: -112px -16px; }
  511.75 +.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
  511.76 +.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
  511.77 +.ui-icon-arrow-1-n { background-position: 0 -32px; }
  511.78 +.ui-icon-arrow-1-ne { background-position: -16px -32px; }
  511.79 +.ui-icon-arrow-1-e { background-position: -32px -32px; }
  511.80 +.ui-icon-arrow-1-se { background-position: -48px -32px; }
  511.81 +.ui-icon-arrow-1-s { background-position: -64px -32px; }
  511.82 +.ui-icon-arrow-1-sw { background-position: -80px -32px; }
  511.83 +.ui-icon-arrow-1-w { background-position: -96px -32px; }
  511.84 +.ui-icon-arrow-1-nw { background-position: -112px -32px; }
  511.85 +.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
  511.86 +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
  511.87 +.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
  511.88 +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
  511.89 +.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
  511.90 +.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
  511.91 +.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
  511.92 +.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
  511.93 +.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
  511.94 +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
  511.95 +.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
  511.96 +.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
  511.97 +.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
  511.98 +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
  511.99 +.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
 511.100 +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
 511.101 +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
 511.102 +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
 511.103 +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
 511.104 +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
 511.105 +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
 511.106 +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
 511.107 +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
 511.108 +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
 511.109 +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
 511.110 +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
 511.111 +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
 511.112 +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
 511.113 +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
 511.114 +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
 511.115 +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
 511.116 +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
 511.117 +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
 511.118 +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
 511.119 +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
 511.120 +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
 511.121 +.ui-icon-arrow-4 { background-position: 0 -80px; }
 511.122 +.ui-icon-arrow-4-diag { background-position: -16px -80px; }
 511.123 +.ui-icon-extlink { background-position: -32px -80px; }
 511.124 +.ui-icon-newwin { background-position: -48px -80px; }
 511.125 +.ui-icon-refresh { background-position: -64px -80px; }
 511.126 +.ui-icon-shuffle { background-position: -80px -80px; }
 511.127 +.ui-icon-transfer-e-w { background-position: -96px -80px; }
 511.128 +.ui-icon-transferthick-e-w { background-position: -112px -80px; }
 511.129 +.ui-icon-folder-collapsed { background-position: 0 -96px; }
 511.130 +.ui-icon-folder-open { background-position: -16px -96px; }
 511.131 +.ui-icon-document { background-position: -32px -96px; }
 511.132 +.ui-icon-document-b { background-position: -48px -96px; }
 511.133 +.ui-icon-note { background-position: -64px -96px; }
 511.134 +.ui-icon-mail-closed { background-position: -80px -96px; }
 511.135 +.ui-icon-mail-open { background-position: -96px -96px; }
 511.136 +.ui-icon-suitcase { background-position: -112px -96px; }
 511.137 +.ui-icon-comment { background-position: -128px -96px; }
 511.138 +.ui-icon-person { background-position: -144px -96px; }
 511.139 +.ui-icon-print { background-position: -160px -96px; }
 511.140 +.ui-icon-trash { background-position: -176px -96px; }
 511.141 +.ui-icon-locked { background-position: -192px -96px; }
 511.142 +.ui-icon-unlocked { background-position: -208px -96px; }
 511.143 +.ui-icon-bookmark { background-position: -224px -96px; }
 511.144 +.ui-icon-tag { background-position: -240px -96px; }
 511.145 +.ui-icon-home { background-position: 0 -112px; }
 511.146 +.ui-icon-flag { background-position: -16px -112px; }
 511.147 +.ui-icon-calendar { background-position: -32px -112px; }
 511.148 +.ui-icon-cart { background-position: -48px -112px; }
 511.149 +.ui-icon-pencil { background-position: -64px -112px; }
 511.150 +.ui-icon-clock { background-position: -80px -112px; }
 511.151 +.ui-icon-disk { background-position: -96px -112px; }
 511.152 +.ui-icon-calculator { background-position: -112px -112px; }
 511.153 +.ui-icon-zoomin { background-position: -128px -112px; }
 511.154 +.ui-icon-zoomout { background-position: -144px -112px; }
 511.155 +.ui-icon-search { background-position: -160px -112px; }
 511.156 +.ui-icon-wrench { background-position: -176px -112px; }
 511.157 +.ui-icon-gear { background-position: -192px -112px; }
 511.158 +.ui-icon-heart { background-position: -208px -112px; }
 511.159 +.ui-icon-star { background-position: -224px -112px; }
 511.160 +.ui-icon-link { background-position: -240px -112px; }
 511.161 +.ui-icon-cancel { background-position: 0 -128px; }
 511.162 +.ui-icon-plus { background-position: -16px -128px; }
 511.163 +.ui-icon-plusthick { background-position: -32px -128px; }
 511.164 +.ui-icon-minus { background-position: -48px -128px; }
 511.165 +.ui-icon-minusthick { background-position: -64px -128px; }
 511.166 +.ui-icon-close { background-position: -80px -128px; }
 511.167 +.ui-icon-closethick { background-position: -96px -128px; }
 511.168 +.ui-icon-key { background-position: -112px -128px; }
 511.169 +.ui-icon-lightbulb { background-position: -128px -128px; }
 511.170 +.ui-icon-scissors { background-position: -144px -128px; }
 511.171 +.ui-icon-clipboard { background-position: -160px -128px; }
 511.172 +.ui-icon-copy { background-position: -176px -128px; }
 511.173 +.ui-icon-contact { background-position: -192px -128px; }
 511.174 +.ui-icon-image { background-position: -208px -128px; }
 511.175 +.ui-icon-video { background-position: -224px -128px; }
 511.176 +.ui-icon-script { background-position: -240px -128px; }
 511.177 +.ui-icon-alert { background-position: 0 -144px; }
 511.178 +.ui-icon-info { background-position: -16px -144px; }
 511.179 +.ui-icon-notice { background-position: -32px -144px; }
 511.180 +.ui-icon-help { background-position: -48px -144px; }
 511.181 +.ui-icon-check { background-position: -64px -144px; }
 511.182 +.ui-icon-bullet { background-position: -80px -144px; }
 511.183 +.ui-icon-radio-off { background-position: -96px -144px; }
 511.184 +.ui-icon-radio-on { background-position: -112px -144px; }
 511.185 +.ui-icon-pin-w { background-position: -128px -144px; }
 511.186 +.ui-icon-pin-s { background-position: -144px -144px; }
 511.187 +.ui-icon-play { background-position: 0 -160px; }
 511.188 +.ui-icon-pause { background-position: -16px -160px; }
 511.189 +.ui-icon-seek-next { background-position: -32px -160px; }
 511.190 +.ui-icon-seek-prev { background-position: -48px -160px; }
 511.191 +.ui-icon-seek-end { background-position: -64px -160px; }
 511.192 +.ui-icon-seek-first { background-position: -80px -160px; }
 511.193 +.ui-icon-stop { background-position: -96px -160px; }
 511.194 +.ui-icon-eject { background-position: -112px -160px; }
 511.195 +.ui-icon-volume-off { background-position: -128px -160px; }
 511.196 +.ui-icon-volume-on { background-position: -144px -160px; }
 511.197 +.ui-icon-power { background-position: 0 -176px; }
 511.198 +.ui-icon-signal-diag { background-position: -16px -176px; }
 511.199 +.ui-icon-signal { background-position: -32px -176px; }
 511.200 +.ui-icon-battery-0 { background-position: -48px -176px; }
 511.201 +.ui-icon-battery-1 { background-position: -64px -176px; }
 511.202 +.ui-icon-battery-2 { background-position: -80px -176px; }
 511.203 +.ui-icon-battery-3 { background-position: -96px -176px; }
 511.204 +.ui-icon-circle-plus { background-position: 0 -192px; }
 511.205 +.ui-icon-circle-minus { background-position: -16px -192px; }
 511.206 +.ui-icon-circle-close { background-position: -32px -192px; }
 511.207 +.ui-icon-circle-triangle-e { background-position: -48px -192px; }
 511.208 +.ui-icon-circle-triangle-s { background-position: -64px -192px; }
 511.209 +.ui-icon-circle-triangle-w { background-position: -80px -192px; }
 511.210 +.ui-icon-circle-triangle-n { background-position: -96px -192px; }
 511.211 +.ui-icon-circle-arrow-e { background-position: -112px -192px; }
 511.212 +.ui-icon-circle-arrow-s { background-position: -128px -192px; }
 511.213 +.ui-icon-circle-arrow-w { background-position: -144px -192px; }
 511.214 +.ui-icon-circle-arrow-n { background-position: -160px -192px; }
 511.215 +.ui-icon-circle-zoomin { background-position: -176px -192px; }
 511.216 +.ui-icon-circle-zoomout { background-position: -192px -192px; }
 511.217 +.ui-icon-circle-check { background-position: -208px -192px; }
 511.218 +.ui-icon-circlesmall-plus { background-position: 0 -208px; }
 511.219 +.ui-icon-circlesmall-minus { background-position: -16px -208px; }
 511.220 +.ui-icon-circlesmall-close { background-position: -32px -208px; }
 511.221 +.ui-icon-squaresmall-plus { background-position: -48px -208px; }
 511.222 +.ui-icon-squaresmall-minus { background-position: -64px -208px; }
 511.223 +.ui-icon-squaresmall-close { background-position: -80px -208px; }
 511.224 +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
 511.225 +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
 511.226 +.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
 511.227 +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
 511.228 +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
 511.229 +.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
 511.230 +
 511.231 +
 511.232 +/* Misc visuals
 511.233 +----------------------------------*/
 511.234 +
 511.235 +/* Corner radius */
 511.236 +.ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; }
 511.237 +.ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; }
 511.238 +.ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; }
 511.239 +.ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; }
 511.240 +.ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; }
 511.241 +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; }
 511.242 +.ui-corner-right {  -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; }
 511.243 +.ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; }
 511.244 +.ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; }
 511.245 +
 511.246 +/* Overlays */
 511.247 +.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
 511.248 +.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; }
 511.249 \ No newline at end of file
   512.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_flat_0_aaaaaa_40x100.png has changed
   513.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_flat_100_467656_40x100.png has changed
   514.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_flat_75_f0f7e9_40x100.png has changed
   515.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_flat_75_ffffff_40x100.png has changed
   516.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_glass_55_fef5c3_1x400.png has changed
   517.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_glass_65_ffffff_1x400.png has changed
   518.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_glass_75_dadada_1x400.png has changed
   519.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_highlight-soft_75_cae960_1x100.png has changed
   520.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_inset-soft_100_467656_1x100.png has changed
   521.1 Binary file web/static/css/ui/themes/isi/images/ui-bg_inset-soft_95_ddd936_1x100.png has changed
   522.1 Binary file web/static/css/ui/themes/isi/images/ui-icons_222222_256x240.png has changed
   523.1 Binary file web/static/css/ui/themes/isi/images/ui-icons_2e83ff_256x240.png has changed
   524.1 Binary file web/static/css/ui/themes/isi/images/ui-icons_454545_256x240.png has changed
   525.1 Binary file web/static/css/ui/themes/isi/images/ui-icons_cd0a0a_256x240.png has changed
   526.1 Binary file web/static/css/ui/themes/isi/images/ui-icons_f5f3ef_256x240.png has changed
   527.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   527.2 +++ b/web/static/css/ui/themes/isi/jquery-ui-1.7.2.custom.css	Mon Apr 26 11:16:23 2010 +0200
   527.3 @@ -0,0 +1,406 @@
   527.4 +/*
   527.5 +* jQuery UI CSS Framework
   527.6 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
   527.7 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
   527.8 +*/
   527.9 +
  527.10 +/* Layout helpers
  527.11 +----------------------------------*/
  527.12 +.ui-helper-hidden { display: none; }
  527.13 +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
  527.14 +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
  527.15 +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  527.16 +.ui-helper-clearfix { display: inline-block; }
  527.17 +/* required comment for clearfix to work in Opera \*/
  527.18 +* html .ui-helper-clearfix { height:1%; }
  527.19 +.ui-helper-clearfix { display:block; }
  527.20 +/* end clearfix */
  527.21 +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
  527.22 +
  527.23 +
  527.24 +/* Interaction Cues
  527.25 +----------------------------------*/
  527.26 +.ui-state-disabled { cursor: default !important; }
  527.27 +
  527.28 +
  527.29 +/* Icons
  527.30 +----------------------------------*/
  527.31 +
  527.32 +/* states and images */
  527.33 +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
  527.34 +
  527.35 +
  527.36 +/* Misc visuals
  527.37 +----------------------------------*/
  527.38 +
  527.39 +/* Overlays */
  527.40 +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
  527.41 +
  527.42 +
  527.43 +
  527.44 +/*
  527.45 +* jQuery UI CSS Framework
  527.46 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
  527.47 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
  527.48 +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=cae960&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=eee&fcContent=222222&iconColorContent=222222&bgColorDefault=467656&bgTextureDefault=01_flat.png&bgImgOpacityDefault=100&borderColorDefault=d3d3d3&fcDefault=ede8e3&iconColorDefault=f5f3ef&bgColorHover=f0f7e9&bgTextureHover=01_flat.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fef5c3&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=efd748&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=ddd936&bgTextureError=05_inset_soft.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
  527.49 +*/
  527.50 +
  527.51 +
  527.52 +/* Component containers
  527.53 +----------------------------------*/
  527.54 +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
  527.55 +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
  527.56 +.ui-widget-content { border: 1px solid #eee; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
  527.57 +.ui-widget-content a { color: #222222; }
  527.58 +.ui-widget-header { border: 1px solid #aaa; background: #cae960 url(images/ui-bg_highlight-soft_75_cae960_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
  527.59 +.ui-widget-header a { color: #222222; }
  527.60 +
  527.61 +/* Interaction states
  527.62 +----------------------------------*/
  527.63 +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3; background: #467656 url(images/ui-bg_flat_100_467656_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #ede8e3; outline: none; }
  527.64 +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ede8e3; text-decoration: none; outline: none; }
  527.65 +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #f0f7e9 url(images/ui-bg_flat_75_f0f7e9_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
  527.66 +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; }
  527.67 +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
  527.68 +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; }
  527.69 +
  527.70 +/* Interaction Cues
  527.71 +----------------------------------*/
  527.72 +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #efd748; background: #fef5c3 url(images/ui-bg_glass_55_fef5c3_1x400.png) 50% 50% repeat-x; color: #363636; }
  527.73 +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
  527.74 +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #ddd936 url(images/ui-bg_inset-soft_95_ddd936_1x100.png) 50% bottom repeat-x; color: #cd0a0a; }
  527.75 +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
  527.76 +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
  527.77 +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
  527.78 +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
  527.79 +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
  527.80 +
  527.81 +/* Icons
  527.82 +----------------------------------*/
  527.83 +
  527.84 +/* states and images */
  527.85 +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
  527.86 +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  527.87 +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  527.88 +.ui-state-default .ui-icon { background-image: url(images/ui-icons_f5f3ef_256x240.png); }
  527.89 +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
  527.90 +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
  527.91 +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
  527.92 +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
  527.93 +
  527.94 +/* positioning */
  527.95 +.ui-icon-carat-1-n { background-position: 0 0; }
  527.96 +.ui-icon-carat-1-ne { background-position: -16px 0; }
  527.97 +.ui-icon-carat-1-e { background-position: -32px 0; }
  527.98 +.ui-icon-carat-1-se { background-position: -48px 0; }
  527.99 +.ui-icon-carat-1-s { background-position: -64px 0; }
 527.100 +.ui-icon-carat-1-sw { background-position: -80px 0; }
 527.101 +.ui-icon-carat-1-w { background-position: -96px 0; }
 527.102 +.ui-icon-carat-1-nw { background-position: -112px 0; }
 527.103 +.ui-icon-carat-2-n-s { background-position: -128px 0; }
 527.104 +.ui-icon-carat-2-e-w { background-position: -144px 0; }
 527.105 +.ui-icon-triangle-1-n { background-position: 0 -16px; }
 527.106 +.ui-icon-triangle-1-ne { background-position: -16px -16px; }
 527.107 +.ui-icon-triangle-1-e { background-position: -32px -16px; }
 527.108 +.ui-icon-triangle-1-se { background-position: -48px -16px; }
 527.109 +.ui-icon-triangle-1-s { background-position: -64px -16px; }
 527.110 +.ui-icon-triangle-1-sw { background-position: -80px -16px; }
 527.111 +.ui-icon-triangle-1-w { background-position: -96px -16px; }
 527.112 +.ui-icon-triangle-1-nw { background-position: -112px -16px; }
 527.113 +.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
 527.114 +.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
 527.115 +.ui-icon-arrow-1-n { background-position: 0 -32px; }
 527.116 +.ui-icon-arrow-1-ne { background-position: -16px -32px; }
 527.117 +.ui-icon-arrow-1-e { background-position: -32px -32px; }
 527.118 +.ui-icon-arrow-1-se { background-position: -48px -32px; }
 527.119 +.ui-icon-arrow-1-s { background-position: -64px -32px; }
 527.120 +.ui-icon-arrow-1-sw { background-position: -80px -32px; }
 527.121 +.ui-icon-arrow-1-w { background-position: -96px -32px; }
 527.122 +.ui-icon-arrow-1-nw { background-position: -112px -32px; }
 527.123 +.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
 527.124 +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
 527.125 +.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
 527.126 +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
 527.127 +.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
 527.128 +.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
 527.129 +.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
 527.130 +.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
 527.131 +.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
 527.132 +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
 527.133 +.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
 527.134 +.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
 527.135 +.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
 527.136 +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
 527.137 +.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
 527.138 +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
 527.139 +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
 527.140 +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
 527.141 +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
 527.142 +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
 527.143 +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
 527.144 +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
 527.145 +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
 527.146 +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
 527.147 +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
 527.148 +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
 527.149 +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
 527.150 +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
 527.151 +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
 527.152 +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
 527.153 +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
 527.154 +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
 527.155 +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
 527.156 +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
 527.157 +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
 527.158 +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
 527.159 +.ui-icon-arrow-4 { background-position: 0 -80px; }
 527.160 +.ui-icon-arrow-4-diag { background-position: -16px -80px; }
 527.161 +.ui-icon-extlink { background-position: -32px -80px; }
 527.162 +.ui-icon-newwin { background-position: -48px -80px; }
 527.163 +.ui-icon-refresh { background-position: -64px -80px; }
 527.164 +.ui-icon-shuffle { background-position: -80px -80px; }
 527.165 +.ui-icon-transfer-e-w { background-position: -96px -80px; }
 527.166 +.ui-icon-transferthick-e-w { background-position: -112px -80px; }
 527.167 +.ui-icon-folder-collapsed { background-position: 0 -96px; }
 527.168 +.ui-icon-folder-open { background-position: -16px -96px; }
 527.169 +.ui-icon-document { background-position: -32px -96px; }
 527.170 +.ui-icon-document-b { background-position: -48px -96px; }
 527.171 +.ui-icon-note { background-position: -64px -96px; }
 527.172 +.ui-icon-mail-closed { background-position: -80px -96px; }
 527.173 +.ui-icon-mail-open { background-position: -96px -96px; }
 527.174 +.ui-icon-suitcase { background-position: -112px -96px; }
 527.175 +.ui-icon-comment { background-position: -128px -96px; }
 527.176 +.ui-icon-person { background-position: -144px -96px; }
 527.177 +.ui-icon-print { background-position: -160px -96px; }
 527.178 +.ui-icon-trash { background-position: -176px -96px; }
 527.179 +.ui-icon-locked { background-position: -192px -96px; }
 527.180 +.ui-icon-unlocked { background-position: -208px -96px; }
 527.181 +.ui-icon-bookmark { background-position: -224px -96px; }
 527.182 +.ui-icon-tag { background-position: -240px -96px; }
 527.183 +.ui-icon-home { background-position: 0 -112px; }
 527.184 +.ui-icon-flag { background-position: -16px -112px; }
 527.185 +.ui-icon-calendar { background-position: -32px -112px; }
 527.186 +.ui-icon-cart { background-position: -48px -112px; }
 527.187 +.ui-icon-pencil { background-position: -64px -112px; }
 527.188 +.ui-icon-clock { background-position: -80px -112px; }
 527.189 +.ui-icon-disk { background-position: -96px -112px; }
 527.190 +.ui-icon-calculator { background-position: -112px -112px; }
 527.191 +.ui-icon-zoomin { background-position: -128px -112px; }
 527.192 +.ui-icon-zoomout { background-position: -144px -112px; }
 527.193 +.ui-icon-search { background-position: -160px -112px; }
 527.194 +.ui-icon-wrench { background-position: -176px -112px; }
 527.195 +.ui-icon-gear { background-position: -192px -112px; }
 527.196 +.ui-icon-heart { background-position: -208px -112px; }
 527.197 +.ui-icon-star { background-position: -224px -112px; }
 527.198 +.ui-icon-link { background-position: -240px -112px; }
 527.199 +.ui-icon-cancel { background-position: 0 -128px; }
 527.200 +.ui-icon-plus { background-position: -16px -128px; }
 527.201 +.ui-icon-plusthick { background-position: -32px -128px; }
 527.202 +.ui-icon-minus { background-position: -48px -128px; }
 527.203 +.ui-icon-minusthick { background-position: -64px -128px; }
 527.204 +.ui-icon-close { background-position: -80px -128px; }
 527.205 +.ui-icon-closethick { background-position: -96px -128px; }
 527.206 +.ui-icon-key { background-position: -112px -128px; }
 527.207 +.ui-icon-lightbulb { background-position: -128px -128px; }
 527.208 +.ui-icon-scissors { background-position: -144px -128px; }
 527.209 +.ui-icon-clipboard { background-position: -160px -128px; }
 527.210 +.ui-icon-copy { background-position: -176px -128px; }
 527.211 +.ui-icon-contact { background-position: -192px -128px; }
 527.212 +.ui-icon-image { background-position: -208px -128px; }
 527.213 +.ui-icon-video { background-position: -224px -128px; }
 527.214 +.ui-icon-script { background-position: -240px -128px; }
 527.215 +.ui-icon-alert { background-position: 0 -144px; }
 527.216 +.ui-icon-info { background-position: -16px -144px; }
 527.217 +.ui-icon-notice { background-position: -32px -144px; }
 527.218 +.ui-icon-help { background-position: -48px -144px; }
 527.219 +.ui-icon-check { background-position: -64px -144px; }
 527.220 +.ui-icon-bullet { background-position: -80px -144px; }
 527.221 +.ui-icon-radio-off { background-position: -96px -144px; }
 527.222 +.ui-icon-radio-on { background-position: -112px -144px; }
 527.223 +.ui-icon-pin-w { background-position: -128px -144px; }
 527.224 +.ui-icon-pin-s { background-position: -144px -144px; }
 527.225 +.ui-icon-play { background-position: 0 -160px; }
 527.226 +.ui-icon-pause { background-position: -16px -160px; }
 527.227 +.ui-icon-seek-next { background-position: -32px -160px; }
 527.228 +.ui-icon-seek-prev { background-position: -48px -160px; }
 527.229 +.ui-icon-seek-end { background-position: -64px -160px; }
 527.230 +.ui-icon-seek-first { background-position: -80px -160px; }
 527.231 +.ui-icon-stop { background-position: -96px -160px; }
 527.232 +.ui-icon-eject { background-position: -112px -160px; }
 527.233 +.ui-icon-volume-off { background-position: -128px -160px; }
 527.234 +.ui-icon-volume-on { background-position: -144px -160px; }
 527.235 +.ui-icon-power { background-position: 0 -176px; }
 527.236 +.ui-icon-signal-diag { background-position: -16px -176px; }
 527.237 +.ui-icon-signal { background-position: -32px -176px; }
 527.238 +.ui-icon-battery-0 { background-position: -48px -176px; }
 527.239 +.ui-icon-battery-1 { background-position: -64px -176px; }
 527.240 +.ui-icon-battery-2 { background-position: -80px -176px; }
 527.241 +.ui-icon-battery-3 { background-position: -96px -176px; }
 527.242 +.ui-icon-circle-plus { background-position: 0 -192px; }
 527.243 +.ui-icon-circle-minus { background-position: -16px -192px; }
 527.244 +.ui-icon-circle-close { background-position: -32px -192px; }
 527.245 +.ui-icon-circle-triangle-e { background-position: -48px -192px; }
 527.246 +.ui-icon-circle-triangle-s { background-position: -64px -192px; }
 527.247 +.ui-icon-circle-triangle-w { background-position: -80px -192px; }
 527.248 +.ui-icon-circle-triangle-n { background-position: -96px -192px; }
 527.249 +.ui-icon-circle-arrow-e { background-position: -112px -192px; }
 527.250 +.ui-icon-circle-arrow-s { background-position: -128px -192px; }
 527.251 +.ui-icon-circle-arrow-w { background-position: -144px -192px; }
 527.252 +.ui-icon-circle-arrow-n { background-position: -160px -192px; }
 527.253 +.ui-icon-circle-zoomin { background-position: -176px -192px; }
 527.254 +.ui-icon-circle-zoomout { background-position: -192px -192px; }
 527.255 +.ui-icon-circle-check { background-position: -208px -192px; }
 527.256 +.ui-icon-circlesmall-plus { background-position: 0 -208px; }
 527.257 +.ui-icon-circlesmall-minus { background-position: -16px -208px; }
 527.258 +.ui-icon-circlesmall-close { background-position: -32px -208px; }
 527.259 +.ui-icon-squaresmall-plus { background-position: -48px -208px; }
 527.260 +.ui-icon-squaresmall-minus { background-position: -64px -208px; }
 527.261 +.ui-icon-squaresmall-close { background-position: -80px -208px; }
 527.262 +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
 527.263 +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
 527.264 +.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
 527.265 +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
 527.266 +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
 527.267 +.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
 527.268 +
 527.269 +
 527.270 +/* Misc visuals
 527.271 +----------------------------------*/
 527.272 +
 527.273 +/* Corner radius */
 527.274 +.ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; }
 527.275 +.ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; }
 527.276 +.ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }
 527.277 +.ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; }
 527.278 +.ui-corner-top { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; }
 527.279 +.ui-corner-bottom { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; }
 527.280 +.ui-corner-right {  -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; }
 527.281 +.ui-corner-left { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }
 527.282 +.ui-corner-all { -moz-border-radius: 6px; -webkit-border-radius: 6px; }
 527.283 +
 527.284 +/* Overlays */
 527.285 +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
 527.286 +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion
 527.287 +----------------------------------*/
 527.288 +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
 527.289 +.ui-accordion .ui-accordion-li-fix { display: inline; }
 527.290 +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
 527.291 +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
 527.292 +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
 527.293 +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
 527.294 +.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
 527.295 +----------------------------------*/
 527.296 +.ui-datepicker { width: 17em; padding: .2em .2em 0; }
 527.297 +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
 527.298 +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
 527.299 +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
 527.300 +.ui-datepicker .ui-datepicker-prev { left:2px; }
 527.301 +.ui-datepicker .ui-datepicker-next { right:2px; }
 527.302 +.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
 527.303 +.ui-datepicker .ui-datepicker-next-hover { right:1px; }
 527.304 +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
 527.305 +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
 527.306 +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
 527.307 +.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
 527.308 +.ui-datepicker select.ui-datepicker-month, 
 527.309 +.ui-datepicker select.ui-datepicker-year { width: 49%;}
 527.310 +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
 527.311 +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
 527.312 +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
 527.313 +.ui-datepicker td { border: 0; padding: 1px; }
 527.314 +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
 527.315 +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
 527.316 +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
 527.317 +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
 527.318 +
 527.319 +/* with multiple calendars */
 527.320 +.ui-datepicker.ui-datepicker-multi { width:auto; }
 527.321 +.ui-datepicker-multi .ui-datepicker-group { float:left; }
 527.322 +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
 527.323 +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
 527.324 +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
 527.325 +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
 527.326 +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
 527.327 +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
 527.328 +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
 527.329 +.ui-datepicker-row-break { clear:both; width:100%; }
 527.330 +
 527.331 +/* RTL support */
 527.332 +.ui-datepicker-rtl { direction: rtl; }
 527.333 +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
 527.334 +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
 527.335 +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
 527.336 +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
 527.337 +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
 527.338 +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
 527.339 +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
 527.340 +.ui-datepicker-rtl .ui-datepicker-group { float:right; }
 527.341 +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
 527.342 +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
 527.343 +
 527.344 +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
 527.345 +.ui-datepicker-cover {
 527.346 +    display: none; /*sorry for IE5*/
 527.347 +    display/**/: block; /*sorry for IE5*/
 527.348 +    position: absolute; /*must have*/
 527.349 +    z-index: -1; /*must have*/
 527.350 +    filter: mask(); /*must have*/
 527.351 +    top: -4px; /*must have*/
 527.352 +    left: -4px; /*must have*/
 527.353 +    width: 200px; /*must have*/
 527.354 +    height: 200px; /*must have*/
 527.355 +}/* Dialog
 527.356 +----------------------------------*/
 527.357 +.ui-dialog { position: relative; padding: .2em; width: 300px; }
 527.358 +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
 527.359 +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
 527.360 +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
 527.361 +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
 527.362 +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
 527.363 +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
 527.364 +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
 527.365 +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
 527.366 +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
 527.367 +.ui-draggable .ui-dialog-titlebar { cursor: move; }
 527.368 +/* Progressbar
 527.369 +----------------------------------*/
 527.370 +.ui-progressbar { height:2em; text-align: left; }
 527.371 +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
 527.372 +----------------------------------*/
 527.373 +.ui-resizable { position: relative;}
 527.374 +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
 527.375 +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
 527.376 +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
 527.377 +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
 527.378 +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
 527.379 +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
 527.380 +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
 527.381 +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
 527.382 +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
 527.383 +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
 527.384 +----------------------------------*/
 527.385 +.ui-slider { position: relative; text-align: left; }
 527.386 +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
 527.387 +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
 527.388 +
 527.389 +.ui-slider-horizontal { height: .8em; }
 527.390 +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
 527.391 +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
 527.392 +.ui-slider-horizontal .ui-slider-range-min { left: 0; }
 527.393 +.ui-slider-horizontal .ui-slider-range-max { right: 0; }
 527.394 +
 527.395 +.ui-slider-vertical { width: .8em; height: 100px; }
 527.396 +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
 527.397 +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
 527.398 +.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
 527.399 +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
 527.400 +----------------------------------*/
 527.401 +.ui-tabs { padding: .2em; zoom: 1; }
 527.402 +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
 527.403 +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
 527.404 +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
 527.405 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
 527.406 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
 527.407 +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
 527.408 +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
 527.409 +.ui-tabs .ui-tabs-hide { display: none !important; }
   528.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   528.2 +++ b/web/static/css/ui/themes/isi/ui.accordion.css	Mon Apr 26 11:16:23 2010 +0200
   528.3 @@ -0,0 +1,9 @@
   528.4 +/* Accordion
   528.5 +----------------------------------*/
   528.6 +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
   528.7 +.ui-accordion .ui-accordion-li-fix { display: inline; }
   528.8 +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
   528.9 +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
  528.10 +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
  528.11 +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
  528.12 +.ui-accordion .ui-accordion-content-active { display: block; }
  528.13 \ No newline at end of file
   529.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   529.2 +++ b/web/static/css/ui/themes/isi/ui.all.css	Mon Apr 26 11:16:23 2010 +0200
   529.3 @@ -0,0 +1,2 @@
   529.4 +@import "ui.base.css";
   529.5 +@import "ui.theme.css";
   530.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   530.2 +++ b/web/static/css/ui/themes/isi/ui.base.css	Mon Apr 26 11:16:23 2010 +0200
   530.3 @@ -0,0 +1,8 @@
   530.4 +@import url("ui.core.css");
   530.5 +@import url("ui.resizable.css");
   530.6 +@import url("ui.accordion.css");
   530.7 +@import url("ui.dialog.css");
   530.8 +@import url("ui.slider.css");
   530.9 +@import url("ui.tabs.css");
  530.10 +@import url("ui.datepicker.css");
  530.11 +@import url("ui.progressbar.css");
  530.12 \ No newline at end of file
   531.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   531.2 +++ b/web/static/css/ui/themes/isi/ui.core.css	Mon Apr 26 11:16:23 2010 +0200
   531.3 @@ -0,0 +1,37 @@
   531.4 +/*
   531.5 +* jQuery UI CSS Framework
   531.6 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
   531.7 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
   531.8 +*/
   531.9 +
  531.10 +/* Layout helpers
  531.11 +----------------------------------*/
  531.12 +.ui-helper-hidden { display: none; }
  531.13 +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
  531.14 +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
  531.15 +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  531.16 +.ui-helper-clearfix { display: inline-block; }
  531.17 +/* required comment for clearfix to work in Opera \*/
  531.18 +* html .ui-helper-clearfix { height:1%; }
  531.19 +.ui-helper-clearfix { display:block; }
  531.20 +/* end clearfix */
  531.21 +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
  531.22 +
  531.23 +
  531.24 +/* Interaction Cues
  531.25 +----------------------------------*/
  531.26 +.ui-state-disabled { cursor: default !important; }
  531.27 +
  531.28 +
  531.29 +/* Icons
  531.30 +----------------------------------*/
  531.31 +
  531.32 +/* states and images */
  531.33 +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
  531.34 +
  531.35 +
  531.36 +/* Misc visuals
  531.37 +----------------------------------*/
  531.38 +
  531.39 +/* Overlays */
  531.40 +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
  531.41 \ No newline at end of file
   532.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   532.2 +++ b/web/static/css/ui/themes/isi/ui.datepicker.css	Mon Apr 26 11:16:23 2010 +0200
   532.3 @@ -0,0 +1,62 @@
   532.4 +/* Datepicker
   532.5 +----------------------------------*/
   532.6 +.ui-datepicker { width: 17em; padding: .2em .2em 0; }
   532.7 +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
   532.8 +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
   532.9 +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
  532.10 +.ui-datepicker .ui-datepicker-prev { left:2px; }
  532.11 +.ui-datepicker .ui-datepicker-next { right:2px; }
  532.12 +.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
  532.13 +.ui-datepicker .ui-datepicker-next-hover { right:1px; }
  532.14 +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
  532.15 +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
  532.16 +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
  532.17 +.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
  532.18 +.ui-datepicker select.ui-datepicker-month, 
  532.19 +.ui-datepicker select.ui-datepicker-year { width: 49%;}
  532.20 +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
  532.21 +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
  532.22 +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
  532.23 +.ui-datepicker td { border: 0; padding: 1px; }
  532.24 +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
  532.25 +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
  532.26 +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
  532.27 +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
  532.28 +
  532.29 +/* with multiple calendars */
  532.30 +.ui-datepicker.ui-datepicker-multi { width:auto; }
  532.31 +.ui-datepicker-multi .ui-datepicker-group { float:left; }
  532.32 +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
  532.33 +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
  532.34 +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
  532.35 +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
  532.36 +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
  532.37 +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
  532.38 +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
  532.39 +.ui-datepicker-row-break { clear:both; width:100%; }
  532.40 +
  532.41 +/* RTL support */
  532.42 +.ui-datepicker-rtl { direction: rtl; }
  532.43 +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
  532.44 +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
  532.45 +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
  532.46 +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
  532.47 +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
  532.48 +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
  532.49 +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
  532.50 +.ui-datepicker-rtl .ui-datepicker-group { float:right; }
  532.51 +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
  532.52 +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
  532.53 +
  532.54 +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
  532.55 +.ui-datepicker-cover {
  532.56 +    display: none; /*sorry for IE5*/
  532.57 +    display/**/: block; /*sorry for IE5*/
  532.58 +    position: absolute; /*must have*/
  532.59 +    z-index: -1; /*must have*/
  532.60 +    filter: mask(); /*must have*/
  532.61 +    top: -4px; /*must have*/
  532.62 +    left: -4px; /*must have*/
  532.63 +    width: 200px; /*must have*/
  532.64 +    height: 200px; /*must have*/
  532.65 +}
  532.66 \ No newline at end of file
   533.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   533.2 +++ b/web/static/css/ui/themes/isi/ui.progressbar.css	Mon Apr 26 11:16:23 2010 +0200
   533.3 @@ -0,0 +1,4 @@
   533.4 +/* Progressbar
   533.5 +----------------------------------*/
   533.6 +.ui-progressbar { height:2em; text-align: left; }
   533.7 +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
   533.8 \ No newline at end of file
   534.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   534.2 +++ b/web/static/css/ui/themes/isi/ui.resizable.css	Mon Apr 26 11:16:23 2010 +0200
   534.3 @@ -0,0 +1,13 @@
   534.4 +/* Resizable
   534.5 +----------------------------------*/
   534.6 +.ui-resizable { position: relative;}
   534.7 +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
   534.8 +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
   534.9 +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
  534.10 +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
  534.11 +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
  534.12 +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
  534.13 +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
  534.14 +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
  534.15 +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
  534.16 +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
  534.17 \ No newline at end of file
   535.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   535.2 +++ b/web/static/css/ui/themes/isi/ui.slider.css	Mon Apr 26 11:16:23 2010 +0200
   535.3 @@ -0,0 +1,17 @@
   535.4 +/* Slider
   535.5 +----------------------------------*/
   535.6 +.ui-slider { position: relative; text-align: left; }
   535.7 +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
   535.8 +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
   535.9 +
  535.10 +.ui-slider-horizontal { height: .8em; }
  535.11 +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
  535.12 +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
  535.13 +.ui-slider-horizontal .ui-slider-range-min { left: 0; }
  535.14 +.ui-slider-horizontal .ui-slider-range-max { right: 0; }
  535.15 +
  535.16 +.ui-slider-vertical { width: .8em; height: 100px; }
  535.17 +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
  535.18 +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
  535.19 +.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
  535.20 +.ui-slider-vertical .ui-slider-range-max { top: 0; }
  535.21 \ No newline at end of file
   536.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   536.2 +++ b/web/static/css/ui/themes/isi/ui.tabs.css	Mon Apr 26 11:16:23 2010 +0200
   536.3 @@ -0,0 +1,11 @@
   536.4 +/* Tabs
   536.5 +----------------------------------*/
   536.6 +.ui-tabs { padding: .2em; zoom: 1; }
   536.7 +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
   536.8 +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
   536.9 +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
  536.10 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
  536.11 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
  536.12 +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
  536.13 +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
  536.14 +.ui-tabs .ui-tabs-hide { display: none !important; }
   537.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   537.2 +++ b/web/static/css/ui/themes/isi/ui.theme.css	Mon Apr 26 11:16:23 2010 +0200
   537.3 @@ -0,0 +1,247 @@
   537.4 +
   537.5 +
   537.6 +
   537.7 +
   537.8 +/*
   537.9 +* jQuery UI CSS Framework
  537.10 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
  537.11 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
  537.12 +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=cae960&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=eee&fcContent=222222&iconColorContent=222222&bgColorDefault=467656&bgTextureDefault=01_flat.png&bgImgOpacityDefault=100&borderColorDefault=d3d3d3&fcDefault=ede8e3&iconColorDefault=f5f3ef&bgColorHover=f0f7e9&bgTextureHover=01_flat.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fef5c3&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=efd748&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=ddd936&bgTextureError=05_inset_soft.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
  537.13 +*/
  537.14 +
  537.15 +
  537.16 +/* Component containers
  537.17 +----------------------------------*/
  537.18 +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
  537.19 +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
  537.20 +.ui-widget-content { border: 1px solid #eee; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
  537.21 +.ui-widget-content a { color: #222222; }
  537.22 +.ui-widget-header { border: 1px solid #aaa; background: #cae960 url(images/ui-bg_highlight-soft_75_cae960_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
  537.23 +.ui-widget-header a { color: #222222; }
  537.24 +
  537.25 +/* Interaction states
  537.26 +----------------------------------*/
  537.27 +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #d3d3d3; background: #467656 url(images/ui-bg_flat_100_467656_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #ede8e3; outline: none; }
  537.28 +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ede8e3; text-decoration: none; outline: none; }
  537.29 +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #f0f7e9 url(images/ui-bg_flat_75_f0f7e9_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
  537.30 +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; outline: none; }
  537.31 +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; outline: none; }
  537.32 +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; outline: none; text-decoration: none; }
  537.33 +
  537.34 +/* Interaction Cues
  537.35 +----------------------------------*/
  537.36 +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #efd748; background: #fef5c3 url(images/ui-bg_glass_55_fef5c3_1x400.png) 50% 50% repeat-x; color: #363636; }
  537.37 +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
  537.38 +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #ddd936 url(images/ui-bg_inset-soft_95_ddd936_1x100.png) 50% bottom repeat-x; color: #cd0a0a; }
  537.39 +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; }
  537.40 +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; }
  537.41 +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
  537.42 +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
  537.43 +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
  537.44 +
  537.45 +/* Icons
  537.46 +----------------------------------*/
  537.47 +
  537.48 +/* states and images */
  537.49 +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
  537.50 +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  537.51 +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  537.52 +.ui-state-default .ui-icon { background-image: url(images/ui-icons_f5f3ef_256x240.png); }
  537.53 +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
  537.54 +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
  537.55 +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
  537.56 +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
  537.57 +
  537.58 +/* positioning */
  537.59 +.ui-icon-carat-1-n { background-position: 0 0; }
  537.60 +.ui-icon-carat-1-ne { background-position: -16px 0; }
  537.61 +.ui-icon-carat-1-e { background-position: -32px 0; }
  537.62 +.ui-icon-carat-1-se { background-position: -48px 0; }
  537.63 +.ui-icon-carat-1-s { background-position: -64px 0; }
  537.64 +.ui-icon-carat-1-sw { background-position: -80px 0; }
  537.65 +.ui-icon-carat-1-w { background-position: -96px 0; }
  537.66 +.ui-icon-carat-1-nw { background-position: -112px 0; }
  537.67 +.ui-icon-carat-2-n-s { background-position: -128px 0; }
  537.68 +.ui-icon-carat-2-e-w { background-position: -144px 0; }
  537.69 +.ui-icon-triangle-1-n { background-position: 0 -16px; }
  537.70 +.ui-icon-triangle-1-ne { background-position: -16px -16px; }
  537.71 +.ui-icon-triangle-1-e { background-position: -32px -16px; }
  537.72 +.ui-icon-triangle-1-se { background-position: -48px -16px; }
  537.73 +.ui-icon-triangle-1-s { background-position: -64px -16px; }
  537.74 +.ui-icon-triangle-1-sw { background-position: -80px -16px; }
  537.75 +.ui-icon-triangle-1-w { background-position: -96px -16px; }
  537.76 +.ui-icon-triangle-1-nw { background-position: -112px -16px; }
  537.77 +.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
  537.78 +.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
  537.79 +.ui-icon-arrow-1-n { background-position: 0 -32px; }
  537.80 +.ui-icon-arrow-1-ne { background-position: -16px -32px; }
  537.81 +.ui-icon-arrow-1-e { background-position: -32px -32px; }
  537.82 +.ui-icon-arrow-1-se { background-position: -48px -32px; }
  537.83 +.ui-icon-arrow-1-s { background-position: -64px -32px; }
  537.84 +.ui-icon-arrow-1-sw { background-position: -80px -32px; }
  537.85 +.ui-icon-arrow-1-w { background-position: -96px -32px; }
  537.86 +.ui-icon-arrow-1-nw { background-position: -112px -32px; }
  537.87 +.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
  537.88 +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
  537.89 +.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
  537.90 +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
  537.91 +.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
  537.92 +.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
  537.93 +.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
  537.94 +.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
  537.95 +.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
  537.96 +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
  537.97 +.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
  537.98 +.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
  537.99 +.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
 537.100 +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
 537.101 +.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
 537.102 +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
 537.103 +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
 537.104 +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
 537.105 +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
 537.106 +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
 537.107 +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
 537.108 +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
 537.109 +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
 537.110 +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
 537.111 +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
 537.112 +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
 537.113 +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
 537.114 +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
 537.115 +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
 537.116 +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
 537.117 +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
 537.118 +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
 537.119 +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
 537.120 +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
 537.121 +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
 537.122 +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
 537.123 +.ui-icon-arrow-4 { background-position: 0 -80px; }
 537.124 +.ui-icon-arrow-4-diag { background-position: -16px -80px; }
 537.125 +.ui-icon-extlink { background-position: -32px -80px; }
 537.126 +.ui-icon-newwin { background-position: -48px -80px; }
 537.127 +.ui-icon-refresh { background-position: -64px -80px; }
 537.128 +.ui-icon-shuffle { background-position: -80px -80px; }
 537.129 +.ui-icon-transfer-e-w { background-position: -96px -80px; }
 537.130 +.ui-icon-transferthick-e-w { background-position: -112px -80px; }
 537.131 +.ui-icon-folder-collapsed { background-position: 0 -96px; }
 537.132 +.ui-icon-folder-open { background-position: -16px -96px; }
 537.133 +.ui-icon-document { background-position: -32px -96px; }
 537.134 +.ui-icon-document-b { background-position: -48px -96px; }
 537.135 +.ui-icon-note { background-position: -64px -96px; }
 537.136 +.ui-icon-mail-closed { background-position: -80px -96px; }
 537.137 +.ui-icon-mail-open { background-position: -96px -96px; }
 537.138 +.ui-icon-suitcase { background-position: -112px -96px; }
 537.139 +.ui-icon-comment { background-position: -128px -96px; }
 537.140 +.ui-icon-person { background-position: -144px -96px; }
 537.141 +.ui-icon-print { background-position: -160px -96px; }
 537.142 +.ui-icon-trash { background-position: -176px -96px; }
 537.143 +.ui-icon-locked { background-position: -192px -96px; }
 537.144 +.ui-icon-unlocked { background-position: -208px -96px; }
 537.145 +.ui-icon-bookmark { background-position: -224px -96px; }
 537.146 +.ui-icon-tag { background-position: -240px -96px; }
 537.147 +.ui-icon-home { background-position: 0 -112px; }
 537.148 +.ui-icon-flag { background-position: -16px -112px; }
 537.149 +.ui-icon-calendar { background-position: -32px -112px; }
 537.150 +.ui-icon-cart { background-position: -48px -112px; }
 537.151 +.ui-icon-pencil { background-position: -64px -112px; }
 537.152 +.ui-icon-clock { background-position: -80px -112px; }
 537.153 +.ui-icon-disk { background-position: -96px -112px; }
 537.154 +.ui-icon-calculator { background-position: -112px -112px; }
 537.155 +.ui-icon-zoomin { background-position: -128px -112px; }
 537.156 +.ui-icon-zoomout { background-position: -144px -112px; }
 537.157 +.ui-icon-search { background-position: -160px -112px; }
 537.158 +.ui-icon-wrench { background-position: -176px -112px; }
 537.159 +.ui-icon-gear { background-position: -192px -112px; }
 537.160 +.ui-icon-heart { background-position: -208px -112px; }
 537.161 +.ui-icon-star { background-position: -224px -112px; }
 537.162 +.ui-icon-link { background-position: -240px -112px; }
 537.163 +.ui-icon-cancel { background-position: 0 -128px; }
 537.164 +.ui-icon-plus { background-position: -16px -128px; }
 537.165 +.ui-icon-plusthick { background-position: -32px -128px; }
 537.166 +.ui-icon-minus { background-position: -48px -128px; }
 537.167 +.ui-icon-minusthick { background-position: -64px -128px; }
 537.168 +.ui-icon-close { background-position: -80px -128px; }
 537.169 +.ui-icon-closethick { background-position: -96px -128px; }
 537.170 +.ui-icon-key { background-position: -112px -128px; }
 537.171 +.ui-icon-lightbulb { background-position: -128px -128px; }
 537.172 +.ui-icon-scissors { background-position: -144px -128px; }
 537.173 +.ui-icon-clipboard { background-position: -160px -128px; }
 537.174 +.ui-icon-copy { background-position: -176px -128px; }
 537.175 +.ui-icon-contact { background-position: -192px -128px; }
 537.176 +.ui-icon-image { background-position: -208px -128px; }
 537.177 +.ui-icon-video { background-position: -224px -128px; }
 537.178 +.ui-icon-script { background-position: -240px -128px; }
 537.179 +.ui-icon-alert { background-position: 0 -144px; }
 537.180 +.ui-icon-info { background-position: -16px -144px; }
 537.181 +.ui-icon-notice { background-position: -32px -144px; }
 537.182 +.ui-icon-help { background-position: -48px -144px; }
 537.183 +.ui-icon-check { background-position: -64px -144px; }
 537.184 +.ui-icon-bullet { background-position: -80px -144px; }
 537.185 +.ui-icon-radio-off { background-position: -96px -144px; }
 537.186 +.ui-icon-radio-on { background-position: -112px -144px; }
 537.187 +.ui-icon-pin-w { background-position: -128px -144px; }
 537.188 +.ui-icon-pin-s { background-position: -144px -144px; }
 537.189 +.ui-icon-play { background-position: 0 -160px; }
 537.190 +.ui-icon-pause { background-position: -16px -160px; }
 537.191 +.ui-icon-seek-next { background-position: -32px -160px; }
 537.192 +.ui-icon-seek-prev { background-position: -48px -160px; }
 537.193 +.ui-icon-seek-end { background-position: -64px -160px; }
 537.194 +.ui-icon-seek-first { background-position: -80px -160px; }
 537.195 +.ui-icon-stop { background-position: -96px -160px; }
 537.196 +.ui-icon-eject { background-position: -112px -160px; }
 537.197 +.ui-icon-volume-off { background-position: -128px -160px; }
 537.198 +.ui-icon-volume-on { background-position: -144px -160px; }
 537.199 +.ui-icon-power { background-position: 0 -176px; }
 537.200 +.ui-icon-signal-diag { background-position: -16px -176px; }
 537.201 +.ui-icon-signal { background-position: -32px -176px; }
 537.202 +.ui-icon-battery-0 { background-position: -48px -176px; }
 537.203 +.ui-icon-battery-1 { background-position: -64px -176px; }
 537.204 +.ui-icon-battery-2 { background-position: -80px -176px; }
 537.205 +.ui-icon-battery-3 { background-position: -96px -176px; }
 537.206 +.ui-icon-circle-plus { background-position: 0 -192px; }
 537.207 +.ui-icon-circle-minus { background-position: -16px -192px; }
 537.208 +.ui-icon-circle-close { background-position: -32px -192px; }
 537.209 +.ui-icon-circle-triangle-e { background-position: -48px -192px; }
 537.210 +.ui-icon-circle-triangle-s { background-position: -64px -192px; }
 537.211 +.ui-icon-circle-triangle-w { background-position: -80px -192px; }
 537.212 +.ui-icon-circle-triangle-n { background-position: -96px -192px; }
 537.213 +.ui-icon-circle-arrow-e { background-position: -112px -192px; }
 537.214 +.ui-icon-circle-arrow-s { background-position: -128px -192px; }
 537.215 +.ui-icon-circle-arrow-w { background-position: -144px -192px; }
 537.216 +.ui-icon-circle-arrow-n { background-position: -160px -192px; }
 537.217 +.ui-icon-circle-zoomin { background-position: -176px -192px; }
 537.218 +.ui-icon-circle-zoomout { background-position: -192px -192px; }
 537.219 +.ui-icon-circle-check { background-position: -208px -192px; }
 537.220 +.ui-icon-circlesmall-plus { background-position: 0 -208px; }
 537.221 +.ui-icon-circlesmall-minus { background-position: -16px -208px; }
 537.222 +.ui-icon-circlesmall-close { background-position: -32px -208px; }
 537.223 +.ui-icon-squaresmall-plus { background-position: -48px -208px; }
 537.224 +.ui-icon-squaresmall-minus { background-position: -64px -208px; }
 537.225 +.ui-icon-squaresmall-close { background-position: -80px -208px; }
 537.226 +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
 537.227 +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
 537.228 +.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
 537.229 +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
 537.230 +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
 537.231 +.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
 537.232 +
 537.233 +
 537.234 +/* Misc visuals
 537.235 +----------------------------------*/
 537.236 +
 537.237 +/* Corner radius */
 537.238 +.ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; }
 537.239 +.ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; }
 537.240 +.ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }
 537.241 +.ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; }
 537.242 +.ui-corner-top { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; }
 537.243 +.ui-corner-bottom { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; }
 537.244 +.ui-corner-right {  -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; }
 537.245 +.ui-corner-left { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; }
 537.246 +.ui-corner-all { -moz-border-radius: 6px; -webkit-border-radius: 6px; }
 537.247 +
 537.248 +/* Overlays */
 537.249 +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
 537.250 +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }
 537.251 \ No newline at end of file
   538.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png has changed
   539.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png has changed
   540.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_flat_10_000000_40x100.png has changed
   541.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_glass_100_f6f6f6_1x400.png has changed
   542.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_glass_100_fdf5ce_1x400.png has changed
   543.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_glass_65_ffffff_1x400.png has changed
   544.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_gloss-wave_35_f6a828_500x100.png has changed
   545.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_highlight-soft_100_eeeeee_1x100.png has changed
   546.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-bg_highlight-soft_75_ffe45c_1x100.png has changed
   547.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-icons_222222_256x240.png has changed
   548.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-icons_228ef1_256x240.png has changed
   549.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-icons_ef8c08_256x240.png has changed
   550.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-icons_ffd27a_256x240.png has changed
   551.1 Binary file web/static/css/ui/themes/ui-lightness/images/ui-icons_ffffff_256x240.png has changed
   552.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   552.2 +++ b/web/static/css/ui/themes/ui-lightness/jquery-ui-1.7.2.custom.css	Mon Apr 26 11:16:23 2010 +0200
   552.3 @@ -0,0 +1,406 @@
   552.4 +/*
   552.5 +* jQuery UI CSS Framework
   552.6 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
   552.7 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
   552.8 +*/
   552.9 +
  552.10 +/* Layout helpers
  552.11 +----------------------------------*/
  552.12 +.ui-helper-hidden { display: none; }
  552.13 +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
  552.14 +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
  552.15 +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  552.16 +.ui-helper-clearfix { display: inline-block; }
  552.17 +/* required comment for clearfix to work in Opera \*/
  552.18 +* html .ui-helper-clearfix { height:1%; }
  552.19 +.ui-helper-clearfix { display:block; }
  552.20 +/* end clearfix */
  552.21 +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
  552.22 +
  552.23 +
  552.24 +/* Interaction Cues
  552.25 +----------------------------------*/
  552.26 +.ui-state-disabled { cursor: default !important; }
  552.27 +
  552.28 +
  552.29 +/* Icons
  552.30 +----------------------------------*/
  552.31 +
  552.32 +/* states and images */
  552.33 +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
  552.34 +
  552.35 +
  552.36 +/* Misc visuals
  552.37 +----------------------------------*/
  552.38 +
  552.39 +/* Overlays */
  552.40 +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
  552.41 +
  552.42 +
  552.43 +
  552.44 +/*
  552.45 +* jQuery UI CSS Framework
  552.46 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
  552.47 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
  552.48 +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
  552.49 +*/
  552.50 +
  552.51 +
  552.52 +/* Component containers
  552.53 +----------------------------------*/
  552.54 +.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
  552.55 +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
  552.56 +.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
  552.57 +.ui-widget-content a { color: #333333; }
  552.58 +.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
  552.59 +.ui-widget-header a { color: #ffffff; }
  552.60 +
  552.61 +/* Interaction states
  552.62 +----------------------------------*/
  552.63 +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; outline: none; }
  552.64 +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; outline: none; }
  552.65 +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; outline: none; }
  552.66 +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; outline: none; }
  552.67 +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; outline: none; }
  552.68 +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; outline: none; text-decoration: none; }
  552.69 +
  552.70 +/* Interaction Cues
  552.71 +----------------------------------*/
  552.72 +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
  552.73 +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
  552.74 +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
  552.75 +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #ffffff; }
  552.76 +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #ffffff; }
  552.77 +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
  552.78 +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
  552.79 +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
  552.80 +
  552.81 +/* Icons
  552.82 +----------------------------------*/
  552.83 +
  552.84 +/* states and images */
  552.85 +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
  552.86 +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  552.87 +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
  552.88 +.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
  552.89 +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
  552.90 +.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
  552.91 +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
  552.92 +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
  552.93 +
  552.94 +/* positioning */
  552.95 +.ui-icon-carat-1-n { background-position: 0 0; }
  552.96 +.ui-icon-carat-1-ne { background-position: -16px 0; }
  552.97 +.ui-icon-carat-1-e { background-position: -32px 0; }
  552.98 +.ui-icon-carat-1-se { background-position: -48px 0; }
  552.99 +.ui-icon-carat-1-s { background-position: -64px 0; }
 552.100 +.ui-icon-carat-1-sw { background-position: -80px 0; }
 552.101 +.ui-icon-carat-1-w { background-position: -96px 0; }
 552.102 +.ui-icon-carat-1-nw { background-position: -112px 0; }
 552.103 +.ui-icon-carat-2-n-s { background-position: -128px 0; }
 552.104 +.ui-icon-carat-2-e-w { background-position: -144px 0; }
 552.105 +.ui-icon-triangle-1-n { background-position: 0 -16px; }
 552.106 +.ui-icon-triangle-1-ne { background-position: -16px -16px; }
 552.107 +.ui-icon-triangle-1-e { background-position: -32px -16px; }
 552.108 +.ui-icon-triangle-1-se { background-position: -48px -16px; }
 552.109 +.ui-icon-triangle-1-s { background-position: -64px -16px; }
 552.110 +.ui-icon-triangle-1-sw { background-position: -80px -16px; }
 552.111 +.ui-icon-triangle-1-w { background-position: -96px -16px; }
 552.112 +.ui-icon-triangle-1-nw { background-position: -112px -16px; }
 552.113 +.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
 552.114 +.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
 552.115 +.ui-icon-arrow-1-n { background-position: 0 -32px; }
 552.116 +.ui-icon-arrow-1-ne { background-position: -16px -32px; }
 552.117 +.ui-icon-arrow-1-e { background-position: -32px -32px; }
 552.118 +.ui-icon-arrow-1-se { background-position: -48px -32px; }
 552.119 +.ui-icon-arrow-1-s { background-position: -64px -32px; }
 552.120 +.ui-icon-arrow-1-sw { background-position: -80px -32px; }
 552.121 +.ui-icon-arrow-1-w { background-position: -96px -32px; }
 552.122 +.ui-icon-arrow-1-nw { background-position: -112px -32px; }
 552.123 +.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
 552.124 +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
 552.125 +.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
 552.126 +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
 552.127 +.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
 552.128 +.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
 552.129 +.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
 552.130 +.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
 552.131 +.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
 552.132 +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
 552.133 +.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
 552.134 +.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
 552.135 +.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
 552.136 +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
 552.137 +.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
 552.138 +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
 552.139 +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
 552.140 +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
 552.141 +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
 552.142 +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
 552.143 +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
 552.144 +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
 552.145 +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
 552.146 +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
 552.147 +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
 552.148 +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
 552.149 +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
 552.150 +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
 552.151 +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
 552.152 +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
 552.153 +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
 552.154 +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
 552.155 +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
 552.156 +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
 552.157 +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
 552.158 +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
 552.159 +.ui-icon-arrow-4 { background-position: 0 -80px; }
 552.160 +.ui-icon-arrow-4-diag { background-position: -16px -80px; }
 552.161 +.ui-icon-extlink { background-position: -32px -80px; }
 552.162 +.ui-icon-newwin { background-position: -48px -80px; }
 552.163 +.ui-icon-refresh { background-position: -64px -80px; }
 552.164 +.ui-icon-shuffle { background-position: -80px -80px; }
 552.165 +.ui-icon-transfer-e-w { background-position: -96px -80px; }
 552.166 +.ui-icon-transferthick-e-w { background-position: -112px -80px; }
 552.167 +.ui-icon-folder-collapsed { background-position: 0 -96px; }
 552.168 +.ui-icon-folder-open { background-position: -16px -96px; }
 552.169 +.ui-icon-document { background-position: -32px -96px; }
 552.170 +.ui-icon-document-b { background-position: -48px -96px; }
 552.171 +.ui-icon-note { background-position: -64px -96px; }
 552.172 +.ui-icon-mail-closed { background-position: -80px -96px; }
 552.173 +.ui-icon-mail-open { background-position: -96px -96px; }
 552.174 +.ui-icon-suitcase { background-position: -112px -96px; }
 552.175 +.ui-icon-comment { background-position: -128px -96px; }
 552.176 +.ui-icon-person { background-position: -144px -96px; }
 552.177 +.ui-icon-print { background-position: -160px -96px; }
 552.178 +.ui-icon-trash { background-position: -176px -96px; }
 552.179 +.ui-icon-locked { background-position: -192px -96px; }
 552.180 +.ui-icon-unlocked { background-position: -208px -96px; }
 552.181 +.ui-icon-bookmark { background-position: -224px -96px; }
 552.182 +.ui-icon-tag { background-position: -240px -96px; }
 552.183 +.ui-icon-home { background-position: 0 -112px; }
 552.184 +.ui-icon-flag { background-position: -16px -112px; }
 552.185 +.ui-icon-calendar { background-position: -32px -112px; }
 552.186 +.ui-icon-cart { background-position: -48px -112px; }
 552.187 +.ui-icon-pencil { background-position: -64px -112px; }
 552.188 +.ui-icon-clock { background-position: -80px -112px; }
 552.189 +.ui-icon-disk { background-position: -96px -112px; }
 552.190 +.ui-icon-calculator { background-position: -112px -112px; }
 552.191 +.ui-icon-zoomin { background-position: -128px -112px; }
 552.192 +.ui-icon-zoomout { background-position: -144px -112px; }
 552.193 +.ui-icon-search { background-position: -160px -112px; }
 552.194 +.ui-icon-wrench { background-position: -176px -112px; }
 552.195 +.ui-icon-gear { background-position: -192px -112px; }
 552.196 +.ui-icon-heart { background-position: -208px -112px; }
 552.197 +.ui-icon-star { background-position: -224px -112px; }
 552.198 +.ui-icon-link { background-position: -240px -112px; }
 552.199 +.ui-icon-cancel { background-position: 0 -128px; }
 552.200 +.ui-icon-plus { background-position: -16px -128px; }
 552.201 +.ui-icon-plusthick { background-position: -32px -128px; }
 552.202 +.ui-icon-minus { background-position: -48px -128px; }
 552.203 +.ui-icon-minusthick { background-position: -64px -128px; }
 552.204 +.ui-icon-close { background-position: -80px -128px; }
 552.205 +.ui-icon-closethick { background-position: -96px -128px; }
 552.206 +.ui-icon-key { background-position: -112px -128px; }
 552.207 +.ui-icon-lightbulb { background-position: -128px -128px; }
 552.208 +.ui-icon-scissors { background-position: -144px -128px; }
 552.209 +.ui-icon-clipboard { background-position: -160px -128px; }
 552.210 +.ui-icon-copy { background-position: -176px -128px; }
 552.211 +.ui-icon-contact { background-position: -192px -128px; }
 552.212 +.ui-icon-image { background-position: -208px -128px; }
 552.213 +.ui-icon-video { background-position: -224px -128px; }
 552.214 +.ui-icon-script { background-position: -240px -128px; }
 552.215 +.ui-icon-alert { background-position: 0 -144px; }
 552.216 +.ui-icon-info { background-position: -16px -144px; }
 552.217 +.ui-icon-notice { background-position: -32px -144px; }
 552.218 +.ui-icon-help { background-position: -48px -144px; }
 552.219 +.ui-icon-check { background-position: -64px -144px; }
 552.220 +.ui-icon-bullet { background-position: -80px -144px; }
 552.221 +.ui-icon-radio-off { background-position: -96px -144px; }
 552.222 +.ui-icon-radio-on { background-position: -112px -144px; }
 552.223 +.ui-icon-pin-w { background-position: -128px -144px; }
 552.224 +.ui-icon-pin-s { background-position: -144px -144px; }
 552.225 +.ui-icon-play { background-position: 0 -160px; }
 552.226 +.ui-icon-pause { background-position: -16px -160px; }
 552.227 +.ui-icon-seek-next { background-position: -32px -160px; }
 552.228 +.ui-icon-seek-prev { background-position: -48px -160px; }
 552.229 +.ui-icon-seek-end { background-position: -64px -160px; }
 552.230 +.ui-icon-seek-first { background-position: -80px -160px; }
 552.231 +.ui-icon-stop { background-position: -96px -160px; }
 552.232 +.ui-icon-eject { background-position: -112px -160px; }
 552.233 +.ui-icon-volume-off { background-position: -128px -160px; }
 552.234 +.ui-icon-volume-on { background-position: -144px -160px; }
 552.235 +.ui-icon-power { background-position: 0 -176px; }
 552.236 +.ui-icon-signal-diag { background-position: -16px -176px; }
 552.237 +.ui-icon-signal { background-position: -32px -176px; }
 552.238 +.ui-icon-battery-0 { background-position: -48px -176px; }
 552.239 +.ui-icon-battery-1 { background-position: -64px -176px; }
 552.240 +.ui-icon-battery-2 { background-position: -80px -176px; }
 552.241 +.ui-icon-battery-3 { background-position: -96px -176px; }
 552.242 +.ui-icon-circle-plus { background-position: 0 -192px; }
 552.243 +.ui-icon-circle-minus { background-position: -16px -192px; }
 552.244 +.ui-icon-circle-close { background-position: -32px -192px; }
 552.245 +.ui-icon-circle-triangle-e { background-position: -48px -192px; }
 552.246 +.ui-icon-circle-triangle-s { background-position: -64px -192px; }
 552.247 +.ui-icon-circle-triangle-w { background-position: -80px -192px; }
 552.248 +.ui-icon-circle-triangle-n { background-position: -96px -192px; }
 552.249 +.ui-icon-circle-arrow-e { background-position: -112px -192px; }
 552.250 +.ui-icon-circle-arrow-s { background-position: -128px -192px; }
 552.251 +.ui-icon-circle-arrow-w { background-position: -144px -192px; }
 552.252 +.ui-icon-circle-arrow-n { background-position: -160px -192px; }
 552.253 +.ui-icon-circle-zoomin { background-position: -176px -192px; }
 552.254 +.ui-icon-circle-zoomout { background-position: -192px -192px; }
 552.255 +.ui-icon-circle-check { background-position: -208px -192px; }
 552.256 +.ui-icon-circlesmall-plus { background-position: 0 -208px; }
 552.257 +.ui-icon-circlesmall-minus { background-position: -16px -208px; }
 552.258 +.ui-icon-circlesmall-close { background-position: -32px -208px; }
 552.259 +.ui-icon-squaresmall-plus { background-position: -48px -208px; }
 552.260 +.ui-icon-squaresmall-minus { background-position: -64px -208px; }
 552.261 +.ui-icon-squaresmall-close { background-position: -80px -208px; }
 552.262 +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
 552.263 +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
 552.264 +.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
 552.265 +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
 552.266 +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
 552.267 +.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
 552.268 +
 552.269 +
 552.270 +/* Misc visuals
 552.271 +----------------------------------*/
 552.272 +
 552.273 +/* Corner radius */
 552.274 +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }
 552.275 +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
 552.276 +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
 552.277 +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 552.278 +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
 552.279 +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 552.280 +.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 552.281 +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
 552.282 +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
 552.283 +
 552.284 +/* Overlays */
 552.285 +.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
 552.286 +.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; }/* Accordion
 552.287 +----------------------------------*/
 552.288 +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
 552.289 +.ui-accordion .ui-accordion-li-fix { display: inline; }
 552.290 +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
 552.291 +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
 552.292 +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
 552.293 +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
 552.294 +.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
 552.295 +----------------------------------*/
 552.296 +.ui-datepicker { width: 17em; padding: .2em .2em 0; }
 552.297 +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
 552.298 +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
 552.299 +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
 552.300 +.ui-datepicker .ui-datepicker-prev { left:2px; }
 552.301 +.ui-datepicker .ui-datepicker-next { right:2px; }
 552.302 +.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
 552.303 +.ui-datepicker .ui-datepicker-next-hover { right:1px; }
 552.304 +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
 552.305 +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
 552.306 +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
 552.307 +.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
 552.308 +.ui-datepicker select.ui-datepicker-month, 
 552.309 +.ui-datepicker select.ui-datepicker-year { width: 49%;}
 552.310 +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
 552.311 +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
 552.312 +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
 552.313 +.ui-datepicker td { border: 0; padding: 1px; }
 552.314 +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
 552.315 +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
 552.316 +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
 552.317 +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
 552.318 +
 552.319 +/* with multiple calendars */
 552.320 +.ui-datepicker.ui-datepicker-multi { width:auto; }
 552.321 +.ui-datepicker-multi .ui-datepicker-group { float:left; }
 552.322 +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
 552.323 +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
 552.324 +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
 552.325 +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
 552.326 +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
 552.327 +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
 552.328 +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
 552.329 +.ui-datepicker-row-break { clear:both; width:100%; }
 552.330 +
 552.331 +/* RTL support */
 552.332 +.ui-datepicker-rtl { direction: rtl; }
 552.333 +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
 552.334 +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
 552.335 +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
 552.336 +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
 552.337 +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
 552.338 +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
 552.339 +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
 552.340 +.ui-datepicker-rtl .ui-datepicker-group { float:right; }
 552.341 +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
 552.342 +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
 552.343 +
 552.344 +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
 552.345 +.ui-datepicker-cover {
 552.346 +    display: none; /*sorry for IE5*/
 552.347 +    display/**/: block; /*sorry for IE5*/
 552.348 +    position: absolute; /*must have*/
 552.349 +    z-index: -1; /*must have*/
 552.350 +    filter: mask(); /*must have*/
 552.351 +    top: -4px; /*must have*/
 552.352 +    left: -4px; /*must have*/
 552.353 +    width: 200px; /*must have*/
 552.354 +    height: 200px; /*must have*/
 552.355 +}/* Dialog
 552.356 +----------------------------------*/
 552.357 +.ui-dialog { position: relative; padding: .2em; width: 300px; }
 552.358 +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative;  }
 552.359 +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } 
 552.360 +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
 552.361 +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
 552.362 +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
 552.363 +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
 552.364 +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
 552.365 +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
 552.366 +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
 552.367 +.ui-draggable .ui-dialog-titlebar { cursor: move; }
 552.368 +/* Progressbar
 552.369 +----------------------------------*/
 552.370 +.ui-progressbar { height:2em; text-align: left; }
 552.371 +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
 552.372 +----------------------------------*/
 552.373 +.ui-resizable { position: relative;}
 552.374 +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
 552.375 +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
 552.376 +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
 552.377 +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
 552.378 +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
 552.379 +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
 552.380 +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
 552.381 +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
 552.382 +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
 552.383 +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
 552.384 +----------------------------------*/
 552.385 +.ui-slider { position: relative; text-align: left; }
 552.386 +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
 552.387 +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
 552.388 +
 552.389 +.ui-slider-horizontal { height: .8em; }
 552.390 +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
 552.391 +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
 552.392 +.ui-slider-horizontal .ui-slider-range-min { left: 0; }
 552.393 +.ui-slider-horizontal .ui-slider-range-max { right: 0; }
 552.394 +
 552.395 +.ui-slider-vertical { width: .8em; height: 100px; }
 552.396 +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
 552.397 +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
 552.398 +.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
 552.399 +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
 552.400 +----------------------------------*/
 552.401 +.ui-tabs { padding: .2em; zoom: 1; }
 552.402 +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
 552.403 +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
 552.404 +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
 552.405 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
 552.406 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
 552.407 +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
 552.408 +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
 552.409 +.ui-tabs .ui-tabs-hide { display: none !important; }
   553.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   553.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.accordion.css	Mon Apr 26 11:16:23 2010 +0200
   553.3 @@ -0,0 +1,9 @@
   553.4 +/* Accordion
   553.5 +----------------------------------*/
   553.6 +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
   553.7 +.ui-accordion .ui-accordion-li-fix { display: inline; }
   553.8 +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
   553.9 +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
  553.10 +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
  553.11 +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
  553.12 +.ui-accordion .ui-accordion-content-active { display: block; }
  553.13 \ No newline at end of file
   554.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   554.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.all.css	Mon Apr 26 11:16:23 2010 +0200
   554.3 @@ -0,0 +1,2 @@
   554.4 +@import "ui.base.css";
   554.5 +@import "ui.theme.css";
   555.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   555.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.base.css	Mon Apr 26 11:16:23 2010 +0200
   555.3 @@ -0,0 +1,8 @@
   555.4 +@import url("ui.core.css");
   555.5 +@import url("ui.resizable.css");
   555.6 +@import url("ui.accordion.css");
   555.7 +@import url("ui.dialog.css");
   555.8 +@import url("ui.slider.css");
   555.9 +@import url("ui.tabs.css");
  555.10 +@import url("ui.datepicker.css");
  555.11 +@import url("ui.progressbar.css");
  555.12 \ No newline at end of file
   556.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   556.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.core.css	Mon Apr 26 11:16:23 2010 +0200
   556.3 @@ -0,0 +1,37 @@
   556.4 +/*
   556.5 +* jQuery UI CSS Framework
   556.6 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
   556.7 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
   556.8 +*/
   556.9 +
  556.10 +/* Layout helpers
  556.11 +----------------------------------*/
  556.12 +.ui-helper-hidden { display: none; }
  556.13 +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
  556.14 +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
  556.15 +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  556.16 +.ui-helper-clearfix { display: inline-block; }
  556.17 +/* required comment for clearfix to work in Opera \*/
  556.18 +* html .ui-helper-clearfix { height:1%; }
  556.19 +.ui-helper-clearfix { display:block; }
  556.20 +/* end clearfix */
  556.21 +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
  556.22 +
  556.23 +
  556.24 +/* Interaction Cues
  556.25 +----------------------------------*/
  556.26 +.ui-state-disabled { cursor: default !important; }
  556.27 +
  556.28 +
  556.29 +/* Icons
  556.30 +----------------------------------*/
  556.31 +
  556.32 +/* states and images */
  556.33 +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
  556.34 +
  556.35 +
  556.36 +/* Misc visuals
  556.37 +----------------------------------*/
  556.38 +
  556.39 +/* Overlays */
  556.40 +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
  556.41 \ No newline at end of file
   557.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   557.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.datepicker.css	Mon Apr 26 11:16:23 2010 +0200
   557.3 @@ -0,0 +1,62 @@
   557.4 +/* Datepicker
   557.5 +----------------------------------*/
   557.6 +.ui-datepicker { width: 17em; padding: .2em .2em 0; }
   557.7 +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
   557.8 +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
   557.9 +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
  557.10 +.ui-datepicker .ui-datepicker-prev { left:2px; }
  557.11 +.ui-datepicker .ui-datepicker-next { right:2px; }
  557.12 +.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
  557.13 +.ui-datepicker .ui-datepicker-next-hover { right:1px; }
  557.14 +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px;  }
  557.15 +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
  557.16 +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
  557.17 +.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
  557.18 +.ui-datepicker select.ui-datepicker-month, 
  557.19 +.ui-datepicker select.ui-datepicker-year { width: 49%;}
  557.20 +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
  557.21 +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
  557.22 +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0;  }
  557.23 +.ui-datepicker td { border: 0; padding: 1px; }
  557.24 +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
  557.25 +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
  557.26 +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
  557.27 +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
  557.28 +
  557.29 +/* with multiple calendars */
  557.30 +.ui-datepicker.ui-datepicker-multi { width:auto; }
  557.31 +.ui-datepicker-multi .ui-datepicker-group { float:left; }
  557.32 +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
  557.33 +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
  557.34 +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
  557.35 +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
  557.36 +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
  557.37 +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
  557.38 +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
  557.39 +.ui-datepicker-row-break { clear:both; width:100%; }
  557.40 +
  557.41 +/* RTL support */
  557.42 +.ui-datepicker-rtl { direction: rtl; }
  557.43 +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
  557.44 +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
  557.45 +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
  557.46 +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
  557.47 +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
  557.48 +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
  557.49 +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
  557.50 +.ui-datepicker-rtl .ui-datepicker-group { float:right; }
  557.51 +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
  557.52 +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
  557.53 +
  557.54 +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
  557.55 +.ui-datepicker-cover {
  557.56 +    display: none; /*sorry for IE5*/
  557.57 +    display/**/: block; /*sorry for IE5*/
  557.58 +    position: absolute; /*must have*/
  557.59 +    z-index: -1; /*must have*/
  557.60 +    filter: mask(); /*must have*/
  557.61 +    top: -4px; /*must have*/
  557.62 +    left: -4px; /*must have*/
  557.63 +    width: 200px; /*must have*/
  557.64 +    height: 200px; /*must have*/
  557.65 +}
  557.66 \ No newline at end of file
   558.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   558.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.progressbar.css	Mon Apr 26 11:16:23 2010 +0200
   558.3 @@ -0,0 +1,4 @@
   558.4 +/* Progressbar
   558.5 +----------------------------------*/
   558.6 +.ui-progressbar { height:2em; text-align: left; }
   558.7 +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
   558.8 \ No newline at end of file
   559.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   559.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.resizable.css	Mon Apr 26 11:16:23 2010 +0200
   559.3 @@ -0,0 +1,13 @@
   559.4 +/* Resizable
   559.5 +----------------------------------*/
   559.6 +.ui-resizable { position: relative;}
   559.7 +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
   559.8 +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
   559.9 +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
  559.10 +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
  559.11 +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
  559.12 +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
  559.13 +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
  559.14 +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
  559.15 +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
  559.16 +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
  559.17 \ No newline at end of file
   560.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   560.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.slider.css	Mon Apr 26 11:16:23 2010 +0200
   560.3 @@ -0,0 +1,17 @@
   560.4 +/* Slider
   560.5 +----------------------------------*/
   560.6 +.ui-slider { position: relative; text-align: left; }
   560.7 +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
   560.8 +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
   560.9 +
  560.10 +.ui-slider-horizontal { height: .8em; }
  560.11 +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
  560.12 +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
  560.13 +.ui-slider-horizontal .ui-slider-range-min { left: 0; }
  560.14 +.ui-slider-horizontal .ui-slider-range-max { right: 0; }
  560.15 +
  560.16 +.ui-slider-vertical { width: .8em; height: 100px; }
  560.17 +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
  560.18 +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
  560.19 +.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
  560.20 +.ui-slider-vertical .ui-slider-range-max { top: 0; }
  560.21 \ No newline at end of file
   561.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   561.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.tabs.css	Mon Apr 26 11:16:23 2010 +0200
   561.3 @@ -0,0 +1,11 @@
   561.4 +/* Tabs
   561.5 +----------------------------------*/
   561.6 +.ui-tabs { padding: .2em; zoom: 1; }
   561.7 +.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
   561.8 +.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
   561.9 +.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
  561.10 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
  561.11 +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
  561.12 +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
  561.13 +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
  561.14 +.ui-tabs .ui-tabs-hide { display: none !important; }
   562.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   562.2 +++ b/web/static/css/ui/themes/ui-lightness/ui.theme.css	Mon Apr 26 11:16:23 2010 +0200
   562.3 @@ -0,0 +1,247 @@
   562.4 +
   562.5 +
   562.6 +
   562.7 +
   562.8 +/*
   562.9 +* jQuery UI CSS Framework
  562.10 +* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
  562.11 +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
  562.12 +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
  562.13 +*/
  562.14 +
  562.15 +
  562.16 +/* Component containers
  562.17 +----------------------------------*/
  562.18 +.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
  562.19 +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
  562.20 +.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
  562.21 +.ui-widget-content a { color: #333333; }
  562.22 +.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
  562.23 +.ui-widget-header a { color: #ffffff; }
  562.24 +
  562.25 +/* Interaction states
  562.26 +----------------------------------*/
  562.27 +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; outline: none; }
  562.28 +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; outline: none; }
  562.29 +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; outline: none; }
  562.30 +.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; outline: none; }
  562.31 +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; outline: none; }
  562.32 +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; outline: none; text-decoration: none; }
  562.33 +
  562.34 +/* Interaction Cues
  562.35 +----------------------------------*/
  562.36 +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
  562.37 +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
  562.38 +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
  562.39 +.ui-state-error a, .ui-widget-content .ui-state-error a { color: #ffffff; }
  562.40 +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #ffffff; }
  562.41 +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
  562.42 +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
  562.43 +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
  562.44 +
  562.45 +/* Icons
  562.46 +----------------------------------*/
  562.47 +
  562.48 +/* states and images */
  562.49 +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
  562.50 +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
  562.51 +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
  562.52 +.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
  562.53 +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
  562.54 +.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
  562.55 +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
  562.56 +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
  562.57 +
  562.58 +/* positioning */
  562.59 +.ui-icon-carat-1-n { background-position: 0 0; }
  562.60 +.ui-icon-carat-1-ne { background-position: -16px 0; }
  562.61 +.ui-icon-carat-1-e { background-position: -32px 0; }
  562.62 +.ui-icon-carat-1-se { background-position: -48px 0; }
  562.63 +.ui-icon-carat-1-s { background-position: -64px 0; }
  562.64 +.ui-icon-carat-1-sw { background-position: -80px 0; }
  562.65 +.ui-icon-carat-1-w { background-position: -96px 0; }
  562.66 +.ui-icon-carat-1-nw { background-position: -112px 0; }
  562.67 +.ui-icon-carat-2-n-s { background-position: -128px 0; }
  562.68 +.ui-icon-carat-2-e-w { background-position: -144px 0; }
  562.69 +.ui-icon-triangle-1-n { background-position: 0 -16px; }
  562.70 +.ui-icon-triangle-1-ne { background-position: -16px -16px; }
  562.71 +.ui-icon-triangle-1-e { background-position: -32px -16px; }
  562.72 +.ui-icon-triangle-1-se { background-position: -48px -16px; }
  562.73 +.ui-icon-triangle-1-s { background-position: -64px -16px; }
  562.74 +.ui-icon-triangle-1-sw { background-position: -80px -16px; }
  562.75 +.ui-icon-triangle-1-w { background-position: -96px -16px; }
  562.76 +.ui-icon-triangle-1-nw { background-position: -112px -16px; }
  562.77 +.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
  562.78 +.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
  562.79 +.ui-icon-arrow-1-n { background-position: 0 -32px; }
  562.80 +.ui-icon-arrow-1-ne { background-position: -16px -32px; }
  562.81 +.ui-icon-arrow-1-e { background-position: -32px -32px; }
  562.82 +.ui-icon-arrow-1-se { background-position: -48px -32px; }
  562.83 +.ui-icon-arrow-1-s { background-position: -64px -32px; }
  562.84 +.ui-icon-arrow-1-sw { background-position: -80px -32px; }
  562.85 +.ui-icon-arrow-1-w { background-position: -96px -32px; }
  562.86 +.ui-icon-arrow-1-nw { background-position: -112px -32px; }
  562.87 +.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
  562.88 +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
  562.89 +.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
  562.90 +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
  562.91 +.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
  562.92 +.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
  562.93 +.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
  562.94 +.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
  562.95 +.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
  562.96 +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
  562.97 +.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
  562.98 +.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
  562.99 +.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
 562.100 +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
 562.101 +.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
 562.102 +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
 562.103 +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
 562.104 +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
 562.105 +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
 562.106 +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
 562.107 +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
 562.108 +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
 562.109 +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
 562.110 +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
 562.111 +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
 562.112 +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
 562.113 +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
 562.114 +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
 562.115 +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
 562.116 +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
 562.117 +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
 562.118 +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
 562.119 +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
 562.120 +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
 562.121 +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
 562.122 +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
 562.123 +.ui-icon-arrow-4 { background-position: 0 -80px; }
 562.124 +.ui-icon-arrow-4-diag { background-position: -16px -80px; }
 562.125 +.ui-icon-extlink { background-position: -32px -80px; }
 562.126 +.ui-icon-newwin { background-position: -48px -80px; }
 562.127 +.ui-icon-refresh { background-position: -64px -80px; }
 562.128 +.ui-icon-shuffle { background-position: -80px -80px; }
 562.129 +.ui-icon-transfer-e-w { background-position: -96px -80px; }
 562.130 +.ui-icon-transferthick-e-w { background-position: -112px -80px; }
 562.131 +.ui-icon-folder-collapsed { background-position: 0 -96px; }
 562.132 +.ui-icon-folder-open { background-position: -16px -96px; }
 562.133 +.ui-icon-document { background-position: -32px -96px; }
 562.134 +.ui-icon-document-b { background-position: -48px -96px; }
 562.135 +.ui-icon-note { background-position: -64px -96px; }
 562.136 +.ui-icon-mail-closed { background-position: -80px -96px; }
 562.137 +.ui-icon-mail-open { background-position: -96px -96px; }
 562.138 +.ui-icon-suitcase { background-position: -112px -96px; }
 562.139 +.ui-icon-comment { background-position: -128px -96px; }
 562.140 +.ui-icon-person { background-position: -144px -96px; }
 562.141 +.ui-icon-print { background-position: -160px -96px; }
 562.142 +.ui-icon-trash { background-position: -176px -96px; }
 562.143 +.ui-icon-locked { background-position: -192px -96px; }
 562.144 +.ui-icon-unlocked { background-position: -208px -96px; }
 562.145 +.ui-icon-bookmark { background-position: -224px -96px; }
 562.146 +.ui-icon-tag { background-position: -240px -96px; }
 562.147 +.ui-icon-home { background-position: 0 -112px; }
 562.148 +.ui-icon-flag { background-position: -16px -112px; }
 562.149 +.ui-icon-calendar { background-position: -32px -112px; }
 562.150 +.ui-icon-cart { background-position: -48px -112px; }
 562.151 +.ui-icon-pencil { background-position: -64px -112px; }
 562.152 +.ui-icon-clock { background-position: -80px -112px; }
 562.153 +.ui-icon-disk { background-position: -96px -112px; }
 562.154 +.ui-icon-calculator { background-position: -112px -112px; }
 562.155 +.ui-icon-zoomin { background-position: -128px -112px; }
 562.156 +.ui-icon-zoomout { background-position: -144px -112px; }
 562.157 +.ui-icon-search { background-position: -160px -112px; }
 562.158 +.ui-icon-wrench { background-position: -176px -112px; }
 562.159 +.ui-icon-gear { background-position: -192px -112px; }
 562.160 +.ui-icon-heart { background-position: -208px -112px; }
 562.161 +.ui-icon-star { background-position: -224px -112px; }
 562.162 +.ui-icon-link { background-position: -240px -112px; }
 562.163 +.ui-icon-cancel { background-position: 0 -128px; }
 562.164 +.ui-icon-plus { background-position: -16px -128px; }
 562.165 +.ui-icon-plusthick { background-position: -32px -128px; }
 562.166 +.ui-icon-minus { background-position: -48px -128px; }
 562.167 +.ui-icon-minusthick { background-position: -64px -128px; }
 562.168 +.ui-icon-close { background-position: -80px -128px; }
 562.169 +.ui-icon-closethick { background-position: -96px -128px; }
 562.170 +.ui-icon-key { background-position: -112px -128px; }
 562.171 +.ui-icon-lightbulb { background-position: -128px -128px; }
 562.172 +.ui-icon-scissors { background-position: -144px -128px; }
 562.173 +.ui-icon-clipboard { background-position: -160px -128px; }
 562.174 +.ui-icon-copy { background-position: -176px -128px; }
 562.175 +.ui-icon-contact { background-position: -192px -128px; }
 562.176 +.ui-icon-image { background-position: -208px -128px; }
 562.177 +.ui-icon-video { background-position: -224px -128px; }
 562.178 +.ui-icon-script { background-position: -240px -128px; }
 562.179 +.ui-icon-alert { background-position: 0 -144px; }
 562.180 +.ui-icon-info { background-position: -16px -144px; }
 562.181 +.ui-icon-notice { background-position: -32px -144px; }
 562.182 +.ui-icon-help { background-position: -48px -144px; }
 562.183 +.ui-icon-check { background-position: -64px -144px; }
 562.184 +.ui-icon-bullet { background-position: -80px -144px; }
 562.185 +.ui-icon-radio-off { background-position: -96px -144px; }
 562.186 +.ui-icon-radio-on { background-position: -112px -144px; }
 562.187 +.ui-icon-pin-w { background-position: -128px -144px; }
 562.188 +.ui-icon-pin-s { background-position: -144px -144px; }
 562.189 +.ui-icon-play { background-position: 0 -160px; }
 562.190 +.ui-icon-pause { background-position: -16px -160px; }
 562.191 +.ui-icon-seek-next { background-position: -32px -160px; }
 562.192 +.ui-icon-seek-prev { background-position: -48px -160px; }
 562.193 +.ui-icon-seek-end { background-position: -64px -160px; }
 562.194 +.ui-icon-seek-first { background-position: -80px -160px; }
 562.195 +.ui-icon-stop { background-position: -96px -160px; }
 562.196 +.ui-icon-eject { background-position: -112px -160px; }
 562.197 +.ui-icon-volume-off { background-position: -128px -160px; }
 562.198 +.ui-icon-volume-on { background-position: -144px -160px; }
 562.199 +.ui-icon-power { background-position: 0 -176px; }
 562.200 +.ui-icon-signal-diag { background-position: -16px -176px; }
 562.201 +.ui-icon-signal { background-position: -32px -176px; }
 562.202 +.ui-icon-battery-0 { background-position: -48px -176px; }
 562.203 +.ui-icon-battery-1 { background-position: -64px -176px; }
 562.204 +.ui-icon-battery-2 { background-position: -80px -176px; }
 562.205 +.ui-icon-battery-3 { background-position: -96px -176px; }
 562.206 +.ui-icon-circle-plus { background-position: 0 -192px; }
 562.207 +.ui-icon-circle-minus { background-position: -16px -192px; }
 562.208 +.ui-icon-circle-close { background-position: -32px -192px; }
 562.209 +.ui-icon-circle-triangle-e { background-position: -48px -192px; }
 562.210 +.ui-icon-circle-triangle-s { background-position: -64px -192px; }
 562.211 +.ui-icon-circle-triangle-w { background-position: -80px -192px; }
 562.212 +.ui-icon-circle-triangle-n { background-position: -96px -192px; }
 562.213 +.ui-icon-circle-arrow-e { background-position: -112px -192px; }
 562.214 +.ui-icon-circle-arrow-s { background-position: -128px -192px; }
 562.215 +.ui-icon-circle-arrow-w { background-position: -144px -192px; }
 562.216 +.ui-icon-circle-arrow-n { background-position: -160px -192px; }
 562.217 +.ui-icon-circle-zoomin { background-position: -176px -192px; }
 562.218 +.ui-icon-circle-zoomout { background-position: -192px -192px; }
 562.219 +.ui-icon-circle-check { background-position: -208px -192px; }
 562.220 +.ui-icon-circlesmall-plus { background-position: 0 -208px; }
 562.221 +.ui-icon-circlesmall-minus { background-position: -16px -208px; }
 562.222 +.ui-icon-circlesmall-close { background-position: -32px -208px; }
 562.223 +.ui-icon-squaresmall-plus { background-position: -48px -208px; }
 562.224 +.ui-icon-squaresmall-minus { background-position: -64px -208px; }
 562.225 +.ui-icon-squaresmall-close { background-position: -80px -208px; }
 562.226 +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
 562.227 +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
 562.228 +.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
 562.229 +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
 562.230 +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
 562.231 +.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
 562.232 +
 562.233 +
 562.234 +/* Misc visuals
 562.235 +----------------------------------*/
 562.236 +
 562.237 +/* Corner radius */
 562.238 +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }
 562.239 +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
 562.240 +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
 562.241 +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 562.242 +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
 562.243 +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 562.244 +.ui-corner-right {  -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
 562.245 +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
 562.246 +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
 562.247 +
 562.248 +/* Overlays */
 562.249 +.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
 562.250 +.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; }
 562.251 \ No newline at end of file
   563.1 Binary file web/static/images/Sorting icons.psd has changed
   564.1 Binary file web/static/images/back_disabled.jpg has changed
   565.1 Binary file web/static/images/back_enabled.jpg has changed
   566.1 Binary file web/static/images/forward_disabled.jpg has changed
   567.1 Binary file web/static/images/forward_enabled.jpg has changed
   568.1 Binary file web/static/images/sort_asc.jpg has changed
   569.1 Binary file web/static/images/sort_asc.png has changed
   570.1 Binary file web/static/images/sort_asc_disabled.jpg has changed
   571.1 Binary file web/static/images/sort_asc_disabled.png has changed
   572.1 Binary file web/static/images/sort_both.jpg has changed
   573.1 Binary file web/static/images/sort_both.png has changed
   574.1 Binary file web/static/images/sort_desc.jpg has changed
   575.1 Binary file web/static/images/sort_desc.png has changed
   576.1 Binary file web/static/images/sort_desc_disabled.jpg has changed
   577.1 Binary file web/static/images/sort_desc_disabled.png has changed
   578.1 Binary file web/static/img/icon_addlink.gif has changed
   579.1 Binary file web/static/img/icon_changelink.gif has changed
   580.1 Binary file web/static/img/icon_deletelink.gif has changed
   581.1 Binary file web/static/img/python-powered-w-70x28.png has changed
   582.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   582.2 +++ b/web/static/js/cluetip	Mon Apr 26 11:16:23 2010 +0200
   582.3 @@ -0,0 +1,1 @@
   582.4 +cluetip-1.0.6/
   582.5 \ No newline at end of file
   583.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   583.2 +++ b/web/static/js/cluetip-1.0.6/README	Mon Apr 26 11:16:23 2010 +0200
   583.3 @@ -0,0 +1,56 @@
   583.4 +
   583.5 +/*
   583.6 + * jQuery clueTip Plugin
   583.7 + *
   583.8 + * Dual licensed under the MIT and GPL licenses:
   583.9 + * http://www.opensource.org/licenses/mit-license.php
  583.10 + * http://www.gnu.org/licenses/gpl.html
  583.11 + *
  583.12 + * @name clueTip
  583.13 + * @type jQuery
  583.14 + * @cat Plugins/tooltip
  583.15 + * @return jQuery
  583.16 + * @author Karl Swedberg
  583.17 + *
  583.18 + * @requires jQuery v1.3+
  583.19 + *
  583.20 + * @credit Inspired by Cody Lindley's jTip (http://www.codylindley.com)
  583.21 + * @credit Thanks to the following people for their many and varied contributions:
  583.22 +      Shelane Enos, Glen Lipka, Hector Santos, Torben Schreiter, Dan G. Switzer, Jörn Zaefferer 
  583.23 + * @credit Thanks to Jonathan Chaffer, as always, for help with the hard parts. :-)
  583.24 + */
  583.25 +
  583.26 + /**
  583.27 + * 
  583.28 + * Displays a highly customizable tooltip when the user hovers (default) or clicks (optional) the matched element. 
  583.29 + * By default, the clueTip plugin loads a page indicated by the "rel" attribute via ajax and displays its contents.
  583.30 + * If a "title" attribute is specified, its value is used as the clueTip's heading.
  583.31 + * The attribute to be used for both the body and the heading of the clueTip is user-configurable. 
  583.32 + * Optionally, the clueTip's body can display content from an element on the same page.
  583.33 + * * Just indicate the element's id (e.g. "#some-id") in the rel attribute.
  583.34 + * Optionally, the clueTip's body can display content from the title attribute, when a delimiter is indicated. 
  583.35 + * * The string before the first instance of the delimiter is set as the clueTip's heading.
  583.36 + * * All subsequent strings are wrapped in separate DIVs and placed in the clueTip's body.
  583.37 + * The clueTip plugin allows for many, many more options. Please see the examples and the option descriptions below...
  583.38 + * 
  583.39 + * 
  583.40 + * @example $('#tip).cluetip();
  583.41 + * @desc This is the most basic clueTip. It displays a 275px-wide clueTip on mouseover of the element with an ID of "tip." On mouseout of the element, the clueTip is hidden.
  583.42 + *
  583.43 + *
  583.44 + * @example $('a.clue').cluetip({
  583.45 + *  hoverClass: 'highlight',
  583.46 + *  sticky: true,
  583.47 + *  closePosition: 'bottom',
  583.48 + *  closeText: '<img src="cross.png" alt="close" />',
  583.49 + *  truncate: 60,
  583.50 + *  ajaxSettings: {
  583.51 + *    type: 'POST'
  583.52 + *  }
  583.53 + * });
  583.54 + * @desc Displays a clueTip on mouseover of all <a> elements with class="clue". The hovered element gets a class of "highlight" added to it (so that it can be styled appropriately. This is esp. useful for non-anchor elements.). The clueTip is "sticky," which means that it will not be hidden until the user either clicks on its "close" text/graphic or displays another clueTip. The "close" text/graphic is set to diplay at the bottom of the clueTip (default is top) and display an image rather than the default "Close" text. Moreover, the body of the clueTip is truncated to the first 60 characters, which are followed by an ellipsis (...). Finally, the clueTip retrieves the content using POST rather than the $.ajax method's default "GET."
  583.55 + * 
  583.56 + * More examples can be found at http://plugins.learningjquery.com/cluetip/demo/
  583.57 + * 
  583.58 + * Full list of options/settings can be found at http://plugins.learningjquery.com/cluetip/
  583.59 + */
   584.1 Binary file web/static/js/cluetip-1.0.6/cluetip-1.0.6.zip has changed
   585.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   585.2 +++ b/web/static/js/cluetip-1.0.6/demo/ajax.htm	Mon Apr 26 11:16:23 2010 +0200
   585.3 @@ -0,0 +1,29 @@
   585.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   585.5 +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   585.6 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   585.7 +<head>
   585.8 +  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
   585.9 +  <title>Title</title>
  585.10 +  <style type="text/css" media="screen">
  585.11 +
  585.12 +    .float-left {
  585.13 +      float: left;
  585.14 +      margin-right: .5em;
  585.15 +      display: inline;
  585.16 +    }
  585.17 +    h2 {
  585.18 +      font-size: 1.1em;
  585.19 +    }
  585.20 +  </style>
  585.21 +
  585.22 +  
  585.23 +
  585.24 +</head>
  585.25 +<body>
  585.26 +  <h2>A Web Page</h2>
  585.27 +  <img class="float-left" src="outdoor-sculpture.jpg" alt="" width="121" height="91" />
  585.28 +  <p>This is a full web page with all the trappings. It's just a little short</p>
  585.29 +  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  585.30 +  </p>
  585.31 +</body>
  585.32 +</html>
  585.33 \ No newline at end of file
   586.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   586.2 +++ b/web/static/js/cluetip-1.0.6/demo/ajax2.htm	Mon Apr 26 11:16:23 2010 +0200
   586.3 @@ -0,0 +1,19 @@
   586.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   586.5 +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   586.6 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   586.7 +<head>
   586.8 +  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
   586.9 +  <title>some page</title>
  586.10 +
  586.11 +</head>
  586.12 +<body>
  586.13 +  <div id="someid1">
  586.14 +    <p>here is div #someid1</p>
  586.15 +    <p>text is text is text is text</p>
  586.16 +  </div>
  586.17 +  <div id="someid2">
  586.18 +    <p>here is div #someid2</p>
  586.19 +    <p>and more text inside the div</p>
  586.20 +  </div>    
  586.21 +</body>
  586.22 +</html>
  586.23 \ No newline at end of file
   587.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   587.2 +++ b/web/static/js/cluetip-1.0.6/demo/ajax3.htm	Mon Apr 26 11:16:23 2010 +0200
   587.3 @@ -0,0 +1,4 @@
   587.4 +<p>This clueTip has some <strike>nicely</strike> <strong>formatted</strong> <em>text</em>. Just kidding!
   587.5 +</p>
   587.6 +
   587.7 +
   588.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   588.2 +++ b/web/static/js/cluetip-1.0.6/demo/ajax4.htm	Mon Apr 26 11:16:23 2010 +0200
   588.3 @@ -0,0 +1,5 @@
   588.4 +
   588.5 +<p>Another clueTip? consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
   588.6 +</p>
   588.7 +
   588.8 +
   589.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   589.2 +++ b/web/static/js/cluetip-1.0.6/demo/ajax5.htm	Mon Apr 26 11:16:23 2010 +0200
   589.3 @@ -0,0 +1,6 @@
   589.4 +<p>This is another clueTip. It is here for demonstration purposes only.</p>
   589.5 +<img class="float-left" src="boy-wonder.jpg" width="65" height="65" alt="Boy Wonder" />
   589.6 +<p>Did you know that jQuery has a vibrant community of web developers and designers who discuss the library and offer help to those seeking it? You can find it at groups.google.com. Just search for jQuery.
   589.7 +</p>
   589.8 +
   589.9 +
   590.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   590.2 +++ b/web/static/js/cluetip-1.0.6/demo/ajax6.htm	Mon Apr 26 11:16:23 2010 +0200
   590.3 @@ -0,0 +1,21 @@
   590.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   590.5 +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   590.6 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   590.7 +<head>
   590.8 +  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
   590.9 +  <title>sticky option</title>
  590.10 +
  590.11 +
  590.12 +</head>
  590.13 +<body class="page">
  590.14 +  <img src="kids-drop-sand.jpg" width="65" height="65" alt="Kids Drop Sand" />
  590.15 +  <p>The sticky option is really nice when you have a clueTip with a link to <a href="http://www.learningjquery.com">learningjquery.com</a> in it (or any other site). Now, you can click the link to go somewhere else. Not that you'd want to.</p>
  590.16 +  <img src="kids-drop-sand.jpg" width="65" height="65" alt="Kids Drop Sand" />
  590.17 +  
  590.18 +  <p>Notice that this is another example of a full web page. It even has a nice photograph in it. Twice!</p>
  590.19 +</body>
  590.20 +</html>
  590.21 +
  590.22 +
  590.23 +
  590.24 +
   591.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   591.2 +++ b/web/static/js/cluetip-1.0.6/demo/ajaxclick.htm	Mon Apr 26 11:16:23 2010 +0200
   591.3 @@ -0,0 +1,6 @@
   591.4 +<img class="float-left" src="boy-wonder.jpg" width="65" height="65" alt="Boy Wonder" />
   591.5 +<p>This clueTip won't appear unless you click to activate it. And it won't go away until you click again, or until you activate another clueTip by hovering or clicking. Only one clueTip gets to show at a time.</p> 
   591.6 +<p>To learn more, visit <a href="http://www.learningjquery.com/">learningjquery.com</a>. ;-)
   591.7 +</p>
   591.8 +
   591.9 +
   592.1 Binary file web/static/js/cluetip-1.0.6/demo/boy-wonder.jpg has changed
   593.1 Binary file web/static/js/cluetip-1.0.6/demo/cross.png has changed
   594.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   594.2 +++ b/web/static/js/cluetip-1.0.6/demo/demo.css	Mon Apr 26 11:16:23 2010 +0200
   594.3 @@ -0,0 +1,115 @@
   594.4 +body {
   594.5 +  font-family: Helvetica, Verdana, sans-serif;
   594.6 +  font-size: 95%;
   594.7 +  margin: 0;
   594.8 +}
   594.9 +
  594.10 +h1 {
  594.11 +  height: 80px;
  594.12 +  font-weight: normal;
  594.13 +  padding: 20px 20px 0;
  594.14 +  margin: 0 0 .5em;
  594.15 +  color: #fff;
  594.16 +  background: #6363c1 url(headbg.jpg) repeat-x 0 0;
  594.17 +}
  594.18 +li {
  594.19 +  margin-top: .5em;
  594.20 +  margin-bottom: .5em;
  594.21 +}
  594.22 +pre, code {
  594.23 +  font-size: 1em;
  594.24 +}
  594.25 +pre {
  594.26 +  padding: .5em;
  594.27 +  background-color: #eef;
  594.28 +}
  594.29 +#navigation {
  594.30 +  float: left;
  594.31 +  list-style-type: none;
  594.32 +  margin: -60px 0 0 20px;
  594.33 +  padding-left: 0;
  594.34 +}
  594.35 +
  594.36 +#navigation li {
  594.37 +  float: left;
  594.38 +  margin: 5px 0;
  594.39 +  padding: 5px 0;
  594.40 +}
  594.41 +#navigation a {
  594.42 +  color: #fff;
  594.43 +  background: #6565c1;
  594.44 +  padding: 5px;
  594.45 +  text-decoration: none;
  594.46 +  border: 1px solid #fff;
  594.47 +}
  594.48 +#navigation a.active {
  594.49 +  color: #009;
  594.50 +  background: #fff;
  594.51 +  border: 1px solid #009;
  594.52 +  border-bottom: 1px solid #fff;
  594.53 +}
  594.54 +#container {
  594.55 +  clear: left;
  594.56 +  padding: .5em 20px 100px 20px;
  594.57 +}
  594.58 +
  594.59 +.highlight {
  594.60 +  background: #fcc;
  594.61 +}
  594.62 +.highlighter {
  594.63 +  background: #ff3;
  594.64 +}
  594.65 +.back-to-top {
  594.66 +  display: block;
  594.67 +  margin-top: 1em;
  594.68 +  width: 7em;
  594.69 +}
  594.70 +
  594.71 +.float-left {
  594.72 +  float: left;
  594.73 +  margin-right: .5em;
  594.74 +  display: inline;
  594.75 +  position: relative;
  594.76 +}
  594.77 +.float-right {
  594.78 +  float: right;
  594.79 +  margin-left: .5em;
  594.80 +  display: inline;
  594.81 +  position: relative;
  594.82 +}
  594.83 +h2 {
  594.84 +  font-size: 1.1em;
  594.85 +}
  594.86 +h3 {
  594.87 +  margin-top: 0;
  594.88 +  padding-top: 1em;
  594.89 +}
  594.90 +h4 {
  594.91 +  margin: .5em 0;
  594.92 +}
  594.93 +a {
  594.94 +  color: #009;
  594.95 +}
  594.96 +.html, .jquery {
  594.97 +  margin-top: .5em;
  594.98 +  color: #900;
  594.99 +  cursor: pointer;
 594.100 +  font-size: .9em;
 594.101 +  width: 8.5em;
 594.102 +}
 594.103 +
 594.104 +ul li {
 594.105 +  margin: .5em 0;
 594.106 +}
 594.107 +ins {
 594.108 +  text-decoration: none;
 594.109 +  color: #090;
 594.110 +}
 594.111 +#jqlogo {
 594.112 +  position:absolute;
 594.113 +  top: 10px;
 594.114 +  right: 10px;
 594.115 +}
 594.116 +#jqlogo img {
 594.117 +  border: 0;
 594.118 +}
 594.119 \ No newline at end of file
   595.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   595.2 +++ b/web/static/js/cluetip-1.0.6/demo/demo.js	Mon Apr 26 11:16:23 2010 +0200
   595.3 @@ -0,0 +1,85 @@
   595.4 +
   595.5 +/* the next line is an example of how you can override default options globally (currently commented out) ... */
   595.6 +
   595.7 + // $.fn.cluetip.defaults.tracking = true;
   595.8 +  // $.fn.cluetip.defaults.width = 'auto';
   595.9 +$(document).ready(function() {
  595.10 +
  595.11 + // $.cluetip.setup({insertionType: 'insertBefore', insertionElement: 'div:first'});
  595.12 + // $.fn.cluetip.defaults.ajaxSettings.beforeSend = function(ct) {
  595.13 + //     console.log(this);
  595.14 + // };
  595.15 +
  595.16 +//default theme
  595.17 +  $('a.title').cluetip({splitTitle: '|'});
  595.18 +  $('a.basic').cluetip();
  595.19 +  $('a.custom-width').cluetip({width: '200px', showTitle: false});
  595.20 +  $('h4').cluetip({attribute: 'id', hoverClass: 'highlight'});
  595.21 +  $('#sticky').cluetip({sticky: true, closePosition: 'title', arrows: true });
  595.22 +  $('#examples a:eq(5)').cluetip({
  595.23 +    hoverClass: 'highlight',
  595.24 +    sticky: true,
  595.25 +    closePosition: 'bottom',
  595.26 +    closeText: '<img src="cross.png" alt="close" width="16" height="16" />',
  595.27 +    truncate: 60
  595.28 +  });
  595.29 +  $('a.load-local').cluetip({local:true, hideLocal: true, sticky: true, arrows: true, cursor: 'pointer'});
  595.30 +  $('#clickme').cluetip({activation: 'click', sticky: true, width: 650});
  595.31 +  $('ol:first a:last').cluetip({tracking: true});
  595.32 +
  595.33 +// jTip theme
  595.34 +  $('a.jt:eq(0)').cluetip({
  595.35 +    cluetipClass: 'jtip', 
  595.36 +    arrows: true, 
  595.37 +    dropShadow: false,
  595.38 +    sticky: true,
  595.39 +    mouseOutClose: true,
  595.40 +    closePosition: 'title',
  595.41 +    closeText: '<img src="cross.png" alt="close" />'
  595.42 +  });
  595.43 +  $('a.jt:eq(1)').cluetip({cluetipClass: 'jtip', arrows: true, dropShadow: false, hoverIntent: false});
  595.44 +  $('span[title]').css({borderBottom: '1px solid #900'}).cluetip({splitTitle: '|', arrows: true, dropShadow: false, cluetipClass: 'jtip'});
  595.45 +
  595.46 +  $('a.jt:eq(2)').cluetip({
  595.47 +    cluetipClass: 'jtip', 
  595.48 +    arrows: true, 
  595.49 +    dropShadow: false, 
  595.50 +    height: '150px', 
  595.51 +    sticky: true,
  595.52 +    positionBy: 'bottomTop'    
  595.53 +  });
  595.54 +
  595.55 +  $('a.jt:eq(3)').cluetip({local: true, hideLocal: false});
  595.56 +  
  595.57 +  $('a.jt:eq(4)').cluetip({
  595.58 +    cluetipClass: 'jtip', arrows: true, 
  595.59 +    dropShadow: false, 
  595.60 +    onActivate: function(e) {
  595.61 +      var cb = $('#cb')[0];
  595.62 +      return !cb || cb.checked;
  595.63 +    }
  595.64 +  });
  595.65 +
  595.66 +// Rounded Corner theme
  595.67 +  $('ol.rounded a:eq(0)').cluetip({splitTitle: '|', dropShadow: false, cluetipClass: 'rounded', showtitle: false});
  595.68 +  $('ol.rounded a:eq(1)').cluetip({cluetipClass: 'rounded', dropShadow: false, showtitle: false, positionBy: 'mouse'});
  595.69 +  $('ol.rounded a:eq(2)').cluetip({cluetipClass: 'rounded', dropShadow: false, showtitle: false, positionBy: 'bottomTop', topOffset: 70});
  595.70 +  $('ol.rounded a:eq(3)').cluetip({cluetipClass: 'rounded', dropShadow: false, sticky: true, ajaxCache: false, arrows: true});
  595.71 +  $('ol.rounded a:eq(4)').cluetip({cluetipClass: 'rounded', dropShadow: false});    
  595.72 +});
  595.73 +
  595.74 +//unrelated to clueTip -- just for the demo page...
  595.75 +
  595.76 +$(document).ready(function() {
  595.77 +  $('div.html, div.jquery').next().css('display', 'none').end().click(function() {
  595.78 +    $(this).next().toggle('fast');
  595.79 +  });
  595.80 +  
  595.81 +  $('a.false').click(function() {
  595.82 +    return false;
  595.83 +  });
  595.84 +});
  595.85 +  
  595.86 +
  595.87 +
  595.88 +
   596.1 Binary file web/static/js/cluetip-1.0.6/demo/grate.jpg has changed
   597.1 Binary file web/static/js/cluetip-1.0.6/demo/grskating.jpg has changed
   598.1 Binary file web/static/js/cluetip-1.0.6/demo/handovermouth.jpg has changed
   599.1 Binary file web/static/js/cluetip-1.0.6/demo/headbg.jpg has changed
   600.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   600.2 +++ b/web/static/js/cluetip-1.0.6/demo/index.html	Mon Apr 26 11:16:23 2010 +0200
   600.3 @@ -0,0 +1,218 @@
   600.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   600.5 +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   600.6 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   600.7 +<head>
   600.8 +  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
   600.9 +  <title>clueTip Plugin Demo</title>
  600.10 +
  600.11 +  <link rel="stylesheet" href="../jquery.cluetip.css" type="text/css" />
  600.12 +  <link rel="stylesheet" href="demo.css" type="text/css" /></head>
  600.13 +
  600.14 +  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
  600.15 +  <script src="../lib/jquery.hoverIntent.js" type="text/javascript"></script>
  600.16 +  <script src="../lib/jquery.bgiframe.min.js" type="text/javascript"></script>
  600.17 +  <script src="../jquery.cluetip.js" type="text/javascript"></script>
  600.18 +  <script src="demo.js" type="text/javascript"></script>
  600.19 +<body>
  600.20 +
  600.21 +  <h1 id="top">clueTip : A jQuery Plugin</h1>
  600.22 +  <ul id="navigation">
  600.23 +    <li><a href="../#getting-started">Overview</a></li>
  600.24 +    <li><a class="active" href="/">Demo</a></li>
  600.25 +    <li><a href="../#details">Details</a></li>
  600.26 +    <li><a href="../#options">API / Options</a></li>
  600.27 +    <li><a href="../#faq">FAQ</a></li>
  600.28 +    <li><a href="../#credits">Credits</a></li>
  600.29 +    <li><a href="../#download">Download & Support</a></li>
  600.30 +  </ul>
  600.31 +  <div id="container">
  600.32 +
  600.33 +    <div id="examplesection">
  600.34 +    <h3>clueTip Plugin Demo</h3>
  600.35 +    <p>Below are quite a few examples of how you can add a clueTip to your page, using a wide range of options. Keep in mind that there is nothing magical about the HTML markup. You can use any jQuery selector you want to attach your clueTips. For example, if you want to attach clueTips to all links with a class of "peanuts," you would simply write in your jQuery code: <code>$('a.peanuts').cluetip();</code>.</p>
  600.36 +    <h4>Default Style</h4>
  600.37 +    <div id="examples"> 
  600.38 +      <ol>
  600.39 +        <li><strong>basic tip from title</strong>: <a class="title" href="#" title="This is the title|The first set of body content comes after the first delimiter in the title.|In this case, the delimiter is a pipe.">This example</a> pulls the clueTip's contents from the invoking element's title attribute via the "splitTitle" option. 
  600.40 +          <div class="html">View the HTML</div>
  600.41 +          <pre><code><a class="title" href="#" title="This is the title|The first set of contents comes after the first delimiter in the title.|In this case, the delimiter is a pipe"></code></pre>
  600.42 +          <div class="jquery">View the jQuery</div>
  600.43 +          <pre><code>$('a.title').cluetip({splitTitle: '|'});</code></pre>
  600.44 +        </li>
  600.45 +        <li><strong>basic ajax</strong>, with no title attribute: This one <a class="basic" href="ajax.htm" rel="ajax.htm">requires no options</a>.
  600.46 +          <div><select style="width: 600px"><option>no bleed-thru</option><option>in IE6</option><option>when using bgiframe plugin</option></select> </div>
  600.47 +          <div class="html">View the HTML</div>
  600.48 +          <pre><code><a class="basic" href="ajax.htm" rel="ajax.htm"></code></pre>
  600.49 +          <div class="jquery">View the jQuery</div>
  600.50 +          <pre><code>$('a.basic').cluetip();</code></pre>
  600.51 +        </li>
  600.52 +        <li><strong>custom width and hidden title bar</strong>: This tip has a custom width of 200px. The clueTip title bar (heading) is hidden. <a class="custom-width" href="ajax3.htm" rel="ajax3.htm">Try me!</a>
  600.53 +          <div class="html">View the HTML</div>
  600.54 +          <pre><code><a class="custom-width" href="ajax3.htm" rel="ajax3.htm"></code></pre>
  600.55 +          <div class="jquery">View the jQuery</div>
  600.56 +          <pre><code>$('a.custom-width').cluetip({width: '200px', showTitle: false});</code></pre>
  600.57 +        </li>
  600.58 +        <li><strong>sticky, with arrows</strong>:This sticky clueTip has its "close" text in the title bar. It won't close until you close it, or until you hover over another clue-tipped link. It also displays an arrow on one of its sides, pointing to the invoking element. <a id="sticky" href="ajax6.htm" rel="ajax6.htm">sticky clueTip with arrows</a>
  600.59 +          <div class="html">View the HTML</div>
  600.60 +          <pre><code><a id="sticky" href="ajax6.htm" rel="ajax6.htm"></code></pre>
  600.61 +          <div class="jquery">View the jQuery</div>
  600.62 +          <pre><code>$('#sticky').cluetip({sticky: true, closePosition: 'title', arrows: true});</code></pre> 
  600.63 +        </li>
  600.64 +
  600.65 +        <li><strong>non-link element, custom attribute, and hover class</strong>: Block-level items such as this <code>h4</code> have clueTips positioned by the mouse.
  600.66 +          <h4 title="Fancy Title!" id="ajax3.htm">Hover over me.</h4>
  600.67 +          <div class="html">View the HTML</div>
  600.68 +          <pre><code><h4 title="Fancy Title!" id="ajax3.htm">Hover over me</h4></code></pre>
  600.69 +          <div class="jquery">View the jQuery</div>
  600.70 +          <pre><code>$('h4').cluetip({attribute: 'id', hoverClass: 'highlight'});</code></pre>
  600.71 +        </li>
  600.72 +        <li><strong>local, with arrows</strong>:  This one uses local content from a hidden <code>div</code> element and displays an arrow that points to the invoking element: <a id="load-local" class="load-local" href="#loadme" rel="#loadme">hover for local</a>
  600.73 +          <div class="html">View the HTML</div>
  600.74 +          <pre><code><a class="load-local" href="#loadme" rel="#loadme"></code></pre>
  600.75 +          <div class="jquery">View the jQuery</div>
  600.76 +          <pre><code>$('a.load-local').cluetip({local:true, cursor: 'pointer'});</code></pre>  
  600.77 +        </li>
  600.78 +        <li><strong>sticky, truncated clueTip</strong> with custom hover class, close position, and close text (it also has a title). Its <code>href</code> is different from its <code>rel</code>, so if you <em>click</em> it, you'll go to the linked page <a href="http://www.learningjquery.com" title="about this link:" rel="ajax6.htm">hover for cluetip, click to visit URL</a> 
  600.79 +          <div class="html">View the HTML</div>
  600.80 +          <pre><code><a href="http://www.learningjquery.com" title="about this link:" rel="ajax6.htm"></code></pre>
  600.81 +          <div class="jquery">View the jQuery</div>
  600.82 +<pre><code>$('#examples a:eq(5)').cluetip({
  600.83 +  hoverClass: 'highlight',
  600.84 +  sticky: true,
  600.85 +  closePosition: 'bottom',
  600.86 +  closeText: '<img src="styles/cross.png" alt="" />'
  600.87 +  truncate: 60
  600.88 +});</code></pre>
  600.89 +        </li>
  600.90 +        <li><strong>click to activate</strong>:  This one won't show the clueTip unless you click it: <a id="clickme" href="ajaxclick.htm" rel="ajaxclick.htm" title="active ingredients">click me</a>. It's also really wide.
  600.91 +          <div class="html">View the HTML</div>
  600.92 +          <pre><code><a href="ajaxclick.htm" rel="ajax5.htm" title="active ingredients"></code></pre>
  600.93 +          <div class="jquery">View the jQuery</div>
  600.94 +          <pre><code>$('#clickme').cluetip({activation: 'click', width: 650});</code></pre>
  600.95 +        </li>
  600.96 +        <li><strong><ins>experimental</ins> mouse tracking</strong>: <a href="ajax5.htm" title="mouse tracks" rel="ajax5.htm">The clueTip will move</a> in the direction of your mouse movement, as long as you're still hovering over the invoking element.
  600.97 +          <div class="html">View the HTML</div>
  600.98 +          <pre><code><a href="ajax5.htm" title="mouse tracks" rel="ajax5.htm"></code></pre>
  600.99 +          <div class="jquery">View the jQuery</div>
 600.100 +<pre><code>$('ol:first a:last').cluetip({tracking: true});</code></pre>
 600.101 +        </li>
 600.102 +      </ol>
 600.103 +      <h4>jTip Theme</h4>
 600.104 +      <ol>
 600.105 +        <li><a class="jt" href="ajax6.htm" rel="ajax6.htm" title="jTip Style!">jTip Style clueTip</a>, with slideDown effect and an image placed in the title for closing it, because it's sticky. <br />
 600.106 +        <ins>New</ins>: The clueTip will close if you mouse out of it. 
 600.107 +          <div class="html">View the HTML</div>
 600.108 +          <pre><code><a class="jt" href="ajax6.htm" rel="ajax6.htm" title="jTip Style!"></code></pre>
 600.109 +          <div class="jquery">View the jQuery</div>
 600.110 +<pre><code>$('a.jt:eq(0)').cluetip({
 600.111 +  cluetipClass: 'jtip', 
 600.112 +  arrows: true, 
 600.113 +  dropShadow: false,
 600.114 +  hoverIntent: false,
 600.115 +  sticky: true,
 600.116 +  mouseOutClose: true,
 600.117 +  closePosition: 'title',
 600.118 +  closeText: '<img src="cross.png" alt="close" />'
 600.119 +});
 600.120 +</code></pre>
 600.121 +        </li>
 600.122 +        <li>This one has hoverIntent turned off. Look for the link floated right: <span style="float:right"><a class="jt" href="ajax5.htm" rel="ajax5.htm">jTip Style clueTip</a></span> 
 600.123 +          <div class="html">View the HTML</div>
 600.124 +          <pre><code><a class="jt" href="ajax5.htm" rel="ajax5.htm"></code></pre>
 600.125 +          <div class="jquery">View the jQuery</div>
 600.126 +<pre><code>$('a.jt:eq(1)').cluetip({cluetipClass: 'jtip', arrows: true, dropShadow: false, hoverIntent: false});
 600.127 +</code></pre>  
 600.128 +        </li>
 600.129 +        <li>This one pulls the clueTip contents directly from the <code>title</code> attribute of a <code>span</code> tag: <span title="Split Title|This clueTip's contents were created directly from the title attribute|Nice for minimum info.">splitTitle clueTip</span>
 600.130 +          <div class="html">View the HTML</div>
 600.131 +          <code><span title="Split Title|This clueTip's contents were created directly from the title attribute|Nice for minimum info."></code>
 600.132 +          <div class="jquery">View the jQuery</div>          
 600.133 +<pre><code>$('span[title]').css({borderBottom: '1px solid #900'}).cluetip({
 600.134 +  splitTitle: '|', 
 600.135 +  arrows: true, 
 600.136 +  dropShadow: false, 
 600.137 +  cluetipClass: 'jtip'}
 600.138 +);</code></pre>        
 600.139 +        </li>
 600.140 +        <li>this sticky clueTip has a <a class="jt" href="ajax5.htm" rel="ajax5.htm">fixed height</a>. It's generally a good idea to make fixed-height clueTips sticky as well, just in case the content requires a scrollbar to read it fully. It will be positioned below the clicked element unless there isn't enough room, in which case it will be positioned above.
 600.141 +          <div class="html">View the HTML</div>
 600.142 +          <pre><code><a class="jt" href="ajax5.htm" rel="ajax5.htm"></code></pre>
 600.143 +          <div class="jquery">View the jQuery</div>
 600.144 +<pre><code>$('a.jt:eq(2)').cluetip({
 600.145 +  cluetipClass: 'jtip', arrows: true, 
 600.146 +  dropShadow: false, 
 600.147 +  height: '150px', 
 600.148 +  sticky: true,
 600.149 +  positionBy: 'bottomTop'
 600.150 +});</code></pre>
 600.151 +        </li>
 600.152 +        <li>For this one, we're loading <a class="jt" href="#" rel="p.localvisible">visible local content</a>
 600.153 +        <div class="html">View the HTML</div>  
 600.154 +        <pre><code><a class="jt" href="#" rel="p.localvisible">visible local content</a></code></pre>
 600.155 +        <div class="jquery">View the jQuery</div>
 600.156 +        <pre><code>$('a.jt:eq(3)').cluetip({local: true, hideLocal: false});</code></pre>
 600.157 +        <p class="localvisible">and here is our visible local content!</p>
 600.158 +        </li>
 600.159 +        <li><a class="jt" href="ajax3.htm" rel="ajax3.htm">togglable clueTip</a> can be turned off by unchecking the checkbox<br />
 600.160 +          <input type="checkbox" name="cb" id="cb" checked="checked" /> <label for="cb">clueTips</label>
 600.161 +          <div class="html">View the HTML</div>
 600.162 +          <pre><code><a class="jt" href="ajax5.htm" rel="ajax5.htm"></code></pre>
 600.163 +          <div class="jquery">View the jQuery</div>
 600.164 +<pre><code>$('a.jt:eq(3)').cluetip({
 600.165 +  cluetipClass: 'jtip', arrows: true, 
 600.166 +  dropShadow: false, 
 600.167 +  onActivate: function(e) {
 600.168 +    var cb = $('#cb')[0];
 600.169 +    return !cb || cb.checked;
 600.170 +  }
 600.171 +});</code></pre>       
 600.172 +        </li>
 600.173 +      </ol>
 600.174 +      <h4>Rounded Corners Theme</h4>
 600.175 +      <ol class="rounded">
 600.176 +        <li><a href="ajax4.htm" title="|first line body|second line body">content from title attribute</a>, with the clueTip heading hidden. 
 600.177 +          <div class="html">View the HTML</div>
 600.178 +          <pre><code><a href="ajax4.htm" title="|first line body|second line body"></code></pre>
 600.179 +          <div class="jquery">View the jQuery</div>
 600.180 +          <pre><code>$('ol.rounded a:eq(0)').cluetip({splitTitle: '|', dropShadow: false, cluetipClass: 'rounded', showTitle: false});</code></pre>
 600.181 +        </li>
 600.182 +        <li>
 600.183 +          <a href="ajax4.htm" rel="ajax4.htm" title="mouse positioned">rounded corners theme and positioning by mouse</a>. 
 600.184 +          <div class="html">View the HTML</div>
 600.185 +          <pre><code><a href="ajax4.htm" rel="ajax4.htm" title="mouse positioned"></code></pre>
 600.186 +          <div class="jquery">View the jQuery</div>
 600.187 +          <pre><code>$('ol.rounded a:eq(1)').cluetip({
 600.188 +  cluetipClass: 'rounded', 
 600.189 +  dropShadow: false, 
 600.190 +  positionBy: 'mouse'
 600.191 +});</code></pre>
 600.192 +        </li>
 600.193 +        <li>Another one with rounded corners theme. This one has <a href="ajax4.htm" rel="ajax4.htm" title="bottom/top positioned">"bottomTop" positioning</a>: positioned under link, unless there isn't enough room (then over). It also has <strong>"topOffset" set to 70</strong>.
 600.194 +            <div class="html">View the HTML</div>
 600.195 +            <pre><code><a href="ajax4.htm" rel="ajax4.htm" title="bottom/top positioned"></code></pre>
 600.196 +            <div class="jquery">View the jQuery</div>
 600.197 +            <pre><code>$('ol.rounded a:eq(2)').cluetip({cluetipClass: 'rounded', dropShadow: false, positionBy: 'bottomTop', topOffset: 70});</code></pre>
 600.198 +        </li>
 600.199 +        <li><a href="ajax4.htm" rel="ajax4.htm" title="rounded corners">non-caching ajax clueTip with arrows enabled</a>.
 600.200 +          <div class="html">View the HTML</div>
 600.201 +          <pre><code><a href="ajax4.htm" rel="ajax4.htm" title="rounded corners"></code></pre>
 600.202 +          <div class="jquery">View the jQuery</div>
 600.203 +          <pre><code>$('ol.rounded a:eq(3)').cluetip({cluetipClass: 'rounded', dropShadow: false, sticky: true, ajaxCache: false, arrows: true});</code></pre>
 600.204 +        </li>
 600.205 +        <li><a href="ajax404.htm" rel="ajax404.htm">ajax error</a>: This one points to a file that does not exist.
 600.206 +          <div class="html">View the HTML</div>
 600.207 +          <pre><code><a href="ajax404.htm" rel="ajax404.htm"></code></pre>
 600.208 +          <div class="jquery">View the jQuery</div>
 600.209 +          <pre><code>$('ol.rounded a:eq(4)').cluetip({cluetipClass: 'rounded', dropShadow: false});</code></pre>
 600.210 +        </li>
 600.211 +      </ol>
 600.212 +      
 600.213 +    </div>  
 600.214 +    
 600.215 +    <div id="loadme">this is the <a class="false" href="http://www.learningjquery.com">local content</a> to load when the 'local' parameter is set to true.</div>
 600.216 +    </div>
 600.217 +   
 600.218 +  </div>
 600.219 +  <a href="http://jquery.com" id="jqlogo"><img src="http://www.learningjquery.com/wp-content/themes/jquery/images/jq.png" alt="jQuery web site" /></a>
 600.220 +</body>
 600.221 +</html>
 600.222 \ No newline at end of file
   601.1 Binary file web/static/js/cluetip-1.0.6/demo/kids-drop-sand.jpg has changed
   602.1 Binary file web/static/js/cluetip-1.0.6/demo/outdoor-sculpture.jpg has changed
   603.1 Binary file web/static/js/cluetip-1.0.6/demo/pixel.gif has changed
   604.1 Binary file web/static/js/cluetip-1.0.6/demo/tristan.jpg has changed
   605.1 Binary file web/static/js/cluetip-1.0.6/demo/wait.gif has changed
   606.1 Binary file web/static/js/cluetip-1.0.6/images/arrowdown.gif has changed
   607.1 Binary file web/static/js/cluetip-1.0.6/images/arrowleft.gif has changed
   608.1 Binary file web/static/js/cluetip-1.0.6/images/arrowright.gif has changed
   609.1 Binary file web/static/js/cluetip-1.0.6/images/arrowup.gif has changed
   610.1 Binary file web/static/js/cluetip-1.0.6/images/bl.gif has changed
   611.1 Binary file web/static/js/cluetip-1.0.6/images/bl.png has changed
   612.1 Binary file web/static/js/cluetip-1.0.6/images/br.gif has changed
   613.1 Binary file web/static/js/cluetip-1.0.6/images/br.png has changed
   614.1 Binary file web/static/js/cluetip-1.0.6/images/darrowdown.gif has changed
   615.1 Binary file web/static/js/cluetip-1.0.6/images/darrowleft.gif has changed
   616.1 Binary file web/static/js/cluetip-1.0.6/images/darrowright.gif has changed
   617.1 Binary file web/static/js/cluetip-1.0.6/images/darrowup.gif has changed
   618.1 Binary file web/static/js/cluetip-1.0.6/images/itunes.png has changed
   619.1 Binary file web/static/js/cluetip-1.0.6/images/rarrowdown.gif has changed
   620.1 Binary file web/static/js/cluetip-1.0.6/images/rarrowleft.gif has changed
   621.1 Binary file web/static/js/cluetip-1.0.6/images/rarrowright.gif has changed
   622.1 Binary file web/static/js/cluetip-1.0.6/images/rarrowup.gif has changed
   623.1 Binary file web/static/js/cluetip-1.0.6/images/tl.gif has changed
   624.1 Binary file web/static/js/cluetip-1.0.6/images/tl.png has changed
   625.1 Binary file web/static/js/cluetip-1.0.6/images/tr.gif has changed
   626.1 Binary file web/static/js/cluetip-1.0.6/images/tr.png has changed
   627.1 Binary file web/static/js/cluetip-1.0.6/images/wait.gif has changed
   628.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   628.2 +++ b/web/static/js/cluetip-1.0.6/index.html	Mon Apr 26 11:16:23 2010 +0200
   628.3 @@ -0,0 +1,329 @@
   628.4 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   628.5 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   628.6 +<head>
   628.7 +<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
   628.8 +<title>clueTip: A jQuery Tooltip Plugin</title>
   628.9 +<link rel="stylesheet" type="text/css" media="screen" href="../jq.css" />
  628.10 +<link rel="stylesheet" type="text/css" media="screen" href="../tabs.css" />
  628.11 +<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
  628.12 +<script type="text/javascript" src="../jquery.tabs.min.js"></script>
  628.13 +<script type="text/javascript" src="../jquery.history.pack.js"></script>
  628.14 +<script type="text/javascript" src="../chili-1.8.js"></script>
  628.15 +
  628.16 +
  628.17 +<script type="text/javascript">
  628.18 +$(function() {
  628.19 +    // initialize the tabs
  628.20 +    var main = $('#main').tabs(1);
  628.21 +    // $('#subdetails').tabs( { selectedClass: 'sample-tab-selected', bookmarkable: false });
  628.22 +});
  628.23 +</script>
  628.24 +
  628.25 +</head>
  628.26 +<body><div><a id="logo" href="http://jquery.com" title="Powered By jQuery"></a></div>
  628.27 +<h1 id="banner"><a id="backnav" href="..">‹‹ home</a>clueTip: A jQuery Tooltip Plugin</h1>
  628.28 +<div id="main">
  628.29 +  <ul id="nav" class="anchors">
  628.30 +    <li><a href="#getting-started">Overview</a></li>
  628.31 +    <li><a href="demo/">Demo</a></li>
  628.32 +    <li><a href="#details">Details</a></li>
  628.33 +    <li><a href="#options">API / Options</a></li>
  628.34 +    <li><a href="#faq">FAQ</a></li>
  628.35 +    <li><a href="#credits">Credits</a></li>
  628.36 +    <li><a href="#download">Download & Support</a></li>
  628.37 +  </ul>
  628.38 +    <div id="getting-started" class="tabContent">
  628.39 +        <h1>Overview</h1>
  628.40 +        <p>The clueTip plugin allows you to easily show a fancy tooltip when the user's mouse hovers over (or, optionally, clicks on) any element you designate in your script. If the element includes a <code>title</code> attribute, its text becomes the heading of the clueTip.</p>
  628.41 +        <p>If you like this plugin and you're feeling generous, perhaps you'd also like to visit my <a href="http://www.amazon.com/gp/registry/wishlist/1NLSYA46XTVG4/" title="Amazon.com: Wish List">amazon.com wish list</a>?</p>
  628.42 +        <h1>Quick Start Guide</h1>
  628.43 +        Showing the most basic clueTip can be achieved in two easy steps.
  628.44 +        <div class="step-one">Add HTML markup to your page for elements that you want to invoke a clueTip. By default, the clueTip plugin will use the <code>rel</code> attribute to load contents into the tooltip body via <acronym title="Asynchronous HTML and HTTP">AHAH</acronym>. </div>
  628.45 +<pre><code class="mix">
  628.46 +  <!-- use ajax/ahah to pull content from fragment.html: -->
  628.47 +  <p><a class="tips" href="fragment.html" rel="fragment.html">show me the cluetip!</a></p> 
  628.48 + 
  628.49 +  <!-- use title attribute for clueTip contents, but don't include anything in the clueTip's heading -->
  628.50 +  <p><a id="houdini" href="houdini.html" title="|Houdini was an escape artist.|He was also adept at prestidigitation.">Houdini</a></p>
  628.51 +</code></pre>
  628.52 +        <div class="step-two">Include the <strong>jQuery</strong> core file and the <strong>clueTip</strong> plugin in the <code><head></code> of your document. You may optionally include the <em>hoverIntent</em> plugin as well. After these scripts are referenced, you can reference a custom script file to invoke your clueTips (preferred) or enter the script directly in the <code><head></code> (shown below). You should also include the clueTip <strong>stylesheet</strong> (jquery.cluetip.css) after the scripts. </div>
  628.53 +        <br />
  628.54 +<pre><code class="mix"><script src="jquery.js" type="text/javascript"></script>
  628.55 +<script src="jquery.hoverIntent.js" type="text/javascript"></script> <!-- optional -->
  628.56 +<script src="jquery.cluetip.js" type="text/javascript"></script>
  628.57 +
  628.58 +<script type="text/javascript">
  628.59 +$(document).ready(function() {
  628.60 +  $('a.tips').cluetip();
  628.61 +  
  628.62 +  $('#houdini').cluetip({
  628.63 +    splitTitle: '|', // use the invoking element's title attribute to populate the clueTip...
  628.64 +                     // ...and split the contents into separate divs where there is a "|"
  628.65 +    showTitle: false // hide the clueTip's heading
  628.66 +  });
  628.67 +});
  628.68 +</script>
  628.69 +<link rel="stylesheet" href="jquery.cluetip.css" type="text/css" />
  628.70 +</code></pre>
  628.71 +      <p>You can change the default style and behavior in many ways. See <a href="#options">API / Options</a> for details.</p>
  628.72 +    </div>
  628.73 +    <div id="demo" class="tabContent"></div>
  628.74 +    <div id="details" class="tabContent">
  628.75 +      <h1>clueTip Plugin Details</h1>
  628.76 +      <div id="subdetails">
  628.77 +        <ul>
  628.78 +            <li><a href="#subdetails1">Multiple Content Sources</a></li>
  628.79 +            <li><a href="#subdetails2">Smart Positioning</a></li>
  628.80 +            <li><a href="#subdetails3">Flexible Behavior</a></li>
  628.81 +            <li><a href="#subdetails4">Style Variety</a></li>
  628.82 +        </ul>
  628.83 +
  628.84 +        <div id="subdetails1" class="sample-tab-selected sampleTabContent">
  628.85 +          <h4>Multiple Content Sources</h4>
  628.86 +          <p>The contents of the clueTip can come from one of these sources:</p>
  628.87 +          <ol>
  628.88 +            <li>a separate file, via AHAH / AJAX</li>
  628.89 +            <li>an element on the same page, typically hidden</li>
  628.90 +            <li>the title attribute, parsed by a user-defined delimiter (if the "splitTitle" option is set). The text before the first delimiter becomes the clueTip title, and the rest of the text parts are placed in <code><div class="split-body"></div></code> elements and appended to the clueTip body </li>
  628.91 +          </ol>
  628.92 +        </div>  
  628.93 +        <div id="subdetails2" class="sampleTabContent">
  628.94 +          <h4>Smart Positioning</h4>
  628.95 +          The clueTip Plugin has 4 positioning modes, which you can change via the "positionBy" option.
  628.96 +          <ol>
  628.97 +            <li><code>positionBy: 'auto'</code> (default)
  628.98 +              <ul>
  628.99 +                <li><strong>places the tooltip just to the right of the invoking element</strong>, but... </li>
 628.100 +                <li>if there is not enough room for the tooltip to be fully visible between the right edge of the invoking element and the right edge of the browser window, <strong>switches from the right side to the left side</strong>, but... </li>
 628.101 +                <li>if the invoking element is too close to the bottom edge of the browser window, <strong>adjusts the tooltip upwards until the whole tooltip is visible</strong>, but... </li>
 628.102 +                <li>if the tooltip is taller than the window (i.e. the viewable area), <strong>adjusts the tooltip back down until the tooltip's top is at the top edge of the browser window</strong>, but...</li>
 628.103 +                <li>position if the invoking element is so wide that the tooltip can't completely fit to the left or the right of it, <strong>places the tooltip to the right or left of the <em>mouse</em></strong>, but... </li>
 628.104 +                <li>if the tooltip itself can't fit to the right or left of the mouse position, <strong>places the tooltip below the mouse position (centered horizontal if enough room)</strong>, but... </li>
 628.105 +                <li>if (a) there isn't enough room below without being cut off, and (b) there is enough room between the top of the viewable area and the mouse, <strong>puts the tooltip above the mouse position</strong></li>
 628.106 +              </ul>
 628.107 +            </li>
 628.108 +            <li><code>positionBy: 'mouse'</code>
 628.109 +              <ul>
 628.110 +                <li><strong>places the tooltip to the right of the mouse position</strong>, but...</li>
 628.111 +                <li>if there is not enough room to the right, <strong>places the tooltip to the left of the mouse position</strong>, but...</li>
 628.112 +                <li>if the tooltip itself can't fit to the right or left of the mouse position, <strong>places the tooltip below the mouse position (centered horizontally if enough room)</strong>, but... </li>
 628.113 +                <li>if (a) there isn't enough room below without being cut off, and (b) there is enough room between the top of the viewable area and the mouse, <strong>puts the tooltip above the mouse position</strong></li>
 628.114 +              </ul>
 628.115 +            </li>
 628.116 +            <li><code>positionBy: 'bottomTop'</code>
 628.117 +              <ul>
 628.118 +                <li><strong>places the tooltip below the mouse position (centered horizontally if enough room)</strong>, but...</li>
 628.119 +                <li>if (a) there isn't enough room below without being cut off, and (b) there is enough room between the top of the viewable area and the mouse, <strong>puts the tooltip above the mouse position</strong></li>
 628.120 +              </ul>
 628.121 +            </li>
 628.122 +            <li><code>positionBy: 'fixed'</code>
 628.123 +              <ul>
 628.124 +                <li><strong>places the tooltip in the same location relative to the invoking element</strong>, regardless of where it appears on the page.</li>
 628.125 +                <li>the fixed position can be adjusted by modifying the number of pixels in the <code>topOffset</code> and <code>leftOffset</code> options</li>
 628.126 +              </ul>
 628.127 +            </li>
 628.128 +          </ol>
 628.129 +        </div>    
 628.130 +        <div id="subdetails3" class="sampleTabContent">
 628.131 +          <h4>Flexible Behavior</h4>
 628.132 +          <ol>
 628.133 +            <li>The clueTip takes advantage of Brian Cherne's fantastic <a href="http://cherne.net/brian/resources/jquery.hoverIntent.html" title="hoverIntent jQuery Plugin">hoverIntent plugin</a> if it's available. (Just include it in a <code><script></code> tag if you want the clueTip to use it.)</li>
 628.134 +            <li>It can be activated on hover or on click.</li>
 628.135 +            <li>It can fade in, slide down, etc.</li>
 628.136 +            <li>It can close when the invoking element is moused out or when the tooltip is moused out or when the user clicks a "close" link.</li>
 628.137 +            <li>It can cache the results of ajax requests—or not.</li>
 628.138 +            <li>It can be turned off</li>
 628.139 +          </ol>
 628.140 +        </div>
 628.141 +        <div id="subdetails4" class="sampleTabContent">
 628.142 +          <h4>Variety of Styles</h4>
 628.143 +          <p>The clueTip Plugin comes with three themes: default, jTip, and rounded corners. Additional themes can be created by following the naming patterns in the stylesheet, jquery.cluetip.css. To apply one of the alternative themes, just indicate it in the <code>cluetipClass</code> option as <code>'jtip'</code> or <code>'rounded'</code>.</p>
 628.144 +          <p>The "loading" image comes from this rule in the stylesheet: </p>
 628.145 +    <pre><code class="css">#cluetip-waitimage {
 628.146 +      width: 43px;
 628.147 +      height: 11px;
 628.148 +      position: absolute;
 628.149 +      background-image: url(wait.gif);
 628.150 +    }</code></pre>
 628.151 +          <p>It can be turned off with the following option: <code>waitImage: false</code></p>
 628.152 +          <p>Other options that affect the visual appearance include <code>hoverClass</code>, <code>arrows</code>, <code>dropShadow</code>, and <code>dropShadowSteps</code>. Please see <a href=#options>API / Options</a> for more information.</p>
 628.153 +        </div>
 628.154 +      </div>
 628.155 +    </div>    
 628.156 +    <div id="options" class="tabContent">
 628.157 +        <h1>clueTip Plugin API / Options</h1>
 628.158 +        The clueTip Plugin API provides two methods, with many options.
 628.159 +        <dl>
 628.160 +            <dt><code class="method">$.cluetip.setup(options)</code></dt>
 628.161 +            <dd>Global defaults for clueTips. Will apply to all calls to the clueTip plugin.</dd>
 628.162 +        </dl>
 628.163 +        <pre><code class="mix">{
 628.164 +          insertionType:    'appendTo', // how the clueTip is inserted into the DOM
 628.165 +                                        // possible values: 'appendTo', 'prependTo', 'insertBefore', 'insertAfter'
 628.166 +          insertionElement: 'body'      // where in the DOM the clueTip is to be inserted 
 628.167 +        }</code></pre>        
 628.168 +        <dl>
 628.169 +            <dt><code class="method">cluetip(options)</code></dt>
 628.170 +            <dd>Displays a highly customizable tooltip via ajax (default) or local content or the title attribute of the invoking element </dd>
 628.171 +        </dl>
 628.172 +<pre><code class="mix">$.fn.cluetip.defaults = {  // default options; override as needed
 628.173 +    width:            275,      // The width of the clueTip
 628.174 +    height:           'auto',   // The height of the clueTip. more info below [1]
 628.175 +    cluezIndex:       97,       // Sets the z-index style property of the clueTip
 628.176 +    positionBy:       'auto',   // Sets the type of positioning. more info below [2]
 628.177 +    topOffset:        15,       // Number of px to offset clueTip from top of invoking element. more info below [3]
 628.178 +    leftOffset:       15,       // Number of px to offset clueTip from left of invoking element. more info below [4]
 628.179 +    local:            false,    // Whether to use content from the same page for the clueTip's body
 628.180 +                                // (treats the attribute used for accessing the tip as a jQuery selector,
 628.181 +                                // but only selects the first element if the selector matches more than one). more info below [5]
 628.182 +    hideLocal:        true,     // If local option is set to true, this determines whether local content
 628.183 +                                //  to be shown in clueTip should be hidden at its original location
 628.184 +    attribute:        'rel',    // the attribute to be used for fetching the clueTip's body content
 628.185 +    titleAttribute:   'title',  // the attribute to be used for fetching the clueTip's title
 628.186 +    splitTitle:       '',       // A character used to split the title attribute into the clueTip title and divs
 628.187 +                                // within the clueTip body. more info below [6]
 628.188 +    showTitle:        true,     // show title bar of the clueTip, even if title attribute not set
 628.189 +    cluetipClass:     'default',// class added to outermost clueTip div in the form of 'cluetip-' + clueTipClass. more info below [7]
 628.190 +    hoverClass:       '',       // class applied to the invoking element onmouseover and removed onmouseout
 628.191 +    waitImage:        true,     // whether to show a "loading" img, which is set in jquery.cluetip.css
 628.192 +    arrows:           false,    // if true, displays arrow on appropriate side of clueTip. more info below [8]
 628.193 +    dropShadow:       true,     // set to false if you don't want the drop-shadow effect on the clueTip
 628.194 +    dropShadowSteps:  6,        // adjusts the size of the drop shadow
 628.195 +    sticky:           false,    // keep visible until manually closed
 628.196 +    mouseOutClose:    false,    // close when clueTip is moused out
 628.197 +    activation:       'hover',  // set to 'click' to force user to click to show clueTip
 628.198 +    clickThrough:     false,    // if true, and activation is not 'click', then clicking on a clueTipped link will take user to 
 628.199 +                                // the link's href, even if href and tipAttribute are equal
 628.200 +    tracking:         false,    // if true, clueTip will track mouse movement (experimental)
 628.201 +    delayedClose:     0,        // close clueTip on a timed delay (experimental)
 628.202 +    closePosition:    'top',    // location of close text for sticky cluetips; can be 'top' or 'bottom' or 'title'
 628.203 +    closeText:        'Close',  // text (or HTML) to to be clicked to close sticky clueTips
 628.204 +    truncate:         0,        // number of characters to truncate clueTip's contents. if 0, no truncation occurs
 628.205 +
 628.206 +    // effect and speed for opening clueTips
 628.207 +    fx: {             
 628.208 +                      open:       'show', // can be 'show' or 'slideDown' or 'fadeIn'
 628.209 +                      openSpeed:  ''
 628.210 +    },
 628.211 +                  
 628.212 +    // settings for when hoverIntent plugin is used
 628.213 +    hoverIntent: {    
 628.214 +                      sensitivity:  3,
 628.215 +                      interval:     50,
 628.216 +                      timeout:      0
 628.217 +    }, 
 628.218 +    
 628.219 +    // function to run just before clueTip is shown.            
 628.220 +    onActivate:       function(e) {return true;},
 628.221 +
 628.222 +    // function to run just after clueTip is shown.
 628.223 +    onShow:           function(ct, c){},
 628.224 +    
 628.225 +    // whether to cache results of ajax request to avoid unnecessary hits to server
 628.226 +    ajaxCache:        true,     
 628.227 +    
 628.228 +    // process data retrieved via xhr before it's displayed
 628.229 +    ajaxProcess:      function(data) {
 628.230 +                        data = $(data).not('style, meta, link, script, title');
 628.231 +                        return data;
 628.232 +    },
 628.233 +    
 628.234 +    // can pass in standard $.ajax() parameters, not including error, complete, success, and url
 628.235 +    ajaxSettings: {   
 628.236 +                      dataType: 'html'
 628.237 +    }
 628.238 +  };</code></pre>
 628.239 +   <ol>
 628.240 +    <li><strong>height</strong>: Setting a specific height also sets <div id="cluetip-outer"> to "overflow:auto"</li>
 628.241 +    <li><strong>positionBy</strong>: Available options are 'auto', 'mouse', 'bottomTop', 'fixed'.  Change to 'mouse' if you want to override positioning by element and position the clueTip based on where the mouse is instead. Change to 'bottomTop' if you want positioning to begin below the mouse when there is room or above if not -- rather than right or left of the elemnent and flush with element's top Change to 'fixed' if you want the clueTip to appear in exactly the same location relative to the linked element no matter where it appears on the page. Use 'fixed' at your own risk.</li>
 628.242 +    <li><strong>topOffset</strong>:For positionBy "auto", "mouse", and "bottomTop", the number will be added to the clueTip's "top" value if the clueTip appears below the invoking element and subtracted from it if the clueTip appears above. For positionBy "fixed", the number will always be added to the "top" value, offsetting the clueTip from the top of the invoking element.</li>
 628.243 +    <li><strong>leftOffset</strong>: For positionBy "auto", "mouse", and "bottomTop", the number will be added to clueTip's "left" value if the clueTip appears to the right of the invoking element and subtracted if the clueTip appears to the left. For positionBy "fixed", the number will always be added to the "left" value of the clueTip, offsetting it from the right side of the invoking element.</li>
 628.244 +    <li><strong>local</strong>: for example, using the default tip attribute, "rel", you could have a link — <a href="somewhere.htm" rel=".someClass"> — that would show the contents of the first element in the DOM that has a class of "someClass."</li>
 628.245 +    <li><strong>splitTitle</strong>: if used, the clueTip will be populated only by the title attribute</li>
 628.246 +    <li><strong>cluetipClass</strong>: this is also used for a "directional" class on the same div, depending on where the clueTip is in relation to the invoking element. The class appears in the form of 'cluetip-' + <em>direction</em> + <em>cluetipClass</em>. this allows you to create your own clueTip theme in a separate CSS file or use one of the three pre-packaged themes: default, jtip, or rounded.</li>
 628.247 +    <li><strong>arrows</strong>: <strong>UPDATE</strong>: this option displays a div containing an arrow background image. Arrow images are set using the background-image property in the CSS. The direction of the arrow changes depending on which side of the invoking element the clueTip appears. The arrows option sets the background-position of the cluetip div so that the arrow will accurately point to the invoking element, regardless of where it appears in relation to it.</li>
 628.248 +  </ol> 
 628.249 +    </div>
 628.250 +
 628.251 +    <div id="faq" class="tabContent">
 628.252 +        <h1>Frequently Asked Questions</h1>
 628.253 +        <dl>
 628.254 +        <dt>How is clueTip licensed?</dt>
 628.255 +        <dd>
 628.256 +          <p>The clueTip plugin is licensed the same way as the jQuery core file: under a dual MIT and GPL license. Users of the plugin can choose whichever license suits them. The top of the jquery.cluetip.js file has this notice:</p>
 628.257 +          <p>Dual licensed under the MIT and GPL licenses:<br />
 628.258 +           * http://www.opensource.org/licenses/mit-license.php<br />
 628.259 +           * http://www.gnu.org/licenses/gpl.html</p>
 628.260 +        </dd>
 628.261 +        <dt>What versions of jQuery is the clueTip Plugin compatible with?</dt>
 628.262 +        <dd>As of clueTip version 1.06, the plugin is compatible with version 1.3.2 or later. Prevsiou clueTip versions are compatible with jQuery 1.2.6 through 1.3.2 or later is recommended.</dd>
 628.263 +        <dt>Does the clueTip Plugin have any dependencies on other plugins?</dt>
 628.264 +        <dd><em>Optional</em> plugins that can be used in conjunction with the clueTip plugin include <a href="http://cherne.net/brian/resources/jquery.hoverIntent.html" title="hoverIntent jQuery Plug-in">hoverIntent</a> and <a href="http://brandonaaron.net/jquery/plugins/bgiframe/docs/">bgIframe</a>.</dd>
 628.265 +		<dt>How do I get clueTip to work with dynamic content.</dt>
 628.266 +		<dd>There are a number of options available for working with dynamic content. By default, the <code>ajaxCache</code> function is set to <code>true</code>. This reduces the number of http requests  made to the server. However, it doesn't account for possible changes to the ajaxed data. If the contents of a particular clueTip will be updated on the server between invocations, you may want to set <code>ajaxCache: false</code>. </dd>
 628.267 +		<dt><em>New as of clueTip 1.0.3</em>: How do I programmatically close (hide) a clueTip?</dt>
 628.268 +		<dd>If you want to trigger a clueTip to close, based on some other interaction, you can use the following code: <code>$(document).trigger('hideCluetip');</code> </dd>
 628.269 +		<dt><em>New as of clueTip 1.0.4</em>: Why don't the styles that I've applied to my local content carry over once they're inside a clueTip?</dt>
 628.270 +		<dd>When using an element on the same page to populate the clueTip's content, the plugin <em>clones</em> that element. Because of potential problems caused by duplicate IDs within a page, the plugin also, by default, adds a suffix to the ID of the cloned element. If you have tied styles to the original ID, they won't be carried over. You can either give the <code>localIdSuffix</code> an empty string ( '' ) for its value or add the id to your stylesheet rule.</dd>
 628.271 +		<dt>How do I add a delay before showing or closing the clueTip? </dt>
 628.272 +		<dd>While the clueTip plugin itself doesn't have a mechanism for delaying responses, it can take advantage of the optional hoverIntent plugin. To delay the showing of a clueTip, use the <code>interval</code> property of the <code>hoverIntent</code> option; to delay its hiding, use the <code>timeout</code> property. Both properties are measured in milliseconds. For example, the following sets both the show and the hide delays to 750 milliseconds (3/4 second):
 628.273 +<pre><code>$('a').cluetip({
 628.274 +  hoverIntent: {
 628.275 +    sensitivity:  1,
 628.276 +    interval:     750,
 628.277 +    timeout:      750    
 628.278 +  }
 628.279 +});
 628.280 +</code></pre>
 628.281 +		  See <a href="http://cherne.net/brian/resources/jquery.hoverIntent.html">hoverIntent plugin's documentation</a> for details.</dd>
 628.282 +		  <dt>Why are the clueTips hidden behind my Flash elements?</dt>
 628.283 +		  <dd><p>This is a common problem when trying to layer a DOM element over a Flash object. To avoid it, you need to set <param name="wmode" value="transparent" /> inside the <object></object> tags and/or wmode="transparent" as an attribute of the <embed /> tag. For example, your HTML might look like this:</p>
 628.284 +
 628.285 +<pre><code><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"    
 628.286 +  codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"
 628.287 +  width="500" height="300">
 628.288 +  <param name="movie" value="test.swf" />
 628.289 +  <param name="quality" value="high" />
 628.290 +  <strong><param name="wmode" value="transparent" /></strong>
 628.291 +
 628.292 +  <embed src="test.swf" quality="high" <strong>wmode="transparent"</strong>
 628.293 +    pluginspage="http://www.macromedia.com/go/getflashplayer"
 628.294 +    type="application/x-shockwave-flash" width="500" height="300" />
 628.295 +</object></code></pre>		    
 628.296 +		  </dd>
 628.297 +        </dl>
 628.298 +    </div>
 628.299 +    <div id="credits" class="tabContent">
 628.300 +      <h1>clueTip Plugin Credits</h1>
 628.301 +      
 628.302 +      <ul>
 628.303 +        <li>The clueTip Plugin was inspired by <a href="http://www.codylindley.com">Cody Lindley</a>'s jTip script. </li>
 628.304 +        <li>Many feature ideas were provided by Shelane Enos. </li>
 628.305 +        <li><a href="http://commadot.com/">Glen Lipka</a> and <a href="http://bassistance.de/">Jörn Zaefferer</a> provided expert advice. </li>
 628.306 +        <li><a href="http://www.pengoworks.com/">Dan G. Switzer</a> and Hector Santos helped a lot and contributed code for a couple features. </li>
 628.307 +        <li><a href="http://blog.schreiter.info/">Torben Schreiter</a> helped squash some bugs and offered code for pre-loading images from ajaxed files</li>
 628.308 +        <li><a href="http://www.tweaktheviking.com">Jonathan Chaffer</a> helped a lot, but eschewed the co-author designation out of sheer modesty. </li>
 628.309 +      </ul>
 628.310 +    </div>
 628.311 +    <div id="download" class="tabContent">
 628.312 +      <h1>Download</h1>
 628.313 +      <p>The latest "stable" release of the clueTip Plugin is available at:
 628.314 +      <a class="external" href="http://plugins.jquery.com/project/cluetip/">http://plugins.jquery.com/project/cluetip/</a>.
 628.315 +      </p>
 628.316 +      <p>The plugin is also available on Github, where it is updated more frequently with incremental improvements and bug fixes: <a href="http://github.com/kswedberg/jquery-cluetip/tree/master">clueTip on Github</a></p>
 628.317 +      <h1>Support</h1>
 628.318 +      <p>Support for the clueTip Plugin is available through the
 628.319 +        <a class="external" href="http://groups.google.com/group/jquery-en/">jQuery Mailing List</a>.  
 628.320 +        This is a very active list to which many jQuery developers and users subscribe.
 628.321 +      </p>
 628.322 +      <h1>Bug Reports & Feature Requests</h1>
 628.323 +      If you discover a bug in the clueTip plugin, please <a href="http://plugins.jquery.com/node/add/project_issue/cluetip/bug">report the bug here</a>. (Note: if you have to be registered and logged in to report a bug. If you have not already registered, <a href="http://plugins.jquery.com/user/register">you can do so here</p>.
 628.324 +      <p>If you would like the clueTip to do something that it doesn't already do, you may <a href="http://plugins.jquery.com/node/add/project_issue/cluetip/feature">request a feature</a>.
 628.325 +      </p>
 628.326 +      <div id="footer">
 628.327 +        This documentation is maintained by Karl Swedberg.  Send comments or questions to karl [at] learningjquery [dot] com.
 628.328 +      </div>
 628.329 +    </div>
 628.330 +</div> <!-- main -->
 628.331 +
 628.332 +</body></html>
   629.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   629.2 +++ b/web/static/js/cluetip-1.0.6/jquery.cluetip.css	Mon Apr 26 11:16:23 2010 +0200
   629.3 @@ -0,0 +1,211 @@
   629.4 +/* global */
   629.5 +#cluetip-close img {
   629.6 +    border: 0
   629.7 +    }
   629.8 +#cluetip-title {
   629.9 +    overflow: hidden
  629.10 +    }
  629.11 +#cluetip-title #cluetip-close {
  629.12 +    float: right;
  629.13 +    position: relative
  629.14 +    }
  629.15 +#cluetip-waitimage {
  629.16 +    width: 43px;
  629.17 +    height: 11px;
  629.18 +    position: absolute;
  629.19 +    background-image: url(images/wait.gif)
  629.20 +    }
  629.21 +.cluetip-arrows {
  629.22 +    display: none;
  629.23 +    position: absolute;
  629.24 +    top: 0;
  629.25 +    left: -11px;
  629.26 +    height: 22px;
  629.27 +    width: 11px;
  629.28 +    background-repeat: no-repeat;
  629.29 +    background-position: 0 0
  629.30 +    }
  629.31 +#cluetip-extra {
  629.32 +    display: none
  629.33 +    }
  629.34 +/***************************************
  629.35 +   =cluetipClass: 'default' 
  629.36 +-------------------------------------- */
  629.37 +.cluetip-default {
  629.38 +    background-color: #ddf1c1
  629.39 +    }
  629.40 +.cluetip-default #cluetip-outer {
  629.41 +    position: relative;
  629.42 +    margin: 0;
  629.43 +    background-color: #ddf1c1
  629.44 +    }
  629.45 +.cluetip-default h3#cluetip-title {
  629.46 +    margin: 0 0 5px;
  629.47 +    padding: 8px 10px 4px;
  629.48 +    font-size: 1.1em;
  629.49 +    font-weight: normal;
  629.50 +    background-color: #beeb82;
  629.51 +    color: #fff
  629.52 +    }
  629.53 +.cluetip-default #cluetip-title a {
  629.54 +    color: #ddf1c1;
  629.55 +    font-size: 0.95em
  629.56 +    }
  629.57 +.cluetip-default #cluetip-inner {
  629.58 +    padding: 10px
  629.59 +    }
  629.60 +.cluetip-default div#cluetip-close {
  629.61 +    text-align: right;
  629.62 +    margin: 0 5px 5px;
  629.63 +    color: #900
  629.64 +    }
  629.65 +/* default arrows */
  629.66 +.clue-right-default .cluetip-arrows {
  629.67 +    background-image: url(images/darrowleft.gif)
  629.68 +    }
  629.69 +.clue-left-default .cluetip-arrows {
  629.70 +    background-image: url(images/darrowright.gif);
  629.71 +    left: 100%;
  629.72 +    margin-right: -11px
  629.73 +    }
  629.74 +.clue-top-default .cluetip-arrows {
  629.75 +    background-image: url(images/darrowdown.gif);
  629.76 +    top: 100%;
  629.77 +    left: 50%;
  629.78 +    margin-left: -11px;
  629.79 +    height: 11px;
  629.80 +    width: 22px
  629.81 +    }
  629.82 +.clue-bottom-default .cluetip-arrows {
  629.83 +    background-image: url(images/darrowup.gif);
  629.84 +    top: -11px;
  629.85 +    left: 50%;
  629.86 +    margin-left: -11px;
  629.87 +    height: 11px;
  629.88 +    width: 22px
  629.89 +    }
  629.90 +/***************************************
  629.91 +   =cluetipClass: 'jtip'
  629.92 +-------------------------------------- */
  629.93 +.cluetip-jtip {
  629.94 +    background-color: transparent
  629.95 +    }
  629.96 +.cluetip-jtip #cluetip-outer {
  629.97 +    border: 2px solid #ccc;
  629.98 +    position: relative;
  629.99 +    background-color: #fff
 629.100 +    }
 629.101 +.cluetip-jtip h3#cluetip-title {
 629.102 +    margin: 0 0 5px;
 629.103 +    padding: 2px 5px;
 629.104 +    font-size: 16px;
 629.105 +    font-weight: normal;
 629.106 +    background-color: #ccc;
 629.107 +    color: #333
 629.108 +    }
 629.109 +.cluetip-jtip #cluetip-inner {
 629.110 +    padding: 0 5px 5px;
 629.111 +    display: inline-block
 629.112 +    }
 629.113 +.cluetip-jtip div#cluetip-close {
 629.114 +    text-align: right;
 629.115 +    margin: 0 5px 5px;
 629.116 +    color: #900
 629.117 +    }
 629.118 +/* jtip arrows */
 629.119 +.clue-right-jtip .cluetip-arrows {
 629.120 +    background-image: url(images/arrowleft.gif)
 629.121 +    }
 629.122 +.clue-left-jtip .cluetip-arrows {
 629.123 +    background-image: url(images/arrowright.gif);
 629.124 +    left: 100%;
 629.125 +    margin-right: -11px
 629.126 +    }
 629.127 +.clue-top-jtip .cluetip-arrows {
 629.128 +    background-image: url(images/arrowdown.gif);
 629.129 +    top: 100%;
 629.130 +    left: 50%;
 629.131 +    margin-left: -11px;
 629.132 +    height: 11px;
 629.133 +    width: 22px
 629.134 +    }
 629.135 +.clue-bottom-jtip .cluetip-arrows {
 629.136 +    background-image: url(images/arrowup.gif);
 629.137 +    top: -11px;
 629.138 +    left: 50%;
 629.139 +    margin-left: -11px;
 629.140 +    height: 11px;
 629.141 +    width: 22px
 629.142 +    }
 629.143 +/***************************************
 629.144 +   =cluetipClass: 'rounded'
 629.145 +-------------------------------------- */
 629.146 +.cluetip-rounded {
 629.147 +    background: transparent url(images/bl.gif) no-repeat 0 100%;
 629.148 +    margin-top: 10px;
 629.149 +    margin-left: 12px
 629.150 +    }
 629.151 +.cluetip-rounded #cluetip-outer {
 629.152 +    background: transparent url(images/tl.gif) no-repeat 0 0;
 629.153 +    margin-top: -12px
 629.154 +    }
 629.155 +.cluetip-rounded #cluetip-title {
 629.156 +    background-color: transparent;
 629.157 +    padding: 12px 12px 0;
 629.158 +    margin: 0 -12px 0 0;
 629.159 +    position: relative
 629.160 +    }
 629.161 +.cluetip-rounded #cluetip-extra {
 629.162 +    position: absolute;
 629.163 +    display: block;
 629.164 +    background: transparent url(images/tr.gif) no-repeat 100% 0;
 629.165 +    top: 0;
 629.166 +    right: 0;
 629.167 +    width: 12px;
 629.168 +    height: 30px;
 629.169 +    margin: -12px -12px 0 0
 629.170 +    }
 629.171 +.cluetip-rounded #cluetip-inner {
 629.172 +    background: url(images/br.gif) no-repeat 100% 100%;
 629.173 +    padding: 5px 12px 12px;
 629.174 +    margin: -18px -12px 0 0;
 629.175 +    position: relative
 629.176 +    }
 629.177 +.cluetip-rounded div#cluetip-close {
 629.178 +    text-align: right;
 629.179 +    margin: 0 5px 5px;
 629.180 +    color: #009;
 629.181 +    background: transparent
 629.182 +    }
 629.183 +.cluetip-rounded div#cluetip-close a {
 629.184 +    color: #777
 629.185 +    }
 629.186 +/* rounded arrows */
 629.187 +.clue-right-rounded .cluetip-arrows {
 629.188 +    background-image: url(images/rarrowleft.gif)
 629.189 +    }
 629.190 +.clue-left-rounded .cluetip-arrows {
 629.191 +    background-image: url(images/rarrowright.gif);
 629.192 +    left: 100%;
 629.193 +    margin-left: 12px
 629.194 +    }
 629.195 +.clue-top-rounded .cluetip-arrows {
 629.196 +    background-image: url(images/rarrowdown.gif);
 629.197 +    top: 100%;
 629.198 +    left: 50%;
 629.199 +    margin-left: -11px;
 629.200 +    height: 11px;
 629.201 +    width: 22px
 629.202 +    }
 629.203 +.clue-bottom-rounded .cluetip-arrows {
 629.204 +    background-image: url(images/rarrowup.gif);
 629.205 +    top: -23px;
 629.206 +    left: 50%;
 629.207 +    margin-left: -11px;
 629.208 +    height: 11px;
 629.209 +    width: 22px
 629.210 +    }
 629.211 +/* stupid IE6 HasLayout hack */
 629.212 +.cluetip-rounded #cluetip-title, .cluetip-rounded #cluetip-inner {
 629.213 +    zoom: 1
 629.214 +    }
   630.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   630.2 +++ b/web/static/js/cluetip-1.0.6/jquery.cluetip.js	Mon Apr 26 11:16:23 2010 +0200
   630.3 @@ -0,0 +1,549 @@
   630.4 +/*
   630.5 + * jQuery clueTip plugin
   630.6 + * Version 1.0.6  (January 13, 2022)
   630.7 + * @requires jQuery v1.3+
   630.8 + *
   630.9 + * Dual licensed under the MIT and GPL licenses:
  630.10 + * http://www.opensource.org/licenses/mit-license.php
  630.11 + * http://www.gnu.org/licenses/gpl.html
  630.12 + *
  630.13 + */
  630.14 + 
  630.15 +/*
  630.16 + *
  630.17 + * Full list of options/settings can be found at the bottom of this file and at http://plugins.learningjquery.com/cluetip/
  630.18 + *
  630.19 + * Examples can be found at http://plugins.learningjquery.com/cluetip/demo/
  630.20 + *
  630.21 +*/
  630.22 +
  630.23 +;(function($) { 
  630.24 +  $.cluetip = {version: '1.0.6'};
  630.25 +  var $cluetip, $cluetipInner, $cluetipOuter, $cluetipTitle, $cluetipArrows, $cluetipWait, $dropShadow, imgCount;
  630.26 +  
  630.27 +  $.fn.cluetip = function(js, options) {
  630.28 +    if (typeof js == 'object') {
  630.29 +      options = js;
  630.30 +      js = null;
  630.31 +    }
  630.32 +    if (js == 'destroy') {
  630.33 +      return this.removeData('thisInfo').unbind('.cluetip');
  630.34 +    }
  630.35 +    return this.each(function(index) {
  630.36 +      var link = this, $this = $(this);
  630.37 +      
  630.38 +      // support metadata plugin (v1.0 and 2.0)
  630.39 +      var opts = $.extend(true, {}, $.fn.cluetip.defaults, options || {}, $.metadata ? $this.metadata() : $.meta ? $this.data() : {});
  630.40 +
  630.41 +      // start out with no contents (for ajax activation)
  630.42 +      var cluetipContents = false;
  630.43 +      var cluezIndex = +opts.cluezIndex;
  630.44 +      $this.data('thisInfo', {title: link.title, zIndex: cluezIndex});
  630.45 +      var isActive = false, closeOnDelay = 0;
  630.46 +
  630.47 +      // create the cluetip divs
  630.48 +      if (!$('#cluetip').length) {
  630.49 +        $(['<div id="cluetip">',
  630.50 +          '<div id="cluetip-outer">',
  630.51 +            '<h3 id="cluetip-title"></h3>',
  630.52 +            '<div id="cluetip-inner"></div>',
  630.53 +          '</div>',
  630.54 +          '<div id="cluetip-extra"></div>',
  630.55 +          '<div id="cluetip-arrows" class="cluetip-arrows"></div>',
  630.56 +        '</div>'].join(''))
  630.57 +        [insertionType](insertionElement).hide();
  630.58 +        
  630.59 +        $cluetip = $('#cluetip').css({position: 'absolute'});
  630.60 +        $cluetipOuter = $('#cluetip-outer').css({position: 'relative', zIndex: cluezIndex});
  630.61 +        $cluetipInner = $('#cluetip-inner');
  630.62 +        $cluetipTitle = $('#cluetip-title');        
  630.63 +        $cluetipArrows = $('#cluetip-arrows');
  630.64 +        $cluetipWait = $('<div id="cluetip-waitimage"></div>')
  630.65 +          .css({position: 'absolute'}).insertBefore($cluetip).hide();
  630.66 +      }
  630.67 +      var dropShadowSteps = (opts.dropShadow) ? +opts.dropShadowSteps : 0;
  630.68 +      if (!$dropShadow) {
  630.69 +        $dropShadow = $([]);
  630.70 +        for (var i=0; i < dropShadowSteps; i++) {
  630.71 +          $dropShadow = $dropShadow.add($('<div></div>').css({zIndex: cluezIndex-1, opacity:.1, top: 1+i, left: 1+i}));
  630.72 +        }
  630.73 +        $dropShadow.css({position: 'absolute', backgroundColor: '#000'})
  630.74 +        .prependTo($cluetip);
  630.75 +      }
  630.76 +      var tipAttribute = $this.attr(opts.attribute), ctClass = opts.cluetipClass;
  630.77 +      if (!tipAttribute && !opts.splitTitle && !js) {
  630.78 +        return true;
  630.79 +      }
  630.80 +      // if hideLocal is set to true, on DOM ready hide the local content that will be displayed in the clueTip
  630.81 +      if (opts.local && opts.localPrefix) {tipAttribute = opts.localPrefix + tipAttribute;}
  630.82 +      if (opts.local && opts.hideLocal) { $(tipAttribute + ':first').hide(); }
  630.83 +      var tOffset = parseInt(opts.topOffset, 10), lOffset = parseInt(opts.leftOffset, 10);
  630.84 +      // vertical measurement variables
  630.85 +      var tipHeight, wHeight,
  630.86 +          defHeight = isNaN(parseInt(opts.height, 10)) ? 'auto' : (/\D/g).test(opts.height) ? opts.height : opts.height + 'px';
  630.87 +      var sTop, linkTop, posY, tipY, mouseY, baseline;
  630.88 +      // horizontal measurement variables
  630.89 +      var tipInnerWidth = parseInt(opts.width, 10) || 275,
  630.90 +          tipWidth = tipInnerWidth + (parseInt($cluetip.css('paddingLeft'),10)||0) + (parseInt($cluetip.css('paddingRight'),10)||0) + dropShadowSteps,
  630.91 +          linkWidth = this.offsetWidth,
  630.92 +          linkLeft, posX, tipX, mouseX, winWidth;
  630.93 +            
  630.94 +      // parse the title
  630.95 +      var tipParts;
  630.96 +      var tipTitle = (opts.attribute != 'title') ? $this.attr(opts.titleAttribute) : '';
  630.97 +      if (opts.splitTitle) {
  630.98 +        if (tipTitle == undefined) {tipTitle = '';}
  630.99 +        tipParts = tipTitle.split(opts.splitTitle);
 630.100 +        tipTitle = tipParts.shift();
 630.101 +      }
 630.102 +      if (opts.escapeTitle) {
 630.103 +        tipTitle = tipTitle.replace(/&/g,'&').replace(/>/g,'>').replace(/</g,'<');
 630.104 +      }
 630.105 +      
 630.106 +      var localContent;
 630.107 +      function returnFalse() { return false; }
 630.108 +
 630.109 +/***************************************      
 630.110 +* ACTIVATION
 630.111 +****************************************/
 630.112 +    
 630.113 +//activate clueTip
 630.114 +    var activate = function(event) {
 630.115 +      if (!opts.onActivate($this)) {
 630.116 +        return false;
 630.117 +      }
 630.118 +      isActive = true;
 630.119 +      $cluetip.removeClass().css({width: tipInnerWidth});
 630.120 +      if (tipAttribute == $this.attr('href')) {
 630.121 +        $this.css('cursor', opts.cursor);
 630.122 +      }
 630.123 +      if (opts.hoverClass) {
 630.124 +        $this.addClass(opts.hoverClass);
 630.125 +      }
 630.126 +      linkTop = posY = $this.offset().top;
 630.127 +      linkLeft = $this.offset().left;
 630.128 +      mouseX = event.pageX;
 630.129 +      mouseY = event.pageY;
 630.130 +      if (link.tagName.toLowerCase() != 'area') {
 630.131 +        sTop = $(document).scrollTop();
 630.132 +        winWidth = $(window).width();
 630.133 +      }
 630.134 +// position clueTip horizontally
 630.135 +      if (opts.positionBy == 'fixed') {
 630.136 +        posX = linkWidth + linkLeft + lOffset;
 630.137 +        $cluetip.css({left: posX});
 630.138 +      } else {
 630.139 +        posX = (linkWidth > linkLeft && linkLeft > tipWidth)
 630.140 +          || linkLeft + linkWidth + tipWidth + lOffset > winWidth 
 630.141 +          ? linkLeft - tipWidth - lOffset 
 630.142 +          : linkWidth + linkLeft + lOffset;
 630.143 +        if (link.tagName.toLowerCase() == 'area' || opts.positionBy == 'mouse' || linkWidth + tipWidth > winWidth) { // position by mouse
 630.144 +          if (mouseX + 20 + tipWidth > winWidth) {  
 630.145 +            $cluetip.addClass(' cluetip-' + ctClass);
 630.146 +            posX = (mouseX - tipWidth - lOffset) >= 0 ? mouseX - tipWidth - lOffset - parseInt($cluetip.css('marginLeft'),10) + parseInt($cluetipInner.css('marginRight'),10) :  mouseX - (tipWidth/2);
 630.147 +          } else {
 630.148 +            posX = mouseX + lOffset;
 630.149 +          }
 630.150 +        }
 630.151 +        var pY = posX < 0 ? event.pageY + tOffset : event.pageY;
 630.152 +        $cluetip.css({
 630.153 +          left: (posX > 0 && opts.positionBy != 'bottomTop') ? posX : (mouseX + (tipWidth/2) > winWidth) ? winWidth/2 - tipWidth/2 : Math.max(mouseX - (tipWidth/2),0),
 630.154 +          zIndex: $this.data('thisInfo').zIndex
 630.155 +        });
 630.156 +        $cluetipArrows.css({zIndex: $this.data('thisInfo').zIndex+1});
 630.157 +      }
 630.158 +        wHeight = $(window).height();
 630.159 +
 630.160 +/***************************************
 630.161 +* load a string from cluetip method's first argument
 630.162 +***************************************/
 630.163 +      if (js) {
 630.164 +        if (typeof js == 'function') {
 630.165 +          js = js.call(link);
 630.166 +        }
 630.167 +        $cluetipInner.html(js);
 630.168 +        cluetipShow(pY);
 630.169 +      }
 630.170 +/***************************************
 630.171 +* load the title attribute only (or user-selected attribute). 
 630.172 +* clueTip title is the string before the first delimiter
 630.173 +* subsequent delimiters place clueTip body text on separate lines
 630.174 +***************************************/
 630.175 +
 630.176 +      else if (tipParts) {
 630.177 +        var tpl = tipParts.length;
 630.178 +        $cluetipInner.html(tpl ? tipParts[0] : '');
 630.179 +        if (tpl > 1) {
 630.180 +          for (var i=1; i < tpl; i++){
 630.181 +            $cluetipInner.append('<div class="split-body">' + tipParts[i] + '</div>');
 630.182 +          }          
 630.183 +        }
 630.184 +        cluetipShow(pY);
 630.185 +      }
 630.186 +/***************************************
 630.187 +* load external file via ajax          
 630.188 +***************************************/
 630.189 +
 630.190 +      else if (!opts.local && tipAttribute.indexOf('#') !== 0) {
 630.191 +        if (/\.(jpe?g|tiff?|gif|png)$/i.test(tipAttribute)) {
 630.192 +          $cluetipInner.html('<img src="' + tipAttribute + '" alt="' + tipTitle + '" />');
 630.193 +          cluetipShow(pY);
 630.194 +        } else if (cluetipContents && opts.ajaxCache) {
 630.195 +          $cluetipInner.html(cluetipContents);
 630.196 +          cluetipShow(pY);
 630.197 +        } else {
 630.198 +          var optionBeforeSend = opts.ajaxSettings.beforeSend,
 630.199 +              optionError = opts.ajaxSettings.error,
 630.200 +              optionSuccess = opts.ajaxSettings.success,
 630.201 +              optionComplete = opts.ajaxSettings.complete;
 630.202 +          var ajaxSettings = {
 630.203 +            cache: false, // force requested page not to be cached by browser
 630.204 +            url: tipAttribute,
 630.205 +            beforeSend: function(xhr) {
 630.206 +              if (optionBeforeSend) {optionBeforeSend.call(link, xhr, $cluetip, $cluetipInner);}
 630.207 +              $cluetipOuter.children().empty();
 630.208 +              if (opts.waitImage) {
 630.209 +                $cluetipWait
 630.210 +                .css({top: mouseY+20, left: mouseX+20, zIndex: $this.data('thisInfo').zIndex-1})
 630.211 +                .show();
 630.212 +              }
 630.213 +            },
 630.214 +            error: function(xhr, textStatus) {
 630.215 +              if (isActive) {
 630.216 +                if (optionError) {
 630.217 +                  optionError.call(link, xhr, textStatus, $cluetip, $cluetipInner);
 630.218 +                } else {
 630.219 +                  $cluetipInner.html('<i>sorry, the contents could not be loaded</i>');  
 630.220 +                }
 630.221 +              }
 630.222 +            },
 630.223 +            success: function(data, textStatus) {       
 630.224 +              cluetipContents = opts.ajaxProcess.call(link, data);
 630.225 +              if (isActive) {
 630.226 +                if (optionSuccess) {optionSuccess.call(link, data, textStatus, $cluetip, $cluetipInner);}
 630.227 +                $cluetipInner.html(cluetipContents);
 630.228 +              }
 630.229 +            },
 630.230 +            complete: function(xhr, textStatus) {
 630.231 +              if (optionComplete) {optionComplete.call(link, xhr, textStatus, $cluetip, $cluetipInner);}
 630.232 +              imgCount = $('#cluetip-inner img').length;
 630.233 +              if (imgCount && !$.browser.opera) {
 630.234 +                $('#cluetip-inner img').bind('load error', function() {
 630.235 +                  imgCount--;
 630.236 +                  if (imgCount<1) {
 630.237 +                    $cluetipWait.hide();
 630.238 +                    if (isActive) { cluetipShow(pY); }
 630.239 +                  }
 630.240 +                }); 
 630.241 +              } else {
 630.242 +                $cluetipWait.hide();
 630.243 +                if (isActive) { cluetipShow(pY); }
 630.244 +              } 
 630.245 +            }
 630.246 +          };
 630.247 +          var ajaxMergedSettings = $.extend(true, {}, opts.ajaxSettings, ajaxSettings);
 630.248 +          
 630.249 +          $.ajax(ajaxMergedSettings);
 630.250 +        }
 630.251 +
 630.252 +/***************************************
 630.253 +* load an element from the same page
 630.254 +***************************************/
 630.255 +      } else if (opts.local) {
 630.256 +        
 630.257 +        var $localContent = $(tipAttribute + (/#\S+$/.test(tipAttribute) ? '' : ':eq(' + index + ')')).clone(true).show();
 630.258 +        $cluetipInner.html($localContent);
 630.259 +        cluetipShow(pY);
 630.260 +      }
 630.261 +    };
 630.262 +
 630.263 +// get dimensions and options for cluetip and prepare it to be shown
 630.264 +    var cluetipShow = function(bpY) {
 630.265 +      $cluetip.addClass('cluetip-' + ctClass);
 630.266 +      if (opts.truncate) { 
 630.267 +        var $truncloaded = $cluetipInner.text().slice(0,opts.truncate) + '...';
 630.268 +        $cluetipInner.html($truncloaded);
 630.269 +      }
 630.270 +      function doNothing() {}; //empty function
 630.271 +      tipTitle ? $cluetipTitle.show().html(tipTitle) : (opts.showTitle) ? $cluetipTitle.show().html(' ') : $cluetipTitle.hide();
 630.272 +      if (opts.sticky) {
 630.273 +        var $closeLink = $('<div id="cluetip-close"><a href="#">' + opts.closeText + '</a></div>');
 630.274 +        (opts.closePosition == 'bottom') ? $closeLink.appendTo($cluetipInner) : (opts.closePosition == 'title') ? $closeLink.prependTo($cluetipTitle) : $closeLink.prependTo($cluetipInner);
 630.275 +        $closeLink.bind('click.cluetip', function() {
 630.276 +          cluetipClose();
 630.277 +          return false;
 630.278 +        });
 630.279 +        if (opts.mouseOutClose) {
 630.280 +          $cluetip.bind('mouseleave.cluetip', function() {
 630.281 +            cluetipClose();
 630.282 +          });
 630.283 +        } else {
 630.284 +          $cluetip.unbind('mouseleave.cluetip');
 630.285 +        }
 630.286 +      }
 630.287 +// now that content is loaded, finish the positioning 
 630.288 +      var direction = '';
 630.289 +      $cluetipOuter.css({zIndex: $this.data('thisInfo').zIndex, overflow: defHeight == 'auto' ? 'visible' : 'auto', height: defHeight});
 630.290 +      tipHeight = defHeight == 'auto' ? Math.max($cluetip.outerHeight(),$cluetip.height()) : parseInt(defHeight,10);   
 630.291 +      tipY = posY;
 630.292 +      baseline = sTop + wHeight;
 630.293 +      if (opts.positionBy == 'fixed') {
 630.294 +        tipY = posY - opts.dropShadowSteps + tOffset;
 630.295 +      } else if ( (posX < mouseX && Math.max(posX, 0) + tipWidth > mouseX) || opts.positionBy == 'bottomTop') {
 630.296 +        if (posY + tipHeight + tOffset > baseline && mouseY - sTop > tipHeight + tOffset) { 
 630.297 +          tipY = mouseY - tipHeight - tOffset;
 630.298 +          direction = 'top';
 630.299 +        } else { 
 630.300 +          tipY = mouseY + tOffset;
 630.301 +          direction = 'bottom';
 630.302 +        }
 630.303 +      } else if ( posY + tipHeight + tOffset > baseline ) {
 630.304 +        tipY = (tipHeight >= wHeight) ? sTop : baseline - tipHeight - tOffset;
 630.305 +      } else if ($this.css('display') == 'block' || link.tagName.toLowerCase() == 'area' || opts.positionBy == "mouse") {
 630.306 +        tipY = bpY - tOffset;
 630.307 +      } else {
 630.308 +        tipY = posY - opts.dropShadowSteps;
 630.309 +      }
 630.310 +      if (direction == '') {
 630.311 +        posX < linkLeft ? direction = 'left' : direction = 'right';
 630.312 +      }
 630.313 +      $cluetip.css({top: tipY + 'px'}).removeClass().addClass('clue-' + direction + '-' + ctClass).addClass(' cluetip-' + ctClass);
 630.314 +      if (opts.arrows) { // set up arrow positioning to align with element
 630.315 +        var bgY = (posY - tipY - opts.dropShadowSteps);
 630.316 +        $cluetipArrows.css({top: (/(left|right)/.test(direction) && posX >=0 && bgY > 0) ? bgY + 'px' : /(left|right)/.test(direction) ? 0 : ''}).show();
 630.317 +      } else {
 630.318 +        $cluetipArrows.hide();
 630.319 +      }
 630.320 +
 630.321 +// (first hide, then) ***SHOW THE CLUETIP***
 630.322 +      $dropShadow.hide();
 630.323 +      $cluetip.hide()[opts.fx.open](opts.fx.openSpeed || 0);
 630.324 +      if (opts.dropShadow) { $dropShadow.css({height: tipHeight, width: tipInnerWidth, zIndex: $this.data('thisInfo').zIndex-1}).show(); }
 630.325 +      if ($.fn.bgiframe) { $cluetip.bgiframe(); }
 630.326 +      // delayed close (not fully tested)
 630.327 +      if (opts.delayedClose > 0) {
 630.328 +        closeOnDelay = setTimeout(cluetipClose, opts.delayedClose);
 630.329 +      }
 630.330 +      // trigger the optional onShow function
 630.331 +      opts.onShow.call(link, $cluetip, $cluetipInner);
 630.332 +    };
 630.333 +
 630.334 +/***************************************
 630.335 +   =INACTIVATION
 630.336 +-------------------------------------- */
 630.337 +    var inactivate = function(event) {
 630.338 +      isActive = false;
 630.339 +      $cluetipWait.hide();
 630.340 +      if (!opts.sticky || (/click|toggle/).test(opts.activation) ) {
 630.341 +        cluetipClose();
 630.342 +        clearTimeout(closeOnDelay);        
 630.343 +      }
 630.344 +      if (opts.hoverClass) {
 630.345 +        $this.removeClass(opts.hoverClass);
 630.346 +      }
 630.347 +    };
 630.348 +// close cluetip and reset some things
 630.349 +    var cluetipClose = function() {
 630.350 +      $cluetipOuter 
 630.351 +      .parent().hide().removeClass();
 630.352 +      opts.onHide.call(link, $cluetip, $cluetipInner);
 630.353 +      $this.removeClass('cluetip-clicked');
 630.354 +      if (tipTitle) {
 630.355 +        $this.attr(opts.titleAttribute, tipTitle);
 630.356 +      }
 630.357 +      $this.css('cursor','');
 630.358 +      if (opts.arrows) {
 630.359 +        $cluetipArrows.css({top: ''});
 630.360 +      }
 630.361 +    };
 630.362 +
 630.363 +    $(document).bind('hideCluetip', function(e) {
 630.364 +      cluetipClose();
 630.365 +    });
 630.366 +/***************************************
 630.367 +   =BIND EVENTS
 630.368 +-------------------------------------- */
 630.369 +  // activate by click
 630.370 +      if ( (/click|toggle/).test(opts.activation) ) {
 630.371 +        $this.bind('click.cluetip', function(event) {
 630.372 +          if ($cluetip.is(':hidden') || !$this.is('.cluetip-clicked')) {
 630.373 +            activate(event);
 630.374 +            $('.cluetip-clicked').removeClass('cluetip-clicked');
 630.375 +            $this.addClass('cluetip-clicked');
 630.376 +          } else {
 630.377 +            inactivate(event);
 630.378 +          }
 630.379 +          this.blur();
 630.380 +          return false;
 630.381 +        });
 630.382 +  // activate by focus; inactivate by blur    
 630.383 +      } else if (opts.activation == 'focus') {
 630.384 +        $this.bind('focus.cluetip', function(event) {
 630.385 +          activate(event);
 630.386 +        });
 630.387 +        $this.bind('blur.cluetip', function(event) {
 630.388 +          inactivate(event);
 630.389 +        });
 630.390 +  // activate by hover
 630.391 +      } else {
 630.392 +        // clicking is returned false if clickThrough option is set to false
 630.393 +        $this[opts.clickThrough ? 'unbind' : 'bind']('click', returnFalse);
 630.394 +        //set up mouse tracking
 630.395 +        var mouseTracks = function(evt) {
 630.396 +          if (opts.tracking == true) {
 630.397 +            var trackX = posX - evt.pageX;
 630.398 +            var trackY = tipY ? tipY - evt.pageY : posY - evt.pageY;
 630.399 +            $this.bind('mousemove.cluetip', function(evt) {
 630.400 +              $cluetip.css({left: evt.pageX + trackX, top: evt.pageY + trackY });
 630.401 +            });
 630.402 +          }
 630.403 +        };
 630.404 +        if ($.fn.hoverIntent && opts.hoverIntent) {
 630.405 +          $this.hoverIntent({
 630.406 +            sensitivity: opts.hoverIntent.sensitivity,
 630.407 +            interval: opts.hoverIntent.interval,  
 630.408 +            over: function(event) {
 630.409 +              activate(event);
 630.410 +              mouseTracks(event);
 630.411 +            }, 
 630.412 +            timeout: opts.hoverIntent.timeout,  
 630.413 +            out: function(event) {inactivate(event); $this.unbind('mousemove.cluetip');}
 630.414 +          });           
 630.415 +        } else {
 630.416 +          $this.bind('mouseenter.cluetip', function(event) {
 630.417 +            activate(event);
 630.418 +            mouseTracks(event);
 630.419 +          })
 630.420 +          .bind('mouseleave.cluetip', function(event) {
 630.421 +            inactivate(event);
 630.422 +            $this.unbind('mousemove.cluetip');
 630.423 +          });
 630.424 +        }
 630.425 +        $this.bind('mouseover.cluetip', function(event) {
 630.426 +          $this.attr('title','');
 630.427 +        }).bind('mouseleave.cluetip', function(event) {
 630.428 +          $this.attr('title', $this.data('thisInfo').title);
 630.429 +        });
 630.430 +      }
 630.431 +    });
 630.432 +  };
 630.433 +  
 630.434 +/*
 630.435 + * options for clueTip
 630.436 + *
 630.437 + * each one can be explicitly overridden by changing its value. 
 630.438 + * for example: $.fn.cluetip.defaults.width = 200; 
 630.439 + * would change the default width for all clueTips to 200. 
 630.440 + *
 630.441 + * each one can also be overridden by passing an options map to the cluetip method.
 630.442 + * for example: $('a.example').cluetip({width: 200}); 
 630.443 + * would change the default width to 200 for clueTips invoked by a link with class of "example"
 630.444 + *
 630.445 + */
 630.446 +  
 630.447 +  $.fn.cluetip.defaults = {  // set up default options
 630.448 +    width:            275,      // The width of the clueTip
 630.449 +    height:           'auto',   // The height of the clueTip
 630.450 +    cluezIndex:       97,       // Sets the z-index style property of the clueTip
 630.451 +    positionBy:       'auto',   // Sets the type of positioning: 'auto', 'mouse','bottomTop', 'fixed'
 630.452 +    topOffset:        15,       // Number of px to offset clueTip from top of invoking element
 630.453 +    leftOffset:       15,       // Number of px to offset clueTip from left of invoking element
 630.454 +    local:            false,    // Whether to use content from the same page for the clueTip's body
 630.455 +    localPrefix:      null,       // string to be prepended to the tip attribute if local is true
 630.456 +    hideLocal:        true,     // If local option is set to true, this determines whether local content
 630.457 +                                // to be shown in clueTip should be hidden at its original location
 630.458 +    attribute:        'rel',    // the attribute to be used for fetching the clueTip's body content
 630.459 +    titleAttribute:   'title',  // the attribute to be used for fetching the clueTip's title
 630.460 +    splitTitle:       '',       // A character used to split the title attribute into the clueTip title and divs
 630.461 +                                // within the clueTip body. more info below [6]
 630.462 +    escapeTitle:      false,    // whether to html escape the title attribute
 630.463 +    showTitle:        true,     // show title bar of the clueTip, even if title attribute not set
 630.464 +    cluetipClass:     'default',// class added to outermost clueTip div in the form of 'cluetip-' + clueTipClass.
 630.465 +    hoverClass:       '',       // class applied to the invoking element onmouseover and removed onmouseout
 630.466 +    waitImage:        true,     // whether to show a "loading" img, which is set in jquery.cluetip.css
 630.467 +    cursor:           'help',
 630.468 +    arrows:           false,    // if true, displays arrow on appropriate side of clueTip
 630.469 +    dropShadow:       true,     // set to false if you don't want the drop-shadow effect on the clueTip
 630.470 +    dropShadowSteps:  6,        // adjusts the size of the drop shadow
 630.471 +    sticky:           false,    // keep visible until manually closed
 630.472 +    mouseOutClose:    false,    // close when clueTip is moused out
 630.473 +    activation:       'hover',  // set to 'click' to force user to click to show clueTip
 630.474 +                                // set to 'focus' to show on focus of a form element and hide on blur
 630.475 +    clickThrough:     false,    // if true, and activation is not 'click', then clicking on link will take user to the link's href,
 630.476 +                                // even if href and tipAttribute are equal
 630.477 +    tracking:         false,    // if true, clueTip will track mouse movement (experimental)
 630.478 +    delayedClose:     0,        // close clueTip on a timed delay (experimental)
 630.479 +    closePosition:    'top',    // location of close text for sticky cluetips; can be 'top' or 'bottom' or 'title'
 630.480 +    closeText:        'Close',  // text (or HTML) to to be clicked to close sticky clueTips
 630.481 +    truncate:         0,        // number of characters to truncate clueTip's contents. if 0, no truncation occurs
 630.482 +    
 630.483 +    // effect and speed for opening clueTips
 630.484 +    fx: {             
 630.485 +                      open:       'show', // can be 'show' or 'slideDown' or 'fadeIn'
 630.486 +                      openSpeed:  ''
 630.487 +    },     
 630.488 +
 630.489 +    // settings for when hoverIntent plugin is used             
 630.490 +    hoverIntent: {    
 630.491 +                      sensitivity:  3,
 630.492 +              			  interval:     50,
 630.493 +              			  timeout:      0
 630.494 +    },
 630.495 +
 630.496 +    // short-circuit function to run just before clueTip is shown. 
 630.497 +    onActivate:       function(e) {return true;},
 630.498 +
 630.499 +    // function to run just after clueTip is shown. 
 630.500 +    onShow:           function(ct, ci){},
 630.501 +    // function to run just after clueTip is hidden.
 630.502 +    onHide:           function(ct, ci){},
 630.503 +    // whether to cache results of ajax request to avoid unnecessary hits to server    
 630.504 +    ajaxCache:        true,  
 630.505 +
 630.506 +    // process data retrieved via xhr before it's displayed
 630.507 +    ajaxProcess:      function(data) {
 630.508 +                        data = data.replace(/<(script|style|title)[^<]+<\/(script|style|title)>/gm, '').replace(/<(link|meta)[^>]+>/g,'');
 630.509 +                        return data;
 630.510 +    },                
 630.511 +
 630.512 +    // can pass in standard $.ajax() parameters. Callback functions, such as beforeSend, 
 630.513 +    // will be queued first within the default callbacks. 
 630.514 +    // The only exception is error, which overrides the default
 630.515 +    ajaxSettings: {
 630.516 +                      // error: function(ct, ci) { /* override default error callback */ }
 630.517 +                      // beforeSend: function(ct, ci) { /* called first within default beforeSend callback }
 630.518 +                      dataType: 'html'
 630.519 +    },
 630.520 +    debug: false
 630.521 +  };
 630.522 +
 630.523 +
 630.524 +/*
 630.525 + * Global defaults for clueTips. Apply to all calls to the clueTip plugin.
 630.526 + *
 630.527 + * @example $.cluetip.setup({
 630.528 + *   insertionType: 'prependTo',
 630.529 + *   insertionElement: '#container'
 630.530 + * });
 630.531 + * 
 630.532 + * @property
 630.533 + * @name $.cluetip.setup
 630.534 + * @type Map
 630.535 + * @cat Plugins/tooltip
 630.536 + * @option String insertionType: Default is 'appendTo'. Determines the method to be used for inserting the clueTip into the DOM. Permitted values are 'appendTo', 'prependTo', 'insertBefore', and 'insertAfter'
 630.537 + * @option String insertionElement: Default is 'body'. Determines which element in the DOM the plugin will reference when inserting the clueTip.
 630.538 + *
 630.539 + */
 630.540 +   
 630.541 +  var insertionType = 'appendTo', insertionElement = 'body';
 630.542 +
 630.543 +  $.cluetip.setup = function(options) {
 630.544 +    if (options && options.insertionType && (options.insertionType).match(/appendTo|prependTo|insertBefore|insertAfter/)) {
 630.545 +      insertionType = options.insertionType;
 630.546 +    }
 630.547 +    if (options && options.insertionElement) {
 630.548 +      insertionElement = options.insertionElement;
 630.549 +    }
 630.550 +  };
 630.551 +  
 630.552 +})(jQuery);
   631.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   631.2 +++ b/web/static/js/cluetip-1.0.6/jquery.cluetip.min.js	Mon Apr 26 11:16:23 2010 +0200
   631.3 @@ -0,0 +1,58 @@
   631.4 +/*
   631.5 + * jQuery clueTip plugin
   631.6 + * Version 1.0.6  (January 13, 2022)
   631.7 + * @requires jQuery v1.3+
   631.8 + *
   631.9 + * Dual licensed under the MIT and GPL licenses:
  631.10 + * http://www.opensource.org/licenses/mit-license.php
  631.11 + * http://www.gnu.org/licenses/gpl.html
  631.12 + *
  631.13 + */
  631.14 + 
  631.15 +/*
  631.16 + *
  631.17 + * Full list of options/settings can be found at the bottom of this file and at http://plugins.learningjquery.com/cluetip/
  631.18 + *
  631.19 + * Examples can be found at http://plugins.learningjquery.com/cluetip/demo/
  631.20 + *
  631.21 +*/
  631.22 +(function($){$.cluetip={version:'1.0.6'};var $cluetip,$cluetipInner,$cluetipOuter,$cluetipTitle,$cluetipArrows,$cluetipWait,$dropShadow,imgCount;$.fn.cluetip=function(js,options){if(typeof js=='object'){options=js;js=null;}
  631.23 +if(js=='destroy'){return this.removeData('thisInfo').unbind('.cluetip');}
  631.24 +return this.each(function(index){var link=this,$this=$(this);var opts=$.extend(true,{},$.fn.cluetip.defaults,options||{},$.metadata?$this.metadata():$.meta?$this.data():{});var cluetipContents=false;var cluezIndex=+opts.cluezIndex;$this.data('thisInfo',{title:link.title,zIndex:cluezIndex});var isActive=false,closeOnDelay=0;if(!$('#cluetip').length){$(['<div id="cluetip">','<div id="cluetip-outer">','<h3 id="cluetip-title"></h3>','<div id="cluetip-inner"></div>','</div>','<div id="cluetip-extra"></div>','<div id="cluetip-arrows" class="cluetip-arrows"></div>','</div>'].join(''))
  631.25 +[insertionType](insertionElement).hide();$cluetip=$('#cluetip').css({position:'absolute'});$cluetipOuter=$('#cluetip-outer').css({position:'relative',zIndex:cluezIndex});$cluetipInner=$('#cluetip-inner');$cluetipTitle=$('#cluetip-title');$cluetipArrows=$('#cluetip-arrows');$cluetipWait=$('<div id="cluetip-waitimage"></div>').css({position:'absolute'}).insertBefore($cluetip).hide();}
  631.26 +var dropShadowSteps=(opts.dropShadow)?+opts.dropShadowSteps:0;if(!$dropShadow){$dropShadow=$([]);for(var i=0;i<dropShadowSteps;i++){$dropShadow=$dropShadow.add($('<div></div>').css({zIndex:cluezIndex-1,opacity:.1,top:1+i,left:1+i}));}
  631.27 +$dropShadow.css({position:'absolute',backgroundColor:'#000'}).prependTo($cluetip);}
  631.28 +var tipAttribute=$this.attr(opts.attribute),ctClass=opts.cluetipClass;if(!tipAttribute&&!opts.splitTitle&&!js){return true;}
  631.29 +if(opts.local&&opts.localPrefix){tipAttribute=opts.localPrefix+tipAttribute;}
  631.30 +if(opts.local&&opts.hideLocal){$(tipAttribute+':first').hide();}
  631.31 +var tOffset=parseInt(opts.topOffset,10),lOffset=parseInt(opts.leftOffset,10);var tipHeight,wHeight,defHeight=isNaN(parseInt(opts.height,10))?'auto':(/\D/g).test(opts.height)?opts.height:opts.height+'px';var sTop,linkTop,posY,tipY,mouseY,baseline;var tipInnerWidth=parseInt(opts.width,10)||275,tipWidth=tipInnerWidth+(parseInt($cluetip.css('paddingLeft'),10)||0)+(parseInt($cluetip.css('paddingRight'),10)||0)+dropShadowSteps,linkWidth=this.offsetWidth,linkLeft,posX,tipX,mouseX,winWidth;var tipParts;var tipTitle=(opts.attribute!='title')?$this.attr(opts.titleAttribute):'';if(opts.splitTitle){if(tipTitle==undefined){tipTitle='';}
  631.32 +tipParts=tipTitle.split(opts.splitTitle);tipTitle=tipParts.shift();}
  631.33 +if(opts.escapeTitle){tipTitle=tipTitle.replace(/&/g,'&').replace(/>/g,'>').replace(/</g,'<');}
  631.34 +var localContent;function returnFalse(){return false;}
  631.35 +var activate=function(event){if(!opts.onActivate($this)){return false;}
  631.36 +isActive=true;$cluetip.removeClass().css({width:tipInnerWidth});if(tipAttribute==$this.attr('href')){$this.css('cursor',opts.cursor);}
  631.37 +if(opts.hoverClass){$this.addClass(opts.hoverClass);}
  631.38 +linkTop=posY=$this.offset().top;linkLeft=$this.offset().left;mouseX=event.pageX;mouseY=event.pageY;if(link.tagName.toLowerCase()!='area'){sTop=$(document).scrollTop();winWidth=$(window).width();}
  631.39 +if(opts.positionBy=='fixed'){posX=linkWidth+linkLeft+lOffset;$cluetip.css({left:posX});}else{posX=(linkWidth>linkLeft&&linkLeft>tipWidth)||linkLeft+linkWidth+tipWidth+lOffset>winWidth?linkLeft-tipWidth-lOffset:linkWidth+linkLeft+lOffset;if(link.tagName.toLowerCase()=='area'||opts.positionBy=='mouse'||linkWidth+tipWidth>winWidth){if(mouseX+20+tipWidth>winWidth){$cluetip.addClass(' cluetip-'+ctClass);posX=(mouseX-tipWidth-lOffset)>=0?mouseX-tipWidth-lOffset-parseInt($cluetip.css('marginLeft'),10)+parseInt($cluetipInner.css('marginRight'),10):mouseX-(tipWidth/2);}else{posX=mouseX+lOffset;}}
  631.40 +var pY=posX<0?event.pageY+tOffset:event.pageY;$cluetip.css({left:(posX>0&&opts.positionBy!='bottomTop')?posX:(mouseX+(tipWidth/2)>winWidth)?winWidth/2-tipWidth/2:Math.max(mouseX-(tipWidth/2),0),zIndex:$this.data('thisInfo').zIndex});$cluetipArrows.css({zIndex:$this.data('thisInfo').zIndex+1});}
  631.41 +wHeight=$(window).height();if(js){if(typeof js=='function'){js=js.call(link);}
  631.42 +$cluetipInner.html(js);cluetipShow(pY);}
  631.43 +else if(tipParts){var tpl=tipParts.length;$cluetipInner.html(tpl?tipParts[0]:'');if(tpl>1){for(var i=1;i<tpl;i++){$cluetipInner.append('<div class="split-body">'+tipParts[i]+'</div>');}}
  631.44 +cluetipShow(pY);}
  631.45 +else if(!opts.local&&tipAttribute.indexOf('#')!==0){if(/\.(jpe?g|tiff?|gif|png)$/i.test(tipAttribute)){$cluetipInner.html('<img src="'+tipAttribute+'" alt="'+tipTitle+'" />');cluetipShow(pY);}else if(cluetipContents&&opts.ajaxCache){$cluetipInner.html(cluetipContents);cluetipShow(pY);}else{var optionBeforeSend=opts.ajaxSettings.beforeSend,optionError=opts.ajaxSettings.error,optionSuccess=opts.ajaxSettings.success,optionComplete=opts.ajaxSettings.complete;var ajaxSettings={cache:false,url:tipAttribute,beforeSend:function(xhr){if(optionBeforeSend){optionBeforeSend.call(link,xhr,$cluetip,$cluetipInner);}
  631.46 +$cluetipOuter.children().empty();if(opts.waitImage){$cluetipWait.css({top:mouseY+20,left:mouseX+20,zIndex:$this.data('thisInfo').zIndex-1}).show();}},error:function(xhr,textStatus){if(isActive){if(optionError){optionError.call(link,xhr,textStatus,$cluetip,$cluetipInner);}else{$cluetipInner.html('<i>sorry, the contents could not be loaded</i>');}}},success:function(data,textStatus){cluetipContents=opts.ajaxProcess.call(link,data);if(isActive){if(optionSuccess){optionSuccess.call(link,data,textStatus,$cluetip,$cluetipInner);}
  631.47 +$cluetipInner.html(cluetipContents);}},complete:function(xhr,textStatus){if(optionComplete){optionComplete.call(link,xhr,textStatus,$cluetip,$cluetipInner);}
  631.48 +imgCount=$('#cluetip-inner img').length;if(imgCount&&!$.browser.opera){$('#cluetip-inner img').bind('load error',function(){imgCount--;if(imgCount<1){$cluetipWait.hide();if(isActive){cluetipShow(pY);}}});}else{$cluetipWait.hide();if(isActive){cluetipShow(pY);}}}};var ajaxMergedSettings=$.extend(true,{},opts.ajaxSettings,ajaxSettings);$.ajax(ajaxMergedSettings);}}else if(opts.local){var $localContent=$(tipAttribute+(/#\S+$/.test(tipAttribute)?'':':eq('+index+')')).clone(true).show();$cluetipInner.html($localContent);cluetipShow(pY);}};var cluetipShow=function(bpY){$cluetip.addClass('cluetip-'+ctClass);if(opts.truncate){var $truncloaded=$cluetipInner.text().slice(0,opts.truncate)+'...';$cluetipInner.html($truncloaded);}
  631.49 +function doNothing(){};tipTitle?$cluetipTitle.show().html(tipTitle):(opts.showTitle)?$cluetipTitle.show().html(' '):$cluetipTitle.hide();if(opts.sticky){var $closeLink=$('<div id="cluetip-close"><a href="#">'+opts.closeText+'</a></div>');(opts.closePosition=='bottom')?$closeLink.appendTo($cluetipInner):(opts.closePosition=='title')?$closeLink.prependTo($cluetipTitle):$closeLink.prependTo($cluetipInner);$closeLink.bind('click.cluetip',function(){cluetipClose();return false;});if(opts.mouseOutClose){$cluetip.bind('mouseleave.cluetip',function(){cluetipClose();});}else{$cluetip.unbind('mouseleave.cluetip');}}
  631.50 +var direction='';$cluetipOuter.css({zIndex:$this.data('thisInfo').zIndex,overflow:defHeight=='auto'?'visible':'auto',height:defHeight});tipHeight=defHeight=='auto'?Math.max($cluetip.outerHeight(),$cluetip.height()):parseInt(defHeight,10);tipY=posY;baseline=sTop+wHeight;if(opts.positionBy=='fixed'){tipY=posY-opts.dropShadowSteps+tOffset;}else if((posX<mouseX&&Math.max(posX,0)+tipWidth>mouseX)||opts.positionBy=='bottomTop'){if(posY+tipHeight+tOffset>baseline&&mouseY-sTop>tipHeight+tOffset){tipY=mouseY-tipHeight-tOffset;direction='top';}else{tipY=mouseY+tOffset;direction='bottom';}}else if(posY+tipHeight+tOffset>baseline){tipY=(tipHeight>=wHeight)?sTop:baseline-tipHeight-tOffset;}else if($this.css('display')=='block'||link.tagName.toLowerCase()=='area'||opts.positionBy=="mouse"){tipY=bpY-tOffset;}else{tipY=posY-opts.dropShadowSteps;}
  631.51 +if(direction==''){posX<linkLeft?direction='left':direction='right';}
  631.52 +$cluetip.css({top:tipY+'px'}).removeClass().addClass('clue-'+direction+'-'+ctClass).addClass(' cluetip-'+ctClass);if(opts.arrows){var bgY=(posY-tipY-opts.dropShadowSteps);$cluetipArrows.css({top:(/(left|right)/.test(direction)&&posX>=0&&bgY>0)?bgY+'px':/(left|right)/.test(direction)?0:''}).show();}else{$cluetipArrows.hide();}
  631.53 +$dropShadow.hide();$cluetip.hide()[opts.fx.open](opts.fx.openSpeed||0);if(opts.dropShadow){$dropShadow.css({height:tipHeight,width:tipInnerWidth,zIndex:$this.data('thisInfo').zIndex-1}).show();}
  631.54 +if($.fn.bgiframe){$cluetip.bgiframe();}
  631.55 +if(opts.delayedClose>0){closeOnDelay=setTimeout(cluetipClose,opts.delayedClose);}
  631.56 +opts.onShow.call(link,$cluetip,$cluetipInner);};var inactivate=function(event){isActive=false;$cluetipWait.hide();if(!opts.sticky||(/click|toggle/).test(opts.activation)){cluetipClose();clearTimeout(closeOnDelay);}
  631.57 +if(opts.hoverClass){$this.removeClass(opts.hoverClass);}};var cluetipClose=function(){$cluetipOuter.parent().hide().removeClass();opts.onHide.call(link,$cluetip,$cluetipInner);$this.removeClass('cluetip-clicked');if(tipTitle){$this.attr(opts.titleAttribute,tipTitle);}
  631.58 +$this.css('cursor','');if(opts.arrows){$cluetipArrows.css({top:''});}};$(document).bind('hideCluetip',function(e){cluetipClose();});if((/click|toggle/).test(opts.activation)){$this.bind('click.cluetip',function(event){if($cluetip.is(':hidden')||!$this.is('.cluetip-clicked')){activate(event);$('.cluetip-clicked').removeClass('cluetip-clicked');$this.addClass('cluetip-clicked');}else{inactivate(event);}
  631.59 +this.blur();return false;});}else if(opts.activation=='focus'){$this.bind('focus.cluetip',function(event){activate(event);});$this.bind('blur.cluetip',function(event){inactivate(event);});}else{$this[opts.clickThrough?'unbind':'bind']('click',returnFalse);var mouseTracks=function(evt){if(opts.tracking==true){var trackX=posX-evt.pageX;var trackY=tipY?tipY-evt.pageY:posY-evt.pageY;$this.bind('mousemove.cluetip',function(evt){$cluetip.css({left:evt.pageX+trackX,top:evt.pageY+trackY});});}};if($.fn.hoverIntent&&opts.hoverIntent){$this.hoverIntent({sensitivity:opts.hoverIntent.sensitivity,interval:opts.hoverIntent.interval,over:function(event){activate(event);mouseTracks(event);},timeout:opts.hoverIntent.timeout,out:function(event){inactivate(event);$this.unbind('mousemove.cluetip');}});}else{$this.bind('mouseenter.cluetip',function(event){activate(event);mouseTracks(event);}).bind('mouseleave.cluetip',function(event){inactivate(event);$this.unbind('mousemove.cluetip');});}
  631.60 +$this.bind('mouseover.cluetip',function(event){$this.attr('title','');}).bind('mouseleave.cluetip',function(event){$this.attr('title',$this.data('thisInfo').title);});}});};$.fn.cluetip.defaults={width:275,height:'auto',cluezIndex:97,positionBy:'auto',topOffset:15,leftOffset:15,local:false,localPrefix:null,hideLocal:true,attribute:'rel',titleAttribute:'title',splitTitle:'',escapeTitle:false,showTitle:true,cluetipClass:'default',hoverClass:'',waitImage:true,cursor:'help',arrows:false,dropShadow:true,dropShadowSteps:6,sticky:false,mouseOutClose:false,activation:'hover',clickThrough:false,tracking:false,delayedClose:0,closePosition:'top',closeText:'Close',truncate:0,fx:{open:'show',openSpeed:''},hoverIntent:{sensitivity:3,interval:50,timeout:0},onActivate:function(e){return true;},onShow:function(ct,ci){},onHide:function(ct,ci){},ajaxCache:true,ajaxProcess:function(data){data=data.replace(/<(script|style|title)[^<]+<\/(script|style|title)>/gm,'').replace(/<(link|meta)[^>]+>/g,'');return data;},ajaxSettings:{dataType:'html'},debug:false};var insertionType='appendTo',insertionElement='body';$.cluetip.setup=function(options){if(options&&options.insertionType&&(options.insertionType).match(/appendTo|prependTo|insertBefore|insertAfter/)){insertionType=options.insertionType;}
  631.61 +if(options&&options.insertionElement){insertionElement=options.insertionElement;}};})(jQuery);
  631.62 \ No newline at end of file
   632.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   632.2 +++ b/web/static/js/cluetip-1.0.6/lib/jquery-1.3.2.js	Mon Apr 26 11:16:23 2010 +0200
   632.3 @@ -0,0 +1,4675 @@
   632.4 +/*!
   632.5 + * jQuery JavaScript Library v1.3.3pre
   632.6 + * http://jquery.com/
   632.7 + *
   632.8 + * Copyright (c) 2009 John Resig
   632.9 + * Dual licensed under the MIT and GPL licenses.
  632.10 + * http://docs.jquery.com/License
  632.11 + *
  632.12 + * Date: 2021-06-04 13:36:23 -0400 (Thu, 04 Jun 2021)
  632.13 + * Revision: 6372
  632.14 + */
  632.15 +(function(window, undefined){
  632.16 +
  632.17 +// Define a local copy of jQuery
  632.18 +var jQuery = function( selector, context ) {
  632.19 +		// The jQuery object is actually just the init constructor 'enhanced'
  632.20 +		return arguments.length === 0 ?
  632.21 +			rootjQuery :
  632.22 +			new jQuery.fn.init( selector, context );
  632.23 +	},
  632.24 +
  632.25 +	// Map over jQuery in case of overwrite
  632.26 +	_jQuery = window.jQuery,
  632.27 +
  632.28 +	// Map over the $ in case of overwrite
  632.29 +	_$ = window.$,
  632.30 +
  632.31 +	// A central reference to the root jQuery(document)
  632.32 +	rootjQuery,
  632.33 +
  632.34 +	// A simple way to check for HTML strings or ID strings
  632.35 +	// (both of which we optimize for)
  632.36 +	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
  632.37 +
  632.38 +	// Is it a simple selector
  632.39 +	isSimple = /^.[^:#\[\.,]*$/,
  632.40 +
  632.41 +	// Keep a UserAgent string for use with jQuery.browser
  632.42 +	userAgent = navigator.userAgent.toLowerCase(),
  632.43 +
  632.44 +	// Save a reference to the core toString method
  632.45 +	toString = Object.prototype.toString;
  632.46 +
  632.47 +// Expose jQuery to the global object
  632.48 +window.jQuery = window.$ = jQuery;
  632.49 +
  632.50 +jQuery.fn = jQuery.prototype = {
  632.51 +	init: function( selector, context ) {
  632.52 +		var match, elem, ret;
  632.53 +
  632.54 +		// Handle $(""), $(null), or $(undefined)
  632.55 +		if ( !selector ) {
  632.56 +			this.length = 0;
  632.57 +			return this;
  632.58 +		}
  632.59 +
  632.60 +		// Handle $(DOMElement)
  632.61 +		if ( selector.nodeType ) {
  632.62 +			this[0] = selector;
  632.63 +			this.length = 1;
  632.64 +			this.context = selector;
  632.65 +			return this;
  632.66 +		}
  632.67 +
  632.68 +		// Handle HTML strings
  632.69 +		if ( typeof selector === "string" ) {
  632.70 +			// Are we dealing with HTML string or an ID?
  632.71 +			match = quickExpr.exec( selector );
  632.72 +
  632.73 +			// Verify a match, and that no context was specified for #id
  632.74 +			if ( match && (match[1] || !context) ) {
  632.75 +
  632.76 +				// HANDLE: $(html) -> $(array)
  632.77 +				if ( match[1] ) {
  632.78 +					selector = jQuery.clean( [ match[1] ], context );
  632.79 +
  632.80 +				// HANDLE: $("#id")
  632.81 +				} else {
  632.82 +					elem = document.getElementById( match[3] );
  632.83 +
  632.84 +					// Handle the case where IE and Opera return items
  632.85 +					// by name instead of ID
  632.86 +					if ( elem && elem.id !== match[3] ) {
  632.87 +						return rootjQuery.find( selector );
  632.88 +					}
  632.89 +
  632.90 +					// Otherwise, we inject the element directly into the jQuery object
  632.91 +					ret = jQuery( elem || null );
  632.92 +					ret.context = document;
  632.93 +					ret.selector = selector;
  632.94 +					return ret;
  632.95 +				}
  632.96 +
  632.97 +			// HANDLE: $(expr, $(...))
  632.98 +			} else if ( !context || context.jquery ) {
  632.99 +				return (context || rootjQuery).find( selector );
 632.100 +
 632.101 +			// HANDLE: $(expr, context)
 632.102 +			// (which is just equivalent to: $(context).find(expr)
 632.103 +			} else {
 632.104 +				return jQuery( context ).find( selector );
 632.105 +			}
 632.106 +
 632.107 +		// HANDLE: $(function)
 632.108 +		// Shortcut for document ready
 632.109 +		} else if ( jQuery.isFunction( selector ) ) {
 632.110 +			return rootjQuery.ready( selector );
 632.111 +		}
 632.112 +
 632.113 +		// Make sure that old selector state is passed along
 632.114 +		if ( selector.selector && selector.context ) {
 632.115 +			this.selector = selector.selector;
 632.116 +			this.context = selector.context;
 632.117 +		}
 632.118 +
 632.119 +		return this.setArray(jQuery.isArray( selector ) ?
 632.120 +			selector :
 632.121 +			jQuery.makeArray(selector));
 632.122 +	},
 632.123 +
 632.124 +	// Start with an empty selector
 632.125 +	selector: "",
 632.126 +
 632.127 +	// The current version of jQuery being used
 632.128 +	jquery: "1.3.3pre",
 632.129 +
 632.130 +	// The number of elements contained in the matched element set
 632.131 +	size: function() {
 632.132 +		return this.length;
 632.133 +	},
 632.134 +
 632.135 +	// Get the Nth element in the matched element set OR
 632.136 +	// Get the whole matched element set as a clean array
 632.137 +	get: function( num ) {
 632.138 +		return num == null ?
 632.139 +
 632.140 +			// Return a 'clean' array
 632.141 +			Array.prototype.slice.call( this ) :
 632.142 +
 632.143 +			// Return just the object
 632.144 +			this[ num ];
 632.145 +	},
 632.146 +
 632.147 +	// Take an array of elements and push it onto the stack
 632.148 +	// (returning the new matched element set)
 632.149 +	pushStack: function( elems, name, selector ) {
 632.150 +		// Build a new jQuery matched element set
 632.151 +		var ret = jQuery( elems || null );
 632.152 +
 632.153 +		// Add the old object onto the stack (as a reference)
 632.154 +		ret.prevObject = this;
 632.155 +
 632.156 +		ret.context = this.context;
 632.157 +
 632.158 +		if ( name === "find" ) {
 632.159 +			ret.selector = this.selector + (this.selector ? " " : "") + selector;
 632.160 +		} else if ( name ) {
 632.161 +			ret.selector = this.selector + "." + name + "(" + selector + ")";
 632.162 +		}
 632.163 +
 632.164 +		// Return the newly-formed element set
 632.165 +		return ret;
 632.166 +	},
 632.167 +
 632.168 +	// Force the current matched set of elements to become
 632.169 +	// the specified array of elements (destroying the stack in the process)
 632.170 +	// You should use pushStack() in order to do this, but maintain the stack
 632.171 +	setArray: function( elems ) {
 632.172 +		// Resetting the length to 0, then using the native Array push
 632.173 +		// is a super-fast way to populate an object with array-like properties
 632.174 +		this.length = 0;
 632.175 +		Array.prototype.push.apply( this, elems );
 632.176 +
 632.177 +		return this;
 632.178 +	},
 632.179 +
 632.180 +	// Execute a callback for every element in the matched set.
 632.181 +	// (You can seed the arguments with an array of args, but this is
 632.182 +	// only used internally.)
 632.183 +	each: function( callback, args ) {
 632.184 +		return jQuery.each( this, callback, args );
 632.185 +	},
 632.186 +
 632.187 +	// Determine the position of an element within
 632.188 +	// the matched set of elements
 632.189 +	index: function( elem ) {
 632.190 +		if ( !elem || typeof elem === "string" ) {
 632.191 +			return jQuery.inArray( this[0],
 632.192 +				// If it receives a string, the selector is used
 632.193 +				// If it receives nothing, the siblings are used
 632.194 +				elem ? jQuery( elem ) : this.parent().children() );
 632.195 +		}
 632.196 +		// Locate the position of the desired element
 632.197 +		return jQuery.inArray(
 632.198 +			// If it receives a jQuery object, the first element is used
 632.199 +			elem.jquery ? elem[0] : elem, this );
 632.200 +	},
 632.201 +
 632.202 +	is: function( selector ) {
 632.203 +		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
 632.204 +	},
 632.205 +
 632.206 +	// For internal use only.
 632.207 +	// Behaves like an Array's method, not like a jQuery method.
 632.208 +	push: [].push,
 632.209 +	sort: [].sort,
 632.210 +	splice: [].splice
 632.211 +};
 632.212 +
 632.213 +// Give the init function the jQuery prototype for later instantiation
 632.214 +jQuery.fn.init.prototype = jQuery.fn;
 632.215 +
 632.216 +jQuery.extend = jQuery.fn.extend = function() {
 632.217 +	// copy reference to target object
 632.218 +	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
 632.219 +
 632.220 +	// Handle a deep copy situation
 632.221 +	if ( typeof target === "boolean" ) {
 632.222 +		deep = target;
 632.223 +		target = arguments[1] || {};
 632.224 +		// skip the boolean and the target
 632.225 +		i = 2;
 632.226 +	}
 632.227 +
 632.228 +	// Handle case when target is a string or something (possible in deep copy)
 632.229 +	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
 632.230 +		target = {};
 632.231 +	}
 632.232 +
 632.233 +	// extend jQuery itself if only one argument is passed
 632.234 +	if ( length === i ) {
 632.235 +		target = this;
 632.236 +		--i;
 632.237 +	}
 632.238 +
 632.239 +	for ( ; i < length; i++ ) {
 632.240 +		// Only deal with non-null/undefined values
 632.241 +		if ( (options = arguments[ i ]) != null ) {
 632.242 +			// Extend the base object
 632.243 +			for ( name in options ) {
 632.244 +				src = target[ name ];
 632.245 +				copy = options[ name ];
 632.246 +
 632.247 +				// Prevent never-ending loop
 632.248 +				if ( target === copy ) {
 632.249 +					continue;
 632.250 +				}
 632.251 +
 632.252 +				// Recurse if we're merging object values
 632.253 +				if ( deep && copy && typeof copy === "object" && !copy.nodeType ) {
 632.254 +					target[ name ] = jQuery.extend( deep,
 632.255 +						// Never move original objects, clone them
 632.256 +						src || ( copy.length != null ? [ ] : { } ), copy );
 632.257 +
 632.258 +				// Don't bring in undefined values
 632.259 +				} else if ( copy !== undefined ) {
 632.260 +					target[ name ] = copy;
 632.261 +				}
 632.262 +			}
 632.263 +		}
 632.264 +	}
 632.265 +
 632.266 +	// Return the modified object
 632.267 +	return target;
 632.268 +};
 632.269 +
 632.270 +jQuery.extend({
 632.271 +	noConflict: function( deep ) {
 632.272 +		window.$ = _$;
 632.273 +
 632.274 +		if ( deep ) {
 632.275 +			window.jQuery = _jQuery;
 632.276 +		}
 632.277 +
 632.278 +		return jQuery;
 632.279 +	},
 632.280 +
 632.281 +	// See test/unit/core.js for details concerning isFunction.
 632.282 +	// Since version 1.3, DOM methods and functions like alert
 632.283 +	// aren't supported. They return false on IE (#2968).
 632.284 +	isFunction: function( obj ) {
 632.285 +		return toString.call(obj) === "[object Function]";
 632.286 +	},
 632.287 +
 632.288 +	isArray: function( obj ) {
 632.289 +		return toString.call(obj) === "[object Array]";
 632.290 +	},
 632.291 +
 632.292 +	// check if an element is in a (or is an) XML document
 632.293 +	isXMLDoc: function( elem ) {
 632.294 +		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
 632.295 +			!!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
 632.296 +	},
 632.297 +
 632.298 +	// Evalulates a script in a global context
 632.299 +	globalEval: function( data ) {
 632.300 +		if ( data && /\S/.test(data) ) {
 632.301 +			// Inspired by code by Andrea Giammarchi
 632.302 +			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
 632.303 +			var head = document.getElementsByTagName("head")[0] || document.documentElement,
 632.304 +				script = document.createElement("script");
 632.305 +
 632.306 +			script.type = "text/javascript";
 632.307 +			if ( jQuery.support.scriptEval ) {
 632.308 +				script.appendChild( document.createTextNode( data ) );
 632.309 +			} else {
 632.310 +				script.text = data;
 632.311 +			}
 632.312 +
 632.313 +			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
 632.314 +			// This arises when a base node is used (#2709).
 632.315 +			head.insertBefore( script, head.firstChild );
 632.316 +			head.removeChild( script );
 632.317 +		}
 632.318 +	},
 632.319 +
 632.320 +	nodeName: function( elem, name ) {
 632.321 +		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
 632.322 +	},
 632.323 +
 632.324 +	// args is for internal usage only
 632.325 +	each: function( object, callback, args ) {
 632.326 +		var name, i = 0, length = object.length;
 632.327 +
 632.328 +		if ( args ) {
 632.329 +			if ( length === undefined ) {
 632.330 +				for ( name in object ) {
 632.331 +					if ( callback.apply( object[ name ], args ) === false ) {
 632.332 +						break;
 632.333 +					}
 632.334 +				}
 632.335 +			} else {
 632.336 +				for ( ; i < length; ) {
 632.337 +					if ( callback.apply( object[ i++ ], args ) === false ) {
 632.338 +						break;
 632.339 +					}
 632.340 +				}
 632.341 +			}
 632.342 +
 632.343 +		// A special, fast, case for the most common use of each
 632.344 +		} else {
 632.345 +			if ( length === undefined ) {
 632.346 +				for ( name in object ) {
 632.347 +					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
 632.348 +						break;
 632.349 +					}
 632.350 +				}
 632.351 +			} else {
 632.352 +				for ( var value = object[0];
 632.353 +					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
 632.354 +			}
 632.355 +		}
 632.356 +
 632.357 +		return object;
 632.358 +	},
 632.359 +
 632.360 +	trim: function( text ) {
 632.361 +		return (text || "").replace( /^\s+|\s+$/g, "" );
 632.362 +	},
 632.363 +
 632.364 +	makeArray: function( array ) {
 632.365 +		var ret = [], i;
 632.366 +
 632.367 +		if ( array != null ) {
 632.368 +			i = array.length;
 632.369 +
 632.370 +			// The window, strings (and functions) also have 'length'
 632.371 +			if ( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval ) {
 632.372 +				ret[0] = array;
 632.373 +			} else {
 632.374 +				while ( i ) {
 632.375 +					ret[--i] = array[i];
 632.376 +				}
 632.377 +			}
 632.378 +		}
 632.379 +
 632.380 +		return ret;
 632.381 +	},
 632.382 +
 632.383 +	inArray: function( elem, array ) {
 632.384 +		for ( var i = 0, length = array.length; i < length; i++ ) {
 632.385 +			if ( array[ i ] === elem ) {
 632.386 +				return i;
 632.387 +			}
 632.388 +		}
 632.389 +
 632.390 +		return -1;
 632.391 +	},
 632.392 +
 632.393 +	merge: function( first, second ) {
 632.394 +		// We have to loop this way because IE & Opera overwrite the length
 632.395 +		// expando of getElementsByTagName
 632.396 +		var i = 0, elem, pos = first.length;
 632.397 +
 632.398 +		// Also, we need to make sure that the correct elements are being returned
 632.399 +		// (IE returns comment nodes in a '*' query)
 632.400 +		if ( !jQuery.support.getAll ) {
 632.401 +			while ( (elem = second[ i++ ]) != null ) {
 632.402 +				if ( elem.nodeType !== 8 ) {
 632.403 +					first[ pos++ ] = elem;
 632.404 +				}
 632.405 +			}
 632.406 +
 632.407 +		} else {
 632.408 +			while ( (elem = second[ i++ ]) != null ) {
 632.409 +				first[ pos++ ] = elem;
 632.410 +			}
 632.411 +		}
 632.412 +
 632.413 +		return first;
 632.414 +	},
 632.415 +
 632.416 +	unique: function( array ) {
 632.417 +		var ret = [], done = {}, id;
 632.418 +
 632.419 +		try {
 632.420 +			for ( var i = 0, length = array.length; i < length; i++ ) {
 632.421 +				id = jQuery.data( array[ i ] );
 632.422 +
 632.423 +				if ( !done[ id ] ) {
 632.424 +					done[ id ] = true;
 632.425 +					ret.push( array[ i ] );
 632.426 +				}
 632.427 +			}
 632.428 +		} catch( e ) {
 632.429 +			ret = array;
 632.430 +		}
 632.431 +
 632.432 +		return ret;
 632.433 +	},
 632.434 +
 632.435 +	grep: function( elems, callback, inv ) {
 632.436 +		var ret = [];
 632.437 +
 632.438 +		// Go through the array, only saving the items
 632.439 +		// that pass the validator function
 632.440 +		for ( var i = 0, length = elems.length; i < length; i++ ) {
 632.441 +			if ( !inv !== !callback( elems[ i ], i ) ) {
 632.442 +				ret.push( elems[ i ] );
 632.443 +			}
 632.444 +		}
 632.445 +
 632.446 +		return ret;
 632.447 +	},
 632.448 +
 632.449 +	map: function( elems, callback ) {
 632.450 +		var ret = [], value;
 632.451 +
 632.452 +		// Go through the array, translating each of the items to their
 632.453 +		// new value (or values).
 632.454 +		for ( var i = 0, length = elems.length; i < length; i++ ) {
 632.455 +			value = callback( elems[ i ], i );
 632.456 +
 632.457 +			if ( value != null ) {
 632.458 +				ret[ ret.length ] = value;
 632.459 +			}
 632.460 +		}
 632.461 +
 632.462 +		return ret.concat.apply( [], ret );
 632.463 +	},
 632.464 +
 632.465 +	// Use of jQuery.browser is deprecated.
 632.466 +	// It's included for backwards compatibility and plugins,
 632.467 +	// although they should work to migrate away.
 632.468 +	browser: {
 632.469 +		version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
 632.470 +		safari: /webkit/.test( userAgent ),
 632.471 +		opera: /opera/.test( userAgent ),
 632.472 +		msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
 632.473 +		mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
 632.474 +	}
 632.475 +});
 632.476 +
 632.477 +// All jQuery objects should point back to these
 632.478 +rootjQuery = jQuery(document);
 632.479 +
 632.480 +function evalScript( i, elem ) {
 632.481 +	if ( elem.src ) {
 632.482 +		jQuery.ajax({
 632.483 +			url: elem.src,
 632.484 +			async: false,
 632.485 +			dataType: "script"
 632.486 +		});
 632.487 +	} else {
 632.488 +		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
 632.489 +	}
 632.490 +
 632.491 +	if ( elem.parentNode ) {
 632.492 +		elem.parentNode.removeChild( elem );
 632.493 +	}
 632.494 +}
 632.495 +
 632.496 +function now() {
 632.497 +	return (new Date).getTime();
 632.498 +}
 632.499 +var expando = "jQuery" + now(), uuid = 0, windowData = {};
 632.500 +
 632.501 +jQuery.extend({
 632.502 +	cache: {},
 632.503 +
 632.504 +	data: function( elem, name, data ) {
 632.505 +		elem = elem == window ?
 632.506 +			windowData :
 632.507 +			elem;
 632.508 +
 632.509 +		var id = elem[ expando ];
 632.510 +
 632.511 +		// Compute a unique ID for the element
 632.512 +		if ( !id )
 632.513 +			id = elem[ expando ] = ++uuid;
 632.514 +
 632.515 +		// Only generate the data cache if we're
 632.516 +		// trying to access or manipulate it
 632.517 +		if ( name && !jQuery.cache[ id ] )
 632.518 +			jQuery.cache[ id ] = {};
 632.519 +
 632.520 +		// Prevent overriding the named cache with undefined values
 632.521 +		if ( data !== undefined )
 632.522 +			jQuery.cache[ id ][ name ] = data;
 632.523 +
 632.524 +		// Return the named cache data, or the ID for the element
 632.525 +		return name ?
 632.526 +			jQuery.cache[ id ][ name ] :
 632.527 +			id;
 632.528 +	},
 632.529 +
 632.530 +	removeData: function( elem, name ) {
 632.531 +		elem = elem == window ?
 632.532 +			windowData :
 632.533 +			elem;
 632.534 +
 632.535 +		var id = elem[ expando ];
 632.536 +
 632.537 +		// If we want to remove a specific section of the element's data
 632.538 +		if ( name ) {
 632.539 +			if ( jQuery.cache[ id ] ) {
 632.540 +				// Remove the section of cache data
 632.541 +				delete jQuery.cache[ id ][ name ];
 632.542 +
 632.543 +				// If we've removed all the data, remove the element's cache
 632.544 +				name = "";
 632.545 +
 632.546 +				for ( name in jQuery.cache[ id ] )
 632.547 +					break;
 632.548 +
 632.549 +				if ( !name )
 632.550 +					jQuery.removeData( elem );
 632.551 +			}
 632.552 +
 632.553 +		// Otherwise, we want to remove all of the element's data
 632.554 +		} else {
 632.555 +			// Clean up the element expando
 632.556 +			try {
 632.557 +				delete elem[ expando ];
 632.558 +			} catch(e){
 632.559 +				// IE has trouble directly removing the expando
 632.560 +				// but it's ok with using removeAttribute
 632.561 +				if ( elem.removeAttribute )
 632.562 +					elem.removeAttribute( expando );
 632.563 +			}
 632.564 +
 632.565 +			// Completely remove the data cache
 632.566 +			delete jQuery.cache[ id ];
 632.567 +		}
 632.568 +	},
 632.569 +	queue: function( elem, type, data ) {
 632.570 +		if ( elem ){
 632.571 +
 632.572 +			type = (type || "fx") + "queue";
 632.573 +
 632.574 +			var q = jQuery.data( elem, type );
 632.575 +
 632.576 +			if ( !q || jQuery.isArray(data) )
 632.577 +				q = jQuery.data( elem, type, jQuery.makeArray(data) );
 632.578 +			else if( data )
 632.579 +				q.push( data );
 632.580 +
 632.581 +		}
 632.582 +		return q;
 632.583 +	},
 632.584 +
 632.585 +	dequeue: function( elem, type ){
 632.586 +		var queue = jQuery.queue( elem, type ),
 632.587 +			fn = queue.shift();
 632.588 +
 632.589 +		if( !type || type === "fx" )
 632.590 +			fn = queue[0];
 632.591 +
 632.592 +		if( fn !== undefined )
 632.593 +			fn.call(elem);
 632.594 +	}
 632.595 +});
 632.596 +
 632.597 +jQuery.fn.extend({
 632.598 +	data: function( key, value ){
 632.599 +		var parts = key.split(".");
 632.600 +		parts[1] = parts[1] ? "." + parts[1] : "";
 632.601 +
 632.602 +		if ( value === undefined ) {
 632.603 +			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
 632.604 +
 632.605 +			if ( data === undefined && this.length )
 632.606 +				data = jQuery.data( this[0], key );
 632.607 +
 632.608 +			return data === undefined && parts[1] ?
 632.609 +				this.data( parts[0] ) :
 632.610 +				data;
 632.611 +		} else
 632.612 +			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
 632.613 +				jQuery.data( this, key, value );
 632.614 +			});
 632.615 +	},
 632.616 +
 632.617 +	removeData: function( key ){
 632.618 +		return this.each(function(){
 632.619 +			jQuery.removeData( this, key );
 632.620 +		});
 632.621 +	},
 632.622 +	queue: function(type, data){
 632.623 +		if ( typeof type !== "string" ) {
 632.624 +			data = type;
 632.625 +			type = "fx";
 632.626 +		}
 632.627 +
 632.628 +		if ( data === undefined )
 632.629 +			return jQuery.queue( this[0], type );
 632.630 +
 632.631 +		return this.each(function(){
 632.632 +			var queue = jQuery.queue( this, type, data );
 632.633 +
 632.634 +			 if( type == "fx" && queue.length == 1 )
 632.635 +				queue[0].call(this);
 632.636 +		});
 632.637 +	},
 632.638 +	dequeue: function(type){
 632.639 +		return this.each(function(){
 632.640 +			jQuery.dequeue( this, type );
 632.641 +		});
 632.642 +	}
 632.643 +});/*!
 632.644 + * Sizzle CSS Selector Engine - v1.0
 632.645 + *  Copyright 2009, The Dojo Foundation
 632.646 + *  Released under the MIT, BSD, and GPL Licenses.
 632.647 + *  More information: http://sizzlejs.com/
 632.648 + */
 632.649 +(function(){
 632.650 +
 632.651 +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
 632.652 +	done = 0,
 632.653 +	toString = Object.prototype.toString,
 632.654 +	hasDuplicate = false;
 632.655 +
 632.656 +var Sizzle = function(selector, context, results, seed) {
 632.657 +	results = results || [];
 632.658 +	var origContext = context = context || document;
 632.659 +
 632.660 +	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
 632.661 +		return [];
 632.662 +	}
 632.663 +	
 632.664 +	if ( !selector || typeof selector !== "string" ) {
 632.665 +		return results;
 632.666 +	}
 632.667 +
 632.668 +	var parts = [], m, set, checkSet, check, mode, extra, prune = true, contextXML = isXML(context);
 632.669 +	
 632.670 +	// Reset the position of the chunker regexp (start from head)
 632.671 +	chunker.lastIndex = 0;
 632.672 +	
 632.673 +	while ( (m = chunker.exec(selector)) !== null ) {
 632.674 +		parts.push( m[1] );
 632.675 +		
 632.676 +		if ( m[2] ) {
 632.677 +			extra = RegExp.rightContext;
 632.678 +			break;
 632.679 +		}
 632.680 +	}
 632.681 +
 632.682 +	if ( parts.length > 1 && origPOS.exec( selector ) ) {
 632.683 +		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
 632.684 +			set = posProcess( parts[0] + parts[1], context );
 632.685 +		} else {
 632.686 +			set = Expr.relative[ parts[0] ] ?
 632.687 +				[ context ] :
 632.688 +				Sizzle( parts.shift(), context );
 632.689 +
 632.690 +			while ( parts.length ) {
 632.691 +				selector = parts.shift();
 632.692 +
 632.693 +				if ( Expr.relative[ selector ] )
 632.694 +					selector += parts.shift();
 632.695 +
 632.696 +				set = posProcess( selector, set );
 632.697 +			}
 632.698 +		}
 632.699 +	} else {
 632.700 +		// Take a shortcut and set the context if the root selector is an ID
 632.701 +		// (but not if it'll be faster if the inner selector is an ID)
 632.702 +		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
 632.703 +				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
 632.704 +			var ret = Sizzle.find( parts.shift(), context, contextXML );
 632.705 +			context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
 632.706 +		}
 632.707 +
 632.708 +		if ( context ) {
 632.709 +			var ret = seed ?
 632.710 +				{ expr: parts.pop(), set: makeArray(seed) } :
 632.711 +				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
 632.712 +			set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
 632.713 +
 632.714 +			if ( parts.length > 0 ) {
 632.715 +				checkSet = makeArray(set);
 632.716 +			} else {
 632.717 +				prune = false;
 632.718 +			}
 632.719 +
 632.720 +			while ( parts.length ) {
 632.721 +				var cur = parts.pop(), pop = cur;
 632.722 +
 632.723 +				if ( !Expr.relative[ cur ] ) {
 632.724 +					cur = "";
 632.725 +				} else {
 632.726 +					pop = parts.pop();
 632.727 +				}
 632.728 +
 632.729 +				if ( pop == null ) {
 632.730 +					pop = context;
 632.731 +				}
 632.732 +
 632.733 +				Expr.relative[ cur ]( checkSet, pop, contextXML );
 632.734 +			}
 632.735 +		} else {
 632.736 +			checkSet = parts = [];
 632.737 +		}
 632.738 +	}
 632.739 +
 632.740 +	if ( !checkSet ) {
 632.741 +		checkSet = set;
 632.742 +	}
 632.743 +
 632.744 +	if ( !checkSet ) {
 632.745 +		throw "Syntax error, unrecognized expression: " + (cur || selector);
 632.746 +	}
 632.747 +
 632.748 +	if ( toString.call(checkSet) === "[object Array]" ) {
 632.749 +		if ( !prune ) {
 632.750 +			results.push.apply( results, checkSet );
 632.751 +		} else if ( context && context.nodeType === 1 ) {
 632.752 +			for ( var i = 0; checkSet[i] != null; i++ ) {
 632.753 +				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
 632.754 +					results.push( set[i] );
 632.755 +				}
 632.756 +			}
 632.757 +		} else {
 632.758 +			for ( var i = 0; checkSet[i] != null; i++ ) {
 632.759 +				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
 632.760 +					results.push( set[i] );
 632.761 +				}
 632.762 +			}
 632.763 +		}
 632.764 +	} else {
 632.765 +		makeArray( checkSet, results );
 632.766 +	}
 632.767 +
 632.768 +	if ( extra ) {
 632.769 +		Sizzle( extra, origContext, results, seed );
 632.770 +		Sizzle.uniqueSort( results );
 632.771 +	}
 632.772 +
 632.773 +	return results;
 632.774 +};
 632.775 +
 632.776 +Sizzle.uniqueSort = function(results){
 632.777 +	if ( sortOrder ) {
 632.778 +		hasDuplicate = false;
 632.779 +		results.sort(sortOrder);
 632.780 +
 632.781 +		if ( hasDuplicate ) {
 632.782 +			for ( var i = 1; i < results.length; i++ ) {
 632.783 +				if ( results[i] === results[i-1] ) {
 632.784 +					results.splice(i--, 1);
 632.785 +				}
 632.786 +			}
 632.787 +		}
 632.788 +	}
 632.789 +};
 632.790 +
 632.791 +Sizzle.matches = function(expr, set){
 632.792 +	return Sizzle(expr, null, null, set);
 632.793 +};
 632.794 +
 632.795 +Sizzle.find = function(expr, context, isXML){
 632.796 +	var set, match;
 632.797 +
 632.798 +	if ( !expr ) {
 632.799 +		return [];
 632.800 +	}
 632.801 +
 632.802 +	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
 632.803 +		var type = Expr.order[i], match;
 632.804 +		
 632.805 +		if ( (match = Expr.match[ type ].exec( expr )) ) {
 632.806 +			var left = RegExp.leftContext;
 632.807 +
 632.808 +			if ( left.substr( left.length - 1 ) !== "\\" ) {
 632.809 +				match[1] = (match[1] || "").replace(/\\/g, "");
 632.810 +				set = Expr.find[ type ]( match, context, isXML );
 632.811 +				if ( set != null ) {
 632.812 +					expr = expr.replace( Expr.match[ type ], "" );
 632.813 +					break;
 632.814 +				}
 632.815 +			}
 632.816 +		}
 632.817 +	}
 632.818 +
 632.819 +	if ( !set ) {
 632.820 +		set = context.getElementsByTagName("*");
 632.821 +	}
 632.822 +
 632.823 +	return {set: set, expr: expr};
 632.824 +};
 632.825 +
 632.826 +Sizzle.filter = function(expr, set, inplace, not){
 632.827 +	var old = expr, result = [], curLoop = set, match, anyFound,
 632.828 +		isXMLFilter = set && set[0] && isXML(set[0]);
 632.829 +
 632.830 +	while ( expr && set.length ) {
 632.831 +		for ( var type in Expr.filter ) {
 632.832 +			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
 632.833 +				var filter = Expr.filter[ type ], found, item;
 632.834 +				anyFound = false;
 632.835 +
 632.836 +				if ( curLoop == result ) {
 632.837 +					result = [];
 632.838 +				}
 632.839 +
 632.840 +				if ( Expr.preFilter[ type ] ) {
 632.841 +					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
 632.842 +
 632.843 +					if ( !match ) {
 632.844 +						anyFound = found = true;
 632.845 +					} else if ( match === true ) {
 632.846 +						continue;
 632.847 +					}
 632.848 +				}
 632.849 +
 632.850 +				if ( match ) {
 632.851 +					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
 632.852 +						if ( item ) {
 632.853 +							found = filter( item, match, i, curLoop );
 632.854 +							var pass = not ^ !!found;
 632.855 +
 632.856 +							if ( inplace && found != null ) {
 632.857 +								if ( pass ) {
 632.858 +									anyFound = true;
 632.859 +								} else {
 632.860 +									curLoop[i] = false;
 632.861 +								}
 632.862 +							} else if ( pass ) {
 632.863 +								result.push( item );
 632.864 +								anyFound = true;
 632.865 +							}
 632.866 +						}
 632.867 +					}
 632.868 +				}
 632.869 +
 632.870 +				if ( found !== undefined ) {
 632.871 +					if ( !inplace ) {
 632.872 +						curLoop = result;
 632.873 +					}
 632.874 +
 632.875 +					expr = expr.replace( Expr.match[ type ], "" );
 632.876 +
 632.877 +					if ( !anyFound ) {
 632.878 +						return [];
 632.879 +					}
 632.880 +
 632.881 +					break;
 632.882 +				}
 632.883 +			}
 632.884 +		}
 632.885 +
 632.886 +		// Improper expression
 632.887 +		if ( expr == old ) {
 632.888 +			if ( anyFound == null ) {
 632.889 +				throw "Syntax error, unrecognized expression: " + expr;
 632.890 +			} else {
 632.891 +				break;
 632.892 +			}
 632.893 +		}
 632.894 +
 632.895 +		old = expr;
 632.896 +	}
 632.897 +
 632.898 +	return curLoop;
 632.899 +};
 632.900 +
 632.901 +var Expr = Sizzle.selectors = {
 632.902 +	order: [ "ID", "NAME", "TAG" ],
 632.903 +	match: {
 632.904 +		ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
 632.905 +		CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
 632.906 +		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
 632.907 +		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
 632.908 +		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
 632.909 +		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
 632.910 +		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
 632.911 +		PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
 632.912 +	},
 632.913 +	attrMap: {
 632.914 +		"class": "className",
 632.915 +		"for": "htmlFor"
 632.916 +	},
 632.917 +	attrHandle: {
 632.918 +		href: function(elem){
 632.919 +			return elem.getAttribute("href");
 632.920 +		}
 632.921 +	},
 632.922 +	relative: {
 632.923 +		"+": function(checkSet, part, isXML){
 632.924 +			var isPartStr = typeof part === "string",
 632.925 +				isTag = isPartStr && !/\W/.test(part),
 632.926 +				isPartStrNotTag = isPartStr && !isTag;
 632.927 +
 632.928 +			if ( isTag && !isXML ) {
 632.929 +				part = part.toUpperCase();
 632.930 +			}
 632.931 +
 632.932 +			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
 632.933 +				if ( (elem = checkSet[i]) ) {
 632.934 +					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
 632.935 +
 632.936 +					checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
 632.937 +						elem || false :
 632.938 +						elem === part;
 632.939 +				}
 632.940 +			}
 632.941 +
 632.942 +			if ( isPartStrNotTag ) {
 632.943 +				Sizzle.filter( part, checkSet, true );
 632.944 +			}
 632.945 +		},
 632.946 +		">": function(checkSet, part, isXML){
 632.947 +			var isPartStr = typeof part === "string";
 632.948 +
 632.949 +			if ( isPartStr && !/\W/.test(part) ) {
 632.950 +				part = isXML ? part : part.toUpperCase();
 632.951 +
 632.952 +				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 632.953 +					var elem = checkSet[i];
 632.954 +					if ( elem ) {
 632.955 +						var parent = elem.parentNode;
 632.956 +						checkSet[i] = parent.nodeName === part ? parent : false;
 632.957 +					}
 632.958 +				}
 632.959 +			} else {
 632.960 +				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 632.961 +					var elem = checkSet[i];
 632.962 +					if ( elem ) {
 632.963 +						checkSet[i] = isPartStr ?
 632.964 +							elem.parentNode :
 632.965 +							elem.parentNode === part;
 632.966 +					}
 632.967 +				}
 632.968 +
 632.969 +				if ( isPartStr ) {
 632.970 +					Sizzle.filter( part, checkSet, true );
 632.971 +				}
 632.972 +			}
 632.973 +		},
 632.974 +		"": function(checkSet, part, isXML){
 632.975 +			var doneName = done++, checkFn = dirCheck;
 632.976 +
 632.977 +			if ( !part.match(/\W/) ) {
 632.978 +				var nodeCheck = part = isXML ? part : part.toUpperCase();
 632.979 +				checkFn = dirNodeCheck;
 632.980 +			}
 632.981 +
 632.982 +			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
 632.983 +		},
 632.984 +		"~": function(checkSet, part, isXML){
 632.985 +			var doneName = done++, checkFn = dirCheck;
 632.986 +
 632.987 +			if ( typeof part === "string" && !part.match(/\W/) ) {
 632.988 +				var nodeCheck = part = isXML ? part : part.toUpperCase();
 632.989 +				checkFn = dirNodeCheck;
 632.990 +			}
 632.991 +
 632.992 +			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
 632.993 +		}
 632.994 +	},
 632.995 +	find: {
 632.996 +		ID: function(match, context, isXML){
 632.997 +			if ( typeof context.getElementById !== "undefined" && !isXML ) {
 632.998 +				var m = context.getElementById(match[1]);
 632.999 +				return m ? [m] : [];
632.1000 +			}
632.1001 +		},
632.1002 +		NAME: function(match, context, isXML){
632.1003 +			if ( typeof context.getElementsByName !== "undefined" ) {
632.1004 +				var ret = [], results = context.getElementsByName(match[1]);
632.1005 +
632.1006 +				for ( var i = 0, l = results.length; i < l; i++ ) {
632.1007 +					if ( results[i].getAttribute("name") === match[1] ) {
632.1008 +						ret.push( results[i] );
632.1009 +					}
632.1010 +				}
632.1011 +
632.1012 +				return ret.length === 0 ? null : ret;
632.1013 +			}
632.1014 +		},
632.1015 +		TAG: function(match, context){
632.1016 +			return context.getElementsByTagName(match[1]);
632.1017 +		}
632.1018 +	},
632.1019 +	preFilter: {
632.1020 +		CLASS: function(match, curLoop, inplace, result, not, isXML){
632.1021 +			match = " " + match[1].replace(/\\/g, "") + " ";
632.1022 +
632.1023 +			if ( isXML ) {
632.1024 +				return match;
632.1025 +			}
632.1026 +
632.1027 +			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
632.1028 +				if ( elem ) {
632.1029 +					if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
632.1030 +						if ( !inplace )
632.1031 +							result.push( elem );
632.1032 +					} else if ( inplace ) {
632.1033 +						curLoop[i] = false;
632.1034 +					}
632.1035 +				}
632.1036 +			}
632.1037 +
632.1038 +			return false;
632.1039 +		},
632.1040 +		ID: function(match){
632.1041 +			return match[1].replace(/\\/g, "");
632.1042 +		},
632.1043 +		TAG: function(match, curLoop){
632.1044 +			for ( var i = 0; curLoop[i] === false; i++ ){}
632.1045 +			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
632.1046 +		},
632.1047 +		CHILD: function(match){
632.1048 +			if ( match[1] == "nth" ) {
632.1049 +				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
632.1050 +				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
632.1051 +					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
632.1052 +					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
632.1053 +
632.1054 +				// calculate the numbers (first)n+(last) including if they are negative
632.1055 +				match[2] = (test[1] + (test[2] || 1)) - 0;
632.1056 +				match[3] = test[3] - 0;
632.1057 +			}
632.1058 +
632.1059 +			// TODO: Move to normal caching system
632.1060 +			match[0] = done++;
632.1061 +
632.1062 +			return match;
632.1063 +		},
632.1064 +		ATTR: function(match, curLoop, inplace, result, not, isXML){
632.1065 +			var name = match[1].replace(/\\/g, "");
632.1066 +			
632.1067 +			if ( !isXML && Expr.attrMap[name] ) {
632.1068 +				match[1] = Expr.attrMap[name];
632.1069 +			}
632.1070 +
632.1071 +			if ( match[2] === "~=" ) {
632.1072 +				match[4] = " " + match[4] + " ";
632.1073 +			}
632.1074 +
632.1075 +			return match;
632.1076 +		},
632.1077 +		PSEUDO: function(match, curLoop, inplace, result, not){
632.1078 +			if ( match[1] === "not" ) {
632.1079 +				// If we're dealing with a complex expression, or a simple one
632.1080 +				if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
632.1081 +					match[3] = Sizzle(match[3], null, null, curLoop);
632.1082 +				} else {
632.1083 +					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
632.1084 +					if ( !inplace ) {
632.1085 +						result.push.apply( result, ret );
632.1086 +					}
632.1087 +					return false;
632.1088 +				}
632.1089 +			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
632.1090 +				return true;
632.1091 +			}
632.1092 +			
632.1093 +			return match;
632.1094 +		},
632.1095 +		POS: function(match){
632.1096 +			match.unshift( true );
632.1097 +			return match;
632.1098 +		}
632.1099 +	},
632.1100 +	filters: {
632.1101 +		enabled: function(elem){
632.1102 +			return elem.disabled === false && elem.type !== "hidden";
632.1103 +		},
632.1104 +		disabled: function(elem){
632.1105 +			return elem.disabled === true;
632.1106 +		},
632.1107 +		checked: function(elem){
632.1108 +			return elem.checked === true;
632.1109 +		},
632.1110 +		selected: function(elem){
632.1111 +			// Accessing this property makes selected-by-default
632.1112 +			// options in Safari work properly
632.1113 +			elem.parentNode.selectedIndex;
632.1114 +			return elem.selected === true;
632.1115 +		},
632.1116 +		parent: function(elem){
632.1117 +			return !!elem.firstChild;
632.1118 +		},
632.1119 +		empty: function(elem){
632.1120 +			return !elem.firstChild;
632.1121 +		},
632.1122 +		has: function(elem, i, match){
632.1123 +			return !!Sizzle( match[3], elem ).length;
632.1124 +		},
632.1125 +		header: function(elem){
632.1126 +			return /h\d/i.test( elem.nodeName );
632.1127 +		},
632.1128 +		text: function(elem){
632.1129 +			return "text" === elem.type;
632.1130 +		},
632.1131 +		radio: function(elem){
632.1132 +			return "radio" === elem.type;
632.1133 +		},
632.1134 +		checkbox: function(elem){
632.1135 +			return "checkbox" === elem.type;
632.1136 +		},
632.1137 +		file: function(elem){
632.1138 +			return "file" === elem.type;
632.1139 +		},
632.1140 +		password: function(elem){
632.1141 +			return "password" === elem.type;
632.1142 +		},
632.1143 +		submit: function(elem){
632.1144 +			return "submit" === elem.type;
632.1145 +		},
632.1146 +		image: function(elem){
632.1147 +			return "image" === elem.type;
632.1148 +		},
632.1149 +		reset: function(elem){
632.1150 +			return "reset" === elem.type;
632.1151 +		},
632.1152 +		button: function(elem){
632.1153 +			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
632.1154 +		},
632.1155 +		input: function(elem){
632.1156 +			return /input|select|textarea|button/i.test(elem.nodeName);
632.1157 +		}
632.1158 +	},
632.1159 +	setFilters: {
632.1160 +		first: function(elem, i){
632.1161 +			return i === 0;
632.1162 +		},
632.1163 +		last: function(elem, i, match, array){
632.1164 +			return i === array.length - 1;
632.1165 +		},
632.1166 +		even: function(elem, i){
632.1167 +			return i % 2 === 0;
632.1168 +		},
632.1169 +		odd: function(elem, i){
632.1170 +			return i % 2 === 1;
632.1171 +		},
632.1172 +		lt: function(elem, i, match){
632.1173 +			return i < match[3] - 0;
632.1174 +		},
632.1175 +		gt: function(elem, i, match){
632.1176 +			return i > match[3] - 0;
632.1177 +		},
632.1178 +		nth: function(elem, i, match){
632.1179 +			return match[3] - 0 == i;
632.1180 +		},
632.1181 +		eq: function(elem, i, match){
632.1182 +			return match[3] - 0 == i;
632.1183 +		}
632.1184 +	},
632.1185 +	filter: {
632.1186 +		PSEUDO: function(elem, match, i, array){
632.1187 +			var name = match[1], filter = Expr.filters[ name ];
632.1188 +
632.1189 +			if ( filter ) {
632.1190 +				return filter( elem, i, match, array );
632.1191 +			} else if ( name === "contains" ) {
632.1192 +				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
632.1193 +			} else if ( name === "not" ) {
632.1194 +				var not = match[3];
632.1195 +
632.1196 +				for ( i = 0, l = not.length; i < l; i++ ) {
632.1197 +					if ( not[i] === elem ) {
632.1198 +						return false;
632.1199 +					}
632.1200 +				}
632.1201 +
632.1202 +				return true;
632.1203 +			}
632.1204 +		},
632.1205 +		CHILD: function(elem, match){
632.1206 +			var type = match[1], node = elem;
632.1207 +			switch (type) {
632.1208 +				case 'only':
632.1209 +				case 'first':
632.1210 +					while ( (node = node.previousSibling) )  {
632.1211 +						if ( node.nodeType === 1 ) return false;
632.1212 +					}
632.1213 +					if ( type == 'first') return true;
632.1214 +					node = elem;
632.1215 +				case 'last':
632.1216 +					while ( (node = node.nextSibling) )  {
632.1217 +						if ( node.nodeType === 1 ) return false;
632.1218 +					}
632.1219 +					return true;
632.1220 +				case 'nth':
632.1221 +					var first = match[2], last = match[3];
632.1222 +
632.1223 +					if ( first == 1 && last == 0 ) {
632.1224 +						return true;
632.1225 +					}
632.1226 +					
632.1227 +					var doneName = match[0],
632.1228 +						parent = elem.parentNode;
632.1229 +	
632.1230 +					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
632.1231 +						var count = 0;
632.1232 +						for ( node = parent.firstChild; node; node = node.nextSibling ) {
632.1233 +							if ( node.nodeType === 1 ) {
632.1234 +								node.nodeIndex = ++count;
632.1235 +							}
632.1236 +						} 
632.1237 +						parent.sizcache = doneName;
632.1238 +					}
632.1239 +					
632.1240 +					var diff = elem.nodeIndex - last;
632.1241 +					if ( first == 0 ) {
632.1242 +						return diff == 0;
632.1243 +					} else {
632.1244 +						return ( diff % first == 0 && diff / first >= 0 );
632.1245 +					}
632.1246 +			}
632.1247 +		},
632.1248 +		ID: function(elem, match){
632.1249 +			return elem.nodeType === 1 && elem.getAttribute("id") === match;
632.1250 +		},
632.1251 +		TAG: function(elem, match){
632.1252 +			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
632.1253 +		},
632.1254 +		CLASS: function(elem, match){
632.1255 +			return (" " + (elem.className || elem.getAttribute("class")) + " ")
632.1256 +				.indexOf( match ) > -1;
632.1257 +		},
632.1258 +		ATTR: function(elem, match){
632.1259 +			var name = match[1],
632.1260 +				result = Expr.attrHandle[ name ] ?
632.1261 +					Expr.attrHandle[ name ]( elem ) :
632.1262 +					elem[ name ] != null ?
632.1263 +						elem[ name ] :
632.1264 +						elem.getAttribute( name ),
632.1265 +				value = result + "",
632.1266 +				type = match[2],
632.1267 +				check = match[4];
632.1268 +
632.1269 +			return result == null ?
632.1270 +				type === "!=" :
632.1271 +				type === "=" ?
632.1272 +				value === check :
632.1273 +				type === "*=" ?
632.1274 +				value.indexOf(check) >= 0 :
632.1275 +				type === "~=" ?
632.1276 +				(" " + value + " ").indexOf(check) >= 0 :
632.1277 +				!check ?
632.1278 +				value && result !== false :
632.1279 +				type === "!=" ?
632.1280 +				value != check :
632.1281 +				type === "^=" ?
632.1282 +				value.indexOf(check) === 0 :
632.1283 +				type === "$=" ?
632.1284 +				value.substr(value.length - check.length) === check :
632.1285 +				type === "|=" ?
632.1286 +				value === check || value.substr(0, check.length + 1) === check + "-" :
632.1287 +				false;
632.1288 +		},
632.1289 +		POS: function(elem, match, i, array){
632.1290 +			var name = match[2], filter = Expr.setFilters[ name ];
632.1291 +
632.1292 +			if ( filter ) {
632.1293 +				return filter( elem, i, match, array );
632.1294 +			}
632.1295 +		}
632.1296 +	}
632.1297 +};
632.1298 +
632.1299 +var origPOS = Expr.match.POS;
632.1300 +
632.1301 +for ( var type in Expr.match ) {
632.1302 +	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
632.1303 +}
632.1304 +
632.1305 +var makeArray = function(array, results) {
632.1306 +	array = Array.prototype.slice.call( array );
632.1307 +
632.1308 +	if ( results ) {
632.1309 +		results.push.apply( results, array );
632.1310 +		return results;
632.1311 +	}
632.1312 +	
632.1313 +	return array;
632.1314 +};
632.1315 +
632.1316 +// Perform a simple check to determine if the browser is capable of
632.1317 +// converting a NodeList to an array using builtin methods.
632.1318 +try {
632.1319 +	Array.prototype.slice.call( document.documentElement.childNodes );
632.1320 +
632.1321 +// Provide a fallback method if it does not work
632.1322 +} catch(e){
632.1323 +	makeArray = function(array, results) {
632.1324 +		var ret = results || [];
632.1325 +
632.1326 +		if ( toString.call(array) === "[object Array]" ) {
632.1327 +			Array.prototype.push.apply( ret, array );
632.1328 +		} else {
632.1329 +			if ( typeof array.length === "number" ) {
632.1330 +				for ( var i = 0, l = array.length; i < l; i++ ) {
632.1331 +					ret.push( array[i] );
632.1332 +				}
632.1333 +			} else {
632.1334 +				for ( var i = 0; array[i]; i++ ) {
632.1335 +					ret.push( array[i] );
632.1336 +				}
632.1337 +			}
632.1338 +		}
632.1339 +
632.1340 +		return ret;
632.1341 +	};
632.1342 +}
632.1343 +
632.1344 +var sortOrder;
632.1345 +
632.1346 +if ( document.documentElement.compareDocumentPosition ) {
632.1347 +	sortOrder = function( a, b ) {
632.1348 +		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
632.1349 +		if ( ret === 0 ) {
632.1350 +			hasDuplicate = true;
632.1351 +		}
632.1352 +		return ret;
632.1353 +	};
632.1354 +} else if ( "sourceIndex" in document.documentElement ) {
632.1355 +	sortOrder = function( a, b ) {
632.1356 +		var ret = a.sourceIndex - b.sourceIndex;
632.1357 +		if ( ret === 0 ) {
632.1358 +			hasDuplicate = true;
632.1359 +		}
632.1360 +		return ret;
632.1361 +	};
632.1362 +} else if ( document.createRange ) {
632.1363 +	sortOrder = function( a, b ) {
632.1364 +		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
632.1365 +		aRange.selectNode(a);
632.1366 +		aRange.collapse(true);
632.1367 +		bRange.selectNode(b);
632.1368 +		bRange.collapse(true);
632.1369 +		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
632.1370 +		if ( ret === 0 ) {
632.1371 +			hasDuplicate = true;
632.1372 +		}
632.1373 +		return ret;
632.1374 +	};
632.1375 +}
632.1376 +
632.1377 +// Check to see if the browser returns elements by name when
632.1378 +// querying by getElementById (and provide a workaround)
632.1379 +(function(){
632.1380 +	// We're going to inject a fake input element with a specified name
632.1381 +	var form = document.createElement("div"),
632.1382 +		id = "script" + (new Date).getTime();
632.1383 +	form.innerHTML = "<a name='" + id + "'/>";
632.1384 +
632.1385 +	// Inject it into the root element, check its status, and remove it quickly
632.1386 +	var root = document.documentElement;
632.1387 +	root.insertBefore( form, root.firstChild );
632.1388 +
632.1389 +	// The workaround has to do additional checks after a getElementById
632.1390 +	// Which slows things down for other browsers (hence the branching)
632.1391 +	if ( !!document.getElementById( id ) ) {
632.1392 +		Expr.find.ID = function(match, context, isXML){
632.1393 +			if ( typeof context.getElementById !== "undefined" && !isXML ) {
632.1394 +				var m = context.getElementById(match[1]);
632.1395 +				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
632.1396 +			}
632.1397 +		};
632.1398 +
632.1399 +		Expr.filter.ID = function(elem, match){
632.1400 +			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
632.1401 +			return elem.nodeType === 1 && node && node.nodeValue === match;
632.1402 +		};
632.1403 +	}
632.1404 +
632.1405 +	root.removeChild( form );
632.1406 +	root = form = null; // release memory in IE
632.1407 +})();
632.1408 +
632.1409 +(function(){
632.1410 +	// Check to see if the browser returns only elements
632.1411 +	// when doing getElementsByTagName("*")
632.1412 +
632.1413 +	// Create a fake element
632.1414 +	var div = document.createElement("div");
632.1415 +	div.appendChild( document.createComment("") );
632.1416 +
632.1417 +	// Make sure no comments are found
632.1418 +	if ( div.getElementsByTagName("*").length > 0 ) {
632.1419 +		Expr.find.TAG = function(match, context){
632.1420 +			var results = context.getElementsByTagName(match[1]);
632.1421 +
632.1422 +			// Filter out possible comments
632.1423 +			if ( match[1] === "*" ) {
632.1424 +				var tmp = [];
632.1425 +
632.1426 +				for ( var i = 0; results[i]; i++ ) {
632.1427 +					if ( results[i].nodeType === 1 ) {
632.1428 +						tmp.push( results[i] );
632.1429 +					}
632.1430 +				}
632.1431 +
632.1432 +				results = tmp;
632.1433 +			}
632.1434 +
632.1435 +			return results;
632.1436 +		};
632.1437 +	}
632.1438 +
632.1439 +	// Check to see if an attribute returns normalized href attributes
632.1440 +	div.innerHTML = "<a href='#'></a>";
632.1441 +	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
632.1442 +			div.firstChild.getAttribute("href") !== "#" ) {
632.1443 +		Expr.attrHandle.href = function(elem){
632.1444 +			return elem.getAttribute("href", 2);
632.1445 +		};
632.1446 +	}
632.1447 +
632.1448 +	div = null; // release memory in IE
632.1449 +})();
632.1450 +
632.1451 +if ( document.querySelectorAll ) (function(){
632.1452 +	var oldSizzle = Sizzle, div = document.createElement("div");
632.1453 +	div.innerHTML = "<p class='TEST'></p>";
632.1454 +
632.1455 +	// Safari can't handle uppercase or unicode characters when
632.1456 +	// in quirks mode.
632.1457 +	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
632.1458 +		return;
632.1459 +	}
632.1460 +	
632.1461 +	Sizzle = function(query, context, extra, seed){
632.1462 +		context = context || document;
632.1463 +
632.1464 +		// Only use querySelectorAll on non-XML documents
632.1465 +		// (ID selectors don't work in non-HTML documents)
632.1466 +		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
632.1467 +			try {
632.1468 +				return makeArray( context.querySelectorAll(query), extra );
632.1469 +			} catch(e){}
632.1470 +		}
632.1471 +		
632.1472 +		return oldSizzle(query, context, extra, seed);
632.1473 +	};
632.1474 +
632.1475 +	for ( var prop in oldSizzle ) {
632.1476 +		Sizzle[ prop ] = oldSizzle[ prop ];
632.1477 +	}
632.1478 +
632.1479 +	div = null; // release memory in IE
632.1480 +})();
632.1481 +
632.1482 +if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
632.1483 +	var div = document.createElement("div");
632.1484 +	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
632.1485 +
632.1486 +	// Opera can't find a second classname (in 9.6)
632.1487 +	if ( div.getElementsByClassName("e").length === 0 )
632.1488 +		return;
632.1489 +
632.1490 +	// Safari caches class attributes, doesn't catch changes (in 3.2)
632.1491 +	div.lastChild.className = "e";
632.1492 +
632.1493 +	if ( div.getElementsByClassName("e").length === 1 )
632.1494 +		return;
632.1495 +
632.1496 +	Expr.order.splice(1, 0, "CLASS");
632.1497 +	Expr.find.CLASS = function(match, context, isXML) {
632.1498 +		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
632.1499 +			return context.getElementsByClassName(match[1]);
632.1500 +		}
632.1501 +	};
632.1502 +
632.1503 +	div = null; // release memory in IE
632.1504 +})();
632.1505 +
632.1506 +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
632.1507 +	var sibDir = dir == "previousSibling" && !isXML;
632.1508 +	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
632.1509 +		var elem = checkSet[i];
632.1510 +		if ( elem ) {
632.1511 +			if ( sibDir && elem.nodeType === 1 ){
632.1512 +				elem.sizcache = doneName;
632.1513 +				elem.sizset = i;
632.1514 +			}
632.1515 +			elem = elem[dir];
632.1516 +			var match = false;
632.1517 +
632.1518 +			while ( elem ) {
632.1519 +				if ( elem.sizcache === doneName ) {
632.1520 +					match = checkSet[elem.sizset];
632.1521 +					break;
632.1522 +				}
632.1523 +
632.1524 +				if ( elem.nodeType === 1 && !isXML ){
632.1525 +					elem.sizcache = doneName;
632.1526 +					elem.sizset = i;
632.1527 +				}
632.1528 +
632.1529 +				if ( elem.nodeName === cur ) {
632.1530 +					match = elem;
632.1531 +					break;
632.1532 +				}
632.1533 +
632.1534 +				elem = elem[dir];
632.1535 +			}
632.1536 +
632.1537 +			checkSet[i] = match;
632.1538 +		}
632.1539 +	}
632.1540 +}
632.1541 +
632.1542 +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
632.1543 +	var sibDir = dir == "previousSibling" && !isXML;
632.1544 +	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
632.1545 +		var elem = checkSet[i];
632.1546 +		if ( elem ) {
632.1547 +			if ( sibDir && elem.nodeType === 1 ) {
632.1548 +				elem.sizcache = doneName;
632.1549 +				elem.sizset = i;
632.1550 +			}
632.1551 +			elem = elem[dir];
632.1552 +			var match = false;
632.1553 +
632.1554 +			while ( elem ) {
632.1555 +				if ( elem.sizcache === doneName ) {
632.1556 +					match = checkSet[elem.sizset];
632.1557 +					break;
632.1558 +				}
632.1559 +
632.1560 +				if ( elem.nodeType === 1 ) {
632.1561 +					if ( !isXML ) {
632.1562 +						elem.sizcache = doneName;
632.1563 +						elem.sizset = i;
632.1564 +					}
632.1565 +					if ( typeof cur !== "string" ) {
632.1566 +						if ( elem === cur ) {
632.1567 +							match = true;
632.1568 +							break;
632.1569 +						}
632.1570 +
632.1571 +					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
632.1572 +						match = elem;
632.1573 +						break;
632.1574 +					}
632.1575 +				}
632.1576 +
632.1577 +				elem = elem[dir];
632.1578 +			}
632.1579 +
632.1580 +			checkSet[i] = match;
632.1581 +		}
632.1582 +	}
632.1583 +}
632.1584 +
632.1585 +var contains = document.compareDocumentPosition ?  function(a, b){
632.1586 +	return a.compareDocumentPosition(b) & 16;
632.1587 +} : function(a, b){
632.1588 +	return a !== b && (a.contains ? a.contains(b) : true);
632.1589 +};
632.1590 +
632.1591 +var isXML = function(elem){
632.1592 +	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
632.1593 +		!!elem.ownerDocument && elem.ownerDocument.documentElement.nodeName !== "HTML";
632.1594 +};
632.1595 +
632.1596 +var posProcess = function(selector, context){
632.1597 +	var tmpSet = [], later = "", match,
632.1598 +		root = context.nodeType ? [context] : context;
632.1599 +
632.1600 +	// Position selectors must be done after the filter
632.1601 +	// And so must :not(positional) so we move all PSEUDOs to the end
632.1602 +	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
632.1603 +		later += match[0];
632.1604 +		selector = selector.replace( Expr.match.PSEUDO, "" );
632.1605 +	}
632.1606 +
632.1607 +	selector = Expr.relative[selector] ? selector + "*" : selector;
632.1608 +
632.1609 +	for ( var i = 0, l = root.length; i < l; i++ ) {
632.1610 +		Sizzle( selector, root[i], tmpSet );
632.1611 +	}
632.1612 +
632.1613 +	return Sizzle.filter( later, tmpSet );
632.1614 +};
632.1615 +
632.1616 +// EXPOSE
632.1617 +jQuery.find = Sizzle;
632.1618 +jQuery.expr = Sizzle.selectors;
632.1619 +jQuery.expr[":"] = jQuery.expr.filters;
632.1620 +
632.1621 +Sizzle.selectors.filters.hidden = function(elem){
632.1622 +	var width = elem.offsetWidth, height = elem.offsetHeight;
632.1623 +	return ( width === 0 && height === 0 ) ?
632.1624 +		true :
632.1625 +		( width !== 0 && height !== 0 ) ?
632.1626 +			false :
632.1627 +			!!( jQuery.curCSS(elem, "display") === "none" );
632.1628 +};
632.1629 +
632.1630 +Sizzle.selectors.filters.visible = function(elem){
632.1631 +	var width = elem.offsetWidth, height = elem.offsetHeight;
632.1632 +	return ( width === 0 && height === 0 ) ?
632.1633 +		false :
632.1634 +		( width > 0 && height > 0 ) ?
632.1635 +			true :
632.1636 +			!!( jQuery.curCSS(elem, "display") !== "none" );
632.1637 +};
632.1638 +
632.1639 +Sizzle.selectors.filters.animated = function(elem){
632.1640 +	return jQuery.grep(jQuery.timers, function(fn){
632.1641 +		return elem === fn.elem;
632.1642 +	}).length;
632.1643 +};
632.1644 +
632.1645 +jQuery.filter = jQuery.multiFilter = function( expr, elems, not ) {
632.1646 +	if ( not ) {
632.1647 +		expr = ":not(" + expr + ")";
632.1648 +	}
632.1649 +
632.1650 +	return Sizzle.matches(expr, elems);
632.1651 +};
632.1652 +
632.1653 +jQuery.dir = function( elem, dir ){
632.1654 +	var matched = [], cur = elem[dir];
632.1655 +	while ( cur && cur != document ) {
632.1656 +		if ( cur.nodeType == 1 )
632.1657 +			matched.push( cur );
632.1658 +		cur = cur[dir];
632.1659 +	}
632.1660 +	return matched;
632.1661 +};
632.1662 +
632.1663 +jQuery.nth = function(cur, result, dir, elem){
632.1664 +	result = result || 1;
632.1665 +	var num = 0;
632.1666 +
632.1667 +	for ( ; cur; cur = cur[dir] )
632.1668 +		if ( cur.nodeType == 1 && ++num == result )
632.1669 +			break;
632.1670 +
632.1671 +	return cur;
632.1672 +};
632.1673 +
632.1674 +jQuery.sibling = function(n, elem){
632.1675 +	var r = [];
632.1676 +
632.1677 +	for ( ; n; n = n.nextSibling ) {
632.1678 +		if ( n.nodeType == 1 && n != elem )
632.1679 +			r.push( n );
632.1680 +	}
632.1681 +
632.1682 +	return r;
632.1683 +};
632.1684 +
632.1685 +return;
632.1686 +
632.1687 +window.Sizzle = Sizzle;
632.1688 +
632.1689 +})();
632.1690 +jQuery.fn.extend({
632.1691 +	find: function( selector ) {
632.1692 +		var ret = this.pushStack( "", "find", selector ), length = 0;
632.1693 +
632.1694 +		for ( var i = 0, l = this.length; i < l; i++ ) {
632.1695 +			length = ret.length;
632.1696 +			jQuery.find( selector, this[i], ret );
632.1697 +
632.1698 +			if ( i > 0 ) {
632.1699 +				// Make sure that the results are unique
632.1700 +				for ( var n = length; n < ret.length; n++ ) {
632.1701 +					for ( var r = 0; r < length; r++ ) {
632.1702 +						if ( ret[r] === ret[n] ) {
632.1703 +							ret.splice(n--, 1);
632.1704 +							break;
632.1705 +						}
632.1706 +					}
632.1707 +				}
632.1708 +			}
632.1709 +		}
632.1710 +
632.1711 +		return ret;
632.1712 +	},
632.1713 +
632.1714 +	filter: function( selector ) {
632.1715 +		return this.pushStack(
632.1716 +			jQuery.isFunction( selector ) &&
632.1717 +			jQuery.grep(this, function(elem, i){
632.1718 +				return selector.call( elem, i );
632.1719 +			}) ||
632.1720 +
632.1721 +			jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
632.1722 +				return elem.nodeType === 1;
632.1723 +			}) ), "filter", selector );
632.1724 +	},
632.1725 +
632.1726 +	closest: function( selector ) {
632.1727 +		var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
632.1728 +			closer = 0;
632.1729 +
632.1730 +		return this.map(function(){
632.1731 +			var cur = this;
632.1732 +			while ( cur && cur.ownerDocument ) {
632.1733 +				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
632.1734 +					jQuery.data(cur, "closest", closer);
632.1735 +					return cur;
632.1736 +				}
632.1737 +				cur = cur.parentNode;
632.1738 +				closer++;
632.1739 +			}
632.1740 +		});
632.1741 +	},
632.1742 +
632.1743 +	not: function( selector ) {
632.1744 +		if ( typeof selector === "string" )
632.1745 +			// test special case where just one selector is passed in
632.1746 +			if ( isSimple.test( selector ) )
632.1747 +				return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
632.1748 +			else
632.1749 +				selector = jQuery.multiFilter( selector, this );
632.1750 +
632.1751 +		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
632.1752 +		return this.filter(function() {
632.1753 +			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
632.1754 +		});
632.1755 +	},
632.1756 +
632.1757 +	add: function( selector ) {
632.1758 +		return this.pushStack( jQuery.unique( jQuery.merge(
632.1759 +			this.get(),
632.1760 +			typeof selector === "string" ?
632.1761 +				jQuery( selector ) :
632.1762 +				jQuery.makeArray( selector )
632.1763 +		)));
632.1764 +	},
632.1765 +
632.1766 +	eq: function( i ) {
632.1767 +		return this.slice( i, +i + 1 );
632.1768 +	},
632.1769 +
632.1770 +	slice: function() {
632.1771 +		return this.pushStack( Array.prototype.slice.apply( this, arguments ),
632.1772 +			"slice", Array.prototype.slice.call(arguments).join(",") );
632.1773 +	},
632.1774 +
632.1775 +	map: function( callback ) {
632.1776 +		return this.pushStack( jQuery.map(this, function(elem, i){
632.1777 +			return callback.call( elem, i, elem );
632.1778 +		}));
632.1779 +	},
632.1780 +
632.1781 +	andSelf: function() {
632.1782 +		return this.add( this.prevObject );
632.1783 +	},
632.1784 +
632.1785 +	end: function() {
632.1786 +		return this.prevObject || jQuery(null);
632.1787 +	}
632.1788 +});
632.1789 +
632.1790 +jQuery.each({
632.1791 +	parent: function(elem){return elem.parentNode;},
632.1792 +	parents: function(elem){return jQuery.dir(elem,"parentNode");},
632.1793 +	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
632.1794 +	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
632.1795 +	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
632.1796 +	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
632.1797 +	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
632.1798 +	children: function(elem){return jQuery.sibling(elem.firstChild);},
632.1799 +	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
632.1800 +}, function(name, fn){
632.1801 +	jQuery.fn[ name ] = function( selector ) {
632.1802 +		var ret = jQuery.map( this, fn );
632.1803 +
632.1804 +		if ( selector && typeof selector == "string" )
632.1805 +			ret = jQuery.multiFilter( selector, ret );
632.1806 +
632.1807 +		return this.pushStack( jQuery.unique( ret ), name, selector );
632.1808 +	};
632.1809 +});jQuery.fn.extend({
632.1810 +	attr: function( name, value ) {
632.1811 +		var options = name, isFunction = jQuery.isFunction( value );
632.1812 +
632.1813 +		if ( typeof name === "string" ) {
632.1814 +			// Are we setting the attribute?
632.1815 +			if ( value === undefined ) {
632.1816 +				return this.length ?
632.1817 +					jQuery.attr( this[0], name ) :
632.1818 +					null;
632.1819 +
632.1820 +			// Convert name, value params to options hash format
632.1821 +			} else {
632.1822 +				options = {};
632.1823 +				options[ name ] = value;
632.1824 +			}
632.1825 +		}
632.1826 +
632.1827 +		// For each element...
632.1828 +		for ( var i = 0, l = this.length; i < l; i++ ) {
632.1829 +			var elem = this[i];
632.1830 +
632.1831 +			// Set all the attributes
632.1832 +			for ( var prop in options ) {
632.1833 +				value = options[prop];
632.1834 +
632.1835 +				if ( isFunction ) {
632.1836 +					value = value.call( elem, i );
632.1837 +				}
632.1838 +
632.1839 +				jQuery.attr( elem, prop, value );
632.1840 +			}
632.1841 +		}
632.1842 +
632.1843 +		return this;
632.1844 +	},
632.1845 +
632.1846 +	hasClass: function( selector ) {
632.1847 +		return !!selector && this.is( "." + selector );
632.1848 +	},
632.1849 +
632.1850 +	val: function( value ) {
632.1851 +		if ( value === undefined ) {
632.1852 +			var elem = this[0];
632.1853 +
632.1854 +			if ( elem ) {
632.1855 +				if( jQuery.nodeName( elem, 'option' ) )
632.1856 +					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
632.1857 +
632.1858 +				// We need to handle select boxes special
632.1859 +				if ( jQuery.nodeName( elem, "select" ) ) {
632.1860 +					var index = elem.selectedIndex,
632.1861 +						values = [],
632.1862 +						options = elem.options,
632.1863 +						one = elem.type == "select-one";
632.1864 +
632.1865 +					// Nothing was selected
632.1866 +					if ( index < 0 )
632.1867 +						return null;
632.1868 +
632.1869 +					// Loop through all the selected options
632.1870 +					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
632.1871 +						var option = options[ i ];
632.1872 +
632.1873 +						if ( option.selected ) {
632.1874 +							// Get the specifc value for the option
632.1875 +							value = jQuery(option).val();
632.1876 +
632.1877 +							// We don't need an array for one selects
632.1878 +							if ( one )
632.1879 +								return value;
632.1880 +
632.1881 +							// Multi-Selects return an array
632.1882 +							values.push( value );
632.1883 +						}
632.1884 +					}
632.1885 +
632.1886 +					return values;
632.1887 +				}
632.1888 +
632.1889 +				// Everything else, we just grab the value
632.1890 +				return (elem.value || "").replace(/\r/g, "");
632.1891 +
632.1892 +			}
632.1893 +
632.1894 +			return undefined;
632.1895 +		}
632.1896 +
632.1897 +		if ( typeof value === "number" )
632.1898 +			value += '';
632.1899 +
632.1900 +		return this.each(function(){
632.1901 +			if ( this.nodeType != 1 )
632.1902 +				return;
632.1903 +
632.1904 +			if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
632.1905 +				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
632.1906 +					jQuery.inArray(this.name, value) >= 0);
632.1907 +
632.1908 +			else if ( jQuery.nodeName( this, "select" ) ) {
632.1909 +				var values = jQuery.makeArray(value);
632.1910 +
632.1911 +				jQuery( "option", this ).each(function(){
632.1912 +					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
632.1913 +						jQuery.inArray( this.text, values ) >= 0);
632.1914 +				});
632.1915 +
632.1916 +				if ( !values.length )
632.1917 +					this.selectedIndex = -1;
632.1918 +
632.1919 +			} else
632.1920 +				this.value = value;
632.1921 +		});
632.1922 +	}
632.1923 +});
632.1924 +
632.1925 +jQuery.each({
632.1926 +	removeAttr: function( name ) {
632.1927 +		jQuery.attr( this, name, "" );
632.1928 +		if (this.nodeType == 1)
632.1929 +			this.removeAttribute( name );
632.1930 +	},
632.1931 +
632.1932 +	addClass: function( classNames ) {
632.1933 +		jQuery.className.add( this, classNames );
632.1934 +	},
632.1935 +
632.1936 +	removeClass: function( classNames ) {
632.1937 +		jQuery.className.remove( this, classNames );
632.1938 +	},
632.1939 +
632.1940 +	toggleClass: function( classNames, state ) {
632.1941 +		var type = typeof classNames;
632.1942 +		if ( type === "string" ) {
632.1943 +			// toggle individual class names
632.1944 +			var isBool = typeof state === "boolean", className, i = 0,
632.1945 +				classNames = classNames.split( /\s+/ );
632.1946 +			while ( (className = classNames[ i++ ]) ) {
632.1947 +				// check each className given, space seperated list
632.1948 +				state = isBool ? state : !jQuery.className.has( this, className );
632.1949 +				jQuery.className[ state ? "add" : "remove" ]( this, className );
632.1950 +			}
632.1951 +		} else if ( type === "undefined" || type === "boolean" ) {
632.1952 +			if ( this.className ) {
632.1953 +				// store className if set
632.1954 +				jQuery.data( this, "__className__", this.className );
632.1955 +			}
632.1956 +			// toggle whole className
632.1957 +			this.className = this.className || classNames === false ? "" : jQuery.data( this, "__className__" ) || "";
632.1958 +		}
632.1959 +	}
632.1960 +}, function(name, fn){
632.1961 +	jQuery.fn[ name ] = function(){
632.1962 +		return this.each( fn, arguments );
632.1963 +	};
632.1964 +});
632.1965 +
632.1966 +jQuery.extend({
632.1967 +	className: {
632.1968 +		// internal only, use addClass("class")
632.1969 +		add: function( elem, classNames ) {
632.1970 +			jQuery.each((classNames || "").split(/\s+/), function(i, className){
632.1971 +				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
632.1972 +					elem.className += (elem.className ? " " : "") + className;
632.1973 +			});
632.1974 +		},
632.1975 +
632.1976 +		// internal only, use removeClass("class")
632.1977 +		remove: function( elem, classNames ) {
632.1978 +			if (elem.nodeType == 1)
632.1979 +				elem.className = classNames !== undefined ?
632.1980 +					jQuery.grep(elem.className.split(/\s+/), function(className){
632.1981 +						return !jQuery.className.has( classNames, className );
632.1982 +					}).join(" ") :
632.1983 +					"";
632.1984 +		},
632.1985 +
632.1986 +		// internal only, use hasClass("class")
632.1987 +		has: function( elem, className ) {
632.1988 +			return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
632.1989 +		}
632.1990 +	},
632.1991 +
632.1992 +	attr: function( elem, name, value ) {
632.1993 +		// don't set attributes on text and comment nodes
632.1994 +		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
632.1995 +			return undefined;
632.1996 +
632.1997 +		var notxml = !elem.tagName || !jQuery.isXMLDoc( elem ),
632.1998 +			// Whether we are setting (or getting)
632.1999 +			set = value !== undefined;
632.2000 +
632.2001 +		// Try to normalize/fix the name
632.2002 +		name = notxml && jQuery.props[ name ] || name;
632.2003 +
632.2004 +		// Only do all the following if this is a node (faster for style)
632.2005 +		if ( elem.tagName ) {
632.2006 +
632.2007 +			// These attributes require special treatment
632.2008 +			var special = /href|src|style/.test( name );
632.2009 +
632.2010 +			// Safari mis-reports the default selected property of a hidden option
632.2011 +			// Accessing the parent's selectedIndex property fixes it
632.2012 +			if ( name == "selected" && elem.parentNode )
632.2013 +				elem.parentNode.selectedIndex;
632.2014 +
632.2015 +			// If applicable, access the attribute via the DOM 0 way
632.2016 +			if ( name in elem && notxml && !special ) {
632.2017 +				if ( set ){
632.2018 +					// We can't allow the type property to be changed (since it causes problems in IE)
632.2019 +					if ( name == "type" && elem.nodeName.match(/(button|input)/i) && elem.parentNode )
632.2020 +						throw "type property can't be changed";
632.2021 +
632.2022 +					elem[ name ] = value;
632.2023 +				}
632.2024 +
632.2025 +				// browsers index elements by id/name on forms, give priority to attributes.
632.2026 +				if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
632.2027 +					return elem.getAttributeNode( name ).nodeValue;
632.2028 +
632.2029 +				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
632.2030 +				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
632.2031 +				if ( name == "tabIndex" ) {
632.2032 +					var attributeNode = elem.getAttributeNode( "tabIndex" );
632.2033 +					return attributeNode && attributeNode.specified
632.2034 +						? attributeNode.value
632.2035 +						: elem.nodeName.match(/(button|input|object|select|textarea)/i)
632.2036 +							? 0
632.2037 +							: elem.nodeName.match(/^(a|area)$/i) && elem.href
632.2038 +								? 0
632.2039 +								: undefined;
632.2040 +				}
632.2041 +
632.2042 +				return elem[ name ];
632.2043 +			}
632.2044 +
632.2045 +			if ( !jQuery.support.style && notxml && name == "style" ) {
632.2046 +				if ( set )
632.2047 +					elem.style.cssText = "" + value;
632.2048 +
632.2049 +				return elem.style.cssText;
632.2050 +			}
632.2051 +
632.2052 +			if ( set )
632.2053 +				// convert the value to a string (all browsers do this but IE) see #1070
632.2054 +				elem.setAttribute( name, "" + value );
632.2055 +
632.2056 +			var attr = !jQuery.support.hrefNormalized && notxml && special
632.2057 +					// Some attributes require a special call on IE
632.2058 +					? elem.getAttribute( name, 2 )
632.2059 +					: elem.getAttribute( name );
632.2060 +
632.2061 +			// Non-existent attributes return null, we normalize to undefined
632.2062 +			return attr === null ? undefined : attr;
632.2063 +		}
632.2064 +
632.2065 +		// elem is actually elem.style ... set the style
632.2066 +		// Using attr for specific style information is now deprecated. Use style insead.
632.2067 +		return jQuery.style(elem, name, value);
632.2068 +	}
632.2069 +});jQuery.fn.extend({
632.2070 +	text: function( text ) {
632.2071 +		if ( typeof text !== "object" && text != null )
632.2072 +			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
632.2073 +
632.2074 +		var ret = "";
632.2075 +
632.2076 +		jQuery.each( text || this, function(){
632.2077 +			jQuery.each( this.childNodes, function(){
632.2078 +				if ( this.nodeType != 8 )
632.2079 +					ret += this.nodeType != 1 ?
632.2080 +						this.nodeValue :
632.2081 +						jQuery.fn.text( [ this ] );
632.2082 +			});
632.2083 +		});
632.2084 +
632.2085 +		return ret;
632.2086 +	},
632.2087 +
632.2088 +	wrapAll: function( html ) {
632.2089 +		if ( this[0] ) {
632.2090 +			// The elements to wrap the target around
632.2091 +			var wrap = jQuery( html, this[0].ownerDocument ).clone();
632.2092 +
632.2093 +			if ( this[0].parentNode )
632.2094 +				wrap.insertBefore( this[0] );
632.2095 +
632.2096 +			wrap.map(function(){
632.2097 +				var elem = this;
632.2098 +
632.2099 +				while ( elem.firstChild )
632.2100 +					elem = elem.firstChild;
632.2101 +
632.2102 +				return elem;
632.2103 +			}).append(this);
632.2104 +		}
632.2105 +
632.2106 +		return this;
632.2107 +	},
632.2108 +
632.2109 +	wrapInner: function( html ) {
632.2110 +		return this.each(function(){
632.2111 +			jQuery( this ).contents().wrapAll( html );
632.2112 +		});
632.2113 +	},
632.2114 +
632.2115 +	wrap: function( html ) {
632.2116 +		return this.each(function(){
632.2117 +			jQuery( this ).wrapAll( html );
632.2118 +		});
632.2119 +	},
632.2120 +
632.2121 +	append: function() {
632.2122 +		return this.domManip(arguments, true, function(elem){
632.2123 +			if (this.nodeType == 1)
632.2124 +				this.appendChild( elem );
632.2125 +		});
632.2126 +	},
632.2127 +
632.2128 +	prepend: function() {
632.2129 +		return this.domManip(arguments, true, function(elem){
632.2130 +			if (this.nodeType == 1)
632.2131 +				this.insertBefore( elem, this.firstChild );
632.2132 +		});
632.2133 +	},
632.2134 +
632.2135 +	before: function() {
632.2136 +		return this.domManip(arguments, false, function(elem){
632.2137 +			this.parentNode.insertBefore( elem, this );
632.2138 +		});
632.2139 +	},
632.2140 +
632.2141 +	after: function() {
632.2142 +		return this.domManip(arguments, false, function(elem){
632.2143 +			this.parentNode.insertBefore( elem, this.nextSibling );
632.2144 +		});
632.2145 +	},
632.2146 +
632.2147 +	clone: function( events ) {
632.2148 +		// Do the clone
632.2149 +		var ret = this.map(function(){
632.2150 +			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
632.2151 +				// IE copies events bound via attachEvent when
632.2152 +				// using cloneNode. Calling detachEvent on the
632.2153 +				// clone will also remove the events from the orignal
632.2154 +				// In order to get around this, we use innerHTML.
632.2155 +				// Unfortunately, this means some modifications to
632.2156 +				// attributes in IE that are actually only stored
632.2157 +				// as properties will not be copied (such as the
632.2158 +				// the name attribute on an input).
632.2159 +				var html = this.outerHTML, ownerDocument = this.ownerDocument;
632.2160 +				if ( !html ) {
632.2161 +					var div = ownerDocument.createElement("div");
632.2162 +					div.appendChild( this.cloneNode(true) );
632.2163 +					html = div.innerHTML;
632.2164 +				}
632.2165 +
632.2166 +				return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")], ownerDocument)[0];
632.2167 +			} else
632.2168 +				return this.cloneNode(true);
632.2169 +		});
632.2170 +
632.2171 +		// Copy the events from the original to the clone
632.2172 +		if ( events === true ) {
632.2173 +			var orig = this.find("*").andSelf(), i = 0;
632.2174 +
632.2175 +			ret.find("*").andSelf().each(function(){
632.2176 +				if ( this.nodeName !== orig[i].nodeName )
632.2177 +					return;
632.2178 +
632.2179 +				var events = jQuery.data( orig[i], "events" );
632.2180 +
632.2181 +				for ( var type in events ) {
632.2182 +					for ( var handler in events[ type ] ) {
632.2183 +						jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
632.2184 +					}
632.2185 +				}
632.2186 +
632.2187 +				i++;
632.2188 +			});
632.2189 +		}
632.2190 +
632.2191 +		// Return the cloned set
632.2192 +		return ret;
632.2193 +	},
632.2194 +
632.2195 +	html: function( value ) {
632.2196 +		return value === undefined ?
632.2197 +			(this[0] ?
632.2198 +				this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
632.2199 +				null) :
632.2200 +			this.empty().append( value );
632.2201 +	},
632.2202 +
632.2203 +	replaceWith: function( value ) {
632.2204 +		return this.after( value ).remove();
632.2205 +	},
632.2206 +
632.2207 +	domManip: function( args, table, callback ) {
632.2208 +		if ( this[0] ) {
632.2209 +			var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
632.2210 +				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
632.2211 +				first = fragment.firstChild;
632.2212 +
632.2213 +			if ( first )
632.2214 +				for ( var i = 0, l = this.length; i < l; i++ )
632.2215 +					callback.call( root(this[i], first), this.length > 1 || i > 0 ?
632.2216 +							fragment.cloneNode(true) : fragment );
632.2217 +
632.2218 +			if ( scripts )
632.2219 +				jQuery.each( scripts, evalScript );
632.2220 +		}
632.2221 +
632.2222 +		return this;
632.2223 +
632.2224 +		function root( elem, cur ) {
632.2225 +			return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
632.2226 +				(elem.getElementsByTagName("tbody")[0] ||
632.2227 +				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
632.2228 +				elem;
632.2229 +		}
632.2230 +	}
632.2231 +});
632.2232 +
632.2233 +jQuery.each({
632.2234 +	appendTo: "append",
632.2235 +	prependTo: "prepend",
632.2236 +	insertBefore: "before",
632.2237 +	insertAfter: "after",
632.2238 +	replaceAll: "replaceWith"
632.2239 +}, function(name, original){
632.2240 +	jQuery.fn[ name ] = function( selector ) {
632.2241 +		var ret = [], insert = jQuery( selector );
632.2242 +
632.2243 +		for ( var i = 0, l = insert.length; i < l; i++ ) {
632.2244 +			var elems = (i > 0 ? this.clone(true) : this).get();
632.2245 +			jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
632.2246 +			ret = ret.concat( elems );
632.2247 +		}
632.2248 +
632.2249 +		return this.pushStack( ret, name, selector );
632.2250 +	};
632.2251 +});
632.2252 +
632.2253 +jQuery.each({
632.2254 +	remove: function( selector ) {
632.2255 +		if ( !selector || jQuery.multiFilter( selector, [ this ] ).length ) {
632.2256 +			if ( this.nodeType === 1 ) {
632.2257 +				cleanData( jQuery("*", this).add(this) );
632.2258 +			}
632.2259 +
632.2260 +			if ( this.parentNode ) {
632.2261 +				this.parentNode.removeChild( this );
632.2262 +			}
632.2263 +		}
632.2264 +	},
632.2265 +
632.2266 +	empty: function() {
632.2267 +		// Remove element nodes and prevent memory leaks
632.2268 +		if ( this.nodeType === 1 ) {
632.2269 +			cleanData( jQuery("*", this) );
632.2270 +		}
632.2271 +
632.2272 +		// Remove any remaining nodes
632.2273 +		while ( this.firstChild ) {
632.2274 +			this.removeChild( this.firstChild );
632.2275 +		}
632.2276 +	}
632.2277 +}, function(name, fn){
632.2278 +	jQuery.fn[ name ] = function(){
632.2279 +		return this.each( fn, arguments );
632.2280 +	};
632.2281 +});
632.2282 +
632.2283 +jQuery.extend({
632.2284 +	clean: function( elems, context, fragment ) {
632.2285 +		context = context || document;
632.2286 +
632.2287 +		// !context.createElement fails in IE with an error but returns typeof 'object'
632.2288 +		if ( typeof context.createElement === "undefined" )
632.2289 +			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
632.2290 +
632.2291 +		// If a single string is passed in and it's a single tag
632.2292 +		// just do a createElement and skip the rest
632.2293 +		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
632.2294 +			var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
632.2295 +			if ( match )
632.2296 +				return [ context.createElement( match[1] ) ];
632.2297 +		}
632.2298 +
632.2299 +		var ret = [], scripts = [], div = context.createElement("div");
632.2300 +
632.2301 +		jQuery.each(elems, function(i, elem){
632.2302 +			if ( typeof elem === "number" )
632.2303 +				elem += '';
632.2304 +
632.2305 +			if ( !elem )
632.2306 +				return;
632.2307 +
632.2308 +			// Convert html string into DOM nodes
632.2309 +			if ( typeof elem === "string" ) {
632.2310 +				// Fix "XHTML"-style tags in all browsers
632.2311 +				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
632.2312 +					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
632.2313 +						all :
632.2314 +						front + "></" + tag + ">";
632.2315 +				});
632.2316 +
632.2317 +				// Trim whitespace, otherwise indexOf won't work as expected
632.2318 +				var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
632.2319 +
632.2320 +				var wrap =
632.2321 +					// option or optgroup
632.2322 +					!tags.indexOf("<opt") &&
632.2323 +					[ 1, "<select multiple='multiple'>", "</select>" ] ||
632.2324 +
632.2325 +					!tags.indexOf("<leg") &&
632.2326 +					[ 1, "<fieldset>", "</fieldset>" ] ||
632.2327 +
632.2328 +					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
632.2329 +					[ 1, "<table>", "</table>" ] ||
632.2330 +
632.2331 +					!tags.indexOf("<tr") &&
632.2332 +					[ 2, "<table><tbody>", "</tbody></table>" ] ||
632.2333 +
632.2334 +				 	// <thead> matched above
632.2335 +					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
632.2336 +					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
632.2337 +
632.2338 +					!tags.indexOf("<col") &&
632.2339 +					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
632.2340 +
632.2341 +					// IE can't serialize <link> and <script> tags normally
632.2342 +					!jQuery.support.htmlSerialize &&
632.2343 +					[ 1, "div<div>", "</div>" ] ||
632.2344 +
632.2345 +					[ 0, "", "" ];
632.2346 +
632.2347 +				// Go to html and back, then peel off extra wrappers
632.2348 +				div.innerHTML = wrap[1] + elem + wrap[2];
632.2349 +
632.2350 +				// Move to the right depth
632.2351 +				while ( wrap[0]-- )
632.2352 +					div = div.lastChild;
632.2353 +
632.2354 +				// Remove IE's autoinserted <tbody> from table fragments
632.2355 +				if ( !jQuery.support.tbody ) {
632.2356 +
632.2357 +					// String was a <table>, *may* have spurious <tbody>
632.2358 +					var hasBody = /<tbody/i.test(elem),
632.2359 +						tbody = !tags.indexOf("<table") && !hasBody ?
632.2360 +							div.firstChild && div.firstChild.childNodes :
632.2361 +
632.2362 +						// String was a bare <thead> or <tfoot>
632.2363 +						wrap[1] == "<table>" && !hasBody ?
632.2364 +							div.childNodes :
632.2365 +							[];
632.2366 +
632.2367 +					for ( var j = tbody.length - 1; j >= 0 ; --j )
632.2368 +						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
632.2369 +							tbody[ j ].parentNode.removeChild( tbody[ j ] );
632.2370 +
632.2371 +					}
632.2372 +
632.2373 +				// IE completely kills leading whitespace when innerHTML is used
632.2374 +				if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
632.2375 +					div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
632.2376 +
632.2377 +				elem = jQuery.makeArray( div.childNodes );
632.2378 +			}
632.2379 +
632.2380 +			if ( elem.nodeType )
632.2381 +				ret.push( elem );
632.2382 +			else
632.2383 +				ret = jQuery.merge( ret, elem );
632.2384 +
632.2385 +		});
632.2386 +
632.2387 +		if ( fragment ) {
632.2388 +			for ( var i = 0; ret[i]; i++ ) {
632.2389 +				if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
632.2390 +					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
632.2391 +				} else {
632.2392 +					if ( ret[i].nodeType === 1 )
632.2393 +						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
632.2394 +					fragment.appendChild( ret[i] );
632.2395 +				}
632.2396 +			}
632.2397 +
632.2398 +			return scripts;
632.2399 +		}
632.2400 +
632.2401 +		return ret;
632.2402 +	}
632.2403 +});
632.2404 +
632.2405 +function cleanData( elems ) {
632.2406 +	for ( var i = 0, l = elems.length; i < l; i++ ) {
632.2407 +		var id = elems[i][expando];
632.2408 +		if ( id ) {
632.2409 +			delete jQuery.cache[ id ];
632.2410 +		}
632.2411 +	}
632.2412 +}
632.2413 +/*
632.2414 + * A number of helper functions used for managing events.
632.2415 + * Many of the ideas behind this code originated from
632.2416 + * Dean Edwards' addEvent library.
632.2417 + */
632.2418 +jQuery.event = {
632.2419 +
632.2420 +	// Bind an event to an element
632.2421 +	// Original by Dean Edwards
632.2422 +	add: function( elem, types, handler, data ) {
632.2423 +		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
632.2424 +			return;
632.2425 +		}
632.2426 +
632.2427 +		// For whatever reason, IE has trouble passing the window object
632.2428 +		// around, causing it to be cloned in the process
632.2429 +		if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
632.2430 +			elem = window;
632.2431 +		}
632.2432 +
632.2433 +		// Make sure that the function being executed has a unique ID
632.2434 +		if ( !handler.guid ) {
632.2435 +			handler.guid = this.guid++;
632.2436 +		}
632.2437 +
632.2438 +		// if data is passed, bind to handler
632.2439 +		if ( data !== undefined ) {
632.2440 +			// Create temporary function pointer to original handler
632.2441 +			var fn = handler;
632.2442 +
632.2443 +			// Create unique handler function, wrapped around original handler
632.2444 +			handler = this.proxy( fn );
632.2445 +
632.2446 +			// Store data in unique handler
632.2447 +			handler.data = data;
632.2448 +		}
632.2449 +
632.2450 +		// Init the element's event structure
632.2451 +		var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ),
632.2452 +			handle = jQuery.data( elem, "handle" ) || jQuery.data( elem, "handle", function() {
632.2453 +				// Handle the second event of a trigger and when
632.2454 +				// an event is called after a page has unloaded
632.2455 +				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
632.2456 +					jQuery.event.handle.apply( arguments.callee.elem, arguments ) :
632.2457 +					undefined;
632.2458 +			});
632.2459 +		// Add elem as a property of the handle function
632.2460 +		// This is to prevent a memory leak with non-native
632.2461 +		// event in IE.
632.2462 +		handle.elem = elem;
632.2463 +
632.2464 +		// Handle multiple events separated by a space
632.2465 +		// jQuery(...).bind("mouseover mouseout", fn);
632.2466 +		types = types.split( /\s+/ );
632.2467 +		var type, i=0;
632.2468 +		while ( (type = types[ i++ ]) ) {
632.2469 +			// Namespaced event handlers
632.2470 +			var namespaces = type.split(".");
632.2471 +			type = namespaces.shift();
632.2472 +			handler.type = namespaces.slice().sort().join(".");
632.2473 +
632.2474 +			// Get the current list of functions bound to this event
632.2475 +			var handlers = events[ type ],
632.2476 +				special = this.special[ type ] || {};
632.2477 +
632.2478 +			if ( special.add ) {
632.2479 +				var modifiedHandler = special.add.call( elem, handler, data, namespaces );
632.2480 +				if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) {
632.2481 +					modifiedHandler.guid = modifiedHandler.guid || handler.guid;
632.2482 +					handler = modifiedHandler;
632.2483 +				}
632.2484 +			}
632.2485 +
632.2486 +			// Init the event handler queue
632.2487 +			if ( !handlers ) {
632.2488 +				handlers = events[ type ] = {};
632.2489 +
632.2490 +				// Check for a special event handler
632.2491 +				// Only use addEventListener/attachEvent if the special
632.2492 +				// events handler returns false
632.2493 +				if ( !special.setup || special.setup.call( elem, data, namespaces ) === false ) {
632.2494 +					// Bind the global event handler to the element
632.2495 +					if ( elem.addEventListener ) {
632.2496 +						elem.addEventListener( type, handle, false );
632.2497 +					} else if ( elem.attachEvent ) {
632.2498 +						elem.attachEvent( "on" + type, handle );
632.2499 +					}
632.2500 +				}
632.2501 +			}
632.2502 +
632.2503 +			// Add the function to the element's handler list
632.2504 +			handlers[ handler.guid ] = handler;
632.2505 +
632.2506 +			// Keep track of which events have been used, for global triggering
632.2507 +			this.global[ type ] = true;
632.2508 +		}
632.2509 +
632.2510 +		// Nullify elem to prevent memory leaks in IE
632.2511 +		elem = null;
632.2512 +	},
632.2513 +
632.2514 +	guid: 1,
632.2515 +	global: {},
632.2516 +
632.2517 +	// Detach an event or set of events from an element
632.2518 +	remove: function( elem, types, handler ) {
632.2519 +		// don't do events on text and comment nodes
632.2520 +		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
632.2521 +			return;
632.2522 +		}
632.2523 +
632.2524 +		var events = jQuery.data( elem, "events" ), ret, type;
632.2525 +
632.2526 +		if ( events ) {
632.2527 +			// Unbind all events for the element
632.2528 +			if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) {
632.2529 +				for ( type in events ) {
632.2530 +					this.remove( elem, type + (types || "") );
632.2531 +				}
632.2532 +			} else {
632.2533 +				// types is actually an event object here
632.2534 +				if ( types.type ) {
632.2535 +					handler = types.handler;
632.2536 +					types = types.type;
632.2537 +				}
632.2538 +
632.2539 +				// Handle multiple events seperated by a space
632.2540 +				// jQuery(...).unbind("mouseover mouseout", fn);
632.2541 +				types = types.split(/\s+/);
632.2542 +				var i = 0;
632.2543 +				while ( (type = types[ i++ ]) ) {
632.2544 +					// Namespaced event handlers
632.2545 +					var namespaces = type.split(".");
632.2546 +					type = namespaces.shift();
632.2547 +					var all = !namespaces.length,
632.2548 +						namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)"),
632.2549 +						special = this.special[ type ] || {};
632.2550 +
632.2551 +					if ( events[ type ] ) {
632.2552 +						// remove the given handler for the given type
632.2553 +						if ( handler ) {
632.2554 +							delete events[ type ][ handler.guid ];
632.2555 +
632.2556 +						// remove all handlers for the given type
632.2557 +						} else {
632.2558 +							for ( var handle in events[ type ] ) {
632.2559 +								// Handle the removal of namespaced events
632.2560 +								if ( all || namespace.test( events[ type ][ handle ].type ) ) {
632.2561 +									delete events[ type ][ handle ];
632.2562 +								}
632.2563 +							}
632.2564 +						}
632.2565 +
632.2566 +						if ( special.remove ) {
632.2567 +							special.remove.call( elem, namespaces );
632.2568 +						}
632.2569 +
632.2570 +						// remove generic event handler if no more handlers exist
632.2571 +						for ( ret in events[ type ] ) {
632.2572 +							break;
632.2573 +						}
632.2574 +						if ( !ret ) {
632.2575 +							if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
632.2576 +								if ( elem.removeEventListener ) {
632.2577 +									elem.removeEventListener( type, jQuery.data( elem, "handle" ), false );
632.2578 +								} else if ( elem.detachEvent ) {
632.2579 +									elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) );
632.2580 +								}
632.2581 +							}
632.2582 +							ret = null;
632.2583 +							delete events[ type ];
632.2584 +						}
632.2585 +					}
632.2586 +				}
632.2587 +			}
632.2588 +
632.2589 +			// Remove the expando if it's no longer used
632.2590 +			for ( ret in events ) {
632.2591 +				break;
632.2592 +			}
632.2593 +			if ( !ret ) {
632.2594 +				var handle = jQuery.data( elem, "handle" );
632.2595 +				if ( handle ) {
632.2596 +					handle.elem = null;
632.2597 +				}
632.2598 +				jQuery.removeData( elem, "events" );
632.2599 +				jQuery.removeData( elem, "handle" );
632.2600 +			}
632.2601 +		}
632.2602 +	},
632.2603 +
632.2604 +	// bubbling is internal
632.2605 +	trigger: function( event, data, elem /*, bubbling */ ) {
632.2606 +		// Event object or event type
632.2607 +		var type = event.type || event,
632.2608 +			bubbling = arguments[3];
632.2609 +
632.2610 +		if ( !bubbling ) {
632.2611 +			event = typeof event === "object" ?
632.2612 +				// jQuery.Event object
632.2613 +				event[expando] ? event :
632.2614 +				// Object literal
632.2615 +				jQuery.extend( jQuery.Event(type), event ) :
632.2616 +				// Just the event type (string)
632.2617 +				jQuery.Event(type);
632.2618 +
632.2619 +			if ( type.indexOf("!") >= 0 ) {
632.2620 +				event.type = type = type.slice(0, -1);
632.2621 +				event.exclusive = true;
632.2622 +			}
632.2623 +
632.2624 +			// Handle a global trigger
632.2625 +			if ( !elem ) {
632.2626 +				// Don't bubble custom events when global (to avoid too much overhead)
632.2627 +				event.stopPropagation();
632.2628 +				// Only trigger if we've ever bound an event for it
632.2629 +				if ( this.global[ type ] ) {
632.2630 +					jQuery.each( jQuery.cache, function() {
632.2631 +						if ( this.events && this.events[type] ) {
632.2632 +							jQuery.event.trigger( event, data, this.handle.elem );
632.2633 +						}
632.2634 +					});
632.2635 +				}
632.2636 +			}
632.2637 +
632.2638 +			// Handle triggering a single element
632.2639 +
632.2640 +			// don't do events on text and comment nodes
632.2641 +			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
632.2642 +				return undefined;
632.2643 +			}
632.2644 +
632.2645 +			// Clean up in case it is reused
632.2646 +			event.result = undefined;
632.2647 +			event.target = elem;
632.2648 +
632.2649 +			// Clone the incoming data, if any
632.2650 +			data = jQuery.makeArray( data );
632.2651 +			data.unshift( event );
632.2652 +		}
632.2653 +
632.2654 +		event.currentTarget = elem;
632.2655 +
632.2656 +		// Trigger the event, it is assumed that "handle" is a function
632.2657 +		var handle = jQuery.data( elem, "handle" );
632.2658 +		if ( handle ) {
632.2659 +			handle.apply( elem, data );
632.2660 +		}
632.2661 +
632.2662 +		// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
632.2663 +		if ( (!elem[ type ] || (jQuery.nodeName(elem, 'a') && type === "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false ) {
632.2664 +			event.result = false;
632.2665 +		}
632.2666 +
632.2667 +		// Trigger the native events (except for clicks on links)
632.2668 +		if ( !bubbling && elem[ type ] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type === "click") ) {
632.2669 +			this.triggered = true;
632.2670 +			try {
632.2671 +				elem[ type ]();
632.2672 +			// prevent IE from throwing an error for some hidden elements
632.2673 +			} catch (e) {}
632.2674 +		}
632.2675 +
632.2676 +		this.triggered = false;
632.2677 +
632.2678 +		if ( !event.isPropagationStopped() ) {
632.2679 +			var parent = elem.parentNode || elem.ownerDocument;
632.2680 +			if ( parent ) {
632.2681 +				jQuery.event.trigger( event, data, parent, true );
632.2682 +			}
632.2683 +		}
632.2684 +	},
632.2685 +
632.2686 +	handle: function( event ) {
632.2687 +		// returned undefined or false
632.2688 +		var all, handlers;
632.2689 +
632.2690 +		event = arguments[0] = jQuery.event.fix( event || window.event );
632.2691 +		event.currentTarget = this;
632.2692 +
632.2693 +		// Namespaced event handlers
632.2694 +		var namespaces = event.type.split(".");
632.2695 +		event.type = namespaces.shift();
632.2696 +
632.2697 +		// Cache this now, all = true means, any handler
632.2698 +		all = !namespaces.length && !event.exclusive;
632.2699 +
632.2700 +		var namespace = new RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
632.2701 +
632.2702 +		handlers = ( jQuery.data(this, "events") || {} )[ event.type ];
632.2703 +
632.2704 +		for ( var j in handlers ) {
632.2705 +			var handler = handlers[ j ];
632.2706 +
632.2707 +			// Filter the functions by class
632.2708 +			if ( all || namespace.test(handler.type) ) {
632.2709 +				// Pass in a reference to the handler function itself
632.2710 +				// So that we can later remove it
632.2711 +				event.handler = handler;
632.2712 +				event.data = handler.data;
632.2713 +
632.2714 +				var ret = handler.apply( this, arguments );
632.2715 +
632.2716 +				if ( ret !== undefined ) {
632.2717 +					event.result = ret;
632.2718 +					if ( ret === false ) {
632.2719 +						event.preventDefault();
632.2720 +						event.stopPropagation();
632.2721 +					}
632.2722 +				}
632.2723 +
632.2724 +				if ( event.isImmediatePropagationStopped() ) {
632.2725 +					break;
632.2726 +				}
632.2727 +
632.2728 +			}
632.2729 +		}
632.2730 +	},
632.2731 +
632.2732 +	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
632.2733 +
632.2734 +	fix: function( event ) {
632.2735 +		if ( event[ expando ] ) {
632.2736 +			return event;
632.2737 +		}
632.2738 +
632.2739 +		// store a copy of the original event object
632.2740 +		// and "clone" to set read-only properties
632.2741 +		var originalEvent = event;
632.2742 +		event = jQuery.Event( originalEvent );
632.2743 +
632.2744 +		for ( var i = this.props.length, prop; i; ) {
632.2745 +			prop = this.props[ --i ];
632.2746 +			event[ prop ] = originalEvent[ prop ];
632.2747 +		}
632.2748 +
632.2749 +		// Fix target property, if necessary
632.2750 +		if ( !event.target ) {
632.2751 +			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
632.2752 +		}
632.2753 +
632.2754 +		// check if target is a textnode (safari)
632.2755 +		if ( event.target.nodeType === 3 ) {
632.2756 +			event.target = event.target.parentNode;
632.2757 +		}
632.2758 +
632.2759 +		// Add relatedTarget, if necessary
632.2760 +		if ( !event.relatedTarget && event.fromElement ) {
632.2761 +			event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
632.2762 +		}
632.2763 +
632.2764 +		// Calculate pageX/Y if missing and clientX/Y available
632.2765 +		if ( event.pageX == null && event.clientX != null ) {
632.2766 +			var doc = document.documentElement, body = document.body;
632.2767 +			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
632.2768 +			event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
632.2769 +		}
632.2770 +
632.2771 +		// Add which for key events
632.2772 +		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
632.2773 +			event.which = event.charCode || event.keyCode;
632.2774 +		}
632.2775 +
632.2776 +		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
632.2777 +		if ( !event.metaKey && event.ctrlKey ) {
632.2778 +			event.metaKey = event.ctrlKey;
632.2779 +		}
632.2780 +
632.2781 +		// Add which for click: 1 == left; 2 == middle; 3 == right
632.2782 +		// Note: button is not normalized, so don't use it
632.2783 +		if ( !event.which && event.button ) {
632.2784 +			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
632.2785 +		}
632.2786 +
632.2787 +		return event;
632.2788 +	},
632.2789 +
632.2790 +	proxy: function( fn, proxy, thisObject ) {
632.2791 +		if ( proxy !== undefined && !jQuery.isFunction( proxy ) ) {
632.2792 +			thisObject = proxy;
632.2793 +			proxy = undefined;
632.2794 +		}
632.2795 +		// FIXME: Should proxy be redefined to be applied with thisObject if defined?
632.2796 +		proxy = proxy || function() { return fn.apply( thisObject !== undefined ? thisObject : this, arguments ); };
632.2797 +		// Set the guid of unique handler to the same of original handler, so it can be removed
632.2798 +		proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
632.2799 +		// So proxy can be declared as an argument
632.2800 +		return proxy;
632.2801 +	},
632.2802 +
632.2803 +	special: {
632.2804 +		ready: {
632.2805 +			// Make sure the ready event is setup
632.2806 +			setup: bindReady,
632.2807 +			teardown: function() {}
632.2808 +		},
632.2809 +
632.2810 +		live: {
632.2811 +			add: function( proxy, data, namespaces ) {
632.2812 +				jQuery.extend( proxy, data || {} );
632.2813 +				proxy.guid += data.selector + data.live;
632.2814 +				jQuery.event.add( this, data.live, liveHandler );
632.2815 +			},
632.2816 +
632.2817 +			remove: function( namespaces ) {
632.2818 +				if ( namespaces.length ) {
632.2819 +					var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
632.2820 +
632.2821 +					jQuery.each( (jQuery.data(this, "events").live || {}), function() {
632.2822 +						if ( name.test(this.type) ) {
632.2823 +							remove++;
632.2824 +						}
632.2825 +					});
632.2826 +
632.2827 +					if ( remove < 1 ) {
632.2828 +						jQuery.event.remove( this, namespaces[0], liveHandler );
632.2829 +					}
632.2830 +				}
632.2831 +			}
632.2832 +		}
632.2833 +	}
632.2834 +};
632.2835 +
632.2836 +jQuery.Event = function( src ){
632.2837 +	// Allow instantiation without the 'new' keyword
632.2838 +	if ( !this.preventDefault ) {
632.2839 +		return new jQuery.Event( src );
632.2840 +	}
632.2841 +
632.2842 +	// Event object
632.2843 +	if ( src && src.type ) {
632.2844 +		this.originalEvent = src;
632.2845 +		this.type = src.type;
632.2846 +	// Event type
632.2847 +	} else {
632.2848 +		this.type = src;
632.2849 +	}
632.2850 +
632.2851 +	// timeStamp is buggy for some events on Firefox(#3843)
632.2852 +	// So we won't rely on the native value
632.2853 +	this.timeStamp = now();
632.2854 +
632.2855 +	// Mark it as fixed
632.2856 +	this[ expando ] = true;
632.2857 +};
632.2858 +
632.2859 +function returnFalse() {
632.2860 +	return false;
632.2861 +}
632.2862 +function returnTrue() {
632.2863 +	return true;
632.2864 +}
632.2865 +
632.2866 +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
632.2867 +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
632.2868 +jQuery.Event.prototype = {
632.2869 +	preventDefault: function() {
632.2870 +		this.isDefaultPrevented = returnTrue;
632.2871 +
632.2872 +		var e = this.originalEvent;
632.2873 +		if ( !e ) {
632.2874 +			return;
632.2875 +		}
632.2876 +		// if preventDefault exists run it on the original event
632.2877 +		if ( e.preventDefault ) {
632.2878 +			e.preventDefault();
632.2879 +		}
632.2880 +		// otherwise set the returnValue property of the original event to false (IE)
632.2881 +		e.returnValue = false;
632.2882 +	},
632.2883 +	stopPropagation: function() {
632.2884 +		this.isPropagationStopped = returnTrue;
632.2885 +
632.2886 +		var e = this.originalEvent;
632.2887 +		if ( !e ) {
632.2888 +			return;
632.2889 +		}
632.2890 +		// if stopPropagation exists run it on the original event
632.2891 +		if ( e.stopPropagation ) {
632.2892 +			e.stopPropagation();
632.2893 +		}
632.2894 +		// otherwise set the cancelBubble property of the original event to true (IE)
632.2895 +		e.cancelBubble = true;
632.2896 +	},
632.2897 +	stopImmediatePropagation: function(){
632.2898 +		this.isImmediatePropagationStopped = returnTrue;
632.2899 +		this.stopPropagation();
632.2900 +	},
632.2901 +	isDefaultPrevented: returnFalse,
632.2902 +	isPropagationStopped: returnFalse,
632.2903 +	isImmediatePropagationStopped: returnFalse
632.2904 +};
632.2905 +// Checks if an event happened on an element within another element
632.2906 +// Used in jQuery.event.special.mouseenter and mouseleave handlers
632.2907 +var withinElement = function( event ) {
632.2908 +	// Check if mouse(over|out) are still within the same parent element
632.2909 +	var parent = event.relatedTarget;
632.2910 +	// Traverse up the tree
632.2911 +	while ( parent && parent != this ) {
632.2912 +		// Firefox sometimes assigns relatedTarget a XUL element
632.2913 +		// which we cannot access the parentNode property of
632.2914 +		try { parent = parent.parentNode; }
632.2915 +		// assuming we've left the element since we most likely mousedover a xul element
632.2916 +		catch(e) { break; }
632.2917 +	}
632.2918 +
632.2919 +	if ( parent != this ) {
632.2920 +		// set the correct event type
632.2921 +		event.type = event.data;
632.2922 +		// handle event if we actually just moused on to a non sub-element
632.2923 +		jQuery.event.handle.apply( this, arguments );
632.2924 +	}
632.2925 +};
632.2926 +
632.2927 +jQuery.each({
632.2928 +	mouseover: 'mouseenter',
632.2929 +	mouseout: 'mouseleave'
632.2930 +}, function( orig, fix ) {
632.2931 +	jQuery.event.special[ fix ] = {
632.2932 +		setup: function(){
632.2933 +			jQuery.event.add( this, orig, withinElement, fix );
632.2934 +		},
632.2935 +		teardown: function(){
632.2936 +			jQuery.event.remove( this, orig, withinElement );
632.2937 +		}
632.2938 +	};
632.2939 +});
632.2940 +
632.2941 +jQuery.fn.extend({
632.2942 +	bind: function( type, data, fn, thisObject ) {
632.2943 +		if ( jQuery.isFunction( data ) ) {
632.2944 +			if ( fn !== undefined ) {
632.2945 +				thisObject = fn;
632.2946 +			}
632.2947 +			fn = data;
632.2948 +			data = undefined;
632.2949 +		}
632.2950 +		fn = thisObject === undefined ? fn : jQuery.event.proxy( fn, thisObject );
632.2951 +		return type === "unload" ? this.one(type, data, fn, thisObject) : this.each(function() {
632.2952 +			jQuery.event.add( this, type, fn, data );
632.2953 +		});
632.2954 +	},
632.2955 +
632.2956 +	one: function( type, data, fn, thisObject ) {
632.2957 +		if ( jQuery.isFunction( data ) ) {
632.2958 +			if ( fn !== undefined ) {
632.2959 +				thisObject = fn;
632.2960 +			}
632.2961 +			fn = data;
632.2962 +			data = undefined;
632.2963 +		}
632.2964 +		fn = thisObject === undefined ? fn : jQuery.event.proxy( fn, thisObject );
632.2965 +		var one = jQuery.event.proxy( fn, function( event ) {
632.2966 +			jQuery( this ).unbind( event, one );
632.2967 +			return fn.apply( this, arguments );
632.2968 +		});
632.2969 +		return this.each(function() {
632.2970 +			jQuery.event.add( this, type, one, data );
632.2971 +		});
632.2972 +	},
632.2973 +
632.2974 +	unbind: function( type, fn ) {
632.2975 +		return this.each(function() {
632.2976 +			jQuery.event.remove( this, type, fn );
632.2977 +		});
632.2978 +	},
632.2979 +
632.2980 +	trigger: function( type, data ) {
632.2981 +		return this.each(function() {
632.2982 +			jQuery.event.trigger( type, data, this );
632.2983 +		});
632.2984 +	},
632.2985 +
632.2986 +	triggerHandler: function( type, data ) {
632.2987 +		if ( this[0] ) {
632.2988 +			var event = jQuery.Event( type );
632.2989 +			event.preventDefault();
632.2990 +			event.stopPropagation();
632.2991 +			jQuery.event.trigger( event, data, this[0] );
632.2992 +			return event.result;
632.2993 +		}
632.2994 +	},
632.2995 +
632.2996 +	toggle: function( fn ) {
632.2997 +		// Save reference to arguments for access in closure
632.2998 +		var args = arguments, i = 1;
632.2999 +
632.3000 +		// link all the functions, so any of them can unbind this click handler
632.3001 +		while( i < args.length ) {
632.3002 +			jQuery.event.proxy( fn, args[ i++ ] );
632.3003 +		}
632.3004 +
632.3005 +		return this.click( jQuery.event.proxy( fn, function( event ) {
632.3006 +			// Figure out which function to execute
632.3007 +			this.lastToggle = ( this.lastToggle || 0 ) % i;
632.3008 +
632.3009 +			// Make sure that clicks stop
632.3010 +			event.preventDefault();
632.3011 +
632.3012 +			// and execute the function
632.3013 +			return args[ this.lastToggle++ ].apply( this, arguments ) || false;
632.3014 +		}));
632.3015 +	},
632.3016 +
632.3017 +	hover: function( fnOver, fnOut ) {
632.3018 +		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
632.3019 +	},
632.3020 +
632.3021 +	ready: function( fn ) {
632.3022 +		// Attach the listeners
632.3023 +		bindReady();
632.3024 +
632.3025 +		// If the DOM is already ready
632.3026 +		if ( jQuery.isReady ) {
632.3027 +			// Execute the function immediately
632.3028 +			fn.call( document, jQuery );
632.3029 +
632.3030 +		// Otherwise, remember the function for later
632.3031 +		} else {
632.3032 +			// Add the function to the wait list
632.3033 +			jQuery.readyList.push( fn );
632.3034 +		}
632.3035 +
632.3036 +		return this;
632.3037 +	},
632.3038 +
632.3039 +	live: function( type, data, fn, thisObject ) {
632.3040 +		if ( jQuery.isFunction( data ) ) {
632.3041 +			if ( fn !== undefined ) {
632.3042 +				thisObject = fn;
632.3043 +			}
632.3044 +			fn = data;
632.3045 +			data = undefined;
632.3046 +		}
632.3047 +		jQuery( this.context ).bind( liveConvert( type, this.selector ), {
632.3048 +			data: data, selector: this.selector, live: type
632.3049 +		}, fn, thisObject );
632.3050 +		return this;
632.3051 +	},
632.3052 +
632.3053 +	die: function( type, fn ) {
632.3054 +		jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
632.3055 +		return this;
632.3056 +	}
632.3057 +});
632.3058 +
632.3059 +function liveHandler( event ) {
632.3060 +	var stop = true, elems = [], args = arguments;
632.3061 +
632.3062 +	jQuery.each( jQuery.data( this, "events" ).live || [], function( i, fn ) {
632.3063 +		if ( fn.live === event.type ) {
632.3064 +			var elem = jQuery( event.target ).closest( fn.selector )[0];
632.3065 +			if ( elem ) {
632.3066 +				elems.push({ elem: elem, fn: fn });
632.3067 +			}
632.3068 +		}
632.3069 +	});
632.3070 +
632.3071 +	elems.sort(function( a, b ) {
632.3072 +		return jQuery.data( a.elem, "closest" ) - jQuery.data( b.elem, "closest" );
632.3073 +	});
632.3074 +
632.3075 +	jQuery.each(elems, function() {
632.3076 +		event.currentTarget = this.elem;
632.3077 +		event.data = this.fn.data;
632.3078 +		if ( this.fn.apply( this.elem, args ) === false ) {
632.3079 +			return (stop = false);
632.3080 +		}
632.3081 +	});
632.3082 +
632.3083 +	return stop;
632.3084 +}
632.3085 +
632.3086 +function liveConvert( type, selector ) {
632.3087 +	return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
632.3088 +}
632.3089 +
632.3090 +jQuery.extend({
632.3091 +	isReady: false,
632.3092 +	readyList: [],
632.3093 +	// Handle when the DOM is ready
632.3094 +	ready: function() {
632.3095 +		// Make sure that the DOM is not already loaded
632.3096 +		if ( !jQuery.isReady ) {
632.3097 +			// Remember that the DOM is ready
632.3098 +			jQuery.isReady = true;
632.3099 +
632.3100 +			// If there are functions bound, to execute
632.3101 +			if ( jQuery.readyList ) {
632.3102 +				// Execute all of them
632.3103 +				var fn, i = 0;
632.3104 +				while ( (fn = jQuery.readyList[ i++ ]) ) {
632.3105 +					fn.call( document, jQuery );
632.3106 +				}
632.3107 +
632.3108 +				// Reset the list of functions
632.3109 +				jQuery.readyList = null;
632.3110 +			}
632.3111 +
632.3112 +			// Trigger any bound ready events
632.3113 +			jQuery( document ).triggerHandler( "ready" );
632.3114 +		}
632.3115 +	}
632.3116 +});
632.3117 +
632.3118 +var readyBound = false;
632.3119 +
632.3120 +function bindReady() {
632.3121 +	if ( readyBound ) return;
632.3122 +	readyBound = true;
632.3123 +
632.3124 +	// Mozilla, Opera and webkit nightlies currently support this event
632.3125 +	if ( document.addEventListener ) {
632.3126 +		// Use the handy event callback
632.3127 +		document.addEventListener( "DOMContentLoaded", function() {
632.3128 +			document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
632.3129 +			jQuery.ready();
632.3130 +		}, false );
632.3131 +
632.3132 +	// If IE event model is used
632.3133 +	} else if ( document.attachEvent ) {
632.3134 +		// ensure firing before onload,
632.3135 +		// maybe late but safe also for iframes
632.3136 +		document.attachEvent("onreadystatechange", function() {
632.3137 +			if ( document.readyState === "complete" ) {
632.3138 +				document.detachEvent( "onreadystatechange", arguments.callee );
632.3139 +				jQuery.ready();
632.3140 +			}
632.3141 +		});
632.3142 +
632.3143 +		// If IE and not an iframe
632.3144 +		// continually check to see if the document is ready
632.3145 +		if ( document.documentElement.doScroll && window === window.top ) (function() {
632.3146 +			if ( jQuery.isReady ) {
632.3147 +				return;
632.3148 +			}
632.3149 +
632.3150 +			try {
632.3151 +				// If IE is used, use the trick by Diego Perini
632.3152 +				// http://javascript.nwbox.com/IEContentLoaded/
632.3153 +				document.documentElement.doScroll("left");
632.3154 +			} catch( error ) {
632.3155 +				setTimeout( arguments.callee, 0 );
632.3156 +				return;
632.3157 +			}
632.3158 +
632.3159 +			// and execute any waiting functions
632.3160 +			jQuery.ready();
632.3161 +		})();
632.3162 +	}
632.3163 +
632.3164 +	// A fallback to window.onload, that will always work
632.3165 +	jQuery.event.add( window, "load", jQuery.ready );
632.3166 +}
632.3167 +
632.3168 +jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
632.3169 +	"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
632.3170 +	"change,select,submit,keydown,keypress,keyup,error").split(","), function( i, name ) {
632.3171 +
632.3172 +	// Handle event binding
632.3173 +	jQuery.fn[ name ] = function( fn ) {
632.3174 +		return fn ? this.bind( name, fn ) : this.trigger( name );
632.3175 +	};
632.3176 +});
632.3177 +
632.3178 +// Prevent memory leaks in IE
632.3179 +// And prevent errors on refresh with events like mouseover in other browsers
632.3180 +// Window isn't included so as not to unbind existing unload events
632.3181 +// More info:
632.3182 +//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
632.3183 +//  - https://bugzilla.mozilla.org/show_bug.cgi?id=252542
632.3184 +jQuery( window ).bind( 'unload', function() {
632.3185 +	for ( var id in jQuery.cache ) {
632.3186 +		// Skip the window
632.3187 +		if ( id != 1 && jQuery.cache[ id ].handle ) {
632.3188 +			jQuery.event.remove( jQuery.cache[ id ].handle.elem );
632.3189 +		}
632.3190 +	}
632.3191 +});
632.3192 +(function(){
632.3193 +
632.3194 +	jQuery.support = {};
632.3195 +
632.3196 +	var root = document.documentElement,
632.3197 +		script = document.createElement("script"),
632.3198 +		div = document.createElement("div"),
632.3199 +		id = "script" + (new Date).getTime();
632.3200 +
632.3201 +	div.style.display = "none";
632.3202 +	div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select>';
632.3203 +
632.3204 +	var all = div.getElementsByTagName("*"),
632.3205 +		a = div.getElementsByTagName("a")[0];
632.3206 +
632.3207 +	// Can't get basic test support
632.3208 +	if ( !all || !all.length || !a ) {
632.3209 +		return;
632.3210 +	}
632.3211 +
632.3212 +	jQuery.support = {
632.3213 +		// IE strips leading whitespace when .innerHTML is used
632.3214 +		leadingWhitespace: div.firstChild.nodeType == 3,
632.3215 +
632.3216 +		// Make sure that tbody elements aren't automatically inserted
632.3217 +		// IE will insert them into empty tables
632.3218 +		tbody: !div.getElementsByTagName("tbody").length,
632.3219 +
632.3220 +		// Make sure that link elements get serialized correctly by innerHTML
632.3221 +		// This requires a wrapper element in IE
632.3222 +		htmlSerialize: !!div.getElementsByTagName("link").length,
632.3223 +
632.3224 +		// Get the style information from getAttribute
632.3225 +		// (IE uses .cssText insted)
632.3226 +		style: /red/.test( a.getAttribute("style") ),
632.3227 +
632.3228 +		// Make sure that URLs aren't manipulated
632.3229 +		// (IE normalizes it by default)
632.3230 +		hrefNormalized: a.getAttribute("href") === "/a",
632.3231 +
632.3232 +		// Make sure that element opacity exists
632.3233 +		// (IE uses filter instead)
632.3234 +		opacity: a.style.opacity === "0.5",
632.3235 +
632.3236 +		// Verify style float existence
632.3237 +		// (IE uses styleFloat instead of cssFloat)
632.3238 +		cssFloat: !!a.style.cssFloat,
632.3239 +
632.3240 +		// Will be defined later
632.3241 +		scriptEval: false,
632.3242 +		noCloneEvent: true,
632.3243 +		boxModel: null
632.3244 +	};
632.3245 +
632.3246 +	script.type = "text/javascript";
632.3247 +	try {
632.3248 +		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
632.3249 +	} catch(e){}
632.3250 +
632.3251 +	root.insertBefore( script, root.firstChild );
632.3252 +
632.3253 +	// Make sure that the execution of code works by injecting a script
632.3254 +	// tag with appendChild/createTextNode
632.3255 +	// (IE doesn't support this, fails, and uses .text instead)
632.3256 +	if ( window[ id ] ) {
632.3257 +		jQuery.support.scriptEval = true;
632.3258 +		delete window[ id ];
632.3259 +	}
632.3260 +
632.3261 +	root.removeChild( script );
632.3262 +
632.3263 +	if ( div.attachEvent && div.fireEvent ) {
632.3264 +		div.attachEvent("onclick", function click(){
632.3265 +			// Cloning a node shouldn't copy over any
632.3266 +			// bound event handlers (IE does this)
632.3267 +			jQuery.support.noCloneEvent = false;
632.3268 +			div.detachEvent("onclick", click);
632.3269 +		});
632.3270 +		div.cloneNode(true).fireEvent("onclick");
632.3271 +	}
632.3272 +
632.3273 +	// Figure out if the W3C box model works as expected
632.3274 +	// document.body must exist before we can do this
632.3275 +	jQuery(function(){
632.3276 +		var div = document.createElement("div");
632.3277 +		div.style.width = div.style.paddingLeft = "1px";
632.3278 +
632.3279 +		document.body.appendChild( div );
632.3280 +		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
632.3281 +		document.body.removeChild( div ).style.display = 'none';
632.3282 +		div = null;
632.3283 +	});
632.3284 +
632.3285 +	// release memory in IE
632.3286 +	root = script = div = all = a = null;
632.3287 +})();
632.3288 +
632.3289 +jQuery.props = {
632.3290 +	"for": "htmlFor",
632.3291 +	"class": "className",
632.3292 +	readonly: "readOnly",
632.3293 +	maxlength: "maxLength",
632.3294 +	cellspacing: "cellSpacing",
632.3295 +	rowspan: "rowSpan",
632.3296 +	colspan: "colSpan",
632.3297 +	tabindex: "tabIndex"
632.3298 +};
632.3299 +// exclude the following css properties to add px
632.3300 +var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
632.3301 +	// cache check for defaultView.getComputedStyle
632.3302 +	getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
632.3303 +	// normalize float css property
632.3304 +	styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
632.3305 +
632.3306 +jQuery.fn.css = function( name, value ) {
632.3307 +	var options = name, isFunction = jQuery.isFunction( value );
632.3308 +
632.3309 +	if ( typeof name === "string" ) {
632.3310 +		// Are we setting the style?
632.3311 +		if ( value === undefined ) {
632.3312 +			return this.length ?
632.3313 +				jQuery.css( this[0], name ) :
632.3314 +				null;
632.3315 +
632.3316 +		// Convert name, value params to options hash format
632.3317 +		} else {
632.3318 +			options = {};
632.3319 +			options[ name ] = value;
632.3320 +		}
632.3321 +	}
632.3322 +
632.3323 +	// For each element...
632.3324 +	for ( var i = 0, l = this.length; i < l; i++ ) {
632.3325 +		var elem = this[i];
632.3326 +
632.3327 +		// Set all the styles
632.3328 +		for ( var prop in options ) {
632.3329 +			value = options[prop];
632.3330 +
632.3331 +			if ( isFunction ) {
632.3332 +				value = value.call( elem, i );
632.3333 +			}
632.3334 +
632.3335 +			if ( typeof value === "number" && !exclude.test(prop) ) {
632.3336 +				value = value + "px";
632.3337 +			}
632.3338 +
632.3339 +			jQuery.style( elem, prop, value );
632.3340 +		}
632.3341 +	}
632.3342 +
632.3343 +	return this;
632.3344 +};
632.3345 +
632.3346 +jQuery.extend({
632.3347 +	style: function( elem, name, value ) {
632.3348 +		// don't set styles on text and comment nodes
632.3349 +		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
632.3350 +			return undefined;
632.3351 +
632.3352 +		// ignore negative width and height values #1599
632.3353 +		if ( (name == 'width' || name == 'height') && parseFloat(value) < 0 )
632.3354 +			value = undefined;
632.3355 +
632.3356 +		var style = elem.style || elem, set = value !== undefined;
632.3357 +
632.3358 +		// IE uses filters for opacity
632.3359 +		if ( !jQuery.support.opacity && name == "opacity" ) {
632.3360 +			if ( set ) {
632.3361 +				// IE has trouble with opacity if it does not have layout
632.3362 +				// Force it by setting the zoom level
632.3363 +				style.zoom = 1;
632.3364 +
632.3365 +				// Set the alpha filter to set the opacity
632.3366 +				style.filter = (style.filter || "").replace( /alpha\([^)]*\)/, "" ) +
632.3367 +					(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
632.3368 +			}
632.3369 +
632.3370 +			return style.filter && style.filter.indexOf("opacity=") >= 0 ?
632.3371 +				(parseFloat( style.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
632.3372 +				"";
632.3373 +		}
632.3374 +
632.3375 +		// Make sure we're using the right name for getting the float value
632.3376 +		if ( /float/i.test( name ) )
632.3377 +			name = styleFloat;
632.3378 +
632.3379 +		name = name.replace(/-([a-z])/ig, function(all, letter){
632.3380 +			return letter.toUpperCase();
632.3381 +		});
632.3382 +
632.3383 +		if ( set )
632.3384 +			style[ name ] = value;
632.3385 +
632.3386 +		return style[ name ];
632.3387 +	},
632.3388 +
632.3389 +	css: function( elem, name, force, extra ) {
632.3390 +		if ( name == "width" || name == "height" ) {
632.3391 +			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
632.3392 +
632.3393 +			function getWH() {
632.3394 +				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
632.3395 +
632.3396 +				if ( extra === "border" )
632.3397 +					return;
632.3398 +
632.3399 +				jQuery.each( which, function() {
632.3400 +					if ( !extra )
632.3401 +						val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
632.3402 +					if ( extra === "margin" )
632.3403 +						val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
632.3404 +					else
632.3405 +						val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
632.3406 +				});
632.3407 +			}
632.3408 +
632.3409 +			if ( elem.offsetWidth !== 0 )
632.3410 +				getWH();
632.3411 +			else
632.3412 +				jQuery.swap( elem, props, getWH );
632.3413 +
632.3414 +			return Math.max(0, Math.round(val));
632.3415 +		}
632.3416 +
632.3417 +		return jQuery.curCSS( elem, name, force );
632.3418 +	},
632.3419 +
632.3420 +	curCSS: function( elem, name, force ) {
632.3421 +		var ret, style = elem.style, filter;
632.3422 +
632.3423 +		// IE uses filters for opacity
632.3424 +		if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
632.3425 +			ret = (elem.currentStyle.filter || "").match(/opacity=([^)]*)/) ?
632.3426 +				(parseFloat(RegExp.$1) / 100) + "" :
632.3427 +				"";
632.3428 +
632.3429 +			return ret === "" ?
632.3430 +				"1" :
632.3431 +				ret;
632.3432 +		}
632.3433 +
632.3434 +		// Make sure we're using the right name for getting the float value
632.3435 +		if ( /float/i.test( name ) )
632.3436 +			name = styleFloat;
632.3437 +
632.3438 +		if ( !force && style && style[ name ] ) {
632.3439 +			ret = style[ name ];
632.3440 +
632.3441 +		} else if ( getComputedStyle ) {
632.3442 +
632.3443 +			// Only "float" is needed here
632.3444 +			if ( /float/i.test( name ) )
632.3445 +				name = "float";
632.3446 +
632.3447 +			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
632.3448 +
632.3449 +			var computedStyle = elem.ownerDocument.defaultView.getComputedStyle( elem, null );
632.3450 +
632.3451 +			if ( computedStyle )
632.3452 +				ret = computedStyle.getPropertyValue( name );
632.3453 +
632.3454 +			// We should always get a number back from opacity
632.3455 +			if ( name == "opacity" && ret == "" )
632.3456 +				ret = "1";
632.3457 +
632.3458 +		} else if ( elem.currentStyle ) {
632.3459 +			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
632.3460 +				return letter.toUpperCase();
632.3461 +			});
632.3462 +
632.3463 +			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
632.3464 +
632.3465 +			// From the awesome hack by Dean Edwards
632.3466 +			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
632.3467 +
632.3468 +			// If we're not dealing with a regular pixel number
632.3469 +			// but a number that has a weird ending, we need to convert it to pixels
632.3470 +			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
632.3471 +				// Remember the original values
632.3472 +				var left = style.left, rsLeft = elem.runtimeStyle.left;
632.3473 +
632.3474 +				// Put in the new values to get a computed value out
632.3475 +				elem.runtimeStyle.left = elem.currentStyle.left;
632.3476 +				style.left = ret || 0;
632.3477 +				ret = style.pixelLeft + "px";
632.3478 +
632.3479 +				// Revert the changed values
632.3480 +				style.left = left;
632.3481 +				elem.runtimeStyle.left = rsLeft;
632.3482 +			}
632.3483 +		}
632.3484 +
632.3485 +		return ret;
632.3486 +	},
632.3487 +
632.3488 +	// A method for quickly swapping in/out CSS properties to get correct calculations
632.3489 +	swap: function( elem, options, callback ) {
632.3490 +		var old = {};
632.3491 +		// Remember the old values, and insert the new ones
632.3492 +		for ( var name in options ) {
632.3493 +			old[ name ] = elem.style[ name ];
632.3494 +			elem.style[ name ] = options[ name ];
632.3495 +		}
632.3496 +
632.3497 +		callback.call( elem );
632.3498 +
632.3499 +		// Revert the old values
632.3500 +		for ( var name in options )
632.3501 +			elem.style[ name ] = old[ name ];
632.3502 +	}
632.3503 +});jQuery.fn.extend({
632.3504 +	// Keep a copy of the old load
632.3505 +	_load: jQuery.fn.load,
632.3506 +
632.3507 +	load: function( url, params, callback ) {
632.3508 +		if ( typeof url !== "string" )
632.3509 +			return this._load( url );
632.3510 +
632.3511 +		var off = url.indexOf(" ");
632.3512 +		if ( off >= 0 ) {
632.3513 +			var selector = url.slice(off, url.length);
632.3514 +			url = url.slice(0, off);
632.3515 +		}
632.3516 +
632.3517 +		// Default to a GET request
632.3518 +		var type = "GET";
632.3519 +
632.3520 +		// If the second parameter was provided
632.3521 +		if ( params )
632.3522 +			// If it's a function
632.3523 +			if ( jQuery.isFunction( params ) ) {
632.3524 +				// We assume that it's the callback
632.3525 +				callback = params;
632.3526 +				params = null;
632.3527 +
632.3528 +			// Otherwise, build a param string
632.3529 +			} else if( typeof params === "object" ) {
632.3530 +				params = jQuery.param( params );
632.3531 +				type = "POST";
632.3532 +			}
632.3533 +
632.3534 +		var self = this;
632.3535 +
632.3536 +		// Request the remote document
632.3537 +		jQuery.ajax({
632.3538 +			url: url,
632.3539 +			type: type,
632.3540 +			dataType: "html",
632.3541 +			data: params,
632.3542 +			complete: function(res, status){
632.3543 +				// If successful, inject the HTML into all the matched elements
632.3544 +				if ( status == "success" || status == "notmodified" )
632.3545 +					// See if a selector was specified
632.3546 +					self.html( selector ?
632.3547 +						// Create a dummy div to hold the results
632.3548 +						jQuery("<div/>")
632.3549 +							// inject the contents of the document in, removing the scripts
632.3550 +							// to avoid any 'Permission Denied' errors in IE
632.3551 +							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
632.3552 +
632.3553 +							// Locate the specified elements
632.3554 +							.find(selector) :
632.3555 +
632.3556 +						// If not, just inject the full result
632.3557 +						res.responseText );
632.3558 +
632.3559 +				if( callback )
632.3560 +					self.each( callback, [res.responseText, status, res] );
632.3561 +			}
632.3562 +		});
632.3563 +		return this;
632.3564 +	},
632.3565 +
632.3566 +	serialize: function() {
632.3567 +		return jQuery.param(this.serializeArray());
632.3568 +	},
632.3569 +	serializeArray: function() {
632.3570 +		return this.map(function(){
632.3571 +			return this.elements ? jQuery.makeArray(this.elements) : this;
632.3572 +		})
632.3573 +		.filter(function(){
632.3574 +			return this.name && !this.disabled &&
632.3575 +				(this.checked || /select|textarea/i.test(this.nodeName) ||
632.3576 +					/text|hidden|password|search/i.test(this.type));
632.3577 +		})
632.3578 +		.map(function(i, elem){
632.3579 +			var val = jQuery(this).val();
632.3580 +			return val == null ? null :
632.3581 +				jQuery.isArray(val) ?
632.3582 +					jQuery.map( val, function(val, i){
632.3583 +						return {name: elem.name, value: val};
632.3584 +					}) :
632.3585 +					{name: elem.name, value: val};
632.3586 +		}).get();
632.3587 +	}
632.3588 +});
632.3589 +
632.3590 +// Attach a bunch of functions for handling common AJAX events
632.3591 +jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
632.3592 +	jQuery.fn[o] = function(f){
632.3593 +		return this.bind(o, f);
632.3594 +	};
632.3595 +});
632.3596 +
632.3597 +var jsc = now();
632.3598 +
632.3599 +jQuery.extend({
632.3600 +
632.3601 +	get: function( url, data, callback, type ) {
632.3602 +		// shift arguments if data argument was ommited
632.3603 +		if ( jQuery.isFunction( data ) ) {
632.3604 +			callback = data;
632.3605 +			data = null;
632.3606 +		}
632.3607 +
632.3608 +		return jQuery.ajax({
632.3609 +			type: "GET",
632.3610 +			url: url,
632.3611 +			data: data,
632.3612 +			success: callback,
632.3613 +			dataType: type
632.3614 +		});
632.3615 +	},
632.3616 +
632.3617 +	getScript: function( url, callback ) {
632.3618 +		return jQuery.get(url, null, callback, "script");
632.3619 +	},
632.3620 +
632.3621 +	getJSON: function( url, data, callback ) {
632.3622 +		return jQuery.get(url, data, callback, "json");
632.3623 +	},
632.3624 +
632.3625 +	post: function( url, data, callback, type ) {
632.3626 +		if ( jQuery.isFunction( data ) ) {
632.3627 +			callback = data;
632.3628 +			data = {};
632.3629 +		}
632.3630 +
632.3631 +		return jQuery.ajax({
632.3632 +			type: "POST",
632.3633 +			url: url,
632.3634 +			data: data,
632.3635 +			success: callback,
632.3636 +			dataType: type
632.3637 +		});
632.3638 +	},
632.3639 +
632.3640 +	ajaxSetup: function( settings ) {
632.3641 +		jQuery.extend( jQuery.ajaxSettings, settings );
632.3642 +	},
632.3643 +
632.3644 +	ajaxSettings: {
632.3645 +		url: location.href,
632.3646 +		global: true,
632.3647 +		type: "GET",
632.3648 +		contentType: "application/x-www-form-urlencoded",
632.3649 +		processData: true,
632.3650 +		async: true,
632.3651 +		/*
632.3652 +		timeout: 0,
632.3653 +		data: null,
632.3654 +		username: null,
632.3655 +		password: null,
632.3656 +		*/
632.3657 +		// Create the request object; Microsoft failed to properly
632.3658 +		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
632.3659 +		// This function can be overriden by calling jQuery.ajaxSetup
632.3660 +		xhr:function(){
632.3661 +			return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
632.3662 +		},
632.3663 +		accepts: {
632.3664 +			xml: "application/xml, text/xml",
632.3665 +			html: "text/html",
632.3666 +			script: "text/javascript, application/javascript",
632.3667 +			json: "application/json, text/javascript",
632.3668 +			text: "text/plain",
632.3669 +			_default: "*/*"
632.3670 +		}
632.3671 +	},
632.3672 +
632.3673 +	// Last-Modified header cache for next request
632.3674 +	lastModified: {},
632.3675 +
632.3676 +	ajax: function( s ) {
632.3677 +		// Extend the settings, but re-extend 's' so that it can be
632.3678 +		// checked again later (in the test suite, specifically)
632.3679 +		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
632.3680 +
632.3681 +		var jsonp, jsre = /=\?(&|$)/g, status, data,
632.3682 +			type = s.type.toUpperCase();
632.3683 +
632.3684 +		// convert data if not already a string
632.3685 +		if ( s.data && s.processData && typeof s.data !== "string" )
632.3686 +			s.data = jQuery.param(s.data);
632.3687 +
632.3688 +		// Handle JSONP Parameter Callbacks
632.3689 +		if ( s.dataType == "jsonp" ) {
632.3690 +			if ( type == "GET" ) {
632.3691 +				if ( !s.url.match(jsre) )
632.3692 +					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
632.3693 +			} else if ( !s.data || !s.data.match(jsre) )
632.3694 +				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
632.3695 +			s.dataType = "json";
632.3696 +		}
632.3697 +
632.3698 +		// Build temporary JSONP function
632.3699 +		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
632.3700 +			jsonp = "jsonp" + jsc++;
632.3701 +
632.3702 +			// Replace the =? sequence both in the query string and the data
632.3703 +			if ( s.data )
632.3704 +				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
632.3705 +			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
632.3706 +
632.3707 +			// We need to make sure
632.3708 +			// that a JSONP style response is executed properly
632.3709 +			s.dataType = "script";
632.3710 +
632.3711 +			// Handle JSONP-style loading
632.3712 +			window[ jsonp ] = function(tmp){
632.3713 +				data = tmp;
632.3714 +				success();
632.3715 +				complete();
632.3716 +				// Garbage collect
632.3717 +				window[ jsonp ] = undefined;
632.3718 +				try{ delete window[ jsonp ]; } catch(e){}
632.3719 +				if ( head )
632.3720 +					head.removeChild( script );
632.3721 +			};
632.3722 +		}
632.3723 +
632.3724 +		if ( s.dataType == "script" && s.cache == null )
632.3725 +			s.cache = false;
632.3726 +
632.3727 +		if ( s.cache === false && type == "GET" ) {
632.3728 +			var ts = now();
632.3729 +			// try replacing _= if it is there
632.3730 +			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
632.3731 +			// if nothing was replaced, add timestamp to the end
632.3732 +			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
632.3733 +		}
632.3734 +
632.3735 +		// If data is available, append data to url for get requests
632.3736 +		if ( s.data && type == "GET" ) {
632.3737 +			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
632.3738 +		}
632.3739 +
632.3740 +		// Watch for a new set of requests
632.3741 +		if ( s.global && ! jQuery.active++ )
632.3742 +			jQuery.event.trigger( "ajaxStart" );
632.3743 +
632.3744 +		// Matches an absolute URL, and saves the domain
632.3745 +		var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
632.3746 +
632.3747 +		// If we're requesting a remote document
632.3748 +		// and trying to load JSON or Script with a GET
632.3749 +		if ( s.dataType == "script" && type == "GET" && parts
632.3750 +			&& ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
632.3751 +
632.3752 +			var head = document.getElementsByTagName("head")[0];
632.3753 +			var script = document.createElement("script");
632.3754 +			script.src = s.url;
632.3755 +			if (s.scriptCharset)
632.3756 +				script.charset = s.scriptCharset;
632.3757 +
632.3758 +			// Handle Script loading
632.3759 +			if ( !jsonp ) {
632.3760 +				var done = false;
632.3761 +
632.3762 +				// Attach handlers for all browsers
632.3763 +				script.onload = script.onreadystatechange = function(){
632.3764 +					if ( !done && (!this.readyState ||
632.3765 +							this.readyState == "loaded" || this.readyState == "complete") ) {
632.3766 +						done = true;
632.3767 +						success();
632.3768 +						complete();
632.3769 +
632.3770 +						// Handle memory leak in IE
632.3771 +						script.onload = script.onreadystatechange = null;
632.3772 +						head.removeChild( script );
632.3773 +					}
632.3774 +				};
632.3775 +			}
632.3776 +
632.3777 +			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
632.3778 +			// This arises when a base node is used (#2709 and #4378).
632.3779 +			head.insertBefore( script, head.firstChild );
632.3780 +
632.3781 +			// We handle everything using the script element injection
632.3782 +			return undefined;
632.3783 +		}
632.3784 +
632.3785 +		var requestDone = false;
632.3786 +
632.3787 +		// Create the request object
632.3788 +		var xhr = s.xhr();
632.3789 +
632.3790 +		// Open the socket
632.3791 +		// Passing null username, generates a login popup on Opera (#2865)
632.3792 +		if( s.username )
632.3793 +			xhr.open(type, s.url, s.async, s.username, s.password);
632.3794 +		else
632.3795 +			xhr.open(type, s.url, s.async);
632.3796 +
632.3797 +		// Need an extra try/catch for cross domain requests in Firefox 3
632.3798 +		try {
632.3799 +			// Set the correct header, if data is being sent
632.3800 +			if ( s.data )
632.3801 +				xhr.setRequestHeader("Content-Type", s.contentType);
632.3802 +
632.3803 +			// Set the If-Modified-Since header, if ifModified mode.
632.3804 +			if ( s.ifModified )
632.3805 +				xhr.setRequestHeader("If-Modified-Since",
632.3806 +					jQuery.lastModified[s.url] || "Thu, 01 Jan 2022 00:00:00 GMT" );
632.3807 +
632.3808 +			// Set header so the called script knows that it's an XMLHttpRequest
632.3809 +			xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
632.3810 +
632.3811 +			// Set the Accepts header for the server, depending on the dataType
632.3812 +			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
632.3813 +				s.accepts[ s.dataType ] + ", */*" :
632.3814 +				s.accepts._default );
632.3815 +		} catch(e){}
632.3816 +
632.3817 +		// Allow custom headers/mimetypes and early abort
632.3818 +		if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
632.3819 +			// Handle the global AJAX counter
632.3820 +			if ( s.global && ! --jQuery.active )
632.3821 +				jQuery.event.trigger( "ajaxStop" );
632.3822 +			// close opended socket
632.3823 +			xhr.abort();
632.3824 +			return false;
632.3825 +		}
632.3826 +
632.3827 +		if ( s.global )
632.3828 +			jQuery.event.trigger("ajaxSend", [xhr, s]);
632.3829 +
632.3830 +		// Wait for a response to come back
632.3831 +		var onreadystatechange = function(isTimeout){
632.3832 +			// The request was aborted, clear the interval and decrement jQuery.active
632.3833 +			if (xhr.readyState == 0) {
632.3834 +				if (ival) {
632.3835 +					// clear poll interval
632.3836 +					clearInterval(ival);
632.3837 +					ival = null;
632.3838 +					// Handle the global AJAX counter
632.3839 +					if ( s.global && ! --jQuery.active )
632.3840 +						jQuery.event.trigger( "ajaxStop" );
632.3841 +				}
632.3842 +			// The transfer is complete and the data is available, or the request timed out
632.3843 +			} else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
632.3844 +				requestDone = true;
632.3845 +
632.3846 +				// clear poll interval
632.3847 +				if (ival) {
632.3848 +					clearInterval(ival);
632.3849 +					ival = null;
632.3850 +				}
632.3851 +
632.3852 +				status = isTimeout == "timeout" ? "timeout" :
632.3853 +					!jQuery.httpSuccess( xhr ) ? "error" :
632.3854 +					s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
632.3855 +					"success";
632.3856 +
632.3857 +				if ( status == "success" ) {
632.3858 +					// Watch for, and catch, XML document parse errors
632.3859 +					try {
632.3860 +						// process the data (runs the xml through httpData regardless of callback)
632.3861 +						data = jQuery.httpData( xhr, s.dataType, s );
632.3862 +					} catch(e) {
632.3863 +						status = "parsererror";
632.3864 +					}
632.3865 +				}
632.3866 +
632.3867 +				// Make sure that the request was successful or notmodified
632.3868 +				if ( status == "success" ) {
632.3869 +					// Cache Last-Modified header, if ifModified mode.
632.3870 +					var modRes;
632.3871 +					try {
632.3872 +						modRes = xhr.getResponseHeader("Last-Modified");
632.3873 +					} catch(e) {} // swallow exception thrown by FF if header is not available
632.3874 +
632.3875 +					if ( s.ifModified && modRes )
632.3876 +						jQuery.lastModified[s.url] = modRes;
632.3877 +
632.3878 +					// JSONP handles its own success callback
632.3879 +					if ( !jsonp )
632.3880 +						success();
632.3881 +				} else
632.3882 +					jQuery.handleError(s, xhr, status);
632.3883 +
632.3884 +				// Fire the complete handlers
632.3885 +				complete();
632.3886 +
632.3887 +				if ( isTimeout )
632.3888 +					xhr.abort();
632.3889 +
632.3890 +				// Stop memory leaks
632.3891 +				if ( s.async )
632.3892 +					xhr = null;
632.3893 +			}
632.3894 +		};
632.3895 +
632.3896 +		if ( s.async ) {
632.3897 +			// don't attach the handler to the request, just poll it instead
632.3898 +			var ival = setInterval(onreadystatechange, 13);
632.3899 +
632.3900 +			// Timeout checker
632.3901 +			if ( s.timeout > 0 )
632.3902 +				setTimeout(function(){
632.3903 +					// Check to see if the request is still happening
632.3904 +					if ( xhr && !requestDone )
632.3905 +						onreadystatechange( "timeout" );
632.3906 +				}, s.timeout);
632.3907 +		}
632.3908 +
632.3909 +		// Send the data
632.3910 +		try {
632.3911 +			xhr.send( type === "POST" ? s.data : null );
632.3912 +		} catch(e) {
632.3913 +			jQuery.handleError(s, xhr, null, e);
632.3914 +		}
632.3915 +
632.3916 +		// firefox 1.5 doesn't fire statechange for sync requests
632.3917 +		if ( !s.async )
632.3918 +			onreadystatechange();
632.3919 +
632.3920 +		function success(){
632.3921 +			// If a local callback was specified, fire it and pass it the data
632.3922 +			if ( s.success )
632.3923 +				s.success( data, status );
632.3924 +
632.3925 +			// Fire the global callback
632.3926 +			if ( s.global )
632.3927 +				jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
632.3928 +		}
632.3929 +
632.3930 +		function complete(){
632.3931 +			// Process result
632.3932 +			if ( s.complete )
632.3933 +				s.complete(xhr, status);
632.3934 +
632.3935 +			// The request was completed
632.3936 +			if ( s.global )
632.3937 +				jQuery.event.trigger( "ajaxComplete", [xhr, s] );
632.3938 +
632.3939 +			// Handle the global AJAX counter
632.3940 +			if ( s.global && ! --jQuery.active )
632.3941 +				jQuery.event.trigger( "ajaxStop" );
632.3942 +		}
632.3943 +
632.3944 +		// return XMLHttpRequest to allow aborting the request etc.
632.3945 +		return xhr;
632.3946 +	},
632.3947 +
632.3948 +	handleError: function( s, xhr, status, e ) {
632.3949 +		// If a local callback was specified, fire it
632.3950 +		if ( s.error ) s.error( xhr, status, e );
632.3951 +
632.3952 +		// Fire the global callback
632.3953 +		if ( s.global )
632.3954 +			jQuery.event.trigger( "ajaxError", [xhr, s, e] );
632.3955 +	},
632.3956 +
632.3957 +	// Counter for holding the number of active queries
632.3958 +	active: 0,
632.3959 +
632.3960 +	// Determines if an XMLHttpRequest was successful or not
632.3961 +	httpSuccess: function( xhr ) {
632.3962 +		try {
632.3963 +			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
632.3964 +			return !xhr.status && location.protocol == "file:" ||
632.3965 +				( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
632.3966 +		} catch(e){}
632.3967 +		return false;
632.3968 +	},
632.3969 +
632.3970 +	// Determines if an XMLHttpRequest returns NotModified
632.3971 +	httpNotModified: function( xhr, url ) {
632.3972 +		try {
632.3973 +			var xhrRes = xhr.getResponseHeader("Last-Modified");
632.3974 +
632.3975 +			// Firefox always returns 200. check Last-Modified date
632.3976 +			return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
632.3977 +		} catch(e){}
632.3978 +		return false;
632.3979 +	},
632.3980 +
632.3981 +	httpData: function( xhr, type, s ) {
632.3982 +		var ct = xhr.getResponseHeader("content-type"),
632.3983 +			xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
632.3984 +			data = xml ? xhr.responseXML : xhr.responseText;
632.3985 +
632.3986 +		if ( xml && data.documentElement.tagName == "parsererror" ) {
632.3987 +			throw "parsererror";
632.3988 +		}
632.3989 +
632.3990 +		// Allow a pre-filtering function to sanitize the response
632.3991 +		// s != null is checked to keep backwards compatibility
632.3992 +		if ( s && s.dataFilter ) {
632.3993 +			data = s.dataFilter( data, type );
632.3994 +		}
632.3995 +
632.3996 +		// The filter can actually parse the response
632.3997 +		if ( typeof data === "string" ) {
632.3998 +
632.3999 +			// If the type is "script", eval it in global context
632.4000 +			if ( type === "script" ) {
632.4001 +				jQuery.globalEval( data );
632.4002 +			}
632.4003 +
632.4004 +			// Get the JavaScript object, if JSON is used.
632.4005 +			if ( type == "json" ) {
632.4006 +				if ( typeof JSON === "object" && JSON.parse ) {
632.4007 +					data = JSON.parse( data );
632.4008 +				} else {
632.4009 +					data = (new Function("return " + data))();
632.4010 +				}
632.4011 +			}
632.4012 +		}
632.4013 +
632.4014 +		return data;
632.4015 +	},
632.4016 +
632.4017 +	// Serialize an array of form elements or a set of
632.4018 +	// key/values into a query string
632.4019 +	param: function( a ) {
632.4020 +		var s = [ ];
632.4021 +
632.4022 +		function add( key, value ){
632.4023 +			s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
632.4024 +		};
632.4025 +
632.4026 +		// If an array was passed in, assume that it is an array
632.4027 +		// of form elements
632.4028 +		if ( jQuery.isArray(a) || a.jquery )
632.4029 +			// Serialize the form elements
632.4030 +			jQuery.each( a, function(){
632.4031 +				add( this.name, this.value );
632.4032 +			});
632.4033 +
632.4034 +		// Otherwise, assume that it's an object of key/value pairs
632.4035 +		else
632.4036 +			// Serialize the key/values
632.4037 +			for ( var j in a )
632.4038 +				// If the value is an array then the key names need to be repeated
632.4039 +				if ( jQuery.isArray(a[j]) )
632.4040 +					jQuery.each( a[j], function(){
632.4041 +						add( j, this );
632.4042 +					});
632.4043 +				else
632.4044 +					add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
632.4045 +
632.4046 +		// Return the resulting serialization
632.4047 +		return s.join("&").replace(/%20/g, "+");
632.4048 +	}
632.4049 +
632.4050 +});
632.4051 +var elemdisplay = {},
632.4052 +	timerId,
632.4053 +	fxAttrs = [
632.4054 +		// height animations
632.4055 +		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
632.4056 +		// width animations
632.4057 +		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
632.4058 +		// opacity animations
632.4059 +		[ "opacity" ]
632.4060 +	];
632.4061 +
632.4062 +function genFx( type, num ){
632.4063 +	var obj = {};
632.4064 +	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
632.4065 +		obj[ this ] = type;
632.4066 +	});
632.4067 +	return obj;
632.4068 +}
632.4069 +
632.4070 +jQuery.fn.extend({
632.4071 +	show: function(speed,callback){
632.4072 +		if ( speed ) {
632.4073 +			return this.animate( genFx("show", 3), speed, callback);
632.4074 +		} else {
632.4075 +			for ( var i = 0, l = this.length; i < l; i++ ){
632.4076 +				var old = jQuery.data(this[i], "olddisplay");
632.4077 +
632.4078 +				this[i].style.display = old || "";
632.4079 +
632.4080 +				if ( jQuery.css(this[i], "display") === "none" ) {
632.4081 +					var tagName = this[i].tagName, display;
632.4082 +
632.4083 +					if ( elemdisplay[ tagName ] ) {
632.4084 +						display = elemdisplay[ tagName ];
632.4085 +					} else {
632.4086 +						var elem = jQuery("<" + tagName + " />").appendTo("body");
632.4087 +
632.4088 +						display = elem.css("display");
632.4089 +						if ( display === "none" )
632.4090 +							display = "block";
632.4091 +
632.4092 +						elem.remove();
632.4093 +
632.4094 +						elemdisplay[ tagName ] = display;
632.4095 +					}
632.4096 +
632.4097 +					jQuery.data(this[i], "olddisplay", display);
632.4098 +				}
632.4099 +			}
632.4100 +
632.4101 +			// Set the display of the elements in a second loop
632.4102 +			// to avoid the constant reflow
632.4103 +			for ( var i = 0, l = this.length; i < l; i++ ){
632.4104 +				this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
632.4105 +			}
632.4106 +
632.4107 +			return this;
632.4108 +		}
632.4109 +	},
632.4110 +
632.4111 +	hide: function(speed,callback){
632.4112 +		if ( speed ) {
632.4113 +			return this.animate( genFx("hide", 3), speed, callback);
632.4114 +		} else {
632.4115 +			for ( var i = 0, l = this.length; i < l; i++ ){
632.4116 +				var old = jQuery.data(this[i], "olddisplay");
632.4117 +				if ( !old && old !== "none" )
632.4118 +					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
632.4119 +			}
632.4120 +
632.4121 +			// Set the display of the elements in a second loop
632.4122 +			// to avoid the constant reflow
632.4123 +			for ( var i = 0, l = this.length; i < l; i++ ){
632.4124 +				this[i].style.display = "none";
632.4125 +			}
632.4126 +
632.4127 +			return this;
632.4128 +		}
632.4129 +	},
632.4130 +
632.4131 +	// Save the old toggle function
632.4132 +	_toggle: jQuery.fn.toggle,
632.4133 +
632.4134 +	toggle: function( fn, fn2 ){
632.4135 +		var bool = typeof fn === "boolean";
632.4136 +
632.4137 +		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
632.4138 +			this._toggle.apply( this, arguments ) :
632.4139 +			fn == null || bool ?
632.4140 +				this.each(function(){
632.4141 +					var state = bool ? fn : jQuery(this).is(":hidden");
632.4142 +					jQuery(this)[ state ? "show" : "hide" ]();
632.4143 +				}) :
632.4144 +				this.animate(genFx("toggle", 3), fn, fn2);
632.4145 +	},
632.4146 +
632.4147 +	fadeTo: function(speed,to,callback){
632.4148 +		return this.filter(":hidden").css('opacity', 0).show().end()
632.4149 +					.animate({opacity: to}, speed, callback);
632.4150 +	},
632.4151 +
632.4152 +	animate: function( prop, speed, easing, callback ) {
632.4153 +		var optall = jQuery.speed(speed, easing, callback);
632.4154 +
632.4155 +		return this[ optall.queue === false ? "each" : "queue" ](function(){
632.4156 +
632.4157 +			var opt = jQuery.extend({}, optall), p,
632.4158 +				hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
632.4159 +				self = this;
632.4160 +
632.4161 +			for ( p in prop ) {
632.4162 +				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
632.4163 +					return opt.complete.call(this);
632.4164 +
632.4165 +				if ( ( p == "height" || p == "width" ) && this.style ) {
632.4166 +					// Store display property
632.4167 +					opt.display = jQuery.css(this, "display");
632.4168 +
632.4169 +					// Make sure that nothing sneaks out
632.4170 +					opt.overflow = this.style.overflow;
632.4171 +				}
632.4172 +			}
632.4173 +
632.4174 +			if ( opt.overflow != null )
632.4175 +				this.style.overflow = "hidden";
632.4176 +
632.4177 +			opt.curAnim = jQuery.extend({}, prop);
632.4178 +
632.4179 +			jQuery.each( prop, function(name, val){
632.4180 +				var e = new jQuery.fx( self, opt, name );
632.4181 +
632.4182 +				if ( /toggle|show|hide/.test(val) )
632.4183 +					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
632.4184 +				else {
632.4185 +					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
632.4186 +						start = e.cur(true) || 0;
632.4187 +
632.4188 +					if ( parts ) {
632.4189 +						var end = parseFloat(parts[2]),
632.4190 +							unit = parts[3] || "px";
632.4191 +
632.4192 +						// We need to compute starting value
632.4193 +						if ( unit != "px" ) {
632.4194 +							self.style[ name ] = (end || 1) + unit;
632.4195 +							start = ((end || 1) / e.cur(true)) * start;
632.4196 +							self.style[ name ] = start + unit;
632.4197 +						}
632.4198 +
632.4199 +						// If a +=/-= token was provided, we're doing a relative animation
632.4200 +						if ( parts[1] )
632.4201 +							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
632.4202 +
632.4203 +						e.custom( start, end, unit );
632.4204 +					} else
632.4205 +						e.custom( start, val, "" );
632.4206 +				}
632.4207 +			});
632.4208 +
632.4209 +			// For JS strict compliance
632.4210 +			return true;
632.4211 +		});
632.4212 +	},
632.4213 +
632.4214 +	stop: function(clearQueue, gotoEnd){
632.4215 +		var timers = jQuery.timers;
632.4216 +
632.4217 +		if (clearQueue)
632.4218 +			this.queue([]);
632.4219 +
632.4220 +		this.each(function(){
632.4221 +			// go in reverse order so anything added to the queue during the loop is ignored
632.4222 +			for ( var i = timers.length - 1; i >= 0; i-- )
632.4223 +				if ( timers[i].elem == this ) {
632.4224 +					if (gotoEnd)
632.4225 +						// force the next step to be the last
632.4226 +						timers[i](true);
632.4227 +					timers.splice(i, 1);
632.4228 +				}
632.4229 +		});
632.4230 +
632.4231 +		// start the next in the queue if the last step wasn't forced
632.4232 +		if (!gotoEnd)
632.4233 +			this.dequeue();
632.4234 +
632.4235 +		return this;
632.4236 +	}
632.4237 +
632.4238 +});
632.4239 +
632.4240 +// Generate shortcuts for custom animations
632.4241 +jQuery.each({
632.4242 +	slideDown: genFx("show", 1),
632.4243 +	slideUp: genFx("hide", 1),
632.4244 +	slideToggle: genFx("toggle", 1),
632.4245 +	fadeIn: { opacity: "show" },
632.4246 +	fadeOut: { opacity: "hide" }
632.4247 +}, function( name, props ){
632.4248 +	jQuery.fn[ name ] = function( speed, callback ){
632.4249 +		return this.animate( props, speed, callback );
632.4250 +	};
632.4251 +});
632.4252 +
632.4253 +jQuery.extend({
632.4254 +
632.4255 +	speed: function(speed, easing, fn) {
632.4256 +		var opt = typeof speed === "object" ? speed : {
632.4257 +			complete: fn || !fn && easing ||
632.4258 +				jQuery.isFunction( speed ) && speed,
632.4259 +			duration: speed,
632.4260 +			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
632.4261 +		};
632.4262 +
632.4263 +		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
632.4264 +			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
632.4265 +
632.4266 +		// Queueing
632.4267 +		opt.old = opt.complete;
632.4268 +		opt.complete = function(){
632.4269 +			if ( opt.queue !== false )
632.4270 +				jQuery(this).dequeue();
632.4271 +			if ( jQuery.isFunction( opt.old ) )
632.4272 +				opt.old.call( this );
632.4273 +		};
632.4274 +
632.4275 +		return opt;
632.4276 +	},
632.4277 +
632.4278 +	easing: {
632.4279 +		linear: function( p, n, firstNum, diff ) {
632.4280 +			return firstNum + diff * p;
632.4281 +		},
632.4282 +		swing: function( p, n, firstNum, diff ) {
632.4283 +			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
632.4284 +		}
632.4285 +	},
632.4286 +
632.4287 +	timers: [],
632.4288 +
632.4289 +	fx: function( elem, options, prop ){
632.4290 +		this.options = options;
632.4291 +		this.elem = elem;
632.4292 +		this.prop = prop;
632.4293 +
632.4294 +		if ( !options.orig )
632.4295 +			options.orig = {};
632.4296 +	}
632.4297 +
632.4298 +});
632.4299 +
632.4300 +jQuery.fx.prototype = {
632.4301 +
632.4302 +	// Simple function for setting a style value
632.4303 +	update: function(){
632.4304 +		if ( this.options.step )
632.4305 +			this.options.step.call( this.elem, this.now, this );
632.4306 +
632.4307 +		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
632.4308 +
632.4309 +		// Set display property to block for height/width animations
632.4310 +		if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
632.4311 +			this.elem.style.display = "block";
632.4312 +	},
632.4313 +
632.4314 +	// Get the current size
632.4315 +	cur: function(force){
632.4316 +		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
632.4317 +			return this.elem[ this.prop ];
632.4318 +
632.4319 +		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
632.4320 +		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
632.4321 +	},
632.4322 +
632.4323 +	// Start an animation from one number to another
632.4324 +	custom: function(from, to, unit){
632.4325 +		this.startTime = now();
632.4326 +		this.start = from;
632.4327 +		this.end = to;
632.4328 +		this.unit = unit || this.unit || "px";
632.4329 +		this.now = this.start;
632.4330 +		this.pos = this.state = 0;
632.4331 +
632.4332 +		var self = this;
632.4333 +		function t(gotoEnd){
632.4334 +			return self.step(gotoEnd);
632.4335 +		}
632.4336 +
632.4337 +		t.elem = this.elem;
632.4338 +
632.4339 +		if ( t() && jQuery.timers.push(t) && !timerId )
632.4340 +			timerId = setInterval(jQuery.fx.tick, 13);
632.4341 +	},
632.4342 +
632.4343 +	// Simple 'show' function
632.4344 +	show: function(){
632.4345 +		// Remember where we started, so that we can go back to it later
632.4346 +		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
632.4347 +		this.options.show = true;
632.4348 +
632.4349 +		// Begin the animation
632.4350 +		// Make sure that we start at a small width/height to avoid any
632.4351 +		// flash of content
632.4352 +		this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
632.4353 +
632.4354 +		// Start by showing the element
632.4355 +		jQuery(this.elem).show();
632.4356 +	},
632.4357 +
632.4358 +	// Simple 'hide' function
632.4359 +	hide: function(){
632.4360 +		// Remember where we started, so that we can go back to it later
632.4361 +		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
632.4362 +		this.options.hide = true;
632.4363 +
632.4364 +		// Begin the animation
632.4365 +		this.custom(this.cur(), 0);
632.4366 +	},
632.4367 +
632.4368 +	// Each step of an animation
632.4369 +	step: function(gotoEnd){
632.4370 +		var t = now();
632.4371 +
632.4372 +		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
632.4373 +			this.now = this.end;
632.4374 +			this.pos = this.state = 1;
632.4375 +			this.update();
632.4376 +
632.4377 +			this.options.curAnim[ this.prop ] = true;
632.4378 +
632.4379 +			var done = true;
632.4380 +			for ( var i in this.options.curAnim )
632.4381 +				if ( this.options.curAnim[i] !== true )
632.4382 +					done = false;
632.4383 +
632.4384 +			if ( done ) {
632.4385 +				if ( this.options.display != null ) {
632.4386 +					// Reset the overflow
632.4387 +					this.elem.style.overflow = this.options.overflow;
632.4388 +
632.4389 +					// Reset the display
632.4390 +					this.elem.style.display = this.options.display;
632.4391 +					if ( jQuery.css(this.elem, "display") == "none" )
632.4392 +						this.elem.style.display = "block";
632.4393 +				}
632.4394 +
632.4395 +				// Hide the element if the "hide" operation was done
632.4396 +				if ( this.options.hide )
632.4397 +					jQuery(this.elem).hide();
632.4398 +
632.4399 +				// Reset the properties, if the item has been hidden or shown
632.4400 +				if ( this.options.hide || this.options.show )
632.4401 +					for ( var p in this.options.curAnim )
632.4402 +						jQuery.style(this.elem, p, this.options.orig[p]);
632.4403 +
632.4404 +				// Execute the complete function
632.4405 +				this.options.complete.call( this.elem );
632.4406 +			}
632.4407 +
632.4408 +			return false;
632.4409 +		} else {
632.4410 +			var n = t - this.startTime;
632.4411 +			this.state = n / this.options.duration;
632.4412 +
632.4413 +			// Perform the easing function, defaults to swing
632.4414 +			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
632.4415 +			this.now = this.start + ((this.end - this.start) * this.pos);
632.4416 +
632.4417 +			// Perform the next step of the animation
632.4418 +			this.update();
632.4419 +		}
632.4420 +
632.4421 +		return true;
632.4422 +	}
632.4423 +
632.4424 +};
632.4425 +
632.4426 +jQuery.extend( jQuery.fx, {
632.4427 +
632.4428 +	tick:function(){
632.4429 +		var timers = jQuery.timers;
632.4430 +
632.4431 +		for ( var i = 0; i < timers.length; i++ )
632.4432 +			if ( !timers[i]() )
632.4433 +				timers.splice(i--, 1);
632.4434 +
632.4435 +		if ( !timers.length )
632.4436 +			jQuery.fx.stop();
632.4437 +	},
632.4438 +		
632.4439 +	stop:function(){
632.4440 +		clearInterval( timerId );
632.4441 +		timerId = null;
632.4442 +	},
632.4443 +	
632.4444 +	speeds:{
632.4445 +		slow: 600,
632.4446 + 		fast: 200,
632.4447 + 		// Default speed
632.4448 + 		_default: 400
632.4449 +	},
632.4450 +
632.4451 +	step: {
632.4452 +
632.4453 +		opacity: function(fx){
632.4454 +			jQuery.style(fx.elem, "opacity", fx.now);
632.4455 +		},
632.4456 +
632.4457 +		_default: function(fx){
632.4458 +			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
632.4459 +				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
632.4460 +			else
632.4461 +				fx.elem[ fx.prop ] = fx.now;
632.4462 +		}
632.4463 +	}
632.4464 +});
632.4465 +if ( "getBoundingClientRect" in document.documentElement )
632.4466 +	jQuery.fn.offset = function() {
632.4467 +		var elem = this[0];
632.4468 +		if ( !elem || !elem.ownerDocument ) return null;
632.4469 +		if ( elem === elem.ownerDocument.body ) return jQuery.offset.bodyOffset( elem );
632.4470 +		var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
632.4471 +			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
632.4472 +			top  = box.top  + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
632.4473 +			left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
632.4474 +		return { top: top, left: left };
632.4475 +	};
632.4476 +else
632.4477 +	jQuery.fn.offset = function() {
632.4478 +		var elem = this[0];
632.4479 +		if ( !elem || !elem.ownerDocument ) return null;
632.4480 +		if ( elem === elem.ownerDocument.body ) return jQuery.offset.bodyOffset( elem );
632.4481 +		jQuery.offset.initialize();
632.4482 +
632.4483 +		var offsetParent = elem.offsetParent, prevOffsetParent = elem,
632.4484 +			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
632.4485 +			body = doc.body, defaultView = doc.defaultView,
632.4486 +			prevComputedStyle = defaultView.getComputedStyle(elem, null),
632.4487 +			top = elem.offsetTop, left = elem.offsetLeft;
632.4488 +
632.4489 +		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
632.4490 +			if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) break;
632.4491 +			computedStyle = defaultView.getComputedStyle(elem, null);
632.4492 +			top -= elem.scrollTop, left -= elem.scrollLeft;
632.4493 +			if ( elem === offsetParent ) {
632.4494 +				top += elem.offsetTop, left += elem.offsetLeft;
632.4495 +				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
632.4496 +					top  += parseFloat( computedStyle.borderTopWidth  ) || 0,
632.4497 +					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
632.4498 +				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
632.4499 +			}
632.4500 +			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
632.4501 +				top  += parseFloat( computedStyle.borderTopWidth  ) || 0,
632.4502 +				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
632.4503 +			prevComputedStyle = computedStyle;
632.4504 +		}
632.4505 +
632.4506 +		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
632.4507 +			top  += body.offsetTop,
632.4508 +			left += body.offsetLeft;
632.4509 +
632.4510 +		if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" )
632.4511 +			top  += Math.max( docElem.scrollTop, body.scrollTop ),
632.4512 +			left += Math.max( docElem.scrollLeft, body.scrollLeft );
632.4513 +
632.4514 +		return { top: top, left: left };
632.4515 +	};
632.4516 +
632.4517 +jQuery.offset = {
632.4518 +	initialize: function() {
632.4519 +		var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, 'marginTop', true) ) || 0,
632.4520 +			html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
632.4521 +
632.4522 +		jQuery.extend( container.style, { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' } );
632.4523 +
632.4524 +		container.innerHTML = html;
632.4525 +		body.insertBefore( container, body.firstChild );
632.4526 +		innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
632.4527 +
632.4528 +		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
632.4529 +		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
632.4530 +
632.4531 +		checkDiv.style.position = 'fixed', checkDiv.style.top = '20px';
632.4532 +		this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15); // safari subtracts parent border width here which is 5px
632.4533 +		checkDiv.style.position = '', checkDiv.style.top = '';
632.4534 +
632.4535 +		innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
632.4536 +		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
632.4537 +
632.4538 +		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
632.4539 +
632.4540 +		body.removeChild( container );
632.4541 +		jQuery.offset.initialize = function(){};
632.4542 +		
632.4543 +		body = container = innerDiv = checkDiv = table = td = null;
632.4544 +	},
632.4545 +
632.4546 +	bodyOffset: function(body) {
632.4547 +		jQuery.offset.initialize();
632.4548 +		var top = body.offsetTop, left = body.offsetLeft;
632.4549 +		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
632.4550 +			top  += parseFloat( jQuery.curCSS(body, 'marginTop',  true) ) || 0,
632.4551 +			left += parseFloat( jQuery.curCSS(body, 'marginLeft', true) ) || 0;
632.4552 +		return { top: top, left: left };
632.4553 +	}
632.4554 +};
632.4555 +
632.4556 +
632.4557 +jQuery.fn.extend({
632.4558 +	position: function() {
632.4559 +		if ( !this[0] ) return null;
632.4560 +
632.4561 +		var elem = this[0],
632.4562 +
632.4563 +		// Get *real* offsetParent
632.4564 +		offsetParent = this.offsetParent(),
632.4565 +
632.4566 +		// Get correct offsets
632.4567 +		offset       = this.offset(),
632.4568 +		parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
632.4569 +
632.4570 +		// Subtract element margins
632.4571 +		// note: when an element has margin: auto the offsetLeft and marginLeft
632.4572 +		// are the same in Safari causing offset.left to incorrectly be 0
632.4573 +		offset.top  -= parseFloat( jQuery.curCSS(elem, 'marginTop',  true) ) || 0;
632.4574 +		offset.left -= parseFloat( jQuery.curCSS(elem, 'marginLeft', true) ) || 0;
632.4575 +
632.4576 +		// Add offsetParent borders
632.4577 +		parentOffset.top  += parseFloat( jQuery.curCSS(offsetParent[0], 'borderTopWidth',  true) ) || 0;
632.4578 +		parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], 'borderLeftWidth', true) ) || 0;
632.4579 +
632.4580 +		// Subtract the two offsets
632.4581 +		return {
632.4582 +			top:  offset.top  - parentOffset.top,
632.4583 +			left: offset.left - parentOffset.left
632.4584 +		};
632.4585 +	},
632.4586 +
632.4587 +	offsetParent: function() {
632.4588 +		var offsetParent = this[0].offsetParent || document.body;
632.4589 +		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') === 'static') )
632.4590 +			offsetParent = offsetParent.offsetParent;
632.4591 +		return jQuery( offsetParent );
632.4592 +	}
632.4593 +});
632.4594 +
632.4595 +
632.4596 +// Create scrollLeft and scrollTop methods
632.4597 +jQuery.each( ['Left', 'Top'], function(i, name) {
632.4598 +	var method = 'scroll' + name;
632.4599 +
632.4600 +	jQuery.fn[ method ] = function(val) {
632.4601 +		if ( !this[0] ) return null;
632.4602 +		
632.4603 +		var elem = this[0], win = ("scrollTo" in elem && elem.document) ? elem :
632.4604 +			(elem.nodeName === "#document") ? elem.defaultView || elem.parentWindow :
632.4605 +				false;
632.4606 +
632.4607 +		return val !== undefined ?
632.4608 +
632.4609 +			// Set the scroll offset
632.4610 +			this.each(function() {
632.4611 +				win = ("scrollTo" in this && this.document) ? this : 
632.4612 +					(this.nodeName === "#document") ? this.defaultView || this.parentWindow :
632.4613 +						false;
632.4614 +				
632.4615 +				win ?
632.4616 +					win.scrollTo(
632.4617 +						!i ? val : jQuery(win).scrollLeft(),
632.4618 +						 i ? val : jQuery(win).scrollTop()
632.4619 +					) :
632.4620 +					this[ method ] = val;
632.4621 +			}) :
632.4622 +
632.4623 +			// Return the scroll offset
632.4624 +			win ?
632.4625 +				win[ i ? 'pageYOffset' : 'pageXOffset' ] ||
632.4626 +					jQuery.support.boxModel && win.document.documentElement[ method ] ||
632.4627 +					win.document.body[ method ] :
632.4628 +				elem[ method ];
632.4629 +	};
632.4630 +});
632.4631 +// Create innerHeight, innerWidth, outerHeight and outerWidth methods
632.4632 +jQuery.each([ "Height", "Width" ], function(i, name){
632.4633 +
632.4634 +	var type = name.toLowerCase();
632.4635 +
632.4636 +	// innerHeight and innerWidth
632.4637 +	jQuery.fn["inner" + name] = function(){
632.4638 +		return this[0] ?
632.4639 +			jQuery.css( this[0], type, false, "padding" ) :
632.4640 +			null;
632.4641 +	};
632.4642 +
632.4643 +	// outerHeight and outerWidth
632.4644 +	jQuery.fn["outer" + name] = function(margin) {
632.4645 +		return this[0] ?
632.4646 +			jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
632.4647 +			null;
632.4648 +	};
632.4649 +
632.4650 +	jQuery.fn[ type ] = function( size ) {
632.4651 +		// Get window width or height
632.4652 +		var elem = this[0];
632.4653 +		if ( !elem ) return null;
632.4654 +		return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
632.4655 +			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
632.4656 +			elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
632.4657 +			elem.document.body[ "client" + name ] :
632.4658 +
632.4659 +			// Get document width or height
632.4660 +			(elem.nodeName === "#document") ? // is it a document
632.4661 +				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
632.4662 +				Math.max(
632.4663 +					elem.documentElement["client" + name],
632.4664 +					elem.body["scroll" + name], elem.documentElement["scroll" + name],
632.4665 +					elem.body["offset" + name], elem.documentElement["offset" + name]
632.4666 +				) :
632.4667 +
632.4668 +				// Get or set width or height on the element
632.4669 +				size === undefined ?
632.4670 +					// Get width or height on the element
632.4671 +					jQuery.css( elem, type ) :
632.4672 +
632.4673 +					// Set the width or height on the element (default to pixels if value is unitless)
632.4674 +					this.css( type, typeof size === "string" ? size : size + "px" );
632.4675 +	};
632.4676 +
632.4677 +});
632.4678 +})(window);
   633.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   633.2 +++ b/web/static/js/cluetip-1.0.6/lib/jquery-1.4.js	Mon Apr 26 11:16:23 2010 +0200
   633.3 @@ -0,0 +1,5999 @@
   633.4 +/*!
   633.5 + * jQuery JavaScript Library v1.4
   633.6 + * http://jquery.com/
   633.7 + *
   633.8 + * Copyright 2010, John Resig
   633.9 + * Dual licensed under the MIT or GPL Version 2 licenses.
  633.10 + * http://docs.jquery.com/License
  633.11 + *
  633.12 + * Includes Sizzle.js
  633.13 + * http://sizzlejs.com/
  633.14 + * Copyright 2010, The Dojo Foundation
  633.15 + * Released under the MIT, BSD, and GPL Licenses.
  633.16 + *
  633.17 + * Date: Wed Jan 13 11:24:54 2010 -0500
  633.18 + */
  633.19 +(function( window, undefined ) {
  633.20 +
  633.21 +// Define a local copy of jQuery
  633.22 +var jQuery = function( selector, context ) {
  633.23 +		// The jQuery object is actually just the init constructor 'enhanced'
  633.24 +		return new jQuery.fn.init( selector, context );
  633.25 +	},
  633.26 +
  633.27 +	// Map over jQuery in case of overwrite
  633.28 +	_jQuery = window.jQuery,
  633.29 +
  633.30 +	// Map over the $ in case of overwrite
  633.31 +	_$ = window.$,
  633.32 +
  633.33 +	// Use the correct document accordingly with window argument (sandbox)
  633.34 +	document = window.document,
  633.35 +
  633.36 +	// A central reference to the root jQuery(document)
  633.37 +	rootjQuery,
  633.38 +
  633.39 +	// A simple way to check for HTML strings or ID strings
  633.40 +	// (both of which we optimize for)
  633.41 +	quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,
  633.42 +
  633.43 +	// Is it a simple selector
  633.44 +	isSimple = /^.[^:#\[\.,]*$/,
  633.45 +
  633.46 +	// Check if a string has a non-whitespace character in it
  633.47 +	rnotwhite = /\S/,
  633.48 +
  633.49 +	// Used for trimming whitespace
  633.50 +	rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,
  633.51 +
  633.52 +	// Match a standalone tag
  633.53 +	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
  633.54 +
  633.55 +	// Keep a UserAgent string for use with jQuery.browser
  633.56 +	userAgent = navigator.userAgent,
  633.57 +
  633.58 +	// For matching the engine and version of the browser
  633.59 +	browserMatch,
  633.60 +	
  633.61 +	// Has the ready events already been bound?
  633.62 +	readyBound = false,
  633.63 +	
  633.64 +	// The functions to execute on DOM ready
  633.65 +	readyList = [],
  633.66 +
  633.67 +	// The ready event handler
  633.68 +	DOMContentLoaded,
  633.69 +
  633.70 +	// Save a reference to some core methods
  633.71 +	toString = Object.prototype.toString,
  633.72 +	hasOwnProperty = Object.prototype.hasOwnProperty,
  633.73 +	push = Array.prototype.push,
  633.74 +	slice = Array.prototype.slice,
  633.75 +	indexOf = Array.prototype.indexOf;
  633.76 +
  633.77 +jQuery.fn = jQuery.prototype = {
  633.78 +	init: function( selector, context ) {
  633.79 +		var match, elem, ret, doc;
  633.80 +
  633.81 +		// Handle $(""), $(null), or $(undefined)
  633.82 +		if ( !selector ) {
  633.83 +			return this;
  633.84 +		}
  633.85 +
  633.86 +		// Handle $(DOMElement)
  633.87 +		if ( selector.nodeType ) {
  633.88 +			this.context = this[0] = selector;
  633.89 +			this.length = 1;
  633.90 +			return this;
  633.91 +		}
  633.92 +
  633.93 +		// Handle HTML strings
  633.94 +		if ( typeof selector === "string" ) {
  633.95 +			// Are we dealing with HTML string or an ID?
  633.96 +			match = quickExpr.exec( selector );
  633.97 +
  633.98 +			// Verify a match, and that no context was specified for #id
  633.99 +			if ( match && (match[1] || !context) ) {
 633.100 +
 633.101 +				// HANDLE: $(html) -> $(array)
 633.102 +				if ( match[1] ) {
 633.103 +					doc = (context ? context.ownerDocument || context : document);
 633.104 +
 633.105 +					// If a single string is passed in and it's a single tag
 633.106 +					// just do a createElement and skip the rest
 633.107 +					ret = rsingleTag.exec( selector );
 633.108 +
 633.109 +					if ( ret ) {
 633.110 +						if ( jQuery.isPlainObject( context ) ) {
 633.111 +							selector = [ document.createElement( ret[1] ) ];
 633.112 +							jQuery.fn.attr.call( selector, context, true );
 633.113 +
 633.114 +						} else {
 633.115 +							selector = [ doc.createElement( ret[1] ) ];
 633.116 +						}
 633.117 +
 633.118 +					} else {
 633.119 +						ret = buildFragment( [ match[1] ], [ doc ] );
 633.120 +						selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
 633.121 +					}
 633.122 +
 633.123 +				// HANDLE: $("#id")
 633.124 +				} else {
 633.125 +					elem = document.getElementById( match[2] );
 633.126 +
 633.127 +					if ( elem ) {
 633.128 +						// Handle the case where IE and Opera return items
 633.129 +						// by name instead of ID
 633.130 +						if ( elem.id !== match[2] ) {
 633.131 +							return rootjQuery.find( selector );
 633.132 +						}
 633.133 +
 633.134 +						// Otherwise, we inject the element directly into the jQuery object
 633.135 +						this.length = 1;
 633.136 +						this[0] = elem;
 633.137 +					}
 633.138 +
 633.139 +					this.context = document;
 633.140 +					this.selector = selector;
 633.141 +					return this;
 633.142 +				}
 633.143 +
 633.144 +			// HANDLE: $("TAG")
 633.145 +			} else if ( !context && /^\w+$/.test( selector ) ) {
 633.146 +				this.selector = selector;
 633.147 +				this.context = document;
 633.148 +				selector = document.getElementsByTagName( selector );
 633.149 +
 633.150 +			// HANDLE: $(expr, $(...))
 633.151 +			} else if ( !context || context.jquery ) {
 633.152 +				return (context || rootjQuery).find( selector );
 633.153 +
 633.154 +			// HANDLE: $(expr, context)
 633.155 +			// (which is just equivalent to: $(context).find(expr)
 633.156 +			} else {
 633.157 +				return jQuery( context ).find( selector );
 633.158 +			}
 633.159 +
 633.160 +		// HANDLE: $(function)
 633.161 +		// Shortcut for document ready
 633.162 +		} else if ( jQuery.isFunction( selector ) ) {
 633.163 +			return rootjQuery.ready( selector );
 633.164 +		}
 633.165 +
 633.166 +		if (selector.selector !== undefined) {
 633.167 +			this.selector = selector.selector;
 633.168 +			this.context = selector.context;
 633.169 +		}
 633.170 +
 633.171 +		return jQuery.isArray( selector ) ?
 633.172 +			this.setArray( selector ) :
 633.173 +			jQuery.makeArray( selector, this );
 633.174 +	},
 633.175 +
 633.176 +	// Start with an empty selector
 633.177 +	selector: "",
 633.178 +
 633.179 +	// The current version of jQuery being used
 633.180 +	jquery: "1.4",
 633.181 +
 633.182 +	// The default length of a jQuery object is 0
 633.183 +	length: 0,
 633.184 +
 633.185 +	// The number of elements contained in the matched element set
 633.186 +	size: function() {
 633.187 +		return this.length;
 633.188 +	},
 633.189 +
 633.190 +	toArray: function() {
 633.191 +		return slice.call( this, 0 );
 633.192 +	},
 633.193 +
 633.194 +	// Get the Nth element in the matched element set OR
 633.195 +	// Get the whole matched element set as a clean array
 633.196 +	get: function( num ) {
 633.197 +		return num == null ?
 633.198 +
 633.199 +			// Return a 'clean' array
 633.200 +			this.toArray() :
 633.201 +
 633.202 +			// Return just the object
 633.203 +			( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
 633.204 +	},
 633.205 +
 633.206 +	// Take an array of elements and push it onto the stack
 633.207 +	// (returning the new matched element set)
 633.208 +	pushStack: function( elems, name, selector ) {
 633.209 +		// Build a new jQuery matched element set
 633.210 +		var ret = jQuery( elems || null );
 633.211 +
 633.212 +		// Add the old object onto the stack (as a reference)
 633.213 +		ret.prevObject = this;
 633.214 +
 633.215 +		ret.context = this.context;
 633.216 +
 633.217 +		if ( name === "find" ) {
 633.218 +			ret.selector = this.selector + (this.selector ? " " : "") + selector;
 633.219 +		} else if ( name ) {
 633.220 +			ret.selector = this.selector + "." + name + "(" + selector + ")";
 633.221 +		}
 633.222 +
 633.223 +		// Return the newly-formed element set
 633.224 +		return ret;
 633.225 +	},
 633.226 +
 633.227 +	// Force the current matched set of elements to become
 633.228 +	// the specified array of elements (destroying the stack in the process)
 633.229 +	// You should use pushStack() in order to do this, but maintain the stack
 633.230 +	setArray: function( elems ) {
 633.231 +		// Resetting the length to 0, then using the native Array push
 633.232 +		// is a super-fast way to populate an object with array-like properties
 633.233 +		this.length = 0;
 633.234 +		push.apply( this, elems );
 633.235 +
 633.236 +		return this;
 633.237 +	},
 633.238 +
 633.239 +	// Execute a callback for every element in the matched set.
 633.240 +	// (You can seed the arguments with an array of args, but this is
 633.241 +	// only used internally.)
 633.242 +	each: function( callback, args ) {
 633.243 +		return jQuery.each( this, callback, args );
 633.244 +	},
 633.245 +	
 633.246 +	ready: function( fn ) {
 633.247 +		// Attach the listeners
 633.248 +		jQuery.bindReady();
 633.249 +
 633.250 +		// If the DOM is already ready
 633.251 +		if ( jQuery.isReady ) {
 633.252 +			// Execute the function immediately
 633.253 +			fn.call( document, jQuery );
 633.254 +
 633.255 +		// Otherwise, remember the function for later
 633.256 +		} else if ( readyList ) {
 633.257 +			// Add the function to the wait list
 633.258 +			readyList.push( fn );
 633.259 +		}
 633.260 +
 633.261 +		return this;
 633.262 +	},
 633.263 +	
 633.264 +	eq: function( i ) {
 633.265 +		return i === -1 ?
 633.266 +			this.slice( i ) :
 633.267 +			this.slice( i, +i + 1 );
 633.268 +	},
 633.269 +
 633.270 +	first: function() {
 633.271 +		return this.eq( 0 );
 633.272 +	},
 633.273 +
 633.274 +	last: function() {
 633.275 +		return this.eq( -1 );
 633.276 +	},
 633.277 +
 633.278 +	slice: function() {
 633.279 +		return this.pushStack( slice.apply( this, arguments ),
 633.280 +			"slice", slice.call(arguments).join(",") );
 633.281 +	},
 633.282 +
 633.283 +	map: function( callback ) {
 633.284 +		return this.pushStack( jQuery.map(this, function( elem, i ) {
 633.285 +			return callback.call( elem, i, elem );
 633.286 +		}));
 633.287 +	},
 633.288 +	
 633.289 +	end: function() {
 633.290 +		return this.prevObject || jQuery(null);
 633.291 +	},
 633.292 +
 633.293 +	// For internal use only.
 633.294 +	// Behaves like an Array's method, not like a jQuery method.
 633.295 +	push: push,
 633.296 +	sort: [].sort,
 633.297 +	splice: [].splice
 633.298 +};
 633.299 +
 633.300 +// Give the init function the jQuery prototype for later instantiation
 633.301 +jQuery.fn.init.prototype = jQuery.fn;
 633.302 +
 633.303 +jQuery.extend = jQuery.fn.extend = function() {
 633.304 +	// copy reference to target object
 633.305 +	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
 633.306 +
 633.307 +	// Handle a deep copy situation
 633.308 +	if ( typeof target === "boolean" ) {
 633.309 +		deep = target;
 633.310 +		target = arguments[1] || {};
 633.311 +		// skip the boolean and the target
 633.312 +		i = 2;
 633.313 +	}
 633.314 +
 633.315 +	// Handle case when target is a string or something (possible in deep copy)
 633.316 +	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
 633.317 +		target = {};
 633.318 +	}
 633.319 +
 633.320 +	// extend jQuery itself if only one argument is passed
 633.321 +	if ( length === i ) {
 633.322 +		target = this;
 633.323 +		--i;
 633.324 +	}
 633.325 +
 633.326 +	for ( ; i < length; i++ ) {
 633.327 +		// Only deal with non-null/undefined values
 633.328 +		if ( (options = arguments[ i ]) != null ) {
 633.329 +			// Extend the base object
 633.330 +			for ( name in options ) {
 633.331 +				src = target[ name ];
 633.332 +				copy = options[ name ];
 633.333 +
 633.334 +				// Prevent never-ending loop
 633.335 +				if ( target === copy ) {
 633.336 +					continue;
 633.337 +				}
 633.338 +
 633.339 +				// Recurse if we're merging object literal values or arrays
 633.340 +				if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
 633.341 +					var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
 633.342 +						: jQuery.isArray(copy) ? [] : {};
 633.343 +
 633.344 +					// Never move original objects, clone them
 633.345 +					target[ name ] = jQuery.extend( deep, clone, copy );
 633.346 +
 633.347 +				// Don't bring in undefined values
 633.348 +				} else if ( copy !== undefined ) {
 633.349 +					target[ name ] = copy;
 633.350 +				}
 633.351 +			}
 633.352 +		}
 633.353 +	}
 633.354 +
 633.355 +	// Return the modified object
 633.356 +	return target;
 633.357 +};
 633.358 +
 633.359 +jQuery.extend({
 633.360 +	noConflict: function( deep ) {
 633.361 +		window.$ = _$;
 633.362 +
 633.363 +		if ( deep ) {
 633.364 +			window.jQuery = _jQuery;
 633.365 +		}
 633.366 +
 633.367 +		return jQuery;
 633.368 +	},
 633.369 +	
 633.370 +	// Is the DOM ready to be used? Set to true once it occurs.
 633.371 +	isReady: false,
 633.372 +	
 633.373 +	// Handle when the DOM is ready
 633.374 +	ready: function() {
 633.375 +		// Make sure that the DOM is not already loaded
 633.376 +		if ( !jQuery.isReady ) {
 633.377 +			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
 633.378 +			if ( !document.body ) {
 633.379 +				return setTimeout( jQuery.ready, 13 );
 633.380 +			}
 633.381 +
 633.382 +			// Remember that the DOM is ready
 633.383 +			jQuery.isReady = true;
 633.384 +
 633.385 +			// If there are functions bound, to execute
 633.386 +			if ( readyList ) {
 633.387 +				// Execute all of them
 633.388 +				var fn, i = 0;
 633.389 +				while ( (fn = readyList[ i++ ]) ) {
 633.390 +					fn.call( document, jQuery );
 633.391 +				}
 633.392 +
 633.393 +				// Reset the list of functions
 633.394 +				readyList = null;
 633.395 +			}
 633.396 +
 633.397 +			// Trigger any bound ready events
 633.398 +			if ( jQuery.fn.triggerHandler ) {
 633.399 +				jQuery( document ).triggerHandler( "ready" );
 633.400 +			}
 633.401 +		}
 633.402 +	},
 633.403 +	
 633.404 +	bindReady: function() {
 633.405 +		if ( readyBound ) {
 633.406 +			return;
 633.407 +		}
 633.408 +
 633.409 +		readyBound = true;
 633.410 +
 633.411 +		// Catch cases where $(document).ready() is called after the
 633.412 +		// browser event has already occurred.
 633.413 +		if ( document.readyState === "complete" ) {
 633.414 +			return jQuery.ready();
 633.415 +		}
 633.416 +
 633.417 +		// Mozilla, Opera and webkit nightlies currently support this event
 633.418 +		if ( document.addEventListener ) {
 633.419 +			// Use the handy event callback
 633.420 +			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 633.421 +			
 633.422 +			// A fallback to window.onload, that will always work
 633.423 +			window.addEventListener( "load", jQuery.ready, false );
 633.424 +
 633.425 +		// If IE event model is used
 633.426 +		} else if ( document.attachEvent ) {
 633.427 +			// ensure firing before onload,
 633.428 +			// maybe late but safe also for iframes
 633.429 +			document.attachEvent("onreadystatechange", DOMContentLoaded);
 633.430 +			
 633.431 +			// A fallback to window.onload, that will always work
 633.432 +			window.attachEvent( "onload", jQuery.ready );
 633.433 +
 633.434 +			// If IE and not a frame
 633.435 +			// continually check to see if the document is ready
 633.436 +			var toplevel = false;
 633.437 +
 633.438 +			try {
 633.439 +				toplevel = window.frameElement == null;
 633.440 +			} catch(e) {}
 633.441 +
 633.442 +			if ( document.documentElement.doScroll && toplevel ) {
 633.443 +				doScrollCheck();
 633.444 +			}
 633.445 +		}
 633.446 +	},
 633.447 +
 633.448 +	// See test/unit/core.js for details concerning isFunction.
 633.449 +	// Since version 1.3, DOM methods and functions like alert
 633.450 +	// aren't supported. They return false on IE (#2968).
 633.451 +	isFunction: function( obj ) {
 633.452 +		return toString.call(obj) === "[object Function]";
 633.453 +	},
 633.454 +
 633.455 +	isArray: function( obj ) {
 633.456 +		return toString.call(obj) === "[object Array]";
 633.457 +	},
 633.458 +
 633.459 +	isPlainObject: function( obj ) {
 633.460 +		// Must be an Object.
 633.461 +		// Because of IE, we also have to check the presence of the constructor property.
 633.462 +		// Make sure that DOM nodes and window objects don't pass through, as well
 633.463 +		if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
 633.464 +			return false;
 633.465 +		}
 633.466 +		
 633.467 +		// Not own constructor property must be Object
 633.468 +		if ( obj.constructor
 633.469 +			&& !hasOwnProperty.call(obj, "constructor")
 633.470 +			&& !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
 633.471 +			return false;
 633.472 +		}
 633.473 +		
 633.474 +		// Own properties are enumerated firstly, so to speed up,
 633.475 +		// if last one is own, then all properties are own.
 633.476 +	
 633.477 +		var key;
 633.478 +		for ( key in obj ) {}
 633.479 +		
 633.480 +		return key === undefined || hasOwnProperty.call( obj, key );
 633.481 +	},
 633.482 +
 633.483 +	isEmptyObject: function( obj ) {
 633.484 +		for ( var name in obj ) {
 633.485 +			return false;
 633.486 +		}
 633.487 +		return true;
 633.488 +	},
 633.489 +
 633.490 +	noop: function() {},
 633.491 +
 633.492 +	// Evalulates a script in a global context
 633.493 +	globalEval: function( data ) {
 633.494 +		if ( data && rnotwhite.test(data) ) {
 633.495 +			// Inspired by code by Andrea Giammarchi
 633.496 +			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
 633.497 +			var head = document.getElementsByTagName("head")[0] || document.documentElement,
 633.498 +				script = document.createElement("script");
 633.499 +
 633.500 +			script.type = "text/javascript";
 633.501 +
 633.502 +			if ( jQuery.support.scriptEval ) {
 633.503 +				script.appendChild( document.createTextNode( data ) );
 633.504 +			} else {
 633.505 +				script.text = data;
 633.506 +			}
 633.507 +
 633.508 +			// Use insertBefore instead of appendChild to circumvent an IE6 bug.
 633.509 +			// This arises when a base node is used (#2709).
 633.510 +			head.insertBefore( script, head.firstChild );
 633.511 +			head.removeChild( script );
 633.512 +		}
 633.513 +	},
 633.514 +
 633.515 +	nodeName: function( elem, name ) {
 633.516 +		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
 633.517 +	},
 633.518 +
 633.519 +	// args is for internal usage only
 633.520 +	each: function( object, callback, args ) {
 633.521 +		var name, i = 0,
 633.522 +			length = object.length,
 633.523 +			isObj = length === undefined || jQuery.isFunction(object);
 633.524 +
 633.525 +		if ( args ) {
 633.526 +			if ( isObj ) {
 633.527 +				for ( name in object ) {
 633.528 +					if ( callback.apply( object[ name ], args ) === false ) {
 633.529 +						break;
 633.530 +					}
 633.531 +				}
 633.532 +			} else {
 633.533 +				for ( ; i < length; ) {
 633.534 +					if ( callback.apply( object[ i++ ], args ) === false ) {
 633.535 +						break;
 633.536 +					}
 633.537 +				}
 633.538 +			}
 633.539 +
 633.540 +		// A special, fast, case for the most common use of each
 633.541 +		} else {
 633.542 +			if ( isObj ) {
 633.543 +				for ( name in object ) {
 633.544 +					if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
 633.545 +						break;
 633.546 +					}
 633.547 +				}
 633.548 +			} else {
 633.549 +				for ( var value = object[0];
 633.550 +					i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
 633.551 +			}
 633.552 +		}
 633.553 +
 633.554 +		return object;
 633.555 +	},
 633.556 +
 633.557 +	trim: function( text ) {
 633.558 +		return (text || "").replace( rtrim, "" );
 633.559 +	},
 633.560 +
 633.561 +	// results is for internal usage only
 633.562 +	makeArray: function( array, results ) {
 633.563 +		var ret = results || [];
 633.564 +
 633.565 +		if ( array != null ) {
 633.566 +			// The window, strings (and functions) also have 'length'
 633.567 +			// The extra typeof function check is to prevent crashes
 633.568 +			// in Safari 2 (See: #3039)
 633.569 +			if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
 633.570 +				push.call( ret, array );
 633.571 +			} else {
 633.572 +				jQuery.merge( ret, array );
 633.573 +			}
 633.574 +		}
 633.575 +
 633.576 +		return ret;
 633.577 +	},
 633.578 +
 633.579 +	inArray: function( elem, array ) {
 633.580 +		if ( array.indexOf ) {
 633.581 +			return array.indexOf( elem );
 633.582 +		}
 633.583 +
 633.584 +		for ( var i = 0, length = array.length; i < length; i++ ) {
 633.585 +			if ( array[ i ] === elem ) {
 633.586 +				return i;
 633.587 +			}
 633.588 +		}
 633.589 +
 633.590 +		return -1;
 633.591 +	},
 633.592 +
 633.593 +	merge: function( first, second ) {
 633.594 +		var i = first.length, j = 0;
 633.595 +
 633.596 +		if ( typeof second.length === "number" ) {
 633.597 +			for ( var l = second.length; j < l; j++ ) {
 633.598 +				first[ i++ ] = second[ j ];
 633.599 +			}
 633.600 +		} else {
 633.601 +			while ( second[j] !== undefined ) {
 633.602 +				first[ i++ ] = second[ j++ ];
 633.603 +			}
 633.604 +		}
 633.605 +
 633.606 +		first.length = i;
 633.607 +
 633.608 +		return first;
 633.609 +	},
 633.610 +
 633.611 +	grep: function( elems, callback, inv ) {
 633.612 +		var ret = [];
 633.613 +
 633.614 +		// Go through the array, only saving the items
 633.615 +		// that pass the validator function
 633.616 +		for ( var i = 0, length = elems.length; i < length; i++ ) {
 633.617 +			if ( !inv !== !callback( elems[ i ], i ) ) {
 633.618 +				ret.push( elems[ i ] );
 633.619 +			}
 633.620 +		}
 633.621 +
 633.622 +		return ret;
 633.623 +	},
 633.624 +
 633.625 +	// arg is for internal usage only
 633.626 +	map: function( elems, callback, arg ) {
 633.627 +		var ret = [], value;
 633.628 +
 633.629 +		// Go through the array, translating each of the items to their
 633.630 +		// new value (or values).
 633.631 +		for ( var i = 0, length = elems.length; i < length; i++ ) {
 633.632 +			value = callback( elems[ i ], i, arg );
 633.633 +
 633.634 +			if ( value != null ) {
 633.635 +				ret[ ret.length ] = value;
 633.636 +			}
 633.637 +		}
 633.638 +
 633.639 +		return ret.concat.apply( [], ret );
 633.640 +	},
 633.641 +
 633.642 +	// A global GUID counter for objects
 633.643 +	guid: 1,
 633.644 +
 633.645 +	proxy: function( fn, proxy, thisObject ) {
 633.646 +		if ( arguments.length === 2 ) {
 633.647 +			if ( typeof proxy === "string" ) {
 633.648 +				thisObject = fn;
 633.649 +				fn = thisObject[ proxy ];
 633.650 +				proxy = undefined;
 633.651 +
 633.652 +			} else if ( proxy && !jQuery.isFunction( proxy ) ) {
 633.653 +				thisObject = proxy;
 633.654 +				proxy = undefined;
 633.655 +			}
 633.656 +		}
 633.657 +
 633.658 +		if ( !proxy && fn ) {
 633.659 +			proxy = function() {
 633.660 +				return fn.apply( thisObject || this, arguments );
 633.661 +			};
 633.662 +		}
 633.663 +
 633.664 +		// Set the guid of unique handler to the same of original handler, so it can be removed
 633.665 +		if ( fn ) {
 633.666 +			proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
 633.667 +		}
 633.668 +
 633.669 +		// So proxy can be declared as an argument
 633.670 +		return proxy;
 633.671 +	},
 633.672 +
 633.673 +	// Use of jQuery.browser is frowned upon.
 633.674 +	// More details: http://docs.jquery.com/Utilities/jQuery.browser
 633.675 +	uaMatch: function( ua ) {
 633.676 +		var ret = { browser: "" };
 633.677 +
 633.678 +		ua = ua.toLowerCase();
 633.679 +
 633.680 +		if ( /webkit/.test( ua ) ) {
 633.681 +			ret = { browser: "webkit", version: /webkit[\/ ]([\w.]+)/ };
 633.682 +
 633.683 +		} else if ( /opera/.test( ua ) ) {
 633.684 +			ret = { browser: "opera", version:  /version/.test( ua ) ? /version[\/ ]([\w.]+)/ : /opera[\/ ]([\w.]+)/ };
 633.685 +			
 633.686 +		} else if ( /msie/.test( ua ) ) {
 633.687 +			ret = { browser: "msie", version: /msie ([\w.]+)/ };
 633.688 +
 633.689 +		} else if ( /mozilla/.test( ua ) && !/compatible/.test( ua ) ) {
 633.690 +			ret = { browser: "mozilla", version: /rv:([\w.]+)/ };
 633.691 +		}
 633.692 +
 633.693 +		ret.version = (ret.version && ret.version.exec( ua ) || [0, "0"])[1];
 633.694 +
 633.695 +		return ret;
 633.696 +	},
 633.697 +
 633.698 +	browser: {}
 633.699 +});
 633.700 +
 633.701 +browserMatch = jQuery.uaMatch( userAgent );
 633.702 +if ( browserMatch.browser ) {
 633.703 +	jQuery.browser[ browserMatch.browser ] = true;
 633.704 +	jQuery.browser.version = browserMatch.version;
 633.705 +}
 633.706 +
 633.707 +// Deprecated, use jQuery.browser.webkit instead
 633.708 +if ( jQuery.browser.webkit ) {
 633.709 +	jQuery.browser.safari = true;
 633.710 +}
 633.711 +
 633.712 +if ( indexOf ) {
 633.713 +	jQuery.inArray = function( elem, array ) {
 633.714 +		return indexOf.call( array, elem );
 633.715 +	};
 633.716 +}
 633.717 +
 633.718 +// All jQuery objects should point back to these
 633.719 +rootjQuery = jQuery(document);
 633.720 +
 633.721 +// Cleanup functions for the document ready method
 633.722 +if ( document.addEventListener ) {
 633.723 +	DOMContentLoaded = function() {
 633.724 +		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 633.725 +		jQuery.ready();
 633.726 +	};
 633.727 +
 633.728 +} else if ( document.attachEvent ) {
 633.729 +	DOMContentLoaded = function() {
 633.730 +		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
 633.731 +		if ( document.readyState === "complete" ) {
 633.732 +			document.detachEvent( "onreadystatechange", DOMContentLoaded );
 633.733 +			jQuery.ready();
 633.734 +		}
 633.735 +	};
 633.736 +}
 633.737 +
 633.738 +// The DOM ready check for Internet Explorer
 633.739 +function doScrollCheck() {
 633.740 +	if ( jQuery.isReady ) {
 633.741 +		return;
 633.742 +	}
 633.743 +
 633.744 +	try {
 633.745 +		// If IE is used, use the trick by Diego Perini
 633.746 +		// http://javascript.nwbox.com/IEContentLoaded/
 633.747 +		document.documentElement.doScroll("left");
 633.748 +	} catch( error ) {
 633.749 +		setTimeout( doScrollCheck, 1 );
 633.750 +		return;
 633.751 +	}
 633.752 +
 633.753 +	// and execute any waiting functions
 633.754 +	jQuery.ready();
 633.755 +}
 633.756 +
 633.757 +if ( indexOf ) {
 633.758 +	jQuery.inArray = function( elem, array ) {
 633.759 +		return indexOf.call( array, elem );
 633.760 +	};
 633.761 +}
 633.762 +
 633.763 +function evalScript( i, elem ) {
 633.764 +	if ( elem.src ) {
 633.765 +		jQuery.ajax({
 633.766 +			url: elem.src,
 633.767 +			async: false,
 633.768 +			dataType: "script"
 633.769 +		});
 633.770 +	} else {
 633.771 +		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
 633.772 +	}
 633.773 +
 633.774 +	if ( elem.parentNode ) {
 633.775 +		elem.parentNode.removeChild( elem );
 633.776 +	}
 633.777 +}
 633.778 +
 633.779 +// Mutifunctional method to get and set values to a collection
 633.780 +// The value/s can be optionally by executed if its a function
 633.781 +function access( elems, key, value, exec, fn, pass ) {
 633.782 +	var length = elems.length;
 633.783 +	
 633.784 +	// Setting many attributes
 633.785 +	if ( typeof key === "object" ) {
 633.786 +		for ( var k in key ) {
 633.787 +			access( elems, k, key[k], exec, fn, value );
 633.788 +		}
 633.789 +		return elems;
 633.790 +	}
 633.791 +	
 633.792 +	// Setting one attribute
 633.793 +	if ( value !== undefined ) {
 633.794 +		// Optionally, function values get executed if exec is true
 633.795 +		exec = !pass && exec && jQuery.isFunction(value);
 633.796 +		
 633.797 +		for ( var i = 0; i < length; i++ ) {
 633.798 +			fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
 633.799 +		}
 633.800 +		
 633.801 +		return elems;
 633.802 +	}
 633.803 +	
 633.804 +	// Getting an attribute
 633.805 +	return length ? fn( elems[0], key ) : null;
 633.806 +}
 633.807 +
 633.808 +function now() {
 633.809 +	return (new Date).getTime();
 633.810 +}
 633.811 +(function() {
 633.812 +
 633.813 +	jQuery.support = {};
 633.814 +
 633.815 +	var root = document.documentElement,
 633.816 +		script = document.createElement("script"),
 633.817 +		div = document.createElement("div"),
 633.818 +		id = "script" + now();
 633.819 +
 633.820 +	div.style.display = "none";
 633.821 +	div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
 633.822 +
 633.823 +	var all = div.getElementsByTagName("*"),
 633.824 +		a = div.getElementsByTagName("a")[0];
 633.825 +
 633.826 +	// Can't get basic test support
 633.827 +	if ( !all || !all.length || !a ) {
 633.828 +		return;
 633.829 +	}
 633.830 +
 633.831 +	jQuery.support = {
 633.832 +		// IE strips leading whitespace when .innerHTML is used
 633.833 +		leadingWhitespace: div.firstChild.nodeType === 3,
 633.834 +
 633.835 +		// Make sure that tbody elements aren't automatically inserted
 633.836 +		// IE will insert them into empty tables
 633.837 +		tbody: !div.getElementsByTagName("tbody").length,
 633.838 +
 633.839 +		// Make sure that link elements get serialized correctly by innerHTML
 633.840 +		// This requires a wrapper element in IE
 633.841 +		htmlSerialize: !!div.getElementsByTagName("link").length,
 633.842 +
 633.843 +		// Get the style information from getAttribute
 633.844 +		// (IE uses .cssText insted)
 633.845 +		style: /red/.test( a.getAttribute("style") ),
 633.846 +
 633.847 +		// Make sure that URLs aren't manipulated
 633.848 +		// (IE normalizes it by default)
 633.849 +		hrefNormalized: a.getAttribute("href") === "/a",
 633.850 +
 633.851 +		// Make sure that element opacity exists
 633.852 +		// (IE uses filter instead)
 633.853 +		// Use a regex to work around a WebKit issue. See #5145
 633.854 +		opacity: /^0.55$/.test( a.style.opacity ),
 633.855 +
 633.856 +		// Verify style float existence
 633.857 +		// (IE uses styleFloat instead of cssFloat)
 633.858 +		cssFloat: !!a.style.cssFloat,
 633.859 +
 633.860 +		// Make sure that if no value is specified for a checkbox
 633.861 +		// that it defaults to "on".
 633.862 +		// (WebKit defaults to "" instead)
 633.863 +		checkOn: div.getElementsByTagName("input")[0].value === "on",
 633.864 +
 633.865 +		// Make sure that a selected-by-default option has a working selected property.
 633.866 +		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
 633.867 +		optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
 633.868 +
 633.869 +		// Will be defined later
 633.870 +		scriptEval: false,
 633.871 +		noCloneEvent: true,
 633.872 +		boxModel: null
 633.873 +	};
 633.874 +
 633.875 +	script.type = "text/javascript";
 633.876 +	try {
 633.877 +		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
 633.878 +	} catch(e) {}
 633.879 +
 633.880 +	root.insertBefore( script, root.firstChild );
 633.881 +
 633.882 +	// Make sure that the execution of code works by injecting a script
 633.883 +	// tag with appendChild/createTextNode
 633.884 +	// (IE doesn't support this, fails, and uses .text instead)
 633.885 +	if ( window[ id ] ) {
 633.886 +		jQuery.support.scriptEval = true;
 633.887 +		delete window[ id ];
 633.888 +	}
 633.889 +
 633.890 +	root.removeChild( script );
 633.891 +
 633.892 +	if ( div.attachEvent && div.fireEvent ) {
 633.893 +		div.attachEvent("onclick", function click() {
 633.894 +			// Cloning a node shouldn't copy over any
 633.895 +			// bound event handlers (IE does this)
 633.896 +			jQuery.support.noCloneEvent = false;
 633.897 +			div.detachEvent("onclick", click);
 633.898 +		});
 633.899 +		div.cloneNode(true).fireEvent("onclick");
 633.900 +	}
 633.901 +
 633.902 +	// Figure out if the W3C box model works as expected
 633.903 +	// document.body must exist before we can do this
 633.904 +	// TODO: This timeout is temporary until I move ready into core.js.
 633.905 +	jQuery(function() {
 633.906 +		var div = document.createElement("div");
 633.907 +		div.style.width = div.style.paddingLeft = "1px";
 633.908 +
 633.909 +		document.body.appendChild( div );
 633.910 +		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
 633.911 +		document.body.removeChild( div ).style.display = 'none';
 633.912 +		div = null;
 633.913 +	});
 633.914 +
 633.915 +	// Technique from Juriy Zaytsev
 633.916 +	// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
 633.917 +	var eventSupported = function( eventName ) { 
 633.918 +		var el = document.createElement("div"); 
 633.919 +		eventName = "on" + eventName; 
 633.920 +
 633.921 +		var isSupported = (eventName in el); 
 633.922 +		if ( !isSupported ) { 
 633.923 +			el.setAttribute(eventName, "return;"); 
 633.924 +			isSupported = typeof el[eventName] === "function"; 
 633.925 +		} 
 633.926 +		el = null; 
 633.927 +
 633.928 +		return isSupported; 
 633.929 +	};
 633.930 +	
 633.931 +	jQuery.support.submitBubbles = eventSupported("submit");
 633.932 +	jQuery.support.changeBubbles = eventSupported("change");
 633.933 +
 633.934 +	// release memory in IE
 633.935 +	root = script = div = all = a = null;
 633.936 +})();
 633.937 +
 633.938 +jQuery.props = {
 633.939 +	"for": "htmlFor",
 633.940 +	"class": "className",
 633.941 +	readonly: "readOnly",
 633.942 +	maxlength: "maxLength",
 633.943 +	cellspacing: "cellSpacing",
 633.944 +	rowspan: "rowSpan",
 633.945 +	colspan: "colSpan",
 633.946 +	tabindex: "tabIndex",
 633.947 +	usemap: "useMap",
 633.948 +	frameborder: "frameBorder"
 633.949 +};
 633.950 +var expando = "jQuery" + now(), uuid = 0, windowData = {};
 633.951 +var emptyObject = {};
 633.952 +
 633.953 +jQuery.extend({
 633.954 +	cache: {},
 633.955 +	
 633.956 +	expando:expando,
 633.957 +
 633.958 +	// The following elements throw uncatchable exceptions if you
 633.959 +	// attempt to add expando properties to them.
 633.960 +	noData: {
 633.961 +		"embed": true,
 633.962 +		"object": true,
 633.963 +		"applet": true
 633.964 +	},
 633.965 +
 633.966 +	data: function( elem, name, data ) {
 633.967 +		if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
 633.968 +			return;
 633.969 +		}
 633.970 +
 633.971 +		elem = elem == window ?
 633.972 +			windowData :
 633.973 +			elem;
 633.974 +
 633.975 +		var id = elem[ expando ], cache = jQuery.cache, thisCache;
 633.976 +
 633.977 +		// Handle the case where there's no name immediately
 633.978 +		if ( !name && !id ) {
 633.979 +			return null;
 633.980 +		}
 633.981 +
 633.982 +		// Compute a unique ID for the element
 633.983 +		if ( !id ) { 
 633.984 +			id = ++uuid;
 633.985 +		}
 633.986 +
 633.987 +		// Avoid generating a new cache unless none exists and we
 633.988 +		// want to manipulate it.
 633.989 +		if ( typeof name === "object" ) {
 633.990 +			elem[ expando ] = id;
 633.991 +			thisCache = cache[ id ] = jQuery.extend(true, {}, name);
 633.992 +		} else if ( cache[ id ] ) {
 633.993 +			thisCache = cache[ id ];
 633.994 +		} else if ( typeof data === "undefined" ) {
 633.995 +			thisCache = emptyObject;
 633.996 +		} else {
 633.997 +			thisCache = cache[ id ] = {};
 633.998 +		}
 633.999 +
633.1000 +		// Prevent overriding the named cache with undefined values
633.1001 +		if ( data !== undefined ) {
633.1002 +			elem[ expando ] = id;
633.1003 +			thisCache[ name ] = data;
633.1004 +		}
633.1005 +
633.1006 +		return typeof name === "string" ? thisCache[ name ] : thisCache;
633.1007 +	},
633.1008 +
633.1009 +	removeData: function( elem, name ) {
633.1010 +		if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
633.1011 +			return;
633.1012 +		}
633.1013 +
633.1014 +		elem = elem == window ?
633.1015 +			windowData :
633.1016 +			elem;
633.1017 +
633.1018 +		var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];
633.1019 +
633.1020 +		// If we want to remove a specific section of the element's data
633.1021 +		if ( name ) {
633.1022 +			if ( thisCache ) {
633.1023 +				// Remove the section of cache data
633.1024 +				delete thisCache[ name ];
633.1025 +
633.1026 +				// If we've removed all the data, remove the element's cache
633.1027 +				if ( jQuery.isEmptyObject(thisCache) ) {
633.1028 +					jQuery.removeData( elem );
633.1029 +				}
633.1030 +			}
633.1031 +
633.1032 +		// Otherwise, we want to remove all of the element's data
633.1033 +		} else {
633.1034 +			// Clean up the element expando
633.1035 +			try {
633.1036 +				delete elem[ expando ];
633.1037 +			} catch( e ) {
633.1038 +				// IE has trouble directly removing the expando
633.1039 +				// but it's ok with using removeAttribute
633.1040 +				if ( elem.removeAttribute ) {
633.1041 +					elem.removeAttribute( expando );
633.1042 +				}
633.1043 +			}
633.1044 +
633.1045 +			// Completely remove the data cache
633.1046 +			delete cache[ id ];
633.1047 +		}
633.1048 +	}
633.1049 +});
633.1050 +
633.1051 +jQuery.fn.extend({
633.1052 +	data: function( key, value ) {
633.1053 +		if ( typeof key === "undefined" && this.length ) {
633.1054 +			return jQuery.data( this[0] );
633.1055 +
633.1056 +		} else if ( typeof key === "object" ) {
633.1057 +			return this.each(function() {
633.1058 +				jQuery.data( this, key );
633.1059 +			});
633.1060 +		}
633.1061 +
633.1062 +		var parts = key.split(".");
633.1063 +		parts[1] = parts[1] ? "." + parts[1] : "";
633.1064 +
633.1065 +		if ( value === undefined ) {
633.1066 +			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
633.1067 +
633.1068 +			if ( data === undefined && this.length ) {
633.1069 +				data = jQuery.data( this[0], key );
633.1070 +			}
633.1071 +			return data === undefined && parts[1] ?
633.1072 +				this.data( parts[0] ) :
633.1073 +				data;
633.1074 +		} else {
633.1075 +			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
633.1076 +				jQuery.data( this, key, value );
633.1077 +			});
633.1078 +		}
633.1079 +	},
633.1080 +
633.1081 +	removeData: function( key ) {
633.1082 +		return this.each(function() {
633.1083 +			jQuery.removeData( this, key );
633.1084 +		});
633.1085 +	}
633.1086 +});
633.1087 +jQuery.extend({
633.1088 +	queue: function( elem, type, data ) {
633.1089 +		if ( !elem ) {
633.1090 +			return;
633.1091 +		}
633.1092 +
633.1093 +		type = (type || "fx") + "queue";
633.1094 +		var q = jQuery.data( elem, type );
633.1095 +
633.1096 +		// Speed up dequeue by getting out quickly if this is just a lookup
633.1097 +		if ( !data ) {
633.1098 +			return q || [];
633.1099 +		}
633.1100 +
633.1101 +		if ( !q || jQuery.isArray(data) ) {
633.1102 +			q = jQuery.data( elem, type, jQuery.makeArray(data) );
633.1103 +
633.1104 +		} else {
633.1105 +			q.push( data );
633.1106 +		}
633.1107 +
633.1108 +		return q;
633.1109 +	},
633.1110 +
633.1111 +	dequeue: function( elem, type ) {
633.1112 +		type = type || "fx";
633.1113 +
633.1114 +		var queue = jQuery.queue( elem, type ), fn = queue.shift();
633.1115 +
633.1116 +		// If the fx queue is dequeued, always remove the progress sentinel
633.1117 +		if ( fn === "inprogress" ) {
633.1118 +			fn = queue.shift();
633.1119 +		}
633.1120 +
633.1121 +		if ( fn ) {
633.1122 +			// Add a progress sentinel to prevent the fx queue from being
633.1123 +			// automatically dequeued
633.1124 +			if ( type === "fx" ) {
633.1125 +				queue.unshift("inprogress");
633.1126 +			}
633.1127 +
633.1128 +			fn.call(elem, function() {
633.1129 +				jQuery.dequeue(elem, type);
633.1130 +			});
633.1131 +		}
633.1132 +	}
633.1133 +});
633.1134 +
633.1135 +jQuery.fn.extend({
633.1136 +	queue: function( type, data ) {
633.1137 +		if ( typeof type !== "string" ) {
633.1138 +			data = type;
633.1139 +			type = "fx";
633.1140 +		}
633.1141 +
633.1142 +		if ( data === undefined ) {
633.1143 +			return jQuery.queue( this[0], type );
633.1144 +		}
633.1145 +		return this.each(function( i, elem ) {
633.1146 +			var queue = jQuery.queue( this, type, data );
633.1147 +
633.1148 +			if ( type === "fx" && queue[0] !== "inprogress" ) {
633.1149 +				jQuery.dequeue( this, type );
633.1150 +			}
633.1151 +		});
633.1152 +	},
633.1153 +	dequeue: function( type ) {
633.1154 +		return this.each(function() {
633.1155 +			jQuery.dequeue( this, type );
633.1156 +		});
633.1157 +	},
633.1158 +
633.1159 +	// Based off of the plugin by Clint Helfers, with permission.
633.1160 +	// http://blindsignals.com/index.php/2009/07/jquery-delay/
633.1161 +	delay: function( time, type ) {
633.1162 +		time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
633.1163 +		type = type || "fx";
633.1164 +
633.1165 +		return this.queue( type, function() {
633.1166 +			var elem = this;
633.1167 +			setTimeout(function() {
633.1168 +				jQuery.dequeue( elem, type );
633.1169 +			}, time );
633.1170 +		});
633.1171 +	},
633.1172 +
633.1173 +	clearQueue: function( type ) {
633.1174 +		return this.queue( type || "fx", [] );
633.1175 +	}
633.1176 +});
633.1177 +var rclass = /[\n\t]/g,
633.1178 +	rspace = /\s+/,
633.1179 +	rreturn = /\r/g,
633.1180 +	rspecialurl = /href|src|style/,
633.1181 +	rtype = /(button|input)/i,
633.1182 +	rfocusable = /(button|input|object|select|textarea)/i,
633.1183 +	rclickable = /^(a|area)$/i,
633.1184 +	rradiocheck = /radio|checkbox/;
633.1185 +
633.1186 +jQuery.fn.extend({
633.1187 +	attr: function( name, value ) {
633.1188 +		return access( this, name, value, true, jQuery.attr );
633.1189 +	},
633.1190 +
633.1191 +	removeAttr: function( name, fn ) {
633.1192 +		return this.each(function(){
633.1193 +			jQuery.attr( this, name, "" );
633.1194 +			if ( this.nodeType === 1 ) {
633.1195 +				this.removeAttribute( name );
633.1196 +			}
633.1197 +		});
633.1198 +	},
633.1199 +
633.1200 +	addClass: function( value ) {
633.1201 +		if ( jQuery.isFunction(value) ) {
633.1202 +			return this.each(function(i) {
633.1203 +				var self = jQuery(this);
633.1204 +				self.addClass( value.call(this, i, self.attr("class")) );
633.1205 +			});
633.1206 +		}
633.1207 +
633.1208 +		if ( value && typeof value === "string" ) {
633.1209 +			var classNames = (value || "").split( rspace );
633.1210 +
633.1211 +			for ( var i = 0, l = this.length; i < l; i++ ) {
633.1212 +				var elem = this[i];
633.1213 +
633.1214 +				if ( elem.nodeType === 1 ) {
633.1215 +					if ( !elem.className ) {
633.1216 +						elem.className = value;
633.1217 +
633.1218 +					} else {
633.1219 +						var className = " " + elem.className + " ";
633.1220 +						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
633.1221 +							if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
633.1222 +								elem.className += " " + classNames[c];
633.1223 +							}
633.1224 +						}
633.1225 +					}
633.1226 +				}
633.1227 +			}
633.1228 +		}
633.1229 +
633.1230 +		return this;
633.1231 +	},
633.1232 +
633.1233 +	removeClass: function( value ) {
633.1234 +		if ( jQuery.isFunction(value) ) {
633.1235 +			return this.each(function(i) {
633.1236 +				var self = jQuery(this);
633.1237 +				self.removeClass( value.call(this, i, self.attr("class")) );
633.1238 +			});
633.1239 +		}
633.1240 +
633.1241 +		if ( (value && typeof value === "string") || value === undefined ) {
633.1242 +			var classNames = (value || "").split(rspace);
633.1243 +
633.1244 +			for ( var i = 0, l = this.length; i < l; i++ ) {
633.1245 +				var elem = this[i];
633.1246 +
633.1247 +				if ( elem.nodeType === 1 && elem.className ) {
633.1248 +					if ( value ) {
633.1249 +						var className = (" " + elem.className + " ").replace(rclass, " ");
633.1250 +						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
633.1251 +							className = className.replace(" " + classNames[c] + " ", " ");
633.1252 +						}
633.1253 +						elem.className = className.substring(1, className.length - 1);
633.1254 +
633.1255 +					} else {
633.1256 +						elem.className = "";
633.1257 +					}
633.1258 +				}
633.1259 +			}
633.1260 +		}
633.1261 +
633.1262 +		return this;
633.1263 +	},
633.1264 +
633.1265 +	toggleClass: function( value, stateVal ) {
633.1266 +		var type = typeof value, isBool = typeof stateVal === "boolean";
633.1267 +
633.1268 +		if ( jQuery.isFunction( value ) ) {
633.1269 +			return this.each(function(i) {
633.1270 +				var self = jQuery(this);
633.1271 +				self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
633.1272 +			});
633.1273 +		}
633.1274 +
633.1275 +		return this.each(function() {
633.1276 +			if ( type === "string" ) {
633.1277 +				// toggle individual class names
633.1278 +				var className, i = 0, self = jQuery(this),
633.1279 +					state = stateVal,
633.1280 +					classNames = value.split( rspace );
633.1281 +
633.1282 +				while ( (className = classNames[ i++ ]) ) {
633.1283 +					// check each className given, space seperated list
633.1284 +					state = isBool ? state : !self.hasClass( className );
633.1285 +					self[ state ? "addClass" : "removeClass" ]( className );
633.1286 +				}
633.1287 +
633.1288 +			} else if ( type === "undefined" || type === "boolean" ) {
633.1289 +				if ( this.className ) {
633.1290 +					// store className if set
633.1291 +					jQuery.data( this, "__className__", this.className );
633.1292 +				}
633.1293 +
633.1294 +				// toggle whole className
633.1295 +				this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
633.1296 +			}
633.1297 +		});
633.1298 +	},
633.1299 +
633.1300 +	hasClass: function( selector ) {
633.1301 +		var className = " " + selector + " ";
633.1302 +		for ( var i = 0, l = this.length; i < l; i++ ) {
633.1303 +			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
633.1304 +				return true;
633.1305 +			}
633.1306 +		}
633.1307 +
633.1308 +		return false;
633.1309 +	},
633.1310 +
633.1311 +	val: function( value ) {
633.1312 +		if ( value === undefined ) {
633.1313 +			var elem = this[0];
633.1314 +
633.1315 +			if ( elem ) {
633.1316 +				if ( jQuery.nodeName( elem, "option" ) ) {
633.1317 +					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
633.1318 +				}
633.1319 +
633.1320 +				// We need to handle select boxes special
633.1321 +				if ( jQuery.nodeName( elem, "select" ) ) {
633.1322 +					var index = elem.selectedIndex,
633.1323 +						values = [],
633.1324 +						options = elem.options,
633.1325 +						one = elem.type === "select-one";
633.1326 +
633.1327 +					// Nothing was selected
633.1328 +					if ( index < 0 ) {
633.1329 +						return null;
633.1330 +					}
633.1331 +
633.1332 +					// Loop through all the selected options
633.1333 +					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
633.1334 +						var option = options[ i ];
633.1335 +
633.1336 +						if ( option.selected ) {
633.1337 +							// Get the specifc value for the option
633.1338 +							value = jQuery(option).val();
633.1339 +
633.1340 +							// We don't need an array for one selects
633.1341 +							if ( one ) {
633.1342 +								return value;
633.1343 +							}
633.1344 +
633.1345 +							// Multi-Selects return an array
633.1346 +							values.push( value );
633.1347 +						}
633.1348 +					}
633.1349 +
633.1350 +					return values;
633.1351 +				}
633.1352 +
633.1353 +				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
633.1354 +				if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
633.1355 +					return elem.getAttribute("value") === null ? "on" : elem.value;
633.1356 +				}
633.1357 +				
633.1358 +
633.1359 +				// Everything else, we just grab the value
633.1360 +				return (elem.value || "").replace(rreturn, "");
633.1361 +
633.1362 +			}
633.1363 +
633.1364 +			return undefined;
633.1365 +		}
633.1366 +
633.1367 +		var isFunction = jQuery.isFunction(value);
633.1368 +
633.1369 +		return this.each(function(i) {
633.1370 +			var self = jQuery(this), val = value;
633.1371 +
633.1372 +			if ( this.nodeType !== 1 ) {
633.1373 +				return;
633.1374 +			}
633.1375 +
633.1376 +			if ( isFunction ) {
633.1377 +				val = value.call(this, i, self.val());
633.1378 +			}
633.1379 +
633.1380 +			// Typecast each time if the value is a Function and the appended
633.1381 +			// value is therefore different each time.
633.1382 +			if ( typeof val === "number" ) {
633.1383 +				val += "";
633.1384 +			}
633.1385 +
633.1386 +			if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
633.1387 +				this.checked = jQuery.inArray( self.val(), val ) >= 0;
633.1388 +
633.1389 +			} else if ( jQuery.nodeName( this, "select" ) ) {
633.1390 +				var values = jQuery.makeArray(val);
633.1391 +
633.1392 +				jQuery( "option", this ).each(function() {
633.1393 +					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
633.1394 +				});
633.1395 +
633.1396 +				if ( !values.length ) {
633.1397 +					this.selectedIndex = -1;
633.1398 +				}
633.1399 +
633.1400 +			} else {
633.1401 +				this.value = val;
633.1402 +			}
633.1403 +		});
633.1404 +	}
633.1405 +});
633.1406 +
633.1407 +jQuery.extend({
633.1408 +	attrFn: {
633.1409 +		val: true,
633.1410 +		css: true,
633.1411 +		html: true,
633.1412 +		text: true,
633.1413 +		data: true,
633.1414 +		width: true,
633.1415 +		height: true,
633.1416 +		offset: true
633.1417 +	},
633.1418 +		
633.1419 +	attr: function( elem, name, value, pass ) {
633.1420 +		// don't set attributes on text and comment nodes
633.1421 +		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
633.1422 +			return undefined;
633.1423 +		}
633.1424 +
633.1425 +		if ( pass && name in jQuery.attrFn ) {
633.1426 +			return jQuery(elem)[name](value);
633.1427 +		}
633.1428 +
633.1429 +		var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
633.1430 +			// Whether we are setting (or getting)
633.1431 +			set = value !== undefined;
633.1432 +
633.1433 +		// Try to normalize/fix the name
633.1434 +		name = notxml && jQuery.props[ name ] || name;
633.1435 +
633.1436 +		// Only do all the following if this is a node (faster for style)
633.1437 +		if ( elem.nodeType === 1 ) {
633.1438 +			// These attributes require special treatment
633.1439 +			var special = rspecialurl.test( name );
633.1440 +
633.1441 +			// Safari mis-reports the default selected property of an option
633.1442 +			// Accessing the parent's selectedIndex property fixes it
633.1443 +			if ( name === "selected" && !jQuery.support.optSelected ) {
633.1444 +				var parent = elem.parentNode;
633.1445 +				if ( parent ) {
633.1446 +					parent.selectedIndex;
633.1447 +	
633.1448 +					// Make sure that it also works with optgroups, see #5701
633.1449 +					if ( parent.parentNode ) {
633.1450 +						parent.parentNode.selectedIndex;
633.1451 +					}
633.1452 +				}
633.1453 +			}
633.1454 +
633.1455 +			// If applicable, access the attribute via the DOM 0 way
633.1456 +			if ( name in elem && notxml && !special ) {
633.1457 +				if ( set ) {
633.1458 +					// We can't allow the type property to be changed (since it causes problems in IE)
633.1459 +					if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
633.1460 +						throw "type property can't be changed";
633.1461 +					}
633.1462 +
633.1463 +					elem[ name ] = value;
633.1464 +				}
633.1465 +
633.1466 +				// browsers index elements by id/name on forms, give priority to attributes.
633.1467 +				if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
633.1468 +					return elem.getAttributeNode( name ).nodeValue;
633.1469 +				}
633.1470 +
633.1471 +				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
633.1472 +				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
633.1473 +				if ( name === "tabIndex" ) {
633.1474 +					var attributeNode = elem.getAttributeNode( "tabIndex" );
633.1475 +
633.1476 +					return attributeNode && attributeNode.specified ?
633.1477 +						attributeNode.value :
633.1478 +						rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
633.1479 +							0 :
633.1480 +							undefined;
633.1481 +				}
633.1482 +
633.1483 +				return elem[ name ];
633.1484 +			}
633.1485 +
633.1486 +			if ( !jQuery.support.style && notxml && name === "style" ) {
633.1487 +				if ( set ) {
633.1488 +					elem.style.cssText = "" + value;
633.1489 +				}
633.1490 +
633.1491 +				return elem.style.cssText;
633.1492 +			}
633.1493 +
633.1494 +			if ( set ) {
633.1495 +				// convert the value to a string (all browsers do this but IE) see #1070
633.1496 +				elem.setAttribute( name, "" + value );
633.1497 +			}
633.1498 +
633.1499 +			var attr = !jQuery.support.hrefNormalized && notxml && special ?
633.1500 +					// Some attributes require a special call on IE
633.1501 +					elem.getAttribute( name, 2 ) :
633.1502 +					elem.getAttribute( name );
633.1503 +
633.1504 +			// Non-existent attributes return null, we normalize to undefined
633.1505 +			return attr === null ? undefined : attr;
633.1506 +		}
633.1507 +
633.1508 +		// elem is actually elem.style ... set the style
633.1509 +		// Using attr for specific style information is now deprecated. Use style insead.
633.1510 +		return jQuery.style( elem, name, value );
633.1511 +	}
633.1512 +});
633.1513 +var fcleanup = function( nm ) {
633.1514 +	return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
633.1515 +		return "\\" + ch;
633.1516 +	});
633.1517 +};
633.1518 +
633.1519 +/*
633.1520 + * A number of helper functions used for managing events.
633.1521 + * Many of the ideas behind this code originated from
633.1522 + * Dean Edwards' addEvent library.
633.1523 + */
633.1524 +jQuery.event = {
633.1525 +
633.1526 +	// Bind an event to an element
633.1527 +	// Original by Dean Edwards
633.1528 +	add: function( elem, types, handler, data ) {
633.1529 +		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
633.1530 +			return;
633.1531 +		}
633.1532 +
633.1533 +		// For whatever reason, IE has trouble passing the window object
633.1534 +		// around, causing it to be cloned in the process
633.1535 +		if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
633.1536 +			elem = window;
633.1537 +		}
633.1538 +
633.1539 +		// Make sure that the function being executed has a unique ID
633.1540 +		if ( !handler.guid ) {
633.1541 +			handler.guid = jQuery.guid++;
633.1542 +		}
633.1543 +
633.1544 +		// if data is passed, bind to handler
633.1545 +		if ( data !== undefined ) {
633.1546 +			// Create temporary function pointer to original handler
633.1547 +			var fn = handler;
633.1548 +
633.1549 +			// Create unique handler function, wrapped around original handler
633.1550 +			handler = jQuery.proxy( fn );
633.1551 +
633.1552 +			// Store data in unique handler
633.1553 +			handler.data = data;
633.1554 +		}
633.1555 +
633.1556 +		// Init the element's event structure
633.1557 +		var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ),
633.1558 +			handle = jQuery.data( elem, "handle" ), eventHandle;
633.1559 +
633.1560 +		if ( !handle ) {
633.1561 +			eventHandle = function() {
633.1562 +				// Handle the second event of a trigger and when
633.1563 +				// an event is called after a page has unloaded
633.1564 +				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
633.1565 +					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
633.1566 +					undefined;
633.1567 +			};
633.1568 +
633.1569 +			handle = jQuery.data( elem, "handle", eventHandle );
633.1570 +		}
633.1571 +
633.1572 +		// If no handle is found then we must be trying to bind to one of the
633.1573 +		// banned noData elements
633.1574 +		if ( !handle ) {
633.1575 +			return;
633.1576 +		}
633.1577 +
633.1578 +		// Add elem as a property of the handle function
633.1579 +		// This is to prevent a memory leak with non-native
633.1580 +		// event in IE.
633.1581 +		handle.elem = elem;
633.1582 +
633.1583 +		// Handle multiple events separated by a space
633.1584 +		// jQuery(...).bind("mouseover mouseout", fn);
633.1585 +		types = types.split( /\s+/ );
633.1586 +		var type, i=0;
633.1587 +		while ( (type = types[ i++ ]) ) {
633.1588 +			// Namespaced event handlers
633.1589 +			var namespaces = type.split(".");
633.1590 +			type = namespaces.shift();
633.1591 +			handler.type = namespaces.slice(0).sort().join(".");
633.1592 +
633.1593 +			// Get the current list of functions bound to this event
633.1594 +			var handlers = events[ type ],
633.1595 +				special = this.special[ type ] || {};
633.1596 +
633.1597 +			
633.1598 +
633.1599 +			// Init the event handler queue
633.1600 +			if ( !handlers ) {
633.1601 +				handlers = events[ type ] = {};
633.1602 +
633.1603 +				// Check for a special event handler
633.1604 +				// Only use addEventListener/attachEvent if the special
633.1605 +				// events handler returns false
633.1606 +				if ( !special.setup || special.setup.call( elem, data, namespaces, handler) === false ) {
633.1607 +					// Bind the global event handler to the element
633.1608 +					if ( elem.addEventListener ) {
633.1609 +						elem.addEventListener( type, handle, false );
633.1610 +					} else if ( elem.attachEvent ) {
633.1611 +						elem.attachEvent( "on" + type, handle );
633.1612 +					}
633.1613 +				}
633.1614 +			}
633.1615 +			
633.1616 +			if ( special.add ) { 
633.1617 +				var modifiedHandler = special.add.call( elem, handler, data, namespaces, handlers ); 
633.1618 +				if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) { 
633.1619 +					modifiedHandler.guid = modifiedHandler.guid || handler.guid; 
633.1620 +					handler = modifiedHandler; 
633.1621 +				} 
633.1622 +			} 
633.1623 +			
633.1624 +			// Add the function to the element's handler list
633.1625 +			handlers[ handler.guid ] = handler;
633.1626 +
633.1627 +			// Keep track of which events have been used, for global triggering
633.1628 +			this.global[ type ] = true;
633.1629 +		}
633.1630 +
633.1631 +		// Nullify elem to prevent memory leaks in IE
633.1632 +		elem = null;
633.1633 +	},
633.1634 +
633.1635 +	global: {},
633.1636 +
633.1637 +	// Detach an event or set of events from an element
633.1638 +	remove: function( elem, types, handler ) {
633.1639 +		// don't do events on text and comment nodes
633.1640 +		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
633.1641 +			return;
633.1642 +		}
633.1643 +
633.1644 +		var events = jQuery.data( elem, "events" ), ret, type, fn;
633.1645 +
633.1646 +		if ( events ) {
633.1647 +			// Unbind all events for the element
633.1648 +			if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) {
633.1649 +				for ( type in events ) {
633.1650 +					this.remove( elem, type + (types || "") );
633.1651 +				}
633.1652 +			} else {
633.1653 +				// types is actually an event object here
633.1654 +				if ( types.type ) {
633.1655 +					handler = types.handler;
633.1656 +					types = types.type;
633.1657 +				}
633.1658 +
633.1659 +				// Handle multiple events separated by a space
633.1660 +				// jQuery(...).unbind("mouseover mouseout", fn);
633.1661 +				types = types.split(/\s+/);
633.1662 +				var i = 0;
633.1663 +				while ( (type = types[ i++ ]) ) {
633.1664 +					// Namespaced event handlers
633.1665 +					var namespaces = type.split(".");
633.1666 +					type = namespaces.shift();
633.1667 +					var all = !namespaces.length,
633.1668 +						cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ),
633.1669 +						namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"),
633.1670 +						special = this.special[ type ] || {};
633.1671 +
633.1672 +					if ( events[ type ] ) {
633.1673 +						// remove the given handler for the given type
633.1674 +						if ( handler ) {
633.1675 +							fn = events[ type ][ handler.guid ];
633.1676 +							delete events[ type ][ handler.guid ];
633.1677 +
633.1678 +						// remove all handlers for the given type
633.1679 +						} else {
633.1680 +							for ( var handle in events[ type ] ) {
633.1681 +								// Handle the removal of namespaced events
633.1682 +								if ( all || namespace.test( events[ type ][ handle ].type ) ) {
633.1683 +									delete events[ type ][ handle ];
633.1684 +								}
633.1685 +							}
633.1686 +						}
633.1687 +
633.1688 +						if ( special.remove ) {
633.1689 +							special.remove.call( elem, namespaces, fn);
633.1690 +						}
633.1691 +
633.1692 +						// remove generic event handler if no more handlers exist
633.1693 +						for ( ret in events[ type ] ) {
633.1694 +							break;
633.1695 +						}
633.1696 +						if ( !ret ) {
633.1697 +							if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
633.1698 +								if ( elem.removeEventListener ) {
633.1699 +									elem.removeEventListener( type, jQuery.data( elem, "handle" ), false );
633.1700 +								} else if ( elem.detachEvent ) {
633.1701 +									elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) );
633.1702 +								}
633.1703 +							}
633.1704 +							ret = null;
633.1705 +							delete events[ type ];
633.1706 +						}
633.1707 +					}
633.1708 +				}
633.1709 +			}
633.1710 +
633.1711 +			// Remove the expando if it's no longer used
633.1712 +			for ( ret in events ) {
633.1713 +				break;
633.1714 +			}
633.1715 +			if ( !ret ) {
633.1716 +				var handle = jQuery.data( elem, "handle" );
633.1717 +				if ( handle ) {
633.1718 +					handle.elem = null;
633.1719 +				}
633.1720 +				jQuery.removeData( elem, "events" );
633.1721 +				jQuery.removeData( elem, "handle" );
633.1722 +			}
633.1723 +		}
633.1724 +	},
633.1725 +
633.1726 +	// bubbling is internal
633.1727 +	trigger: function( event, data, elem /*, bubbling */ ) {
633.1728 +		// Event object or event type
633.1729 +		var type = event.type || event,
633.1730 +			bubbling = arguments[3];
633.1731 +
633.1732 +		if ( !bubbling ) {
633.1733 +			event = typeof event === "object" ?
633.1734 +				// jQuery.Event object
633.1735 +				event[expando] ? event :
633.1736 +				// Object literal
633.1737 +				jQuery.extend( jQuery.Event(type), event ) :
633.1738 +				// Just the event type (string)
633.1739 +				jQuery.Event(type);
633.1740 +
633.1741 +			if ( type.indexOf("!") >= 0 ) {
633.1742 +				event.type = type = type.slice(0, -1);
633.1743 +				event.exclusive = true;
633.1744 +			}
633.1745 +
633.1746 +			// Handle a global trigger
633.1747 +			if ( !elem ) {
633.1748 +				// Don't bubble custom events when global (to avoid too much overhead)
633.1749 +				event.stopPropagation();
633.1750 +
633.1751 +				// Only trigger if we've ever bound an event for it
633.1752 +				if ( this.global[ type ] ) {
633.1753 +					jQuery.each( jQuery.cache, function() {
633.1754 +						if ( this.events && this.events[type] ) {
633.1755 +							jQuery.event.trigger( event, data, this.handle.elem );
633.1756 +						}
633.1757 +					});
633.1758 +				}
633.1759 +			}
633.1760 +
633.1761 +			// Handle triggering a single element
633.1762 +
633.1763 +			// don't do events on text and comment nodes
633.1764 +			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
633.1765 +				return undefined;
633.1766 +			}
633.1767 +
633.1768 +			// Clean up in case it is reused
633.1769 +			event.result = undefined;
633.1770 +			event.target = elem;
633.1771 +
633.1772 +			// Clone the incoming data, if any
633.1773 +			data = jQuery.makeArray( data );
633.1774 +			data.unshift( event );
633.1775 +		}
633.1776 +
633.1777 +		event.currentTarget = elem;
633.1778 +
633.1779 +		// Trigger the event, it is assumed that "handle" is a function
633.1780 +		var handle = jQuery.data( elem, "handle" );
633.1781 +		if ( handle ) {
633.1782 +			handle.apply( elem, data );
633.1783 +		}
633.1784 +
633.1785 +		var nativeFn, nativeHandler;
633.1786 +		try {
633.1787 +			if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
633.1788 +				nativeFn = elem[ type ];
633.1789 +				nativeHandler = elem[ "on" + type ];
633.1790 +			}
633.1791 +		// prevent IE from throwing an error for some elements with some event types, see #3533
633.1792 +		} catch (e) {}
633.1793 +
633.1794 +		var isClick = jQuery.nodeName(elem, "a") && type === "click";
633.1795 +
633.1796 +		// Trigger the native events (except for clicks on links)
633.1797 +		if ( !bubbling && nativeFn && !event.isDefaultPrevented() && !isClick ) {
633.1798 +			this.triggered = true;
633.1799 +			try {
633.1800 +				elem[ type ]();
633.1801 +			// prevent IE from throwing an error for some hidden elements
633.1802 +			} catch (e) {}
633.1803 +
633.1804 +		// Handle triggering native .onfoo handlers
633.1805 +		} else if ( nativeHandler && elem[ "on" + type ].apply( elem, data ) === false ) {
633.1806 +			event.result = false;
633.1807 +		}
633.1808 +
633.1809 +		this.triggered = false;
633.1810 +
633.1811 +		if ( !event.isPropagationStopped() ) {
633.1812 +			var parent = elem.parentNode || elem.ownerDocument;
633.1813 +			if ( parent ) {
633.1814 +				jQuery.event.trigger( event, data, parent, true );
633.1815 +			}
633.1816 +		}
633.1817 +	},
633.1818 +
633.1819 +	handle: function( event ) {
633.1820 +		// returned undefined or false
633.1821 +		var all, handlers;
633.1822 +
633.1823 +		event = arguments[0] = jQuery.event.fix( event || window.event );
633.1824 +		event.currentTarget = this;
633.1825 +
633.1826 +		// Namespaced event handlers
633.1827 +		var namespaces = event.type.split(".");
633.1828 +		event.type = namespaces.shift();
633.1829 +
633.1830 +		// Cache this now, all = true means, any handler
633.1831 +		all = !namespaces.length && !event.exclusive;
633.1832 +
633.1833 +		var namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
633.1834 +
633.1835 +		handlers = ( jQuery.data(this, "events") || {} )[ event.type ];
633.1836 +
633.1837 +		for ( var j in handlers ) {
633.1838 +			var handler = handlers[ j ];
633.1839 +
633.1840 +			// Filter the functions by class
633.1841 +			if ( all || namespace.test(handler.type) ) {
633.1842 +				// Pass in a reference to the handler function itself
633.1843 +				// So that we can later remove it
633.1844 +				event.handler = handler;
633.1845 +				event.data = handler.data;
633.1846 +
633.1847 +				var ret = handler.apply( this, arguments );
633.1848 +
633.1849 +				if ( ret !== undefined ) {
633.1850 +					event.result = ret;
633.1851 +					if ( ret === false ) {
633.1852 +						event.preventDefault();
633.1853 +						event.stopPropagation();
633.1854 +					}
633.1855 +				}
633.1856 +
633.1857 +				if ( event.isImmediatePropagationStopped() ) {
633.1858 +					break;
633.1859 +				}
633.1860 +
633.1861 +			}
633.1862 +		}
633.1863 +
633.1864 +		return event.result;
633.1865 +	},
633.1866 +
633.1867 +	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
633.1868 +
633.1869 +	fix: function( event ) {
633.1870 +		if ( event[ expando ] ) {
633.1871 +			return event;
633.1872 +		}
633.1873 +
633.1874 +		// store a copy of the original event object
633.1875 +		// and "clone" to set read-only properties
633.1876 +		var originalEvent = event;
633.1877 +		event = jQuery.Event( originalEvent );
633.1878 +
633.1879 +		for ( var i = this.props.length, prop; i; ) {
633.1880 +			prop = this.props[ --i ];
633.1881 +			event[ prop ] = originalEvent[ prop ];
633.1882 +		}
633.1883 +
633.1884 +		// Fix target property, if necessary
633.1885 +		if ( !event.target ) {
633.1886 +			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
633.1887 +		}
633.1888 +
633.1889 +		// check if target is a textnode (safari)
633.1890 +		if ( event.target.nodeType === 3 ) {
633.1891 +			event.target = event.target.parentNode;
633.1892 +		}
633.1893 +
633.1894 +		// Add relatedTarget, if necessary
633.1895 +		if ( !event.relatedTarget && event.fromElement ) {
633.1896 +			event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
633.1897 +		}
633.1898 +
633.1899 +		// Calculate pageX/Y if missing and clientX/Y available
633.1900 +		if ( event.pageX == null && event.clientX != null ) {
633.1901 +			var doc = document.documentElement, body = document.body;
633.1902 +			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
633.1903 +			event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
633.1904 +		}
633.1905 +
633.1906 +		// Add which for key events
633.1907 +		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
633.1908 +			event.which = event.charCode || event.keyCode;
633.1909 +		}
633.1910 +
633.1911 +		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
633.1912 +		if ( !event.metaKey && event.ctrlKey ) {
633.1913 +			event.metaKey = event.ctrlKey;
633.1914 +		}
633.1915 +
633.1916 +		// Add which for click: 1 === left; 2 === middle; 3 === right
633.1917 +		// Note: button is not normalized, so don't use it
633.1918 +		if ( !event.which && event.button !== undefined ) {
633.1919 +			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
633.1920 +		}
633.1921 +
633.1922 +		return event;
633.1923 +	},
633.1924 +
633.1925 +	// Deprecated, use jQuery.guid instead
633.1926 +	guid: 1E8,
633.1927 +
633.1928 +	// Deprecated, use jQuery.proxy instead
633.1929 +	proxy: jQuery.proxy,
633.1930 +
633.1931 +	special: {
633.1932 +		ready: {
633.1933 +			// Make sure the ready event is setup
633.1934 +			setup: jQuery.bindReady,
633.1935 +			teardown: jQuery.noop
633.1936 +		},
633.1937 +
633.1938 +		live: {
633.1939 +			add: function( proxy, data, namespaces, live ) {
633.1940 +				jQuery.extend( proxy, data || {} );
633.1941 +
633.1942 +				proxy.guid += data.selector + data.live; 
633.1943 +				jQuery.event.add( this, data.live, liveHandler, data ); 
633.1944 +				
633.1945 +			},
633.1946 +
633.1947 +			remove: function( namespaces ) {
633.1948 +				if ( namespaces.length ) {
633.1949 +					var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
633.1950 +
633.1951 +					jQuery.each( (jQuery.data(this, "events").live || {}), function() {
633.1952 +						if ( name.test(this.type) ) {
633.1953 +							remove++;
633.1954 +						}
633.1955 +					});
633.1956 +
633.1957 +					if ( remove < 1 ) {
633.1958 +						jQuery.event.remove( this, namespaces[0], liveHandler );
633.1959 +					}
633.1960 +				}
633.1961 +			},
633.1962 +			special: {}
633.1963 +		},
633.1964 +		beforeunload: {
633.1965 +			setup: function( data, namespaces, fn ) {
633.1966 +				// We only want to do this special case on windows
633.1967 +				if ( this.setInterval ) {
633.1968 +					this.onbeforeunload = fn;
633.1969 +				}
633.1970 +
633.1971 +				return false;
633.1972 +			},
633.1973 +			teardown: function( namespaces, fn ) {
633.1974 +				if ( this.onbeforeunload === fn ) {
633.1975 +					this.onbeforeunload = null;
633.1976 +				}
633.1977 +			}
633.1978 +		}
633.1979 +	}
633.1980 +};
633.1981 +
633.1982 +jQuery.Event = function( src ) {
633.1983 +	// Allow instantiation without the 'new' keyword
633.1984 +	if ( !this.preventDefault ) {
633.1985 +		return new jQuery.Event( src );
633.1986 +	}
633.1987 +
633.1988 +	// Event object
633.1989 +	if ( src && src.type ) {
633.1990 +		this.originalEvent = src;
633.1991 +		this.type = src.type;
633.1992 +	// Event type
633.1993 +	} else {
633.1994 +		this.type = src;
633.1995 +	}
633.1996 +
633.1997 +	// timeStamp is buggy for some events on Firefox(#3843)
633.1998 +	// So we won't rely on the native value
633.1999 +	this.timeStamp = now();
633.2000 +
633.2001 +	// Mark it as fixed
633.2002 +	this[ expando ] = true;
633.2003 +};
633.2004 +
633.2005 +function returnFalse() {
633.2006 +	return false;
633.2007 +}
633.2008 +function returnTrue() {
633.2009 +	return true;
633.2010 +}
633.2011 +
633.2012 +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
633.2013 +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
633.2014 +jQuery.Event.prototype = {
633.2015 +	preventDefault: function() {
633.2016 +		this.isDefaultPrevented = returnTrue;
633.2017 +
633.2018 +		var e = this.originalEvent;
633.2019 +		if ( !e ) {
633.2020 +			return;
633.2021 +		}
633.2022 +		
633.2023 +		// if preventDefault exists run it on the original event
633.2024 +		if ( e.preventDefault ) {
633.2025 +			e.preventDefault();
633.2026 +		}
633.2027 +		// otherwise set the returnValue property of the original event to false (IE)
633.2028 +		e.returnValue = false;
633.2029 +	},
633.2030 +	stopPropagation: function() {
633.2031 +		this.isPropagationStopped = returnTrue;
633.2032 +
633.2033 +		var e = this.originalEvent;
633.2034 +		if ( !e ) {
633.2035 +			return;
633.2036 +		}
633.2037 +		// if stopPropagation exists run it on the original event
633.2038 +		if ( e.stopPropagation ) {
633.2039 +			e.stopPropagation();
633.2040 +		}
633.2041 +		// otherwise set the cancelBubble property of the original event to true (IE)
633.2042 +		e.cancelBubble = true;
633.2043 +	},
633.2044 +	stopImmediatePropagation: function() {
633.2045 +		this.isImmediatePropagationStopped = returnTrue;
633.2046 +		this.stopPropagation();
633.2047 +	},
633.2048 +	isDefaultPrevented: returnFalse,
633.2049 +	isPropagationStopped: returnFalse,
633.2050 +	isImmediatePropagationStopped: returnFalse
633.2051 +};
633.2052 +
633.2053 +// Checks if an event happened on an element within another element
633.2054 +// Used in jQuery.event.special.mouseenter and mouseleave handlers
633.2055 +var withinElement = function( event ) {
633.2056 +	// Check if mouse(over|out) are still within the same parent element
633.2057 +	var parent = event.relatedTarget;
633.2058 +
633.2059 +	// Traverse up the tree
633.2060 +	while ( parent && parent !== this ) {
633.2061 +		// Firefox sometimes assigns relatedTarget a XUL element
633.2062 +		// which we cannot access the parentNode property of
633.2063 +		try {
633.2064 +			parent = parent.parentNode;
633.2065 +
633.2066 +		// assuming we've left the element since we most likely mousedover a xul element
633.2067 +		} catch(e) {
633.2068 +			break;
633.2069 +		}
633.2070 +	}
633.2071 +
633.2072 +	if ( parent !== this ) {
633.2073 +		// set the correct event type
633.2074 +		event.type = event.data;
633.2075 +
633.2076 +		// handle event if we actually just moused on to a non sub-element
633.2077 +		jQuery.event.handle.apply( this, arguments );
633.2078 +	}
633.2079 +
633.2080 +},
633.2081 +
633.2082 +// In case of event delegation, we only need to rename the event.type,
633.2083 +// liveHandler will take care of the rest.
633.2084 +delegate = function( event ) {
633.2085 +	event.type = event.data;
633.2086 +	jQuery.event.handle.apply( this, arguments );
633.2087 +};
633.2088 +
633.2089 +// Create mouseenter and mouseleave events
633.2090 +jQuery.each({
633.2091 +	mouseenter: "mouseover",
633.2092 +	mouseleave: "mouseout"
633.2093 +}, function( orig, fix ) {
633.2094 +	jQuery.event.special[ orig ] = {
633.2095 +		setup: function( data ) {
633.2096 +			jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
633.2097 +		},
633.2098 +		teardown: function( data ) {
633.2099 +			jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
633.2100 +		}
633.2101 +	};
633.2102 +});
633.2103 +
633.2104 +// submit delegation
633.2105 +if ( !jQuery.support.submitBubbles ) {
633.2106 +
633.2107 +jQuery.event.special.submit = {
633.2108 +	setup: function( data, namespaces, fn ) {
633.2109 +		if ( this.nodeName.toLowerCase() !== "form" ) {
633.2110 +			jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) {
633.2111 +				var elem = e.target, type = elem.type;
633.2112 +
633.2113 +				if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
633.2114 +					return trigger( "submit", this, arguments );
633.2115 +				}
633.2116 +			});
633.2117 +	 
633.2118 +			jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) {
633.2119 +				var elem = e.target, type = elem.type;
633.2120 +
633.2121 +				if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
633.2122 +					return trigger( "submit", this, arguments );
633.2123 +				}
633.2124 +			});
633.2125 +
633.2126 +		} else {
633.2127 +			return false;
633.2128 +		}
633.2129 +	},
633.2130 +
633.2131 +	remove: function( namespaces, fn ) {
633.2132 +		jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") );
633.2133 +		jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") );
633.2134 +	}
633.2135 +};
633.2136 +
633.2137 +}
633.2138 +
633.2139 +// change delegation, happens here so we have bind.
633.2140 +if ( !jQuery.support.changeBubbles ) {
633.2141 +
633.2142 +var formElems = /textarea|input|select/i;
633.2143 +
633.2144 +function getVal( elem ) {
633.2145 +	var type = elem.type, val = elem.value;
633.2146 +
633.2147 +	if ( type === "radio" || type === "checkbox" ) {
633.2148 +		val = elem.checked;
633.2149 +
633.2150 +	} else if ( type === "select-multiple" ) {
633.2151 +		val = elem.selectedIndex > -1 ?
633.2152 +			jQuery.map( elem.options, function( elem ) {
633.2153 +				return elem.selected;
633.2154 +			}).join("-") :
633.2155 +			"";
633.2156 +
633.2157 +	} else if ( elem.nodeName.toLowerCase() === "select" ) {
633.2158 +		val = elem.selectedIndex;
633.2159 +	}
633.2160 +
633.2161 +	return val;
633.2162 +}
633.2163 +
633.2164 +function testChange( e ) {
633.2165 +		var elem = e.target, data, val;
633.2166 +
633.2167 +		if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
633.2168 +			return;
633.2169 +		}
633.2170 +
633.2171 +		data = jQuery.data( elem, "_change_data" );
633.2172 +		val = getVal(elem);
633.2173 +
633.2174 +		if ( val === data ) {
633.2175 +			return;
633.2176 +		}
633.2177 +
633.2178 +		// the current data will be also retrieved by beforeactivate
633.2179 +		if ( e.type !== "focusout" || elem.type !== "radio" ) {
633.2180 +			jQuery.data( elem, "_change_data", val );
633.2181 +		}
633.2182 +
633.2183 +		if ( elem.type !== "select" && (data != null || val) ) {
633.2184 +			e.type = "change";
633.2185 +			return jQuery.event.trigger( e, arguments[1], this );
633.2186 +		}
633.2187 +}
633.2188 +
633.2189 +jQuery.event.special.change = {
633.2190 +	filters: {
633.2191 +		focusout: testChange, 
633.2192 +
633.2193 +		click: function( e ) {
633.2194 +			var elem = e.target, type = elem.type;
633.2195 +
633.2196 +			if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
633.2197 +				return testChange.call( this, e );
633.2198 +			}
633.2199 +		},
633.2200 +
633.2201 +		// Change has to be called before submit
633.2202 +		// Keydown will be called before keypress, which is used in submit-event delegation
633.2203 +		keydown: function( e ) {
633.2204 +			var elem = e.target, type = elem.type;
633.2205 +
633.2206 +			if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
633.2207 +				(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
633.2208 +				type === "select-multiple" ) {
633.2209 +				return testChange.call( this, e );
633.2210 +			}
633.2211 +		},
633.2212 +
633.2213 +		// Beforeactivate happens also before the previous element is blurred
633.2214 +		// with this event you can't trigger a change event, but you can store
633.2215 +		// information/focus[in] is not needed anymore
633.2216 +		beforeactivate: function( e ) {
633.2217 +			var elem = e.target;
633.2218 +
633.2219 +			if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) {
633.2220 +				jQuery.data( elem, "_change_data", getVal(elem) );
633.2221 +			}
633.2222 +		}
633.2223 +	},
633.2224 +	setup: function( data, namespaces, fn ) {
633.2225 +		for ( var type in changeFilters ) {
633.2226 +			jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
633.2227 +		}
633.2228 +
633.2229 +		return formElems.test( this.nodeName );
633.2230 +	},
633.2231 +	remove: function( namespaces, fn ) {
633.2232 +		for ( var type in changeFilters ) {
633.2233 +			jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
633.2234 +		}
633.2235 +
633.2236 +		return formElems.test( this.nodeName );
633.2237 +	}
633.2238 +};
633.2239 +
633.2240 +var changeFilters = jQuery.event.special.change.filters;
633.2241 +
633.2242 +}
633.2243 +
633.2244 +function trigger( type, elem, args ) {
633.2245 +	args[0].type = type;
633.2246 +	return jQuery.event.handle.apply( elem, args );
633.2247 +}
633.2248 +
633.2249 +// Create "bubbling" focus and blur events
633.2250 +if ( document.addEventListener ) {
633.2251 +	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
633.2252 +		jQuery.event.special[ fix ] = {
633.2253 +			setup: function() {
633.2254 +				this.addEventListener( orig, handler, true );
633.2255 +			}, 
633.2256 +			teardown: function() { 
633.2257 +				this.removeEventListener( orig, handler, true );
633.2258 +			}
633.2259 +		};
633.2260 +
633.2261 +		function handler( e ) { 
633.2262 +			e = jQuery.event.fix( e );
633.2263 +			e.type = fix;
633.2264 +			return jQuery.event.handle.call( this, e );
633.2265 +		}
633.2266 +	});
633.2267 +}
633.2268 +
633.2269 +jQuery.each(["bind", "one"], function( i, name ) {
633.2270 +	jQuery.fn[ name ] = function( type, data, fn ) {
633.2271 +		// Handle object literals
633.2272 +		if ( typeof type === "object" ) {
633.2273 +			for ( var key in type ) {
633.2274 +				this[ name ](key, data, type[key], fn);
633.2275 +			}
633.2276 +			return this;
633.2277 +		}
633.2278 +		
633.2279 +		if ( jQuery.isFunction( data ) ) {
633.2280 +			thisObject = fn;
633.2281 +			fn = data;
633.2282 +			data = undefined;
633.2283 +		}
633.2284 +
633.2285 +		var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
633.2286 +			jQuery( this ).unbind( event, handler );
633.2287 +			return fn.apply( this, arguments );
633.2288 +		}) : fn;
633.2289 +
633.2290 +		return type === "unload" && name !== "one" ?
633.2291 +			this.one( type, data, fn, thisObject ) :
633.2292 +			this.each(function() {
633.2293 +				jQuery.event.add( this, type, handler, data );
633.2294 +			});
633.2295 +	};
633.2296 +});
633.2297 +
633.2298 +jQuery.fn.extend({
633.2299 +	unbind: function( type, fn ) {
633.2300 +		// Handle object literals
633.2301 +		if ( typeof type === "object" && !type.preventDefault ) {
633.2302 +			for ( var key in type ) {
633.2303 +				this.unbind(key, type[key]);
633.2304 +			}
633.2305 +			return this;
633.2306 +		}
633.2307 +
633.2308 +		return this.each(function() {
633.2309 +			jQuery.event.remove( this, type, fn );
633.2310 +		});
633.2311 +	},
633.2312 +	trigger: function( type, data ) {
633.2313 +		return this.each(function() {
633.2314 +			jQuery.event.trigger( type, data, this );
633.2315 +		});
633.2316 +	},
633.2317 +
633.2318 +	triggerHandler: function( type, data ) {
633.2319 +		if ( this[0] ) {
633.2320 +			var event = jQuery.Event( type );
633.2321 +			event.preventDefault();
633.2322 +			event.stopPropagation();
633.2323 +			jQuery.event.trigger( event, data, this[0] );
633.2324 +			return event.result;
633.2325 +		}
633.2326 +	},
633.2327 +
633.2328 +	toggle: function( fn ) {
633.2329 +		// Save reference to arguments for access in closure
633.2330 +		var args = arguments, i = 1;
633.2331 +
633.2332 +		// link all the functions, so any of them can unbind this click handler
633.2333 +		while ( i < args.length ) {
633.2334 +			jQuery.proxy( fn, args[ i++ ] );
633.2335 +		}
633.2336 +
633.2337 +		return this.click( jQuery.proxy( fn, function( event ) {
633.2338 +			// Figure out which function to execute
633.2339 +			var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
633.2340 +			jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
633.2341 +
633.2342 +			// Make sure that clicks stop
633.2343 +			event.preventDefault();
633.2344 +
633.2345 +			// and execute the function
633.2346 +			return args[ lastToggle ].apply( this, arguments ) || false;
633.2347 +		}));
633.2348 +	},
633.2349 +
633.2350 +	hover: function( fnOver, fnOut ) {
633.2351 +		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
633.2352 +	},
633.2353 +
633.2354 +	live: function( type, data, fn ) {
633.2355 +		if ( jQuery.isFunction( data ) ) {
633.2356 +			fn = data;
633.2357 +			data = undefined;
633.2358 +		}
633.2359 +
633.2360 +		jQuery( this.context ).bind( liveConvert( type, this.selector ), {
633.2361 +			data: data, selector: this.selector, live: type
633.2362 +		}, fn );
633.2363 +
633.2364 +		return this;
633.2365 +	},
633.2366 +
633.2367 +	die: function( type, fn ) {
633.2368 +		jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
633.2369 +		return this;
633.2370 +	}
633.2371 +});
633.2372 +
633.2373 +function liveHandler( event ) {
633.2374 +	var stop = true, elems = [], selectors = [], args = arguments,
633.2375 +		related, match, fn, elem, j, i, data,
633.2376 +		live = jQuery.extend({}, jQuery.data( this, "events" ).live);
633.2377 +
633.2378 +	for ( j in live ) {
633.2379 +		fn = live[j];
633.2380 +		if ( fn.live === event.type ||
633.2381 +				fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) {
633.2382 +
633.2383 +			data = fn.data;
633.2384 +			if ( !(data.beforeFilter && data.beforeFilter[event.type] && 
633.2385 +					!data.beforeFilter[event.type](event)) ) {
633.2386 +				selectors.push( fn.selector );
633.2387 +			}
633.2388 +		} else {
633.2389 +			delete live[j];
633.2390 +		}
633.2391 +	}
633.2392 +
633.2393 +	match = jQuery( event.target ).closest( selectors, event.currentTarget );
633.2394 +
633.2395 +	for ( i = 0, l = match.length; i < l; i++ ) {
633.2396 +		for ( j in live ) {
633.2397 +			fn = live[j];
633.2398 +			elem = match[i].elem;
633.2399 +			related = null;
633.2400 +
633.2401 +			if ( match[i].selector === fn.selector ) {
633.2402 +				// Those two events require additional checking
633.2403 +				if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) {
633.2404 +					related = jQuery( event.relatedTarget ).closest( fn.selector )[0];
633.2405 +				}
633.2406 +
633.2407 +				if ( !related || related !== elem ) {
633.2408 +					elems.push({ elem: elem, fn: fn });
633.2409 +				}
633.2410 +			}
633.2411 +		}
633.2412 +	}
633.2413 +
633.2414 +	for ( i = 0, l = elems.length; i < l; i++ ) {
633.2415 +		match = elems[i];
633.2416 +		event.currentTarget = match.elem;
633.2417 +		event.data = match.fn.data;
633.2418 +		if ( match.fn.apply( match.elem, args ) === false ) {
633.2419 +			stop = false;
633.2420 +			break;
633.2421 +		}
633.2422 +	}
633.2423 +
633.2424 +	return stop;
633.2425 +}
633.2426 +
633.2427 +function liveConvert( type, selector ) {
633.2428 +	return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "&")].join(".");
633.2429 +}
633.2430 +
633.2431 +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
633.2432 +	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
633.2433 +	"change select submit keydown keypress keyup error").split(" "), function( i, name ) {
633.2434 +
633.2435 +	// Handle event binding
633.2436 +	jQuery.fn[ name ] = function( fn ) {
633.2437 +		return fn ? this.bind( name, fn ) : this.trigger( name );
633.2438 +	};
633.2439 +
633.2440 +	if ( jQuery.attrFn ) {
633.2441 +		jQuery.attrFn[ name ] = true;
633.2442 +	}
633.2443 +});
633.2444 +
633.2445 +// Prevent memory leaks in IE
633.2446 +// Window isn't included so as not to unbind existing unload events
633.2447 +// More info:
633.2448 +//  - http://isaacschlueter.com/2006/10/msie-memory-leaks/
633.2449 +if ( window.attachEvent && !window.addEventListener ) {
633.2450 +	window.attachEvent("onunload", function() {
633.2451 +		for ( var id in jQuery.cache ) {
633.2452 +			if ( jQuery.cache[ id ].handle ) {
633.2453 +				// Try/Catch is to handle iframes being unloaded, see #4280
633.2454 +				try {
633.2455 +					jQuery.event.remove( jQuery.cache[ id ].handle.elem );
633.2456 +				} catch(e) {}
633.2457 +			}
633.2458 +		}
633.2459 +	});
633.2460 +}
633.2461 +/*!
633.2462 + * Sizzle CSS Selector Engine - v1.0
633.2463 + *  Copyright 2009, The Dojo Foundation
633.2464 + *  Released under the MIT, BSD, and GPL Licenses.
633.2465 + *  More information: http://sizzlejs.com/
633.2466 + */
633.2467 +(function(){
633.2468 +
633.2469 +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
633.2470 +	done = 0,
633.2471 +	toString = Object.prototype.toString,
633.2472 +	hasDuplicate = false,
633.2473 +	baseHasDuplicate = true;
633.2474 +
633.2475 +// Here we check if the JavaScript engine is using some sort of
633.2476 +// optimization where it does not always call our comparision
633.2477 +// function. If that is the case, discard the hasDuplicate value.
633.2478 +//   Thus far that includes Google Chrome.
633.2479 +[0, 0].sort(function(){
633.2480 +	baseHasDuplicate = false;
633.2481 +	return 0;
633.2482 +});
633.2483 +
633.2484 +var Sizzle = function(selector, context, results, seed) {
633.2485 +	results = results || [];
633.2486 +	var origContext = context = context || document;
633.2487 +
633.2488 +	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
633.2489 +		return [];
633.2490 +	}
633.2491 +	
633.2492 +	if ( !selector || typeof selector !== "string" ) {
633.2493 +		return results;
633.2494 +	}
633.2495 +
633.2496 +	var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
633.2497 +		soFar = selector;
633.2498 +	
633.2499 +	// Reset the position of the chunker regexp (start from head)
633.2500 +	while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
633.2501 +		soFar = m[3];
633.2502 +		
633.2503 +		parts.push( m[1] );
633.2504 +		
633.2505 +		if ( m[2] ) {
633.2506 +			extra = m[3];
633.2507 +			break;
633.2508 +		}
633.2509 +	}
633.2510 +
633.2511 +	if ( parts.length > 1 && origPOS.exec( selector ) ) {
633.2512 +		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
633.2513 +			set = posProcess( parts[0] + parts[1], context );
633.2514 +		} else {
633.2515 +			set = Expr.relative[ parts[0] ] ?
633.2516 +				[ context ] :
633.2517 +				Sizzle( parts.shift(), context );
633.2518 +
633.2519 +			while ( parts.length ) {
633.2520 +				selector = parts.shift();
633.2521 +
633.2522 +				if ( Expr.relative[ selector ] ) {
633.2523 +					selector += parts.shift();
633.2524 +				}
633.2525 +				
633.2526 +				set = posProcess( selector, set );
633.2527 +			}
633.2528 +		}
633.2529 +	} else {
633.2530 +		// Take a shortcut and set the context if the root selector is an ID
633.2531 +		// (but not if it'll be faster if the inner selector is an ID)
633.2532 +		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
633.2533 +				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
633.2534 +			var ret = Sizzle.find( parts.shift(), context, contextXML );
633.2535 +			context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
633.2536 +		}
633.2537 +
633.2538 +		if ( context ) {
633.2539 +			var ret = seed ?
633.2540 +				{ expr: parts.pop(), set: makeArray(seed) } :
633.2541 +				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
633.2542 +			set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
633.2543 +
633.2544 +			if ( parts.length > 0 ) {
633.2545 +				checkSet = makeArray(set);
633.2546 +			} else {
633.2547 +				prune = false;
633.2548 +			}
633.2549 +
633.2550 +			while ( parts.length ) {
633.2551 +				var cur = parts.pop(), pop = cur;
633.2552 +
633.2553 +				if ( !Expr.relative[ cur ] ) {
633.2554 +					cur = "";
633.2555 +				} else {
633.2556 +					pop = parts.pop();
633.2557 +				}
633.2558 +
633.2559 +				if ( pop == null ) {
633.2560 +					pop = context;
633.2561 +				}
633.2562 +
633.2563 +				Expr.relative[ cur ]( checkSet, pop, contextXML );
633.2564 +			}
633.2565 +		} else {
633.2566 +			checkSet = parts = [];
633.2567 +		}
633.2568 +	}
633.2569 +
633.2570 +	if ( !checkSet ) {
633.2571 +		checkSet = set;
633.2572 +	}
633.2573 +
633.2574 +	if ( !checkSet ) {
633.2575 +		throw "Syntax error, unrecognized expression: " + (cur || selector);
633.2576 +	}
633.2577 +
633.2578 +	if ( toString.call(checkSet) === "[object Array]" ) {
633.2579 +		if ( !prune ) {
633.2580 +			results.push.apply( results, checkSet );
633.2581 +		} else if ( context && context.nodeType === 1 ) {
633.2582 +			for ( var i = 0; checkSet[i] != null; i++ ) {
633.2583 +				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
633.2584 +					results.push( set[i] );
633.2585 +				}
633.2586 +			}
633.2587 +		} else {
633.2588 +			for ( var i = 0; checkSet[i] != null; i++ ) {
633.2589 +				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
633.2590 +					results.push( set[i] );
633.2591 +				}
633.2592 +			}
633.2593 +		}
633.2594 +	} else {
633.2595 +		makeArray( checkSet, results );
633.2596 +	}
633.2597 +
633.2598 +	if ( extra ) {
633.2599 +		Sizzle( extra, origContext, results, seed );
633.2600 +		Sizzle.uniqueSort( results );
633.2601 +	}
633.2602 +
633.2603 +	return results;
633.2604 +};
633.2605 +
633.2606 +Sizzle.uniqueSort = function(results){
633.2607 +	if ( sortOrder ) {
633.2608 +		hasDuplicate = baseHasDuplicate;
633.2609 +		results.sort(sortOrder);
633.2610 +
633.2611 +		if ( hasDuplicate ) {
633.2612 +			for ( var i = 1; i < results.length; i++ ) {
633.2613 +				if ( results[i] === results[i-1] ) {
633.2614 +					results.splice(i--, 1);
633.2615 +				}
633.2616 +			}
633.2617 +		}
633.2618 +	}
633.2619 +
633.2620 +	return results;
633.2621 +};
633.2622 +
633.2623 +Sizzle.matches = function(expr, set){
633.2624 +	return Sizzle(expr, null, null, set);
633.2625 +};
633.2626 +
633.2627 +Sizzle.find = function(expr, context, isXML){
633.2628 +	var set, match;
633.2629 +
633.2630 +	if ( !expr ) {
633.2631 +		return [];
633.2632 +	}
633.2633 +
633.2634 +	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
633.2635 +		var type = Expr.order[i], match;
633.2636 +		
633.2637 +		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
633.2638 +			var left = match[1];
633.2639 +			match.splice(1,1);
633.2640 +
633.2641 +			if ( left.substr( left.length - 1 ) !== "\\" ) {
633.2642 +				match[1] = (match[1] || "").replace(/\\/g, "");
633.2643 +				set = Expr.find[ type ]( match, context, isXML );
633.2644 +				if ( set != null ) {
633.2645 +					expr = expr.replace( Expr.match[ type ], "" );
633.2646 +					break;
633.2647 +				}
633.2648 +			}
633.2649 +		}
633.2650 +	}
633.2651 +
633.2652 +	if ( !set ) {
633.2653 +		set = context.getElementsByTagName("*");
633.2654 +	}
633.2655 +
633.2656 +	return {set: set, expr: expr};
633.2657 +};
633.2658 +
633.2659 +Sizzle.filter = function(expr, set, inplace, not){
633.2660 +	var old = expr, result = [], curLoop = set, match, anyFound,
633.2661 +		isXMLFilter = set && set[0] && isXML(set[0]);
633.2662 +
633.2663 +	while ( expr && set.length ) {
633.2664 +		for ( var type in Expr.filter ) {
633.2665 +			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
633.2666 +				var filter = Expr.filter[ type ], found, item, left = match[1];
633.2667 +				anyFound = false;
633.2668 +
633.2669 +				match.splice(1,1);
633.2670 +
633.2671 +				if ( left.substr( left.length - 1 ) === "\\" ) {
633.2672 +					continue;
633.2673 +				}
633.2674 +
633.2675 +				if ( curLoop === result ) {
633.2676 +					result = [];
633.2677 +				}
633.2678 +
633.2679 +				if ( Expr.preFilter[ type ] ) {
633.2680 +					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
633.2681 +
633.2682 +					if ( !match ) {
633.2683 +						anyFound = found = true;
633.2684 +					} else if ( match === true ) {
633.2685 +						continue;
633.2686 +					}
633.2687 +				}
633.2688 +
633.2689 +				if ( match ) {
633.2690 +					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
633.2691 +						if ( item ) {
633.2692 +							found = filter( item, match, i, curLoop );
633.2693 +							var pass = not ^ !!found;
633.2694 +
633.2695 +							if ( inplace && found != null ) {
633.2696 +								if ( pass ) {
633.2697 +									anyFound = true;
633.2698 +								} else {
633.2699 +									curLoop[i] = false;
633.2700 +								}
633.2701 +							} else if ( pass ) {
633.2702 +								result.push( item );
633.2703 +								anyFound = true;
633.2704 +							}
633.2705 +						}
633.2706 +					}
633.2707 +				}
633.2708 +
633.2709 +				if ( found !== undefined ) {
633.2710 +					if ( !inplace ) {
633.2711 +						curLoop = result;
633.2712 +					}
633.2713 +
633.2714 +					expr = expr.replace( Expr.match[ type ], "" );
633.2715 +
633.2716 +					if ( !anyFound ) {
633.2717 +						return [];
633.2718 +					}
633.2719 +
633.2720 +					break;
633.2721 +				}
633.2722 +			}
633.2723 +		}
633.2724 +
633.2725 +		// Improper expression
633.2726 +		if ( expr === old ) {
633.2727 +			if ( anyFound == null ) {
633.2728 +				throw "Syntax error, unrecognized expression: " + expr;
633.2729 +			} else {
633.2730 +				break;
633.2731 +			}
633.2732 +		}
633.2733 +
633.2734 +		old = expr;
633.2735 +	}
633.2736 +
633.2737 +	return curLoop;
633.2738 +};
633.2739 +
633.2740 +var Expr = Sizzle.selectors = {
633.2741 +	order: [ "ID", "NAME", "TAG" ],
633.2742 +	match: {
633.2743 +		ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
633.2744 +		CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
633.2745 +		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
633.2746 +		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
633.2747 +		TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
633.2748 +		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
633.2749 +		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
633.2750 +		PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
633.2751 +	},
633.2752 +	leftMatch: {},
633.2753 +	attrMap: {
633.2754 +		"class": "className",
633.2755 +		"for": "htmlFor"
633.2756 +	},
633.2757 +	attrHandle: {
633.2758 +		href: function(elem){
633.2759 +			return elem.getAttribute("href");
633.2760 +		}
633.2761 +	},
633.2762 +	relative: {
633.2763 +		"+": function(checkSet, part){
633.2764 +			var isPartStr = typeof part === "string",
633.2765 +				isTag = isPartStr && !/\W/.test(part),
633.2766 +				isPartStrNotTag = isPartStr && !isTag;
633.2767 +
633.2768 +			if ( isTag ) {
633.2769 +				part = part.toLowerCase();
633.2770 +			}
633.2771 +
633.2772 +			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
633.2773 +				if ( (elem = checkSet[i]) ) {
633.2774 +					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
633.2775 +
633.2776 +					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
633.2777 +						elem || false :
633.2778 +						elem === part;
633.2779 +				}
633.2780 +			}
633.2781 +
633.2782 +			if ( isPartStrNotTag ) {
633.2783 +				Sizzle.filter( part, checkSet, true );
633.2784 +			}
633.2785 +		},
633.2786 +		">": function(checkSet, part){
633.2787 +			var isPartStr = typeof part === "string";
633.2788 +
633.2789 +			if ( isPartStr && !/\W/.test(part) ) {
633.2790 +				part = part.toLowerCase();
633.2791 +
633.2792 +				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
633.2793 +					var elem = checkSet[i];
633.2794 +					if ( elem ) {
633.2795 +						var parent = elem.parentNode;
633.2796 +						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
633.2797 +					}
633.2798 +				}
633.2799 +			} else {
633.2800 +				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
633.2801 +					var elem = checkSet[i];
633.2802 +					if ( elem ) {
633.2803 +						checkSet[i] = isPartStr ?
633.2804 +							elem.parentNode :
633.2805 +							elem.parentNode === part;
633.2806 +					}
633.2807 +				}
633.2808 +
633.2809 +				if ( isPartStr ) {
633.2810 +					Sizzle.filter( part, checkSet, true );
633.2811 +				}
633.2812 +			}
633.2813 +		},
633.2814 +		"": function(checkSet, part, isXML){
633.2815 +			var doneName = done++, checkFn = dirCheck;
633.2816 +
633.2817 +			if ( typeof part === "string" && !/\W/.test(part) ) {
633.2818 +				var nodeCheck = part = part.toLowerCase();
633.2819 +				checkFn = dirNodeCheck;
633.2820 +			}
633.2821 +
633.2822 +			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
633.2823 +		},
633.2824 +		"~": function(checkSet, part, isXML){
633.2825 +			var doneName = done++, checkFn = dirCheck;
633.2826 +
633.2827 +			if ( typeof part === "string" && !/\W/.test(part) ) {
633.2828 +				var nodeCheck = part = part.toLowerCase();
633.2829 +				checkFn = dirNodeCheck;
633.2830 +			}
633.2831 +
633.2832 +			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
633.2833 +		}
633.2834 +	},
633.2835 +	find: {
633.2836 +		ID: function(match, context, isXML){
633.2837 +			if ( typeof context.getElementById !== "undefined" && !isXML ) {
633.2838 +				var m = context.getElementById(match[1]);
633.2839 +				return m ? [m] : [];
633.2840 +			}
633.2841 +		},
633.2842 +		NAME: function(match, context){
633.2843 +			if ( typeof context.getElementsByName !== "undefined" ) {
633.2844 +				var ret = [], results = context.getElementsByName(match[1]);
633.2845 +
633.2846 +				for ( var i = 0, l = results.length; i < l; i++ ) {
633.2847 +					if ( results[i].getAttribute("name") === match[1] ) {
633.2848 +						ret.push( results[i] );
633.2849 +					}
633.2850 +				}
633.2851 +
633.2852 +				return ret.length === 0 ? null : ret;
633.2853 +			}
633.2854 +		},
633.2855 +		TAG: function(match, context){
633.2856 +			return context.getElementsByTagName(match[1]);
633.2857 +		}
633.2858 +	},
633.2859 +	preFilter: {
633.2860 +		CLASS: function(match, curLoop, inplace, result, not, isXML){
633.2861 +			match = " " + match[1].replace(/\\/g, "") + " ";
633.2862 +
633.2863 +			if ( isXML ) {
633.2864 +				return match;
633.2865 +			}
633.2866 +
633.2867 +			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
633.2868 +				if ( elem ) {
633.2869 +					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
633.2870 +						if ( !inplace ) {
633.2871 +							result.push( elem );
633.2872 +						}
633.2873 +					} else if ( inplace ) {
633.2874 +						curLoop[i] = false;
633.2875 +					}
633.2876 +				}
633.2877 +			}
633.2878 +
633.2879 +			return false;
633.2880 +		},
633.2881 +		ID: function(match){
633.2882 +			return match[1].replace(/\\/g, "");
633.2883 +		},
633.2884 +		TAG: function(match, curLoop){
633.2885 +			return match[1].toLowerCase();
633.2886 +		},
633.2887 +		CHILD: function(match){
633.2888 +			if ( match[1] === "nth" ) {
633.2889 +				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
633.2890 +				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
633.2891 +					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
633.2892 +					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
633.2893 +
633.2894 +				// calculate the numbers (first)n+(last) including if they are negative
633.2895 +				match[2] = (test[1] + (test[2] || 1)) - 0;
633.2896 +				match[3] = test[3] - 0;
633.2897 +			}
633.2898 +
633.2899 +			// TODO: Move to normal caching system
633.2900 +			match[0] = done++;
633.2901 +
633.2902 +			return match;
633.2903 +		},
633.2904 +		ATTR: function(match, curLoop, inplace, result, not, isXML){
633.2905 +			var name = match[1].replace(/\\/g, "");
633.2906 +			
633.2907 +			if ( !isXML && Expr.attrMap[name] ) {
633.2908 +				match[1] = Expr.attrMap[name];
633.2909 +			}
633.2910 +
633.2911 +			if ( match[2] === "~=" ) {
633.2912 +				match[4] = " " + match[4] + " ";
633.2913 +			}
633.2914 +
633.2915 +			return match;
633.2916 +		},
633.2917 +		PSEUDO: function(match, curLoop, inplace, result, not){
633.2918 +			if ( match[1] === "not" ) {
633.2919 +				// If we're dealing with a complex expression, or a simple one
633.2920 +				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
633.2921 +					match[3] = Sizzle(match[3], null, null, curLoop);
633.2922 +				} else {
633.2923 +					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
633.2924 +					if ( !inplace ) {
633.2925 +						result.push.apply( result, ret );
633.2926 +					}
633.2927 +					return false;
633.2928 +				}
633.2929 +			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
633.2930 +				return true;
633.2931 +			}
633.2932 +			
633.2933 +			return match;
633.2934 +		},
633.2935 +		POS: function(match){
633.2936 +			match.unshift( true );
633.2937 +			return match;
633.2938 +		}
633.2939 +	},
633.2940 +	filters: {
633.2941 +		enabled: function(elem){
633.2942 +			return elem.disabled === false && elem.type !== "hidden";
633.2943 +		},
633.2944 +		disabled: function(elem){
633.2945 +			return elem.disabled === true;
633.2946 +		},
633.2947 +		checked: function(elem){
633.2948 +			return elem.checked === true;
633.2949 +		},
633.2950 +		selected: function(elem){
633.2951 +			// Accessing this property makes selected-by-default
633.2952 +			// options in Safari work properly
633.2953 +			elem.parentNode.selectedIndex;
633.2954 +			return elem.selected === true;
633.2955 +		},
633.2956 +		parent: function(elem){
633.2957 +			return !!elem.firstChild;
633.2958 +		},
633.2959 +		empty: function(elem){
633.2960 +			return !elem.firstChild;
633.2961 +		},
633.2962 +		has: function(elem, i, match){
633.2963 +			return !!Sizzle( match[3], elem ).length;
633.2964 +		},
633.2965 +		header: function(elem){
633.2966 +			return /h\d/i.test( elem.nodeName );
633.2967 +		},
633.2968 +		text: function(elem){
633.2969 +			return "text" === elem.type;
633.2970 +		},
633.2971 +		radio: function(elem){
633.2972 +			return "radio" === elem.type;
633.2973 +		},
633.2974 +		checkbox: function(elem){
633.2975 +			return "checkbox" === elem.type;
633.2976 +		},
633.2977 +		file: function(elem){
633.2978 +			return "file" === elem.type;
633.2979 +		},
633.2980 +		password: function(elem){
633.2981 +			return "password" === elem.type;
633.2982 +		},
633.2983 +		submit: function(elem){
633.2984 +			return "submit" === elem.type;
633.2985 +		},
633.2986 +		image: function(elem){
633.2987 +			return "image" === elem.type;
633.2988 +		},
633.2989 +		reset: function(elem){
633.2990 +			return "reset" === elem.type;
633.2991 +		},
633.2992 +		button: function(elem){
633.2993 +			return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
633.2994 +		},
633.2995 +		input: function(elem){
633.2996 +			return /input|select|textarea|button/i.test(elem.nodeName);
633.2997 +		}
633.2998 +	},
633.2999 +	setFilters: {
633.3000 +		first: function(elem, i){
633.3001 +			return i === 0;
633.3002 +		},
633.3003 +		last: function(elem, i, match, array){
633.3004 +			return i === array.length - 1;
633.3005 +		},
633.3006 +		even: function(elem, i){
633.3007 +			return i % 2 === 0;
633.3008 +		},
633.3009 +		odd: function(elem, i){
633.3010 +			return i % 2 === 1;
633.3011 +		},
633.3012 +		lt: function(elem, i, match){
633.3013 +			return i < match[3] - 0;
633.3014 +		},
633.3015 +		gt: function(elem, i, match){
633.3016 +			return i > match[3] - 0;
633.3017 +		},
633.3018 +		nth: function(elem, i, match){
633.3019 +			return match[3] - 0 === i;
633.3020 +		},
633.3021 +		eq: function(elem, i, match){
633.3022 +			return match[3] - 0 === i;
633.3023 +		}
633.3024 +	},
633.3025 +	filter: {
633.3026 +		PSEUDO: function(elem, match, i, array){
633.3027 +			var name = match[1], filter = Expr.filters[ name ];
633.3028 +
633.3029 +			if ( filter ) {
633.3030 +				return filter( elem, i, match, array );
633.3031 +			} else if ( name === "contains" ) {
633.3032 +				return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
633.3033 +			} else if ( name === "not" ) {
633.3034 +				var not = match[3];
633.3035 +
633.3036 +				for ( var i = 0, l = not.length; i < l; i++ ) {
633.3037 +					if ( not[i] === elem ) {
633.3038 +						return false;
633.3039 +					}
633.3040 +				}
633.3041 +
633.3042 +				return true;
633.3043 +			} else {
633.3044 +				throw "Syntax error, unrecognized expression: " + name;
633.3045 +			}
633.3046 +		},
633.3047 +		CHILD: function(elem, match){
633.3048 +			var type = match[1], node = elem;
633.3049 +			switch (type) {
633.3050 +				case 'only':
633.3051 +				case 'first':
633.3052 +					while ( (node = node.previousSibling) )	 {
633.3053 +						if ( node.nodeType === 1 ) { 
633.3054 +							return false; 
633.3055 +						}
633.3056 +					}
633.3057 +					if ( type === "first" ) { 
633.3058 +						return true; 
633.3059 +					}
633.3060 +					node = elem;
633.3061 +				case 'last':
633.3062 +					while ( (node = node.nextSibling) )	 {
633.3063 +						if ( node.nodeType === 1 ) { 
633.3064 +							return false; 
633.3065 +						}
633.3066 +					}
633.3067 +					return true;
633.3068 +				case 'nth':
633.3069 +					var first = match[2], last = match[3];
633.3070 +
633.3071 +					if ( first === 1 && last === 0 ) {
633.3072 +						return true;
633.3073 +					}
633.3074 +					
633.3075 +					var doneName = match[0],
633.3076 +						parent = elem.parentNode;
633.3077 +	
633.3078 +					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
633.3079 +						var count = 0;
633.3080 +						for ( node = parent.firstChild; node; node = node.nextSibling ) {
633.3081 +							if ( node.nodeType === 1 ) {
633.3082 +								node.nodeIndex = ++count;
633.3083 +							}
633.3084 +						} 
633.3085 +						parent.sizcache = doneName;
633.3086 +					}
633.3087 +					
633.3088 +					var diff = elem.nodeIndex - last;
633.3089 +					if ( first === 0 ) {
633.3090 +						return diff === 0;
633.3091 +					} else {
633.3092 +						return ( diff % first === 0 && diff / first >= 0 );
633.3093 +					}
633.3094 +			}
633.3095 +		},
633.3096 +		ID: function(elem, match){
633.3097 +			return elem.nodeType === 1 && elem.getAttribute("id") === match;
633.3098 +		},
633.3099 +		TAG: function(elem, match){
633.3100 +			return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
633.3101 +		},
633.3102 +		CLASS: function(elem, match){
633.3103 +			return (" " + (elem.className || elem.getAttribute("class")) + " ")
633.3104 +				.indexOf( match ) > -1;
633.3105 +		},
633.3106 +		ATTR: function(elem, match){
633.3107 +			var name = match[1],
633.3108 +				result = Expr.attrHandle[ name ] ?
633.3109 +					Expr.attrHandle[ name ]( elem ) :
633.3110 +					elem[ name ] != null ?
633.3111 +						elem[ name ] :
633.3112 +						elem.getAttribute( name ),
633.3113 +				value = result + "",
633.3114 +				type = match[2],
633.3115 +				check = match[4];
633.3116 +
633.3117 +			return result == null ?
633.3118 +				type === "!=" :
633.3119 +				type === "=" ?
633.3120 +				value === check :
633.3121 +				type === "*=" ?
633.3122 +				value.indexOf(check) >= 0 :
633.3123 +				type === "~=" ?
633.3124 +				(" " + value + " ").indexOf(check) >= 0 :
633.3125 +				!check ?
633.3126 +				value && result !== false :
633.3127 +				type === "!=" ?
633.3128 +				value !== check :
633.3129 +				type === "^=" ?
633.3130 +				value.indexOf(check) === 0 :
633.3131 +				type === "$=" ?
633.3132 +				value.substr(value.length - check.length) === check :
633.3133 +				type === "|=" ?
633.3134 +				value === check || value.substr(0, check.length + 1) === check + "-" :
633.3135 +				false;
633.3136 +		},
633.3137 +		POS: function(elem, match, i, array){
633.3138 +			var name = match[2], filter = Expr.setFilters[ name ];
633.3139 +
633.3140 +			if ( filter ) {
633.3141 +				return filter( elem, i, match, array );
633.3142 +			}
633.3143 +		}
633.3144 +	}
633.3145 +};
633.3146 +
633.3147 +var origPOS = Expr.match.POS;
633.3148 +
633.3149 +for ( var type in Expr.match ) {
633.3150 +	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
633.3151 +	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
633.3152 +		return "\\" + (num - 0 + 1);
633.3153 +	}));
633.3154 +}
633.3155 +
633.3156 +var makeArray = function(array, results) {
633.3157 +	array = Array.prototype.slice.call( array, 0 );
633.3158 +
633.3159 +	if ( results ) {
633.3160 +		results.push.apply( results, array );
633.3161 +		return results;
633.3162 +	}
633.3163 +	
633.3164 +	return array;
633.3165 +};
633.3166 +
633.3167 +// Perform a simple check to determine if the browser is capable of
633.3168 +// converting a NodeList to an array using builtin methods.
633.3169 +try {
633.3170 +	Array.prototype.slice.call( document.documentElement.childNodes, 0 );
633.3171 +
633.3172 +// Provide a fallback method if it does not work
633.3173 +} catch(e){
633.3174 +	makeArray = function(array, results) {
633.3175 +		var ret = results || [];
633.3176 +
633.3177 +		if ( toString.call(array) === "[object Array]" ) {
633.3178 +			Array.prototype.push.apply( ret, array );
633.3179 +		} else {
633.3180 +			if ( typeof array.length === "number" ) {
633.3181 +				for ( var i = 0, l = array.length; i < l; i++ ) {
633.3182 +					ret.push( array[i] );
633.3183 +				}
633.3184 +			} else {
633.3185 +				for ( var i = 0; array[i]; i++ ) {
633.3186 +					ret.push( array[i] );
633.3187 +				}
633.3188 +			}
633.3189 +		}
633.3190 +
633.3191 +		return ret;
633.3192 +	};
633.3193 +}
633.3194 +
633.3195 +var sortOrder;
633.3196 +
633.3197 +if ( document.documentElement.compareDocumentPosition ) {
633.3198 +	sortOrder = function( a, b ) {
633.3199 +		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
633.3200 +			if ( a == b ) {
633.3201 +				hasDuplicate = true;
633.3202 +			}
633.3203 +			return a.compareDocumentPosition ? -1 : 1;
633.3204 +		}
633.3205 +
633.3206 +		var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
633.3207 +		if ( ret === 0 ) {
633.3208 +			hasDuplicate = true;
633.3209 +		}
633.3210 +		return ret;
633.3211 +	};
633.3212 +} else if ( "sourceIndex" in document.documentElement ) {
633.3213 +	sortOrder = function( a, b ) {
633.3214 +		if ( !a.sourceIndex || !b.sourceIndex ) {
633.3215 +			if ( a == b ) {
633.3216 +				hasDuplicate = true;
633.3217 +			}
633.3218 +			return a.sourceIndex ? -1 : 1;
633.3219 +		}
633.3220 +
633.3221 +		var ret = a.sourceIndex - b.sourceIndex;
633.3222 +		if ( ret === 0 ) {
633.3223 +			hasDuplicate = true;
633.3224 +		}
633.3225 +		return ret;
633.3226 +	};
633.3227 +} else if ( document.createRange ) {
633.3228 +	sortOrder = function( a, b ) {
633.3229 +		if ( !a.ownerDocument || !b.ownerDocument ) {
633.3230 +			if ( a == b ) {
633.3231 +				hasDuplicate = true;
633.3232 +			}
633.3233 +			return a.ownerDocument ? -1 : 1;
633.3234 +		}
633.3235 +
633.3236 +		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
633.3237 +		aRange.setStart(a, 0);
633.3238 +		aRange.setEnd(a, 0);
633.3239 +		bRange.setStart(b, 0);
633.3240 +		bRange.setEnd(b, 0);
633.3241 +		var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
633.3242 +		if ( ret === 0 ) {
633.3243 +			hasDuplicate = true;
633.3244 +		}
633.3245 +		return ret;
633.3246 +	};
633.3247 +}
633.3248 +
633.3249 +// Utility function for retreiving the text value of an array of DOM nodes
633.3250 +function getText( elems ) {
633.3251 +	var ret = "", elem;
633.3252 +
633.3253 +	for ( var i = 0; elems[i]; i++ ) {
633.3254 +		elem = elems[i];
633.3255 +
633.3256 +		// Get the text from text nodes and CDATA nodes
633.3257 +		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
633.3258 +			ret += elem.nodeValue;
633.3259 +
633.3260 +		// Traverse everything else, except comment nodes
633.3261 +		} else if ( elem.nodeType !== 8 ) {
633.3262 +			ret += getText( elem.childNodes );
633.3263 +		}
633.3264 +	}
633.3265 +
633.3266 +	return ret;
633.3267 +}
633.3268 +
633.3269 +// Check to see if the browser returns elements by name when
633.3270 +// querying by getElementById (and provide a workaround)
633.3271 +(function(){
633.3272 +	// We're going to inject a fake input element with a specified name
633.3273 +	var form = document.createElement("div"),
633.3274 +		id = "script" + (new Date).getTime();
633.3275 +	form.innerHTML = "<a name='" + id + "'/>";
633.3276 +
633.3277 +	// Inject it into the root element, check its status, and remove it quickly
633.3278 +	var root = document.documentElement;
633.3279 +	root.insertBefore( form, root.firstChild );
633.3280 +
633.3281 +	// The workaround has to do additional checks after a getElementById
633.3282 +	// Which slows things down for other browsers (hence the branching)
633.3283 +	if ( document.getElementById( id ) ) {
633.3284 +		Expr.find.ID = function(match, context, isXML){
633.3285 +			if ( typeof context.getElementById !== "undefined" && !isXML ) {
633.3286 +				var m = context.getElementById(match[1]);
633.3287 +				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
633.3288 +			}
633.3289 +		};
633.3290 +
633.3291 +		Expr.filter.ID = function(elem, match){
633.3292 +			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
633.3293 +			return elem.nodeType === 1 && node && node.nodeValue === match;
633.3294 +		};
633.3295 +	}
633.3296 +
633.3297 +	root.removeChild( form );
633.3298 +	root = form = null; // release memory in IE
633.3299 +})();
633.3300 +
633.3301 +(function(){
633.3302 +	// Check to see if the browser returns only elements
633.3303 +	// when doing getElementsByTagName("*")
633.3304 +
633.3305 +	// Create a fake element
633.3306 +	var div = document.createElement("div");
633.3307 +	div.appendChild( document.createComment("") );
633.3308 +
633.3309 +	// Make sure no comments are found
633.3310 +	if ( div.getElementsByTagName("*").length > 0 ) {
633.3311 +		Expr.find.TAG = function(match, context){
633.3312 +			var results = context.getElementsByTagName(match[1]);
633.3313 +
633.3314 +			// Filter out possible comments
633.3315 +			if ( match[1] === "*" ) {
633.3316 +				var tmp = [];
633.3317 +
633.3318 +				for ( var i = 0; results[i]; i++ ) {
633.3319 +					if ( results[i].nodeType === 1 ) {
633.3320 +						tmp.push( results[i] );
633.3321 +					}
633.3322 +				}
633.3323 +
633.3324 +				results = tmp;
633.3325 +			}
633.3326 +
633.3327 +			return results;
633.3328 +		};
633.3329 +	}
633.3330 +
633.3331 +	// Check to see if an attribute returns normalized href attributes
633.3332 +	div.innerHTML = "<a href='#'></a>";
633.3333 +	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
633.3334 +			div.firstChild.getAttribute("href") !== "#" ) {
633.3335 +		Expr.attrHandle.href = function(elem){
633.3336 +			return elem.getAttribute("href", 2);
633.3337 +		};
633.3338 +	}
633.3339 +
633.3340 +	div = null; // release memory in IE
633.3341 +})();
633.3342 +
633.3343 +if ( document.querySelectorAll ) {
633.3344 +	(function(){
633.3345 +		var oldSizzle = Sizzle, div = document.createElement("div");
633.3346 +		div.innerHTML = "<p class='TEST'></p>";
633.3347 +
633.3348 +		// Safari can't handle uppercase or unicode characters when
633.3349 +		// in quirks mode.
633.3350 +		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
633.3351 +			return;
633.3352 +		}
633.3353 +	
633.3354 +		Sizzle = function(query, context, extra, seed){
633.3355 +			context = context || document;
633.3356 +
633.3357 +			// Only use querySelectorAll on non-XML documents
633.3358 +			// (ID selectors don't work in non-HTML documents)
633.3359 +			if ( !seed && context.nodeType === 9 && !isXML(context) ) {
633.3360 +				try {
633.3361 +					return makeArray( context.querySelectorAll(query), extra );
633.3362 +				} catch(e){}
633.3363 +			}
633.3364 +		
633.3365 +			return oldSizzle(query, context, extra, seed);
633.3366 +		};
633.3367 +
633.3368 +		for ( var prop in oldSizzle ) {
633.3369 +			Sizzle[ prop ] = oldSizzle[ prop ];
633.3370 +		}
633.3371 +
633.3372 +		div = null; // release memory in IE
633.3373 +	})();
633.3374 +}
633.3375 +
633.3376 +(function(){
633.3377 +	var div = document.createElement("div");
633.3378 +
633.3379 +	div.innerHTML = "<div class='test e'></div><div class='test'></div>";
633.3380 +
633.3381 +	// Opera can't find a second classname (in 9.6)
633.3382 +	// Also, make sure that getElementsByClassName actually exists
633.3383 +	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
633.3384 +		return;
633.3385 +	}
633.3386 +
633.3387 +	// Safari caches class attributes, doesn't catch changes (in 3.2)
633.3388 +	div.lastChild.className = "e";
633.3389 +
633.3390 +	if ( div.getElementsByClassName("e").length === 1 ) {
633.3391 +		return;
633.3392 +	}
633.3393 +	
633.3394 +	Expr.order.splice(1, 0, "CLASS");
633.3395 +	Expr.find.CLASS = function(match, context, isXML) {
633.3396 +		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
633.3397 +			return context.getElementsByClassName(match[1]);
633.3398 +		}
633.3399 +	};
633.3400 +
633.3401 +	div = null; // release memory in IE
633.3402 +})();
633.3403 +
633.3404 +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
633.3405 +	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
633.3406 +		var elem = checkSet[i];
633.3407 +		if ( elem ) {
633.3408 +			elem = elem[dir];
633.3409 +			var match = false;
633.3410 +
633.3411 +			while ( elem ) {
633.3412 +				if ( elem.sizcache === doneName ) {
633.3413 +					match = checkSet[elem.sizset];
633.3414 +					break;
633.3415 +				}
633.3416 +
633.3417 +				if ( elem.nodeType === 1 && !isXML ){
633.3418 +					elem.sizcache = doneName;
633.3419 +					elem.sizset = i;
633.3420 +				}
633.3421 +
633.3422 +				if ( elem.nodeName.toLowerCase() === cur ) {
633.3423 +					match = elem;
633.3424 +					break;
633.3425 +				}
633.3426 +
633.3427 +				elem = elem[dir];
633.3428 +			}
633.3429 +
633.3430 +			checkSet[i] = match;
633.3431 +		}
633.3432 +	}
633.3433 +}
633.3434 +
633.3435 +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
633.3436 +	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
633.3437 +		var elem = checkSet[i];
633.3438 +		if ( elem ) {
633.3439 +			elem = elem[dir];
633.3440 +			var match = false;
633.3441 +
633.3442 +			while ( elem ) {
633.3443 +				if ( elem.sizcache === doneName ) {
633.3444 +					match = checkSet[elem.sizset];
633.3445 +					break;
633.3446 +				}
633.3447 +
633.3448 +				if ( elem.nodeType === 1 ) {
633.3449 +					if ( !isXML ) {
633.3450 +						elem.sizcache = doneName;
633.3451 +						elem.sizset = i;
633.3452 +					}
633.3453 +					if ( typeof cur !== "string" ) {
633.3454 +						if ( elem === cur ) {
633.3455 +							match = true;
633.3456 +							break;
633.3457 +						}
633.3458 +
633.3459 +					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
633.3460 +						match = elem;
633.3461 +						break;
633.3462 +					}
633.3463 +				}
633.3464 +
633.3465 +				elem = elem[dir];
633.3466 +			}
633.3467 +
633.3468 +			checkSet[i] = match;
633.3469 +		}
633.3470 +	}
633.3471 +}
633.3472 +
633.3473 +var contains = document.compareDocumentPosition ? function(a, b){
633.3474 +	return a.compareDocumentPosition(b) & 16;
633.3475 +} : function(a, b){
633.3476 +	return a !== b && (a.contains ? a.contains(b) : true);
633.3477 +};
633.3478 +
633.3479 +var isXML = function(elem){
633.3480 +	// documentElement is verified for cases where it doesn't yet exist
633.3481 +	// (such as loading iframes in IE - #4833) 
633.3482 +	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
633.3483 +	return documentElement ? documentElement.nodeName !== "HTML" : false;
633.3484 +};
633.3485 +
633.3486 +var posProcess = function(selector, context){
633.3487 +	var tmpSet = [], later = "", match,
633.3488 +		root = context.nodeType ? [context] : context;
633.3489 +
633.3490 +	// Position selectors must be done after the filter
633.3491 +	// And so must :not(positional) so we move all PSEUDOs to the end
633.3492 +	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
633.3493 +		later += match[0];
633.3494 +		selector = selector.replace( Expr.match.PSEUDO, "" );
633.3495 +	}
633.3496 +
633.3497 +	selector = Expr.relative[selector] ? selector + "*" : selector;
633.3498 +
633.3499 +	for ( var i = 0, l = root.length; i < l; i++ ) {
633.3500 +		Sizzle( selector, root[i], tmpSet );
633.3501 +	}
633.3502 +
633.3503 +	return Sizzle.filter( later, tmpSet );
633.3504 +};
633.3505 +
633.3506 +// EXPOSE
633.3507 +jQuery.find = Sizzle;
633.3508 +jQuery.expr = Sizzle.selectors;
633.3509 +jQuery.expr[":"] = jQuery.expr.filters;
633.3510 +jQuery.unique = Sizzle.uniqueSort;
633.3511 +jQuery.getText = getText;
633.3512 +jQuery.isXMLDoc = isXML;
633.3513 +jQuery.contains = contains;
633.3514 +
633.3515 +return;
633.3516 +
633.3517 +window.Sizzle = Sizzle;
633.3518 +
633.3519 +})();
633.3520 +var runtil = /Until$/,
633.3521 +	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
633.3522 +	// Note: This RegExp should be improved, or likely pulled from Sizzle
633.3523 +	rmultiselector = /,/,
633.3524 +	slice = Array.prototype.slice;
633.3525 +
633.3526 +// Implement the identical functionality for filter and not
633.3527 +var winnow = function( elements, qualifier, keep ) {
633.3528 +	if ( jQuery.isFunction( qualifier ) ) {
633.3529 +		return jQuery.grep(elements, function( elem, i ) {
633.3530 +			return !!qualifier.call( elem, i, elem ) === keep;
633.3531 +		});
633.3532 +
633.3533 +	} else if ( qualifier.nodeType ) {
633.3534 +		return jQuery.grep(elements, function( elem, i ) {
633.3535 +			return (elem === qualifier) === keep;
633.3536 +		});
633.3537 +
633.3538 +	} else if ( typeof qualifier === "string" ) {
633.3539 +		var filtered = jQuery.grep(elements, function( elem ) {
633.3540 +			return elem.nodeType === 1;
633.3541 +		});
633.3542 +
633.3543 +		if ( isSimple.test( qualifier ) ) {
633.3544 +			return jQuery.filter(qualifier, filtered, !keep);
633.3545 +		} else {
633.3546 +			qualifier = jQuery.filter( qualifier, elements );
633.3547 +		}
633.3548 +	}
633.3549 +
633.3550 +	return jQuery.grep(elements, function( elem, i ) {
633.3551 +		return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
633.3552 +	});
633.3553 +};
633.3554 +
633.3555 +jQuery.fn.extend({
633.3556 +	find: function( selector ) {
633.3557 +		var ret = this.pushStack( "", "find", selector ), length = 0;
633.3558 +
633.3559 +		for ( var i = 0, l = this.length; i < l; i++ ) {
633.3560 +			length = ret.length;
633.3561 +			jQuery.find( selector, this[i], ret );
633.3562 +
633.3563 +			if ( i > 0 ) {
633.3564 +				// Make sure that the results are unique
633.3565 +				for ( var n = length; n < ret.length; n++ ) {
633.3566 +					for ( var r = 0; r < length; r++ ) {
633.3567 +						if ( ret[r] === ret[n] ) {
633.3568 +							ret.splice(n--, 1);
633.3569 +							break;
633.3570 +						}
633.3571 +					}
633.3572 +				}
633.3573 +			}
633.3574 +		}
633.3575 +
633.3576 +		return ret;
633.3577 +	},
633.3578 +
633.3579 +	has: function( target ) {
633.3580 +		var targets = jQuery( target );
633.3581 +		return this.filter(function() {
633.3582 +			for ( var i = 0, l = targets.length; i < l; i++ ) {
633.3583 +				if ( jQuery.contains( this, targets[i] ) ) {
633.3584 +					return true;
633.3585 +				}
633.3586 +			}
633.3587 +		});
633.3588 +	},
633.3589 +
633.3590 +	not: function( selector ) {
633.3591 +		return this.pushStack( winnow(this, selector, false), "not", selector);
633.3592 +	},
633.3593 +
633.3594 +	filter: function( selector ) {
633.3595 +		return this.pushStack( winnow(this, selector, true), "filter", selector );
633.3596 +	},
633.3597 +	
633.3598 +	is: function( selector ) {
633.3599 +		return !!selector && jQuery.filter( selector, this ).length > 0;
633.3600 +	},
633.3601 +
633.3602 +	closest: function( selectors, context ) {
633.3603 +		if ( jQuery.isArray( selectors ) ) {
633.3604 +			var ret = [], cur = this[0], match, matches = {}, selector;
633.3605 +
633.3606 +			if ( cur && selectors.length ) {
633.3607 +				for ( var i = 0, l = selectors.length; i < l; i++ ) {
633.3608 +					selector = selectors[i];
633.3609 +
633.3610 +					if ( !matches[selector] ) {
633.3611 +						matches[selector] = jQuery.expr.match.POS.test( selector ) ? 
633.3612 +							jQuery( selector, context || this.context ) :
633.3613 +							selector;
633.3614 +					}
633.3615 +				}
633.3616 +
633.3617 +				while ( cur && cur.ownerDocument && cur !== context ) {
633.3618 +					for ( selector in matches ) {
633.3619 +						match = matches[selector];
633.3620 +
633.3621 +						if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
633.3622 +							ret.push({ selector: selector, elem: cur });
633.3623 +							delete matches[selector];
633.3624 +						}
633.3625 +					}
633.3626 +					cur = cur.parentNode;
633.3627 +				}
633.3628 +			}
633.3629 +
633.3630 +			return ret;
633.3631 +		}
633.3632 +
633.3633 +		var pos = jQuery.expr.match.POS.test( selectors ) ? 
633.3634 +			jQuery( selectors, context || this.context ) : null;
633.3635 +
633.3636 +		return this.map(function( i, cur ) {
633.3637 +			while ( cur && cur.ownerDocument && cur !== context ) {
633.3638 +				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
633.3639 +					return cur;
633.3640 +				}
633.3641 +				cur = cur.parentNode;
633.3642 +			}
633.3643 +			return null;
633.3644 +		});
633.3645 +	},
633.3646 +	
633.3647 +	// Determine the position of an element within
633.3648 +	// the matched set of elements
633.3649 +	index: function( elem ) {
633.3650 +		if ( !elem || typeof elem === "string" ) {
633.3651 +			return jQuery.inArray( this[0],
633.3652 +				// If it receives a string, the selector is used
633.3653 +				// If it receives nothing, the siblings are used
633.3654 +				elem ? jQuery( elem ) : this.parent().children() );
633.3655 +		}
633.3656 +		// Locate the position of the desired element
633.3657 +		return jQuery.inArray(
633.3658 +			// If it receives a jQuery object, the first element is used
633.3659 +			elem.jquery ? elem[0] : elem, this );
633.3660 +	},
633.3661 +
633.3662 +	add: function( selector, context ) {
633.3663 +		var set = typeof selector === "string" ?
633.3664 +				jQuery( selector, context || this.context ) :
633.3665 +				jQuery.makeArray( selector ),
633.3666 +			all = jQuery.merge( this.get(), set );
633.3667 +
633.3668 +		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
633.3669 +			all :
633.3670 +			jQuery.unique( all ) );
633.3671 +	},
633.3672 +
633.3673 +	andSelf: function() {
633.3674 +		return this.add( this.prevObject );
633.3675 +	}
633.3676 +});
633.3677 +
633.3678 +// A painfully simple check to see if an element is disconnected
633.3679 +// from a document (should be improved, where feasible).
633.3680 +function isDisconnected( node ) {
633.3681 +	return !node || !node.parentNode || node.parentNode.nodeType === 11;
633.3682 +}
633.3683 +
633.3684 +jQuery.each({
633.3685 +	parent: function( elem ) {
633.3686 +		var parent = elem.parentNode;
633.3687 +		return parent && parent.nodeType !== 11 ? parent : null;
633.3688 +	},
633.3689 +	parents: function( elem ) {
633.3690 +		return jQuery.dir( elem, "parentNode" );
633.3691 +	},
633.3692 +	parentsUntil: function( elem, i, until ) {
633.3693 +		return jQuery.dir( elem, "parentNode", until );
633.3694 +	},
633.3695 +	next: function( elem ) {
633.3696 +		return jQuery.nth( elem, 2, "nextSibling" );
633.3697 +	},
633.3698 +	prev: function( elem ) {
633.3699 +		return jQuery.nth( elem, 2, "previousSibling" );
633.3700 +	},
633.3701 +	nextAll: function( elem ) {
633.3702 +		return jQuery.dir( elem, "nextSibling" );
633.3703 +	},
633.3704 +	prevAll: function( elem ) {
633.3705 +		return jQuery.dir( elem, "previousSibling" );
633.3706 +	},
633.3707 +	nextUntil: function( elem, i, until ) {
633.3708 +		return jQuery.dir( elem, "nextSibling", until );
633.3709 +	},
633.3710 +	prevUntil: function( elem, i, until ) {
633.3711 +		return jQuery.dir( elem, "previousSibling", until );
633.3712 +	},
633.3713 +	siblings: function( elem ) {
633.3714 +		return jQuery.sibling( elem.parentNode.firstChild, elem );
633.3715 +	},
633.3716 +	children: function( elem ) {
633.3717 +		return jQuery.sibling( elem.firstChild );
633.3718 +	},
633.3719 +	contents: function( elem ) {
633.3720 +		return jQuery.nodeName( elem, "iframe" ) ?
633.3721 +			elem.contentDocument || elem.contentWindow.document :
633.3722 +			jQuery.makeArray( elem.childNodes );
633.3723 +	}
633.3724 +}, function( name, fn ) {
633.3725 +	jQuery.fn[ name ] = function( until, selector ) {
633.3726 +		var ret = jQuery.map( this, fn, until );
633.3727 +		
633.3728 +		if ( !runtil.test( name ) ) {
633.3729 +			selector = until;
633.3730 +		}
633.3731 +
633.3732 +		if ( selector && typeof selector === "string" ) {
633.3733 +			ret = jQuery.filter( selector, ret );
633.3734 +		}
633.3735 +
633.3736 +		ret = this.length > 1 ? jQuery.unique( ret ) : ret;
633.3737 +
633.3738 +		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
633.3739 +			ret = ret.reverse();
633.3740 +		}
633.3741 +
633.3742 +		return this.pushStack( ret, name, slice.call(arguments).join(",") );
633.3743 +	};
633.3744 +});
633.3745 +
633.3746 +jQuery.extend({
633.3747 +	filter: function( expr, elems, not ) {
633.3748 +		if ( not ) {
633.3749 +			expr = ":not(" + expr + ")";
633.3750 +		}
633.3751 +
633.3752 +		return jQuery.find.matches(expr, elems);
633.3753 +	},
633.3754 +	
633.3755 +	dir: function( elem, dir, until ) {
633.3756 +		var matched = [], cur = elem[dir];
633.3757 +		while ( cur && cur.nodeType !== 9 && (until === undefined || !jQuery( cur ).is( until )) ) {
633.3758 +			if ( cur.nodeType === 1 ) {
633.3759 +				matched.push( cur );
633.3760 +			}
633.3761 +			cur = cur[dir];
633.3762 +		}
633.3763 +		return matched;
633.3764 +	},
633.3765 +
633.3766 +	nth: function( cur, result, dir, elem ) {
633.3767 +		result = result || 1;
633.3768 +		var num = 0;
633.3769 +
633.3770 +		for ( ; cur; cur = cur[dir] ) {
633.3771 +			if ( cur.nodeType === 1 && ++num === result ) {
633.3772 +				break;
633.3773 +			}
633.3774 +		}
633.3775 +
633.3776 +		return cur;
633.3777 +	},
633.3778 +
633.3779 +	sibling: function( n, elem ) {
633.3780 +		var r = [];
633.3781 +
633.3782 +		for ( ; n; n = n.nextSibling ) {
633.3783 +			if ( n.nodeType === 1 && n !== elem ) {
633.3784 +				r.push( n );
633.3785 +			}
633.3786 +		}
633.3787 +
633.3788 +		return r;
633.3789 +	}
633.3790 +});
633.3791 +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
633.3792 +	rleadingWhitespace = /^\s+/,
633.3793 +	rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
633.3794 +	rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
633.3795 +	rtagName = /<([\w:]+)/,
633.3796 +	rtbody = /<tbody/i,
633.3797 +	rhtml = /<|&\w+;/,
633.3798 +	fcloseTag = function( all, front, tag ) {
633.3799 +		return rselfClosing.test( tag ) ?
633.3800 +			all :
633.3801 +			front + "></" + tag + ">";
633.3802 +	},
633.3803 +	wrapMap = {
633.3804 +		option: [ 1, "<select multiple='multiple'>", "</select>" ],
633.3805 +		legend: [ 1, "<fieldset>", "</fieldset>" ],
633.3806 +		thead: [ 1, "<table>", "</table>" ],
633.3807 +		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
633.3808 +		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
633.3809 +		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
633.3810 +		area: [ 1, "<map>", "</map>" ],
633.3811 +		_default: [ 0, "", "" ]
633.3812 +	};
633.3813 +
633.3814 +wrapMap.optgroup = wrapMap.option;
633.3815 +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
633.3816 +wrapMap.th = wrapMap.td;
633.3817 +
633.3818 +// IE can't serialize <link> and <script> tags normally
633.3819 +if ( !jQuery.support.htmlSerialize ) {
633.3820 +	wrapMap._default = [ 1, "div<div>", "</div>" ];
633.3821 +}
633.3822 +
633.3823 +jQuery.fn.extend({
633.3824 +	text: function( text ) {
633.3825 +		if ( jQuery.isFunction(text) ) {
633.3826 +			return this.each(function(i) {
633.3827 +				var self = jQuery(this);
633.3828 +				return self.text( text.call(this, i, self.text()) );
633.3829 +			});
633.3830 +		}
633.3831 +
633.3832 +		if ( typeof text !== "object" && text !== undefined ) {
633.3833 +			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
633.3834 +		}
633.3835 +
633.3836 +		return jQuery.getText( this );
633.3837 +	},
633.3838 +
633.3839 +	wrapAll: function( html ) {
633.3840 +		if ( jQuery.isFunction( html ) ) {
633.3841 +			return this.each(function(i) {
633.3842 +				jQuery(this).wrapAll( html.call(this, i) );
633.3843 +			});
633.3844 +		}
633.3845 +
633.3846 +		if ( this[0] ) {
633.3847 +			// The elements to wrap the target around
633.3848 +			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
633.3849 +
633.3850 +			if ( this[0].parentNode ) {
633.3851 +				wrap.insertBefore( this[0] );
633.3852 +			}
633.3853 +
633.3854 +			wrap.map(function() {
633.3855 +				var elem = this;
633.3856 +
633.3857 +				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
633.3858 +					elem = elem.firstChild;
633.3859 +				}
633.3860 +
633.3861 +				return elem;
633.3862 +			}).append(this);
633.3863 +		}
633.3864 +
633.3865 +		return this;
633.3866 +	},
633.3867 +
633.3868 +	wrapInner: function( html ) {
633.3869 +		return this.each(function() {
633.3870 +			var self = jQuery( this ), contents = self.contents();
633.3871 +
633.3872 +			if ( contents.length ) {
633.3873 +				contents.wrapAll( html );
633.3874 +
633.3875 +			} else {
633.3876 +				self.append( html );
633.3877 +			}
633.3878 +		});
633.3879 +	},
633.3880 +
633.3881 +	wrap: function( html ) {
633.3882 +		return this.each(function() {
633.3883 +			jQuery( this ).wrapAll( html );
633.3884 +		});
633.3885 +	},
633.3886 +
633.3887 +	unwrap: function() {
633.3888 +		return this.parent().each(function() {
633.3889 +			if ( !jQuery.nodeName( this, "body" ) ) {
633.3890 +				jQuery( this ).replaceWith( this.childNodes );
633.3891 +			}
633.3892 +		}).end();
633.3893 +	},
633.3894 +
633.3895 +	append: function() {
633.3896 +		return this.domManip(arguments, true, function( elem ) {
633.3897 +			if ( this.nodeType === 1 ) {
633.3898 +				this.appendChild( elem );
633.3899 +			}
633.3900 +		});
633.3901 +	},
633.3902 +
633.3903 +	prepend: function() {
633.3904 +		return this.domManip(arguments, true, function( elem ) {
633.3905 +			if ( this.nodeType === 1 ) {
633.3906 +				this.insertBefore( elem, this.firstChild );
633.3907 +			}
633.3908 +		});
633.3909 +	},
633.3910 +
633.3911 +	before: function() {
633.3912 +		if ( this[0] && this[0].parentNode ) {
633.3913 +			return this.domManip(arguments, false, function( elem ) {
633.3914 +				this.parentNode.insertBefore( elem, this );
633.3915 +			});
633.3916 +		} else if ( arguments.length ) {
633.3917 +			var set = jQuery(arguments[0]);
633.3918 +			set.push.apply( set, this.toArray() );
633.3919 +			return this.pushStack( set, "before", arguments );
633.3920 +		}
633.3921 +	},
633.3922 +
633.3923 +	after: function() {
633.3924 +		if ( this[0] && this[0].parentNode ) {
633.3925 +			return this.domManip(arguments, false, function( elem ) {
633.3926 +				this.parentNode.insertBefore( elem, this.nextSibling );
633.3927 +			});
633.3928 +		} else if ( arguments.length ) {
633.3929 +			var set = this.pushStack( this, "after", arguments );
633.3930 +			set.push.apply( set, jQuery(arguments[0]).toArray() );
633.3931 +			return set;
633.3932 +		}
633.3933 +	},
633.3934 +
633.3935 +	clone: function( events ) {
633.3936 +		// Do the clone
633.3937 +		var ret = this.map(function() {
633.3938 +			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
633.3939 +				// IE copies events bound via attachEvent when
633.3940 +				// using cloneNode. Calling detachEvent on the
633.3941 +				// clone will also remove the events from the orignal
633.3942 +				// In order to get around this, we use innerHTML.
633.3943 +				// Unfortunately, this means some modifications to
633.3944 +				// attributes in IE that are actually only stored
633.3945 +				// as properties will not be copied (such as the
633.3946 +				// the name attribute on an input).
633.3947 +				var html = this.outerHTML, ownerDocument = this.ownerDocument;
633.3948 +				if ( !html ) {
633.3949 +					var div = ownerDocument.createElement("div");
633.3950 +					div.appendChild( this.cloneNode(true) );
633.3951 +					html = div.innerHTML;
633.3952 +				}
633.3953 +
633.3954 +				return jQuery.clean([html.replace(rinlinejQuery, "")
633.3955 +					.replace(rleadingWhitespace, "")], ownerDocument)[0];
633.3956 +			} else {
633.3957 +				return this.cloneNode(true);
633.3958 +			}
633.3959 +		});
633.3960 +
633.3961 +		// Copy the events from the original to the clone
633.3962 +		if ( events === true ) {
633.3963 +			cloneCopyEvent( this, ret );
633.3964 +			cloneCopyEvent( this.find("*"), ret.find("*") );
633.3965 +		}
633.3966 +
633.3967 +		// Return the cloned set
633.3968 +		return ret;
633.3969 +	},
633.3970 +
633.3971 +	html: function( value ) {
633.3972 +		if ( value === undefined ) {
633.3973 +			return this[0] && this[0].nodeType === 1 ?
633.3974 +				this[0].innerHTML.replace(rinlinejQuery, "") :
633.3975 +				null;
633.3976 +
633.3977 +		// See if we can take a shortcut and just use innerHTML
633.3978 +		} else if ( typeof value === "string" && !/<script/i.test( value ) &&
633.3979 +			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
633.3980 +			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
633.3981 +
633.3982 +			try {
633.3983 +				for ( var i = 0, l = this.length; i < l; i++ ) {
633.3984 +					// Remove element nodes and prevent memory leaks
633.3985 +					if ( this[i].nodeType === 1 ) {
633.3986 +						cleanData( this[i].getElementsByTagName("*") );
633.3987 +						this[i].innerHTML = value;
633.3988 +					}
633.3989 +				}
633.3990 +
633.3991 +			// If using innerHTML throws an exception, use the fallback method
633.3992 +			} catch(e) {
633.3993 +				this.empty().append( value );
633.3994 +			}
633.3995 +
633.3996 +		} else if ( jQuery.isFunction( value ) ) {
633.3997 +			this.each(function(i){
633.3998 +				var self = jQuery(this), old = self.html();
633.3999 +				self.empty().append(function(){
633.4000 +					return value.call( this, i, old );
633.4001 +				});
633.4002 +			});
633.4003 +
633.4004 +		} else {
633.4005 +			this.empty().append( value );
633.4006 +		}
633.4007 +
633.4008 +		return this;
633.4009 +	},
633.4010 +
633.4011 +	replaceWith: function( value ) {
633.4012 +		if ( this[0] && this[0].parentNode ) {
633.4013 +			// Make sure that the elements are removed from the DOM before they are inserted
633.4014 +			// this can help fix replacing a parent with child elements
633.4015 +			if ( !jQuery.isFunction( value ) ) {
633.4016 +				value = jQuery( value ).detach();
633.4017 +			}
633.4018 +
633.4019 +			return this.each(function() {
633.4020 +				var next = this.nextSibling, parent = this.parentNode;
633.4021 +
633.4022 +				jQuery(this).remove();
633.4023 +
633.4024 +				if ( next ) {
633.4025 +					jQuery(next).before( value );
633.4026 +				} else {
633.4027 +					jQuery(parent).append( value );
633.4028 +				}
633.4029 +			});
633.4030 +		} else {
633.4031 +			return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
633.4032 +		}
633.4033 +	},
633.4034 +
633.4035 +	detach: function( selector ) {
633.4036 +		return this.remove( selector, true );
633.4037 +	},
633.4038 +
633.4039 +	domManip: function( args, table, callback ) {
633.4040 +		var results, first, value = args[0], scripts = [];
633.4041 +
633.4042 +		if ( jQuery.isFunction(value) ) {
633.4043 +			return this.each(function(i) {
633.4044 +				var self = jQuery(this);
633.4045 +				args[0] = value.call(this, i, table ? self.html() : undefined);
633.4046 +				return self.domManip( args, table, callback );
633.4047 +			});
633.4048 +		}
633.4049 +
633.4050 +		if ( this[0] ) {
633.4051 +			// If we're in a fragment, just use that instead of building a new one
633.4052 +			if ( args[0] && args[0].parentNode && args[0].parentNode.nodeType === 11 ) {
633.4053 +				results = { fragment: args[0].parentNode };
633.4054 +			} else {
633.4055 +				results = buildFragment( args, this, scripts );
633.4056 +			}
633.4057 +
633.4058 +			first = results.fragment.firstChild;
633.4059 +
633.4060 +			if ( first ) {
633.4061 +				table = table && jQuery.nodeName( first, "tr" );
633.4062 +
633.4063 +				for ( var i = 0, l = this.length; i < l; i++ ) {
633.4064 +					callback.call(
633.4065 +						table ?
633.4066 +							root(this[i], first) :
633.4067 +							this[i],
633.4068 +						results.cacheable || this.length > 1 || i > 0 ?
633.4069 +							results.fragment.cloneNode(true) :
633.4070 +							results.fragment
633.4071 +					);
633.4072 +				}
633.4073 +			}
633.4074 +
633.4075 +			if ( scripts ) {
633.4076 +				jQuery.each( scripts, evalScript );
633.4077 +			}
633.4078 +		}
633.4079 +
633.4080 +		return this;
633.4081 +
633.4082 +		function root( elem, cur ) {
633.4083 +			return jQuery.nodeName(elem, "table") ?
633.4084 +				(elem.getElementsByTagName("tbody")[0] ||
633.4085 +				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
633.4086 +				elem;
633.4087 +		}
633.4088 +	}
633.4089 +});
633.4090 +
633.4091 +function cloneCopyEvent(orig, ret) {
633.4092 +	var i = 0;
633.4093 +
633.4094 +	ret.each(function() {
633.4095 +		if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
633.4096 +			return;
633.4097 +		}
633.4098 +
633.4099 +		var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;
633.4100 +
633.4101 +		if ( events ) {
633.4102 +			delete curData.handle;
633.4103 +			curData.events = {};
633.4104 +
633.4105 +			for ( var type in events ) {
633.4106 +				for ( var handler in events[ type ] ) {
633.4107 +					jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
633.4108 +				}
633.4109 +			}
633.4110 +		}
633.4111 +	});
633.4112 +}
633.4113 +
633.4114 +function buildFragment( args, nodes, scripts ) {
633.4115 +	var fragment, cacheable, cached, cacheresults, doc;
633.4116 +
633.4117 +	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 ) {
633.4118 +		cacheable = true;
633.4119 +		cacheresults = jQuery.fragments[ args[0] ];
633.4120 +		if ( cacheresults ) {
633.4121 +			if ( cacheresults !== 1 ) {
633.4122 +				fragment = cacheresults;
633.4123 +			}
633.4124 +			cached = true;
633.4125 +		}
633.4126 +	}
633.4127 +
633.4128 +	if ( !fragment ) {
633.4129 +		doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
633.4130 +		fragment = doc.createDocumentFragment();
633.4131 +		jQuery.clean( args, doc, fragment, scripts );
633.4132 +	}
633.4133 +
633.4134 +	if ( cacheable ) {
633.4135 +		jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
633.4136 +	}
633.4137 +
633.4138 +	return { fragment: fragment, cacheable: cacheable };
633.4139 +}
633.4140 +
633.4141 +jQuery.fragments = {};
633.4142 +
633.4143 +jQuery.each({
633.4144 +	appendTo: "append",
633.4145 +	prependTo: "prepend",
633.4146 +	insertBefore: "before",
633.4147 +	insertAfter: "after",
633.4148 +	replaceAll: "replaceWith"
633.4149 +}, function( name, original ) {
633.4150 +	jQuery.fn[ name ] = function( selector ) {
633.4151 +		var ret = [], insert = jQuery( selector );
633.4152 +
633.4153 +		for ( var i = 0, l = insert.length; i < l; i++ ) {
633.4154 +			var elems = (i > 0 ? this.clone(true) : this).get();
633.4155 +			jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
633.4156 +			ret = ret.concat( elems );
633.4157 +		}
633.4158 +		return this.pushStack( ret, name, insert.selector );
633.4159 +	};
633.4160 +});
633.4161 +
633.4162 +jQuery.each({
633.4163 +	// keepData is for internal use only--do not document
633.4164 +	remove: function( selector, keepData ) {
633.4165 +		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
633.4166 +			if ( !keepData && this.nodeType === 1 ) {
633.4167 +				cleanData( this.getElementsByTagName("*") );
633.4168 +				cleanData( [ this ] );
633.4169 +			}
633.4170 +
633.4171 +			if ( this.parentNode ) {
633.4172 +				 this.parentNode.removeChild( this );
633.4173 +			}
633.4174 +		}
633.4175 +	},
633.4176 +
633.4177 +	empty: function() {
633.4178 +		// Remove element nodes and prevent memory leaks
633.4179 +		if ( this.nodeType === 1 ) {
633.4180 +			cleanData( this.getElementsByTagName("*") );
633.4181 +		}
633.4182 +
633.4183 +		// Remove any remaining nodes
633.4184 +		while ( this.firstChild ) {
633.4185 +			this.removeChild( this.firstChild );
633.4186 +		}
633.4187 +	}
633.4188 +}, function( name, fn ) {
633.4189 +	jQuery.fn[ name ] = function() {
633.4190 +		return this.each( fn, arguments );
633.4191 +	};
633.4192 +});
633.4193 +
633.4194 +jQuery.extend({
633.4195 +	clean: function( elems, context, fragment, scripts ) {
633.4196 +		context = context || document;
633.4197 +
633.4198 +		// !context.createElement fails in IE with an error but returns typeof 'object'
633.4199 +		if ( typeof context.createElement === "undefined" ) {
633.4200 +			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
633.4201 +		}
633.4202 +
633.4203 +		var ret = [];
633.4204 +
633.4205 +		jQuery.each(elems, function( i, elem ) {
633.4206 +			if ( typeof elem === "number" ) {
633.4207 +				elem += "";
633.4208 +			}
633.4209 +
633.4210 +			if ( !elem ) {
633.4211 +				return;
633.4212 +			}
633.4213 +
633.4214 +			// Convert html string into DOM nodes
633.4215 +			if ( typeof elem === "string" && !rhtml.test( elem ) ) {
633.4216 +				elem = context.createTextNode( elem );
633.4217 +
633.4218 +			} else if ( typeof elem === "string" ) {
633.4219 +				// Fix "XHTML"-style tags in all browsers
633.4220 +				elem = elem.replace(rxhtmlTag, fcloseTag);
633.4221 +
633.4222 +				// Trim whitespace, otherwise indexOf won't work as expected
633.4223 +				var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
633.4224 +					wrap = wrapMap[ tag ] || wrapMap._default,
633.4225 +					depth = wrap[0],
633.4226 +					div = context.createElement("div");
633.4227 +
633.4228 +				// Go to html and back, then peel off extra wrappers
633.4229 +				div.innerHTML = wrap[1] + elem + wrap[2];
633.4230 +
633.4231 +				// Move to the right depth
633.4232 +				while ( depth-- ) {
633.4233 +					div = div.lastChild;
633.4234 +				}
633.4235 +
633.4236 +				// Remove IE's autoinserted <tbody> from table fragments
633.4237 +				if ( !jQuery.support.tbody ) {
633.4238 +
633.4239 +					// String was a <table>, *may* have spurious <tbody>
633.4240 +					var hasBody = rtbody.test(elem),
633.4241 +						tbody = tag === "table" && !hasBody ?
633.4242 +							div.firstChild && div.firstChild.childNodes :
633.4243 +
633.4244 +							// String was a bare <thead> or <tfoot>
633.4245 +							wrap[1] === "<table>" && !hasBody ?
633.4246 +								div.childNodes :
633.4247 +								[];
633.4248 +
633.4249 +					for ( var j = tbody.length - 1; j >= 0 ; --j ) {
633.4250 +						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
633.4251 +							tbody[ j ].parentNode.removeChild( tbody[ j ] );
633.4252 +						}
633.4253 +					}
633.4254 +
633.4255 +				}
633.4256 +
633.4257 +				// IE completely kills leading whitespace when innerHTML is used
633.4258 +				if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
633.4259 +					div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
633.4260 +				}
633.4261 +
633.4262 +				elem = jQuery.makeArray( div.childNodes );
633.4263 +			}
633.4264 +
633.4265 +			if ( elem.nodeType ) {
633.4266 +				ret.push( elem );
633.4267 +			} else {
633.4268 +				ret = jQuery.merge( ret, elem );
633.4269 +			}
633.4270 +
633.4271 +		});
633.4272 +
633.4273 +		if ( fragment ) {
633.4274 +			for ( var i = 0; ret[i]; i++ ) {
633.4275 +				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
633.4276 +					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
633.4277 +				} else {
633.4278 +					if ( ret[i].nodeType === 1 ) {
633.4279 +						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
633.4280 +					}
633.4281 +					fragment.appendChild( ret[i] );
633.4282 +				}
633.4283 +			}
633.4284 +		}
633.4285 +
633.4286 +		return ret;
633.4287 +	}
633.4288 +});
633.4289 +
633.4290 +function cleanData( elems ) {
633.4291 +	for ( var i = 0, elem, id; (elem = elems[i]) != null; i++ ) {
633.4292 +		if ( !jQuery.noData[elem.nodeName.toLowerCase()] && (id = elem[expando]) ) {
633.4293 +			delete jQuery.cache[ id ];
633.4294 +		}
633.4295 +	}
633.4296 +}
633.4297 +// exclude the following css properties to add px
633.4298 +var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
633.4299 +	ralpha = /alpha\([^)]*\)/,
633.4300 +	ropacity = /opacity=([^)]*)/,
633.4301 +	rfloat = /float/i,
633.4302 +	rdashAlpha = /-([a-z])/ig,
633.4303 +	rupper = /([A-Z])/g,
633.4304 +	rnumpx = /^-?\d+(?:px)?$/i,
633.4305 +	rnum = /^-?\d/,
633.4306 +
633.4307 +	cssShow = { position: "absolute", visibility: "hidden", display:"block" },
633.4308 +	cssWidth = [ "Left", "Right" ],
633.4309 +	cssHeight = [ "Top", "Bottom" ],
633.4310 +
633.4311 +	// cache check for defaultView.getComputedStyle
633.4312 +	getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
633.4313 +	// normalize float css property
633.4314 +	styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
633.4315 +	fcamelCase = function( all, letter ) {
633.4316 +		return letter.toUpperCase();
633.4317 +	};
633.4318 +
633.4319 +jQuery.fn.css = function( name, value ) {
633.4320 +	return access( this, name, value, true, function( elem, name, value ) {
633.4321 +		if ( value === undefined ) {
633.4322 +			return jQuery.curCSS( elem, name );
633.4323 +		}
633.4324 +		
633.4325 +		if ( typeof value === "number" && !rexclude.test(name) ) {
633.4326 +			value += "px";
633.4327 +		}
633.4328 +
633.4329 +		jQuery.style( elem, name, value );
633.4330 +	});
633.4331 +};
633.4332 +
633.4333 +jQuery.extend({
633.4334 +	style: function( elem, name, value ) {
633.4335 +		// don't set styles on text and comment nodes
633.4336 +		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
633.4337 +			return undefined;
633.4338 +		}
633.4339 +
633.4340 +		// ignore negative width and height values #1599
633.4341 +		if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
633.4342 +			value = undefined;
633.4343 +		}
633.4344 +
633.4345 +		var style = elem.style || elem, set = value !== undefined;
633.4346 +
633.4347 +		// IE uses filters for opacity
633.4348 +		if ( !jQuery.support.opacity && name === "opacity" ) {
633.4349 +			if ( set ) {
633.4350 +				// IE has trouble with opacity if it does not have layout
633.4351 +				// Force it by setting the zoom level
633.4352 +				style.zoom = 1;
633.4353 +
633.4354 +				// Set the alpha filter to set the opacity
633.4355 +				var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
633.4356 +				var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
633.4357 +				style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
633.4358 +			}
633.4359 +
633.4360 +			return style.filter && style.filter.indexOf("opacity=") >= 0 ?
633.4361 +				(parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
633.4362 +				"";
633.4363 +		}
633.4364 +
633.4365 +		// Make sure we're using the right name for getting the float value
633.4366 +		if ( rfloat.test( name ) ) {
633.4367 +			name = styleFloat;
633.4368 +		}
633.4369 +
633.4370 +		name = name.replace(rdashAlpha, fcamelCase);
633.4371 +
633.4372 +		if ( set ) {
633.4373 +			style[ name ] = value;
633.4374 +		}
633.4375 +
633.4376 +		return style[ name ];
633.4377 +	},
633.4378 +
633.4379 +	css: function( elem, name, force, extra ) {
633.4380 +		if ( name === "width" || name === "height" ) {
633.4381 +			var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;
633.4382 +
633.4383 +			function getWH() {
633.4384 +				val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
633.4385 +
633.4386 +				if ( extra === "border" ) {
633.4387 +					return;
633.4388 +				}
633.4389 +
633.4390 +				jQuery.each( which, function() {
633.4391 +					if ( !extra ) {
633.4392 +						val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
633.4393 +					}
633.4394 +
633.4395 +					if ( extra === "margin" ) {
633.4396 +						val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
633.4397 +					} else {
633.4398 +						val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
633.4399 +					}
633.4400 +				});
633.4401 +			}
633.4402 +
633.4403 +			if ( elem.offsetWidth !== 0 ) {
633.4404 +				getWH();
633.4405 +			} else {
633.4406 +				jQuery.swap( elem, props, getWH );
633.4407 +			}
633.4408 +
633.4409 +			return Math.max(0, Math.round(val));
633.4410 +		}
633.4411 +
633.4412 +		return jQuery.curCSS( elem, name, force );
633.4413 +	},
633.4414 +
633.4415 +	curCSS: function( elem, name, force ) {
633.4416 +		var ret, style = elem.style, filter;
633.4417 +
633.4418 +		// IE uses filters for opacity
633.4419 +		if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
633.4420 +			ret = ropacity.test(elem.currentStyle.filter || "") ?
633.4421 +				(parseFloat(RegExp.$1) / 100) + "" :
633.4422 +				"";
633.4423 +
633.4424 +			return ret === "" ?
633.4425 +				"1" :
633.4426 +				ret;
633.4427 +		}
633.4428 +
633.4429 +		// Make sure we're using the right name for getting the float value
633.4430 +		if ( rfloat.test( name ) ) {
633.4431 +			name = styleFloat;
633.4432 +		}
633.4433 +
633.4434 +		if ( !force && style && style[ name ] ) {
633.4435 +			ret = style[ name ];
633.4436 +
633.4437 +		} else if ( getComputedStyle ) {
633.4438 +
633.4439 +			// Only "float" is needed here
633.4440 +			if ( rfloat.test( name ) ) {
633.4441 +				name = "float";
633.4442 +			}
633.4443 +
633.4444 +			name = name.replace( rupper, "-$1" ).toLowerCase();
633.4445 +
633.4446 +			var defaultView = elem.ownerDocument.defaultView;
633.4447 +
633.4448 +			if ( !defaultView ) {
633.4449 +				return null;
633.4450 +			}
633.4451 +
633.4452 +			var computedStyle = defaultView.getComputedStyle( elem, null );
633.4453 +
633.4454 +			if ( computedStyle ) {
633.4455 +				ret = computedStyle.getPropertyValue( name );
633.4456 +			}
633.4457 +
633.4458 +			// We should always get a number back from opacity
633.4459 +			if ( name === "opacity" && ret === "" ) {
633.4460 +				ret = "1";
633.4461 +			}
633.4462 +
633.4463 +		} else if ( elem.currentStyle ) {
633.4464 +			var camelCase = name.replace(rdashAlpha, fcamelCase);
633.4465 +
633.4466 +			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
633.4467 +
633.4468 +			// From the awesome hack by Dean Edwards
633.4469 +			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
633.4470 +
633.4471 +			// If we're not dealing with a regular pixel number
633.4472 +			// but a number that has a weird ending, we need to convert it to pixels
633.4473 +			if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
633.4474 +				// Remember the original values
633.4475 +				var left = style.left, rsLeft = elem.runtimeStyle.left;
633.4476 +
633.4477 +				// Put in the new values to get a computed value out
633.4478 +				elem.runtimeStyle.left = elem.currentStyle.left;
633.4479 +				style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
633.4480 +				ret = style.pixelLeft + "px";
633.4481 +
633.4482 +				// Revert the changed values
633.4483 +				style.left = left;
633.4484 +				elem.runtimeStyle.left = rsLeft;
633.4485 +			}
633.4486 +		}
633.4487 +
633.4488 +		return ret;
633.4489 +	},
633.4490 +
633.4491 +	// A method for quickly swapping in/out CSS properties to get correct calculations
633.4492 +	swap: function( elem, options, callback ) {
633.4493 +		var old = {};
633.4494 +
633.4495 +		// Remember the old values, and insert the new ones
633.4496 +		for ( var name in options ) {
633.4497 +			old[ name ] = elem.style[ name ];
633.4498 +			elem.style[ name ] = options[ name ];
633.4499 +		}
633.4500 +
633.4501 +		callback.call( elem );
633.4502 +
633.4503 +		// Revert the old values
633.4504 +		for ( var name in options ) {
633.4505 +			elem.style[ name ] = old[ name ];
633.4506 +		}
633.4507 +	}
633.4508 +});
633.4509 +
633.4510 +if ( jQuery.expr && jQuery.expr.filters ) {
633.4511 +	jQuery.expr.filters.hidden = function( elem ) {
633.4512 +		var width = elem.offsetWidth, height = elem.offsetHeight,
633.4513 +			skip = elem.nodeName.toLowerCase() === "tr";
633.4514 +
633.4515 +		return width === 0 && height === 0 && !skip ?
633.4516 +			true :
633.4517 +			width > 0 && height > 0 && !skip ?
633.4518 +				false :
633.4519 +				jQuery.curCSS(elem, "display") === "none";
633.4520 +	};
633.4521 +
633.4522 +	jQuery.expr.filters.visible = function( elem ) {
633.4523 +		return !jQuery.expr.filters.hidden( elem );
633.4524 +	};
633.4525 +}
633.4526 +var jsc = now(),
633.4527 +	rscript = /<script(.|\s)*?\/script>/gi,
633.4528 +	rselectTextarea = /select|textarea/i,
633.4529 +	rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
633.4530 +	jsre = /=\?(&|$)/,
633.4531 +	rquery = /\?/,
633.4532 +	rts = /(\?|&)_=.*?(&|$)/,
633.4533 +	rurl = /^(\w+:)?\/\/([^\/?#]+)/,
633.4534 +	r20 = /%20/g;
633.4535 +
633.4536 +jQuery.fn.extend({
633.4537 +	// Keep a copy of the old load
633.4538 +	_load: jQuery.fn.load,
633.4539 +
633.4540 +	load: function( url, params, callback ) {
633.4541 +		if ( typeof url !== "string" ) {
633.4542 +			return this._load( url );
633.4543 +
633.4544 +		// Don't do a request if no elements are being requested
633.4545 +		} else if ( !this.length ) {
633.4546 +			return this;
633.4547 +		}
633.4548 +
633.4549 +		var off = url.indexOf(" ");
633.4550 +		if ( off >= 0 ) {
633.4551 +			var selector = url.slice(off, url.length);
633.4552 +			url = url.slice(0, off);
633.4553 +		}
633.4554 +
633.4555 +		// Default to a GET request
633.4556 +		var type = "GET";
633.4557 +
633.4558 +		// If the second parameter was provided
633.4559 +		if ( params ) {
633.4560 +			// If it's a function
633.4561 +			if ( jQuery.isFunction( params ) ) {
633.4562 +				// We assume that it's the callback
633.4563 +				callback = params;
633.4564 +				params = null;
633.4565 +
633.4566 +			// Otherwise, build a param string
633.4567 +			} else if ( typeof params === "object" ) {
633.4568 +				params = jQuery.param( params, jQuery.ajaxSettings.traditional );
633.4569 +				type = "POST";
633.4570 +			}
633.4571 +		}
633.4572 +
633.4573 +		// Request the remote document
633.4574 +		jQuery.ajax({
633.4575 +			url: url,
633.4576 +			type: type,
633.4577 +			dataType: "html",
633.4578 +			data: params,
633.4579 +			context:this,
633.4580 +			complete: function( res, status ) {
633.4581 +				// If successful, inject the HTML into all the matched elements
633.4582 +				if ( status === "success" || status === "notmodified" ) {
633.4583 +					// See if a selector was specified
633.4584 +					this.html( selector ?
633.4585 +						// Create a dummy div to hold the results
633.4586 +						jQuery("<div />")
633.4587 +							// inject the contents of the document in, removing the scripts
633.4588 +							// to avoid any 'Permission Denied' errors in IE
633.4589 +							.append(res.responseText.replace(rscript, ""))
633.4590 +
633.4591 +							// Locate the specified elements
633.4592 +							.find(selector) :
633.4593 +
633.4594 +						// If not, just inject the full result
633.4595 +						res.responseText );
633.4596 +				}
633.4597 +
633.4598 +				if ( callback ) {
633.4599 +					this.each( callback, [res.responseText, status, res] );
633.4600 +				}
633.4601 +			}
633.4602 +		});
633.4603 +
633.4604 +		return this;
633.4605 +	},
633.4606 +
633.4607 +	serialize: function() {
633.4608 +		return jQuery.param(this.serializeArray());
633.4609 +	},
633.4610 +	serializeArray: function() {
633.4611 +		return this.map(function() {
633.4612 +			return this.elements ? jQuery.makeArray(this.elements) : this;
633.4613 +		})
633.4614 +		.filter(function() {
633.4615 +			return this.name && !this.disabled &&
633.4616 +				(this.checked || rselectTextarea.test(this.nodeName) ||
633.4617 +					rinput.test(this.type));
633.4618 +		})
633.4619 +		.map(function( i, elem ) {
633.4620 +			var val = jQuery(this).val();
633.4621 +
633.4622 +			return val == null ?
633.4623 +				null :
633.4624 +				jQuery.isArray(val) ?
633.4625 +					jQuery.map( val, function( val, i ) {
633.4626 +						return { name: elem.name, value: val };
633.4627 +					}) :
633.4628 +					{ name: elem.name, value: val };
633.4629 +		}).get();
633.4630 +	}
633.4631 +});
633.4632 +
633.4633 +// Attach a bunch of functions for handling common AJAX events
633.4634 +jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
633.4635 +	jQuery.fn[o] = function( f ) {
633.4636 +		return this.bind(o, f);
633.4637 +	};
633.4638 +});
633.4639 +
633.4640 +jQuery.extend({
633.4641 +
633.4642 +	get: function( url, data, callback, type ) {
633.4643 +		// shift arguments if data argument was omited
633.4644 +		if ( jQuery.isFunction( data ) ) {
633.4645 +			type = type || callback;
633.4646 +			callback = data;
633.4647 +			data = null;
633.4648 +		}
633.4649 +
633.4650 +		return jQuery.ajax({
633.4651 +			type: "GET",
633.4652 +			url: url,
633.4653 +			data: data,
633.4654 +			success: callback,
633.4655 +			dataType: type
633.4656 +		});
633.4657 +	},
633.4658 +
633.4659 +	getScript: function( url, callback ) {
633.4660 +		return jQuery.get(url, null, callback, "script");
633.4661 +	},
633.4662 +
633.4663 +	getJSON: function( url, data, callback ) {
633.4664 +		return jQuery.get(url, data, callback, "json");
633.4665 +	},
633.4666 +
633.4667 +	post: function( url, data, callback, type ) {
633.4668 +		// shift arguments if data argument was omited
633.4669 +		if ( jQuery.isFunction( data ) ) {
633.4670 +			type = type || callback;
633.4671 +			callback = data;
633.4672 +			data = {};
633.4673 +		}
633.4674 +
633.4675 +		return jQuery.ajax({
633.4676 +			type: "POST",
633.4677 +			url: url,
633.4678 +			data: data,
633.4679 +			success: callback,
633.4680 +			dataType: type
633.4681 +		});
633.4682 +	},
633.4683 +
633.4684 +	ajaxSetup: function( settings ) {
633.4685 +		jQuery.extend( jQuery.ajaxSettings, settings );
633.4686 +	},
633.4687 +
633.4688 +	ajaxSettings: {
633.4689 +		url: location.href,
633.4690 +		global: true,
633.4691 +		type: "GET",
633.4692 +		contentType: "application/x-www-form-urlencoded",
633.4693 +		processData: true,
633.4694 +		async: true,
633.4695 +		/*
633.4696 +		timeout: 0,
633.4697 +		data: null,
633.4698 +		username: null,
633.4699 +		password: null,
633.4700 +		traditional: false,
633.4701 +		*/
633.4702 +		// Create the request object; Microsoft failed to properly
633.4703 +		// implement the XMLHttpRequest in IE7 (can't request local files),
633.4704 +		// so we use the ActiveXObject when it is available
633.4705 +		// This function can be overriden by calling jQuery.ajaxSetup
633.4706 +		xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
633.4707 +			function() {
633.4708 +				return new window.XMLHttpRequest();
633.4709 +			} :
633.4710 +			function() {
633.4711 +				try {
633.4712 +					return new window.ActiveXObject("Microsoft.XMLHTTP");
633.4713 +				} catch(e) {}
633.4714 +			},
633.4715 +		accepts: {
633.4716 +			xml: "application/xml, text/xml",
633.4717 +			html: "text/html",
633.4718 +			script: "text/javascript, application/javascript",
633.4719 +			json: "application/json, text/javascript",
633.4720 +			text: "text/plain",
633.4721 +			_default: "*/*"
633.4722 +		}
633.4723 +	},
633.4724 +
633.4725 +	// Last-Modified header cache for next request
633.4726 +	lastModified: {},
633.4727 +	etag: {},
633.4728 +
633.4729 +	ajax: function( origSettings ) {
633.4730 +		var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
633.4731 +		
633.4732 +		var jsonp, status, data,
633.4733 +			callbackContext = s.context || s,
633.4734 +			type = s.type.toUpperCase();
633.4735 +
633.4736 +		// convert data if not already a string
633.4737 +		if ( s.data && s.processData && typeof s.data !== "string" ) {
633.4738 +			s.data = jQuery.param( s.data, s.traditional );
633.4739 +		}
633.4740 +
633.4741 +		// Handle JSONP Parameter Callbacks
633.4742 +		if ( s.dataType === "jsonp" ) {
633.4743 +			if ( type === "GET" ) {
633.4744 +				if ( !jsre.test( s.url ) ) {
633.4745 +					s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
633.4746 +				}
633.4747 +			} else if ( !s.data || !jsre.test(s.data) ) {
633.4748 +				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
633.4749 +			}
633.4750 +			s.dataType = "json";
633.4751 +		}
633.4752 +
633.4753 +		// Build temporary JSONP function
633.4754 +		if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
633.4755 +			jsonp = s.jsonpCallback || ("jsonp" + jsc++);
633.4756 +
633.4757 +			// Replace the =? sequence both in the query string and the data
633.4758 +			if ( s.data ) {
633.4759 +				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
633.4760 +			}
633.4761 +
633.4762 +			s.url = s.url.replace(jsre, "=" + jsonp + "$1");
633.4763 +
633.4764 +			// We need to make sure
633.4765 +			// that a JSONP style response is executed properly
633.4766 +			s.dataType = "script";
633.4767 +
633.4768 +			// Handle JSONP-style loading
633.4769 +			window[ jsonp ] = window[ jsonp ] || function( tmp ) {
633.4770 +				data = tmp;
633.4771 +				success();
633.4772 +				complete();
633.4773 +				// Garbage collect
633.4774 +				window[ jsonp ] = undefined;
633.4775 +
633.4776 +				try {
633.4777 +					delete window[ jsonp ];
633.4778 +				} catch(e) {}
633.4779 +
633.4780 +				if ( head ) {
633.4781 +					head.removeChild( script );
633.4782 +				}
633.4783 +			};
633.4784 +		}
633.4785 +
633.4786 +		if ( s.dataType === "script" && s.cache === null ) {
633.4787 +			s.cache = false;
633.4788 +		}
633.4789 +
633.4790 +		if ( s.cache === false && type === "GET" ) {
633.4791 +			var ts = now();
633.4792 +
633.4793 +			// try replacing _= if it is there
633.4794 +			var ret = s.url.replace(rts, "$1_=" + ts + "$2");
633.4795 +
633.4796 +			// if nothing was replaced, add timestamp to the end
633.4797 +			s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
633.4798 +		}
633.4799 +
633.4800 +		// If data is available, append data to url for get requests
633.4801 +		if ( s.data && type === "GET" ) {
633.4802 +			s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
633.4803 +		}
633.4804 +
633.4805 +		// Watch for a new set of requests
633.4806 +		if ( s.global && ! jQuery.active++ ) {
633.4807 +			jQuery.event.trigger( "ajaxStart" );
633.4808 +		}
633.4809 +
633.4810 +		// Matches an absolute URL, and saves the domain
633.4811 +		var parts = rurl.exec( s.url ),
633.4812 +			remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
633.4813 +
633.4814 +		// If we're requesting a remote document
633.4815 +		// and trying to load JSON or Script with a GET
633.4816 +		if ( s.dataType === "script" && type === "GET" && remote ) {
633.4817 +			var head = document.getElementsByTagName("head")[0] || document.documentElement;
633.4818 +			var script = document.createElement("script");
633.4819 +			script.src = s.url;
633.4820 +			if ( s.scriptCharset ) {
633.4821 +				script.charset = s.scriptCharset;
633.4822 +			}
633.4823 +
633.4824 +			// Handle Script loading
633.4825 +			if ( !jsonp ) {
633.4826 +				var done = false;
633.4827 +
633.4828 +				// Attach handlers for all browsers
633.4829 +				script.onload = script.onreadystatechange = function() {
633.4830 +					if ( !done && (!this.readyState ||
633.4831 +							this.readyState === "loaded" || this.readyState === "complete") ) {
633.4832 +						done = true;
633.4833 +						success();
633.4834 +						complete();
633.4835 +
633.4836 +						// Handle memory leak in IE
633.4837 +						script.onload = script.onreadystatechange = null;
633.4838 +						if ( head && script.parentNode ) {
633.4839 +							head.removeChild( script );
633.4840 +						}
633.4841 +					}
633.4842 +				};
633.4843 +			}
633.4844 +
633.4845 +			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
633.4846 +			// This arises when a base node is used (#2709 and #4378).
633.4847 +			head.insertBefore( script, head.firstChild );
633.4848 +
633.4849 +			// We handle everything using the script element injection
633.4850 +			return undefined;
633.4851 +		}
633.4852 +
633.4853 +		var requestDone = false;
633.4854 +
633.4855 +		// Create the request object
633.4856 +		var xhr = s.xhr();
633.4857 +
633.4858 +		if ( !xhr ) {
633.4859 +			return;
633.4860 +		}
633.4861 +
633.4862 +		// Open the socket
633.4863 +		// Passing null username, generates a login popup on Opera (#2865)
633.4864 +		if ( s.username ) {
633.4865 +			xhr.open(type, s.url, s.async, s.username, s.password);
633.4866 +		} else {
633.4867 +			xhr.open(type, s.url, s.async);
633.4868 +		}
633.4869 +
633.4870 +		// Need an extra try/catch for cross domain requests in Firefox 3
633.4871 +		try {
633.4872 +			// Set the correct header, if data is being sent
633.4873 +			if ( s.data || origSettings && origSettings.contentType ) {
633.4874 +				xhr.setRequestHeader("Content-Type", s.contentType);
633.4875 +			}
633.4876 +
633.4877 +			// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
633.4878 +			if ( s.ifModified ) {
633.4879 +				if ( jQuery.lastModified[s.url] ) {
633.4880 +					xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
633.4881 +				}
633.4882 +
633.4883 +				if ( jQuery.etag[s.url] ) {
633.4884 +					xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
633.4885 +				}
633.4886 +			}
633.4887 +
633.4888 +			// Set header so the called script knows that it's an XMLHttpRequest
633.4889 +			// Only send the header if it's not a remote XHR
633.4890 +			if ( !remote ) {
633.4891 +				xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
633.4892 +			}
633.4893 +
633.4894 +			// Set the Accepts header for the server, depending on the dataType
633.4895 +			xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
633.4896 +				s.accepts[ s.dataType ] + ", */*" :
633.4897 +				s.accepts._default );
633.4898 +		} catch(e) {}
633.4899 +
633.4900 +		// Allow custom headers/mimetypes and early abort
633.4901 +		if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
633.4902 +			// Handle the global AJAX counter
633.4903 +			if ( s.global && ! --jQuery.active ) {
633.4904 +				jQuery.event.trigger( "ajaxStop" );
633.4905 +			}
633.4906 +
633.4907 +			// close opended socket
633.4908 +			xhr.abort();
633.4909 +			return false;
633.4910 +		}
633.4911 +
633.4912 +		if ( s.global ) {
633.4913 +			trigger("ajaxSend", [xhr, s]);
633.4914 +		}
633.4915 +
633.4916 +		// Wait for a response to come back
633.4917 +		var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
633.4918 +			// The request was aborted
633.4919 +			if ( !xhr || xhr.readyState === 0 ) {
633.4920 +				// Opera doesn't call onreadystatechange before this point
633.4921 +				// so we simulate the call
633.4922 +				if ( !requestDone ) {
633.4923 +					complete();
633.4924 +				}
633.4925 +
633.4926 +				requestDone = true;
633.4927 +				if ( xhr ) {
633.4928 +					xhr.onreadystatechange = jQuery.noop;
633.4929 +				}
633.4930 +
633.4931 +			// The transfer is complete and the data is available, or the request timed out
633.4932 +			} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
633.4933 +				requestDone = true;
633.4934 +				xhr.onreadystatechange = jQuery.noop;
633.4935 +
633.4936 +				status = isTimeout === "timeout" ?
633.4937 +					"timeout" :
633.4938 +					!jQuery.httpSuccess( xhr ) ?
633.4939 +						"error" :
633.4940 +						s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
633.4941 +							"notmodified" :
633.4942 +							"success";
633.4943 +
633.4944 +				if ( status === "success" ) {
633.4945 +					// Watch for, and catch, XML document parse errors
633.4946 +					try {
633.4947 +						// process the data (runs the xml through httpData regardless of callback)
633.4948 +						data = jQuery.httpData( xhr, s.dataType, s );
633.4949 +					} catch(e) {
633.4950 +						status = "parsererror";
633.4951 +					}
633.4952 +				}
633.4953 +
633.4954 +				// Make sure that the request was successful or notmodified
633.4955 +				if ( status === "success" || status === "notmodified" ) {
633.4956 +					// JSONP handles its own success callback
633.4957 +					if ( !jsonp ) {
633.4958 +						success();
633.4959 +					}
633.4960 +				} else {
633.4961 +					jQuery.handleError(s, xhr, status);
633.4962 +				}
633.4963 +
633.4964 +				// Fire the complete handlers
633.4965 +				complete();
633.4966 +
633.4967 +				if ( isTimeout === "timeout" ) {
633.4968 +					xhr.abort();
633.4969 +				}
633.4970 +
633.4971 +				// Stop memory leaks
633.4972 +				if ( s.async ) {
633.4973 +					xhr = null;
633.4974 +				}
633.4975 +			}
633.4976 +		};
633.4977 +
633.4978 +		// Override the abort handler, if we can (IE doesn't allow it, but that's OK)
633.4979 +		// Opera doesn't fire onreadystatechange at all on abort
633.4980 +		try {
633.4981 +			var oldAbort = xhr.abort;
633.4982 +			xhr.abort = function() {
633.4983 +				if ( xhr ) {
633.4984 +					oldAbort.call( xhr );
633.4985 +					if ( xhr ) {
633.4986 +						xhr.readyState = 0;
633.4987 +					}
633.4988 +				}
633.4989 +
633.4990 +				onreadystatechange();
633.4991 +			};
633.4992 +		} catch(e) { }
633.4993 +
633.4994 +		// Timeout checker
633.4995 +		if ( s.async && s.timeout > 0 ) {
633.4996 +			setTimeout(function() {
633.4997 +				// Check to see if the request is still happening
633.4998 +				if ( xhr && !requestDone ) {
633.4999 +					onreadystatechange( "timeout" );
633.5000 +				}
633.5001 +			}, s.timeout);
633.5002 +		}
633.5003 +
633.5004 +		// Send the data
633.5005 +		try {
633.5006 +			xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
633.5007 +		} catch(e) {
633.5008 +			jQuery.handleError(s, xhr, null, e);
633.5009 +			// Fire the complete handlers
633.5010 +			complete();
633.5011 +		}
633.5012 +
633.5013 +		// firefox 1.5 doesn't fire statechange for sync requests
633.5014 +		if ( !s.async ) {
633.5015 +			onreadystatechange();
633.5016 +		}
633.5017 +
633.5018 +		function success() {
633.5019 +			// If a local callback was specified, fire it and pass it the data
633.5020 +			if ( s.success ) {
633.5021 +				s.success.call( callbackContext, data, status, xhr );
633.5022 +			}
633.5023 +
633.5024 +			// Fire the global callback
633.5025 +			if ( s.global ) {
633.5026 +				trigger( "ajaxSuccess", [xhr, s] );
633.5027 +			}
633.5028 +		}
633.5029 +
633.5030 +		function complete() {
633.5031 +			// Process result
633.5032 +			if ( s.complete ) {
633.5033 +				s.complete.call( callbackContext, xhr, status);
633.5034 +			}
633.5035 +
633.5036 +			// The request was completed
633.5037 +			if ( s.global ) {
633.5038 +				trigger( "ajaxComplete", [xhr, s] );
633.5039 +			}
633.5040 +
633.5041 +			// Handle the global AJAX counter
633.5042 +			if ( s.global && ! --jQuery.active ) {
633.5043 +				jQuery.event.trigger( "ajaxStop" );
633.5044 +			}
633.5045 +		}
633.5046 +		
633.5047 +		function trigger(type, args) {
633.5048 +			(s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
633.5049 +		}
633.5050 +
633.5051 +		// return XMLHttpRequest to allow aborting the request etc.
633.5052 +		return xhr;
633.5053 +	},
633.5054 +
633.5055 +	handleError: function( s, xhr, status, e ) {
633.5056 +		// If a local callback was specified, fire it
633.5057 +		if ( s.error ) {
633.5058 +			s.error.call( s.context || window, xhr, status, e );
633.5059 +		}
633.5060 +
633.5061 +		// Fire the global callback
633.5062 +		if ( s.global ) {
633.5063 +			(s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
633.5064 +		}
633.5065 +	},
633.5066 +
633.5067 +	// Counter for holding the number of active queries
633.5068 +	active: 0,
633.5069 +
633.5070 +	// Determines if an XMLHttpRequest was successful or not
633.5071 +	httpSuccess: function( xhr ) {
633.5072 +		try {
633.5073 +			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
633.5074 +			return !xhr.status && location.protocol === "file:" ||
633.5075 +				// Opera returns 0 when status is 304
633.5076 +				( xhr.status >= 200 && xhr.status < 300 ) ||
633.5077 +				xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
633.5078 +		} catch(e) {}
633.5079 +
633.5080 +		return false;
633.5081 +	},
633.5082 +
633.5083 +	// Determines if an XMLHttpRequest returns NotModified
633.5084 +	httpNotModified: function( xhr, url ) {
633.5085 +		var lastModified = xhr.getResponseHeader("Last-Modified"),
633.5086 +			etag = xhr.getResponseHeader("Etag");
633.5087 +
633.5088 +		if ( lastModified ) {
633.5089 +			jQuery.lastModified[url] = lastModified;
633.5090 +		}
633.5091 +
633.5092 +		if ( etag ) {
633.5093 +			jQuery.etag[url] = etag;
633.5094 +		}
633.5095 +
633.5096 +		// Opera returns 0 when status is 304
633.5097 +		return xhr.status === 304 || xhr.status === 0;
633.5098 +	},
633.5099 +
633.5100 +	httpData: function( xhr, type, s ) {
633.5101 +		var ct = xhr.getResponseHeader("content-type") || "",
633.5102 +			xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
633.5103 +			data = xml ? xhr.responseXML : xhr.responseText;
633.5104 +
633.5105 +		if ( xml && data.documentElement.nodeName === "parsererror" ) {
633.5106 +			throw "parsererror";
633.5107 +		}
633.5108 +
633.5109 +		// Allow a pre-filtering function to sanitize the response
633.5110 +		// s is checked to keep backwards compatibility
633.5111 +		if ( s && s.dataFilter ) {
633.5112 +			data = s.dataFilter( data, type );
633.5113 +		}
633.5114 +
633.5115 +		// The filter can actually parse the response
633.5116 +		if ( typeof data === "string" ) {
633.5117 +			// Get the JavaScript object, if JSON is used.
633.5118 +			if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
633.5119 +				// Make sure the incoming data is actual JSON
633.5120 +				// Logic borrowed from http://json.org/json2.js
633.5121 +				if (/^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
633.5122 +					.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
633.5123 +					.replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) {
633.5124 +
633.5125 +					// Try to use the native JSON parser first
633.5126 +					if ( window.JSON && window.JSON.parse ) {
633.5127 +						data = window.JSON.parse( data );
633.5128 +
633.5129 +					} else {
633.5130 +						data = (new Function("return " + data))();
633.5131 +					}
633.5132 +
633.5133 +				} else {
633.5134 +					throw "Invalid JSON: " + data;
633.5135 +				}
633.5136 +
633.5137 +			// If the type is "script", eval it in global context
633.5138 +			} else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
633.5139 +				jQuery.globalEval( data );
633.5140 +			}
633.5141 +		}
633.5142 +
633.5143 +		return data;
633.5144 +	},
633.5145 +
633.5146 +	// Serialize an array of form elements or a set of
633.5147 +	// key/values into a query string
633.5148 +	param: function( a, traditional ) {
633.5149 +		
633.5150 +		var s = [];
633.5151 +		
633.5152 +		// Set traditional to true for jQuery <= 1.3.2 behavior.
633.5153 +		if ( traditional === undefined ) {
633.5154 +			traditional = jQuery.ajaxSettings.traditional;
633.5155 +		}
633.5156 +		
633.5157 +		function add( key, value ) {
633.5158 +			// If value is a function, invoke it and return its value
633.5159 +			value = jQuery.isFunction(value) ? value() : value;
633.5160 +			s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
633.5161 +		}
633.5162 +		
633.5163 +		// If an array was passed in, assume that it is an array of form elements.
633.5164 +		if ( jQuery.isArray(a) || a.jquery ) {
633.5165 +			// Serialize the form elements
633.5166 +			jQuery.each( a, function() {
633.5167 +				add( this.name, this.value );
633.5168 +			});
633.5169 +			
633.5170 +		} else {
633.5171 +			// If traditional, encode the "old" way (the way 1.3.2 or older
633.5172 +			// did it), otherwise encode params recursively.
633.5173 +			jQuery.each( a, function buildParams( prefix, obj ) {
633.5174 +				
633.5175 +				if ( jQuery.isArray(obj) ) {
633.5176 +					// Serialize array item.
633.5177 +					jQuery.each( obj, function( i, v ) {
633.5178 +						if ( traditional ) {
633.5179 +							// Treat each array item as a scalar.
633.5180 +							add( prefix, v );
633.5181 +						} else {
633.5182 +							// If array item is non-scalar (array or object), encode its
633.5183 +							// numeric index to resolve deserialization ambiguity issues.
633.5184 +							// Note that rack (as of 1.0.0) can't currently deserialize
633.5185 +							// nested arrays properly, and attempting to do so may cause
633.5186 +							// a server error. Possible fixes are to modify rack's
633.5187 +							// deserialization algorithm or to provide an option or flag
633.5188 +							// to force array serialization to be shallow.
633.5189 +							buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
633.5190 +						}
633.5191 +					});
633.5192 +					
633.5193 +				} else if ( !traditional && obj != null && typeof obj === "object" ) {
633.5194 +					// Serialize object item.
633.5195 +					jQuery.each( obj, function( k, v ) {
633.5196 +						buildParams( prefix + "[" + k + "]", v );
633.5197 +					});
633.5198 +					
633.5199 +				} else {
633.5200 +					// Serialize scalar item.
633.5201 +					add( prefix, obj );
633.5202 +				}
633.5203 +			});
633.5204 +		}
633.5205 +		
633.5206 +		// Return the resulting serialization
633.5207 +		return s.join("&").replace(r20, "+");
633.5208 +	}
633.5209 +
633.5210 +});
633.5211 +var elemdisplay = {},
633.5212 +	rfxtypes = /toggle|show|hide/,
633.5213 +	rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
633.5214 +	timerId,
633.5215 +	fxAttrs = [
633.5216 +		// height animations
633.5217 +		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
633.5218 +		// width animations
633.5219 +		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
633.5220 +		// opacity animations
633.5221 +		[ "opacity" ]
633.5222 +	];
633.5223 +
633.5224 +jQuery.fn.extend({
633.5225 +	show: function( speed, callback ) {
633.5226 +		if ( speed != null ) {
633.5227 +			return this.animate( genFx("show", 3), speed, callback);
633.5228 +
633.5229 +		} else {
633.5230 +			for ( var i = 0, l = this.length; i < l; i++ ) {
633.5231 +				var old = jQuery.data(this[i], "olddisplay");
633.5232 +
633.5233 +				this[i].style.display = old || "";
633.5234 +
633.5235 +				if ( jQuery.css(this[i], "display") === "none" ) {
633.5236 +					var nodeName = this[i].nodeName, display;
633.5237 +
633.5238 +					if ( elemdisplay[ nodeName ] ) {
633.5239 +						display = elemdisplay[ nodeName ];
633.5240 +
633.5241 +					} else {
633.5242 +						var elem = jQuery("<" + nodeName + " />").appendTo("body");
633.5243 +
633.5244 +						display = elem.css("display");
633.5245 +
633.5246 +						if ( display === "none" ) {
633.5247 +							display = "block";
633.5248 +						}
633.5249 +
633.5250 +						elem.remove();
633.5251 +
633.5252 +						elemdisplay[ nodeName ] = display;
633.5253 +					}
633.5254 +
633.5255 +					jQuery.data(this[i], "olddisplay", display);
633.5256 +				}
633.5257 +			}
633.5258 +
633.5259 +			// Set the display of the elements in a second loop
633.5260 +			// to avoid the constant reflow
633.5261 +			for ( var j = 0, k = this.length; j < k; j++ ) {
633.5262 +				this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
633.5263 +			}
633.5264 +
633.5265 +			return this;
633.5266 +		}
633.5267 +	},
633.5268 +
633.5269 +	hide: function( speed, callback ) {
633.5270 +		if ( speed != null ) {
633.5271 +			return this.animate( genFx("hide", 3), speed, callback);
633.5272 +
633.5273 +		} else {
633.5274 +			for ( var i = 0, l = this.length; i < l; i++ ) {
633.5275 +				var old = jQuery.data(this[i], "olddisplay");
633.5276 +				if ( !old && old !== "none" ) {
633.5277 +					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
633.5278 +				}
633.5279 +			}
633.5280 +
633.5281 +			// Set the display of the elements in a second loop
633.5282 +			// to avoid the constant reflow
633.5283 +			for ( var j = 0, k = this.length; j < k; j++ ) {
633.5284 +				this[j].style.display = "none";
633.5285 +			}
633.5286 +
633.5287 +			return this;
633.5288 +		}
633.5289 +	},
633.5290 +
633.5291 +	// Save the old toggle function
633.5292 +	_toggle: jQuery.fn.toggle,
633.5293 +
633.5294 +	toggle: function( fn, fn2 ) {
633.5295 +		var bool = typeof fn === "boolean";
633.5296 +
633.5297 +		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
633.5298 +			this._toggle.apply( this, arguments );
633.5299 +
633.5300 +		} else if ( fn == null || bool ) {
633.5301 +			this.each(function() {
633.5302 +				var state = bool ? fn : jQuery(this).is(":hidden");
633.5303 +				jQuery(this)[ state ? "show" : "hide" ]();
633.5304 +			});
633.5305 +
633.5306 +		} else {
633.5307 +			this.animate(genFx("toggle", 3), fn, fn2);
633.5308 +		}
633.5309 +
633.5310 +		return this;
633.5311 +	},
633.5312 +
633.5313 +	fadeTo: function( speed, to, callback ) {
633.5314 +		return this.filter(":hidden").css("opacity", 0).show().end()
633.5315 +					.animate({opacity: to}, speed, callback);
633.5316 +	},
633.5317 +
633.5318 +	animate: function( prop, speed, easing, callback ) {
633.5319 +		var optall = jQuery.speed(speed, easing, callback);
633.5320 +
633.5321 +		if ( jQuery.isEmptyObject( prop ) ) {
633.5322 +			return this.each( optall.complete );
633.5323 +		}
633.5324 +
633.5325 +		return this[ optall.queue === false ? "each" : "queue" ](function() {
633.5326 +			var opt = jQuery.extend({}, optall), p,
633.5327 +				hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
633.5328 +				self = this;
633.5329 +
633.5330 +			for ( p in prop ) {
633.5331 +				var name = p.replace(rdashAlpha, fcamelCase);
633.5332 +
633.5333 +				if ( p !== name ) {
633.5334 +					prop[ name ] = prop[ p ];
633.5335 +					delete prop[ p ];
633.5336 +					p = name;
633.5337 +				}
633.5338 +
633.5339 +				if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
633.5340 +					return opt.complete.call(this);
633.5341 +				}
633.5342 +
633.5343 +				if ( ( p === "height" || p === "width" ) && this.style ) {
633.5344 +					// Store display property
633.5345 +					opt.display = jQuery.css(this, "display");
633.5346 +
633.5347 +					// Make sure that nothing sneaks out
633.5348 +					opt.overflow = this.style.overflow;
633.5349 +				}
633.5350 +
633.5351 +				if ( jQuery.isArray( prop[p] ) ) {
633.5352 +					// Create (if needed) and add to specialEasing
633.5353 +					(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
633.5354 +					prop[p] = prop[p][0];
633.5355 +				}
633.5356 +			}
633.5357 +
633.5358 +			if ( opt.overflow != null ) {
633.5359 +				this.style.overflow = "hidden";
633.5360 +			}
633.5361 +
633.5362 +			opt.curAnim = jQuery.extend({}, prop);
633.5363 +
633.5364 +			jQuery.each( prop, function( name, val ) {
633.5365 +				var e = new jQuery.fx( self, opt, name );
633.5366 +
633.5367 +				if ( rfxtypes.test(val) ) {
633.5368 +					e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
633.5369 +
633.5370 +				} else {
633.5371 +					var parts = rfxnum.exec(val),
633.5372 +						start = e.cur(true) || 0;
633.5373 +
633.5374 +					if ( parts ) {
633.5375 +						var end = parseFloat( parts[2] ),
633.5376 +							unit = parts[3] || "px";
633.5377 +
633.5378 +						// We need to compute starting value
633.5379 +						if ( unit !== "px" ) {
633.5380 +							self.style[ name ] = (end || 1) + unit;
633.5381 +							start = ((end || 1) / e.cur(true)) * start;
633.5382 +							self.style[ name ] = start + unit;
633.5383 +						}
633.5384 +
633.5385 +						// If a +=/-= token was provided, we're doing a relative animation
633.5386 +						if ( parts[1] ) {
633.5387 +							end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
633.5388 +						}
633.5389 +
633.5390 +						e.custom( start, end, unit );
633.5391 +
633.5392 +					} else {
633.5393 +						e.custom( start, val, "" );
633.5394 +					}
633.5395 +				}
633.5396 +			});
633.5397 +
633.5398 +			// For JS strict compliance
633.5399 +			return true;
633.5400 +		});
633.5401 +	},
633.5402 +
633.5403 +	stop: function( clearQueue, gotoEnd ) {
633.5404 +		var timers = jQuery.timers;
633.5405 +
633.5406 +		if ( clearQueue ) {
633.5407 +			this.queue([]);
633.5408 +		}
633.5409 +
633.5410 +		this.each(function() {
633.5411 +			// go in reverse order so anything added to the queue during the loop is ignored
633.5412 +			for ( var i = timers.length - 1; i >= 0; i-- ) {
633.5413 +				if ( timers[i].elem === this ) {
633.5414 +					if (gotoEnd) {
633.5415 +						// force the next step to be the last
633.5416 +						timers[i](true);
633.5417 +					}
633.5418 +
633.5419 +					timers.splice(i, 1);
633.5420 +				}
633.5421 +			}
633.5422 +		});
633.5423 +
633.5424 +		// start the next in the queue if the last step wasn't forced
633.5425 +		if ( !gotoEnd ) {
633.5426 +			this.dequeue();
633.5427 +		}
633.5428 +
633.5429 +		return this;
633.5430 +	}
633.5431 +
633.5432 +});
633.5433 +
633.5434 +// Generate shortcuts for custom animations
633.5435 +jQuery.each({
633.5436 +	slideDown: genFx("show", 1),
633.5437 +	slideUp: genFx("hide", 1),
633.5438 +	slideToggle: genFx("toggle", 1),
633.5439 +	fadeIn: { opacity: "show" },
633.5440 +	fadeOut: { opacity: "hide" }
633.5441 +}, function( name, props ) {
633.5442 +	jQuery.fn[ name ] = function( speed, callback ) {
633.5443 +		return this.animate( props, speed, callback );
633.5444 +	};
633.5445 +});
633.5446 +
633.5447 +jQuery.extend({
633.5448 +	speed: function( speed, easing, fn ) {
633.5449 +		var opt = speed && typeof speed === "object" ? speed : {
633.5450 +			complete: fn || !fn && easing ||
633.5451 +				jQuery.isFunction( speed ) && speed,
633.5452 +			duration: speed,
633.5453 +			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
633.5454 +		};
633.5455 +
633.5456 +		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
633.5457 +			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
633.5458 +
633.5459 +		// Queueing
633.5460 +		opt.old = opt.complete;
633.5461 +		opt.complete = function() {
633.5462 +			if ( opt.queue !== false ) {
633.5463 +				jQuery(this).dequeue();
633.5464 +			}
633.5465 +			if ( jQuery.isFunction( opt.old ) ) {
633.5466 +				opt.old.call( this );
633.5467 +			}
633.5468 +		};
633.5469 +
633.5470 +		return opt;
633.5471 +	},
633.5472 +
633.5473 +	easing: {
633.5474 +		linear: function( p, n, firstNum, diff ) {
633.5475 +			return firstNum + diff * p;
633.5476 +		},
633.5477 +		swing: function( p, n, firstNum, diff ) {
633.5478 +			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
633.5479 +		}
633.5480 +	},
633.5481 +
633.5482 +	timers: [],
633.5483 +
633.5484 +	fx: function( elem, options, prop ) {
633.5485 +		this.options = options;
633.5486 +		this.elem = elem;
633.5487 +		this.prop = prop;
633.5488 +
633.5489 +		if ( !options.orig ) {
633.5490 +			options.orig = {};
633.5491 +		}
633.5492 +	}
633.5493 +
633.5494 +});
633.5495 +
633.5496 +jQuery.fx.prototype = {
633.5497 +	// Simple function for setting a style value
633.5498 +	update: function() {
633.5499 +		if ( this.options.step ) {
633.5500 +			this.options.step.call( this.elem, this.now, this );
633.5501 +		}
633.5502 +
633.5503 +		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
633.5504 +
633.5505 +		// Set display property to block for height/width animations
633.5506 +		if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
633.5507 +			this.elem.style.display = "block";
633.5508 +		}
633.5509 +	},
633.5510 +
633.5511 +	// Get the current size
633.5512 +	cur: function( force ) {
633.5513 +		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
633.5514 +			return this.elem[ this.prop ];
633.5515 +		}
633.5516 +
633.5517 +		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
633.5518 +		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
633.5519 +	},
633.5520 +
633.5521 +	// Start an animation from one number to another
633.5522 +	custom: function( from, to, unit ) {
633.5523 +		this.startTime = now();
633.5524 +		this.start = from;
633.5525 +		this.end = to;
633.5526 +		this.unit = unit || this.unit || "px";
633.5527 +		this.now = this.start;
633.5528 +		this.pos = this.state = 0;
633.5529 +
633.5530 +		var self = this;
633.5531 +		function t( gotoEnd ) {
633.5532 +			return self.step(gotoEnd);
633.5533 +		}
633.5534 +
633.5535 +		t.elem = this.elem;
633.5536 +
633.5537 +		if ( t() && jQuery.timers.push(t) && !timerId ) {
633.5538 +			timerId = setInterval(jQuery.fx.tick, 13);
633.5539 +		}
633.5540 +	},
633.5541 +
633.5542 +	// Simple 'show' function
633.5543 +	show: function() {
633.5544 +		// Remember where we started, so that we can go back to it later
633.5545 +		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
633.5546 +		this.options.show = true;
633.5547 +
633.5548 +		// Begin the animation
633.5549 +		// Make sure that we start at a small width/height to avoid any
633.5550 +		// flash of content
633.5551 +		this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
633.5552 +
633.5553 +		// Start by showing the element
633.5554 +		jQuery( this.elem ).show();
633.5555 +	},
633.5556 +
633.5557 +	// Simple 'hide' function
633.5558 +	hide: function() {
633.5559 +		// Remember where we started, so that we can go back to it later
633.5560 +		this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
633.5561 +		this.options.hide = true;
633.5562 +
633.5563 +		// Begin the animation
633.5564 +		this.custom(this.cur(), 0);
633.5565 +	},
633.5566 +
633.5567 +	// Each step of an animation
633.5568 +	step: function( gotoEnd ) {
633.5569 +		var t = now(), done = true;
633.5570 +
633.5571 +		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
633.5572 +			this.now = this.end;
633.5573 +			this.pos = this.state = 1;
633.5574 +			this.update();
633.5575 +
633.5576 +			this.options.curAnim[ this.prop ] = true;
633.5577 +
633.5578 +			for ( var i in this.options.curAnim ) {
633.5579 +				if ( this.options.curAnim[i] !== true ) {
633.5580 +					done = false;
633.5581 +				}
633.5582 +			}
633.5583 +
633.5584 +			if ( done ) {
633.5585 +				if ( this.options.display != null ) {
633.5586 +					// Reset the overflow
633.5587 +					this.elem.style.overflow = this.options.overflow;
633.5588 +
633.5589 +					// Reset the display
633.5590 +					var old = jQuery.data(this.elem, "olddisplay");
633.5591 +					this.elem.style.display = old ? old : this.options.display;
633.5592 +
633.5593 +					if ( jQuery.css(this.elem, "display") === "none" ) {
633.5594 +						this.elem.style.display = "block";
633.5595 +					}
633.5596 +				}
633.5597 +
633.5598 +				// Hide the element if the "hide" operation was done
633.5599 +				if ( this.options.hide ) {
633.5600 +					jQuery(this.elem).hide();
633.5601 +				}
633.5602 +
633.5603 +				// Reset the properties, if the item has been hidden or shown
633.5604 +				if ( this.options.hide || this.options.show ) {
633.5605 +					for ( var p in this.options.curAnim ) {
633.5606 +						jQuery.style(this.elem, p, this.options.orig[p]);
633.5607 +					}
633.5608 +				}
633.5609 +
633.5610 +				// Execute the complete function
633.5611 +				this.options.complete.call( this.elem );
633.5612 +			}
633.5613 +
633.5614 +			return false;
633.5615 +
633.5616 +		} else {
633.5617 +			var n = t - this.startTime;
633.5618 +			this.state = n / this.options.duration;
633.5619 +
633.5620 +			// Perform the easing function, defaults to swing
633.5621 +			var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
633.5622 +			var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
633.5623 +			this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
633.5624 +			this.now = this.start + ((this.end - this.start) * this.pos);
633.5625 +
633.5626 +			// Perform the next step of the animation
633.5627 +			this.update();
633.5628 +		}
633.5629 +
633.5630 +		return true;
633.5631 +	}
633.5632 +};
633.5633 +
633.5634 +jQuery.extend( jQuery.fx, {
633.5635 +	tick: function() {
633.5636 +		var timers = jQuery.timers;
633.5637 +
633.5638 +		for ( var i = 0; i < timers.length; i++ ) {
633.5639 +			if ( !timers[i]() ) {
633.5640 +				timers.splice(i--, 1);
633.5641 +			}
633.5642 +		}
633.5643 +
633.5644 +		if ( !timers.length ) {
633.5645 +			jQuery.fx.stop();
633.5646 +		}
633.5647 +	},
633.5648 +		
633.5649 +	stop: function() {
633.5650 +		clearInterval( timerId );
633.5651 +		timerId = null;
633.5652 +	},
633.5653 +	
633.5654 +	speeds: {
633.5655 +		slow: 600,
633.5656 + 		fast: 200,
633.5657 + 		// Default speed
633.5658 + 		_default: 400
633.5659 +	},
633.5660 +
633.5661 +	step: {
633.5662 +		opacity: function( fx ) {
633.5663 +			jQuery.style(fx.elem, "opacity", fx.now);
633.5664 +		},
633.5665 +
633.5666 +		_default: function( fx ) {
633.5667 +			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
633.5668 +				fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
633.5669 +			} else {
633.5670 +				fx.elem[ fx.prop ] = fx.now;
633.5671 +			}
633.5672 +		}
633.5673 +	}
633.5674 +});
633.5675 +
633.5676 +if ( jQuery.expr && jQuery.expr.filters ) {
633.5677 +	jQuery.expr.filters.animated = function( elem ) {
633.5678 +		return jQuery.grep(jQuery.timers, function( fn ) {
633.5679 +			return elem === fn.elem;
633.5680 +		}).length;
633.5681 +	};
633.5682 +}
633.5683 +
633.5684 +function genFx( type, num ) {
633.5685 +	var obj = {};
633.5686 +
633.5687 +	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
633.5688 +		obj[ this ] = type;
633.5689 +	});
633.5690 +
633.5691 +	return obj;
633.5692 +}
633.5693 +if ( "getBoundingClientRect" in document.documentElement ) {
633.5694 +	jQuery.fn.offset = function( options ) {
633.5695 +		var elem = this[0];
633.5696 +
633.5697 +		if ( !elem || !elem.ownerDocument ) {
633.5698 +			return null;
633.5699 +		}
633.5700 +
633.5701 +		if ( options ) { 
633.5702 +			return this.each(function( i ) {
633.5703 +				jQuery.offset.setOffset( this, options, i );
633.5704 +			});
633.5705 +		}
633.5706 +
633.5707 +		if ( elem === elem.ownerDocument.body ) {
633.5708 +			return jQuery.offset.bodyOffset( elem );
633.5709 +		}
633.5710 +
633.5711 +		var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
633.5712 +			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
633.5713 +			top  = box.top  + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
633.5714 +			left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
633.5715 +
633.5716 +		return { top: top, left: left };
633.5717 +	};
633.5718 +
633.5719 +} else {
633.5720 +	jQuery.fn.offset = function( options ) {
633.5721 +		var elem = this[0];
633.5722 +
633.5723 +		if ( !elem || !elem.ownerDocument ) {
633.5724 +			return null;
633.5725 +		}
633.5726 +
633.5727 +		if ( options ) { 
633.5728 +			return this.each(function( i ) {
633.5729 +				jQuery.offset.setOffset( this, options, i );
633.5730 +			});
633.5731 +		}
633.5732 +
633.5733 +		if ( elem === elem.ownerDocument.body ) {
633.5734 +			return jQuery.offset.bodyOffset( elem );
633.5735 +		}
633.5736 +
633.5737 +		jQuery.offset.initialize();
633.5738 +
633.5739 +		var offsetParent = elem.offsetParent, prevOffsetParent = elem,
633.5740 +			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
633.5741 +			body = doc.body, defaultView = doc.defaultView,
633.5742 +			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
633.5743 +			top = elem.offsetTop, left = elem.offsetLeft;
633.5744 +
633.5745 +		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
633.5746 +			if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
633.5747 +				break;
633.5748 +			}
633.5749 +
633.5750 +			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
633.5751 +			top  -= elem.scrollTop;
633.5752 +			left -= elem.scrollLeft;
633.5753 +
633.5754 +			if ( elem === offsetParent ) {
633.5755 +				top  += elem.offsetTop;
633.5756 +				left += elem.offsetLeft;
633.5757 +
633.5758 +				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
633.5759 +					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
633.5760 +					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
633.5761 +				}
633.5762 +
633.5763 +				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
633.5764 +			}
633.5765 +
633.5766 +			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
633.5767 +				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
633.5768 +				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
633.5769 +			}
633.5770 +
633.5771 +			prevComputedStyle = computedStyle;
633.5772 +		}
633.5773 +
633.5774 +		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
633.5775 +			top  += body.offsetTop;
633.5776 +			left += body.offsetLeft;
633.5777 +		}
633.5778 +
633.5779 +		if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
633.5780 +			top  += Math.max( docElem.scrollTop, body.scrollTop );
633.5781 +			left += Math.max( docElem.scrollLeft, body.scrollLeft );
633.5782 +		}
633.5783 +
633.5784 +		return { top: top, left: left };
633.5785 +	};
633.5786 +}
633.5787 +
633.5788 +jQuery.offset = {
633.5789 +	initialize: function() {
633.5790 +		var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
633.5791 +			html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
633.5792 +
633.5793 +		jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
633.5794 +
633.5795 +		container.innerHTML = html;
633.5796 +		body.insertBefore( container, body.firstChild );
633.5797 +		innerDiv = container.firstChild;
633.5798 +		checkDiv = innerDiv.firstChild;
633.5799 +		td = innerDiv.nextSibling.firstChild.firstChild;
633.5800 +
633.5801 +		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
633.5802 +		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
633.5803 +
633.5804 +		checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
633.5805 +		// safari subtracts parent border width here which is 5px
633.5806 +		this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
633.5807 +		checkDiv.style.position = checkDiv.style.top = "";
633.5808 +
633.5809 +		innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
633.5810 +		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
633.5811 +
633.5812 +		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
633.5813 +
633.5814 +		body.removeChild( container );
633.5815 +		body = container = innerDiv = checkDiv = table = td = null;
633.5816 +		jQuery.offset.initialize = jQuery.noop;
633.5817 +	},
633.5818 +
633.5819 +	bodyOffset: function( body ) {
633.5820 +		var top = body.offsetTop, left = body.offsetLeft;
633.5821 +
633.5822 +		jQuery.offset.initialize();
633.5823 +
633.5824 +		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
633.5825 +			top  += parseFloat( jQuery.curCSS(body, "marginTop",  true) ) || 0;
633.5826 +			left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
633.5827 +		}
633.5828 +
633.5829 +		return { top: top, left: left };
633.5830 +	},
633.5831 +	
633.5832 +	setOffset: function( elem, options, i ) {
633.5833 +		// set position first, in-case top/left are set even on static elem
633.5834 +		if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
633.5835 +			elem.style.position = "relative";
633.5836 +		}
633.5837 +		var curElem   = jQuery( elem ),
633.5838 +			curOffset = curElem.offset(),
633.5839 +			curTop    = parseInt( jQuery.curCSS( elem, "top",  true ), 10 ) || 0,
633.5840 +			curLeft   = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
633.5841 +
633.5842 +		if ( jQuery.isFunction( options ) ) {
633.5843 +			options = options.call( elem, i, curOffset );
633.5844 +		}
633.5845 +
633.5846 +		var props = {
633.5847 +			top:  (options.top  - curOffset.top)  + curTop,
633.5848 +			left: (options.left - curOffset.left) + curLeft
633.5849 +		};
633.5850 +		
633.5851 +		if ( "using" in options ) {
633.5852 +			options.using.call( elem, props );
633.5853 +		} else {
633.5854 +			curElem.css( props );
633.5855 +		}
633.5856 +	}
633.5857 +};
633.5858 +
633.5859 +
633.5860 +jQuery.fn.extend({
633.5861 +	position: function() {
633.5862 +		if ( !this[0] ) {
633.5863 +			return null;
633.5864 +		}
633.5865 +
633.5866 +		var elem = this[0],
633.5867 +
633.5868 +		// Get *real* offsetParent
633.5869 +		offsetParent = this.offsetParent(),
633.5870 +
633.5871 +		// Get correct offsets
633.5872 +		offset       = this.offset(),
633.5873 +		parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
633.5874 +
633.5875 +		// Subtract element margins
633.5876 +		// note: when an element has margin: auto the offsetLeft and marginLeft
633.5877 +		// are the same in Safari causing offset.left to incorrectly be 0
633.5878 +		offset.top  -= parseFloat( jQuery.curCSS(elem, "marginTop",  true) ) || 0;
633.5879 +		offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
633.5880 +
633.5881 +		// Add offsetParent borders
633.5882 +		parentOffset.top  += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth",  true) ) || 0;
633.5883 +		parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
633.5884 +
633.5885 +		// Subtract the two offsets
633.5886 +		return {
633.5887 +			top:  offset.top  - parentOffset.top,
633.5888 +			left: offset.left - parentOffset.left
633.5889 +		};
633.5890 +	},
633.5891 +
633.5892 +	offsetParent: function() {
633.5893 +		return this.map(function() {
633.5894 +			var offsetParent = this.offsetParent || document.body;
633.5895 +			while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
633.5896 +				offsetParent = offsetParent.offsetParent;
633.5897 +			}
633.5898 +			return offsetParent;
633.5899 +		});
633.5900 +	}
633.5901 +});
633.5902 +
633.5903 +
633.5904 +// Create scrollLeft and scrollTop methods
633.5905 +jQuery.each( ["Left", "Top"], function( i, name ) {
633.5906 +	var method = "scroll" + name;
633.5907 +
633.5908 +	jQuery.fn[ method ] = function(val) {
633.5909 +		var elem = this[0], win;
633.5910 +		
633.5911 +		if ( !elem ) {
633.5912 +			return null;
633.5913 +		}
633.5914 +
633.5915 +		if ( val !== undefined ) {
633.5916 +			// Set the scroll offset
633.5917 +			return this.each(function() {
633.5918 +				win = getWindow( this );
633.5919 +
633.5920 +				if ( win ) {
633.5921 +					win.scrollTo(
633.5922 +						!i ? val : jQuery(win).scrollLeft(),
633.5923 +						 i ? val : jQuery(win).scrollTop()
633.5924 +					);
633.5925 +
633.5926 +				} else {
633.5927 +					this[ method ] = val;
633.5928 +				}
633.5929 +			});
633.5930 +		} else {
633.5931 +			win = getWindow( elem );
633.5932 +
633.5933 +			// Return the scroll offset
633.5934 +			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
633.5935 +				jQuery.support.boxModel && win.document.documentElement[ method ] ||
633.5936 +					win.document.body[ method ] :
633.5937 +				elem[ method ];
633.5938 +		}
633.5939 +	};
633.5940 +});
633.5941 +
633.5942 +function getWindow( elem ) {
633.5943 +	return ("scrollTo" in elem && elem.document) ?
633.5944 +		elem :
633.5945 +		elem.nodeType === 9 ?
633.5946 +			elem.defaultView || elem.parentWindow :
633.5947 +			false;
633.5948 +}
633.5949 +// Create innerHeight, innerWidth, outerHeight and outerWidth methods
633.5950 +jQuery.each([ "Height", "Width" ], function( i, name ) {
633.5951 +
633.5952 +	var type = name.toLowerCase();
633.5953 +
633.5954 +	// innerHeight and innerWidth
633.5955 +	jQuery.fn["inner" + name] = function() {
633.5956 +		return this[0] ?
633.5957 +			jQuery.css( this[0], type, false, "padding" ) :
633.5958 +			null;
633.5959 +	};
633.5960 +
633.5961 +	// outerHeight and outerWidth
633.5962 +	jQuery.fn["outer" + name] = function( margin ) {
633.5963 +		return this[0] ?
633.5964 +			jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
633.5965 +			null;
633.5966 +	};
633.5967 +
633.5968 +	jQuery.fn[ type ] = function( size ) {
633.5969 +		// Get window width or height
633.5970 +		var elem = this[0];
633.5971 +		if ( !elem ) {
633.5972 +			return size == null ? null : this;
633.5973 +		}
633.5974 +
633.5975 +		return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
633.5976 +			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
633.5977 +			elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
633.5978 +			elem.document.body[ "client" + name ] :
633.5979 +
633.5980 +			// Get document width or height
633.5981 +			(elem.nodeType === 9) ? // is it a document
633.5982 +				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
633.5983 +				Math.max(
633.5984 +					elem.documentElement["client" + name],
633.5985 +					elem.body["scroll" + name], elem.documentElement["scroll" + name],
633.5986 +					elem.body["offset" + name], elem.documentElement["offset" + name]
633.5987 +				) :
633.5988 +
633.5989 +				// Get or set width or height on the element
633.5990 +				size === undefined ?
633.5991 +					// Get width or height on the element
633.5992 +					jQuery.css( elem, type ) :
633.5993 +
633.5994 +					// Set the width or height on the element (default to pixels if value is unitless)
633.5995 +					this.css( type, typeof size === "string" ? size : size + "px" );
633.5996 +	};
633.5997 +
633.5998 +});
633.5999 +// Expose jQuery to the global object
633.6000 +window.jQuery = window.$ = jQuery;
633.6001 +
633.6002 +})(window);
   634.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   634.2 +++ b/web/static/js/cluetip-1.0.6/lib/jquery.bgiframe.min.js	Mon Apr 26 11:16:23 2010 +0200
   634.3 @@ -0,0 +1,10 @@
   634.4 +/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
   634.5 + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
   634.6 + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
   634.7 + *
   634.8 + * $LastChangedDate: 2021-07-21 19:45:56 -0400 (Sat, 21 Jul 2021) $
   634.9 + * $Rev: 2447 $
  634.10 + *
  634.11 + * Version 2.1.1
  634.12 + */
  634.13 +(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};})(jQuery);
  634.14 \ No newline at end of file
   635.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   635.2 +++ b/web/static/js/cluetip-1.0.6/lib/jquery.hoverIntent.js	Mon Apr 26 11:16:23 2010 +0200
   635.3 @@ -0,0 +1,114 @@
   635.4 +/**
   635.5 +* hoverIntent is similar to jQuery's built-in "hover" function except that
   635.6 +* instead of firing the onMouseOver event immediately, hoverIntent checks
   635.7 +* to see if the user's mouse has slowed down (beneath the sensitivity
   635.8 +* threshold) before firing the onMouseOver event.
   635.9 +* 
  635.10 +* hoverIntent r5 // 2022.03.27 // jQuery 1.1.2
  635.11 +* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
  635.12 +* 
  635.13 +* hoverIntent is currently available for use in all personal or commercial 
  635.14 +* projects under both MIT and GPL licenses. This means that you can choose 
  635.15 +* the license that best suits your project, and use it accordingly.
  635.16 +* 
  635.17 +* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
  635.18 +* $("ul li").hoverIntent( showNav , hideNav );
  635.19 +* 
  635.20 +* // advanced usage receives configuration object only
  635.21 +* $("ul li").hoverIntent({
  635.22 +*	sensitivity: 2, // number = sensitivity threshold (must be 1 or higher)
  635.23 +*	interval: 50,   // number = milliseconds of polling interval
  635.24 +*	over: showNav,  // function = onMouseOver callback (required)
  635.25 +*	timeout: 100,   // number = milliseconds delay before onMouseOut function call
  635.26 +*	out: hideNav    // function = onMouseOut callback (required)
  635.27 +* });
  635.28 +* 
  635.29 +* @param  f  onMouseOver function || An object with configuration options
  635.30 +* @param  g  onMouseOut function  || Nothing (use configuration options object)
  635.31 +* @return    The object (aka "this") that called hoverIntent, and the event object
  635.32 +* @author    Brian Cherne <[email protected]>
  635.33 +* 
  635.34 +* modified by Karl Swedberg. Namespaced events in order to work better with clueTip plugin
  635.35 +*/
  635.36 +(function($) {
  635.37 +	$.fn.hoverIntent = function(f,g) {
  635.38 +		// default configuration options
  635.39 +		var cfg = {
  635.40 +			sensitivity: 7,
  635.41 +			interval: 100,
  635.42 +			timeout: 0
  635.43 +		};
  635.44 +		// override configuration options with user supplied object
  635.45 +		cfg = $.extend(cfg, g ? { over: f, out: g } : f );
  635.46 +
  635.47 +		// instantiate variables
  635.48 +		// cX, cY = current X and Y position of mouse, updated by mousemove event
  635.49 +		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
  635.50 +		var cX, cY, pX, pY;
  635.51 +
  635.52 +		// A private function for getting mouse position
  635.53 +		var track = function(ev) {
  635.54 +			cX = ev.pageX;
  635.55 +			cY = ev.pageY;
  635.56 +		};
  635.57 +
  635.58 +		// A private function for comparing current and previous mouse position
  635.59 +		var compare = function(ev,ob) {
  635.60 +			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
  635.61 +			// compare mouse positions to see if they've crossed the threshold
  635.62 +			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
  635.63 +				$(ob).unbind("mousemove",track);
  635.64 +				// set hoverIntent state to true (so mouseOut can be called)
  635.65 +				ob.hoverIntent_s = 1;
  635.66 +				return cfg.over.apply(ob,[ev]);
  635.67 +			} else {
  635.68 +				// set previous coordinates for next time
  635.69 +				pX = cX; pY = cY;
  635.70 +				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
  635.71 +				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
  635.72 +			}
  635.73 +		};
  635.74 +
  635.75 +		// A private function for delaying the mouseOut function
  635.76 +		var delay = function(ev,ob) {
  635.77 +			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
  635.78 +			ob.hoverIntent_s = 0;
  635.79 +			return cfg.out.apply(ob,[ev]);
  635.80 +		};
  635.81 +
  635.82 +		// A private function for handling mouse 'hovering'
  635.83 +		var handleHover = function(e) {
  635.84 +			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
  635.85 +			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
  635.86 +			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
  635.87 +			if ( p == this ) { return false; }
  635.88 +
  635.89 +			// copy objects to be passed into t (required for event object to be passed in IE)
  635.90 +			var ev = jQuery.extend({},e);
  635.91 +			var ob = this;
  635.92 +
  635.93 +			// cancel hoverIntent timer if it exists
  635.94 +			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
  635.95 +
  635.96 +			// else e.type == "onmouseover"
  635.97 +			if (e.type == "mouseover") {
  635.98 +				// set "previous" X and Y position based on initial entry point
  635.99 +				pX = ev.pageX; pY = ev.pageY;
 635.100 +				// update "current" X and Y position based on mousemove
 635.101 +				$(ob).bind("mousemove.cluetip",track);
 635.102 +				// start polling interval (self-calling timeout) to compare mouse coordinates over time
 635.103 +				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
 635.104 +
 635.105 +			// else e.type == "onmouseout"
 635.106 +			} else {
 635.107 +				// unbind expensive mousemove event
 635.108 +				$(ob).unbind("mousemove.cluetip",track);
 635.109 +				// if hoverIntent state is true, then call the mouseOut function after the specified delay
 635.110 +				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
 635.111 +			}
 635.112 +		};
 635.113 +
 635.114 +		// bind the function to the two event listeners
 635.115 +		return this.bind('mouseover.cluetip', handleHover).bind('mouseout.cluetip', handleHover);
 635.116 +	};
 635.117 +})(jQuery);
 635.118 \ No newline at end of file
   636.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   636.2 +++ b/web/static/js/cluetip-1.0.6/sdemo.html	Mon Apr 26 11:16:23 2010 +0200
   636.3 @@ -0,0 +1,47 @@
   636.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
   636.5 +<html>
   636.6 +  <head>
   636.7 +    <title>Prova</title>
   636.8 +    <link href="cluetip/jquery.cluetip.css" rel="stylesheet" type="text/css" media="screen" />
   636.9 +  </head>
  636.10 +
  636.11 +  <body>
  636.12 +    <h1>Test</h1>
  636.13 +
  636.14 +
  636.15 +  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script>  
  636.16 +  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>  
  636.17 +  <script type="text/javascript" src="cluetip/lib/jquery.hoverIntent.js"></script>
  636.18 +  <script type="text/javascript" src="cluetip/lib/jquery.bgiframe.min.js"></script>
  636.19 +  <script type="text/javascript" src="cluetip/jquery.cluetip.js"></script>
  636.20 +
  636.21 +<a class="title" href="#" title="This is the title|The first set of contents comes after the first delimiter in the title.|In this case, the delimiter is a pipe">
  636.22 +
  636.23 +Chi ben <a href="#" title"Comincium|Gia sem chi">incomincia</a>
  636.24 +
  636.25 +<table>
  636.26 +       <tr>
  636.27 +	 <td class="title" title="Versione di logon.conf|
  636.28 +    NOTA per WIN98: il numero di versione DEVE ESSERE INCREMENTATO
  636.29 +    AD OGNI MODIFICA di logon.conf se si vuole che il client Win98
  636.30 +    aggiorni i parametri di registro già precedentemente settati)">Versione</td>  
  636.31 +	 <td></td>  
  636.32 +       </tr>
  636.33 +</table>
  636.34 +
  636.35 +
  636.36 +<script>
  636.37 +$(document).ready(function () {
  636.38 +
  636.39 +  $('td.title').cluetip({splitTitle: '|',  });
  636.40 +  $('a.title').cluetip();
  636.41 +});
  636.42 +</script>
  636.43 +    <hr>
  636.44 +    <address><a href="mailto:sandro@ubuntu">Sandro Dentella</a></address>
  636.45 +<!-- Created: Thu Feb  4 15:26:02 CET 2010 -->
  636.46 +<!-- hhmts start -->
  636.47 +Last modified: Thu Feb  4 16:05:29 CET 2010
  636.48 +<!-- hhmts end -->
  636.49 +  </body>
  636.50 +</html>
   637.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   637.2 +++ b/web/static/js/jquery-ui.min.js	Mon Apr 26 11:16:23 2010 +0200
   637.3 @@ -0,0 +1,9 @@
   637.4 +/*
   637.5 + * jQuery UI 1.7.2
   637.6 + *
   637.7 + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
   637.8 + * Dual licensed under the MIT (MIT-LICENSE.txt)
   637.9 + * and GPL (GPL-LICENSE.txt) licenses.
  637.10 + *
  637.11 + * http://docs.jquery.com/UI
  637.12 + */
  637.13 jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.2",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);(function(a){a.widget("ui.draggable",a.extend({},a.ui.mouse,{_init:function(){if(this.options.helper=="original"&&!(/^(?:r|a|f)/).test(this.element.css("position"))){this.element[0].style.position="relative"}(this.options.addClasses&&this.element.addClass("ui-draggable"));(this.options.disabled&&this.element.addClass("ui-draggable-disabled"));this._mouseInit()},destroy:function(){if(!this.element.data("draggable")){return}this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy()},_mouseCapture:function(b){var c=this.options;if(this.helper||c.disabled||a(b.target).is(".ui-resizable-handle")){return false}this.handle=this._getHandle(b);if(!this.handle){return false}return true},_mouseStart:function(b){var c=this.options;this.helper=this._createHelper(b);this._cacheHelperProportions();if(a.ui.ddmanager){a.ui.ddmanager.current=this}this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(b);this.originalPageX=b.pageX;this.originalPageY=b.pageY;if(c.cursorAt){this._adjustOffsetFromHelper(c.cursorAt)}if(c.containment){this._setContainment()}this._trigger("start",b);this._cacheHelperProportions();if(a.ui.ddmanager&&!c.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,b)}this.helper.addClass("ui-draggable-dragging");this._mouseDrag(b,true);return true},_mouseDrag:function(b,d){this.position=this._generatePosition(b);this.positionAbs=this._convertPositionTo("absolute");if(!d){var c=this._uiHash();this._trigger("drag",b,c);this.position=c.position}if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}if(a.ui.ddmanager){a.ui.ddmanager.drag(this,b)}return false},_mouseStop:function(c){var d=false;if(a.ui.ddmanager&&!this.options.dropBehaviour){d=a.ui.ddmanager.drop(this,c)}if(this.dropped){d=this.dropped;this.dropped=false}if((this.options.revert=="invalid"&&!d)||(this.options.revert=="valid"&&d)||this.options.revert===true||(a.isFunction(this.options.revert)&&this.options.revert.call(this.element,d))){var b=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){b._trigger("stop",c);b._clear()})}else{this._trigger("stop",c);this._clear()}return false},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?true:false;a(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==b.target){c=true}});return c},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c])):(d.helper=="clone"?this.element.clone():this.element);if(!b.parents("body").length){b.appendTo((d.appendTo=="parent"?this.element[0].parentNode:d.appendTo))}if(b[0]!=this.element[0]&&!(/(fixed|absolute)/).test(b.css("position"))){b.css("position","absolute")}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.element.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.element.css("marginLeft"),10)||0),top:(parseInt(this.element.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)&&e.containment.constructor!=Array){var c=a(e.containment)[0];if(!c){return}var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}else{if(e.containment.constructor==Array){this.containment=e.containment}}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");if(this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval){this.helper.remove()}this.helper=null;this.cancelHelperRemoval=false},_trigger:function(b,c,d){d=d||this._uiHash();a.ui.plugin.call(this,b,[c,d]);if(b=="drag"){this.positionAbs=this._convertPositionTo("absolute")}return a.widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(b){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,offset:this.positionAbs}}}));a.extend(a.ui.draggable,{version:"1.7.2",eventPrefix:"drag",defaults:{addClasses:true,appendTo:"parent",axis:false,cancel:":input,option",connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false}});a.ui.plugin.add("draggable","connectToSortable",{start:function(c,e){var d=a(this).data("draggable"),f=d.options,b=a.extend({},e,{item:d.element});d.sortables=[];a(f.connectToSortable).each(function(){var g=a.data(this,"sortable");if(g&&!g.options.disabled){d.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",c,b)}})},stop:function(c,e){var d=a(this).data("draggable"),b=a.extend({},e,{item:d.element});a.each(d.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;d.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert){this.instance.options.revert=true}this.instance._mouseStop(c);this.instance.options.helper=this.instance.options._helper;if(d.options.helper=="original"){this.instance.currentItem.css({top:"auto",left:"auto"})}}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",c,b)}})},drag:function(c,f){var e=a(this).data("draggable"),b=this;var d=function(i){var n=this.offset.click.top,m=this.offset.click.left;var g=this.positionAbs.top,k=this.positionAbs.left;var j=i.height,l=i.width;var p=i.top,h=i.left;return a.ui.isOver(g+n,k+m,p,h,j,l)};a.each(e.sortables,function(g){this.instance.positionAbs=e.positionAbs;this.instance.helperProportions=e.helperProportions;this.instance.offset.click=e.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=a(b).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return f.helper[0]};c.target=this.instance.currentItem[0];this.instance._mouseCapture(c,true);this.instance._mouseStart(c,true,true);this.instance.offset.click.top=e.offset.click.top;this.instance.offset.click.left=e.offset.click.left;this.instance.offset.parent.left-=e.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=e.offset.parent.top-this.instance.offset.parent.top;e._trigger("toSortable",c);e.dropped=this.instance.element;e.currentItem=e.element;this.instance.fromOutside=e}if(this.instance.currentItem){this.instance._mouseDrag(c)}}else{if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",c,this.instance._uiHash(this.instance));this.instance._mouseStop(c,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();if(this.instance.placeholder){this.instance.placeholder.remove()}e._trigger("fromSortable",c);e.dropped=false}}})}});a.ui.plugin.add("draggable","cursor",{start:function(c,d){var b=a("body"),e=a(this).data("draggable").options;if(b.css("cursor")){e._cursor=b.css("cursor")}b.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._cursor){a("body").css("cursor",d._cursor)}}});a.ui.plugin.add("draggable","iframeFix",{start:function(b,c){var d=a(this).data("draggable").options;a(d.iframeFix===true?"iframe":d.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1000}).css(a(this).offset()).appendTo("body")})},stop:function(b,c){a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});a.ui.plugin.add("draggable","opacity",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("opacity")){e._opacity=b.css("opacity")}b.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._opacity){a(c.helper).css("opacity",d._opacity)}}});a.ui.plugin.add("draggable","scroll",{start:function(c,d){var b=a(this).data("draggable");if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){b.overflowOffset=b.scrollParent.offset()}},drag:function(d,e){var c=a(this).data("draggable"),f=c.options,b=false;if(c.scrollParent[0]!=document&&c.scrollParent[0].tagName!="HTML"){if(!f.axis||f.axis!="x"){if((c.overflowOffset.top+c.scrollParent[0].offsetHeight)-d.pageY<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop+f.scrollSpeed}else{if(d.pageY-c.overflowOffset.top<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop-f.scrollSpeed}}}if(!f.axis||f.axis!="y"){if((c.overflowOffset.left+c.scrollParent[0].offsetWidth)-d.pageX<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft+f.scrollSpeed}else{if(d.pageX-c.overflowOffset.left<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft-f.scrollSpeed}}}}else{if(!f.axis||f.axis!="x"){if(d.pageY-a(document).scrollTop()<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-f.scrollSpeed)}else{if(a(window).height()-(d.pageY-a(document).scrollTop())<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+f.scrollSpeed)}}}if(!f.axis||f.axis!="y"){if(d.pageX-a(document).scrollLeft()<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-f.scrollSpeed)}else{if(a(window).width()-(d.pageX-a(document).scrollLeft())<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+f.scrollSpeed)}}}}if(b!==false&&a.ui.ddmanager&&!f.dropBehaviour){a.ui.ddmanager.prepareOffsets(c,d)}}});a.ui.plugin.add("draggable","snap",{start:function(c,d){var b=a(this).data("draggable"),e=b.options;b.snapElements=[];a(e.snap.constructor!=String?(e.snap.items||":data(draggable)"):e.snap).each(function(){var g=a(this);var f=g.offset();if(this!=b.element[0]){b.snapElements.push({item:this,width:g.outerWidth(),height:g.outerHeight(),top:f.top,left:f.left})}})},drag:function(u,p){var g=a(this).data("draggable"),q=g.options;var y=q.snapTolerance;var x=p.offset.left,w=x+g.helperProportions.width,f=p.offset.top,e=f+g.helperProportions.height;for(var v=g.snapElements.length-1;v>=0;v--){var s=g.snapElements[v].left,n=s+g.snapElements[v].width,m=g.snapElements[v].top,A=m+g.snapElements[v].height;if(!((s-y<x&&x<n+y&&m-y<f&&f<A+y)||(s-y<x&&x<n+y&&m-y<e&&e<A+y)||(s-y<w&&w<n+y&&m-y<f&&f<A+y)||(s-y<w&&w<n+y&&m-y<e&&e<A+y))){if(g.snapElements[v].snapping){(g.options.snap.release&&g.options.snap.release.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=false;continue}if(q.snapMode!="inner"){var c=Math.abs(m-e)<=y;var z=Math.abs(A-f)<=y;var j=Math.abs(s-w)<=y;var k=Math.abs(n-x)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m-g.helperProportions.height,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s-g.helperProportions.width}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n}).left-g.margins.left}}var h=(c||z||j||k);if(q.snapMode!="outer"){var c=Math.abs(m-f)<=y;var z=Math.abs(A-e)<=y;var j=Math.abs(s-x)<=y;var k=Math.abs(n-w)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A-g.helperProportions.height,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n-g.helperProportions.width}).left-g.margins.left}}if(!g.snapElements[v].snapping&&(c||z||j||k||h)){(g.options.snap.snap&&g.options.snap.snap.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=(c||z||j||k||h)}}});a.ui.plugin.add("draggable","stack",{start:function(b,c){var e=a(this).data("draggable").options;var d=a.makeArray(a(e.stack.group)).sort(function(g,f){return(parseInt(a(g).css("zIndex"),10)||e.stack.min)-(parseInt(a(f).css("zIndex"),10)||e.stack.min)});a(d).each(function(f){this.style.zIndex=e.stack.min+f});this[0].style.zIndex=e.stack.min+d.length}});a.ui.plugin.add("draggable","zIndex",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("zIndex")){e._zIndex=b.css("zIndex")}b.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._zIndex){a(c.helper).css("zIndex",d._zIndex)}}})})(jQuery);(function(a){a.widget("ui.droppable",{_init:function(){var c=this.options,b=c.accept;this.isover=0;this.isout=1;this.options.accept=this.options.accept&&a.isFunction(this.options.accept)?this.options.accept:function(e){return e.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};a.ui.ddmanager.droppables[this.options.scope]=a.ui.ddmanager.droppables[this.options.scope]||[];a.ui.ddmanager.droppables[this.options.scope].push(this);(this.options.addClasses&&this.element.addClass("ui-droppable"))},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++){if(b[c]==this){b.splice(c,1)}}this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable")},_setData:function(b,c){if(b=="accept"){this.options.accept=c&&a.isFunction(c)?c:function(e){return e.is(c)}}else{a.widget.prototype._setData.apply(this,arguments)}},_activate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.addClass(this.options.activeClass)}(b&&this._trigger("activate",c,this.ui(b)))},_deactivate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}(b&&this._trigger("deactivate",c,this.ui(b)))},_over:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.addClass(this.options.hoverClass)}this._trigger("over",c,this.ui(b))}},_out:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("out",c,this.ui(b))}},_drop:function(c,d){var b=d||a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return false}var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var f=a.data(this,"droppable");if(f.options.greedy&&a.ui.intersect(b,a.extend(f,{offset:f.element.offset()}),f.options.tolerance)){e=true;return false}});if(e){return false}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("drop",c,this.ui(b));return this.element}return false},ui:function(b){return{draggable:(b.currentItem||b.element),helper:b.helper,position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs}}});a.extend(a.ui.droppable,{version:"1.7.2",eventPrefix:"drop",defaults:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"}});a.ui.intersect=function(q,j,o){if(!j.offset){return false}var e=(q.positionAbs||q.position.absolute).left,d=e+q.helperProportions.width,n=(q.positionAbs||q.position.absolute).top,m=n+q.helperProportions.height;var g=j.offset.left,c=g+j.proportions.width,p=j.offset.top,k=p+j.proportions.height;switch(o){case"fit":return(g<e&&d<c&&p<n&&m<k);break;case"intersect":return(g<e+(q.helperProportions.width/2)&&d-(q.helperProportions.width/2)<c&&p<n+(q.helperProportions.height/2)&&m-(q.helperProportions.height/2)<k);break;case"pointer":var h=((q.positionAbs||q.position.absolute).left+(q.clickOffset||q.offset.click).left),i=((q.positionAbs||q.position.absolute).top+(q.clickOffset||q.offset.click).top),f=a.ui.isOver(i,h,p,g,j.proportions.height,j.proportions.width);return f;break;case"touch":return((n>=p&&n<=k)||(m>=p&&m<=k)||(n<p&&m>k))&&((e>=g&&e<=c)||(d>=g&&d<=c)||(e<g&&d>c));break;default:return false;break}};a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,g){var b=a.ui.ddmanager.droppables[e.options.scope];var f=g?g.type:null;var h=(e.currentItem||e.element).find(":data(droppable)").andSelf();droppablesLoop:for(var d=0;d<b.length;d++){if(b[d].options.disabled||(e&&!b[d].options.accept.call(b[d].element[0],(e.currentItem||e.element)))){continue}for(var c=0;c<h.length;c++){if(h[c]==b[d].element[0]){b[d].proportions.height=0;continue droppablesLoop}}b[d].visible=b[d].element.css("display")!="none";if(!b[d].visible){continue}b[d].offset=b[d].element.offset();b[d].proportions={width:b[d].element[0].offsetWidth,height:b[d].element[0].offsetHeight};if(f=="mousedown"){b[d]._activate.call(b[d],g)}}},drop:function(b,c){var d=false;a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(!this.options){return}if(!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)){d=this._drop.call(this,c)}if(!this.options.disabled&&this.visible&&this.options.accept.call(this.element[0],(b.currentItem||b.element))){this.isout=1;this.isover=0;this._deactivate.call(this,c)}});return d},drag:function(b,c){if(b.options.refreshPositions){a.ui.ddmanager.prepareOffsets(b,c)}a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(this.options.disabled||this.greedyChild||!this.visible){return}var e=a.ui.intersect(b,this,this.options.tolerance);var g=!e&&this.isover==1?"isout":(e&&this.isover==0?"isover":null);if(!g){return}var f;if(this.options.greedy){var d=this.element.parents(":data(droppable):eq(0)");if(d.length){f=a.data(d[0],"droppable");f.greedyChild=(g=="isover"?1:0)}}if(f&&g=="isover"){f.isover=0;f.isout=1;f._out.call(f,c)}this[g]=1;this[g=="isout"?"isover":"isout"]=0;this[g=="isover"?"_over":"_out"].call(this,c);if(f&&g=="isout"){f.isout=0;f.isover=1;f._over.call(f,c)}})}}})(jQuery);(function(c){c.widget("ui.resizable",c.extend({},c.ui.mouse,{_init:function(){var e=this,j=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(j.aspectRatio),aspectRatio:j.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:j.helper||j.ghost||j.animate?j.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){if(/relative/.test(this.element.css("position"))&&c.browser.opera){this.element.css({position:"relative",top:"auto",left:"auto"})}this.element.wrap(c('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=j.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var k=this.handles.split(",");this.handles={};for(var f=0;f<k.length;f++){var h=c.trim(k[f]),d="ui-resizable-"+h;var g=c('<div class="ui-resizable-handle '+d+'"></div>');if(/sw|se|ne|nw/.test(h)){g.css({zIndex:++j.zIndex})}if("se"==h){g.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[h]=".ui-resizable-"+h;this.element.append(g)}}this._renderAxis=function(p){p=p||this.element;for(var m in this.handles){if(this.handles[m].constructor==String){this.handles[m]=c(this.handles[m],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var n=c(this.handles[m],this.element),o=0;o=/sw|ne|nw|se|n|s/.test(m)?n.outerHeight():n.outerWidth();var l=["padding",/ne|nw|n/.test(m)?"Top":/se|sw|s/.test(m)?"Bottom":/^e$/.test(m)?"Right":"Left"].join("");p.css(l,o);this._proportionallyResize()}if(!c(this.handles[m]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!e.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}e.axis=i&&i[1]?i[1]:"se"}});if(j.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){c(this).removeClass("ui-resizable-autohide");e._handles.show()},function(){if(!e.resizing){c(this).addClass("ui-resizable-autohide");e._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var d=function(f){c(f).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){d(this.element);var e=this.element;e.parent().append(this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")})).end().remove()}this.originalElement.css("resize",this.originalResizeStyle);d(this.originalElement)},_mouseCapture:function(e){var f=false;for(var d in this.handles){if(c(this.handles[d])[0]==e.target){f=true}}return this.options.disabled||!!f},_mouseStart:function(f){var i=this.options,e=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(d.is(".ui-draggable")||(/absolute/).test(d.css("position"))){d.css({position:"absolute",top:e.top,left:e.left})}if(c.browser.opera&&(/relative/).test(d.css("position"))){d.css({position:"relative",top:"auto",left:"auto"})}this._renderProxy();var j=b(this.helper.css("left")),g=b(this.helper.css("top"));if(i.containment){j+=c(i.containment).scrollLeft()||0;g+=c(i.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:j,top:g};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:j,top:g};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:f.pageX,top:f.pageY};this.aspectRatio=(typeof i.aspectRatio=="number")?i.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var h=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",h=="auto"?this.axis+"-resize":h);d.addClass("ui-resizable-resizing");this._propagate("start",f);return true},_mouseDrag:function(d){var g=this.helper,f=this.options,l={},p=this,i=this.originalMousePosition,m=this.axis;var q=(d.pageX-i.left)||0,n=(d.pageY-i.top)||0;var h=this._change[m];if(!h){return false}var k=h.apply(this,[d,q,n]),j=c.browser.msie&&c.browser.version<7,e=this.sizeDiff;if(this._aspectRatio||d.shiftKey){k=this._updateRatio(k,d)}k=this._respectSize(k,d);this._propagate("resize",d);g.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(k);this._trigger("resize",d,this.ui());return false},_mouseStop:function(g){this.resizing=false;var h=this.options,l=this;if(this._helper){var f=this._proportionallyResizeElements,d=f.length&&(/textarea/i).test(f[0].nodeName),e=d&&c.ui.hasScroll(f[0],"left")?0:l.sizeDiff.height,j=d?0:l.sizeDiff.width;var m={width:(l.size.width-j),height:(l.size.height-e)},i=(parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left))||null,k=(parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top))||null;if(!h.animate){this.element.css(c.extend(m,{top:k,left:i}))}l.helper.height(l.size.height);l.helper.width(l.size.width);if(this._helper&&!h.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",g);if(this._helper){this.helper.remove()}return false},_updateCache:function(d){var e=this.options;this.offset=this.helper.offset();if(a(d.left)){this.position.left=d.left}if(a(d.top)){this.position.top=d.top}if(a(d.height)){this.size.height=d.height}if(a(d.width)){this.size.width=d.width}},_updateRatio:function(g,f){var h=this.options,i=this.position,e=this.size,d=this.axis;if(g.height){g.width=(e.height*this.aspectRatio)}else{if(g.width){g.height=(e.width/this.aspectRatio)}}if(d=="sw"){g.left=i.left+(e.width-g.width);g.top=null}if(d=="nw"){g.top=i.top+(e.height-g.height);g.left=i.left+(e.width-g.width)}return g},_respectSize:function(k,f){var i=this.helper,h=this.options,q=this._aspectRatio||f.shiftKey,p=this.axis,s=a(k.width)&&h.maxWidth&&(h.maxWidth<k.width),l=a(k.height)&&h.maxHeight&&(h.maxHeight<k.height),g=a(k.width)&&h.minWidth&&(h.minWidth>k.width),r=a(k.height)&&h.minHeight&&(h.minHeight>k.height);if(g){k.width=h.minWidth}if(r){k.height=h.minHeight}if(s){k.width=h.maxWidth}if(l){k.height=h.maxHeight}var e=this.originalPosition.left+this.originalSize.width,n=this.position.top+this.size.height;var j=/sw|nw|w/.test(p),d=/nw|ne|n/.test(p);if(g&&j){k.left=e-h.minWidth}if(s&&j){k.left=e-h.maxWidth}if(r&&d){k.top=n-h.minHeight}if(l&&d){k.top=n-h.maxHeight}var m=!k.width&&!k.height;if(m&&!k.left&&k.top){k.top=null}else{if(m&&!k.top&&k.left){k.left=null}}return k},_proportionallyResize:function(){var j=this.options;if(!this._proportionallyResizeElements.length){return}var f=this.helper||this.element;for(var e=0;e<this._proportionallyResizeElements.length;e++){var g=this._proportionallyResizeElements[e];if(!this.borderDif){var d=[g.css("borderTopWidth"),g.css("borderRightWidth"),g.css("borderBottomWidth"),g.css("borderLeftWidth")],h=[g.css("paddingTop"),g.css("paddingRight"),g.css("paddingBottom"),g.css("paddingLeft")];this.borderDif=c.map(d,function(k,m){var l=parseInt(k,10)||0,n=parseInt(h[m],10)||0;return l+n})}if(c.browser.msie&&!(!(c(f).is(":hidden")||c(f).parents(":hidden").length))){continue}g.css({height:(f.height()-this.borderDif[0]-this.borderDif[2])||0,width:(f.width()-this.borderDif[1]-this.borderDif[3])||0})}},_renderProxy:function(){var e=this.element,h=this.options;this.elementOffset=e.offset();if(this._helper){this.helper=this.helper||c('<div style="overflow:hidden;"></div>');var d=c.browser.msie&&c.browser.version<7,f=(d?1:0),g=(d?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+g,height:this.element.outerHeight()+g,position:"absolute",left:this.elementOffset.left-f+"px",top:this.elementOffset.top-f+"px",zIndex:++h.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(f,e,d){return{width:this.originalSize.width+e}},w:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{left:h.left+e,width:f.width-e}},n:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{top:h.top+d,height:f.height-d}},s:function(f,e,d){return{height:this.originalSize.height+d}},se:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},sw:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[f,e,d]))},ne:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},nw:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[f,e,d]))}},_propagate:function(e,d){c.ui.plugin.call(this,e,[d,this.ui()]);(e!="resize"&&this._trigger(e,d,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}));c.extend(c.ui.resizable,{version:"1.7.2",eventPrefix:"resize",defaults:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,cancel:":input,option",containment:false,delay:0,distance:1,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000}});c.ui.plugin.add("resizable","alsoResize",{start:function(e,f){var d=c(this).data("resizable"),g=d.options;_store=function(h){c(h).each(function(){c(this).data("resizable-alsoresize",{width:parseInt(c(this).width(),10),height:parseInt(c(this).height(),10),left:parseInt(c(this).css("left"),10),top:parseInt(c(this).css("top"),10)})})};if(typeof(g.alsoResize)=="object"&&!g.alsoResize.parentNode){if(g.alsoResize.length){g.alsoResize=g.alsoResize[0];_store(g.alsoResize)}else{c.each(g.alsoResize,function(h,i){_store(h)})}}else{_store(g.alsoResize)}},resize:function(f,h){var e=c(this).data("resizable"),i=e.options,g=e.originalSize,k=e.originalPosition;var j={height:(e.size.height-g.height)||0,width:(e.size.width-g.width)||0,top:(e.position.top-k.top)||0,left:(e.position.left-k.left)||0},d=function(l,m){c(l).each(function(){var p=c(this),q=c(this).data("resizable-alsoresize"),o={},n=m&&m.length?m:["width","height","top","left"];c.each(n||["width","height","top","left"],function(r,u){var s=(q[u]||0)+(j[u]||0);if(s&&s>=0){o[u]=s||null}});if(/relative/.test(p.css("position"))&&c.browser.opera){e._revertToRelativePosition=true;p.css({position:"absolute",top:"auto",left:"auto"})}p.css(o)})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.nodeType){c.each(i.alsoResize,function(l,m){d(l,m)})}else{d(i.alsoResize)}},stop:function(e,f){var d=c(this).data("resizable");if(d._revertToRelativePosition&&c.browser.opera){d._revertToRelativePosition=false;el.css({position:"relative"})}c(this).removeData("resizable-alsoresize-start")}});c.ui.plugin.add("resizable","animate",{stop:function(h,m){var n=c(this).data("resizable"),i=n.options;var g=n._proportionallyResizeElements,d=g.length&&(/textarea/i).test(g[0].nodeName),e=d&&c.ui.hasScroll(g[0],"left")?0:n.sizeDiff.height,k=d?0:n.sizeDiff.width;var f={width:(n.size.width-k),height:(n.size.height-e)},j=(parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left))||null,l=(parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top))||null;n.element.animate(c.extend(f,l&&j?{top:l,left:j}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var o={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};if(g&&g.length){c(g[0]).css({width:o.width,height:o.height})}n._updateCache(o);n._propagate("resize",h)}})}});c.ui.plugin.add("resizable","containment",{start:function(e,q){var s=c(this).data("resizable"),i=s.options,k=s.element;var f=i.containment,j=(f instanceof c)?f.get(0):(/parent/.test(f))?k.parent().get(0):f;if(!j){return}s.containerElement=c(j);if(/document/.test(f)||f==document){s.containerOffset={left:0,top:0};s.containerPosition={left:0,top:0};s.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var m=c(j),h=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){h[p]=b(m.css("padding"+o))});s.containerOffset=m.offset();s.containerPosition=m.position();s.containerSize={height:(m.innerHeight()-h[3]),width:(m.innerWidth()-h[1])};var n=s.containerOffset,d=s.containerSize.height,l=s.containerSize.width,g=(c.ui.hasScroll(j,"left")?j.scrollWidth:l),r=(c.ui.hasScroll(j)?j.scrollHeight:d);s.parentData={element:j,left:n.left,top:n.top,width:g,height:r}}},resize:function(f,p){var s=c(this).data("resizable"),h=s.options,e=s.containerSize,n=s.containerOffset,l=s.size,m=s.position,q=s._aspectRatio||f.shiftKey,d={top:0,left:0},g=s.containerElement;if(g[0]!=document&&(/static/).test(g.css("position"))){d=n}if(m.left<(s._helper?n.left:0)){s.size.width=s.size.width+(s._helper?(s.position.left-n.left):(s.position.left-d.left));if(q){s.size.height=s.size.width/h.aspectRatio}s.position.left=h.helper?n.left:0}if(m.top<(s._helper?n.top:0)){s.size.height=s.size.height+(s._helper?(s.position.top-n.top):s.position.top);if(q){s.size.width=s.size.height*h.aspectRatio}s.position.top=s._helper?n.top:0}s.offset.left=s.parentData.left+s.position.left;s.offset.top=s.parentData.top+s.position.top;var k=Math.abs((s._helper?s.offset.left-d.left:(s.offset.left-d.left))+s.sizeDiff.width),r=Math.abs((s._helper?s.offset.top-d.top:(s.offset.top-n.top))+s.sizeDiff.height);var j=s.containerElement.get(0)==s.element.parent().get(0),i=/relative|absolute/.test(s.containerElement.css("position"));if(j&&i){k-=s.parentData.left}if(k+s.size.width>=s.parentData.width){s.size.width=s.parentData.width-k;if(q){s.size.height=s.size.width/s.aspectRatio}}if(r+s.size.height>=s.parentData.height){s.size.height=s.parentData.height-r;if(q){s.size.width=s.size.height*s.aspectRatio}}},stop:function(e,m){var p=c(this).data("resizable"),f=p.options,k=p.position,l=p.containerOffset,d=p.containerPosition,g=p.containerElement;var i=c(p.helper),q=i.offset(),n=i.outerWidth()-p.sizeDiff.width,j=i.outerHeight()-p.sizeDiff.height;if(p._helper&&!f.animate&&(/relative/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}if(p._helper&&!f.animate&&(/static/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}}});c.ui.plugin.add("resizable","ghost",{start:function(f,g){var d=c(this).data("resizable"),h=d.options,e=d.size;d.ghost=d.originalElement.clone();d.ghost.css({opacity:0.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof h.ghost=="string"?h.ghost:"");d.ghost.appendTo(d.helper)},resize:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost){d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})}},stop:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost&&d.helper){d.helper.get(0).removeChild(d.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(d,l){var n=c(this).data("resizable"),g=n.options,j=n.size,h=n.originalSize,i=n.originalPosition,m=n.axis,k=g._aspectRatio||d.shiftKey;g.grid=typeof g.grid=="number"?[g.grid,g.grid]:g.grid;var f=Math.round((j.width-h.width)/(g.grid[0]||1))*(g.grid[0]||1),e=Math.round((j.height-h.height)/(g.grid[1]||1))*(g.grid[1]||1);if(/^(se|s|e)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e}else{if(/^(ne)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e}else{if(/^(sw)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.left=i.left-f}else{n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e;n.position.left=i.left-f}}}}});var b=function(d){return parseInt(d,10)||0};var a=function(d){return !isNaN(parseInt(d,10))}})(jQuery);(function(a){a.widget("ui.selectable",a.extend({},a.ui.mouse,{_init:function(){var b=this;this.element.addClass("ui-selectable");this.dragged=false;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]);c.each(function(){var d=a(this);var e=d.offset();a.data(this,"selectable-item",{element:this,$element:d,left:e.left,top:e.top,right:e.left+d.outerWidth(),bottom:e.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=c.addClass("ui-selectee");this._mouseInit();this.helper=a(document.createElement("div")).css({border:"1px dotted black"}).addClass("ui-selectable-helper")},destroy:function(){this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy()},_mouseStart:function(d){var b=this;this.opos=[d.pageX,d.pageY];if(this.options.disabled){return}var c=this.options;this.selectees=a(c.filter,this.element[0]);this._trigger("start",d);a(c.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:d.clientX,top:d.clientY,width:0,height:0});if(c.autoRefresh){this.refresh()}this.selectees.filter(".ui-selected").each(function(){var e=a.data(this,"selectable-item");e.startselected=true;if(!d.metaKey){e.$element.removeClass("ui-selected");e.selected=false;e.$element.addClass("ui-unselecting");e.unselecting=true;b._trigger("unselecting",d,{unselecting:e.element})}});a(d.target).parents().andSelf().each(function(){var e=a.data(this,"selectable-item");if(e){e.$element.removeClass("ui-unselecting").addClass("ui-selecting");e.unselecting=false;e.selecting=true;e.selected=true;b._trigger("selecting",d,{selecting:e.element});return false}})},_mouseDrag:function(i){var c=this;this.dragged=true;if(this.options.disabled){return}var e=this.options;var d=this.opos[0],h=this.opos[1],b=i.pageX,g=i.pageY;if(d>b){var f=b;b=d;d=f}if(h>g){var f=g;g=h;h=f}this.helper.css({left:d,top:h,width:b-d,height:g-h});this.selectees.each(function(){var j=a.data(this,"selectable-item");if(!j||j.element==c.element[0]){return}var k=false;if(e.tolerance=="touch"){k=(!(j.left>b||j.right<d||j.top>g||j.bottom<h))}else{if(e.tolerance=="fit"){k=(j.left>d&&j.right<b&&j.top>h&&j.bottom<g)}}if(k){if(j.selected){j.$element.removeClass("ui-selected");j.selected=false}if(j.unselecting){j.$element.removeClass("ui-unselecting");j.unselecting=false}if(!j.selecting){j.$element.addClass("ui-selecting");j.selecting=true;c._trigger("selecting",i,{selecting:j.element})}}else{if(j.selecting){if(i.metaKey&&j.startselected){j.$element.removeClass("ui-selecting");j.selecting=false;j.$element.addClass("ui-selected");j.selected=true}else{j.$element.removeClass("ui-selecting");j.selecting=false;if(j.startselected){j.$element.addClass("ui-unselecting");j.unselecting=true}c._trigger("unselecting",i,{unselecting:j.element})}}if(j.selected){if(!i.metaKey&&!j.startselected){j.$element.removeClass("ui-selected");j.selected=false;j.$element.addClass("ui-unselecting");j.unselecting=true;c._trigger("unselecting",i,{unselecting:j.element})}}}});return false},_mouseStop:function(d){var b=this;this.dragged=false;var c=this.options;a(".ui-unselecting",this.element[0]).each(function(){var e=a.data(this,"selectable-item");e.$element.removeClass("ui-unselecting");e.unselecting=false;e.startselected=false;b._trigger("unselected",d,{unselected:e.element})});a(".ui-selecting",this.element[0]).each(function(){var e=a.data(this,"selectable-item");e.$element.removeClass("ui-selecting").addClass("ui-selected");e.selecting=false;e.selected=true;e.startselected=true;b._trigger("selected",d,{selected:e.element})});this._trigger("stop",d);this.helper.remove();return false}}));a.extend(a.ui.selectable,{version:"1.7.2",defaults:{appendTo:"body",autoRefresh:true,cancel:":input,option",delay:0,distance:0,filter:"*",tolerance:"touch"}})})(jQuery);(function(a){a.widget("ui.sortable",a.extend({},a.ui.mouse,{_init:function(){var b=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?(/left|right/).test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--){this.items[b].item.removeData("sortable-item")}},_mouseCapture:function(e,f){if(this.reverting){return false}if(this.options.disabled||this.options.type=="static"){return false}this._refreshItems(e);var d=null,c=this,b=a(e.target).parents().each(function(){if(a.data(this,"sortable-item")==c){d=a(this);return false}});if(a.data(e.target,"sortable-item")==c){d=a(e.target)}if(!d){return false}if(this.options.handle&&!f){var g=false;a(this.options.handle,d).find("*").andSelf().each(function(){if(this==e.target){g=true}});if(!g){return false}}this.currentItem=d;this._removeCurrentsFromItems();return true},_mouseStart:function(e,f,b){var g=this.options,c=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(e);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");a.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(e);this.originalPageX=e.pageX;this.originalPageY=e.pageY;if(g.cursorAt){this._adjustOffsetFromHelper(g.cursorAt)}this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};if(this.helper[0]!=this.currentItem[0]){this.currentItem.hide()}this._createPlaceholder();if(g.containment){this._setContainment()}if(g.cursor){if(a("body").css("cursor")){this._storedCursor=a("body").css("cursor")}a("body").css("cursor",g.cursor)}if(g.opacity){if(this.helper.css("opacity")){this._storedOpacity=this.helper.css("opacity")}this.helper.css("opacity",g.opacity)}if(g.zIndex){if(this.helper.css("zIndex")){this._storedZIndex=this.helper.css("zIndex")}this.helper.css("zIndex",g.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){this.overflowOffset=this.scrollParent.offset()}this._trigger("start",e,this._uiHash());if(!this._preserveHelperProportions){this._cacheHelperProportions()}if(!b){for(var d=this.containers.length-1;d>=0;d--){this.containers[d]._trigger("activate",e,c._uiHash(this))}}if(a.ui.ddmanager){a.ui.ddmanager.current=this}if(a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,e)}this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(e);return true},_mouseDrag:function(f){this.position=this._generatePosition(f);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs){this.lastPositionAbs=this.positionAbs}if(this.options.scroll){var g=this.options,b=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if((this.overflowOffset.top+this.scrollParent[0].offsetHeight)-f.pageY<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop+g.scrollSpeed}else{if(f.pageY-this.overflowOffset.top<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop-g.scrollSpeed}}if((this.overflowOffset.left+this.scrollParent[0].offsetWidth)-f.pageX<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft+g.scrollSpeed}else{if(f.pageX-this.overflowOffset.left<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft-g.scrollSpeed}}}else{if(f.pageY-a(document).scrollTop()<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-g.scrollSpeed)}else{if(a(window).height()-(f.pageY-a(document).scrollTop())<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+g.scrollSpeed)}}if(f.pageX-a(document).scrollLeft()<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-g.scrollSpeed)}else{if(a(window).width()-(f.pageX-a(document).scrollLeft())<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+g.scrollSpeed)}}}if(b!==false&&a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,f)}}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d],c=e.item[0],h=this._intersectsWithPointer(e);if(!h){continue}if(c!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=c&&!a.ui.contains(this.placeholder[0],c)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],c):true)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(e)){this._rearrange(f,e)}else{break}this._trigger("change",f,this._uiHash());break}}this._contactContainers(f);if(a.ui.ddmanager){a.ui.ddmanager.drag(this,f)}this._trigger("sort",f,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(c,d){if(!c){return}if(a.ui.ddmanager&&!this.options.dropBehaviour){a.ui.ddmanager.drop(this,c)}if(this.options.revert){var b=this;var e=b.placeholder.offset();b.reverting=true;a(this.helper).animate({left:e.left-this.offset.parent.left-b.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-b.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){b._clear(c)})}else{this._clear(c,d)}return false},cancel:function(){var b=this;if(this.dragging){this._mouseUp();if(this.options.helper=="original"){this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}for(var c=this.containers.length-1;c>=0;c--){this.containers[c]._trigger("deactivate",null,b._uiHash(this));if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",null,b._uiHash(this));this.containers[c].containerCache.over=0}}}if(this.placeholder[0].parentNode){this.placeholder[0].parentNode.removeChild(this.placeholder[0])}if(this.options.helper!="original"&&this.helper&&this.helper[0].parentNode){this.helper.remove()}a.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});if(this.domPosition.prev){a(this.domPosition.prev).after(this.currentItem)}else{a(this.domPosition.parent).prepend(this.currentItem)}return true},serialize:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};a(b).each(function(){var e=(a(d.item||this).attr(d.attribute||"id")||"").match(d.expression||(/(.+)[-=_](.+)/));if(e){c.push((d.key||e[1]+"[]")+"="+(d.key&&d.expression?e[1]:e[2]))}});return c.join("&")},toArray:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};b.each(function(){c.push(a(d.item||this).attr(d.attribute||"id")||"")});return c},_intersectsWith:function(m){var e=this.positionAbs.left,d=e+this.helperProportions.width,k=this.positionAbs.top,j=k+this.helperProportions.height;var f=m.left,c=f+m.width,n=m.top,i=n+m.height;var o=this.offset.click.top,h=this.offset.click.left;var g=(k+o)>n&&(k+o)<i&&(e+h)>f&&(e+h)<c;if(this.options.tolerance=="pointer"||this.options.forcePointerForContainers||(this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>m[this.floating?"width":"height"])){return g}else{return(f<e+(this.helperProportions.width/2)&&d-(this.helperProportions.width/2)<c&&n<k+(this.helperProportions.height/2)&&j-(this.helperProportions.height/2)<i)}},_intersectsWithPointer:function(d){var e=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,d.top,d.height),c=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,d.left,d.width),g=e&&c,b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(!g){return false}return this.floating?(((f&&f=="right")||b=="down")?2:1):(b&&(b=="down"?2:1))},_intersectsWithSides:function(e){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+(e.height/2),e.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+(e.width/2),e.width),b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(this.floating&&f){return((f=="right"&&d)||(f=="left"&&!d))}else{return b&&((b=="down"&&c)||(b=="up"&&!c))}},_getDragVerticalDirection:function(){var b=this.positionAbs.top-this.lastPositionAbs.top;return b!=0&&(b>0?"down":"up")},_getDragHorizontalDirection:function(){var b=this.positionAbs.left-this.lastPositionAbs.left;return b!=0&&(b>0?"right":"left")},refresh:function(b){this._refreshItems(b);this.refreshPositions()},_connectWith:function(){var b=this.options;return b.connectWith.constructor==String?[b.connectWith]:b.connectWith},_getItemsAsjQuery:function(b){var l=this;var g=[];var e=[];var h=this._connectWith();if(h&&b){for(var d=h.length-1;d>=0;d--){var k=a(h[d]);for(var c=k.length-1;c>=0;c--){var f=a.data(k[c],"sortable");if(f&&f!=this&&!f.options.disabled){e.push([a.isFunction(f.options.items)?f.options.items.call(f.element):a(f.options.items,f.element).not(".ui-sortable-helper"),f])}}}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper"),this]);for(var d=e.length-1;d>=0;d--){e[d][0].each(function(){g.push(this)})}return a(g)},_removeCurrentsFromItems:function(){var d=this.currentItem.find(":data(sortable-item)");for(var c=0;c<this.items.length;c++){for(var b=0;b<d.length;b++){if(d[b]==this.items[c].item[0]){this.items.splice(c,1)}}}},_refreshItems:function(b){this.items=[];this.containers=[this];var h=this.items;var p=this;var f=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]];var l=this._connectWith();if(l){for(var e=l.length-1;e>=0;e--){var m=a(l[e]);for(var d=m.length-1;d>=0;d--){var g=a.data(m[d],"sortable");if(g&&g!=this&&!g.options.disabled){f.push([a.isFunction(g.options.items)?g.options.items.call(g.element[0],b,{item:this.currentItem}):a(g.options.items,g.element),g]);this.containers.push(g)}}}}for(var e=f.length-1;e>=0;e--){var k=f[e][1];var c=f[e][0];for(var d=0,n=c.length;d<n;d++){var o=a(c[d]);o.data("sortable-item",k);h.push({item:o,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){if(this.offsetParent&&this.helper){this.offset.parent=this._getParentOffset()}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d];if(e.instance!=this.currentContainer&&this.currentContainer&&e.item[0]!=this.currentItem[0]){continue}var c=this.options.toleranceElement?a(this.options.toleranceElement,e.item):e.item;if(!b){e.width=c.outerWidth();e.height=c.outerHeight()}var f=c.offset();e.left=f.left;e.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers){this.options.custom.refreshContainers.call(this)}else{for(var d=this.containers.length-1;d>=0;d--){var f=this.containers[d].element.offset();this.containers[d].containerCache.left=f.left;this.containers[d].containerCache.top=f.top;this.containers[d].containerCache.width=this.containers[d].element.outerWidth();this.containers[d].containerCache.height=this.containers[d].element.outerHeight()}}},_createPlaceholder:function(d){var b=d||this,e=b.options;if(!e.placeholder||e.placeholder.constructor==String){var c=e.placeholder;e.placeholder={element:function(){var f=a(document.createElement(b.currentItem[0].nodeName)).addClass(c||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!c){f.style.visibility="hidden"}return f},update:function(f,g){if(c&&!e.forcePlaceholderSize){return}if(!g.height()){g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10))}if(!g.width()){g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=a(e.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);e.placeholder.update(b,b.placeholder)},_contactContainers:function(d){for(var c=this.containers.length-1;c>=0;c--){if(this._intersectsWith(this.containers[c].containerCache)){if(!this.containers[c].containerCache.over){if(this.currentContainer!=this.containers[c]){var h=10000;var g=null;var e=this.positionAbs[this.containers[c].floating?"left":"top"];for(var b=this.items.length-1;b>=0;b--){if(!a.ui.contains(this.containers[c].element[0],this.items[b].item[0])){continue}var f=this.items[b][this.containers[c].floating?"left":"top"];if(Math.abs(f-e)<h){h=Math.abs(f-e);g=this.items[b]}}if(!g&&!this.options.dropOnEmpty){continue}this.currentContainer=this.containers[c];g?this._rearrange(d,g,null,true):this._rearrange(d,null,this.containers[c].element,true);this._trigger("change",d,this._uiHash());this.containers[c]._trigger("change",d,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder)}this.containers[c]._trigger("over",d,this._uiHash(this));this.containers[c].containerCache.over=1}}else{if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",d,this._uiHash(this));this.containers[c].containerCache.over=0}}}},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c,this.currentItem])):(d.helper=="clone"?this.currentItem.clone():this.currentItem);if(!b.parents("body").length){a(d.appendTo!="parent"?d.appendTo:this.currentItem[0].parentNode)[0].appendChild(b[0])}if(b[0]==this.currentItem[0]){this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}}if(b[0].style.width==""||d.forceHelperSize){b.width(this.currentItem.width())}if(b[0].style.height==""||d.forceHelperSize){b.height(this.currentItem.height())}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.currentItem.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.currentItem.css("marginLeft"),10)||0),top:(parseInt(this.currentItem.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)){var c=a(e.containment)[0];var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_rearrange:function(g,f,c,e){c?c[0].appendChild(this.placeholder[0]):f.item[0].parentNode.insertBefore(this.placeholder[0],(this.direction=="down"?f.item[0]:f.item[0].nextSibling));this.counter=this.counter?++this.counter:1;var d=this,b=this.counter;window.setTimeout(function(){if(b==d.counter){d.refreshPositions(!e)}},0)},_clear:function(d,e){this.reverting=false;var f=[],b=this;if(!this._noFinalSort&&this.currentItem[0].parentNode){this.placeholder.before(this.currentItem)}this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var c in this._storedCSS){if(this._storedCSS[c]=="auto"||this._storedCSS[c]=="static"){this._storedCSS[c]=""}}this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}if(this.fromOutside&&!e){f.push(function(g){this._trigger("receive",g,this._uiHash(this.fromOutside))})}if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!e){f.push(function(g){this._trigger("update",g,this._uiHash())})}if(!a.ui.contains(this.element[0],this.currentItem[0])){if(!e){f.push(function(g){this._trigger("remove",g,this._uiHash())})}for(var c=this.containers.length-1;c>=0;c--){if(a.ui.contains(this.containers[c].element[0],this.currentItem[0])&&!e){f.push((function(g){return function(h){g._trigger("receive",h,this._uiHash(this))}}).call(this,this.containers[c]));f.push((function(g){return function(h){g._trigger("update",h,this._uiHash(this))}}).call(this,this.containers[c]))}}}for(var c=this.containers.length-1;c>=0;c--){if(!e){f.push((function(g){return function(h){g._trigger("deactivate",h,this._uiHash(this))}}).call(this,this.containers[c]))}if(this.containers[c].containerCache.over){f.push((function(g){return function(h){g._trigger("out",h,this._uiHash(this))}}).call(this,this.containers[c]));this.containers[c].containerCache.over=0}}if(this._storedCursor){a("body").css("cursor",this._storedCursor)}if(this._storedOpacity){this.helper.css("opacity",this._storedOpacity)}if(this._storedZIndex){this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex)}this.dragging=false;if(this.cancelHelperRemoval){if(!e){this._trigger("beforeStop",d,this._uiHash());for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}return false}if(!e){this._trigger("beforeStop",d,this._uiHash())}this.placeholder[0].parentNode.removeChild(this.placeholder[0]);if(this.helper[0]!=this.currentItem[0]){this.helper.remove()}this.helper=null;if(!e){for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){if(a.widget.prototype._trigger.apply(this,arguments)===false){this.cancel()}},_uiHash:function(c){var b=c||this;return{helper:b.helper,placeholder:b.placeholder||a([]),position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs,item:b.currentItem,sender:c?c.element:null}}}));a.extend(a.ui.sortable,{getter:"serialize toArray",version:"1.7.2",eventPrefix:"sort",defaults:{appendTo:"parent",axis:false,cancel:":input,option",connectWith:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000}})})(jQuery);jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.data("ec.storage."+h[f],g[0].style[h[f]])}}},restore:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.css(h[f],g.data("ec.storage."+h[f]))}}},setMode:function(f,g){if(g=="toggle"){g=f.is(":hidden")?"show":"hide"}return g},getBaseline:function(g,h){var i,f;switch(g[0]){case"top":i=0;break;case"middle":i=0.5;break;case"bottom":i=1;break;default:i=g[0]/h.height}switch(g[1]){case"left":f=0;break;case"center":f=0.5;break;case"right":f=1;break;default:f=g[1]/h.width}return{x:f,y:i}},createWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent()}var g={width:f.outerWidth(true),height:f.outerHeight(true),"float":f.css("float")};f.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');var j=f.parent();if(f.css("position")=="static"){j.css({position:"relative"});f.css({position:"relative"})}else{var i=f.css("top");if(isNaN(parseInt(i,10))){i="auto"}var h=f.css("left");if(isNaN(parseInt(h,10))){h="auto"}j.css({position:f.css("position"),top:i,left:h,zIndex:f.css("z-index")}).show();f.css({position:"relative",top:0,left:0})}j.css(g);return j},removeWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent().replaceWith(f)}return f},setTransition:function(g,i,f,h){h=h||{};d.each(i,function(k,j){unit=g.cssUnit(j);if(unit[0]>0){h[j]=unit[0]*f+unit[1]}});return h},animateClass:function(h,i,k,j){var f=(typeof k=="function"?k:(j?j:null));var g=(typeof k=="string"?k:null);return this.each(function(){var q={};var o=d(this);var p=o.attr("style")||"";if(typeof p=="object"){p=p.cssText}if(h.toggle){o.hasClass(h.toggle)?h.remove=h.toggle:h.add=h.toggle}var l=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.addClass(h.add)}if(h.remove){o.removeClass(h.remove)}var m=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.removeClass(h.add)}if(h.remove){o.addClass(h.remove)}for(var r in m){if(typeof m[r]!="function"&&m[r]&&r.indexOf("Moz")==-1&&r.indexOf("length")==-1&&m[r]!=l[r]&&(r.match(/color/i)||(!r.match(/color/i)&&!isNaN(parseInt(m[r],10))))&&(l.position!="static"||(l.position=="static"&&!r.match(/left|top|bottom|right/)))){q[r]=m[r]}}o.animate(q,i,g,function(){if(typeof d(this).attr("style")=="object"){d(this).attr("style")["cssText"]="";d(this).attr("style")["cssText"]=p}else{d(this).attr("style",p)}if(h.add){d(this).addClass(h.add)}if(h.remove){d(this).removeClass(h.remove)}if(f){f.apply(this,arguments)}})})}};function c(g,f){var i=g[1]&&g[1].constructor==Object?g[1]:{};if(f){i.mode=f}var h=g[1]&&g[1].constructor!=Object?g[1]:(i.duration?i.duration:g[2]);h=d.fx.off?0:typeof h==="number"?h:d.fx.speeds[h]||d.fx.speeds._default;var j=i.callback||(d.isFunction(g[1])&&g[1])||(d.isFunction(g[2])&&g[2])||(d.isFunction(g[3])&&g[3]);return[g[0],i,h,j]}d.fn.extend({_show:d.fn.show,_hide:d.fn.hide,__toggle:d.fn.toggle,_addClass:d.fn.addClass,_removeClass:d.fn.removeClass,_toggleClass:d.fn.toggleClass,effect:function(g,f,h,i){return d.effects[g]?d.effects[g].call(this,{method:g,options:f||{},duration:h,callback:i}):null},show:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._show.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"show"))}},hide:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._hide.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"hide"))}},toggle:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))||(d.isFunction(arguments[0])||typeof arguments[0]=="boolean")){return this.__toggle.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"toggle"))}},addClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{add:g},f,i,h]):this._addClass(g)},removeClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{remove:g},f,i,h]):this._removeClass(g)},toggleClass:function(g,f,i,h){return((typeof f!=="boolean")&&f)?d.effects.animateClass.apply(this,[{toggle:g},f,i,h]):this._toggleClass(g,f)},morph:function(f,h,g,j,i){return d.effects.animateClass.apply(this,[{add:h,remove:f},g,j,i])},switchClass:function(){return this.morph.apply(this,arguments)},cssUnit:function(f){var g=this.css(f),h=[];d.each(["em","px","%","pt"],function(j,k){if(g.indexOf(k)>0){h=[parseFloat(g),k]}});return h}});d.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(g,f){d.fx.step[f]=function(h){if(h.state==0){h.start=e(h.elem,f);h.end=b(h.end)}h.elem.style[f]="rgb("+[Math.max(Math.min(parseInt((h.pos*(h.end[0]-h.start[0]))+h.start[0],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[1]-h.start[1]))+h.start[1],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[2]-h.start[2]))+h.start[2],10),255),0)].join(",")+")"}});function b(g){var f;if(g&&g.constructor==Array&&g.length==3){return g}if(f=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(g)){return[parseInt(f[1],10),parseInt(f[2],10),parseInt(f[3],10)]}if(f=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(g)){return[parseFloat(f[1])*2.55,parseFloat(f[2])*2.55,parseFloat(f[3])*2.55]}if(f=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(g)){return[parseInt(f[1],16),parseInt(f[2],16),parseInt(f[3],16)]}if(f=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(g)){return[parseInt(f[1]+f[1],16),parseInt(f[2]+f[2],16),parseInt(f[3]+f[3],16)]}if(f=/rgba\(0, 0, 0, 0\)/.exec(g)){return a.transparent}return a[d.trim(g).toLowerCase()]}function e(h,f){var g;do{g=d.curCSS(h,f);if(g!=""&&g!="transparent"||d.nodeName(h,"body")){break}f="backgroundColor"}while(h=h.parentNode);return b(g)}var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};d.easing.jswing=d.easing.swing;d.extend(d.easing,{def:"easeOutQuad",swing:function(g,h,f,j,i){return d.easing[d.easing.def](g,h,f,j,i)},easeInQuad:function(g,h,f,j,i){return j*(h/=i)*h+f},easeOutQuad:function(g,h,f,j,i){return -j*(h/=i)*(h-2)+f},easeInOutQuad:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h+f}return -j/2*((--h)*(h-2)-1)+f},easeInCubic:function(g,h,f,j,i){return j*(h/=i)*h*h+f},easeOutCubic:function(g,h,f,j,i){return j*((h=h/i-1)*h*h+1)+f},easeInOutCubic:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h+f}return j/2*((h-=2)*h*h+2)+f},easeInQuart:function(g,h,f,j,i){return j*(h/=i)*h*h*h+f},easeOutQuart:function(g,h,f,j,i){return -j*((h=h/i-1)*h*h*h-1)+f},easeInOutQuart:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h+f}return -j/2*((h-=2)*h*h*h-2)+f},easeInQuint:function(g,h,f,j,i){return j*(h/=i)*h*h*h*h+f},easeOutQuint:function(g,h,f,j,i){return j*((h=h/i-1)*h*h*h*h+1)+f},easeInOutQuint:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h*h+f}return j/2*((h-=2)*h*h*h*h+2)+f},easeInSine:function(g,h,f,j,i){return -j*Math.cos(h/i*(Math.PI/2))+j+f},easeOutSine:function(g,h,f,j,i){return j*Math.sin(h/i*(Math.PI/2))+f},easeInOutSine:function(g,h,f,j,i){return -j/2*(Math.cos(Math.PI*h/i)-1)+f},easeInExpo:function(g,h,f,j,i){return(h==0)?f:j*Math.pow(2,10*(h/i-1))+f},easeOutExpo:function(g,h,f,j,i){return(h==i)?f+j:j*(-Math.pow(2,-10*h/i)+1)+f},easeInOutExpo:function(g,h,f,j,i){if(h==0){return f}if(h==i){return f+j}if((h/=i/2)<1){return j/2*Math.pow(2,10*(h-1))+f}return j/2*(-Math.pow(2,-10*--h)+2)+f},easeInCirc:function(g,h,f,j,i){return -j*(Math.sqrt(1-(h/=i)*h)-1)+f},easeOutCirc:function(g,h,f,j,i){return j*Math.sqrt(1-(h=h/i-1)*h)+f},easeInOutCirc:function(g,h,f,j,i){if((h/=i/2)<1){return -j/2*(Math.sqrt(1-h*h)-1)+f}return j/2*(Math.sqrt(1-(h-=2)*h)+1)+f},easeInElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return -(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f},easeOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return h*Math.pow(2,-10*i)*Math.sin((i*l-j)*(2*Math.PI)/k)+m+f},easeInOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l/2)==2){return f+m}if(!k){k=l*(0.3*1.5)}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}if(i<1){return -0.5*(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f}return h*Math.pow(2,-10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k)*0.5+m+f},easeInBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*(h/=j)*h*((i+1)*h-i)+f},easeOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*((h=h/j-1)*h*((i+1)*h+i)+1)+f},easeInOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}if((h/=j/2)<1){return k/2*(h*h*(((i*=(1.525))+1)*h-i))+f}return k/2*((h-=2)*h*(((i*=(1.525))+1)*h+i)+2)+f},easeInBounce:function(g,h,f,j,i){return j-d.easing.easeOutBounce(g,i-h,0,j,i)+f},easeOutBounce:function(g,h,f,j,i){if((h/=i)<(1/2.75)){return j*(7.5625*h*h)+f}else{if(h<(2/2.75)){return j*(7.5625*(h-=(1.5/2.75))*h+0.75)+f}else{if(h<(2.5/2.75)){return j*(7.5625*(h-=(2.25/2.75))*h+0.9375)+f}else{return j*(7.5625*(h-=(2.625/2.75))*h+0.984375)+f}}}},easeInOutBounce:function(g,h,f,j,i){if(h<i/2){return d.easing.easeInBounce(g,h*2,0,j,i)*0.5+f}return d.easing.easeOutBounce(g,h*2-i,0,j,i)*0.5+j*0.5+f}})})(jQuery);(function(a){a.effects.blind=function(b){return this.queue(function(){var d=a(this),c=["position","top","left"];var h=a.effects.setMode(d,b.options.mode||"hide");var g=b.options.direction||"vertical";a.effects.save(d,c);d.show();var j=a.effects.createWrapper(d).css({overflow:"hidden"});var e=(g=="vertical")?"height":"width";var i=(g=="vertical")?j.height():j.width();if(h=="show"){j.css(e,0)}var f={};f[e]=h=="show"?i:0;j.animate(f,b.duration,b.options.easing,function(){if(h=="hide"){d.hide()}a.effects.restore(d,c);a.effects.removeWrapper(d);if(b.callback){b.callback.apply(d[0],arguments)}d.dequeue()})})}})(jQuery);(function(a){a.effects.bounce=function(b){return this.queue(function(){var e=a(this),l=["position","top","left"];var k=a.effects.setMode(e,b.options.mode||"effect");var n=b.options.direction||"up";var c=b.options.distance||20;var d=b.options.times||5;var g=b.duration||250;if(/show|hide/.test(k)){l.push("opacity")}a.effects.save(e,l);e.show();a.effects.createWrapper(e);var f=(n=="up"||n=="down")?"top":"left";var p=(n=="up"||n=="left")?"pos":"neg";var c=b.options.distance||(f=="top"?e.outerHeight({margin:true})/3:e.outerWidth({margin:true})/3);if(k=="show"){e.css("opacity",0).css(f,p=="pos"?-c:c)}if(k=="hide"){c=c/(d*2)}if(k!="hide"){d--}if(k=="show"){var h={opacity:1};h[f]=(p=="pos"?"+=":"-=")+c;e.animate(h,g/2,b.options.easing);c=c/2;d--}for(var j=0;j<d;j++){var o={},m={};o[f]=(p=="pos"?"-=":"+=")+c;m[f]=(p=="pos"?"+=":"-=")+c;e.animate(o,g/2,b.options.easing).animate(m,g/2,b.options.easing);c=(k=="hide")?c*2:c/2}if(k=="hide"){var h={opacity:0};h[f]=(p=="pos"?"-=":"+=")+c;e.animate(h,g/2,b.options.easing,function(){e.hide();a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}})}else{var o={},m={};o[f]=(p=="pos"?"-=":"+=")+c;m[f]=(p=="pos"?"+=":"-=")+c;e.animate(o,g/2,b.options.easing).animate(m,g/2,b.options.easing,function(){a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}})}e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);(function(a){a.effects.clip=function(b){return this.queue(function(){var f=a(this),j=["position","top","left","height","width"];var i=a.effects.setMode(f,b.options.mode||"hide");var k=b.options.direction||"vertical";a.effects.save(f,j);f.show();var c=a.effects.createWrapper(f).css({overflow:"hidden"});var e=f[0].tagName=="IMG"?c:f;var g={size:(k=="vertical")?"height":"width",position:(k=="vertical")?"top":"left"};var d=(k=="vertical")?e.height():e.width();if(i=="show"){e.css(g.size,0);e.css(g.position,d/2)}var h={};h[g.size]=i=="show"?d:0;h[g.position]=i=="show"?0:d/2;e.animate(h,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){f.hide()}a.effects.restore(f,j);a.effects.removeWrapper(f);if(b.callback){b.callback.apply(f[0],arguments)}f.dequeue()}})})}})(jQuery);(function(a){a.effects.drop=function(b){return this.queue(function(){var e=a(this),d=["position","top","left","opacity"];var i=a.effects.setMode(e,b.options.mode||"hide");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e);var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true})/2:e.outerWidth({margin:true})/2);if(i=="show"){e.css("opacity",0).css(f,c=="pos"?-j:j)}var g={opacity:i=="show"?1:0};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);(function(a){a.effects.explode=function(b){return this.queue(function(){var k=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;var e=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;b.options.mode=b.options.mode=="toggle"?(a(this).is(":visible")?"hide":"show"):b.options.mode;var h=a(this).show().css("visibility","hidden");var l=h.offset();l.top-=parseInt(h.css("marginTop"),10)||0;l.left-=parseInt(h.css("marginLeft"),10)||0;var g=h.outerWidth(true);var c=h.outerHeight(true);for(var f=0;f<k;f++){for(var d=0;d<e;d++){h.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-d*(g/e),top:-f*(c/k)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/e,height:c/k,left:l.left+d*(g/e)+(b.options.mode=="show"?(d-Math.floor(e/2))*(g/e):0),top:l.top+f*(c/k)+(b.options.mode=="show"?(f-Math.floor(k/2))*(c/k):0),opacity:b.options.mode=="show"?0:1}).animate({left:l.left+d*(g/e)+(b.options.mode=="show"?0:(d-Math.floor(e/2))*(g/e)),top:l.top+f*(c/k)+(b.options.mode=="show"?0:(f-Math.floor(k/2))*(c/k)),opacity:b.options.mode=="show"?1:0},b.duration||500)}}setTimeout(function(){b.options.mode=="show"?h.css({visibility:"visible"}):h.css({visibility:"visible"}).hide();if(b.callback){b.callback.apply(h[0])}h.dequeue();a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);(function(a){a.effects.fold=function(b){return this.queue(function(){var e=a(this),k=["position","top","left"];var h=a.effects.setMode(e,b.options.mode||"hide");var o=b.options.size||15;var n=!(!b.options.horizFirst);var g=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(e,k);e.show();var d=a.effects.createWrapper(e).css({overflow:"hidden"});var i=((h=="show")!=n);var f=i?["width","height"]:["height","width"];var c=i?[d.width(),d.height()]:[d.height(),d.width()];var j=/([0-9]+)%/.exec(o);if(j){o=parseInt(j[1],10)/100*c[h=="hide"?0:1]}if(h=="show"){d.css(n?{height:0,width:o}:{height:o,width:0})}var m={},l={};m[f[0]]=h=="show"?c[0]:o;l[f[1]]=h=="show"?c[1]:0;d.animate(m,g,b.options.easing).animate(l,g,b.options.easing,function(){if(h=="hide"){e.hide()}a.effects.restore(e,k);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(e[0],arguments)}e.dequeue()})})}})(jQuery);(function(a){a.effects.highlight=function(b){return this.queue(function(){var e=a(this),d=["backgroundImage","backgroundColor","opacity"];var h=a.effects.setMode(e,b.options.mode||"show");var c=b.options.color||"#ffff99";var g=e.css("backgroundColor");a.effects.save(e,d);e.show();e.css({backgroundImage:"none",backgroundColor:c});var f={backgroundColor:g};if(h=="hide"){f.opacity=0}e.animate(f,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(h=="hide"){e.hide()}a.effects.restore(e,d);if(h=="show"&&a.browser.msie){this.style.removeAttribute("filter")}if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);(function(a){a.effects.pulsate=function(b){return this.queue(function(){var d=a(this);var g=a.effects.setMode(d,b.options.mode||"show");var f=b.options.times||5;var e=b.duration?b.duration/2:a.fx.speeds._default/2;if(g=="hide"){f--}if(d.is(":hidden")){d.css("opacity",0);d.show();d.animate({opacity:1},e,b.options.easing);f=f-2}for(var c=0;c<f;c++){d.animate({opacity:0},e,b.options.easing).animate({opacity:1},e,b.options.easing)}if(g=="hide"){d.animate({opacity:0},e,b.options.easing,function(){d.hide();if(b.callback){b.callback.apply(this,arguments)}})}else{d.animate({opacity:0},e,b.options.easing).animate({opacity:1},e,b.options.easing,function(){if(b.callback){b.callback.apply(this,arguments)}})}d.queue("fx",function(){d.dequeue()});d.dequeue()})}})(jQuery);(function(a){a.effects.puff=function(b){return this.queue(function(){var f=a(this);var c=a.extend(true,{},b.options);var h=a.effects.setMode(f,b.options.mode||"hide");var g=parseInt(b.options.percent,10)||150;c.fade=true;var e={height:f.height(),width:f.width()};var d=g/100;f.from=(h=="hide")?e:{height:e.height*d,width:e.width*d};c.from=f.from;c.percent=(h=="hide")?g:100;c.mode=h;f.effect("scale",c,b.duration,b.callback);f.dequeue()})};a.effects.scale=function(b){return this.queue(function(){var g=a(this);var d=a.extend(true,{},b.options);var j=a.effects.setMode(g,b.options.mode||"effect");var h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:(j=="hide"?0:100));var i=b.options.direction||"both";var c=b.options.origin;if(j!="effect"){d.origin=c||["middle","center"];d.restore=true}var f={height:g.height(),width:g.width()};g.from=b.options.from||(j=="show"?{height:0,width:0}:f);var e={y:i!="horizontal"?(h/100):1,x:i!="vertical"?(h/100):1};g.to={height:f.height*e.y,width:f.width*e.x};if(b.options.fade){if(j=="show"){g.from.opacity=0;g.to.opacity=1}if(j=="hide"){g.from.opacity=1;g.to.opacity=0}}d.from=g.from;d.to=g.to;d.mode=j;g.effect("size",d,b.duration,b.callback);g.dequeue()})};a.effects.size=function(b){return this.queue(function(){var c=a(this),n=["position","top","left","width","height","overflow","opacity"];var m=["position","top","left","overflow","opacity"];var j=["width","height","overflow"];var p=["fontSize"];var k=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"];var f=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"];var g=a.effects.setMode(c,b.options.mode||"effect");var i=b.options.restore||false;var e=b.options.scale||"both";var o=b.options.origin;var d={height:c.height(),width:c.width()};c.from=b.options.from||d;c.to=b.options.to||d;if(o){var h=a.effects.getBaseline(o,d);c.from.top=(d.height-c.from.height)*h.y;c.from.left=(d.width-c.from.width)*h.x;c.to.top=(d.height-c.to.height)*h.y;c.to.left=(d.width-c.to.width)*h.x}var l={from:{y:c.from.height/d.height,x:c.from.width/d.width},to:{y:c.to.height/d.height,x:c.to.width/d.width}};if(e=="box"||e=="both"){if(l.from.y!=l.to.y){n=n.concat(k);c.from=a.effects.setTransition(c,k,l.from.y,c.from);c.to=a.effects.setTransition(c,k,l.to.y,c.to)}if(l.from.x!=l.to.x){n=n.concat(f);c.from=a.effects.setTransition(c,f,l.from.x,c.from);c.to=a.effects.setTransition(c,f,l.to.x,c.to)}}if(e=="content"||e=="both"){if(l.from.y!=l.to.y){n=n.concat(p);c.from=a.effects.setTransition(c,p,l.from.y,c.from);c.to=a.effects.setTransition(c,p,l.to.y,c.to)}}a.effects.save(c,i?n:m);c.show();a.effects.createWrapper(c);c.css("overflow","hidden").css(c.from);if(e=="content"||e=="both"){k=k.concat(["marginTop","marginBottom"]).concat(p);f=f.concat(["marginLeft","marginRight"]);j=n.concat(k).concat(f);c.find("*[width]").each(function(){child=a(this);if(i){a.effects.save(child,j)}var q={height:child.height(),width:child.width()};child.from={height:q.height*l.from.y,width:q.width*l.from.x};child.to={height:q.height*l.to.y,width:q.width*l.to.x};if(l.from.y!=l.to.y){child.from=a.effects.setTransition(child,k,l.from.y,child.from);child.to=a.effects.setTransition(child,k,l.to.y,child.to)}if(l.from.x!=l.to.x){child.from=a.effects.setTransition(child,f,l.from.x,child.from);child.to=a.effects.setTransition(child,f,l.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){if(i){a.effects.restore(child,j)}})})}c.animate(c.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(g=="hide"){c.hide()}a.effects.restore(c,i?n:m);a.effects.removeWrapper(c);if(b.callback){b.callback.apply(this,arguments)}c.dequeue()}})})}})(jQuery);(function(a){a.effects.shake=function(b){return this.queue(function(){var e=a(this),l=["position","top","left"];var k=a.effects.setMode(e,b.options.mode||"effect");var n=b.options.direction||"left";var c=b.options.distance||20;var d=b.options.times||3;var g=b.duration||b.options.duration||140;a.effects.save(e,l);e.show();a.effects.createWrapper(e);var f=(n=="up"||n=="down")?"top":"left";var p=(n=="up"||n=="left")?"pos":"neg";var h={},o={},m={};h[f]=(p=="pos"?"-=":"+=")+c;o[f]=(p=="pos"?"+=":"-=")+c*2;m[f]=(p=="pos"?"-=":"+=")+c*2;e.animate(h,g,b.options.easing);for(var j=1;j<d;j++){e.animate(o,g,b.options.easing).animate(m,g,b.options.easing)}e.animate(o,g,b.options.easing).animate(h,g/2,b.options.easing,function(){a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}});e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);(function(a){a.effects.slide=function(b){return this.queue(function(){var e=a(this),d=["position","top","left"];var i=a.effects.setMode(e,b.options.mode||"show");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e).css({overflow:"hidden"});var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true}):e.outerWidth({margin:true}));if(i=="show"){e.css(f,c=="pos"?-j:j)}var g={};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);(function(a){a.effects.transfer=function(b){return this.queue(function(){var f=a(this),h=a(b.options.to),e=h.offset(),g={top:e.top,left:e.left,height:h.innerHeight(),width:h.innerWidth()},d=f.offset(),c=a('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(b.options.className).css({top:d.top,left:d.left,height:f.innerHeight(),width:f.innerWidth(),position:"absolute"}).animate(g,b.duration,b.options.easing,function(){c.remove();(b.callback&&b.callback.apply(f[0],arguments));f.dequeue()})})}})(jQuery);(function(a){a.widget("ui.accordion",{_init:function(){var d=this.options,b=this;this.running=0;if(d.collapsible==a.ui.accordion.defaults.collapsible&&d.alwaysOpen!=a.ui.accordion.defaults.alwaysOpen){d.collapsible=!d.alwaysOpen}if(d.navigation){var c=this.element.find("a").filter(d.navigationFilter);if(c.length){if(c.filter(d.header).length){this.active=c}else{this.active=c.parent().parent().prev();c.addClass("ui-accordion-content-active")}}}this.element.addClass("ui-accordion ui-widget ui-helper-reset");if(this.element[0].nodeName=="UL"){this.element.children("li").addClass("ui-accordion-li-fix")}this.headers=this.element.find(d.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){a(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");this.active=this._findActive(this.active||d.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");a("<span/>").addClass("ui-icon "+d.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(d.icons.header).toggleClass(d.icons.headerSelected);if(a.browser.msie){this.element.find("a").css("zoom","1")}this.resize();this.element.attr("role","tablist");this.headers.attr("role","tab").bind("keydown",function(e){return b._keydown(e)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();if(!this.active.length){this.headers.eq(0).attr("tabIndex","0")}else{this.active.attr("aria-expanded","true").attr("tabIndex","0")}if(!a.browser.safari){this.headers.find("a").attr("tabIndex","-1")}if(d.event){this.headers.bind((d.event)+".accordion",function(e){return b._clickHandler.call(b,e,this)})}},destroy:function(){var c=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");this.headers.find("a").removeAttr("tabindex");this.headers.children(".ui-icon").remove();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(c.autoHeight||c.fillHeight){b.css("height","")}},_setData:function(b,c){if(b=="alwaysOpen"){b="collapsible";c=!c}a.widget.prototype._setData.apply(this,arguments)},_keydown:function(e){var g=this.options,f=a.ui.keyCode;if(g.disabled||e.altKey||e.ctrlKey){return}var d=this.headers.length;var b=this.headers.index(e.target);var c=false;switch(e.keyCode){case f.RIGHT:case f.DOWN:c=this.headers[(b+1)%d];break;case f.LEFT:case f.UP:c=this.headers[(b-1+d)%d];break;case f.SPACE:case f.ENTER:return this._clickHandler({target:e.target},e.target)}if(c){a(e.target).attr("tabIndex","-1");a(c).attr("tabIndex","0");c.focus();return false}return true},resize:function(){var e=this.options,d;if(e.fillSpace){if(a.browser.msie){var b=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}d=this.element.parent().height();if(a.browser.msie){this.element.parent().css("overflow",b)}this.headers.each(function(){d-=a(this).outerHeight()});var c=0;this.headers.next().each(function(){c=Math.max(c,a(this).innerHeight()-a(this).height())}).height(Math.max(0,d-c)).css("overflow","auto")}else{if(e.autoHeight){d=0;this.headers.next().each(function(){d=Math.max(d,a(this).outerHeight())}).height(d)}}},activate:function(b){var c=this._findActive(b)[0];this._clickHandler({target:c},c)},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===false?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,f){var d=this.options;if(d.disabled){return false}if(!b.target&&d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var h=this.active.next(),e={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:h},c=(this.active=a([]));this._toggle(c,h,e);return false}var g=a(b.currentTarget||f);var i=g[0]==this.active[0];if(this.running||(!d.collapsible&&i)){return false}this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");if(!i){g.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);g.next().addClass("ui-accordion-content-active")}var c=g.next(),h=this.active.next(),e={options:d,newHeader:i&&d.collapsible?a([]):g,oldHeader:this.active,newContent:i&&d.collapsible?a([]):c.find("> *"),oldContent:h.find("> *")},j=this.headers.index(this.active[0])>this.headers.index(g[0]);this.active=i?a([]):g;this._toggle(c,h,e,i,j);return false},_toggle:function(b,i,g,j,k){var d=this.options,m=this;this.toShow=b;this.toHide=i;this.data=g;var c=function(){if(!m){return}return m._completed.apply(m,arguments)};this._trigger("changestart",null,this.data);this.running=i.size()===0?b.size():i.size();if(d.animated){var f={};if(d.collapsible&&j){f={toShow:a([]),toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}else{f={toShow:b,toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}if(!d.proxied){d.proxied=d.animated}if(!d.proxiedDuration){d.proxiedDuration=d.duration}d.animated=a.isFunction(d.proxied)?d.proxied(f):d.proxied;d.duration=a.isFunction(d.proxiedDuration)?d.proxiedDuration(f):d.proxiedDuration;var l=a.ui.accordion.animations,e=d.duration,h=d.animated;if(!l[h]){l[h]=function(n){this.slide(n,{easing:h,duration:e||700})}}l[h](f)}else{if(d.collapsible&&j){b.toggle()}else{i.hide();b.show()}c(true)}i.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();b.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(b){var c=this.options;this.running=b?0:--this.running;if(this.running){return}if(c.clearStyle){this.toShow.add(this.toHide).css({height:"",overflow:""})}this._trigger("change",null,this.data)}});a.extend(a.ui.accordion,{version:"1.7.2",defaults:{active:null,alwaysOpen:true,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},animations:{slide:function(j,h){j=a.extend({easing:"swing",duration:300},j,h);if(!j.toHide.size()){j.toShow.animate({height:"show"},j);return}if(!j.toShow.size()){j.toHide.animate({height:"hide"},j);return}var c=j.toShow.css("overflow"),g,d={},f={},e=["height","paddingTop","paddingBottom"],b;var i=j.toShow;b=i[0].style.width;i.width(parseInt(i.parent().width(),10)-parseInt(i.css("paddingLeft"),10)-parseInt(i.css("paddingRight"),10)-(parseInt(i.css("borderLeftWidth"),10)||0)-(parseInt(i.css("borderRightWidth"),10)||0));a.each(e,function(k,m){f[m]="hide";var l=(""+a.css(j.toShow[0],m)).match(/^([\d+-.]+)(.*)$/);d[m]={value:l[1],unit:l[2]||"px"}});j.toShow.css({height:0,overflow:"hidden"}).show();j.toHide.filter(":hidden").each(j.complete).end().filter(":visible").animate(f,{step:function(k,l){if(l.prop=="height"){g=(l.now-l.start)/(l.end-l.start)}j.toShow[0].style[l.prop]=(g*d[l.prop].value)+d[l.prop].unit},duration:j.duration,easing:j.easing,complete:function(){if(!j.autoHeight){j.toShow.css("height","")}j.toShow.css("width",b);j.toShow.css({overflow:c});j.complete()}})},bounceslide:function(b){this.slide(b,{easing:b.down?"easeOutBounce":"swing",duration:b.down?1000:200})},easeslide:function(b){this.slide(b,{easing:"easeinout",duration:700})}}})})(jQuery);(function($){$.extend($.ui,{datepicker:{version:"1.7.2"}});var PROP_NAME="datepicker";function Datepicker(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._datepickerShowing=false;this._inDialog=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass="ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],dateFormat:"mm/dd/yy",firstDay:0,isRTL:false};this._defaults={showOn:"focus",showAnim:"show",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,showMonthAfterYear:false,yearRange:"-10:+10",showOtherMonths:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"normal",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false};$.extend(this._defaults,this.regional[""]);this.dpDiv=$('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",log:function(){if(this.debug){console.log.apply("",arguments)}},setDefaults:function(settings){extendRemove(this._defaults,settings||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase();var inline=(nodeName=="div"||nodeName=="span");if(!target.id){target.id="dp"+(++this.uuid)}var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{});if(nodeName=="input"){this._connectDatepicker(target,inst)}else{if(inline){this._inlineDatepicker(target,inst)}}},_newInst:function(target,inline){var id=target[0].id.replace(/([:\[\]\.])/g,"\\\\$1");return{id:id,input:target,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:inline,dpDiv:(!inline?this.dpDiv:$('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}},_connectDatepicker:function(target,inst){var input=$(target);inst.append=$([]);inst.trigger=$([]);if(input.hasClass(this.markerClassName)){return}var appendText=this._get(inst,"appendText");var isRTL=this._get(inst,"isRTL");if(appendText){inst.append=$('<span class="'+this._appendClass+'">'+appendText+"</span>");input[isRTL?"before":"after"](inst.append)}var showOn=this._get(inst,"showOn");if(showOn=="focus"||showOn=="both"){input.focus(this._showDatepicker)}if(showOn=="button"||showOn=="both"){var buttonText=this._get(inst,"buttonText");var buttonImage=this._get(inst,"buttonImage");inst.trigger=$(this._get(inst,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:buttonImage,alt:buttonText,title:buttonText}):$('<button type="button"></button>').addClass(this._triggerClass).html(buttonImage==""?buttonText:$("<img/>").attr({src:buttonImage,alt:buttonText,title:buttonText})));input[isRTL?"before":"after"](inst.trigger);inst.trigger.click(function(){if($.datepicker._datepickerShowing&&$.datepicker._lastInput==target){$.datepicker._hideDatepicker()}else{$.datepicker._showDatepicker(target)}return false})}input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst)},_inlineDatepicker:function(target,inst){var divSpan=$(target);if(divSpan.hasClass(this.markerClassName)){return}divSpan.addClass(this.markerClassName).append(inst.dpDiv).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst);this._setDate(inst,this._getDefaultDate(inst));this._updateDatepicker(inst);this._updateAlternate(inst)},_dialogDatepicker:function(input,dateText,onSelect,settings,pos){var inst=this._dialogInst;if(!inst){var id="dp"+(++this.uuid);this._dialogInput=$('<input type="text" id="'+id+'" size="1" style="position: absolute; top: -100px;"/>');this._dialogInput.keydown(this._doKeyDown);$("body").append(this._dialogInput);inst=this._dialogInst=this._newInst(this._dialogInput,false);inst.settings={};$.data(this._dialogInput[0],PROP_NAME,inst)}extendRemove(inst.settings,settings||{});this._dialogInput.val(dateText);this._pos=(pos?(pos.length?pos:[pos.pageX,pos.pageY]):null);if(!this._pos){var browserWidth=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;var browserHeight=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;var scrollX=document.documentElement.scrollLeft||document.body.scrollLeft;var scrollY=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[(browserWidth/2)-100+scrollX,(browserHeight/2)-150+scrollY]}this._dialogInput.css("left",this._pos[0]+"px").css("top",this._pos[1]+"px");inst.settings.onSelect=onSelect;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);if($.blockUI){$.blockUI(this.dpDiv)}$.data(this._dialogInput[0],PROP_NAME,inst);return this},_destroyDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();$.removeData(target,PROP_NAME);if(nodeName=="input"){inst.append.remove();inst.trigger.remove();$target.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress)}else{if(nodeName=="div"||nodeName=="span"){$target.removeClass(this.markerClassName).empty()}}},_enableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=false;inst.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().removeClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)})},_disableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=true;inst.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().addClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)});this._disabledInputs[this._disabledInputs.length]=target},_isDisabledDatepicker:function(target){if(!target){return false}for(var i=0;i<this._disabledInputs.length;i++){if(this._disabledInputs[i]==target){return true}}return false},_getInst:function(target){try{return $.data(target,PROP_NAME)}catch(err){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(target,name,value){var inst=this._getInst(target);if(arguments.length==2&&typeof name=="string"){return(name=="defaults"?$.extend({},$.datepicker._defaults):(inst?(name=="all"?$.extend({},inst.settings):this._get(inst,name)):null))}var settings=name||{};if(typeof name=="string"){settings={};settings[name]=value}if(inst){if(this._curInst==inst){this._hideDatepicker(null)}var date=this._getDateDatepicker(target);extendRemove(inst.settings,settings);this._setDateDatepicker(target,date);this._updateDatepicker(inst)}},_changeDatepicker:function(target,name,value){this._optionDatepicker(target,name,value)},_refreshDatepicker:function(target){var inst=this._getInst(target);if(inst){this._updateDatepicker(inst)}},_setDateDatepicker:function(target,date,endDate){var inst=this._getInst(target);if(inst){this._setDate(inst,date,endDate);this._updateDatepicker(inst);this._updateAlternate(inst)}},_getDateDatepicker:function(target){var inst=this._getInst(target);if(inst&&!inst.inline){this._setDateFromField(inst)}return(inst?this._getDate(inst):null)},_doKeyDown:function(event){var inst=$.datepicker._getInst(event.target);var handled=true;var isRTL=inst.dpDiv.is(".ui-datepicker-rtl");inst._keyEvent=true;if($.datepicker._datepickerShowing){switch(event.keyCode){case 9:$.datepicker._hideDatepicker(null,"");break;case 13:var sel=$("td."+$.datepicker._dayOverClass+", td."+$.datepicker._currentClass,inst.dpDiv);if(sel[0]){$.datepicker._selectDay(event.target,inst.selectedMonth,inst.selectedYear,sel[0])}else{$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"))}return false;break;case 27:$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"));break;case 33:$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M");break;case 34:$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M");break;case 35:if(event.ctrlKey||event.metaKey){$.datepicker._clearDate(event.target)}handled=event.ctrlKey||event.metaKey;break;case 36:if(event.ctrlKey||event.metaKey){$.datepicker._gotoToday(event.target)}handled=event.ctrlKey||event.metaKey;break;case 37:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?+1:-1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M")}break;case 38:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,-7,"D")}handled=event.ctrlKey||event.metaKey;break;case 39:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?-1:+1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M")}break;case 40:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,+7,"D")}handled=event.ctrlKey||event.metaKey;break;default:handled=false}}else{if(event.keyCode==36&&event.ctrlKey){$.datepicker._showDatepicker(this)}else{handled=false}}if(handled){event.preventDefault();event.stopPropagation()}},_doKeyPress:function(event){var inst=$.datepicker._getInst(event.target);if($.datepicker._get(inst,"constrainInput")){var chars=$.datepicker._possibleChars($.datepicker._get(inst,"dateFormat"));var chr=String.fromCharCode(event.charCode==undefined?event.keyCode:event.charCode);return event.ctrlKey||(chr<" "||!chars||chars.indexOf(chr)>-1)}},_showDatepicker:function(input){input=input.target||input;if(input.nodeName.toLowerCase()!="input"){input=$("input",input.parentNode)[0]}if($.datepicker._isDisabledDatepicker(input)||$.datepicker._lastInput==input){return}var inst=$.datepicker._getInst(input);var beforeShow=$.datepicker._get(inst,"beforeShow");extendRemove(inst.settings,(beforeShow?beforeShow.apply(input,[input,inst]):{}));$.datepicker._hideDatepicker(null,"");$.datepicker._lastInput=input;$.datepicker._setDateFromField(inst);if($.datepicker._inDialog){input.value=""}if(!$.datepicker._pos){$.datepicker._pos=$.datepicker._findPos(input);$.datepicker._pos[1]+=input.offsetHeight}var isFixed=false;$(input).parents().each(function(){isFixed|=$(this).css("position")=="fixed";return !isFixed});if(isFixed&&$.browser.opera){$.datepicker._pos[0]-=document.documentElement.scrollLeft;$.datepicker._pos[1]-=document.documentElement.scrollTop}var offset={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null;inst.rangeStart=null;inst.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});$.datepicker._updateDatepicker(inst);offset=$.datepicker._checkOffset(inst,offset,isFixed);inst.dpDiv.css({position:($.datepicker._inDialog&&$.blockUI?"static":(isFixed?"fixed":"absolute")),display:"none",left:offset.left+"px",top:offset.top+"px"});if(!inst.inline){var showAnim=$.datepicker._get(inst,"showAnim")||"show";var duration=$.datepicker._get(inst,"duration");var postProcess=function(){$.datepicker._datepickerShowing=true;if($.browser.msie&&parseInt($.browser.version,10)<7){$("iframe.ui-datepicker-cover").css({width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4})}};if($.effects&&$.effects[showAnim]){inst.dpDiv.show(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[showAnim](duration,postProcess)}if(duration==""){postProcess()}if(inst.input[0].type!="hidden"){inst.input[0].focus()}$.datepicker._curInst=inst}},_updateDatepicker:function(inst){var dims={width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4};var self=this;inst.dpDiv.empty().append(this._generateHTML(inst)).find("iframe.ui-datepicker-cover").css({width:dims.width,height:dims.height}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){$(this).removeClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).removeClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).removeClass("ui-datepicker-next-hover")}}).bind("mouseover",function(){if(!self._isDisabledDatepicker(inst.inline?inst.dpDiv.parent()[0]:inst.input[0])){$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");$(this).addClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).addClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).addClass("ui-datepicker-next-hover")}}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();var numMonths=this._getNumberOfMonths(inst);var cols=numMonths[1];var width=17;if(cols>1){inst.dpDiv.addClass("ui-datepicker-multi-"+cols).css("width",(width*cols)+"em")}else{inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("")}inst.dpDiv[(numMonths[0]!=1||numMonths[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");inst.dpDiv[(this._get(inst,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");if(inst.input&&inst.input[0].type!="hidden"&&inst==$.datepicker._curInst){$(inst.input[0]).focus()}},_checkOffset:function(inst,offset,isFixed){var dpWidth=inst.dpDiv.outerWidth();var dpHeight=inst.dpDiv.outerHeight();var inputWidth=inst.input?inst.input.outerWidth():0;var inputHeight=inst.input?inst.input.outerHeight():0;var viewWidth=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)+$(document).scrollLeft();var viewHeight=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)+$(document).scrollTop();offset.left-=(this._get(inst,"isRTL")?(dpWidth-inputWidth):0);offset.left-=(isFixed&&offset.left==inst.input.offset().left)?$(document).scrollLeft():0;offset.top-=(isFixed&&offset.top==(inst.input.offset().top+inputHeight))?$(document).scrollTop():0;offset.left-=(offset.left+dpWidth>viewWidth&&viewWidth>dpWidth)?Math.abs(offset.left+dpWidth-viewWidth):0;offset.top-=(offset.top+dpHeight>viewHeight&&viewHeight>dpHeight)?Math.abs(offset.top+dpHeight+inputHeight*2-viewHeight):0;return offset},_findPos:function(obj){while(obj&&(obj.type=="hidden"||obj.nodeType!=1)){obj=obj.nextSibling}var position=$(obj).offset();return[position.left,position.top]},_hideDatepicker:function(input,duration){var inst=this._curInst;if(!inst||(input&&inst!=$.data(input,PROP_NAME))){return}if(inst.stayOpen){this._selectDate("#"+inst.id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear))}inst.stayOpen=false;if(this._datepickerShowing){duration=(duration!=null?duration:this._get(inst,"duration"));var showAnim=this._get(inst,"showAnim");var postProcess=function(){$.datepicker._tidyDialog(inst)};if(duration!=""&&$.effects&&$.effects[showAnim]){inst.dpDiv.hide(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[(duration==""?"hide":(showAnim=="slideDown"?"slideUp":(showAnim=="fadeIn"?"fadeOut":"hide")))](duration,postProcess)}if(duration==""){this._tidyDialog(inst)}var onClose=this._get(inst,"onClose");if(onClose){onClose.apply((inst.input?inst.input[0]:null),[(inst.input?inst.input.val():""),inst])}this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if($.blockUI){$.unblockUI();$("body").append(this.dpDiv)}}this._inDialog=false}this._curInst=null},_tidyDialog:function(inst){inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(event){if(!$.datepicker._curInst){return}var $target=$(event.target);if(($target.parents("#"+$.datepicker._mainDivId).length==0)&&!$target.hasClass($.datepicker.markerClassName)&&!$target.hasClass($.datepicker._triggerClass)&&$.datepicker._datepickerShowing&&!($.datepicker._inDialog&&$.blockUI)){$.datepicker._hideDatepicker(null,"")}},_adjustDate:function(id,offset,period){var target=$(id);var inst=this._getInst(target[0]);if(this._isDisabledDatepicker(target[0])){return}this._adjustInstDate(inst,offset+(period=="M"?this._get(inst,"showCurrentAtPos"):0),period);this._updateDatepicker(inst)},_gotoToday:function(id){var target=$(id);var inst=this._getInst(target[0]);if(this._get(inst,"gotoCurrent")&&inst.currentDay){inst.selectedDay=inst.currentDay;inst.drawMonth=inst.selectedMonth=inst.currentMonth;inst.drawYear=inst.selectedYear=inst.currentYear}else{var date=new Date();inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear()}this._notifyChange(inst);this._adjustDate(target)},_selectMonthYear:function(id,select,period){var target=$(id);var inst=this._getInst(target[0]);inst._selectingMonthYear=false;inst["selected"+(period=="M"?"Month":"Year")]=inst["draw"+(period=="M"?"Month":"Year")]=parseInt(select.options[select.selectedIndex].value,10);this._notifyChange(inst);this._adjustDate(target)},_clickMonthYear:function(id){var target=$(id);var inst=this._getInst(target[0]);if(inst.input&&inst._selectingMonthYear&&!$.browser.msie){inst.input[0].focus()}inst._selectingMonthYear=!inst._selectingMonthYear},_selectDay:function(id,month,year,td){var target=$(id);if($(td).hasClass(this._unselectableClass)||this._isDisabledDatepicker(target[0])){return}var inst=this._getInst(target[0]);inst.selectedDay=inst.currentDay=$("a",td).html();inst.selectedMonth=inst.currentMonth=month;inst.selectedYear=inst.currentYear=year;if(inst.stayOpen){inst.endDay=inst.endMonth=inst.endYear=null}this._selectDate(id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear));if(inst.stayOpen){inst.rangeStart=this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay));this._updateDatepicker(inst)}},_clearDate:function(id){var target=$(id);var inst=this._getInst(target[0]);inst.stayOpen=false;inst.endDay=inst.endMonth=inst.endYear=inst.rangeStart=null;this._selectDate(target,"")},_selectDate:function(id,dateStr){var target=$(id);var inst=this._getInst(target[0]);dateStr=(dateStr!=null?dateStr:this._formatDate(inst));if(inst.input){inst.input.val(dateStr)}this._updateAlternate(inst);var onSelect=this._get(inst,"onSelect");if(onSelect){onSelect.apply((inst.input?inst.input[0]:null),[dateStr,inst])}else{if(inst.input){inst.input.trigger("change")}}if(inst.inline){this._updateDatepicker(inst)}else{if(!inst.stayOpen){this._hideDatepicker(null,this._get(inst,"duration"));this._lastInput=inst.input[0];if(typeof(inst.input[0])!="object"){inst.input[0].focus()}this._lastInput=null}}},_updateAlternate:function(inst){var altField=this._get(inst,"altField");if(altField){var altFormat=this._get(inst,"altFormat")||this._get(inst,"dateFormat");var date=this._getDate(inst);dateStr=this.formatDate(altFormat,date,this._getFormatConfig(inst));$(altField).each(function(){$(this).val(dateStr)})}},noWeekends:function(date){var day=date.getDay();return[(day>0&&day<6),""]},iso8601Week:function(date){var checkDate=new Date(date.getFullYear(),date.getMonth(),date.getDate());var firstMon=new Date(checkDate.getFullYear(),1-1,4);var firstDay=firstMon.getDay()||7;firstMon.setDate(firstMon.getDate()+1-firstDay);if(firstDay<4&&checkDate<firstMon){checkDate.setDate(checkDate.getDate()-3);return $.datepicker.iso8601Week(checkDate)}else{if(checkDate>new Date(checkDate.getFullYear(),12-1,28)){firstDay=new Date(checkDate.getFullYear()+1,1-1,4).getDay()||7;if(firstDay>4&&(checkDate.getDay()||7)<firstDay-3){return 1}}}return Math.floor(((checkDate-firstMon)/86400000)/7)+1},parseDate:function(format,value,settings){if(format==null||value==null){throw"Invalid arguments"}value=(typeof value=="object"?value.toString():value+"");if(value==""){return null}var shortYearCutoff=(settings?settings.shortYearCutoff:null)||this._defaults.shortYearCutoff;var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var year=-1;var month=-1;var day=-1;var doy=-1;var literal=false;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var getNumber=function(match){lookAhead(match);var origSize=(match=="@"?14:(match=="y"?4:(match=="o"?3:2)));var size=origSize;var num=0;while(size>0&&iValue<value.length&&value.charAt(iValue)>="0"&&value.charAt(iValue)<="9"){num=num*10+parseInt(value.charAt(iValue++),10);size--}if(size==origSize){throw"Missing number at position "+iValue}return num};var getName=function(match,shortNames,longNames){var names=(lookAhead(match)?longNames:shortNames);var size=0;for(var j=0;j<names.length;j++){size=Math.max(size,names[j].length)}var name="";var iInit=iValue;while(size>0&&iValue<value.length){name+=value.charAt(iValue++);for(var i=0;i<names.length;i++){if(name==names[i]){return i+1}}size--}throw"Unknown name at position "+iInit};var checkLiteral=function(){if(value.charAt(iValue)!=format.charAt(iFormat)){throw"Unexpected literal at position "+iValue}iValue++};var iValue=0;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{checkLiteral()}}else{switch(format.charAt(iFormat)){case"d":day=getNumber("d");break;case"D":getName("D",dayNamesShort,dayNames);break;case"o":doy=getNumber("o");break;case"m":month=getNumber("m");break;case"M":month=getName("M",monthNamesShort,monthNames);break;case"y":year=getNumber("y");break;case"@":var date=new Date(getNumber("@"));year=date.getFullYear();month=date.getMonth()+1;day=date.getDate();break;case"'":if(lookAhead("'")){checkLiteral()}else{literal=true}break;default:checkLiteral()}}}if(year==-1){year=new Date().getFullYear()}else{if(year<100){year+=new Date().getFullYear()-new Date().getFullYear()%100+(year<=shortYearCutoff?0:-100)}}if(doy>-1){month=1;day=doy;do{var dim=this._getDaysInMonth(year,month-1);if(day<=dim){break}month++;day-=dim}while(true)}var date=this._daylightSavingAdjust(new Date(year,month-1,day));if(date.getFullYear()!=year||date.getMonth()+1!=month||date.getDate()!=day){throw"Invalid date"}return date},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TIMESTAMP:"@",W3C:"yy-mm-dd",formatDate:function(format,date,settings){if(!date){return""}var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var formatNumber=function(match,value,len){var num=""+value;if(lookAhead(match)){while(num.length<len){num="0"+num}}return num};var formatName=function(match,value,shortNames,longNames){return(lookAhead(match)?longNames[value]:shortNames[value])};var output="";var literal=false;if(date){for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{output+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":output+=formatNumber("d",date.getDate(),2);break;case"D":output+=formatName("D",date.getDay(),dayNamesShort,dayNames);break;case"o":var doy=date.getDate();for(var m=date.getMonth()-1;m>=0;m--){doy+=this._getDaysInMonth(date.getFullYear(),m)}output+=formatNumber("o",doy,3);break;case"m":output+=formatNumber("m",date.getMonth()+1,2);break;case"M":output+=formatName("M",date.getMonth(),monthNamesShort,monthNames);break;case"y":output+=(lookAhead("y")?date.getFullYear():(date.getYear()%100<10?"0":"")+date.getYear()%100);break;case"@":output+=date.getTime();break;case"'":if(lookAhead("'")){output+="'"}else{literal=true}break;default:output+=format.charAt(iFormat)}}}}return output},_possibleChars:function(format){var chars="";var literal=false;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{chars+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":case"m":case"y":case"@":chars+="0123456789";break;case"D":case"M":return null;case"'":if(lookAhead("'")){chars+="'"}else{literal=true}break;default:chars+=format.charAt(iFormat)}}}return chars},_get:function(inst,name){return inst.settings[name]!==undefined?inst.settings[name]:this._defaults[name]},_setDateFromField:function(inst){var dateFormat=this._get(inst,"dateFormat");var dates=inst.input?inst.input.val():null;inst.endDay=inst.endMonth=inst.endYear=null;var date=defaultDate=this._getDefaultDate(inst);var settings=this._getFormatConfig(inst);try{date=this.parseDate(dateFormat,dates,settings)||defaultDate}catch(event){this.log(event);date=defaultDate}inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();inst.currentDay=(dates?date.getDate():0);inst.currentMonth=(dates?date.getMonth():0);inst.currentYear=(dates?date.getFullYear():0);this._adjustInstDate(inst)},_getDefaultDate:function(inst){var date=this._determineDate(this._get(inst,"defaultDate"),new Date());var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);return date},_determineDate:function(date,defaultDate){var offsetNumeric=function(offset){var date=new Date();date.setDate(date.getDate()+offset);return date};var offsetString=function(offset,getDaysInMonth){var date=new Date();var year=date.getFullYear();var month=date.getMonth();var day=date.getDate();var pattern=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;var matches=pattern.exec(offset);while(matches){switch(matches[2]||"d"){case"d":case"D":day+=parseInt(matches[1],10);break;case"w":case"W":day+=parseInt(matches[1],10)*7;break;case"m":case"M":month+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break;case"y":case"Y":year+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break}matches=pattern.exec(offset)}return new Date(year,month,day)};date=(date==null?defaultDate:(typeof date=="string"?offsetString(date,this._getDaysInMonth):(typeof date=="number"?(isNaN(date)?defaultDate:offsetNumeric(date)):date)));date=(date&&date.toString()=="Invalid Date"?defaultDate:date);if(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0)}return this._daylightSavingAdjust(date)},_daylightSavingAdjust:function(date){if(!date){return null}date.setHours(date.getHours()>12?date.getHours()+2:0);return date},_setDate:function(inst,date,endDate){var clear=!(date);var origMonth=inst.selectedMonth;var origYear=inst.selectedYear;date=this._determineDate(date,new Date());inst.selectedDay=inst.currentDay=date.getDate();inst.drawMonth=inst.selectedMonth=inst.currentMonth=date.getMonth();inst.drawYear=inst.selectedYear=inst.currentYear=date.getFullYear();if(origMonth!=inst.selectedMonth||origYear!=inst.selectedYear){this._notifyChange(inst)}this._adjustInstDate(inst);if(inst.input){inst.input.val(clear?"":this._formatDate(inst))}},_getDate:function(inst){var startDate=(!inst.currentYear||(inst.input&&inst.input.val()=="")?null:this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return startDate},_generateHTML:function(inst){var today=new Date();today=this._daylightSavingAdjust(new Date(today.getFullYear(),today.getMonth(),today.getDate()));var isRTL=this._get(inst,"isRTL");var showButtonPanel=this._get(inst,"showButtonPanel");var hideIfNoPrevNext=this._get(inst,"hideIfNoPrevNext");var navigationAsDateFormat=this._get(inst,"navigationAsDateFormat");var numMonths=this._getNumberOfMonths(inst);var showCurrentAtPos=this._get(inst,"showCurrentAtPos");var stepMonths=this._get(inst,"stepMonths");var stepBigMonths=this._get(inst,"stepBigMonths");var isMultiMonth=(numMonths[0]!=1||numMonths[1]!=1);var currentDate=this._daylightSavingAdjust((!inst.currentDay?new Date(9999,9,9):new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");var drawMonth=inst.drawMonth-showCurrentAtPos;var drawYear=inst.drawYear;if(drawMonth<0){drawMonth+=12;drawYear--}if(maxDate){var maxDraw=this._daylightSavingAdjust(new Date(maxDate.getFullYear(),maxDate.getMonth()-numMonths[1]+1,maxDate.getDate()));maxDraw=(minDate&&maxDraw<minDate?minDate:maxDraw);while(this._daylightSavingAdjust(new Date(drawYear,drawMonth,1))>maxDraw){drawMonth--;if(drawMonth<0){drawMonth=11;drawYear--}}}inst.drawMonth=drawMonth;inst.drawYear=drawYear;var prevText=this._get(inst,"prevText");prevText=(!navigationAsDateFormat?prevText:this.formatDate(prevText,this._daylightSavingAdjust(new Date(drawYear,drawMonth-stepMonths,1)),this._getFormatConfig(inst)));var prev=(this._canAdjustMonth(inst,-1,drawYear,drawMonth)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', -"+stepMonths+", 'M');\" title=\""+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>"));var nextText=this._get(inst,"nextText");nextText=(!navigationAsDateFormat?nextText:this.formatDate(nextText,this._daylightSavingAdjust(new Date(drawYear,drawMonth+stepMonths,1)),this._getFormatConfig(inst)));var next=(this._canAdjustMonth(inst,+1,drawYear,drawMonth)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', +"+stepMonths+", 'M');\" title=\""+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>"));var currentText=this._get(inst,"currentText");var gotoDate=(this._get(inst,"gotoCurrent")&&inst.currentDay?currentDate:today);currentText=(!navigationAsDateFormat?currentText:this.formatDate(currentText,gotoDate,this._getFormatConfig(inst)));var controls=(!inst.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">'+this._get(inst,"closeText")+"</button>":"");var buttonPanel=(showButtonPanel)?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(isRTL?controls:"")+(this._isInRange(inst,gotoDate)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#'+inst.id+"');\">"+currentText+"</button>":"")+(isRTL?"":controls)+"</div>":"";var firstDay=parseInt(this._get(inst,"firstDay"),10);firstDay=(isNaN(firstDay)?0:firstDay);var dayNames=this._get(inst,"dayNames");var dayNamesShort=this._get(inst,"dayNamesShort");var dayNamesMin=this._get(inst,"dayNamesMin");var monthNames=this._get(inst,"monthNames");var monthNamesShort=this._get(inst,"monthNamesShort");var beforeShowDay=this._get(inst,"beforeShowDay");var showOtherMonths=this._get(inst,"showOtherMonths");var calculateWeek=this._get(inst,"calculateWeek")||this.iso8601Week;var endDate=inst.endDay?this._daylightSavingAdjust(new Date(inst.endYear,inst.endMonth,inst.endDay)):currentDate;var defaultDate=this._getDefaultDate(inst);var html="";for(var row=0;row<numMonths[0];row++){var group="";for(var col=0;col<numMonths[1];col++){var selectedDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,inst.selectedDay));var cornerClass=" ui-corner-all";var calender="";if(isMultiMonth){calender+='<div class="ui-datepicker-group ui-datepicker-group-';switch(col){case 0:calender+="first";cornerClass=" ui-corner-"+(isRTL?"right":"left");break;case numMonths[1]-1:calender+="last";cornerClass=" ui-corner-"+(isRTL?"left":"right");break;default:calender+="middle";cornerClass="";break}calender+='">'}calender+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+cornerClass+'">'+(/all|left/.test(cornerClass)&&row==0?(isRTL?next:prev):"")+(/all|right/.test(cornerClass)&&row==0?(isRTL?prev:next):"")+this._generateMonthYearHeader(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,row>0||col>0,monthNames,monthNamesShort)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var thead="";for(var dow=0;dow<7;dow++){var day=(dow+firstDay)%7;thead+="<th"+((dow+firstDay+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+dayNames[day]+'">'+dayNamesMin[day]+"</span></th>"}calender+=thead+"</tr></thead><tbody>";var daysInMonth=this._getDaysInMonth(drawYear,drawMonth);if(drawYear==inst.selectedYear&&drawMonth==inst.selectedMonth){inst.selectedDay=Math.min(inst.selectedDay,daysInMonth)}var leadDays=(this._getFirstDayOfMonth(drawYear,drawMonth)-firstDay+7)%7;var numRows=(isMultiMonth?6:Math.ceil((leadDays+daysInMonth)/7));var printDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,1-leadDays));for(var dRow=0;dRow<numRows;dRow++){calender+="<tr>";var tbody="";for(var dow=0;dow<7;dow++){var daySettings=(beforeShowDay?beforeShowDay.apply((inst.input?inst.input[0]:null),[printDate]):[true,""]);var otherMonth=(printDate.getMonth()!=drawMonth);var unselectable=otherMonth||!daySettings[0]||(minDate&&printDate<minDate)||(maxDate&&printDate>maxDate);tbody+='<td class="'+((dow+firstDay+6)%7>=5?" ui-datepicker-week-end":"")+(otherMonth?" ui-datepicker-other-month":"")+((printDate.getTime()==selectedDate.getTime()&&drawMonth==inst.selectedMonth&&inst._keyEvent)||(defaultDate.getTime()==printDate.getTime()&&defaultDate.getTime()==selectedDate.getTime())?" "+this._dayOverClass:"")+(unselectable?" "+this._unselectableClass+" ui-state-disabled":"")+(otherMonth&&!showOtherMonths?"":" "+daySettings[1]+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" "+this._currentClass:"")+(printDate.getTime()==today.getTime()?" ui-datepicker-today":""))+'"'+((!otherMonth||showOtherMonths)&&daySettings[2]?' title="'+daySettings[2]+'"':"")+(unselectable?"":" onclick=\"DP_jQuery.datepicker._selectDay('#"+inst.id+"',"+drawMonth+","+drawYear+', this);return false;"')+">"+(otherMonth?(showOtherMonths?printDate.getDate():" "):(unselectable?'<span class="ui-state-default">'+printDate.getDate()+"</span>":'<a class="ui-state-default'+(printDate.getTime()==today.getTime()?" ui-state-highlight":"")+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" ui-state-active":"")+'" href="#">'+printDate.getDate()+"</a>"))+"</td>";printDate.setDate(printDate.getDate()+1);printDate=this._daylightSavingAdjust(printDate)}calender+=tbody+"</tr>"}drawMonth++;if(drawMonth>11){drawMonth=0;drawYear++}calender+="</tbody></table>"+(isMultiMonth?"</div>"+((numMonths[0]>0&&col==numMonths[1]-1)?'<div class="ui-datepicker-row-break"></div>':""):"");group+=calender}html+=group}html+=buttonPanel+($.browser.msie&&parseInt($.browser.version,10)<7&&!inst.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");inst._keyEvent=false;return html},_generateMonthYearHeader:function(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,secondary,monthNames,monthNamesShort){minDate=(inst.rangeStart&&minDate&&selectedDate<minDate?selectedDate:minDate);var changeMonth=this._get(inst,"changeMonth");var changeYear=this._get(inst,"changeYear");var showMonthAfterYear=this._get(inst,"showMonthAfterYear");var html='<div class="ui-datepicker-title">';var monthHtml="";if(secondary||!changeMonth){monthHtml+='<span class="ui-datepicker-month">'+monthNames[drawMonth]+"</span> "}else{var inMinYear=(minDate&&minDate.getFullYear()==drawYear);var inMaxYear=(maxDate&&maxDate.getFullYear()==drawYear);monthHtml+='<select class="ui-datepicker-month" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'M');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(var month=0;month<12;month++){if((!inMinYear||month>=minDate.getMonth())&&(!inMaxYear||month<=maxDate.getMonth())){monthHtml+='<option value="'+month+'"'+(month==drawMonth?' selected="selected"':"")+">"+monthNamesShort[month]+"</option>"}}monthHtml+="</select>"}if(!showMonthAfterYear){html+=monthHtml+((secondary||changeMonth||changeYear)&&(!(changeMonth&&changeYear))?" ":"")}if(secondary||!changeYear){html+='<span class="ui-datepicker-year">'+drawYear+"</span>"}else{var years=this._get(inst,"yearRange").split(":");var year=0;var endYear=0;if(years.length!=2){year=drawYear-10;endYear=drawYear+10}else{if(years[0].charAt(0)=="+"||years[0].charAt(0)=="-"){year=drawYear+parseInt(years[0],10);endYear=drawYear+parseInt(years[1],10)}else{year=parseInt(years[0],10);endYear=parseInt(years[1],10)}}year=(minDate?Math.max(year,minDate.getFullYear()):year);endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);html+='<select class="ui-datepicker-year" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'Y');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(;year<=endYear;year++){html+='<option value="'+year+'"'+(year==drawYear?' selected="selected"':"")+">"+year+"</option>"}html+="</select>"}if(showMonthAfterYear){html+=(secondary||changeMonth||changeYear?" ":"")+monthHtml}html+="</div>";return html},_adjustInstDate:function(inst,offset,period){var year=inst.drawYear+(period=="Y"?offset:0);var month=inst.drawMonth+(period=="M"?offset:0);var day=Math.min(inst.selectedDay,this._getDaysInMonth(year,month))+(period=="D"?offset:0);var date=this._daylightSavingAdjust(new Date(year,month,day));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();if(period=="M"||period=="Y"){this._notifyChange(inst)}},_notifyChange:function(inst){var onChange=this._get(inst,"onChangeMonthYear");if(onChange){onChange.apply((inst.input?inst.input[0]:null),[inst.selectedYear,inst.selectedMonth+1,inst])}},_getNumberOfMonths:function(inst){var numMonths=this._get(inst,"numberOfMonths");return(numMonths==null?[1,1]:(typeof numMonths=="number"?[1,numMonths]:numMonths))},_getMinMaxDate:function(inst,minMax,checkRange){var date=this._determineDate(this._get(inst,minMax+"Date"),null);return(!checkRange||!inst.rangeStart?date:(!date||inst.rangeStart>date?inst.rangeStart:date))},_getDaysInMonth:function(year,month){return 32-new Date(year,month,32).getDate()},_getFirstDayOfMonth:function(year,month){return new Date(year,month,1).getDay()},_canAdjustMonth:function(inst,offset,curYear,curMonth){var numMonths=this._getNumberOfMonths(inst);var date=this._daylightSavingAdjust(new Date(curYear,curMonth+(offset<0?offset:numMonths[1]),1));if(offset<0){date.setDate(this._getDaysInMonth(date.getFullYear(),date.getMonth()))}return this._isInRange(inst,date)},_isInRange:function(inst,date){var newMinDate=(!inst.rangeStart?null:this._daylightSavingAdjust(new Date(inst.selectedYear,inst.selectedMonth,inst.selectedDay)));newMinDate=(newMinDate&&inst.rangeStart<newMinDate?inst.rangeStart:newMinDate);var minDate=newMinDate||this._getMinMaxDate(inst,"min");var maxDate=this._getMinMaxDate(inst,"max");return((!minDate||date>=minDate)&&(!maxDate||date<=maxDate))},_getFormatConfig:function(inst){var shortYearCutoff=this._get(inst,"shortYearCutoff");shortYearCutoff=(typeof shortYearCutoff!="string"?shortYearCutoff:new Date().getFullYear()%100+parseInt(shortYearCutoff,10));return{shortYearCutoff:shortYearCutoff,dayNamesShort:this._get(inst,"dayNamesShort"),dayNames:this._get(inst,"dayNames"),monthNamesShort:this._get(inst,"monthNamesShort"),monthNames:this._get(inst,"monthNames")}},_formatDate:function(inst,day,month,year){if(!day){inst.currentDay=inst.selectedDay;inst.currentMonth=inst.selectedMonth;inst.currentYear=inst.selectedYear}var date=(day?(typeof day=="object"?day:this._daylightSavingAdjust(new Date(year,month,day))):this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return this.formatDate(this._get(inst,"dateFormat"),date,this._getFormatConfig(inst))}});function extendRemove(target,props){$.extend(target,props);for(var name in props){if(props[name]==null||props[name]==undefined){target[name]=props[name]}}return target}function isArray(a){return(a&&(($.browser.safari&&typeof a=="object"&&a.length)||(a.constructor&&a.constructor.toString().match(/\Array\(\)/))))}$.fn.datepicker=function(options){if(!$.datepicker.initialized){$(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv);$.datepicker.initialized=true}var otherArgs=Array.prototype.slice.call(arguments,1);if(typeof options=="string"&&(options=="isDisabled"||options=="getDate")){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}if(options=="option"&&arguments.length==2&&typeof arguments[1]=="string"){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}return this.each(function(){typeof options=="string"?$.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this].concat(otherArgs)):$.datepicker._attachDatepicker(this,options)})};$.datepicker=new Datepicker();$.datepicker.initialized=false;$.datepicker.uuid=new Date().getTime();$.datepicker.version="1.7.2";window.DP_jQuery=$})(jQuery);(function(c){var b={dragStart:"start.draggable",drag:"drag.draggable",dragStop:"stop.draggable",maxHeight:"maxHeight.resizable",minHeight:"minHeight.resizable",maxWidth:"maxWidth.resizable",minWidth:"minWidth.resizable",resizeStart:"start.resizable",resize:"drag.resizable",resizeStop:"stop.resizable"},a="ui-dialog ui-widget ui-widget-content ui-corner-all ";c.widget("ui.dialog",{_init:function(){this.originalTitle=this.element.attr("title");var l=this,m=this.options,j=m.title||this.originalTitle||" ",e=c.ui.dialog.getTitleId(this.element),k=(this.uiDialog=c("<div/>")).appendTo(document.body).hide().addClass(a+m.dialogClass).css({position:"absolute",overflow:"hidden",zIndex:m.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(n){(m.closeOnEscape&&n.keyCode&&n.keyCode==c.ui.keyCode.ESCAPE&&l.close(n))}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(n){l.moveToTop(false,n)}),g=this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(k),f=(this.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(k),i=c('<a href="#"/>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){i.addClass("ui-state-hover")},function(){i.removeClass("ui-state-hover")}).focus(function(){i.addClass("ui-state-focus")}).blur(function(){i.removeClass("ui-state-focus")}).mousedown(function(n){n.stopPropagation()}).click(function(n){l.close(n);return false}).appendTo(f),h=(this.uiDialogTitlebarCloseText=c("<span/>")).addClass("ui-icon ui-icon-closethick").text(m.closeText).appendTo(i),d=c("<span/>").addClass("ui-dialog-title").attr("id",e).html(j).prependTo(f);f.find("*").add(f).disableSelection();(m.draggable&&c.fn.draggable&&this._makeDraggable());(m.resizable&&c.fn.resizable&&this._makeResizable());this._createButtons(m.buttons);this._isOpen=false;(m.bgiframe&&c.fn.bgiframe&&k.bgiframe());(m.autoOpen&&this.open())},destroy:function(){(this.overlay&&this.overlay.destroy());this.uiDialog.hide();this.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");this.uiDialog.remove();(this.originalTitle&&this.element.attr("title",this.originalTitle))},close:function(f){var d=this;if(false===d._trigger("beforeclose",f)){return}(d.overlay&&d.overlay.destroy());d.uiDialog.unbind("keypress.ui-dialog");(d.options.hide?d.uiDialog.hide(d.options.hide,function(){d._trigger("close",f)}):d.uiDialog.hide()&&d._trigger("close",f));c.ui.dialog.overlay.resize();d._isOpen=false;if(d.options.modal){var e=0;c(".ui-dialog").each(function(){if(this!=d.uiDialog[0]){e=Math.max(e,c(this).css("z-index"))}});c.ui.dialog.maxZ=e}},isOpen:function(){return this._isOpen},moveToTop:function(f,e){if((this.options.modal&&!f)||(!this.options.stack&&!this.options.modal)){return this._trigger("focus",e)}if(this.options.zIndex>c.ui.dialog.maxZ){c.ui.dialog.maxZ=this.options.zIndex}(this.overlay&&this.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=++c.ui.dialog.maxZ));var d={scrollTop:this.element.attr("scrollTop"),scrollLeft:this.element.attr("scrollLeft")};this.uiDialog.css("z-index",++c.ui.dialog.maxZ);this.element.attr(d);this._trigger("focus",e)},open:function(){if(this._isOpen){return}var e=this.options,d=this.uiDialog;this.overlay=e.modal?new c.ui.dialog.overlay(this):null;(d.next().length&&d.appendTo("body"));this._size();this._position(e.position);d.show(e.show);this.moveToTop(true);(e.modal&&d.bind("keypress.ui-dialog",function(h){if(h.keyCode!=c.ui.keyCode.TAB){return}var g=c(":tabbable",this),i=g.filter(":first")[0],f=g.filter(":last")[0];if(h.target==f&&!h.shiftKey){setTimeout(function(){i.focus()},1)}else{if(h.target==i&&h.shiftKey){setTimeout(function(){f.focus()},1)}}}));c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();this._trigger("open");this._isOpen=true},_createButtons:function(g){var f=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");this.uiDialog.find(".ui-dialog-buttonpane").remove();(typeof g=="object"&&g!==null&&c.each(g,function(){return !(d=true)}));if(d){c.each(g,function(h,i){c('<button type="button"></button>').addClass("ui-state-default ui-corner-all").text(h).click(function(){i.apply(f.element[0],arguments)}).hover(function(){c(this).addClass("ui-state-hover")},function(){c(this).removeClass("ui-state-hover")}).focus(function(){c(this).addClass("ui-state-focus")}).blur(function(){c(this).removeClass("ui-state-focus")}).appendTo(e)});e.appendTo(this.uiDialog)}},_makeDraggable:function(){var d=this,f=this.options,e;this.uiDialog.draggable({cancel:".ui-dialog-content",handle:".ui-dialog-titlebar",containment:"document",start:function(){e=f.height;c(this).height(c(this).height()).addClass("ui-dialog-dragging");(f.dragStart&&f.dragStart.apply(d.element[0],arguments))},drag:function(){(f.drag&&f.drag.apply(d.element[0],arguments))},stop:function(){c(this).removeClass("ui-dialog-dragging").height(e);(f.dragStop&&f.dragStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}})},_makeResizable:function(g){g=(g===undefined?this.options.resizable:g);var d=this,f=this.options,e=typeof g=="string"?g:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",alsoResize:this.element,maxWidth:f.maxWidth,maxHeight:f.maxHeight,minWidth:f.minWidth,minHeight:f.minHeight,start:function(){c(this).addClass("ui-dialog-resizing");(f.resizeStart&&f.resizeStart.apply(d.element[0],arguments))},resize:function(){(f.resize&&f.resize.apply(d.element[0],arguments))},handles:e,stop:function(){c(this).removeClass("ui-dialog-resizing");f.height=c(this).height();f.width=c(this).width();(f.resizeStop&&f.resizeStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}}).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_position:function(i){var e=c(window),f=c(document),g=f.scrollTop(),d=f.scrollLeft(),h=g;if(c.inArray(i,["center","top","right","bottom","left"])>=0){i=[i=="right"||i=="left"?i:"center",i=="top"||i=="bottom"?i:"middle"]}if(i.constructor!=Array){i=["center","middle"]}if(i[0].constructor==Number){d+=i[0]}else{switch(i[0]){case"left":d+=0;break;case"right":d+=e.width()-this.uiDialog.outerWidth();break;default:case"center":d+=(e.width()-this.uiDialog.outerWidth())/2}}if(i[1].constructor==Number){g+=i[1]}else{switch(i[1]){case"top":g+=0;break;case"bottom":g+=e.height()-this.uiDialog.outerHeight();break;default:case"middle":g+=(e.height()-this.uiDialog.outerHeight())/2}}g=Math.max(g,h);this.uiDialog.css({top:g,left:d})},_setData:function(e,f){(b[e]&&this.uiDialog.data(b[e],f));switch(e){case"buttons":this._createButtons(f);break;case"closeText":this.uiDialogTitlebarCloseText.text(f);break;case"dialogClass":this.uiDialog.removeClass(this.options.dialogClass).addClass(a+f);break;case"draggable":(f?this._makeDraggable():this.uiDialog.draggable("destroy"));break;case"height":this.uiDialog.height(f);break;case"position":this._position(f);break;case"resizable":var d=this.uiDialog,g=this.uiDialog.is(":data(resizable)");(g&&!f&&d.resizable("destroy"));(g&&typeof f=="string"&&d.resizable("option","handles",f));(g||this._makeResizable(f));break;case"title":c(".ui-dialog-title",this.uiDialogTitlebar).html(f||" ");break;case"width":this.uiDialog.width(f);break}c.widget.prototype._setData.apply(this,arguments)},_size:function(){var e=this.options;this.element.css({height:0,minHeight:0,width:"auto"});var d=this.uiDialog.css({height:"auto",width:e.width}).height();this.element.css({minHeight:Math.max(e.minHeight-d,0),height:e.height=="auto"?"auto":Math.max(e.height-d,0)})}});c.extend(c.ui.dialog,{version:"1.7.2",defaults:{autoOpen:true,bgiframe:false,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1000},getter:"isOpen",uuid:0,maxZ:0,getTitleId:function(d){return"ui-dialog-title-"+(d.attr("id")||++this.uuid)},overlay:function(d){this.$el=c.ui.dialog.overlay.create(d)}});c.extend(c.ui.dialog.overlay,{instances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(d){return d+".dialog-overlay"}).join(" "),create:function(e){if(this.instances.length===0){setTimeout(function(){if(c.ui.dialog.overlay.instances.length){c(document).bind(c.ui.dialog.overlay.events,function(f){var g=c(f.target).parents(".ui-dialog").css("zIndex")||0;return(g>c.ui.dialog.overlay.maxZ)})}},1);c(document).bind("keydown.dialog-overlay",function(f){(e.options.closeOnEscape&&f.keyCode&&f.keyCode==c.ui.keyCode.ESCAPE&&e.close(f))});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var d=c("<div></div>").appendTo(document.body).addClass("ui-widget-overlay").css({width:this.width(),height:this.height()});(e.options.bgiframe&&c.fn.bgiframe&&d.bgiframe());this.instances.push(d);return d},destroy:function(d){this.instances.splice(c.inArray(this.instances,d),1);if(this.instances.length===0){c([document,window]).unbind(".dialog-overlay")}d.remove();var e=0;c.each(this.instances,function(){e=Math.max(e,this.css("z-index"))});this.maxZ=e},height:function(){if(c.browser.msie&&c.browser.version<7){var e=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);var d=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);if(e<d){return c(window).height()+"px"}else{return e+"px"}}else{return c(document).height()+"px"}},width:function(){if(c.browser.msie&&c.browser.version<7){var d=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);var e=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);if(d<e){return c(window).width()+"px"}else{return d+"px"}}else{return c(document).width()+"px"}},resize:function(){var d=c([]);c.each(c.ui.dialog.overlay.instances,function(){d=d.add(this)});d.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);(function(a){a.widget("ui.progressbar",{_init:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=a('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow").removeData("progressbar").unbind(".progressbar");this.valueDiv.remove();a.widget.prototype.destroy.apply(this,arguments)},value:function(b){if(b===undefined){return this._value()}this._setData("value",b);return this},_setData:function(b,c){switch(b){case"value":this.options.value=c;this._refreshValue();this._trigger("change",null,{});break}a.widget.prototype._setData.apply(this,arguments)},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_valueMin:function(){var b=0;return b},_valueMax:function(){var b=100;return b},_refreshValue:function(){var b=this.value();this.valueDiv[b==this._valueMax()?"addClass":"removeClass"]("ui-corner-right");this.valueDiv.width(b+"%");this.element.attr("aria-valuenow",b)}});a.extend(a.ui.progressbar,{version:"1.7.2",defaults:{value:0}})})(jQuery);(function(a){a.widget("ui.slider",a.extend({},a.ui.mouse,{_init:function(){var b=this,c=this.options;this._keySliding=false;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");this.range=a([]);if(c.range){if(c.range===true){this.range=a("<div></div>");if(!c.values){c.values=[this._valueMin(),this._valueMin()]}if(c.values.length&&c.values.length!=2){c.values=[c.values[0],c.values[0]]}}else{this.range=a("<div></div>")}this.range.appendTo(this.element).addClass("ui-slider-range");if(c.range=="min"||c.range=="max"){this.range.addClass("ui-slider-range-"+c.range)}this.range.addClass("ui-widget-header")}if(a(".ui-slider-handle",this.element).length==0){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}if(c.values&&c.values.length){while(a(".ui-slider-handle",this.element).length<c.values.length){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}}this.handles=a(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(d){d.preventDefault()}).hover(function(){if(!c.disabled){a(this).addClass("ui-state-hover")}},function(){a(this).removeClass("ui-state-hover")}).focus(function(){if(!c.disabled){a(".ui-slider .ui-state-focus").removeClass("ui-state-focus");a(this).addClass("ui-state-focus")}else{a(this).blur()}}).blur(function(){a(this).removeClass("ui-state-focus")});this.handles.each(function(d){a(this).data("index.ui-slider-handle",d)});this.handles.keydown(function(i){var f=true;var e=a(this).data("index.ui-slider-handle");if(b.options.disabled){return}switch(i.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:f=false;if(!b._keySliding){b._keySliding=true;a(this).addClass("ui-state-active");b._start(i,e)}break}var g,d,h=b._step();if(b.options.values&&b.options.values.length){g=d=b.values(e)}else{g=d=b.value()}switch(i.keyCode){case a.ui.keyCode.HOME:d=b._valueMin();break;case a.ui.keyCode.END:d=b._valueMax();break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g==b._valueMax()){return}d=g+h;break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g==b._valueMin()){return}d=g-h;break}b._slide(i,e,d);return f}).keyup(function(e){var d=a(this).data("index.ui-slider-handle");if(b._keySliding){b._stop(e,d);b._change(e,d);b._keySliding=false;a(this).removeClass("ui-state-active")}});this._refreshValue()},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy()},_mouseCapture:function(d){var e=this.options;if(e.disabled){return false}this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();var h={x:d.pageX,y:d.pageY};var j=this._normValueFromMouse(h);var c=this._valueMax()-this._valueMin()+1,f;var k=this,i;this.handles.each(function(l){var m=Math.abs(j-k.values(l));if(c>m){c=m;f=a(this);i=l}});if(e.range==true&&this.values(1)==e.min){f=a(this.handles[++i])}this._start(d,i);k._handleIndex=i;f.addClass("ui-state-active").focus();var g=f.offset();var b=!a(d.target).parents().andSelf().is(".ui-slider-handle");this._clickOffset=b?{left:0,top:0}:{left:d.pageX-g.left-(f.width()/2),top:d.pageY-g.top-(f.height()/2)-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};j=this._normValueFromMouse(h);this._slide(d,i,j);return true},_mouseStart:function(b){return true},_mouseDrag:function(d){var b={x:d.pageX,y:d.pageY};var c=this._normValueFromMouse(b);this._slide(d,this._handleIndex,c);return false},_mouseStop:function(b){this.handles.removeClass("ui-state-active");this._stop(b,this._handleIndex);this._change(b,this._handleIndex);this._handleIndex=null;this._clickOffset=null;return false},_detectOrientation:function(){this.orientation=this.options.orientation=="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(d){var c,h;if("horizontal"==this.orientation){c=this.elementSize.width;h=d.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{c=this.elementSize.height;h=d.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}var f=(h/c);if(f>1){f=1}if(f<0){f=0}if("vertical"==this.orientation){f=1-f}var e=this._valueMax()-this._valueMin(),i=f*e,b=i%this.options.step,g=this._valueMin()+i-b;if(b>(this.options.step/2)){g+=this.options.step}return parseFloat(g.toFixed(5))},_start:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("start",d,b)},_slide:function(f,e,d){var g=this.handles[e];if(this.options.values&&this.options.values.length){var b=this.values(e?0:1);if((this.options.values.length==2&&this.options.range===true)&&((e==0&&d>b)||(e==1&&d<b))){d=b}if(d!=this.values(e)){var c=this.values();c[e]=d;var h=this._trigger("slide",f,{handle:this.handles[e],value:d,values:c});var b=this.values(e?0:1);if(h!==false){this.values(e,d,(f.type=="mousedown"&&this.options.animate),true)}}}else{if(d!=this.value()){var h=this._trigger("slide",f,{handle:this.handles[e],value:d});if(h!==false){this._setData("value",d,(f.type=="mousedown"&&this.options.animate))}}}},_stop:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("stop",d,b)},_change:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("change",d,b)},value:function(b){if(arguments.length){this._setData("value",b);this._change(null,0)}return this._value()},values:function(b,e,c,d){if(arguments.length>1){this.options.values[b]=e;this._refreshValue(c);if(!d){this._change(null,b)}}if(arguments.length){if(this.options.values&&this.options.values.length){return this._values(b)}else{return this.value()}}else{return this._values()}},_setData:function(b,d,c){a.widget.prototype._setData.apply(this,arguments);switch(b){case"disabled":if(d){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled")}else{this.handles.removeAttr("disabled")}case"orientation":this._detectOrientation();this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue(c);break;case"value":this._refreshValue(c);break}},_step:function(){var b=this.options.step;return b},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_values:function(b){if(arguments.length){var c=this.options.values[b];if(c<this._valueMin()){c=this._valueMin()}if(c>this._valueMax()){c=this._valueMax()}return c}else{return this.options.values}},_valueMin:function(){var b=this.options.min;return b},_valueMax:function(){var b=this.options.max;return b},_refreshValue:function(c){var f=this.options.range,d=this.options,l=this;if(this.options.values&&this.options.values.length){var i,h;this.handles.each(function(p,n){var o=(l.values(p)-l._valueMin())/(l._valueMax()-l._valueMin())*100;var m={};m[l.orientation=="horizontal"?"left":"bottom"]=o+"%";a(this).stop(1,1)[c?"animate":"css"](m,d.animate);if(l.options.range===true){if(l.orientation=="horizontal"){(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({left:o+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({width:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}else{(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({bottom:(o)+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({height:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}}lastValPercent=o})}else{var j=this.value(),g=this._valueMin(),k=this._valueMax(),e=k!=g?(j-g)/(k-g)*100:0;var b={};b[l.orientation=="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[c?"animate":"css"](b,d.animate);(f=="min")&&(this.orientation=="horizontal")&&this.range.stop(1,1)[c?"animate":"css"]({width:e+"%"},d.animate);(f=="max")&&(this.orientation=="horizontal")&&this.range[c?"animate":"css"]({width:(100-e)+"%"},{queue:false,duration:d.animate});(f=="min")&&(this.orientation=="vertical")&&this.range.stop(1,1)[c?"animate":"css"]({height:e+"%"},d.animate);(f=="max")&&(this.orientation=="vertical")&&this.range[c?"animate":"css"]({height:(100-e)+"%"},{queue:false,duration:d.animate})}}}));a.extend(a.ui.slider,{getter:"value values",version:"1.7.2",eventPrefix:"slide",defaults:{animate:false,delay:0,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null}})})(jQuery);(function(a){a.widget("ui.tabs",{_init:function(){if(this.options.deselectable!==undefined){this.options.collapsible=this.options.deselectable}this._tabify(true)},_setData:function(b,c){if(b=="selected"){if(this.options.collapsible&&c==this.options.selected){return}this.select(c)}else{this.options[b]=c;if(b=="deselectable"){this.options.collapsible=c}this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+a.data(b)},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+a.data(this.list[0]));return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(c,b){return{tab:c,panel:b,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(n){this.list=this.element.children("ul:first");this.lis=a("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return a("a",this)[0]});this.panels=a([]);var p=this,d=this.options;var c=/^#.+/;this.anchors.each(function(r,o){var q=a(o).attr("href");var s=q.split("#")[0],u;if(s&&(s===location.toString().split("#")[0]||(u=a("base")[0])&&s===u.href)){q=o.hash;o.href=q}if(c.test(q)){p.panels=p.panels.add(p._sanitizeSelector(q))}else{if(q!="#"){a.data(o,"href.tabs",q);a.data(o,"load.tabs",q.replace(/#.*$/,""));var w=p._tabId(o);o.href="#"+w;var v=a("#"+w);if(!v.length){v=a(d.panelTemplate).attr("id",w).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(p.panels[r-1]||p.list);v.data("destroy.tabs",true)}p.panels=p.panels.add(v)}else{d.disabled.push(r)}}});if(n){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(d.selected===undefined){if(location.hash){this.anchors.each(function(q,o){if(o.hash==location.hash){d.selected=q;return false}})}if(typeof d.selected!="number"&&d.cookie){d.selected=parseInt(p._cookie(),10)}if(typeof d.selected!="number"&&this.lis.filter(".ui-tabs-selected").length){d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}d.selected=d.selected||0}else{if(d.selected===null){d.selected=-1}}d.selected=((d.selected>=0&&this.anchors[d.selected])||d.selected<0)?d.selected:0;d.disabled=a.unique(d.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(q,o){return p.lis.index(q)}))).sort();if(a.inArray(d.selected,d.disabled)!=-1){d.disabled.splice(a.inArray(d.selected,d.disabled),1)}this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");if(d.selected>=0&&this.anchors.length){this.panels.eq(d.selected).removeClass("ui-tabs-hide");this.lis.eq(d.selected).addClass("ui-tabs-selected ui-state-active");p.element.queue("tabs",function(){p._trigger("show",null,p._ui(p.anchors[d.selected],p.panels[d.selected]))});this.load(d.selected)}a(window).bind("unload",function(){p.lis.add(p.anchors).unbind(".tabs");p.lis=p.anchors=p.panels=null})}else{d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}this.element[d.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");if(d.cookie){this._cookie(d.selected,d.cookie)}for(var g=0,m;(m=this.lis[g]);g++){a(m)[a.inArray(g,d.disabled)!=-1&&!a(m).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled")}if(d.cache===false){this.anchors.removeData("cache.tabs")}this.lis.add(this.anchors).unbind(".tabs");if(d.event!="mouseover"){var f=function(o,i){if(i.is(":not(.ui-state-disabled)")){i.addClass("ui-state-"+o)}};var j=function(o,i){i.removeClass("ui-state-"+o)};this.lis.bind("mouseover.tabs",function(){f("hover",a(this))});this.lis.bind("mouseout.tabs",function(){j("hover",a(this))});this.anchors.bind("focus.tabs",function(){f("focus",a(this).closest("li"))});this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var b,h;if(d.fx){if(a.isArray(d.fx)){b=d.fx[0];h=d.fx[1]}else{b=h=d.fx}}function e(i,o){i.css({display:""});if(a.browser.msie&&o.opacity){i[0].style.removeAttribute("filter")}}var k=h?function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.hide().removeClass("ui-tabs-hide").animate(h,h.duration||"normal",function(){e(o,h);p._trigger("show",null,p._ui(i,o[0]))})}:function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.removeClass("ui-tabs-hide");p._trigger("show",null,p._ui(i,o[0]))};var l=b?function(o,i){i.animate(b,b.duration||"normal",function(){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");e(i,b);p.element.dequeue("tabs")})}:function(o,i,q){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");p.element.dequeue("tabs")};this.anchors.bind(d.event+".tabs",function(){var o=this,r=a(this).closest("li"),i=p.panels.filter(":not(.ui-tabs-hide)"),q=a(p._sanitizeSelector(this.hash));if((r.hasClass("ui-tabs-selected")&&!d.collapsible)||r.hasClass("ui-state-disabled")||r.hasClass("ui-state-processing")||p._trigger("select",null,p._ui(this,q[0]))===false){this.blur();return false}d.selected=p.anchors.index(this);p.abort();if(d.collapsible){if(r.hasClass("ui-tabs-selected")){d.selected=-1;if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){l(o,i)}).dequeue("tabs");this.blur();return false}else{if(!i.length){if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this));this.blur();return false}}}if(d.cookie){p._cookie(d.selected,d.cookie)}if(q.length){if(i.length){p.element.queue("tabs",function(){l(o,i)})}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this))}else{throw"jQuery UI Tabs: Mismatching fragment identifier."}if(a.browser.msie){this.blur()}});this.anchors.bind("click.tabs",function(){return false})},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var c=a.data(this,"href.tabs");if(c){this.href=c}var d=a(this).unbind(".tabs");a.each(["href","load","cache"],function(e,f){d.removeData(f+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){if(a.data(this,"destroy.tabs")){a(this).remove()}else{a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}});if(b.cookie){this._cookie(null,b.cookie)}},add:function(e,d,c){if(c===undefined){c=this.anchors.length}var b=this,g=this.options,i=a(g.tabTemplate.replace(/#\{href\}/g,e).replace(/#\{label\}/g,d)),h=!e.indexOf("#")?e.replace("#",""):this._tabId(a("a",i)[0]);i.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var f=a("#"+h);if(!f.length){f=a(g.panelTemplate).attr("id",h).data("destroy.tabs",true)}f.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(c>=this.lis.length){i.appendTo(this.list);f.appendTo(this.list[0].parentNode)}else{i.insertBefore(this.lis[c]);f.insertBefore(this.panels[c])}g.disabled=a.map(g.disabled,function(k,j){return k>=c?++k:k});this._tabify();if(this.anchors.length==1){i.addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[c],this.panels[c]))},remove:function(b){var d=this.options,e=this.lis.eq(b).remove(),c=this.panels.eq(b).remove();if(e.hasClass("ui-tabs-selected")&&this.anchors.length>1){this.select(b+(b+1<this.anchors.length?1:-1))}d.disabled=a.map(a.grep(d.disabled,function(g,f){return g!=b}),function(g,f){return g>=b?--g:g});this._tabify();this._trigger("remove",null,this._ui(e.find("a")[0],c[0]))},enable:function(b){var c=this.options;if(a.inArray(b,c.disabled)==-1){return}this.lis.eq(b).removeClass("ui-state-disabled");c.disabled=a.grep(c.disabled,function(e,d){return e!=b});this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]))},disable:function(c){var b=this,d=this.options;if(c!=d.selected){this.lis.eq(c).addClass("ui-state-disabled");d.disabled.push(c);d.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}},select:function(b){if(typeof b=="string"){b=this.anchors.index(this.anchors.filter("[href$="+b+"]"))}else{if(b===null){b=-1}}if(b==-1&&this.options.collapsible){b=this.options.selected}this.anchors.eq(b).trigger(this.options.event+".tabs")},load:function(e){var c=this,g=this.options,b=this.anchors.eq(e)[0],d=a.data(b,"load.tabs");this.abort();if(!d||this.element.queue("tabs").length!==0&&a.data(b,"cache.tabs")){this.element.dequeue("tabs");return}this.lis.eq(e).addClass("ui-state-processing");if(g.spinner){var f=a("span",b);f.data("label.tabs",f.html()).html(g.spinner)}this.xhr=a.ajax(a.extend({},g.ajaxOptions,{url:d,success:function(i,h){a(c._sanitizeSelector(b.hash)).html(i);c._cleanup();if(g.cache){a.data(b,"cache.tabs",true)}c._trigger("load",null,c._ui(c.anchors[e],c.panels[e]));try{g.ajaxOptions.success(i,h)}catch(j){}c.element.dequeue("tabs")}}))},abort:function(){this.element.queue([]);this.panels.stop(false,true);if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup()},url:function(c,b){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",b)},length:function(){return this.anchors.length}});a.extend(a.ui.tabs,{version:"1.7.2",getter:"length",defaults:{ajaxOptions:null,cache:false,cookie:null,collapsible:false,disabled:[],event:"click",fx:null,idPrefix:"ui-tabs-",panelTemplate:"<div></div>",spinner:"<em>Loading…</em>",tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'}});a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(d,f){var b=this,g=this.options;var c=b._rotate||(b._rotate=function(h){clearTimeout(b.rotation);b.rotation=setTimeout(function(){var i=g.selected;b.select(++i<b.anchors.length?i:0)},d);if(h){h.stopPropagation()}});var e=b._unrotate||(b._unrotate=!f?function(h){if(h.clientX){b.rotate(null)}}:function(h){t=g.selected;c()});if(d){this.element.bind("tabsshow",c);this.anchors.bind(g.event+".tabs",e);c()}else{clearTimeout(b.rotation);this.element.unbind("tabsshow",c);this.anchors.unbind(g.event+".tabs",e);delete this._rotate;delete this._unrotate}}})})(jQuery);
  637.14 \ No newline at end of file
   638.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   638.2 +++ b/web/static/js/jquery.dataTables.min.js	Mon Apr 26 11:16:23 2010 +0200
   638.3 @@ -0,0 +1,568 @@
   638.4 +/*
   638.5 + * File:        jquery.dataTables.min.js
   638.6 + * Version:     1.6.0
   638.7 + * Author:      Allan Jardine (www.sprymedia.co.uk)
   638.8 + * Info:        www.datatables.net
   638.9 + * 
  638.10 + * Copyright 2008-2010 Allan Jardine, all rights reserved.
  638.11 + *
  638.12 + * This source file is free software, under either the GPL v2 license or a
  638.13 + * BSD style license, as supplied with this software.
  638.14 + * 
  638.15 + * This source file is distributed in the hope that it will be useful, but 
  638.16 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  638.17 + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  638.18 + */
  638.19 +(function($){$.fn.dataTableSettings=[];var _aoSettings=$.fn.dataTableSettings;$.fn.dataTableExt={};
  638.20 +var _oExt=$.fn.dataTableExt;_oExt.sVersion="1.6.0";_oExt.iApiIndex=0;_oExt.oApi={};
  638.21 +_oExt.afnFiltering=[];_oExt.aoFeatures=[];_oExt.ofnSearch={};_oExt.afnSortData=[];
  638.22 +_oExt.oStdClasses={sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active",sPageButtonStaticDisabled:"paginate_button",sPageFirst:"first",sPagePrevious:"previous",sPageNext:"next",sPageLast:"last",sStripOdd:"odd",sStripEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"",sSortColumn:"sorting_",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:""};
  638.23 +_oExt.oJUIClasses={sPagePrevEnabled:"fg-button ui-state-default ui-corner-left",sPagePrevDisabled:"fg-button ui-state-default ui-corner-left ui-state-disabled",sPageNextEnabled:"fg-button ui-state-default ui-corner-right",sPageNextDisabled:"fg-button ui-state-default ui-corner-right ui-state-disabled",sPageJUINext:"ui-icon ui-icon-circle-arrow-e",sPageJUIPrev:"ui-icon ui-icon-circle-arrow-w",sPageButton:"fg-button ui-state-default",sPageButtonActive:"fg-button ui-state-default ui-state-disabled",sPageButtonStaticDisabled:"fg-button ui-state-default ui-state-disabled",sPageFirst:"first ui-corner-tl ui-corner-bl",sPagePrevious:"previous",sPageNext:"next",sPageLast:"last ui-corner-tr ui-corner-br",sStripOdd:"odd",sStripEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate fg-buttonset fg-buttonset-multi paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"ui-state-default",sSortDesc:"ui-state-default",sSortable:"ui-state-default",sSortableAsc:"ui-state-default",sSortableDesc:"ui-state-default",sSortableNone:"ui-state-default",sSortColumn:"sorting_",sSortJUIAsc:"css_right ui-icon ui-icon-triangle-1-n",sSortJUIDesc:"css_right ui-icon ui-icon-triangle-1-s",sSortJUI:"css_right ui-icon ui-icon-carat-2-n-s",sSortJUIAscAllowed:"css_right ui-icon ui-icon-carat-1-n",sSortJUIDescAllowed:"css_right ui-icon ui-icon-carat-1-s"};
  638.24 +_oExt.oPagination={two_button:{fnInit:function(oSettings,nPaging,fnCallbackDraw){var nPrevious,nNext,nPreviousInner,nNextInner;
  638.25 +if(!oSettings.bJUI){nPrevious=document.createElement("div");nNext=document.createElement("div")
  638.26 +}else{nPrevious=document.createElement("a");nNext=document.createElement("a");nNextInner=document.createElement("span");
  638.27 +nNextInner.className=oSettings.oClasses.sPageJUINext;nNext.appendChild(nNextInner);
  638.28 +nPreviousInner=document.createElement("span");nPreviousInner.className=oSettings.oClasses.sPageJUIPrev;
  638.29 +nPrevious.appendChild(nPreviousInner)}nPrevious.className=oSettings.oClasses.sPagePrevDisabled;
  638.30 +nNext.className=oSettings.oClasses.sPageNextDisabled;nPrevious.title=oSettings.oLanguage.oPaginate.sPrevious;
  638.31 +nNext.title=oSettings.oLanguage.oPaginate.sNext;nPaging.appendChild(nPrevious);nPaging.appendChild(nNext);
  638.32 +$(nPrevious).click(function(){oSettings.oApi._fnPageChange(oSettings,"previous");
  638.33 +fnCallbackDraw(oSettings)});$(nNext).click(function(){oSettings.oApi._fnPageChange(oSettings,"next");
  638.34 +fnCallbackDraw(oSettings)});$(nPrevious).bind("selectstart",function(){return false
  638.35 +});$(nNext).bind("selectstart",function(){return false});if(oSettings.sTableId!==""&&typeof oSettings.aanFeatures.p=="undefined"){nPaging.setAttribute("id",oSettings.sTableId+"_paginate");
  638.36 +nPrevious.setAttribute("id",oSettings.sTableId+"_previous");nNext.setAttribute("id",oSettings.sTableId+"_next")
  638.37 +}},fnUpdate:function(oSettings,fnCallbackDraw){if(!oSettings.aanFeatures.p){return
  638.38 +}var an=oSettings.aanFeatures.p;for(var i=0,iLen=an.length;i<iLen;i++){if(an[i].childNodes.length!==0){an[i].childNodes[0].className=(oSettings._iDisplayStart===0)?oSettings.oClasses.sPagePrevDisabled:oSettings.oClasses.sPagePrevEnabled;
  638.39 +an[i].childNodes[1].className=(oSettings.fnDisplayEnd()==oSettings.fnRecordsDisplay())?oSettings.oClasses.sPageNextDisabled:oSettings.oClasses.sPageNextEnabled
  638.40 +}}}},iFullNumbersShowPages:5,full_numbers:{fnInit:function(oSettings,nPaging,fnCallbackDraw){var nFirst=document.createElement("span");
  638.41 +var nPrevious=document.createElement("span");var nList=document.createElement("span");
  638.42 +var nNext=document.createElement("span");var nLast=document.createElement("span");
  638.43 +nFirst.innerHTML=oSettings.oLanguage.oPaginate.sFirst;nPrevious.innerHTML=oSettings.oLanguage.oPaginate.sPrevious;
  638.44 +nNext.innerHTML=oSettings.oLanguage.oPaginate.sNext;nLast.innerHTML=oSettings.oLanguage.oPaginate.sLast;
  638.45 +var oClasses=oSettings.oClasses;nFirst.className=oClasses.sPageButton+" "+oClasses.sPageFirst;
  638.46 +nPrevious.className=oClasses.sPageButton+" "+oClasses.sPagePrevious;nNext.className=oClasses.sPageButton+" "+oClasses.sPageNext;
  638.47 +nLast.className=oClasses.sPageButton+" "+oClasses.sPageLast;nPaging.appendChild(nFirst);
  638.48 +nPaging.appendChild(nPrevious);nPaging.appendChild(nList);nPaging.appendChild(nNext);
  638.49 +nPaging.appendChild(nLast);$(nFirst).click(function(){oSettings.oApi._fnPageChange(oSettings,"first");
  638.50 +fnCallbackDraw(oSettings)});$(nPrevious).click(function(){oSettings.oApi._fnPageChange(oSettings,"previous");
  638.51 +fnCallbackDraw(oSettings)});$(nNext).click(function(){oSettings.oApi._fnPageChange(oSettings,"next");
  638.52 +fnCallbackDraw(oSettings)});$(nLast).click(function(){oSettings.oApi._fnPageChange(oSettings,"last");
  638.53 +fnCallbackDraw(oSettings)});$("span",nPaging).bind("mousedown",function(){return false
  638.54 +}).bind("selectstart",function(){return false});if(oSettings.sTableId!==""&&typeof oSettings.aanFeatures.p=="undefined"){nPaging.setAttribute("id",oSettings.sTableId+"_paginate");
  638.55 +nFirst.setAttribute("id",oSettings.sTableId+"_first");nPrevious.setAttribute("id",oSettings.sTableId+"_previous");
  638.56 +nNext.setAttribute("id",oSettings.sTableId+"_next");nLast.setAttribute("id",oSettings.sTableId+"_last")
  638.57 +}},fnUpdate:function(oSettings,fnCallbackDraw){if(!oSettings.aanFeatures.p){return
  638.58 +}var iPageCount=_oExt.oPagination.iFullNumbersShowPages;var iPageCountHalf=Math.floor(iPageCount/2);
  638.59 +var iPages=Math.ceil((oSettings.fnRecordsDisplay())/oSettings._iDisplayLength);var iCurrentPage=Math.ceil(oSettings._iDisplayStart/oSettings._iDisplayLength)+1;
  638.60 +var sList="";var iStartButton,iEndButton,i,iLen;var oClasses=oSettings.oClasses;if(iPages<iPageCount){iStartButton=1;
  638.61 +iEndButton=iPages}else{if(iCurrentPage<=iPageCountHalf){iStartButton=1;iEndButton=iPageCount
  638.62 +}else{if(iCurrentPage>=(iPages-iPageCountHalf)){iStartButton=iPages-iPageCount+1;
  638.63 +iEndButton=iPages}else{iStartButton=iCurrentPage-Math.ceil(iPageCount/2)+1;iEndButton=iStartButton+iPageCount-1
  638.64 +}}}for(i=iStartButton;i<=iEndButton;i++){if(iCurrentPage!=i){sList+='<span class="'+oClasses.sPageButton+'">'+i+"</span>"
  638.65 +}else{sList+='<span class="'+oClasses.sPageButtonActive+'">'+i+"</span>"}}var an=oSettings.aanFeatures.p;
  638.66 +var anButtons,anStatic,nPaginateList;var fnClick=function(){var iTarget=(this.innerHTML*1)-1;
  638.67 +oSettings._iDisplayStart=iTarget*oSettings._iDisplayLength;fnCallbackDraw(oSettings);
  638.68 +return false};var fnFalse=function(){return false};for(i=0,iLen=an.length;i<iLen;
  638.69 +i++){if(an[i].childNodes.length===0){continue}nPaginateList=an[i].childNodes[2];nPaginateList.innerHTML=sList;
  638.70 +$("span",nPaginateList).click(fnClick).bind("mousedown",fnFalse).bind("selectstart",fnFalse);
  638.71 +anButtons=an[i].getElementsByTagName("span");anStatic=[anButtons[0],anButtons[1],anButtons[anButtons.length-2],anButtons[anButtons.length-1]];
  638.72 +$(anStatic).removeClass(oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled);
  638.73 +if(iCurrentPage==1){anStatic[0].className+=" "+oClasses.sPageButtonStaticDisabled;
  638.74 +anStatic[1].className+=" "+oClasses.sPageButtonStaticDisabled}else{anStatic[0].className+=" "+oClasses.sPageButton;
  638.75 +anStatic[1].className+=" "+oClasses.sPageButton}if(iCurrentPage==iPages||oSettings._iDisplayLength==-1){anStatic[2].className+=" "+oClasses.sPageButtonStaticDisabled;
  638.76 +anStatic[3].className+=" "+oClasses.sPageButtonStaticDisabled}else{anStatic[2].className+=" "+oClasses.sPageButton;
  638.77 +anStatic[3].className+=" "+oClasses.sPageButton}}}}};_oExt.oSort={"string-asc":function(a,b){var x=a.toLowerCase();
  638.78 +var y=b.toLowerCase();return((x<y)?-1:((x>y)?1:0))},"string-desc":function(a,b){var x=a.toLowerCase();
  638.79 +var y=b.toLowerCase();return((x<y)?1:((x>y)?-1:0))},"html-asc":function(a,b){var x=a.replace(/<.*?>/g,"").toLowerCase();
  638.80 +var y=b.replace(/<.*?>/g,"").toLowerCase();return((x<y)?-1:((x>y)?1:0))},"html-desc":function(a,b){var x=a.replace(/<.*?>/g,"").toLowerCase();
  638.81 +var y=b.replace(/<.*?>/g,"").toLowerCase();return((x<y)?1:((x>y)?-1:0))},"date-asc":function(a,b){var x=Date.parse(a);
  638.82 +var y=Date.parse(b);if(isNaN(x)){x=Date.parse("01/01/1970 00:00:00")}if(isNaN(y)){y=Date.parse("01/01/1970 00:00:00")
  638.83 +}return x-y},"date-desc":function(a,b){var x=Date.parse(a);var y=Date.parse(b);if(isNaN(x)){x=Date.parse("01/01/1970 00:00:00")
  638.84 +}if(isNaN(y)){y=Date.parse("01/01/1970 00:00:00")}return y-x},"numeric-asc":function(a,b){var x=a=="-"?0:a;
  638.85 +var y=b=="-"?0:b;return x-y},"numeric-desc":function(a,b){var x=a=="-"?0:a;var y=b=="-"?0:b;
  638.86 +return y-x}};_oExt.aTypes=[function(sData){if(typeof sData=="number"){return"numeric"
  638.87 +}else{if(typeof sData.charAt!="function"){return null}}var sValidFirstChars="0123456789-";
  638.88 +var sValidChars="0123456789.";var Char;var bDecimal=false;Char=sData.charAt(0);if(sValidFirstChars.indexOf(Char)==-1){return null
  638.89 +}for(var i=1;i<sData.length;i++){Char=sData.charAt(i);if(sValidChars.indexOf(Char)==-1){return null
  638.90 +}if(Char=="."){if(bDecimal){return null}bDecimal=true}}return"numeric"},function(sData){var iParse=Date.parse(sData);
  638.91 +if(iParse!==null&&!isNaN(iParse)){return"date"}return null}];_oExt._oExternConfig={iNextUnique:0};
  638.92 +$.fn.dataTable=function(oInit){function classSettings(){this.fnRecordsTotal=function(){if(this.oFeatures.bServerSide){return this._iRecordsTotal
  638.93 +}else{return this.aiDisplayMaster.length}};this.fnRecordsDisplay=function(){if(this.oFeatures.bServerSide){return this._iRecordsDisplay
  638.94 +}else{return this.aiDisplay.length}};this.fnDisplayEnd=function(){if(this.oFeatures.bServerSide){return this._iDisplayStart+this.aiDisplay.length
  638.95 +}else{return this._iDisplayEnd}};this.sInstance=null;this.oFeatures={bPaginate:true,bLengthChange:true,bFilter:true,bSort:true,bInfo:true,bAutoWidth:true,bProcessing:false,bSortClasses:true,bStateSave:false,bServerSide:false};
  638.96 +this.aanFeatures=[];this.oLanguage={sProcessing:"Processing...",sLengthMenu:"Show _MENU_ entries",sZeroRecords:"No matching records found",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sSearch:"Search:",sUrl:"",oPaginate:{sFirst:"First",sPrevious:"Previous",sNext:"Next",sLast:"Last"}};
  638.97 +this.aoData=[];this.aiDisplay=[];this.aiDisplayMaster=[];this.aoColumns=[];this.iNextId=0;
  638.98 +this.asDataSearch=[];this.oPreviousSearch={sSearch:"",bEscapeRegex:true};this.aoPreSearchCols=[];
  638.99 +this.aaSorting=[[0,"asc",0]];this.aaSortingFixed=null;this.asStripClasses=[];this.fnRowCallback=null;
 638.100 +this.fnHeaderCallback=null;this.fnFooterCallback=null;this.aoDrawCallback=[];this.fnInitComplete=null;
 638.101 +this.sTableId="";this.nTable=null;this.iDefaultSortIndex=0;this.bInitialised=false;
 638.102 +this.aoOpenRows=[];this.sDom="lfrtip";this.sPaginationType="two_button";this.iCookieDuration=60*60*2;
 638.103 +this.sAjaxSource=null;this.bAjaxDataGet=true;this.fnServerData=$.getJSON;this.iServerDraw=0;
 638.104 +this._iDisplayLength=10;this._iDisplayStart=0;this._iDisplayEnd=10;this._iRecordsTotal=0;
 638.105 +this._iRecordsDisplay=0;this.bJUI=false;this.oClasses=_oExt.oStdClasses;this.bFiltered=false;
 638.106 +this.bSorted=false}this.oApi={};this.fnDraw=function(bComplete){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.107 +if(typeof bComplete!="undefined"&&bComplete===false){_fnCalculateEnd(oSettings);_fnDraw(oSettings)
 638.108 +}else{_fnReDraw(oSettings)}};this.fnFilter=function(sInput,iColumn,bEscapeRegex){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.109 +if(typeof bEscapeRegex=="undefined"){bEscapeRegex=true}if(typeof iColumn=="undefined"||iColumn===null){_fnFilterComplete(oSettings,{sSearch:sInput,bEscapeRegex:bEscapeRegex},1)
 638.110 +}else{oSettings.aoPreSearchCols[iColumn].sSearch=sInput;oSettings.aoPreSearchCols[iColumn].bEscapeRegex=bEscapeRegex;
 638.111 +_fnFilterComplete(oSettings,oSettings.oPreviousSearch,1)}};this.fnSettings=function(nNode){return _fnSettingsFromNode(this[_oExt.iApiIndex])
 638.112 +};this.fnVersionCheck=function(sVersion){var fnZPad=function(Zpad,count){while(Zpad.length<count){Zpad+="0"
 638.113 +}return Zpad};var aThis=_oExt.sVersion.split(".");var aThat=sVersion.split(".");var sThis="",sThat="";
 638.114 +for(var i=0,iLen=aThat.length;i<iLen;i++){sThis+=fnZPad(aThis[i],3);sThat+=fnZPad(aThat[i],3)
 638.115 +}return parseInt(sThis)>=parseInt(sThat)};this.fnSort=function(aaSort){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.116 +oSettings.aaSorting=aaSort;_fnSort(oSettings)};this.fnSortListener=function(nNode,iColumn,fnCallback){_fnSortAttachListener(_fnSettingsFromNode(this[_oExt.iApiIndex]),nNode,iColumn,fnCallback)
 638.117 +};this.fnAddData=function(mData,bRedraw){if(mData.length===0){return[]}var aiReturn=[];
 638.118 +var iTest;var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);if(typeof mData[0]=="object"){for(var i=0;
 638.119 +i<mData.length;i++){iTest=_fnAddData(oSettings,mData[i]);if(iTest==-1){return aiReturn
 638.120 +}aiReturn.push(iTest)}}else{iTest=_fnAddData(oSettings,mData);if(iTest==-1){return aiReturn
 638.121 +}aiReturn.push(iTest)}oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();_fnBuildSearchArray(oSettings,1);
 638.122 +if(typeof bRedraw=="undefined"||bRedraw){_fnReDraw(oSettings)}return aiReturn};this.fnDeleteRow=function(mTarget,fnCallBack,bNullRow){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.123 +var i,iAODataIndex;iAODataIndex=(typeof mTarget=="object")?_fnNodeToDataIndex(oSettings,mTarget):mTarget;
 638.124 +for(i=0;i<oSettings.aiDisplayMaster.length;i++){if(oSettings.aiDisplayMaster[i]==iAODataIndex){oSettings.aiDisplayMaster.splice(i,1);
 638.125 +break}}for(i=0;i<oSettings.aiDisplay.length;i++){if(oSettings.aiDisplay[i]==iAODataIndex){oSettings.aiDisplay.splice(i,1);
 638.126 +break}}_fnBuildSearchArray(oSettings,1);if(typeof fnCallBack=="function"){fnCallBack.call(this)
 638.127 +}if(oSettings._iDisplayStart>=oSettings.aiDisplay.length){oSettings._iDisplayStart-=oSettings._iDisplayLength;
 638.128 +if(oSettings._iDisplayStart<0){oSettings._iDisplayStart=0}}_fnCalculateEnd(oSettings);
 638.129 +_fnDraw(oSettings);var aData=oSettings.aoData[iAODataIndex]._aData.slice();if(typeof bNullRow!="undefined"&&bNullRow===true){oSettings.aoData[iAODataIndex]=null
 638.130 +}return aData};this.fnClearTable=function(bRedraw){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.131 +_fnClearTable(oSettings);if(typeof bRedraw=="undefined"||bRedraw){_fnDraw(oSettings)
 638.132 +}};this.fnOpen=function(nTr,sHtml,sClass){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.133 +this.fnClose(nTr);var nNewRow=document.createElement("tr");var nNewCell=document.createElement("td");
 638.134 +nNewRow.appendChild(nNewCell);nNewCell.className=sClass;nNewCell.colSpan=_fnVisbleColumns(oSettings);
 638.135 +nNewCell.innerHTML=sHtml;var nTrs=$("tbody tr",oSettings.nTable);if($.inArray(nTr,nTrs)!=-1){$(nNewRow).insertAfter(nTr)
 638.136 +}if(!oSettings.oFeatures.bServerSide){oSettings.aoOpenRows.push({nTr:nNewRow,nParent:nTr})
 638.137 +}};this.fnClose=function(nTr){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.138 +for(var i=0;i<oSettings.aoOpenRows.length;i++){if(oSettings.aoOpenRows[i].nParent==nTr){var nTrParent=oSettings.aoOpenRows[i].nTr.parentNode;
 638.139 +if(nTrParent){nTrParent.removeChild(oSettings.aoOpenRows[i].nTr)}oSettings.aoOpenRows.splice(i,1);
 638.140 +return 0}}return 1};this.fnGetData=function(mRow){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.141 +if(typeof mRow!="undefined"){var iRow=(typeof mRow=="object")?_fnNodeToDataIndex(oSettings,mRow):mRow;
 638.142 +return oSettings.aoData[iRow]._aData}return _fnGetDataMaster(oSettings)};this.fnGetNodes=function(iRow){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.143 +if(typeof iRow!="undefined"){return oSettings.aoData[iRow].nTr}return _fnGetTrNodes(oSettings)
 638.144 +};this.fnGetPosition=function(nNode){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.145 +var i;if(nNode.nodeName=="TR"){return _fnNodeToDataIndex(oSettings,nNode)}else{if(nNode.nodeName=="TD"){var iDataIndex=_fnNodeToDataIndex(oSettings,nNode.parentNode);
 638.146 +var iCorrector=0;for(var j=0;j<oSettings.aoColumns.length;j++){if(oSettings.aoColumns[j].bVisible){if(oSettings.aoData[iDataIndex].nTr.getElementsByTagName("td")[j-iCorrector]==nNode){return[iDataIndex,j-iCorrector,j]
 638.147 +}}else{iCorrector++}}}}return null};this.fnUpdate=function(mData,mRow,iColumn,bRedraw){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.148 +var iVisibleColumn;var sDisplay;var iRow=(typeof mRow=="object")?_fnNodeToDataIndex(oSettings,mRow):mRow;
 638.149 +if(typeof mData!="object"){sDisplay=mData;oSettings.aoData[iRow]._aData[iColumn]=sDisplay;
 638.150 +if(oSettings.aoColumns[iColumn].fnRender!==null){sDisplay=oSettings.aoColumns[iColumn].fnRender({iDataRow:iRow,iDataColumn:iColumn,aData:oSettings.aoData[iRow]._aData,oSettings:oSettings});
 638.151 +if(oSettings.aoColumns[iColumn].bUseRendered){oSettings.aoData[iRow]._aData[iColumn]=sDisplay
 638.152 +}}iVisibleColumn=_fnColumnIndexToVisible(oSettings,iColumn);if(iVisibleColumn!==null){oSettings.aoData[iRow].nTr.getElementsByTagName("td")[iVisibleColumn].innerHTML=sDisplay
 638.153 +}}else{if(mData.length!=oSettings.aoColumns.length){alert("DataTables warning: An array passed to fnUpdate must have the same number of columns as the table in question - in this case "+oSettings.aoColumns.length);
 638.154 +return 1}for(var i=0;i<mData.length;i++){sDisplay=mData[i];oSettings.aoData[iRow]._aData[i]=sDisplay;
 638.155 +if(oSettings.aoColumns[i].fnRender!==null){sDisplay=oSettings.aoColumns[i].fnRender({iDataRow:iRow,iDataColumn:i,aData:oSettings.aoData[iRow]._aData,oSettings:oSettings});
 638.156 +if(oSettings.aoColumns[i].bUseRendered){oSettings.aoData[iRow]._aData[i]=sDisplay
 638.157 +}}iVisibleColumn=_fnColumnIndexToVisible(oSettings,i);if(iVisibleColumn!==null){oSettings.aoData[iRow].nTr.getElementsByTagName("td")[iVisibleColumn].innerHTML=sDisplay
 638.158 +}}}_fnBuildSearchArray(oSettings,1);if(typeof bRedraw!="undefined"&&bRedraw){_fnReDraw(oSettings)
 638.159 +}return 0};this.fnSetColumnVis=function(iCol,bShow){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.160 +var i,iLen;var iColumns=oSettings.aoColumns.length;var nTd;if(oSettings.aoColumns[iCol].bVisible==bShow){return
 638.161 +}var nTrHead=$("thead:eq(0)>tr",oSettings.nTable)[0];var nTrFoot=$("tfoot:eq(0)>tr",oSettings.nTable)[0];
 638.162 +var anTheadTh=[];var anTfootTh=[];for(i=0;i<iColumns;i++){anTheadTh.push(oSettings.aoColumns[i].nTh);
 638.163 +anTfootTh.push(oSettings.aoColumns[i].nTf)}if(bShow){var iInsert=0;for(i=0;i<iCol;
 638.164 +i++){if(oSettings.aoColumns[i].bVisible){iInsert++}}if(iInsert>=_fnVisbleColumns(oSettings)){nTrHead.appendChild(anTheadTh[iCol]);
 638.165 +if(nTrFoot){nTrFoot.appendChild(anTfootTh[iCol])}for(i=0,iLen=oSettings.aoData.length;
 638.166 +i<iLen;i++){nTd=oSettings.aoData[i]._anHidden[iCol];oSettings.aoData[i].nTr.appendChild(nTd)
 638.167 +}}else{var iBefore;for(i=iCol;i<iColumns;i++){iBefore=_fnColumnIndexToVisible(oSettings,i);
 638.168 +if(iBefore!==null){break}}nTrHead.insertBefore(anTheadTh[iCol],nTrHead.getElementsByTagName("th")[iBefore]);
 638.169 +if(nTrFoot){nTrFoot.insertBefore(anTfootTh[iCol],nTrFoot.getElementsByTagName("th")[iBefore])
 638.170 +}for(i=0,iLen=oSettings.aoData.length;i<iLen;i++){nTd=oSettings.aoData[i]._anHidden[iCol];
 638.171 +oSettings.aoData[i].nTr.insertBefore(nTd,oSettings.aoData[i].nTr.getElementsByTagName("td")[iBefore])
 638.172 +}}oSettings.aoColumns[iCol].bVisible=true}else{nTrHead.removeChild(anTheadTh[iCol]);
 638.173 +if(nTrFoot){nTrFoot.removeChild(anTfootTh[iCol])}var iVisCol=_fnColumnIndexToVisible(oSettings,iCol);
 638.174 +for(i=0,iLen=oSettings.aoData.length;i<iLen;i++){nTd=oSettings.aoData[i].nTr.getElementsByTagName("td")[iVisCol];
 638.175 +oSettings.aoData[i]._anHidden[iCol]=nTd;nTd.parentNode.removeChild(nTd)}oSettings.aoColumns[iCol].bVisible=false
 638.176 +}for(i=0,iLen=oSettings.aoOpenRows.length;i<iLen;i++){oSettings.aoOpenRows[i].nTr.colSpan=_fnVisbleColumns(oSettings)
 638.177 +}_fnSaveState(oSettings)};this.fnPageChange=function(sAction,bRedraw){var oSettings=_fnSettingsFromNode(this[_oExt.iApiIndex]);
 638.178 +_fnPageChange(oSettings,sAction);if(typeof bRedraw=="undefined"||bRedraw){_fnReDraw(oSettings)
 638.179 +}};function _fnExternApiFunc(sFunc){return function(){var aArgs=[_fnSettingsFromNode(this[_oExt.iApiIndex])].concat(Array.prototype.slice.call(arguments));
 638.180 +return _oExt.oApi[sFunc].apply(this,aArgs)}}for(var sFunc in _oExt.oApi){if(sFunc){this[sFunc]=_fnExternApiFunc(sFunc)
 638.181 +}}function _fnInitalise(oSettings){if(oSettings.bInitialised===false){setTimeout(function(){_fnInitalise(oSettings)
 638.182 +},200);return}_fnAddOptionsHtml(oSettings);_fnDrawHead(oSettings);if(oSettings.oFeatures.bSort){_fnSort(oSettings,false);
 638.183 +_fnSortingClasses(oSettings)}else{oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();
 638.184 +_fnCalculateEnd(oSettings);_fnDraw(oSettings)}if(oSettings.sAjaxSource!==null&&!oSettings.oFeatures.bServerSide){_fnProcessingDisplay(oSettings,true);
 638.185 +oSettings.fnServerData(oSettings.sAjaxSource,null,function(json){for(var i=0;i<json.aaData.length;
 638.186 +i++){_fnAddData(oSettings,json.aaData[i])}oSettings.iInitDisplayStart=oSettings._iDisplayStart;
 638.187 +if(oSettings.oFeatures.bSort){_fnSort(oSettings)}else{oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();
 638.188 +_fnCalculateEnd(oSettings);_fnDraw(oSettings)}_fnProcessingDisplay(oSettings,false);
 638.189 +if(typeof oSettings.fnInitComplete=="function"){oSettings.fnInitComplete(oSettings,json)
 638.190 +}});return}if(typeof oSettings.fnInitComplete=="function"){oSettings.fnInitComplete(oSettings)
 638.191 +}if(!oSettings.oFeatures.bServerSide){_fnProcessingDisplay(oSettings,false)}}function _fnLanguageProcess(oSettings,oLanguage,bInit){_fnMap(oSettings.oLanguage,oLanguage,"sProcessing");
 638.192 +_fnMap(oSettings.oLanguage,oLanguage,"sLengthMenu");_fnMap(oSettings.oLanguage,oLanguage,"sZeroRecords");
 638.193 +_fnMap(oSettings.oLanguage,oLanguage,"sInfo");_fnMap(oSettings.oLanguage,oLanguage,"sInfoEmpty");
 638.194 +_fnMap(oSettings.oLanguage,oLanguage,"sInfoFiltered");_fnMap(oSettings.oLanguage,oLanguage,"sInfoPostFix");
 638.195 +_fnMap(oSettings.oLanguage,oLanguage,"sSearch");if(typeof oLanguage.oPaginate!="undefined"){_fnMap(oSettings.oLanguage.oPaginate,oLanguage.oPaginate,"sFirst");
 638.196 +_fnMap(oSettings.oLanguage.oPaginate,oLanguage.oPaginate,"sPrevious");_fnMap(oSettings.oLanguage.oPaginate,oLanguage.oPaginate,"sNext");
 638.197 +_fnMap(oSettings.oLanguage.oPaginate,oLanguage.oPaginate,"sLast")}if(bInit){_fnInitalise(oSettings)
 638.198 +}}function _fnAddColumn(oSettings,oOptions,nTh){oSettings.aoColumns[oSettings.aoColumns.length++]={sType:null,_bAutoType:true,bVisible:true,bSearchable:true,bSortable:true,asSorting:["asc","desc"],sSortingClass:oSettings.oClasses.sSortable,sSortingClassJUI:oSettings.oClasses.sSortJUI,sTitle:nTh?nTh.innerHTML:"",sName:"",sWidth:null,sClass:null,fnRender:null,bUseRendered:true,iDataSort:oSettings.aoColumns.length-1,sSortDataType:"std",nTh:nTh?nTh:document.createElement("th"),nTf:null};
 638.199 +var iLength=oSettings.aoColumns.length-1;var oCol=oSettings.aoColumns[iLength];if(typeof oOptions!="undefined"&&oOptions!==null){if(typeof oOptions.sType!="undefined"){oCol.sType=oOptions.sType;
 638.200 +oCol._bAutoType=false}_fnMap(oCol,oOptions,"bVisible");_fnMap(oCol,oOptions,"bSearchable");
 638.201 +_fnMap(oCol,oOptions,"bSortable");_fnMap(oCol,oOptions,"sTitle");_fnMap(oCol,oOptions,"sName");
 638.202 +_fnMap(oCol,oOptions,"sWidth");_fnMap(oCol,oOptions,"sClass");_fnMap(oCol,oOptions,"fnRender");
 638.203 +_fnMap(oCol,oOptions,"bUseRendered");_fnMap(oCol,oOptions,"iDataSort");_fnMap(oCol,oOptions,"asSorting");
 638.204 +_fnMap(oCol,oOptions,"sSortDataType")}if(!oSettings.oFeatures.bSort){oCol.bSortable=false
 638.205 +}if(!oCol.bSortable||($.inArray("asc",oCol.asSorting)==-1&&$.inArray("desc",oCol.asSorting)==-1)){oCol.sSortingClass=oSettings.oClasses.sSortableNone;
 638.206 +oCol.sSortingClassJUI=""}else{if($.inArray("asc",oCol.asSorting)!=-1&&$.inArray("desc",oCol.asSorting)==-1){oCol.sSortingClass=oSettings.oClasses.sSortableAsc;
 638.207 +oCol.sSortingClassJUI=oSettings.oClasses.sSortJUIAscAllowed}else{if($.inArray("asc",oCol.asSorting)==-1&&$.inArray("desc",oCol.asSorting)!=-1){oCol.sSortingClass=oSettings.oClasses.sSortableDesc;
 638.208 +oCol.sSortingClassJUI=oSettings.oClasses.sSortJUIDescAllowed}}}if(typeof oSettings.aoPreSearchCols[iLength]=="undefined"||oSettings.aoPreSearchCols[iLength]===null){oSettings.aoPreSearchCols[iLength]={sSearch:"",bEscapeRegex:true}
 638.209 +}else{if(typeof oSettings.aoPreSearchCols[iLength].bEscapeRegex=="undefined"){oSettings.aoPreSearchCols[iLength].bEscapeRegex=true
 638.210 +}}}function _fnAddData(oSettings,aData){if(aData.length!=oSettings.aoColumns.length){alert("DataTables warning: Added data does not match known number of columns");
 638.211 +return -1}var iThisIndex=oSettings.aoData.length;oSettings.aoData.push({nTr:document.createElement("tr"),_iId:oSettings.iNextId++,_aData:aData.slice(),_anHidden:[],_sRowStripe:""});
 638.212 +var nTd;for(var i=0;i<aData.length;i++){nTd=document.createElement("td");if(typeof oSettings.aoColumns[i].fnRender=="function"){var sRendered=oSettings.aoColumns[i].fnRender({iDataRow:iThisIndex,iDataColumn:i,aData:aData,oSettings:oSettings});
 638.213 +nTd.innerHTML=sRendered;if(oSettings.aoColumns[i].bUseRendered){oSettings.aoData[iThisIndex]._aData[i]=sRendered
 638.214 +}}else{nTd.innerHTML=aData[i]}if(oSettings.aoColumns[i].sClass!==null){nTd.className=oSettings.aoColumns[i].sClass
 638.215 +}if(oSettings.aoColumns[i]._bAutoType&&oSettings.aoColumns[i].sType!="string"){if(oSettings.aoColumns[i].sType===null){oSettings.aoColumns[i].sType=_fnDetectType(aData[i])
 638.216 +}else{if(oSettings.aoColumns[i].sType=="date"||oSettings.aoColumns[i].sType=="numeric"){oSettings.aoColumns[i].sType=_fnDetectType(aData[i])
 638.217 +}}}if(oSettings.aoColumns[i].bVisible){oSettings.aoData[iThisIndex].nTr.appendChild(nTd)
 638.218 +}else{oSettings.aoData[iThisIndex]._anHidden[i]=nTd}}oSettings.aiDisplayMaster.push(iThisIndex);
 638.219 +return iThisIndex}function _fnGatherData(oSettings){var iLoop;var i,j;if(oSettings.sAjaxSource===null){$("tbody:eq(0)>tr",oSettings.nTable).each(function(){var iThisIndex=oSettings.aoData.length;
 638.220 +oSettings.aoData.push({nTr:this,_iId:oSettings.iNextId++,_aData:[],_anHidden:[],_sRowStripe:""});
 638.221 +oSettings.aiDisplayMaster.push(iThisIndex);var aLocalData=oSettings.aoData[iThisIndex]._aData;
 638.222 +$("td",this).each(function(i){aLocalData[i]=this.innerHTML})})}var iCorrector=0;for(i=0;
 638.223 +i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].sTitle===null){oSettings.aoColumns[i].sTitle=oSettings.aoColumns[i].nTh.innerHTML
 638.224 +}var bAutoType=oSettings.aoColumns[i]._bAutoType;var bRender=typeof oSettings.aoColumns[i].fnRender=="function";
 638.225 +var bClass=oSettings.aoColumns[i].sClass!==null;var bVisible=oSettings.aoColumns[i].bVisible;
 638.226 +if(bAutoType||bRender||bClass||!bVisible){iLoop=oSettings.aoData.length;for(j=0;j<iLoop;
 638.227 +j++){var nCellNode=oSettings.aoData[j].nTr.getElementsByTagName("td")[i-iCorrector];
 638.228 +if(bAutoType){if(oSettings.aoColumns[i].sType===null){oSettings.aoColumns[i].sType=_fnDetectType(oSettings.aoData[j]._aData[i])
 638.229 +}else{if(oSettings.aoColumns[i].sType=="date"||oSettings.aoColumns[i].sType=="numeric"){oSettings.aoColumns[i].sType=_fnDetectType(oSettings.aoData[j]._aData[i])
 638.230 +}}}if(bRender){var sRendered=oSettings.aoColumns[i].fnRender({iDataRow:j,iDataColumn:i,aData:oSettings.aoData[j]._aData,oSettings:oSettings});
 638.231 +nCellNode.innerHTML=sRendered;if(oSettings.aoColumns[i].bUseRendered){oSettings.aoData[j]._aData[i]=sRendered
 638.232 +}}if(bClass){nCellNode.className+=" "+oSettings.aoColumns[i].sClass}if(!bVisible){oSettings.aoData[j]._anHidden[i]=nCellNode;
 638.233 +nCellNode.parentNode.removeChild(nCellNode)}}if(!bVisible){iCorrector++}}}}function _fnDrawHead(oSettings){var i,nTh,iLen;
 638.234 +var iThs=oSettings.nTable.getElementsByTagName("thead")[0].getElementsByTagName("th").length;
 638.235 +var iCorrector=0;if(iThs!==0){for(i=0,iLen=oSettings.aoColumns.length;i<iLen;i++){nTh=oSettings.aoColumns[i].nTh;
 638.236 +if(oSettings.aoColumns[i].bVisible){if(oSettings.aoColumns[i].sWidth!==null){nTh.style.width=oSettings.aoColumns[i].sWidth
 638.237 +}if(oSettings.aoColumns[i].sTitle!=nTh.innerHTML){nTh.innerHTML=oSettings.aoColumns[i].sTitle
 638.238 +}}else{nTh.parentNode.removeChild(nTh);iCorrector++}}}else{var nTr=document.createElement("tr");
 638.239 +for(i=0,iLen=oSettings.aoColumns.length;i<iLen;i++){nTh=oSettings.aoColumns[i].nTh;
 638.240 +nTh.innerHTML=oSettings.aoColumns[i].sTitle;if(oSettings.aoColumns[i].bVisible){if(oSettings.aoColumns[i].sClass!==null){nTh.className=oSettings.aoColumns[i].sClass
 638.241 +}if(oSettings.aoColumns[i].sWidth!==null){nTh.style.width=oSettings.aoColumns[i].sWidth
 638.242 +}nTr.appendChild(nTh)}}$("thead:eq(0)",oSettings.nTable).html("")[0].appendChild(nTr)
 638.243 +}if(oSettings.bJUI){for(i=0,iLen=oSettings.aoColumns.length;i<iLen;i++){oSettings.aoColumns[i].nTh.insertBefore(document.createElement("span"),oSettings.aoColumns[i].nTh.firstChild)
 638.244 +}}if(oSettings.oFeatures.bSort){for(i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bSortable!==false){_fnSortAttachListener(oSettings,oSettings.aoColumns[i].nTh,i)
 638.245 +}else{$(oSettings.aoColumns[i].nTh).addClass(oSettings.oClasses.sSortableNone)}}$("thead:eq(0) th",oSettings.nTable).mousedown(function(e){if(e.shiftKey){this.onselectstart=function(){return false
 638.246 +};return false}})}if(oSettings.oFeatures.bAutoWidth&&oSettings.nTable.offsetWidth!==0){oSettings.nTable.style.width=oSettings.nTable.offsetWidth+"px"
 638.247 +}var nTfoot=oSettings.nTable.getElementsByTagName("tfoot");if(nTfoot.length!==0){iCorrector=0;
 638.248 +var nTfs=nTfoot[0].getElementsByTagName("th");for(i=0,iLen=nTfs.length;i<iLen;i++){oSettings.aoColumns[i].nTf=nTfs[i-iCorrector];
 638.249 +if(!oSettings.aoColumns[i].bVisible){nTfs[i-iCorrector].parentNode.removeChild(nTfs[i-iCorrector]);
 638.250 +iCorrector++}}}}function _fnDraw(oSettings){var i,iLen;var anRows=[];var iRowCount=0;
 638.251 +var bRowError=false;var iStrips=oSettings.asStripClasses.length;var iOpenRows=oSettings.aoOpenRows.length;
 638.252 +if(oSettings.oFeatures.bServerSide&&!_fnAjaxUpdate(oSettings)){return}if(typeof oSettings.iInitDisplayStart!="undefined"&&oSettings.iInitDisplayStart!=-1){oSettings._iDisplayStart=oSettings.iInitDisplayStart;
 638.253 +oSettings.iInitDisplayStart=-1;_fnCalculateEnd(oSettings)}if(oSettings.aiDisplay.length!==0){var iStart=oSettings._iDisplayStart;
 638.254 +var iEnd=oSettings._iDisplayEnd;if(oSettings.oFeatures.bServerSide){iStart=0;iEnd=oSettings.aoData.length
 638.255 +}for(var j=iStart;j<iEnd;j++){var aoData=oSettings.aoData[oSettings.aiDisplay[j]];
 638.256 +var nRow=aoData.nTr;if(iStrips!==0){var sStrip=oSettings.asStripClasses[iRowCount%iStrips];
 638.257 +if(aoData._sRowStripe!=sStrip){$(nRow).removeClass(aoData._sRowStripe).addClass(sStrip);
 638.258 +aoData._sRowStripe=sStrip}}if(typeof oSettings.fnRowCallback=="function"){nRow=oSettings.fnRowCallback(nRow,oSettings.aoData[oSettings.aiDisplay[j]]._aData,iRowCount,j);
 638.259 +if(!nRow&&!bRowError){alert("DataTables warning: A node was not returned by fnRowCallback");
 638.260 +bRowError=true}}anRows.push(nRow);iRowCount++;if(iOpenRows!==0){for(var k=0;k<iOpenRows;
 638.261 +k++){if(nRow==oSettings.aoOpenRows[k].nParent){anRows.push(oSettings.aoOpenRows[k].nTr)
 638.262 +}}}}}else{anRows[0]=document.createElement("tr");if(typeof oSettings.asStripClasses[0]!="undefined"){anRows[0].className=oSettings.asStripClasses[0]
 638.263 +}var nTd=document.createElement("td");nTd.setAttribute("valign","top");nTd.colSpan=oSettings.aoColumns.length;
 638.264 +nTd.className=oSettings.oClasses.sRowEmpty;nTd.innerHTML=oSettings.oLanguage.sZeroRecords;
 638.265 +anRows[iRowCount].appendChild(nTd)}if(typeof oSettings.fnHeaderCallback=="function"){oSettings.fnHeaderCallback($("thead:eq(0)>tr",oSettings.nTable)[0],_fnGetDataMaster(oSettings),oSettings._iDisplayStart,oSettings.fnDisplayEnd(),oSettings.aiDisplay)
 638.266 +}if(typeof oSettings.fnFooterCallback=="function"){oSettings.fnFooterCallback($("tfoot:eq(0)>tr",oSettings.nTable)[0],_fnGetDataMaster(oSettings),oSettings._iDisplayStart,oSettings.fnDisplayEnd(),oSettings.aiDisplay)
 638.267 +}var nTrs=$("tbody:eq(0)>tr",oSettings.nTable);for(i=0,iLen=nTrs.length;i<iLen;i++){nTrs[i].parentNode.removeChild(nTrs[i])
 638.268 +}var nBody=$("tbody:eq(0)",oSettings.nTable);if(nBody[0]){for(i=0,iLen=anRows.length;
 638.269 +i<iLen;i++){nBody[0].appendChild(anRows[i])}}for(i=0,iLen=oSettings.aoDrawCallback.length;
 638.270 +i<iLen;i++){oSettings.aoDrawCallback[i].fn(oSettings)}oSettings.bSorted=false;oSettings.bFiltered=false
 638.271 +}function _fnReDraw(oSettings){if(oSettings.oFeatures.bSort){_fnSort(oSettings,oSettings.oPreviousSearch)
 638.272 +}else{if(oSettings.oFeatures.bFilter){_fnFilterComplete(oSettings,oSettings.oPreviousSearch)
 638.273 +}else{_fnCalculateEnd(oSettings);_fnDraw(oSettings)}}}function _fnAjaxUpdate(oSettings){if(oSettings.bAjaxDataGet){_fnProcessingDisplay(oSettings,true);
 638.274 +var iColumns=oSettings.aoColumns.length;var aoData=[];var i;oSettings.iServerDraw++;
 638.275 +aoData.push({name:"sEcho",value:oSettings.iServerDraw});aoData.push({name:"iColumns",value:iColumns});
 638.276 +aoData.push({name:"sColumns",value:_fnColumnOrdering(oSettings)});aoData.push({name:"iDisplayStart",value:oSettings._iDisplayStart});
 638.277 +aoData.push({name:"iDisplayLength",value:oSettings.oFeatures.bPaginate!==false?oSettings._iDisplayLength:-1});
 638.278 +if(oSettings.oFeatures.bFilter!==false){aoData.push({name:"sSearch",value:oSettings.oPreviousSearch.sSearch});
 638.279 +aoData.push({name:"bEscapeRegex",value:oSettings.oPreviousSearch.bEscapeRegex});for(i=0;
 638.280 +i<iColumns;i++){aoData.push({name:"sSearch_"+i,value:oSettings.aoPreSearchCols[i].sSearch});
 638.281 +aoData.push({name:"bEscapeRegex_"+i,value:oSettings.aoPreSearchCols[i].bEscapeRegex});
 638.282 +aoData.push({name:"bSearchable_"+i,value:oSettings.aoColumns[i].bSearchable})}}if(oSettings.oFeatures.bSort!==false){var iFixed=oSettings.aaSortingFixed!==null?oSettings.aaSortingFixed.length:0;
 638.283 +var iUser=oSettings.aaSorting.length;aoData.push({name:"iSortingCols",value:iFixed+iUser});
 638.284 +for(i=0;i<iFixed;i++){aoData.push({name:"iSortCol_"+i,value:oSettings.aaSortingFixed[i][0]});
 638.285 +aoData.push({name:"sSortDir_"+i,value:oSettings.aaSortingFixed[i][1]})}for(i=0;i<iUser;
 638.286 +i++){aoData.push({name:"iSortCol_"+(i+iFixed),value:oSettings.aaSorting[i][0]});aoData.push({name:"sSortDir_"+(i+iFixed),value:oSettings.aaSorting[i][1]})
 638.287 +}for(i=0;i<iColumns;i++){aoData.push({name:"bSortable_"+i,value:oSettings.aoColumns[i].bSortable})
 638.288 +}}oSettings.fnServerData(oSettings.sAjaxSource,aoData,function(json){_fnAjaxUpdateDraw(oSettings,json)
 638.289 +});return false}else{return true}}function _fnAjaxUpdateDraw(oSettings,json){if(typeof json.sEcho!="undefined"){if(json.sEcho*1<oSettings.iServerDraw){return
 638.290 +}else{oSettings.iServerDraw=json.sEcho*1}}_fnClearTable(oSettings);oSettings._iRecordsTotal=json.iTotalRecords;
 638.291 +oSettings._iRecordsDisplay=json.iTotalDisplayRecords;var sOrdering=_fnColumnOrdering(oSettings);
 638.292 +var bReOrder=(typeof json.sColumns!="undefined"&&sOrdering!==""&&json.sColumns!=sOrdering);
 638.293 +if(bReOrder){var aiIndex=_fnReOrderIndex(oSettings,json.sColumns)}for(var i=0,iLen=json.aaData.length;
 638.294 +i<iLen;i++){if(bReOrder){var aData=[];for(var j=0,jLen=oSettings.aoColumns.length;
 638.295 +j<jLen;j++){aData.push(json.aaData[i][aiIndex[j]])}_fnAddData(oSettings,aData)}else{_fnAddData(oSettings,json.aaData[i])
 638.296 +}}oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();oSettings.bAjaxDataGet=false;
 638.297 +_fnDraw(oSettings);oSettings.bAjaxDataGet=true;_fnProcessingDisplay(oSettings,false)
 638.298 +}function _fnAddOptionsHtml(oSettings){var nHolding=document.createElement("div");
 638.299 +oSettings.nTable.parentNode.insertBefore(nHolding,oSettings.nTable);var nWrapper=document.createElement("div");
 638.300 +nWrapper.className=oSettings.oClasses.sWrapper;if(oSettings.sTableId!==""){nWrapper.setAttribute("id",oSettings.sTableId+"_wrapper")
 638.301 +}var nInsertNode=nWrapper;var sDom=oSettings.sDom.replace("H","fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix");
 638.302 +sDom=sDom.replace("F","fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix");
 638.303 +var aDom=sDom.split("");var nTmp,iPushFeature,cOption,nNewNode,cNext,sClass,j;for(var i=0;
 638.304 +i<aDom.length;i++){iPushFeature=0;cOption=aDom[i];if(cOption=="<"){nNewNode=document.createElement("div");
 638.305 +cNext=aDom[i+1];if(cNext=="'"||cNext=='"'){sClass="";j=2;while(aDom[i+j]!=cNext){sClass+=aDom[i+j];
 638.306 +j++}nNewNode.className=sClass;i+=j}nInsertNode.appendChild(nNewNode);nInsertNode=nNewNode
 638.307 +}else{if(cOption==">"){nInsertNode=nInsertNode.parentNode}else{if(cOption=="l"&&oSettings.oFeatures.bPaginate&&oSettings.oFeatures.bLengthChange){nTmp=_fnFeatureHtmlLength(oSettings);
 638.308 +iPushFeature=1}else{if(cOption=="f"&&oSettings.oFeatures.bFilter){nTmp=_fnFeatureHtmlFilter(oSettings);
 638.309 +iPushFeature=1}else{if(cOption=="r"&&oSettings.oFeatures.bProcessing){nTmp=_fnFeatureHtmlProcessing(oSettings);
 638.310 +iPushFeature=1}else{if(cOption=="t"){nTmp=oSettings.nTable;iPushFeature=1}else{if(cOption=="i"&&oSettings.oFeatures.bInfo){nTmp=_fnFeatureHtmlInfo(oSettings);
 638.311 +iPushFeature=1}else{if(cOption=="p"&&oSettings.oFeatures.bPaginate){nTmp=_fnFeatureHtmlPaginate(oSettings);
 638.312 +iPushFeature=1}else{if(_oExt.aoFeatures.length!==0){var aoFeatures=_oExt.aoFeatures;
 638.313 +for(var k=0,kLen=aoFeatures.length;k<kLen;k++){if(cOption==aoFeatures[k].cFeature){nTmp=aoFeatures[k].fnInit(oSettings);
 638.314 +if(nTmp){iPushFeature=1}break}}}}}}}}}}}if(iPushFeature==1){if(typeof oSettings.aanFeatures[cOption]!="object"){oSettings.aanFeatures[cOption]=[]
 638.315 +}oSettings.aanFeatures[cOption].push(nTmp);nInsertNode.appendChild(nTmp)}}nHolding.parentNode.replaceChild(nWrapper,nHolding)
 638.316 +}function _fnFeatureHtmlFilter(oSettings){var nFilter=document.createElement("div");
 638.317 +if(oSettings.sTableId!==""&&typeof oSettings.aanFeatures.f=="undefined"){nFilter.setAttribute("id",oSettings.sTableId+"_filter")
 638.318 +}nFilter.className=oSettings.oClasses.sFilter;var sSpace=oSettings.oLanguage.sSearch===""?"":" ";
 638.319 +nFilter.innerHTML=oSettings.oLanguage.sSearch+sSpace+'<input type="text" />';var jqFilter=$("input",nFilter);
 638.320 +jqFilter.val(oSettings.oPreviousSearch.sSearch.replace('"',"""));jqFilter.keyup(function(e){var n=oSettings.aanFeatures.f;
 638.321 +for(var i=0,iLen=n.length;i<iLen;i++){if(n[i]!=this.parentNode){$("input",n[i]).val(this.value)
 638.322 +}}_fnFilterComplete(oSettings,{sSearch:this.value,bEscapeRegex:oSettings.oPreviousSearch.bEscapeRegex})
 638.323 +});jqFilter.keypress(function(e){if(e.keyCode==13){return false}});return nFilter
 638.324 +}function _fnFilterComplete(oSettings,oInput,iForce){_fnFilter(oSettings,oInput.sSearch,iForce,oInput.bEscapeRegex);
 638.325 +for(var i=0;i<oSettings.aoPreSearchCols.length;i++){_fnFilterColumn(oSettings,oSettings.aoPreSearchCols[i].sSearch,i,oSettings.aoPreSearchCols[i].bEscapeRegex)
 638.326 +}if(_oExt.afnFiltering.length!==0){_fnFilterCustom(oSettings)}oSettings.bFiltered=true;
 638.327 +oSettings._iDisplayStart=0;_fnCalculateEnd(oSettings);_fnDraw(oSettings);_fnBuildSearchArray(oSettings,0)
 638.328 +}function _fnFilterCustom(oSettings){var afnFilters=_oExt.afnFiltering;for(var i=0,iLen=afnFilters.length;
 638.329 +i<iLen;i++){var iCorrector=0;for(var j=0,jLen=oSettings.aiDisplay.length;j<jLen;j++){var iDisIndex=oSettings.aiDisplay[j-iCorrector];
 638.330 +if(!afnFilters[i](oSettings,oSettings.aoData[iDisIndex]._aData,iDisIndex)){oSettings.aiDisplay.splice(j-iCorrector,1);
 638.331 +iCorrector++}}}}function _fnFilterColumn(oSettings,sInput,iColumn,bEscapeRegex){if(sInput===""){return
 638.332 +}var iIndexCorrector=0;var sRegexMatch=bEscapeRegex?_fnEscapeRegex(sInput):sInput;
 638.333 +var rpSearch=new RegExp(sRegexMatch,"i");for(var i=oSettings.aiDisplay.length-1;i>=0;
 638.334 +i--){var sData=_fnDataToSearch(oSettings.aoData[oSettings.aiDisplay[i]]._aData[iColumn],oSettings.aoColumns[iColumn].sType);
 638.335 +if(!rpSearch.test(sData)){oSettings.aiDisplay.splice(i,1);iIndexCorrector++}}}function _fnFilter(oSettings,sInput,iForce,bEscapeRegex){var i;
 638.336 +if(typeof iForce=="undefined"||iForce===null){iForce=0}if(_oExt.afnFiltering.length!==0){iForce=1
 638.337 +}var asSearch=bEscapeRegex?_fnEscapeRegex(sInput).split(" "):sInput.split(" ");var sRegExpString="^(?=.*?"+asSearch.join(")(?=.*?")+").*$";
 638.338 +var rpSearch=new RegExp(sRegExpString,"i");if(sInput.length<=0){oSettings.aiDisplay.splice(0,oSettings.aiDisplay.length);
 638.339 +oSettings.aiDisplay=oSettings.aiDisplayMaster.slice()}else{if(oSettings.aiDisplay.length==oSettings.aiDisplayMaster.length||oSettings.oPreviousSearch.sSearch.length>sInput.length||iForce==1||sInput.indexOf(oSettings.oPreviousSearch.sSearch)!==0){oSettings.aiDisplay.splice(0,oSettings.aiDisplay.length);
 638.340 +_fnBuildSearchArray(oSettings,1);for(i=0;i<oSettings.aiDisplayMaster.length;i++){if(rpSearch.test(oSettings.asDataSearch[i])){oSettings.aiDisplay.push(oSettings.aiDisplayMaster[i])
 638.341 +}}}else{var iIndexCorrector=0;for(i=0;i<oSettings.asDataSearch.length;i++){if(!rpSearch.test(oSettings.asDataSearch[i])){oSettings.aiDisplay.splice(i-iIndexCorrector,1);
 638.342 +iIndexCorrector++}}}}oSettings.oPreviousSearch.sSearch=sInput;oSettings.oPreviousSearch.bEscapeRegex=bEscapeRegex
 638.343 +}function _fnBuildSearchArray(oSettings,iMaster){oSettings.asDataSearch.splice(0,oSettings.asDataSearch.length);
 638.344 +var aArray=(typeof iMaster!="undefined"&&iMaster==1)?oSettings.aiDisplayMaster:oSettings.aiDisplay;
 638.345 +for(var i=0,iLen=aArray.length;i<iLen;i++){oSettings.asDataSearch[i]="";for(var j=0,jLen=oSettings.aoColumns.length;
 638.346 +j<jLen;j++){if(oSettings.aoColumns[j].bSearchable){var sData=oSettings.aoData[aArray[i]]._aData[j];
 638.347 +oSettings.asDataSearch[i]+=_fnDataToSearch(sData,oSettings.aoColumns[j].sType)+" "
 638.348 +}}}}function _fnDataToSearch(sData,sType){if(typeof _oExt.ofnSearch[sType]=="function"){return _oExt.ofnSearch[sType](sData)
 638.349 +}else{if(sType=="html"){return sData.replace(/\n/g," ").replace(/<.*?>/g,"")}else{if(typeof sData=="string"){return sData.replace(/\n/g," ")
 638.350 +}}}return sData}function _fnSort(oSettings,bApplyClasses){var aaSort=[];var oSort=_oExt.oSort;
 638.351 +var aoData=oSettings.aoData;var iDataSort;var iDataType;var i,j,jLen;if(!oSettings.oFeatures.bServerSide&&(oSettings.aaSorting.length!==0||oSettings.aaSortingFixed!==null)){if(oSettings.aaSortingFixed!==null){aaSort=oSettings.aaSortingFixed.concat(oSettings.aaSorting)
 638.352 +}else{aaSort=oSettings.aaSorting.slice()}for(i=0;i<aaSort.length;i++){var iColumn=aaSort[i][0];
 638.353 +var sDataType=oSettings.aoColumns[iColumn].sSortDataType;if(typeof _oExt.afnSortData[sDataType]!="undefined"){var iCorrector=0;
 638.354 +var aData=_oExt.afnSortData[sDataType](oSettings,iColumn);for(j=0,jLen=aoData.length;
 638.355 +j<jLen;j++){if(aoData[j]!==null){aoData[j]._aData[iColumn]=aData[iCorrector];iCorrector++
 638.356 +}}}}if(!window.runtime){var fnLocalSorting;var sDynamicSort="fnLocalSorting = function(a,b){var iTest;";
 638.357 +for(i=0;i<aaSort.length-1;i++){iDataSort=oSettings.aoColumns[aaSort[i][0]].iDataSort;
 638.358 +iDataType=oSettings.aoColumns[iDataSort].sType;sDynamicSort+="iTest = oSort['"+iDataType+"-"+aaSort[i][1]+"']( aoData[a]._aData["+iDataSort+"], aoData[b]._aData["+iDataSort+"] ); if ( iTest === 0 )"
 638.359 +}iDataSort=oSettings.aoColumns[aaSort[aaSort.length-1][0]].iDataSort;iDataType=oSettings.aoColumns[iDataSort].sType;
 638.360 +sDynamicSort+="iTest = oSort['"+iDataType+"-"+aaSort[aaSort.length-1][1]+"']( aoData[a]._aData["+iDataSort+"], aoData[b]._aData["+iDataSort+"] );if (iTest===0) return oSort['numeric-"+aaSort[aaSort.length-1][1]+"'](a, b); return iTest;}";
 638.361 +eval(sDynamicSort);oSettings.aiDisplayMaster.sort(fnLocalSorting)}else{var aAirSort=[];
 638.362 +var iLen=aaSort.length;for(i=0;i<iLen;i++){iDataSort=oSettings.aoColumns[aaSort[i][0]].iDataSort;
 638.363 +aAirSort.push([iDataSort,oSettings.aoColumns[iDataSort].sType+"-"+aaSort[i][1]])}oSettings.aiDisplayMaster.sort(function(a,b){var iTest;
 638.364 +for(var i=0;i<iLen;i++){iTest=oSort[aAirSort[i][1]](aoData[a]._aData[aAirSort[i][0]],aoData[b]._aData[aAirSort[i][0]]);
 638.365 +if(iTest!==0){return iTest}}return 0})}}if(typeof bApplyClasses=="undefined"||bApplyClasses){_fnSortingClasses(oSettings)
 638.366 +}oSettings.bSorted=true;if(oSettings.oFeatures.bFilter){_fnFilterComplete(oSettings,oSettings.oPreviousSearch,1)
 638.367 +}else{oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();oSettings._iDisplayStart=0;
 638.368 +_fnCalculateEnd(oSettings);_fnDraw(oSettings)}}function _fnSortAttachListener(oSettings,nNode,iDataIndex,fnCallback){$(nNode).click(function(e){if(oSettings.aoColumns[iDataIndex].bSortable===false){return
 638.369 +}var fnInnerSorting=function(){var iColumn,iNextSort;if(e.shiftKey){var bFound=false;
 638.370 +for(var i=0;i<oSettings.aaSorting.length;i++){if(oSettings.aaSorting[i][0]==iDataIndex){bFound=true;
 638.371 +iColumn=oSettings.aaSorting[i][0];iNextSort=oSettings.aaSorting[i][2]+1;if(typeof oSettings.aoColumns[iColumn].asSorting[iNextSort]=="undefined"){oSettings.aaSorting.splice(i,1)
 638.372 +}else{oSettings.aaSorting[i][1]=oSettings.aoColumns[iColumn].asSorting[iNextSort];
 638.373 +oSettings.aaSorting[i][2]=iNextSort}break}}if(bFound===false){oSettings.aaSorting.push([iDataIndex,oSettings.aoColumns[iDataIndex].asSorting[0],0])
 638.374 +}}else{if(oSettings.aaSorting.length==1&&oSettings.aaSorting[0][0]==iDataIndex){iColumn=oSettings.aaSorting[0][0];
 638.375 +iNextSort=oSettings.aaSorting[0][2]+1;if(typeof oSettings.aoColumns[iColumn].asSorting[iNextSort]=="undefined"){iNextSort=0
 638.376 +}oSettings.aaSorting[0][1]=oSettings.aoColumns[iColumn].asSorting[iNextSort];oSettings.aaSorting[0][2]=iNextSort
 638.377 +}else{oSettings.aaSorting.splice(0,oSettings.aaSorting.length);oSettings.aaSorting.push([iDataIndex,oSettings.aoColumns[iDataIndex].asSorting[0],0])
 638.378 +}}_fnSort(oSettings)};if(!oSettings.oFeatures.bProcessing){fnInnerSorting()}else{_fnProcessingDisplay(oSettings,true);
 638.379 +setTimeout(function(){fnInnerSorting();if(!oSettings.oFeatures.bServerSide){_fnProcessingDisplay(oSettings,false)
 638.380 +}},0)}if(typeof fnCallback=="function"){fnCallback(oSettings)}})}function _fnSortingClasses(oSettings){var i,j,iFound;
 638.381 +var aaSort,sClass;var iColumns=oSettings.aoColumns.length;var oClasses=oSettings.oClasses;
 638.382 +for(i=0;i<iColumns;i++){if(oSettings.aoColumns[i].bSortable){$(oSettings.aoColumns[i].nTh).removeClass(oClasses.sSortAsc+" "+oClasses.sSortDesc+" "+oSettings.aoColumns[i].sSortingClass)
 638.383 +}}if(oSettings.aaSortingFixed!==null){aaSort=oSettings.aaSortingFixed.concat(oSettings.aaSorting)
 638.384 +}else{aaSort=oSettings.aaSorting.slice()}for(i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bSortable){sClass=oSettings.aoColumns[i].sSortingClass;
 638.385 +iFound=-1;for(j=0;j<aaSort.length;j++){if(aaSort[j][0]==i){sClass=(aaSort[j][1]=="asc")?oClasses.sSortAsc:oClasses.sSortDesc;
 638.386 +iFound=j;break}}$(oSettings.aoColumns[i].nTh).addClass(sClass);if(oSettings.bJUI){var jqSpan=$("span",oSettings.aoColumns[i].nTh);
 638.387 +jqSpan.removeClass(oClasses.sSortJUIAsc+" "+oClasses.sSortJUIDesc+" "+oClasses.sSortJUI+" "+oClasses.sSortJUIAscAllowed+" "+oClasses.sSortJUIDescAllowed);
 638.388 +var sSpanClass;if(iFound==-1){sSpanClass=oSettings.aoColumns[i].sSortingClassJUI}else{if(aaSort[iFound][1]=="asc"){sSpanClass=oClasses.sSortJUIAsc
 638.389 +}else{sSpanClass=oClasses.sSortJUIDesc}}jqSpan.addClass(sSpanClass)}}else{$(oSettings.aoColumns[i].nTh).addClass(oSettings.aoColumns[i].sSortingClass)
 638.390 +}}if(oSettings.oFeatures.bSort&&oSettings.oFeatures.bSortClasses){var nTrs=_fnGetTrNodes(oSettings);
 638.391 +sClass=oClasses.sSortColumn;$("td",nTrs).removeClass(sClass+"1 "+sClass+"2 "+sClass+"3");
 638.392 +var iClass=1;for(i=0;i<aaSort.length;i++){var iVis=_fnColumnIndexToVisible(oSettings,aaSort[i][0]);
 638.393 +if(iVis!==null){if(iClass<=2){$("td:eq("+iVis+")",nTrs).addClass(sClass+iClass)}else{$("td:eq("+iVis+")",nTrs).addClass(sClass+"3")
 638.394 +}iClass++}}}}function _fnFeatureHtmlPaginate(oSettings){var nPaginate=document.createElement("div");
 638.395 +nPaginate.className=oSettings.oClasses.sPaging+oSettings.sPaginationType;_oExt.oPagination[oSettings.sPaginationType].fnInit(oSettings,nPaginate,function(oSettings){_fnCalculateEnd(oSettings);
 638.396 +_fnDraw(oSettings)});if(typeof oSettings.aanFeatures.p=="undefined"){oSettings.aoDrawCallback.push({fn:function(oSettings){_oExt.oPagination[oSettings.sPaginationType].fnUpdate(oSettings,function(oSettings){_fnCalculateEnd(oSettings);
 638.397 +_fnDraw(oSettings)})},sName:"pagination"})}return nPaginate}function _fnPageChange(oSettings,sAction){if(sAction=="first"){oSettings._iDisplayStart=0
 638.398 +}else{if(sAction=="previous"){oSettings._iDisplayStart=oSettings._iDisplayLength>=0?oSettings._iDisplayStart-oSettings._iDisplayLength:0;
 638.399 +if(oSettings._iDisplayStart<0){oSettings._iDisplayStart=0}}else{if(sAction=="next"){if(oSettings._iDisplayLength>=0){if(oSettings._iDisplayStart+oSettings._iDisplayLength<oSettings.fnRecordsDisplay()){oSettings._iDisplayStart+=oSettings._iDisplayLength
 638.400 +}}else{oSettings._iDisplayStart=0}}else{if(sAction=="last"){if(oSettings._iDisplayLength>=0){var iPages=parseInt((oSettings.fnRecordsDisplay()-1)/oSettings._iDisplayLength,10)+1;
 638.401 +oSettings._iDisplayStart=(iPages-1)*oSettings._iDisplayLength}else{oSettings._iDisplayStart=0
 638.402 +}}else{alert("DataTables warning: unknown paging action: "+sAction)}}}}}function _fnFeatureHtmlInfo(oSettings){var nInfo=document.createElement("div");
 638.403 +nInfo.className=oSettings.oClasses.sInfo;if(typeof oSettings.aanFeatures.i=="undefined"){oSettings.aoDrawCallback.push({fn:_fnUpdateInfo,sName:"information"});
 638.404 +if(oSettings.sTableId!==""){nInfo.setAttribute("id",oSettings.sTableId+"_info")}}return nInfo
 638.405 +}function _fnUpdateInfo(oSettings){if(!oSettings.oFeatures.bInfo||oSettings.aanFeatures.i.length===0){return
 638.406 +}var nFirst=oSettings.aanFeatures.i[0];if(oSettings.fnRecordsDisplay()===0&&oSettings.fnRecordsDisplay()==oSettings.fnRecordsTotal()){nFirst.innerHTML=oSettings.oLanguage.sInfoEmpty+oSettings.oLanguage.sInfoPostFix
 638.407 +}else{if(oSettings.fnRecordsDisplay()===0){nFirst.innerHTML=oSettings.oLanguage.sInfoEmpty+" "+oSettings.oLanguage.sInfoFiltered.replace("_MAX_",oSettings.fnRecordsTotal())+oSettings.oLanguage.sInfoPostFix
 638.408 +}else{if(oSettings.fnRecordsDisplay()==oSettings.fnRecordsTotal()){nFirst.innerHTML=oSettings.oLanguage.sInfo.replace("_START_",oSettings._iDisplayStart+1).replace("_END_",oSettings.fnDisplayEnd()).replace("_TOTAL_",oSettings.fnRecordsDisplay())+oSettings.oLanguage.sInfoPostFix
 638.409 +}else{nFirst.innerHTML=oSettings.oLanguage.sInfo.replace("_START_",oSettings._iDisplayStart+1).replace("_END_",oSettings.fnDisplayEnd()).replace("_TOTAL_",oSettings.fnRecordsDisplay())+" "+oSettings.oLanguage.sInfoFiltered.replace("_MAX_",oSettings.fnRecordsTotal())+oSettings.oLanguage.sInfoPostFix
 638.410 +}}}var n=oSettings.aanFeatures.i;if(n.length>1){var sInfo=nFirst.innerHTML;for(var i=1,iLen=n.length;
 638.411 +i<iLen;i++){n[i].innerHTML=sInfo}}}function _fnFeatureHtmlLength(oSettings){var sName=(oSettings.sTableId==="")?"":'name="'+oSettings.sTableId+'_length"';
 638.412 +var sStdMenu='<select size="1" '+sName+'><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select>';
 638.413 +var nLength=document.createElement("div");if(oSettings.sTableId!==""&&typeof oSettings.aanFeatures.l=="undefined"){nLength.setAttribute("id",oSettings.sTableId+"_length")
 638.414 +}nLength.className=oSettings.oClasses.sLength;nLength.innerHTML=oSettings.oLanguage.sLengthMenu.replace("_MENU_",sStdMenu);
 638.415 +$('select option[value="'+oSettings._iDisplayLength+'"]',nLength).attr("selected",true);
 638.416 +$("select",nLength).change(function(e){var iVal=$(this).val();var n=oSettings.aanFeatures.l;
 638.417 +for(var i=0,iLen=n.length;i<iLen;i++){if(n[i]!=this.parentNode){$("select",n[i]).val(iVal)
 638.418 +}}oSettings._iDisplayLength=parseInt(iVal,10);_fnCalculateEnd(oSettings);if(oSettings._iDisplayEnd==oSettings.aiDisplay.length){oSettings._iDisplayStart=oSettings._iDisplayEnd-oSettings._iDisplayLength;
 638.419 +if(oSettings._iDisplayStart<0){oSettings._iDisplayStart=0}}if(oSettings._iDisplayLength==-1){oSettings._iDisplayStart=0
 638.420 +}_fnDraw(oSettings)});return nLength}function _fnFeatureHtmlProcessing(oSettings){var nProcessing=document.createElement("div");
 638.421 +if(oSettings.sTableId!==""&&typeof oSettings.aanFeatures.r=="undefined"){nProcessing.setAttribute("id",oSettings.sTableId+"_processing")
 638.422 +}nProcessing.innerHTML=oSettings.oLanguage.sProcessing;nProcessing.className=oSettings.oClasses.sProcessing;
 638.423 +oSettings.nTable.parentNode.insertBefore(nProcessing,oSettings.nTable);return nProcessing
 638.424 +}function _fnProcessingDisplay(oSettings,bShow){if(oSettings.oFeatures.bProcessing){var an=oSettings.aanFeatures.r;
 638.425 +for(var i=0,iLen=an.length;i<iLen;i++){an[i].style.visibility=bShow?"visible":"hidden"
 638.426 +}}}function _fnVisibleToColumnIndex(oSettings,iMatch){var iColumn=-1;for(var i=0;
 638.427 +i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bVisible===true){iColumn++
 638.428 +}if(iColumn==iMatch){return i}}return null}function _fnColumnIndexToVisible(oSettings,iMatch){var iVisible=-1;
 638.429 +for(var i=0;i<oSettings.aoColumns.length;i++){if(oSettings.aoColumns[i].bVisible===true){iVisible++
 638.430 +}if(i==iMatch){return oSettings.aoColumns[i].bVisible===true?iVisible:null}}return null
 638.431 +}function _fnNodeToDataIndex(s,n){for(var i=0,iLen=s.aoData.length;i<iLen;i++){if(s.aoData[i]!==null&&s.aoData[i].nTr==n){return i
 638.432 +}}return null}function _fnVisbleColumns(oS){var iVis=0;for(var i=0;i<oS.aoColumns.length;
 638.433 +i++){if(oS.aoColumns[i].bVisible===true){iVis++}}return iVis}function _fnCalculateEnd(oSettings){if(oSettings.oFeatures.bPaginate===false){oSettings._iDisplayEnd=oSettings.aiDisplay.length
 638.434 +}else{if(oSettings._iDisplayStart+oSettings._iDisplayLength>oSettings.aiDisplay.length||oSettings._iDisplayLength==-1){oSettings._iDisplayEnd=oSettings.aiDisplay.length
 638.435 +}else{oSettings._iDisplayEnd=oSettings._iDisplayStart+oSettings._iDisplayLength}}}function _fnConvertToWidth(sWidth,nParent){if(!sWidth||sWidth===null||sWidth===""){return 0
 638.436 +}if(typeof nParent=="undefined"){nParent=document.getElementsByTagName("body")[0]
 638.437 +}var iWidth;var nTmp=document.createElement("div");nTmp.style.width=sWidth;nParent.appendChild(nTmp);
 638.438 +iWidth=nTmp.offsetWidth;nParent.removeChild(nTmp);return(iWidth)}function _fnCalculateColumnWidths(oSettings){var iTableWidth=oSettings.nTable.offsetWidth;
 638.439 +var iTotalUserIpSize=0;var iTmpWidth;var iVisibleColumns=0;var iColums=oSettings.aoColumns.length;
 638.440 +var i;var oHeaders=$("thead:eq(0)>th",oSettings.nTable);for(i=0;i<iColums;i++){if(oSettings.aoColumns[i].bVisible){iVisibleColumns++;
 638.441 +if(oSettings.aoColumns[i].sWidth!==null){iTmpWidth=_fnConvertToWidth(oSettings.aoColumns[i].sWidth,oSettings.nTable.parentNode);
 638.442 +iTotalUserIpSize+=iTmpWidth;oSettings.aoColumns[i].sWidth=iTmpWidth+"px"}}}if(iColums==oHeaders.length&&iTotalUserIpSize===0&&iVisibleColumns==iColums){for(i=0;
 638.443 +i<oSettings.aoColumns.length;i++){oSettings.aoColumns[i].sWidth=oHeaders[i].offsetWidth+"px"
 638.444 +}}else{var nCalcTmp=oSettings.nTable.cloneNode(false);nCalcTmp.setAttribute("id","");
 638.445 +var sTableTmp='<table class="'+nCalcTmp.className+'">';var sCalcHead="<tr>";var sCalcHtml="<tr>";
 638.446 +for(i=0;i<iColums;i++){if(oSettings.aoColumns[i].bVisible){sCalcHead+="<th>"+oSettings.aoColumns[i].sTitle+"</th>";
 638.447 +if(oSettings.aoColumns[i].sWidth!==null){var sWidth="";if(oSettings.aoColumns[i].sWidth!==null){sWidth=' style="width:'+oSettings.aoColumns[i].sWidth+';"'
 638.448 +}sCalcHtml+="<td"+sWidth+' tag_index="'+i+'">'+fnGetMaxLenString(oSettings,i)+"</td>"
 638.449 +}else{sCalcHtml+='<td tag_index="'+i+'">'+fnGetMaxLenString(oSettings,i)+"</td>"}}}sCalcHead+="</tr>";
 638.450 +sCalcHtml+="</tr>";nCalcTmp=$(sTableTmp+sCalcHead+sCalcHtml+"</table>")[0];nCalcTmp.style.width=iTableWidth+"px";
 638.451 +nCalcTmp.style.visibility="hidden";nCalcTmp.style.position="absolute";oSettings.nTable.parentNode.appendChild(nCalcTmp);
 638.452 +var oNodes=$("tr:eq(1)>td",nCalcTmp);var iIndex;for(i=0;i<oNodes.length;i++){iIndex=oNodes[i].getAttribute("tag_index");
 638.453 +oSettings.aoColumns[iIndex].sWidth=$("td",nCalcTmp)[i].offsetWidth+"px"}oSettings.nTable.parentNode.removeChild(nCalcTmp)
 638.454 +}}function fnGetMaxLenString(oSettings,iCol){var iMax=0;var iMaxIndex=-1;for(var i=0;
 638.455 +i<oSettings.aoData.length;i++){if(oSettings.aoData[i]._aData[iCol].length>iMax){iMax=oSettings.aoData[i]._aData[iCol].length;
 638.456 +iMaxIndex=i}}if(iMaxIndex>=0){return oSettings.aoData[iMaxIndex]._aData[iCol]}return""
 638.457 +}function _fnArrayCmp(aArray1,aArray2){if(aArray1.length!=aArray2.length){return 1
 638.458 +}for(var i=0;i<aArray1.length;i++){if(aArray1[i]!=aArray2[i]){return 2}}return 0}function _fnDetectType(sData){var aTypes=_oExt.aTypes;
 638.459 +var iLen=aTypes.length;for(var i=0;i<iLen;i++){var sType=aTypes[i](sData);if(sType!==null){return sType
 638.460 +}}return"string"}function _fnSettingsFromNode(nTable){for(var i=0;i<_aoSettings.length;
 638.461 +i++){if(_aoSettings[i].nTable==nTable){return _aoSettings[i]}}return null}function _fnGetDataMaster(oSettings){var aData=[];
 638.462 +var iLen=oSettings.aoData.length;for(var i=0;i<iLen;i++){if(oSettings.aoData[i]===null){aData.push(null)
 638.463 +}else{aData.push(oSettings.aoData[i]._aData)}}return aData}function _fnGetTrNodes(oSettings){var aNodes=[];
 638.464 +var iLen=oSettings.aoData.length;for(var i=0;i<iLen;i++){if(oSettings.aoData[i]===null){aNodes.push(null)
 638.465 +}else{aNodes.push(oSettings.aoData[i].nTr)}}return aNodes}function _fnEscapeRegex(sVal){var acEscape=["/",".","*","+","?","|","(",")","[","]","{","}","\\","$","^"];
 638.466 +var reReplace=new RegExp("(\\"+acEscape.join("|\\")+")","g");return sVal.replace(reReplace,"\\$1")
 638.467 +}function _fnReOrderIndex(oSettings,sColumns){var aColumns=sColumns.split(",");var aiReturn=[];
 638.468 +for(var i=0,iLen=oSettings.aoColumns.length;i<iLen;i++){for(var j=0;j<iLen;j++){if(oSettings.aoColumns[i].sName==aColumns[j]){aiReturn.push(j);
 638.469 +break}}}return aiReturn}function _fnColumnOrdering(oSettings){var sNames="";for(var i=0,iLen=oSettings.aoColumns.length;
 638.470 +i<iLen;i++){sNames+=oSettings.aoColumns[i].sName+","}if(sNames.length==iLen){return""
 638.471 +}return sNames.slice(0,-1)}function _fnClearTable(oSettings){oSettings.aoData.length=0;
 638.472 +oSettings.aiDisplayMaster.length=0;oSettings.aiDisplay.length=0;_fnCalculateEnd(oSettings)
 638.473 +}function _fnSaveState(oSettings){if(!oSettings.oFeatures.bStateSave){return}var i;
 638.474 +var sValue="{";sValue+='"iStart": '+oSettings._iDisplayStart+",";sValue+='"iEnd": '+oSettings._iDisplayEnd+",";
 638.475 +sValue+='"iLength": '+oSettings._iDisplayLength+",";sValue+='"sFilter": "'+oSettings.oPreviousSearch.sSearch.replace('"','\\"')+'",';
 638.476 +sValue+='"sFilterEsc": '+oSettings.oPreviousSearch.bEscapeRegex+",";sValue+='"aaSorting": [ ';
 638.477 +for(i=0;i<oSettings.aaSorting.length;i++){sValue+="["+oSettings.aaSorting[i][0]+",'"+oSettings.aaSorting[i][1]+"'],"
 638.478 +}sValue=sValue.substring(0,sValue.length-1);sValue+="],";sValue+='"aaSearchCols": [ ';
 638.479 +for(i=0;i<oSettings.aoPreSearchCols.length;i++){sValue+="['"+oSettings.aoPreSearchCols[i].sSearch.replace("'","'")+"',"+oSettings.aoPreSearchCols[i].bEscapeRegex+"],"
 638.480 +}sValue=sValue.substring(0,sValue.length-1);sValue+="],";sValue+='"abVisCols": [ ';
 638.481 +for(i=0;i<oSettings.aoColumns.length;i++){sValue+=oSettings.aoColumns[i].bVisible+","
 638.482 +}sValue=sValue.substring(0,sValue.length-1);sValue+="]";sValue+="}";_fnCreateCookie("SpryMedia_DataTables_"+oSettings.sInstance,sValue,oSettings.iCookieDuration)
 638.483 +}function _fnLoadState(oSettings,oInit){if(!oSettings.oFeatures.bStateSave){return
 638.484 +}var oData;var sData=_fnReadCookie("SpryMedia_DataTables_"+oSettings.sInstance);if(sData!==null&&sData!==""){try{if(typeof JSON=="object"&&typeof JSON.parse=="function"){oData=JSON.parse(sData.replace(/'/g,'"'))
 638.485 +}else{oData=eval("("+sData+")")}}catch(e){return}oSettings._iDisplayStart=oData.iStart;
 638.486 +oSettings.iInitDisplayStart=oData.iStart;oSettings._iDisplayEnd=oData.iEnd;oSettings._iDisplayLength=oData.iLength;
 638.487 +oSettings.oPreviousSearch.sSearch=oData.sFilter;oSettings.aaSorting=oData.aaSorting.slice();
 638.488 +if(typeof oData.sFilterEsc!="undefined"){oSettings.oPreviousSearch.bEscapeRegex=oData.sFilterEsc
 638.489 +}if(typeof oData.aaSearchCols!="undefined"){for(var i=0;i<oData.aaSearchCols.length;
 638.490 +i++){oSettings.aoPreSearchCols[i]={sSearch:oData.aaSearchCols[i][0],bEscapeRegex:oData.aaSearchCols[i][1]}
 638.491 +}}if(typeof oData.abVisCols!="undefined"){oInit.saved_aoColumns=[];for(i=0;i<oData.abVisCols.length;
 638.492 +i++){oInit.saved_aoColumns[i]={};oInit.saved_aoColumns[i].bVisible=oData.abVisCols[i]
 638.493 +}}}}function _fnCreateCookie(sName,sValue,iSecs){var date=new Date();date.setTime(date.getTime()+(iSecs*1000));
 638.494 +sName+="_"+window.location.pathname.replace(/[\/:]/g,"").toLowerCase();document.cookie=sName+"="+sValue+"; expires="+date.toGMTString()+"; path=/"
 638.495 +}function _fnReadCookie(sName){var sNameEQ=sName+"_"+window.location.pathname.replace(/[\/:]/g,"").toLowerCase()+"=";
 638.496 +var sCookieContents=document.cookie.split(";");for(var i=0;i<sCookieContents.length;
 638.497 +i++){var c=sCookieContents[i];while(c.charAt(0)==" "){c=c.substring(1,c.length)}if(c.indexOf(sNameEQ)===0){return c.substring(sNameEQ.length,c.length)
 638.498 +}}return null}function _fnGetUniqueThs(nThead){var nTrs=nThead.getElementsByTagName("tr");
 638.499 +if(nTrs.length==1){return nTrs[0].getElementsByTagName("th")}var aLayout=[],aReturn=[];
 638.500 +var ROWSPAN=2,COLSPAN=3,TDELEM=4;var i,j,k,iLen,jLen,iColumnShifted;var fnShiftCol=function(a,i,j){while(typeof a[i][j]!="undefined"){j++
 638.501 +}return j};var fnAddRow=function(i){if(typeof aLayout[i]=="undefined"){aLayout[i]=[]
 638.502 +}};for(i=0,iLen=nTrs.length;i<iLen;i++){fnAddRow(i);var iColumn=0;var nTds=[];for(j=0,jLen=nTrs[i].childNodes.length;
 638.503 +j<jLen;j++){if(nTrs[i].childNodes[j].nodeName=="TD"||nTrs[i].childNodes[j].nodeName=="TH"){nTds.push(nTrs[i].childNodes[j])
 638.504 +}}for(j=0,jLen=nTds.length;j<jLen;j++){var iColspan=nTds[j].getAttribute("colspan")*1;
 638.505 +var iRowspan=nTds[j].getAttribute("rowspan")*1;if(!iColspan||iColspan===0||iColspan===1){iColumnShifted=fnShiftCol(aLayout,i,iColumn);
 638.506 +aLayout[i][iColumnShifted]=(nTds[j].nodeName=="TD")?TDELEM:nTds[j];if(iRowspan||iRowspan===0||iRowspan===1){for(k=1;
 638.507 +k<iRowspan;k++){fnAddRow(i+k);aLayout[i+k][iColumnShifted]=ROWSPAN}}iColumn++}else{iColumnShifted=fnShiftCol(aLayout,i,iColumn);
 638.508 +for(k=0;k<iColspan;k++){aLayout[i][iColumnShifted+k]=COLSPAN}iColumn+=iColspan}}}for(i=0,iLen=aLayout[0].length;
 638.509 +i<iLen;i++){for(j=0,jLen=aLayout.length;j<jLen;j++){if(typeof aLayout[j][i]=="object"){aReturn.push(aLayout[j][i])
 638.510 +}}}return aReturn}function _fnMap(oRet,oSrc,sName,sMappedName){if(typeof sMappedName=="undefined"){sMappedName=sName
 638.511 +}if(typeof oSrc[sName]!="undefined"){oRet[sMappedName]=oSrc[sName]}}this.oApi._fnInitalise=_fnInitalise;
 638.512 +this.oApi._fnLanguageProcess=_fnLanguageProcess;this.oApi._fnAddColumn=_fnAddColumn;
 638.513 +this.oApi._fnAddData=_fnAddData;this.oApi._fnGatherData=_fnGatherData;this.oApi._fnDrawHead=_fnDrawHead;
 638.514 +this.oApi._fnDraw=_fnDraw;this.oApi._fnAjaxUpdate=_fnAjaxUpdate;this.oApi._fnAddOptionsHtml=_fnAddOptionsHtml;
 638.515 +this.oApi._fnFeatureHtmlFilter=_fnFeatureHtmlFilter;this.oApi._fnFeatureHtmlInfo=_fnFeatureHtmlInfo;
 638.516 +this.oApi._fnFeatureHtmlPaginate=_fnFeatureHtmlPaginate;this.oApi._fnPageChange=_fnPageChange;
 638.517 +this.oApi._fnFeatureHtmlLength=_fnFeatureHtmlLength;this.oApi._fnFeatureHtmlProcessing=_fnFeatureHtmlProcessing;
 638.518 +this.oApi._fnProcessingDisplay=_fnProcessingDisplay;this.oApi._fnFilterComplete=_fnFilterComplete;
 638.519 +this.oApi._fnFilterColumn=_fnFilterColumn;this.oApi._fnFilter=_fnFilter;this.oApi._fnSortingClasses=_fnSortingClasses;
 638.520 +this.oApi._fnVisibleToColumnIndex=_fnVisibleToColumnIndex;this.oApi._fnColumnIndexToVisible=_fnColumnIndexToVisible;
 638.521 +this.oApi._fnNodeToDataIndex=_fnNodeToDataIndex;this.oApi._fnVisbleColumns=_fnVisbleColumns;
 638.522 +this.oApi._fnBuildSearchArray=_fnBuildSearchArray;this.oApi._fnDataToSearch=_fnDataToSearch;
 638.523 +this.oApi._fnCalculateEnd=_fnCalculateEnd;this.oApi._fnConvertToWidth=_fnConvertToWidth;
 638.524 +this.oApi._fnCalculateColumnWidths=_fnCalculateColumnWidths;this.oApi._fnArrayCmp=_fnArrayCmp;
 638.525 +this.oApi._fnDetectType=_fnDetectType;this.oApi._fnGetDataMaster=_fnGetDataMaster;
 638.526 +this.oApi._fnGetTrNodes=_fnGetTrNodes;this.oApi._fnEscapeRegex=_fnEscapeRegex;this.oApi._fnReOrderIndex=_fnReOrderIndex;
 638.527 +this.oApi._fnColumnOrdering=_fnColumnOrdering;this.oApi._fnClearTable=_fnClearTable;
 638.528 +this.oApi._fnSaveState=_fnSaveState;this.oApi._fnLoadState=_fnLoadState;this.oApi._fnCreateCookie=_fnCreateCookie;
 638.529 +this.oApi._fnReadCookie=_fnReadCookie;this.oApi._fnGetUniqueThs=_fnGetUniqueThs;this.oApi._fnReDraw=_fnReDraw;
 638.530 +var _that=this;return this.each(function(){var i=0,iLen,j,jLen;for(i=0,iLen=_aoSettings.length;
 638.531 +i<iLen;i++){if(_aoSettings[i].nTable==this){alert("DataTables warning: Unable to re-initialise DataTable. Please use the API to make any configuration changes required.");
 638.532 +return _aoSettings[i]}}var oSettings=new classSettings();_aoSettings.push(oSettings);
 638.533 +var bInitHandedOff=false;var bUsePassedData=false;var sId=this.getAttribute("id");
 638.534 +if(sId!==null){oSettings.sTableId=sId;oSettings.sInstance=sId}else{oSettings.sInstance=_oExt._oExternConfig.iNextUnique++
 638.535 +}oSettings.nTable=this;oSettings.oApi=_that.oApi;if(typeof oInit!="undefined"&&oInit!==null){_fnMap(oSettings.oFeatures,oInit,"bPaginate");
 638.536 +_fnMap(oSettings.oFeatures,oInit,"bLengthChange");_fnMap(oSettings.oFeatures,oInit,"bFilter");
 638.537 +_fnMap(oSettings.oFeatures,oInit,"bSort");_fnMap(oSettings.oFeatures,oInit,"bInfo");
 638.538 +_fnMap(oSettings.oFeatures,oInit,"bProcessing");_fnMap(oSettings.oFeatures,oInit,"bAutoWidth");
 638.539 +_fnMap(oSettings.oFeatures,oInit,"bSortClasses");_fnMap(oSettings.oFeatures,oInit,"bServerSide");
 638.540 +_fnMap(oSettings,oInit,"asStripClasses");_fnMap(oSettings,oInit,"fnRowCallback");
 638.541 +_fnMap(oSettings,oInit,"fnHeaderCallback");_fnMap(oSettings,oInit,"fnFooterCallback");
 638.542 +_fnMap(oSettings,oInit,"fnInitComplete");_fnMap(oSettings,oInit,"fnServerData");_fnMap(oSettings,oInit,"aaSorting");
 638.543 +_fnMap(oSettings,oInit,"aaSortingFixed");_fnMap(oSettings,oInit,"sPaginationType");
 638.544 +_fnMap(oSettings,oInit,"sAjaxSource");_fnMap(oSettings,oInit,"iCookieDuration");_fnMap(oSettings,oInit,"sDom");
 638.545 +_fnMap(oSettings,oInit,"oSearch","oPreviousSearch");_fnMap(oSettings,oInit,"aoSearchCols","aoPreSearchCols");
 638.546 +_fnMap(oSettings,oInit,"iDisplayLength","_iDisplayLength");_fnMap(oSettings,oInit,"bJQueryUI","bJUI");
 638.547 +if(typeof oInit.fnDrawCallback=="function"){oSettings.aoDrawCallback.push({fn:oInit.fnDrawCallback,sName:"user"})
 638.548 +}if(oSettings.oFeatures.bServerSide&&oSettings.oFeatures.bSort&&oSettings.oFeatures.bSortClasses){oSettings.aoDrawCallback.push({fn:_fnSortingClasses,sName:"server_side_sort_classes"})
 638.549 +}if(typeof oInit.bJQueryUI!="undefined"&&oInit.bJQueryUI){oSettings.oClasses=_oExt.oJUIClasses;
 638.550 +if(typeof oInit.sDom=="undefined"){oSettings.sDom='<"H"lfr>t<"F"ip>'}}if(typeof oInit.iDisplayStart!="undefined"&&typeof oSettings.iInitDisplayStart=="undefined"){oSettings.iInitDisplayStart=oInit.iDisplayStart;
 638.551 +oSettings._iDisplayStart=oInit.iDisplayStart}if(typeof oInit.bStateSave!="undefined"){oSettings.oFeatures.bStateSave=oInit.bStateSave;
 638.552 +_fnLoadState(oSettings,oInit);oSettings.aoDrawCallback.push({fn:_fnSaveState,sName:"state_save"})
 638.553 +}if(typeof oInit.aaData!="undefined"){bUsePassedData=true}if(typeof oInit!="undefined"&&typeof oInit.aoData!="undefined"){oInit.aoColumns=oInit.aoData
 638.554 +}if(typeof oInit.oLanguage!="undefined"){if(typeof oInit.oLanguage.sUrl!="undefined"&&oInit.oLanguage.sUrl!==""){oSettings.oLanguage.sUrl=oInit.oLanguage.sUrl;
 638.555 +$.getJSON(oSettings.oLanguage.sUrl,null,function(json){_fnLanguageProcess(oSettings,json,true)
 638.556 +});bInitHandedOff=true}else{_fnLanguageProcess(oSettings,oInit.oLanguage,false)}}}else{oInit={}
 638.557 +}if(typeof oInit.asStripClasses=="undefined"){oSettings.asStripClasses.push(oSettings.oClasses.sStripOdd);
 638.558 +oSettings.asStripClasses.push(oSettings.oClasses.sStripEven)}var nThead=this.getElementsByTagName("thead");
 638.559 +var nThs=nThead.length===0?null:_fnGetUniqueThs(nThead[0]);var bUseCols=typeof oInit.aoColumns!="undefined";
 638.560 +for(i=0,iLen=bUseCols?oInit.aoColumns.length:nThs.length;i<iLen;i++){var oCol=bUseCols?oInit.aoColumns[i]:null;
 638.561 +var nTh=nThs?nThs[i]:null;if(typeof oInit.saved_aoColumns!="undefined"&&oInit.saved_aoColumns.length==iLen){if(oCol===null){oCol={}
 638.562 +}oCol.bVisible=oInit.saved_aoColumns[i].bVisible}_fnAddColumn(oSettings,oCol,nTh)
 638.563 +}for(i=0,iLen=oSettings.aaSorting.length;i<iLen;i++){if(typeof oSettings.aaSorting[i][2]=="undefined"){oSettings.aaSorting[i][2]=0
 638.564 +}var oColumn=oSettings.aoColumns[oSettings.aaSorting[i][0]];for(j=0,jLen=oColumn.asSorting.length;
 638.565 +j<jLen;j++){if(oSettings.aaSorting[i][1]==oColumn.asSorting[j]){oSettings.aaSorting[i][2]=j;
 638.566 +break}}}if(this.getElementsByTagName("thead").length===0){this.appendChild(document.createElement("thead"))
 638.567 +}if(this.getElementsByTagName("tbody").length===0){this.appendChild(document.createElement("tbody"))
 638.568 +}if(bUsePassedData){for(i=0;i<oInit.aaData.length;i++){_fnAddData(oSettings,oInit.aaData[i])
 638.569 +}}else{_fnGatherData(oSettings)}oSettings.aiDisplay=oSettings.aiDisplayMaster.slice();
 638.570 +if(oSettings.oFeatures.bAutoWidth){_fnCalculateColumnWidths(oSettings)}oSettings.bInitialised=true;
 638.571 +if(bInitHandedOff===false){_fnInitalise(oSettings)}})}})(jQuery);
 638.572 \ No newline at end of file
   639.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   639.2 +++ b/web/static/js/jquery.min.js	Mon Apr 26 11:16:23 2010 +0200
   639.3 @@ -0,0 +1,151 @@
   639.4 +/*!
   639.5 + * jQuery JavaScript Library v1.4
   639.6 + * http://jquery.com/
   639.7 + *
   639.8 + * Copyright 2010, John Resig
   639.9 + * Dual licensed under the MIT or GPL Version 2 licenses.
  639.10 + * http://docs.jquery.com/License
  639.11 + *
  639.12 + * Includes Sizzle.js
  639.13 + * http://sizzlejs.com/
  639.14 + * Copyright 2010, The Dojo Foundation
  639.15 + * Released under the MIT, BSD, and GPL Licenses.
  639.16 + *
  639.17 + * Date: Wed Jan 13 15:23:05 2010 -0500
  639.18 + */
  639.19 +(function(A,w){function oa(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(oa,1);return}c.ready()}}function La(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function $(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var o in b)$(a,o,b[o],f,e,d);return a}if(d!==w){f=!i&&f&&c.isFunction(d);for(o=0;o<j;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,i);return a}return j?
  639.20 +e(a[0],b):null}function K(){return(new Date).getTime()}function aa(){return false}function ba(){return true}function pa(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function qa(a){var b=true,d=[],f=[],e=arguments,i,j,o,p,n,t=c.extend({},c.data(this,"events").live);for(p in t){j=t[p];if(j.live===a.type||j.altLive&&c.inArray(a.type,j.altLive)>-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete t[p]}i=c(a.target).closest(f,a.currentTarget);
  639.21 +n=0;for(l=i.length;n<l;n++)for(p in t){j=t[p];o=i[n].elem;f=null;if(i[n].selector===j.selector){if(j.live==="mouseenter"||j.live==="mouseleave")f=c(a.relatedTarget).closest(j.selector)[0];if(!f||f!==o)d.push({elem:o,fn:j})}}n=0;for(l=d.length;n<l;n++){i=d[n];a.currentTarget=i.elem;a.data=i.fn.data;if(i.fn.apply(i.elem,e)===false){b=false;break}}return b}function ra(a,b){return["live",a,b.replace(/\./g,"`").replace(/ /g,"&")].join(".")}function sa(a){return!a||!a.parentNode||a.parentNode.nodeType===
  639.22 +11}function ta(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var i in f)for(var j in f[i])c.event.add(this,i,f[i][j],f[i][j].data)}}})}function ua(a,b,d){var f,e,i;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&a[0].indexOf("<option")<0){e=true;if(i=c.fragments[a[0]])if(i!==1)f=i}if(!f){b=b&&b[0]?b[0].ownerDocument||b[0]:s;f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=
  639.23 +i?f:1;return{fragment:f,cacheable:e}}function T(a){for(var b=0,d,f;(d=a[b])!=null;b++)if(!c.noData[d.nodeName.toLowerCase()]&&(f=d[H]))delete c.cache[f]}function L(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ma=A.jQuery,Na=A.$,s=A.document,U,Oa=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Pa=/^.[^:#\[\.,]*$/,Qa=/\S/,
  639.24 +Ra=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Sa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],M,ca=Object.prototype.toString,da=Object.prototype.hasOwnProperty,ea=Array.prototype.push,R=Array.prototype.slice,V=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Oa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Sa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];
  639.25 +c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ua([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return U.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a)}else return!b||b.jquery?(b||U).find(a):c(b).find(a);else if(c.isFunction(a))return U.ready(a);if(a.selector!==w){this.selector=a.selector;
  639.26 +this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,this)},selector:"",jquery:"1.4",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length=
  639.27 +0;ea.apply(this,a);return this},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||
  639.28 +c(null)},push:ea,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(i in e){j=a[i];o=e[i];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){j=j&&(c.isPlainObject(j)||c.isArray(j))?j:c.isArray(o)?[]:{};a[i]=c.extend(f,j,o)}else if(o!==w)a[i]=
  639.29 +o}return a};c.extend({noConflict:function(a){A.$=Na;if(a)A.jQuery=Ma;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",M,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",
  639.30 +M);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&oa()}}},isFunction:function(a){return ca.call(a)==="[object Function]"},isArray:function(a){return ca.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||ca.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!da.call(a,"constructor")&&!da.call(a.constructor.prototype,"isPrototypeOf"))return false;var b;for(b in a);return b===w||da.call(a,b)},
  639.31 +isEmptyObject:function(a){for(var b in a)return false;return true},noop:function(){},globalEval:function(a){if(a&&Qa.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,i=a.length,j=i===w||c.isFunction(a);
  639.32 +if(d)if(j)for(f in a){if(b.apply(a[f],d)===false)break}else for(;e<i;){if(b.apply(a[e++],d)===false)break}else if(j)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<i&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Ra,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ea.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=
  639.33 +0,f=b.length;d<f;d++)if(b[d]===a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,i=a.length;e<i;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,i=0,j=a.length;i<j;i++){e=b(a[i],i,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b===
  639.34 +"string"){d=a;a=d[b];b=w}else if(b&&!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){var b={browser:""};a=a.toLowerCase();if(/webkit/.test(a))b={browser:"webkit",version:/webkit[\/ ]([\w.]+)/};else if(/opera/.test(a))b={browser:"opera",version:/version/.test(a)?/version[\/ ]([\w.]+)/:/opera[\/ ]([\w.]+)/};else if(/msie/.test(a))b={browser:"msie",version:/msie ([\w.]+)/};else if(/mozilla/.test(a)&&
  639.35 +!/compatible/.test(a))b={browser:"mozilla",version:/rv:([\w.]+)/};b.version=(b.version&&b.version.exec(a)||[0,"0"])[1];return b},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=true;if(V)c.inArray=function(a,b){return V.call(b,a)};U=c(s);if(s.addEventListener)M=function(){s.removeEventListener("DOMContentLoaded",M,false);c.ready()};else if(s.attachEvent)M=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",
  639.36 +M);c.ready()}};if(V)c.inArray=function(a,b){return V.call(b,a)};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+K();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,
  639.37 +htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b,
  639.38 +a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function o(){c.support.noCloneEvent=false;d.detachEvent("onclick",o)});d.cloneNode(true).fireEvent("onclick")}c(function(){var o=s.createElement("div");o.style.width=o.style.paddingLeft="1px";s.body.appendChild(o);c.boxModel=c.support.boxModel=o.offsetWidth===2;s.body.removeChild(o).style.display="none"});a=function(o){var p=s.createElement("div");o="on"+o;var n=o in
  639.39 +p;if(!n){p.setAttribute(o,"return;");n=typeof p[o]==="function"}return n};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var H="jQuery"+K(),Ta=0,ya={},Ua={};c.extend({cache:{},expando:H,noData:{embed:true,object:true,applet:true},data:function(a,
  639.40 +b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var f=a[H],e=c.cache;if(!b&&!f)return null;f||(f=++Ta);if(typeof b==="object"){a[H]=f;e=e[f]=c.extend(true,{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Ua:(e[f]={});if(d!==w){a[H]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?ya:a;var d=a[H],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[H]}catch(i){a.removeAttribute&&
  639.41 +a.removeAttribute(H)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,
  639.42 +a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,
  639.43 +a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var za=/[\n\t]/g,fa=/\s+/,Va=/\r/g,Wa=/href|src|style/,Xa=/(button|input)/i,Ya=/(button|input|object|select|textarea)/i,Za=/^(a|area)$/i,Aa=/radio|checkbox/;c.fn.extend({attr:function(a,
  639.44 +b){return $(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(p){var n=c(this);n.addClass(a.call(this,p,n.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(fa),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className)for(var i=" "+e.className+" ",j=0,o=b.length;j<o;j++){if(i.indexOf(" "+b[j]+" ")<0)e.className+=
  639.45 +" "+b[j]}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(p){var n=c(this);n.removeClass(a.call(this,p,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(fa),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var i=(" "+e.className+" ").replace(za," "),j=0,o=b.length;j<o;j++)i=i.replace(" "+b[j]+" "," ");e.className=i.substring(1,i.length-1)}else e.className=""}return this},toggleClass:function(a,
  639.46 +b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var i=c(this);i.toggleClass(a.call(this,e,i.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,i=0,j=c(this),o=b,p=a.split(fa);e=p[i++];){o=f?o:!j.hasClass(e);j[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=
  639.47 +" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(za," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i<d;i++){var j=e[i];if(j.selected){a=c(j).val();if(b)return a;f.push(a)}}return f}if(Aa.test(b.type)&&
  639.48 +!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Va,"")}return w}var o=c.isFunction(a);return this.each(function(p){var n=c(this),t=a;if(this.nodeType===1){if(o)t=a.call(this,p,n.val());if(typeof t==="number")t+="";if(c.isArray(t)&&Aa.test(this.type))this.checked=c.inArray(n.val(),t)>=0;else if(c.nodeName(this,"select")){var z=c.makeArray(t);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),z)>=0});if(!z.length)this.selectedIndex=
  639.49 +-1}else this.value=t}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Wa.test(b);if(b in a&&f&&!i){if(e){if(b==="type"&&Xa.test(a.nodeName)&&a.parentNode)throw"type property can't be changed";a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;
  639.50 +if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Ya.test(a.nodeName)||Za.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var $a=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===
  639.51 +3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;if(!d.guid)d.guid=c.guid++;if(f!==w){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):w};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var o,p=0;o=b[p++];){var n=o.split(".");o=n.shift();d.type=n.slice(0).sort().join(".");var t=e[o],z=this.special[o]||{};if(!t){t=e[o]={};
  639.52 +if(!z.setup||z.setup.call(a,f,n,d)===false)if(a.addEventListener)a.addEventListener(o,i,false);else a.attachEvent&&a.attachEvent("on"+o,i)}if(z.add)if((n=z.add.call(a,d,f,n,t))&&c.isFunction(n)){n.guid=n.guid||d.guid;d=n}t[d.guid]=d;this.global[o]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===w||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/);
  639.53 +for(var o=0;i=b[o++];){var p=i.split(".");i=p.shift();var n=!p.length,t=c.map(p.slice(0).sort(),$a);t=new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.)?")+"(\\.|$)");var z=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var B in f[i])if(n||t.test(f[i][B].type))delete f[i][B];z.remove&&z.remove.call(a,p,j);for(e in f[i])break;if(!e){if(!z.teardown||z.teardown.call(a,p)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+
  639.54 +i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(B=c.data(a,"handle"))B.elem=null;c.removeData(a,"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[H]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===
  639.55 +8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;var i=c.data(d,"handle");i&&i.apply(d,b);var j,o;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){j=d[e];o=d["on"+e]}}catch(p){}i=c.nodeName(d,"a")&&e==="click";if(!f&&j&&!a.isDefaultPrevented()&&!i){this.triggered=true;try{d[e]()}catch(n){}}else if(o&&d["on"+e].apply(d,b)===false)a.result=false;this.triggered=false;if(!a.isPropagationStopped())(d=d.parentNode||d.ownerDocument)&&c.event.trigger(a,b,d,true)},
  639.56 +handle:function(a){var b,d;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result},
  639.57 +props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[H])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||
  639.58 +s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&
  639.59 +a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;c.event.add(this,b.live,qa,b)},remove:function(a){if(a.length){var b=0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],qa)}},special:{}},beforeunload:{setup:function(a,
  639.60 +b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=K();this[H]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=ba;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=
  639.61 +ba;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=ba;this.stopPropagation()},isDefaultPrevented:aa,isPropagationStopped:aa,isImmediatePropagationStopped:aa};var Ba=function(a){for(var b=a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ca=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",
  639.62 +mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ca:Ba,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ca:Ba)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return pa("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+
  639.63 +d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return pa("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var ga=/textarea|input|select/i;function Da(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>
  639.64 +-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ha(a,b){var d=a.target,f,e;if(!(!ga.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Da(d);if(e!==f){if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",e);if(d.type!=="select"&&(f!=null||e)){a.type="change";return c.event.trigger(a,b,this)}}}}c.event.special.change={filters:{focusout:ha,click:function(a){var b=a.target,d=b.type;if(d===
  639.65 +"radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ha.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ha.call(this,a)},beforeactivate:function(a){a=a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Da(a))}},setup:function(a,b,d){for(var f in W)c.event.add(this,f+".specialChange."+d.guid,W[f]);return ga.test(this.nodeName)},
  639.66 +remove:function(a,b){for(var d in W)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),W[d]);return ga.test(this.nodeName)}};var W=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,
  639.67 +f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){thisObject=e;e=f;f=w}var j=b==="one"?c.proxy(e,function(o){c(this).unbind(o,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e,thisObject):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a,
  639.68 +b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||
  639.69 +a)},live:function(a,b,d){if(c.isFunction(b)){d=b;b=w}c(this.context).bind(ra(a,this.selector),{data:b,selector:this.selector,live:a},d);return this},die:function(a,b){c(this.context).unbind(ra(a,this.selector),b?{guid:b.guid+this.selector+a}:null);return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d){return d?
  639.70 +this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",k,m=0;g[m];m++){k=g[m];if(k.nodeType===3||k.nodeType===4)h+=k.nodeValue;else if(k.nodeType!==8)h+=a(k.childNodes)}return h}function b(g,h,k,m,r,q){r=0;for(var v=m.length;r<v;r++){var u=m[r];if(u){u=u[g];for(var y=false;u;){if(u.sizcache===
  639.71 +k){y=m[u.sizset];break}if(u.nodeType===1&&!q){u.sizcache=k;u.sizset=r}if(u.nodeName.toLowerCase()===h){y=u;break}u=u[g]}m[r]=y}}}function d(g,h,k,m,r,q){r=0;for(var v=m.length;r<v;r++){var u=m[r];if(u){u=u[g];for(var y=false;u;){if(u.sizcache===k){y=m[u.sizset];break}if(u.nodeType===1){if(!q){u.sizcache=k;u.sizset=r}if(typeof h!=="string"){if(u===h){y=true;break}}else if(p.filter(h,[u]).length>0){y=u;break}}u=u[g]}m[r]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
  639.72 +e=0,i=Object.prototype.toString,j=false,o=true;[0,0].sort(function(){o=false;return 0});var p=function(g,h,k,m){k=k||[];var r=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return k;for(var q=[],v,u,y,S,I=true,N=x(h),J=g;(f.exec(""),v=f.exec(J))!==null;){J=v[3];q.push(v[1]);if(v[2]){S=v[3];break}}if(q.length>1&&t.exec(g))if(q.length===2&&n.relative[q[0]])u=ia(q[0]+q[1],h);else for(u=n.relative[q[0]]?[h]:p(q.shift(),h);q.length;){g=q.shift();if(n.relative[g])g+=q.shift();
  639.73 +u=ia(g,u)}else{if(!m&&q.length>1&&h.nodeType===9&&!N&&n.match.ID.test(q[0])&&!n.match.ID.test(q[q.length-1])){v=p.find(q.shift(),h,N);h=v.expr?p.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:q.pop(),set:B(m)}:p.find(q.pop(),q.length===1&&(q[0]==="~"||q[0]==="+")&&h.parentNode?h.parentNode:h,N);u=v.expr?p.filter(v.expr,v.set):v.set;if(q.length>0)y=B(u);else I=false;for(;q.length;){var E=q.pop();v=E;if(n.relative[E])v=q.pop();else E="";if(v==null)v=h;n.relative[E](y,v,N)}}else y=[]}y||(y=u);if(!y)throw"Syntax error, unrecognized expression: "+
  639.74 +(E||g);if(i.call(y)==="[object Array]")if(I)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&F(h,y[g])))k.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&k.push(u[g]);else k.push.apply(k,y);else B(y,k);if(S){p(S,r,k,m);p.uniqueSort(k)}return k};p.uniqueSort=function(g){if(D){j=o;g.sort(D);if(j)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};p.matches=function(g,h){return p(g,null,null,h)};p.find=function(g,h,k){var m,r;if(!g)return[];
  639.75 +for(var q=0,v=n.order.length;q<v;q++){var u=n.order[q];if(r=n.leftMatch[u].exec(g)){var y=r[1];r.splice(1,1);if(y.substr(y.length-1)!=="\\"){r[1]=(r[1]||"").replace(/\\/g,"");m=n.find[u](r,h,k);if(m!=null){g=g.replace(n.match[u],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};p.filter=function(g,h,k,m){for(var r=g,q=[],v=h,u,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var I in n.filter)if((u=n.leftMatch[I].exec(g))!=null&&u[2]){var N=n.filter[I],J,E;E=u[1];y=false;u.splice(1,1);if(E.substr(E.length-
  639.76 +1)!=="\\"){if(v===q)q=[];if(n.preFilter[I])if(u=n.preFilter[I](u,v,k,q,m,S)){if(u===true)continue}else y=J=true;if(u)for(var X=0;(E=v[X])!=null;X++)if(E){J=N(E,u,X,v);var Ea=m^!!J;if(k&&J!=null)if(Ea)y=true;else v[X]=false;else if(Ea){q.push(E);y=true}}if(J!==w){k||(v=q);g=g.replace(n.match[I],"");if(!y)return[];break}}}if(g===r)if(y==null)throw"Syntax error, unrecognized expression: "+g;else break;r=g}return v};var n=p.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
  639.77 +CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
  639.78 +relative:{"+":function(g,h){var k=typeof h==="string",m=k&&!/\W/.test(h);k=k&&!m;if(m)h=h.toLowerCase();m=0;for(var r=g.length,q;m<r;m++)if(q=g[m]){for(;(q=q.previousSibling)&&q.nodeType!==1;);g[m]=k||q&&q.nodeName.toLowerCase()===h?q||false:q===h}k&&p.filter(h,g,true)},">":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,r=g.length;m<r;m++){var q=g[m];if(q){k=q.parentNode;g[m]=k.nodeName.toLowerCase()===h?k:false}}}else{m=0;for(r=g.length;m<r;m++)if(q=g[m])g[m]=
  639.79 +k?q.parentNode:q.parentNode===h;k&&p.filter(h,g,true)}},"":function(g,h,k){var m=e++,r=d;if(typeof h==="string"&&!/\W/.test(h)){var q=h=h.toLowerCase();r=b}r("parentNode",h,m,g,q,k)},"~":function(g,h,k){var m=e++,r=d;if(typeof h==="string"&&!/\W/.test(h)){var q=h=h.toLowerCase();r=b}r("previousSibling",h,m,g,q,k)}},find:{ID:function(g,h,k){if(typeof h.getElementById!=="undefined"&&!k)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var k=[];
  639.80 +h=h.getElementsByName(g[1]);for(var m=0,r=h.length;m<r;m++)h[m].getAttribute("name")===g[1]&&k.push(h[m]);return k.length===0?null:k}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,k,m,r,q){g=" "+g[1].replace(/\\/g,"")+" ";if(q)return g;q=0;for(var v;(v=h[q])!=null;q++)if(v)if(r^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))k||m.push(v);else if(k)h[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
  639.81 +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,m,r,q){h=g[1].replace(/\\/g,"");if(!q&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,m,r){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=p(g[3],null,null,h);else{g=p.filter(g[3],h,k,true^r);k||m.push.apply(m,
  639.82 +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!p(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
  639.83 +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
  639.84 +setFilters:{first:function(g,h){return h===0},last:function(g,h,k,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return h<k[3]-0},gt:function(g,h,k){return h>k[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,m){var r=h[1],q=n.filters[r];if(q)return q(g,k,h,m);else if(r==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(r==="not"){h=
  639.85 +h[3];k=0;for(m=h.length;k<m;k++)if(h[k]===g)return false;return true}else throw"Syntax error, unrecognized expression: "+r;},CHILD:function(g,h){var k=h[1],m=g;switch(k){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(k==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":k=h[2];var r=h[3];if(k===1&&r===0)return true;h=h[0];var q=g.parentNode;if(q&&(q.sizcache!==h||!g.nodeIndex)){var v=0;for(m=q.firstChild;m;m=
  639.86 +m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;q.sizcache=h}g=g.nodeIndex-r;return k===0?g===0:g%k===0&&g/k>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=n.attrHandle[k]?n.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
  639.87 +"="?k===h:m==="*="?k.indexOf(h)>=0:m==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:m==="!="?k!==h:m==="^="?k.indexOf(h)===0:m==="$="?k.substr(k.length-h.length)===h:m==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,m){var r=n.setFilters[h[2]];if(r)return r(g,k,h,m)}}},t=n.match.POS;for(var z in n.match){n.match[z]=new RegExp(n.match[z].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[z]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[z].source.replace(/\\(\d+)/g,function(g,
  639.88 +h){return"\\"+(h-0+1)}))}var B=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){B=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,m=g.length;k<m;k++)h.push(g[k]);else for(k=0;g[k];k++)h.push(g[k]);return h}}var D;if(s.documentElement.compareDocumentPosition)D=function(g,h){if(!g.compareDocumentPosition||
  639.89 +!h.compareDocumentPosition){if(g==h)j=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)j=true;return g};else if("sourceIndex"in s.documentElement)D=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)j=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)j=true;return g};else if(s.createRange)D=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)j=true;return g.ownerDocument?-1:1}var k=g.ownerDocument.createRange(),m=
  639.90 +h.ownerDocument.createRange();k.setStart(g,0);k.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=k.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)j=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var k=s.documentElement;k.insertBefore(g,k.firstChild);if(s.getElementById(h)){n.find.ID=function(m,r,q){if(typeof r.getElementById!=="undefined"&&!q)return(r=r.getElementById(m[1]))?r.id===m[1]||typeof r.getAttributeNode!=="undefined"&&
  639.91 +r.getAttributeNode("id").nodeValue===m[1]?[r]:w:[]};n.filter.ID=function(m,r){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===r}}k.removeChild(g);k=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;k[m];m++)k[m].nodeType===1&&h.push(k[m]);k=h}return k};g.innerHTML="<a href='#'></a>";
  639.92 +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=p,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){p=function(m,r,q,v){r=r||s;if(!v&&r.nodeType===9&&!x(r))try{return B(r.querySelectorAll(m),q)}catch(u){}return g(m,r,q,v)};for(var k in g)p[k]=g[k];h=null}}();
  639.93 +(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,k,m){if(typeof k.getElementsByClassName!=="undefined"&&!m)return k.getElementsByClassName(h[1])};g=null}}})();var F=s.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g,
  639.94 +h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ia=function(g,h){var k=[],m="",r;for(h=h.nodeType?[h]:h;r=n.match.PSEUDO.exec(g);){m+=r[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;r=0;for(var q=h.length;r<q;r++)p(g,h[r],k);return p.filter(m,k)};c.find=p;c.expr=p.selectors;c.expr[":"]=c.expr.filters;c.unique=p.uniqueSort;c.getText=a;c.isXMLDoc=x;c.contains=F})();var ab=/Until$/,bb=/^(?:parents|prevUntil|prevAll)/,
  639.95 +cb=/,/;R=Array.prototype.slice;var Fa=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,i){return!!b.call(e,i,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Pa.test(b))return c.filter(b,f,!d);else b=c.filter(b,a)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
  639.96 +c.find(a,this[f],b);if(f>0)for(var i=d;i<b.length;i++)for(var j=0;j<d;j++)if(b[j]===b[i]){b.splice(i--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Fa(this,a,false),"not",a)},filter:function(a){return this.pushStack(Fa(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i=
  639.97 +{},j;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){j=a[e];i[j]||(i[j]=c.expr.match.POS.test(j)?c(j,b||this.context):j)}for(;f&&f.ownerDocument&&f!==b;){for(j in i){e=i[j];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var p=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,t){for(;t&&t.ownerDocument&&t!==b;){if(p?p.index(t)>-1:c(t).is(a))return t;t=t.parentNode}return null})},index:function(a){if(!a||typeof a===
  639.98 +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(sa(a[0])||sa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
  639.99 +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
 639.100 +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);ab.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||cb.test(f))&&bb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||!c(a).is(d));){a.nodeType===
 639.101 +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ga=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,db=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/<tbody/i,gb=/<|&\w+;/,hb=function(a,b,d){return eb.test(d)?a:b+"></"+d+">"},G={option:[1,"<select multiple='multiple'>","</select>"],
 639.102 +legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};G.optgroup=G.option;G.tbody=G.tfoot=G.colgroup=G.caption=G.thead;G.th=G.td;if(!c.support.htmlSerialize)G._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);
 639.103 +return d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.getText(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
 639.104 +wrapInner:function(a){return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&
 639.105 +this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,
 639.106 +"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ga,"").replace(Y,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ta(this,b);ta(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===
 639.107 +1?this[0].innerHTML.replace(Ga,""):null;else if(typeof a==="string"&&!/<script/i.test(a)&&(c.support.leadingWhitespace||!Y.test(a))&&!G[(Ha.exec(a)||["",""])[1].toLowerCase()])try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){T(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}else c.isFunction(a)?this.each(function(e){var i=c(this),j=i.html();i.empty().append(function(){return a.call(this,e,j)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
 639.108 +this[0].parentNode){c.isFunction(a)||(a=c(a).detach());return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(t){return c.nodeName(t,"table")?t.getElementsByTagName("tbody")[0]||t.appendChild(t.ownerDocument.createElement("tbody")):t}var e,i,j=a[0],o=[];if(c.isFunction(j))return this.each(function(t){var z=
 639.109 +c(this);a[0]=j.call(this,t,b?z.html():w);return z.domManip(a,b,d)});if(this[0]){e=a[0]&&a[0].parentNode&&a[0].parentNode.nodeType===11?{fragment:a[0].parentNode}:ua(a,this,o);if(i=e.fragment.firstChild){b=b&&c.nodeName(i,"tr");for(var p=0,n=this.length;p<n;p++)d.call(b?f(this[p],i):this[p],e.cacheable||this.length>1||p>0?e.fragment.cloneNode(true):e.fragment)}o&&c.each(o,La)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},
 639.110 +function(a,b){c.fn[a]=function(d){var f=[];d=c(d);for(var e=0,i=d.length;e<i;e++){var j=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),j);f=f.concat(j)}return this.pushStack(f,a,d.selector)}});c.each({remove:function(a,b){if(!a||c.filter(a,[this]).length){if(!b&&this.nodeType===1){T(this.getElementsByTagName("*"));T([this])}this.parentNode&&this.parentNode.removeChild(this)}},empty:function(){for(this.nodeType===1&&T(this.getElementsByTagName("*"));this.firstChild;)this.removeChild(this.firstChild)}},
 639.111 +function(a,b){c.fn[a]=function(){return this.each(b,arguments)}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;var e=[];c.each(a,function(i,j){if(typeof j==="number")j+="";if(j){if(typeof j==="string"&&!gb.test(j))j=b.createTextNode(j);else if(typeof j==="string"){j=j.replace(db,hb);var o=(Ha.exec(j)||["",""])[1].toLowerCase(),p=G[o]||G._default,n=p[0];i=b.createElement("div");for(i.innerHTML=p[1]+j+p[2];n--;)i=i.lastChild;
 639.112 +if(!c.support.tbody){n=fb.test(j);o=o==="table"&&!n?i.firstChild&&i.firstChild.childNodes:p[1]==="<table>"&&!n?i.childNodes:[];for(p=o.length-1;p>=0;--p)c.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!c.support.leadingWhitespace&&Y.test(j)&&i.insertBefore(b.createTextNode(Y.exec(j)[0]),i.firstChild);j=c.makeArray(i.childNodes)}if(j.nodeType)e.push(j);else e=c.merge(e,j)}});if(d)for(a=0;e[a];a++)if(f&&c.nodeName(e[a],"script")&&(!e[a].type||e[a].type.toLowerCase()===
 639.113 +"text/javascript"))f.push(e[a].parentNode?e[a].parentNode.removeChild(e[a]):e[a]);else{e[a].nodeType===1&&e.splice.apply(e,[a+1,0].concat(c.makeArray(e[a].getElementsByTagName("script"))));d.appendChild(e[a])}return e}});var ib=/z-?index|font-?weight|opacity|zoom|line-?height/i,Ia=/alpha\([^)]*\)/,Ja=/opacity=([^)]*)/,ja=/float/i,ka=/-([a-z])/ig,jb=/([A-Z])/g,kb=/^-?\d+(?:px)?$/i,lb=/^-?\d/,mb={position:"absolute",visibility:"hidden",display:"block"},nb=["Left","Right"],ob=["Top","Bottom"],pb=s.defaultView&&
 639.114 +s.defaultView.getComputedStyle,Ka=c.support.cssFloat?"cssFloat":"styleFloat",la=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return $(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!ib.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""===
 639.115 +"NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=Ia.test(a)?a.replace(Ia,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Ja.exec(f.filter)[1])/100+"":""}if(ja.test(b))b=Ka;b=b.replace(ka,la);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,i=b==="width"?nb:ob;function j(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(i,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=
 639.116 +parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,"border"+this+"Width",true))||0})}a.offsetWidth!==0?j():c.swap(a,mb,j);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Ja.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ja.test(b))b=Ka;if(!d&&e&&e[b])f=e[b];else if(pb){if(ja.test(b))b="float";b=b.replace(jb,"-$1").toLowerCase();e=
 639.117 +a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ka,la);f=a.currentStyle[b]||a.currentStyle[d];if(!kb.test(f)&&lb.test(f)){b=e.left;var i=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=i}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=
 639.118 +f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var qb=K(),rb=/<script(.|\s)*?\/script>/gi,sb=/select|textarea/i,tb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,O=/=\?(&|$)/,ma=/\?/,ub=/(\?|&)_=.*?(&|$)/,vb=/^(\w+:)?\/\/([^\/?#]+)/,
 639.119 +wb=/%20/g;c.fn.extend({_load:c.fn.load,load:function(a,b,d){if(typeof a!=="string")return this._load(a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}c.ajax({url:a,type:f,dataType:"html",data:b,context:this,complete:function(i,j){if(j==="success"||j==="notmodified")this.html(e?c("<div />").append(i.responseText.replace(rb,
 639.120 +"")).find(e):i.responseText);d&&this.each(d,[i.responseText,j,i])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||sb.test(this.nodeName)||tb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});
 639.121 +c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},
 639.122 +ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",
 639.123 +text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&e.success.call(p,o,j,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(p,x,j);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(r,q){(e.context?c(e.context):c.event).trigger(r,q)}var e=c.extend(true,{},c.ajaxSettings,a),i,j,o,p=e.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,
 639.124 +e.traditional);if(e.dataType==="jsonp"){if(n==="GET")O.test(e.url)||(e.url+=(ma.test(e.url)?"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!O.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&O.test(e.data)||O.test(e.url))){i=e.jsonpCallback||"jsonp"+qb++;if(e.data)e.data=(e.data+"").replace(O,"="+i+"$1");e.url=e.url.replace(O,"="+i+"$1");e.dataType="script";A[i]=A[i]||function(r){o=r;b();d();A[i]=w;try{delete A[i]}catch(q){}B&&
 639.125 +B.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===false&&n==="GET"){var t=K(),z=e.url.replace(ub,"$1_="+t+"$2");e.url=z+(z===e.url?(ma.test(e.url)?"&":"?")+"_="+t:"")}if(e.data&&n==="GET")e.url+=(ma.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");t=(t=vb.exec(e.url))&&(t[1]&&t[1]!==location.protocol||t[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&t){var B=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");
 639.126 +C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!i){var D=false;C.onload=C.onreadystatechange=function(){if(!D&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){D=true;b();d();C.onload=C.onreadystatechange=null;B&&C.parentNode&&B.removeChild(C)}}}B.insertBefore(C,B.firstChild);return w}var F=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",
 639.127 +e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}t||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ia){}if(e.beforeSend&&e.beforeSend.call(p,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",
 639.128 +[x,e]);var g=x.onreadystatechange=function(r){if(!x||x.readyState===0){F||d();F=true;if(x)x.onreadystatechange=c.noop}else if(!F&&x&&(x.readyState===4||r==="timeout")){F=true;x.onreadystatechange=c.noop;j=r==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";if(j==="success")try{o=c.httpData(x,e.dataType,e)}catch(q){j="parsererror"}if(j==="success"||j==="notmodified")i||b();else c.handleError(e,x,j);d();r==="timeout"&&x.abort();if(e.async)x=
 639.129 +null}};try{var h=x.abort;x.abort=function(){if(x){h.call(x);if(x)x.readyState=0}g()}}catch(k){}e.async&&e.timeout>0&&setTimeout(function(){x&&!F&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||A,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol===
 639.130 +"file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;if(e&&a.documentElement.nodeName==="parsererror")throw"parsererror";if(d&&
 639.131 +d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&f.indexOf("json")>=0)if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))a=A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+a))();else throw"Invalid JSON: "+a;else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(e,i){i=
 639.132 +c.isFunction(i)?i():i;f[f.length]=encodeURIComponent(e)+"="+encodeURIComponent(i)}var f=[];if(b===w)b=c.ajaxSettings.traditional;c.isArray(a)||a.jquery?c.each(a,function(){d(this.name,this.value)}):c.each(a,function e(i,j){if(c.isArray(j))c.each(j,function(o,p){b?d(i,p):e(i+"["+(typeof p==="object"||c.isArray(p)?o:"")+"]",p)});else!b&&j!=null&&typeof j==="object"?c.each(j,function(o,p){e(i+"["+o+"]",p)}):d(i,j)});return f.join("&").replace(wb,"+")}});var na={},xb=/toggle|show|hide/,yb=/^([+-]=)?([\d+-.]+)(.*)$/,
 639.133 +Z,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a!=null)return this.animate(L("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(na[d])f=na[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();
 639.134 +na[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a!=null)return this.animate(L("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&
 639.135 +c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(L("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var i=c.extend({},e),j,o=this.nodeType===1&&c(this).is(":hidden"),
 639.136 +p=this;for(j in a){var n=j.replace(ka,la);if(j!==n){a[n]=a[j];delete a[j];j=n}if(a[j]==="hide"&&o||a[j]==="show"&&!o)return i.complete.call(this);if((j==="height"||j==="width")&&this.style){i.display=c.css(this,"display");i.overflow=this.style.overflow}if(c.isArray(a[j])){(i.specialEasing=i.specialEasing||{})[j]=a[j][1];a[j]=a[j][0]}}if(i.overflow!=null)this.style.overflow="hidden";i.curAnim=c.extend({},a);c.each(a,function(t,z){var B=new c.fx(p,i,t);if(xb.test(z))B[z==="toggle"?o?"show":"hide":z](a);
 639.137 +else{var C=yb.exec(z),D=B.cur(true)||0;if(C){z=parseFloat(C[2]);var F=C[3]||"px";if(F!=="px"){p.style[t]=(z||1)+F;D=(z||1)/B.cur(true)*D;p.style[t]=D+F}if(C[1])z=(C[1]==="-="?-1:1)*z+D;B.custom(D,z,F)}else B.custom(D,z,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:L("show",1),slideUp:L("hide",1),slideToggle:L("toggle",
 639.138 +1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration==="number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,
 639.139 +b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==
 639.140 +null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(i){return e.step(i)}this.startTime=K();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!Z)Z=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop===
 639.141 +"width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=K(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=
 639.142 +this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=
 639.143 +c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},stop:function(){clearInterval(Z);Z=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=
 639.144 +null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),
 639.145 +f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(t){c.offset.setOffset(this,a,t)});if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=
 639.146 +b,e=b.ownerDocument,i,j=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var p=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==j;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;i=e?e.getComputedStyle(b,null):b.currentStyle;p-=b.scrollTop;n-=b.scrollLeft;if(b===d){p+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){p+=parseFloat(i.borderTopWidth)||
 639.147 +0;n+=parseFloat(i.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&i.overflow!=="visible"){p+=parseFloat(i.borderTopWidth)||0;n+=parseFloat(i.borderLeftWidth)||0}f=i}if(f.position==="relative"||f.position==="static"){p+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){p+=Math.max(j.scrollTop,o.scrollTop);n+=Math.max(j.scrollLeft,o.scrollLeft)}return{top:p,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),
 639.148 +d,f,e,i=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);
 639.149 +d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i;a.removeChild(b);c.offset.initialize=c.noop},
 639.150 +bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),i=parseInt(c.curCSS(a,"top",true),10)||0,j=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,d,e);d={top:b.top-e.top+i,left:b.left-
 639.151 +e.left+j};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=
 639.152 +this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],i;if(!e)return null;if(f!==w)return this.each(function(){if(i=wa(this))i.scrollTo(!a?f:c(i).scrollLeft(),a?f:c(i).scrollTop());else this[d]=f});else return(i=wa(e))?"pageXOffset"in i?i[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&i.document.documentElement[d]||i.document.body[d]:e[d]}});
 639.153 +c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+
 639.154 +b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
   640.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   640.2 +++ b/web/static/js/sdemo.html	Mon Apr 26 11:16:23 2010 +0200
   640.3 @@ -0,0 +1,40 @@
   640.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
   640.5 +<html>
   640.6 +  <head>
   640.7 +    <title>Prova</title>
   640.8 +  </head>
   640.9 +
  640.10 +  <body>
  640.11 +    <h1>Test</h1>
  640.12 +
  640.13 +  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script>  
  640.14 +  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>  
  640.15 +  <script type="text/javascript" src="./jquery.dataTables.min.js"></script>
  640.16 +  <script type="text/javascript" src="./lib/jquery.hoverIntent.js"></script>
  640.17 +  <script type="text/javascript" src="./lib/jquery.bgiframe.min.js"></script>
  640.18 +  <script type="text/javascript" src="./jquery.cluetip.js"></script>
  640.19 +<table>
  640.20 +       <tr>
  640.21 +	 <td title="Versione di logon.conf
  640.22 +    NOTA per WIN98: il numero di versione DEVE ESSERE INCREMENTATO
  640.23 +    AD OGNI MODIFICA di logon.conf se si vuole che il client Win98
  640.24 +    aggiorni i parametri di registro già precedentemente settati)">Versione</td>  
  640.25 +	 <td></td>  
  640.26 +       </tr>
  640.27 +</table>
  640.28 +
  640.29 +
  640.30 +<script>
  640.31 +$(document).ready(function () {
  640.32 +
  640.33 +  $('td.title').cluetip({splitTitle: '|'});
  640.34 +});
  640.35 +</script>
  640.36 +    <hr>
  640.37 +    <address><a href="mailto:sandro@ubuntu">Sandro Dentella</a></address>
  640.38 +<!-- Created: Thu Feb  4 15:26:02 CET 2010 -->
  640.39 +<!-- hhmts start -->
  640.40 +Last modified: Thu Feb  4 15:46:36 CET 2010
  640.41 +<!-- hhmts end -->
  640.42 +  </body>
  640.43 +</html>
   641.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   641.2 +++ b/web/sync_src	Mon Apr 26 11:16:23 2010 +0200
   641.3 @@ -0,0 +1,5 @@
   641.4 +#!/bin/bash
   641.5 +
   641.6 +rsync -a . --exclude local_settings.py --exclude .hg /misc/src/hg/isi/isi-web/shared/isiweb_
   641.7 +rsync -a . --exclude local_settings.py --exclude .hg --exclude isi.db [email protected]:/usr/share/isi/isiweb
   641.8 +ssh [email protected] /etc/init.d/isiweb restart
   642.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   642.2 +++ b/web/templates/base.mako	Mon Apr 26 11:16:23 2010 +0200
   642.3 @@ -0,0 +1,83 @@
   642.4 +<%inherit file="/static/base.mako"/>
   642.5 +
   642.6 +<%def name="title()">Reteidra</%def>
   642.7 +## navigation menu
   642.8 +<%def name="navigation_menu()"></%def>
   642.9 +
  642.10 +<%def name="main_menu()">
  642.11 +   <div id="main_menu" class="horizontal_menu">
  642.12 +	<ul id="treemenu">
  642.13 +        % if user.is_staff:
  642.14 +            <li class="mainli"><a href="/users/start/" title="Gestione gruppi/utenti" 
  642.15 +                  class="mainfoldericon "><span>Utenti</span></a></li>
  642.16 +            <li class="mainli"><a href="/samba/conf/?nt=0" title="Configurazione Dominio samba" 
  642.17 +                  class="mainfoldericon "><span>Samba</span></a></li>
  642.18 +            <li class="mainli"><a href="/logon/conf/?nt=0" title="Configurazione logon dei client" 
  642.19 +                  class="mainfoldericon "><span>Logon</span></a></li>
  642.20 +            <li class="mainli"><a href="/dnsmasq/conf/?nt=0" title="Configurazione dhcp/dns"  
  642.21 +                  class="mainfoldericon "><span>DnsMasq</span></a></li>
  642.22 +        % endif
  642.23 +            <li class="mainli"><a href="/navigazione/conf/?nt=0" title="Inibizione navigazione"  
  642.24 +                  class="mainfoldericon  "><span>Navigazione</span></a></li>
  642.25 +        </ul>
  642.26 +   </div>
  642.27 +   <div style="clear:left;"></div>
  642.28 +</%def>
  642.29 +
  642.30 +
  642.31 +<%def name="js()">
  642.32 +  <script type="text/javascript" src="/jsi18n/"></script>  
  642.33 +  <script type="text/javascript" src="/media/js/core.js"></script>
  642.34 +  <script type="text/javascript" src="/media/js/admin/RelatedObjectLookups.js"></script>
  642.35 +  <script type="text/javascript" src="/media/js/SelectBox.js"></script>
  642.36 +  <script type="text/javascript" src="/media/js/SelectFilter2.js"></script>
  642.37 +  <script type="text/javascript" src="/media/js/calendar.js"></script>
  642.38 +  <script type="text/javascript" src="/media/js/admin/DateTimeShortcuts.js"></script>
  642.39 +  <script type="text/javascript" src="/static/js/jquery.min.js"></script>
  642.40 +  <script type="text/javascript" src="/static/js/jquery-ui.min.js"></script>
  642.41 +  <script type="text/javascript" src="/static/js/jquery.dataTables.min.js"></script>
  642.42 +  <script type="text/javascript" src="/static/js/cluetip/lib/jquery.hoverIntent.js"></script>
  642.43 +  <script type="text/javascript" src="/static/js/cluetip/lib/jquery.bgiframe.min.js"></script>
  642.44 +  <script type="text/javascript" src="/static/js/cluetip/jquery.cluetip.js"></script>
  642.45 +</%def>
  642.46 +	
  642.47 +<%def name="css()">
  642.48 +  <link rel="stylesheet" type="text/css" href="/static/css/ui/themes/isi/ui.all.css" />
  642.49 +  <link rel="stylesheet" type="text/css" href="/static/css/ui/themes/isi/ui.theme.css" />
  642.50 +  <link rel="stylesheet" type="text/css" href="/static/css/cluetip.css" />
  642.51 +  ${parent.css()}
  642.52 +</%def>
  642.53 +	
  642.54 +<%def name="footer()">
  642.55 +  ${parent.footer()}
  642.56 +  <a href="http://www.python.org"><img
  642.57 +  src="/static/img/python-powered-w-70x28.png" alt="Python-powered" /></a> - Written by Alessandro Dentella
  642.58 +</%def>  
  642.59 +
  642.60 +<%def name="calendar_js()">
  642.61 +</%def>
  642.62 +
  642.63 +<%def name="header()">
  642.64 +  <div id="header">
  642.65 +      <div id="logo"></div>
  642.66 +
  642.67 +      <div id="user-tools">
  642.68 +	  % if user.is_authenticated():
  642.69 +	      <a href="/accounts/logout/?next=/accounts/login">Logout ${user.username} </a>
  642.70 +	      <a href="/accounts/change_password/"> | Password </a>
  642.71 +	      % if user.is_staff:
  642.72 +		  | <a href="/admin/"> Admin</a>
  642.73 +	      % endif
  642.74 +	  % else:
  642.75 +	      <a href="/accounts/login/">Login</a>
  642.76 +	  % endif
  642.77 +##	  | <a href="/help${request.path.replace('/help', '')}" >Help</a>
  642.78 +	  | <a href="/docs/" >Docs</a>
  642.79 +      </div>  <!-- user-tools-->
  642.80 +      <div style="clear:left;"></div>
  642.81 +
  642.82 +	  ${self.main_menu()}
  642.83 +  </div>  <!-- header -->
  642.84 +  <div id="bottomheader"></div>        
  642.85 +</%def>
  642.86 +
   643.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   643.2 +++ b/web/urls.py	Mon Apr 26 11:16:23 2010 +0200
   643.3 @@ -0,0 +1,27 @@
   643.4 +from django.conf.urls.defaults import *
   643.5 +from vov.functions import conf 
   643.6 +
   643.7 +# Uncomment the next two lines to enable the admin:
   643.8 +from django.contrib import admin
   643.9 +admin.autodiscover()
  643.10 +
  643.11 +urlpatterns = patterns('',
  643.12 +    # Example:
  643.13 +    (r'^$', include('isiweb.users.urls')),
  643.14 +#    (r'^', include('isiweb.samba.urls')),
  643.15 +    (r'^users/', include('isiweb.users.urls')),
  643.16 +    (r'^samba/', include('isiweb.samba.urls')),
  643.17 +    (r'^dnsmasq/', include('isiweb.dnsmasq.urls')),
  643.18 +    (r'^logon/', include('isiweb.logon.urls')),
  643.19 +    (r'^navigazione/', include('isiweb.navigazione.urls')),
  643.20 +                       
  643.21 +
  643.22 +    # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 
  643.23 +    # to INSTALLED_APPS to enable admin documentation:
  643.24 +    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
  643.25 +
  643.26 +    # Uncomment the next line to enable the admin:
  643.27 +    (r'^admin/', include(admin.site.urls)),
  643.28 +)
  643.29 +urlpatterns += conf.vov_default_patterns(
  643.30 +    default_url='/users/start/')
   644.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   644.2 +++ b/web/users/isildap.py	Mon Apr 26 11:16:23 2010 +0200
   644.3 @@ -0,0 +1,94 @@
   644.4 +# import pumpkin
   644.5 +# from pumpkin import fields, filters
   644.6 +# from pumpkin.resource import LDAPResource
   644.7 +# from pumpkin.directory import Directory
   644.8 +# from pumpkin.base import Model
   644.9 +# from django.conf import settings
  644.10 +# from isi import IsiConn
  644.11 +
  644.12 +
  644.13 +
  644.14 +
  644.15 +# def get_conn():
  644.16 +
  644.17 +#     isiconn = IsiConn()
  644.18 +#     LDAP_RES = LDAPResource()
  644.19 +#     LDAP_RES.server = getattr(settings, 'LDAP_SERVER', isiconn.uri)
  644.20 +#     LDAP_RES.login =  getattr(settings, 'LDAP_ROOTBINDDN', isiconn.rootdn)
  644.21 +#     LDAP_RES.password = getattr(settings, 'LDAP_PASSWORD', isiconn.passwd)
  644.22 +#     LDAP_RES.TLS = False
  644.23 +#     LDAP_RES.basedn = getattr(settings, 'LDAP_BASEDN', isiconn.base)
  644.24 +#     LDAP_RES.method = pumpkin.resource.AUTH_SIMPLE
  644.25 +
  644.26 +#     LDAP_CONN = Directory()
  644.27 +#     LDAP_CONN.connect(LDAP_RES)
  644.28 +#     return LDAP_CONN
  644.29 +
  644.30 +# def get_user(username, conn=None):
  644.31 +#     return (conn or get_conn()).get(IsiUser, search_filter=filters.eq('uid', username))
  644.32 +
  644.33 +# def get_group(group_name):
  644.34 +#     return get_conn().get(PosixGroup, search_filter=filters.eq('name', group_name))
  644.35 +
  644.36 +# class IsiUser(Model):
  644.37 +
  644.38 +#     """This is my custom model"""
  644.39 +
  644.40 +#     _object_class_ = ['posixAccount', 'inetOrgPerson', 'posixAccount', 'shadowAccount', 'sambaSamAccount']
  644.41 +#     _rdn_ = 'logname'
  644.42 +
  644.43 +#     logname = fields.StringField('uid')
  644.44 +#     classe = fields.StringField('departmentNumber')
  644.45 +#     uid = fields.IntegerField('uidNumber')
  644.46 +#     gid = fields.IntegerField('gidNumber')
  644.47 +#     fullname = fields.StringField('cn')
  644.48 +#     firstname = fields.StringField('givenName')
  644.49 +#     surname = fields.StringField('sn')
  644.50 +#     shell = fields.StringField('loginShell')
  644.51 +#     home = fields.StringField('homeDirectory')
  644.52 +#     mail = fields.StringListField('mail')
  644.53 +
  644.54 +#     def get_logname(self):
  644.55 +#         return self.logname
  644.56 +    
  644.57 +#     def url(self, text=None):
  644.58 +#         return u'<a href="/users/user/detail/%s">%s</a>' % (self.logname, text or self.logname)
  644.59 +
  644.60 +# class PosixGroup(Model):
  644.61 +#     _object_class_ = 'posixGroup'
  644.62 +#     _rdn_ = 'name'
  644.63 +#     name = fields.StringField('cn')
  644.64 +#     gid = fields.IntegerField('gidNumber')
  644.65 +#     members = fields.StringListField('memberUid')
  644.66 +
  644.67 +
  644.68 +#     def __repr__(self):
  644.69 +#         return u'<%s %s >' % (self.__class__.__name__, self.name)
  644.70 +
  644.71 +#     def __str__(self):
  644.72 +#         return u'%s' % (self.name)
  644.73 +
  644.74 +#     def url(self, text=None):
  644.75 +#         return u'<a href="/users/group/%s">%s</a>' % (self.name, text or self.name)
  644.76 +
  644.77 +#     def members_info(self):
  644.78 +#         if self.members:
  644.79 +#             return "members: %s (%s)" % (len(self.members), ",".join(self.members))
  644.80 +#         return ''
  644.81 +
  644.82 +#     def members_as_users(self):
  644.83 +
  644.84 +#         conn = get_conn()
  644.85 +#         return [get_user(u, conn) for u in sorted(self.members)]
  644.86 +        
  644.87 +
  644.88 +# #pg = PosixGroup(LDAP_CONN, 'cn=admins,ou=Groups,dc=isi,dc=lan')
  644.89 +
  644.90 +# # sci = PosixGroup(LDAP_CONN)
  644.91 +# # sci.name = u'sciabattoni'
  644.92 +# # sci.members = [u'sandro']
  644.93 +# # sci.set_parent('ou=Groups,dc=isi,dc=lan')
  644.94 +# # sci.gid = 1111
  644.95 +# # sci.save()
  644.96 +
  644.97 +
   645.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   645.2 +++ b/web/users/menu.txt	Mon Apr 26 11:16:23 2010 +0200
   645.3 @@ -0,0 +1,4 @@
   645.4 +Utenti, users/user/, Utenti,
   645.5 +Samba, samba/conf/, Samba,
   645.6 +Logon, logon/conf/, Logon,
   645.7 +DnsMasq, dnsmas/user/, DnsMasq,
   646.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   646.2 +++ b/web/users/models.py	Mon Apr 26 11:16:23 2010 +0200
   646.3 @@ -0,0 +1,3 @@
   646.4 +from django.db import models
   646.5 +
   646.6 +# Create your models here.
   647.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   647.2 +++ b/web/users/templates/users/change_password_form.mako	Mon Apr 26 11:16:23 2010 +0200
   647.3 @@ -0,0 +1,22 @@
   647.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   647.5 +
   647.6 +<%def name="title()">Cambio Password</%def>
   647.7 +
   647.8 +<%def name="layout()">
   647.9 +
  647.10 +h=username=$!username
  647.11 +password
  647.12 +--
  647.13 +admin_password  s=Imposta
  647.14 +
  647.15 +</%def>
  647.16 +
  647.17 +${jun.show_form_errors(form)}
  647.18 +${forms.mako_create_nform(context, layout, form, style='-')}
  647.19 +
  647.20 +
  647.21 +<script type="text/javascript">
  647.22 +  $(document).ready(function() {
  647.23 +    $('td label[title]').cluetip({splitTitle: '|'});
  647.24 +  });
  647.25 +</script>
   648.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   648.2 +++ b/web/users/templates/users/classe_detail.mako	Mon Apr 26 11:16:23 2010 +0200
   648.3 @@ -0,0 +1,25 @@
   648.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   648.5 +
   648.6 +<h2>${classe.name}</h2>
   648.7 +
   648.8 +<table id="utable" >
   648.9 +<thead>
  648.10 +<tr>
  648.11 +  <th>logname</th>
  648.12 +  <th>nome</th>
  648.13 +  <th>cognome</th>
  648.14 +</tr>
  648.15 +</thead>
  648.16 +<tbody>
  648.17 +% for u in classe.members_as_users(order_by='last_name'):
  648.18 +  
  648.19 +  <tr>
  648.20 +    <td>${u.logname}</td>
  648.21 +    <td>${u.first_name}</td>
  648.22 +    <td>${u.last_name}</td>
  648.23 +  </tr>
  648.24 +
  648.25 +% endfor
  648.26 +</tbody>
  648.27 +</table>
  648.28 +
   649.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   649.2 +++ b/web/users/templates/users/create_links.mako	Mon Apr 26 11:16:23 2010 +0200
   649.3 @@ -0,0 +1,25 @@
   649.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   649.5 +
   649.6 +<%def name="title()">Creazione link</%def>
   649.7 +
   649.8 +<%def name="layout()">
   649.9 +
  649.10 +h=name=${name}
  649.11 +s=Procedi
  649.12 +
  649.13 +</%def>
  649.14 +
  649.15 +<h2>Crea link studenti</h2>
  649.16 +    
  649.17 +<div id="content_popup">
  649.18 +   <div id="testo_popup" class="ui-dialog-titlebar ui-widget-header
  649.19 +		   ui-corner-all ui-helper-clearfix" style="margin: 20px; padding: 10px;">
  649.20 +		  
  649.21 +		  Desideri rigenerare i link degli utenti per la classe ${name}?
  649.22 +
  649.23 +  </div>
  649.24 +${jun.show_form_errors(form)}
  649.25 +${forms.mako_create_nform(context, layout, form, style='-')}
  649.26 +
  649.27 +		
  649.28 +</div>
   650.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   650.2 +++ b/web/users/templates/users/expire_password.mako	Mon Apr 26 11:16:23 2010 +0200
   650.3 @@ -0,0 +1,26 @@
   650.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   650.5 +
   650.6 +<%def name="title()">Forza scadenza password</%def>
   650.7 +
   650.8 +<%def name="layout()">
   650.9 +
  650.10 +h=name=${name}
  650.11 +h=model=${model}
  650.12 +s=Procedi
  650.13 +
  650.14 +</%def>
  650.15 +
  650.16 +<h2>Scadenza password</h2>
  650.17 +    
  650.18 +<div id="content_popup">
  650.19 +   <div id="testo_popup" class="ui-dialog-titlebar ui-widget-header
  650.20 +		   ui-corner-all ui-helper-clearfix" style="margin: 20px; padding: 10px;">
  650.21 +		  
  650.22 +		  Desideri forzarela scadenza password per la classe ${name}?
  650.23 +
  650.24 +  </div>
  650.25 +${jun.show_form_errors(form)}
  650.26 +${forms.mako_create_nform(context, layout, form, style='-')}
  650.27 +
  650.28 +		
  650.29 +</div>
   651.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   651.2 +++ b/web/users/templates/users/group_detail.mako	Mon Apr 26 11:16:23 2010 +0200
   651.3 @@ -0,0 +1,85 @@
   651.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   651.5 +
   651.6 +% if group_name:
   651.7 +  <h2>${group_name}</h2>
   651.8 +%else:
   651.9 +  <h2>Tutti gli utenti</h2>
  651.10 +%endif
  651.11 +
  651.12 +<table id="utable" >
  651.13 +<thead>
  651.14 +<tr>
  651.15 +  <th></th>
  651.16 +  <th>logname</th>
  651.17 +  <th>nome</th>
  651.18 +  <th>cognome</th>
  651.19 +  <th>maingroup</th>
  651.20 +  <th>classe</th>
  651.21 +</tr>
  651.22 +</thead>
  651.23 +<tbody>
  651.24 +% for u in users:
  651.25 +  
  651.26 +  <tr>
  651.27 +    <td><a href="/users/user/edit/${u.logname}/" class="wpopup"><img src="/static/img/icon_changelink.gif"></a></td>
  651.28 +    <td><a href="/users/user/detail/${u.logname}/" class="logname">${u.logname}</a></td>
  651.29 +    <td>${u.first_name or ''}</td>
  651.30 +    <td>${u.last_name or ''}</td>
  651.31 +    <td>${u.maingroup}</td>
  651.32 +    <td>${u.classe or ''}</td>
  651.33 +  </tr>
  651.34 +
  651.35 +% endfor
  651.36 +</tbody>
  651.37 +</table>
  651.38 +
  651.39 +  % if group:
  651.40 +    <h2>Azioni</h2>
  651.41 +    <ul>
  651.42 +     <li><a href="/users/group/set_quota/${group.name}/" class="wpopup">Imposta quota</a></li>
  651.43 +     % if group.is_class() or group.is_course():
  651.44 +	<li><a href="/users/group/create_links/${group.name}" class="wpopup">Crea link agli alunni</a></li>
  651.45 +     % endif
  651.46 +     <li><a href="/users/group/expire_password/${group.name}/"
  651.47 +     class="wpopup">Forsa scadenza password</a></li>
  651.48 +##     <li><a href="/users/group/${group.name}/show_expire/" class="wpopup">Mostra scadenza password</a></li>
  651.49 +  % endif
  651.50 +</ul>
  651.51 +
  651.52 +<script type="text/javascript" >
  651.53 +
  651.54 +  $(document).ready(function() {
  651.55 +    $('.popup').click(function() {
  651.56 +       $('<div></div>').load(this.href + '?&nt=1').dialog({modal:true, width:660});
  651.57 +       return false;
  651.58 +    });
  651.59 +
  651.60 +    $('td label[title]').cluetip({splitTitle: '|'});
  651.61 +
  651.62 +    $('#utable').dataTable( {
  651.63 +##              "aaSorting": [[0,'asc'],],
  651.64 +              "bPaginate": false,
  651.65 +		"bLengthChange": true,
  651.66 +		"bFilter": true,
  651.67 +		"bSort": true,
  651.68 +		"bInfo": true,
  651.69 +		"bAutoWidth": false}
  651.70 +   );
  651.71 +
  651.72 +    ## overlay popup per descrizione
  651.73 +    $('.logname').click(function() {
  651.74 +	 $('<div></div>').load(this.href + '?&nt=1').dialog({modal:true, width:660});
  651.75 +	 return false;
  651.76 +    });
  651.77 +    
  651.78 +  ## window popup per edit
  651.79 +    $('.wpopup').click(function() {
  651.80 +       window.open(this.href + '?&popup=1', '', 'width=600, height=400, status=status, scrollbars=yes');
  651.81 +       return false;
  651.82 +    });
  651.83 +  });
  651.84 +
  651.85 +
  651.86 +</script>
  651.87 +
  651.88 +
   652.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   652.2 +++ b/web/users/templates/users/group_form.mako	Mon Apr 26 11:16:23 2010 +0200
   652.3 @@ -0,0 +1,23 @@
   652.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   652.5 +
   652.6 +<%def name="title()">Aggiunti un gruppo</%def>
   652.7 +
   652.8 +<%def name="layout()">
   652.9 +
  652.10 +name
  652.11 +--
  652.12 +s=Aggiungi
  652.13 +
  652.14 +</%def>
  652.15 +
  652.16 +<h2>Aggiungi un gruppo</h2>
  652.17 +    
  652.18 +${jun.show_form_errors(form)}
  652.19 +${forms.mako_create_nform(context, layout, form, style='-')}
  652.20 +
  652.21 +
  652.22 +<script type="text/javascript" >
  652.23 +  $(document).ready(function() {
  652.24 +    $('td label[title]').cluetip({splitTitle: '|'});
  652.25 +  });
  652.26 +</script>
   653.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   653.2 +++ b/web/users/templates/users/group_list.mako	Mon Apr 26 11:16:23 2010 +0200
   653.3 @@ -0,0 +1,51 @@
   653.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   653.5 +
   653.6 +
   653.7 +<table id="gtable" >
   653.8 +<thead>
   653.9 +<tr>
  653.10 +  <th>nome gruppo</th>
  653.11 +  <th>members</th>
  653.12 +</tr>
  653.13 +</thead>
  653.14 +<tbody>
  653.15 +% for g in groups:
  653.16 +  
  653.17 +  <tr>
  653.18 +    <td><a class="gr_popup" href="/users/group/detail/${g.name}/">${g}</a>
  653.19 +    </td>
  653.20 +    </td>
  653.21 +    <td>
  653.22 +        ${g.members_info()}
  653.23 +    </td>
  653.24 +  </tr>
  653.25 +
  653.26 +% endfor
  653.27 +</tbody>
  653.28 +</table>
  653.29 +
  653.30 +<script type="text/javascript" >
  653.31 +
  653.32 +  $(document).ready(function() {
  653.33 +    $('.gr_popup').click(function() {
  653.34 +       $('<div></div>').load(this.href + '?&nt=1').dialog({modal:true, width:660});
  653.35 +       return false;
  653.36 +    });
  653.37 +    
  653.38 +  });
  653.39 +
  653.40 +
  653.41 +  $(document).ready(function(){
  653.42 +      $('#gtable').dataTable( {
  653.43 +##                "aaSorting": [[0,'asc']],
  653.44 +                "bPaginate": false,
  653.45 +		"bLengthChange": true,
  653.46 +		"bFilter": true,
  653.47 +		"bSort": true,
  653.48 +		"bInfo": true,
  653.49 +		"bAutoWidth": false}
  653.50 +     );
  653.51 +  });
  653.52 +</script>
  653.53 +
  653.54 +
   654.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   654.2 +++ b/web/users/templates/users/missing_object.mako	Mon Apr 26 11:16:23 2010 +0200
   654.3 @@ -0,0 +1,6 @@
   654.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   654.5 +
   654.6 +
   654.7 +<h2>Richiesta fallita</h2>
   654.8 +
   654.9 +L'oggetto richiesto (${name}) non esiste
   655.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   655.2 +++ b/web/users/templates/users/quota_set.mako	Mon Apr 26 11:16:23 2010 +0200
   655.3 @@ -0,0 +1,32 @@
   655.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   655.5 +
   655.6 +<%def name="title()">Imposta quota</%def>
   655.7 +
   655.8 +<%def name="layout()">
   655.9 +
  655.10 +h=name=${name}
  655.11 +h=model=${model}
  655.12 +soft_space_limit 
  655.13 +hard_space_limit
  655.14 +##soft_file_limit hard_file_limit
  655.15 +
  655.16 +s=Procedi
  655.17 +
  655.18 +</%def>
  655.19 +
  655.20 +<h2>Imposta quota</h2>
  655.21 +
  655.22 +La quota viene impotata per tutti gli utenti del gruppo che siano membri in
  655.23 +  questo momento. Membri aggiunti in futuro *non* hanno impostata la quota.    
  655.24 +
  655.25 +${jun.show_form_errors(form)}
  655.26 +${forms.mako_create_nform(context, layout, form, style='-')}
  655.27 +
  655.28 +		
  655.29 +</div>
  655.30 +
  655.31 +<script type="text/javascript" >
  655.32 +  $(document).ready(function() {
  655.33 +    $('td label[title]').cluetip({splitTitle: '|'});
  655.34 +  });
  655.35 +</script>
   656.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   656.2 +++ b/web/users/templates/users/start.mako	Mon Apr 26 11:16:23 2010 +0200
   656.3 @@ -0,0 +1,117 @@
   656.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   656.5 +
   656.6 +<%def name="sezione(sez)">
   656.7 +
   656.8 +  <div id="${sez}" class="ui-tabs-hide tab" >
   656.9 +  </div>
  656.10 +</%def>
  656.11 +
  656.12 +<div id="tabs">
  656.13 +  <ul > 
  656.14 +     %for sez in ('utenti', 'gruppi',  'classi'):
  656.15 +           <li><a href="#${sez}">${sez}</a></li>
  656.16 +     %endfor
  656.17 +  </ul>
  656.18 +  ${self.users()}
  656.19 +  ${self.gruppi()}
  656.20 +  ${self.classi()}
  656.21 +  
  656.22 +</div> <!-- tabs -->
  656.23 +
  656.24 +
  656.25 +<%def name="gruppi()">
  656.26 +<div id="gruppi">
  656.27 +   <ul>
  656.28 +   <li><a href="/users/group/add/" class="w1popup">Aggiungi un gruppo</a>
  656.29 +   <li><a href="/users/group/list/" id="mostra_gruppi">Mostra tutti i gruppi</a>
  656.30 +   </ul> 
  656.31 +
  656.32 +   <div id="list_group">
  656.33 +   </div>
  656.34 +
  656.35 +
  656.36 +  </div>
  656.37 +</%def>
  656.38 +
  656.39 +<%def name="users()">
  656.40 +<div id="utenti">
  656.41 +    
  656.42 +   <ul>
  656.43 +   <li><a href="/users/user/add/" class="w1popup">Aggiungi un utente</a>
  656.44 +   <li><a href="/users/user/fileadd/" class="w1popup">Aggiungi utenti da file</a>
  656.45 +   <li><a href="/users/user/convert/" class="w1popup">Converti formato utenti:</a>
  656.46 +   permette di importare da 'sissi' e 'isi' e di gestire nomi doppi
  656.47 +   <li><a href="/users/user/list/" class="mostra_users">Mostra tutti gli utenti</a>
  656.48 +   <li>Mostra gli utenti del gruppo 
  656.49 +   %for g in ('docenti', 'alunni', 'admins', 'ata', 'segreteria', 'esterni'):
  656.50 +      <a href="/users/user/list/${g}" class="mostra_users">${g}</a>
  656.51 +   %endfor
  656.52 +   </li>
  656.53 +   </ul> 
  656.54 +
  656.55 +   <div id="list_users">
  656.56 +   </div>
  656.57 +
  656.58 +
  656.59 +</div>
  656.60 +   </%def>
  656.61 +
  656.62 +<%def name="classi()">
  656.63 +  <div id="classi">
  656.64 +     <ul>
  656.65 +	%for c in classes:
  656.66 +	  <li><a href="/users/user/list/${c}/" class="popup_classe">${c}</a></li>
  656.67 +	%endfor
  656.68 +     </ul> 
  656.69 +
  656.70 +  </div>
  656.71 +</%def>
  656.72 +
  656.73 +
  656.74 +
  656.75 +
  656.76 +
  656.77 +
  656.78 +<script type="text/javascript" >
  656.79 +$(document).ready(function () {
  656.80 +
  656.81 +  $('#tabs').tabs();
  656.82 +  $('td.title').cluetip({splitTitle: '|'  });
  656.83 +##  $('td.title').cluetip({splitTitle: '|', sticky: true, closePosition: 'title', arrows: true });
  656.84 +
  656.85 +  $('.toggle').click(function(){
  656.86 +     $('.advanced').toggle();
  656.87 +   });
  656.88 +
  656.89 +   ## Mostra gruppi
  656.90 +   $('#mostra_gruppi').click(function() {
  656.91 +     var ref = this;
  656.92 +     $('#list_group').load(ref.href + '?nt=1');
  656.93 +     return false;
  656.94 +   });
  656.95 +   ## Mostra users
  656.96 +   $('.mostra_users').click(function() {
  656.97 +     var ref = this;
  656.98 +     $('#list_users').load(ref.href + '?nt=1');
  656.99 +     return false;
 656.100 +   });
 656.101 +
 656.102 +   ## Mostra classe
 656.103 +   $('.popup_classe').click(function() {
 656.104 +     var ref = this;
 656.105 +     $('<div></div>').load(ref.href + '?nt=1').dialog({modal: true,
 656.106 +   width:800, heigh: 600});
 656.107 +     return false;
 656.108 +   });
 656.109 +
 656.110 +   $('.w1popup').click(function() {
 656.111 +       window.open(this.href + '?&popup=1', '', 'width=650, height=550, scrollbars=yes');
 656.112 +       return false;
 656.113 +   });
 656.114 +
 656.115 +
 656.116 +
 656.117 +});
 656.118 +</script>
 656.119 +
 656.120 +
   657.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   657.2 +++ b/web/users/templates/users/user_bulk_form.mako	Mon Apr 26 11:16:23 2010 +0200
   657.3 @@ -0,0 +1,40 @@
   657.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   657.5 +
   657.6 +<%def name="title()">Aggiunti utenti da file</%def>
   657.7 +
   657.8 +<%def name="layout()">
   657.9 +
  657.10 +user_file
  657.11 +--
  657.12 +expire          use_cf
  657.13 +update_users    default_password  
  657.14 +--
  657.15 +s=Importa
  657.16 +
  657.17 +</%def>
  657.18 +
  657.19 +<h2>Aggiungi utenti da file</h2>
  657.20 +    
  657.21 +L'aggiunta utenti da file prende un tempo lungo, circa 1 secondo ad utente
  657.22 +ovvero fino a 2 minuti per 100 utenti. Non interrrompete il caricamento.
  657.23 +
  657.24 +<h3>Conversione</h3> 
  657.25 +
  657.26 +Se temete collisioni nei nomi dei dati potete passare il file utenti tramite
  657.27 +l'importazione con <a href="/users/user/convert/?popup=1">conversione dei dati</a>, che
  657.28 +accetta anche il formato 'isi' nonché file in formato excel
  657.29 +
  657.30 +<h3>Password</h3>
  657.31 +Potete usare un password di default o usar il CF come password (primi o
  657.32 +caratteri con prima lettera maiuscola). Se volete password casuali dovete
  657.33 +passare il file attraverso la conversione del formato.
  657.34 +
  657.35 +${jun.show_form_errors(form)}
  657.36 +${forms.mako_create_nform(context, layout, form, style='-')}
  657.37 +
  657.38 +
  657.39 +<script type="text/javascript" >
  657.40 +$(document).ready(function () {
  657.41 +  $('td label[title]').cluetip({splitTitle: '|'});
  657.42 +});
  657.43 +</script>
   658.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   658.2 +++ b/web/users/templates/users/user_convert.mako	Mon Apr 26 11:16:23 2010 +0200
   658.3 @@ -0,0 +1,55 @@
   658.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   658.5 +
   658.6 +
   658.7 +<%def name="create_table(user_list)">
   658.8 +  <table>
   658.9 +  <thead>
  658.10 +      <tr><td>Logname</td><td>Nome</td><td>Classe</td></tr>
  658.11 +  </thead>
  658.12 +  <tbody>
  658.13 +    % for u in user_list:
  658.14 +      <tr>
  658.15 +        <td>${u.logname}</td><td>${'%s %s' % (u.first_name or '',
  658.16 +                     u.last_name)}</td><td>${u.classe or ''}</td>
  658.17 +      </tr>
  658.18 +    % endfor
  658.19 +  </tbody>
  658.20 +  </table> 
  658.21 +</%def>
  658.22 +
  658.23 +
  658.24 +<%def name="title()">File</%def>
  658.25 +
  658.26 +<h2>File definizione utenti</h2>
  658.27 +Il file con la definizione degli utenti può essere scaricato <a
  658.28 +    href="/static/utenti/users.csv">qui</a>. L'immissione deve 
  658.29 +     essere fatta tramite il normale <a  href="/users/user/fileadd/?popup=1">inserimento utenti</a>
  658.30 +
  658.31 +% if bulk.renamed:
  658.32 +  <h3>Utenti da rinominare per nomi doppi</h3>
  658.33 +  Nel file ci sono ${len(bulk.renamed)} utenti da rinominare:
  658.34 +  ${create_table(bulk.renamed)}
  658.35 +% endif
  658.36 +
  658.37 +% if bulk.deleted:
  658.38 +  <h3>Utenti da cancellare  <img src="/static/img/icon_deletelink.gif"></h3>
  658.39 +
  658.40 +  Nel file ci sono ${len(bulk.deleted)} utenti che verranno cancellati:
  658.41 +  ${create_table(bulk.deleted)}
  658.42 +
  658.43 +% endif
  658.44 +
  658.45 +% if bulk.get_updated_users(logname=True):
  658.46 +  <h3>Utenti da aggiornare</h3>
  658.47 +  Nel file ci sono ${len(bulk.get_updated_users(logname=True))} utenti che
  658.48 + verranno aggiornati
  658.49 +  ${create_table(bulk.get_updated_users(logname=False))}
  658.50 +
  658.51 +% endif
  658.52 +
  658.53 +% if bulk.get_new_users(logname=True):
  658.54 +  <h3>Utenti nuovi</h3>
  658.55 +  Nel file ci sono ${len(bulk.get_new_users(logname=True))} utenti nuovi
  658.56 +  ${create_table(bulk.get_new_users(logname=False))}
  658.57 +% endif
  658.58 +
   659.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   659.2 +++ b/web/users/templates/users/user_convert_form.mako	Mon Apr 26 11:16:23 2010 +0200
   659.3 @@ -0,0 +1,51 @@
   659.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   659.5 +
   659.6 +<%def name="title()">Aggiunti utenti da file</%def>
   659.7 +
   659.8 +<%def name="layout()">
   659.9 +
  659.10 +user_file
  659.11 +file_format
  659.12 +user_format
  659.13 +maingroup
  659.14 +extended
  659.15 +random_password
  659.16 +--
  659.17 +s=Converti
  659.18 +
  659.19 +</%def>
  659.20 +
  659.21 +<h2>Conversione formato utenti</h2>
  659.22 +    
  659.23 +Al momento questa pagina permette la conversione di un file di utenti
  659.24 +in formato <tt>.isi</tt> a partire da
  659.25 +<ul>
  659.26 +<li><a href="/docs/gestione/comandi_isi.html#formato-sissi">Sissi - il sistema usato da molte amministrazioni scolastiche</li>
  659.27 +<li><a href="/docs/gestione/comandi_isi.html#formato-file-isi">.isi</a> - isi stesso. Questa conversione ha senso per gestire doppioni e
  659.28 +      password casuali</li>
  659.29 +</ul>
  659.30 +
  659.31 +La documentazione ufficiale di <a href="/docs/">ReteISI</a> riporta la definizione dei due
  659.32 +formati.
  659.33 +
  659.34 +Il file che si carica deve contenere *tutti* gli utenti per il gruppo
  659.35 +definito, gli utenti del gruppo non compresi nel file verranno 
  659.36 +marcati per la cancellazione (avranno un '-' attaccato alla logname).
  659.37 +
  659.38 +Questo garantisce che utenti che non sono più della scuola vengano
  659.39 +eliminati. Lo scenario normale è che il maingroup è 'alunni'.
  659.40 +
  659.41 +Questa form mostra una pagina con il link degli utenti da passare alla
  659.42 +  sezione di gestione utenti e mostra cosa succede ma *non effettua alcuna
  659.43 +  cancellazione*, le righe contrassegnate dal '-' indicano gli utenti che
  659.44 +  verranno eliminati.
  659.45 +
  659.46 +${jun.show_form_errors(form)}
  659.47 +${forms.mako_create_nform(context, layout, form, style='-')}
  659.48 +
  659.49 +
  659.50 +<script type="text/javascript" >
  659.51 +$(document).ready(function () {
  659.52 +  $('td label[title]').cluetip({splitTitle: '|'});
  659.53 +});
  659.54 +</script>
   660.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   660.2 +++ b/web/users/templates/users/user_detail.mako	Mon Apr 26 11:16:23 2010 +0200
   660.3 @@ -0,0 +1,56 @@
   660.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   660.5 +
   660.6 +
   660.7 +<h2>Utente: ${"%s (%s %s)" % (u.logname, u.first_name or '', u.last_name)}</h2>
   660.8 +
   660.9 +
  660.10 +<table>
  660.11 +
  660.12 +% for at in ( 'logname  first_name last_name maingroup home uid gid  classe cf'.split()):
  660.13 +  <tr>
  660.14 +   <td><b>${at}:</b> </td><td>${getattr(u, at) or ''} </td>
  660.15 +  </tr>
  660.16 +% endfor
  660.17 +  <tr>
  660.18 +    <td><b>gruppi</b></td><td>${u.get_my_groups(as_text=True)}</td>
  660.19 +  </tr>
  660.20 +</table>
  660.21 +
  660.22 +<h3>Azioni</h3> 
  660.23 +<ul>
  660.24 +  <li> <a href="/users/user/password/change/${u.logname}/" class="popup">Imposta password</a>
  660.25 +  </li>
  660.26 +
  660.27 +## <li>Imposta la <a href="/users/user/quota/${obj.logname}/">quota</a></li>
  660.28 +  <li>
  660.29 +    <a href="/users/user/delete/${u.logname}/?home_mode=tar" class="w2popup">Elimina e zippa la HOME</a>
  660.30 +  </li>
  660.31 +  <li>
  660.32 +    <a href="/users/user/delete/${u.logname}/?home_mode=rm" class="w2popup">Elimina anche la HOME</a>
  660.33 +  </li> 
  660.34 +</ul>
  660.35 +
  660.36 +<script type="text/javascript" >
  660.37 +  $(document).ready(function() {
  660.38 +    $('.popup').click(function() {
  660.39 +       window.open(this.href + '?&popup=1', '', 'width=500, height=400, status=status');
  660.40 +       return false;
  660.41 +    });
  660.42 +    ## window popup per delete
  660.43 +    $('.w2popup').click(function() {
  660.44 +       window.open(this.href + '&popup=1', '', 'width=450, height=600, status=status');
  660.45 +       return false;
  660.46 +    });
  660.47 +    
  660.48 +  });
  660.49 +
  660.50 +##    ## cambio passwordx
  660.51 +##    $('.kpopup').click(function() {
  660.52 +##      var ref = this;
  660.53 +##      $('<div></div>').load(ref.href + '?popup=1').dialog({modal: true,  width:600, heigh: 250});
  660.54 +##      return false;
  660.55 +##    });
  660.56 +## 
  660.57 +## 
  660.58 +##   $('td label[title]').cluetip({splitTitle: '|'});
  660.59 +</script>
   661.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   661.2 +++ b/web/users/templates/users/user_form.mako	Mon Apr 26 11:16:23 2010 +0200
   661.3 @@ -0,0 +1,34 @@
   661.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   661.5 +
   661.6 +<%def name="title()">Aggiunti utente</%def>
   661.7 +
   661.8 +<%def name="layout()">
   661.9 +
  661.10 +username
  661.11 +first_name
  661.12 +last_name
  661.13 +maingroup
  661.14 +## home
  661.15 +cf
  661.16 +classe
  661.17 +groups
  661.18 +--
  661.19 +expire
  661.20 +use_cf
  661.21 +##password
  661.22 +--
  661.23 +s=Salva
  661.24 +
  661.25 +</%def>
  661.26 +
  661.27 +<h2>Aggiungi utente</h2>
  661.28 +    
  661.29 +${jun.show_form_errors(form)}
  661.30 +${forms.mako_create_nform(context, layout, form, style='-')}
  661.31 +
  661.32 +
  661.33 +<script type="text/javascript" >
  661.34 +$(document).ready(function () {
  661.35 +  $('td label[title]').cluetip({splitTitle: '|'});
  661.36 +});
  661.37 +</script>
   662.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   662.2 +++ b/web/users/templates/users/user_form_update.mako	Mon Apr 26 11:16:23 2010 +0200
   662.3 @@ -0,0 +1,31 @@
   662.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   662.5 +
   662.6 +<%def name="title()">modifica utente ${obj.logname}</%def>
   662.7 +
   662.8 +<%def name="layout()">
   662.9 +
  662.10 +h=username=${obj.logname}
  662.11 +first_name
  662.12 +last_name
  662.13 +h=maingroup=${obj.maingroup}
  662.14 +##home
  662.15 +cf
  662.16 +classe
  662.17 +groups
  662.18 +--
  662.19 +s=Salva
  662.20 +
  662.21 +</%def>
  662.22 +
  662.23 +<h2>${"%s %s" % (obj.first_name, obj.last_name)}</h2>
  662.24 +    
  662.25 +${jun.show_form_errors(form)}
  662.26 +${forms.mako_create_nform(context, layout, form, style='-')}
  662.27 +
  662.28 +
  662.29 +<script type="text/javascript" >
  662.30 +  $(document).ready(function() {
  662.31 +    $('td label[title]').cluetip({splitTitle: '|'});
  662.32 +  });
  662.33 +</script>
  662.34 +
   663.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   663.2 +++ b/web/users/templates/users/user_list.mako	Mon Apr 26 11:16:23 2010 +0200
   663.3 @@ -0,0 +1,70 @@
   663.4 +<%inherit file="${jun.get_parent_template(context)}"/> 
   663.5 +
   663.6 +% if group_name:
   663.7 +  <h2>${group_name}</h2>
   663.8 +%else:
   663.9 +  <h2>Tutti gli utenti</h2>
  663.10 +%endif
  663.11 +
  663.12 +<table id="utable" >
  663.13 +<thead>
  663.14 +<tr>
  663.15 +  <th></th>
  663.16 +  <th>logname</th>
  663.17 +  <th>nome</th>
  663.18 +  <th>cognome</th>
  663.19 +</tr>
  663.20 +</thead>
  663.21 +<tbody>
  663.22 +% for u in users:
  663.23 +  
  663.24 +  <tr>
  663.25 +    <td><a href="/users/user/edit/${u.logname}/" class="wpopup"><img src="/static/img/icon_changelink.gif"></a></td>
  663.26 +    <td><a href="/users/user/detail/${u.logname}/" class="logname">${u.logname}</a></td>
  663.27 +    <td>${u.first_name or ''}</td>
  663.28 +    <td>${u.last_name or ''}</td>
  663.29 +  </tr>
  663.30 +
  663.31 +% endfor
  663.32 +</tbody>
  663.33 +</table>
  663.34 +
  663.35 +<script type="text/javascript" >
  663.36 +
  663.37 +  $(document).ready(function() {
  663.38 +    $('.popup').click(function() {
  663.39 +       $('<div></div>').load(this.href + '?&nt=1').dialog({modal:true, width:660});
  663.40 +       return false;
  663.41 +    });
  663.42 +
  663.43 +    $('#utable').dataTable( {
  663.44 +##              "aaSorting": [[0,'asc'],],
  663.45 +              "bPaginate": false,
  663.46 +		"bLengthChange": true,
  663.47 +		"bFilter": true,
  663.48 +		"bSort": true,
  663.49 +		"bInfo": true,
  663.50 +		"bAutoWidth": false }
  663.51 +   );
  663.52 +
  663.53 +    ## overlay popup per descrizione
  663.54 +    $('.logname').click(function() {
  663.55 +       $('<div></div>').load(this.href + '?&nt=1').dialog({modal:true, width:660});
  663.56 +       return false;
  663.57 +    });
  663.58 +
  663.59 +    ## window popup per edit
  663.60 +    $('.wpopup').click(function() {
  663.61 +       window.open(this.href + '?&popup=1', '', 'width=450, height=600, status=status, scrollbars=yes');
  663.62 +       return false;
  663.63 +    });
  663.64 +  
  663.65 +    $('td label[title]').cluetip({splitTitle: '|'});
  663.66 +
  663.67 +  });
  663.68 +
  663.69 +
  663.70 +
  663.71 +</script>
  663.72 +
  663.73 +
   664.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   664.2 +++ b/web/users/templates/users/user_opts.mako	Mon Apr 26 11:16:23 2010 +0200
   664.3 @@ -0,0 +1,30 @@
   664.4 +<%inherit file="/base.mako"/>
   664.5 +
   664.6 +
   664.7 +
   664.8 +<ul class="css-tabs">
   664.9 +	<li><a href="/users/group/list/?nt=1">gruppi</a></li>
  664.10 +	<li><a href="/users/user/list/">utenti</a></li>
  664.11 +	<li><a href="/users/user/passwd">password</a></li>
  664.12 +</ul>
  664.13 +
  664.14 +<!-- single pane. it is always visible -->
  664.15 +<div class="css-panes">
  664.16 +	<div style="display:block"></div>
  664.17 +</div>
  664.18 +
  664.19 +<!-- activate tabs with JavaScript -->
  664.20 +<script type="text/javascript">
  664.21 +
  664.22 +
  664.23 +$(function() {
  664.24 +
  664.25 +	$("ul.css-tabs").tabs("div.css-panes > div", {effect: 'ajax'});
  664.26 +
  664.27 +});
  664.28 +</script>
  664.29 +
  664.30 +<div id="dialog" title="Basic modal dialog">
  664.31 +	<p>Adding the modal overlay screen makes the dialog look more prominent because it dims out the page content.</p>
  664.32 +</div>
  664.33 +
   665.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   665.2 +++ b/web/users/tests.py	Mon Apr 26 11:16:23 2010 +0200
   665.3 @@ -0,0 +1,23 @@
   665.4 +"""
   665.5 +This file demonstrates two different styles of tests (one doctest and one
   665.6 +unittest). These will both pass when you run "manage.py test".
   665.7 +
   665.8 +Replace these with more appropriate tests for your application.
   665.9 +"""
  665.10 +
  665.11 +from django.test import TestCase
  665.12 +
  665.13 +class SimpleTest(TestCase):
  665.14 +    def test_basic_addition(self):
  665.15 +        """
  665.16 +        Tests that 1 + 1 always equals 2.
  665.17 +        """
  665.18 +        self.failUnlessEqual(1 + 1, 2)
  665.19 +
  665.20 +__test__ = {"doctest": """
  665.21 +Another way to test that 1 + 1 is equal to 2.
  665.22 +
  665.23 +>>> 1 + 1 == 2
  665.24 +True
  665.25 +"""}
  665.26 +
   666.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   666.2 +++ b/web/users/urls.py	Mon Apr 26 11:16:23 2010 +0200
   666.3 @@ -0,0 +1,40 @@
   666.4 +from django.conf.urls.defaults import *
   666.5 +models = 'user|group|classe'
   666.6 +default_model = 'user'
   666.7 +
   666.8 +M = {
   666.9 +    'model'     : '(?P<model>%s)' % models,
  666.10 +    'name' : '(?P<name>\w+)',
  666.11 +    }
  666.12 +
  666.13 +
  666.14 +# Uncomment the next two lines to enable the admin:
  666.15 +# from django.contrib import admin
  666.16 +# admin.autodiscover()
  666.17 +
  666.18 +urlpatterns = patterns('isiweb.users.views',
  666.19 +    # Example:
  666.20 +    ('^$', 'start', ),
  666.21 +    ('^start', 'start', ),
  666.22 +    ('^user/password/change/(?P<username>.*)/', 'change_password', ),
  666.23 +    ('^%(model)s/list/$' % M, 'object_list'),
  666.24 +    ('^%(model)s/list/(?P<group_name>.*)/' % M, 'object_list'),
  666.25 +    ('^%(model)s/detail/(?P<name>.*)/' % M, 'object_detail'),
  666.26 +    ('^%(model)s/expire_password/(?P<name>.*)/' % M, 'expire_password'),
  666.27 +#    ('^%(model)s/show_expire/(?P<name>.*)/' % M, 'show_expire'),
  666.28 +    ('^%(model)s/set_quota/(?P<name>.*)/' % M, 'set_quota'),
  666.29 +    ('^group/create_links/(?P<name>.*)/' % M, 'create_links'),
  666.30 +    ('^user/edit/(?P<logname>.*)/' % M, 'edit_user'),
  666.31 +    ('^user/add/' % M, 'add_user'),
  666.32 +    ('^group/add/' % M, 'add_group'),
  666.33 +    ('^user/delete/(?P<logname>.*)/' % M, 'del_user'),
  666.34 +    ('^user/fileadd/' % M, 'add_bulk_user'),
  666.35 +    ('^user/convert/' % M, 'convert'),
  666.36 +
  666.37 +    # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 
  666.38 +    # to INSTALLED_APPS to enable admin documentation:
  666.39 +    # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
  666.40 +
  666.41 +    # Uncomment the next line to enable the admin:
  666.42 +    # (r'^admin/', include(admin.site.urls)),
  666.43 +)
   667.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   667.2 +++ b/web/users/user_forms.py	Mon Apr 26 11:16:23 2010 +0200
   667.3 @@ -0,0 +1,359 @@
   667.4 +# -*- coding: utf-8 -*-
   667.5 +
   667.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   667.7 +#
   667.8 +#  This program is free software: you can redistribute it and/or modify
   667.9 +#  it under the terms of the GNU General Public License as published by
  667.10 +#  the Free Software Foundation, either version 3 of the License, or
  667.11 +#  (at your option) any later version.
  667.12 +#
  667.13 +#  This program is distributed in the hope that it will be useful,
  667.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  667.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  667.16 +#  GNU General Public License for more details.
  667.17 +#
  667.18 +#  You should have received a copy of the GNU General Public License
  667.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  667.20 +
  667.21 +
  667.22 +import re
  667.23 +import os
  667.24 +from django import forms
  667.25 +from django.forms import util
  667.26 +from django.conf import settings
  667.27 +import  isi
  667.28 +from isi import bulk_users
  667.29 +from django.contrib import messages
  667.30 +from isiweb.logger import logger
  667.31 +from vov.middleware.thread_local import get_current_user
  667.32 +import tempfile
  667.33 +
  667.34 +l = isi.Manager()
  667.35 +
  667.36 +class PasswordForm(forms.Form):
  667.37 +
  667.38 +    username = forms.CharField(help_text=u"Inserire il nome della persona di cui volete cambiare la password")
  667.39 +    password = forms.CharField(label=u'Nuova password',widget=forms.PasswordInput(render_value=False)) 
  667.40 +    admin_password = forms.CharField(label=u'Admin Password',widget=forms.PasswordInput(render_value=False),
  667.41 +                                     help_text=u"""Un insegnante può cambiare la password ad un alunno.
  667.42 +                                           La password da immettere qui è quella con cui ci si è autenticati""") 
  667.43 +    def clean(self):
  667.44 +
  667.45 +        username    = self.cleaned_data['username'] 
  667.46 +        password    = self.cleaned_data['password']
  667.47 +        admin          = self.admin_username  # set in the view
  667.48 +        admin_password = self.cleaned_data['admin_password']
  667.49 +
  667.50 +        if self.admin_username == username:
  667.51 +                return self.cleaned_data
  667.52 +        elif self.admin_username == 'admin':
  667.53 +            if not admin_password == l.srv.passwd:
  667.54 +                raise util.ValidationError(u"Password incorretta per 'admin'")
  667.55 +            else:
  667.56 +                return self.cleaned_data
  667.57 +            
  667.58 +        user = l.get_user(username, quiet=True)
  667.59 +        admin = l.get_user(self.admin_username, quiet=True)
  667.60 +        if not user:
  667.61 +            raise util.ValidationError(u"Lo user '%s' non esiste" % username)
  667.62 +        else:
  667.63 +            if not l.test_password(self.admin_username, admin_password):
  667.64 +                logger.warning(u"L'utente '%s' ha cercato di cambiare password a %s" % (admin, username))
  667.65 +                raise util.ValidationError(u"Password di chi compie l' operazione non corretta (%s/%s)" % (admin, admin_password))
  667.66 +
  667.67 +        if user.maingroup in ('alunni', 'esterni'):
  667.68 +            if admin.maingroup in ('alunni', 'esterni'):
  667.69 +                raise util.ValidationError("Gi alunni non possono cambiare la password ad *altri* alunni")
  667.70 +                
  667.71 +        else:
  667.72 +            if admin.maingroup in ('admins',):
  667.73 +                return self.cleaned_data
  667.74 +            else:
  667.75 +                raise util.ValidationError("Solo admin possono cambiare la password a non-alunni user: %s (%s)/ admin: %s (%s)" % (username, user.maingroup, admin.logname, admin.maingroup))
  667.76 +            
  667.77 +    def save(self):
  667.78 +        username    = self.cleaned_data['username']
  667.79 +        user = l.get_samba_user(username)
  667.80 +        user.set_password(self.cleaned_data['password'])
  667.81 +        return user.logname
  667.82 +
  667.83 +def get_maingroups():
  667.84 +    yield ('', '-------')
  667.85 +    for i in sorted(isi.get_main_groups()):
  667.86 +        yield (i, i)
  667.87 +
  667.88 +class UserForm(forms.Form):
  667.89 +
  667.90 +    username    = forms.CharField(max_length=50)
  667.91 +    first_name = forms.CharField(max_length=50, required=False)
  667.92 +    last_name = forms.CharField(max_length=50)
  667.93 +    home      = forms.CharField(max_length=50, required=False)
  667.94 +    cf      = forms.CharField(max_length=11, required=False, help_text="CF|Necessario per avere il corretto aggiornamento al cambio anno (chiave primaria)")
  667.95 +    classe     = forms.CharField(max_length=20, required=False, help_text="classe|Obbligatoria se alunni")
  667.96 +    maingroup = forms.ChoiceField(choices=get_maingroups())
  667.97 +    groups    = forms.CharField(max_length=100, required=False, help_text="Separati da virgole!!!|non serve rimettere la classe")
  667.98 +    expire    = forms.BooleanField(required=False, help_text="Forza cambio password|Marca questo campo per costringere cambio password (in Windows)")
  667.99 +    password = forms.CharField(label=u'Password',required=False, widget=forms.PasswordInput(render_value=False)) 
 667.100 +    use_cf    = forms.BooleanField(required=False, help_text="CF|Usa il CF per comporre la password (8 caratteri con iniziale maiuscola)")
 667.101 +
 667.102 +    def clean(self):
 667.103 +
 667.104 +        if not 'maingroup' in  self.cleaned_data:
 667.105 +            raise util.ValidationError("Manca maingroup")
 667.106 +
 667.107 +        if self.cleaned_data['maingroup'] in ('alunni',):
 667.108 +            if not self.cleaned_data['classe']:
 667.109 +                raise util.ValidationError("Ogni alunno deve avere una classe")
 667.110 +
 667.111 +            class_ = self.cleaned_data['classe']
 667.112 +
 667.113 +            if class_ and (class_ not in  self.cleaned_data['groups']):
 667.114 +                self.cleaned_data['groups'].insert(0, class_)
 667.115 +
 667.116 +        return self.cleaned_data
 667.117 +
 667.118 +    def clean_groups(self):
 667.119 +
 667.120 +        if self.cleaned_data['groups']:
 667.121 +            return [x.strip() for x in self.cleaned_data['groups'].split(',')]
 667.122 +        else:
 667.123 +            return []
 667.124 +
 667.125 +    def get_opts(self):
 667.126 +
 667.127 +        d = self.cleaned_data
 667.128 +
 667.129 +        kw = {
 667.130 +            'use_cf' : d['use_cf'],
 667.131 +            'last_name' : d['last_name'],
 667.132 +            'first_name' : d['first_name'], 
 667.133 +            'full_name' : "%s %s" % (d['first_name'], d['last_name']), 
 667.134 +            'groups' : d['groups'] or [],
 667.135 +            'passwd' : d['password'] or None,
 667.136 +            'classe' : d['classe'] or None,
 667.137 +            'cf' : d['cf'] or None,
 667.138 +            'use_cf' : d['use_cf'],
 667.139 +#             'sex' : self.sex,
 667.140 +#             'address' : self.address,
 667.141 +#             'city' : self.city, 
 667.142 +#             'zip_code' : self.zip,
 667.143 +#             'phone' : self.phone,
 667.144 +            }
 667.145 +        return kw
 667.146 +
 667.147 +    def save(self):
 667.148 +
 667.149 +        d = self.cleaned_data
 667.150 +        kw = self.get_opts()
 667.151 +
 667.152 +        u = l.get_samba_user(self.cleaned_data['username'])
 667.153 +
 667.154 +        user = l.modify_user(d['username'], d['maingroup'], no_filesystem=False,
 667.155 +                             force_passwd_change=d['expire'], interactive=False,
 667.156 +                             run_alulink=True, update_passwd=False, **kw)
 667.157 +        user.home = self.cleaned_data['home']
 667.158 +        user.save()
 667.159 +        return user
 667.160 +        
 667.161 +class NewUserForm(UserForm):
 667.162 +
 667.163 +#    password = forms.CharField(label=u'Password',widget=forms.PasswordInput(render_value=False), required=False) 
 667.164 +#    use_cf = forms.BooleanField(help_text="Usa CF come password DNTLSN63D07 diventa Dntlsn63")
 667.165 +
 667.166 +
 667.167 +    def clean_logname(self):
 667.168 +
 667.169 +        if not re.search('^[A-Za-z0-9_]*$', self.cleaned_data['logname']):
 667.170 +            raise util.ValidationError("Caratteri non permessi nel logname (deve essere asci 0-127)")
 667.171 +
 667.172 +        if l.get_user(self.cleaned_data['logname'], quiet=True):
 667.173 +            raise util.ValidationError(u"Un utente '%s' esiste già" % self.cleaned_data['logname'])
 667.174 +        return self.cleaned_data['logname']
 667.175 +
 667.176 +    def save(self):
 667.177 +        
 667.178 +
 667.179 +        d = self.cleaned_data
 667.180 +
 667.181 +        kw = self.get_opts()
 667.182 +        user = l.add_user(d['username'], d['maingroup'], d['expire'], interactive=False,
 667.183 +                          run_alulink=True, **kw)
 667.184 +        return user
 667.185 +
 667.186 +class BulkUserForm(forms.Form):
 667.187 +
 667.188 +    user_file = forms.FileField(required=True,
 667.189 +                                help_text="File in formato .isi|Il formato '.isi' si riferisce ai dati contenuti, il file deve invece essere in formato .csv. il formato .xls e' supportato dalla procedura di conversione")
 667.190 +    expire    = forms.BooleanField(required=False,
 667.191 +                                   help_text="Forza cambio password|Marca questo campo per costringere cambio password (in Windows)")
 667.192 +    default_password = forms.CharField(label=u'Password', required=False,
 667.193 +                               widget=forms.PasswordInput(render_value=False)) 
 667.194 +    use_cf    = forms.BooleanField(required=False,
 667.195 +                                   help_text="CF|Usa il CF per comporre la password (8 caratteri con iniziale maiuscola)")
 667.196 +    update_users = forms.BooleanField(required=False,
 667.197 +                                      help_text="Modo aggiornamento|Se un utente è gia presente (stessa logname) lo modifica")
 667.198 +
 667.199 +    def clean(self):
 667.200 +        self._file_name = None
 667.201 +
 667.202 +        for key in ('user_file',):
 667.203 +            if key not in self.cleaned_data:
 667.204 +                raise util.ValidationError("Missing key '%s'" % key)
 667.205 +                
 667.206 +        if not self.cleaned_data['update_users']:
 667.207 +            idf, name = tempfile.mkstemp()
 667.208 +            f = open(name, 'w')
 667.209 +            txt = self.cleaned_data['user_file'].read()
 667.210 +            f.write(txt)
 667.211 +            f.close()
 667.212 +            self._file_name = name
 667.213 +            add, delete, update = l.check_file(name)
 667.214 +
 667.215 +            if update:
 667.216 +                msg = u"""Alcuni utenti esistono gia' e non e' stata usata l'opzione "update_user":\n%s """ % (
 667.217 +                    "\n".join("%s (%s %s)" % (u.logname, u.last_name, u.first_name) for u in update))
 667.218 +                raise util.ValidationError(msg)
 667.219 +        return self.cleaned_data
 667.220 +
 667.221 +    def save(self):
 667.222 +
 667.223 +        return l.read_file(
 667.224 +            self._file_name or self.cleaned_data['user_file'],
 667.225 +            update_user = self.cleaned_data['update_users'],
 667.226 +            use_cf      = self.cleaned_data['use_cf'],
 667.227 +            force_passwd_change      = self.cleaned_data['expire'],
 667.228 +            default_passwd = self.cleaned_data['default_password'],
 667.229 +            interactive = False,
 667.230 +            run_alulink = True,
 667.231 +            )
 667.232 +        
 667.233 +USERNAME_FORMATS = (
 667.234 +    ('',  'default di sistema'),
 667.235 +    ('name', 'nome.cognome'),
 667.236 +    ('id-name', 'd_nome.cognome, a_nome.cognome'),
 667.237 +    ('cf', 'a_dntlsn63d07'),
 667.238 +    )
 667.239 +        
 667.240 +FILE_FORMAT = (
 667.241 +    ('isi', 'isi'),
 667.242 +    ('sissi', 'sissi'),
 667.243 +    )
 667.244 +class ConvertUserForm(forms.Form):
 667.245 +
 667.246 +    user_file = forms.FileField(required=True, help_text="file|File utenti da importare/convertire")
 667.247 +    file_format    = forms.ChoiceField(required=False, choices=FILE_FORMAT,
 667.248 +                                   help_text="Formato file|Al momento sono accettati: 'isi' e 'sissi'")
 667.249 +    user_format    = forms.ChoiceField(required=False, choices=USERNAME_FORMATS,
 667.250 +                                   help_text="Formato username|Puoi decidere quale formato per lo username")
 667.251 +    maingroup = forms.ChoiceField(choices=get_maingroups(), help_text="gruppo|Il gruppo per il quale si stanno convertendo gli utenti", required=True)
 667.252 +    extended  = forms.BooleanField(required=False, help_text="record estesi|I record avranno anche i campi per la gestione della biblioteca (se presenti nel file di input)")
 667.253 +    random_password = forms.BooleanField(required=False,
 667.254 +                                         help_text="Generazione password|forza generazione di password casuali di 8 caratteri")
 667.255 +
 667.256 +    def clean_maingroup(self):
 667.257 +        if not self.cleaned_data['maingroup']:
 667.258 +            raise util.ValidationError("Devi indicare il 'maingroup'")
 667.259 +        return self.cleaned_data['maingroup']
 667.260 +
 667.261 +    def clean(self):
 667.262 +
 667.263 +        for key in ('user_file', 'maingroup'):
 667.264 +            if key not in self.cleaned_data:
 667.265 +                raise util.ValidationError("Missing key '%s'" % key)
 667.266 +                
 667.267 +
 667.268 +        name, ext = os.path.splitext(self.cleaned_data['user_file'].name)
 667.269 +        idf, file_name = tempfile.mkstemp(suffix="." + ext)
 667.270 +        f = open(file_name, 'w')
 667.271 +        txt = self.cleaned_data['user_file'].read()
 667.272 +        f.write(txt)
 667.273 +        f.close()
 667.274 +
 667.275 +        b = bulk_users.BulkUsers(maingroup=self.cleaned_data['maingroup'],
 667.276 +                                 random_password=self.cleaned_data['random_password'],
 667.277 +                                 )
 667.278 +        b.user_format = self.cleaned_data['user_format']
 667.279 +        try:
 667.280 +            b.read_file(file_name, file_format=self.cleaned_data['file_format'],)
 667.281 +            self.bulk = b
 667.282 +        except isi.exc.WrongFileFormat, e:
 667.283 +            raise util.ValidationError(e.message.replace('di input', self.cleaned_data['user_file'].name))
 667.284 +        except isi.exc.MissingCourseMapping, e:
 667.285 +            raise util.ValidationError(e.message)
 667.286 +        return self.cleaned_data
 667.287 +
 667.288 +    def save(self):
 667.289 +        self.bulk.as_isi(filename="%s/static/utenti/users.csv" % settings.CWD,
 667.290 +                 extended=self.cleaned_data['extended'])
 667.291 +        return self.bulk
 667.292 +
 667.293 +        
 667.294 +class ExpirePassword(forms.Form):
 667.295 +
 667.296 +    model = forms.CharField(max_length=20)
 667.297 +    name  = forms.CharField(max_length=20)
 667.298 +
 667.299 +    def get_obj(self):
 667.300 +        if self.cleaned_data['model'] == 'user':
 667.301 +            obj = l.get_samba_user(self.cleaned_data['name'])
 667.302 +        else:     
 667.303 +            obj = l.get_group(self.cleaned_data['name'])
 667.304 +        return obj
 667.305 +
 667.306 +    def save(self):
 667.307 +        
 667.308 +        self.get_obj().expire_password(samba=True)
 667.309 +        return obj
 667.310 +        
 667.311 +class CreateLinks(forms.Form):
 667.312 +
 667.313 +    name  = forms.CharField(max_length=20)
 667.314 +
 667.315 +    def save(self):
 667.316 +        obj = l.get_group(self.cleaned_data['name'])
 667.317 +        obj.create_links()
 667.318 +        return obj
 667.319 +
 667.320 +
 667.321 +class NewGroupForm(forms.Form):
 667.322 +
 667.323 +    name  = forms.CharField(max_length=20)
 667.324 +
 667.325 +    def save(self):
 667.326 +        try:
 667.327 +            group = l.add_group(self.cleaned_data['name'])
 667.328 +        except:
 667.329 +            pass
 667.330 +        return group
 667.331 +
 667.332 +
 667.333 +class QuotaSet(ExpirePassword):
 667.334 +
 667.335 +    soft_space_limit  = forms.IntegerField(help_text="Space|limite accettato, superabile per un breve periodo di tempo",
 667.336 +                                           label="Spazio permesso (MB)")
 667.337 +    hard_space_limit  = forms.IntegerField(help_text="Space|limite massimo (maggiore di 'spazio permesso')", label="Spazio massimo (MB)")
 667.338 +
 667.339 +##    soft_file_limit  = forms.IntegerField(help_text="Numero file|limite accettato per un breve periodo di tempo")
 667.340 +##    hard_file_limit  = forms.IntegerField(help_text="numero file|limite massimo")
 667.341 +
 667.342 +    def clean(self):
 667.343 +        s1 = self.cleaned_data['soft_space_limit'] * 1024
 667.344 +        s2 = self.cleaned_data['hard_space_limit'] * 1024
 667.345 +
 667.346 +        if s2 < s1:
 667.347 +            raise util.ValidationError("Spazio massimo deve essere superiore a spazio permesso")
 667.348 +
 667.349 +        return self.cleaned_data
 667.350 +
 667.351 +    def save(self):
 667.352 +        s1 = self.cleaned_data['soft_space_limit'] * 1024
 667.353 +        s2 = self.cleaned_data['soft_space_limit'] * 1024
 667.354 +#        l1 = self.cleaned_data['soft_file_limit']
 667.355 +#        l2 = self.cleaned_data['soft_file_limit']
 667.356 +
 667.357 +        obj = self.get_obj()
 667.358 +        if self.cleaned_data['model'] == 'user':
 667.359 +            obj.set_quota(s1, s2, 0,0)
 667.360 +        else:
 667.361 +            obj.set_members_quota(s1, s2, 0,0 )
 667.362 +        return obj
   668.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   668.2 +++ b/web/users/views.py	Mon Apr 26 11:16:23 2010 +0200
   668.3 @@ -0,0 +1,295 @@
   668.4 +# -*- coding: utf-8 -*-
   668.5 +
   668.6 +# Copyright (C) 2010, Sandro Dentella <[email protected]>
   668.7 +#
   668.8 +#  This program is free software: you can redistribute it and/or modify
   668.9 +#  it under the terms of the GNU General Public License as published by
  668.10 +#  the Free Software Foundation, either version 3 of the License, or
  668.11 +#  (at your option) any later version.
  668.12 +#
  668.13 +#  This program is distributed in the hope that it will be useful,
  668.14 +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  668.15 +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  668.16 +#  GNU General Public License for more details.
  668.17 +#
  668.18 +#  You should have received a copy of the GNU General Public License
  668.19 +#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  668.20 +
  668.21 +
  668.22 +from vov.template import mako_loader
  668.23 +from vov.template.mako_loader import render_to_response
  668.24 +from django.template import RequestContext
  668.25 +from django.http import HttpResponseRedirect, HttpResponse
  668.26 +from vov.views.decorators import login_required
  668.27 +from django.views.decorators.csrf import csrf_protect
  668.28 +from isi import srv, models, exc
  668.29 +from django.contrib import messages
  668.30 +from vov.views import mgeneric
  668.31 +import user_forms
  668.32 +import isi
  668.33 +
  668.34 +from pumpkin import filters
  668.35 +
  668.36 +l = isi.Manager(web=True)
  668.37 +
  668.38 +@login_required
  668.39 +def object_list(request, model, group_name=None):
  668.40 +
  668.41 +    if model == 'group':
  668.42 +        groups = sorted(l.pumpkin_conn.search(models.PosixGroup), key=lambda x: x.name)
  668.43 +        template_name = "users/group_list.mako"
  668.44 +        context = {'groups' : groups}
  668.45 +
  668.46 +    elif model == 'user':
  668.47 +
  668.48 +        if group_name:
  668.49 +            group = l.get_group(group_name)
  668.50 +            users = group.members_as_users()
  668.51 +
  668.52 +        else:
  668.53 +            users = l.pumpkin_conn.search(models.PosixUser)
  668.54 +            group = None
  668.55 +        template_name = "users/group_detail.mako"
  668.56 +        context = {'users' : users, 'group' : group, 'group_name' : group_name}
  668.57 +
  668.58 +    return mako_loader.render_to_response(
  668.59 +        template_name, context,
  668.60 +        context_instance=RequestContext(request),)
  668.61 +    
  668.62 +    
  668.63 +@login_required
  668.64 +def object_detail(request, model, name):
  668.65 +
  668.66 +    context = {}
  668.67 +    try:
  668.68 +        if model == 'group':
  668.69 +            group = l.get_group(name)
  668.70 +            template_name = "users/group_detail.mako"
  668.71 +            context = {'group' : group, 'group_name' : group.name, 'users' : group.members_as_users()}
  668.72 +
  668.73 +        elif model == 'user':
  668.74 +            user = l.get_user(name)
  668.75 +            template_name = "users/user_detail.mako"
  668.76 +            context = {'u' : user}
  668.77 +
  668.78 +        elif model == 'classe':
  668.79 +            classe = l.get_group(name)
  668.80 +            template_name = "users/classe_detail.mako"
  668.81 +            context = {'classe' : classe}
  668.82 +    except exc.MissingMatch, e:
  668.83 +        template_name = 'users/missing_object.mako'
  668.84 +        context = {'model' : model, 'name' : name}
  668.85 +
  668.86 +    return mako_loader.render_to_response(
  668.87 +        template_name, context, context_instance=RequestContext(request),)
  668.88 +    
  668.89 +
  668.90 +def test_tab(request):
  668.91 +    return mako_loader.render_to_response(
  668.92 +        'users/test.mako', {}, context_instance=RequestContext(request),)
  668.93 +    
  668.94 +    
  668.95 +@login_required
  668.96 +def start(request):
  668.97 +
  668.98 +    if not request.user.is_staff:
  668.99 +        return HttpResponseRedirect('/navigazione/conf/')
 668.100 +    context = {
 668.101 +        'classes' : sorted(srv.get_classes())
 668.102 +    }
 668.103 +        
 668.104 +    return mako_loader.render_to_response(
 668.105 +        'users/start.mako', context, context_instance=RequestContext(request),)
 668.106 +    
 668.107 +    
 668.108 +@login_required
 668.109 +def change_password(request, username):
 668.110 +
 668.111 +    class MyPasswordForm(user_forms.PasswordForm):
 668.112 +        username = request.user.username
 668.113 +
 668.114 +    if request.method == 'POST': # If the form has been submitted...
 668.115 +        form = user_forms.PasswordForm(request.POST) # A form bound to the POST data
 668.116 +        form.admin_username = request.user.username
 668.117 +        if form.is_valid(): # All validation rules pass
 668.118 +            username = form.save()
 668.119 +            messages.success(request, "Password cambiata per utente %s" % username)
 668.120 +            return HttpResponseRedirect('/views/close_popup/?no_reload=1') 
 668.121 +    else:
 668.122 +        form = user_forms.PasswordForm() 
 668.123 +
 668.124 +    context = {'form' : form,'username' : username}
 668.125 +
 668.126 +    return mako_loader.render_to_response('users/change_password_form.mako', context,
 668.127 +                                   context_instance=RequestContext(request),)
 668.128 +
 668.129 +    
 668.130 +@login_required
 668.131 +def edit_user(request, logname):
 668.132 +
 668.133 +    try:
 668.134 +        user = l.get_samba_user(logname)
 668.135 +
 668.136 +        if request.method == 'POST': # If the form has been submitted...
 668.137 +            form = user_forms.UserForm(request.POST) # A form bound to the POST data
 668.138 +            if form.is_valid(): # All validation rules pass
 668.139 +                user = form.save()
 668.140 +                messages.success(request, 'Modificato utente %s' % user )
 668.141 +                return HttpResponseRedirect('/users/user/detail/%s/?popup=1' % user.logname) 
 668.142 +        else:
 668.143 +            form = user_forms.UserForm(initial=user.as_dict()) # An unbound form
 668.144 +
 668.145 +        context = {'form' : form, 'obj' : user}
 668.146 +    except:
 668.147 +        context = {'name' : logname}
 668.148 +        return mako_loader.render_to_response('users/missing_object.mako',
 668.149 +                                              context, context_instance=RequestContext(request),)
 668.150 +        
 668.151 +
 668.152 +    return mako_loader.render_to_response('users/user_form_update.mako', context,
 668.153 +                                   context_instance=RequestContext(request),)
 668.154 +
 668.155 +@login_required
 668.156 +def add_user(request):
 668.157 +
 668.158 +    if request.method == 'POST': # If the form has been submitted...
 668.159 +        form = user_forms.NewUserForm(request.POST) # A form bound to the POST data
 668.160 +        if form.is_valid(): # All validation rules pass
 668.161 +            user = form.save()
 668.162 +            messages.success(request, 'Aggiunto utente %s' % user )
 668.163 +            return HttpResponseRedirect('/users/user/detail/%s/?popup=1' % user.logname) 
 668.164 +    else:
 668.165 +        form = user_forms.NewUserForm() # An unbound form
 668.166 +
 668.167 +    context = {'form' : form, }
 668.168 +
 668.169 +    return mako_loader.render_to_response('users/user_form.mako', context,
 668.170 +                                   context_instance=RequestContext(request),)
 668.171 +
 668.172 +@login_required
 668.173 +def add_group(request):
 668.174 +
 668.175 +    if request.method == 'POST': # If the form has been submitted...
 668.176 +        form = user_forms.NewGroupForm(request.POST) # A form bound to the POST data
 668.177 +        if form.is_valid(): # All validation rules pass
 668.178 +            group = form.save()
 668.179 +            messages.success(request, 'Aggiunto gruppo %s' % group )
 668.180 +            return HttpResponseRedirect('/users/group/detail/%s/?popup=1' % group.name) 
 668.181 +    else:
 668.182 +        form = user_forms.NewGroupForm() # An unbound form
 668.183 +
 668.184 +    context = {'form' : form, }
 668.185 +
 668.186 +    return mako_loader.render_to_response('users/group_form.mako', context,
 668.187 +                                   context_instance=RequestContext(request),)
 668.188 +
 668.189 +@login_required
 668.190 +def add_bulk_user(request):
 668.191 +
 668.192 +    if request.method == 'POST': # If the form has been submitted...
 668.193 +        form = user_forms.BulkUserForm(request.POST, request.FILES) # A form bound to the POST data
 668.194 +        if form.is_valid(): # All validation rules pass
 668.195 +            n_users = form.save()
 668.196 +            messages.success(request, 'Aggiunti %s utenti' % n_users )
 668.197 +            return HttpResponseRedirect('/views/close_popup/')
 668.198 +    else:
 668.199 +        form = user_forms.BulkUserForm() # An unbound form
 668.200 +
 668.201 +    context = {'form' : form, }
 668.202 +
 668.203 +    return mako_loader.render_to_response('users/user_bulk_form.mako', context,
 668.204 +                                   context_instance=RequestContext(request),)
 668.205 +
 668.206 +@login_required
 668.207 +def convert(request):
 668.208 +
 668.209 +    if request.method == 'POST': # If the form has been submitted...
 668.210 +        form = user_forms.ConvertUserForm(request.POST, request.FILES) # A form bound to the POST data
 668.211 +        if form.is_valid(): # All validation rules pass
 668.212 +            bulk = form.save()
 668.213 +
 668.214 +            context = {'form' : form, 'bulk': bulk}
 668.215 +            return mako_loader.render_to_response('users/user_convert.mako', context,
 668.216 +                                   context_instance=RequestContext(request),)
 668.217 +
 668.218 +    else:
 668.219 +        form = user_forms.ConvertUserForm() # An unbound form
 668.220 +
 668.221 +    context = {'form' : form}
 668.222 +    return mako_loader.render_to_response('users/user_convert_form.mako', context,
 668.223 +                                   context_instance=RequestContext(request),)
 668.224 +
 668.225 +class DelUser(mgeneric.Obj):
 668.226 +
 668.227 +    def __init__(self, request, logname):
 668.228 +
 668.229 +        self.post_delete_redirect = '/views/close_popup/?no_reload=1'
 668.230 +        self.user = l.get_user(logname)
 668.231 +        self.request = request
 668.232 +        self.value = u'%s (%s %s)' % (self.user.logname, self.user.first_name, self.user.last_name)
 668.233 +        self.extra_form = '<input type="hidden" name="home_mode" value="%s">' % self.request.GET['home_mode']
 668.234 +
 668.235 +    def delete(self):
 668.236 +        self.user.delete(home_mode=self.request.POST['home_mode'])
 668.237 +        self.message = 'Eliminato utente: %s' % self.user.logname
 668.238 +        l.logger.debug('Eliminato host %s' % self.user.logname)
 668.239 +
 668.240 +
 668.241 +@login_required
 668.242 +def del_user(request, logname):
 668.243 +
 668.244 +    obj = DelUser(request, logname)
 668.245 +    return mgeneric.delete_non_model(request, obj=obj, )
 668.246 +
 668.247 +@login_required
 668.248 +def create_links(request, name):
 668.249 +
 668.250 +    if request.method == 'POST': # If the form has been submitted...
 668.251 +        form = user_forms.CreateLinks(request.POST, request.FILES) # A form bound to the POST data
 668.252 +        if form.is_valid(): # All validation rules pass
 668.253 +            classe = form.save()
 668.254 +            messages.success(request, 'Rigenerati link per classe %s' % classe )
 668.255 +            return HttpResponseRedirect('/views/close_popup/?no_reload=1')
 668.256 +    else:
 668.257 +        form = user_forms.CreateLinks() # An unbound form
 668.258 +
 668.259 +    context = {'form' : form, 'name' : name}
 668.260 +
 668.261 +    return mako_loader.render_to_response('users/create_links.mako', context,
 668.262 +                                   context_instance=RequestContext(request),)
 668.263 +
 668.264 +
 668.265 +@login_required
 668.266 +def expire_password(request, model, name):
 668.267 +
 668.268 +    if request.method == 'POST': # If the form has been submitted...
 668.269 +        form = user_forms.ExpirePassword(request.POST, request.FILES) # A form bound to the POST data
 668.270 +        if form.is_valid(): # All validation rules pass
 668.271 +            classe = form.save()
 668.272 +            messages.success(request, 'Forzata scadenza password %s' % classe )
 668.273 +            return HttpResponseRedirect('/views/close_popup/?no_reload=1')
 668.274 +    else:
 668.275 +        form = user_forms.ExpirePassword() # An unbound form
 668.276 +
 668.277 +    context = {'form' : form, 'name' : name, 'model' : model}
 668.278 +
 668.279 +    return mako_loader.render_to_response('users/expire_password.mako', context,
 668.280 +                                   context_instance=RequestContext(request),)
 668.281 +
 668.282 +@login_required
 668.283 +def set_quota(request, model, name):
 668.284 +
 668.285 +    if request.method == 'POST': # If the form has been submitted...
 668.286 +        form = user_forms.QuotaSet(request.POST, request.FILES) # A form bound to the POST data
 668.287 +        if form.is_valid(): # All validation rules pass
 668.288 +            classe = form.save()
 668.289 +            messages.success(request, 'Impostata quota')
 668.290 +            return HttpResponseRedirect('/views/close_popup/?no_reload=1')
 668.291 +    else:
 668.292 +        form = user_forms.QuotaSet() # An unbound form
 668.293 +
 668.294 +    context = {'form' : form, 'name' : name, 'model' : model}
 668.295 +
 668.296 +    return mako_loader.render_to_response('users/quota_set.mako', context,
 668.297 +                                   context_instance=RequestContext(request),)
 668.298 +