ltsp-cluster-control-2.0.3/0000775000175000017500000000000012026403130016030 5ustar stgraberstgraberltsp-cluster-control-2.0.3/scripts/0000775000175000017500000000000012026403130017517 5ustar stgraberstgraberltsp-cluster-control-2.0.3/scripts/rdp.config0000664000175000017500000000134512026403127021504 0ustar stgraberstgraberCRONTAB_01 => text CRONTAB_02 => text CRONTAB_03 => text CRONTAB_04 => text CRONTAB_05 => text CRONTAB_06 => text CRONTAB_07 => text CRONTAB_08 => text CRONTAB_09 => text CRONTAB_10 => text INVENTORY_NUMBER => text LANG => text MIC_VOLUME => text PRINTER_0_DEVICE => text PXE_CONFIG => text RDP_SOUND => list:nopulse,pulse-oss RDP_OPTIONS => text RDP_SERVER => text SCANNER => list:True,False SCREEN_07 => list:ldm,rdesktop SOUND_DAEMON => list:True,False TIMESERVER => text TIMEZONE => text SHUTDOWN_TIME => text X_ARGS => text XKBLAYOUT => text XKBVARIANT => text XRANDR_AUTO_MULTIHEAD => list:True,False XRANDR_MODE_0 => text XRANDR_MODE_1 => text XRANDR_OUTPUT_0 => text XRANDR_OUTPUT_1 => text XINITRC_PROMPT_ON_EXIT => list:True,False ltsp-cluster-control-2.0.3/scripts/control-center.py0000664000175000017500000001274412026403127023045 0ustar stgraberstgraber#/usr/bin/python import pgdb, os, sys #FIXME: This should be a configuration file db_user="ltsp" db_password="ltspcluster" db_host="localhost" db_database="ltsp" #Init DB db=pgdb.connect(user=db_user,password=db_password,host=db_host,database=db_database) cursor=db.cursor() def Cleanup(): "Reset all temporary tables" cursor.execute("TRUNCATE status;") db.commit() print "Cleaned status table" cursor.execute("TRUNCATE log;") cursor.execute("ALTER SEQUENCE log_id_key_seq RESTART WITH 1;") db.commit() print "Cleaned log table" cursor.execute("TRUNCATE computershw;") db.commit() print "Cleaned computershw table" def Rebuild(): "Rebuild the nodes tree" cursor.execute("SELECT rebuild_tree()") db.commit() print "Regenerated tree" def CleanAttributes(attr_list): "Remove all attributes, keeping only the ones in attr_list" where='' for attr in attr_list: if where == '': where+="name != '"+attr+"'" where+=" AND name != '"+attr+"'" cursor.execute("SELECT id FROM attributesdef WHERE "+where) items=cursor.fetchall() for item in items: cursor.execute("DELETE FROM attributes WHERE attributesdef_id='"+str(item[0])+"'") cursor.execute("DELETE FROM attributesdefdict WHERE attributesdef_id='"+str(item[0])+"'") cursor.execute("DELETE FROM attributesselect WHERE attributesdef_id='"+str(item[0])+"'") cursor.execute("DELETE FROM attributesdef WHERE "+where) db.commit() def UpdateAttributes(): "Open an attribute definition file and update the attribute list from it" if len(sys.argv) < 2: print "ERROR: You need to specify a configuration file" return None if not os.path.exists(sys.argv[1]): print "ERROR: File doesn't exist" return None config=open(sys.argv[1],"r") attr_list=set() for line in config.readlines(): attr_name, attr_type=line.strip().split(" => ") #FIXME: We should handle bogus config file here attr_list.add(attr_name) cursor.execute("SELECT id FROM attributesdef WHERE name='"+attr_name+"'") # Add missing attributes if len(cursor.fetchall()) == 0: if attr_type == "text": cursor.execute("INSERT INTO attributesdef (name) VALUES ('"+attr_name+"')") elif attr_type == "multilist": cursor.execute("INSERT INTO attributesdef (name,attributetype) VALUES ('"+attr_name+"','2')") elif attr_type.startswith("list"): list=attr_type.replace("list:","").split(",") cursor.execute("INSERT INTO attributesdef (name,attributetype) VALUES ('"+attr_name+"','1')") cursor.execute("SELECT id FROM attributesdef WHERE name='"+attr_name+"'") attr_id=cursor.fetchall()[0][0] for value in list: cursor.execute("INSERT INTO attributesdefdict (attributesdef_id,value,sortval) VALUES ('"+str(attr_id)+"','"+value+"','0')") db.commit() else: #FIXME: Updating attribute type should happen here pass #Drop removed attributes CleanAttributes(attr_list) config.close() def ReorderDatabase(): # Clean all temporary tables to make sure we don't have constraint conflict there Cleanup() # Drop all contraints for now cursor.execute("ALTER TABLE attributes DROP CONSTRAINT attributes_attributesdef_id_fkey;") cursor.execute("ALTER TABLE attributesdefdesc DROP CONSTRAINT attributesdefdesc_attributesdef_id_fkey;") cursor.execute("ALTER TABLE attributesdefdict DROP CONSTRAINT attributesdefdict_attributesdef_id_fkey;") cursor.execute("ALTER TABLE attributesselect DROP CONSTRAINT attributesselect_attributesdef_id_fkey;") db.commit() # Reorder attributesdef cursor.execute("SELECT id FROM attributesdef ORDER BY id ASC") attributes=cursor.fetchall() attr_id=0 for attribute in attributes: attr_id+=1 cursor.execute("UPDATE attributes SET attributesdef_id='"+str(attr_id)+"' WHERE attributesdef_id='"+str(attribute[0])+"'") cursor.execute("UPDATE attributesdefdesc SET attributesdef_id='"+str(attr_id)+"' WHERE attributesdef_id='"+str(attribute[0])+"'") cursor.execute("UPDATE attributesdefdict SET attributesdef_id='"+str(attr_id)+"' WHERE attributesdef_id='"+str(attribute[0])+"'") cursor.execute("UPDATE attributesselect SET attributesdef_id='"+str(attr_id)+"' WHERE attributesdef_id='"+str(attribute[0])+"'") cursor.execute("UPDATE attributesdef SET id='"+str(attr_id)+"' WHERE id='"+str(attribute[0])+"'") db.commit() # Restore the constraints cursor.execute("ALTER TABLE attributes ADD CONSTRAINT attributes_attributesdef_id_fkey FOREIGN KEY (attributesdef_id) REFERENCES attributesdef(id) ON UPDATE CASCADE;") cursor.execute("ALTER TABLE attributesdefdesc ADD CONSTRAINT attributesdefdesc_attributesdef_id_fkey FOREIGN KEY (attributesdef_id) REFERENCES attributesdef(id) ON UPDATE CASCADE;") cursor.execute("ALTER TABLE attributesdefdict ADD CONSTRAINT attributesdefdict_attributesdef_id_fkey FOREIGN KEY (attributesdef_id) REFERENCES attributesdef(id) ON UPDATE CASCADE;") cursor.execute("ALTER TABLE attributesselect ADD CONSTRAINT attributesselect_attributesdef_id_fkey FOREIGN KEY (attributesdef_id) REFERENCES attributesdef(id) ON UPDATE CASCADE;") db.commit() #FIXME: This should be implemented using parameters Cleanup() UpdateAttributes() ReorderDatabase() Rebuild() #Close DB db.close() ltsp-cluster-control-2.0.3/scripts/reset.sh0000664000175000017500000000016512026403127021205 0ustar stgraberstgraber#!/bin/sh set -e sudo -u postgres dropdb ltsp sudo -u postgres createdb ltsp -O ltsp sudo -u postgres psql ltsp < $1 ltsp-cluster-control-2.0.3/scripts/control-center-clean-log0000664000175000017500000000045012026403127024244 0ustar stgraberstgraber#!/bin/sh # Remove old logs from database # FIXME : Should be merged to control-center.py # Number of days of logs to keep in history MAX_AGE=${MAX_AGE:-"5"} DB=${DB:-"ltsp"} export LC_ALL=C su postgres -c "echo delete from log where ts \< now\(\) - interval \'$MAX_AGE days\' | psql -d $DB" ltsp-cluster-control-2.0.3/scripts/rdp+ldm.config0000664000175000017500000000224512026403127022254 0ustar stgraberstgraberCRONTAB_01 => text CRONTAB_02 => text CRONTAB_03 => text CRONTAB_04 => text CRONTAB_05 => text CRONTAB_06 => text CRONTAB_07 => text CRONTAB_08 => text CRONTAB_09 => text CRONTAB_10 => text CUPS_SERVER => text FRONT_MIC_VOLUME => text INVENTORY_NUMBER => text LANG => text LDM_AUTOLOGIN => list:True,False LDM_DIRECTX => list:True,False LDM_GUESTLOGIN => list:True,False LDM_NODMPS => list:True,False LDM_PASSWORD => text LDM_PRINTER_DEFAULT => text LDM_PRINTER_LIST => multilist LDM_SERVER => text LDM_USERNAME => text LOCAL_APPS_MENU_ITEMS => text LOCAL_APPS_MENU => list:True,False MIC_VOLUME => text PRINTER_0_DEVICE => text PXE_CONFIG => text REMOTE_APPS => list:True,False RDP_OPTIONS => text RDP_SOUND => list:nopulse,pulse-oss SOUND_DAEMON => list:True,False RDP_SERVER => text SCANNER => list:True,False SCREEN_07 => list:ldm,rdesktop SHUTDOWN_TIME => text START_ITALC => list:True,False TIMESERVER => text TIMEZONE => text X_ARGS => text X_NUMLOCK => list:True,False XKBLAYOUT => text XKBVARIANT => text XRANDR_AUTO_MULTIHEAD => list:True,False XRANDR_MODE_0 => text XRANDR_MODE_1 => text XRANDR_OUTPUT_0 => text XRANDR_OUTPUT_1 => text XINITRC_PROMPT_ON_EXIT => list:True,False ltsp-cluster-control-2.0.3/AUTHORS0000664000175000017500000000032412026403127017105 0ustar stgraberstgraber * Nicolas Dufresne, 2004 Revolution Linux * Benoit des Ligneris, 2004-2008 Revolution Linux * Francis Giraldeau, 2004-2008 Revolution Linux * Stephane Graber , 2008-2009 Revolution Linux ltsp-cluster-control-2.0.3/release.conf0000664000175000017500000000005012026403127020320 0ustar stgraberstgraberNAME=ltsp-cluster-control VERSION=2.0.3 ltsp-cluster-control-2.0.3/test/0000775000175000017500000000000012026403130017007 5ustar stgraberstgraberltsp-cluster-control-2.0.3/test/graph_stats_insert.plot0000664000175000017500000000066312026403127023625 0ustar stgraberstgraberset boxwidth 0.9 absolute set style fill empty border -1 set style data histograms set style histogram gap 1 title offset character 0, 0, 0 set datafile missing '-' set title "Mean time to perform inserts depending on the tree deep" set key off set ylabel "Mea time (ms)" set yrange [0:] set xlabel "Tree deep" set terminal png set output "graph_stats_insert.png" #set xtic rotate plot 'graph_stats_insert.out' using 2:xticlabels(1) ltsp-cluster-control-2.0.3/test/req.py0000664000175000017500000000343212026403127020160 0ustar stgraberstgraber#!/usr/bin/env python import psycopg2 import os import time import random import math import pprint import sys import unittest import string class DBManager(): def __init__(self, dbname, user, password, host): self.dbname = dbname self.user = user self.password = password self.host = host self.pp = pprint.PrettyPrinter(indent=4) def connect(self): self.conn = psycopg2.connect("dbname=%s user=%s password=%s host=%s" % (self.dbname, self.user, self.password, self.host)) self.curs = self.conn.cursor() print "connected" def close(self): self.conn.close() def test01(self): self.curs.execute("SELECT id, id_parent, mac FROM nodes WHERE nodetype='1';") res = self.curs.fetchall() duplicates = {} for r in res: mac = string.lower(r[2]) dup = duplicates.get(mac) if dup: duplicates[mac].append(r) else: duplicates[mac] = [r] # Search for duplicates real_dup = {} for m,r in duplicates.items(): if len(r) > 1: real_dup[m] = r self.pp.pprint(real_dup) if __name__=="__main__": from optparse import OptionParser p = OptionParser() p.add_option("-d", dest="dbname", help="Database name") p.add_option("-u", dest="dbuser", help="Username") p.add_option("-p", dest="dbpass", help="Password") p.add_option("-l", dest="host", help="Hostname") (o, args) = p.parse_args() if o.dbname is None or o.dbuser is None or o.dbpass is None or o.host is None: p.print_help() sys.exit(1) t = DBManager(o.dbname, o.dbuser, o.dbpass, o.host) t.connect() t.test01() t.close() ltsp-cluster-control-2.0.3/test/stats.py0000664000175000017500000000207412026403127020530 0ustar stgraberstgraber#!/usr/bin/env python import string from statlib import stats import pprint import sys # Calculate statistics for gnuplot tests = ["insert", "move", "nstree", "adjlst"] #deep = [3,10] deep = [10] stats_data = {} for t in tests: stats_data[t] = {} for d in deep: tag = "%s-d%s" % (t,d) stats_data[t][d] = {} samples = [] f_path = "test-%s-n1000_d%s.out" % (t,d) print "processing %s" % f_path f = open(f_path,'r') for line in f.readlines(): data = float(string.split(line.strip())[1]) * 1000 samples.append(data) stats_data[t][d]["mean"] = stats.mean(samples) stats_data[t][d]["stdev"] = stats.stdev(samples) pp = pprint.PrettyPrinter(indent=4) pp.pprint(stats_data) def output(test_name): f = open("graph_stats_%s.out" % test_name, "w") keys = stats_data[test_name].keys() keys.sort() for k in keys: f.write("%s %f %f\n" % (k, stats_data[test_name][k]["mean"], stats_data[test_name][k]["stdev"])) f.close() for t in tests: output(t) ltsp-cluster-control-2.0.3/test/parse-vmstat.py0000664000175000017500000000200112026403127022006 0ustar stgraberstgraber#!/usr/bin/python import string import sys import os from statlib import stats f_name = sys.argv[1] f = open(f_name,"r") lines = f.readlines()[2:] f.close() f = open(f_name + ".parsed","w") metrics = ["bi","bo","sum"] stats_data = ["mean","stdev"] data = {} for metric in metrics: data[metric] = {} data[metric]["samples"] = [] for stat in stats_data: data[metric][stat] = 0 print data for i,line in enumerate(lines): s = string.split(line) bi = int(s[8]) bo = int(s[9]) sum = bi + bo f.write("%s %s %s %s\n" % (i,s[8],s[9],sum)) data["bi"]["samples"].append(int(bi)) data["bo"]["samples"].append(int(bo)) data["sum"]["samples"].append(sum) f.close() print data for metric in metrics: data[metric]["mean"] = stats.mean(data[metric]["samples"]) data[metric]["stdev"] = stats.stdev(data[metric]["samples"]) f = open(f_name + ".stats","w") for metric in metrics: f.write("%s %s %s\n" % (metric, data[metric]["mean"],data[metric]["stdev"])) f.close() ltsp-cluster-control-2.0.3/test/graph_stats_move.plot0000664000175000017500000000065512026403127023270 0ustar stgraberstgraberset boxwidth 0.9 absolute set style fill empty border -1 set style data histograms set style histogram gap 1 title offset character 0, 0, 0 set datafile missing '-' set title "Mean time to perform move depending on the tree deep" set key off set ylabel "Mean time (ms)" set yrange [0:] set xlabel "Tree deep" set terminal png set output "graph_stats_move.png" #set xtic rotate plot 'graph_stats_move.out' using 2:xticlabels(1) ltsp-cluster-control-2.0.3/test/graph_insert.plot0000664000175000017500000000051112026403127022377 0ustar stgraberstgraberset boxwidth 0.9 absolute set style fill empty border -1 set title "Client CPU usage latency depending on tlength setting (resample=trivial)" set ylabel "CPU usage (jiffies - 250Hz)" set xlabel "tlength (bytes)" set terminal png set output "graph_insert.png" plot 'test-insert-n1000_d10.out' using 1:2 with lines title "deep=10" ltsp-cluster-control-2.0.3/test/graph_stats_search.plot0000664000175000017500000000113012026403127023554 0ustar stgraberstgraberset boxwidth 0.9 absolute set style fill empty border -1 set style data histograms set style histogram errorbars gap 1 title offset character 0, 0, 0 set datafile missing '-' set title "Mean time to perform searches depending on the tree deep and search model" set key off set ylabel "Mean time (ms)" set yrange [0:] set xlabel "Tree deep and model" set terminal png set output "graph_stats_search.png" #set xtic rotate set key inside left top title "model" plot 'graph_stats_nstree.out' using 2:3:xticlabels(1) title "nstree", \ 'graph_stats_adjlst.out' using 2:3:xticlabels(1) title "adjlst" ltsp-cluster-control-2.0.3/test/btree.py0000775000175000017500000002031312026403127020472 0ustar stgraberstgraber#!/usr/bin/env python import psycopg2 import os import time import random import math import pprint import sys import unittest class DBManager(): def __init__(self, dbname, user, password, host): self.dbname = dbname self.user = user self.password = password self.host = host self.t_insert = [] self.t_move = [] self.pp = pprint.PrettyPrinter(indent=4) self.stats = {} self.reset_stats() def reset_stats(self): self.stats["insert"] = [] self.stats["move"] = [] self.stats["nstree"] = [] self.stats["adjlst"] = [] def save_stats(self, basename): ts = time.strftime("%Y%m%d%H%M%S") os.mkdir(ts) """save all statistics""" for k in self.stats.keys(): if len(self.stats[k]) > 0: f = open(os.path.join(ts,"test-%s-%s.out" % (k, basename)), "w") for i, v in enumerate(self.stats[k]): f.write("%s %s\n" % (i, v)) f.close() def connect(self): self.conn = psycopg2.connect("dbname=%s user=%s password=%s host=%s" % (self.dbname, self.user, self.password, self.host)) self.curs = self.conn.cursor() print "connected" def close(self): self.conn.close() def insert_node(self, id_parent, name): """insert one node""" t1 = time.time() self.curs.execute("""INSERT into nodes (id_parent,name) values ('%s','%s') """ % (id_parent, name)) self.conn.commit() t2 = time.time() t = t2 - t1 self.stats["insert"].append(t) def delete_all_nodes(self): print "del" try: self.curs.execute("DROP TRIGGER nodes_delete_tr ON nodes") except: self.conn.rollback() self.curs.execute("DELETE from attributes where nodes_id > 0") self.conn.commit() self.curs.execute("DELETE FROM nodes where id > 0") self.conn.commit() print "end del" def delete_all_attributes(self): self.curs.execute("DELETE FROM attributes") self.conn.commit() def insert_nodes(self, num_nodes): """insert num_nodes for each leaves in the tree""" print "insert nodes" self.curs.execute("SELECT t1.id FROM nodes AS t1 LEFT JOIN nodes as t2 ON t1.id = t2.id_parent WHERE t2.id IS NULL AND t1.id != -1") leaves = self.curs.fetchall() if len(leaves) == 0: for j in range(num_nodes): self.insert_node(0, "test") else: for leaf in leaves: for j in range(num_nodes): self.insert_node(leaf[0], "test") def move_node(self, id, new_parent): """Move a node in the tree""" t1 = time.time() self.curs.execute("UPDATE nodes SET id_parent = '%s' WHERE id=%s" % (new_parent, id)) self.conn.commit() t2 = time.time() t = t2 - t1 self.stats["move"].append(t) def move_middle_node_to_root(self): id = self.get_middle_node() self.curs.execute("SELECT id_parent FROM nodes WHERE id='%s'" % (id)) parent = self.curs.fetchall() self.move_node(id, 0) def attribute_query_leaf_nstree(self, node_id): """Merge attributes for one leaf, nstree model""" print "nstree" attrs = {} q = """SELECT id, leftval, rightval FROM nodes WHERE id = %s""" % node_id self.curs.execute(q) rep = self.curs.fetchall() leftval = rep[0][1] rightval = rep[0][2] q = """SELECT * FROM nodes N INNER JOIN attributes A ON A.nodes_id=N.id """ q += """LEFT JOIN attributesDef AD ON A.attributesdef_id=AD.id """ q += """WHERE N.leftval<%s AND N.rightval>=%s ORDER BY N.leftval""" % (rightval, rightval) t1 = time.time() self.curs.execute(q) res = self.curs.fetchall() for r in res: attrs[r[13]] = r[10] t2 = time.time() t = t2 - t1 self.stats["nstree"].append(t) #self.pp.pprint(attrs) def attribute_query_leaf_adjlst(self, node_id): """Merge attributes for one leaf, adjacent list model""" print "adjlst" hierarchy = [node_id] attrs = {} curr_id = node_id t1 = time.time() while curr_id != 0: q = """SELECT id_parent FROM nodes WHERE id=%s""" % curr_id self.curs.execute(q) res = self.curs.fetchall() curr_id = res[0][0] hierarchy.append(curr_id) hierarchy.reverse() for level in hierarchy: q = """SELECT AD.name, A.value FROM nodes N INNER JOIN attributes A ON A.nodes_id=N.id LEFT JOIN attributesDef AD ON A.attributesdef_id=AD.id WHERE N.id=%s""" % level self.curs.execute(q) res = self.curs.fetchall() for r in res: attrs[r[0]] = r[1] t2 = time.time() t = t2 - t1 self.stats["adjlst"].append(t) #self.pp.pprint(attrs) def define_node_attribute(self, key, val, id): # Search if this attribute is already defined q = "SELECT attributesdef.id from attributesdef WHERE name='%s'" % key self.curs.execute(q) res = self.curs.fetchall() attr_id = res[0][0] q = "SELECT attributesdef.id from attributes LEFT JOIN attributesdef ON attributesdef.id=attributes.attributesdef_id WHERE nodes_id=%s AND attributesdef.name='%s'" % (id, key) self.curs.execute(q) res = self.curs.fetchall() if len(res) == 0: # If not defined, then add it q = "INSERT INTO attributes (nodes_id,attributesdef_id,value) VALUES ('%s','%s','%s')" % (id,attr_id,val) self.curs.execute(q) self.conn.commit() else: # If already defined, update it q = "UPDATE attributes SET value = '%s' where nodes_id = '%s' AND attributesdef_id = '%s'" % (val,id,attr_id) self.curs.exectute(q) self.conn.commit() def get_middle_node(self): """Search and return the middle leaf in the tree, assume that nodes are ordered""" self.curs.execute("SELECT t1.id FROM nodes AS t1 LEFT JOIN nodes as t2 ON t1.id = t2.id_parent WHERE t2.id IS NULL ORDER BY t2.id") rows = self.curs.fetchall() pos = len(rows)/2 return rows[pos][0] class TestDBManager(): def __init__(self, dbname, user, password, host): self.db = DBManager(dbname, user, password, host) self.db.connect() self.nb_nodes = 0 self.deep = 0 self.nb_iter = 0 def common(self): self.db.delete_all_nodes() self.db.delete_all_attributes() nb_child = int(round(math.pow(self.nb_nodes,1/float(self.deep)))) for i in range(self.deep): self.db.insert_nodes(nb_child) for i in range(self.nb_iter): self.db.move_middle_node_to_root() self.db.define_node_attribute("SCREEN_01","bidon",0) self.db.define_node_attribute("SCREEN_02","coucou",0) node = self.db.get_middle_node() self.db.define_node_attribute("SCREEN_01","test",node) for i in range(self.nb_iter): self.db.attribute_query_leaf_nstree(node) self.db.attribute_query_leaf_adjlst(node) self.db.save_stats("n%s_d%s" % (self.nb_nodes, self.deep)) def test01(self): self.nb_nodes = 1000 self.deep = 3 self.nb_iter = 20 self.common() def test02(self): self.nb_nodes = 1000 self.deep = 10 self.nb_iter = 20 self.common() if __name__=="__main__": from optparse import OptionParser p = OptionParser() p.add_option("-d", dest="dbname", help="Database name") p.add_option("-u", dest="dbuser", help="Username") p.add_option("-p", dest="dbpass", help="Password") p.add_option("-l", dest="host", help="Hostname") (o, args) = p.parse_args() if o.dbname is None or o.dbuser is None or o.dbpass is None or o.host is None: p.print_help() sys.exit(1) t = TestDBManager(o.dbname, o.dbuser, o.dbpass, o.host) #print "test01" #t.test01() print "test02" t.test02() print "done" ltsp-cluster-control-2.0.3/Terminal/0000775000175000017500000000000012026403130017603 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Terminal/autocreate.php0000664000175000017500000000037412026403127022462 0ustar stgraberstgrabernotFound()) { $parent=new Node($finder->getNodeID()); } } //if($parent) { echo "
";print_r($parent);echo "
"; } ?> ltsp-cluster-control-2.0.3/Terminal/session.php0000664000175000017500000000164412026403127022012 0ustar stgraberstgraber$value) { if (isset($get[$key])) { $get[$key]="$value"; } } if ($get["action"] == "") return; function getFromDB($column, $where, $from = "status") { if (!$result = select('SELECT ' . $column . ' FROM ' . $from . ' WHERE ' . $where)) { return NULL; } else return $result; } switch ($get["action"]) { case "getsessions": if ($get["username"] == "") return; $nodes=getFromDB("appservip","username='".$get["username"]."' AND code='3'"); if (!is_array($nodes)) continue; $nodes=array_unique($nodes); foreach ($nodes as $node) print $node['appservip']."\n"; break; } ?> ltsp-cluster-control-2.0.3/Terminal/TeachTools.php0000664000175000017500000000311312026403127022365 0ustar stgraberstgraber * ?action=list/ip=192.168.2.221 * */ require_once 'util/functions.php'; require_once "util/Node.php"; require_once "util/ClassroomFinder.php"; # Security : only the expected variable are assigned # No post unset($_POST); # No cookies unset($_COOKIES); # Expected variables $get["action"]=''; $get["ip"]=''; # Get the allowed variables foreach ($_GET as $key=>$value) { if (isset($get[$key])) { $get[$key]="$value"; } } # Open the current node $node=new Node(trim($get["ip"])); if ($node->notFound()) { print "ERROR : Node not found ".$get["ip"]; die(); } $classroom=new ClassroomFinder($node->getParentID()); print "CLASSROOM=".$classroom->getClassroom()."\n"; $computers=$classroom->getComputers(); if (!empty($computers)) { foreach ($computers as $computer) { if ($computer['ip'] != $get["ip"] && ($computer['code'] == '3' || $computer['code'] == '2')) { print $computer['ip'].','.$computer['mac'].','.$computer['username']."\n"; } } } ?> ltsp-cluster-control-2.0.3/Terminal/util0000777000175000017500000000000012026403127022647 2../Admin/utilustar stgraberstgraberltsp-cluster-control-2.0.3/Terminal/index.php0000664000175000017500000002673012026403127021441 0ustar stgraberstgraber * code 1 ?ip=192.168.2.221/mac=00:90:F5:2A:ED:A7/bootservip=192.168.2.253/code=1 * XTERM is booting and has its bootservip * code 2 ?ip=192.168.2.221/appservip=192.168.2.254/display=0.0/code=2 * XTERM has it appserver & display * code 3 * ?ip=192.168.2.221/appservip=192.168.2.253/display=0.0/code=3/username=3 * a user is connected * code 4 * ?ip=192.168.2.221/appservip=192.168.2.253/display=0.0/code=4/username=3 * a user is de connected * */ openlog("ltsp-directory", LOG_PID, LOG_USER); # Ensure the Db is configured if (!is_readable("util/config.php")) { $first_start = true; include "util/setup.php"; die(); } require_once 'util/functions.php'; require_once 'util/Node.php'; require_once 'util/EntityNodeFinder.php'; require_once 'util/HWGroupFinder.php'; # Security : only the expected variable are assigned # No cookies unset($_COOKIES); # Expected variables $get["debug"]=''; $get["ip"]=''; $get["password"]=''; $get["username"]=''; $get["groups"]=''; $get["mac"]=''; $get["bootservip"]=''; $get["appservip"]=''; $get["display"]=''; $get["code"]=''; $get["hwlist"]=''; $get["publickey"]=''; # Get the allowed variables from _GET and _POST foreach (array_merge($_GET,$_POST) as $key=>$value) { if (isset($get[$key])) { if (($key == "display") && ($value == 0)) { $get[$key]="0.0"; } else { $get[$key]="$value"; } } } # Delete the _GET and _POST variable unset($_GET); unset($_POST); // JMD: fix in case we mount nfs via DNS if (!isIP($get["bootservip"]) && $get["bootservip"]!='') { $get["bootservip"]=gethostbyname($get["bootservip"]); } // ND: same fix in case terminal ip is a dns // And why not doing it for all! Adding appservip if (!isIP($get["ip"]) && $get["ip"]!='') { $get["ip"]=gethostbyname($get["ip"]); } if (!isIP($get["appservip"]) && $get["appservip"]!='') { $get["appservip"]=gethostbyname($get["appservip"]); } // Make sure mac is uppercase if ($get["mac"]!='') { $get["mac"] = strtoupper($get["mac"]); } # Clean the $get variable foreach ($get as $key=>$value) { if (empty($value)) { unset($get[$key]); } } # Code 999 : Testing purpose if ($get["code"] == 999) { print "ALIVE"; die(); } # Retrieve current ip address if ($CONFIG['terminal_auth'] == 'true') { $ip=getIP(); } else { $ip=$get["ip"]; } # Code 0 : get config, logs nothing if ($get["code"] == 0) { # Connection authentication $auth = $ip==$get["ip"]; # Access node $node=new Node($get["mac"]); # Compute hw groups if ($node->hasHWgroup()) { $nodesIds = $node->getHWgroupIDs(); } $get["hwgroups"]=$hwGroups; # Set status and return LTSP returnLtsp($node,$get,$error,$auth,$nodesIds); } # Code 1 : initialize with MAC elseif ($get["code"] == 1) { # Connection authentication $auth = $ip==$get["ip"]; # Access node $node=new Node($get["mac"]); # If it is not a node, let's create it ! if ($node->notFound() && $auth) { $node=createNode($get); } # Save inventory if (isset($get["hwlist"])) { $hwList = decodeHwList($get["hwlist"]); $node->setHardware($hwList); unset($get["hwlist"]); } # Compute hw groups if ($node->hasHWgroup()) { $nodesIds = $node->getHWgroupIDs(); } $get["hwgroups"]=$hwGroups; # Set status and return LTSP if ($auth) $error=setStatus($node,$get); else $error = "Cannot set status, auth error, client ip: ".$ip." expected: ".$get["ip"]; logAccess($get); returnLtsp($node,$get,$error,$auth,$nodesIds); } # Code 2 : update status with appserver ip elseif ($get["code"] == 2) { # Connection authentication $auth = $ip==$get["ip"]; # Access node $node=new Node($get["ip"]); $status=$node->getStatus(); if ($node->hasHWgroup()) { $nodesIds = $node->getHWgroupIDs(); } # Set status and return LTSP if ($auth) $error=setStatus($node,$get); else $error = "Cannot set status, auth error, client ip: ".$ip." expected: ".$get["ip"]; logAccess($get); returnLtsp($node,$get,$error,$auth,$nodesIds); } # Code 3 : register user and groups elseif ($get["code"] == 3) { $node=new Node($get["ip"]); # Retrieve entity nodes $entityFinder = new EntityNodeFinder(strtolower($get["username"]),split(",", strtolower($get["groups"]))); $nodesIds = $entityFinder->getNodesIds(); # Add HW groups $status=$node->getStatus(); if (!empty($status["hwgroups"])) { $nodesIds = array_merge($nodesIds,split(",",$status["hwgroups"])); } # Retrieve ltsp attributes $array=$node->getExtendedLTS($nodesIds); # Authentication required to set termaccess and public keys $auth = (!($CONFIG['terminal_auth']=='true') || $get["password"]==$CONFIG["terminal_password"]); $status["termaccess"] = 0; if ($auth && $array["IS_TEACHER"]=="Y") { $status["termaccess"] = 2; } # Set status and return LTSP unset($get["password"]); unset($get["groups"]); $error=setStatus($node,$get,$status); logAccess($get); returnLtsp($array,$get,$error,$auth,$nodesIds); } # Code 4 : Logout, remove security infos elseif ($get["code"] == 4) { $node=new Node($get["ip"]); # Cleanup security parameters $get["termaccess"]=0; $get["publickey"]=''; # Set status and return LTSP $error=setStatus($node,$get); logAccess($get); returnLtsp($node,$get,$error); } else { returnLtsp("Invalid code : ".$get["code"],$get); log_error("Invalid code : ".$get["code"],$get); } die(); // No more code below this point: functions /** * * Create a node if it does not exists * */ function createNode($get) { # Try to insert the node until success $success=FALSE; $counter=0; while ((!$success) && ($counter < 10)) { @include("autocreate.php"); if(!$parent) $parent=new Node(); if ($node=$parent->createChildComputer($get["mac"])) { $success=TRUE; } else { log_error("Try number $counter, mac=".$get["mac"].", node =\"$node\"",$parent->lastError()); } $counter++; sleep(1); } if (!$success) { returnLtsp($counter.$parent->lastError(),$get); log_error($parent->lastError(),$get); die(); } return $node; } /** * True if is a IP, false otherwise. * * @return boolean */ function isIP($ip) { return ereg("^([0-2]{0,1}[0-9]{1,2}\.){3}[0-2]{0,1}[0-9]{1,2}$", $ip); } /** * * Update the status using the $get variable (including $get[code]) * */ function setStatus($node,$get,$status=NULL) { # Read status from the DB if (!isset($status)) { $status=$node->getStatus(); } # Merge the arrays if (!isset($status)) { $status=$get; } else { $status=array_merge($status,$get); } # Unset the debug column unset($status["debug"]); # Continue on setStatus error (for read only databases) # If error, add MILLE_CONFIG_ERROR to the conf file and return the default file if (!$node->setStatus($status)) { log_error($node->lastError(),$get); return $node->lastError(); } } /** * * Decode the hwList parameter * */ function decodeHwList($hardware) { $hwList = array(); foreach (split("\n",$hardware) as $line) { if (!empty($line)) { $pos=strpos($line,"="); $hwkey = substr($line,0,$pos); if ($pos < strlen($line)) $hwval = substr($line,$pos+1,strlen($line)); else $hwval = ''; $hwList[] = array('hwkey'=>$hwkey,'hwvalue'=>$hwval); } } return $hwList; } # Return the LTSP.conf file generated for this terminal function returnLtsp($node,$get,$error=NULL,$auth=true,$groups=NULL) { if (is_array($node)) { $array=$node; } elseif (strtolower(get_class($node)) != "node" || $node->notFound()) { $error=$node; $node=new Node(0); $array=$node->getLTS(); } elseif (isset($groups) && $groups!='') { $array=$node->getExtendedLTS($groups); } else { $array=$node->getLTS(); } if (is_object($error)) { log_error($error->lastError(),$get); if (!$get["debug"]) { $array["MILLE_CONFIGURATOR_ERROR"]="yes"; } } if (!$auth) { $array["MILLE_AUTH_ERROR"]="yes"; } print "[Default]\n"; foreach ($array as $key=>$value) { if ( $value == "%LOADBALANCER%" ) $value=returnGetLBServer("default"); elseif ( preg_match('/^%LOADBALANCER%(.*)%$/',$value,$group) ) $value=returnGetLBServer($group[1]); print ("$key=\"".returnGetLtspVariable($value)."\"\n"); } if ($node->id_parent > 0) print "CLUSTER_CONFIGURED=\"True\"\n"; else print "CLUSTER_CONFIGURED=\"False\"\n"; return $array; } # Get an IP address from the loadbalancer function returnGetLBServer ($group) { global $CONFIG; $lbserver=fopen("http://".$CONFIG['loadbalancer'].":8008/?group=".$group,"r"); $server=trim(fgets($lbserver)); fclose($lbserver); return $server; } # Remove the initial "'" and final "'" produced by escapeshellarg function returnGetLtspVariable($string) { $string=escapeshellarg($string); $result=substr($string,1); $result=substr($result,0,-1); return $result; } # Function to log access in the access log function logAccess($get) { $line = ','; foreach ($get as $key=>$value) { $line .= "$key=$value,"; } $line = substr($line, 0, -1); syslog(LOG_INFO,$line); } # Function to log error on a file function log_error($message,$get) { if (is_array($get)) { $line = ','; foreach ($get as $key=>$value) { $line .= "$key=$value,"; } } else { $line=",$get"; } $line .= " - " . $message; syslog(LOG_ERR,$line); } function getIP() { if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) $ip = getenv("HTTP_CLIENT_IP"); else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) $ip = getenv("HTTP_X_FORWARDED_FOR"); else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) $ip = getenv("REMOTE_ADDR"); else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) $ip = $_SERVER['REMOTE_ADDR']; else $ip = "unknown"; return($ip); } # Function for debugging on the screen function debug($msg){ $conf = array('error_prepend' => '', 'error_append' => ''); $debug = &Log::singleton('display', '', '', $conf, PEAR_LOG_DEBUG); $debug->log($msg); } ?> ltsp-cluster-control-2.0.3/Terminal/Security.php0000664000175000017500000000250412026403127022132 0ustar stgraberstgraber * ?action=list/ip=192.168.2.221 * */ require_once 'util/functions.php'; require_once 'util/Node.php'; require_once 'util/SecurityRulesFinder.php'; # Security : only the expected variable are assigned # No post unset($_POST); # No cookies unset($_COOKIES); # Expected variables $get["action"]=''; $get["ip"]=''; # Get the allowed variables foreach ($_GET as $key=>$value) { if (isset($get[$key])) { $get[$key]="$value"; } } # Open the current node $rulesFinder=new SecurityRulesFinder($get["ip"]); $keys=$rulesFinder->getAuthorizedKeys(); if (!empty($keys)) { foreach ($keys as $key) { print "key:".$key."\n"; } } $ips=$rulesFinder->getAuthorizedIps(); if (!empty($ips)) { foreach ($ips as $ip) { print "ip:".$ip."\n"; } } ?> ltsp-cluster-control-2.0.3/Adminng/0000775000175000017500000000000012026403130017405 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/themes/0000775000175000017500000000000012026403130020672 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/0000775000175000017500000000000012026403130022214 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/css/0000775000175000017500000000000012026403130023004 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/css/style.css0000664000175000017500000001011412026403127024661 0ustar stgraberstgraberbody { background-image: url(../images/bgrepeat.jpg); background-color: #D3CAAA; background-repeat: repeat-x; padding: 0; margin: 0; } #jswarning { background:#d8d0ba; margin-left:auto; margin-right:auto; width:50em; padding: 0.5em 0.5em 0.5em 0.5em; text-align:center; margin-bottom: 1em; border: dotted 3px red; } #main { margin-left: 16em; margin-right: 1em; } #leftbar { float: left; width: 15em; } #container { margin: 0 auto; padding: 0 0 0 14px; position: relative; background-color: #fff; background-image: url(../images/page-border-left-repeat.jpg); background-repeat: repeat-y; background-position: left; width: 94%; } #content { margin: 0; position: relative; background-color: #fff; background-image: url(../images/page-border-right-repeat.jpg); background-repeat: repeat-y; background-position: right; } #topNav { background-image: url(../images/top.jpg); background-repeat: repeat-x; background-position: top; padding-top: 1em; z-index: 1; } #topNav h1 { margin:0.2em 0em 0em 5px; } #bg-left { position: absolute; top: 0; left: 0; width: 14px; height: 655px; background-image: url(../images/page-border-left.jpg); background-repeat: no-repeat; background-position: top left; z-index: 6; } #bg-right { position: absolute; top: 0; right: 0; width: 13px; height: 655px; background-image: url(../images/page-border-right.jpg); background-repeat: no-repeat; background-position: top right; z-index: 6; } #bottom-left { width: 14px; height: 34px; background-image: url(../images/footerbg-left.jpg); position: absolute; bottom: 0; left: 0; z-index: 7; } #bottom-right { width: 13px; height: 34px; background-image: url(../images/footerbg-right.jpg); position: absolute; bottom: 0; right: 0; z-index: 7; } #body { overflow: hidden; margin-top:1em; margin-left:5px; min-height: 538px; } * html #body { height: 1%; } #footer { background-image: url(../images/footerbg.jpg); background-repeat: repeat-x; background-position: bottom; padding: 0 0 0 0; } #footer .wrapper { padding: 0 15px 15px 15px; color: #656565; font-size: 70%; position: relative; } #footer .wrapper p { width: 70%; font-size: 90%; } .ubuntu_roundnavbar * { display:block; height:1px; overflow:hidden; font-size:.01em; background:#CCC1A3; } .ubuntu_roundnavbar1 { margin-left:3px; margin-right:3px; padding-left:1px; padding-right:1px; border-left:1px solid #e9e4d7; border-right:1px solid #e9e4d7; background:#d8d0ba; } .ubuntu_roundnavbar2 { margin-left:1px; margin-right:1px; padding-right:1px; padding-left:1px; border-left:1px solid #f9f8f5; border-right:1px solid #f9f8f5; } .ubuntu_roundnavbar3 { margin-left:1px; margin-right:1px; border-left:1px solid #d5ccb4; border-right:1px solid #d5ccb4; } .ubuntu_roundnavbar4 { border-left:1px solid #e9e4d7; border-right:1px solid #e9e4d7; } .ubuntu_roundnavbar5 { border-left:1px solid #d8d0ba; border-right:1px solid #d8d0ba; } table.ubuntu_menu { width: 100%; margin-bottom:1em; background:#eaeada; font-size:small; border-collapse:collapse; } tr.ubuntu_menuheader td { background:#CCC1A3; font-size:small; padding-left:10px; padding-top:0px; color:#5a3320; } table.ubuntu_menu a { color:#303030; text-decoration:none; } td.ubuntu_menu_entry { padding-left:19px; padding-right:19px; background:url(../images/action.png) 8px center no-repeat; padding-bottom:2px; padding-top:2px; } table.ubuntu_menu tr td a:hover { color:#FF0000; } table.listing { width: 99%; border: 0; border-collapse: collapse; } table.listing tr:hover { background-color: #f1f1f1; } table.listing tr.trheader { border-bottom: 1px solid #000000; background-color: #f6f6f6; } table.listing td { padding:5px; } ltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/page.php0000664000175000017500000000422112026403127023646 0ustar stgraberstgraber <?php echo $page['title']; ?>

"; echo _("Javascript doesn't seem to be enabled on your computer, please turn it on."); ?>
 
 
 
 
ltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/icons/0000775000175000017500000000000012026403130023327 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/icons/system-log-out.png0000664000175000017500000000207412026403127026756 0ustar stgraberstgraber‰PNG  IHDRÄ´l;sBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<¹IDAT8•ÏkUÇ?÷Þ™;ó~˜¦yMŠ>BcL„¶!¥’U ºhŒ¸ ´"-j1XÁtÙ7!BqSõ¨ˆˆ]¹\%‹JºhZ\4ÐR^Á¬ð_&ïç×Åûá{É zà0ÃÌá3ß{æüÖZþ‡ @Në `ˆ[÷=æ¼÷Á¥%cÌõƒ¨J)Òé4‡ð=€0 q]}syé‹k@}/Ü0Æ\çü» ªÕ*µZZ­†1c RJ¦§¦¹rå#¤l ®×k|õÍןK€i)ïxž‡Öš0 ‰¢ˆ8ŽI’­5CCC(¥PJNgHÛ}Sàû>Zk¢("IÚ¹7Æày™L!$B4 Z{=Œ¾`­5¾ï÷@…H)ÑZãµrÛm­´ˆ~`Ùä8žçáû>¾ïãy^ǵֈ¾ø!›}ã{!nõU,¥ì¸R Çq˜˜˜ ŽcŠÅ"®ëö…þ<=}ñðÔÔõàÑ#õ·GÅícwûææ&¾ï399Ùùim³I‚së[²ùüâkW¯zJ©H*U–ŽSPìIü^°µ–B¡À©S§0Ætâ àÎü<ãÃÃŒŸ=ëÛR‰×oÜðÛïYXð{À{Ug2fff¸{÷.Ç òô)«ssŒÎÌ0<:ÊîÊ X‹P ›$ ÌÎ"¤dŸb!Dç'NœàÙ³g”J%R©¿^¸À‘‘}ŸÝÕUl‘T*$• 2•"uò$ÁŠóù<Õj•‡’Ífqœfèé›7¹3?c /õ l«‘Ož`ãxq·Á[[[ìììN§ÑZ$ GΜá͵5VÎãp6ÃÑÓ§‘ÍŽQЏZútM†a§Ä¤” ¤”Œ‘{eœÙ{÷øéìê››õQÇñ[[3öß¾ø[î®gÇq(•Jì;T*eâ8F ¢±xr­¶òxc£f!¹d­Ûò÷Ûp¥ZkŠÅ"ë÷×Ñž&ÿRž\.GEc¨šç··?©•Ë_ xÜÍè;@´ÖAÀúú=^ãòå÷9vl¬9ý¢0 ‰ã˜`w q1Š>>ë ¶Ö¢”ÂZ˃÷948À‡ —Éår¸®K‡Ôê°’$&€m8Ž‘Ròü¯ç,o½=G*åãºns؇aϳ4[ú?ÁÁNÀþÎÄ«Íã",F†i4ªè0’ÄR©”¡¹=úƒGŽŽ,ßþñöbw牃fdWê´ÖËìYImûç¥z‘š”IIEND®B`‚ltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/icons/utilities-system-monitor.png0000664000175000017500000000173612026403127031074 0ustar stgraberstgraber‰PNG  IHDRÄ´l;bKGDˆŠ… ¥©Õ pHYs  šœtIMEÖ ;ž{¡kIDAT8Ë­Ô_hEÀñïÌÎþ1Fâ%j"Íh/Ú§«E# ¦ûà“"UAê“ÐJÐQ¡(ÖŠ¡F´–úàSl ö!hÓ–¤`›BR›KÓäÔÄj,M.—ÛÝÛÖKÛ¤—ŠdŸvg~ó™ßüÙŸØà« ¹ÜÔkðär¹ô§Ÿì¿=°aâÂù‘;º×Âå73ùb±Ø.v}ð¾Ù¹£)ó óïû7´Ö„A€(¥HÔÔ’HÔòñîPåÀùüϾ{ˆlvúeÚ’là×ZI$jã‰ÊAÍNódk aÙa#•EºE2zÁÄUŒÁèL„Ö£C¾ž!¿Ð¼±——/•‡T1œNIšÁR£Sªlm4&ÒH]c‹ …%X._’e{HËCØmix¢£“uMa{HÛC8qŸe{X®ƒ´=Æ&ÿ\±5+àp¹7%h¨3{=ɦe»XŽKkÒ m,ÅäÌ?áÔØÌ X-oŸü‹ÚºS%›º˜ýý3ZÖw’¼óß§Ê™Ešï~ Ña@©ʹéÆð©ñidîOožA´½BvâíumÙ”¼Ì}IUßvþÎסua‰(ÒôŸˆ 2|ð‹!Ùôð~rgŸaè|ímÐRïsÿÆN~ÞÆÖ®¯âeŒ1­1:¢ÿÌ*·˜·xð‘péûôT £3ñ½¼ãÖYý{ŽL°ûî!žÚòù5Ы{wU†¥º…G·!¤DHAßé$ÒRè¡ë±}œ<¹ãSèÁ˜/ÐZC¤1Z)¤±¯g£ ƒcS¥–b Ûˆtî»+ÀÏ¿6 ›·{7S þ=¼  äpõÃÛÓ׌r]”ë¡<…´,Î^¼ÿ†s³õ(åP"DiM -¤%‘–¬|]×½Ò %R 48¹Žžþs ý–O†”()ã:þÝ«ªªVflÛ©Tc\„ ,R¸&ƒ÷†=`¸bJ¥QJ­„«o®f_æQææçÈçç ü€ þSes)%R^Ù‘ɼÖQ{[¢­ ýë™îb6;¾EÞ />ÿxºõžÞµ€{{m=úãÀ‘r‘õ€z HîU±nÃ_ö~ ¸ üŲ`ï:€W.®ÖöÀE#U•:ÄIEND®B`‚ltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/icons/COPYING0000664000175000017500000000022412026403127024366 0ustar stgraberstgraberThe icons in this repository are herefore released into the Public Domain. They are taken from the Tango Icon library, http://tango.freedesktop.org ltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/0000775000175000017500000000000012026403130023461 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/page-border-left.jpg0000664000175000017500000000447312026403127027320 0ustar stgraberstgraberÿØÿàJFIFddÿìDuckyFÿîAdobedÀÿÛ„    ÿÀ=ÿÄv ´u&5!71%6"±2q1ÿÚ ?øóæL8Ìï™àÿ­©ô¾o<¿ÑßÉsõìËÉL]n6û,œaÆnç4„’¹| ¤ÊœRãÿžG¬üÿSøç©üƒ¦_ú]‘+ý7ý}-'ôd'Ðàœìÿg]>\TຊC×—.*qãÎcüaãåñòúÿ—ŸçùýÏïèPÐýý›µÖ$ …ã¤4¬´h|[9Zà33¶ºÄ€0¼t¦•–‹g+CÜfv×XŽ”Ò²Ñ˜üÞxü±„!çùB0óæ#ðõ‡Qñlæh{€ÌÎÚëÂñÒšVZ4>-œ­p™Û]b@^:SJËF‡Å³•¡î3;k¬H ÇJiYhÐø¶r´=Àfgmu‰axéM+-ÎV‡¸ Ìí®± /)¥e£CâÙÊÐ÷™µÖ$…ã¥4¬´h|[9Zà33¶ºÄ€0¼t¦•–‹g+CÜfv×XŽ”Ò²Ñ¡ñlæh~þÍÎÚëÂñÒšVZ2>- oìÜí®± /'¥e¢ããÒцþÍÎÚëÂñÒzVZ,>1m(oÌÜí®± /'¥e¢ƒãØÒ†üÍÎÚëÂñÒzVZ&>1Í8o¬Üí®± /'­e¢#ãàÔýõµÖ$…ã¤ô¬´<|c<šßYÙËeb@^:OJËCGÆ3Ñ« ñœ¶V$…ã¤ô¬´,|c=šÐßùËeb@^:OJËBGÆ3ᯠퟜ¶V$…㤴¬´|k>›Þ™ùËeb@8^:KJËAG†³ñ³ 韜¶V$…㤴¬´ |k?Û0ÞZËeb@8^:KJË@†€-¨o- å²± /%¥dþ6á¼43vÊ´€0¼t–•“ì|h ܆ðÐÍÛjÒÂñÒZVO‘á Kv»G7m«H ÇIiY=‡†mènÍݶ­ /%¥dô7á»4³vÚ´Àp¼tŽ•“Äxp#`†êÒÍ[jÓÂñÒ:VNááÀ†£K5m«L ÇHéY;‡Ö8n,Õ¶­0/#¥dé Øá¹´óVÚ´Àp¼tŽ•9‡‡–HnM<Õ¶­0/#¥dãÙ¡¹4óVÚ´Àp¼tŽ•“€xpEg†âÔÌÛªÓÂñÒVMÑáá-¢ƒS3n«L ÇHiY6‡‡…˜míLͺ­0/!¥d×Ú¡·µs6ê´Àp¼t†•5‡…¶¸mÍ\ͺ©0/!¥dÒ[!¶µ³ê¤Àp¼t†Ÿ$ÏÛa¶5³ê¤Àp¼u~Ÿ$Ì@[¡¶5³ê¤Àp¼/÷ðÉ@ÈCkkæ-õI€áxêÿ aääŒ6¦¾bßT˜ޝ÷ðÃ@ÉCjkåíõIaxêÿ Ôœ6–Æ^ßT˜…þþ£¨YHm Œ½¾©0,/_ïát:€H•†ÎÙËÛê“ÂñÕÞþã¨D¹hl휽¾©0,/ ½ü-P‰ÒðÙ›9{}R`X^:»ßÂÄu¢„6fÏÝíõIaxêï áÔ"¬´6†¾bßT˜Ž®÷ðªB+¡ ¡¯˜·Õ&…㫽ü*P‹HÃgkæ-õIaxêß QÔBêPÙ›‹}R`X^:·ßˆuÀœ6fÆ^ßT˜Ž­÷ðŸD1p†ÊØËÛê“ÂñÕ¾þ£¨†N0Ù9{}R`X^:·ßÂluÏlœ½¾©0,/[ïá0:ˆiñ±¶ròIaxêß aÔCda±6ròIáxêÏ 1Äcta±6²Ò)áxêÏ Äc‡(l-¬´…J`X^:³ßÂë#SÀ ÇUûø¾$@§;¦þNJ§€…žþ/£ˆÐ)Îé¿“’©à…ág¿‹èâ4 sºoääªxáxYïâú8œî›ù9*žx^{ø¾Ž#@§;¦þNJ§€…žþ/£ˆÐ)Îé¿“’©à…ág¿‹èâ4 sºoääªxáxYïâú8œî›ù9*žx^{ø¾Ž#@§;¦þNJ§€…žþ/£ˆÐ)Îé¿“’©à…ág¿‹èâ4 sºoääªxáxYïâú8ÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/footerbg.jpg0000664000175000017500000000255112026403127026003 0ustar stgraberstgraberÿØÿàJFIFddÿìDuckyFÿîAdobedÀÿÛ„    ÿÀ"çÿÄ\Q‘ÑÿÚ ?¿€¼þ[›3÷æ×œ¹þënCÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!åy´Úó“ºd<¯6›^rwL‡•æÓkÎNéò¼ÚmyÉÝ2W›M¯9;¦CÊóiµç'tÈy^m6¼äî™+ͦלÓ!å¹´Úó“ºdn(ÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/action.png0000664000175000017500000000027712026403127025460 0ustar stgraberstgraber‰PNG  IHDRfXægAMAÖØÔOX2tEXtSoftwareAdobe ImageReadyqÉe<QIDATxÚbLMM}ÄÀÀÀÄ@üˆŸ1ÇñK ^ Ä›Ø ˆåY€ÄA Nâ£@, Äë€ø+Hˆ'ñ[¨ÎL ’XŒÍ€o —k÷ƒæIEND®B`‚ltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/page-border-right-repeat.jpg0000664000175000017500000000051312026403127030750 0ustar stgraberstgraberÿØÿàJFIFddÿìDuckyFÿîAdobedÀÿÛ„    ÿÀ ÿÄX²rs4FABÿÚ ?{OÑ“ŠãJR~,ÐV–ÓÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/page-border-left-repeat.jpg0000664000175000017500000000051212026403127030564 0ustar stgraberstgraberÿØÿàJFIFddÿìDuckyFÿîAdobedÀÿÛ„    ÿÀÿÄW´5u12ÿÚ ? \Ísû4¬À‡Ãx3:>—ÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/page-border-right.jpg0000664000175000017500000000472012026403127027476 0ustar stgraberstgraberÿØÿàJFIFHHÿáExifMM*ÿÛC   ÿÛC ÿÀ= ÿÄ ÿÄ2 %5qrs±²Á4$2t!13QbaÿÄÿÄ1!aÿÚ ?øôeaå眊iÊF€>”ÇàÑ?‚ÿBíæÇ%w\tßþ³Kä•ö«GÄÒ…mºÑäD®eBˆ¢÷÷¢i†©ÒšMÓôÿ‰£K×Ó×Ô~B½ëå;çõ/Žï4…{û¬P§þB…b¤¿¦iuÆýwx’£ÄΕx-aÒ9Þ«ÌS¥×õÝàR:‘:UേHçz¯1Lf—\o×wHêDLéW‚Ö#ê¼Å1š]q¿]Þ#©3¥^ XtŽwªóÆiuÆýwxޤDΕx-aÒ9Þ«ÌS¥×õÝàR:‘:UേHçz¯1Lf—\o×wHêDLéW‚Ö#ê¼Å1š]q¿]Þ#©3¥^ XtŽwªóÆiuÆýwxޤDΕx-aÒ9Þ«ÌS¥×õÝàR:‘:UേHçz¯1Lf—\o×wHêDLéW‚Ö#ê¼Å1š]q¿]Þ#©4%^ XtŽwªó¾iuÆýwxޤDÒ•dÖçz¯1Kf—\o×wHêDM9Xö-aÒ9Þ«ÌRÉ¥×õÝàR:šÒ¡ìZäs½W˜¥S[®7AÞ#© ­*Ŭ:G;ÕyŠS5ºãtàR:›¡ìZäo½W˜¤ó[®7AÞ$© ³*ðZäo½W˜¤Ó[²7AÞ$©7% ÿÑks½UŠG5»#tàR:•zR=‹XtŽwª±Hf—dnƒ¼ GR“†P=ƒXtŽwª±G¦—dnƒ¼ GR“’P=ƒX#ê¬Q¹¥Ù ï‘Ô¤æ”`Öçz«fivFè;À¤u):eØ5‡Hçz«ZivFè;À¤u*'\ {°G;ÕX¢“K²7AÞ#©IÝ'{XtŽwª±Df·dnƒ¼ GR“ÆN,ö°éïUf(tÒìÐwHêRzI…žÎ#ê¬Å š]‘ºð)JOy0³Ùäs½U˜¡K²7AÞ#©Q>¤ÂÏgs½U˜ ³;¶7AÞ#©Iû%{XtŽ÷ª³gvÆh;À¤U(’‹=¬:G;ÕY‡üÎíŒÐwHêP%{XtŽ÷ª³ÙÛ ï‘T J,ö°éïTáó3»c4àR:˜ÉœÖ#½êœ=¦wlfƒ¼ ESÙ ³šÃ¤w½S‡”ÎíŒÐwHª`!#kXtŽ÷ªpï™Ý±šð)LäbÎkw½S‡\ÊîŒÐsHª`/"k8tŽ÷ªs‰•Ý ç‘TÀjD,ÖpéïTáË2»£4àR*˜ÈEšÎ#½êœÃ‚ewFh9À¤U0"‹1œ:G{Õ9†ôÊî‹ÐsHª`I c8tŽ÷ªs ¹•Ý¢ç‘TÀžEFÌg‘ÞõNa±2»¢ô\àR*˜ÈE˜Æ#½êœÃRewEè¹À¤U0/ 1œÞõF+º/EÎ"©Á•_[8tŽ÷ª0Í™]ñz.p)N dËcw½Q†TÆï‹ÑsHªpsWE–ÎQ°G{ÕcÌnø½8ЧuxYle#½êŒ1&7|^‹œ ES„ º,¦2‘ÞõFó¾/EÎ%"©Â][FÈïz£0½˜Ýñz.q)N*è²ØÊ6G»Õ…Ü}`b¨Ñ’Ë€ù$š%!©ÂE\ô2¦2‘îõFa|çñÓÀì‘'u\Y,売;Þ¨Ì/þ:x’$á«‹%œ´vG{Õ…ËŸÇO²Dœ%Uad1–ŽÈïz£0µsøéàvH“„Ê®,†2„w½o…›Ÿ X’&Bª‹!Œ´vG{ÖøW¹ð¥Ù"`ª¨²ËGdw½o…kŸ X’&V« !Œ£dw½o…SŸ X’&fª‹Œ£d{½o…3Ÿ X’nª Œ´vG{ÖøR9ð¥Ù"`ê ±ØÊ6G{Öù…Ÿ X’&†©‹Œ£dw½o„óŸ X’&’©‹Œ£dw½o˜M¹ð¥Ù"`ª˜±˜Ê6G»Öù„ËŸ X’¢©‹Œ£d{½o˜K¹ð¥Ù!`ª˜±˜Ê6G»Öù„­#éF‘ôõôð° •HXÌe#Ýë|ÂMÏ…,É ÝT…ŒÆQ²=Þ¶ÂEÏ…,É áT…ŒÆQ²=Þ¶Â=Ï…,É çT…ŠÆQ²=Þ¶Â4€Aô!bê€õ’CŸõ#Ýël#R!Χ‹(Ùï[a±µ<üH|£d{½m„RBÄ;Tû‘Œ£d{½m„JBÄ;Tû‘Œ£d{½m„JBÄ;Tû‘Œ£d{½m„JBÄ;Tû‘Œ£d{½m„JBÄ;Tû‘Œ£d{½m„JBÄ;Tû‘Œ£d{½m„A Oè~JBÄ;Ôû‘Œ£d{½m„;Ÿ X’!æ¨\ùFÈ÷zÛjCÖ‰äz$,CÍOüÉ!Ïú‘îõ¶çôR!Þ§ÜŒe#Ýël"è¤,C½O¹Ê6G»ÖØDÑHX‡zŸr1”lw­°ˆ?¢±õ>äc(Ùï[aJ• *dQ¡DHŸÀ~Ò!â¨z‰,8ÿQ²=Þ¶Â?Á‰Òs‰H+ªw3FÈ÷zÛôƒ¤çÖ&Tîf2‘îõ¾c~ðbtœâRÀÀjÌÆQ²=Þ·ÌoÑþ N“œJCX S¹˜Ê6G»Öùú?Á‰Òs‰Hkªw3FÈ÷zß1¿Gø1:Nq) ``5Næc(Ùï[æ7èÿ'IÎ%!¬ ©ÜÌe#Ýë|ÆýàÄé9Ĥ5€Õ;™Œ£d{½o˜ß£ü'8”†°0§s1”lw­óôƒ¤çÖTîf2‘îõ¾c~ðbtœâRÀÀjÌÆQ²=Þ·ÌÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/bgrepeat.jpg0000664000175000017500000000065612026403127025771 0ustar stgraberstgraberÿØÿàJFIFddÿìDuckyFÿîAdobedÀÿÛ„    ÿÀvÿÄUaÿÚ ?ñîe°ÀÀÀÀÀÀÀÀÀÀÀÀÀ@ì€P @(= €pÁÀ9À8 @8¨s€¤€¤€¦@àŠ@RÀRCÈ)RäЇH d ¤à‡Hà)à‡8çà€qPà€P @((ƒÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/footerbg-left.jpg0000664000175000017500000000072412026403127026733 0ustar stgraberstgraberÿØÿàJFIFddÿìDuckyFÿîAdobedÀÿÛ„    ÿÀ"ÿÄk1!A´5uQ212ÿÚ ?èëòpº”T?ðs>µp˜ gzÇüœ.¥Ǽσí\&ÝúRÄÈ 0ÝnK éóeAi¿¸® µ›;1pVk<Ø^ÇÈ™t­›J¤BO º²–”A+! ýyÞÜjß×v)¬ÝˆXéPN!VÑRS,´?d^ÆÞ¢Õ¶)u`jÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/top.jpg0000664000175000017500000000054612026403127025000 0ustar stgraberstgraberÿØÿàJFIFddÿìDuckydÿîAdobedÀÿÛ„ÿÀÿÄb 1‘Q45U‘RÿÚ ?Pêrbe ÷;wÃß:uÅa¡ÌÌ…L »v$ŽS`QB ÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/images/footerbg-right.jpg0000664000175000017500000000070512026403127027115 0ustar stgraberstgraberÿØÿàJFIFddÿìDuckyFÿîAdobedÀÿÛ„    ÿÀ" ÿÄm1²!Ars4¡%FAB!ÿÚ ?½§ô2yNe+(Lÿ‹<)P{áLOèdòœÊUêI4X~˜xR ö;Ãsïžëƒ¡éRa¶í.krÛ©˜‘( ¸*paó*êi·¦û‚³ëé4…5×5“{_Áú 6à³ÁDÏÓf¢hðaS-QÚjÞ²Û[ƒë@ÿÙltsp-cluster-control-2.0.3/Adminng/themes/ubuntu/functions.php0000664000175000017500000000472012026403127024746 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2008, Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ function theme_ubuntu_menu($categories) { # Takes an array as input containing arrays then containing title, link and status for each item foreach ($categories as $category) { echo " "; foreach ($category['items'] as $item) { if ($item['current'] == 0) { echo " "; } else { echo " "; } } echo "
".$category['name']."
".$item['title']."
".$item['title']."
"; } } ?> ltsp-cluster-control-2.0.3/Adminng/themes/engine.php0000664000175000017500000000252712026403127022664 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2008, Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ # Check if a theme has been selected. if (!isset($config['theme'])) die("You must set a theme."); # Function to render a standard page. function renderPage($page,$menu) { global $config; include "themes/".$config['theme']."/page.php"; } ?> ltsp-cluster-control-2.0.3/Adminng/README-DEVELOPMENT-POLICY0000664000175000017500000000217612026403127023056 0ustar stgraberstgraberAfter a quick discussion on coding styles, here's what we've currently got for consensus: For shell scripts: - Shell scripts should be fully posix compliant. - We will favour the use of if [ ]; then else fi, over && and ||, for clarity - When using a multi check if, exception will be using the if [ .. ] && [ .. ] || [ .. ] form, as opposed to [ .. -a .. -o .. ] form. - If a single line test is used, use test &&/|| result, and only for tests that fit on a single line. - We'll use spaces instead of tabs, and the indentation level will be 4 spaces, the same as python. For C programs: - Programs should be passed through the "indent" program periodically to clean them up. - The following indent command line should be used: indent -kr -i4 -nut -c50 -psl - K&R style (Scott's a greybeard) - 4 character tab width, and spaces instead of tabs - Align inline comments on column 50 - A newline after function definitions - All if() else blocks will have {}'s, even if only 1 line long, or Ollie will break your thumbs. - Comments will be /* */ or Scott will break the rest of your fingers. ltsp-cluster-control-2.0.3/Adminng/modules/0000775000175000017500000000000012026403130021055 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/modules/loadbalancer.block.php0000664000175000017500000003001012026403127025266 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ require "loadbalancer.data.php"; function loadbalancer_appservlist() { global $config; # Jquery $content= " "; # Generate a block containing a list of all application servers $lbserver = LoadBalancer::getInstance($config['loadbalancer']['host'],$config['loadbalancer']['port']); $content.=""._("Server list from")." ".$config['loadbalancer']['host']."

"; $server_id=0; $group_id=0; foreach ($lbserver->getStatusRaw() as $group_name => $group_content) { if (count($group_content) == 0) { continue; } $content.= "
"._("Group").": ".$group_name."
"; $content.= "

"._("Search").":

"; foreach ($group_content as $server_name => $server_content) { foreach ($server_content as $attribute_name => $attribute_content) { switch ($attribute_name) { case "active": if ($attribute_content == "1") { $server_attribute[$attribute_name]=""._("Active").""; $server_disabled=false; } else { $server_attribute[$attribute_name]=""._("Inactive").""; $server_disabled=true; } break; case "MEMFREE": case "MEMUSED": case "MEMTOTAL": $server_attribute[$attribute_name]=round($attribute_content/1024)."MB"; break; case "LOADAVG": case "NBUSERS": if ($attribute_content == Null) { $server_attribute[$attribute_name]="0"; } else { $server_attribute[$attribute_name]=$attribute_content; } break; default: $server_attribute[$attribute_name]=$attribute_content; break; } } $content.= " "; if ($server_disabled) { $content.= " "; } else { $content.= " "; } $content.= " "; if (is_array($server_attribute["ADDRESSES"])) { $server_attribute["ADDRESSES"]=implode(",",$server_attribute["ADDRESSES"]); } # Advanced information, will only display when the header is clicked $content.=" "; $server_id++; } $content.= "
"._("Server name")." "._("Status")." "._("Number of users")."
$server_name ".$server_attribute["active"]." 0".$server_name." ".$server_attribute["active"]." ".$server_attribute["NBUSERS"]." ("._("click for list").")
"._("CPU").": ".$server_attribute["CPUCOUNT"]." x ".$server_attribute["CPUFREQ"]."Mhz
"._("Operating system").": ".$server_attribute["DISTRO"]."
"._("Memory").": ".$server_attribute["MEMUSED"]."/".$server_attribute["MEMTOTAL"]." (".$server_attribute["MEMFREE"]." "._("free").")
"._("Load average").": ".$server_attribute["LOADAVG"]."
"._("IP addresses").": ".$server_attribute["ADDRESSES"]."
"._("Hostname").": ".$server_attribute["HOSTNAME"]."

"; $group_id++; } return $content; } function loadbalancer_userlist($server = Null) { global $config; # Jquery $content= " "; # Generate a block containing a list of all application servers $lbserver = LoadBalancer::getInstance($config['loadbalancer']['host'],$config['loadbalancer']['port']); $users=array(); foreach ($lbserver->getStatusRaw() as $group) { foreach ($group as $server_name => $server_content) { if ($server == Null || $server_name == $server) { if (is_array($server_content['USERS']) && $server_content['IP']) { foreach ($server_content['USERS'] as $user) { $users[]=array($user,$server_name,$server_content['IP']); } } elseif ($server_content['USERS'] && $server_content['IP']) { $users[]=array($server_content['USERS'],$server_name,$server_content['IP']); } } } } # Clear and sort the array sort($users); if (count($users) > 1) { $struser=count($users)." "._("users"); } else { $struser=count($users)." "._("user"); } if ($server == Null) { $content.=""._("Full user list")." (".$struser.")

"; } else { $content.=""._("Users on")." ".$server." (".$struser.")

"; } $content.= "

"._("Search").":

"; if ($server == Null) { $content.= " "; } $content.= " "; $user_id=0; foreach ($users as $user) { $colspan=2; $content.= " "; if ($server == Null) { $colspan=3; $content.= " "; } $content.= " "; # Advanced information, will only display when the header is clicked $content.=" "; $user_id++; } $content.= "
"._("Username").""._("Application server").""._("Actions")."
".$user[0]." ("._("click to expand").")".$user[1]."
Some ajax magic will happen here
"; return $content; } ?> ltsp-cluster-control-2.0.3/Adminng/modules/frontpage.page.php0000664000175000017500000000231612026403127024476 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ menuAddItem(_("Administration"),_("Home"),"frontpage"); function frontpage_main($arguments) { # Control center front page $content = "Hello"; return $content; } ?> ltsp-cluster-control-2.0.3/Adminng/modules/users.page.php0000664000175000017500000000242712026403127023655 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ menuAddItem(_("Monitoring"),_("Users"),"users"); function users_main($arguments) { require_once "loadbalancer.block.php"; # Main page for application servers information $content = loadbalancer_userlist(); return $content; } ?> ltsp-cluster-control-2.0.3/Adminng/modules/accountmanager.block.php0000664000175000017500000000616712026403127025666 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ require "accountmanager.data.php"; function accountmanager_processlist($server, $username = Null) { global $config; $accountmanager = AccountManager::getInstance(); # Generate a block containing a list of all application servers if ($username == Null) { $content=""._("List of process on")." ".$server."

"; } else { $content=""._("List of process for user")." ".$username." "._("on")." ".$server."

"; } $content.= "

"._("Search").":

"; if ($username == Null) { $content.= " "; } $content.= " "; $process_id=0; $lines=split("\n",$accountmanager->listProcess($server,$username)); foreach ($lines as $line) { $line=trim($line); if (!$line) { continue; } ereg("([0-9]*) (.*)",$line,$process); if (!$process[1]) { continue; } $colspan=3; $content.= " "; if ($username == Null) { $colspan=4; $content.= " "; } $content.= " "; $process_id++; } $content.= "
"._("Username")."".str_replace(" "," ",_("Process ID"))." ".str_replace(" "," ",_("Process name"))." ".str_replace(" "," ",_("Actions"))."
Username".$process[1]." ".$process[2]."  
"; return $content; } ?> ltsp-cluster-control-2.0.3/Adminng/modules/accountmanager.function.js0000664000175000017500000000113412026403127026233 0ustar stgraberstgraberfunction ajaxFunction() { var xmlhttp; if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else if (window.ActiveXObject) { // code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } else { alert("Your browser does not support XMLHTTP!"); } xmlhttp.onreadystatechange=function() { if(xmlhttp.readyState==4) { document.myForm.time.value=xmlhttp.responseText; } } xmlhttp.open("GET","time.asp",true); xmlhttp.send(null); } ltsp-cluster-control-2.0.3/Adminng/modules/loadbalancer.data.php0000664000175000017500000000716212026403127025121 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ include "includes/xmlrpc/xmlrpc.inc"; include "includes/xmlrpc/xmlrpcs.inc"; # This module access the Load Balancer server to retrieve its current status and allow to easily class LoadBalancer { static private $_instance = null; private $_status = null; # The status array private $_xmlclient = null; # The xmlrpc_client object connected to the Load Balancer # Make sure we don't end up with two instances of the same class static public function getInstance($server, $port) { if (self::$_instance == null) self::$_instance = new LoadBalancer($server, $port); return self::$_instance; } # Open the connection with the Load Balancer public function __construct($server, $port) { $this->_xmlclient = new xmlrpc_client("", "$server", $port) or die ("Connection information for the Load Balancer is invalid."); $this->_xmlclient->return_type = 'phpvals'; } # Get and store the status of the Load Balancer. public function updateStatus() { # Query the loadbalancer for its status $message = new xmlrpcmsg("get_status", array()); $resp = $this->_xmlclient->send($message); if (!$resp) { die("Connection timed out or invalid answer."); } # Parse the answer and generate a status array $lbstatus=array(); foreach ($resp->value() as $group) { $lbstatus[$group['name']]=array(); foreach ($group['nodes'] as $node) { $lbstatus[$group['name']][$node['name']]=array(); $lbstatus[$group['name']][$node['name']]['active']=$node['active']; foreach ($node['values'] as $value) { $lbstatus[$group['name']][$node['name']][$value['name']]=$value['value']; } } } $this->_status=$lbstatus; } # Return the status array public function getStatusRaw() { # If no status stored, retrieve the current one if ($this->_status == null) { $this->updateStatus(); } return $this->_status; } # Return the list of groups public function getGroups() { return array_keys($this->getStatusRaw()); } # Return status of a specific server public function getServerStatus($group, $server) { $status=$this->getStatusRaw(); return $status[$group][$server]; } } ?> ltsp-cluster-control-2.0.3/Adminng/modules/accountmanager.data.php0000664000175000017500000000521612026403127025477 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ class AccountManager { static private $_instance = null; private $_td = null; # mcrypt # Make sure we don't end up with two instances of the same class static public function getInstance() { if (self::$_instance == null) self::$_instance = new AccountManager(); return self::$_instance; } # Initialize mcrypt public function __construct() { global $config; $this->_td = mcrypt_module_open('blowfish', '', 'ecb', ''); $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($this->_td), MCRYPT_RAND); mcrypt_generic_init($this->_td, $config['accountmanager']['key'], $iv); } # Stop mcrypt public function __destruct() { mcrypt_generic_deinit($this->_td); mcrypt_module_close($this->_td); } private function sendRequest($server,$request) { $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_connect($socket, $server, 8001); $encrypted_data = mcrypt_generic($this->_td, "$request"); socket_write($socket,"admin $encrypted_data"); $response=""; while ($out = socket_read($socket, 2048)) { $response.=$out; } socket_close($socket); return $response; } public function killUser($server,$username) { return $this->sendRequest($server,"kill $username"); } public function listProcess($server,$username) { return $this->sendRequest($server,"plist $username"); } } ?> ltsp-cluster-control-2.0.3/Adminng/modules/appservers.page.php0000664000175000017500000000417112026403127024704 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of· * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ menuAddItem(_("Monitoring"),_("Application servers"),"appservers"); function appservers_main($arguments) { if (is_array($arguments) && count($arguments) == 2 && $arguments[1] == "users") { require_once "loadbalancer.block.php"; $content = loadbalancer_userlist($arguments[0]); return $content; } elseif (is_array($arguments) && count($arguments) == 3 && $arguments[2] == "kill") { require "accountmanager.data.php"; $accountmanager = AccountManager::getInstance(); $accountmanager->killUser($arguments[0],$arguments[1]); return "User $username has been killed"; } elseif (is_array($arguments) && count($arguments) == 3 && $arguments[2] == "plist") { require_once "accountmanager.block.php"; $content = accountmanager_processlist($arguments[0],$arguments[1]); return $content; } # Main page for application servers information require_once "loadbalancer.block.php"; $content = loadbalancer_appservlist(); return $content; } ?> ltsp-cluster-control-2.0.3/Adminng/REQUIREMENTS0000664000175000017500000000005612026403127021262 0ustar stgraberstgraberlibjs-jquery libjs-jquery-ui smarty php5-curl ltsp-cluster-control-2.0.3/Adminng/.htaccess0000664000175000017500000000043312026403127021211 0ustar stgraberstgraber RewriteEngine on # Rewrite current-style URLs of the form 'index.php?q=x'. RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d #RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] RewriteRule ^(.*)$ /index.php?q=$1 [L,QSA] ltsp-cluster-control-2.0.3/Adminng/TODO0000664000175000017500000000015312026403127020102 0ustar stgraberstgraber- Port to php5-xmlrpc - Move to smarty - Get rid of non-jquery code - Get rid of impromptu (use jquery-ui) ltsp-cluster-control-2.0.3/Adminng/po/0000775000175000017500000000000012026403130020023 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/po/Makefile0000664000175000017500000000134012026403127021467 0ustar stgraberstgraberDOMAIN=ltsp-cluster-control POFILES=$(wildcard *.po) MOFILES=$(patsubst %.po,%.mo,$(POFILES)) LINGUAS=$(basename $(POFILES)) GETTEXTFILES=$(shell find ../ -type f -name "*.php") POTFILE=$(DOMAIN).pot DESTDIR=/ %.mo: %.po msgfmt --statistics -o $@ $< %.po: $(DOMAIN).pot msgmerge -U $*.po $(DOMAIN).pot $(DOMAIN).pot: $(GETTEXTFILES) $(shell xgettext -L php -o $(DOMAIN).pot $(GETTEXTFILES) --from-code utf-8) update-po: -for lang in $(LINGUAS); do\ msgmerge -U $$lang.po $(DOMAIN).pot; \ done install: $(MOFILES) -for lang in $(LINGUAS); do\ mkdir -p $$lang/LC_MESSAGES/; \ mv $$lang.mo $$lang/LC_MESSAGES/$(DOMAIN).mo; \ done all: update-po $(MOFILES) distclean: clean clean: - rm *.mo *~ .PHONY: update-po check ltsp-cluster-control-2.0.3/Adminng/po/fr/0000775000175000017500000000000012026403127020440 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/po/fr/LC_MESSAGES/0000775000175000017500000000000012026403130022217 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/po/fr/LC_MESSAGES/ltsp-cluster-control.mo0000664000175000017500000000560212026403127026704 0ustar stgraberstgraberÞ•,|;ÜÈÉÑØçú#26=BQW `m]vJÔ;T gt {†– § ²¿Æ ×ãTê?DMS\`o ’•š5 ÖÞäó &! HS[c‚‰ ˜¤{¬P( y $š ¿ × æ î û  ) 8 I T j y ^€ ß í ÿ   ! 7 M _ e i u #$( ! *&%,' " + ) ActionsActiveAdministrationApplication serverApplication serversAre you sure you want to disconnectCPUCancelExitFull user listGroupHostnameIP addressesInactiveIt may take a few seconds for the user to disappear (depending on your loadbalancer setting).Javascript doesn't seem to be enabled on your computer, please turn it on.LTSP-Cluster Control CenterList of process for userList of process onLoad averageMemoryMonitoringNumber of usersOperating systemProcess IDProcess nameSearchServer list fromServer nameStatusThe LTSP-Cluster Control Center requires javascript for most of its user interfaces.UserUsernameUsersUsers onYesclick for listclick to expanddisconnected.freeonuserusersProject-Id-Version: PACKAGE VERSION Report-Msgid-Bugs-To: POT-Creation-Date: 2009-06-29 11:58-0400 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language-Team: LANGUAGE MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit ActionsActifAdministrationServeur d'applicationServeurs d'applicationsEtes-vous sûr de vouloir déconnecterProcesseurAnnulerQuitterListe de tous les utilisateursGroupeNom de l'hôteAddreses IPInactifLa disparition de l'utilisateur peut prendre plusieurs secondes (dépendant de la configuration du répartiteur de charge).Javascript ne semble pas être activé sur votre ordinateur, merci de l'activer.Centre de contrôle LTSP-ClusterListe des processus de l'utilisateurListe des processus surCharge moyenneMemoireSurveillanceNombre d'utilisateursSystème d'exploitation# de processusNom de processusRechercherListe des serveurs deNom du serveurStatutLe centre de contrôle LTSP-Cluster nécessite javascript pour la majorité de ses interfaces.L'utilisateurNom d'utilisateurUtilisateursUtilisateurs surOuicliquer pour la listecliquer pour étendreest déconnecté.libresurutilisateurutilisateursltsp-cluster-control-2.0.3/Adminng/po/ltsp-cluster-control.pot0000664000175000017500000000766312026403127024710 0ustar stgraberstgraber# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-06-29 11:58-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../themes/ubuntu/page.php:28 msgid "" "The LTSP-Cluster Control Center requires javascript for most of its user " "interfaces." msgstr "" #: ../themes/ubuntu/page.php:30 msgid "" "Javascript doesn't seem to be enabled on your computer, please turn it on." msgstr "" #: ../index.php:75 ../modules/appservers.page.php:27 #: ../modules/users.page.php:27 msgid "Monitoring" msgstr "" #: ../index.php:76 msgid "Administration" msgstr "" #: ../index.php:84 msgid "LTSP-Cluster Control Center" msgstr "" #: ../modules/loadbalancer.block.php:45 msgid "Server list from" msgstr "" #: ../modules/loadbalancer.block.php:49 msgid "Group" msgstr "" #: ../modules/loadbalancer.block.php:51 ../modules/loadbalancer.block.php:215 #: ../modules/accountmanager.block.php:40 msgid "Search" msgstr "" #: ../modules/loadbalancer.block.php:54 msgid "Server name" msgstr "" #: ../modules/loadbalancer.block.php:55 msgid "Status" msgstr "" #: ../modules/loadbalancer.block.php:56 msgid "Number of users" msgstr "" #: ../modules/loadbalancer.block.php:64 msgid "Active" msgstr "" #: ../modules/loadbalancer.block.php:68 msgid "Inactive" msgstr "" #: ../modules/loadbalancer.block.php:104 msgid "click for list" msgstr "" #: ../modules/loadbalancer.block.php:115 msgid "CPU" msgstr "" #: ../modules/loadbalancer.block.php:116 msgid "Operating system" msgstr "" #: ../modules/loadbalancer.block.php:117 msgid "Memory" msgstr "" #: ../modules/loadbalancer.block.php:117 msgid "free" msgstr "" #: ../modules/loadbalancer.block.php:118 msgid "Load average" msgstr "" #: ../modules/loadbalancer.block.php:119 msgid "IP addresses" msgstr "" #: ../modules/loadbalancer.block.php:120 msgid "Hostname" msgstr "" #: ../modules/loadbalancer.block.php:153 msgid "Are you sure you want to disconnect" msgstr "" #: ../modules/loadbalancer.block.php:154 msgid "Cancel" msgstr "" #: ../modules/loadbalancer.block.php:154 msgid "Yes" msgstr "" #: ../modules/loadbalancer.block.php:168 msgid "User" msgstr "" #: ../modules/loadbalancer.block.php:168 msgid "disconnected." msgstr "" #: ../modules/loadbalancer.block.php:168 msgid "" "It may take a few seconds for the user to disappear (depending on your " "loadbalancer setting)." msgstr "" #: ../modules/loadbalancer.block.php:169 msgid "Exit" msgstr "" #: ../modules/loadbalancer.block.php:202 msgid "users" msgstr "" #: ../modules/loadbalancer.block.php:205 msgid "user" msgstr "" #: ../modules/loadbalancer.block.php:209 msgid "Full user list" msgstr "" #: ../modules/loadbalancer.block.php:212 msgid "Users on" msgstr "" #: ../modules/loadbalancer.block.php:218 #: ../modules/accountmanager.block.php:46 msgid "Username" msgstr "" #: ../modules/loadbalancer.block.php:222 msgid "Application server" msgstr "" #: ../modules/loadbalancer.block.php:226 #: ../modules/accountmanager.block.php:52 msgid "Actions" msgstr "" #: ../modules/loadbalancer.block.php:235 msgid "click to expand" msgstr "" #: ../modules/appservers.page.php:27 msgid "Application servers" msgstr "" #: ../modules/users.page.php:27 msgid "Users" msgstr "" #: ../modules/accountmanager.block.php:34 msgid "List of process on" msgstr "" #: ../modules/accountmanager.block.php:37 msgid "List of process for user" msgstr "" #: ../modules/accountmanager.block.php:37 msgid "on" msgstr "" #: ../modules/accountmanager.block.php:50 msgid "Process ID" msgstr "" #: ../modules/accountmanager.block.php:51 msgid "Process name" msgstr "" ltsp-cluster-control-2.0.3/Adminng/po/fr.po0000664000175000017500000001157612026403127021012 0ustar stgraberstgraber# French translation for ltsp-cluster-control # Copyright (C) 2009, Stéphane Graber # msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-06-29 11:58-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../themes/ubuntu/page.php:28 msgid "" "The LTSP-Cluster Control Center requires javascript for most of its user " "interfaces." msgstr "" "Le centre de contrôle LTSP-Cluster nécessite javascript pour la majorité de " "ses interfaces." #: ../themes/ubuntu/page.php:30 msgid "" "Javascript doesn't seem to be enabled on your computer, please turn it on." msgstr "" "Javascript ne semble pas être activé sur votre ordinateur, merci de " "l'activer." #: ../index.php:75 ../modules/appservers.page.php:27 #: ../modules/users.page.php:27 msgid "Monitoring" msgstr "Surveillance" #: ../index.php:76 msgid "Administration" msgstr "Administration" #: ../index.php:84 msgid "LTSP-Cluster Control Center" msgstr "Centre de contrôle LTSP-Cluster" #: ../modules/loadbalancer.block.php:45 msgid "Server list from" msgstr "Liste des serveurs de" #: ../modules/loadbalancer.block.php:49 msgid "Group" msgstr "Groupe" #: ../modules/loadbalancer.block.php:51 ../modules/loadbalancer.block.php:215 #: ../modules/accountmanager.block.php:40 msgid "Search" msgstr "Rechercher" #: ../modules/loadbalancer.block.php:54 msgid "Server name" msgstr "Nom du serveur" #: ../modules/loadbalancer.block.php:55 msgid "Status" msgstr "Statut" #: ../modules/loadbalancer.block.php:56 msgid "Number of users" msgstr "Nombre d'utilisateurs" #: ../modules/loadbalancer.block.php:64 msgid "Active" msgstr "Actif" #: ../modules/loadbalancer.block.php:68 msgid "Inactive" msgstr "Inactif" #: ../modules/loadbalancer.block.php:104 msgid "click for list" msgstr "cliquer pour la liste" #: ../modules/loadbalancer.block.php:115 msgid "CPU" msgstr "Processeur" #: ../modules/loadbalancer.block.php:116 msgid "Operating system" msgstr "Système d'exploitation" #: ../modules/loadbalancer.block.php:117 msgid "Memory" msgstr "Memoire" #: ../modules/loadbalancer.block.php:117 msgid "free" msgstr "libre" #: ../modules/loadbalancer.block.php:118 msgid "Load average" msgstr "Charge moyenne" #: ../modules/loadbalancer.block.php:119 msgid "IP addresses" msgstr "Addreses IP" #: ../modules/loadbalancer.block.php:120 msgid "Hostname" msgstr "Nom de l'hôte" #: ../modules/loadbalancer.block.php:153 msgid "Are you sure you want to disconnect" msgstr "Etes-vous sûr de vouloir déconnecter" #: ../modules/loadbalancer.block.php:154 msgid "Cancel" msgstr "Annuler" #: ../modules/loadbalancer.block.php:154 msgid "Yes" msgstr "Oui" #: ../modules/loadbalancer.block.php:168 msgid "User" msgstr "L'utilisateur" #: ../modules/loadbalancer.block.php:168 msgid "disconnected." msgstr "est déconnecté." #: ../modules/loadbalancer.block.php:168 msgid "" "It may take a few seconds for the user to disappear (depending on your " "loadbalancer setting)." msgstr "" "La disparition de l'utilisateur peut prendre plusieurs secondes (dépendant " "de la configuration du répartiteur de charge)." #: ../modules/loadbalancer.block.php:169 msgid "Exit" msgstr "Quitter" #: ../modules/loadbalancer.block.php:202 msgid "users" msgstr "utilisateurs" #: ../modules/loadbalancer.block.php:205 msgid "user" msgstr "utilisateur" #: ../modules/loadbalancer.block.php:209 msgid "Full user list" msgstr "Liste de tous les utilisateurs" #: ../modules/loadbalancer.block.php:212 msgid "Users on" msgstr "Utilisateurs sur" #: ../modules/loadbalancer.block.php:218 #: ../modules/accountmanager.block.php:46 msgid "Username" msgstr "Nom d'utilisateur" #: ../modules/loadbalancer.block.php:222 msgid "Application server" msgstr "Serveur d'application" #: ../modules/loadbalancer.block.php:226 #: ../modules/accountmanager.block.php:52 msgid "Actions" msgstr "Actions" #: ../modules/loadbalancer.block.php:235 msgid "click to expand" msgstr "cliquer pour étendre" #: ../modules/appservers.page.php:27 msgid "Application servers" msgstr "Serveurs d'applications" #: ../modules/users.page.php:27 msgid "Users" msgstr "Utilisateurs" #: ../modules/accountmanager.block.php:34 msgid "List of process on" msgstr "Liste des processus sur" #: ../modules/accountmanager.block.php:37 msgid "List of process for user" msgstr "Liste des processus de l'utilisateur" #: ../modules/accountmanager.block.php:37 msgid "on" msgstr "sur" #: ../modules/accountmanager.block.php:50 msgid "Process ID" msgstr "# de processus" #: ../modules/accountmanager.block.php:51 msgid "Process name" msgstr "Nom de processus" ltsp-cluster-control-2.0.3/Adminng/README0000664000175000017500000000067112026403127020277 0ustar stgraberstgraberDependencies: PHP5 (obviously) gettext support for PHP5 php5-mcrypt Translations: In order to get the translations to work correctly, your PHP must support gettext. Furthermore, some distributions like Ubuntu don't ship /usr/locale/*/ unless you install the language packs for the language you want to be supported. If that's the case for your, install the language packs for every language you want to support. ltsp-cluster-control-2.0.3/Adminng/smarty/0000775000175000017500000000000012026403130020724 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/smarty/config/0000775000175000017500000000000012026403127022177 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/smarty/test.php0000664000175000017500000000046412026403127022426 0ustar stgraberstgrabertemplate_dir = 'template'; $smarty->compile_dir = 'template_c'; $smarty->cache_dir = 'cache'; $smarty->config_dir = 'config'; $smarty->assign('name', 'Ned'); $smarty->display('index.tpl'); ?> ltsp-cluster-control-2.0.3/Adminng/smarty/template/0000775000175000017500000000000012026403130022537 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/smarty/template/index.tpl0000664000175000017500000000012312026403127024371 0ustar stgraberstgraber Smarty Hello, {$name}! ltsp-cluster-control-2.0.3/Adminng/smarty/cache/0000775000175000017500000000000012026403127021775 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/smarty/template_c/0000775000175000017500000000000012026403130023041 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/smarty/template_c/%%45^45E^45E480CD%%index.tpl.php0000664000175000017500000000033112026403127027552 0ustar stgraberstgraber Smarty Hello, _tpl_vars['name']; ?> ! ltsp-cluster-control-2.0.3/Adminng/config.sample.php0000664000175000017500000000040712026403127022652 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Adminng/includes/0000775000175000017500000000000012026403130021213 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/includes/server.php0000664000175000017500000000053712026403127023245 0ustar stgraberstgrabergetParam(0)->scalarval(); return new xmlrpcresp(new xmlrpcval("You said : ".$value,"string")); } $s = new xmlrpc_server( array( "test" => array("function" => "test") ) ); ?> ltsp-cluster-control-2.0.3/Adminng/includes/xmlrpc/0000775000175000017500000000000012026403130022520 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/includes/xmlrpc/xmlrpcs.inc0000664000175000017500000011734612026403127024725 0ustar stgraberstgraber // $Id: xmlrpcs.inc,v 1.71 2008/10/29 23:41:28 ggiunta Exp $ // Copyright (c) 1999,2000,2002 Edd Dumbill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // * Neither the name of the "XML-RPC for PHP" nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. // XML RPC Server class // requires: xmlrpc.inc $GLOBALS['xmlrpcs_capabilities'] = array( // xmlrpc spec: always supported 'xmlrpc' => new xmlrpcval(array( 'specUrl' => new xmlrpcval('http://www.xmlrpc.com/spec', 'string'), 'specVersion' => new xmlrpcval(1, 'int') ), 'struct'), // if we support system.xxx functions, we always support multicall, too... // Note that, as of 2006/09/17, the following URL does not respond anymore 'system.multicall' => new xmlrpcval(array( 'specUrl' => new xmlrpcval('http://www.xmlrpc.com/discuss/msgReader$1208', 'string'), 'specVersion' => new xmlrpcval(1, 'int') ), 'struct'), // introspection: version 2! we support 'mixed', too 'introspection' => new xmlrpcval(array( 'specUrl' => new xmlrpcval('http://phpxmlrpc.sourceforge.net/doc-2/ch10.html', 'string'), 'specVersion' => new xmlrpcval(2, 'int') ), 'struct') ); /* Functions that implement system.XXX methods of xmlrpc servers */ $_xmlrpcs_getCapabilities_sig=array(array($GLOBALS['xmlrpcStruct'])); $_xmlrpcs_getCapabilities_doc='This method lists all the capabilites that the XML-RPC server has: the (more or less standard) extensions to the xmlrpc spec that it adheres to'; $_xmlrpcs_getCapabilities_sdoc=array(array('list of capabilities, described as structs with a version number and url for the spec')); function _xmlrpcs_getCapabilities($server, $m=null) { $outAr = $GLOBALS['xmlrpcs_capabilities']; // NIL extension if ($GLOBALS['xmlrpc_null_extension']) { $outAr['nil'] = new xmlrpcval(array( 'specUrl' => new xmlrpcval('http://www.ontosys.com/xml-rpc/extensions.php', 'string'), 'specVersion' => new xmlrpcval(1, 'int') ), 'struct'); } return new xmlrpcresp(new xmlrpcval($outAr, 'struct')); } // listMethods: signature was either a string, or nothing. // The useless string variant has been removed $_xmlrpcs_listMethods_sig=array(array($GLOBALS['xmlrpcArray'])); $_xmlrpcs_listMethods_doc='This method lists all the methods that the XML-RPC server knows how to dispatch'; $_xmlrpcs_listMethods_sdoc=array(array('list of method names')); function _xmlrpcs_listMethods($server, $m=null) // if called in plain php values mode, second param is missing { $outAr=array(); foreach($server->dmap as $key => $val) { $outAr[]=new xmlrpcval($key, 'string'); } if($server->allow_system_funcs) { foreach($GLOBALS['_xmlrpcs_dmap'] as $key => $val) { $outAr[]=new xmlrpcval($key, 'string'); } } return new xmlrpcresp(new xmlrpcval($outAr, 'array')); } $_xmlrpcs_methodSignature_sig=array(array($GLOBALS['xmlrpcArray'], $GLOBALS['xmlrpcString'])); $_xmlrpcs_methodSignature_doc='Returns an array of known signatures (an array of arrays) for the method name passed. If no signatures are known, returns a none-array (test for type != array to detect missing signature)'; $_xmlrpcs_methodSignature_sdoc=array(array('list of known signatures, each sig being an array of xmlrpc type names', 'name of method to be described')); function _xmlrpcs_methodSignature($server, $m) { // let accept as parameter both an xmlrpcval or string if (is_object($m)) { $methName=$m->getParam(0); $methName=$methName->scalarval(); } else { $methName=$m; } if(strpos($methName, "system.") === 0) { $dmap=$GLOBALS['_xmlrpcs_dmap']; $sysCall=1; } else { $dmap=$server->dmap; $sysCall=0; } if(isset($dmap[$methName])) { if(isset($dmap[$methName]['signature'])) { $sigs=array(); foreach($dmap[$methName]['signature'] as $inSig) { $cursig=array(); foreach($inSig as $sig) { $cursig[]=new xmlrpcval($sig, 'string'); } $sigs[]=new xmlrpcval($cursig, 'array'); } $r=new xmlrpcresp(new xmlrpcval($sigs, 'array')); } else { // NB: according to the official docs, we should be returning a // "none-array" here, which means not-an-array $r=new xmlrpcresp(new xmlrpcval('undef', 'string')); } } else { $r=new xmlrpcresp(0,$GLOBALS['xmlrpcerr']['introspect_unknown'], $GLOBALS['xmlrpcstr']['introspect_unknown']); } return $r; } $_xmlrpcs_methodHelp_sig=array(array($GLOBALS['xmlrpcString'], $GLOBALS['xmlrpcString'])); $_xmlrpcs_methodHelp_doc='Returns help text if defined for the method passed, otherwise returns an empty string'; $_xmlrpcs_methodHelp_sdoc=array(array('method description', 'name of the method to be described')); function _xmlrpcs_methodHelp($server, $m) { // let accept as parameter both an xmlrpcval or string if (is_object($m)) { $methName=$m->getParam(0); $methName=$methName->scalarval(); } else { $methName=$m; } if(strpos($methName, "system.") === 0) { $dmap=$GLOBALS['_xmlrpcs_dmap']; $sysCall=1; } else { $dmap=$server->dmap; $sysCall=0; } if(isset($dmap[$methName])) { if(isset($dmap[$methName]['docstring'])) { $r=new xmlrpcresp(new xmlrpcval($dmap[$methName]['docstring']), 'string'); } else { $r=new xmlrpcresp(new xmlrpcval('', 'string')); } } else { $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['introspect_unknown'], $GLOBALS['xmlrpcstr']['introspect_unknown']); } return $r; } $_xmlrpcs_multicall_sig = array(array($GLOBALS['xmlrpcArray'], $GLOBALS['xmlrpcArray'])); $_xmlrpcs_multicall_doc = 'Boxcar multiple RPC calls in one request. See http://www.xmlrpc.com/discuss/msgReader$1208 for details'; $_xmlrpcs_multicall_sdoc = array(array('list of response structs, where each struct has the usual members', 'list of calls, with each call being represented as a struct, with members "methodname" and "params"')); function _xmlrpcs_multicall_error($err) { if(is_string($err)) { $str = $GLOBALS['xmlrpcstr']["multicall_${err}"]; $code = $GLOBALS['xmlrpcerr']["multicall_${err}"]; } else { $code = $err->faultCode(); $str = $err->faultString(); } $struct = array(); $struct['faultCode'] = new xmlrpcval($code, 'int'); $struct['faultString'] = new xmlrpcval($str, 'string'); return new xmlrpcval($struct, 'struct'); } function _xmlrpcs_multicall_do_call($server, $call) { if($call->kindOf() != 'struct') { return _xmlrpcs_multicall_error('notstruct'); } $methName = @$call->structmem('methodName'); if(!$methName) { return _xmlrpcs_multicall_error('nomethod'); } if($methName->kindOf() != 'scalar' || $methName->scalartyp() != 'string') { return _xmlrpcs_multicall_error('notstring'); } if($methName->scalarval() == 'system.multicall') { return _xmlrpcs_multicall_error('recursion'); } $params = @$call->structmem('params'); if(!$params) { return _xmlrpcs_multicall_error('noparams'); } if($params->kindOf() != 'array') { return _xmlrpcs_multicall_error('notarray'); } $numParams = $params->arraysize(); $msg = new xmlrpcmsg($methName->scalarval()); for($i = 0; $i < $numParams; $i++) { if(!$msg->addParam($params->arraymem($i))) { $i++; return _xmlrpcs_multicall_error(new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['incorrect_params'], $GLOBALS['xmlrpcstr']['incorrect_params'] . ": probable xml error in param " . $i)); } } $result = $server->execute($msg); if($result->faultCode() != 0) { return _xmlrpcs_multicall_error($result); // Method returned fault. } return new xmlrpcval(array($result->value()), 'array'); } function _xmlrpcs_multicall_do_call_phpvals($server, $call) { if(!is_array($call)) { return _xmlrpcs_multicall_error('notstruct'); } if(!array_key_exists('methodName', $call)) { return _xmlrpcs_multicall_error('nomethod'); } if (!is_string($call['methodName'])) { return _xmlrpcs_multicall_error('notstring'); } if($call['methodName'] == 'system.multicall') { return _xmlrpcs_multicall_error('recursion'); } if(!array_key_exists('params', $call)) { return _xmlrpcs_multicall_error('noparams'); } if(!is_array($call['params'])) { return _xmlrpcs_multicall_error('notarray'); } // this is a real dirty and simplistic hack, since we might have received a // base64 or datetime values, but they will be listed as strings here... $numParams = count($call['params']); $pt = array(); foreach($call['params'] as $val) $pt[] = php_2_xmlrpc_type(gettype($val)); $result = $server->execute($call['methodName'], $call['params'], $pt); if($result->faultCode() != 0) { return _xmlrpcs_multicall_error($result); // Method returned fault. } return new xmlrpcval(array($result->value()), 'array'); } function _xmlrpcs_multicall($server, $m) { $result = array(); // let accept a plain list of php parameters, beside a single xmlrpc msg object if (is_object($m)) { $calls = $m->getParam(0); $numCalls = $calls->arraysize(); for($i = 0; $i < $numCalls; $i++) { $call = $calls->arraymem($i); $result[$i] = _xmlrpcs_multicall_do_call($server, $call); } } else { $numCalls=count($m); for($i = 0; $i < $numCalls; $i++) { $result[$i] = _xmlrpcs_multicall_do_call_phpvals($server, $m[$i]); } } return new xmlrpcresp(new xmlrpcval($result, 'array')); } $GLOBALS['_xmlrpcs_dmap']=array( 'system.listMethods' => array( 'function' => '_xmlrpcs_listMethods', 'signature' => $_xmlrpcs_listMethods_sig, 'docstring' => $_xmlrpcs_listMethods_doc, 'signature_docs' => $_xmlrpcs_listMethods_sdoc), 'system.methodHelp' => array( 'function' => '_xmlrpcs_methodHelp', 'signature' => $_xmlrpcs_methodHelp_sig, 'docstring' => $_xmlrpcs_methodHelp_doc, 'signature_docs' => $_xmlrpcs_methodHelp_sdoc), 'system.methodSignature' => array( 'function' => '_xmlrpcs_methodSignature', 'signature' => $_xmlrpcs_methodSignature_sig, 'docstring' => $_xmlrpcs_methodSignature_doc, 'signature_docs' => $_xmlrpcs_methodSignature_sdoc), 'system.multicall' => array( 'function' => '_xmlrpcs_multicall', 'signature' => $_xmlrpcs_multicall_sig, 'docstring' => $_xmlrpcs_multicall_doc, 'signature_docs' => $_xmlrpcs_multicall_sdoc), 'system.getCapabilities' => array( 'function' => '_xmlrpcs_getCapabilities', 'signature' => $_xmlrpcs_getCapabilities_sig, 'docstring' => $_xmlrpcs_getCapabilities_doc, 'signature_docs' => $_xmlrpcs_getCapabilities_sdoc) ); $GLOBALS['_xmlrpcs_occurred_errors'] = ''; $GLOBALS['_xmlrpcs_prev_ehandler'] = ''; /** * Error handler used to track errors that occur during server-side execution of PHP code. * This allows to report back to the client whether an internal error has occurred or not * using an xmlrpc response object, instead of letting the client deal with the html junk * that a PHP execution error on the server generally entails. * * NB: in fact a user defined error handler can only handle WARNING, NOTICE and USER_* errors. * */ function _xmlrpcs_errorHandler($errcode, $errstring, $filename=null, $lineno=null, $context=null) { // obey the @ protocol if (error_reporting() == 0) return; //if($errcode != E_NOTICE && $errcode != E_WARNING && $errcode != E_USER_NOTICE && $errcode != E_USER_WARNING) if($errcode != E_STRICT) { $GLOBALS['_xmlrpcs_occurred_errors'] = $GLOBALS['_xmlrpcs_occurred_errors'] . $errstring . "\n"; } // Try to avoid as much as possible disruption to the previous error handling // mechanism in place if($GLOBALS['_xmlrpcs_prev_ehandler'] == '') { // The previous error handler was the default: all we should do is log error // to the default error log (if level high enough) if(ini_get('log_errors') && (intval(ini_get('error_reporting')) & $errcode)) { error_log($errstring); } } else { // Pass control on to previous error handler, trying to avoid loops... if($GLOBALS['_xmlrpcs_prev_ehandler'] != '_xmlrpcs_errorHandler') { // NB: this code will NOT work on php < 4.0.2: only 2 params were used for error handlers if(is_array($GLOBALS['_xmlrpcs_prev_ehandler'])) { // the following works both with static class methods and plain object methods as error handler call_user_func_array($GLOBALS['_xmlrpcs_prev_ehandler'], array($errcode, $errstring, $filename, $lineno, $context)); } else { $GLOBALS['_xmlrpcs_prev_ehandler']($errcode, $errstring, $filename, $lineno, $context); } } } } $GLOBALS['_xmlrpc_debuginfo']=''; /** * Add a string to the debug info that can be later seralized by the server * as part of the response message. * Note that for best compatbility, the debug string should be encoded using * the $GLOBALS['xmlrpc_internalencoding'] character set. * @param string $m * @access public */ function xmlrpc_debugmsg($m) { $GLOBALS['_xmlrpc_debuginfo'] .= $m . "\n"; } class xmlrpc_server { /** * Array defining php functions exposed as xmlrpc methods by this server * @access private */ var $dmap=array(); /** * Defines how functions in dmap will be invoked: either using an xmlrpc msg object * or plain php values. * valid strings are 'xmlrpcvals', 'phpvals' or 'epivals' */ var $functions_parameters_type='xmlrpcvals'; /** * Option used for fine-tuning the encoding the php values returned from * functions registered in the dispatch map when the functions_parameters_types * member is set to 'phpvals' * @see php_xmlrpc_encode for a list of values */ var $phpvals_encoding_options = array( 'auto_dates' ); /// controls wether the server is going to echo debugging messages back to the client as comments in response body. valid values: 0,1,2,3 var $debug = 1; /** * Controls behaviour of server when invoked user function throws an exception: * 0 = catch it and return an 'internal error' xmlrpc response (default) * 1 = catch it and return an xmlrpc response with the error corresponding to the exception * 2 = allow the exception to float to the upper layers */ var $exception_handling = 0; /** * When set to true, it will enable HTTP compression of the response, in case * the client has declared its support for compression in the request. */ var $compress_response = false; /** * List of http compression methods accepted by the server for requests. * NB: PHP supports deflate, gzip compressions out of the box if compiled w. zlib */ var $accepted_compression = array(); /// shall we serve calls to system.* methods? var $allow_system_funcs = true; /// list of charset encodings natively accepted for requests var $accepted_charset_encodings = array(); /** * charset encoding to be used for response. * NB: if we can, we will convert the generated response from internal_encoding to the intended one. * can be: a supported xml encoding (only UTF-8 and ISO-8859-1 at present, unless mbstring is enabled), * null (leave unspecified in response, convert output stream to US_ASCII), * 'default' (use xmlrpc library default as specified in xmlrpc.inc, convert output stream if needed), * or 'auto' (use client-specified charset encoding or same as request if request headers do not specify it (unless request is US-ASCII: then use library default anyway). * NB: pretty dangerous if you accept every charset and do not have mbstring enabled) */ var $response_charset_encoding = ''; /** * Storage for internal debug info * @access private */ var $debug_info = ''; /** * Extra data passed at runtime to method handling functions. Used only by EPI layer */ var $user_data = null; /** * @param array $dispmap the dispatch map withd efinition of exposed services * @param boolean $servicenow set to false to prevent the server from runnung upon construction */ function xmlrpc_server($dispMap=null, $serviceNow=true) { // if ZLIB is enabled, let the server by default accept compressed requests, // and compress responses sent to clients that support them if(function_exists('gzinflate')) { $this->accepted_compression = array('gzip', 'deflate'); $this->compress_response = true; } // by default the xml parser can support these 3 charset encodings $this->accepted_charset_encodings = array('UTF-8', 'ISO-8859-1', 'US-ASCII'); // dispMap is a dispatch array of methods // mapped to function names and signatures // if a method // doesn't appear in the map then an unknown // method error is generated /* milosch - changed to make passing dispMap optional. * instead, you can use the class add_to_map() function * to add functions manually (borrowed from SOAPX4) */ if($dispMap) { $this->dmap = $dispMap; if($serviceNow) { $this->service(); } } } /** * Set debug level of server. * @param integer $in debug lvl: determines info added to xmlrpc responses (as xml comments) * 0 = no debug info, * 1 = msgs set from user with debugmsg(), * 2 = add complete xmlrpc request (headers and body), * 3 = add also all processing warnings happened during method processing * (NB: this involves setting a custom error handler, and might interfere * with the standard processing of the php function exposed as method. In * particular, triggering an USER_ERROR level error will not halt script * execution anymore, but just end up logged in the xmlrpc response) * Note that info added at elevel 2 and 3 will be base64 encoded * @access public */ function setDebug($in) { $this->debug=$in; } /** * Return a string with the serialized representation of all debug info * @param string $charset_encoding the target charset encoding for the serialization * @return string an XML comment (or two) */ function serializeDebug($charset_encoding='') { // Tough encoding problem: which internal charset should we assume for debug info? // It might contain a copy of raw data received from client, ie with unknown encoding, // intermixed with php generated data and user generated data... // so we split it: system debug is base 64 encoded, // user debug info should be encoded by the end user using the INTERNAL_ENCODING $out = ''; if ($this->debug_info != '') { $out .= "\n"; } if($GLOBALS['_xmlrpc_debuginfo']!='') { $out .= "\n"; // NB: a better solution MIGHT be to use CDATA, but we need to insert it // into return payload AFTER the beginning tag //$out .= "', ']_]_>', $GLOBALS['_xmlrpc_debuginfo']) . "\n]]>\n"; } return $out; } /** * Execute the xmlrpc request, printing the response * @param string $data the request body. If null, the http POST request will be examined * @return xmlrpcresp the response object (usually not used by caller...) * @access public */ function service($data=null, $return_payload=false) { if ($data === null) { // workaround for a known bug in php ver. 5.2.2 that broke $HTTP_RAW_POST_DATA $ver = phpversion(); if ($ver[0] >= 5) { $data = file_get_contents('php://input'); } else { $data = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : ''; } } $raw_data = $data; // reset internal debug info $this->debug_info = ''; // Echo back what we received, before parsing it if($this->debug > 1) { $this->debugmsg("+++GOT+++\n" . $data . "\n+++END+++"); } $r = $this->parseRequestHeaders($data, $req_charset, $resp_charset, $resp_encoding); if (!$r) { $r=$this->parseRequest($data, $req_charset); } // save full body of request into response, for more debugging usages $r->raw_data = $raw_data; if($this->debug > 2 && $GLOBALS['_xmlrpcs_occurred_errors']) { $this->debugmsg("+++PROCESSING ERRORS AND WARNINGS+++\n" . $GLOBALS['_xmlrpcs_occurred_errors'] . "+++END+++"); } $payload=$this->xml_header($resp_charset); if($this->debug > 0) { $payload = $payload . $this->serializeDebug($resp_charset); } // G. Giunta 2006-01-27: do not create response serialization if it has // already happened. Helps building json magic if (empty($r->payload)) { $r->serialize($resp_charset); } $payload = $payload . $r->payload; if ($return_payload) { return $payload; } // if we get a warning/error that has output some text before here, then we cannot // add a new header. We cannot say we are sending xml, either... if(!headers_sent()) { header('Content-Type: '.$r->content_type); // we do not know if client actually told us an accepted charset, but if he did // we have to tell him what we did header("Vary: Accept-Charset"); // http compression of output: only // if we can do it, and we want to do it, and client asked us to, // and php ini settings do not force it already $php_no_self_compress = !ini_get('zlib.output_compression') && (ini_get('output_handler') != 'ob_gzhandler'); if($this->compress_response && function_exists('gzencode') && $resp_encoding != '' && $php_no_self_compress) { if(strpos($resp_encoding, 'gzip') !== false) { $payload = gzencode($payload); header("Content-Encoding: gzip"); header("Vary: Accept-Encoding"); } elseif (strpos($resp_encoding, 'deflate') !== false) { $payload = gzcompress($payload); header("Content-Encoding: deflate"); header("Vary: Accept-Encoding"); } } // do not ouput content-length header if php is compressing output for us: // it will mess up measurements if($php_no_self_compress) { header('Content-Length: ' . (int)strlen($payload)); } } else { error_log('XML-RPC: '.__METHOD__.': http headers already sent before response is fully generated. Check for php warning or error messages'); } print $payload; // return request, in case subclasses want it return $r; } /** * Add a method to the dispatch map * @param string $methodname the name with which the method will be made available * @param string $function the php function that will get invoked * @param array $sig the array of valid method signatures * @param string $doc method documentation * @param array $sigdoc the array of valid method signatures docs (one string per param, one for return type) * @access public */ function add_to_map($methodname,$function,$sig=null,$doc=false,$sigdoc=false) { $this->dmap[$methodname] = array( 'function' => $function, 'docstring' => $doc ); if ($sig) { $this->dmap[$methodname]['signature'] = $sig; } if ($sigdoc) { $this->dmap[$methodname]['signature_docs'] = $sigdoc; } } /** * Verify type and number of parameters received against a list of known signatures * @param array $in array of either xmlrpcval objects or xmlrpc type definitions * @param array $sig array of known signatures to match against * @access private */ function verifySignature($in, $sig) { // check each possible signature in turn if (is_object($in)) { $numParams = $in->getNumParams(); } else { $numParams = count($in); } foreach($sig as $cursig) { if(count($cursig)==$numParams+1) { $itsOK=1; for($n=0; $n<$numParams; $n++) { if (is_object($in)) { $p=$in->getParam($n); if($p->kindOf() == 'scalar') { $pt=$p->scalartyp(); } else { $pt=$p->kindOf(); } } else { $pt= $in[$n] == 'i4' ? 'int' : strtolower($in[$n]); // dispatch maps never use i4... } // param index is $n+1, as first member of sig is return type if($pt != $cursig[$n+1] && $cursig[$n+1] != $GLOBALS['xmlrpcValue']) { $itsOK=0; $pno=$n+1; $wanted=$cursig[$n+1]; $got=$pt; break; } } if($itsOK) { return array(1,''); } } } if(isset($wanted)) { return array(0, "Wanted ${wanted}, got ${got} at param ${pno}"); } else { return array(0, "No method signature matches number of parameters"); } } /** * Parse http headers received along with xmlrpc request. If needed, inflate request * @return null on success or an xmlrpcresp * @access private */ function parseRequestHeaders(&$data, &$req_encoding, &$resp_encoding, &$resp_compression) { // check if $_SERVER is populated: it might have been disabled via ini file // (this is true even when in CLI mode) if (count($_SERVER) == 0) { error_log('XML-RPC: '.__METHOD__.': cannot parse request headers as $_SERVER is not populated'); } if($this->debug > 1) { if(function_exists('getallheaders')) { $this->debugmsg(''); // empty line foreach(getallheaders() as $name => $val) { $this->debugmsg("HEADER: $name: $val"); } } } if(isset($_SERVER['HTTP_CONTENT_ENCODING'])) { $content_encoding = str_replace('x-', '', $_SERVER['HTTP_CONTENT_ENCODING']); } else { $content_encoding = ''; } // check if request body has been compressed and decompress it if($content_encoding != '' && strlen($data)) { if($content_encoding == 'deflate' || $content_encoding == 'gzip') { // if decoding works, use it. else assume data wasn't gzencoded if(function_exists('gzinflate') && in_array($content_encoding, $this->accepted_compression)) { if($content_encoding == 'deflate' && $degzdata = @gzuncompress($data)) { $data = $degzdata; if($this->debug > 1) { $this->debugmsg("\n+++INFLATED REQUEST+++[".strlen($data)." chars]+++\n" . $data . "\n+++END+++"); } } elseif($content_encoding == 'gzip' && $degzdata = @gzinflate(substr($data, 10))) { $data = $degzdata; if($this->debug > 1) $this->debugmsg("+++INFLATED REQUEST+++[".strlen($data)." chars]+++\n" . $data . "\n+++END+++"); } else { $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_decompress_fail'], $GLOBALS['xmlrpcstr']['server_decompress_fail']); return $r; } } else { //error_log('The server sent deflated data. Your php install must have the Zlib extension compiled in to support this.'); $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_cannot_decompress'], $GLOBALS['xmlrpcstr']['server_cannot_decompress']); return $r; } } } // check if client specified accepted charsets, and if we know how to fulfill // the request if ($this->response_charset_encoding == 'auto') { $resp_encoding = ''; if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) { // here we should check if we can match the client-requested encoding // with the encodings we know we can generate. /// @todo we should parse q=0.x preferences instead of getting first charset specified... $client_accepted_charsets = explode(',', strtoupper($_SERVER['HTTP_ACCEPT_CHARSET'])); // Give preference to internal encoding $known_charsets = array($GLOBALS['xmlrpc_internalencoding'], 'UTF-8', 'ISO-8859-1', 'US-ASCII'); foreach ($known_charsets as $charset) { foreach ($client_accepted_charsets as $accepted) if (strpos($accepted, $charset) === 0) { $resp_encoding = $charset; break; } if ($resp_encoding) break; } } } else { $resp_encoding = $this->response_charset_encoding; } if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) { $resp_compression = $_SERVER['HTTP_ACCEPT_ENCODING']; } else { $resp_compression = ''; } // 'guestimate' request encoding /// @todo check if mbstring is enabled and automagic input conversion is on: it might mingle with this check??? $req_encoding = guess_encoding(isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '', $data); return null; } /** * Parse an xml chunk containing an xmlrpc request and execute the corresponding * php function registered with the server * @param string $data the xml request * @param string $req_encoding (optional) the charset encoding of the xml request * @return xmlrpcresp * @access private */ function parseRequest($data, $req_encoding='') { // 2005/05/07 commented and moved into caller function code //if($data=='') //{ // $data=$GLOBALS['HTTP_RAW_POST_DATA']; //} // G. Giunta 2005/02/13: we do NOT expect to receive html entities // so we do not try to convert them into xml character entities //$data = xmlrpc_html_entity_xlate($data); $GLOBALS['_xh']=array(); $GLOBALS['_xh']['ac']=''; $GLOBALS['_xh']['stack']=array(); $GLOBALS['_xh']['valuestack'] = array(); $GLOBALS['_xh']['params']=array(); $GLOBALS['_xh']['pt']=array(); $GLOBALS['_xh']['isf']=0; $GLOBALS['_xh']['isf_reason']=''; $GLOBALS['_xh']['method']=false; // so we can check later if we got a methodname or not $GLOBALS['_xh']['rt']=''; // decompose incoming XML into request structure if ($req_encoding != '') { if (!in_array($req_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) // the following code might be better for mb_string enabled installs, but // makes the lib about 200% slower... //if (!is_valid_charset($req_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { error_log('XML-RPC: '.__METHOD__.': invalid charset encoding of received request: '.$req_encoding); $req_encoding = $GLOBALS['xmlrpc_defencoding']; } /// @BUG this will fail on PHP 5 if charset is not specified in the xml prologue, // the encoding is not UTF8 and there are non-ascii chars in the text... /// @todo use an ampty string for php 5 ??? $parser = xml_parser_create($req_encoding); } else { $parser = xml_parser_create(); } xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell // the xml parser to give us back data in the expected charset // What if internal encoding is not in one of the 3 allowed? // we use the broadest one, ie. utf8 // This allows to send data which is native in various charset, // by extending xmlrpc_encode_entitites() and setting xmlrpc_internalencoding if (!in_array($GLOBALS['xmlrpc_internalencoding'], array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8'); } else { xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $GLOBALS['xmlrpc_internalencoding']); } if ($this->functions_parameters_type != 'xmlrpcvals') xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_fast'); else xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee'); xml_set_character_data_handler($parser, 'xmlrpc_cd'); xml_set_default_handler($parser, 'xmlrpc_dh'); if(!xml_parse($parser, $data, 1)) { // return XML error as a faultCode $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerrxml']+xml_get_error_code($parser), sprintf('XML error: %s at line %d, column %d', xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser), xml_get_current_column_number($parser))); xml_parser_free($parser); } elseif ($GLOBALS['_xh']['isf']) { xml_parser_free($parser); $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_request'], $GLOBALS['xmlrpcstr']['invalid_request'] . ' ' . $GLOBALS['_xh']['isf_reason']); } else { xml_parser_free($parser); // small layering violation in favor of speed and memory usage: // we should allow the 'execute' method handle this, but in the // most common scenario (xmlrpcvals type server with some methods // registered as phpvals) that would mean a useless encode+decode pass if ($this->functions_parameters_type != 'xmlrpcvals' || (isset($this->dmap[$GLOBALS['_xh']['method']]['parameters_type']) && ($this->dmap[$GLOBALS['_xh']['method']]['parameters_type'] == 'phpvals'))) { if($this->debug > 1) { $this->debugmsg("\n+++PARSED+++\n".var_export($GLOBALS['_xh']['params'], true)."\n+++END+++"); } $r = $this->execute($GLOBALS['_xh']['method'], $GLOBALS['_xh']['params'], $GLOBALS['_xh']['pt']); } else { // build an xmlrpcmsg object with data parsed from xml $m=new xmlrpcmsg($GLOBALS['_xh']['method']); // now add parameters in for($i=0; $iaddParam($GLOBALS['_xh']['params'][$i]); } if($this->debug > 1) { $this->debugmsg("\n+++PARSED+++\n".var_export($m, true)."\n+++END+++"); } $r = $this->execute($m); } } return $r; } /** * Execute a method invoked by the client, checking parameters used * @param mixed $m either an xmlrpcmsg obj or a method name * @param array $params array with method parameters as php types (if m is method name only) * @param array $paramtypes array with xmlrpc types of method parameters (if m is method name only) * @return xmlrpcresp * @access private */ function execute($m, $params=null, $paramtypes=null) { if (is_object($m)) { $methName = $m->method(); } else { $methName = $m; } $sysCall = $this->allow_system_funcs && (strpos($methName, "system.") === 0); $dmap = $sysCall ? $GLOBALS['_xmlrpcs_dmap'] : $this->dmap; if(!isset($dmap[$methName]['function'])) { // No such method return new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['unknown_method'], $GLOBALS['xmlrpcstr']['unknown_method']); } // Check signature if(isset($dmap[$methName]['signature'])) { $sig = $dmap[$methName]['signature']; if (is_object($m)) { list($ok, $errstr) = $this->verifySignature($m, $sig); } else { list($ok, $errstr) = $this->verifySignature($paramtypes, $sig); } if(!$ok) { // Didn't match. return new xmlrpcresp( 0, $GLOBALS['xmlrpcerr']['incorrect_params'], $GLOBALS['xmlrpcstr']['incorrect_params'] . ": ${errstr}" ); } } $func = $dmap[$methName]['function']; // let the 'class::function' syntax be accepted in dispatch maps if(is_string($func) && strpos($func, '::')) { $func = explode('::', $func); } // verify that function to be invoked is in fact callable if(!is_callable($func)) { error_log("XML-RPC: ".__METHOD__.": function $func registered as method handler is not callable"); return new xmlrpcresp( 0, $GLOBALS['xmlrpcerr']['server_error'], $GLOBALS['xmlrpcstr']['server_error'] . ": no function matches method" ); } // If debug level is 3, we should catch all errors generated during // processing of user function, and log them as part of response if($this->debug > 2) { $GLOBALS['_xmlrpcs_prev_ehandler'] = set_error_handler('_xmlrpcs_errorHandler'); } try { // Allow mixed-convention servers if (is_object($m)) { if($sysCall) { $r = call_user_func($func, $this, $m); } else { $r = call_user_func($func, $m); } if (!is_a($r, 'xmlrpcresp')) { error_log("XML-RPC: ".__METHOD__.": function $func registered as method handler does not return an xmlrpcresp object"); if (is_a($r, 'xmlrpcval')) { $r = new xmlrpcresp($r); } else { $r = new xmlrpcresp( 0, $GLOBALS['xmlrpcerr']['server_error'], $GLOBALS['xmlrpcstr']['server_error'] . ": function does not return xmlrpcresp object" ); } } } else { // call a 'plain php' function if($sysCall) { array_unshift($params, $this); $r = call_user_func_array($func, $params); } else { // 3rd API convention for method-handling functions: EPI-style if ($this->functions_parameters_type == 'epivals') { $r = call_user_func_array($func, array($methName, $params, $this->user_data)); // mimic EPI behaviour: if we get an array that looks like an error, make it // an eror response if (is_array($r) && array_key_exists('faultCode', $r) && array_key_exists('faultString', $r)) { $r = new xmlrpcresp(0, (integer)$r['faultCode'], (string)$r['faultString']); } else { // functions using EPI api should NOT return resp objects, // so make sure we encode the return type correctly $r = new xmlrpcresp(php_xmlrpc_encode($r, array('extension_api'))); } } else { $r = call_user_func_array($func, $params); } } // the return type can be either an xmlrpcresp object or a plain php value... if (!is_a($r, 'xmlrpcresp')) { // what should we assume here about automatic encoding of datetimes // and php classes instances??? $r = new xmlrpcresp(php_xmlrpc_encode($r, $this->phpvals_encoding_options)); } } } catch(Exception $e) { // (barring errors in the lib) an uncatched exception happened // in the called function, we wrap it in a proper error-response switch($this->exception_handling) { case 2: throw $e; break; case 1: $r = new xmlrpcresp(0, $e->getCode(), $e->getMessage()); break; default: $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['server_error'], $GLOBALS['xmlrpcstr']['server_error']); } } if($this->debug > 2) { // note: restore the error handler we found before calling the // user func, even if it has been changed inside the func itself if($GLOBALS['_xmlrpcs_prev_ehandler']) { set_error_handler($GLOBALS['_xmlrpcs_prev_ehandler']); } else { restore_error_handler(); } } return $r; } /** * add a string to the 'internal debug message' (separate from 'user debug message') * @param string $strings * @access private */ function debugmsg($string) { $this->debug_info .= $string."\n"; } /** * @access private */ function xml_header($charset_encoding='') { if ($charset_encoding != '') { return "\n"; } else { return "\n"; } } /** * A debugging routine: just echoes back the input packet as a string value * DEPRECATED! */ function echoInput() { $r=new xmlrpcresp(new xmlrpcval( "'Aha said I: '" . $GLOBALS['HTTP_RAW_POST_DATA'], 'string')); print $r->serialize(); } } ?>ltsp-cluster-control-2.0.3/Adminng/includes/xmlrpc/xmlrpc_wrappers.inc0000664000175000017500000010522612026403127026457 0ustar stgraberstgraber' . $funcname[1]; } $exists = method_exists($funcname[0], $funcname[1]); if (!$exists && version_compare(phpversion(), '5.1') < 0) { // workaround for php 5.0: static class methods are not seen by method_exists $exists = is_callable( $funcname ); } } else { $plainfuncname = $funcname; $exists = function_exists($funcname); } if(!$exists) { error_log('XML-RPC: function to be wrapped is not defined: '.$plainfuncname); return false; } else { // determine name of new php function if($newfuncname == '') { if(is_array($funcname)) { if(is_string($funcname[0])) $xmlrpcfuncname = "{$prefix}_".implode('_', $funcname); else $xmlrpcfuncname = "{$prefix}_".get_class($funcname[0]) . '_' . $funcname[1]; } else { $xmlrpcfuncname = "{$prefix}_$funcname"; } } else { $xmlrpcfuncname = $newfuncname; } while($buildit && function_exists($xmlrpcfuncname)) { $xmlrpcfuncname .= 'x'; } // start to introspect PHP code if(is_array($funcname)) { $func = new ReflectionMethod($funcname[0], $funcname[1]); if($func->isPrivate()) { error_log('XML-RPC: method to be wrapped is private: '.$plainfuncname); return false; } if($func->isProtected()) { error_log('XML-RPC: method to be wrapped is protected: '.$plainfuncname); return false; } if($func->isConstructor()) { error_log('XML-RPC: method to be wrapped is the constructor: '.$plainfuncname); return false; } // php 503 always says isdestructor = true... if( version_compare(phpversion(), '5.0.3') != 0 && $func->isDestructor()) { error_log('XML-RPC: method to be wrapped is the destructor: '.$plainfuncname); return false; } if($func->isAbstract()) { error_log('XML-RPC: method to be wrapped is abstract: '.$plainfuncname); return false; } /// @todo add more checks for static vs. nonstatic? } else { $func = new ReflectionFunction($funcname); } if($func->isInternal()) { // Note: from PHP 5.1.0 onward, we will possibly be able to use invokeargs // instead of getparameters to fully reflect internal php functions ? error_log('XML-RPC: function to be wrapped is internal: '.$plainfuncname); return false; } // retrieve parameter names, types and description from javadoc comments // function description $desc = ''; // type of return val: by default 'any' $returns = $GLOBALS['xmlrpcValue']; // desc of return val $returnsDocs = ''; // type + name of function parameters $paramDocs = array(); $docs = $func->getDocComment(); if($docs != '') { $docs = explode("\n", $docs); $i = 0; foreach($docs as $doc) { $doc = trim($doc, " \r\t/*"); if(strlen($doc) && strpos($doc, '@') !== 0 && !$i) { if($desc) { $desc .= "\n"; } $desc .= $doc; } elseif(strpos($doc, '@param') === 0) { // syntax: @param type [$name] desc if(preg_match('/@param\s+(\S+)(\s+\$\S+)?\s+(.+)/', $doc, $matches)) { if(strpos($matches[1], '|')) { //$paramDocs[$i]['type'] = explode('|', $matches[1]); $paramDocs[$i]['type'] = 'mixed'; } else { $paramDocs[$i]['type'] = $matches[1]; } $paramDocs[$i]['name'] = trim($matches[2]); $paramDocs[$i]['doc'] = $matches[3]; } $i++; } elseif(strpos($doc, '@return') === 0) { // syntax: @return type desc //$returns = preg_split('/\s+/', $doc); if(preg_match('/@return\s+(\S+)\s+(.+)/', $doc, $matches)) { $returns = php_2_xmlrpc_type($matches[1]); if(isset($matches[2])) { $returnsDocs = $matches[2]; } } } } } // execute introspection of actual function prototype $params = array(); $i = 0; foreach($func->getParameters() as $paramobj) { $params[$i] = array(); $params[$i]['name'] = '$'.$paramobj->getName(); $params[$i]['isoptional'] = $paramobj->isOptional(); $i++; } // start building of PHP code to be eval'd $innercode = ''; $i = 0; $parsvariations = array(); $pars = array(); $pnum = count($params); foreach($params as $param) { if (isset($paramDocs[$i]['name']) && $paramDocs[$i]['name'] && strtolower($paramDocs[$i]['name']) != strtolower($param['name'])) { // param name from phpdoc info does not match param definition! $paramDocs[$i]['type'] = 'mixed'; } if($param['isoptional']) { // this particular parameter is optional. save as valid previous list of parameters $innercode .= "if (\$paramcount > $i) {\n"; $parsvariations[] = $pars; } $innercode .= "\$p$i = \$msg->getParam($i);\n"; if ($decode_php_objects) { $innercode .= "if (\$p{$i}->kindOf() == 'scalar') \$p$i = \$p{$i}->scalarval(); else \$p$i = php_{$prefix}_decode(\$p$i, array('decode_php_objs'));\n"; } else { $innercode .= "if (\$p{$i}->kindOf() == 'scalar') \$p$i = \$p{$i}->scalarval(); else \$p$i = php_{$prefix}_decode(\$p$i);\n"; } $pars[] = "\$p$i"; $i++; if($param['isoptional']) { $innercode .= "}\n"; } if($i == $pnum) { // last allowed parameters combination $parsvariations[] = $pars; } } $sigs = array(); $psigs = array(); if(count($parsvariations) == 0) { // only known good synopsis = no parameters $parsvariations[] = array(); $minpars = 0; } else { $minpars = count($parsvariations[0]); } if($minpars) { // add to code the check for min params number // NB: this check needs to be done BEFORE decoding param values $innercode = "\$paramcount = \$msg->getNumParams();\n" . "if (\$paramcount < $minpars) return new {$prefix}resp(0, {$GLOBALS['xmlrpcerr']['incorrect_params']}, '{$GLOBALS['xmlrpcstr']['incorrect_params']}');\n" . $innercode; } else { $innercode = "\$paramcount = \$msg->getNumParams();\n" . $innercode; } $innercode .= "\$np = false;\n"; // since there are no closures in php, if we are given an object instance, // we store a pointer to it in a global var... if ( is_array($funcname) && is_object($funcname[0]) ) { $GLOBALS['xmlrpcWPFObjHolder'][$xmlrpcfuncname] =& $funcname[0]; $innercode .= "\$obj =& \$GLOBALS['xmlrpcWPFObjHolder']['$xmlrpcfuncname'];\n"; $realfuncname = '$obj->'.$funcname[1]; } else { $realfuncname = $plainfuncname; } foreach($parsvariations as $pars) { $innercode .= "if (\$paramcount == " . count($pars) . ") \$retval = {$catch_warnings}$realfuncname(" . implode(',', $pars) . "); else\n"; // build a 'generic' signature (only use an appropriate return type) $sig = array($returns); $psig = array($returnsDocs); for($i=0; $i < count($pars); $i++) { if (isset($paramDocs[$i]['type'])) { $sig[] = php_2_xmlrpc_type($paramDocs[$i]['type']); } else { $sig[] = $GLOBALS['xmlrpcValue']; } $psig[] = isset($paramDocs[$i]['doc']) ? $paramDocs[$i]['doc'] : ''; } $sigs[] = $sig; $psigs[] = $psig; } $innercode .= "\$np = true;\n"; $innercode .= "if (\$np) return new {$prefix}resp(0, {$GLOBALS['xmlrpcerr']['incorrect_params']}, '{$GLOBALS['xmlrpcstr']['incorrect_params']}'); else {\n"; //$innercode .= "if (\$_xmlrpcs_error_occurred) return new xmlrpcresp(0, $GLOBALS['xmlrpcerr']user, \$_xmlrpcs_error_occurred); else\n"; $innercode .= "if (is_a(\$retval, '{$prefix}resp')) return \$retval; else\n"; if($returns == $GLOBALS['xmlrpcDateTime'] || $returns == $GLOBALS['xmlrpcBase64']) { $innercode .= "return new {$prefix}resp(new {$prefix}val(\$retval, '$returns'));"; } else { if ($encode_php_objects) $innercode .= "return new {$prefix}resp(php_{$prefix}_encode(\$retval, array('encode_php_objs')));\n"; else $innercode .= "return new {$prefix}resp(php_{$prefix}_encode(\$retval));\n"; } // shall we exclude functions returning by ref? // if($func->returnsReference()) // return false; $code = "function $xmlrpcfuncname(\$msg) {\n" . $innercode . "}\n}"; //print_r($code); if ($buildit) { $allOK = 0; eval($code.'$allOK=1;'); // alternative //$xmlrpcfuncname = create_function('$m', $innercode); if(!$allOK) { error_log('XML-RPC: could not create function '.$xmlrpcfuncname.' to wrap php function '.$plainfuncname); return false; } } /// @todo examine if $paramDocs matches $parsvariations and build array for /// usage as method signature, plus put together a nice string for docs $ret = array('function' => $xmlrpcfuncname, 'signature' => $sigs, 'docstring' => $desc, 'signature_docs' => $psigs, 'source' => $code); return $ret; } } /** * Given a user-defined PHP class or php object, map its methods onto a list of * PHP 'wrapper' functions that can be exposed as xmlrpc methods from an xmlrpc_server * object and called from remote clients (as well as their corresponding signature info). * * @param mixed $classname the name of the class whose methods are to be exposed as xmlrpc methods, or an object instance of that class * @param array $extra_options see the docs for wrap_php_method for more options * string method_type 'static', 'nonstatic', 'all' and 'auto' (default); the latter will switch between static and non-static depending on wheter $classname is a class name or object instance * @return array or false on failure * * @todo get_class_methods will return both static and non-static methods. * we have to differentiate the action, depending on wheter we recived a class name or object */ function wrap_php_class($classname, $extra_options=array()) { $methodfilter = isset($extra_options['method_filter']) ? $extra_options['method_filter'] : ''; $methodtype = isset($extra_options['method_type']) ? $extra_options['method_type'] : 'auto'; if(version_compare(phpversion(), '5.0.3') == -1) { // up to php 5.0.3 some useful reflection methods were missing error_log('XML-RPC: cannot not wrap php functions unless running php version bigger than 5.0.3'); return false; } $result = array(); $mlist = get_class_methods($classname); foreach($mlist as $mname) { if ($methodfilter == '' || preg_match($methodfilter, $mname)) { // echo $mlist."\n"; $func = new ReflectionMethod($classname, $mname); if(!$func->isPrivate() && !$func->isProtected() && !$func->isConstructor() && !$func->isDestructor() && !$func->isAbstract()) { if(($func->isStatic && ($methodtype == 'all' || $methodtype == 'static' || ($methodtype == 'auto' && is_string($classname)))) || (!$func->isStatic && ($methodtype == 'all' || $methodtype == 'nonstatic' || ($methodtype == 'auto' && is_object($classname))))) { $methodwrap = wrap_php_function(array($classname, $mname), '', $extra_options); if ( $methodwrap ) { $result[$methodwrap['function']] = $methodwrap['function']; } } } } } return $result; } /** * Given an xmlrpc client and a method name, register a php wrapper function * that will call it and return results using native php types for both * params and results. The generated php function will return an xmlrpcresp * oject for failed xmlrpc calls * * Known limitations: * - server must support system.methodsignature for the wanted xmlrpc method * - for methods that expose many signatures, only one can be picked (we * could in priciple check if signatures differ only by number of params * and not by type, but it would be more complication than we can spare time) * - nested xmlrpc params: the caller of the generated php function has to * encode on its own the params passed to the php function if these are structs * or arrays whose (sub)members include values of type datetime or base64 * * Notes: the connection properties of the given client will be copied * and reused for the connection used during the call to the generated * php function. * Calling the generated php function 'might' be slow: a new xmlrpc client * is created on every invocation and an xmlrpc-connection opened+closed. * An extra 'debug' param is appended to param list of xmlrpc method, useful * for debugging purposes. * * @param xmlrpc_client $client an xmlrpc client set up correctly to communicate with target server * @param string $methodname the xmlrpc method to be mapped to a php function * @param array $extra_options array of options that specify conversion details. valid ptions include * integer signum the index of the method signature to use in mapping (if method exposes many sigs) * integer timeout timeout (in secs) to be used when executing function/calling remote method * string protocol 'http' (default), 'http11' or 'https' * string new_function_name the name of php function to create. If unsepcified, lib will pick an appropriate name * string return_source if true return php code w. function definition instead fo function name * bool encode_php_objs let php objects be sent to server using the 'improved' xmlrpc notation, so server can deserialize them as php objects * bool decode_php_objs --- WARNING !!! possible security hazard. only use it with trusted servers --- * mixed return_on_fault a php value to be returned when the xmlrpc call fails/returns a fault response (by default the xmlrpcresp object is returned in this case). If a string is used, '%faultCode%' and '%faultString%' tokens will be substituted with actual error values * bool debug set it to 1 or 2 to see debug results of querying server for method synopsis * @return string the name of the generated php function (or false) - OR AN ARRAY... */ function wrap_xmlrpc_method($client, $methodname, $extra_options=0, $timeout=0, $protocol='', $newfuncname='') { // mind numbing: let caller use sane calling convention (as per javadoc, 3 params), // OR the 2.0 calling convention (no options) - we really love backward compat, don't we? if (!is_array($extra_options)) { $signum = $extra_options; $extra_options = array(); } else { $signum = isset($extra_options['signum']) ? (int)$extra_options['signum'] : 0; $timeout = isset($extra_options['timeout']) ? (int)$extra_options['timeout'] : 0; $protocol = isset($extra_options['protocol']) ? $extra_options['protocol'] : ''; $newfuncname = isset($extra_options['new_function_name']) ? $extra_options['new_function_name'] : ''; } //$encode_php_objects = in_array('encode_php_objects', $extra_options); //$verbatim_client_copy = in_array('simple_client_copy', $extra_options) ? 1 : // in_array('build_class_code', $extra_options) ? 2 : 0; $encode_php_objects = isset($extra_options['encode_php_objs']) ? (bool)$extra_options['encode_php_objs'] : false; $decode_php_objects = isset($extra_options['decode_php_objs']) ? (bool)$extra_options['decode_php_objs'] : false; $simple_client_copy = isset($extra_options['simple_client_copy']) ? (int)($extra_options['simple_client_copy']) : 0; $buildit = isset($extra_options['return_source']) ? !($extra_options['return_source']) : true; $prefix = isset($extra_options['prefix']) ? $extra_options['prefix'] : 'xmlrpc'; if (isset($extra_options['return_on_fault'])) { $decode_fault = true; $fault_response = $extra_options['return_on_fault']; } else { $decode_fault = false; $fault_response = ''; } $debug = isset($extra_options['debug']) ? ($extra_options['debug']) : 0; $msgclass = $prefix.'msg'; $valclass = $prefix.'val'; $decodefunc = 'php_'.$prefix.'_decode'; $msg = new $msgclass('system.methodSignature'); $msg->addparam(new $valclass($methodname)); $client->setDebug($debug); $response =& $client->send($msg, $timeout, $protocol); if($response->faultCode()) { error_log('XML-RPC: could not retrieve method signature from remote server for method '.$methodname); return false; } else { $msig = $response->value(); if ($client->return_type != 'phpvals') { $msig = $decodefunc($msig); } if(!is_array($msig) || count($msig) <= $signum) { error_log('XML-RPC: could not retrieve method signature nr.'.$signum.' from remote server for method '.$methodname); return false; } else { // pick a suitable name for the new function, avoiding collisions if($newfuncname != '') { $xmlrpcfuncname = $newfuncname; } else { // take care to insure that methodname is translated to valid // php function name $xmlrpcfuncname = $prefix.'_'.preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'), array('_', ''), $methodname); } while($buildit && function_exists($xmlrpcfuncname)) { $xmlrpcfuncname .= 'x'; } $msig = $msig[$signum]; $mdesc = ''; // if in 'offline' mode, get method description too. // in online mode, favour speed of operation if(!$buildit) { $msg = new $msgclass('system.methodHelp'); $msg->addparam(new $valclass($methodname)); $response =& $client->send($msg, $timeout, $protocol); if (!$response->faultCode()) { $mdesc = $response->value(); if ($client->return_type != 'phpvals') { $mdesc = $mdesc->scalarval(); } } } $results = build_remote_method_wrapper_code($client, $methodname, $xmlrpcfuncname, $msig, $mdesc, $timeout, $protocol, $simple_client_copy, $prefix, $decode_php_objects, $encode_php_objects, $decode_fault, $fault_response); //print_r($code); if ($buildit) { $allOK = 0; eval($results['source'].'$allOK=1;'); // alternative //$xmlrpcfuncname = create_function('$m', $innercode); if($allOK) { return $xmlrpcfuncname; } else { error_log('XML-RPC: could not create function '.$xmlrpcfuncname.' to wrap remote method '.$methodname); return false; } } else { $results['function'] = $xmlrpcfuncname; return $results; } } } } /** * Similar to wrap_xmlrpc_method, but will generate a php class that wraps * all xmlrpc methods exposed by the remote server as own methods. * For more details see wrap_xmlrpc_method. * @param xmlrpc_client $client the client obj all set to query the desired server * @param array $extra_options list of options for wrapped code * @return mixed false on error, the name of the created class if all ok or an array with code, class name and comments (if the appropriatevoption is set in extra_options) */ function wrap_xmlrpc_server($client, $extra_options=array()) { $methodfilter = isset($extra_options['method_filter']) ? $extra_options['method_filter'] : ''; //$signum = isset($extra_options['signum']) ? (int)$extra_options['signum'] : 0; $timeout = isset($extra_options['timeout']) ? (int)$extra_options['timeout'] : 0; $protocol = isset($extra_options['protocol']) ? $extra_options['protocol'] : ''; $newclassname = isset($extra_options['new_class_name']) ? $extra_options['new_class_name'] : ''; $encode_php_objects = isset($extra_options['encode_php_objs']) ? (bool)$extra_options['encode_php_objs'] : false; $decode_php_objects = isset($extra_options['decode_php_objs']) ? (bool)$extra_options['decode_php_objs'] : false; $verbatim_client_copy = isset($extra_options['simple_client_copy']) ? !($extra_options['simple_client_copy']) : true; $buildit = isset($extra_options['return_source']) ? !($extra_options['return_source']) : true; $prefix = isset($extra_options['prefix']) ? $extra_options['prefix'] : 'xmlrpc'; $msgclass = $prefix.'msg'; //$valclass = $prefix.'val'; $decodefunc = 'php_'.$prefix.'_decode'; $msg = new $msgclass('system.listMethods'); $response =& $client->send($msg, $timeout, $protocol); if($response->faultCode()) { error_log('XML-RPC: could not retrieve method list from remote server'); return false; } else { $mlist = $response->value(); if ($client->return_type != 'phpvals') { $mlist = $decodefunc($mlist); } if(!is_array($mlist) || !count($mlist)) { error_log('XML-RPC: could not retrieve meaningful method list from remote server'); return false; } else { // pick a suitable name for the new function, avoiding collisions if($newclassname != '') { $xmlrpcclassname = $newclassname; } else { $xmlrpcclassname = $prefix.'_'.preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'), array('_', ''), $client->server).'_client'; } while($buildit && class_exists($xmlrpcclassname)) { $xmlrpcclassname .= 'x'; } /// @todo add function setdebug() to new class, to enable/disable debugging $source = "class $xmlrpcclassname\n{\nvar \$client;\n\n"; $source .= "function $xmlrpcclassname()\n{\n"; $source .= build_client_wrapper_code($client, $verbatim_client_copy, $prefix); $source .= "\$this->client =& \$client;\n}\n\n"; $opts = array('simple_client_copy' => 2, 'return_source' => true, 'timeout' => $timeout, 'protocol' => $protocol, 'encode_php_objs' => $encode_php_objects, 'prefix' => $prefix, 'decode_php_objs' => $decode_php_objects ); /// @todo build javadoc for class definition, too foreach($mlist as $mname) { if ($methodfilter == '' || preg_match($methodfilter, $mname)) { $opts['new_function_name'] = preg_replace(array('/\./', '/[^a-zA-Z0-9_\x7f-\xff]/'), array('_', ''), $mname); $methodwrap = wrap_xmlrpc_method($client, $mname, $opts); if ($methodwrap) { if (!$buildit) { $source .= $methodwrap['docstring']; } $source .= $methodwrap['source']."\n"; } else { error_log('XML-RPC: will not create class method to wrap remote method '.$mname); } } } $source .= "}\n"; if ($buildit) { $allOK = 0; eval($source.'$allOK=1;'); // alternative //$xmlrpcfuncname = create_function('$m', $innercode); if($allOK) { return $xmlrpcclassname; } else { error_log('XML-RPC: could not create class '.$xmlrpcclassname.' to wrap remote server '.$client->server); return false; } } else { return array('class' => $xmlrpcclassname, 'code' => $source, 'docstring' => ''); } } } } /** * Given the necessary info, build php code that creates a new function to * invoke a remote xmlrpc method. * Take care that no full checking of input parameters is done to ensure that * valid php code is emitted. * Note: real spaghetti code follows... * @access private */ function build_remote_method_wrapper_code($client, $methodname, $xmlrpcfuncname, $msig, $mdesc='', $timeout=0, $protocol='', $client_copy_mode=0, $prefix='xmlrpc', $decode_php_objects=false, $encode_php_objects=false, $decode_fault=false, $fault_response='') { $code = "function $xmlrpcfuncname ("; if ($client_copy_mode < 2) { // client copy mode 0 or 1 == partial / full client copy in emitted code $innercode = build_client_wrapper_code($client, $client_copy_mode, $prefix); $innercode .= "\$client->setDebug(\$debug);\n"; $this_ = ''; } else { // client copy mode 2 == no client copy in emitted code $innercode = ''; $this_ = 'this->'; } $innercode .= "\$msg = new {$prefix}msg('$methodname');\n"; if ($mdesc != '') { // take care that PHP comment is not terminated unwillingly by method description $mdesc = "/**\n* ".str_replace('*/', '* /', $mdesc)."\n"; } else { $mdesc = "/**\nFunction $xmlrpcfuncname\n"; } // param parsing $plist = array(); $pcount = count($msig); for($i = 1; $i < $pcount; $i++) { $plist[] = "\$p$i"; $ptype = $msig[$i]; if($ptype == 'i4' || $ptype == 'int' || $ptype == 'boolean' || $ptype == 'double' || $ptype == 'string' || $ptype == 'dateTime.iso8601' || $ptype == 'base64' || $ptype == 'null') { // only build directly xmlrpcvals when type is known and scalar $innercode .= "\$p$i = new {$prefix}val(\$p$i, '$ptype');\n"; } else { if ($encode_php_objects) { $innercode .= "\$p$i =& php_{$prefix}_encode(\$p$i, array('encode_php_objs'));\n"; } else { $innercode .= "\$p$i =& php_{$prefix}_encode(\$p$i);\n"; } } $innercode .= "\$msg->addparam(\$p$i);\n"; $mdesc .= '* @param '.xmlrpc_2_php_type($ptype)." \$p$i\n"; } if ($client_copy_mode < 2) { $plist[] = '$debug=0'; $mdesc .= "* @param int \$debug when 1 (or 2) will enable debugging of the underlying {$prefix} call (defaults to 0)\n"; } $plist = implode(', ', $plist); $mdesc .= '* @return '.xmlrpc_2_php_type($msig[0])." (or an {$prefix}resp obj instance if call fails)\n*/\n"; $innercode .= "\$res =& \${$this_}client->send(\$msg, $timeout, '$protocol');\n"; if ($decode_fault) { if (is_string($fault_response) && ((strpos($fault_response, '%faultCode%') !== false) || (strpos($fault_response, '%faultString%') !== false))) { $respcode = "str_replace(array('%faultCode%', '%faultString%'), array(\$res->faultCode(), \$res->faultString()), '".str_replace("'", "''", $fault_response)."')"; } else { $respcode = var_export($fault_response, true); } } else { $respcode = '$res'; } if ($decode_php_objects) { $innercode .= "if (\$res->faultcode()) return $respcode; else return php_{$prefix}_decode(\$res->value(), array('decode_php_objs'));"; } else { $innercode .= "if (\$res->faultcode()) return $respcode; else return php_{$prefix}_decode(\$res->value());"; } $code = $code . $plist. ") {\n" . $innercode . "\n}\n"; return array('source' => $code, 'docstring' => $mdesc); } /** * Given necessary info, generate php code that will rebuild a client object * Take care that no full checking of input parameters is done to ensure that * valid php code is emitted. * @access private */ function build_client_wrapper_code($client, $verbatim_client_copy, $prefix='xmlrpc') { $code = "\$client = new {$prefix}_client('".str_replace("'", "\'", $client->path). "', '" . str_replace("'", "\'", $client->server) . "', $client->port);\n"; // copy all client fields to the client that will be generated runtime // (this provides for future expansion or subclassing of client obj) if ($verbatim_client_copy) { foreach($client as $fld => $val) { if($fld != 'debug' && $fld != 'return_type') { $val = var_export($val, true); $code .= "\$client->$fld = $val;\n"; } } } // only make sure that client always returns the correct data type $code .= "\$client->return_type = '{$prefix}vals';\n"; //$code .= "\$client->setDebug(\$debug);\n"; return $code; } ?>ltsp-cluster-control-2.0.3/Adminng/includes/xmlrpc/xmlrpc.inc0000664000175000017500000033750212026403127024540 0ustar stgraberstgraber // $Id: xmlrpc.inc,v 1.174 2009/03/16 19:36:38 ggiunta Exp $ // Copyright (c) 1999,2000,2002 Edd Dumbill. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // * Neither the name of the "XML-RPC for PHP" nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. if(!function_exists('xml_parser_create')) { // For PHP 4 onward, XML functionality is always compiled-in on windows: // no more need to dl-open it. It might have been compiled out on *nix... if(strtoupper(substr(PHP_OS, 0, 3) != 'WIN')) { dl('xml.so'); } } // G. Giunta 2005/01/29: declare global these variables, // so that xmlrpc.inc will work even if included from within a function // Milosch: 2005/08/07 - explicitly request these via $GLOBALS where used. $GLOBALS['xmlrpcI4']='i4'; $GLOBALS['xmlrpcInt']='int'; $GLOBALS['xmlrpcBoolean']='boolean'; $GLOBALS['xmlrpcDouble']='double'; $GLOBALS['xmlrpcString']='string'; $GLOBALS['xmlrpcDateTime']='dateTime.iso8601'; $GLOBALS['xmlrpcBase64']='base64'; $GLOBALS['xmlrpcArray']='array'; $GLOBALS['xmlrpcStruct']='struct'; $GLOBALS['xmlrpcValue']='undefined'; $GLOBALS['xmlrpcTypes']=array( $GLOBALS['xmlrpcI4'] => 1, $GLOBALS['xmlrpcInt'] => 1, $GLOBALS['xmlrpcBoolean'] => 1, $GLOBALS['xmlrpcString'] => 1, $GLOBALS['xmlrpcDouble'] => 1, $GLOBALS['xmlrpcDateTime'] => 1, $GLOBALS['xmlrpcBase64'] => 1, $GLOBALS['xmlrpcArray'] => 2, $GLOBALS['xmlrpcStruct'] => 3 ); $GLOBALS['xmlrpc_valid_parents'] = array( 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'), 'BOOLEAN' => array('VALUE'), 'I4' => array('VALUE'), 'INT' => array('VALUE'), 'STRING' => array('VALUE'), 'DOUBLE' => array('VALUE'), 'DATETIME.ISO8601' => array('VALUE'), 'BASE64' => array('VALUE'), 'MEMBER' => array('STRUCT'), 'NAME' => array('MEMBER'), 'DATA' => array('ARRAY'), 'ARRAY' => array('VALUE'), 'STRUCT' => array('VALUE'), 'PARAM' => array('PARAMS'), 'METHODNAME' => array('METHODCALL'), 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), 'FAULT' => array('METHODRESPONSE'), 'NIL' => array('VALUE'), // only used when extension activated 'EX:NIL' => array('VALUE') // only used when extension activated ); // define extra types for supporting NULL (useful for json or ) $GLOBALS['xmlrpcNull']='null'; $GLOBALS['xmlrpcTypes']['null']=1; // Not in use anymore since 2.0. Shall we remove it? /// @deprecated $GLOBALS['xmlEntities']=array( 'amp' => '&', 'quot' => '"', 'lt' => '<', 'gt' => '>', 'apos' => "'" ); // tables used for transcoding different charsets into us-ascii xml $GLOBALS['xml_iso88591_Entities']=array(); $GLOBALS['xml_iso88591_Entities']['in'] = array(); $GLOBALS['xml_iso88591_Entities']['out'] = array(); for ($i = 0; $i < 32; $i++) { $GLOBALS['xml_iso88591_Entities']['in'][] = chr($i); $GLOBALS['xml_iso88591_Entities']['out'][] = '&#'.$i.';'; } for ($i = 160; $i < 256; $i++) { $GLOBALS['xml_iso88591_Entities']['in'][] = chr($i); $GLOBALS['xml_iso88591_Entities']['out'][] = '&#'.$i.';'; } /// @todo add to iso table the characters from cp_1252 range, i.e. 128 to 159? /// These will NOT be present in true ISO-8859-1, but will save the unwary /// windows user from sending junk (though no luck when reciving them...) /* $GLOBALS['xml_cp1252_Entities']=array(); for ($i = 128; $i < 160; $i++) { $GLOBALS['xml_cp1252_Entities']['in'][] = chr($i); } $GLOBALS['xml_cp1252_Entities']['out'] = array( '€', '?', '‚', 'ƒ', '„', '…', '†', '‡', 'ˆ', '‰', 'Š', '‹', 'Œ', '?', 'Ž', '?', '?', '‘', '’', '“', '”', '•', '–', '—', '˜', '™', 'š', '›', 'œ', '?', 'ž', 'Ÿ' ); */ $GLOBALS['xmlrpcerr'] = array( 'unknown_method'=>1, 'invalid_return'=>2, 'incorrect_params'=>3, 'introspect_unknown'=>4, 'http_error'=>5, 'no_data'=>6, 'no_ssl'=>7, 'curl_fail'=>8, 'invalid_request'=>15, 'no_curl'=>16, 'server_error'=>17, 'multicall_error'=>18, 'multicall_notstruct'=>9, 'multicall_nomethod'=>10, 'multicall_notstring'=>11, 'multicall_recursion'=>12, 'multicall_noparams'=>13, 'multicall_notarray'=>14, 'cannot_decompress'=>103, 'decompress_fail'=>104, 'dechunk_fail'=>105, 'server_cannot_decompress'=>106, 'server_decompress_fail'=>107 ); $GLOBALS['xmlrpcstr'] = array( 'unknown_method'=>'Unknown method', 'invalid_return'=>'Invalid return payload: enable debugging to examine incoming payload', 'incorrect_params'=>'Incorrect parameters passed to method', 'introspect_unknown'=>"Can't introspect: method unknown", 'http_error'=>"Didn't receive 200 OK from remote server.", 'no_data'=>'No data received from server.', 'no_ssl'=>'No SSL support compiled in.', 'curl_fail'=>'CURL error', 'invalid_request'=>'Invalid request payload', 'no_curl'=>'No CURL support compiled in.', 'server_error'=>'Internal server error', 'multicall_error'=>'Received from server invalid multicall response', 'multicall_notstruct'=>'system.multicall expected struct', 'multicall_nomethod'=>'missing methodName', 'multicall_notstring'=>'methodName is not a string', 'multicall_recursion'=>'recursive system.multicall forbidden', 'multicall_noparams'=>'missing params', 'multicall_notarray'=>'params is not an array', 'cannot_decompress'=>'Received from server compressed HTTP and cannot decompress', 'decompress_fail'=>'Received from server invalid compressed HTTP', 'dechunk_fail'=>'Received from server invalid chunked HTTP', 'server_cannot_decompress'=>'Received from client compressed HTTP request and cannot decompress', 'server_decompress_fail'=>'Received from client invalid compressed HTTP request' ); // The charset encoding used by the server for received messages and // by the client for received responses when received charset cannot be determined // or is not supported $GLOBALS['xmlrpc_defencoding']='UTF-8'; // The encoding used internally by PHP. // String values received as xml will be converted to this, and php strings will be converted to xml // as if having been coded with this $GLOBALS['xmlrpc_internalencoding']='ISO-8859-1'; $GLOBALS['xmlrpcName']='XML-RPC for PHP'; $GLOBALS['xmlrpcVersion']='3.0.0.beta'; // let user errors start at 800 $GLOBALS['xmlrpcerruser']=800; // let XML parse errors start at 100 $GLOBALS['xmlrpcerrxml']=100; // formulate backslashes for escaping regexp // Not in use anymore since 2.0. Shall we remove it? /// @deprecated $GLOBALS['xmlrpc_backslash']=chr(92).chr(92); // set to TRUE to enable correct decoding of and values $GLOBALS['xmlrpc_null_extension']=false; // set to TRUE to enable encoding of php NULL values to instead of $GLOBALS['xmlrpc_null_apache_encoding']=false; // used to store state during parsing // quick explanation of components: // ac - used to accumulate values // isf - used to indicate a parsing fault (2) or xmlrpcresp fault (1) // isf_reason - used for storing xmlrpcresp fault string // lv - used to indicate "looking for a value": implements // the logic to allow values with no types to be strings // params - used to store parameters in method calls // method - used to store method name // stack - array with genealogy of xml elements names: // used to validate nesting of xmlrpc elements $GLOBALS['_xh']=null; /** * Convert a string to the correct XML representation in a target charset * To help correct communication of non-ascii chars inside strings, regardless * of the charset used when sending requests, parsing them, sending responses * and parsing responses, an option is to convert all non-ascii chars present in the message * into their equivalent 'charset entity'. Charset entities enumerated this way * are independent of the charset encoding used to transmit them, and all XML * parsers are bound to understand them. * Note that in the std case we are not sending a charset encoding mime type * along with http headers, so we are bound by RFC 3023 to emit strict us-ascii. * * @todo do a bit of basic benchmarking (strtr vs. str_replace) * @todo make usage of iconv() or recode_string() or mb_string() where available */ function xmlrpc_encode_entitites($data, $src_encoding='', $dest_encoding='') { if ($src_encoding == '') { // lame, but we know no better... $src_encoding = $GLOBALS['xmlrpc_internalencoding']; } switch(strtoupper($src_encoding.'_'.$dest_encoding)) { case 'ISO-8859-1_': case 'ISO-8859-1_US-ASCII': $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&', '"', ''', '<', '>'), $data); $escaped_data = str_replace($GLOBALS['xml_iso88591_Entities']['in'], $GLOBALS['xml_iso88591_Entities']['out'], $escaped_data); break; case 'ISO-8859-1_UTF-8': $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&', '"', ''', '<', '>'), $data); $escaped_data = utf8_encode($escaped_data); break; case 'ISO-8859-1_ISO-8859-1': case 'US-ASCII_US-ASCII': case 'US-ASCII_UTF-8': case 'US-ASCII_': case 'US-ASCII_ISO-8859-1': case 'UTF-8_UTF-8': //case 'CP1252_CP1252': $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&', '"', ''', '<', '>'), $data); break; case 'UTF-8_': case 'UTF-8_US-ASCII': case 'UTF-8_ISO-8859-1': // NB: this will choke on invalid UTF-8, going most likely beyond EOF $escaped_data = ''; // be kind to users creating string xmlrpcvals out of different php types $data = (string) $data; $ns = strlen ($data); for ($nn = 0; $nn < $ns; $nn++) { $ch = $data[$nn]; $ii = ord($ch); //1 7 0bbbbbbb (127) if ($ii < 128) { /// @todo shall we replace this with a (supposedly) faster str_replace? switch($ii){ case 34: $escaped_data .= '"'; break; case 38: $escaped_data .= '&'; break; case 39: $escaped_data .= '''; break; case 60: $escaped_data .= '<'; break; case 62: $escaped_data .= '>'; break; default: $escaped_data .= $ch; } // switch } //2 11 110bbbbb 10bbbbbb (2047) else if ($ii>>5 == 6) { $b1 = ($ii & 31); $ii = ord($data[$nn+1]); $b2 = ($ii & 63); $ii = ($b1 * 64) + $b2; $ent = sprintf ('&#%d;', $ii); $escaped_data .= $ent; $nn += 1; } //3 16 1110bbbb 10bbbbbb 10bbbbbb else if ($ii>>4 == 14) { $b1 = ($ii & 15); $ii = ord($data[$nn+1]); $b2 = ($ii & 63); $ii = ord($data[$nn+2]); $b3 = ($ii & 63); $ii = ((($b1 * 64) + $b2) * 64) + $b3; $ent = sprintf ('&#%d;', $ii); $escaped_data .= $ent; $nn += 2; } //4 21 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb else if ($ii>>3 == 30) { $b1 = ($ii & 7); $ii = ord($data[$nn+1]); $b2 = ($ii & 63); $ii = ord($data[$nn+2]); $b3 = ($ii & 63); $ii = ord($data[$nn+3]); $b4 = ($ii & 63); $ii = ((((($b1 * 64) + $b2) * 64) + $b3) * 64) + $b4; $ent = sprintf ('&#%d;', $ii); $escaped_data .= $ent; $nn += 3; } } break; /* case 'CP1252_': case 'CP1252_US-ASCII': $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&', '"', ''', '<', '>'), $data); $escaped_data = str_replace($GLOBALS['xml_iso88591_Entities']['in'], $GLOBALS['xml_iso88591_Entities']['out'], $escaped_data); $escaped_data = str_replace($GLOBALS['xml_cp1252_Entities']['in'], $GLOBALS['xml_cp1252_Entities']['out'], $escaped_data); break; case 'CP1252_UTF-8': $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&', '"', ''', '<', '>'), $data); /// @todo we could use real UTF8 chars here instead of xml entities... (note that utf_8 encode all allone will NOT convert them) $escaped_data = str_replace($GLOBALS['xml_cp1252_Entities']['in'], $GLOBALS['xml_cp1252_Entities']['out'], $escaped_data); $escaped_data = utf8_encode($escaped_data); break; case 'CP1252_ISO-8859-1': $escaped_data = str_replace(array('&', '"', "'", '<', '>'), array('&', '"', ''', '<', '>'), $data); // we might as well replave all funky chars with a '?' here, but we are kind and leave it to the receiving application layer to decide what to do with these weird entities... $escaped_data = str_replace($GLOBALS['xml_cp1252_Entities']['in'], $GLOBALS['xml_cp1252_Entities']['out'], $escaped_data); break; */ default: $escaped_data = ''; error_log("Converting from $src_encoding to $dest_encoding: not supported..."); } return $escaped_data; } /// xml parser handler function for opening element tags function xmlrpc_se($parser, $name, $attrs, $accept_single_vals=false) { // if invalid xmlrpc already detected, skip all processing if ($GLOBALS['_xh']['isf'] < 2) { // check for correct element nesting // top level element can only be of 2 types /// @todo optimization creep: save this check into a bool variable, instead of using count() every time: /// there is only a single top level element in xml anyway if (count($GLOBALS['_xh']['stack']) == 0) { if ($name != 'METHODRESPONSE' && $name != 'METHODCALL' && ( $name != 'VALUE' && !$accept_single_vals)) { $GLOBALS['_xh']['isf'] = 2; $GLOBALS['_xh']['isf_reason'] = 'missing top level xmlrpc element'; return; } else { $GLOBALS['_xh']['rt'] = strtolower($name); $GLOBALS['_xh']['rt'] = strtolower($name); } } else { // not top level element: see if parent is OK $parent = end($GLOBALS['_xh']['stack']); if (!array_key_exists($name, $GLOBALS['xmlrpc_valid_parents']) || !in_array($parent, $GLOBALS['xmlrpc_valid_parents'][$name])) { $GLOBALS['_xh']['isf'] = 2; $GLOBALS['_xh']['isf_reason'] = "xmlrpc element $name cannot be child of $parent"; return; } } switch($name) { // optimize for speed switch cases: most common cases first case 'VALUE': /// @todo we could check for 2 VALUE elements inside a MEMBER or PARAM element $GLOBALS['_xh']['vt']='value'; // indicator: no value found yet $GLOBALS['_xh']['ac']=''; $GLOBALS['_xh']['lv']=1; $GLOBALS['_xh']['php_class']=null; break; case 'I4': case 'INT': case 'STRING': case 'BOOLEAN': case 'DOUBLE': case 'DATETIME.ISO8601': case 'BASE64': if ($GLOBALS['_xh']['vt']!='value') { //two data elements inside a value: an error occurred! $GLOBALS['_xh']['isf'] = 2; $GLOBALS['_xh']['isf_reason'] = "$name element following a {$GLOBALS['_xh']['vt']} element inside a single value"; return; } $GLOBALS['_xh']['ac']=''; // reset the accumulator break; case 'STRUCT': case 'ARRAY': if ($GLOBALS['_xh']['vt']!='value') { //two data elements inside a value: an error occurred! $GLOBALS['_xh']['isf'] = 2; $GLOBALS['_xh']['isf_reason'] = "$name element following a {$GLOBALS['_xh']['vt']} element inside a single value"; return; } // create an empty array to hold child values, and push it onto appropriate stack $cur_val = array(); $cur_val['values'] = array(); $cur_val['type'] = $name; // check for out-of-band information to rebuild php objs // and in case it is found, save it if (@isset($attrs['PHP_CLASS'])) { $cur_val['php_class'] = $attrs['PHP_CLASS']; } $GLOBALS['_xh']['valuestack'][] = $cur_val; $GLOBALS['_xh']['vt']='data'; // be prepared for a data element next break; case 'DATA': if ($GLOBALS['_xh']['vt']!='data') { //two data elements inside a value: an error occurred! $GLOBALS['_xh']['isf'] = 2; $GLOBALS['_xh']['isf_reason'] = "found two data elements inside an array element"; return; } case 'METHODCALL': case 'METHODRESPONSE': case 'PARAMS': // valid elements that add little to processing break; case 'METHODNAME': case 'NAME': /// @todo we could check for 2 NAME elements inside a MEMBER element $GLOBALS['_xh']['ac']=''; break; case 'FAULT': $GLOBALS['_xh']['isf']=1; break; case 'MEMBER': $GLOBALS['_xh']['valuestack'][count($GLOBALS['_xh']['valuestack'])-1]['name']=''; // set member name to null, in case we do not find in the xml later on //$GLOBALS['_xh']['ac']=''; // Drop trough intentionally case 'PARAM': // clear value type, so we can check later if no value has been passed for this param/member $GLOBALS['_xh']['vt']=null; break; case 'NIL': case 'EX:NIL': if ($GLOBALS['xmlrpc_null_extension']) { if ($GLOBALS['_xh']['vt']!='value') { //two data elements inside a value: an error occurred! $GLOBALS['_xh']['isf'] = 2; $GLOBALS['_xh']['isf_reason'] = "$name element following a {$GLOBALS['_xh']['vt']} element inside a single value"; return; } $GLOBALS['_xh']['ac']=''; // reset the accumulator break; } // we do not support the extension, so // drop through intentionally default: /// INVALID ELEMENT: RAISE ISF so that it is later recognized!!! $GLOBALS['_xh']['isf'] = 2; $GLOBALS['_xh']['isf_reason'] = "found not-xmlrpc xml element $name"; break; } // Save current element name to stack, to validate nesting $GLOBALS['_xh']['stack'][] = $name; /// @todo optimization creep: move this inside the big switch() above if($name!='VALUE') { $GLOBALS['_xh']['lv']=0; } } } /// Used in decoding xml chunks that might represent single xmlrpc values function xmlrpc_se_any($parser, $name, $attrs) { xmlrpc_se($parser, $name, $attrs, true); } /// xml parser handler function for close element tags function xmlrpc_ee($parser, $name, $rebuild_xmlrpcvals = true) { if ($GLOBALS['_xh']['isf'] < 2) { // push this element name from stack // NB: if XML validates, correct opening/closing is guaranteed and // we do not have to check for $name == $curr_elem. // we also checked for proper nesting at start of elements... $curr_elem = array_pop($GLOBALS['_xh']['stack']); switch($name) { case 'VALUE': // This if() detects if no scalar was inside if ($GLOBALS['_xh']['vt']=='value') { $GLOBALS['_xh']['value']=$GLOBALS['_xh']['ac']; $GLOBALS['_xh']['vt']=$GLOBALS['xmlrpcString']; } if ($rebuild_xmlrpcvals) { // build the xmlrpc val out of the data received, and substitute it $temp = new xmlrpcval($GLOBALS['_xh']['value'], $GLOBALS['_xh']['vt']); // in case we got info about underlying php class, save it // in the object we're rebuilding if (isset($GLOBALS['_xh']['php_class'])) $temp->_php_class = $GLOBALS['_xh']['php_class']; // check if we are inside an array or struct: // if value just built is inside an array, let's move it into array on the stack $vscount = count($GLOBALS['_xh']['valuestack']); if ($vscount && $GLOBALS['_xh']['valuestack'][$vscount-1]['type']=='ARRAY') { $GLOBALS['_xh']['valuestack'][$vscount-1]['values'][] = $temp; } else { $GLOBALS['_xh']['value'] = $temp; } } else { /// @todo this needs to treat correctly php-serialized objects, /// since std deserializing is done by php_xmlrpc_decode, /// which we will not be calling... if (isset($GLOBALS['_xh']['php_class'])) { } // check if we are inside an array or struct: // if value just built is inside an array, let's move it into array on the stack $vscount = count($GLOBALS['_xh']['valuestack']); if ($vscount && $GLOBALS['_xh']['valuestack'][$vscount-1]['type']=='ARRAY') { $GLOBALS['_xh']['valuestack'][$vscount-1]['values'][] = $GLOBALS['_xh']['value']; } } break; case 'BOOLEAN': case 'I4': case 'INT': case 'STRING': case 'DOUBLE': case 'DATETIME.ISO8601': case 'BASE64': $GLOBALS['_xh']['vt']=strtolower($name); /// @todo: optimization creep - remove the if/elseif cycle below /// since the case() in which we are already did that if ($name=='STRING') { $GLOBALS['_xh']['value']=$GLOBALS['_xh']['ac']; } elseif ($name=='DATETIME.ISO8601') { if (!preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $GLOBALS['_xh']['ac'])) { error_log('XML-RPC: invalid value received in DATETIME: '.$GLOBALS['_xh']['ac']); } $GLOBALS['_xh']['vt']=$GLOBALS['xmlrpcDateTime']; $GLOBALS['_xh']['value']=$GLOBALS['_xh']['ac']; } elseif ($name=='BASE64') { /// @todo check for failure of base64 decoding / catch warnings $GLOBALS['_xh']['value']=base64_decode($GLOBALS['_xh']['ac']); } elseif ($name=='BOOLEAN') { // special case here: we translate boolean 1 or 0 into PHP // constants true or false. // Strings 'true' and 'false' are accepted, even though the // spec never mentions them (see eg. Blogger api docs) // NB: this simple checks helps a lot sanitizing input, ie no // security problems around here if ($GLOBALS['_xh']['ac']=='1' || strcasecmp($GLOBALS['_xh']['ac'], 'true') == 0) { $GLOBALS['_xh']['value']=true; } else { // log if receiveing something strange, even though we set the value to false anyway if ($GLOBALS['_xh']['ac']!='0' && strcasecmp($GLOBALS['_xh']['ac'], 'false') != 0) error_log('XML-RPC: invalid value received in BOOLEAN: '.$GLOBALS['_xh']['ac']); $GLOBALS['_xh']['value']=false; } } elseif ($name=='DOUBLE') { // we have a DOUBLE // we must check that only 0123456789-. are characters here // NOTE: regexp could be much stricter than this... if (!preg_match('/^[+-eE0123456789 \t.]+$/', $GLOBALS['_xh']['ac'])) { /// @todo: find a better way of throwing an error than this! error_log('XML-RPC: non numeric value received in DOUBLE: '.$GLOBALS['_xh']['ac']); $GLOBALS['_xh']['value']='ERROR_NON_NUMERIC_FOUND'; } else { // it's ok, add it on $GLOBALS['_xh']['value']=(double)$GLOBALS['_xh']['ac']; } } else { // we have an I4/INT // we must check that only 0123456789- are characters here if (!preg_match('/^[+-]?[0123456789 \t]+$/', $GLOBALS['_xh']['ac'])) { /// @todo find a better way of throwing an error than this! error_log('XML-RPC: non numeric value received in INT: '.$GLOBALS['_xh']['ac']); $GLOBALS['_xh']['value']='ERROR_NON_NUMERIC_FOUND'; } else { // it's ok, add it on $GLOBALS['_xh']['value']=(int)$GLOBALS['_xh']['ac']; } } //$GLOBALS['_xh']['ac']=''; // is this necessary? $GLOBALS['_xh']['lv']=3; // indicate we've found a value break; case 'NAME': $GLOBALS['_xh']['valuestack'][count($GLOBALS['_xh']['valuestack'])-1]['name'] = $GLOBALS['_xh']['ac']; break; case 'MEMBER': //$GLOBALS['_xh']['ac']=''; // is this necessary? // add to array in the stack the last element built, // unless no VALUE was found if ($GLOBALS['_xh']['vt']) { $vscount = count($GLOBALS['_xh']['valuestack']); $GLOBALS['_xh']['valuestack'][$vscount-1]['values'][$GLOBALS['_xh']['valuestack'][$vscount-1]['name']] = $GLOBALS['_xh']['value']; } else error_log('XML-RPC: missing VALUE inside STRUCT in received xml'); break; case 'DATA': //$GLOBALS['_xh']['ac']=''; // is this necessary? $GLOBALS['_xh']['vt']=null; // reset this to check for 2 data elements in a row - even if they're empty break; case 'STRUCT': case 'ARRAY': // fetch out of stack array of values, and promote it to current value $curr_val = array_pop($GLOBALS['_xh']['valuestack']); $GLOBALS['_xh']['value'] = $curr_val['values']; $GLOBALS['_xh']['vt']=strtolower($name); if (isset($curr_val['php_class'])) { $GLOBALS['_xh']['php_class'] = $curr_val['php_class']; } break; case 'PARAM': // add to array of params the current value, // unless no VALUE was found if ($GLOBALS['_xh']['vt']) { $GLOBALS['_xh']['params'][]=$GLOBALS['_xh']['value']; $GLOBALS['_xh']['pt'][]=$GLOBALS['_xh']['vt']; } else error_log('XML-RPC: missing VALUE inside PARAM in received xml'); break; case 'METHODNAME': $GLOBALS['_xh']['method']=preg_replace('/^[\n\r\t ]+/', '', $GLOBALS['_xh']['ac']); break; case 'NIL': case 'EX:NIL': if ($GLOBALS['xmlrpc_null_extension']) { $GLOBALS['_xh']['vt']='null'; $GLOBALS['_xh']['value']=null; $GLOBALS['_xh']['lv']=3; break; } // drop through intentionally if nil extension not enabled case 'PARAMS': case 'FAULT': case 'METHODCALL': case 'METHORESPONSE': break; default: // End of INVALID ELEMENT! // shall we add an assert here for unreachable code??? break; } } } /// Used in decoding xmlrpc requests/responses without rebuilding xmlrpc values function xmlrpc_ee_fast($parser, $name) { xmlrpc_ee($parser, $name, false); } /// xml parser handler function for character data function xmlrpc_cd($parser, $data) { // skip processing if xml fault already detected if ($GLOBALS['_xh']['isf'] < 2) { // "lookforvalue==3" means that we've found an entire value // and should discard any further character data if($GLOBALS['_xh']['lv']!=3) { // G. Giunta 2006-08-23: useless change of 'lv' from 1 to 2 //if($GLOBALS['_xh']['lv']==1) //{ // if we've found text and we're just in a then // say we've found a value //$GLOBALS['_xh']['lv']=2; //} // we always initialize the accumulator before starting parsing, anyway... //if(!@isset($GLOBALS['_xh']['ac'])) //{ // $GLOBALS['_xh']['ac'] = ''; //} $GLOBALS['_xh']['ac'].=$data; } } } /// xml parser handler function for 'other stuff', ie. not char data or /// element start/end tag. In fact it only gets called on unknown entities... function xmlrpc_dh($parser, $data) { // skip processing if xml fault already detected if ($GLOBALS['_xh']['isf'] < 2) { if(substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';') { // G. Giunta 2006-08-25: useless change of 'lv' from 1 to 2 //if($GLOBALS['_xh']['lv']==1) //{ // $GLOBALS['_xh']['lv']=2; //} $GLOBALS['_xh']['ac'].=$data; } } return true; } class xmlrpc_client { var $path; var $server; var $port=0; var $method='http'; var $errno; var $errstr; var $debug=0; var $username=''; var $password=''; var $authtype=1; var $cert=''; var $certpass=''; var $cacert=''; var $cacertdir=''; var $key=''; var $keypass=''; var $verifypeer=true; var $verifyhost=1; var $no_multicall=false; var $proxy=''; var $proxyport=0; var $proxy_user=''; var $proxy_pass=''; var $proxy_authtype=1; var $cookies=array(); var $extracurlopts=array(); /** * List of http compression methods accepted by the client for responses. * NB: PHP supports deflate, gzip compressions out of the box if compiled w. zlib * * NNB: you can set it to any non-empty array for HTTP11 and HTTPS, since * in those cases it will be up to CURL to decide the compression methods * it supports. You might check for the presence of 'zlib' in the output of * curl_version() to determine wheter compression is supported or not */ var $accepted_compression = array(); /** * Name of compression scheme to be used for sending requests. * Either null, gzip or deflate */ var $request_compression = ''; /** * CURL handle: used for keep-alive connections (PHP 4.3.8 up, see: * http://curl.haxx.se/docs/faq.html#7.3) */ var $xmlrpc_curl_handle = null; /// Wheter to use persistent connections for http 1.1 and https var $keepalive = false; /// Charset encodings that can be decoded without problems by the client var $accepted_charset_encodings = array(); /// Charset encoding to be used in serializing request. NULL = use ASCII var $request_charset_encoding = ''; /** * Decides the content of xmlrpcresp objects returned by calls to send() * valid strings are 'xmlrpcvals', 'phpvals' or 'xml' */ var $return_type = 'xmlrpcvals'; /** * Sent to servers in http headers */ var $user_agent; /** * @param string $path either the complete server URL or the PATH part of the xmlrc server URL, e.g. /xmlrpc/server.php * @param string $server the server name / ip address * @param integer $port the port the server is listening on, defaults to 80 or 443 depending on protocol used * @param string $method the http protocol variant: defaults to 'http', 'https' and 'http11' can be used if CURL is installed */ function xmlrpc_client($path, $server='', $port='', $method='') { // allow user to specify all params in $path if($server == '' and $port == '' and $method == '') { $parts = parse_url($path); $server = $parts['host']; $path = isset($parts['path']) ? $parts['path'] : ''; if(isset($parts['query'])) { $path .= '?'.$parts['query']; } if(isset($parts['fragment'])) { $path .= '#'.$parts['fragment']; } if(isset($parts['port'])) { $port = $parts['port']; } if(isset($parts['scheme'])) { $method = $parts['scheme']; } if(isset($parts['user'])) { $this->username = $parts['user']; } if(isset($parts['pass'])) { $this->password = $parts['pass']; } } if($path == '' || $path[0] != '/') { $this->path='/'.$path; } else { $this->path=$path; } $this->server=$server; if($port != '') { $this->port=$port; } if($method != '') { $this->method=$method; } // if ZLIB is enabled, let the client by default accept compressed responses if(function_exists('gzinflate') || ( function_exists('curl_init') && (($info = curl_version()) && ((is_string($info) && strpos($info, 'zlib') !== null) || isset($info['libz_version']))) )) { $this->accepted_compression = array('gzip', 'deflate'); } // keepalives: enabled by default $this->keepalive = true; // by default the xml parser can support these 3 charset encodings $this->accepted_charset_encodings = array('UTF-8', 'ISO-8859-1', 'US-ASCII'); // initialize user_agent string $this->user_agent = $GLOBALS['xmlrpcName'] . ' ' . $GLOBALS['xmlrpcVersion']; } /** * Enables/disables the echoing to screen of the xmlrpc responses received * @param integer $debug values 0, 1 and 2 are supported (2 = echo sent msg too, before received response) * @access public */ function setDebug($in) { $this->debug=$in; } /** * Add some http BASIC AUTH credentials, used by the client to authenticate * @param string $u username * @param string $p password * @param integer $t auth type. See curl_setopt man page for supported auth types. Defaults to CURLAUTH_BASIC (basic auth) * @access public */ function setCredentials($u, $p, $t=1) { $this->username=$u; $this->password=$p; $this->authtype=$t; } /** * Add a client-side https certificate * @param string $cert * @param string $certpass * @access public */ function setCertificate($cert, $certpass) { $this->cert = $cert; $this->certpass = $certpass; } /** * Add a CA certificate to verify server with (see man page about * CURLOPT_CAINFO for more details * @param string $cacert certificate file name (or dir holding certificates) * @param bool $is_dir set to true to indicate cacert is a dir. defaults to false * @access public */ function setCaCertificate($cacert, $is_dir=false) { if ($is_dir) { $this->cacertdir = $cacert; } else { $this->cacert = $cacert; } } /** * Set attributes for SSL communication: private SSL key * NB: does not work in older php/curl installs * Thanks to Daniel Convissor * @param string $key The name of a file containing a private SSL key * @param string $keypass The secret password needed to use the private SSL key * @access public */ function setKey($key, $keypass) { $this->key = $key; $this->keypass = $keypass; } /** * Set attributes for SSL communication: verify server certificate * @param bool $i enable/disable verification of peer certificate * @access public */ function setSSLVerifyPeer($i) { $this->verifypeer = $i; } /** * Set attributes for SSL communication: verify match of server cert w. hostname * @param int $i * @access public */ function setSSLVerifyHost($i) { $this->verifyhost = $i; } /** * Set proxy info * @param string $proxyhost * @param string $proxyport Defaults to 8080 for HTTP and 443 for HTTPS * @param string $proxyusername Leave blank if proxy has public access * @param string $proxypassword Leave blank if proxy has public access * @param int $proxyauthtype set to constant CURLAUTH_NTLM to use NTLM auth with proxy * @access public */ function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 1) { $this->proxy = $proxyhost; $this->proxyport = $proxyport; $this->proxy_user = $proxyusername; $this->proxy_pass = $proxypassword; $this->proxy_authtype = $proxyauthtype; } /** * Enables/disables reception of compressed xmlrpc responses. * Note that enabling reception of compressed responses merely adds some standard * http headers to xmlrpc requests. It is up to the xmlrpc server to return * compressed responses when receiving such requests. * @param string $compmethod either 'gzip', 'deflate', 'any' or '' * @access public */ function setAcceptedCompression($compmethod) { if ($compmethod == 'any') $this->accepted_compression = array('gzip', 'deflate'); else $this->accepted_compression = array($compmethod); } /** * Enables/disables http compression of xmlrpc request. * Take care when sending compressed requests: servers might not support them * (and automatic fallback to uncompressed requests is not yet implemented) * @param string $compmethod either 'gzip', 'deflate' or '' * @access public */ function setRequestCompression($compmethod) { $this->request_compression = $compmethod; } /** * Adds a cookie to list of cookies that will be sent to server. * NB: setting any param but name and value will turn the cookie into a 'version 1' cookie: * do not do it unless you know what you are doing * @param string $name * @param string $value * @param string $path * @param string $domain * @param int $port * @access public * * @todo check correctness of urlencoding cookie value (copied from php way of doing it...) */ function setCookie($name, $value='', $path='', $domain='', $port=null) { $this->cookies[$name]['value'] = urlencode($value); if ($path || $domain || $port) { $this->cookies[$name]['path'] = $path; $this->cookies[$name]['domain'] = $domain; $this->cookies[$name]['port'] = $port; $this->cookies[$name]['version'] = 1; } else { $this->cookies[$name]['version'] = 0; } } /** * Directly set cURL options, for extra flexibility * It allows eg. to bind client to a specific IP interface / address * @param $options array */ function SetCurlOptions( $options ) { $this->extracurlopts = $options; } /** * Set user-agent string that will be used by this client instance * in http headers sent to the server */ function SetUserAgent( $agentstring ) { $this->user_agent = $agentstring; } /** * Send an xmlrpc request * @param mixed $msg The message object, or an array of messages for using multicall, or the complete xml representation of a request * @param integer $timeout Connection timeout, in seconds, If unspecified, a platform specific timeout will apply * @param string $method if left unspecified, the http protocol chosen during creation of the object will be used * @return xmlrpcresp * @access public */ function& send($msg, $timeout=0, $method='') { // if user deos not specify http protocol, use native method of this client // (i.e. method set during call to constructor) if($method == '') { $method = $this->method; } if(is_array($msg)) { // $msg is an array of xmlrpcmsg's $r = $this->multicall($msg, $timeout, $method); return $r; } elseif(is_string($msg)) { $n = new xmlrpcmsg(''); $n->payload = $msg; $msg = $n; } // where msg is an xmlrpcmsg $msg->debug=$this->debug; if($method == 'https') { $r =& $this->sendPayloadHTTPS( $msg, $this->server, $this->port, $timeout, $this->username, $this->password, $this->authtype, $this->cert, $this->certpass, $this->cacert, $this->cacertdir, $this->proxy, $this->proxyport, $this->proxy_user, $this->proxy_pass, $this->proxy_authtype, $this->keepalive, $this->key, $this->keypass ); } elseif($method == 'http11') { $r =& $this->sendPayloadCURL( $msg, $this->server, $this->port, $timeout, $this->username, $this->password, $this->authtype, null, null, null, null, $this->proxy, $this->proxyport, $this->proxy_user, $this->proxy_pass, $this->proxy_authtype, 'http', $this->keepalive ); } else { $r =& $this->sendPayloadHTTP10( $msg, $this->server, $this->port, $timeout, $this->username, $this->password, $this->authtype, $this->proxy, $this->proxyport, $this->proxy_user, $this->proxy_pass, $this->proxy_authtype ); } return $r; } /** * @access private */ function &sendPayloadHTTP10($msg, $server, $port, $timeout=0, $username='', $password='', $authtype=1, $proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1) { if($port==0) { $port=80; } // Only create the payload if it was not created previously if(empty($msg->payload)) { $msg->createPayload($this->request_charset_encoding); } $payload = $msg->payload; // Deflate request body and set appropriate request headers if(function_exists('gzdeflate') && ($this->request_compression == 'gzip' || $this->request_compression == 'deflate')) { if($this->request_compression == 'gzip') { $a = @gzencode($payload); if($a) { $payload = $a; $encoding_hdr = "Content-Encoding: gzip\r\n"; } } else { $a = @gzcompress($payload); if($a) { $payload = $a; $encoding_hdr = "Content-Encoding: deflate\r\n"; } } } else { $encoding_hdr = ''; } // thanks to Grant Rauscher for this $credentials=''; if($username!='') { $credentials='Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n"; if ($authtype != 1) { error_log('XML-RPC: '.__METHOD__.': warning. Only Basic auth is supported with HTTP 1.0'); } } $accepted_encoding = ''; if(is_array($this->accepted_compression) && count($this->accepted_compression)) { $accepted_encoding = 'Accept-Encoding: ' . implode(', ', $this->accepted_compression) . "\r\n"; } $proxy_credentials = ''; if($proxyhost) { if($proxyport == 0) { $proxyport = 8080; } $connectserver = $proxyhost; $connectport = $proxyport; $uri = 'http://'.$server.':'.$port.$this->path; if($proxyusername != '') { if ($proxyauthtype != 1) { error_log('XML-RPC: '.__METHOD__.': warning. Only Basic auth to proxy is supported with HTTP 1.0'); } $proxy_credentials = 'Proxy-Authorization: Basic ' . base64_encode($proxyusername.':'.$proxypassword) . "\r\n"; } } else { $connectserver = $server; $connectport = $port; $uri = $this->path; } // Cookie generation, as per rfc2965 (version 1 cookies) or // netscape's rules (version 0 cookies) $cookieheader=''; if (count($this->cookies)) { $version = ''; foreach ($this->cookies as $name => $cookie) { if ($cookie['version']) { $version = ' $Version="' . $cookie['version'] . '";'; $cookieheader .= ' ' . $name . '="' . $cookie['value'] . '";'; if ($cookie['path']) $cookieheader .= ' $Path="' . $cookie['path'] . '";'; if ($cookie['domain']) $cookieheader .= ' $Domain="' . $cookie['domain'] . '";'; if ($cookie['port']) $cookieheader .= ' $Port="' . $cookie['port'] . '";'; } else { $cookieheader .= ' ' . $name . '=' . $cookie['value'] . ";"; } } $cookieheader = 'Cookie:' . $version . substr($cookieheader, 0, -1) . "\r\n"; } $op= 'POST ' . $uri. " HTTP/1.0\r\n" . 'User-Agent: ' . $this->user_agent . "\r\n" . 'Host: '. $server . ':' . $port . "\r\n" . $credentials . $proxy_credentials . $accepted_encoding . $encoding_hdr . 'Accept-Charset: ' . implode(',', $this->accepted_charset_encodings) . "\r\n" . $cookieheader . 'Content-Type: ' . $msg->content_type . "\r\nContent-Length: " . strlen($payload) . "\r\n\r\n" . $payload; if($this->debug > 1) { print "
\n---SENDING---\n" . htmlentities($op) . "\n---END---\n
"; // let the client see this now in case http times out... flush(); } if($timeout>0) { $fp=@fsockopen($connectserver, $connectport, $this->errno, $this->errstr, $timeout); } else { $fp=@fsockopen($connectserver, $connectport, $this->errno, $this->errstr); } if($fp) { if($timeout>0 && function_exists('stream_set_timeout')) { stream_set_timeout($fp, $timeout); } } else { $this->errstr='Connect error: '.$this->errstr; $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr . ' (' . $this->errno . ')'); return $r; } if(!fputs($fp, $op, strlen($op))) { fclose($fp); $this->errstr='Write error'; $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $this->errstr); return $r; } else { // reset errno and errstr on succesful socket connection $this->errstr = ''; } // G. Giunta 2005/10/24: close socket before parsing. // should yeld slightly better execution times, and make easier recursive calls (e.g. to follow http redirects) $ipd=''; do { // shall we check for $data === FALSE? // as per the manual, it signals an error $ipd.=fread($fp, 32768); } while(!feof($fp)); fclose($fp); $r =& $msg->parseResponse($ipd, false, $this->return_type); return $r; } /** * @access private */ function &sendPayloadHTTPS($msg, $server, $port, $timeout=0, $username='', $password='', $authtype=1, $cert='',$certpass='', $cacert='', $cacertdir='', $proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1, $keepalive=false, $key='', $keypass='') { $r =& $this->sendPayloadCURL($msg, $server, $port, $timeout, $username, $password, $authtype, $cert, $certpass, $cacert, $cacertdir, $proxyhost, $proxyport, $proxyusername, $proxypassword, $proxyauthtype, 'https', $keepalive, $key, $keypass); return $r; } /** * Contributed by Justin Miller * Requires curl to be built into PHP * NB: CURL versions before 7.11.10 cannot use proxy to talk to https servers! * @access private */ function &sendPayloadCURL($msg, $server, $port, $timeout=0, $username='', $password='', $authtype=1, $cert='', $certpass='', $cacert='', $cacertdir='', $proxyhost='', $proxyport=0, $proxyusername='', $proxypassword='', $proxyauthtype=1, $method='https', $keepalive=false, $key='', $keypass='') { if(!function_exists('curl_init')) { $this->errstr='CURL unavailable on this install'; $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_curl'], $GLOBALS['xmlrpcstr']['no_curl']); return $r; } if($method == 'https') { if(($info = curl_version()) && ((is_string($info) && strpos($info, 'OpenSSL') === null) || (is_array($info) && !isset($info['ssl_version'])))) { $this->errstr='SSL unavailable on this install'; $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_ssl'], $GLOBALS['xmlrpcstr']['no_ssl']); return $r; } } if($port == 0) { if($method == 'http') { $port = 80; } else { $port = 443; } } // Only create the payload if it was not created previously if(empty($msg->payload)) { $msg->createPayload($this->request_charset_encoding); } // Deflate request body and set appropriate request headers $payload = $msg->payload; if(function_exists('gzdeflate') && ($this->request_compression == 'gzip' || $this->request_compression == 'deflate')) { if($this->request_compression == 'gzip') { $a = @gzencode($payload); if($a) { $payload = $a; $encoding_hdr = 'Content-Encoding: gzip'; } } else { $a = @gzcompress($payload); if($a) { $payload = $a; $encoding_hdr = 'Content-Encoding: deflate'; } } } else { $encoding_hdr = ''; } if($this->debug > 1) { print "
\n---SENDING---\n" . htmlentities($payload) . "\n---END---\n
"; // let the client see this now in case http times out... flush(); } if(!$keepalive || !$this->xmlrpc_curl_handle) { $curl = curl_init($method . '://' . $server . ':' . $port . $this->path); if($keepalive) { $this->xmlrpc_curl_handle = $curl; } } else { $curl = $this->xmlrpc_curl_handle; } // results into variable curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); if($this->debug) { curl_setopt($curl, CURLOPT_VERBOSE, 1); } curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); // required for XMLRPC: post the data curl_setopt($curl, CURLOPT_POST, 1); // the data curl_setopt($curl, CURLOPT_POSTFIELDS, $payload); // return the header too curl_setopt($curl, CURLOPT_HEADER, 1); // will only work with PHP >= 5.0 // NB: if we set an empty string, CURL will add http header indicating // ALL methods it is supporting. This is possibly a better option than // letting the user tell what curl can / cannot do... if(is_array($this->accepted_compression) && count($this->accepted_compression)) { //curl_setopt($curl, CURLOPT_ENCODING, implode(',', $this->accepted_compression)); // empty string means 'any supported by CURL' (shall we catch errors in case CURLOPT_SSLKEY undefined ?) if (count($this->accepted_compression) == 1) { curl_setopt($curl, CURLOPT_ENCODING, $this->accepted_compression[0]); } else curl_setopt($curl, CURLOPT_ENCODING, ''); } // extra headers $headers = array('Content-Type: ' . $msg->content_type , 'Accept-Charset: ' . implode(',', $this->accepted_charset_encodings)); // if no keepalive is wanted, let the server know it in advance if(!$keepalive) { $headers[] = 'Connection: close'; } // request compression header if($encoding_hdr) { $headers[] = $encoding_hdr; } curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); // timeout is borked if($timeout) { curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : $timeout - 1); } if($username && $password) { curl_setopt($curl, CURLOPT_USERPWD, $username.':'.$password); if (defined('CURLOPT_HTTPAUTH')) { curl_setopt($curl, CURLOPT_HTTPAUTH, $authtype); } else if ($authtype != 1) { error_log('XML-RPC: '.__METHOD__.': warning. Only Basic auth is supported by the current PHP/curl install'); } } if($method == 'https') { // set cert file if($cert) { curl_setopt($curl, CURLOPT_SSLCERT, $cert); } // set cert password if($certpass) { curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $certpass); } // whether to verify remote host's cert curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifypeer); // set ca certificates file/dir if($cacert) { curl_setopt($curl, CURLOPT_CAINFO, $cacert); } if($cacertdir) { curl_setopt($curl, CURLOPT_CAPATH, $cacertdir); } // set key file (shall we catch errors in case CURLOPT_SSLKEY undefined ?) if($key) { curl_setopt($curl, CURLOPT_SSLKEY, $key); } // set key password (shall we catch errors in case CURLOPT_SSLKEY undefined ?) if($keypass) { curl_setopt($curl, CURLOPT_SSLKEYPASSWD, $keypass); } // whether to verify cert's common name (CN); 0 for no, 1 to verify that it exists, and 2 to verify that it matches the hostname used curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->verifyhost); } // proxy info if($proxyhost) { if($proxyport == 0) { $proxyport = 8080; // NB: even for HTTPS, local connection is on port 8080 } curl_setopt($curl, CURLOPT_PROXY, $proxyhost.':'.$proxyport); //curl_setopt($curl, CURLOPT_PROXYPORT,$proxyport); if($proxyusername) { curl_setopt($curl, CURLOPT_PROXYUSERPWD, $proxyusername.':'.$proxypassword); if (defined('CURLOPT_PROXYAUTH')) { curl_setopt($curl, CURLOPT_PROXYAUTH, $proxyauthtype); } else if ($proxyauthtype != 1) { error_log('XML-RPC: '.__METHOD__.': warning. Only Basic auth to proxy is supported by the current PHP/curl install'); } } } // NB: should we build cookie http headers by hand rather than let CURL do it? // the following code does not honour 'expires', 'path' and 'domain' cookie attributes // set to client obj the the user... if (count($this->cookies)) { $cookieheader = ''; foreach ($this->cookies as $name => $cookie) { $cookieheader .= $name . '=' . $cookie['value'] . '; '; } curl_setopt($curl, CURLOPT_COOKIE, substr($cookieheader, 0, -2)); } foreach ($this->extracurlopts as $opt => $val) { curl_setopt($curl, $opt, $val); } $result = curl_exec($curl); if ($this->debug > 1) { print "
\n---CURL INFO---\n";
				foreach(curl_getinfo($curl) as $name => $val)
					 print $name . ': ' . htmlentities($val). "\n";
				print "---END---\n
"; } if(!$result) /// @todo we should use a better check here - what if we get back '' or '0'? { $this->errstr='no response'; $resp=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['curl_fail'], $GLOBALS['xmlrpcstr']['curl_fail']. ': '. curl_error($curl)); curl_close($curl); if($keepalive) { $this->xmlrpc_curl_handle = null; } } else { if(!$keepalive) { curl_close($curl); } $resp =& $msg->parseResponse($result, true, $this->return_type); } return $resp; } /** * Send an array of request messages and return an array of responses. * Unless $this->no_multicall has been set to true, it will try first * to use one single xmlrpc call to server method system.multicall, and * revert to sending many successive calls in case of failure. * This failure is also stored in $this->no_multicall for subsequent calls. * Unfortunately, there is no server error code universally used to denote * the fact that multicall is unsupported, so there is no way to reliably * distinguish between that and a temporary failure. * If you are sure that server supports multicall and do not want to * fallback to using many single calls, set the fourth parameter to FALSE. * * NB: trying to shoehorn extra functionality into existing syntax has resulted * in pretty much convoluted code... * * @param array $msgs an array of xmlrpcmsg objects * @param integer $timeout connection timeout (in seconds) * @param string $method the http protocol variant to be used * @param boolean fallback When true, upon receiveing an error during multicall, multiple single calls will be attempted * @return array * @access public */ function multicall($msgs, $timeout=0, $method='', $fallback=true) { if ($method == '') { $method = $this->method; } if(!$this->no_multicall) { $results = $this->_try_multicall($msgs, $timeout, $method); if(is_array($results)) { // System.multicall succeeded return $results; } else { // either system.multicall is unsupported by server, // or call failed for some other reason. if ($fallback) { // Don't try it next time... $this->no_multicall = true; } else { if (is_a($results, 'xmlrpcresp')) { $result = $results; } else { $result = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['multicall_error'], $GLOBALS['xmlrpcstr']['multicall_error']); } } } } else { // override fallback, in case careless user tries to do two // opposite things at the same time $fallback = true; } $results = array(); if ($fallback) { // system.multicall is (probably) unsupported by server: // emulate multicall via multiple requests foreach($msgs as $msg) { $results[] =& $this->send($msg, $timeout, $method); } } else { // user does NOT want to fallback on many single calls: // since we should always return an array of responses, // return an array with the same error repeated n times foreach($msgs as $msg) { $results[] = $result; } } return $results; } /** * Attempt to boxcar $msgs via system.multicall. * Returns either an array of xmlrpcreponses, an xmlrpc error response * or false (when received response does not respect valid multicall syntax) * @access private */ function _try_multicall($msgs, $timeout, $method) { // Construct multicall message $calls = array(); foreach($msgs as $msg) { $call['methodName'] = new xmlrpcval($msg->method(),'string'); $numParams = $msg->getNumParams(); $params = array(); for($i = 0; $i < $numParams; $i++) { $params[$i] = $msg->getParam($i); } $call['params'] = new xmlrpcval($params, 'array'); $calls[] = new xmlrpcval($call, 'struct'); } $multicall = new xmlrpcmsg('system.multicall'); $multicall->addParam(new xmlrpcval($calls, 'array')); // Attempt RPC call $result =& $this->send($multicall, $timeout, $method); if($result->faultCode() != 0) { // call to system.multicall failed return $result; } // Unpack responses. $rets = $result->value(); if ($this->return_type == 'xml') { return $rets; } else if ($this->return_type == 'phpvals') { ///@todo test this code branch... $rets = $result->value(); if(!is_array($rets)) { return false; // bad return type from system.multicall } $numRets = count($rets); if($numRets != count($msgs)) { return false; // wrong number of return values. } $response = array(); for($i = 0; $i < $numRets; $i++) { $val = $rets[$i]; if (!is_array($val)) { return false; } switch(count($val)) { case 1: if(!isset($val[0])) { return false; // Bad value } // Normal return value $response[$i] = new xmlrpcresp($val[0], 0, '', 'phpvals'); break; case 2: /// @todo remove usage of @: it is apparently quite slow $code = @$val['faultCode']; if(!is_int($code)) { return false; } $str = @$val['faultString']; if(!is_string($str)) { return false; } $response[$i] = new xmlrpcresp(0, $code, $str); break; default: return false; } } return $response; } else // return type == 'xmlrpcvals' { $rets = $result->value(); if($rets->kindOf() != 'array') { return false; // bad return type from system.multicall } $numRets = $rets->arraysize(); if($numRets != count($msgs)) { return false; // wrong number of return values. } $response = array(); for($i = 0; $i < $numRets; $i++) { $val = $rets->arraymem($i); switch($val->kindOf()) { case 'array': if($val->arraysize() != 1) { return false; // Bad value } // Normal return value $response[$i] = new xmlrpcresp($val->arraymem(0)); break; case 'struct': $code = $val->structmem('faultCode'); if($code->kindOf() != 'scalar' || $code->scalartyp() != 'int') { return false; } $str = $val->structmem('faultString'); if($str->kindOf() != 'scalar' || $str->scalartyp() != 'string') { return false; } $response[$i] = new xmlrpcresp(0, $code->scalarval(), $str->scalarval()); break; default: return false; } } return $response; } } } // end class xmlrpc_client class xmlrpcresp { var $val = 0; var $valtyp; var $errno = 0; var $errstr = ''; var $payload; var $hdrs = array(); var $_cookies = array(); var $content_type = 'text/xml'; var $raw_data = ''; /** * @param mixed $val either an xmlrpcval obj, a php value or the xml serialization of an xmlrpcval (a string) * @param integer $fcode set it to anything but 0 to create an error response * @param string $fstr the error string, in case of an error response * @param string $valtyp either 'xmlrpcvals', 'phpvals' or 'xml' * * @todo add check that $val / $fcode / $fstr is of correct type??? * NB: as of now we do not do it, since it might be either an xmlrpcval or a plain * php val, or a complete xml chunk, depending on usage of xmlrpc_client::send() inside which creator is called... */ function xmlrpcresp($val, $fcode = 0, $fstr = '', $valtyp='') { if($fcode != 0) { // error response $this->errno = $fcode; $this->errstr = $fstr; //$this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later. } else { // successful response $this->val = $val; if ($valtyp == '') { // user did not declare type of response value: try to guess it if (is_object($this->val) && is_a($this->val, 'xmlrpcval')) { $this->valtyp = 'xmlrpcvals'; } else if (is_string($this->val)) { $this->valtyp = 'xml'; } else { $this->valtyp = 'phpvals'; } } else { // user declares type of resp value: believe him $this->valtyp = $valtyp; } } } /** * Returns the error code of the response. * @return integer the error code of this response (0 for not-error responses) * @access public */ function faultCode() { return $this->errno; } /** * Returns the error code of the response. * @return string the error string of this response ('' for not-error responses) * @access public */ function faultString() { return $this->errstr; } /** * Returns the value received by the server. * @return mixed the xmlrpcval object returned by the server. Might be an xml string or php value if the response has been created by specially configured xmlrpc_client objects * @access public */ function value() { return $this->val; } /** * Returns an array with the cookies received from the server. * Array has the form: $cookiename => array ('value' => $val, $attr1 => $val1, $attr2 = $val2, ...) * with attributes being e.g. 'expires', 'path', domain'. * NB: cookies sent as 'expired' by the server (i.e. with an expiry date in the past) * are still present in the array. It is up to the user-defined code to decide * how to use the received cookies, and wheter they have to be sent back with the next * request to the server (using xmlrpc_client::setCookie) or not * @return array array of cookies received from the server * @access public */ function cookies() { return $this->_cookies; } /** * Returns xml representation of the response. XML prologue not included * @param string $charset_encoding the charset to be used for serialization. if null, US-ASCII is assumed * @return string the xml representation of the response * @access public */ function serialize($charset_encoding='') { if ($charset_encoding != '') $this->content_type = 'text/xml; charset=' . $charset_encoding; else $this->content_type = 'text/xml'; $result = "\n"; if($this->errno) { // G. Giunta 2005/2/13: let non-ASCII response messages be tolerated by clients // by xml-encoding non ascii chars $result .= "\n" . "\nfaultCode\n" . $this->errno . "\n\n\nfaultString\n" . xmlrpc_encode_entitites($this->errstr, $GLOBALS['xmlrpc_internalencoding'], $charset_encoding) . "\n\n" . "\n\n"; } else { if(!is_object($this->val) || !is_a($this->val, 'xmlrpcval')) { if (is_string($this->val) && $this->valtyp == 'xml') { $result .= "\n\n" . $this->val . "\n"; } else { /// @todo try to build something serializable? die('cannot serialize xmlrpcresp objects whose content is native php values'); } } else { $result .= "\n\n" . $this->val->serialize($charset_encoding) . "\n"; } } $result .= "\n"; $this->payload = $result; return $result; } } class xmlrpcmsg { var $payload; var $methodname; var $params=array(); var $debug=0; var $content_type = 'text/xml'; /** * @param string $meth the name of the method to invoke * @param array $pars array of parameters to be paased to the method (xmlrpcval objects) */ function xmlrpcmsg($meth, $pars=0) { $this->methodname=$meth; if(is_array($pars) && count($pars)>0) { for($i=0; $iaddParam($pars[$i]); } } } /** * @access private */ function xml_header($charset_encoding='') { if ($charset_encoding != '') { return "\n\n"; } else { return "\n\n"; } } /** * @access private */ function xml_footer() { return ''; } /** * @access private */ function kindOf() { return 'msg'; } /** * @access private */ function createPayload($charset_encoding='') { if ($charset_encoding != '') $this->content_type = 'text/xml; charset=' . $charset_encoding; else $this->content_type = 'text/xml'; $this->payload=$this->xml_header($charset_encoding); $this->payload.='' . $this->methodname . "\n"; $this->payload.="\n"; for($i=0; $iparams); $i++) { $p=$this->params[$i]; $this->payload.="\n" . $p->serialize($charset_encoding) . "\n"; } $this->payload.="\n"; $this->payload.=$this->xml_footer(); } /** * Gets/sets the xmlrpc method to be invoked * @param string $meth the method to be set (leave empty not to set it) * @return string the method that will be invoked * @access public */ function method($meth='') { if($meth!='') { $this->methodname=$meth; } return $this->methodname; } /** * Returns xml representation of the message. XML prologue included * @return string the xml representation of the message, xml prologue included * @access public */ function serialize($charset_encoding='') { $this->createPayload($charset_encoding); return $this->payload; } /** * Add a parameter to the list of parameters to be used upon method invocation * @param xmlrpcval $par * @return boolean false on failure * @access public */ function addParam($par) { // add check: do not add to self params which are not xmlrpcvals if(is_object($par) && is_a($par, 'xmlrpcval')) { $this->params[]=$par; return true; } else { return false; } } /** * Returns the nth parameter in the message. The index zero-based. * @param integer $i the index of the parameter to fetch (zero based) * @return xmlrpcval the i-th parameter * @access public */ function getParam($i) { return $this->params[$i]; } /** * Returns the number of parameters in the messge. * @return integer the number of parameters currently set * @access public */ function getNumParams() { return count($this->params); } /** * Given an open file handle, read all data available and parse it as axmlrpc response. * NB: the file handle is not closed by this function. * NNB: might have trouble in rare cases to work on network streams, as we * check for a read of 0 bytes instead of feof($fp). * But since checking for feof(null) returns false, we would risk an * infinite loop in that case, because we cannot trust the caller * to give us a valid pointer to an open file... * @access public * @return xmlrpcresp * @todo add 2nd & 3rd param to be passed to ParseResponse() ??? */ function &parseResponseFile($fp) { $ipd=''; while($data=fread($fp, 32768)) { $ipd.=$data; } //fclose($fp); $r =& $this->parseResponse($ipd); return $r; } /** * Parses HTTP headers and separates them from data. * @access private */ function &parseResponseHeaders(&$data, $headers_processed=false) { // Support "web-proxy-tunelling" connections for https through proxies if(preg_match('/^HTTP\/1\.[0-1] 200 Connection established/', $data)) { // Look for CR/LF or simple LF as line separator, // (even though it is not valid http) $pos = strpos($data,"\r\n\r\n"); if($pos || is_int($pos)) { $bd = $pos+4; } else { $pos = strpos($data,"\n\n"); if($pos || is_int($pos)) { $bd = $pos+2; } else { // No separation between response headers and body: fault? $bd = 0; } } if ($bd) { // this filters out all http headers from proxy. // maybe we could take them into account, too? $data = substr($data, $bd); } else { error_log('XML-RPC: '.__METHOD__.': HTTPS via proxy error, tunnel connection possibly failed'); $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $GLOBALS['xmlrpcstr']['http_error']. ' (HTTPS via proxy error, tunnel connection possibly failed)'); return $r; } } // Strip HTTP 1.1 100 Continue header if present while(preg_match('/^HTTP\/1\.1 1[0-9]{2} /', $data)) { $pos = strpos($data, 'HTTP', 12); // server sent a Continue header without any (valid) content following... // give the client a chance to know it if(!$pos && !is_int($pos)) // works fine in php 3, 4 and 5 { break; } $data = substr($data, $pos); } if(!preg_match('/^HTTP\/[0-9.]+ 200 /', $data)) { $errstr= substr($data, 0, strpos($data, "\n")-1); error_log('XML-RPC: '.__METHOD__.': HTTP error, got response: ' .$errstr); $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['http_error'], $GLOBALS['xmlrpcstr']['http_error']. ' (' . $errstr . ')'); return $r; } $GLOBALS['_xh']['headers'] = array(); $GLOBALS['_xh']['cookies'] = array(); // be tolerant to usage of \n instead of \r\n to separate headers and data // (even though it is not valid http) $pos = strpos($data,"\r\n\r\n"); if($pos || is_int($pos)) { $bd = $pos+4; } else { $pos = strpos($data,"\n\n"); if($pos || is_int($pos)) { $bd = $pos+2; } else { // No separation between response headers and body: fault? // we could take some action here instead of going on... $bd = 0; } } // be tolerant to line endings, and extra empty lines $ar = preg_split("/\r?\n/", trim(substr($data, 0, $pos))); while(list(,$line) = @each($ar)) { // take care of multi-line headers and cookies $arr = explode(':',$line,2); if(count($arr) > 1) { $header_name = strtolower(trim($arr[0])); /// @todo some other headers (the ones that allow a CSV list of values) /// do allow many values to be passed using multiple header lines. /// We should add content to $GLOBALS['_xh']['headers'][$header_name] /// instead of replacing it for those... if ($header_name == 'set-cookie' || $header_name == 'set-cookie2') { if ($header_name == 'set-cookie2') { // version 2 cookies: // there could be many cookies on one line, comma separated $cookies = explode(',', $arr[1]); } else { $cookies = array($arr[1]); } foreach ($cookies as $cookie) { // glue together all received cookies, using a comma to separate them // (same as php does with getallheaders()) if (isset($GLOBALS['_xh']['headers'][$header_name])) $GLOBALS['_xh']['headers'][$header_name] .= ', ' . trim($cookie); else $GLOBALS['_xh']['headers'][$header_name] = trim($cookie); // parse cookie attributes, in case user wants to correctly honour them // feature creep: only allow rfc-compliant cookie attributes? // @todo support for server sending multiple time cookie with same name, but using different PATHs $cookie = explode(';', $cookie); foreach ($cookie as $pos => $val) { $val = explode('=', $val, 2); $tag = trim($val[0]); $val = trim(@$val[1]); /// @todo with version 1 cookies, we should strip leading and trailing " chars if ($pos == 0) { $cookiename = $tag; $GLOBALS['_xh']['cookies'][$tag] = array(); $GLOBALS['_xh']['cookies'][$cookiename]['value'] = urldecode($val); } else { if ($tag != 'value') { $GLOBALS['_xh']['cookies'][$cookiename][$tag] = $val; } } } } } else { $GLOBALS['_xh']['headers'][$header_name] = trim($arr[1]); } } elseif(isset($header_name)) { /// @todo version1 cookies might span multiple lines, thus breaking the parsing above $GLOBALS['_xh']['headers'][$header_name] .= ' ' . trim($line); } } $data = substr($data, $bd); if($this->debug && count($GLOBALS['_xh']['headers'])) { print '
';
					foreach($GLOBALS['_xh']['headers'] as $header => $value)
					{
						print htmlentities("HEADER: $header: $value\n");
					}
					foreach($GLOBALS['_xh']['cookies'] as $header => $value)
					{
						print htmlentities("COOKIE: $header={$value['value']}\n");
					}
					print "
\n"; } // if CURL was used for the call, http headers have been processed, // and dechunking + reinflating have been carried out if(!$headers_processed) { // Decode chunked encoding sent by http 1.1 servers if(isset($GLOBALS['_xh']['headers']['transfer-encoding']) && $GLOBALS['_xh']['headers']['transfer-encoding'] == 'chunked') { if(!$data = decode_chunked($data)) { error_log('XML-RPC: '.__METHOD__.': errors occurred when trying to rebuild the chunked data received from server'); $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['dechunk_fail'], $GLOBALS['xmlrpcstr']['dechunk_fail']); return $r; } } // Decode gzip-compressed stuff // code shamelessly inspired from nusoap library by Dietrich Ayala if(isset($GLOBALS['_xh']['headers']['content-encoding'])) { $GLOBALS['_xh']['headers']['content-encoding'] = str_replace('x-', '', $GLOBALS['_xh']['headers']['content-encoding']); if($GLOBALS['_xh']['headers']['content-encoding'] == 'deflate' || $GLOBALS['_xh']['headers']['content-encoding'] == 'gzip') { // if decoding works, use it. else assume data wasn't gzencoded if(function_exists('gzinflate')) { if($GLOBALS['_xh']['headers']['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) { $data = $degzdata; if($this->debug) print "
---INFLATED RESPONSE---[".strlen($data)." chars]---\n" . htmlentities($data) . "\n---END---
"; } elseif($GLOBALS['_xh']['headers']['content-encoding'] == 'gzip' && $degzdata = @gzinflate(substr($data, 10))) { $data = $degzdata; if($this->debug) print "
---INFLATED RESPONSE---[".strlen($data)." chars]---\n" . htmlentities($data) . "\n---END---
"; } else { error_log('XML-RPC: '.__METHOD__.': errors occurred when trying to decode the deflated data received from server'); $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['decompress_fail'], $GLOBALS['xmlrpcstr']['decompress_fail']); return $r; } } else { error_log('XML-RPC: '.__METHOD__.': the server sent deflated data. Your php install must have the Zlib extension compiled in to support this.'); $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['cannot_decompress'], $GLOBALS['xmlrpcstr']['cannot_decompress']); return $r; } } } } // end of 'if needed, de-chunk, re-inflate response' // real stupid hack to avoid PHP complaining about returning NULL by ref $r = null; $r =& $r; return $r; } /** * Parse the xmlrpc response contained in the string $data and return an xmlrpcresp object. * @param string $data the xmlrpc response, eventually including http headers * @param bool $headers_processed when true prevents parsing HTTP headers for interpretation of content-encoding and consequent decoding * @param string $return_type decides return type, i.e. content of response->value(). Either 'xmlrpcvals', 'xml' or 'phpvals' * @return xmlrpcresp * @access public */ function &parseResponse($data='', $headers_processed=false, $return_type='xmlrpcvals') { if($this->debug) { //by maHo, replaced htmlspecialchars with htmlentities print "
---GOT---\n" . htmlentities($data) . "\n---END---\n
"; } if($data == '') { error_log('XML-RPC: '.__METHOD__.': no response received from server.'); $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['no_data'], $GLOBALS['xmlrpcstr']['no_data']); return $r; } $GLOBALS['_xh']=array(); $raw_data = $data; // parse the HTTP headers of the response, if present, and separate them from data if(substr($data, 0, 4) == 'HTTP') { $r =& $this->parseResponseHeaders($data, $headers_processed); if ($r) { // failed processing of HTTP response headers // save into response obj the full payload received, for debugging $r->raw_data = $data; return $r; } } else { $GLOBALS['_xh']['headers'] = array(); $GLOBALS['_xh']['cookies'] = array(); } if($this->debug) { $start = strpos($data, '', $start); $comments = substr($data, $start, $end-$start); print "
---SERVER DEBUG INFO (DECODED) ---\n\t".htmlentities(str_replace("\n", "\n\t", base64_decode($comments)))."\n---END---\n
"; } } // be tolerant of extra whitespace in response body $data = trim($data); /// @todo return an error msg if $data=='' ? // be tolerant of junk after methodResponse (e.g. javascript ads automatically inserted by free hosts) // idea from Luca Mariano originally in PEARified version of the lib $pos = strrpos($data, ''); if($pos !== false) { $data = substr($data, 0, $pos+17); } // if user wants back raw xml, give it to him if ($return_type == 'xml') { $r = new xmlrpcresp($data, 0, '', 'xml'); $r->hdrs = $GLOBALS['_xh']['headers']; $r->_cookies = $GLOBALS['_xh']['cookies']; $r->raw_data = $raw_data; return $r; } // try to 'guestimate' the character encoding of the received response $resp_encoding = guess_encoding(@$GLOBALS['_xh']['headers']['content-type'], $data); $GLOBALS['_xh']['ac']=''; //$GLOBALS['_xh']['qt']=''; //unused... $GLOBALS['_xh']['stack'] = array(); $GLOBALS['_xh']['valuestack'] = array(); $GLOBALS['_xh']['isf']=0; // 0 = OK, 1 for xmlrpc fault responses, 2 = invalid xmlrpc $GLOBALS['_xh']['isf_reason']=''; $GLOBALS['_xh']['rt']=''; // 'methodcall or 'methodresponse' // if response charset encoding is not known / supported, try to use // the default encoding and parse the xml anyway, but log a warning... if (!in_array($resp_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) // the following code might be better for mb_string enabled installs, but // makes the lib about 200% slower... //if (!is_valid_charset($resp_encoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { error_log('XML-RPC: '.__METHOD__.': invalid charset encoding of received response: '.$resp_encoding); $resp_encoding = $GLOBALS['xmlrpc_defencoding']; } $parser = xml_parser_create($resp_encoding); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell // the xml parser to give us back data in the expected charset. // What if internal encoding is not in one of the 3 allowed? // we use the broadest one, ie. utf8 // This allows to send data which is native in various charset, // by extending xmlrpc_encode_entitites() and setting xmlrpc_internalencoding if (!in_array($GLOBALS['xmlrpc_internalencoding'], array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8'); } else { xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $GLOBALS['xmlrpc_internalencoding']); } if ($return_type == 'phpvals') { xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee_fast'); } else { xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee'); } xml_set_character_data_handler($parser, 'xmlrpc_cd'); xml_set_default_handler($parser, 'xmlrpc_dh'); // first error check: xml not well formed if(!xml_parse($parser, $data, count($data))) { // thanks to Peter Kocks if((xml_get_current_line_number($parser)) == 1) { $errstr = 'XML error at line 1, check URL'; } else { $errstr = sprintf('XML error: %s at line %d, column %d', xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser), xml_get_current_column_number($parser)); } error_log($errstr); $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcstr']['invalid_return'].' ('.$errstr.')'); xml_parser_free($parser); if($this->debug) { print $errstr; } $r->hdrs = $GLOBALS['_xh']['headers']; $r->_cookies = $GLOBALS['_xh']['cookies']; $r->raw_data = $raw_data; return $r; } xml_parser_free($parser); // second error check: xml well formed but not xml-rpc compliant if ($GLOBALS['_xh']['isf'] > 1) { if ($this->debug) { /// @todo echo something for user? } $r = new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcstr']['invalid_return'] . ' ' . $GLOBALS['_xh']['isf_reason']); } // third error check: parsing of the response has somehow gone boink. // NB: shall we omit this check, since we trust the parsing code? elseif ($return_type == 'xmlrpcvals' && !is_object($GLOBALS['_xh']['value'])) { // something odd has happened // and it's time to generate a client side error // indicating something odd went on $r=new xmlrpcresp(0, $GLOBALS['xmlrpcerr']['invalid_return'], $GLOBALS['xmlrpcstr']['invalid_return']); } else { if ($this->debug) { print "
---PARSED---\n";
					// somehow htmlentities chokes on var_export, and some full html string...
					//print htmlentitites(var_export($GLOBALS['_xh']['value'], true));
					print htmlspecialchars(var_export($GLOBALS['_xh']['value'], true));
					print "\n---END---
"; } // note that using =& will raise an error if $GLOBALS['_xh']['st'] does not generate an object. $v =& $GLOBALS['_xh']['value']; if($GLOBALS['_xh']['isf']) { /// @todo we should test here if server sent an int and a string, /// and/or coerce them into such... if ($return_type == 'xmlrpcvals') { $errno_v = $v->structmem('faultCode'); $errstr_v = $v->structmem('faultString'); $errno = $errno_v->scalarval(); $errstr = $errstr_v->scalarval(); } else { $errno = $v['faultCode']; $errstr = $v['faultString']; } if($errno == 0) { // FAULT returned, errno needs to reflect that $errno = -1; } $r = new xmlrpcresp(0, $errno, $errstr); } else { $r=new xmlrpcresp($v, 0, '', $return_type); } } $r->hdrs = $GLOBALS['_xh']['headers']; $r->_cookies = $GLOBALS['_xh']['cookies']; $r->raw_data = $raw_data; return $r; } } class xmlrpcval { var $me=array(); var $mytype=0; var $_php_class=null; /** * @param mixed $val * @param string $type any valid xmlrpc type name (lowercase). If null, 'string' is assumed */ function xmlrpcval($val=-1, $type='') { /// @todo: optimization creep - do not call addXX, do it all inline. /// downside: booleans will not be coerced anymore if($val!==-1 || $type!='') { // optimization creep: inlined all work done by constructor switch($type) { case '': $this->mytype=1; $this->me['string']=$val; break; case 'i4': case 'int': case 'double': case 'string': case 'boolean': case 'dateTime.iso8601': case 'base64': case 'null': $this->mytype=1; $this->me[$type]=$val; break; case 'array': $this->mytype=2; $this->me['array']=$val; break; case 'struct': $this->mytype=3; $this->me['struct']=$val; break; default: error_log("XML-RPC: ".__METHOD__.": not a known type ($type)"); } /*if($type=='') { $type='string'; } if($GLOBALS['xmlrpcTypes'][$type]==1) { $this->addScalar($val,$type); } elseif($GLOBALS['xmlrpcTypes'][$type]==2) { $this->addArray($val); } elseif($GLOBALS['xmlrpcTypes'][$type]==3) { $this->addStruct($val); }*/ } } /** * Add a single php value to an (unitialized) xmlrpcval * @param mixed $val * @param string $type * @return int 1 or 0 on failure */ function addScalar($val, $type='string') { $typeof=@$GLOBALS['xmlrpcTypes'][$type]; if($typeof!=1) { error_log("XML-RPC: ".__METHOD__.": not a scalar type ($type)"); return 0; } // coerce booleans into correct values // NB: we should either do it for datetimes, integers and doubles, too, // or just plain remove this check, implemented on booleans only... if($type==$GLOBALS['xmlrpcBoolean']) { if(strcasecmp($val,'true')==0 || $val==1 || ($val==true && strcasecmp($val,'false'))) { $val=true; } else { $val=false; } } switch($this->mytype) { case 1: error_log('XML-RPC: '.__METHOD__.': scalar xmlrpcval can have only one value'); return 0; case 3: error_log('XML-RPC: '.__METHOD__.': cannot add anonymous scalar to struct xmlrpcval'); return 0; case 2: // we're adding a scalar value to an array here //$ar=$this->me['array']; //$ar[]=new xmlrpcval($val, $type); //$this->me['array']=$ar; // Faster (?) avoid all the costly array-copy-by-val done here... $this->me['array'][]=new xmlrpcval($val, $type); return 1; default: // a scalar, so set the value and remember we're scalar $this->me[$type]=$val; $this->mytype=$typeof; return 1; } } /** * Add an array of xmlrpcval objects to an xmlrpcval * @param array $vals * @return int 1 or 0 on failure * @access public * * @todo add some checking for $vals to be an array of xmlrpcvals? */ function addArray($vals) { if($this->mytype==0) { $this->mytype=$GLOBALS['xmlrpcTypes']['array']; $this->me['array']=$vals; return 1; } elseif($this->mytype==2) { // we're adding to an array here $this->me['array'] = array_merge($this->me['array'], $vals); return 1; } else { error_log('XML-RPC: '.__METHOD__.': already initialized as a [' . $this->kindOf() . ']'); return 0; } } /** * Add an array of named xmlrpcval objects to an xmlrpcval * @param array $vals * @return int 1 or 0 on failure * @access public * * @todo add some checking for $vals to be an array? */ function addStruct($vals) { if($this->mytype==0) { $this->mytype=$GLOBALS['xmlrpcTypes']['struct']; $this->me['struct']=$vals; return 1; } elseif($this->mytype==3) { // we're adding to a struct here $this->me['struct'] = array_merge($this->me['struct'], $vals); return 1; } else { error_log('XML-RPC: '.__METHOD__.': already initialized as a [' . $this->kindOf() . ']'); return 0; } } // poor man's version of print_r ??? // DEPRECATED! function dump($ar) { foreach($ar as $key => $val) { echo "$key => $val
"; if($key == 'array') { while(list($key2, $val2) = each($val)) { echo "-- $key2 => $val2
"; } } } } /** * Returns a string containing "struct", "array" or "scalar" describing the base type of the value * @return string * @access public */ function kindOf() { switch($this->mytype) { case 3: return 'struct'; break; case 2: return 'array'; break; case 1: return 'scalar'; break; default: return 'undef'; } } /** * @access private */ function serializedata($typ, $val, $charset_encoding='') { $rs=''; switch(@$GLOBALS['xmlrpcTypes'][$typ]) { case 1: switch($typ) { case $GLOBALS['xmlrpcBase64']: $rs.="<${typ}>" . base64_encode($val) . ""; break; case $GLOBALS['xmlrpcBoolean']: $rs.="<${typ}>" . ($val ? '1' : '0') . ""; break; case $GLOBALS['xmlrpcString']: // G. Giunta 2005/2/13: do NOT use htmlentities, since // it will produce named html entities, which are invalid xml $rs.="<${typ}>" . xmlrpc_encode_entitites($val, $GLOBALS['xmlrpc_internalencoding'], $charset_encoding). ""; break; case $GLOBALS['xmlrpcInt']: case $GLOBALS['xmlrpcI4']: $rs.="<${typ}>".(int)$val.""; break; case $GLOBALS['xmlrpcDouble']: // avoid using standard conversion of float to string because it is locale-dependent, // and also because the xmlrpc spec forbids exponential notation. // sprintf('%F') could be most likely ok but it fails eg. on 2e-14. // The code below tries its best at keeping max precision while avoiding exp notation, // but there is of course no limit in the number of decimal places to be used... $rs.="<${typ}>".preg_replace('/\\.?0+$/','',number_format((double)$val, 128, '.', '')).""; break; case $GLOBALS['xmlrpcDateTime']: if (is_string($val)) { $rs.="<${typ}>${val}"; } else if(is_a($val, 'DateTime')) { $rs.="<${typ}>".$val->format('Ymd\TH:i:s').""; } else if(is_int($val)) { $rs.="<${typ}>".strftime("%Y%m%dT%H:%M:%S", $val).""; } else { // not really a good idea here: but what shall we output anyway? left for backward compat... $rs.="<${typ}>${val}"; } break; case $GLOBALS['xmlrpcNull']: if ($GLOBALS['xmlrpc_null_apache_encoding']) { $rs.=""; } else { $rs.=""; } break; default: // no standard type value should arrive here, but provide a possibility // for xmlrpcvals of unknown type... $rs.="<${typ}>${val}"; } break; case 3: // struct if ($this->_php_class) { $rs.='\n"; } else { $rs.="\n"; } foreach($val as $key2 => $val2) { $rs.=''.xmlrpc_encode_entitites($key2, $GLOBALS['xmlrpc_internalencoding'], $charset_encoding)."\n"; //$rs.=$this->serializeval($val2); $rs.=$val2->serialize($charset_encoding); $rs.="\n"; } $rs.=''; break; case 2: // array $rs.="\n\n"; for($i=0; $iserializeval($val[$i]); $rs.=$val[$i]->serialize($charset_encoding); } $rs.="\n"; break; default: break; } return $rs; } /** * Returns xml representation of the value. XML prologue not included * @param string $charset_encoding the charset to be used for serialization. if null, US-ASCII is assumed * @return string * @access public */ function serialize($charset_encoding='') { // add check? slower, but helps to avoid recursion in serializing broken xmlrpcvals... //if (is_object($o) && (get_class($o) == 'xmlrpcval' || is_subclass_of($o, 'xmlrpcval'))) //{ reset($this->me); list($typ, $val) = each($this->me); return '' . $this->serializedata($typ, $val, $charset_encoding) . "\n"; //} } // DEPRECATED function serializeval($o) { // add check? slower, but helps to avoid recursion in serializing broken xmlrpcvals... //if (is_object($o) && (get_class($o) == 'xmlrpcval' || is_subclass_of($o, 'xmlrpcval'))) //{ $ar=$o->me; reset($ar); list($typ, $val) = each($ar); return '' . $this->serializedata($typ, $val) . "\n"; //} } /** * Checks wheter a struct member with a given name is present. * Works only on xmlrpcvals of type struct. * @param string $m the name of the struct member to be looked up * @return boolean * @access public */ function structmemexists($m) { return array_key_exists($m, $this->me['struct']); } /** * Returns the value of a given struct member (an xmlrpcval object in itself). * Will raise a php warning if struct member of given name does not exist * @param string $m the name of the struct member to be looked up * @return xmlrpcval * @access public */ function structmem($m) { return $this->me['struct'][$m]; } /** * Reset internal pointer for xmlrpcvals of type struct. * @access public */ function structreset() { reset($this->me['struct']); } /** * Return next member element for xmlrpcvals of type struct. * @return xmlrpcval * @access public */ function structeach() { return each($this->me['struct']); } // DEPRECATED! this code looks like it is very fragile and has not been fixed // for a long long time. Shall we remove it for 2.0? function getval() { // UNSTABLE reset($this->me); list($a,$b)=each($this->me); // contributed by I Sofer, 2001-03-24 // add support for nested arrays to scalarval // i've created a new method here, so as to // preserve back compatibility if(is_array($b)) { @reset($b); while(list($id,$cont) = @each($b)) { $b[$id] = $cont->scalarval(); } } // add support for structures directly encoding php objects if(is_object($b)) { $t = get_object_vars($b); @reset($t); while(list($id,$cont) = @each($t)) { $t[$id] = $cont->scalarval(); } @reset($t); while(list($id,$cont) = @each($t)) { @$b->$id = $cont; } } // end contrib return $b; } /** * Returns the value of a scalar xmlrpcval * @return mixed * @access public */ function scalarval() { reset($this->me); list(,$b)=each($this->me); return $b; } /** * Returns the type of the xmlrpcval. * For integers, 'int' is always returned in place of 'i4' * @return string * @access public */ function scalartyp() { reset($this->me); list($a,)=each($this->me); if($a==$GLOBALS['xmlrpcI4']) { $a=$GLOBALS['xmlrpcInt']; } return $a; } /** * Returns the m-th member of an xmlrpcval of struct type * @param integer $m the index of the value to be retrieved (zero based) * @return xmlrpcval * @access public */ function arraymem($m) { return $this->me['array'][$m]; } /** * Returns the number of members in an xmlrpcval of array type * @return integer * @access public */ function arraysize() { return count($this->me['array']); } /** * Returns the number of members in an xmlrpcval of struct type * @return integer * @access public */ function structsize() { return count($this->me['struct']); } } // date helpers /** * Given a timestamp, return the corresponding ISO8601 encoded string. * * Really, timezones ought to be supported * but the XML-RPC spec says: * * "Don't assume a timezone. It should be specified by the server in its * documentation what assumptions it makes about timezones." * * These routines always assume localtime unless * $utc is set to 1, in which case UTC is assumed * and an adjustment for locale is made when encoding * * @param int $timet (timestamp) * @param int $utc (0 or 1) * @return string */ function iso8601_encode($timet, $utc=0) { if(!$utc) { $t=strftime("%Y%m%dT%H:%M:%S", $timet); } else { if(function_exists('gmstrftime')) { // gmstrftime doesn't exist in some versions // of PHP $t=gmstrftime("%Y%m%dT%H:%M:%S", $timet); } else { $t=strftime("%Y%m%dT%H:%M:%S", $timet-date('Z')); } } return $t; } /** * Given an ISO8601 date string, return a timet in the localtime, or UTC * @param string $idate * @param int $utc either 0 or 1 * @return int (datetime) */ function iso8601_decode($idate, $utc=0) { $t=0; if(preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $idate, $regs)) { if($utc) { $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); } else { $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); } } return $t; } /** * Takes an xmlrpc value in PHP xmlrpcval object format and translates it into native PHP types. * * Works with xmlrpc message objects as input, too. * * Given proper options parameter, can rebuild generic php object instances * (provided those have been encoded to xmlrpc format using a corresponding * option in php_xmlrpc_encode()) * PLEASE NOTE that rebuilding php objects involves calling their constructor function. * This means that the remote communication end can decide which php code will * get executed on your server, leaving the door possibly open to 'php-injection' * style of attacks (provided you have some classes defined on your server that * might wreak havoc if instances are built outside an appropriate context). * Make sure you trust the remote server/client before eanbling this! * * @author Dan Libby (dan@libby.com) * * @param xmlrpcval $xmlrpc_val * @param array $options if 'decode_php_objs' is set in the options array, xmlrpc structs can be decoded into php objects; if 'dates_as_objects' is set xmlrpc datetimes are decoded as php DateTime objects (standard is * @return mixed */ function php_xmlrpc_decode($xmlrpc_val, $options=array()) { switch($xmlrpc_val->kindOf()) { case 'scalar': if (in_array('extension_api', $options)) { reset($xmlrpc_val->me); list($typ,$val) = each($xmlrpc_val->me); switch ($typ) { case 'dateTime.iso8601': $xmlrpc_val->scalar = $val; $xmlrpc_val->xmlrpc_type = 'datetime'; $xmlrpc_val->timestamp = iso8601_decode($val); return $xmlrpc_val; case 'base64': $xmlrpc_val->scalar = $val; $xmlrpc_val->type = $typ; return $xmlrpc_val; default: return $xmlrpc_val->scalarval(); } } if (in_array('dates_as_objects', $options) && $xmlrpc_val->scalartyp() == 'dateTime.iso8601') { // we return a Datetime object instead of a string // since now the constructor of xmlrpcval accepts safely strings, ints and datetimes, // we cater to all 3 cases here $out = $xmlrpc_val->scalarval(); if (is_string($out)) { $out = strtotime($out); } if (is_int($out)) { $result = new Datetime(); $result->setTimestamp($out); return $result; } elseif (is_a($out, 'Datetime')) { return $out; } } return $xmlrpc_val->scalarval(); case 'array': $size = $xmlrpc_val->arraysize(); $arr = array(); for($i = 0; $i < $size; $i++) { $arr[] = php_xmlrpc_decode($xmlrpc_val->arraymem($i), $options); } return $arr; case 'struct': $xmlrpc_val->structreset(); // If user said so, try to rebuild php objects for specific struct vals. /// @todo should we raise a warning for class not found? // shall we check for proper subclass of xmlrpcval instead of // presence of _php_class to detect what we can do? if (in_array('decode_php_objs', $options) && $xmlrpc_val->_php_class != '' && class_exists($xmlrpc_val->_php_class)) { $obj = @new $xmlrpc_val->_php_class; while(list($key,$value)=$xmlrpc_val->structeach()) { $obj->$key = php_xmlrpc_decode($value, $options); } return $obj; } else { $arr = array(); while(list($key,$value)=$xmlrpc_val->structeach()) { $arr[$key] = php_xmlrpc_decode($value, $options); } return $arr; } case 'msg': $paramcount = $xmlrpc_val->getNumParams(); $arr = array(); for($i = 0; $i < $paramcount; $i++) { $arr[] = php_xmlrpc_decode($xmlrpc_val->getParam($i)); } return $arr; } } // This constant left here only for historical reasons... // it was used to decide if we have to define xmlrpc_encode on our own, but // we do not do it anymore if(function_exists('xmlrpc_decode')) { define('XMLRPC_EPI_ENABLED','1'); } else { define('XMLRPC_EPI_ENABLED','0'); } /** * Takes native php types and encodes them into xmlrpc PHP object format. * It will not re-encode xmlrpcval objects. * * Feature creep -- could support more types via optional type argument * (string => datetime support has been added, ??? => base64 not yet) * * If given a proper options parameter, php object instances will be encoded * into 'special' xmlrpc values, that can later be decoded into php objects * by calling php_xmlrpc_decode() with a corresponding option * * @author Dan Libby (dan@libby.com) * * @param mixed $php_val the value to be converted into an xmlrpcval object * @param array $options can include 'encode_php_objs', 'auto_dates', 'null_extension' or 'extension_api' * @return xmlrpcval */ function php_xmlrpc_encode($php_val, $options=array()) { $type = gettype($php_val); switch($type) { case 'string': if (in_array('auto_dates', $options) && preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $php_val)) $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcDateTime']); else $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcString']); break; case 'integer': $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcInt']); break; case 'double': $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcDouble']); break; // // Add support for encoding/decoding of booleans, since they are supported in PHP case 'boolean': $xmlrpc_val = new xmlrpcval($php_val, $GLOBALS['xmlrpcBoolean']); break; // case 'array': // PHP arrays can be encoded to either xmlrpc structs or arrays, // depending on wheter they are hashes or plain 0..n integer indexed // A shorter one-liner would be // $tmp = array_diff(array_keys($php_val), range(0, count($php_val)-1)); // but execution time skyrockets! $j = 0; $arr = array(); $ko = false; foreach($php_val as $key => $val) { $arr[$key] = php_xmlrpc_encode($val, $options); if(!$ko && $key !== $j) { $ko = true; } $j++; } if($ko) { $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcStruct']); } else { $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcArray']); } break; case 'object': if(is_a($php_val, 'xmlrpcval')) { $xmlrpc_val = $php_val; } else if(is_a($php_val, 'DateTime')) { $xmlrpc_val = new xmlrpcval($php_val->format('Ymd\TH:i:s'), $GLOBALS['xmlrpcStruct']); } else { $arr = array(); reset($php_val); while(list($k,$v) = each($php_val)) { $arr[$k] = php_xmlrpc_encode($v, $options); } $xmlrpc_val = new xmlrpcval($arr, $GLOBALS['xmlrpcStruct']); if (in_array('encode_php_objs', $options)) { // let's save original class name into xmlrpcval: // might be useful later on... $xmlrpc_val->_php_class = get_class($php_val); } } break; case 'NULL': if (in_array('extension_api', $options)) { $xmlrpc_val = new xmlrpcval('', $GLOBALS['xmlrpcString']); } else if (in_array('null_extension', $options)) { $xmlrpc_val = new xmlrpcval('', $GLOBALS['xmlrpcNull']); } else { $xmlrpc_val = new xmlrpcval(); } break; case 'resource': if (in_array('extension_api', $options)) { $xmlrpc_val = new xmlrpcval((int)$php_val, $GLOBALS['xmlrpcInt']); } else { $xmlrpc_val = new xmlrpcval(); } // catch "user function", "unknown type" default: // giancarlo pinerolo // it has to return // an empty object in case, not a boolean. $xmlrpc_val = new xmlrpcval(); break; } return $xmlrpc_val; } /** * Convert the xml representation of a method response, method request or single * xmlrpc value into the appropriate object (a.k.a. deserialize) * @param string $xml_val * @param array $options * @return mixed false on error, or an instance of either xmlrpcval, xmlrpcmsg or xmlrpcresp */ function php_xmlrpc_decode_xml($xml_val, $options=array()) { $GLOBALS['_xh'] = array(); $GLOBALS['_xh']['ac'] = ''; $GLOBALS['_xh']['stack'] = array(); $GLOBALS['_xh']['valuestack'] = array(); $GLOBALS['_xh']['params'] = array(); $GLOBALS['_xh']['pt'] = array(); $GLOBALS['_xh']['isf'] = 0; $GLOBALS['_xh']['isf_reason'] = ''; $GLOBALS['_xh']['method'] = false; $GLOBALS['_xh']['rt'] = ''; /// @todo 'guestimate' encoding $parser = xml_parser_create(); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); // What if internal encoding is not in one of the 3 allowed? // we use the broadest one, ie. utf8! if (!in_array($GLOBALS['xmlrpc_internalencoding'], array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'UTF-8'); } else { xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $GLOBALS['xmlrpc_internalencoding']); } xml_set_element_handler($parser, 'xmlrpc_se_any', 'xmlrpc_ee'); xml_set_character_data_handler($parser, 'xmlrpc_cd'); xml_set_default_handler($parser, 'xmlrpc_dh'); if(!xml_parse($parser, $xml_val, 1)) { $errstr = sprintf('XML error: %s at line %d, column %d', xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser), xml_get_current_column_number($parser)); error_log($errstr); xml_parser_free($parser); return false; } xml_parser_free($parser); if ($GLOBALS['_xh']['isf'] > 1) // test that $GLOBALS['_xh']['value'] is an obj, too??? { error_log($GLOBALS['_xh']['isf_reason']); return false; } switch ($GLOBALS['_xh']['rt']) { case 'methodresponse': $v =& $GLOBALS['_xh']['value']; if ($GLOBALS['_xh']['isf'] == 1) { $vc = $v->structmem('faultCode'); $vs = $v->structmem('faultString'); $r = new xmlrpcresp(0, $vc->scalarval(), $vs->scalarval()); } else { $r = new xmlrpcresp($v); } return $r; case 'methodcall': $m = new xmlrpcmsg($GLOBALS['_xh']['method']); for($i=0; $i < count($GLOBALS['_xh']['params']); $i++) { $m->addParam($GLOBALS['_xh']['params'][$i]); } return $m; case 'value': return $GLOBALS['_xh']['value']; default: return false; } } /** * decode a string that is encoded w/ "chunked" transfer encoding * as defined in rfc2068 par. 19.4.6 * code shamelessly stolen from nusoap library by Dietrich Ayala * * @param string $buffer the string to be decoded * @return string */ function decode_chunked($buffer) { // length := 0 $length = 0; $new = ''; // read chunk-size, chunk-extension (if any) and crlf // get the position of the linebreak $chunkend = strpos($buffer,"\r\n") + 2; $temp = substr($buffer,0,$chunkend); $chunk_size = hexdec( trim($temp) ); $chunkstart = $chunkend; while($chunk_size > 0) { $chunkend = strpos($buffer, "\r\n", $chunkstart + $chunk_size); // just in case we got a broken connection if($chunkend == false) { $chunk = substr($buffer,$chunkstart); // append chunk-data to entity-body $new .= $chunk; $length += strlen($chunk); break; } // read chunk-data and crlf $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart); // append chunk-data to entity-body $new .= $chunk; // length := length + chunk-size $length += strlen($chunk); // read chunk-size and crlf $chunkstart = $chunkend + 2; $chunkend = strpos($buffer,"\r\n",$chunkstart)+2; if($chunkend == false) { break; //just in case we got a broken connection } $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart); $chunk_size = hexdec( trim($temp) ); $chunkstart = $chunkend; } return $new; } /** * xml charset encoding guessing helper function. * Tries to determine the charset encoding of an XML chunk received over HTTP. * NB: according to the spec (RFC 3023), if text/xml content-type is received over HTTP without a content-type, * we SHOULD assume it is strictly US-ASCII. But we try to be more tolerant of unconforming (legacy?) clients/servers, * which will be most probably using UTF-8 anyway... * * @param string $httpheaders the http Content-type header * @param string $xmlchunk xml content buffer * @param string $encoding_prefs comma separated list of character encodings to be used as default (when mb extension is enabled) * * @todo explore usage of mb_http_input(): does it detect http headers + post data? if so, use it instead of hand-detection!!! */ function guess_encoding($httpheader='', $xmlchunk='', $encoding_prefs=null) { // discussion: see http://www.yale.edu/pclt/encoding/ // 1 - test if encoding is specified in HTTP HEADERS //Details: // LWS: (\13\10)?( |\t)+ // token: (any char but excluded stuff)+ // quoted string: " (any char but double quotes and cointrol chars)* " // header: Content-type = ...; charset=value(; ...)* // where value is of type token, no LWS allowed between 'charset' and value // Note: we do not check for invalid chars in VALUE: // this had better be done using pure ereg as below // Note 2: we might be removing whitespace/tabs that ought to be left in if // the received charset is a quoted string. But nobody uses such charset names... /// @todo this test will pass if ANY header has charset specification, not only Content-Type. Fix it? $matches = array(); if(preg_match('/;\s*charset\s*=([^;]+)/i', $httpheader, $matches)) { return strtoupper(trim($matches[1], " \t\"")); } // 2 - scan the first bytes of the data for a UTF-16 (or other) BOM pattern // (source: http://www.w3.org/TR/2000/REC-xml-20001006) // NOTE: actually, according to the spec, even if we find the BOM and determine // an encoding, we should check if there is an encoding specified // in the xml declaration, and verify if they match. /// @todo implement check as described above? /// @todo implement check for first bytes of string even without a BOM? (It sure looks harder than for cases WITH a BOM) if(preg_match('/^(\x00\x00\xFE\xFF|\xFF\xFE\x00\x00|\x00\x00\xFF\xFE|\xFE\xFF\x00\x00)/', $xmlchunk)) { return 'UCS-4'; } elseif(preg_match('/^(\xFE\xFF|\xFF\xFE)/', $xmlchunk)) { return 'UTF-16'; } elseif(preg_match('/^(\xEF\xBB\xBF)/', $xmlchunk)) { return 'UTF-8'; } // 3 - test if encoding is specified in the xml declaration // Details: // SPACE: (#x20 | #x9 | #xD | #xA)+ === [ \x9\xD\xA]+ // EQ: SPACE?=SPACE? === [ \x9\xD\xA]*=[ \x9\xD\xA]* if (preg_match('/^<\?xml\s+version\s*=\s*'. "((?:\"[a-zA-Z0-9_.:-]+\")|(?:'[a-zA-Z0-9_.:-]+'))". '\s+encoding\s*=\s*' . "((?:\"[A-Za-z][A-Za-z0-9._-]*\")|(?:'[A-Za-z][A-Za-z0-9._-]*'))/", $xmlchunk, $matches)) { return strtoupper(substr($matches[2], 1, -1)); } // 4 - if mbstring is available, let it do the guesswork // NB: we favour finding an encoding that is compatible with what we can process if(extension_loaded('mbstring')) { if($encoding_prefs) { $enc = mb_detect_encoding($xmlchunk, $encoding_prefs); } else { $enc = mb_detect_encoding($xmlchunk); } // NB: mb_detect likes to call it ascii, xml parser likes to call it US_ASCII... // IANA also likes better US-ASCII, so go with it if($enc == 'ASCII') { $enc = 'US-'.$enc; } return $enc; } else { // no encoding specified: as per HTTP1.1 assume it is iso-8859-1? // Both RFC 2616 (HTTP 1.1) and 1945 (HTTP 1.0) clearly state that for text/xxx content types // this should be the standard. And we should be getting text/xml as request and response. // BUT we have to be backward compatible with the lib, which always used UTF-8 as default... return $GLOBALS['xmlrpc_defencoding']; } } /** * Checks if a given charset encoding is present in a list of encodings or * if it is a valid subset of any encoding in the list * @param string $encoding charset to be tested * @param mixed $validlist comma separated list of valid charsets (or array of charsets) */ function is_valid_charset($encoding, $validlist) { $charset_supersets = array( 'US-ASCII' => array ('ISO-8859-1', 'ISO-8859-2', 'ISO-8859-3', 'ISO-8859-4', 'ISO-8859-5', 'ISO-8859-6', 'ISO-8859-7', 'ISO-8859-8', 'ISO-8859-9', 'ISO-8859-10', 'ISO-8859-11', 'ISO-8859-12', 'ISO-8859-13', 'ISO-8859-14', 'ISO-8859-15', 'UTF-8', 'EUC-JP', 'EUC-', 'EUC-KR', 'EUC-CN') ); if (is_string($validlist)) $validlist = explode(',', $validlist); if (@in_array(strtoupper($encoding), $validlist)) return true; else { if (array_key_exists($encoding, $charset_supersets)) foreach ($validlist as $allowed) if (in_array($allowed, $charset_supersets[$encoding])) return true; return false; } } ?>ltsp-cluster-control-2.0.3/Adminng/includes/xmlrpc/SOURCE0000664000175000017500000000031712026403127023452 0ustar stgraberstgraberDownloaded from: http://phpxmlrpc.sourceforge.net License: BSD (http://phpxmlrpc.sourceforge.net/license.txt) Preparation: - Unzip - Get the content of lib/ - Move it to the parent - Remove everything else ltsp-cluster-control-2.0.3/Adminng/includes/jquery/0000775000175000017500000000000012026403130022532 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/includes/jquery/jquery.js0000777000175000017500000000000012026403127027506 2jquery-1.3.2.min.jsustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/includes/jquery/jquery-1.3.2.min.js0000664000175000017500000015764612026403127025661 0ustar stgraberstgraber/* * jQuery JavaScript Library v1.3.2 * http://jquery.com/ * * Copyright (c) 2009 John Resig * Dual licensed under the MIT and GPL licenses. * http://docs.jquery.com/License * * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) * Revision: 6246 */ (function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
","
"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); /* * Sizzle CSS Selector Engine - v0.9.3 * Copyright 2009, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();ltsp-cluster-control-2.0.3/Adminng/includes/jquery/SOURCE0000664000175000017500000000023012026403127023456 0ustar stgraberstgraberDownloaded from: http://jquery.com License: Dual licensed under the MIT and GPL licenses. Preparation: - Unzip - Link jquery.js to jquery-1.3.2.min.js ltsp-cluster-control-2.0.3/Adminng/includes/function.js0000664000175000017500000000177212026403127023413 0ustar stgraberstgraberfunction filterTable(term, name) { tables = document.getElementsByTagName('table'); for (var t = 0; t < tables.length; t++) { element = tables[t]; if ((element.attributes['class'] && element.attributes['class'].value == name) || (element.attributes['id'] && element.attributes['id'].value == name)) { var terms = term.value.toLowerCase() for (var r = 1; r < element.rows.length; r++) { var display = ''; if (element.rows[r].innerHTML.replace(/<[^>]+>/g, "").toLowerCase().indexOf(terms) < 0) { display = 'none'; } if (element.rows[r].attributes['class'] && element.rows[r].attributes['class'].value == 'toggle_detail') { display = 'none'; } element.rows[r].style.display = display; } } } } function hideWarning() { jswarning = document.getElementById("jswarning"); jswarning.style.display = 'none'; } ltsp-cluster-control-2.0.3/Adminng/includes/menu.php0000664000175000017500000000356512026403127022707 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2008, Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ $menu = array(); function menuAddCategory($name, $weight) { global $menu; $category = array( "name" => _($name), "weight" => $weight, "items" => array() ); array_push($menu,$category); } function menuAddItem($categoryName, $title, $link) { global $menu, $current_page; if ($current_page == $link) { $current=1; } else { $current=0; } $item = array( "title" => _($title), "link" => "/$link", "current" => $current ); for ($i=0; $i < count($menu); $i++) { if ($menu[$i]['name'] == $categoryName) { array_push($menu[$i]['items'],$item); break; } } } ?> ltsp-cluster-control-2.0.3/Adminng/includes/jquery-ui/0000775000175000017500000000000012026403130023145 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Adminng/includes/jquery-ui/jquery-ui-1.7.2.custom.min.js0000664000175000017500000057016412026403127030216 0ustar stgraberstgraber/* * jQuery UI 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI */ 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;m0){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);;/* * jQuery UI Draggable 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Draggables * * Depends: * ui.core.js */ (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.leftthis.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.topthis.containment[3])?g:(!(g-this.offset.click.topthis.containment[2])?f:(!(f-this.offset.click.left
').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=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=p&&n<=k)||(m>=p&&m<=k)||(nk))&&((e>=g&&e<=c)||(d>=g&&d<=c)||(ec));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').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');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.maxWidthk.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');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,t){var s=(q[t]||0)+(j[t]||0);if(s&&s>=0){o[t]=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);;/* * jQuery UI Selectable 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Selectables * * Depends: * ui.core.js */ (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.rightg||j.bottomd&&j.righth&&j.bottom=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=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)f&&(e+h)m[this.floating?"width":"height"])){return g}else{return(f0?"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=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=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)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.topthis.containment[3])?g:(!(g-this.offset.click.topthis.containment[2])?f:(!(f-this.offset.click.left=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 *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000}})})(jQuery);;/* * jQuery UI Accordion 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Accordion * * Depends: * ui.core.js */ (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("").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);;/* * jQuery UI Dialog 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Dialog * * Depends: * ui.core.js * ui.draggable.js * ui.resizable.js */ (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("
")).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("
")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(k),i=c('').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("")).addClass("ui-icon ui-icon-closethick").text(m.closeText).appendTo(i),d=c("").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("
").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('').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("
").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
");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("
")}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('
').appendTo(this.element).addClass("ui-slider-handle")}if(c.values&&c.values.length){while(a(".ui-slider-handle",this.element).length').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&&d1){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(bthis._valueMax()){b=this._valueMax()}return b},_values:function(b){if(arguments.length){var c=this.options.values[b];if(cthis._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);;/* * jQuery UI Tabs 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Tabs * * Depends: * ui.core.js */ (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=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:"
",spinner:"Loading…",tabTemplate:'
  • #{label}
  • '}});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')}$.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:$('
    '))}},_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=$(''+appendText+"");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")?$("").addClass(this._triggerClass).attr({src:buttonImage,alt:buttonText,title:buttonText}):$('').addClass(this._triggerClass).html(buttonImage==""?buttonText:$("").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=$('');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-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&&checkDatenew Date(checkDate.getFullYear(),12-1,28)){firstDay=new Date(checkDate.getFullYear()+1,1-1,4).getDay()||7;if(firstDay>4&&(checkDate.getDay()||7)0&&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;j0&&iValue-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=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;iFormatmaxDate?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&&maxDrawmaxDraw){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)?''+prevText+"":(hideIfNoPrevNext?"":''+prevText+""));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)?''+nextText+"":(hideIfNoPrevNext?"":''+nextText+""));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?'":"");var buttonPanel=(showButtonPanel)?'
    '+(isRTL?controls:"")+(this._isInRange(inst,gotoDate)?'":"")+(isRTL?"":controls)+"
    ":"";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'+(/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)+'';var thead="";for(var dow=0;dow<7;dow++){var day=(dow+firstDay)%7;thead+="=5?' class="ui-datepicker-week-end"':"")+'>'+dayNamesMin[day]+""}calender+=thead+"";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";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&&printDatemaxDate);tbody+='";printDate.setDate(printDate.getDate()+1);printDate=this._daylightSavingAdjust(printDate)}calender+=tbody+""}drawMonth++;if(drawMonth>11){drawMonth=0;drawYear++}calender+="
    =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?''+printDate.getDate()+"":'=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" ui-state-active":"")+'" href="#">'+printDate.getDate()+""))+"
    "+(isMultiMonth?""+((numMonths[0]>0&&col==numMonths[1]-1)?'
    ':""):"");group+=calender}html+=group}html+=buttonPanel+($.browser.msie&&parseInt($.browser.version,10)<7&&!inst.inline?'':"");inst._keyEvent=false;return html},_generateMonthYearHeader:function(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,secondary,monthNames,monthNamesShort){minDate=(inst.rangeStart&&minDate&&selectedDate "}else{var inMinYear=(minDate&&minDate.getFullYear()==drawYear);var inMaxYear=(maxDate&&maxDate.getFullYear()==drawYear);monthHtml+='"}if(!showMonthAfterYear){html+=monthHtml+((secondary||changeMonth||changeYear)&&(!(changeMonth&&changeYear))?" ":"")}if(secondary||!changeYear){html+=''+drawYear+""}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+='"}if(showMonthAfterYear){html+=(secondary||changeMonth||changeYear?" ":"")+monthHtml}html+="";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&&datemaxDate?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=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);;/* * jQuery UI Progressbar 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Progressbar * * Depends: * ui.core.js */ (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('
    ').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(bthis._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);;/* * jQuery UI Effects 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Effects/ */ jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(var f=0;f');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").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);;/* * jQuery UI Effects Fold 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Effects/Fold * * Depends: * effects.core.js */ (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);;/* * jQuery UI Effects Highlight 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Effects/Highlight * * Depends: * effects.core.js */ (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);;/* * jQuery UI Effects Pulsate 1.7.2 * * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * http://docs.jquery.com/UI/Effects/Pulsate * * Depends: * effects.core.js */ (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').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);;ltsp-cluster-control-2.0.3/Adminng/includes/jquery-ui/SOURCE0000664000175000017500000000031012026403127024070 0ustar stgraberstgraberSource: http://jqueryui.com/download License: Dual licensed under the MIT and GPL licenses. Preparation: - Unzip - Get jquery-ui* from js/ - Move it to the parent repository - Remove everything else ltsp-cluster-control-2.0.3/Adminng/COPYING0000664000175000017500000004310312026403127020447 0ustar stgraberstgraber GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. ltsp-cluster-control-2.0.3/Adminng/index.php0000664000175000017500000000652212026403127021240 0ustar stgraberstgraber, Revolution Linux Inc. * Author: Stéphane Graber * 2008, Stéphane Graber * 2009, Stéphane Graber * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, you can find it on the World Wide * Web at http://www.gnu.org/copyleft/gpl.html, or write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ # Set the document's charset header('Content-type: text/html; charset=utf-8'); # Try to guess the user's langauge FIXME: This shouldn't contain hardcoded locales $languages=split(",",$_SERVER['HTTP_ACCEPT_LANGUAGE']); $locale="en_US.UTF-8"; foreach ($languages as $language) { if (ereg("^fr",$language)) { $locale="fr_CA.UTF-8"; break; } if (ereg("^en",$language)) { $locale="en_US.UTF-8"; break; } } # Setup gettext setlocale(LC_ALL, $locale); bindtextdomain("ltsp-cluster-control","./po/"); bind_textdomain_codeset("ltsp-cluster-control","utf-8"); textdomain("ltsp-cluster-control"); require_once("config.php"); # Set the URL prefix based on current URL and rewriting settings if ($config['url_rewriting'] == "1") { ereg("(.*)/index.*",$_SERVER["SCRIPT_NAME"],$url); $url_prefix=$url[1]."/"; } else { $url_prefix=$_SERVER["SCRIPT_NAME"]."?page="; } # Load the base functions include "includes/menu.php"; include "themes/engine.php"; # Check and parse the query (GET) if ($_GET['q']) { $current_page=$_GET['q']; } else { $current_page=Null; } # Add stock categories menuAddCategory(_("Administration"),1); menuAddCategory(_("Monitoring"),0); # Load the modules FIXME: This needs to be automatic include "modules/appservers.page.php"; include "modules/frontpage.page.php"; include "modules/users.page.php"; # Build the page $page = array(); $page['title'] = _("LTSP-Cluster Control Center"); if ($current_page) { $page['parameters'] = split("/",$current_page); $page['function'] = $page['parameters'][0]."_main"; if (count($page['parameters'] > 1)) { $page['arguments']=array_slice($page['parameters'],1); } else { $page['arguments']=array(); } $page['content'] = call_user_func($page['function'],$page['arguments']); } else { #FIXME: That should be configurable header("Location: /frontpage"); } $page['footer'] = "Copyright © 2008-2009 Revolution Linux Inc."; # Show the result to the user print renderPage($page,$menu); ?> ltsp-cluster-control-2.0.3/Admin/0000775000175000017500000000000012026403130017060 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/css/0000775000175000017500000000000012026403130017650 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/css/style.css0000664000175000017500000000556112026403127021537 0ustar stgraberstgraberTH { font-weight: bolder; text-align: center; } CAPTION { text-align: center; } BODY { line-height: 1.33em; background-image: url( "../images/top-degrade.png"); background-repeat: repeat-x; } H1 { margin: 0; font: 20px Geneva, Arial, Helvetica, sans-serif; text-align: justify; background-color: rgb(96, 132, 188); padding: 10px 20px; border: 1px solid rgb(96, 132, 188); border-top: none; z-index: 2; text-align: center; } H1 IMG { float: right; position: relative; top: -30px; right: 10px; } H2 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; color: #000000; font-weight: bold; } H3 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #000000; font-weight: bold; font-style: italic; } P, BLOCKQUOTE, UL, FIELDSET, FORM, OL, DL, DIR, Table, INPUT { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: #000000; } B, STRONG { font-weight: bolder; } BLOCKQUOTE { margin-left: 40px; margin-right: 40px; } I, CITE, EM, VAR, ADDRESS { font-style: italic; } PRE, TT, CODE, KBD, SAMP { font-family: monospace; } PRE { white-space: pre; } SUB { vertical-align: sub; } SUP { vertical-align: super; } S, STRIKE, DEL { text-decoration: line-through; } OL { list-style-type: decimal; } OL OL, OL UL, UL OL, UL UL { margin-top: 0; margin-bottom: 0; } A IMG { border: 0 } a{ text-decoration : none; } a:link{ color: #002bb8; } a:visited{ color: #5a3696; } a:hover, a:active{ color: #faa700; } hr{ height: 1px; color: #aaa; background-color: #aaa; border: 0; margin: .2em 0 .2em 0; } #logo { height: 40px; border: 0; margin-bottom: 2em; } #menu_info { float: right; width : 275px; } #menu_info > div { float : left; } #user_name, #user_title { font-weight: bold; } a#deconn { color: #ba0000; margin-right: 0; display: block; float : right; } a#deconn img { border: 0; padding: 0; margin : 0; height: 30px; } #menu_list { color: #000; border-bottom: 1px solid rgb(96, 132, 188); margin: 0; padding: 0; z-index: 1; font: bold 13px Verdana, Arial, Helvetica, sans-serif; } #menu_list li { display: inline; list-style-type: none; } #menu_list a { color: rgb(96, 132, 188); background-color: rgb(238, 232, 170); margin: 0; margin-right: 2px; border: 1px solid rgb(96, 132, 188); padding: 2px 6px 0px; text-decoration: none; height: 15px; -moz-border-radius-topright: 2em; -moz-border-radius-topleft: 2em; white-space: nowrap; } #menu_list a:hover { color: rgb(207, 218, 235); background-color: rgb(255, 255, 240); } #menu_list a#chosen, #menu_list a:active { background-color: rgb(96, 132, 188); color: rgb(207, 218, 235); border-bottom: 2px solid rgb(96, 132, 188); } #menu_list a#chosen:hover, #menu_list a:active { color: #FFF; } #menu_list a img { border: 0; padding: 0; margin : -1px 1px -1px -7px; height: 25px; } div.content { background-color: rgb(207, 218, 235); padding: 10px; border: 1px solid rgb(96, 132, 188); } p.error{ color: red; font-size: smaller; }ltsp-cluster-control-2.0.3/Admin/admin.php0000664000175000017500000000173212026403127020672 0ustar stgraberstgraber\n"; print ""; ?> ltsp-cluster-control-2.0.3/Admin/images/0000775000175000017500000000000012026403130020325 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/images/managelist_module.png0000664000175000017500000001706612026403127024544 0ustar stgraberstgraber‰PNG  IHDR€€Ã>aËbKGDùC» pHYsHHFÉk>¨IDATxÚíw|TeÖÇ¿wfR&½’B 5”PBS¡+T\Œk﫲êÚ²³âÚPWÊ«îêË* ¢ ½(AN$$„ô:-3sß?nf2ÉÌ„ L’ßçsÃðì°ÞLwsA¯îA,yù&ü¼Ý~¬©ò÷`éË7sÏ‹ßqøTž¹XÖÅŸÇÄØñ£9Æâè©L ‹ÊíÖÛ mczãçí~É ·7¸ºÈÔ;ÄšD÷ÁK)okñZ…Þ‘!M'€§»k‡iù áíi;Êö÷ÄÃÝYF~öàé°Îîä¶£Àr7ç¶.rÇvÎÕ«7…€§»sÀUáxÓi.qß …Ìé»EsÐüß-…]ÈÀUî¤Só=Í €^¯wzçGKaÏmZXZũ̋m-Z«PT^å°Î†:Žòòr:"ÔjMYnA©m-Z«Wà8žÁ†¹Öœ¿hKü³ç‹ òólÁÕ®dœ/vXgC€Y¥ü°+ø¡]ÚZ£åN³õ›—”©9r:W…sÎt5Ê+4ëmPS#²jG©™eDtq',й\ ÍEqE YùŽgUQ­5ÚÔ›D‘ ËAp*¯˜@“d¶; ÔêM<]Á´r« µO–?@´üq4Qf…£o‡…臧»N³%¶Ðêô—q!¯Ðá9¡AÞLÓ‹ §á\,®b˾ Š›1 ˆ‹íÃŒ„‘ÈœÕÖLˆ"lýõ{œÄØ €ÂÝMÁÛÏMåºØîm-f‹0~dOžXøúƒÝzD†3ç¦1DùfÜ29ŽÂârÒ2rê•ì˜ÁáN»8vc\OúGs¤—Ó „uñÃËÉ×¾[ŠðP_Äö uZå›1¤oXÓ  tuÁ£ƒÀSi;ãñörþY·§«Ã:(‚Ó;?Z {#"ÑùcÉosË.rO'÷·®òŽG|[ :l`ÏmÚ¼£Í²&“ ƒ¡†Ž“ði£ÉHMs?SÂÂ-(«Ôpê¬s{¿ZŠâ²j›2½NçôÎ1®›C K+I=ëÜþï–"¯ÐÖ˜_Táôîñ¢’f¸ƒó *I=[ÐŽã|~]KDAD€“g{w°(±ôZ/§ˆM_`C€Š*-)‡ÏáÛÁöTTk©¶ÚD)B±dæV²ãÀ9†÷ñkk[„}'J8wQêÚĬ†õv}j­µV_ë÷Ûµ7°ÎÔ‰õ잘Â$£Qdù–þH+ÅÇS!5)'Ay•ÔsU– ¢&ø½á9¼Bý¿íXÿ ï¹âv¦‘Uƒäwn¤ûù|ݰÐ.¼”®ÄŠbXLWúD!´ãõ‘¬œ2þHÍeû¾ J¬"gAV#Êd7 &ÓZ ª­ål%2[|Øf>kCWW9/=4žÙ“;Fª€¸˜nÌž<€c¢yþýM”Wj-ug7<{,üŽ÷ºWÆšL²þÈœ«/DL¢ÈI½|OÎwÏÚ ³!ÀÈáFùֈŠÃ"Y¿+­^yíƒÛ\{´;غƒƒ½~é³¥ñik®:lzw…¬wø—€¼Þ»íÖ0œßùÑrt¼û¶Cç÷·ñ®;žÍëD=ØX£ÁˆV«mɵœƒ¡õq2Øî êÀ»ƒuäÔm¯°!@i¥ºÃ ¤¬ªõq2Øà̹R.äá¥tikÙ®*j &R³Š[!'ƒm<@‘†÷–Ÿà®‰] è.áòª¾ÞrŒœN À™œjÞûæ,Á~®x*åíÚ¨Ö™(,ÓQ©6¶þbN‡Yª´Fd•&ô¦öݨµ†«|p@€Ýü¹{ú`fÆ÷'ÐÏ£­e¼¢¨¨Ö±ñ×Ó|õÓaN-lý 6ò÷àíg¦0´¿ô¾ˆö¾*èíáÊSrýÐæ¿´šsyem-ÒU…ÍJà°þ]-ÊïHèÚŇуs xk`c|=Ú}«w„ çNÕtf ­çm-ÀUG§3¨ƒ£Ótðûî´vòÖP]]Ý’k9=œ}pK`7Y´³o†l)´î`((©ì°îàüâŽwß6HË.åPj.ÑݼÚZ¶«Š¢2-ÇεþBN; "jøøûÓŒ `xßf'Œ*ÑêI/©æL©täUé0‰bm°©uìáF´ŸÑ~žDû{ÐÝ[‰\Ö6>G­ÞÄÑŒ ¶*åbIÇ …³; ,(ÓóÝÎ|Öï+ÀÃýÒ¯ªÁD‘BG\‹Vfºäù«õ/¬KZ ˆ`t%ÄèŽ÷Uö>jõF*ÕF§}/`káP»~Jº‡ùI¯Žu€½†c•…diÊ1µbM X¡§X¡'ÀÅþ^ADyø¡¸ »R«ÔzÎå•RTª¾â¿u-ÂÎ;ƒ`tl8l"½"í~I­«Aµn'_n:f“[7ÐKÉu½º×£+Ã{tePxÜ d‚€LIË/æð¹|eçq0;Ãçò-ß/©Ñ²§4‡4C KçMgÎÈWü!äUòÚÒmlOÉèp)r€è©‹†‡¢º°â9øûØQòæã<úÕz²ŠÊê•ïÉ£ñ#¸mX?\šùr…“ ùd×¾Üs„rMý©Øì¸–Ý3 ï+— ¯1r÷ ßr4ÍBÆÛ26.X{Eô€í«c£»8Tþû›öò×o·Ô+»}xÞ¸}}ÂZ,DL·`>¼{oÍNàÛßOðæúݜΗ4W8É®´,>š?ƒÛ†õ¿bÂÕENlß0ktØt²^JWKrDëã•5Ûë)?ÌÏ‹5OÌeÕãsZ¥|k(]]¸÷ú!V=‚©c,³ÂJ5³—}Ǽ¯¡R£³+ßå8¼=\[wN»£¬†æéåysýnKý-Cû’úÆÜ:ìʼRÝM!ç­Ù üòB"}CëÆ!+SŽ3zá§œÊ+º"舸ä0ûß»²l{]n¡ù×Ųêñ9ø(/mQ1™ê2*ªû_¹Ÿ§&Ž´œs*¿˜Ñ ?ãû?Nµõ³khÔ|è\>Ϭ¬KŒñh|Kï™~EFÊu- Žn oÏžÈè¨n<üÕz*µzªtzæ|´Šç¦Œfámñ—m_ÿ%­@bR pÙ9‚%Wå@:¤ÿ#YÕ¤lŸ_[®Ñr×'«Ñ¤é±}"XœË†‰I¡@0©öß®—ýæ/|áµÇàm“6¯‘¬:ÔØ¾:ö¡¯7r¶° æöËžuÙ3h8R¶¤Û²^]üÙ¾`O­ØÌw¥.`gZ6#_ÿŒÏçOcXDH«äÑëõˆˆT*k(öÖ}D4å{n 9ÁÞž{{´Éû +Õd•a¬#°¸ ˜FbÒRàU’UvóÅÚ@«Ó±ód:k¤[ʾxà6ºù_Þü9µvGEW>?ƒ¸È0^^» ƒÉDny3–­âþÑ1<9.¥Ë¥—¯í!½¸ˆ jt.&h |?¥;bz߯¾tññ´(ÝGÙö[èj FNå±rÿq¾Üs„œÒ 9ð4@bÒd’U¹ ¿g³4´OY>ÕÈ‘ºéÖºT£cÉž“|"»^ù¸>‘LͤQ ïѵž¬ÔèÈ/¯¢¤ZC©ZCI•†Rµ–’j j]$ãFoOâzveXd^îuƒòƒ‘·ìãëvQ©µ¼;H YuÖúfôNÔx˜8ç#=Pwéo=EWïË&tsZ»¤h{ ¶\¤ ¢šgVmcã‰Ìz¿3:<§Gõ&Ì»ñ1™ÁdâÉ ‡H-ª‹ˆíÂÒ{¦sCŸH‹Ì§òŠØ›~ž½9ìËÈáDnÁ5“5V _h#zvã‘ø8Æô’ö7d•2yÑWœ¹Xb>5fݘ  *ež¿µ›4ð{vÊÍÜlj F›å`óËkíR¹íÚDÃký|â,/ýð ¬öøËþ^ ôa`€7nrÛþyeÚö—’™ýöx0¹LF™ZÃâ-),ÞšBq•uQˆ ¢g?~nø{¸ãçᎯÒ?7<]¯ŽGóbE5¿gåq +—´Z% <9qÿœ=O7W *ª˜¼è+Žœ·L ¾&Yõ§z¨%Á‚x_V—*@.È}ÿ9‚}š6ºÖÕø`ó>Þݸ‡J­žÑQáLŤÑÄõ“A6}~Óͽ qÌÙ̬ʪuzÞݺŸÿì9jã¤DPê¸ÖÈ›ä&ÁþZD(]ì}åb#B)®Róþ¦½,ÙšB¥VÒEÁ¸ÞÝÑ#Œ¸È0†vÁÛýÚZ5¬Ðêøéh:¯ýø+%ÕZ"}ùwâÍLØ‹ì¢2†¼ö1eK¼Ã’Uß5$@@…R¤ÐW߯Ûž¿·I?¾öS<÷Í&2kg á£tãÆ¾‘$ôbbLOzuñ·%Csï€õ¾Sÿ{'ò‹øÇ†½ì9{¡ÉfzîȬ|ô.”VpÃ?ÿKVQî 9÷ŽÈã‡|…Q— ÅÕ^ûi«`Õãs˜êßOpÇÿ}g>í$0dUƒÜ·÷&}À<€îšÂÓ“F7úcÇs øËŠlOͤ9ˆðaÁ”1<0vh”-õùF£‘/ögåTþyËX†„‡8$€¹<¿B͆gÙp"“ýÙùË^˜~=oÝ1‰ßúœ]iÙÌГ¿OC'Q|ClMËæÁ[ñõpãøëÑÕ߇„w¾`[®f‘¬ZS¾$iþ8®O¤Ã‹—Tixmí>ÞqSý&– ¼üŒGZÆvýÁëë~ᾆòúíøû÷;˜Ö¿'^î.µ µµÖ°7€t4>0šLhuíc€*as–oeÉÖý<;õ:¦ îÍÒmûÜñ pZsW^E ?2 JxnåfÖNkxícÀ_HVmo–Dɪj“^¾xwã>îŒëO°—‡EI/ÿ°‹­§²ùþÉ;™Û‡WÖlçƒÍ{¹¾wïÎĹârB|½ø`Ç^™2Ú±²±î"lŽkLFS»I–¢TÐÓß‹Œâ2 +ª™4 ÊL€1 I-NæòÉÎ|°yŸÅ!T‹bà5à’U-M®ó5ð80ªR§ç?ífñÜIÝΚC§‰å {xãÇ_ˆëѕËÝŸ¬fóñ ¾yt6ó>YÃ]ÃúÑ3ÈǸ˜£ÉÔ®v õ ð&£¤Šý™ˆî`]ÖYæ·.Y‰ÁX/ÄÛ|$‘¬*m•DÉ*‘Ĥ§½€ð¿ý'øóuƒÜ-Q„YÃúòßߎòü7›9|þ"ƒ»‡°þÙy<øùl>žÁƒã‡3gä@V¦Gµq/Ÿß=Ù±²í¬\*Äd4¢Ñ´ í+Íd~ϼÀ˜èpëªÐ†8bþÐ@ù[ÌýÉË&U²*…Ĥÿ÷ˆ"üíûüôøl‹’^Ÿ9–iK¾ãççîa\ßHîÿl?:Å=cóîÜIÜýñjâû÷à¯ßla[Z6ñ}º7Ú Ø›-àp `D«Õ4ãf®m„Õnî9žS@€—2A0ÏÞà;à¤HkÇÏ‘¬Zw…d{¸ ðLÉÊãûC§¹%VšÆv fÎð~¼²z;÷ÊŠ”cÌŽ‹á£ù3˜ñ¯åü’–ÍØ¾<7õ:nþëz„á¢ÛoíØ'€£1€ÑhB­n? «Dš˜õ ¤B£µžº—Õ'@²ª˜Ä¤['€À’U—"œ˜$ ½‰+ xX Ú°‡Iý#qW(E‘¿MÉØ÷WRªÖòÖ <1q$³–~Ë/iÙ<=i4Æ`_Fo®ßÍÎôúF86÷ˆ¶ã“#Q«ÛÏF‘SÅ’ïgdT7òËëeC½hë8OVm6]1i“FK‘ÀA`:ðÐãBYËvâÙ q–¹û“ㇰxK gÞ~Šû>ûMÇÓyèÆá,œ5çVnbñ–nØ“Q! L}àhh0¢V·Ÿ. £B²f£¢ÂëmÂÁ.®“‚‘ZûŸ©óA ^þŠÔý°l×!æëK˜'¢(òçÑYq ÕÚìHÍdþõ±$ÄDÑïÅ%x¸ÈùbÞ$Fš•oj\Ù §‹5&ò´Âý}óófÑÆß¬«^ùÍw‰I “žBZü¹ÛWt>4ÖØ ©1ðÆÆ}¥¹Èe¼2e‹·ìgù#³¸X^Eâ§k¹{Xo~xà¦:åÛ=LÔµˆ¢È79˜€»FI¯Ür"Ã\m¶^Y$&݈iô!àg.ž7fSF›ÿ+Gš^>ÒÛ­×Mç÷ì|K«žÐ§;£{„1yÑWˆ†6><“‡Æ B!“I[ÏØ-79 €OmTMIMûȼ»XCZU C#Byýö ÌÊåXN¹ú7’UåW¦ HLê,BŠPµÀis}ïΗóò2Ôú€ÑHÝÁ§HN ’6üƺgÒ\~ñ¬ñd—T0 4À¦_w4ÂoØ hk äWi(Óè(Së8”[?!DW†tåðù|~Ì«bjˆ'.m”· µÈÑÔ°>_§› +›‹‚7~üÅú”/¡‘íá-Bb’°©_·øQý=ÝYxÛ¾1YíôåÕ™ãøÛªmæÓÞ®æ¾Çr‹Xuø ³b{!^n.õ•ß„)žÉdâTA{³/²7;ŸC¹ÅÔíç/0Ž¿~øvƽù9»Š4üQ¦cb°£ÜQ8  &‘m…jvª1ˆðÙŸfÐ'4ˆí'ϲ¶n3M&µ¸|w•˜t3Ò‚Ŷ <8nª[ÆhYës˜WÑÀ¨7>'5ÏÒ?C Vx ÈSÉö'nÇÃEag¥¯ñÖ¾õLí=Á™¢¦%¼òSºsøäÇ™üb^û~ßü~Q_…Œ¾®Dz¸éáB ëÕýn NWêY[I±Þ„Òwî˜ÄÃñqW©‰}õ#.”YB Yõ\$&õFêã§YêÙ÷ç&‚u\ÔÿwOÆyf,±DªˆÀÀ€>_7ñÚL€Ý™y|¸û(§ ÊìIkŽ…@ ’_cR÷CÏ ?Ï›ÆMC¤ð…Sy…,\÷ +RŽ×‹{ð’ DÔA)ðËPÊ…ÚC†ëU±"Ez¹¹Z4* ’u›ÃâyÓóóF­Ó3óÃÖq›€i$«ÄÖ 1É xiðf ëâíêæ±Ì«ÛÊ]?’,ñµeO}»oZÌÓàU`€«\Ɔ‡fÒÝÏ»Qs¯Ö×ðΎì>v¶¡¤EÀ7H/Þa³A"1É8@-áf î͇ó¦Y'%Ujöfäð[úy~;sž”Ì4úk+ZÀU!'¶{¯Þ<ž›‡J.Sk˜ñÁr~K?o>-ˆ%Ye ¶Œ‰IwïbµUJ!“ñà ƒY0/7—z¦Þ:ÞÏ\f]WR¥eüâo­“C<L¦$ôéÎÒÛÇ;ìóOäó†²Këé¶i ºÄ*HÅÑýD#ÍD&™‹ÜræŽȤQLŒ‰"̯.4Þ`4râB!Õm¶/@@ <À‡!¡Äv¡_X «¨ç¥ñôòŸÉ¬KäQŒÔò¯æ+?¨-:6º¯ßt=ÑÁ~uý0HJ2‡yY‡{Yê@4™X}4ƒw¶ Dm!ÀàOH1 €Ïïœ(­ö5èï¿;’Î?·ÿ¡þ²îbàGÛ¡¹·ÙÀû€Í‹t fbL 1QÄt &ÐK‰ŸG[ìuŒ –ÕRIÞ}˜_N×Ûär˜L²Ê&¨£yHLòʬ¿7¹_$‹gÇE.¯·ÂÖPÑ–[K„ Ž­i9|}0ÔïòK$«Þ$1é_H[›èäËê{§Zò ŒFÞÝy„å‡ÎX¯¸dÕ†?ÅÄ$¤®íI Ñd‰ ™Œ@/%A^zy襼ê{M¢H~yçŠË¹PZ‰Ád3ËùxÄÞ¶0h™ø¤Èa3Ürb»2¢{ÃÃPº#“ (drA@!“Q®Ñ‘^\ΙÂrR JI9_`oJ– ¼`ŽY'1É8ƒ´õšW†37¶åZ ~Ü˾sõv@ïîlê¶è&ܧ+Òú„9–q$—{Ú|e‘Šª×hché`:ÒTír¥)ÞÛx“þÀ×Ý•¥·Žåå)œ«ÿ–ϧHV]¹lÏÒ`qp=öóø·øy^”çÀ7$«þhÊ—Z3 P ­ÚÍâ–t›#° X¬!Ye?Qob’i9yZR Ê²Ëø [ú<ä@ V `W & €dU‹.cëZÇ`à†d.­=’Y:†4ßG²ªiÉy“& ‘Å%ÀÍJíD=8Çú&@bÒ¤è!ˆ4“dUz+®Ø œkPsRØz%ð–Ã.£èD':ÑDü?‘e/S»l"zTXtSoftwarexÚ+//×ËÌË.NN,HÕË/J6ØXSÊ\IEND®B`‚ltsp-cluster-control-2.0.3/Admin/images/logs_module.gif0000664000175000017500000000162612026403127023340 0ustar stgraberstgraberGIF89a ÷›ÍüÅâþv™¶]w•«Ôû¤Ñû´Ùüüýþ¾ÞýZp‰HZqòõùÈäþ±×üa|›§ÂºÜýÀßý–¼ÓŸÄØ·Úüâêô¯Ðâæï÷¨ËÝŒ²Ë°Òãg‡§Se{ìñ÷ÿÿÿÿÿÿ, {=x°€AB†Ø p`C\¨Pa€ 0 B*,p0!ãÆ( h°`€„QR0Ѐ@Ë <άI @ t@§O*pš²æQ¤J=í@µ€T94tà AY< VëX²fÏ>L;ltsp-cluster-control-2.0.3/Admin/images/top-degrade.gif0000664000175000017500000000166112026403127023221 0ustar stgraberstgraberGIF89a";æÿÿÿæè±ôõßÿÿþøùìúúïçé¸ëíÆýýúñòÓêì¿òó×óôÛíïÊðñÐîðÌþþüõöãæè³ëíÂûûòþþûçé·èê»ö÷åýý÷éë¼ö÷æõöâøùéüüôûûóæè´çéµðñÑüüõøùêîðÍíïÉòóØóôÜ÷øèåç°üüöüü÷ëíÁëíÃæè²èê¹ýýøêì¾üüøúúðñòÕåç¯çé¶ëíÅñòÔëíÄêìÀïðÍýýù÷øçùúíûûô!ù,";ÿ€‚ƒ„…ƒ//‚‰†‹ƒ6*‚*‘‚”„6““† Ÿ ˆž£ ¦¤£Ÿ¨¤Ÿ/ª!²77°±±³·¸!±µ²¶±Â0ÃÆÇÈ0ÅÄÄËÑÐÕÒÖÔØÐÙÓÕ; 2áäåäãæ2èâàä..ðò--.-ñøùúùûñöî8P‚ÔðàÁ8H4ab¢Ä'VÌxÑbG‰x<9²D‰’'¤L©r%I“#ˆp@“¦ˆ™2qê¬yÓ&Oœ j$Jth¢B…ªÔèÑ¡'H•z"êÔª ¬NݵëV †EV,YeŪËV­€·pÿãÊKw.‡îFØ›—/^¾zó Þû—ð†Ã0$ÆÀ¸±ãÃŒGVìCñáHHAsŠž1wÝ9sçÏ›Ok&A µë×°c»þ!»uÛ¸sÓ¸½›wnÝ¿ Ðø@¡øâÆP ~|¹ñæÅ_>b…#F\Ç^=û íÖ=¬ø^ýzxìØYÌÈ öf¬g£½ýöïgÔQŸýú PA€ =¨  6DáƒJ!…>X†B8À‡ †(âˆ$ŽÀ‰(¦¨âŠ,¶èâ‹0Æ(ãŒ4Öhã8æ¨ãŽ<öèã@)äDiä‘H&©ä’L6éä“PF)å”,;ltsp-cluster-control-2.0.3/Admin/images/managelist_module.gif0000664000175000017500000000167512026403127024524 0ustar stgraberstgraberGIF89a ÷üüüëmysÊåÏY`ÿ²·Ýùp¬3þ‰’êltrÅäçûÔ£Þôÿÿÿôv~Ûò|ÏîØø¹šÈmßioÿîîÑAKIªÎo»ÚøÔÖùØÚõþïÚï÷Y­ÌÕBLÍ>GxÅãîùÿðŽ“çúÕ>¯Çíýó·»íøüÿÅÈùÓÕØî÷Õî÷ýìî^«ÆËXaÒS\äûÓêûÙÐp£ÓuE£Æ¯ÞyrÂßžÊr¢Ïtµ8>Õí÷åpvl»×ù×ÙvÂàH§ÊºáðÖíö×îÀ³ãÿÈí¢ÿµ³“ÒìÜfnùÓÖ“Àdc¯Ì“Ãe»$/+´µèü_¬Êûûûÿÿÿ, ¢tÒÉLš4q2  h8`ÂD„I"4a@‘Åœ$ ¤‰†#6ð Fš  RBG‚d`|‘¡‰ ),(Àe6€¬øcå’%n$©CAŒ§OshÀÁÉ‘ f À0ÁD‹ (0pb í€ TAp CC'H 1"á%²¸p"@% TÂ1ƒ€;ltsp-cluster-control-2.0.3/Admin/images/printing_module.gif0000664000175000017500000000165012026403127024223 0ustar stgraberstgraberGIF89a ÷u–´‰²ÐºººëëëÕÕÕWnŽ·ÚýIUjÃÃÃÌÌÌÅâýõõõæææ¾Ùèìõýåîö¯¯¯œÂ×R`zóöú­Ñãâ**ÕçðýþþªÔû)1C@HXŒ¿ðË\ðððÿÿÿÿÿÿ, =xh@B*ô@ÁÂl(°ál@Q!…  8p0¡À… "D©À€Ë  HЂ͛7° ƒÏ@2p@(]š€¨QPHE@•†§Q=p@PU  ˜JU@ Lè”Û 2(@W»òf;ltsp-cluster-control-2.0.3/Admin/images/stats_module.png0000664000175000017500000003702412026403127023552 0ustar stgraberstgraber‰PNG  IHDR€€Ã>aËgAMA¯È7ŠébKGDùC» pHYsHHFÉk>=vIDATxÚí½yœWy÷û=µô>=û*i$ÍŒF’G»dY’7ÙÆØ,Áì‰!N „ÅÜ„›ÜB$á „¼&`nØÁ€° ¶å]²¼ÉK–FÒh;vOï]Ëý£ºº«—Ù$Ùrrõ|>5US]U]]¿ß³œçœóœ—ór^ÎËy9/ç弜—ór^þÿ%â\ßÀÿ0€äXìçkzfmžë›,¼áórz"È\þüç?¿[UÕM•}'7¦&Ö»c±ŽÑ¥Í¿þÛŸßýû@ Haá-#ʹ¾ÿFâÔlésŸûÜŸÏ·©|lxC`|l}`zj—÷×÷èïÁ]×€R^N¸ë(f*y1PŒaÿ–"Ày PZló-Ò§>õ©–ÊÊÊMxtcuïÉK<‰Ø®²Þ“xF†p{ܸêêñ,[Ž«®oóЬ?qów˜vy¸uyûÇž~úé=À8–%x˸ó ÀŒ_ýõ•mmmWøcÑå£C—G×y^|:èˆá^ÒŒZWgÇN\uõL0M05ÍÚ­«H½ü"«ÛÖìxžÔÌ÷'À9’¼ í†n¨Z¹råfŸÏwYík¯lð…¦ÖyŽ/+{ö<ñ(JM®%ËPÛÛQ/¾9XŽ™ÎFÐÓ±/³x—,E¼ü"+fBd¬`ð-!ÿ“ à Òd@úû¿ÿûÝ.—kSu÷Ñ ‰±õe§º:¼/<ŽwhuÉRÔêZ”š:Ô ƒå@F«34uË}›™ìÏœÀç>ߊ•Ô&âë±àÊÜKú\?[þ'À¤É_ùÊW6M•ã#—Võ[ï™™éðýò6ÊNC®®A®ªEmZŠÒz9Jum>¦ ¶)7KìÔz§=73îÀþÌ¿²…ªþ^ÿÎ;×íÝ»w$óÌß2nà¿+ò"ò/~ñ‹-õõõ—Wõo(Øà‹Çv•=ô3|ƒý¸|>䪤ª” :P®z{x¦®åƒk–Þ3Ÿ%Ì~öØÌgž†F"'»Ù¤¥¶î…§9O€EK^öå/¹¥¦¦fSY4²±b¸ÿ’ŠÁ¾uÞç –uA•d¤ªj ìöÕH;v!\î|m›qÇã·€6³Û”0ís‚^ õNâx—6ϲr ··`ðV#@Ø7ÞxcåêÕ«7û|¾Ë^}~}`j|]àÙ‡–ùzqGÂH•ÕHuÈ5ÕHë>ˆPÝÅš¨ëyQº½¿P[a6çÖú¼ë™…Û&²Ï‹Pkhv f~ß[BÎ%Š‚´[n¹e·ªª›ë{º.©ì;±ÎÛÿÚ2ßÞñêAªk@TV!Õ5"­lAÊrškæL¹-¥q¬¬m‡ÖÏjÎ ÷g¯cÎz‰ÖÀÒe”y½n{CÝòýãÙßû–7‹EiÓ›nºiseeååµGn(Zï Owø~ò‚Ç!ÕÖCy¢² ѱi×eÅY+Ûñ™µ=·Öúù|­6óÀ,júQLì½Ùßë8Ö]SË ¯sq:qá~8@Î œs7ðF /H»ùæ›·ƒÁU§Nn¬ì[ï‹Ïì Þó}‚]¯Ay%¢¼ÒZ74"Öo*zÐvóË~à˜ò4»”y.:Îö×Ç;¿¯(º7sßXô= ˆ EñÏ|SåŒ °þ…Ç÷·î¹³¥s& ’ŒÙ± ¼¾ìë×!jjў݃¨®Å÷[Ð^yžø¿#Û”*|ÂçGøüèc£Ù}¥4G0'×Ô!×Ô|ï‡>?Ju ã·Þ”|@ö¥€,r3Ž›0 cvr¨•»ev?¡s€·H>àL 'ω­;wqñUˆÞÇŽX?>ã·ÕÏ}iˈEÑžú-êï|8{²öâ^Њ­  (kÖøü—H½´™ïÿÛœÉ4Á³må7|LkëÝ}e.ñï}{V-/ú?{½Åi½ó¾óZ%ŽcËV¯!°ªî¾Fî½ÿ-œ)šNkz;޼´ €ÊÐó5{OÀ–àó#­ºå’«¬ýã#hOýfVç®u ñð½¨Ûv‚®ç=p¹¦Žò/ü-ú讎 Œýå(K—#×Ô1þ­¯a/êòÊ?øäª´±‘ìõM3¶ÙbƒRÍ¿¼f#¥ ašà®«ÇÛÒŠoe+Áõð­lEñûèºóÎ Ü{¿›\BèœÆgJý¤¯â¨šF̲ èºÕ‘þg_ÁxýUÄšõÙƒ]Ÿü³ìvêîÛA+Œîs0˜@úµx?ðQÜ—\Ià? Àø7à¹ô*ÌÈ Sßü uß»϶‹˜¹ó6ï|/’׋©i¤NtaD#¸–-'=4PÒ”Ïæ¯·Q¤éNr˜€ì÷ã]ÙFÙúx[Z ®ßˆìÌúÀZZZV655U¾%ògB¤Ž=z$¢º©p{@–;.GÚºiëNˆFr'ÔÖg·‘A¤ÕHu ¤ö<€´¢ïÇn µÿYâÜ€ºv=Ÿþ•ÿò}<—½øc“>ÑEõßý3úÈ®µ0ﻋôÉã¨Í-Y‹‘:yœÀoG]ÑÂÔOTlºçs ¦MÅèþ ›ð¶´X¿ _K®ú†E=´ÖÖV6mÚ´}ppðxæùŸS7p&0ÄÍ7ß|è ŸúÝHewW€–vDeÆã!Ön@Ú}-éo~ åcÿbE[ÞÉÞ¯|;»Þû`âÿ‹¯þóãºâZ\]BüÞŸ£<ŽÖÝ…9"ýÚ+(+ZÑï¿“ª¯}›É¯ uee× Éí!Ùù ž‹.E¸=˜Ñá{ï$x݇І0m7R²aæÂi<­mø7lÁÛÒ†§uÞ–¶9H4%‹Ç ƒTTTSYYɆ 6?ôÐC¿à¿9ÀjƤ'üÇVvwm¦¥ªj ¯F0:_Æxíeä Œ×^AZ·9{3ÁÔ5ä•«0F‡0Ã!÷ýœÄ}?@ïîBíØDìÞŸ‘>Ñ…ïºcjr]êò\‘ë¨üü_YÇ â½h‘G&úìDŸ}bΜ‚ý»uîÖUxZÛñ´®Â¿a3sI"‘ ‘HljF£$ \.€©©©’Ø´iÓrù€sÚ/p¦HÆIoÙËÛ÷oµ (_û?ˆu[¬#t ãøÑ¬³Ó}ö>‘„?€ºýbô‘!”u›‘ªkÑG‡ÀÀ{Ýï‘zõ%|ýh:Ú±£Èu”]ÿ1¢¿üÞ«ÞAä—?#ú›_‘:Þ…”êÌ|³¯Ô7ânmÇݶ ߯­¸[W!Êfý‘º®“H$ˆF£D£Qâñ8¦iâñxp¹\”——S_Ÿsoš¦1444ëõšššV666Ö 9óçDΔ&8î­x=‘Jã+¥[Û˜=@Þ}-ú«/dÿ—ÖmÆÌX€ø¿üéG32CàËß vË·q¿ïzü ¥µ¹¾ÿGþFd†Ð?ÿɃ/¡ åEé†3$'º(CmmÇ»i®¶v|·"Í6§Ùñx·ã€¡¡¡sœTpò—¿üå¾O.­À“ˆ¯ ýß¾Šq`?ò—ÿåÿó–oeA—×oA¼íÝÙ“¡SÖ¸ºÐ4‘/|ÿWÿ•²oÞBü?!õÌc˜áiF|sÖ_%}vÖ”oÚ†«m5žÌZihšóæmíŽD"EÚ­( Éd’+V,ú¡¸Ýn‰DI455ÑÜÜܸÉ%„Ήœ ðÒK/MMw¼g¸¦»« 6aN[Cª†`ר_øjÞIé{þ cxyÓ…è¯ìÏ"¨;Lèúkò@M½ü|öµ?žJ д t óT/ÆÏþ3{Tâßw–(+³RÄ[v ¯Z‹²å¢íÔî™™™¬ïöz½YínlÌ£ñxœt:½h¸\.B¡Ð¬¦|¾s£Ñ(Á`ñïijjbõêÕ[÷ìÙórýoº8[BRßøÆ7öÿÙuãꇦfDuæHqSHÚ²iÕÖºý¤Æ¥ ú‚xC*Ê»~mµ„Ç•ŸÓ D¡ÂàøS÷æ¿jëcéZ —ÝÕÍCXà'x«‰ÌGùkPs¼oíÕWýuË»®]æ©©)y ªÈxâ ¦¦¦D¯×‹¦i‹ß>/‘HœVrÆëõ‹Å²iÚD"‘õÝ>Ÿ²²2êëëóî) Ñû̃¼ô³#:ЀÛ-hn”©mw±¬Q¦¶ZÂ]|Qn/娤Áè„ÁØ„AÿP'î }åŽ:¾»½–™Hš{O󽻺9†•_Ic‘á #‚˜eŸô5¨ÙQSý§­W^ñÙæ·]T|¾9/”Ò4Æg"Ķn§mç®y¿xjjŠ–-[¶è›îéé¡®®ŸãžJùv§vÇb1’É$†a² ÏÖ*ˆŒôqèÞ[8öÛ;HEC¸Ý‚ŽU*m+–6:ÊÿÌöKI Ã3Ç{tK36n5b Ÿõ{‡y Ë"Ø¥eÎ:DÁ¶ü=h[·bù—Û®yÛGj·na>à³Û4žZ¾’µ¿sݼÇ'“I8ÀêÕ«}Ó£££H’DM5J&“$‰,ØNív»Ýx<zzzæüÎT4Ä¡{oá•ÿú'–5)\ЮÐÑ®?±RÿW­WEþ¾H/DúJ|›ÈëÈ›0x¹3Å¡£Öìñ˜Æc/ó7¿ìál‹pÖÄÚ/Üö7͗켸vë–E_HY’&'ÔÞv»Ý¸\®¢æÕBÄív355…ÏçËÓnÈùîòòò< á<7‹•üìØoïàù[ÿšT4IJ&…[],mʴ΄#@@ ê/µ¯Úõ—Ìã‘>ˆöÁðÓ0Õ ýZ×4-ÕÖÊ\s…—ÛÜì}1Å¡£©«.iવ•|÷ë¯ð@”\ xV¬x>ÑrõU_nؾ­¹0°[¬LGc„Lð¾ïƒÔÕÕÍ{|WWªª.(f(ÔîD"ÇãÉîóùO ¡ªjžõHEC<öµßgèà3Ë$vïòж2Ù.ÿ2Xö.hýˆúÙþ,"tÿÔúß´¿ÐäԀΞgŒë¤ ŽÞt}áåGS{ÉU;ã.d±oÍê§/ú›¿Z}ç—h2I('uÍ»X±jÕ¼Ç355•—²ËwÛ`Û€K’”íÄñù| ÐÜܼhë …ˆD"ÙDÒðÁgxôk¿O*bË;·¹q»ENãP· V–¾ól<¦Ò’ A×÷áäÏ!z*O¿÷¾ä«ŠÌP•D´_ÿÒ‰[cÿ Ì`ŠgÔl”Õñ‰#ë}¾—·µž•ßK¥ˆʨ]¾|Þc Ã`dd¿ßO4ejjЉ‰ FFFH§ÓȲL0¤¦¦†šš‚Á`VÓ‰D–‹!“““TUUqèÞ›yâŸ>"¥øÀ»ýlXçFQ3àK&T^;¿ e+ÁÔÞ¸ER ö"Xõ¿ÀUÓÀH‚‡ OÊ&J™¸ªr›Ú>ñ\z–8£æ¢ü"x7ôŸ ¬ß}Ùfi‘M²¢‹I3‰q!¨»`þ´¯Ûí¦¯¯h4Šax½^ÊËËill¤¼¼¿ßËå*Ù›–J¥H&“”••Íû=NQ…‰‰ :ÿóK¼v÷MÔÖÈÜ𻪪äÜ GW¬û¿aÛ?¯L½Äb̲ÿt-·]µV\É1^;ÂW' &ë+áÓd\Š´ºò"å²ô´ñdjÔŒ;ˆ°xÌó¾Dâøûcñë6o œÎEœ’H§Ië:®¶ö™çp8Luu5555Ù ÛB%Ï:ðr.yùÖ¿¤÷É»ikQ¹î~Ü^)£õ@Í6Øy³eö猳lŒ‚ëK2FÃ)ÛÆÓ=qØ7…&™L{4T]ƒÔäm•Þ–š0M›1rÉ£E@\®“=#;Ö®y‡·¶f±×ÈM7ÐS)Ò-­ ÒN;·î[`sÓUU¦ªª !>¢êéoßÈÉ=wÒ±ÖÅ»®õgL>ø+¯‡Íÿªïô´˜EkÌÌXZ§Ì_ÇîŽ÷²gä)Æã·Žj܆Tíi•¯LO˜¥ÇÍèéÀ¶­ÉýÞ~²§uíÛ®<£`À0MR©‰ú*ëêç=Þ4M&&&(//_ôwE"Ün÷¬VÃ0 âñ8¡Pˆññq^ºíët?ò#:Öº¸æj?H"Wtý¡å#ùZ™Õò³iê¶Li“šFÒÔ0e‰¶~Áè GCGs$Ð%\†¨ö¬ÛC{õ¬^ d2ƒjãpxæøÛåU«Û]gB‚X2ÅŒÛK]ëü\’$‰þþþ¢¤ÎB$•J¡iZÖz$“É¢`2™L¢( ƒÏÝÇÑ;¿Im­ÂûßpÔóÐñÐtõ™kõYZºÎ@J'ijDI¡:º¡sYãe Æ9:†@õ診ÀeJ¾ RëÌ~ýñÅ’À]¥GA4z=}áe—\²Ð `Ñ%‰h2ITש߰qÞãEall ŸÏ·¨Ñ:†adûÛ#‘£££„B!LÓÄåreGUTTéfï¿Þˆß›æ#¿W†¢J9í_ó§Ðxeiàççbü¿E+úÝÐéNêÄuˆH‘FC3sËÅ3âxø8AÌcàMɨ²hw-áX§qˆEô!8 `éÇaèí£c;—ïÜ1¿ýžE’i4 –¯\М™™™l+`Ök–Ðn3ãnjjj¨­­¥¶¶6¯©hËoþæCDÇúøð‡‚+Ñ~ûP¹ÃÜ/RóóŽ9à¯8èOéL¦-ðãfÍЊ–õ;9>A´?K_\Fö‹mFŠ'ÓƒæD†óZBè€d 쨭yoÙòæÓ"€n˜ñ8ñ- ŠÒÓé4‘H$4úîÑÑÑ<’ØMÅŠŠ ¦¦¦¨®®Æå*íµüäœ|êìÞí§u•+§ùM×Â’w©ÍOæ³ó5µY¯9¡éœHhÄI&™§ù…ËæšÍ¼2þ S©)v™øb’K©ë¢Ï™¶7 Ø&~âkºO6ì¾lãéäLÓ$žJ“¬®¡ª©iÞãí„P2™œ7TØTœ+!éãñø}–5«\õ6Nóƒk í“³ƒÍÀÏiêŠIÐu^j¤ I‘ =øš©! ‰¶ò6ž~ÍÐиuÑàZ!éñƒÆ+ÌÙoPjš轉ÄÐűøµ§“BXq€$Q»zþþ;!TVV–õÝó%‚l™+!´çŸØhï¾.ˆ? [ŸâƒöÏ‚äÊV¤ÙÆìÚ¾h?_b)qW¢3šÆ„H4Óè¦>ïR¦–¡J*“šËÄ“=¬O˜è!ÂÌÓƒ8Û“M€é:Ù3|:¹Ib©1àªcý‚n„Ãaü~ÿ¢ÇßÛ纚‘Îgxõ§ßà‚uÖoôäÚúMU ´Y,€6+PsjübòŽ¥+®ÑŸHI"Ó¯gmžeEÙ º¦»˜HN€˜¸ãÂ%×)ñªù<¹þ‚’V`®‘¨Éý¾øÄÉ«¯¾jÙbAIiºa ZÛží„ÐsÿçF´p?ïù@y&êÇJë.}?EZnΣ­gSû –ñ´ÆK3 3ŸÏoƒ¯Z–¥BÍÐhò7ñÜðsY+ &%U¬JŸ20„˜ã]E³ÀÎ ˜33‡N'7 F"AxÉ2ªªªæ=þl&„¦NvrදҾÖ굞Œïøj™~¡9¶¸Ù̽8fÞÜKÚÐyz:MT×U¢¤ Áw¬‹ö9+àS|L%§Œ "ÈX¨pI5ˆäAs¹áeEV`.ÛlS¯Aÿo}ü‡‰ññEâδéÑ‘oî8±ÏM&“„B!:ïù’$Ø~qäL›ßß Þ&0S`&ÁHe¶K²Ä¾…|vz˾P‚éT’1i†¸™ m$Ie–tÁzÖýz’¤žäòÆË+þJ¦**Å;°Æ¥z˜eüç|“L ýP<Ñû¶Ñ±]+‘BI$‰&uëæ=~± !gSÑNÍÌÌŒLsø?¾@K»ŽÍ~+ð&Ô^®òœï%9N-…ûK}¦ì3¸è¼Ñ8ÑK BRÃÔ1ÐÑÑ12A^v_f[wnìS%•áø“ÉId![#´â¦_ª¤?}Œ£Ì2ä|¾'m` CûáËþ¥ã¥—´Ðáb’¨²Œ’™¨¹8Àï÷‹ÅJö"Î5"¨ªªŠññqV­ZÅÉÇï@X³!R¦¯K ‚o™¥Å¦È•¯ÎQvŽ;›g à"§sL¤M^ DM15†aäNv–˜Íî+¨Qh¯OEOÑ9E¤ŸÞ™>LÓšLí’\hA{ äzór0ïÚ‰\4€d!¹W¿ ^¼ôG·ßöGk×üÁBÓĪ,ãI%‡Ã "@0djjjÎA>Ÿ¯äx¿ññq’É$ûÂëSY±Ê—& ¾æŒ '3Òg0M翎Q¿öÓ·Ï5 N- ¾ÈçI¹”{Æu¢i“O””©ç<lHé)zfNrr¦›è =™]–¬µ0a"£ ¤´¶ ða¹èéÀÄbÎðw¦¦´óÁ‡¯éøÐä TEƋϫ¡3›ø|>zzz…Bø|><UUUsöø9ÏM$Œ~†e+ý +Öo5ÿrËï rÚo:@*ØI†,)DAf9Ÿ;dÿ´ÎpÂ`Ê• *’yyº"à3ú£}ôGz8îʬÌnf@·×† &:ªäF *èÓI¿ç ±+±Ç¼kj^}â…ö¾˜@ø ôÿô¾núºŽ\ÈR—Ž CÇü#„ìé^íí틞ôáv»é}á7¤c!V¬^j=ÝÕŠß"€Sl2Øÿšñ"²œS’sß㉨ɋÓ:19Ťµ€v´rÓ¢ôDºé™9A$m¿²7 ™¯µ×VÝ E’À/Pe•t}jPrúb Cÿ\|Ï/ßõŽ¿ùâ¼³?ÔL/><ÿôj[‚Á ±XŒ@`q HŸÏG¸ï0²$SÝà³ÆØ:¸ë3¾¿p „cÛ©éfáÿä›~§Ù×*´ §MÑHê&ÃÞi g}BÂé'gŽÑíÉš~xS€ïÐz{MÖ èÈn7¸¤`j#ùï)X4À"Yÿ÷#]ßZuÿ··½çÝó¦íÜŠ‚?›sž¼Sü~?‰Dâ´ëyYU¨¬Ï¤y… j¹CûçÒhQ z‘p¤”ˆ¢¬<0¬I ûÃ$IzÓÉIº#]L%ÇóAÏ# ¸(¶Nd‰ \²„éu#¼±•ä¿°*ûÞÂÅÎ6€ñ‡àð;}üGKwí¸Ñ3Ï@E–ñ& &@0¤¿¿‘·e‰‹4åËý ë7J€â%[†Ïé÷ Á, gÙ.Âv~ ðÔ¸NwDgÊ#¢Ä²ÇZ¦~†“‘.¦S“VY» ðˆ 3ß×›¢Ø  ÃéÒ¨²Œ0ŽköqÑ «[¥ÒÄŠ"G?79õÃx{÷|'¨ŠŒlÄPeÎ,!4yt/eUV½b„–è©æ’8¤°âÙL2ÆÞžwI+ìÞVÇÿ¢øÜžh‚ÇGâD‰2îžD3hf‚˜âD¤“ÎÐ>fôId‰’‹$fÙ'ò×öqRfAè(’ŒËk%pÝ—±•ÜL°,MO§@„5)aô¯üÚêyrvF0=>¶ ‹»ÝnÜn÷¼SÆJ6”Uz¬ö¿‰¥ýyþß©ÉÎ&˜Å|Ï7й»ø³„÷ô§HƒÁ ´L“o,1ÈxjÍÐ,SŸ¹§¹··E)7Pb·m€aꨒŒéYR0Í´œÁ;¯ÅéV±s/½ãžû~ñÁµkÞ?[n@–$$!L(*•²›Šåååç°!Ët-“røÿ9¶ QèãEÁ©bŽKä“ா4£ ƒÑà )A\2’8EÚ°š¤rÆþÎEÓ,–ôÿF¦U)Y×SeCUR‘ÊÓ ðeÎÐØ÷œ†ÿw_ß¿¯ðá‹çÊ ¨²Œ7•ÌÎÈ™O‚Á ÙZA J t"T5•YÀKRæ)¥ Úñ¥4¿„e(Ú.Øç´…Ê/—óüXŠ×¦cL»Â„ÔIB©IfÒSÙò=YŸ/f!@‰ÐÈtÙÙÍ@ø4ÕmÝ¢›gìl1€ÐA8uÇ}|篶_ø³ !s© xŒP(´ Ø !UUœ™].ŸÛj ‘Éá§ŠÁ.j¬EÁv¡æ‘ ÿôhÂä¹ /åQoš„9ƒfÆó5¾”^”0ý´û¥üæŸÓ HTŸŒ°~³ §ýÙ;?“RåÙÜÀ×ágnÿÉs³hçR§ta»µPSSC Xðl!!@ØÚ/eBålð–´‚43™ ÖDaðæô ?Ë[Ïr ‘‘&IâHGñN¨¬™èà‚äfVIë¨s5âS<È(³~EAß,ÿKÎÏì`PÊý|E’Pô<…/ê9Ó2qÆþýH×·Ö>¶çöW]Q”p9AÓ4³7쪥föœNBHbY)£>ÎÀ™ä‘ µÞî *Yf±Ö1Š–â‚ήþÐ?0àMqtüŽŒ½€7æ§Ê¨'åMóÌr3cL’Ðã™çQlúÙš|Í?ÛüÛ. ª3%[·š¢d¼³Q(ÒÎ yìÞûïþèÆõX˜°‹G0=]².P©ò.vn¡ðÕ6ƒ€ÈdD™e) "¼Ù\Àl„(^”8ÝL<ŠŸõ »Xß°›¤ãÈØ~ŽŽ½ÀáÑý(17³Í—"éöŒÒ'HêñlÀ— öÄ,Q¦AH9óŸu ¸dM€@ ÑM‰âSg«T¬ bjú;ëîþå¥}ú“-…ÙàÄÄDÉÍ… 9uêT9æšè­i¶¬¾$YA ì=ž¹5‡–;³Û0‚žþlÛŽ›°·%¡ÈyA¤[ñ±±q7wpdì^}ã/ GÝxÌjjü)4œÏ83Æ3ééœæ“ïÿÀÛ€;­¨R&ŸŽƒÈh8ë€\n`üŽgžû×– ·~§07àV¼±8Ñé)XJ%„JY ')„€ðD:Ó PsQ¿ 8ÖNð¥9H@Ág6ÐEn!—_’„,É%; í¼EYª‰u®«Y·ôjz#‡™qÓ9ô<±H„ ³œr—Ž^'âcFLNM•NùÚlò·r²$£¥¬œ€1ÂðI2» žÜY"7`‚±¡!ÌŸ+!d'‚ìÊ¢‰Dïò-¤¢Ó–j(~ËÚóÿ„s»k©ð… Y$ !É$“)R¡P¶R™sK  ®®UUQ{TZZÞÇÇvý?¼zê9œÚËËýÏU(3ʸ—ÓPž ê#ÌÓéɬ¯/4ÿ"C ¯ìA•d¦Ã–iÇ,E€³]ŸÖŒ®P¨÷JÃü`íúŽì@R»xD ¨» £(Ì>F‡Ú„Ãáìl {jØôôtv¶¦iÙ ž555Ä{_d¢ë«/oµA}Ôz*™¼@ ðí£Ùµ(Ø_°r-iûá8ORÑ &ºR¤j6¢»ÊQU5o®¢ßïÇãñdç;¤R) à  Ò\Ʀ¥»xGÇﲦ~#>w€P$Ll*…:]A Þ@½«¿Ç¤H¤$f6òËq±Æ]O@ 2Úb|`òpêe&€Žw½ŠS£ •;>µ}ë–+ÝåÙé4 ÃÀ¿z킚vétšÑÑQ&&&ˆD"óVILô3ùÚ£,ݼ —ß úˆUêE8@rºh9K?èÅ$HE+˜ìJÓtá{©jjÍÎUŒôõñØ 7 …ðÕÕáÊŒ€Ö4H$BmmmÞï¯Ô³®iW¯}‰SÏwî}ÚårW› Õ%OñGꨕ›ñ{ý(ªDÊH`šXêkAÅCïÑ1¦‡ÂûÓ< Lb˜ÊŽ :›.òs^sÏ/?|ÙŸ>[NK•eÊq&&&4þßçóa+V¬Xa*W_Œ¡%˜ˆ¨©µô±È7ë¥\AöJ›þÂ&`ÁÿB’‘d¹(hô÷3ôÌ3 =ó Ïÿõ_Sµ~=«®¿ž¦«¯&6OëµK7H?{êž¾¾¾o]øžõ·U^¨õî45¥Ì5±„¥‰† AÄ7JH£ÌUNrZއ0¦é&70o~Àa²¡ÉÈÐð‰‹ËËß]ѲÒ``ÍæÕÖQ½€@ÐívÓßßOmm킪€¸ÊëxìT›† êAè`L9´7Ó¨všøRn (6(´ ™}‹Ö¥¢ULKh¿%ÓêH?Ç~úSv7C•ÆFéþÍcùÁâ "ÝÝøð—x6ååå<òÈ#'Nž<ùÒàÑÑ׎îéýMçƒ'îðJ¾²®&·4Ór@šà‹Öa¦%3]§ŽØü¶c‘yÕßI›Éã ¯ëí­vN2%SD}jV®\PBhffI’fý[(ñ‘cLvbÅŽ6$ÕÚ©æÞ`a`(Ͷ. Mð<ßH¤cÕLOXµ¹¶7†Z“-õÐV)P$˜™¤çÙç9xë­úñ ÷ôä‘AUUNœ8yòÉ'ÁòåSÀÌÀ‘‘®cÏõ>qøáwë!özÜž”êvU£)¡±FÇG{âOš?Íœc—–{ÂÀBh¿J$º~glüº%Û/ Øà´¦Ó¸~Bˆykÿ/vʘ‚‘½wPÕÚŠ¿Æ" f4\&O:[ X”Þtvrf±¶møW]ŽìÏ%ÅltÔ@pÇnø¯Wð·­fE9l‰¡­RàwAxbšÏ“!®ªþ»îºëN œ3†•‰ÑñÞÉS'žë{æõ_Ÿ¸Û˜{û¢=CñCé;µº3„‰â ô¦P<§FíI¦)MC3 ”–¶ì”î¹`“““y£‰ær¾†U >þ=´”LÓÆ%V>ÀÉ+eÒÄr¦ÝTÂÌFŒ<Ðm°3K¶—ÕêlKǪ w'ñµ^Šä«Î ¯ã6–-ƒwý´tÀï‡}ÿÊ6–L6&ŽÑQ#ºar,G†ñ_ÿÚß‘J-Ù(„ò e€Ïôx‘È,1 6Þ3ÑëL¿¨ pËôG°´?¯^ÀýšHÙ¨VíÚѪK"™?gp.H’Ä©S§æ­!$„ȾÞ59=ÄL× 4mZê/}„–é!ñZ¤äZ%›…6ð‚\/jNËs€+ä@F‹UêŽã/$@ŽKšàÒßTÂZ–¯¶ö½ç㸛[hô›lLÈ’!M¡¦i«w\.Äçv±õ!/Á`†™R'ydˆfˆ’¤ÄÑ7ã=5ÙT×z½¨ZÝÒÄ+*TÌèCYhj€oÏÀ¹`ÂÒVØq |ð3¸W¶ÓX¡²Q ÒQž"èa Ò)Úª-2üÉ!¶®"ø › œ&7n­dEÑ7ëEEÙT[¶m¹D÷x˜q{¨m[µ „ÐÌÌ ÉdMÓJ&‚ü~^ e©É~Æ<Ë’íÈžJ0Ç@¤2ƒçÊ2®À$¹šok½„5ÈT.^„l}–÷¹B:VÍLoŒh` ¦ÛÊU444Ô4ÿøÇêkaënH&æ_jaÃ.¸ö#¸—·ÐX®Ò! ³¥*M•TH$²–áOv±õb!*£BD†-Ó?«Ï|³`’)@õŽPhçò-›ëÇ5«ŠØBÁT*•}áS©D3«f‹oé:†ý6B©¡º½äƒVÓPöY‹¤€ìÇê××3]Äo\hê³ —Zd´x5‘ž(ÍÛ¯£¾y5Á`·ÛM¸·7CA°¾Æµ”˜k©ª‡ .„+>€²d9ue «Å[ªóÉà‡k6À§7 ñ®ÍBT¤„˜¶\‚3‘m¾™ÐÁÊ \îõün`E3éå+³Ñý\0M“©©)–/_¾àr²Š·œÔT?Ÿ£¶ã\eA `Dä*ªåä ;žr€Ÿgê!œ‹š!DŽZ¼Šh„@ëe(\ìîéáðm·ÑQ'¬­†5[3ÀÆs/Ä"ØKE ´o‚‹ß…²²ºJ/«]!¶TÄ©òfŒšF}™ÁáÓ›…xçfIªð˜fo&üf¾«ÎÒÇA_78Xváö 7Ž,[Nuuõ¼I;!´Ø²°em3úäwIL™Ôt,CrÕZV€Ì8A¹ÊMR@ª¶@4ãð@—Òx¡–ܯ'ªˆô…)k½Å_“µr‘¾>ŽÜq4¨«+ m=¤’𓨅„Xèâ+ƒævØrJ[u™Õž¶W'© (¨ªŒ¡ÉõåBº¢Ý0þd-ô<ÇÎv*x>¤€á?…oÙxßï¬Ø¾³†ööÜgy„ì-§ñš¿dèÁ¯2vh [êÀµ´gi ¤š\´/–‚¨s 3o@.òïYßïl`73I!¡"$„”ß]- T—Špez7£áÒ³Ó†ÌaÛÄ€mWZËÄ­]h< ‰Oõ™¼Ø“" K²7“`ÙØ00zó³ÏÝôÙ}û¾f^|Ià¥Üý¶°ÅN«½ôÓ ¿p7'ø¦4ÕØ úË`ö@€,ˆÂTƒ9 Æ(–çrDúy±€“ÎÄšÜjÿ–D"Áðð0ŠË…p[#u‰Í8€6à;ƆÛÿŸ®¸½°~§EòÞ.F#qtˆÞ{×›M°H0ô#xö¯>µ:»,ÌkÚËÊÊ\ð!Èp¿ý›¤~þ>NÜ·‡5½wÅ `ö~”M ÊÈÓj© ¤e`N1?å½|ËàÈ !„ !Ëtuuqè±—Ž;Ö¿oß¾£•§N­¸Ú¥^.¹<€€hÄpÁpÓ(~ºajO2cªôO…ƒÉôÙœ+¤€Û{znO8|ÙB´z!#„ì7…N©[Ú‚ëS÷sò»WròWå´_’k;h2} ¹¤ú .e9V­LÖŒ“oœî@€P’ÄÏoûÁ½ÿûÿ}à!,yoCýûT·ërˈ;àÝpÀÈß¿X‹ Cÿ1P\ìïŽcê:{á>2iäsA›ãûöí;>55kllôÍ×,!TjD‚`0H  ±±1¯x¤ÍÈ7üÝÿõqúªh¾f-’zhŠå ô×-ð¤•%Ó»à¹2÷¿³ž¡™©·`Æsç ’$ãõ¸£@70Ä‚^Ï´"K—ÇJEÇ£™s|Ð #¼½?oŸýç‘xÌ¿²†”ÇÇ ÁëÏÀ!‹Éç– `¢¿¿ÿäÚµk;’òù|ÙW¹ÛÕA}>MMMÙ·‡Í&¦iRsÑ –+üùg‘¤ßeéÕH® ûAïý˜aP¶žD°}¿ÂO^ßôƒ€Œ*B’q¹Õ4V*vˆøÜî„" „ÛR’1à L Cü¡[d0t12¡”ÌLÁØ ,iEå…Þ±h‚ýðS¬äPH+€•ŸNôôôì7M³£l'p¶ÔÕÕeßù·Ð—GÛ×´-LÝÎ?B’½?ÿ  ém[P¼[¬è_Í"@z/(k@´ì9M½ì ˆüy2ÛdI¶[> év»uUÂ"€™¶š}Ní¶7ôëÂmaœbè–ÙOĬ¤‘×O$/¼ÖM^ÿ5ìÇꊞk˜@âÈ‘#ûB¡ÐÇÒÆ/++ËšõÙFÛ‹üB©Þþ˜¦IßO?N*4Íòë®F-k©´W­îcý˜Õ‹(¯Ñ̬Ϳ¼V€;CB–¬¹`¶ššªË…"LˤcVû=Oà ÐõbÀu -÷™^@ ÓÈŸNY–Áãƒêey#æ1ør]É @?—H<õÔS‡Âá0••• J /pÓ4³×K&“ 266?|Øè_}êíº2=Ñç]öþ?$Ð\ êÕ`½ßÒRýC ·€X†UgÁAá´n².@ÈÖ45‡(ªŠ’µJŽyA ÓèÖ,g=³6œk=í´²KÛÀíåðP’îãCôÁÃÏÂA2îˆL±¨sm’¯¾úêÔäääpsssv”súØl€Ï¦Ý6àvéÙÉÉIº»»OuwwŸzþùçtww÷ìÛ·ïV÷hâøú„ñÚôÛ¿ÕR{ɇ©¹h ²·¤60NZVÀLgb„S™æaˆ*^ò­€E„Š$ËE…®\.ŠlZ0Ü9ÿo8À”2k¡ndÎ,ºã7g ØãÁÉY‚¥­PVÎtžz®“¸®ß ·a a¹_Îþ ÐÅJÐÇÆÆºLÓl(µÐ;÷Ù`;Afdd„C‡õtvvíìì<øê«¯vŒŒØ?:†eí‘4Úí/søö—yúÞ?ùã‘ï|8züRj/•Ëêf+Ê7zÁ·Úþæ4è1§¬Ü(Ìl»±SÄB’‘D>·Š"°\€æ.Ðt$-¾ÈŒ`ʽ0W ;š„™‰„ËVAÝRÒ<òÔabá(Â7†¬nâ)ÚÿV @Hï”|*9rÔ/±´“G÷0Ð3ÄKp˳pkLà4ƒBÏ5L 988øúÄÄDÑ §æÜ~)Tjp€øÐ þxŒ:-MS,F×o›üÁoûå¬ôæÖø÷––;wÎdæ…ÿí#üêoáéïhú£Û"¿øxìøãõÕo£|ó5x—,Cò4[y4«Ýo&—tYC¨€‚$»ÕåF‘L+œvç‚>9ãÛ%=7¿[8Í©'W` š×Â’V0 žÜßËëû;‚§î°’>ã™gbW }C¦†®Äoºé¦}ŸùÌg¨®¶†OE£QB¡±ÑRã㤇ðk•éT¶±OU:ÊxûžoF"?뇓™jKcƒ]ªál’?‚&ùÇwñàç·~húú‹"w,zøzÏ’-øÛ/Ã׺Wu’Ç™5´ß¿™éT’BÖÑ(ªŠ"g\€ê±´_¶-€l¹©Àï—´éãÕ›¡¶ ƒ§öžà¥§0O} ¾™y&¶5,zãø¹&€]Á!ÝÛÛûÊèèhÅŽwvvŽÄ\ûç«vÿ‘gÓF$EÁåRP½nTY&1>Γ·Þ~ü_¼ã·ð20ŒåßÂX,w¾%c¡ySÝq^ˆ~ê.¾üìï®M\¶kü¹ßYÖûÜ.÷ÞJ¿ZµOÃ:ÜË6ãª^‰\^=È‹ ÂzQ&È~¿êr!É™f +CC³´_“ÚïX|x·.ØÞš¦óÔÞ#xü'øc™%D‰¡o@f0ãµ×^ûq ˆê@ùî‰ñº]¸õÎI¦ÇîûUüGwýâÁ¯ÃÝàmßfk½ý¦¬Óé6qÖ…Oc¹ÈßýšûÇÿW®Úµ¡ijÛÒŠ—7Ön['T/J°Iñ"—9Æ8 èì9ŠÃ).Ëàr[‹¡[-qI) šÃôópv&Ô7ZƒA$‰D2̓w?IßkÇ ÁÁR {ž|‘¼ ‘›è0˜!€÷Û¡ðww>ðð¶uþ@ÝÔëGøÕoß÷¥ÁÁÛOYùõÑ ðvTo›ñ3è;ÍŠÝa¥aiN Ë„º¿úkîê»ë<Ÿ¹$ÞQåë.ß¶ŒMˆC­¨/ceJ#òúN’«Óoª.²”i¦<™ö}t9ü<í/ÈÈ ¬Ûaeù Ñ‘üè>¦N ò’à–Ÿ˜YŸ?–y¦ys å­@ËDÙE í2Ò~zÿ7½ëdÏŸ|·óµÜ/d€·Û³öXw;¢?Ûb[›2AíÅuó3 e¶&Œ¸ý®…2VIVU‹.—åt-~:×ìË úàË 4¬†Æ $´tšCû³ÿ®‰'S±Gà›™üçšÕ›©kÝ‘õug?Ep,c|¯¢®ÅY·n'ÎⲄψ¤=¿ªy#6§›®£ûÓ^œêhó~¶½Ó÷y4瀶¢uºÍ‰eæÅGClOý ê]©qm^#¡e­]³•ºÖí9]úÐÿerbdöâi¥ÔÇÚ;}á,Û³ x³¸b9+7íÊëÎ4ÛÓ¿ÜÞéûf¡ä©Ý Ðð„øèÊMwR»z3–͉ÝeËfMÓPJí~œè ÙпTÔ­FJ3g¶¬‘ì5àÏ;Ú¼ŽwpÀßh†íw›·î¡¬¦+Ë™#ÁÙËJJ4]ÀCÀ?':J¦Ž´Xç(*Áé)CZVÎL8e"ðø»¸Ž6ï£À§6ܻ؋‹äÅ!¿/ãs¤e¡ë:ÀÇÕLô¿€x'2cyñøPo>âø½Ž6oÃ’®£Í»x´¼¶ WqyÎæ1ɾ«0£s».˲Рà:Ú¼˜¥M­ÀFݰSTV‰´Ì<8F`¤?‘èÀw—4pm^ð»Ë#*ê×äݳÍX”¡ž3Y?×2MŒ8xßëhó¥9å;%•+PJæåß‚cÃXf4_Ñ|¨£Í»v)§_ÖT®\‡’–Ì/Oë¿D,Ìé3Ö/¾|!¥3µ"o5ÊʯM£WÏÏ7’ÿ2🖜Æu´y×–V7`sºóÖ¶ÉñFúºçÓ”Ïw´y·¦†ä€p—T „–—™œœ!œ˜¯ˆ~¾¾n¡4îO„&tOyÖ,‰u6&oðÂiP MÓX³~-oÝ„Íf#Žpüè1z.d.Y !„Rê« ó¤¿ `waåNÑøÀ¥BÈÇ|øÜ’IÀ;Ú¼¥ÀUw©×UVÝ”×=”’Œôž%òS×PGÛo·á)¾¾uæô=ˆÉàdÆ€X‘0Ç*W¶b8Ü9·+:`¤·«P¢ í¾Á¥¢q¸lŽ¢¼¸´LÆú{ˆE&¹mçVvß» MÓPêúrTëú›8ø‹Cœ9õv&wð`"¡†hº i™¹ö&Ƈ.§=äv;Yݲ]×8wî2ãY%殄ÿýʒи¯?TÑewØW{–­BËíöV,ÊøP/º€½m÷±¦uuÖ×¾xà0¯¿vbV DJ›³ˆòš•9¿—ß×Ohâú\rÆUìÚ½§Ó>½xð8§OŸËæ¶@C{§o<Ÿ¼¢fr'ð%Ýæ6§ %eÖ ™ꥬ¬˜‡wõ µ +—76Õ¡”¤ïòÕtMsEw16» ¥TÖžœ 8:8Ó²oßn¶n]‹¡k TÜ AsórŠ‹‹8¾/›jJÿîЫ‹m*ïÐm¶œ‚’h(H80Æê5ì}ÿÝØíöL#˳Ò»nÃá°óÒÁ£SûŠŠÜ„Ãa,+>,¤v,+–“éN79èÞ{¶Ð¸² %Ó›Üu­õ„Ãa~s®G<’¬ä,šÆÝ·ÆÕn³«šBËJÓ"Á báwîÞÆ={nG×®õÞ|¸¶¶’ÚåUüAJËŠÙûþ»õOù§§t*š“¥E`tð:¸uK ·mm!>¦;;×Ö”GÌ8‚Puß×7t‡ä¢h\G›WBì.-+ÃÃcM „–±'Ç"“86ö=|?õ µ(e¤- +khXY3õ÷ŠÕ\¾t„7Y&‘ ÿ:˱ª¹–;v®ÍÚ"ìºcW® 3<2‘)5ØI|ZÆ¢˜ÊÍJ)Ï–-­;vŠ±Ñ tÃŽ6sz›R˜±JZT×TÐÖvÅÅn 7qùòŠäÑYVK¬X„hhúˆDuU)÷﹌+U6&MƒûïÛÌ“?92e®ÓІÅîV€úúJª«wóì3¿blÌO „˜  ¤¤ˆí;6°n]c"Ô·XHª®.Ÿz¾´bˆ9‚i)-ÂÁé^q±‹ìÝ‚®©YýÚlä-sqûŽ޼’~šƒBN.fpR àvxÜv>ññ½\º4ÀÕþFF&Ð4AyY1Ë–•ÒܼMÓâ¡”,4Ùt°Û ¢Q“X$”v’딥"Lu2ˆ_ûÐÞ͸:äYs½uý zzé½’Æß)a.&pËl6Ã(=iÿê+i¨¯LÛÇ”´¸‘ätÚ‰FMÌH(Îki+6Éã©™î{ÖS^朷eس{-ÿç§¿&5§w]]Là*\N»Zh³—/¹]&&âÉŒ„Ð û5ž-݈ö¯-)ˆö¸ ¶nZÁ+Ç{¦Œµ‚£_}fü¢jœËe×K8—Ë>£ˆMfÒÓÌb*ml­f㺪‚úà"·B©¸§Õ5ñè¢Ö*…`™ÓihéjŠKœ#=F³€V·¼”]Û nÒC¡HÂL+€áU®üÖ 8¥Æb¦BZKr=B,ff——:Ø»»•õ5ÙÒÈh0®qqè:?úc¬E …¢RIK_ŠÀ…B‘¬0p: ¼» ›Á‚PCA¤TñQ ÄÓùÞ§À ‡BQÅ5•“¡¹‡˜vv×SRd°¾Ú²ãþH2( ÛbÆÏ—p‘¨©«%œ„™«ªpñ[ï[§È¶`áÑ0JŤBøâ/‚K8¥‘H‡ÝXR )¥ˆDL¥T¼h’ê„]µM¥lÛX¦‰-½ ®HB=3Ÿ{R†Gü,¯.^RÀùÆB(…ˆ Maè»·WRíuPìIVQälfÁ¨»g"¡q›Å³K¸#€¼Ú?¡-¯t/)à®LUæÏ ÁjS*lº¢Ø­q£òÎÀ¤É/J€àÄ—žóõÎç~›ž×Þéó ÁWJ)‹¥Äýƒ„ ¥~ M@wOð†¶áìå"‘½)1?m+´Æ¡û‡‚›-3&4mé¤sW¦RRšö”Pê+–‚KW&1£ÅÆigwO0’B<3ßûzBìK–¥´a_”µ$Ø ™ð«ögGŽWP`)xë| ±lya¹w ̘ߌ›IH´cIw@Àd×Åñ"løíócÿxÌS‰€®Sˆx@þ›®I"1sÁÍäk§ýñHVJý\ SPàÚ;}~Ot]ð[ÑH4Z/"K3Æ™sã&ðäÔÄSÁ@²½¦%9yvrAÛp±/ŒoÂ"9ꨄ,„¬"áú;ÓRŸîîñ³~•gQ}Û…¾IÂi—Ü'Ñ8~%áä¹­õ:ngá}”Šco‡(®e*Zˆ{|ÑG{§ï4pøô9¿¥,3n/Ÿ>ë·„àT{§ïÈp‚e3*ÇWîøù¯¾!’È””_ *–$p úËñ€¥wõQÊ\>ßdÀӕН‡øÚC+”âS)RDIÅà¸Å¯»¢}þ¹¾(o_²òºéâøÍ÷{ëæ+à©äè½}ß×íW‡cMkêmšMg^s%såhTòó£–eq øÜî_ÿPq…²´'¬›ÖØxxÎИ¢¬(Îó}þ¨_ñÂëñYÐB\g‚ ©±îþûþ_vGÂùÊxÁ’˜ÄGhÎ4ÕÚœ÷nußФî•S!ÎôDM`KÌíë²+Að-P•…!àŽVEËòüƒ¾«>ÁÁ7¦T(É´é3ÓK!øüj—ï§ùŒÉ-¨@;Ú¼ |wÏV+knLáy`Ôbÿ+a< jÄ#Àœ~E¡ñrë,¶­¶rN÷WÞ1@åï÷ÿ,ÏE¾cÂ\ ÀiÀ+šÆ¶·Ûµêò…ýÈè_ÒùjTÅÌüßK©ø ge‰dK£I­wne Þè±siHK˜Ç¼EPpXê …ñÓ¯>;Ô½(À%À«pÄÐi~ÿC÷–,Ì#'‚ŠÎWM¢±ùg·J)l6Ó´¨(Q´ÖF)÷X”ºº¦ ü!±I³ývúF4ʽ¥l¸e#‡)Ø; xÁPú'þlÿPÿ àw>Y´yƒÏ~¨H§´m›¥E…}¬?¤Ø BQ•,+„þøï«_¿|D\<qJPENA(21TYUÁŽ÷m§eí*††øßOZ‹Fadd„ñ±qy†úe’÷µZ8íù=&f«]:çú5Ê׬bÓçþ€áÒŽ ýŠ—ÞêæäÅqª[.¬²cË ‰QKñÖÕ(]C1–ÕTÇ:ÿö¿ÙP …%ãÀ(”Qñ}J%¶¹v\JÓê¿2¤®ô_xüµ¥*aM• Mä'j)´{¿úìð¡…î/yÈm3¾éqèu{7Õ”ÜVßH«û~*lM×ùKÏâìŸÂÐ-5QVׯýG6 C÷Uƒî~;á4¤¦ÞŸòPÅPô,oŸçT'Þ¡g`’»Ï:¹­×ŽžòÊý¦ïµK‘á®Á˜+•zL*+voÿøó+KÜöø$ºë€R‰¿ebÂŒãJòÂñËêñC“Ûwìtô_í3.uD;Çú*gÖZØ…R·ïýöÂhÜwØáÔ´•Ù+ïßPS¼¦¦ŒFçœ[ÑÄìù}°·ŸKÏbøÕ7‘¦EU™Eã²%.E±KRäP Âþà²ÏFŸOGÁ²m©ßw/ÅM+ÒÞßR&=ácô„~/æ'®Æú&£ÛÎÚ~>¶_õœºm ›jS¢1µQׄöÃÿùpÓ¾;W‹ë€›©Ó€¼vîŸÿËñ+ƒŽÍ¢ªªJWRjJZöphÒ8öèï]é 6ÔØuå Êã7æ.UÛÆxì+ÛvîÒ€)¥”R&‰ˆP(ÄåË—Çúúúþc||üIॅî;Üm×´§X[빥ΫT;[¨smd)“BqyòM†"çþ-Ä^¾¨Âû­qyPùSÁsÚuýúX}m…;­›¦a¤h£’üìå^ë;ÏG›4¥”°,‹X"©qJ),ËšâÈȈ¼|ùòk¿Ì9ß2·"ó_°ÝaèÏ=²µ¹dUE‰Pªí-TÚ›1elI³%MŠô ”„@t”"›Muåâ\±ß+•†<¥"‰Ž,LK©õ %Ʀ¦R{r@TI TʶL Y)3¾B5±ï{Ï¿2*½"¡Q"‰‰DD8N»üÕ4Ms8õ>ŸÏ¼0Ùçqßf£ÝÐ~ñ‘+KªÝ.¤ŶJJŒZ"fˆw •+hcb#¸tƒ?¼}µø¾:뾉É#*˜Ôº_ïí}äÞºÖôÈ5 ›©G»'¢E•5îñññäwR’š–ÜNõwÓŽK)EYYÙ'GGGŸaŽ5áF¶>ÍŽvèƒëËj=, a§Ì¨#{÷€–¤r£@Ä¥b€àÃ[›Äá®Òð%Ëä2Q@½|zeE™¸kfôòÐ$ƒÂãµË3ˆ”r °Ÿ'RLšS!„K×õ¯Y–õ[0{Á9+àœšþý»j½õÒŒû—¹–5£Ä¿´ôî£2c9C¡ø×÷Üš}·¬?û/½Ñ¯ËaBX£¡Ò3GTk]‘H—lO÷qñã/¾95%Òï÷“MŠÔ %Å߉”`exÀ6âŸhüZþÀ}‹½nÃØ¼¾Â+’“~ºiAØšäÝKED¬x°¢ÈÃÆ† ñÆÃë)å— õüëW{×Ö6ÔÏžlON0MÓæ÷ûgšÄi ¥rÒ¯¦p2hü ð4ðfîÀ=‰îèÓ¾·§¾®$õ›.BØ™Œ¾›AK¼‡´‘ú^›«—‰“ÛG\ÖÓ*€„ç_ù̃5õ™’íÔ$ýX·_¦˜µgË3Ï/¾´‘fÀ##pZ¯ö©å·ÚU45Å^13FŒïRRKähàÖmT¹èÛtr’ȉó~·4#×ò·4>N%ÌçÉžI&LOÂ/ͰT¾ø,ñÿ#”=pMûäæŠ*Oêê`%!+Ä{…‚Ôÿž¹¥®Z íéqGOZ±@Xz¾í ìl)ò¤K¶¯¢GÎøC¦…E|Ö|ÀšÉ_:óÙ÷FLÊËìîiKÆ4QðeÑ‹ Üô²Z­Ãƒ¬QzõÜë£çw4·Ì D¦'yñÌä0à. `I®$enhfàaËgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<@BIDATxÚbüÿÿ?Ã(¹ €˜Fƒ`d€M#Ðhá €FÀ4šF8 Ñ0Â@&€h4Œp@£ `„€M#Ðhá €FÀ4šF8 Ñ0Â@&€h4Œp@£ `„€M#Ðhá €XpI0229ÏØÛ¯àü÷ï—ð¿¿ÿÿÿ§’úDˆÅ™ø´ÄkÌbh‰äÙßÿÿÿyâõ~âÏÿÿÿ}ÅÀðïPüÙß¿?þúõáîïߟÞ^¿>å3HÙPŒpô5 ĈkQè`OÀÈæù÷ï§æ¿nÕƧ*³0rEÒÿþA"øß¿ÿp ò*È¿ ÄG) ™@^ùDƒø0 †@Ý?€‰á0Ýâ»ÀÄvõׯO>~¼qõÞ½%oÊþµ€šjÇA†¡/H©R.‚ºsb®ÀÈ'èÞHíÐFmœà±p,Ù–,ùù½ç¿îøè'vå™wë„ÐGvõ!g¡ †B(QFŒÄ¤IX«aŒ‚smkk4Ížë”’\›Šñš¶-!„ÈùŠq ð~ÁQ‚ֲοS"SJÑó‡x-wþ×axÜúþâQß|¿`®ìq‚(ü†DÆŠŸFÏAacå!½†ñ^À!$Òà"â[´ÑPlfª™É¾oÞL€$9¬¸Ñ;¦{Æ-_Èy =²ÈðÛ„ãXð¼âØÃfí# ˆ"AàÂ_Î)š Û6À@ñÆm†eÿöáç Úx ˜ aèºÕý…òV£(jäùi¦^!i EÏÚæÆÇAXfhK‘ç¹mÕ©ª.GºC®[Lálüëý@ƒ.88¬àþû÷—'Ìå®À\. r#(÷"„™……›‹AJšŸAUU˜AEé²²¼@q`ÛÀ¬÷‚A .ú Á÷-º·‘(F © €˜h@‰dÖ÷ï ÀRá7ãǟîÝÿÀpçÎ'†Û·Þ2<}ú‘áëן@;ÿ€¨”…!°Ôzÿû÷ç£À’aó«WG6?y²í541 Š@ƒ&ØÙ-Öãÿ‹<˜O`‘Âlìl Â"ü jjâ ::¢ ÚZ 2Ò "1 Ü‹Ù4°DÁÈIÀ´¶÷óçÿ OŸý`¸vý-å˯nÞ|ÉðöÍG†_?"1üxLÛ¿|y´äêÕþ“@ã¾Ó»T@o€ð`g·È He21±s=#;8ÒE;;+ƒ˜¸ƒªº4ƒ‘¡ƒ†?ƒ´$0-€#9 'Põòã'óÿnÜüÈpîÜ3†[7ž«wÀÄðXzAJ`ã70!ýúõÉìK—Ú7ùF¯öz|Ѐ%`Ä{‹÷"`Žw¹TŸƒ€°ˆƒ²ª ƒ®ž,0§ 1ÈÉ0‹v {@õþ_Ê"ZG£*MJ  ââ+0?zòŸáêÕw —.=f¸{û °døéÃø?0!œ–Ó a-Pø ­z|Ý0âm_‹øß¿þd, ²òâ ÚºJ ZÚ2 J , ÀÎ+´ËFzën&H1 +ªýUˆÄò"+ÐnV =ll5¿ChJ¬ý¢Í|¬ùï=øÃpýê†+—ï1<~øØÐ¶ØXÀaýóçû³Ÿ>Ýê¹zuÂV ö¯ ,=@Ñ-ØÛ/RvÙjE} ¨%jб=¯ª&àc  lÌI2HI00ˆ ;ñÐ9)‘ðØÌÀÈU ¢øÝ»/ ÷ï=a¸ÿ °‘öšáíÛÀîÝ`ýž ù€]B>`ÏA”AYY–ACS‘ALŒœh~Íø÷Ñ@${¸ZMüøÁÀðê-ÃÓ ÀÆãs†+îO€ Òpõ ¾¹ëÍ›3wï.=E‹6z|]€ƒÃ’<`0TÍÿ Lõ ~º’²ƒ…µ0ç‹0 00H#žÚˆûO¢·!9”ãž>ùÀpêÔ†Ç/2\»v˜@‘þœ8¸¸8Øm 66Hðß?P¿ÿóòr3ˆŠ 2i08;›2˜[軘Œàˆ¹‰¢aDTAŸ>K`Bx¬ ?|Ãpâè†{wŸÝ*‘þþýùñóçûóΟoìê|CÍ^z|M€½ýb 9} ¾<¤Eÿ—AVNœÁÊV‡AAIŠ‹’ãÅ„!‘.êHËõ þ<¨¿qý ö-G8ËðøñKð@¨˜ƒšº,°=¡ÌáÂ`>//'/82ÿ» Râý»ÏÀ¾ý+`]ý€áúµG Ïž¾7BMMµbã}ÌÌ4À= ¦´4`d@øõå•V÷ï=c8vø ÃãG/ EHcñÇ7_¿>U{çÎâýÐjá?µ@Ñ,s}ЫŒ Œ‚¿€• (ÐÍ­´ŒMÕ9‰ùrR àDð÷é^)åúOŸ¾3¬Y¹›aýÚ} /ž¿ö¬m´] ŒMT„„yÁUÍ_`ˆƒêÜÐÒ”@˜™Áã LP¿‚Ú/ž¿gØ¿ïÖ'Ο½ÃÀÍÍÁéÆä L,àvUÊFPuÅm(>v~€Ú(ÿΞ¾ÉpòØ5†/Ÿ¿KªÿýðáÚô‹;z©Q Ç7@Q=89-çù÷ïïD`®Oi œ¯¬ç\ Ä%ù~S;¨'%É ÉiêÌ Œü—/>0t´Ìc8uü 0¢ù|üÍ¢쀹^¬ì㧯 ß¿ý{Ùà!\f„ç"†uAjXX óc_¾ü`X½âÃÜ;ݸ÷ .îæ %q ||œàDÀ@¥’Z€ÚÏ_Û/À ñòùG†}»Ï3Üö`nööK‚¢÷ï¯ÜjûA­@TM‹”€ºùV°Fž£>ƒ™•¸Q÷ûãE FxËž‘ÌÜЧ®–E ›7d0·Ôd(®b00RK¿yó `ßÀ~Õ© E.$Òq'H Òe÷å._zÈÐT½„á¹» Înæ U IàêáÏoê¤ÿH=†—À.デÀD Š¿MªþcPÓfdF>¥Ý,Pÿòå'†¼Ôvð„Ïâµ% â`¹§Àú4$ J|°Q8rˆñìCaæl†sgî0D'x3dä0üúIÝA(p˜æÞÁKÿØ$˜¸]Ç[¯vl=Åðúå;HÂûóíÝÓ§»+îÞ]7ø@jw=¾ˆ* B€9ß ùÛLùŸÀÈWÕeˆŠsbPQexûàÃ÷{Ôu€‘êgÇlÉÄ züÇ÷Ÿ ~ýÉÜ ""¼pÏr l —òÄL )!†æ®8Y1† «÷3;twü§OBÃFX†‘AˉáÛí¿ ïügPf ˆXPXÊ2€Â–™™SHFÆc¢šZB*Љ" Z„?u"Ÿe)jD™[Ì¡‘¶ ‚œ Ï/ýeøóôƒ¡#8×üûO9þ l‰ˆ 1ÈÉK1<¸ó XTÞ†—Z V>-¾RQ—dÈÌóføóóÃÊE;>}ü εÔð2µ/øÅÀØ ¸ l”^þË ÄÉf l@k@g@Ù8¥¤TUcS(MDQpt\äÌÄŽ|þ?À:ßÒF‡Á7ÈXü23<9ñ—á×c`ä{03°ó2‚ TX¡ƒr 773ƒ¹µ>Ã×/¿öl¿w¸ˆ§æø ,A„š3XXk2\»ô€áôñëઈþAÇ¿€M-¦@¥€´¬ƒ®¾Ã]gí¾Æe–U€-MN.V†Ÿ?þ0<¹õŠáу7 o^~f•T BXŒ—A×PŽA]K œ@½–ÿð!HܶqÔd•c¸uåëŸÄÄù D4 ’@@Xø03œZý‡áùÿ? ’, ÎîàDròøe`ÉÀÁ­ ÐüíÛË×oß^Øêý’RüÉ ÀÙy9ëÿÿç»zj F‰‘2ƒ»—¸èz|äÃÇ»Àbߟ…AèðŸß!AùŸóJÿ!A¦Öz Gö\dØ»í <€† 1‚Ý/3?p Ø’~ÅðùÓw`Ãñx\Ø¥„€ ƒ‹CN…;°×ÂÏ[ƒ€q3è)0ìÜt‘áεGÀ¢ÿŸÔ@÷ã/`Š«01h8²0\Ýù˜Xÿ0H“›÷¯ß€ÝÔ»ÀpVUnýüùÞó_¿>‡N/ˆäðïßï*`½ïþ X+*I0øë%Њ™ÇÀzêíÿ Ê–Ì 2ÚL ¿ÐvqüŽ®¡*ƒ¼¢$ùã÷6,?Íàê£Ëpéì#†);®]|.æ¥dE L´Ä€­yÐ\¼~ùžáò¹; –bxñäC×ì`‚à÷ÿAËÍðe5I†_O3¼xúïÿþ1ЀÂRɘ‰áÓKf†Çÿ10³ÿe7afpõ4eøðá ÃãG/€m"i5 äêK—úK€Zî€ bÌ ’€“ÓB&&æ*PÏÏÏÃàhÉÀÃÏÊðôü?†×@‡ Ê22¨¨*e$Z/)½¼ü î6 'odè®ÙÄ0§?ÃÇ÷_EÿoS`]éìcÆ ¦£¬óÙÀ£‡ ‘7P¢¹ñå³ ³ûÖ1œ:tƒa˪³ 1é¶ðv¾ž„8°´`öáíWp[¶ÜŒÊ™>yÄÈ)aäÝÃW÷þ1¼¿ù…›‘AT‡•ÁÓÇ’aÅÒÝÀÆð7QQ#7ßè6Ï ‰3F@D'—eÀ¢0\Ø@|7Ocy^†×wþ3¼8û—(ªjÍÌÀÂÁnôLëÅ: 85Ä€9™…•aßæã ï^b”c°u3fpô6¶˜ÀÝOPbµ„¬ƒW°=à N¸Ë•b,Í @ ƸÚ R‚…‰˜ˆþÁ©PuP´–Ò#øþ‰áÝ“ ïþgøðüX Tâ¾vÙø$x¶l< JºÌ22n©ÏŸ9ùóçûÏÐ"¼ €Xˆ/úÿ‹~]P½o¬÷Lä¾¾gwQþ‹(]F1eH£4ìË@§%… œü`öÀ†‘©.°áô¼È‚›‡¼º÷Û¤i8´,öXSŠJÕr3¼}ù<ˆÄÁÉJÔX4#hÛÁF°_I^»€eÈ}LÐŽÜP¤»Ðo€‘þØ þùbh­(q€0¨·õæÜ_v~}y†{wŸ0\¾xØUUʺreêh[oU@,DýòÀF_1¨$ ÀÃàìfvÄós¾¿ûÏÀÂLjÏ=`5 ¡ÎÄÀZAû:ÖO‡„²ëÇ_ðš;.^fHäþ@³ÿ?¶D ZþýŸñ°«,AˆAå|P0³)ÈŽ¿É(ßak ËÔA-þÀþúÞ†·À¾ÿèÞ#PIÀŒ%–@ú~}ª½ò‡A Ø(´±7dxôð%°*ø¬ Œí……õÞ¾½Zü_@Ä–%À®’0hþÜÊFXÄr1¼¼ùŸáÝíÿ L¬|ÿüŸáêî¿`È›01ðŠ1‚W·ý¥çÖíb&Ü'^1|ùøƒAÊR<^€m¼¼~þ…á°¤ãàCÌhY çvPÂýúŽÀEú×w àI&P:d&¢ %ŽÏ÷ÿ3|”þÏ ¦ÄÅ`b¦É°o÷i`׃CVÖ=˜Î@«ï¸Ì ‚ ÀÙy,##Kh1hÂÅÄL…á°X}qá/¸Xb‚š|:üÕm`#XgI{R:L œ|Àúô7}«¢‘@w]:q <¼k`.ŸCÄ?vß¿õ†‹›“ADB¾¡„¨Q7hÿë0Òž#þÑ`Ëþ?°Úü¶ ”ÓAjàë ÿ¬‰ÀjÞ_ûËÀ-Πg ¬n3¼{û‰AHHKOPPÃúýû  B¬I €ˆ dL ¨ø7³Pcfex{˜ZgbÁt¨1Šð‡gÿ1\Øð—áá¹`2AS4¬ÎH \PàîÕ —ŽÝf–apôÒÀ9c† ¾|úÉpóÂK>~n)y p"Âi´Ìóÿôê?Ãc`ƹy.gþ#¼0•ƒn Ö>¸J`‚Ì ‚—P Róã 0!=øÇÀ+ÈÊ o¨ZvÔÏÎ&-íèT"öÀ¥ €ð–®®Ë؆ŀ"_X˜—Aß@‘á'°Yñææ_¼¹ìÐ"H`µp÷È_`ul­j11+01°qCZ·°¢÷$àõûßþ1ì\q„áËûï éf â2|ðÈa\ÓáçŽ++úïß_î2àXD@Lø[þ?A[³”AçZÚr Âbì =òš3÷ã(ò@)û+°¡xûð_†Ë[ÿ0<½ôœ0À{w™&ˆþÑÃÖ!€ŠÚC[Î3\=uAÓ@†!$ÙÑŒÀ1Kû6Ý–pÿ4TXØ ÝK˜ù°­g Ráóë ϯþex|æ/ë[ÀFݧÿ-fì°±aÛÎà43t—2¤$`B¢aU,V·V0{d_€ÕŠ ;ƒŠšxˆ]WJÊÎ4t+³ þ “(7€ÖÂijË€‡ÞSȳÌ$Ì=ÕñO`nxtö?ÃË[ A#&A9`A€Þçe€õ§i4¬ ž,âb`¸~ö Þ•Ç]&v†Œ~!NxäãËý7€EÿÉ=€E¿ƒ¦± ¸åË”àYJ`Ýþý=ÿÖó1pngCè×Ýÿ!Cäpú”†î?ƒ•LP±ŒNÞªÿòè/ƒ€< ƒ²š Ã…s7Á mÇ·É€š.@ü]@áLnnËX}{Ь¨ñ'§ Âðí#Є§ÿáb[½È)äù¿ÀôkPcØ­à•bÓ¬\Ôÿy#µÄH«ÿÅÃO ›fïúåCr¥5ƒ™£<´´ƒ¬ZÆù°Ãe“N3|ùð“Á1Ð’APœ <Žðؾù Ömoöx5Ëxƒì—ÝM°ˆf€5Ša4›‰–(@‡@ÖÍÁØ+XVTÂö;°ª!HJ‰K^pc‡GN†™™Cþïß—°%€Â™€Ô %ÐlŸ¼‚(°ýâ:°Åú™ÄÅ>´Q+Θà‡/0B¨ªß3!·0#§ó32°F0{PZÙd$ˆÿÐåã_€‘¾qÆ^†'·ß0¸†j2DåšÂë}Øn!\†Üt‡áøŽû 2 Àú_‹áã³ÿ ??C#ý¢Þ×íà ©À!ìÿðÜô\ÿ:f ’ƒ±¡jA+–ÿÿýìG4´šù‡ž˜ ë0<•˜¤eÄÀ‹Y98yյ߼¹ZGø }x €Xðš%¨vaF–”´ ¸Þüüòس,ÌÄE>¬^ƒE´4`‚–ÿFéÀíDuŠp&X ñZü‡Î3À†!c „ ù/ƒbgÀ²r €ð%FÆ¿(}y\½0&´…äZh-q E(¢`Ä^ ÿÈb (¥#<1€·‹³32<¸ú’áÉÍW *º¢ n‘*p÷‚Ö4`°b/"QqšáÞ¥÷ :ÖJ N&îèȸ=#"bá ?h—R@"„©îGèù‡Ô `B’ûÇé#"þ æzhÉKÌÐDðj'¬:bD­–YXÀ‹ذ%€ÂÓ ü Z]Ê /V Ôû¨õ5"2áíôÈG® ˜Q¶ž¶‹xFFÔj²û?ÃõS÷~|þËà¢ÌÀÉà Ïý l ?жì5“.3ßò„ANMŒÁ#Áœ Øþù)úaÝÏ H¹)çÃ*s&hߟÛ R}K(°~?¤@þüGªÿQr=¢—ÁÄ€‚Ùó˜Ã×þ|ÿ |Œ˜ |ÝÀÏÀˆ”Í€’2 +ZRD‹|&fDýž `õ8J;€‘ó™Q#–X°%DB@ª.ªpxÛ,ß>}gx,„Åy¬}äànmUÇ6 ÚÌrçÒ[† So2pÛ=.qÆ ÂÒÜ ?¿ÿWð^%¬øÿH‰¥¾ÿÏmøýG)úám¤A&hÝhì1Bûûÿ‘Ì QÿFÿG¶•L”ùŸÒEõ0 H@½ «%0FOO ðï## x›ôß?ÿ8x1¶s£D4#–~>–:¹4™âhâ¯Qr;#ZB ù>¿ÿ–áÓ« FÎR ’J¼ð–?¨ë‡ÑîGʆSo1|xþƒÁ6\‹AÍT’á÷h·Ú/‡-q‡Ç+rÎÿ‡4Â÷Ñàsòx ñ°ÞzñoøA[‘ȉìö¿ˆFlÌÔÛ‚  ±КÆoß~@§tý¶d €Xð¬|ÂÌ̪:BTlrò°‡9ÿþ‚:£•Ž(Æ™±µìч˜á³]È%zãWÃh %P7íå½÷ ?¾üeÐ4A,¯†nþ`DÌ`ecb¸{á=ÃéÏDeøÌ|Ô¡ Ûÿð¥¡yçÒ3”œÏ„4e‹Ü`„õïÁ“;ð~?r•€Üíû‹Äf†&†ÿp5ðÄÀ„TA 2—‰ ’~ãìÛ×Ш>€ÖþÄ–ˆ w ðû1dÇÌo†÷ï¾0° å„ìëG^ˆL30!ÑÈÕÚô&J䣔˜HÌŸ:e†.˜`FžNeB¨öáùW`¢eg×@™êÅVü3-;»ë%°ÄøÍ e+Ç ¦À :ï¾B‡ÉÌH4²û‘§t™‘6#²:¿‘ÇE°˜1o i#!‡ ú¸ ¬Q ŒVnFð(凟Áq²óçÏ÷_¡ D1Z¿Ä„{2èçM°f`ùùÓ÷ Ü àu~ÿ¡]&”œÎˆZ×3áÎ9ŸõHV˜~äÞRhÈÕ 3b5 xØÈûòö'ƒ˜,7Þ¹~ð,Ú÷? ·N¿gàäfcP1‘@4L¡ì´„À„ih‰•M%rá áxD"ëGï)1c–ªŒHâ°+?x¨üíëàÊÄ_¿>Ï9Pc…0@áL?~¼;,.ÿ‚ÎÖyôè 8çƒæðYØP€ °;\#|ȃE>Ž%B‘ -`Ñ„-‚zÓ?>ÿïâaGªÖþaÖÿ@;~|ûÃðìö7n~Ie~øª!˜™’€ CåYPÝŒœ€™pål˜ß˜ÐfK‘çM0ÆLJ´ê–ˆ@na燬%xùgàïïÿwïn<‡.ÅX@8ÀÓ§‡¯@ƒ ÷ï½fø ìN I32pð!5ÑŠ!f¤AŒnæ, J*fFõcbbD Pô\„-ÇA#ƒ?õ?h•/+|´ÛZ?=_Þý&˜ <œ œ@õ°H¯ÉcÁ´!H¥¼zBÏýè«{P9#Z‚Gk¡‡rfcBÊùP1PÝÏ&ÀÈðýÛ_†çÏ^ƒ—É3ò·OŸîƒ…¾Á¶: €p&€'O~ýóçÛIÐàÈ«WÞÃÀ+ÄÀ ,IaðË‹lF¤â¹‹ÈĈ³g€RŸÁÅ1‹x´AÏauŒà.+°øÿû ŸS½Ø{€6`þoùm(AäxL [¨É K,ˆ:š -2™°·Ð{Iðž3î¡qŒI5FÔÖ»g¶ÑØx^<{l·}l}üxïÍß¿¿^¥ßb«ßÜÞ¿?ÞnE¨ï|åòc°¤4™!ÕÒÐ,ŽA&dy&=&“GÌh“Gh¹³ñ9å ²îŽ‰‹—á/°ÀûòþÊ †'Ý%1ÈYßÞBVx22£í8i&¤!|@‹µÄ@««‘4ÆXZIÈ„VÀÃÚ(D/!9ĘÀüûwÂúÿõë  eá *à#–½‚„wr÷ÁƒÛÿþýñtÒÖ¥‹Þ½ùÅ ¢ÀÈ ÅY³Ž–óQl˜‘Æåq ç"çäœÏˆcЭŠtF¤²*‡X”³çÅ¿¾ÿƒRÜ£× j… ”`ØÀË»~~ÿ nEÃ"Š£ØF´ô±–Hm”Æ.Zø`Ö󌨋g°4¤ÑÇC˜`™ ÔŸçœ.öùã/†{wÝš ~ûíùó“ ósž@ ¼ àÙ³c¾»T”¼~ý‰áôÉû \ÀFµœ3Ö!XL6#JNAî6¢ÔqèÅ>ZËš[$ !#WàÀÊÄÀÎÉ ÈùöÑõ‰3AGʘaX]°q013xŒã/hØ—»½ÈÝ?l½”nRc½«Çˆ”ÈÑ–® z .ȘQßìâÌà°›×ŸÀÅÿ‹gž{s  ëî €"´1äÏÛ·×æüû÷çÈÀC‡n0¼“’jŒÀbÕ+®9FfôñysüŒ˜“C̘]EDqLjҀB `úÏÀL¤*|àiѽóž2¼zðáÛ§? ¿¿1‚×é}÷ØðûÃðõÆÏ@ÿì›ÿœáÅÍ ÂRÜ B2ìqv¤Q »­ƒ‘ P¬Q‰žÓ™°5–‘JGô „tô= /°ø6f?ýf¸táx  ñ?>pºø%ŽFˆàêþ«WÜÕÙÌÍ-þüÙ†cGî0øj2(™13\Úö2£…± LØ'i˜Ð#“s轸Ã*fÄk`FM| .«‘¿$Ã}¯NoxÃpûÄg`î@LgþƒÖ°ÑºO¯~Í.Ež[ˆ|*#ÒHÛ4y¡Ò¨|mTž ¾à:¤Ë¶EL« ëƒGA~û™büÏ×È´6€6÷Ï­d—æ~`à¹;À ú¼ìéÓÓO?~*þïà*þA €ˆ9$êçË—gûÿýûýt1Ò¾½Wž=ùÆ ©ÄÈ £Ã^ˆˆ³`ÂÒêEª ©š£_ÏÄŒ­q«ï1s!zW Ô°Và`ïÕa0 –h/?0Pÿ‚F2¡ã¶LÀ„`cA†°^-“` ð²np1Ï®*Àk™QGð0FwYQqŒ˜Są́aƒÚ°fÄ–ÈÝlPµüuÿ»×ßΟ½.úÿüùñûîÝÍ eà Í ÃÀX@³;øÿõëË/ k-åçWÌxóú ÃæçR3¬”L˜¹çøœðÊXxËŸ^LášÊe`DËÍ8æüQr>Ú<¶©b˜YýgPãbíÖÏ €êzPï&ÞÖýû?ÿ&`››¼ð6®ÎÌ€:æÏ[ˆ¸{>Ë÷Ñ¥üLj¼¤miò¸>ò"t¨°q~&èp;|µt®>Ï]ÇÌõ¬Àºdö©ã]¾ÏàÜÿþîûŸ??¹Tv Úýù† €ˆÝþãæÍU]ÙžìÜòÇŽÝeÐÒ‘fptV`P³ff¸²ç/¼Èc`D_Ô‰cŸ™ÞŠeÄR- Œ0cŽ‚11ãYXŠT°ó€}Ì Ï®~exzé3d\èV>)-n}^`¼“fò‘/ÿѦ}!E?#t¶ï?|^e?ß?Ä’n¦ÿH;{˜ÁXq¡aTØ”/#l¹bµøL Xb©vû@ýþë—1\»z|.òׯ/¾Üºµö4Põhý÷`i€"6üýúòS`Ÿ²IZÚjè`í5«N3(* 1((ñ1ü0cb¸}ò|)5òÚ<&lEr¤3"&‘°..• h‘eÖ±TŒ\"êÅ[û?2žõ„ááÙÏ _Þüfø Í{,@Çp °0Hjr3XÅK2˜DˆAöú¡Xõƒ:ýËó‡¬ßû_íŸ×G_Éói%H3dÁÒJžÿLˆeäŒÌHm&¤R¶o@ˆ‰U€|²É‘C§!KIÿÿ»qcÅÅ?¾ƒrþeB¹ˆÔâll§ (G‚&‰44% ŠœxxYnŸúÇðøê?` 2BFʘ1û»ˆFp ëK30c;‡ a¬)dÄÑdž&fè(Ý)OöOz^$§ÏÅ íÀÏ (ÅŽÔ/ï3Ü:ú™áî©/à6ƒY”8C`»;/3äŒ#,‰àÿ´½ÿ‚Ðÿÿ"¶ ÃÔ@ÖéAÕüEÚ Z>Ý\úi“ì¤ §ö„ >ènDa`]ÿëæu{žÜ{÷òåù ;‡vñq,g¡Ç7@‘zLÜ' u&&ºœœ":ׯ¿`X¼è$Cz¦ ƒŠ)ØOoþ‡$ôî!ÆÂMÌb› £¤`Ä”gBfFïC1+'ÃÁ©/vu,͈m‚mŽqäit\]a¤F4ÌîÿÀ*Q,øÀY†kWnƒëýïßß~»xqÖ±¿‰<í÷un @‘sVðÏöœ7¥ÿÿÿùJÛ¶\aXºä,øðdM+&YM&¤5’ØøÄ‘§›¡®dÆÞHDÎù°å['ç¿føòêƒGž8ƒY |1è—/ßQ6‚€Š~бœCp4¸5v|Þø^~XW‹ù*Yt·b›ÎebÄ>®Ïˆ9Œ‹²¼ Ë< Ìî¿ìÀŒÅ‰ü#ÀÈ?wú xÙ÷ß¿?_¸0ãÔ—/ÏÏB‹ý D DîaÑßnÜXµáÑ£ ÿÿÿþÉÆḬ̂š@ŧР#ƒ‚|$®Üž˜Ðr4Ò)¶efÈ 5@Ôˆ{ÿä7ßDä8ÓDG»#ßÙO&A ŠÆ< OÏÿ`xrîxX9ç3 %X21bYÈ‚<´eÀŠ­¸GJ h ¼¨ùy ÃØG#ÿÌðþ…ÿ~þ¹tiö™·o¯ƒ®¡=:€„cbA €ÈM  üxåÊÂOŸï5M@«jA‰`ά“ÀÆÉ?%]FUS&ðR2Ø©¡¸r:ê02#ê<7úì!¶áShí*~qù;Ã×WÿTÍy%Y¡Ë¢ÿÂWÇ`÷Ì6N&M{^†¯Ÿÿ1¼¸ú\š!»— Ýý°RmŒ‘ÇNhô9äHGÚ …¬dÁOV`Îçd/îØ¿ûÃYDÎÿsñâœ3Ïž< TyÚê'é h ò¨Žy{ñâì)þ|û%/ï\ lŒ°ïÚuáý‡o ))æ rj\ <üÌ ®þ¶º!!ôgÀÖ%D@žn†ç,;AÏŸŸþ'u„dÛà@ ïÉoÐ1EvðŸ^üE¬¿g@¬ö…o AÚ碅ÕÕÿ×ÂÝýiûÚ´ƒ/` K™ì€ªæ!†¯ ën€Þøöéþ=ÇîÞ~»Wð70òÏ>{v”ëñYbº|Ø@Q’`Íé×W¯.l€üTPp®äääá;}ê!ëWŸÒÓ­tõD€1f†§wÿ3¼yü²ý™{iÀ€6u ߆>ÝÌȈ¹TiÓ(#ö=;°oÍÀÂð X €u˜ÐŽ·CÛæÅˆž‰¶Ÿ¶\Ú¢‡õça‘ Øú€Âç°¹l­€Wa?yôØÚ?ÁðêåpkÿÇßA9ÿÕ« Ç¡9ÿ tµY'25î Í2½ºqcõü7Ö”[¤Ï99Yž<~ÏÐÞ¶›aÝÚëàùuF#&^AÔÂЫ&,ÝFôÕ/ðºKõÀÊ5@ø÷#¡1 :©óÐ~q6Vf¤ž #fëêÁÎ&@i$b Q3â…ò#þÃ/&†P ϾÁ°yý†7¯Þ‚#ÿóç'Oê9Œ|P®ß ħ)‰| êpIì¬ûøñá3]ÝØf%ƒŸ?ÿ0,ZxŠáê•ç 1±Æ ªªü |À>ìë§ÿÞ>ÿ>Ë—…ËÖo&ÌúÖ8bBj5£L‹2BMD”Ù€% Ó ¿ÀZ@sþ°«ãpzAèÇç2p0±0ˆ(±ÁOëF>Ö½øÝŠ;µ^20!úðŒH3yð¢©‹Ì *î¡÷˜`¿þ‚”ŽÞ|b8vøÃÝ;ÀÛÕ@KÕ^¼8ûìâÅyÇ~þüÊñÇ ãüï(¼d €¨}q$HhÙ¨Š‘QV¹¤¤I+h+¶C@ .ƒ»»://°ž6WÞÁÇwÐj:‚Ç„XÞ}4‘s6¬eÎÚýŸaŽûS†—×1än‘dÐpæ„÷¾ÿ>ðr5+3ôZ9ÈUr/nþbè¶}^M”³_šAH‘||_?òA ˆ øäÝ>ÿPGýà#|#z Å 3?edøü ¢÷'0%\½t ÜÅûúå+xt4³wçΖ›·nmù ~þ è/Uî  Z\Ë=‰BVQÑ-LIÉ=“›[\ t hgŽ––8Cp°ƒ‰©48’?}øLñ@ß|†V“LH+r™˳‘Y0Vã • 3…ö·dØVû–AÞ“!{³8/$÷ƒOÙº–@g€À‚ø7 ‡}fpÌâg" 9õi,˜þýÇÿ… ;ÿð?ÒEY S`÷}ù‰ü¿Ð!ß÷ž1œ:q‘áùÓ—@¿AÜöáÃý÷ÀöÕ¹·ooœ‡÷ ú1tz—¬óÉÑã €hyy4¨zccãÑÓщË–.Ì̬l?þç:cc?mMMqpĽ¶a_=û_u‹mI3t€¼ó†uG¬Mýöú¿b¸wòƒiCøA>qH¥þý'$fY€ÝVV  YÀÍuöô~bUeeHß*¬F@;‚QçЖÈÿ‡œHþ!ðùr’د D‰xØXÿ³§¯ýúk ÷î<wõ@Sýþýý÷ƒ{ïܼ¹öô¿.C[ù >þk*ß @´¾>ž z4‰œŒŒ•—¢¢K‚ª&ÈÎ÷ï¾3xûh1äX›‘áñýÿà˘YŠ”À_}‹¼4‹‰3€†ƒŸ_üͰ"ú-ÃÓ¿õÙl³xÔØxD™ÀÝÂoÿ2Ü?ò‡áø¼o 7þd’daˆY*Ä îȾ`ùœ)x$ÿC+öÐnûb@½&ÄM,J·ÏÀˆÿþ *ö´ïâ%ÃÅó7õü# ÿƒÛ) ·¿xqáù­[/¾´ ã"?"·È'”ˆÖ ¾ÿˆEmlj……ÕS@Cyy!†úzWaQN†'ÀÈÿrú3ÎŒ¨bHC¿ŒX0Ù=¿ô‡a[ÉG†›»‚'iø„™Á3ƒ».?í7ƳŠ5;ƒ_ƒ²øì从þ#öïÿÇU죊`Pdƒ"taÅohžýöõÃý{O®^¾ ¾âþÏ/Ð dÈÕuïÞÝy{÷îöëÏžE8h-ß%h]ÿÛž>j%€¢W`ðñ™ÅÌ̾Ø`æà`a¨«wcÐÓÖyÿž>„´ÖÁÅ?ênäÍ¡Œh«rÑ# ­»ÆÆ :¬š¿3\Ûü“áÙ…ßàq~p#…‘AÒ€•AÇ—A/ƒƒr­íôi`ì ?˜Â 3ˆAUÆW ]ß¾A"ÿÏoØyÿ^¿zÏpóÆ#†Û72¼}ó¬4š‹x`ïéæãÇGa~ˆA7„¿€®ä¥êÍ;èñ @tI¾¾ó왘X6ΜmÐÌ͵aððPfxìÄÜ¿ñÀ,¬H9©ÈßLj1ûÆ„4eоѶ&T€®—ÕÁ??CæßÁm 8èœbPÑôç?tÐ-´ÿ£Ñ¡­yPà T]n%aÐõx?!z ?~üFôG†÷Ÿ3ܹý˜áù³7à™HÈEÖ ¶ÈßoÞÜxóøñá;HJƒ"þ+%}{R@±0Ðøù-0`ddZ´—TôGG#ÿ0ÐßýÎ) ®Ò*"än7$‡3""É,ÿ!¥háï?HŽûûi%l Ö_Èù½à„Àˈ’8@Ù÷×?Ô.>,A‘ *ÊA'ÈKjpéÊå 6¨ÿé„0PbíÅ lÐ=}òñÏÞ¼úÈðýÇOð¸¨ÇÈùùóÃW¯.?Fú­×¯¯Þ„.ÙÑ÷ ÿ…V  "30ˆ¥@3yx¨€>8`ÞúÇðí3äOFœ©Qì‚"› èZV$üöío†Û·_1ððp0ˆ‹óLXU „òâjرòðf@œÄ N¿!GË‚ÎLxýú°ÑöØ’ .æA'r€ÎVmÊåvvvH?þíÛ›oŸ??óèÉ““7ýúü:e{Ú¸{MËO îÚu„¡èѨÁØœü '>ˆŸÔÁÝA1‘…ЊB‰5‘Ø[¨~±k»Ýôžû:çN~m| % ΟÃ%¢h¥Ü÷q'ƒ¾3>CÝpÑR«f©„lãÕ ùv6íïó¼EŸ°YïÁØ]µFÇD8ð|¾gÃ[p]Kí &½<Š;7È›tƒJˆ¦Š‘ D/1R3/é6H3€Ë_Í›‡Ú:ZÝZT×FbvKYKc Å™¤Œ¢/(lÒFR!jQIQ–‡<˶ çL³sÒÁè _ºv‡?ž·¢I9ò¿}ûÅ`j*ËPVfÏÀÇÇÆpÿÖ†'÷þÃ×íwà°2‚§_Asðœ\ 3ýÉ tèYûïÞýf¸yó%ÃÉ“.^x Ìý_ÀÎ>º•~í+xýÜ¿ÿàF(a€äAÇ»23Nd‡Î£ÿgààdcà䄬]) %„œ üñ?¡ÇÇÿß" :U $;¬4rÈk}­þýûëïÏŸŸ}üøñ0Ò¯?Öïþü:™´)Dƒ¶g¿‚Ý~¡´/OÍ6@Q=| +åõKùò“ÁÜ\ùîþÖûÿ!ÇÍ[Ýì\ @ŠxPd³Bϲ5ªÞ¿ûÁpëök† ž1\ºøŒáå«ÏÀ"ö/øD/Päÿþýí×Ë—žÿû÷÷'/—++7;+3ìaøu.°µüÐ&òy¨ÇÅ2B7\2"Í€äA§eüþ²óÛ·7_¿}{ýéë×WÞ¿¿÷òÇ»Ïüøø Úe{Íá ¢ýtmÞWhWî?Ãôø ª&?¿y ÌÌ, ÛEy¿ÿÍ`g¯Ì“m Ž|P_øë'ÐáÓ àÜ~LßO`kìÃûŸ ¾g¸w÷-°nÃpçÎ`Ñûá×OX¤ƒ#êÿ§OÏ>ƒêÔGŽÞøòåù]h.ûÉÆÆ#ÈÁÁ/ÆË+# L ÂüllÜ\ÀDÁÉÊÊÅÁÌÌÊš›`eœ¾ˆÙ¿ ¸¿ýù÷ïÏ`DÿæìŸ¿~}ýþãÇû/ÀHÿÌåo¿ÿ(þºøâ#´(Å¡9ü´xÿÃ0Èz|Õ€¿ÿü&`ί…çé©Á–f‚±îT”~ÿñ‡áÍë¯ /^~axñü ÃãÇøógŸ@UhòTÌ‚Æé¡³ÿ¿}{÷ýíÛ/Ÿ=;óàÅ‹ ·€‘ôÚºÍu jUpBGa˜ :7Â쌌̬ÌÌ 2ˆ}Ñ(òùüÔ¬?Ð1÷ŸÐÈüÍÉŸ¡4,’@ûë¿c„JDq \Ì,‚§û·ÑÕ7ÿÀ>À.Óo†€¨Ï?4¨!õƒá~÷î;0’ÿ€[Ó ¹pk”… ÚO†Ø ZòôéÓ“OÀ"öÕ«WWŸ»M÷-êgÐÆ¬QõZÄþB›¸eF0› f²Êé/üš(`‰ãï@7Þ¨•ˆ¢ÌõJ@uK€¹ÊeÜ—•œ‹A‰v;¼=õ ¾ú41òçïÏŸ~þüü#°HÿlL½6¤ž}ùòâ)4’_@T/¡KŸ>Bs%]'F< Ć-@o€";Ì÷f¢@u"Øúï°Õ sü-ê ÓªþüùùççÏÀ:õø ¬[?ëÕ÷Ÿ>=zýõëë·Àz÷ R}úÚ¨‚Õ­_¡Åí_†Q@µ@d%ÿ¹Ö@íÀ"™‰,@Ìl!3ƒú¿ ¢ØúŒp`dþñçÏ÷ŸÀ†Ó—ïßß}6ž¾ZŸ9þ 4B¿BM°Õ'¤FÔw¤†ÔÿѨ£M rKP*ĺ «IY‘NÈ4 ÿDj,ÁN?¡u*2þ=TëÖ¡šˆÜj<Žàä‡6´þ!5ŒÙÈô(F:Qw t FBW¥‚á ˆi4F6 Ñ0Â@&€h4Œp@£ `„€M#Ðhá €FÀ4šF8 Ñ0Â@&€h4Œp@£ `„€M#Ðhá €FÀ4šF80á Fİ»‹jIEND®B`‚ltsp-cluster-control-2.0.3/Admin/images/configuration_module.png0000664000175000017500000005215012026403127025260 0ustar stgraberstgraber‰PNG  IHDR€€Ã>aËbKGDùC» pHYsHHFÉk>TIDATxÚí½y°mÙ}×÷Ykíá w~óÐó(É’-,É6F<áA.,l1€¤†T¥B Š¢ Q&’W NccÀ€ãcµ ²Zc«[êá½~óxç{æ=¬!¬µöÞ÷õk©Û’0ý`Wí:çžùîßoýÆïï»ÿqâ·ádeeE|Û·}Û`}}}˜eÙ FdEeD]a­E;Ρ¤`¹—ÊD©TH™(¥”µÖàœ3ÖjkŒ)µ5Æ)¥S ‰ð_\Eypp0¿víÚâóŸÿü°átßíŸë>Î]¯ýu]ûîxÿ7}sºvêáž­‹Þ;{èñ¼×|´Ð+£y!O?‘þgß÷½?vôT~d­Eü…ò.¡;^¯$B!Ê+‘HVƒ'Vƒ'âë|è¡ÿüwÿ®ß€qÎÔZOžûäó/ý¾ÿúûàÆÕË/ûÀTýF ëkqüä¿ø™ïϪoWRø ¸`ýîi;‡¯|iŒ„ƒø™á…í'ßmk;Ÿ_ë:ßïÚuA™šÏ‡«{‹g×bH!dªT/ÏÓ³?ú“?ó=žÜ¸²¹¹YÅ}iŒã[¬s‰p„0϶³’%²¹jFx ÞRtÍ¿µþ6^dÂ:¼qñŸá:ïq¢ca´Â–áƒeÒß§ëÄ—v _ê~¼­ªZèÚ —Ö—ß Œù}©—nî †ƒ gÃU”–^¿G?KýňW4^|Bë°ì\w‰"ïa1ζBqBx— \p^y@à‚4e°÷în· Ó°ahÜBŒ/šßÍáÔ%ÍkÞàVã¢ÂZc_yåB–îK@¸  —öøñý.¼òiòET)JJ¤’(©B’$á{…hÊ]>J¼þ!4¯¯ß¸ÍÉä…«_”øDDÜw ðçŸyf5MÔ;\°³Ëxtà¶wnsùëÿºp«§QdËÞÔ×SÈKÒžAå%2«QIE"J„ÐW!Œ[#mͲ4\»`p¥ÃÎü¶¬pXëpÕWpÅ §ÇPOf¶ÄéêX‹¨+„³(cN uÂújB–(œNqYB$8ÙƒZÌH3#±%Š i*¨K°g„4MRÎ>ù?ðWþZÊCàÆ­ÛÝX«zY¦ËÅ\ú¾S€Ë›£á79·n¬ fU0žÌ„\>Å\f–†« ·!HÓ”ºH‘.,‰P¨‘IÌáÛ´­×ƒb îˆLu#xÙšìÆ>3/%å_CNúÇdx”ðôãpf  &DsÖúxÀÆxm3ÎQGmÆ8jc©*G*³…ãÙWÎsóµK}òñ&–Àl:fºus<•„Tð¾S€º®ådV²ºÔÃ9’0Pª£¨˜_…[£aéÔ(^8Ry»(d˜hÍk›çÁšèû[ÁùcŒ6etQø Ÿ}'íïHxï;`mF (kеÿ_l>¡h@¶‚Zû×ÕêÊOiý}wüÝ,oÌ1¦ým‰€­ý9—¯^/œs5P•|SWõmtœ\_z§Åa}• !³é˜29~hÅ"ý…©+Ø8 Ë«~•ÊNð!  (G0Ÿ‚Õ ¿uÆ ÆYÆUëLp ®“úuŠƒ¥|Ûû`e Æ…¾Ñá{ïŽ<Ã߯¶Þhã• ¤uå¿o  ·œaÃo³áw]»zãgÎ8|µ°êûN~ßÿ_ÞÝOÎZ¬³ `<Q$TLÇ:·Î@QÀÙÇ`}Ý+A|ÞASL.ÁÖUÚ»_GóJ€õÛ^lLx”£ˆwBð¡SðïóNxZBU{¡ºŽÂt Aј®ðµ?ÓÊ¿®—Á \`H1οކϽvý:'6Vb5°æ~Œ®ÞÚ‘J\XBÎ:æÓ)s¹âspÑšvÿ<˜¦ xòq¸q vGí•&^9maÅÁ’8ÒaËö½M|Љ ’¾épæì×°¨‚ðïZñ¢ÑÀöwjço´ÿÍu YîØyæ_×/jd°>Ý,`21ÜÞ¡-ëûÎ[î=äœÃ:9YgÑÕˆ…8Ö&˲­Å;ü…ªk8˜Á»ƒwž / ¯,ÁΕðâ`îãU½»'îRu ÇÁ÷}+œ85̃ð­kÝÇëŽP82*‪ ’Ô[œ¾µ0ÙcVa#XélŽL2^z嵿úïOà”ü&ç\p¾¢R3æ¬4ˆ¶Õul¬1P”°7‡‡OÃGž†<÷J°Ô‡¯P¬"B”Ÿpè;düz}øà{á;Þu£feðùá3£éG´JäÂ蝹¾ &¿®ýg'Ê?ŸõüíÁm(ç0ÀR[°Æb¬Ïv¶·‘JñÀCZZ`î;páÚÖÒúòÀ€Š¢ ª‹J1Xê¬Óœ‰rÕ%lÍáô*|ÿ×Á§·áÒ5¿ŠxgÜië6Õ<Ù ?fYžxÞù„ÏökXÔPêðyø×ÙPù‹„±­U0Öÿ®ª÷kÿºÞsÈ{>9¸º‚ÊÀñ¾¦ÒÓ¤‚ÙhD1Ø~¦æø ðþëž;wNmÓÆÿ;GYVÔ²«òÖ/Gau˲aÅiã…´]‚ÎáOÁS+ð /¼e iLUÈ’ð™Á,-Á£Ágýk'Ưö:1y„„íðfÜv¯ƒ{j"zãÒÅÂû£aï&èœönåÑ ÚXlP!£¢Ä“òÒ«¯Œñþ¿â~ ?xîÜÃyªÎx`Ž@àX,h1›b4È­™íÖÖÃb±!Ê.*˜H(Xxê}ðÔ{as n܆ñ8f”w½¬­Ãú, ýçÌk¨‹¸™Vè’ö»ãJé¢ ¾¾ï±¶}\×0x·ýÿþM¨æ^øÖ€­áIJ¢ÒÖ·²ñ=ã­;»˜¤çªªªñ«¿â~snì{g"{Ñ `6›Q‘y_ÝådÇtº)Ö…•gàÖ5쥧.Ã#köÕø[,ÈΨ\7Ÿo\ŽlKÈ„hÝZŸßWu¨1Kиã=•…j²ÑmXŒ½q1 ]Ô ú`´ ÖM e­[7yâñÇì…Oÿ²  ¹ß\Àd:—‹²fI¶ˆŸùtÌÌEHp5¯G[„R¬èÄ¢}JÁ*¤qJùûë ÜZï\£9ﺘ4”~¥Ù1ùÑìWº¼s^ÀÆz/ðß»´£±~´ ³}ïÿ…ñ§³€Ð¬$묯u9@(v÷ ˜Ž½š ïKø›ý¯>ýKŸ{ BèTf‹3C…¢ •¶nèá\ú|x|{ìW$±@ÓIñ¤ôЫбðm§Å âC"€AE+x„í&<ºÛVeþÁÈ×x ¦;ÞÜ£[!ô¤c˜:fÆà‚¯8vÇ3οü…ƒ ø˜ Þ_ p}oöy¨F=ŸŒ™‹aSÞu%ˆÕ ¨NY8‚cáÆYÁM§B×DëЂ5:A¥¼Û½È»JøÄ;Ö:žªQcZ ’Ê¿f؇ÑȘÓ]ß eè°úmÐ:ô]P8í»Œ‡Âr°·ËxQ›ŽT÷|üùWÕC§Ž„ ë0ÖR• 7hM{îÈölz aQúÓtLsSⵇc‡.z‡ŽÙÅ&¥|/Aªö¹¨41vˆåÚ"¼2$ &SÿÞj 7ƒeˆ}ˆ`yD5-©— låÑPBøx`ss‹§ž|To]{5¦€p÷•^¹zçA?Î9üÔ”£(,ܬï6£•êY+Ô¦:HˆøCàguð·ºó˜i+o6Fã1ï*iß× … Èðúø*2±•WŠÁН<ï£~2‘ÐÝn²Œ˜È¤íE8`)sc1Æb­E)Éöö“ñ´X,m hà>Šv÷GhcI”×i”‹ Ssg-Î œpX#¼-ƒyU¾ˆà‰%ؘbuW~ˆbt}5$Úçb^®’vÕBP†mXÚ ÂÔ^aÖúï¾ñ“€<²mjØà;íf±‹TeXÉÖÚ&Fɤdow“ÕcÇ¡íÆ4ðþ±õ¯ü姬µD0ˆ‚j>ff6<„Úhœ«½%æ½.ü{csÆuVoÌË›T-d¸67AÚ–6~±~Ïá÷6ñBD%‰¶Ác*X;êû·^ùl,PqbCqHtê .¤•R@Δ<ñ+ß:ß B°µ¹Å±õµÊ6) ƒûÈlÏŠ÷'R¶LHêb¬^ÇQátÖåX#ÐàhPãýjW:m–@¦Œõö ]'A@÷¹»‘AšA úl '<Âg뼞F;4Z…˪ƒ= D’á„·xÂWqìípõ•vi-@kï# ð‰Ï¾,“DbC `¡ÖšY¶XkpÆá´ñêy0Û¡ð’DpFÌ:vÂGòÒþÞøònE0¾‡`3þv1ׯ`ýˆ‡¤o½‹½Ps¨ÛXC2•ƒJ½¨´UêH$°œ Ð[ - .]½±Â/¸ƒÀÓGVxßì ª*´…ºîá’‹«=ÒÂiÛXA(©êŸ¶œ ^ðqK׎s«pÆÁλÇy]x.Z†BµµÏõ˶^…ùN(S‡x@Dë‘ùS!Ëð…"mah1ØPÆÃ`±¶fQœyèÁ€h<ìî øSæÏ®È,û†èûœµTuí +U‚ÓÆŸFCmqµ§²ª™üûI»ºC7¹ðÝ䇆ð:Ïu‡Ab}¡1Ÿõs¦+líüor­sV©_ý]“‘H²ãZbp„ÚyD´µÞ EÅöÖ'®Í: [N_»à™gž÷xX|ìcÏ>ûìÝ—ñ^Ç—{žøOüÊ'_}ú7/õ{YóÖb± ¨êÒ‘È: ‰giQuŠSà²åæsÁú ‘ÖgJµvì4“?ñËÅ]º•Äv”¨8í:Xöʰù »güØ98œ”¨\x3¼Žÿ «¦,ڂ䊬(M†µ¦y~<žb‹™»¾}gè+R€gžyFv©yüøqõÝßýÝÇÖ××OÖ"9råξœ••ÈS%O;ºò]þÎSG;ùý¿ÿ©…Èæ¥U¥…±†Ê:„s()Yî%2I’TI©”RÊ9kÃÅqÆZµ¦ÔÖx6é'n‘L ²”µfwwi¾ÅÚíjdš(ŠÝùœB0›¦,¶3–WúVP,ÀUjIb%F_Î Ë\Jác Ñ–ƒiÍ¿PÍ$¸˜ÐGHRè ½°¶^rÌw¬aoº€‘ dæî"øDµ«Þág]g á3ˆDPi_²t¡º8›NPù€×^¼óÿØxë ðC?þOÿKµvê=E1ïýÅßýž\+j»<^T€Py–.e©êgJI!¥'I½JO’$0BHÉú°åå‘¡±.Ã{üÅhI•¼þ1€³bN<Ï}þp»hš×jí˜. ‹Ú¢¤ M ––듚[³ k•\Ú×\Ü­)h¡Ø)aVÅvŸoß ¡pqÜ[߃¡©Új]žy/¶^²Ìïhœ³¡.ì ‘ˆòêHщ‚¬ä=yw°¾S&d@°øUo»G« .(-[Tá«r‡¢õØ“w ·cî M ãÚ…¤;ÛÛ<òØ#öâž;Ë °;šŠ•aß.øà§\ŒØÛ¾Ã $õ|9Iš’¤=dš “T†² 2ÍÒT!A"DȱC„MnˆldŒ%DÌyEãóÃÿVRûxw…w—ê¡<=^SÑh±X©Ùî%è7R‚;;#²á2[·o“œXA%5*±híK9*Ù{ùÀÿÖ€Bu€J2ó~?ë)†C.5;·+jݦ…DžC"`Øl¨JùÉ$ïx3»= ÿ8ç0ư»³ƒœîïq"ЛVç\ú/Ÿ»pÆãÌÂ9j]»¿þ×~@ÜRP¬œE&™ lápF€1H¢žƒ› ™ ëÒiÐ ¤µH«F“µv(¤H‘i‚êçÈü0³í•K2)q%X§© ÃÞË;Þ?Å ÅH$2S¨DÒ$ ú‚Éö‚Ù¨ ìba´»åFËÙb‰Ä H$ËÒPá§¢Ão«uM¹˜³y鵇¡`oM¦¥ÞÈ3õ¸±.z0Ó'|̽|ôÏŠA.¹ŸšÉ× Ø2HsP}ýp? -ÌXÕ>Hê'péÅÎŒ|¬¨Åj—ðiJ#„/’K¡Aë´=­F:_é@?q¼ë”c ÌæŽÊ8ªÊR—5¶¨Ñ“1ºšc‹¦*(«’ºZ`M®+ŒÖˆZã´£¼µÍÇ~ð/Ñ;z´q ØÝÝ ð‰T)ÆIªÊ@U²aÏW ]xs•)d*ȇ)y»×F”‹úÅŠ¸Æèú£ÂßÒ‡ØÖ„XK Ö†uÐ d´!íål¦Ñü7óoI^ºº©f‹Jõó 8ïÆ#Q¨õÆL·4°væÛþ¾¬ƒÀ'[S+%ä«°ý*ØmÓEtM»R õþO´•:”ÇÃÉè2X_…o|Γ0¤$z±K‡OÁcËU»0µF³êÀÕ“f"¶UkæÓÒ#mP(ñ¢`k{­N£œò “šéÍ ¦Ò¾¯ ¤Î•B)‡T‚,OÉ2ع¼O]é¶Ñú¦n¬"¥'–2ÒwùbÞ+ÁJ‰v‚uö1¡]éÂKUUÌç žzâÑú3ŸÜŒ3MðM+Àã'××/ÞÚ§ˆ‘’Éø€*=N Ö1Ž=»7½p"p¡ñÁÑF…p°}hùœcßLäÄ·:_%s÷4×N£gàéÇ`Zül§r»s|ͨ7¾\›Ãó÷uYEè¤Z°~tmÚ¯K%ܸ±É,ÌùëZáF½¹‹ÓIs”Jrd.ɇ’ƒ«ûT¥£ì>žèT4Q« œô .¤6B „´”R²–[ïâ`¬Ì&#êÉÈ,öwFÜ{K P!> ¤÷/R1Ž=óVH·I¢k+ðГpûV§>/®À¼{7´*„ þÏúbH »iÑ0Ž×·ee°(ï{NŸ„ý0ØQ›¶¿ßÀ胢:h&sc£FÖ­DAU¶ÃúÆeYüç¯^»Æ#<Âg.•”S¨'ˆtضj…DZßdIŽL%½aÂäÖ˜bR„vt0ÛÖ…àVV|~(”ÿ«ŽÖÖs‹±"(“¿Zãɘ¢,ê×^{mÂ=ÊÀoZ~å…«Ç{Y ^ ü;“Ñ„¹zÀ:Õ„‹Z•°º O? ®´U;gÛ×/áÆgÚi†G/b¦5¡×zXÁ·ÐÁï áƒï5€ýÂOôV›×Qº¨HÑZi×’-íI"BXkŸ§ ļ›yK¿WÂÖÛôV@/j$ÉŠö~Ï…ªàî2d*H{·(™ïM‘Ê& EàBJ,"MBâ„õ”sF„šŠt +½ czáÉ®¥Ìg36NœÆ9gh‹@¦+Û7¥gÖúéîdî‹9¬5”Ř¹Ühðnݶh,WÎ XY†oz¼pÁ¯Æ>'‰Ÿs+4-(:Ά.XçˆÄÏ" oßù0|Ãc00®¼ðë{qît\I\õug 7ºŠ4õ¿K%þw–3ب|‡Í˜  €–Ê6/߯«ˆÞ9D„‰Î`kK2QAø L6t‚–2ƒµ6¤ÕþŸNÆ?¶+¿~ ¤ø&ys¾Œ@—½cíÊWíÊŽ¹µÑ0›Ãòøð×Ã'/ÀöÄ¿fin|6\̨NZ¤]¹»ñѰn .ÃßãéÝFÚóî•¿æqî¾I,D[7‡ üÈÂV¾®=ŸOQá§~{~+EåüØY¤ŸØí’e=&ÓÂWéœ ¸B×úm@¤ ™JÒžd±7§ž+~öqYÓ´«JÊ{ŒÁÖ:ž‰0¾—’jM’Hj\`Hœb<±{ãò>÷€‚½%Ø,‹lhc¨ÊŠyš’uêñÝ/"Ë@Á¶ŸÂo¼ºÏoúˆ|2ê`Ûï²$ÚÞ·hSB!ý }Ï;àɇü´í^å©QjÛ¦’ ëVH'£¯'ЯÔÖãðLÝ€öú^¤òÑÿx f{þ}ˉ¬¶ñÉû»»ÔuÍéS'¹tËG«."D  B)T/A¤¥`¼9ÂU®™êtñ¢Á2Z¡{ŠkBI¬6È< %uïR]‘&‚Z»ˆš fÓ —¯\[Ð!†üu)Àµ;ûâôÑ•F»æó9•ͨK¯ˆUjKÕMÅÍZ¯ã\UðÈIxä(|æ<ˆ´ 9D­qn¢Í¤ð½ôG…'ò “q˜â©µ_õö®À.Z\˜ô gôûµngÿò´U¶,õtk³]ïÊæX¯©;¼;Áb1§Ù/úÀ2žZ^ à ™HÉ ñ  ÕÞ½¨}ÂLº4"h¹áî@ 3Ö›XÌÓfE$é‚$ØÒ5D%Æ£1ÇNr·®¾Úð¾epέþðÏ|j#¦à˜/ ´€éy“—Ó0`6ºN)ÖZ±'ˆ¬)xâIxêaøÜËpñŠŽœ;Bø1©•u8{N÷ϧI©t˨դƒ®]ý]â%£¡vþw4ì™¶õéIÏ®*˜ýÉN;R•ððº Ö¶)µ*)ØÍ©aŒ®P¡aãÊ!s_ëwÆ’$‚ÑÎtÀD7-‹¨h]€%–É}QÈÆ†‡8#1Æ"²!-½Úg;¸N)ز³½Í‘Õ¥È [Á‡ŒÌ—U€ýYùX¿—ósï§‹9OÆlk¦ ¿ûž®U¢@Æh Ðpe“ôs8ýNxèÝþ"Ï o–óà‰4 ”,Ò3uŒæ‡ùsñïÈö;š×R½–­HÈdB–°¼âéážsgt»liYíKjm‘q¿!)¹uã&GNáúö‡ì‰DxÜ^ž R Ö ”B/JêiA—8ØÙ¸ïPÌu; >-öù®js`#p ¬ÄƒÌÇ²Š¢càß^V%ÅtL5ßڥà ú–àÅ×n¦Z¡BùQÁl½¡Es> œ-hLà,¼NÉ–| oé³rÄëÓQ®$Ä ªs¬k-R¥F«'qBiž¥¥¶fa ì^ó=øÈ¸…‰ ϰ–BaŒÿ~'ÈDÂÞhÆí«7|cF…îg¢@ÅlÉcþ¤…j<ÅÚ:Ì'ú§s¦íñÇÃÄ2Žð­öfŒÈÇ"Ì•Yá@Œ¬¬Œµ¡Þáp΢kÍ`¸Äê‘ 7Ä:À¡2ð›R€ZˆoUA+)%‹Ùˆ¹xÜϸ97^]äŽ-s&¶¼?¶º5Å]3®" · X¿‡‹Q20hu>?úû…þ6¶]ñ±”çþ¹ÙÜÆÎ%W8Ý®ü¨(C!H”05N „#޽ƒ®ßÞy T‘¤mæñRœvøßØG#0EØ °Z³·»ÃÉâàr‰CùfŒ•„Õ,¶­‚?Š©_p à#€DXù2²{ჯÆê ˆ†ŒÂÔ‚Õa ÅiJò‚Éx„YLW¯\™q¸ øÖ,Ö(!³0r um¨ëŠ’õFymÇ 4ùú]iœÀ _áwY0Q¬…t°™³Ç—\¹Kб­¬BˆjÑ›³3ž[cLœx]øM)ÀÆêà=…¶MÀb­Aë’Òo —óü5bé°éoö߉+.ÌäÇ´¬™ï.^à8tá„Ö²ã^äáªÒ¯Þ8¸¯„ •ŸƒG]C/õ<»Ë+^ø³YšIÜЫˆ‡Ž-e-û¸?f•e6S/F;šñà£=x$a}âdVªmê…s.4›UéXþœ–0;ªÔ3Çlî˜Vø³„j¶¾€åe –¥&í )ë6 R2™Œxúï°—¿ðk ðº"ЛR€BÛ' ÁŠã4¦ÖôÈœ®åÝiüo\Á±"Xy¢å†u+ +ێߊÒo˜¸ð¶¢¥Vq*°zXˆ~^„ 1Mümdаawºò”+Æù™¼Í×|/‚ºã&Â÷‹ŽË@ÁñÌKÛXÌfû¤½>WoÜæØÉSH)1ŠÊ!eôáªó¡­†«TÐÏ`¸Òš'‡\gª@J×öŒC‡Ñ~“¨²‚báØXïQÕ²à„Å6!ªÙ„¶Ð̱¾%¸½¹/YnêóÅ¢ t4‚Üxë‡ã¢Lšå óyHµ']²Uëk›‚HÇÄž†‰Â³Œ ­ã`º„ ugÏ„oÊ`ú~,këÜ ¼;wb"^’žÂåX®©µh÷ûuŽùÞkë¬ö`emƒÓ§OqêôIúƒ!umÐF¦ÓLëëÐZ7“»Búa%dã»cñ§®CÛ;@š&¯WîA†}qcuÒ…n­¥\ÌÝ‹ŸýT¬4ÄoI¬µgÿð¯{®ÓÍæ”r R¤H»â‚`³¥ :ƒ !Õj 1q\ª›·;:ø0p£k¢BEâ%‡%E0@a./â¬ñAêʆßõkW·uðuçøeŠU 8–«ÚEì`wΪʒù¢ ,K´5NkãG‘„1V()éçYS=B`Œ¦0Íê?4þ¦`gR¼§ß˲Øfó•[AXÅJ#ê3·îïËN,> žä0e:ô+qZw×~9ŽWÛˆ?Ô+ÿ¹F‚4M±¬ù\[úIÜ´ï‹<ÛW‚õ Ay„»ð›cÚ3 -a%µkbø…”’íÝ B/(«Š<ÏI³”D%¤IB’(¤(åO)ý†”¢©wÊ^Âõ펰))šÝå¼ây¤µu‹²EQQk2«-Wnl2ô™Mg”Ú¸íÝ]yä!³}óRw"ø­)À‹ç¯æ‰R¾QéÀb)‹)s;ðèë#ÔH©RÏi6@ˆ‹îªÀ¹Öì6«Ïu¬I|_g%ÚhúƒÀ„ .šTëîØÃâ1ùÃe?e3¾ãM¿ –(šûxE”hÛв3‡Õžðó#6Möv·Í*f/ - WWY^ê‘÷{ôÉ(´E*Iª”$Ê+†SÒïg¨D3î•HA"šXÄÀ>¼¿yÃ^«‡Ÿ~Ï£§›ûŸ~þ f´³«Žöª8[Á¯;¾¤ {éRUk”òeàDJªÅ„©9ƒ°~Ù9ápÖ#SmØÍ´7l«sQБu«)Ê„Õ-º˜£™jm‚È QP2J·÷DÚ5Ú€©|{7ëÁd¶/Ñ0z5»iEŠÀRÙ¹›[¹ž3ÈU؉ÔGÙ‚í­;œ:{š—>÷ÓyÅåËWù—ÿü§ÁjN9ÍÓO?ÅÏ}ˆµãgqÖÒËs²,%QŠ$ñ§R ‰R(å-C"Ë=ɯ~ü³\¿½ÅéS'ùð·¼Çï+|/¥xƒã~å¶ßËÕ¥‹/Ж_Wø² `„ü  úE¿ cµ1Óë`KœôE|kS¤Q~CŰAÙ’¡3„(è¦k­„mëùÍ?ƒÃPæ°?åP*æÿºöÛ¼öW`´ ;½Ï— ¦˜‘ÇO$ I¼Å?–ª‚Ô9JgÃûÎ v¶÷H­æ‘ÇžàìÃ2\9±SgÐuÍ[×yõµ«üìÏü~øA~ßÿÇÉz=²,k\„RÊ+ƒR¨Äo¤ ?öoþ ûSÍþ½ßÅ­k×ù;ÿà§ù¯¾ÿ{H¥ ‘-iE§ÀÚÎÁg?õ)±´¶ÁKûtÏ"ЗU€O¿tåDž&ÍjuΡ˂i½BcDÖ‘oÚŒ@ÏüªöÕ²@˜hÛ­ìLD7B£½x ÒeÖ¶.‡º©­Õ0µŸ­®ÀþmØ»x8èlz‘r%iɘöÅÞ…P§ëDSjE ÑhÌ˯1Ï™ŒÇœ8u–Ó?ÆÞîÙ`…÷~ó;øðw}'¿ð9>öì/óþoþ-8ëù‰²4!MS’$ÅXµ¥YšðÒ«IÑŒö>J¶öǸ±¹Ã…+Ûž,ÏHÓ„T%$©$QA T£›ìîP:e‡ƒž]õ~Y¢…{K P.檟¯ú8]×ÔÖQè,$ãgœ ,ÖHê…hW¢LÁ4èžpmšØ@½í¡ùÐê]w”FDPiL;þV{$ÏòЇ¤\ ”,®\Äd|©ÃÂáDÇ àoׄô|;.V½Šj­9rò,ï{ø,O½ëxôé¯#Éû¸¯ÿnݼÎÅó¯pûÆŒ¥õxï“OPs¬±$IBÅYŸx+à!Kº®YßXg¶ó2ïxü)þ׿ó ¸rý&©’Ì‹#MSò,%M3´Ñ!øTäyN9?Àè3ÙG¡À}ï>À—Të\ú·ÿÉ/?íw°ðÒ©Lå1tUŽJu°›W „Ô Rl-¨×î Vîšö&‡:„w¯ün?¤Š ó\×ä·zÒdiæ#þ°™†é³ ¥oÖÉœf£hBTǬ›ÞCPÒ#bŠ£]ÃmPW%{ûûœ9¶Ê«ç_cZ nïIó> ¨Ê)SŽ;N–f\¹|Å“_DB )Ãß%U(ùŒá·¼ÿ½üËŸ™ðûÿÇ=·ùÆozuY0«k’$!K¤ðsÎa®Ñ"¢°†²4s®^›‡2pA¼y¸tko)µ1dvPU5FKªR’K‡ó&]ƒÕ©3ª¹Ïû—VCjæÚÞ½>MsÁÁaÆëAõÀó÷D‹Ñ;:ÈB‘g÷&\]Eèf šH„MKh†U"ó–HÂêï|tE«bFe“Åã€é¬dº¿Ë"­§×¯\*˪ÖJ8)û«Gò^OJ©Â0ëÜcøeä7ð‚¶ÆPTR”R>[H²$eks“ÿîû¿“K·÷¸tí6³É„KÓi£@ªQ‰ %[…RJ±½½CÊå£Ç-äž5€/©w¶vÄÎþXY]n¤Q•…`m|‰6¶)µ@j5–b,(æ‚LÊPt¾¼iB´¹v"O_¼â‡bÈÒáà‹ XFò¡ß¶mÿ6ì½æ0¥ß.¥Q©L4{ÄÂQÒI÷:V&þ”XXÚH,…v¡êÜt:ÅYç^úÂç_³ÖŽn› ‹ý­ýÉâûNœ}ä¤sÖó(ì éo¥T¨$ÁÖÕèÌÉ£[ù`˜¬¯¯ T& Fér!Fã‰ý ùoè^žÉA¿¯œ"I”ŒÝÁD)!¤B ”H%…RŠDJ‘¤¹¸}ùÕÙt:[[fûÀœ/Qú’ ð®ÇΜþ…O¾Ô`Ì|xÆ\¯ L‰Õ!ñ²X!ZâjM=OH´`9‡y¢ÖöH¤_ý&\dd ßvÝ•ß1÷‡Ú˦݃O È~„k² »/LmàÒϨÉT rÑšü´C¼Ôh‰LMÀ~Ãz*¨Ã¤³\Xæ³GNžâòKŸ¼ªëêðàê·ÿŽÿâ·L‹“Bú"œµh碘$ œKþÙOüýç­µ»ëë[Ç)Ö××Óþ`Ø·ˆ¥z:ÏKkä­Ù\Xç„ÖZ*%BŠá` úyÆ`0`um%YZ^IÓ$C&JJ-åb¼­?ÿñ'Ã~þpØb§æÍ+À¸Ðïô2Ú* d>Ÿ³¨–v F᪠‘ja”@ƒ³’z.Yé˦Ûƒ¿nÚ’¯–±Y7b “òÅ@0Få ©£ð˜ý¼ççóæŽ­kliBAÉ¿IfÕK=ïNŒöh§y¬£\1xµ.BÑ,k½Öôhæßœc<>`ee©Î³l¤ëj ¸ \xÿ»Ÿxî?þÙ¯K’¤ÓÞmÚð^­a²·•婚ïììߘMF/߸zå&ÞOw¸?íbt÷Ù=îùün &¶€é[V€—_»6ìå)ͨ«‚Y±Š°5VÛ°ò3„0-0Z#@—‚#C…©¼•®eã–]Ð 4ä ÍÚAðñ?s2”’c&!}°—$>(+Çæç ôÂù @ZD*‘=Ù˜zå¹*ši[Å®#4Z ëèQá\Ú „ìïPîmæóÙ<˜Ù10ú¡ú;Ÿ}èïûƒ±rEåš§ÃZC:\MûÕãìì¼ „•:Ž¿þM ýîû¯+ Ðö"Qô›WkôrDUFדEW.ôý?&À¹ÔÓ¹­ü üú°Ã½úñ‘7·éÀÅg;@ ÂÕØ—¥c¼ÐÒ@£¦+²ù¹)º²¨Ê N¦ Õ—ÈT"áRšy¶.%}¡h>õ·±•Œè¸¤¸“ƒ¾ h›`ŽTš0:ØçöÍÂyÿذnœ<û­« ¥ü¨—<4è"á0uÅÉÇÖ®_½”…Õ®Ykÿî)è/wˆ»nÝ]ç=7T#Õ·vÿv\½`UtZ`k\pb@Yuà_/§~gÓ•!äIŽÛž;ëR’dÂÓ­ =°Â²óÂSø,ÅcüôLÒS¨Tä‚l èå ”£š9Æ3Ïè×ZhïHç¶¡ø#‚R(=£—)¦ÍÄ-¤IÊÁþËGŽ®æýáûž8ùà£<òðÆòàsK++‹O¿x,÷Ô`ÖÅq/ÑÆÿ­?rãÊ­S@œ(éѲÑu…õ†‚ûjo¨_¸xãT/M[¨‘uS1›%8Y‡”¨@ä²òËÇ&*‡Ha´pä‰ðãW¡GPòW{¡ëÚ5;dÙ˜tôàê~*A6LÉú~U5¸Ú²ûòÕÔòŠ5JI’+ïß{Š~_çŽzn9kLœ )…l— e¨õ !èé±·ƶ0m`kk“ÇŽ¬lž:û¾Þp…­Qñ‘½Y…Øš2X^ÆšºãBµYŸHxðìÙcÇ7Ö~Óñ£yU̪Ï|æ³R;±ØX_·óÙ¤ÜÛÝôxv é_5EyC˜N¦²¿±´X`kMe¦tÕþµÃIOI.5HíW“µ°¹éX_ó“ºeåO]†=r Ð¥ÅT£=¿½Ñ>‚וÁYŸF%©¢·”‘çžLWbupá€j¿‘¥åwQ©D¤‚4W ’DYönTÅaú•ˆ¸5"P¬H‰S¾$éT̳9u(Æâ+]398ÀŒïà€D)†KK¤YFU–$i šq” X3¢|£B M¶ô]7÷ߥ„ûŸxò=fiý+++v­ŸßF/®~üã¿¶wêÑw¸§ž|Ìÿ±_ùøèì#™Çy¸ý~„5#…R A]kv­{'~ê7ýfŒ1\ºz“WÎ_F0à7ø{‘2aa —ïLêÕ;çëÞýçÿå?ÿ©_vñAeù)À¥›;§ò^~ÄY×äUUQk‰®5©ò¤Ž²\5y”‘6Iؾ4B*E’)¬qèÚR—šª´T¥ö«¿Ô¸Ú„ñð@ù–(òaNo)!É$F{e±Æ1»=a±=iÓFgJ!ÈÄÏá –ŠÑ‚Ñö´Å4Í'o)b‡©!\jxw4ÂøŠ›µ’lì³Ó"W´ö¨“ãÇØßÝi'|ÂÌ„R9‡Û•Áò4ù‘ïh šªg'^0‘‡&XŽ<ÏÈóÜ–¤B*E"-ʵµÑÖï •ü¦¬À=àúí-1›,ͬʒb‘ L³$"¸$Á‰Ò_ÈÚ“Yë˜Ý±© _öü»º¶ÐM©±Æ¶  ð%ª—’ zCE’‚. uQS×–bgF¹=mǯ‘†$¨DЦTã9ã­ЮÓ.¤Š¼ÃÂ+'"¸! BZj+YMæÔVéñêùœÙxÄC<ÊÒú1Žž:ÃÊÚ”R”eI1ŸS• êÅ c-º®¨«ªÙÇHHµªS{.ÎD…¡£0¡ì«’Øf–XFÀm|JyÏÚÿ›R€Olœ¬jÝ©Jt½`4MÔž‰‚y‡nœ•¥§xÞ5XW1½ªY rdH‹œñÓ5q5ÆÆ¥ÕÏÈ†Š¬/Xʹ¦^XªyM±=Em‰8ähJzD‰$(\]spk¬ƒ'^ê®Á0FIËô¢tl³ß_]IÖsGmq–OÁxtUÁööýå5VÖrüÔƒô—–‘R5ÿ« <¾"èÛèeU„)g”óFהłb>ÇZC]Ì©ëÊHñÙOš¡T‚”ò@£È’ÑÁ>}a>£Hih6ÞÜqO¸3.¾¥—%á¢xÐaY̘~Tg,‡Ä³†Y\_«R"³)*¤Š-ÀÎJ‹ ’D¢ò”l(I3ß-¦šª0Ô³ŠrkŒ™Ç¨Z´lPÒ·h“¤OšIòö¯îãthÝ6ÀÒØ^”Þ%H‰ \{.̈†ÒÖ¸¨lÉZOcŒwwñ¢O¦*'qEÅ`-!Ëzd½œ$I¼"… ±Rò÷Ó^,µušÁá)]…ð…4quÅþö&—_þ¼Tƒà¥”,æs³‰±Åx³ï¿|ùÚ•—ñ¿oÁü¿¡ü«}rmeyØÂ•C×%Ũ‡Öø±0Û”wC”—@z7aý…6âT¨ÐÑ ÌR"OI–RÒ¾ò¸úJSÍ-z¡©çÕîWB…¸ž­À%¾/“‘ òbz{B½(CÄÖ¶ …`šéfW×é9w¼2‚ eD'¥/*UŽ•^µIÓôÄKS}âqd5âÑ'å죲´~+Â:¿+SY3›,ŠÒÎ!•GüÈXŠcaÎ!Œ Á¡°ŠYÅæËDV0­ óéSÍ'ÓýÍ ûÛÛ/ߺyí:°‡¯÷ß®ã J_™5 ú_* pèÐÂÍí‹)Ö¼œ—`SŸNÉD"ÚÃÖ•ÿ7œ ;y¬Ë¥öè¢X“k½mľ)çûû©Ï*„uÈÌQŽæØªnùvé/Ñ\+×0j„û±.b[á§K]O±‘.¨tÖÄÂ Š¢Àêš[·oŒi.ºp«7j½Þs*ç.Ey£Ç¾d;÷+=äÝœ¿|=±pÏ…¨ºª æ#ßÈwNûÓ¬®±ºB˜ªI‘Þ7£üë­®1U‰) t±À ìb-fP̰åaj°þsmàtq€T.à÷¥g߃ ¬µa)vF^™LÓ«ý}ã4Îê€Ã7þ··Z‡[ƒÕþyg,Öø÷™…f¸\û-XÃ0§±†ªª.¯rg{/®Ì 0Ï<óÌW" wó^]À¯Éñ: °:ì­µ&ÏÓæç- ‡¼ãOðK¿ø´í{¨¯TÕó•/• DŠL’0ªm½O¡1b­·&dÖ!œñۼ͌·ðöä“2A$*ÉX\ S&ÚR/Š 4~… ×áÞ‰mØ.Ýš%d¨ D÷ÓCOì\Ñ¥@ é"ÐQ—Ü™Ó'ë ¯îw‡.ß¶Çëà ¨‹ŠIá=ëêúŽŸPü±?ý‹…¥˜Yê9…`:L+É´tT•A—Žº2ZP…Å34ê0)"BZ„²-í¹r ,‚vƒJ„jaXÎÃD`v4¥Å”U,‰˶¼MàåßÒÜE—à¤÷\DU ÕFSIVûŸà"û&̦SÜb\ìnoNi‡.ÍG?úѯ9pãß›ü›?¿¼º2lÌ?À¢(( Á‰ëÄ6•o¨„1æ„°K˜'R¶&d´qÔµÃT’¢PÌç–ye˜Î³™EÏåÜoì0Õ†©ÌM A«ýX–6 d±ªçº(+ô‚² %[4ÍL~ØHÙ…¥.B÷ÏcX¿a¡ã‘O†Õ%ÏÊáÛ%Óɘ½½ƒroo/rïÝ“wçít¼NNl,çÚ ¬'²ÝÑðæp4ûèZµnc–fÏЦ)HGšBo(X?ê_ë31Ñ`ñ¤ôÍGg5µÑ5d 6‚¢Tµ ¨$‹…a6®™–ŽÙꉣšÃ¢pÌ*?޶¨=·ŽÐ~”ÝHU±Ÿkë®Þát¥%¤˜îôªH™Íf¬?Iúý§»ãù»ðŸ=û‘¥^‘À4BZ\—‡6DÜÁÜFSé»u- šë˜eÿtËÕz™ ±7~ˆlØÛp™Bž@Þ ¯¤LüÙ}¹ð«ßQÄ*¦£®eío•cQ:Ê9”3Ǽ€ÉÜ2®a:sTsÁ“_çPI2—ع8}òX—ÿ«ž–ý†*À/æ•?0Ȳ^¢BºE»y£g©Ä7ah5"tµº˜·fĪQ–¨D^!lh—Ú›òØëŒ±ÂYëj£±Ö chÉZÛ*Zø-qŸa!¢uÒp!›ü]A’9ÒLÐsp¤ ú"‘¥k¶‹w€Ñ‚¢ìbÓý÷Î'nœÿâ­xá˷ËqH^¼põƒ«+ËÔuÝ ¾{‘¥ô;† Ow"C½ÂÓe‘ ‰â|‡+¼¶Š -Pq×¢ Âý¦ËÀÙ”Äú~½gøÖhcÐZSךº®ÑÚPÖm FkŒ1ÔUEUë l"%Ùþ«|½A)‰Ì‘ ªaõ-ZwáÒåo°ÛÛñhàÚæÞ?ò/žýú¢(ü…‘òˆÂj&[E+ÔÈv•@J…4‘G…Ç:\9*¢oD󜒲áÕi9u‚P:{ejß«B¦Ðì,‚h?Wø4ÚZ6£+L± (Jʲ¤ÖÚµ6‹ÊºÙ¼³ÙB.ÊRZc(c¶(Ȳ”ª¬©´c^,8uæ¬íÞn†.Ï;gŸ}öÙßh9~å põÆìÖÖN~du¥ÅÊѲNùáFÙì^Ù[´ „èª˜Š“­ÂƒIÓD±¼² çjp5*äYBÞ Ó!Y’¢„¥¨|'ËRŸ ÏÅ—(H—D3ï§ß°/Ê«Î|•—ÃæŸÞá^¥8ë`^”(åq‰»û#ûcÿÏß'Ž­Ï_i·`1úЇÜ}¡gNl<¢b%|ë3‘‰§2IÓÙ ¨$!)RJꪢ(«Ž©—¡gïÚ¿ƒùOÓ”4MQ‰âùO?Ï¥ó/³³yÇC œCkâAH) ûœ8~œÇ{‚w½û]œ}è²þ2XëùvÏÊ•*¿!SÒÜB¢öÐú üÜ/šáRÎC>† é{ `•’áó•,SOH%ÙÞÚäögªÏ}ò¹­ëç?û“À‹ÀsÀ%íüâOýø? ðIà*oaï?ÄãM)ÀÏ<óŒøØÇ>&ž}öÙø9ò®3Bž¢‚tïG… Ì=÷T¢äɯÿÀ9~êÉ»áÞM¿|ð§ÄA/q¯(©ê|p±±¾aÖÖV•$Éd2Ë/_½N¿ßKªºN=ÞÅ¥Jy¤ÖÒÒPöòÌg,Y&…”B¸¦¼,^{ù…âÓ/¼ôÈZ.þõ¿ûwÿö9¼ ø‡W‚÷V6:·wƒ8»÷ï.X| ` ŒŸyæ™ò¾I£Ž»„ïî¾ ŸøÔgzúë›y¿.Ì¿!_‘fòö­›ËáÙÖÝ£mLÞØ}3Ê÷ë"^OŸ;wîmŠÇ[š$ýjÏ<óŒxåü…þ÷|ï÷ý¶Q¡ë…KWßW”ÕS‹ùtù~îçÅÁh”/¯¬öz½^VEúíßþÞÞÜùÝy¯GÄL6]ºÎˆ³–cÇŽé›×.¿ŠŸœ¹sîܹéÕ«W;Û@6§~“g}SöêÕ«¿A"ûêÿÞ\Àþ#ôÌöþÁg—æ·cƒåUaa>›®¬³ºr"áȱ“neip°”šë¯]¼<šUæ;³,oKs‡¨Âýý,ë1Ú¼zë¥>÷ãÀóÀgð“%à:ÈÝf}?¬à¯ôøš+À¾ù[ÞwæÇÿçë[;A%+++ka^×F"È£¡Rq¦…]—”Eµ¾¯ß„€ ÄWóÒ4§®J·¾¾>Y_nëbôòsÏ=we°q²~ÇSOéµa~moûÎ¥g?ö±Ý¥æÁÎèõÕ¥Ñs¿ök£Ñèî]µ`Ï;g?ô¡½í˽_êøš)À_ú+í‘ç>õé¿|k{ÿ÷ W×¥aÊæîÃú àÍ‹7ç6@Éëª qÙaüp‡@«àI*I’¤¨$)‘Ra¦(KÊùg5išÑ_ZA*EO¸}ôbó•×.MzüîᇬOo,_ûÄÇåµ×®þ“K—.ÞÁWú¼Í£ý7:¾& ðÿèŸüC¯Ýü?³Á`žJkí ¡:»o6(Ž@¢Ð1Í0† >ŠhïI`i±SIaÔ¥W!¾6ÂɽΣž"1$¦Ó }þ¿Ÿûÿô‡ñ)ßígžyfv?Z‚¯jðÅ‹7Ô_ùÑõƒÃÕ¥?òmïÿPÃýwÛ0¦ÆMY,ÐUEUU”ó)uYPWUUz.¢ù]UH+°Æ ]íWx˜ãåÛ®À›iæÎTsÄú‹fF !\V‰/ÿ „ï",-s°¿ù(ðux;3Âiþ'x£Ã9'ÿÌþã¿uüÈÚÉEYU$‘×&læá_~«”(„†N%¬B!U3çomØÝZt]2`ñdL‹õ|N]-°Ö3x[cpÎOÅÑpˆ¤TÉà€eP¡½ÝáÝñ8R‰Ã.'ð PÝÇWM~îW>õgNù–‡C²4¡ß°³?b¾X c¶X0Ÿ¾Ë–¨ ˜0 ÞA»„á“4Q8'I’„~ØÐ½@˱#„Dª]—xN㚺®±Î°¨C Y̧”ó9‹ù¬eÜêÌ/h]39ØÇÖÅA=ÝäË-ßÇWMÎ[3ñÿúáO ùúñcGV*IUÍñ#<üài6ú=>qŠÓ'ŽS³²bg8)ÙÚ›°?S…Ÿ ³^ˆU­qÖ¢” O?»‰â¼B8œÑ¾ ~ŽaËbKGDÿÿÿ ½§“ pHYs  šœtIMEÕ&"NZã IDATxÚíyŒ$×}ß?¯®>gzîkï“܃»$—‡HI$™”mѲ嘒uÀ°“Ø9Ä0ù#ÿ&HA Û@#NÉG,Ŷ,˲‘iñ¯år—{pggvîî飺ªÞ«üñ^uW÷ÌìÎR³³3Üy@mUÍTO÷öïû»;kgí¬µ³îÒ%v¾Dê{@lŽîï`ûþÿ\ äSç<sÎÐê@`Ž:° T2à*”x[ïÿ“v{}À~`†Í1ô¢w*„y`Ú—w€×w ͱ-Á >$D·€ àQàà¤!rBðÒý_°¼œþøÀU#-”tØÀmüÌ9 ì>ü¸!z!%Ê€°Ár-lÇÆv,„káö œ§×Bd'F8úù’¨¡PUSó ¹¨ˆ#P!ÄQ¬I¬ÿ­KÀ«Àoß7÷M Ú@ÛˆèžéG§Ošk/ý •x}}ƒ%Jý½ôì*2p°ÄÈþ!FÈõf°, !,šQ“fäãG>õ°ÆB}–åf?jàG>ͨIèGD ÿ²Ä7"¸.‰²ÚAßðûæx˜5@[Û}À#ÀS)ß—þìv °7ËÄ‘1öÚÇÃû™Ø7ÎðÈÅlžAªˆHEHÅæZE„æ>ù}$CQƒe¿L¥Yf¹Ya9X¦â/±ä/¢BE8§hNJš—"üË’`JG-©p øð»ÀY fÔƒÚÀ­­,ð$ð€3ÀncÍk¢÷ r‡JÇ <öðãê@û^ÊP6©‡uæj3Ì×fdˆ” ¹¤XúË&µ7Bd-E \þ+ð5s]ßj¶ÁV€k8ý€ç€~+'Ȱ)žö{pc÷ãc»?Á©á‡ð,¯%Î[„Js{7A» U@hT€á~Ù~69‡ `ia€Ñ0@¨4+²I>dé¯磄̋Fü&pÍÄ‚­g‹ß¾üsà4` ²‡zõè{ Ï£Çç‘Ñr|à=n¯ï*BÅKT×!׺W«®gR¥ŸU­ŸI¥_Óº6¯“±Äý¹A<'CÅ/S§F]²Xüf“Úë!(ú ¨}à—±Ò‚;{ øuà×€#€å”ÃÏåz6Ïý9ÅÏ?ôxfßg8TºÏÉhb$„Hˆc™¨¥4!õïÚ@I?/ã©ÚÄ—*2ÄOžÕ÷ P©¡í‹¨!Žå"„ R!V²{lâ‚) 1žñX †Ø–QÊ\[]!é»B¸Æ‡ÿ×ÀÇÛ.Šyì{n˜“‡Oñéý?Í}ƒ` »%Ò¥ŠZF]‡õ®"#n`Ô­Ð÷«õ³!Ñ’Ò`ѶÀW€ßÞ4ne¢¶•ð€Aóá@ÿd9þåüÜéȧöþ$®Ñ÷2e·]2cÙÇ+]±Ä2ï°Þã(¥ë£.Ý.Sz=íA´ïCP *ÌÕf˜®M1[»N-¬¶ÄúmN†B)OñHg\ "E´GXÀ=ÀAtJzq#ÕÁf`/ðï€  ÷1]Ÿïã—þežÞý,;Û᪩á:‰*c…bt{iW/åʵ\·4á»\Ê%‘«•ËLW¯±Ð˜§ùmWÇdœ 97O¾?Gf·ÊI‚ë’8ÀF×7ìG×!T ~hãp3~ø"·pÂaì E>ûðçøÂá_À±\”åiŽ”ÝMYíIä®Û3Xa¡¯”tÜ@)¢8$P!•f™‹Kïryé"ËA™P)ùͦ Ž'KÖÍR,qÇm¬qIã|H´jŽo¡ºÂí€ |Êy†½q‹±/yâ±'ù''œ×„Av¸fÒZTŠð‘¹ŽVç¯]E*ÝŸ‡2vÅbcžKKç9¿ð•æ*–Ü©¥¬(x\Ç£'׋Ûç Cš×"T#À¨ ž]2 hþ0êàv`ÄXü ƒÏfyàÇîãÿ2» ûRœªŒ¨Ö`Htþˆ¬V‘k=¥läÙzXcrù ï.œe®1‹Š·F¶6R–e“wó8–C1SÄ+9„y2B5bË|¯0Ùå"n©@0Ù¼§‘=à°÷ÇGyöÀÏp´ï1q;V9’¸|Õšq|yƒøZ×+#î`ÍÖ¦yoé]óD2Üryðjs™‚[ÀËd°-›áÒÑ©ˆ`á‹ßò‰Ã¸x¸,Ð.<‰¶<“ÜÉ †ŸËqdü(Ÿ˜øQ,líß§¹WuŠëvü½ÓÀkgò䊜@Ú²ïö¢8¤,svþ-&+—‘Jߌ%lhwrM)Rö—È{E<áa[»÷}<¢9uM'™b&€ÏçSiæú­Jë6rÿ'Lz—â)—ü!—g÷=GÁíiq{‡ÅÏÚ†ß ÑnžU¬m0¶K0]»Æ‹SÏs¹|(Žîñµû¯ðœ '‹k‡aêAåfXÂ"çæÙ?|‰§pú­ä;~xÐx=„¡o—È_<+/(žñ88~ˆG†?Þ!Ú;®ˆV&ß)æ»Ô‚y6ûOÿ­JP¦ì/Òk4e“å`™«•K,•;.Þã8FÆ’¯ 6V}NÅŠÅÚ<}Ù~2NKXôf{9¸ïs§Ê,þµ ø:ž3Fat+Ràvàp °2{lò÷:<{àgŒ¿¦üp…BÝЀKçêÓ`h«}ïG .•/p~é*MíÆE*Ò®žQ+[eE2D¹1}¹~”R4esÕçš‘Ïlõ:¥l–°°„Åpï0ã÷P}û*áu…I3?` ÂÚ¥gw ]ĹKØ;`súØý<2òñV ¦íúE]¹yiÂÀ]ÁšÞ€¶|Ù¤,qná-ÞžJP!ŽUgØ5^¿$›¢T¬huŠÅÆ{w1YyŸ0 WQ°PŸg¹Ya ?„eÙxv†#Ç3srùù*qD¯I«Ÿ5R`ùVlÛaä ÷÷Y9Aþ—ÓÃÑë•:¬üt¸¶Cô“Žtyªeå×Â*¯Ï~Ÿ¯]ø ß›úÊÁ’&þñ……ƒkyXÂÚ4)È€FX'ëæ.Œ®™”Q±b¶zÝKKâ {œÀ²îÆÐ-oözó<·ã¼ ]ÔiYyÁàñ{‹L¬?íÒ©1ø¥\¨UE5¬òÂÔ_ñâõï°Øœÿ¡,òR¶Ÿ‚WD±©±KjA•@6éÏRÌô¬ù첿L=¨bY²È{öÚCéX!¡` 8n”)±z»Û¦`8™°™Ø3ÁXnW‹˜ŠUt½JYö)îW]ñzK–ƒ ~ùk¼9÷*~Ôø€„·èÍô±§w¶°¨Bl¶gà‡>~èãX£=ã8–³¦-°P_0ÒJK]ý{ØõØ0 ™ï}ÈHaëN@ «yG2{m†s# eGVúû+\¶heT0N‡o#–š üéå?âÂÒ;DqôD½M)ÓÏÁ¾£LwSn.ê`P|g D+*Í2RIús ä‡Ö|n¾6K=¬#„…eYdœ,ö$··š1t#ì¨q ÝõH€eXðFmŠn‰‚S4º=êŒÖuEü’˜€¢]†•¤Öyuö%®._þ@œšsóìêÙáþ£¸–Ëtu’rséŽ{õ F }lË¡7[ZS T›ËTK!°„%lÆ{'ÈõÒýóýß1¸èõèÏ b +Ug—Ò󩀎ZÅâO§‚/”Ïñúü+„*¸5‘$ƒ¹aŽôc¢g/lruùŠ1ï|i¾Še¿ŒŠ¥lžYó¹¹Ú,q—PЛ-1x¨+Û¢ó“(*¡«¯¬Í€c òcY2C«Šþ¨#d«:¸])ÕG,©E5žŸú6õ¨vkÆr8Øw”C§éÍôÊ&—ʨ•-AüdUü2¡ Ég ä¼üšÏÍ׿J¶b¶å°w÷^¼ñVNoÐ|ÿƒF ßÔØhØFühqÐcãYnGÍ~;㧺€uˆý(‰ ¨ˆ×fÿö–¬} à99üJ‡BÐk\,_ TïXx­¥+–µ][ÛuŒš,Ôæ ñm,a±ob?¹ýNBf8f°.5p;ŒÀö· „°Ú¢œ´Ïßéê©5Ò½‹ÍyÎ.¼~K¢7Sâøà)Fóã¨XâG>SµIÊþâ–#~"ÞëA ¥¥l qšM/_ÃVËì/öÓ¿«/Q= ¥è];¸ÑˆÓ(ëàEgiWçuGÕÿW±äüÒY*AyÝ ÇëåôÈà çGQ±"T!‹þ³õë7ÌÀÝi4Â:‘ ql÷†ÏÎ׿tÍ€QY7ÇÄøv±Eç¾; Òˆ]DM×éE] Î^¼(ލ†Ë\­^^—á' åFxtüãôeú[ÕÂõ°Æ•Ê%Â-˜÷ïöõý°-웪‹e¿¬‡\›¬›ell »Ø"e6å fi·m>¢0¢VZîŸTÊ\'¿hÍJ¥$³iæüÙu½i)ÓÇ}ÃÐãõª@wêÈ€«ËWLÀhkOk eˆùÆÍ[›,R)ÊþRK¸–Ki „×Ó’žq‹öfJe’ÚhYÖ\ÜÑ`Ù^#,cÉRs‘Z¸|Ó7ÍØYŽœ /3ÐÑP —YòØKK,[+„+~¹å Ë"ŸÏSÈa„‡kÜÀ‚‰Ú›)BtZR‡:§#: 9dÚ#X£È3TúµëÑÛKGØ]ÜK+"˜žþ¹ÆÌ-Ç î¤I]%u#;@ÅŠjs«–ÈyyŠÃ„+W¼'g3¡Û™"2"PAG¹—R©°oº~N0øÒg©¹pS½?QÜÉ¡ÓÄÄ* P¡OPaÑ_Ø2Åž7µžã˜@6[C+n´‚( Œ,ã æÝ<Å‚žt¦išLQËn6bô<œE1ã2žßÝáþ­U楺<‚¥æÓõk7Ñûýœ~:Ú½"Rn.}àdÑ´šQS÷$܈ˌ„K$€çdÈ<°Ztά±Y¨ ±æ3ì+Z#¼ÛÙŠÝ]õóÖÂX×.ár„þރÝžÂG*"~Tß²nß,üzX¿¹˜5®6®íâæ\R¶£G{^â m€ÛQ$O Ï`83–2øT+ ˜u¶m)®×§¸Xy÷¦Ü?QÜc¸_÷æ7e“rs‘ZP¥ÖØn+R!Ë~ù¦ÁªÄ~jy¶‹—wIyÉücw³`£«TïxìÓcY¢ÝŽÝ*‹:JÀÒ œ¨Î÷gž'TkëA[8ìéÙGÑ-È&¾l0¹ü>W*©…Õm;¾YÅ1åÆÒºÄl;+háÙ®ãvGdmCßM@xäÌ'ïo…€cÔ*¾ªS:Ä’«ÕË7õý]Ûe´°K‹{p¥r‘÷–Î©í¼¤ŠÔzÔVŒ0åâ–%°ðp”›neŒS )6Ó,:ÜÏØøXWï*ÄOUù²ÁûÕËøòÆÆ[f€¼S T!W«W¸T¾@ooâ'º}½^‹€–¶e“õrÝ$Ñu¾íFüÜûäa,Ç2Q½t£g”šÇ£¯“ºþ¹Æ Óõ«7MÕŽv!UÄ‚?Ç¥òùmãë¯Ç\÷—-hÙ–eQÈpl;M×M/ è©Ý–pàÞŽ‚·úú;4ér‘4e“ÉÚû7Mü¥L?õ¨Æ¥òùVõn[«°„MO¾ÛvÒ´¬côÜFà@fÔe÷ÄÓÚ.U«dO )}®7¦nú&žÁµ\üYæüÙ-™ÞÝÑâ~KXd3z zn:p#Ѓ©Ú;@ß@©­ÿY™þU]1¦ôYXGâ§à UÈTm’`Žš?÷‹¶ø7ž€Œ;š]×=|ÒÚ@î?j¼F÷Œëɶ[¾UgÀŠÑ«J1Ó˜&X‡.·-‡rs‘ëµ)îÖå9ò^Áì{ ÁШùȨåA¬»?p#%À1 ƒ€žÁ"nÖ1z•ÁL‰T ]þ=U¿º^K‰K• (Ô] €¬›£'ÓÛâ~KX4Ê>2l ¤=Nî†_”³à0àYYA~ ‹eY©®]Õ•êU­aIáÆlcf]oT «4·YŒÃàd)f{ti˜e!Tªiè¡a:2{»0Øv^èÜtªP!‰ˆVdütˆb)˜§)×GT?ªo©ŠÞÍ^–°èÏè–q#þëAù¹d¨0ÄR ¸áþ©@²™BˆÎ)ª]雸†Ò {^ðçÖ¹[­þ´þ?:r[ØX–…-lj L]™&ã CüD ¨Í0-Ûvð\xEÙ·ê˜ÇŸN2¼ËÉz ®V¦—ýƒuU°°B0;;ÃÌ•Ùd²hˆÞà²aŽDÄ›Žíà:n»Ü‹®2ðÖu”šû³e6ÐØòëžÑãäÝ|«4\*Éä•Iª³­4²®Ç¨uà¶«€Ößê.ï–]Q¿îôpø!ˆãoÆÊ{Úûh»3HØø¡Ïùó牖ZR¾’:j›©"‚(X¥8êØÁ£íêê–»Ù°[ϲ-›|’ÁüˆöÿÍñÞÕ ¼úW¯$ú ]•µ@{†à¦ R„M$«M‰V‘ ;ëÆ‘¿=}û81~Ïq[@Å1ßzþ/¨_lЪèÒ ’½7K€”¾¤ºT%”Á*£ÜÔÊŽ±Ä¶ììo°J¹>>zð)† #!àw¦ßäµo¼‘pŒ®È^BïZºÈ:Fm$.¡¬ÆÌO/PꃞVLImô”³ó7쇻›—k{<~ðIî9Žc»-â—‹üñ×ÿ˜Ê;õnîŸ5çcÆ›€½›vK˜½6O­V]3ñ#ÍhØdÖÎÉ!°v¨ÝµŠ™"Ÿ<ò)?ð$žãµˆßŒšüù ßàÕ¯¾… bŒ¡wÕþ}# ʬc“ÊüÖϡǓ1óîó3 kOúLÔ‚ggn85ónÔùC…až:ü ï{\žDï+^:û]þâý%õë~Â|s†ðÓs¬s^ ³àz§«‰Êù.\`×þ âX­l ï2-,½ ¨Úq‚c§8³ç#ì.í5SBE+ï~ê_ý?`ú•ùdÃê&pÙXÿWRvÀº‚+=.> |:Ž5w™CØVWõ¯joÀ˜êTpÃ>€»ÁÍ, ñ‰ÃÏðØþ'.ŒàÙ¶¥kþÎM½ÃoþÆoqñ׈ƒVØ÷z‘óè=….Ü)cˆüÐ[Ÿ (>è0::Úu´„¥ç÷Ga³Ø\øÀ÷'·ë §¡âÇFNòwŽ|ŠýÉ8ËÁ¶eɗξÈïþÖÿàâŸNbâf¡áü· ÑßDï$2mŒ¿u}‘-btoú™8Ī,—dˆ|&¿êÞ>×JÑ” šÒ¿+Ä|o¦Ä¾C=Ń»æØèI ^Qs¼íêd°©6—ùæ‹ßàëÿíO™üÎLâòEFÔ¿ ¼¼eˆ?i˜pݕۀ&º:x´¹¢ú† âXv«@¤cdL×t°zTýPF-aÑ“-±«w7÷Žœäþ‰3>Æî¾½ôfzq,[ØØ–£·‘³,.Í_à«üU¾ýÛϳðv%á|i8ÿ]ãz¿ipňþ[ÚWÐÙ`â‡À+ÀÿöFUzë¿_"rBüäiŠ^±3. :GÂgí,y§°­+}-Ë¢àöPp äÝ9·@O¦—‘¯ˆc9º“Çr±-GØ&³§«{"23?Ã÷^}ï~ýo™}e ÙPiæz׈ü+†ë€Þ9d‘°-ýFwI#‚þ=»ög‚iiŸûIBpêÉÜ¢~°µ—O{vòN?jm¡ñî·"ÚGŠcœ>ÝçŽp°-G¸šË-G8º¡£ÕÓE3s3¼ýúÛ<ÿgßcáõ ²Ö¢ed|É ñÏuÿ– ¨Ûµi”oüÒ#À>¹³|¡A%^D Oà{åÆOH˜íWñ›w ¼—¾lK”[–Ýum·ºy¤’ÌÖfxãÂxá[ßãÛ¿ÿ7¼öµ·X>ß • ­¢'ÄN¬ý³F üP;‰Þ®îàºAèF—‹ß\“\ýÝEÊo×ÿéYúw÷Qp‹d¬ ˜ê¡¶*ÈØÁºËÄ¶ŠŽïÝÅ`~Øì $RV«Ž?’s&g&¹ðÚE¦^›cñ½2þbYïØÜ i|ûIsNüü×iï.®>¸Ôº}N]'øð÷Ñ[¤÷X9AÏ—Ò“2ã6Ù¾ YÏ ´ŠõÎÛ*Ö^T²sÓ‡Uöçmý~µ}z[¿‹Wþn¯M¿tå3É‚üM<ŠggS¢ß¦V­353ÅõÙi®OÎ0wa‘Æå&þ‰ WìféyÕ{˜1Òô}ó³k©8ÿMC½w I˜9žXuøŒ9v%!h+#ȵ)œtqÇlœ> §dáô 3ï&^¹ëÇ–€ ?;ȱ‘“ôeŒ~×Ó»–ËUþæÿ<Ï»/\¤9¡ñ$æ²!ì”áî$©3iˆ?C;ÇŸp}¼œz[\计§Ð»‰6? Tìaˆoa÷ Ü! +#.לpÀ›°ÉŒÛwÈ qxà^ú³8Æw„C†|çÿ~—Wïm‚Ê ƒ6BWë,ÑÎÝÏ}¾”ùÓ†ðóæù€ Þ>Þ¹ÍHÐ-iW©žG8cŽa–,ÇB–¥h[F8 ,Ñjp©F'» (=‘¡÷q§çÎd‚Ü ÷ §èõj}Ÿ$lP¼øýyí+gâÇèì\9EäšáæŠÀB ×͹lžK6†TÿÿØ$É€­€e:Š+¿Ç¨‡#è‘ûh϶qYÙåÚÑëæ[ô?¥pÊÅé³:#·Iža´8ƾÃdìŒ ÙjK?ˆš¼vî^üoÒœ”É_šÞHxÉ·’’Kæ¾jˆžèxu;¿ÙHÞË6ÄM€0”:†ÑS®‡Œzè3†d2æ$9²èÝ1Š ´Š§]zñÈßë`÷X· 66}¹~Æ‹»Ì áZ.Žå`ƒoÙ/óÖÛoñÖ^ ü²ŠØpü&xsÑr³U#!“ ÞÀ=Ú(¿•––!nÖ²‡ö€ã¢H=ï. ‚äuãÆŽ8 ¸°{¹ƒÅ=Šg\,Wl@w Œ&È ’s 8–ƒÓ Ý:ÌÖ®óú?àâNS;$~|Íøëï¯ÿý²EÝèó„à2õ®ñfrå œµUƒk›>òæì¥ˆŸ<Ÿ7RàcTîN€`eÞ„EéÉ …c.vÁÒ¯¾E­ÑÉ9y†ó£ôfúÈ99ËDô„ƒ-,Bruñ}νsŽ«¿·HpUbš~*Zwøž¹ŸaeÃF|'‰°5¢¨m@Ø)B'×iýŸ¨‘’±%ö?fPcFª€oܦ÷#ÙÃî€Àî±Ú³ôº bÑòß=+CÞ-Ðã–Zñ{[8+R´sË3¼wé=¦_žgéÛMd¹EÇšIмgDÿëÀ«Æ¨q“JÝ»«}¦Õ†¤’1ªcØkrg€“è-ÔÜäNŸEf¯MvŸMö€Cfב9WxX–kydí,9;OÆÉêdpp,Kèø½Þë·N5¨27=Ç•—'©¼ÒÄ/JD~bíŸ7„¿`€ð¶ ç.oDðæÃ€[U9Ú[Õí2ÅF*tüÿ„N¿…;d‘=`“ÛïÒs0O¡¯@ÞÉ“urx–‡m‚9 IU¬¨‡u–ª‹”/VYxµJí½&áŒDV[´TXFÚš«IDAT&JwÉDòÞ5Ä?g‚9‹íÃßÍè–žB¯‘_~%çÀ“û,®Ê!¦–êTë>Í@e„Ý,¹ý6ÞˆŽDzýV^«˜8ŒQALT‰iNGø“!±q“šBkþ|*nÙÿ¼ñé—·"ñ7#t»Wb@%mÐuCŒ ÀH~ôH†òK\™÷yþå7yåìE®\_d®Ü Ù”ÐY‹ð¯ÞRúY#¯b\º«†ÐW ñ/I0g>SÄí~ÝîH!‰”ÕWÀP\Ǧ§˜“%É=cE>}f/ï¼w…÷§æ˜œ]äÒL…é%Ÿ¥†¤‚\›L‘ùÛõTðfÚˆö9Ãý— fÌ3þV2ø>ÌèŽÌA6_ÀñrD ½µ|!ÃC‡F8=ž¡^ɳ¸¥²0K£^%’°@=Ô“×ã¾~Î-‚áös†ðs†ð³æzƈþ„ð‰¿å›?l&‚x%`¬ƒ»:ÅÇJJA¬ðlÌ z‹ å™Áº&ý` %\YnÀ5Á¸w×ROB¸>í‰Û¢°ñÀ'¯? ÃyØB™ÆJ³tÓ¾FI””+¬J¸6ìêim†˜3œ=I»gÉØÁf†o7:,ûa“Ÿ-ÀHÅá=­"“D  Ì9‘ ¦è¤{Ù†sw[Ì’1Q¼ÄH²uÁV×õw ú‡„Àžýq¼œ!¶>âXéASqLL¬ÕÁ*ó J–20˜mýxШË\nG®ÿ°@cö•Ãûc¹±Ršû•æ~ }Ë•ÓIÒwƒY/¶nwÓÞ‘k]Û³ï`sp(]88ÒCah7²5·+ͨ ×'RA†Áª„o‰”,ìëÑê¦b»rî`s×:ÈÁþ½»È•†[¢>ñîoI›lÑæZp¸z<0ÑÆ}&â˜lʸ#¶÷Ÿîqï°ËÈäúFZœ¾Â0÷*ºù€ê{`@Û£ Ü °5VøQàpÁ…§NL0vü£aiq¯ÚþÛ ŒQ2B­cSé]EØ× &D0†N:õ@X;¸ókº-]Ü?*8tâAŠ#{qg¸=1SÜ/ƒõ5žgFõÙšv™óM·fÝÀæˆÿå]xdÇþG?­GδDÜ:“ŠÊ`ý­ègFZ†`ÁH#yvp‡WðX'‡àÌ㟠8¼G‹û´ÅoFçǪ ¬¿õl´Gúu|kHª˜·µ°>Üÿy`OÁƒöõrò‰ŸAGÌ¿Åõ-• Pas]ú?ýFOïk±ú.tÒ ‘ÛV lwŒŸœ½½‚Ç>ú¥ñ-.ï«´#ßÄÖ^qWpàaÍ·¼&&Ћ.HÙÀ&/ø,p&ë >¶—ûŸz7×£9žv¼?}$ ¡¯s·°†rÚL¼Ctyú@*(´€Mý¿ôÉóÅŸ}ŽñcÑœ«”Õ¯:?ú°Ê@ªõ{2ð‰šú,6Í*h¢BŸ°^¦>s +„Ðñ}«_'ó)Ò?7¦èê‚Ñ e„Á9tÑh]'¨v°ñXD×á=VÈ,‹7~ð*ÎÕïR"“/¢¢úÈ Ù„ úø4®,]o˜4‘W@rouÀZ¼0MI]zŽvYø¶¨ÜnH¶E™EŠÞ©Š´¿óæ$o?ÿ'ÌŸ —ˆŒk:Ý+M|6‰CŸåÉwPÍúê\~ ð#¨EZ \«¶¤ÀëèbÑ ëØ­clÅè1+ï›àËpS’»¸¨xí½Þxå%&ߣ¾p¸:ƒjV*Qc™¨QayêBÉ[À\ÞY€—®Ã·¯Â7/Ãù%ðe  —Ð "ÉP'µ¸j»¹Ž±ÆÑáØGÑ¥àÇ0Û×÷xЗ = å82h³·'¦Ï•ÄÍ Vc -Æ…0CÌ}Ò)¨†0_‡óexw&«°àëÃ:Ø;ó'æø>ºMlËKí˜ÀH†DL.Â1à#Æ//šglÇÒu}Ž9z\èÍèpnr– *>ʾ>ûR÷ ÊXw…¦ÀpµD÷¤G¼Í¡»†^Fp¾²€Ûû¹-Ú§†Ñ1ùqôÄûÑéÚa£›“2î[Qyé†ÓÐXöËÆ§=´1÷¶`ì“K†ûçøÓ»wpëqŒdrX‘öä±qÚ“Çvpô‘¥={È5*%¦=¬)Ƙ±ê“95t`™v_`zà¢ùYâ ìØ›dÌ&³ƒòèdQÉ}æ($ÓÇx)#íI¯_˜ºoÐìXN]'#Þ|ÚÃ0·MŸà‡m¯¶ô$±dòXÖ€"Ÿ’ž9’~?Û|r )¨€nb'@I·ˆÅl£V±ëf}éaR‰šHÄ}zè¤c+%¢Òý«ýL¥ì…mûEÝ KÜàH·wÅ]‡Zåçlw¢ß¸Õïà®ÙËþÿ‚çÂÓÚlÒIEND®B`‚ltsp-cluster-control-2.0.3/Admin/images/configuration_module.gif0000664000175000017500000000164112026403127025240 0ustar stgraberstgraberGIF89a ÷ˆ®ÇJWm×××7‘ÿTi‰yœ¹êêêíííbªþR`yD™þ¯ÒäMžþxŽ©õõõAHWo­ZyžšÀÖ¨ËÞ)1C=DUµ¦v?–ÿÿò¥BK\ðððççç3ÿÍÍÍÿÿÿÿÿÿ, †7,X0A 4€¡Á4˜h âhàÀ \À8aãR¦¼°€ pè  ƒMР@ÁL›77dØÉ±(ÈB‰]ÊaÀb°´Ã† @¬hqCT ˆM @Ê($ðÀÖƒU›ÚÊ­ ´m@;ltsp-cluster-control-2.0.3/Admin/images/setup_module.png0000664000175000017500000004354212026403127023556 0ustar stgraberstgraber‰PNG  IHDR€€Ã>aËgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<FôIDATxÚbüÿÿ?Ã(¹ €GÀÈ4šF8 Ñ0Â@&€h4Œp@£ `„€M#Ðhá €p&FFÆzzf ññù /#ü › Nb¸té4Ný½½KA”:»uÝâ+@öXØ¢†ñ÷?X®¼<‰&þ"&sËHÏ))¥ ššxÕÄÅå2L™ÒÌðàÁm0ŸOáÓ§÷py&&&©ÿþ¬¸ =&¤'Àu ȾÄ—ø)?lþ [(*ª3¸»1èè˜0üüùêgx Ä?aóT€Âˆ••áÖ­K S§¶1prr3|ÿþfscã´rÞV^^>°ÀßþüùÆHáûhþ ù D*N.óè9 üïýû·1ܸqžÀèYЈKŠŠj nn ÚÚÆ`?þúõ ÉÏ @²âÿÿ @ú;P¨˜Ö‚„yxxØÎpâƇp°³³k¶¬’””Q‘‘‘a›õéÓW†/_¾2|ûöœÀ~þüÉð÷/,Qüƒ%¶@"†ã/(­X1‹áðá]tM4¢€‚‚*CQQ Øo ø“ & ²–ÿþ«sp°#ë/Ãïß¿ÿÕÁÿ‰R€…áÍ›W ¢ ……1 =b¦¦¶ÑQQ}œœ  `l¬¬"¸€ÿXüÓŸ?&†o _¿~Ó »ß½{,E¾Ü¢ 4ç Ãû÷o&LhªûL·@#¦ ÀÍÍ Œ´f`Žÿ Kâ0)yHÄÿ‹Öå ‚‚üÀ\, Œœ /^¨ö#¬î6­¤¤äŒYYY@úEEØÙYÀÅ;Ì,,R†‹‹ ÈgdF:fUÀ˜Q”SAê@Ur®…Eº££Ðýú`öµk/žFµp “@9 ˜s}7PÌy‚ ââ¢À"\”ALL˜{Ùøù¹ÁE>(²@‰àóçOÌÌÌRÀ ê³}UW׳pu ÈF3??°„á`âªÇ]uÂÒ 38€øÀD Êý „¿~ýºCéZZ °Ä+¹@b11™ K–L§J¸Ëp/ö‘ëS` Ë×ÿõÀz¾Èãäååeåz1p®ß ÈaPD*(ˆs4¨~~öì9ÇïÌùøο””b‘?~ƒÕrppÍáæpvxDâ sYY™Á‘ ­©Ehxx ƒšš4Òr{ ”@‰@ZZžáéÓ‡‡@ ël™3ܹsÞ¨^0W"UD”ÛA‘/ ιll¬ðœ L àÆ!¨t’G,a|øðAˆ ˜08À%¨gÀÉÉ.9`E=þÀ ÖÇÈÈ F°0²¼ºº<·ãjˆƒä32ʦOï&ÌG…@ ë‹|PX¾ÿÖXÜæƒ"ZZZ†‰²²¢ÀzŸ\̃0¤»‡(ªAÊýbbàDÀÆÆ | `õÀl°q‹}HiÁ.=@¹”‘!m\ Ò&Ñ 5ÿþÓ€ÆÃXä¢÷\Ø è¶` ýˆ @J Ò'#£”¡®.—¢0 ‘ÐE…¨††^2°J Öûîàþøë×õ?8B ¹T/ƒ#x˜–@‘jákk+‚‹fvvVx$‚øˆÈf„v¿Pë|ÌÀ.a@ A`1ï4ãPm=Pz/T¨TpFz°jpš(ÒL, 9q v7ABBÂSÈ€ ãl‚‚"–Ëùøø%eeå"€XßÊK>pÑ ó7lD¹5¢A8 åtX]Qψnˆ3üúõ—áÕ«ÀÒé)°ø~ L„/>}úwø4{&¤9ðÏ/Š »@í P“Ÿ_áíÛW` L8³€‰"ä_î޽ɰpáT²Æh$”üVVÎÀÆ›$7¸^‡tÏ ¯W¯Þ3ðñqƒ#”( †Z@"ÿ?<·ƒ”ÀJ Øä,± ôc/ @%¨J•<¯_‹3g6X³An`cc7`…€]Kap×dî, ?~€•>¥ì qÓÿþÅ ¤¤Æ ªªÉpûöu’ €†e””exþü1,÷«YúÔ݃D>¢þáÃW†¿… Rà8ò ‡™`‘ÎÄ„\M`O,¸Èn66Fð€;»¸ j@Þ¼Étó3pÛD\\ˆ…X˜xÀÝRPñYüñã'0ÁÜU}@÷ƒæ‚Add ÃüùSH( a—¢¢ÒtuM*+SA\A1`ñ) **YXXá‘«¯A¥Àë×ïÁ÷ º™ˆˆÃ¹ÿþQ–`lVV&`c’AYYܨ|ú’ @]JnnvhwbÆ¿LÀêJ<’øãÇ Ú{ÿþý]´ËhÜ#P›&44ž¡¯¯¤ð ¦áùÒ ††à5 à =}úèÞË—ÏnƒX¾ÿXX$€e>|–_`,häý‡÷ `Å<òü>¤ÛŽÇ¥ùq,Œ`ౄ„ƒ¾¾2°8—æzn°h̹äàãã`ÐÒ’vM%€Uƒ$(ñÊ혔f{Ø^ðó‹ ©ý@Ã*äåÕÁ§vAÅ?ûöåÝ‘#»‚rú»wo õ÷?xÀÂ&y@Ý9äÈ$&Àıö!5Å&°cÙ˜¸¸Xnad`bÂ=ˆ*!@½PbVo Þ ¨·Ð +ÍÌÍíœ}ˆ3€V 4ƒ‡T|¶žrrrq]¿~i/°¸òåËg†oß¾¢ ƒ]²²bà"ðÄ$X¤ƒÚÿþgøýû/0áýÍ¿Áôïß iß¿`yäÈ'”ˆ jCJJ„ASSH˃‹ÀD 43$òŸ‘‘9| !ßàááeE,MÚ4Kù÷ïßqýþý“¿988D~þüÎðæÍkypq*VA-rÐÀ¤ÞfÀ¨Ã!|Ô6(ÒAú¿ÿ ž5Mù‚"$ªR@F )eÐ41dÜ€^4ã' Øo‡¶ää$í€7À§ÈpïÞu ý¿j²ë€ÕßG..;;W¢Ì !ŸXYAÕßgh‹¿§É”³ @¤nÛ_pÎÍ €¦bAƒAüü¼à<Ø( l0ÒåCOqPnõÞ¼ù^ô<‘R i´1ÂGA£… A$^ ›Ú°#?€J•oß~3\¿þìŽÿþ€ý4ï0qþ…$°à±b@ ùZD«"ÛhiéàÉÉÉ .!(XKý?Jä23³»Yà9D®DŒþ–@|Põ*âŸ={ Ž|Pb‚ ëBJt ©B ‹A¾3¼}û¼ZHDDX*°AÍ&-€Ìûñã°Ëø€áîÝ'@7ýv ï€rÿ_&&æ2 ’/iå¿ §N&ÊL€.Ý@&`ŽWÎ>“8r@Ó» œÊ°.rކLÊ0@#™c–@Eûׯ?>|Îõ âÖEÃŒ|ä^#|ÔðçÏ_À"û%0÷~&NQpiJ<Ä&[@‘ëÖ#†Û·Ÿ€Ý Z–lä‚F1A‘¿¦vÆe %¢ €†KàTW×±USÓ¶åhnn`¤ý×Å úá°Áôánl£ˆáßÿÀ*ã<òAúa |ø žEèï߿ߟ={lÉ­[×ö=~|ÿ1м?Ȇ±û¤òòÊ*jjZŽêêº~Àvˆø‡o€>EШu;!íÿЈúl³pÒXj"ѠŦ 9ÈzÐÂHC1¨eddÆ ¥¥f_»v‰¨ –‰xq`j `03³G·µuGàîÝ9î%1Fñ)(¨™ j@ê}D6±ŠHlu=¾DÂá üíÛgpb:|xÛìcÇö÷Bê˜ :ïÀL wîܸ ÄçNœ8´ÌÆÆ9MGÇ üÁƒLr@ó%ÀöKJ Ã{ Ò4˜ê–”AÚ ¨‰Tb€z4\\¼@¿q¥ÐM ýˆ7ajAû ` R¢â €èš„…ÅàZF šÕB®³@9ÍÎÎÁÄÄ–¡½½¼øF¾U``ü v €5ú`-~ÐìçÏßu/+¸ˆ… ¾0"Í ãÿŠ£'P± j‚ºZ¿ÿü)'§¸˜^áRçb!(æz÷îÍûM›V6=}ú脽½kí³gD ¹UX—Oõ†›ABä¢!ŠH š±õr88¸AU?°=¸Øë]T²–`á ÛøBÝæ„„DÅ}/ƒ½½'8‚@£qH‘Ïc@wË0TVvƒõàúúæÀ@cÕ‰ Ö1¤øn…ƒ6c¼xñØÚ~ÃðæÍ'øp-ê„ê¸?"Qü‡·@âÐ]B¿UU5qmÙùŽ-Ó½Äo¡%÷Ù³Çw¬]»$ÿû÷¯o^¼xȪÞ½û ‚­ U ŒÜµDL>A0(ƒ"4S(, š ”êgSVSÕþü> ô÷: &Ðè8)ñ@LôˆøÐÐd`„öb‹xP¥Ý Ä a«U L KÅ µ]8°Ág'))ë ê–AuØ ú@cñðþþ¯_À ¹gÏÞëñwài_dê9òÿƒ"Ðÿ#- '&`½ËìîîGÈË =…w¡‰¤™ïáÃ{gvîÜT ,~?}z¼y´T"€Ü ¢!]Jd·`&ÐȦ0™«K;==Ф*° la2ü&PÃð$P P3/1ñ@Ì X%)ŽüÐÐ$†ˆˆtUUmèLݤQ2ÐJW†e@dž@(§ …î ðVjH"°¶v}ÀÜüèq†»wÁËžx€â¹22 ¶ HuEÁ@Ð’offÄà ƒTGƒºuà”ÇÅŽ4oŽLÿ‡7Æ@n%иú—/Yâ›deî€æÝACРE™hNhûð/hC•íÍ›W·xxx¹ÅÄÄ@‰ƒƒ\ïƒVC°à†¢!Ê€6zÉî)€Ô€–“IH€–Љ3ˆ‰f2…€â¼à¥æþü–ˆN@傞ž.[ Å@ѤÍS‡„$288xS8Z®—âùÀân+0÷êƒ"LBBœ4~ p% ºí@ù@XIÒïààÉP^Þ o4ûØJºº¦~ ¾8dÿ?¸ÿ Ysφ2ò‡ZBFã@{ô Å-êÜ>Œ†Å åY þ7''¬Týg 05µbHMͶº-h¢â4œ9Ž;¸øë×/O?|x ,¾‚K#XIƒZôc®9€•'FðÚ11ÐÚy`Æ0bpw·c066f6=ð`0aWD“ª¿½Ñ#äÍD`Ž=üïߟPC´èQZZ¼-KRR˜ÓyA#mB@5+€Ú `2Òÿþv³……c0?¿€<¨% X±² ÔuCæE´¤áÔ€ çb.ð@ÁÿÁu4¨ÿjyƒ0PÃA¥(€ì±²rº™ŸPp€ N9ûçÏ_»g›@ÕÖçÏÑ/puYlʈ²^_"€)¨J-$­ílâååWmÙÁÿDí ª'€€€pNE0âíÀœZÆÄÅÅ Œpi`ý%É ®.Ë ««È ##LàDTÃôh€ æFØâ `ÿ^ÎÔÔ& t@hW(à@‘ùþýk°°9zP+RÇ2Âs>dP2œ ê~¡a&} ®//¨Í.¡€‚ÙÈs Y NNî °Ã!pÐÉ  ”ÉöàÁÝ#ÀôçË—à* 4ÈZ© µD^„‚¼¬u! ú¢È„Õ_pô ´ü ˆ:m €¨Þ û ºà F^9й…ÀÈàyTPP˜à:LJJ<_Š EE pj†MÕ‚nõå@UF(™˜XBBÒ€UŒÆóç@›2A% (Bï߿ž ŠWÊÀv퀊r™°›Rå'´À„V÷£®å‹‹ ‹kip"6àj@9@ãV°*ÊÄÄŠAKKŸáÊôqøÿ ì†5 AgÊ?xpïö—/Ÿ_ðððÉëkp ³€¬I@ž«@“À¤¥H¨Û Jô¿ÿ€MUß!&¾ˆ* P¶¶n ‡íçBèÚ{w ÓÚ€Ž1‚ÔÛ|À½x>T\ òû½ d†<} Œ»w!ûð^¾|*jCòFÀÀæàç”26¶app@FÎ@ !Ð’îׯß0ªnna`—•”IþüùO ÞÀèx¡•ƈqX%hH"ø+=îwD• '§ÂàêNÐ6@l (¢@Êõ’’BàÜ tÈÌ|‘lÉ(°AýÝÛ·™Á£o ñ÷?~*ƒúù \ J\ ¢ÿ÷o~Ð `Ds‚Q$$„€ E ú· ?cxúô0Ç^÷ ÔúD‘¶÷äÁ§u!%bÁbÃ#t +¸„¯¿ÿšGØNÙTŸ ›‡‡%ôJ:: Îx T£ìîîÓÀÎÎ.ÉÃ#ôxý?Èï03 KÎI[1R Ú/I ª÷ßO ÎWÄÄ@Q%˜»¹Ð:oY€Åp%(NùùA§mˆ'ŠŠR`¶;R3ÀgÞ`.Ð+h •––8ÀŽsáååw•@”€ “'%h8õ+8@¹HVVX’H€Ïç¹}û>õk·À'zªP¤ƒìÛ€w $l±,Ò1s$@Uh,ÀŸ<¹-ìnmÚ9(ÔÄX·åÀJ‡„„tÛOŸ>N–Hz¼¼‚@7*¬,0sð‡°Ë×û`¹r®#Ò.$Ä:EP8‚J4P©Iÿ_Õ¿!&îˆ* `Ë–ð¹nOví 3}¢ÐQ¹¿à\‰|f´"±ðäP`€–Fƒ¶qˆ ùrP¤†A¹¸8 UdÜ2’¢ÿƒ¶m3¼}ûغþ®ùøx€]$u†‡Ÿ€úðЕº¿¡fqƒ'` ãñˆâ_q r(Ǫ«ËA‡c9A›3€ö½O*Œºc'P h@ë,ƒ¶%ý†vy€îñçlà2 H€O(ÓÔT&VqøžDôD Èð5(lA#™åìÈ{à+›@çA€?¡ à?QÓD•‹|`1-aff—r¨  ¸è±Auí‹ïÁ}jÈ:=&Œ™7ˆ§3w ˆfdäo”€5æK¬˜P6g‚Ø ®¤˜˜(0²¿€søøñ#ô€…à±|Ðè¨:’à†!ØHL ¢AK¹@%h0´øäéÓGÀ„÷œçÛ·ÏÁÿþ†êù1ô?(cC‡‚N!‘e—Wæ|9èyÌðŦØìƒõ@td hæ±¢ RU€Ì•`¾7†AUPèHº¿ÄÄ@Qµ ©iè)+«dr|häÐ÷ï?§B!u?#ÖéWD£ ÄÊúé¸êDȘ=#tˆ˜³d ÈWÀ6É ðœ»¬¬2è4Pã5òÿ£Œ— cò +èlP•jw¼}û<Z—l‰³A6œ€Vq¢¢¢âЮ®Ø  ö$‡£íÈÝ;Hîÿ^X ZކôùÈŸOÞ/+MüŽàDxÝ^(Fþ ’ 6”Gx£+OxÚ¼D¶¥¹ñCHB$[¸ñºunæF V¿Ö¿ê§à¾Õ*/à¸+áØh(•ÀÒJþ ü½D·#kPô4‡P—­®“Úf‘‚A¸ýà8wzr^û¤¡9﬇RмH<þÙà)€¨–ÔÕu]€½3Pеøa+YÅ3Ø#¢¢ £Ð¸ár艱;—­»ƒÙõAò…͘¦V/\¸L·ÁÇ®Š]P›âëWÐþ?Npc1üʈu—òÐ,ê0-úúAXuŠvò"†lª*Hq¼\=!V%#ì V½ÿè§_ð*e"˜ž={îN>þ¾/@á¼hÒVbã €È  ´€0ðhjê»=Ë ê¢Ár?êiÈüúë× SŸØ¶^áŵ?u´ ž?Îpùò p/@BB<7`¹ãíÛ÷à+9ÐGÝ0·…Þø 3æWØ1pÓCQ‰Àg>rX "ÿ3x*ÔŽ‚ÍÂ0dÏd>4ªøèÑ-Puû¨µ¹]FY%€»{ ƒ……tÖ0d†ÄçÏ^‚<êöÀ†`Ñs¨Þy r"/x±#r÷y]æk\u4$r@­iP¤ß»÷ŒA¹_HHÜÞ€müÊë×襤ÄPV¡î €´º!ˬ™Qvá0B,6Å=ЇM×64Õûwî<„V,m$HbøÍðàÁUpëèÏB Ä bÇ@ €HNnn`Œ4è*ïyOž<¸ÃÜÜ>Ø=’5†@-dP½…¼ÅÒøn°€ºw È¶D€¼t ûHj:ÏïÆÛÀâþ°¥­ ,–9¡S¬ˆ6¨‘* @'o —8 ³@E)¨ýÒ ©·‰K˜KÌðâáN°%` }‹ Õį_¿fœWHá fp$L¬ó€f¬™J¸G$*>ˆ¬€6Ñr30ÒŸž8±©‹‹¨?šÃ96Éiôü7Ä@ 2ÄZøÿ8j›9 ˜Phµ/>|xž?xöì¸ZÀÈø¥»«³A 2/Á=ÊõxŠÔxƒ-ÿ†¬øÃ9’:ZG¿Dê=JJRàs…_¼x.êA~…sƒ´æá°íU éq1Ï3¾|ù"Qñ @D'P„‚FÀ–lÁ|ÉÅÅý tÀÐñ<çÎØbffÎÎÎ!ŠÐÑ« V)lƒäˆ6èf &,›/q—6t=>Rú Xì?ïÝà&†GÀ@x^ ZÔ êv!wù@ ²?AÇß!=Ä10à 8P• †%hä4ŽJx°º–‰vR‰„„°´öd”~¼šS¸~õê•EÐ%gÌÀHfff¾´À¶¤nûö-Dgh€"*€sЉI"ï8­F­ÕýÅÅ-ÿ€–r+0þz‚䉷o_CçÊY £]Œà>0(7!¦>°¶’T€º‚ H5ä@‘YÚõ¼ßîÞ½{`s¥¤d€ýâ7 Þ/žµ@9”øKÈB•ßðq XcRÿ3¢t+Aúë×wð¢P‰©H* ç`]Zä1ô0€ OƒºšrrâÀýè/~ЊÉ'OŸÿøñ¨¯*ŠŸt%4;âEsáÝPb@L õõááÉ Ó¦µCë&6`œd‚§¾@Å-d=>bT²‹õx èhuPD~ ¹uä)YÔ쉑?ÁkôAHP„ÃVôÀ´y²í› |BèýûwîÞ½^(Z9ù“9¬¬(«ˆ!;€ÿ`v“˜ÝEP#T @æPÇêÑİ6 #¸:‚4DÿAxIúÖtäÆ-¬!)) .ÄÄäACÏŽq=J;þ,â866†cÇŽù @(roÜ@l2xøð®¼¼’%(IHHÁ=‹Ú b€Ïð 0È( Êi[è-yÌ\ÙŠô/Þ€s=ì\HBb‚ä:ýóÑ£ûàÀ!-- lß– W44 —CðóC† Ak!«ˆ!vC–~CFÑ`§¢<Áz,Уäþm‚ål쉀ºôìX=äP È! »@7bà5¸ì„PÂ…ßË—’@ >ØWBBR˜nÁJ*PáÂY’{tD0|þü‘aß¾­Ð\Ã&ôLÈCüüBà»s@õ+hF uG r÷è¸%‹šÚ±M¾ &çAÓ› }y ®¬eŒè[Ãd8´Þ´ÊèÙ³'`;A%¨÷ðáu`cJ˜ƒ€‚@E%lߤ*ù_G²t²(! 'jØÊcHŸü?x ‘ø1dKùwpÑ …D0l_!¨Á šÃM\Aö &PâÍò}úô ¼µv~àû÷/y~]4q Ò¸þËpéÒEr@‘Ô ÐÖ6 VRR3Y߆,Êä‰#ŠRÔaYD‘Έ4º†«ød€ÁÊ= ± Ã@9±<±hÔ C>©4õ êƒZÁ JJJ\-<}zÜ–V/›™ ŠPăg‚ºQ¯_?— ŠŠZ@ó  <)]ŠîvÁö `;NÙ? A/¨ÃÚÌàÉÈp-¸ËùâÅKpÉj[ÀfJagB–xýÖýï€ñ0!¼aí-ê½´óH­‰‰)°ä{€~LÑ €ˆNÀÔ'icã’ šRõñA©äÐ(bÌŸe ¹q…œð%Ø:ЖlЩñî?ÐFà?”ÖPƒ¬¬a7VA 4+*êåå•Á%Áýû×À‹;ABÐL!hƒhÃç»w/Á‰´S ” >~|^k/!¡N(ììÌÐÕKlðH‡LÕân½ƒüê‘ ˆ1AÆ/$wCV­ ÄšA©•T é_ئÐdHþþýË ¿ý¶]@[Âß«7M† Ö3{ÿ#@ÔԴݤ¤d `¹rêÆxŸ3Ràl\E>z"€Þ?pc´«ñÜõ%>Pdذ\ª—!kþXÁ p..AðÝ< .(bAG©^¿~™áöí àeb ˆÿþý X/h]½ŠŠƒ‚‚<0 _3œÒ$ L* wîÜW ýû²² à†£ºº|œ€Ÿ_ |ã•+W ª‹Às‘AOÏÚ DŒÙC¶˜ý»6U ’‡íòÔÝ?À~¬üý _©,"Úàɉ‘c!ã 5‚á×Ì|úô¼àÓ§·Àbþ:H´Î¯æçÇ{:w(8»‚„a U ‚TЖ_"’GùFû…â"UÒƒ‡œ¤º3ÛA1§œrÈn&ÙÝÙÉOP–µ• Ûb“ÿêÅOPlÌø$›šØ-ß@OÎ@øCLIè¥óc[Ô¡ Œp¨ã…q œþÚ˜y-SâG×91ð’Jž¯É)„!ªjÃÿþjWD1Ü»PG"©ï/4¬ÖîX×oÛ#sí¯…X£‘ÄJŠl§Hw󾧈“RÖoD­®²ö‚HPÚ虺Šî£²Èì©IäÜ™BÖpz$€p­eÙt/KúˆMsxûöîŸñ@Ä$~U P‰[ç„–<j8¡öëÉK°nßû÷ÁÚ: X´ÿ{þüé‘›7/ï½ÿö¹÷ïß¾ÿ¿a=O`° ˆ+*ªê±­œœ‚×/ÙoÝzlœŠƒ»„ Q?P®íCE>H 4OêÒæïA“C ~ö«W/€9RCv*A–‘!¯!@>WÒ­ûƒÔæÐ  © ëéÓÛàF&¨-×5DUUM ¥Èpï bb?ãçÏŸÁúA3}ïß¿ve¯€Ï&.Ð%A›an8yò$ø´J@±!/"**.ê·BÎäû4Í‚tØ#…‰R´‚Æé!í€÷`ûÜÕqôè¾eÀHÿþdBÚæÃ,a¾xñäß:qâÀ`;EÕÚÚ)FUU#àÍ›çÌ  :WV-€Î„ôÿ!¥Ø¯_ÿÀëEE…€mepÑ :ST¥À¬ñ‰m»tß ~üpè/`øq]¾|iÅ¡C‡K€ ™WwîœÖí—€ ¼ïàÁ.P[åúõ£À†çiЬßç«W¯uû£GàË»@¥Ñ¹sg¨ ˆP ÀÊËË/ ""* 9xi˜—Üõ‚]‹ î œ€ZÔnÒ©×øK„ÿÂgû Ý<Æ<<<ÄtpCB€ÖÂK@1ïÛ·¯_®Zµ°($$¦[LLÂúÁƒàݳïÞ1€Ý šš†ìÁÎú…$€ÿàžˆ†$FÈ1m 9Øò/A³šs€YÀa:ºÔUÕýÀFÝw ÝSÀZôÕÉ“G@cö ‘;¾GîûùóÇ›ö'O®)ƒÚ Æ)(Ñ€Æ^½zuðÒ¥K@z?rÕ*mW¬XNí| D° ÀÁÁ)¬£„!-^Vø–mÈ$ l­d ÓÛ·¿Àn`†SA-jPw2—Έgœ2œ éR–ƒK A`õÂhjjõÿôécÄøTM€–E:Æ ã²¹?}úðyݺeÕQQI³¹¹yTŸ=»Ç /¯.¹ 7}1AK¥¿Ð=uª@îOžÜÖÉŸ€l>`âæ·ä99yÁíPbE (!€JCÐ:‚û÷/»~<<ÂÀ´Ë¿ÕÕU鄸¸ä¼3gNlöì1hò„ïåË—WöîÝ›fiiÙÂÌüÐrþï·§×®]ë»uëÖ ;>¡x XåÀíj€"ti”¼´´œ}rrþ GUT´ÁÅd}?ÊZ8Ô­JqPBMƒF ÑRE1„ýƒNÂ|ýú5¸È&Š›@5†Àåûž=[^¼xlÝïU* ãg>«©i[†O&»²²øPyy1ðâPäƒ6Š€Öêþü h÷mp®¾uë6°+x Xb¼7 A™Udw5yxÀ4(Q€Ì{þü.瀽 `cS\€öêvCúô±eãÆU­À:ÔM߀aÊ£®®L„¬wïÞýõëW¬G{#9‘OÌè @á+@å=“””œ8(>A¹2@Á ÅùˆË“¡«lþ@Çòp6 !lÈp.¬ U7ÀâW(¬ l ^quõ×ÃS§v€#ƒš+Õ¢Z´zëÖÕcׯ_^«¡¡õòåcpäZÜ®#|fT¤ƒJ#Pdkh¨ƒ{ `‚&¨›ê~ö¾REEÃØä ƒ3hÒ²C2Š#““çzÈ #¸=:»t=<¤g™H Á‚6 €°Îp ­­l¼V‡ŸÁæA§yì¢þ…VS D m»¼a@@øxÉ—ìÈÐ,d"$—² ÌÒ!¦2K¸@õ!ìÔm|[®`‰ 45 ªbøù…ÁÇÄÕ‚n]Š÷”3½¼€ÕÀ=ð‘À ëÂ_¼xzçÉ“G§ddäAƒ+ º4.†¬R‚” !b`Â7Fu3¸ÄaÈ äLàDZ RÒšsÐÔÔ€¶‡ ³yQïàÞ0ìî€VÎ!5ZŸ2 @ø¨ÍtüwPãìÍ›à”Úî:!•‘ñ'¸áj Á–}¡okõëa7i`_òºAÔp]ú,³ÿüùƒ,°d¨*(‘ññi À–5Ã¥Kç¡}t‚àtœàÿÓ§ŽÉÊÊ9ÍFÞð¬Èí° £a#| ;‚……àËÊ!÷@hõ0t96°d’GY@Z ò7¨ ¸zH­z›š €X4¢XÛ·\BBJ_HHTvJ5(b@«nAÛœA¹Ô€LDzƒ[Űîdö°èÔ ~PUðäŸû÷oß03³þìß3A¶Sÿ†vi™±®õ;Œ˜Ô‚ôÿA]@ЊbH—•ÞBÌü·W@Uä\#°¹à §gL¸ç  BU°å}Μ‰ ÚÚ–Àõ•””±úöí3'hÏ=(w€V ˆ€—ŽªÐL¨E<*f!‡9ýdzùV0‚KÐm™ Ü)&&ÚöÄ,B%Àxdj´d[€vnè„,D.‚ 0ޤ‰/\8”@G´ñññó€T€"T=úø+âa7‡3 ,9GßHŠXØÉ€Ñ‚±AƒA  #PÎ% º¿@ñû õnnÞ`3@ÓÓ°­¾n è^{YhcTgýÝÆ!..¥¬«kä®®®å, Ô`Ë·@ AVVy ¡Mä-¨šmr€­Ãõr±_ï?|ËóãÇ «Uo‚« `î-KN¶V£¯CDÞ‹0XÕZ2þ4ÐeQÞÞ€U–¼$°±§¾‡OYY˹þˆî*ò°1ú<>ª$÷ƒF÷޽^Æuõê1P›é+Ph è9¨wZ±´zõ2p AK@Lu@,O þ(!€Ê;P lHÝâIGŽì]¬ªªi¢©©ç ªSß¿Í.&&ÎM5sÌÐ9sFðÎXÈà²Ãp—°±ÐrhÈD ¤‘øæÍ3`1¼ (ºd´Lù!òjdô[œ*)||‚í¤¤d&¨<èÜ?ОС͠۷Û'07 ßŠíV1ôån°â2t 9° 2[øÿ PÝ{XB½uë:Í#ŸX@„æ@õæèXûC(T5ðÿþíç¥Kg÷¬\9?çñã‡'@ݹKï/|‚rÂ5|‹ö[51ç`ã ’à=ø ÀjA6ÇžTtˆ»@ c@áŠÇf@÷ÌQUÕØÊù –¿¢¢°['lµ+‚°ëã0æ-Ðo%FЄä,žßÐÑ? jëüüùºúÒî #C©÷ óÐås̃¦ @Ä. U C‡^Cgß@ë@ Ø@Gh¾{ùòÙe{ÈY<âà5ü ’T€VcÛÞ…mó'¶’–@D î!hçÅ‹G 9r`à–K„B :ÐðàIh×êtvX}ý7š§ýïß6Ý¢¢²àœ:CHCCºœ mf’mŒ‚¾þÉ ÈAŽ~el(4ZxíÚ•A“ˆì"€žù ì|¶ÂDEE A¥0¨:ÜI^^z[F½On"÷KU‰²²4¸î~ûV ˜äÀ‡CA®„ýnqƒZö ÑJÐ@ ä Ðù„ûú@ú@=ª&ÐÖtÔöþDÉý_Áu;ìX7̘Àóú . ˆ ZØ=ëçrGìYþôDÁ !Œ öönN²² 6 Ü¡¦¦>T´ TTƒZà¸÷Αž`m y HÍäîÐ…­Ÿ‡“ö©(†ì®©U ‰¼†õä #0büõë/8âß½û‚µØ‡¹ ”ø@Å?(¾zõ¼ßhç ñÇ`3  "<'ŒÓÙ €••UXBB² TôƒêUÐT)3ó?ðl¨n…Ü’ÅÝÇD…D€œ[¡+™À Ú¹‹†Ft×w¢ž,†m [I[¨ ¹sà3|¹6¶ëÙAboÞ¼'Pãïáà {$˜€¦ß‚¬,þÃpîÜ)èQºƒÙGÄhjêÄŠŠŠë= Å— 3Ða  V0he (7"Iþá8…c_!¾Þú‘1¨ÇÆ1Á7ˆ G8d’IæŠ$ýívðàèÐ2uØÊ_„}LðRP ZrÓÇ×ÀUÐ…»öMMé^¼xžáÁƒûƒª@,äå~6iCC³Pîm·-Ä»¦ v ‡˜˜¼ˆ¯$@Þ.¯$@ÝKÀŸED¿1A…¼µÄÁ¶6¶Ï¶Ð²¾tË3èœ#ÎéoPû@ 9ASÀA«ÿù éøÓ§.\8Ç0Ø@±—ûuÄ…E´Aƒ;ÂÂ’ÐkÍûï!Ë›¿‚[Ú "Ç"ï¨a€ç8Ø Ü Í—È‹KII„ªl9øäÜÈ• >ýóç¯àó¨7‘€ ©å/à¨ÐR¥z¹#Ø=gΜD?YeP€"9‹29CCÓP¤II)AÏáa†n›þÒ"þðáxF 47€\€" ¶ƒTÄ‚ö݃ԃ&X@«ˆ`+Ò+ oó† éBŽ­efPR’oR}óæ9xgìˆ;ÈÆÄ29Ð. ®0½ hÇ4Øú ÐäÏ£G# R#//¿*( !:ýEæE_òöíð !dˆøtvðüâ&ÈÆ È4ë›7ïÀÛ·A§zÂJôÓh½"ÃÇ7®Ï¶w~ý×kÿ™€ô11‰e÷a‰góæõ$ŸÚAO@¤$ÐÈŽØ×¯_Þ:´·ÃÛ;`ê‹8A·XJJ*€§?!“>˜‹B@=Ð Èé^ˆUCÞþ¡ÊN( “±¾}c,ZР=(¼ä'äA)\%æI`ˆmÝeðõ«4øÄ®ß¿ð¼zõòÉ­[76C‡ÄAﹺz‚,‚ª¾åËêÈ€"¥gå¸sçÆÑcÇõ€< šªýðá8’A‰¹/¡™Á½ÄaLˆÄ| ꈤDÍ)€ªȺBF¬÷é ŸŠØx‚.÷>K;¸rgîS;‘»ˆâR €£HHȃ/³‘‘q7'tÖ´Iå;l%Ñ×ÀÛÛ; Rh^ó4†yNŸ>¶ìڵ˫@ã sx@õ"h6 T|#¸@ZöLðîL¹°KQGÔPW`]KH÷Œç±­Èó K¡ +’A Z jl‚Îæ·jÐN/©!&ÀÜåÛ&,,¾¿—““SË×7@OQQñtúì×›7¯3ìß¿‡a(€"u 胪öÇ÷w½~ýêÔŸ??‰à2¸H‡Ìƒÿ·’A @Xäƒ"røÃkð&JÐáO#Fø8zc¶÷­šèT!æãA;u@gìƒ"4H²4¨Z­ :•4V* `»qmi™JD áfPÕZ ÿõ„€=œ|WWwx*Möìß¿—a¨€"g$´ó´s…دý±}ûÆz`n~ :Ä4ü 0Ðv1P‘ Z2jäºy ôŠ ´O²›è¸}ëÿ£Vµz±ó(u8®D9Vîx~4zJÆç_øèh§3È.P¿‚,Ü•…œêñl(!=zô ¼B ù7`5Æ*]`t>âPDÎ@(¤@­\Ю÷ïßÝ?th_››çÄ/r€\€êHȼ9¤Ÿ8íøHsÍÜÎá‘–VË*´'2… »!“ :ûé>_ìãùˆ£ÕþÁs5ìD1X¯ÔX]ªkíƒäAg€ª ÐÙÁ°­l•ÁÿÀ tT;(€Ä^¾| Þ@úýûÐía°äØ 4ë¿‚‚ƒ!ÃÙ³g‡T B[ÃðÐ21h›à“©©e¢¹¹e('ih˜€c‚T  "÷ x´Â2/»¹ëx‡¬¬:ƒ€€(8B@×½ƒz Æ¨ rhQ r—¹U¾Ý tÌ hyÈkü@PÐièû `‰ÔÓ ]ƒf!ëù‚#äÈIä_n߆\Æ Zç÷æ h¸—e=PÈ|P·õĉ㠧OŸ4‘KÌ•$€hHÚ@üéééÛ¬¨¨Ú7ª#Awä‚6`€"Ò½ûõîùóg'nÞ¼¶¨¬ffVù¼¼<ªÓ2@;oTÀSÊ ¹|99iø@h81°•»È‹3‰€zuÛop„k@,úÖ¼u-ß?ðò0Ðw D*úaR²[·€hÿßÍ›gA‰Øèc´­FÙ:Ñ{Ïž]ƒj®Ÿ˜@”Þêú€ºA mNÚßÍÇ' (""jxïÞXîú œsOž<Ú}çÎÍ“@'9CšÖÿž>}rÞÈÈ$FMM#êõë§ü ùs--s`DˆA‡WP.S€¬1€Å9QõéÐ)[èÚÁг@ye¯@¾} yüTU |•/d‰×[p›TšÝ¿6P¤ï@ìý,úÏ ªÈ'¥%¸­ÆÝ€ Äß…dÌÍ­r89¹Ä^¾|~òöí›ß¼y}4JÆÙ°É M0 ¬ j=}ÓruõìæääPQU5¶ dÁ«u!'’ ÖB¦c¡§s1Áo CŒ*2ëæ'à½ú°vh¾”ëa6QQ>~~¤i`ÄÂÐùÁ ¹ ØØ>H ÔHm™:޴И(@ÇqûíþJ çÎ_S3Ø1%@QãÎ äF!7°QøbÇŽ-•À šývšh®ô3âˆÐú~i ݸÌ,!®úôþ:—¤Êß¿¿ ¹ù/tðv4Û?”adļ?3ü¸:P?´2ǹDrÌܰ>yym`ÝýlhûòÁÔ t jt‚Ø jÌu%A%Æ“'×Á§‰íûl”–íþ9êxïþPD­K£~@4‡ÿ­…‡F4¶½Í Äp“²ºthóׯ_¿{ ‡)2À‹{,e|²ú²•™ù°›öÜÀ|úôxK6dR—CnùÈ ®nì…@¶³IH‚ÈÐèhÌ”ðž? >¨”P>~>Êt²(Ô=ÕP·ƒÝpþü9ŠjH@Ô¼746p jæOÔ-ø†–ß@«öwïÞ}TVVÏÂ6hb¯šPlê4¸déñâ>8ç[ðÞ½{ûèû÷ï·%%¥\>~|-{ùò!`"m#ŸÍÙÍT‚ž ƒAwƒ{ „øäÉ Ð±Ðu¿žH)°X »OèàÁƒà ®‡2 j_ÿŠI­B˜Åê{È™”ûåËøö㇠‹È€b$ €XG%ÈôÌà+Ó~üx^jZ%*¦a‡2Á"rTÝopäø ëÓ@‹1YXX·?}útôÊohÔ6áþüùÓ‡½{wZYÙT())†ß¼y<" :Ó4ÅûðáмÐä/ׯß\rùò¥™À®ÝMhCz  °da. €MøþýÛ{Ð?°¯Íº´¡Ô-aPó²<‹ÜB% Ð6tPÂMò€ºzoß>G"°n&¤ÿEÀºÖ)M SÃ8EüÏ#G7ÿþõ‰¦¦Vþ£GWY@ú~þü ®×ß¾}wØ¥›ôòåËýP½ð:èÉ“Çàƒ¤‡ Á’˜^½zùàóç/·Ônß>®ÏA‘:´ç4d : ÔOgcã [7ðçÏpK²È”¥ (tK¯~8hõÎÙ³gg‹õ—††@ýBÀ*çåÅ‹§ß¸qc0‘ ȵ ±ÜÿÐþ:ä¬\vvnð)% +ÙA Ôå{üø:hê4c l;|Û´iøàe, ^‘rf¨ñùOƒƒCúÛ·ow â ´73,1A4(Rt gçý€v!™#º¥DDDDVTTT›““Sƒ——_ŒƒƒUè:6Ø%Èé^ðµÎ@¹} idЙ‚GŽÁv¤tþBÚ¢åô×Ðaí?Ã)w“h0$hŽ ±!UK¡u7ˆ 2K!`nçáá•‘––ÒöÝÕøùùeÙØØ@‡Yõ±²²M‚,%ûÁpìØ1`"xŽÏNÐ /4Ç¿c†€˜@ƒ%Àr&´$à‚bèx0+R¢€5€ÎÅÅ%LÏLMMoûúà^ÂêÕ«ˆ=LrXb@± "÷þƒV ü)Q°B,Q°Cù qF`ÝýˆïÁì£GF#Ÿ@ŒƒíÄŠQ@_@£ `„€M#Ðhá €FÀ4šF8 Ñ0Â@&€h4Œp@£ `„€3`†¦ÿëCIEND®B`‚ltsp-cluster-control-2.0.3/Admin/images/stats_module.gif0000664000175000017500000000164012026403127023526 0ustar stgraberstgraberGIF89a ÷v—´¼ÝüÅâýÕèøˆ¯ÈÕÛäVm¸‚Víõý‹whM[såíõõùüñõúgK3‰»ìŸƒëñøæòý[;"®ÓåCL]ûýþ±wFšÀÖ¨ËÞk[x_K±Øü°Ñãÿÿÿÿÿÿ, …)tÈ€°àaÀ‚!.˜øÀ€‡2f ÀÁƒŠ 4j술"7àÐ@ÊŒ$Ѐ¥‚!@ð`Í–83&``„<(@À1ÀPF‘z¨¡é†ŽJ¥Ú4Á­&LeÀ‘ ÒN¸ ¶@‰âÆ];! ;ltsp-cluster-control-2.0.3/Admin/images/printing_module.png0000664000175000017500000002714412026403127024250 0ustar stgraberstgraber‰PNG  IHDR€€Ã>aËgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<-öIDATxÚbüÿÿ?Ã(¹ €˜Fƒ`d€M#Ðhá €X9ŒŒŒî iÓÖx23³Lÿû÷Ÿ°}òw(.0ñ¿vr» €X]‘ÄÄÔ Äò¼@6ãŽ|†?þ1|úôUIBBº(ôˆ/CÁ 4è0и¸X<=-xy¹€%ÁLÌÌL ïÞ}bX³f?ÐÄ€BZ@üp°%€b|A÷Ÿ€Èôl`1AÜLÄ ?³67Ðh#N5Â` k€b`™'"ÿQ$1˜XTàÅ]b Ê7€ñ àèþmž b P1ç?4²aâÈ|˜LÀŒÎËÉ8(zSÄ€b|äÈg +òÁ¦ÀćXËà‹”ÿ ô˜žÀùˆ¢ÿ”…©H‘Ï|¨Yÿñõ¹o² ¦Á™þÑ4Œ|¤þV-À"ÿßÌû#¢ÿCåo A—þýûGÓ£YäCÙŒXüƒÐ L€øïŠüHyÿ?š} ¿€J´Á h&¦~½IËȇ5þaõϨ' AØ ~Ž¡uäÿg€E>¶6À¿AÝ AÚü?¤"ÿÿ„¾¡Ö  AXü§Z£‰n‘@gH`p7h&êTôŽüÿ8º ÿ æ@ƒ´ l0ˆî‘dz€øeðV4ˆÛÿ‡\äÿ§C›†Ú €aøGv0 ‘ÿa>Š{y/ €e€œ:s s>8Ñb þ‡¶iïÒF€½€Žüй lâŸAÿ 4H«€ÿC*òav",¡N•F@ƒr:˜Ø–óà‹üÿXÆw# €†l#pPEþ?Xä3bŒ€ü2˜çhýZ‘U÷KGp°7ˆeð%ü³gƒ5òÿãì@€R“Aƒ;òÿ1 OÀü2˜Û4(Wa[4¸#ÿ?žnààîÐY0¸# éŸÁhÐNaIƒ8ò‘º‚$¶iРLÅ?ÃЈüÿh]ARÆ4 Ð ]ük 0x#ÿ’ÿ‡ÔH @ ÂAÿþþý;Ä"É ¬ãƒ· A—~ÿþTð£Vƒ7òÿ#f1†µAÛÃÿ ÚÍ‚4àA^^^ÌÀ ¬ `ñ/ñçÏO)œ]ªAùHAÿ1K4NNvAë,V÷?þ,?räÈZ Ä ð!B€ð ¼™ÌÌÌɈ)`F¬ÓÁƒ=òárXµLLÌ,\\ÜŠLLL ìbccãL¥@éç@ük à €´ ðððˆbddG>hKµ€€˜Æl4ý·­sä3àñµØØØÀ~ƒ¹/TCC#È•b挀¢[ àííÍüë×/.`‚<K#»$,òóóšš&0|þü K 0"ÿ?æªà?¾3èêj0äæv0ìܹ“aÒ¤I`ÿJHHDqrr2rppœòo~ýúõ0|>_½zõ7 "”Y9õº0gk#YÈWò•YYYå€l> +è, Px=Í ¨¨È`mmͰnÝ:†×¯ß0psó Ž©ÃèH[¶YäcËý !Pdß¹s‡aóæÍ ÎÎÎ +V¬`xñâ—ÃÔIø,¾Ãè™””Ô=`¸Ý²oÄWÞ¼ysˆ?¾}ûö-@Q%¸»»ƒNÁ²zÆèpS`.×z\ ˆ™`*æA-|ÈXÿ_`À°0¸ÈWVVÓGeøöí?0ðbk+ îÈDz(Ö¦ùüù3ñcÇ<==^½zÖ PØF`†™³°°hÂzÊÈ?`Âx+//Øx<ThÖ± .<Êý¡FI@d'`ë] è‰@ C=؈ùa“8@Ç‚<ö<;;;A """ BB" ‚‚ÂÀ:Q\/òðð1hjªsÅs†Ÿ?LÐÁ ,Aƒ=ò±¶þKïß¿1¼{÷–!##›ÁÉÉ“áë×Ï ïß¿gøðá=~ ”{ÃÌé _¾|–Š?UÇ%LÀŒ" Ô/ LVÀ#˜ ¾ˆ‰‰]–œ{ß½{·æÒ¥K·¡ I²@±ñN@*˜ZÝ€4ȃþüG:;°Ëà ¬ß¤dddÄÅ%€X ˆÅøùù9ž œëA4dÅì?ð9€B 'OÞæþoÀÀbǺ=üß |Z&ŒR ”@§Å}ýú ˜ó_3hiéÅYÀGÈÁ0¨üýû¸DøøñÃË—/Uá †çÏŸ1 özŒähPÁ ¤¤Â ¢¢¬Ë•ä們-Ìõ@Ç2C#ù/|Šáÿ~ÇH°/^¼®îlœíÿ |ìy¤Tœÿùó˜Ã_ÄœaPÏ‘b—À\OYY9pX€ôüüùœ(>|ÀðàÁ]†›7o0<~üœY€êùÓˆ]œœv=xð öÞ½{Wþ ¶D "vö@O¬b1P。‚ƒ©©9ƒžž!0K‚s>¬ø‡Õ÷ T@BäQP`€F @%Œq´5—ƒ5ò±7!þe†'Ož‚ý I蘣†°¶( aaJ¢¢b ’’R ––ÖÀˆÿ .._¾ÀpæÌ)pbšÇL8jjjÆ@õ9·nÝÚÔü‘˜D@,Dä|c`įbPj”“S&CCpj9„!uRô220`.’ÄÌll,àTìh$ÛÖ°ÿÈ5pk@{2Aá0‚Jc Ø×«cf`D:XÝÆÿ(>øàHf„ñ‘ç þ3 õýMü‡wMÿa© ÕÐnfP¤3ƒý2”~ÿþË@ÌirRó/|~X€K[uuMWWO†S§Ž3ìØ±܆–º¢ÀÕT`éýäÉ¢@áM¾¾¾\@LE>(‚ÍÍ-ââR€ 9apÑ„éäœ vv6pCاvÆÿ€ø7êh#'b¼äÏßÿ ¿þüƒŒÍø d#F ÿƒ£åç¯ðÓF—m#JÔÜŒ<¥‹\2°ífbD^ôÁƒ$@P¡Âd°€ã_ ”`F9à˜Hþÿb&°ß>~ü®ÇÙØXÁÅ;yaöZºþ–º\À˜7°6b˜3gÃÕ«—888DTTTš€ àäpê¯øÌ –K3Pë”âRR²ÀE=ÈÔ ÿƒãÕ«wàFè”ÍÙ¾üàeØ}ù#ß?†—ï~ùÞýÍðêã/°žÏßÿ2¼ûòÚÊf`xýé7ÃÏßÿP†ß|6L‘ÏÁÆOlå …šQ ‰ì?ƒ03;+#lpt¨PŒ‰¬ƒ‹‘A“‰á/Ð.AVeù? œÀRMZ„‹áíë/ Ï~ 21ýdgþîå€ês^^! ÂOCÇ=Wˆ—4¨ºµÄÄĽ‹<†®®†gÏž€FÕutt²¯\¹Ò TvÚeÄ ˆO½/ L¡Ù ¢TÔGGǃiPΧæA˜ìì¬ oß¾›ËL\ÇÿY2|ø*°}ú=`‚`€0/+8å³s˜7 8®„xXx¹˜Áòò"ì âü¬ l¬LðåL6`ĉñ±âO(-„ð§ï€îø‹qŒì+`bûþë/(î~È‹¿^|%†·w ³+ßÞ~öïÿAâ/&w©¿Ï™Ž€ëo_ùùE%ÞwXŸ™™©´c†—¨ s"¬´€èa@I8¿ÿ¶D"#c&Nì·;¤¤¤|€ ÂíÀò¨ä-®  |%@Ð2)P£ÏÑÑ™AMMœ‚©y *Ä“ àþ/ ~û‹‡¡6ΘÁ\C ÀD€ hPă¢ˆPlÌœJ,HÅ-3´1‰u% ù.Äù‹4Fª~ U„ *…@UÇo`Âø Tôñ°ÿ—‰áø•§ g¶žö™ßƒÇ””€•óǯXÃÑûaFHb`ŸžbÃÄ |PÂÿÆ ¯ol˜[0=zT(((_»v Ô+øJ'Ø|@X€¿¿?+°x‰¥$AAAgg7øº6j&XnÙ¼b ŽÆ² Š",àÀüûµp•c¿aCQ‡_ÿÓé"Ff³0ƒåÙ¡¡ÊÃÅÈÀÉl0Ë0œÜ-ÄÀòûxÜà%œ8ÿCÛ11FDQKÍÁÁÉ`ddÅpöìi°¼˜˜˜0(™ø6ˆGÝb LUÚ ‰ 33K`¿T@—ެi`pÃT½yýX_31ð‰J3°r°0¼üò‡a°®£dÄSÂ`æÿ _€¥'ƒˆ„ïG÷‰ý8ც¾Ÿ?ÌPà€’ãY€]PóëϬnU£ÒÒòÀFáæÍ«À¶¯„¤¤¤ÕóçÏAÁ÷ØR@±àˆ?Ð`h¼ÞÀÀˆ••™d'5s?(!ƒ€Ÿ>}bø lÈ00±2ðŠÉ»L_ ²gDDüÔMÀ°ƒ!þ1 mDž½’lìÌ ,‚Ò ?{>€‚88Ø€™êÁkqXqðØÛzùî=ËOï€ Nn5)Y´y„ R@KK˜®€Ç€¥€90lJæ¾£›@ € ˜+A9TXXh˜8÷ÓâtPxþü%Ão`ÊýÍÌà &%ÉjÜÿüKïHf„#ÄŸÿá‘ù„±û(¢Áø?¸«ùû±ð?Ž»À#ßÒ Œ¬àéaP¢çâöv¾|Å›@‘ïùs†;oŸ1Èé‹2\ý{ŸáÄæ; 9?¼L5€m²ß¿±”Þ¿TU5Á3ª ö›€€€"PXT#aKÄ‚¥ø—ætUP¤ËË+[¬‚Б9F$†ÀñóÇW†?ì ¢ _5Ío:-¡c‚ælXd÷ ß@Ý¿¿Døë/$Òÿ¡åzFŒ¼Çˆ·®`Î),ÂðšŸÿçGðx€  8´DÅîWP£öåû÷ ûîœgð´f8õëíGŸ^Û¯?ʳ`íÝÚj qqqI†î1ðððˆ«•ÏŸ?ŸJ¿A¯[°1ƒ MÓ‚fò@}Mªç:hæíÛ7`G³ H00‹·Ï¿€-èŒ4)ÊÁõ)´xå⯿ÿ3|û¡éßЄðï?D-#îè% 0 þÅÁÏÀÄ'ÆðëÓ ð, ””¸Ë‡«Zå`eg8xýÃO±ß §Þ]g¸ l(ßñ—Aêƒ™Š°HbÂZµrÃ4b{÷î-P•À,É5 @(ý=Õ –ˆ1€Ô%`C@=Z\ßó8hÈ?F>)  _~ý§z.aPNEö‡Ÿÿ€Ýtp¤ÿú€–Œ8s”úõÃ/V†\’ ÿ>]wAí*|b1å@%ï½Ï¾ðýa¸ùúƒäs†BSqapñ+^@ã 22òà™WàããSR he€,F…€Â–ÔÀƒ.ì@Cd0×èS©ÈÂñ¸jXŠ#;Êʉ¬ÀðúõïÐ/ˆ(‘zED%*ÃçÏŸ@Ã÷@;qÉ® €P0·ó–rf÷@)Tÿƒ'4©Wìƒ&A¾ÿ®ÿ¾#ÿ×÷o ¿Ø€ ".~pý÷/#éÏiÀ½Føc`ú~óR’0BHî F {¾s 3|b7zA½ÐDظÇ@]½ß •U@éÐ 4±ÕûØBT… žŸ>}%`\‚&ô8ÑU ZÿÔà<–olþŸÒIÐ5ª ÙCÐà(ˆˆ°1¼zõ‘áË×o LÀÌ ß~3}štbæ;0`A‘þàó†÷? %3#¢ÿ>hÆ€=Нÿ¹¾sëïoÀ]AÐÕ²D•°¤fBÐê,в;ÈZV`"…&p;¦ €Ð€,H TGƒ4ƒFê@ãÿ”äxP 4óõãÇ/0äÐ|8¨ š͸}ç–»€ÿ‰Êñ ©OÀŒqû#ýÏ@ö/HnìW ÿVÜïØ¥€áqÜäç7iqͨt%è‚1`ïƒçð\ @è·‡K€ €­GHýÿ¬âŸº âׯßàâ¶ñƒ…yÖ‹‰á-°.üÇÌÁð›GœX2üýƒ?æAꟃ"þÆ`ò'$·3ѱ1G øÃÌÀðŒEÿãa`føþ²¨û døâö'†³¯^|ƒt혇ØåâAþ`eøÅÈÁðþÝ[ø¢PZPäåå/¿‡¬¼bã s¢Ç9@¡— @`GêÈÐ&#I‘ªãA-[Èž8Ì‘.ù ”ê^~zÿŽá›0Ã?N^p#[ýÊõ¯¿30œFüíÐq¬¡zÝ%ÐÝïXÞþågø Lü°Þ­NáããWã6'´ˆç„ÂF¼8(ǃªÐÊ^â«È:¼ïßÀ/¬¹µÂÆðõ+°û÷íÃ/N9Vfð*°ÿ˜8×=¦ã/€½_Hÿwˆ&ð:Fn†O, %¨j…5$ÌhÑ`·1 ;”@3 Œ² €Ð«&ä:6>FÈm \ ªëA ™p.Ì€ 5C&@á_ACNq!ÐF1¤úÔ­µ Ž?&€·Hil¨FjÏ´2B§a™ÈfÆ7JÎ ô*€y8Ô 40‹|P׎˜!c›@ Ÿ€­àÏ?þ1ü”``ÿEþ`·nï# ý™a€÷ÎÒ¦xÎ ÆðãçEð. ~~a`B ^CR…3ûþ¬ÀF ´'öTê²cK„^Ãf¨ž={žQâäd×Qÿb߬*öArÄ6f`Ëš¾|zÏðþ7¯xz4P¬ ¼g`Ø÷€áÛOhäÿ~ à-0|&þ/Ÿ?1ˆŠJÀ—{Qc ŒU>|æ"!° g)€bÁR™ƒ&/_~a8~üƒ„„ƒ´´0°AÁÍ;¼¶<Ôàƒì}c"Ñ¡À¾û‡w ß "6vpäƒrý%ÃÁÐá`f† ÃýþQáÍv`&økHø1’”Ë‘Ãd¨T™óéÓ7†»w_0¼~ý‰áùó7‘PFøžŒò €Xðõ#A+VîßÁðäÉ>))aaa>ð ¨È‡7Ⱦ#”!’ÿ ¯ß¼eøÅ*ÌÀ즰Ývùî"fç†G}=üúÃÍðžQ˜Þl0#×ë°V2¬~Í(BââÛ7Ÿ€¥ö[†·o?ãÔÐ&&cz€ik2tÆ ÒMyþü°Txì[rKA`õ ÀÀÍ i2€ Œmkr‚€­5zÞSêgf5y`Ítù7¡Ý@&†áþ²0¼eføðþ8­Ã2f„£†#x] 0>@_¾ü`xôèËÀËÌ!»˜ÁjP—‘ã®bk€-A†‚¨ˆ-i• ‚‚¼ bbüÀzŒ˜Ø¡‰át3(öM  1€¯_>3|þ lW°‹3,ÃÞëÀÈÿ ü¿# ÃåéQ†÷¯‚W3C¶ÄýAÉ,¢éðÿÏð Ø8zþü-xåÇ/Оl™8Á¾: ônàêáÅ h´ïÕ«÷ÀRáhÜ€œ„…y€ G°:ÈNà¿Ð ŸàN ¸5~>ÿÃÀÄ%À°ù?¿ ã:GøÊ îƒz íò XDD2«` ?P¤¿yóˆ?#ý+8±Àºê°ŒIœ­˜ €ÐÀ;HÚå yá"Кg†çzPõðêÕpñÄÇÇ.y€ ƒ ¼æØä‡¤„ÃÍ»œ ¯Açd±B#¹-Ĉ7‰HF¡ÿ!aÐT5¿ ƒ°¨°ûû> "’i@jPãú °/üþýg`þ\¼ÿú^™VCJ£Vüÿúõë¶ò €0Ú°–>h9//#Ñ–ÀR"(·¿{÷Ü(94ÐIÜÀÄÀ4ó/ƒ¨˜8CDhûV†Ûoþ1<výðF†7_Á>àžÀ¤n ,q Ƨ0#"=‚a‡ÿG*Å Ã. UY@Z”÷?ƒœ 20H 00HK0h‚«Êoß@g|W¯ bDCªÒÐ."|)ÿóçwøŠ£ÿ£×þ '€¤]Í Â0 þڱͱA˜‚ž¼û2>½>€‡ ºnLçÖš´°<è¡´½´„¤_¾¤¤s€fš üF¾mì\t`øbt`!˜$Id‘á¸Aˆ·¡¨C{¨Z‰Ë(JBÁ¶«"è¹'·£ nµFÙlr-}ÏFç*uí€Ö¨¿“J‹H“ ¤¶B il’Ì·¥i˰Ã*ö°NIÉ™DNÑržlhÎmGJßf@høïú´NÿlðP/œÎ¬øŠN¸Ë¢Ž _¹ÐHÌ{÷fO7w´H¹¶a 8,¥ ÄxàýoÃ?‰yH‹w‹ FcbüoÒíììlg÷¦:w¹ßþ +ñRÙ²d9j/WŠbLg± ½¢Huì‹Émc·‘PZŽ}áa„>»…MÏ.AüÙ`ßòüÃñ< 65qêÉ*ïaèz‡Ú¥ÞvÆüê3Ïí ª«†x‚ó2l 7ï ySÕ1YÐ@‘ÌŠ)‹åÒ@kEwX©ëT O²DbA:–Ž! ¸£5æùîïZ‹ª1¨J‹²e¾7žÏ-û!£ƒ¹9ö+Ê¿Ëmá?›¦Ñ1Ë‹‡>,–º ¬@È ¿À˶˜˜hÕ2c†÷@{ùüüÊðæíg°c!›™Áž`¶8LvVpc4àÁlgpÅ…„YØ$€í fèÌ#¬ÍÂŽäO.Ô‹}™°ô5¹êáK‰@E˜R}à ) @èï`Büžîþ*¶ôÏŸÀu÷÷¿¡“b¿ág 0rw 2áÆBÓ5  ðUã »AÕ30€Àoô* €ÐÀXTb@¦*éÙ/cFé5D9öów`¯á;ü€Ø®Xؤ(ç€äI›,ÉQÌ ów Ž»AŒˆ P¤Âì˰3Ž@%(ׂhPµ;É rìÝø¢ômÜwÐÀâRõƒWvª÷_è €ÐÀ{ÈáD¿ÁG•A6.ÐdÎ@Ddçì?ðþxäóƒÐ‡LIiËüÿØþ²ó˶mX[ RU® Ø@q* aðÿÇ ÎöOô@è à%ˆ¦xFP¯T'‘ºJ3@A;X˜i2ß=,‡ L€ÂŒ²LôŸ‡ÐÙÀÀ¶¨~ýÁ€6½@( XO<&P1Á*1 #QŒ8‚Ú–Ù¬ t<wÈN@nOÿ > ŠÜ{& “?@™²ÿÏ` ðÚËCI„’¾~ýú\PPð°þ`ÿleƒR"häŽ\‡€ô>}zaÇŽMÐÁ£¥Þž'xÞž•Áß?œALŒzÚ*y Ônåª € áçïß¿a%J@èë¾ñ h/H3d_ ¹ž€çý¿|d¸~ý2t¨“i4–ñÈyL\Àºû¸á 9òŽœúTuÿo¼%`îÿ4–Pb €PÀÁƒ¿‡„„<–Ê_¾|E Öó?²ï>ýOíUMÄ• SØ =6ò«_P8ƒª^Xm~…6Q@±`´Aþÿ2¤d#QC£Áçÿ12 Hb¨%Ètù/è¸?3YÕ/È ÐaÔ —À ¨þÿÆ€åv€Âv>ÀcHò‡áógÐA"d-[†¤ÂïÐ Þ®ìˆÔ‘`#ø(ìA]qÈJnÒôw°R÷Ë—/ õ_°œ@ ¨éd ÿÃÇïÁ'Zýÿÿ‡,‚ö‚<ZúŒËã°E"°(û‹÷¼'”3±…,€Âìïß_@67Y™4Š;HسýÚ Z[ýZ €ÂHÀââ//ïÏ?þ²üøŽ´š˜‰‰œÀ  ù·%###???ªlD´<èôùêÕ«.]º?¼W ;Øt;éUï?†ÞA»á¿¿ÿþäÜ`Œ@ àÛ·o@#‚À¼ÈȤéud—ÐwÈÙºxJ¸™™x Ûpï&‚üòëÍ›7á;v0+8׃Fñ @&3¸èÿþ ¸*æþ¯?þ‡õ°H€ÂpűcÇÞKKK_FºÄ›7¯ÀÅh‡ 9uôOðRÜ%(Ç«ªª2ÈË˃gðh}Á&i鋚5`çøÎ\Vg••exþü9F"€+ª÷A£x°µ¤ÕÿÌà®7èPbøðáÃ{Ð,/´ ÀˆD€Â6€ý˜‚.±±±º|úôlÒöÄCÁ瀧W™±'™¦¦¦àà @Ó¶yÔµ„ØÓÄq„=×"/ÇÆt ¦~t³A4hIhÍ$´Še011aØ¿8€”!ŸÃáÿÊÍHrWTÝ‚®˜5âÕÉ¿W¯^=ƒ&€ïØÔÖðúõë#ÀVù`CPàÙ³ÇÐ9bζ…•°…,à‘-”ÒtXÄû÷Ÿ€a>åúîÝ»`‡Cü }ÄIè/à±E>îHÅžp°E8zäc&>Lû »ªáûåääÀ;Ÿ>}èaðR{ؽMìÐ5ÿLàK(ˆMqÿ_ OŸ>³‰í°ø¥¸@aM'Nœx¬§.#ÐáÑ£àÔjÀÒàááfððp‡îSã†Ïƒè;O24 þ¡Ü†mj[DbËùø"·YÄå|bô#³A‘+ À .`k÷­¬ì®]{Á ¢¢Á”в¾t¬´¹€ÿÃ6ò!æ2‚K@Ø®’VªÀð}Åpóæ]è4.yá ±={ö øð)`µû÷Î;7€V<€6qöá_ø¿k×®ÀRà¨ß·o°-ð¼T ä R1¨ˆ{ôè%¸!¨¢"ƒ–ûÿ£Ü8Ü"ÿÿØáYÁÝcd`nn–;þ2Pî;¸”$%\AêAã,?b8zô ¸ç,úŸ¿|ù”îBëœ €µ0¾=zô¨˜>=þ”aÕª¥àÒ´Prâ#¸Þ†­˜…íFÇ 5oß‚ö¶}`ävƒÄQ[œÿáíƒõÈGVÚÑ‹¬TÈÉI»Âîß [\á gØ8 ¨èg‡íýû÷V®\ ¾~4÷þüù3@ס%Àw| @„–²þ=yòä! ]­¬¬ÜvíÚe^P·PYY|5‰¤¤4ø2hP‘…… º|ìJc vï hG+¨ÐÕUÆhü[‡õȇlÐø>B´ÉÒrgc01ÑeX¶ìÃŋ׀á*´€ ¾K²©æ7t¡ÇðP/htì£G÷ÁGÏK„oG=ùñãdz@£/ñ+Bƒ7Ĉ~ ŽAqaIIIG•4QQQc`„ [ùŒ ÅA}|Љ”‚‚Bàcɸ¹ùxxxA÷Õ€/6©¥Ò«Wï=dì À ‡¬±ÿ?ì#~• ø¾eqqA¸9¯^½ehlìGtxx¸‡-éíuë¾|ùžâårÐ=h^rŠëÐtï`ŸÿÉ7.Ç5 àq ¾-þÿãš›€"&Àª P¬){šRRR¦âââzüüüRÜÜÜÂ@óS+èB?FP)ª“@4dƒ °±£Ì *ªlü‰2x{[¡8²ƒœÈz‘ܶj¹ÃÀô鋎;ÌLìÀLñ ~],dqÈØ­-ÿ~‹`á3|vÕ_½ïß¿ ´ Ô߿ķ C|ÂÕ÷Gö@»›dhJñ+ÐQà,‹ùbÀHáââ’”çã㓲˜ Ømä&6YY]nÐyµªª²huÿ¢p†SäCæZþsôw`õ‰H––Æ 'Ožæîïÿ?~|ñùçO`Eñó7¨;ÿ ´¦X|Fô ýþׯ_ï¡ñÂo¡-ý×пϸFý°€"e;Ëè‚P½òÚÀà¦LN £¸€t)sC1—¾¾©š‡‡d'ƒ¼¼Zø;â"rÿ¤1( À_( ”““b¸wï1ãåËׯ޻wë´ÿ:“÷ ʆá¯Ð ÿb cã@‘»Ÿé’Űvh”¤a'R‚ج‘‘ÕÀˆfE>jãï߈¨óq5A›GAC ‰ Øbkk†[·î1((hЍ.?ÍÕ¿¡øÿa Òy*D­eºÿ¡Žú]z*ŽžÍž½ù-Ÿ€ ¨®CïûƒZºÿÿ¼ÈGv è d`b¢lLƒÎ\——‡†%¨x M_  €j+hˆ¦ë´ýúáì×*JI‰=%€˜ˆ¾ÿÈŒ|Pƒv  2hƒÚFl ªN ûþØiGDÓôd<¨¾SV–ÆÈýèC¿#)òalP8|þŒ:NceeîA‰‰Ié6è@ÛT4D³0mÚZ-`×ÐTÇájüAªÄ00*6GÀ€4ãÆ€1ó†>3k[ Ïê¡Ï"«Aìï'$‡ª—}Èç`cÃÖ<@z@ à#b@£¨0 ©©Â ¤$ÇÀÊÊ!¤¢¢í e á‰ÉD³Míÿþý º›K^^<û‡<ò;´PNÄ·ÿªlrÿ‰VƒM®UA˜ne`À\*†{ (<@ƒa°C$@¹T \»v‹AJJÞòæÍKr Û¿?Ñ"žˆ& `Ö¬,ÀTš¦DoüÁnθ¹¹ÃúõÛA{üDD$Œß¼yq Úõ£ú²i€¢IðçÏoPFKLLX— Æ(‰@DDÜí—“S¶ IB»ÖTD“¬ã|A´’’4É'‰°³³`àà`öž$u\yÈíßTD“*Øú7Õi nÎíÛ1¦{‰3[Ýüë²kT9L›zbôa7—ºÛˆ³½Í L:4SÈÉÉÍlÈýùó‡:ìKU@4I_¿~9% dvþü-Švûà^¿‡¹æ}-æÚ>\jÿµÛšBt9lúq™>eŽ%—v}þüá0òÙ¡#«TD“°bŬ .N‹_¿~q’—þ£zWY¹ûYðž+ë `úÿÁÍÁnÆ”ćª†‰ó çÃÂ6³`7— xÚuŒŒß¾}þzóæåó QUèØ?Õ@;L*¥XÐÔŸ&´3¸ÎP:à/´Ø-ïºÇ™¢|Ü)ΈV €ÚjÏB›£G„‘@C…°9€ÿÔNÄHë¹£`p€í£p@£ `„€g \fÑRIEND®B`‚ltsp-cluster-control-2.0.3/Admin/images/top-degrade.png0000664000175000017500000000076612026403127023245 0ustar stgraberstgraber‰PNG  IHDR;Þ¡Ì pHYs  šœ¨IDATbþîç©ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ•ßîiÚIEND®B`‚ltsp-cluster-control-2.0.3/Admin/images/logout.gif0000664000175000017500000000163712026403127022342 0ustar stgraberstgraberGIF89a ÷ëttÿxxáccö´´ÿÉÉñ__ü••þ¦¦“mmþjjy''×UUæjjÞ^^˜ŒŒj88…//zFFØVVèooYýýýýeeØ;;þØØ_??íww‹\\ÔSSgBBÿÿÿÿÿÿ, „=Œà  *Ü€"BXˆAƒ&L``b‡Š3nd …0zÐxÁƒ€’Pjœà¡e€— b`ÀÓæË Nî`ÓCƒ£AQ¾ôà¨Q ' ,˜JuA=dÐp•ƒW¯ (Üj¡€ÙÄVPø‚‚·(xX;ltsp-cluster-control-2.0.3/Admin/images/logs_module.png0000664000175000017500000005301112026403127023352 0ustar stgraberstgraber‰PNG  IHDR€€Ã>aËgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<U›IDATxÚbüÿÿ?Ã(¹ €GýŒ˜\@L#8♪Úw(e—-²Y ˜*7b2@ØÐÐwÀ‘‡WðŽ”¬úàèQ +RB`)‰ €˜FjîgeeïsùU4̓€LN fG+ †= ¦‘ùMý‡™ô`‚Ü<™ j$&€ba €©²m›1'ïb‡ƒ…áÏß LLÌ¢<|‡o^9úÚü Äÿ xX7ˆi¤å~`nï…E~FŒ!˜ ›$ Å-Ø ™cØ·ˆi$E~cÿ¡`n· 8XÈ1pr02¨+ ƒðò ;(ªƒH ÂaŸhÄ$€’†uJ,,l5 Ž„(ƒ¡ŽXÂÂH LÌ<nñ.H%ÀˆhÓHÉýB’s@-~€¿»*\RˆŸœ @@NQ7 ùlÐR`ØWÄ<"¿±ï`" k.¸è·”cPSäGQÄÁÎÊpãî[` !ì»wûìK ðo þƒÔ –A€bB ,F¨2Ê#cŒi…3…XXÙ{`E¿¥‘†" xcÐÐÌ3©`î¥@1!G¾F×='µ¦KÆÐâ•ah‚3°XŸ +úÝ•p*„5ùÅmªäÆà°OZ}Oç3±qíaá;¥Ör% ©1Ä:Ø­uÝ{;_€¹‘4ƒ”(N ÈÁ„¬ þPÿ#'€a™QÄ31ÇÁYxD¦É¥/3e@ŒŒÁ_"T‰Xô ³spwƒs5?ƒ£¥4^õÈAi9 /´j`Øv ˆ Nÿÿw Y‚[Ýn¿Q $öáQôvó j7€Ý'#¯U,úåAîjD9V póê[úÊ„Þ@Á«€?¿,C E&‰vЄ ([pAHØ kWªûÔÊ b·L:¾¾¼e³1Z›a ¨èw¶ès h¤ëï½^·Cÿÿýy‚®èñ?N†_@·ëU)y%½¤_¿¾ß‰‹Š+T=yxýL°¨lMpt1ZïãéàÀåáDýnªdfik ˜ZùÛdÄ3˜ÆÌáØ/ʶ¯ˆ+t_#§Ï ,‰j@º™ÄŒžB-¢Ù™9ùýJñ1þabüÅÀÆÎ©,öÿ03³ð@ëJÓo_>œgçà»"ârF/žÝÝýæÕ£Ÿ ¨sêÿiùÀ¢¿è¦P€‹ƒ¬7ÙJˆq19ýš¨e˜OZsŒ2,Œ>4Œ/gƒ1§÷"ev“ü:&Ù9ÿ™}Ým;FVžÐÿ/ý÷æÒo$kd¨ €«p)ðîଥØÞû‡PVVv d67¯ !Œ¬ ÔÂËk¡¥'íçÖÁ3}Ì,¬9°¢6ÓGIŠÒ×ÇÖDïé€0KCÏþä–IÇöµM9ù«¾g#¨âò[îÊyp-“€ò  ¶œÿÿ @ÆÿÿŒü, îH½+äqº€ÂHoÌ|ó÷ûÇÕè _þggø v'*Õ— ¬èEŸ€¨ojÁŒHhà a£c¦’¢èˆãj ‚BlZ»hËÄCEíSßaçäšZgò?°m-—|䊤„ÂæÿL¬Þ P…ï½G>”É%‘‚ÔÅfC*5蚈 ­o½¾·kcð/<Òa@R”Îÿñ󃆒8!Û %>!E†4l -ò`² €fú@‹<Èèûc@c0‰K*ÛC2GPd©Jû”ƒ³uœo«Ã..v9{ 9†‚dS}mq`‚a’Í0d•IÖcb`gþ|3} †¬8#H• cb×`ÑÍ@o/ѽA@ÌØ2Ž/}*âV ìÞñ!K~üÏÊ Ãô‰AƒAD˜‹áç _¾þfˆ Ôf8{éXÍŸÿ¼]T.]{Í&&¡dðüÉíÝo_?þVwR£¾c ÷ K¯æ~Ð0®¯‹"e) -èY˜˜î<|ÏÀÎÁ-§¢¦÷:8²8CEݤ…™™U‡ŸƒÃÕV‘ÁËY‘AV’‡•…‘AB”—áÄùgˆÀF§º¾Cr˜6°Zb`ex÷áÃÓç_ AÀ)ÆùïÎꃰŒÇ0SÏ„Þò„•þ||9]ño`½ûŸ—áÅë/ îöŠàœÊõ/_eð°‡Ì´=xüA—œ CÕÀ¨Êj´0fúy“ûÿƒýï_ôjÑ–PÕ²¬âáp”•æcòÔdH‰ÐeÐP@ñ¨ôU0`.ÉÄ`+ËGØa¢'fŸ‘CÈŽQDOt ЈWàö>†cLÐDž“áÙÇ?àD ÌôØ%dfp°’g¸xõ%Ã_\meÞ¼ÿÁðæÝw†ÿÀ¬dg&ÅðäÅW ³š’šÉ›s'¶\§R¯6Ó¬oÁK¼@3}Z*€ÿùó7ûwŸž ƒ•2Ã…W àçw_Ü ‘~çÁ{pÊÖÑb¸|ë-°ˆûÌ`i$É £.ÌpæÒKn^.nþS·®%ü'§è•Ý *úAõt »ÛבùˆáÆàˆ½víÃË—ï>~üNàÊÉÎÀÅÅÁÀÁÁÊÀÎÎ ìÁ°sý?†?~3|ýú˜>†W¯ÞÙ_>þÆ $Èôßpî•—ácägG-ƒŠËÿ@ Œ|`5 *Äö3h¹98a%þ|ùÊðçãGvYIh1ËÌpóÎH¢aüw{Ù¤ð‡ž €˜ñ©óé{cå— ×ÿßÿ2$Û2Üyõ›áÛ÷ß Âÿ¾1ˆq3HKò2\½ùœë•dùÀJÒ’| BÀÀ’—¤f{\:DVN¶ºÍ@ZíLEn]¿ËpéÒ`nÈðöíG`NdbäcPT”`ÐÐP`ÐÖVdÐÒR²å”•¥¤””¤”@lyI9yq11!`åü?þ#ÿ+8ýüþƒõ?°HüÏðùû?Ma”ˆE"¤÷l/°ÿþó8 ` bâàf`âæ`áaØwä¨5Ú£$ôÖ±ÿo/ È24€Â—0ƒ¿ÿ0Ãö›¿”ÿý ¢9׋rƒBÿþ–/7¤(}òâ›°¢ª‘ÄÑ}Ë÷#u;Iõ$Sm×ng`뻇éß1¾_ O<á \...ŽdMS3-`äJ1ðòr00þV]?0üüñá0—ýòáû·ï ~Óâ¿?àÒ˜˜¥ÅÁ‰FZZŒQ¬¬Ìà’áïïŸ <œÿú2°³²ÍäAsö?h3‚K~>Nx£¥š62XÄ…Õ¸1øìÅgH/Sœãÿýu ‘ÿ›ž ­VÓš0D¨!AŒ"âYÁ›Ãÿ*ôohÒÚ¦~$®š˜ÔÄH°o×Rì©—º0,ìîawfÞÌ›a3õ®o;ƒ›0E¯ó“€íx¸¡ ýò D½Œ¦‘WiÁ~Ûª=ÉŽ%Kþ> ÿ÷•ËFí1›zE üP l6«èv[”6DtDÔ.>xq0² žç Ë+X¶‹élË» Îãé“Wó%ÃþZ Øïp |dhd³j ^7P* iâèDžáù$§„k2hßè¿ü̹œ$}¬f>ÂcòÛâ˜@Hè:SÅpu}yV¯@<õ¹Ÿ7Þ¹ƒªÆ—b&TÜ"7sµ°X·Taaøü“™áÏ›÷à¢ßTOÒýêåzPý ª88XÀ‘¶Àn ÉZÄúï³ùßï‘ðƒAJJ”ÁÖVŸÁÜ\‡›‡“áÁý' çNœc¸táÃé+o½–>â <² ÂrŠ â Š 2Êr ’ò² ¢2² BR2 ÜÂR l<‚ ßÿs0Üyúá°nþüö5F  0?ƒ0! ñúø ?|†6‚ÆËˉÖdd`ff„¯4Æ(€áÅ ¬žøÙÎ\xl ‚2=#‡ðÓÿO÷^§wc €Ío£4A¹ T ¸hq2(Êr1<æò÷¾3XI äz1avpd¿~ÿ˜8Äá1HA{€©±ei Ãï´ß?>s ƒ¡¡ƒ‹‹0‡ò[öwŽ>Ëp Øxô…‡CJAÍP‡AFEžABF„Ah¯¬ °ˆgöÕÙÁîbgÒ2¢ 1 n^~^aqQi)†Oyn>ýÁðé 0!K™ïÀF¢°° ¸DUãg†oß¾{ ||< ]ÆàÒÔ[•"hAx–N,Ò’P°1xû5t ]@òÿÝto 3.pc…O"ä”ßþ0˜*ð2p]øû?Ã3`‘ jðIˆr£äzPCè.´1k9“Ù`lh˜UÊÌÄT÷ëÇw&''`wLW…áÑ£ç ÷Ÿ&€ ßÙ%„Õ”õÔdEd¤9d$YD™ø¸¸Nàö´Ù4`úa`úèTn °íÇ ÄÇÄ T+ÈÏ,¥¸‰A˜á7»(ÃÃ7ÿ>¾|ÁðX"€"XVN‚ABBÜPõ@EPûCPœ JLàA ÷»èAFn`“ Ø#áe8xä>¤Ài 2¼»Hׯ @“ AWPc‘ïÿ?HU`ªìRqs3<¸iðJä\ƒ5a€Äöc]ÝìF&¦Ê¿þ°+)É0¸ºZ0ðëå£GÎ3œ:~‰á#0· kZ0È#^I™ŸAJ‚™Œ lÌPÇÿ‡4¶AÝ8`œAØÀ`:‹á·æ¡£w<ÀÄÍÏËÄÀ/ÈÆÀ+ Àð‰Q˜áåû_ _^?cøl÷òŠ"àÃë×¾»y¿~?8üZ*„m"lA#˜D„˜ ð=°1øüù'P+42ÈÁð`=]ƒDTO¸˜G±3±ƒ jàóm`Ÿš‘áÝ˯ AÆ@ –ëAÅ,(¢AC3i”¡-"Û µµ3Ë€ÌÂ?¿ÿòª©)0¸»[‹ãŸ {vf¸}ç“”ƒ´¾1ƒ<Ð}v 3ð«& …lÀˆ³1¬E¥þƒƒìì g/@ƒÌœÀ`Ãú5ˆ˜5nÐùnÆûÜêàÆàO`–‘dgPa×c/½ý°Æ ,×ÃFÅx¸Ø½. µ*+§¦‹ÒÒ¿ÿ‰©«Ë3ØÙ1¼~õ–aßî£ /ÞýbвgSUfPVá`€¨ºe„ZÀˆÙàÒù?æÄ;¼þF:¸„`@” Â¬"€ á?+°÷óŠá;h`çóKp/@FV˜8ÁƒG_¿~&¦ÀDÀ2P—¤4Ÿ€€¥#°;) dzç^{¿A D6vá§ Ï÷Ñ­1@Ä.rdúþðì/A›evmP–yõé/ƒ›Ÿ0Ãýk/ÞBƒ°\*@]BPNþæ+¼1øÚ99í–ììœõÀ–²¢¢$¸Øðþ‡>ÿå`ÖufVªÊ, œlÀP‚æ&¤³ FÿG깃s?¼èùŽ|¤ÄÀ«"þALd¶×Ù.?böB€…ö—À„ÏÆ %- lùCªƒŸ?íe' v`Cyq J)R')Hbf¸uç´KÈ/Éð`%݃Dl7yt¼¾±ð‹‡ƒ\òáë3e>pcðç÷ /Ÿ@Š~Q!.p®àãçzXcPYQéÈÔ‘þ±ÂÛæænÊÊ:ÕÀœo+**Èàèhìrýb8°ç(ç?œ Â: ¢ÀD¡(ÉÐÿЕLІùŒˆœÿyv…¹ÿ01¬øk;€Úg@Á3d@BLˆ‰á°¨¹ûØ'ù ìÒ}&N`ƒSF ØøLï ÄßÀªƒ›› ܦ€Í' €¿Àxåâcø¬BDEøº‹22Èðþ]ƒDJ`üxjÙSA§¼h`Ðóœòت2Sæ`àÖ{ Æ ¨È·2–@ÉõðQ1 zUE ƒ5”E.\{oh¨¨±²²‡²=°ØçãçûGÞ|üÃÀ¯ë (#Œ| qÿ ‘ÊéÐù3FdŒžõ1ÛaHãxÿ! ¹@ÂÄÁ¦m=`»€‰áÛ¯ 7žK ¦¿ ?½6LùÁ#‘_¾|cx÷2ÂꂪFn`74i†ÕÂÀÆ hdðÝO†/>AÁì›>ÞH—Æ @»>Mü÷ã‹9°ÜsêÎW†¯?W^FaI†‹Àª$Zññã†g¯À·\ÁäÐh 4• Zyc`ìÜÃÎÎíÿû÷_NЮ””°¥‘áé³÷ \*6 <ÀV>xâå÷_¤\ M È9¡ Òû´(ÿ Ãÿ Åþ?$>´‡ð÷?‚ ç‡ùÿƒvé™X”eYõ?;Ã?’ÀÆ!Ã[À½559`¤³#ô#°uÿcq xÿ–áÿoHèÊ"¢—]Ô†A@[˜òÕÈ@‘²ÑÞäR³Ï…È/PcPˆƒAA”Þ5ø@»qs=lT ½1 qÐ`˃Ûwù¿}ù, !!Ì`ccÈðøñ †óg®0°É™0ð)h1È˱0°²@"¹ŽgÀ–ëÑê}XõK¼ð^t¹1ø9÷CKFH ðÒ®cø¬ö„ Ç/€áÀÄÏÀñë%¸Œ‘Ï0¾zõl:°OÉ l¨À—`Vv†ÀªB@€áÜ…gÀêñ”„¼ °ßtè ô\Ûr*êq)¡ ?¾¼wŸ´µ•Á#jÏ_gøÃ leËj3‰‘Tí µÚÿa×(¹ŸQßÃôÀBRü‡ä~äÒV µ À A  Ü^ fúç×ÐN"f†ÿìÜ ¾‹3¼|öŒáÝû/ à9Ðháóçï0— $ЗÏàli®ñði„2Ðá´€"e-:bÍàКAHHßù“á°ÏÂJÂð¢¶ÃæÂ•7ð-W •Dï>þÆ04ˆšÎýþí(÷ƒ†\¯]¿Çðâå;^Ecn>`2 Žô¿ÐâVtÿEçpqÔˆE.âAòþ#ÄôȇÉýÿO 1‚HÕ;øˆ9`uÍÆÄÀÁý—á;»8ëÏL O<UËɉ¦ïÞ}`øüù'8 4 SÉ(à'°÷ûù˜©o$ƒX]Ḁ̂ ­Mëj €HM ðøódšßÁÿÿ<ùmIm> )´`‘þžëA%ÀĉsÏ0 -¸wïx²EQQ<Ñrûú]†œò ¬ÂÒÀ¾2¤Åÿ)¢Q"ºœ Œa¬ŽѰH5Ò`|X‰€<ð-qü7zÿÃGÁ‘ÏÎ.‘x¹þ3ð °1Üû.¬Ö?0¼&\Pû´ø4\üâ¤Ð×à o^BÚ~Àf‚Ž¡¢w¤ùi%DênÌ5ƒ@‘“·?3|&b>!V †ý Ð\*@¹V-ܶÐ+1ÐJP"-âuýøÜ>@˜ýX5ÁÇ@C,`7ý¦°o¿>ë·/_ÀÝ@F` ù L• õƒß¿C€¥¡Ö€e}ó Þ4Cn ò¨Ñ¤1€•+ÆA ‚Qcqµ‰ÑÖÒÿøµû•06Zhrõ8¹Ãpá´Õ‚‚†„,̳;üò+EB{ØV¢ îNÚ#\®"ô?Ÿn½A!úÙOÇàSj­U-r©OTøù¬ Â?oß™¶3Ào}q Ögs† C!5üaÐ}< ýg€YÙ#ª˜¸‡‰ÃÜér~û‹œJÜÊÜççç„b!#­êëSQÒw€}JÚ<öÅ21Ûňß>”@5É Ö\ Í ƒ‹ÍßÉàKVÍa†ÂVªª bcà\€Ãp9Fn˜ºq†RHU¹CC~xN*Jc#e¨¢¨’ýì|±3‡\u<”Áš« åt©'0x.o“¨ÿ!q¬0€<§’Vª¡RYêéãëÕ"–Ts¤× wi,Q®`TÒtˆ¶Ö¸ØÀW´ÑØâï '÷l`| _x°¢ –ž–ÇéW7 ²¹ZÖ±b¨>2%å‘Å¢RÈs.lC>} ç¸gÛ#ׇÝIšý_ÉàGQ#€«¯çVn …¾îø H‹WFU ÞàÓ€®>ÝCƒËÿ ‘ÿ2ùúº¨¼ÛÑŠÒ¼ðöê3R„1‚åA‰LƒK `耖~õ²1ó0ŸœX ÓÈàˆfêg°A%8hÌÌ™ÅÙæÖj@#íûG`Îþô—á׈œÔøM³‚ô‚ê}H‚fw•þBý‰HØ_¿þÆÝ3l?€ANA€…Ÿ švy$ƒ©Ú j%€¿ŸOÎyû÷×ç1`cð8´1­@E?,×ÃVÇ€FÅ %À°XؘÁsé >x ¹ = „_½ù E8¨z€ç^f$ÎL&¨¨ aef@Å,ÿálfäDJLûAzAË·Y€ TÚ0þ6怑÷X̃ÂÏ_¨‰AXˆ‹´ÿ€Òc€ùßÀ‰äIÈ¢`ñÛo¼Õ´)7±VGLsQ·1@Ô8š ^ üzzq&,‘ß}ñáÞó¿àÕBârÂð¢ßP Q"€B°A’¿À€evý˜ý¹¿¿CŠvfFp„²³Nßàç¬ÿÀ|÷þ;h{<Ò˜aåƒs2( 9’ã!434¡À03TŽ•ÉHr¬, ˆRVÒ€Ü u`Kîßß ?¿€ÜþÞÛàe&€ÿ \¬€‰¼ž4JÔ †.|I PhdùjdÀöíÓïÿ¨Õ8Wpª0H„Q­1@ÔLß®N=ÿÿïÏk°Ã6œx ¯àA-q”Æ hk×``~ûþìÐZü?¾‚ò J/#Á/Þü)¢¡¥ #J)@x$‚Øÿ!ÍK ÿ‘Ì„ˆpäÅ hbc‚é¹ X‚üÿËð˜@CŠ¿BYB|, ¼„w´•‹AAnê4ˆš Ò¼¸ <2ø<2ø˜>ÃKÐÚ€{?û€®½Ï™ÿ6£A;kXYÙÀ£fŸ_<Ö§¿Áõ7´ž5Æ@¥ 4B^½ùm2ÂÅ ÕR1ÏÁ¬H%,ra¥¬ègE®&˜f0C«DB€&8h£äp—4Ä Žÿ_€ OPàv9?·«ƒÎí@:1ÞD>¤½1Èñå38pe¹#ƒ¢Ti µÀ߯§ç½ýûóËNXyµþØ+”ÆàE¤Æày t¸øôÜêçäädøöú °;÷ ’Ãàh†$<ƒ†àÔÜ΄ˆlf,U R$³"%HO’ ˜™þ£¶`‰ùÐ*TRýú I° ?–Ÿï€‘Ížá|óæ#x_h° 4å¼>þ…¿øø ÀÆÖšˆ‘AnUª4ˆšçÓÂKßÏ.B¦‰A#ƒÏ€ÁgàAÐrPѯ]-ÄÈÊn|ûö“áË×o |ÂB ì ?¾½} lTÚLðÖ>¨1(íü¶>ëPVh}΄RTCZî°ÒµÈÿoô±1#Ú C&– @ V "Âÿl €ˆùûƒëÏ{1pÿÿíÛÏà6h£< JPï4´«1È ªA4hªØ*WF`cP,„âÆ @Ñ"ü}¿>ýü¿?¿®Á$Ö…¤bP€ý°±ðwŸý|EIðdÉ;``ññó3°cæÕÝë ~þ„÷˜˜ }r .x•ð\ "\\3"'hNff€À jÞXþ#ÌbBMLHUCÜÇ ]Äðý;ãOQ!`µö X| è|DäÿC9˜’Pcû3dÍ hšXÆX±fŸòÆ @Qû„jxcðßç³Á½`’8võÃ×ï vdµ¨è‡…?xúAVV œKÀ3ƒ@=¢ Ÿßføê 32‚‡Wa¹M\”¼tœ(ðîÃ7ðà+¤ffDª»‘ÆzC¹¾‡U ÌH –ØÀÝR&D5K”`š‘\¥ýöëþ½Ä $,À *&>ª´Œ ss…°п *ÖÄš>½‚WÚ&ʈâƒEȆK¢Æ @Ñ"€«ï—Woþÿ6Mü‡áèµOÐYBqxc6ÂÊÉÇ:øáãGÐ6ë/ ’Àv+Ó_†'7.K_ÀÜÊŽ`&hÝ+-Î Î,Ðùfh}ÚXû’³a|ä®+ ƒ‹,ÿÕru‚Ôd‚•(Œˆ€‹‹…á?h4ì ç¯w òŠÒà]B •ΠQ@Ey p=÷# ‚¦‰‘©F™!üýƒó3´1­ ,I@ÓÄÿ¡k…ý)j ­À߯g¼ýÿ ÒytÝaÈèŸ"tÑ(¨1 ù‘ |ÐhfðÅ‹· \œì b’b ϯžaxÿò ¸q® !¹M44 Íá jÒd‚G>Fn‹mXŽfd@ª2þ£ôà9Ù,˜ùP»™ òÜ< ©ì? ?ž\gàãfPT’axøð9°ønù‹ˆá4`¨}úôeÅ:àù‚ØTcj Â& 8)k -.)@4_\šùÚj½,êï>ýßGj Âö~6 UÔ”À[­A‹'AŦ””809ÿf¸sò÷¯?À?Lб|PcPH€¹¿€ÁÏÀÀceED¼h‡cDdƒw3"0X ºÚ̇åvxÛá?jÂBªZ@4xx÷Ç›g Lßß0¨k)O¹ví>xI¨› Ú†+÷Ãø ÑBÐÈ ®}„Ü_ß20C‡–uÌTÛ™™€Aá`²ƒDËð÷æ¬óÿÿþºöêÓu‡_@§‰¡ãWÞÀƒÿYtt”ÀöàÁs`ƒ‡AZF’áå« ¯]`øû22‹)Ð414¾|û)‡BV Á‚L¨‡û#ç~ðL f&r]ÏŒƒìí%¼/Ÿ¾2|¾w‘AJZœAU]¼ÏáéÓ×àÝÁ"Ð!à‚ Ô%ü_1… ð~†Ì¯°sýn @W´ðZ“Ý Z]S‚üür6¬ïzäÊ;`{Ñí5AÝŸ[>1Ø;7‡€ƒxñâ ƒ¬œ$ƒ Ã¥Ý[žÞßûÏî p€GÝ@ì÷¿CNçÆdQÔ3þ‡$X‘Î>¨é6ÈÿˆÐ%øÅ‡Lˆžr•‚()øxXÀGɽ¹z’ƒñƒ…•ÃW Ïž½^ß //Å **Œ1øƒžûƒB°jû>B¾OˆåôÚfªˆ‘APcC¬Æ @Ñ2€«W×€GA3ýŸ¿ýe8zù#tÿæ>BvnqCCup‘ ªCA¥Ššóÿß §¶¬gxýâ5#3""$Äxà :®<ôË„zF¼¸‡ånXÈü‡D>(A@î{ùq&#ZuÁˆDóëýÀRéõ­+ >b4±õïß”A|¹1ML 1øRJÈ¦Ö…Ö ù‘Õ ZßƒÇøçÅÅßìºÑZŒÌìàsAçûøY‹0pòp3<º ÙBn =TâÅÛo žNj ·ïl!ùh€¢åMUðRàÏËË3a‚wž~63ð ²2ðbÙGÈÁ+ÌàåiÁÀÉÍ Dyðàƒ¸¸ƒ²š"óWoÜÈðêÅpwŒ›‹™—› œ~¨» «Á‹¸#é:¯ÿ°¢– þ£È#_ÿň–óÁKÀºÿñ•k ÏŸb‘g°°ÔÖù¯Ž¿ ÎõFFª ¶¶ºà-â/_¾,ILî/‘ûYrŽk!ß§—ðÆ ®¹*ÂFvÁ@’ƒDóäˆ_··½á0Hð–ߢ œÚXa­ËŒ8V†W!GèhˆÂ•pwÖbxðèÓ'/Àã \"l°þÁµ› Oï=b––aÁÂÄðØ€õÉÅ„9ÀƒCLÈE8¢¨G®óÿ£Ç;:æ?ü9pNƒ;ÇÙHrãÔ†GÏÝ$Åàîa Þ¼wïi†¾0èé©2XZêÄ`â}aÐÀ¡Ül £e@ËÊ<ùˆ!û—™áø¼„çï¾3|yü¶dŒƒáãî $-@´¾«12øååìÿÐVëá‹oÁ«oEå AÐÚô}„ù¹~ BbRà:Ô&••`ÐÐVaxÿâ Ãú™ó.œ¼ L<¬@3˜À6Pu&xêcDÊh°[µûR 0¢…#tt´°ãÓÇo §·ícx|ùƒŽ®*ƒ§·5xYûÎÇÁõ>¨Ø71Ñb¸}û ¸4€F9AëÐ#_É ë àÚGˆ<&/ÀÙ™ôÆ @Ñã.\HIÊÌöŒEÒ4ÔÖm°”ãbP“ãv¡~1¼xòžA[]ŒAXä]¹ù|긘0'Ã?fAðpêoƒA‘:—OPX€áý›w ×NŸgøôá+ƒ˜¤$+3¸ÕÎ Ì9ü|l €YÞxƒUÿa·3þÇœ˜a@;UZäÿ†Ð÷Ü|Àpf÷!†?@·€Š|3 m†çÏÞ0ìÛw\UÉÝeõ`Ξ½ž)%%†5_ü'pÐ hä““ ~ 2`ùû Øcø l'ð s1œ?yèHÈ $ ÌO¾'úh€¢×eÈŒ^ƒÚ‘ZÀ Tä”—ï~0øX‰2°ƒOo½w Æ èL½Ÿ~2j‹2ðñs1Ü{þ|–ï×/ŸÀ 7µ ää$À{ o]¾ÎpïÚu`ÃŒ‡ŸXDÿg•6ÿ!bB/ r!êA‘ÿáç þgmóúÍðèÞK†£Û0ܹp™AJRˆÁÕÝŠAQIšáÒÅ[ ž'LÐúúªàRàÂ…Û ràA C¬A+œÅÄ„QÛ¿@ñ‡k }MNI¬Y5a'¯cKD°Æà_ÐùLסAfPcp+ÑA€¢[Å‹„ñ &^Ù8Ð Ñ[`ηÖceex,öAûç-Œ$ÁgêÝ})ĄخÜyÏÀÊ)À §! >i4aôáÃg`s2ÈÉK0‹1|ýô‘áÞÕ OïÞcøõóÐ"`î/%gô€ëýÿˆ"ž‘¹ `€_øÚ…ôóÏ_†·ï?3ܾñ˜áÈ®“ ×Ï\*mb®Ë`i¥V{øðE†‹Àªž@GÖƒN2Íû_¾|—AIIŠÁÚZXÈ€¸‚µ@[¾‚ mo Ÿî20]ëeøw{Ó`Bà&9Œ™ ºÁDX€|!h‹9j—ð'Ãg`\ƒæ D$„.íºõ ôœÁ7ˆ:g €èš~ßÝþ†C7Î÷?³(ø”1`cÐROì PcTô+Û Uà«Õ@¥¨xíö;aq)#]qpƒ ”Ó@ 4ØÚ|)Ì|| ¿¾}gxpã6Ãùcn\y>¨á°øþ ZÉ Lt ­ßLÐ1^Pœÿæ²oÀ®Ú;`.~öü-øÊ™ãG/0œ:p–áÎÕ» œìL új Ö6† âÀ@¾¬Û>>дÑ4º Tìƒ.¡’‘e05Õ×ù ÈuýΜ¹ÎpýÚ]†o¾1||ý÷É|ŽW;Xí–ÿ߀ÞÏ·y•€]œAP¦@¿‚´wá7+7ÃOvHcð-°1øô-ÉA€¢g'VŸÿŒl¼ —¼|ûƒÁÛZŠA@„‹áÙí— ÷€9tû¬mä4Ó׃ ÓF54Ì•À}kP"ݺ#´¨BTTØ>Û *~?¿ÿÀpûê†kn0\9“á°^>{ú*à û<Ÿ:u•áäñKà~û¹Ó×.V%7ï3ü& q`D¨ƒ¬yòä%ÃÉ“WÀãû [Å8¹y>ÍÿÁX .@ Z@k@Å=¨î¿té.ÃêÕ{Á3œ:º Ú* bÏf1p=ßÌ L°bš¼àůß_¿–7ù9.)´.!è.vŒûmŸ ŸøDÁl.`uyâ4´9$€%À&†?o : €·«Y! Œ¢GL¤CH25X(Fj°±Pvòn^ÃÆ#x%Êb–"Š…ÕÄ=w󲜚ÙÌ=s¾sæþý D Æ+ÃP ŠP«YiØu‰”‰‹ÕYëEKGÈÒpü¬7(c/4x’kodc:îˆÇÎê"Ú­¥ZVÞ0hM¡â–Ð0sóL2Ñr?—@± ™ifÒ[»­R¶]…ëvõ‹'˜xDÐÆ Ç£¯#ߘØÉæ-FT‹÷ë®vœ¦<ßP meøv»ÓjçåjŽ~;‡ÔiÏyƒBo‚Úld1 Óx"àþ¢Û ñ×1²@¦G¬#uËÜù^¸¨ó×bð+€è™À‰àï«K¿Ù4#´€nԹ䨰gàà`ø*ê¾/¥²6•7~nÞ}ìI€—½ò‚áÖ½w 6f² ª*2àH%P :dêóç/Àâø=x!æ·o?À[·@]1QQEI`‚ePV–w×TUåÁ§z‚ŠpÐ’4P«Ô u7oÝzŒÌ»à˨@›:@E=è"*y%%†Go˜ÁëýÍŒ””DÁ Rss= 9Òà­>c8uò*ØMÞ~Î ¬ ¯ö72¼<¹ADß…A9´ŽEL4tÉÀÄþŸƒó $¼} LÀ’ØàUaV‡ Ã#á‘v!¼­ÀÄÌð‹ìÆ @Ñ=€ªfq£Œ¼2q øØäæZun>`D}xñØ~Í`¢' Þ ê>|ú \ ð‹ö[÷ß1<}ñ…AØÝͶ®ƒÓV  ëà@›LÞ¾û>htï¨×:ÁûåË·à‘º'_iÐ<=¨Ø¾sç)0ž2Ü¿ÿ ˆŸ‚s<¨Dé-è•7è 5¶z ìyücË6&2à³ed$ÀjÁ³œÀêT\¼|“AÏPAE†‹áÕÁ6†÷V1Hj3h‡å3°¨3€ïŒ-Z MƒöÁŸÏ Dð–ýçm~iaÄ5¸ ùÐô9èÀiÐè rƒí×w†‚ž9A€ðçþÎ×lZÑö Œ, cŸÎ\}Ç «" ,ŠYx„Þ<~Îéžò _¿AÚ mV†âÀ:h5Ñpdƒ–‰ƒFx89PÜ6?|ýld±1psqKVèÅßÁwü€Y@9„A¹Ô­åVv`c tJ‰„¨U¯ÀàåeŒ|=ð5t ñíûï1¼~û´ëÏX:qs² èAæúK»ß0¨Éó1°ÞžËðñÊziUU=ï`6!P}ý˜îf†ÌW°ÀVSŸÁ‰à+°MðïýMV!†Û¯ø¶ì¹Çpôôcp䃖Ðy8(1¼|õ~ ¨1ø—…üÆ @ D€ŒÐrKžfT gøÏȪo_zÃàe#ÃÀÅËÌÀÊÎÉðØÿ5þ|\î<ü¬ÿ߃/©43”`¸~û-Ãm`I $/ì% 6T€Zßò •Ç~0ˆJH‚qX 0gJs³$ø^@Ðh"K‚¥UêêJ ººjÀb^‡AGGØ’×6æøá9=ûÊpìÌȹJÀö‚¼ zA gÚ OÜbx¿‘áÉniE #' N>>Ès µ mɬ@> 0A°²ƒ„‰ Xð@ªP"xq÷Ãé;¬ /¾ gÜÕTÎ\|Î(ùÿÿ2|æ&«1@ôNˆ¶ÀÓ#Ÿ™E®2rK„ÂfÁÎ\æz .P1Ìùï¿fàåfg07Fúpñ¯§)Á ®$î*Þ~ðŽÁD_cœóÝûŸ 94ú¯  Æ «-Ç (l(H#]Š¥Ácù Dº5T€h=?+Šy+7_cøûØ/çfe°2’Ï9 æ~ÄÈÞ·''¾\YÅÀýùƒœ ƒ©™ P;Pÿ k`—@‡$á%+¤:`m'ûÊðXR1||Ç ÇûœÁÍËš]X™áà‰Ç {<— !se`b€ÝAÀúçÃ^)†ÌŒ$7h |¢íÏýíÏX½ØY¹ÍAøØÖa¤%ÀÀ l¼ü–á°¸í$åf¸¬?ûÄ`fl4t3És`q¨‰vìhôìÎý·à¡\ЙÚj"àñ€ÿ0‡€Qr0b%$PWï;û l'È,Yp‚DÕ‹ÈýŸžßfx|x6°{šA^ôƒ‰Ö?^.ȉ  ‰ú Å¼ÐDm°‚ö|eø ìIü~ÿX^d8z‹ƒáé'>pIº•]ƒá 0C€Úà3‹ÿWO“Ó *CÄ·VfV ÑgdfWÓsãþG1!%9.`wìÕçÀHþÂàd- nÜ{ô¼„ÜLØøðƒáÁã ¬Àöh‰ ðó²ÛïÁ¥ èžcU%Q6`kzßñÂÂ<àõ|0ðØCÙ{ø>x”PXýh( c™G@äþ;GW1\?°”ƒõ/ƒ¹â7)¾_ÀŒø9ÿPî®`Dž/Oâ…T su@…¨MÀj|eø÷éƒ<ÏS[k†ÿÄî €Ì1Ö—ßà~˜1˜¾%«1@V  j}s”QÂÜØ(…À¥[ïÁÛÈEE%+;˯¾~ÿÃàj+ÇpÿÑGpÑ/-Î,þÅ­ãwà:QAµ=ÊuÏ_Ar.¨øVVŸÚoò¹ÛvÞöÖþå˜ìÍä€E?Fõaeøòö ÃÇ—þ–"œ¸XþÙ?Àõ>xc9ãèz¤ê ÌÀD_UŒÐ6׆À6Á¯÷o€¥á†/yþóÈÇJ Úê" /€¥ßÎ÷ '’ÏG~Èì!žÆ r¯* ,ùàãÝŸŒ<²×˜ø}ÁÃZ!{öú[Gs>1.†ŸŸ~0<~ðØêçeÐÕw‰@‰@W]Ü0ºtý%0¼c0Ö•€.$ÀÍpéÚ ð|Ë—¯?mqðB Ð$ 6 %Å‹Â?å5ÃÝGïÁIÕB_ Xªp`Iý²ÎODZžAQǘáÍ“û ·n?_+#ÎLÌýД¸ºŠ ù xu i‚NRœÀDðûËWÆÏ”ùŸ3(¨i3œ{È ì<·¾s»Î‚r ¯ÄäQ\ºÇé饈Æà‡MK  ¥ ®à á߳l?1² º€@ÅýÓ߬E¸E¾<Ëp÷þS`d p‹½'Ï?1˜èAÚw|`x ue!èÀ °1øñ'°»÷|•?ƒ¨7|2 º€r9¼.ÿü›açÁÛฑV-šÊ¢h‘èöVüòð€nÝ ÂÂÀ#(Ê ­aÌðöñ-†{wŸ1|ýùŸAœû/3èŒáÐ[NáÓÍHedÖ ”˜… m‚à’€ 4Nðé÷¯¾½¼Ìðè‹(Ãs>=†×¢jÀÈwaàò‰‡ {מfx¸ÿ2R LJï7̇FþOä.!@ †€hNÝßtƒIÁG˜…Ë4?ûä%h °¸ãgàbxÿà9°AöØ’ŸCôðÉð©Æ I¢?Á|РŒ¤7¼X¿ûÒE¼°1:š¹1Úu$$„zôÖýwÀí6 œ¥¡ x߯8í9|”@ƒ*€ƒàÎê#ÌÊ¡6ÿ™X¥AYìÊÍw :ªb ’’Àö ;0g½Gº… °ø \ôKûìFºbÀnâ[p±­ +¨áãac¸zë 8ÂA·t«(Š€#y$MB‚é䆋×_ƒ{ ˜ÑVMIs£ä~Ð^AAN^^VÈÅPÚñ¼ûð#†­{ïiLl¼ †Ö6 Ìß@#ÏÁ%$/°$`µ ~Bãž žl˜þ32 n¼„%DÛºâ@ó a zì9t<ãRkm, Îí éXP﹘øÝýÀ°ýÀ}`cì)ÃëwßÀôþjàN …œvÞÏc0±ó3¨˜1°þ|ÆðèÁ `&ýÇ Kÿ~#›é?$!À{І!øL;h"`†¶ X sÀ†!ïÿ¯ šb/îexòöç>†Ïç0<ïšÁðõô †¿Ÿ>C#tDùW(ý­ ø@ƒ- z/޾a’rüÉÀÆo ja6è@×±›‰…€Â'/€Ý¼oÀD!ÅðX¼?z ¬ÿ¤«)Pzü Ò– ÓD@;x@ BAA`ÔpCÎÉ YÇk·^#_KM”A]E ZÌ3¡8î쥗 vÝa¸vû Ã篿ô½’p_Mð&•KWr;o¨$p´cÐ×cøðƒ“áÎ1†ÿŸÛŸÕ…$¸wðXÚü6øÿ Æ ‘ÇyQÇ @B YD®oàqÞÿŸœ.<”dÜ»êàù §r:,âa‘ÿ©ø‡Ð`,þ`ãEFy_E&MPUðàÉ'`Kž‡AQ‘Øà`xûè%8’-$ ÀO w€]EAU`]ê>{ù‰ANFÜ5A ´:HUQ%òAGÈî=rZôs‹oEÈáOP:û4"¸uÏ`Bûl_°‚ïFõQ'ªC'3>õØ/ÿ , @£uŠ2üÀRë ¼»¦ ,Ï`dcÃðõõ}†Ç_Û’€›õ/8@â16À„¸íšøºˆ DÀÀÀÁùÜ&`úõ_@]’ENSšùÞö‹¿n£E<¶œ›` Áœ çª¾?à jâ$–§/¼d0Ñ—föÛÿû÷î¿õ"àúÿ6°ñš/u AU¨ÿÿàñ;`ƒQžáú×àý_¾þbÐT•@‰àç2¼}ÿ œû½œÕØ¡]Â'Ï¿2<ùˆá0rA爇¥<0ÈK£Ÿàß•¯ÀGÄëiŠ1¸Ù+‚Vï\– ê4|ëá¨ÌÀÉÆÌpêæ†·¥]’§ oÁm‚ÿ ÜȃEˆ6Ê`ø¼Ùÿ¨m‚†!¨a1üÉ ¬$΢h®Âzuý™Ÿ·‘rüO¤Fò008|ˆyPG>|¾÷“‘™ó8ƒ€fÈFFðPÝ1`®r¶Ubà`ø ȇÞ2˜êK‹lN`·ï0Ç}cÐPFþ{ðÊáWo¾1ÈJñ3¼yÿÚ÷BÎ mÄ}c8wé)XÜX_¼½ìÞã ;#÷æK`îvUEì­ € Ëk·^3ì9|˜ØÞƒÇ ̤lÍåÀç:ñhÿG°ù )c{+yð 罇€{ Ä?Ši2¼Wrg`~“áóg _¡vÁ3…ÐuÌŒŒÿ¡I€ mîZ€‡!#† Dðû£¨œ‹f¸Ç•y¿ßBŠø¿è4¨«8x{þ3ƒˆÑ1oPÊÕûþ;+)&>A†oOžƒÛ&zÀþû_p#4èóá . hî´ôëÓ—Ÿà\Ê™ UÇ °mï °6`#tØó¡“îÜ{îöé{žŽj À†àE`•²÷è=`D6ÂXœ¬4UDÁv<þá0ps±1¸Ù*2èhˆ«Ÿ¯ »Ü–"Ÿ¾3±1¼Qbx#¢Èð•›á7·0Ëÿª ¿^6æ ãàÞ8@ªð=Ð6#ÖÞ´‹ÈKÀ’àË7†Ÿ_Ÿ™´2œ¹nNÙýí4âq.  ÁžŽ~ºëƒ¤ ;+Hø 0">ûÇ``ŒHv`{à0ØÁ+‡A³ww¼6ø8ÁýpàóÈBÐUðÀà]sÿØ‚‡O:îõ °5ÏÉÁÆ`b îÆöéí=rXœ¿ï>–‘àcpµWÏL;óØÎx ^ ",]|\T$â§/=v[Ÿ3¼x ¦ågxŒô·¢r ?Ø8ÀK¸A#u[a¸²÷!°û&É ÊöŠáÿ¯àê”Ø™A³–? ƒBLÁà­Fèq±ÿ‰€•¾žÖ;øùQ‚…Q¯Ø‹ûqÿŽo·ð0@ …Ñ$~´á4ƒ\  °( êÝÖ÷2ÒB R* ÿ¹üѽ *J¢à1‚{ÀªïA9 t€3èrjFè9C ß#ôåëÏð¨%Äy,À[ÕŸm{ß·) `‹0ØÛ ía‡N<Cƒ€ºŠ°„PŸ_ jì]¹ñ˜(1|ácx-¦¦ýŒ ÷o1Ùz‘aÿ¼ƒ OÏÞe`øÙéóõ/ÃÓr R¿þýõí°$5 Ù™þ1üýÿÑ&`„nxedD9P"`uY!]DVÐÈïàq‚Ÿ_ÿK•KOØùm¾À ¡Q —?^ïc6ñg`dæ‰^¸úŠAO[ŠA@ØF|÷žáÕË úÀø8ZP˜–„ëÉ0¼|õ 2àÂÈž*ɶz{»j1ÈI €{ûÅ<¨÷* t5%Œô¤ÞK†#À†âÓçÁÅ¿!Ð>[sY`ú°çÈ}p‰:üû=¿4ÃKq5†/Üü €­Ì›ž3ìÛx–áìò# ¼b€©ûõxç×Wë»þ}»¶]^UîëO6IPÖ&øª˜þ¡5 ½p"à†6 m6vðRóÏž2ü½ûÿÏ…‰{~¯Ä°4ôÀ—?¸¤Î3p)ø‚Ffÿ#ò&°Î67“c`døþô)x/¨Uþýçxë^Ø=õé?e°&@@Y^ÜS8{é X­ ƒ™,ƒ¢,°6.O_|®@¥ˆ¥‰ƒ Pým`B9¬^Űr1¼gx!ªÀðƒ‡á0sŸ9t›aó܃ _gøñmw￯÷¾]XÌ𤶓áó“ ¿Ÿ½{þùï+N†ëâ<̲Ÿ²Js²@†Ás êiŸ#dã"rQžá÷—÷ ìdx÷àÃ/ —¿ß$ƒºg­9t_ÀÐPI¨àõñ7 "ŸØ„\ÀÇÐuOža0³”_ÜøþÑ3`Dr3èjˆ‚g A›7@mw`£íÃÐŽè±1 ­å î¢²‚ƒ¡Ž4°ä`g¸tý9xPèó—_ jÊ¢Àn§ ƒ˜0Ù‹O®Þ|lLþbøÌ!ÄðJX¿óK0üdå`¸wëÃ~`1hÎ~†çW¡ŽËƒ'džïcø°i"ÃËÉ‹¾ž¾í¢}‡õ×ï¾ûóX€ƒé”³ò‡o¬r íbÜ CPuŽx´]Ï0'7ïÏïîo™ÍðæÊV†OÊ¥Lïylî/[8i'¾  ¡™@àÙŽë R^Š Ìš DðêÅgvNNE F`è½|üŠAAN<1tïá[ðFOIA5`}~óîkpÒV—æî¯ÀÆ?xäî•§àEÐÊ$M13#9ð0ôé ÕÃ;`7î?Ã'.†§Bê ¹>ýba¸töú…Gnì¼ÈðX’À/v€Ë¿¾‚áå”Nð¸üÏ{Ï‘"þÚ0í·›¯ÿ¼zürÍê…x«€ª 2Lö¨²!žÀl^It ØZWQ“`PVÈï^‹_iq>ð™Ã SEy¹9¤%xÀ=PÐÁR‰á3°¡ø¨îÍ›/à‘@3Epi:xê乇 Ïíï l ox¥ž (0|æâV¿öl¹Ä°sáa†‡§ï1üÝ îaC#ÿÏ›“ _N.fxÖ2™áËñKÐqy”†a“4¿Î>ýõÒ\Žý43£ú»¯¬Š_aÃÆ 6Áÿ_ð3‰Á Zv6†ï>2\Ù¶†áÙÅ Üšþ m \ ÏŸ<³ssóæ+ð$@1±ˆ‡•~ µ_ qNQ;IõÂ#Ààà‘+ÓÎ6/n¦? <÷¯@êz&Ȩ##¢î‡$ÅȈÀ®#¨-:ä /Ã{`bààÇλÍð|¶ÒêðóßÀFÝ`1¿yÃ×3ÏVßüBÂ?‘Ø¿0j—l·{ è]ÕÿŸá¿“ºÄw[ÕŸ  •å¿ØYí>qA)†oÿù.žyÀðìöm>MoA‡&.ay†Ÿß0\ºt´‘v^qqT2¾ Æ!˜ûa}€;8h×93ð/…ž)*ÃÏPWãVFТLPƒùÏO þ7ÐÆJ–¿QLåúù \ü¿cbq†o¬, ïÞüb8}ô.ÃÙã·Þ|FÍ‹ü¿¯0|»±áåÔ]H‘þK„c‹ø¿H5ÿмÀD óï?c?Ðm.šÀD`­úœ˜¸Ù¾2Š0\¸þ—áÙÃW Üjî ¼VU ìrÀ.ä7ðî§+WîþcbbÊ©®N˜Ž/0ˆqˆV°DÀ M\ †Sr8dª`‘cd©Ào/ø)_ÿ‘Nù‡8| ôŸ?ÀØaaø4ùÎ÷ §¹ýî±;ˆ#Úa†»p/O2|Ú»‰áî[rûo$ú/–ˆÿÏ€ç¼`"PýÿŸq&° rT“ø. eßéœ /^Ý,oËÀeRŒ|6¦Ÿ ïÞ}E>è´Õ½""ü‰ÕÕ‰ñ$@ Õs;34€Åq3˜,^ÀÀÂã +–ÃÌ,-¥!•qk(<@o…%ˆ¯ÀÚùÊùÇ ;6_`ø:oå`P´ýxÅðãæf†7+w1ü|ôKÄÿ$ÛÑÇäÿãQ`"Ð`øÏ8‰™ÁQIô Ó?†—YþŠš1°d0pðKk o ?~a¸{÷ þz——«dÒ¤¢½„Ì ¡œ`³$Ìðö€°= ˜µ ˜E4PêgPLs±1HJ ‚ÅþÃÃ?ø™Ë 5o¿g_û Ëñ0…¿_Ÿdøx|ÛUHÈíèu;òxüR= N ŒS™þ9ƒ¶.¼cT`xÌíÌùÒÀœÿ|ÿ0×ÿûû÷ï>nn®ŽE‹êöc.@ õ€Ü(„´”óM„l—…yQZæðzþ#ER$#óÁÅ=°˜ÿ~g3ûí»>Ÿ~FdnG.æQuäD:–D ¤:8Yþü½ö×j×µ_†Flÿ¾ŠƒÖu011¾fcc9ÍÉɱeíÚŽ‡Äš @C=`kr1(æš0šÕ#”Ø-P%)òÿ¼¿ÂðõÖ†§wA#jºÁh8$äö ´=À N v„;?ýÌdu¤€Ž ÝoŒDø[;à?ö°Äøÿÿ†Q0r@1ÁÈ4šF8 Ñ0Â@&€ 2Љü­ø)IEND®B`‚ltsp-cluster-control-2.0.3/Admin/images/setup_module.gif0000664000175000017500000000163412026403127023533 0ustar stgraberstgraberGIF89a ÷œ³Êçòþ¡µÊÂÚò¬ÅÞYrŠØëþ“¬ÅËäý¤¼Ó¼ÕíJbzµÎ猥½œ°Äöùþ½Òè¾×ð}–®ºÒé¨Àúüÿ§ÀÙi‚›˜±Ê¼ÔëÇàøËàõñ÷þÀØïÿÿÿÿÿÿ, =ôàÀ|ð @ $ØÀAÁ @ô €!„ < ðà DŠT`@‚@2x !@„–ð Áe\zÐéáb€ 0PPÀC‡"#XPÚ!à 0`…®&<`†bz¸P ­Ú· ;ltsp-cluster-control-2.0.3/Admin/images/info_module.gif0000664000175000017500000000164712026403127023332 0ustar stgraberstgraberGIF89a ÷LZsRiŠ6‘ÿíííw™¶êêêY¥þ¯ÒäD™þõõõDM_Lþ’¸ÐŸÄبËÞ?–ÿàO?vŒ§Óçð¤ÀÅZêÑŒ?FVoޝ(0BÚÚÚe«ýçççððð3ÿÿÿÿÿÿÿ, Œ%8à ƒ ¸ Â8 ˜X â†pèÀ±ƒ <Àè`£9>Ø ¤ì°BÎD°3;nP𳃨 ÁBïD€+òYÒ*hPÄ·8È•« @så;ltsp-cluster-control-2.0.3/Admin/images/entity_module.gif0000664000175000017500000000162212026403127023704 0ustar stgraberstgraberGIF89a ÷U€¦pžÅ1ST€¥¢wJPy¡(=f³•s-GqDh“òèÞ#6\ïâÖR|£g•»MuÉ›u' vpAg ‡úœ (IDATX×[ŒU×yÇk¯}9gÎmî30Æ`sÀŃ £ 16Ì%©ÚFV#ÛrãÖu¥4‘[?$}¨úR)ÉKä R9JUW­êÎ8àpˆm,SÀ‰Rƒ‹clO Ìa†anç²ÏÙ·µVΆ¤.鯵÷Zk¯ïÿ­õ]ö'6=ø & éhm%“ÉPð<²Ù,n.G*¦%•B¶¶öf‚`½-¥RbYàz€2­ F)’$‘•tú#3??U CBß'®V©T«,ÕZùR 㥰¹C3€ذ;ŽO¯êï÷’¹Žë`I aI„h’0m4ZiT"»»ùäÓ á˜1Ã>4Íýn×îH@ A™¼òË ï¶qsêË$V“ªPM$ ʞdžU«=ÿÈ‘3£›4œåÿKàºæ†wMNžØòÈ#6à Ó`9 $ ,Ñüâ:Œ­!—ã¡/Ù Žý`´­m›“·#`ÝNx ;v‹§¶»‹0}â:„eK7û ´è½A¢¦§¡TbÛÖ­îÞbñýv¨Û\…}‹ðƱïxbfæÈã_ù \¼A® *iXVC{!áú&Íí…¥ RA¤R<:2BxôØ‘iIïÔpÔ,*û–.Å(E:F¸îæÝ““ï~md9>Ž®VZƒRÌ^ž EXã"Hbˆ›ˆ¢æX¾Ïl±H‹çA£j5¨ÕX¾z5õ3§ÿø\6ûfÇÅ AJäÒ¥KÑJá¦ÓF.^ü¯'G¶Iqå AµÚ8"¥8qö,¯y“ãã¬O¥FÑ­’ÊeþõÃ9jY0>Î@{;aSLrÏŠÌŸ<ùÔo …Ÿ…ApUH¹déR¥6<ðùç¿üómÛkæA¹Œ¼8æ­_ýŠ…o|ƒ?;p€hÝ:ŽýèG¬uäuQJ‘\»Æ«gϲæå—ù£ï~—_ÏÍ1>:ÊòÎNjI‚ïûcX;0 ¿xïijãùÂ!KÚWeo__ïf×ýÍs÷Ýg[33ø• hŒ"Þ9wŽøùçùýï}€%Ë–ÁæÍüçO~Â¥Rb’„úµküôÒ%†^y…¡‡`Í–-œ¯×ùtlŒ%­­„Jáû>Ú~ïÞ•r¶Vû“‹Æü£Ìg2íëêzª·Vcnam :I˜™›Ã¼ø"O¼øâ-VÛÛßOÛŽüìÇ?fET*üÛÂÛfphè–µk¶l¡ØÒBôÎ;X–E=I¨ú>®T«UëÄÜÜQ; Ãxêã)ööB’PSŠ”1H¥Ø<8xÛà±bÕ*¬7ÞàßGF@{ûmî^¹ò¶k‡W­â|Sñ}¢†—‡!µK—P®Û:IR2Eˆ8¦Hƒ§5'¾þu6¿ò ½O<ñ6¾{åJv;ÀÀ„ϾñçŸ{•Ë¡ŒA±1$–…gYh¥°u’`¤¤˜$ØIB \ÀµmÞ~ú¶Òµuk#ˆ,òõuënÄÅã(½ÿ>>û,‰”¨$!ŒcB!ˆAÛvƒRØI:—ã˜t“ò@H;*Ž9¾gÛ¢sëV‚8Á¨¤!uQ2B€’”ë2ÿÞ{|°?±hÏ#ˆc| ÔÙ»y–Ñš˜MÊJ*E])¥ˆµ&ñ<|­9¾ûqЇQêDqLA½0 Œc‚(bêðaNíÝKÍ‚T _)jZ(E¤5¥(%ÉÍ@¢ `ºV£¬5!hµ, B‚<Т5•Zzúiö?NÇÀIÜrß2•bþ‹/xý™gèXX@¶¶Õj ¡ZS7†’1,(EYÖærËÂR’A®^¿‘êÍ>j>»@º£ƒ¯½þ:…j¥ÆÜšVD’¿ë.eì«_Å™ÁB ª@¹Ùû€ŸË!- ÛrHú, [k<ÀœE™Êjocßè(«WSžž¾!\kݘ·I5CºÙýÚkÞ¿æçotšveùæzËq°„m“hMÐt6Ñ´v*ÅcÒvϽ,\¹BDaHÕ÷I··“no§êûDaHÌ‹tÞ»’‘ñS)< ´ÝMô6 Ñr,cÛIÂcèÚ¥$/%PI§ùÒÁƒô 1?1AP¯åj•\?òôiä™3äúû)W«„A@P¯3?1AÏÆ!:xr:d‡œmÓ.½@E %¶å8N~`€® ŸRJb¤ã µÆ’’‡ÇÆÐw/gvbaž%1݃ƒ´žûNìßlýÅ/V¯fúüÇ¸Žƒjtofߨÿ½oZŒè$!gY¸K– ãØ±:óù³ç'ò»»èð\Z¤$Já*…{ä}½=TˆZP§T-Ó98Hÿ… œßµ“v))HÉÇ;w²ìÂ:×Rª–©ÕëTˆ¾ž²o¾I.ŽÉ¹.ۦດººø$ŽÚ …s05£ÔƒBÝÓK‡ç‘µmZóyÆðê/½ÄàÐýÌE=k׳âÔ)~»s'y!è,è.È ÁÅ;¸çäIºÖ­g.ŽX3t?ÉKÅÅþŽ\ŽVË¢Ó¶‰º»ùçr9,&Ƀ¦Ä7' ÙBa½øè£¾ÝÕ•ê*•PÆà(³³,þy¼ïyèSO>‰H§±37ÿÆ߇zžW_%Þ³‡ä;ß¡øòËÐÞŽ’\nkãffpp“_*}ä8âIâ˜\>O*›æÔ©SÓ×GÛÜ‘8Æ ªU «V]º„Õô !ÆÜÈ*B`/[Få“O0Ù,ºéÞÅövþ~rhh8 ‚3ÕrÛuoÈçr¤32Ùì£Ñ»ïûÛ¾>–”ËÔA2 ±])%–XMíE3&ÀƒnTFhÏà ü6_àï®Q[¶O&•ºáNÙ&2ŽCÆqÈ:Y×%›N“ËfÉKI¯çòY>Ï__¾Lv×®í–Ö?ǘ›™“ß© šá K©·6}󛛟š η´Ðæºä¤$ãºx®‹íyÈT ëw =ÇuI¹.iÏãש4qõj°öé§¾d)u\h½¨¢¼& ‘$ìùÖ·6ퟜ Ϻ.d³É4úÅÈå Ÿ¿9—É@&Ãi×姦Âí/¼°ÉJ’S˜ÛW‡âžåËÉårä²YZÒir--ds9Z;;ɵ·“Îdî{ëµÿ8=Çiymšn))y!pK´1€o óJ#º»9â¹õû÷î*•s•ÙY*ss”ËeʾO=ЍT*Ø®‹-¥¼-3c (…‰ãsúí¿¼ûó‹ﳄPUÛ&‚!°y2†Dk"¥Ð ÿ ¿ÿܧŸ}6m”âNÚü/røiQÐÕIEND®B`‚ltsp-cluster-control-2.0.3/Admin/util/0000775000175000017500000000000012026403130020035 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/ClassroomFinder.php0000664000175000017500000000702012026403127023645 0ustar stgraberstgraber *
  • IP of the computer * * * Example of valid initialisation : * * * $finder=new ClassroomFinder("10.1.0.9"); * * * @access public */ function ClassroomFinder($id) { $this->notFound = false; $this->nodeid=$id; $node=new Node($id); $this->classroom = $node->getAttribute('CLASSROOM'); if (empty($this->classroom)) { $this->classroom = $node->name; } // Retrieve computers $from ="nodes N INNER JOIN status S ON S.id = N.id"; $where="N.id_parent=".$this->nodeid; $result=$this->getFromDB("S.ip, S.mac, S.code, S.username",$where,$from,true,true); $this->computers=$result; } /** * Get classroom description * * @access private * @return int */ function getClassroom() { return $this->classroom; } /** * Get computers * * @access private * @return int */ function getComputers() { return $this->computers; } /** * Return true if not found * * @access public * @return int */ function notFound() { return $this->notFound; } /** * Get the node ID * * @access public * @return int */ function getNodeID() { return $this->nodeid; } /** * Get the subnet string * * @access public * @return int */ function getSubnet() { return $this->subnet; } /** * Return yes if the object exists * To be used just after the construction * * @access public * @return float */ function isError() { return $this->isError; } /** * Get the last error * * @access public * @return float */ function lastError() { return $this->lastError; } /** * GetFromDB * * @access private * @return array */ function getFromDB($column,$where,$from,$isFatal=true,$multiple = false) { $query='SELECT '.$column.' FROM '.$from.' WHERE '.$where; if ($multiple) { $result = select($query.";"); } else { $result = singleResultSelect($query); } if (!$result) { $this->lastError = getMessage('not_found').$query; $this->notFound = true; if ($isFatal) $this->isError = true; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error').$result." : ".$query; if ($isFatal) $this->isError = true; return NULL; } return $result; } } // class ClassroomFinder ?> ltsp-cluster-control-2.0.3/Admin/util/InfoViewer.php0000664000175000017500000001065012026403127022633 0ustar stgraberstgrabernode = new Node(trim($_GET['node_id'])); $this->status = $this->node->getStatus(); //$this->attributes = $this->node->getAttributes(); $this->lts = $this->node->getLTS(); return; If (!$this->status){ $this->status['ip'] = "192.168.2.109"; $this->status['bootservip'] = "192.168.2.5"; } $newStatus = $this->status; $newStatus['code'] = 1; if ($this->node->setStatus($newStatus)) { $newStatus = $this->node->getStatus(); } else return; $newStatus['code'] = 2; $newStatus['appservip'] = "192.168.2.71"; $newStatus['display'] = 1; if ($this->node->setStatus($newStatus)) { $newStatus = $this->node->getStatus(); } else return; $newStatus['code'] = 3; $newStatus['username'] = "Nicolas"; if ($this->node->setStatus($newStatus)) { $newStatus = $this->node->getStatus(); } else return; $newStatus['code'] = 4; if ($this->node->setStatus($newStatus)) { $this->newStatus = $this->node->getStatus(); } } function print_info() { if (!$this->node_error($this->node)) $this->print_node($this->node); if ($this->status) $this->print_status($this->status); /*foreach ($this->attributes as $attribute) { $this->print_attribute($attribute); }*/ if (is_array($this->lts)) $this->print_lts($this->lts); return; $this->print_status($this->newStatus); } function print_status($status){ if (!is_array($status)) { print "

    ".$this->node->lastError()."

    \n"; return; } foreach ($status as $name => $value) { print "

    ".$name."=".$value."

    \n"; } print '
    '; } function print_lts($lts){ foreach ($this->lts as $name => $value) { print "

    ".$name." = ".$value."

    \n"; } print '
    '; } function print_attribute($attribute){ print "

    name = ".$attribute->getName()."

    \n"; print "

    value = ".$attribute->getValue()."

    \n"; print "

    id = ".$attribute->getID()."

    \n"; print "

    node_id = ".$attribute->getNodeID()."

    \n"; print "

    attributeDef_id = ".$attribute->getAttributeDefID()."

    \n"; print "

    type = ".$attribute->getType()."

    \n"; print "

    mask = ".$attribute->getMask()."

    \n"; if ($attribute->getType() == 0) { print "

    MaskInfo = ".ereg($attribute->getMask(),$attribute->getValue())."

    \n"; } $selection = $attribute->getSelection(); if (is_array($selection)) { print "

    selection = {
    \n"; foreach ($selection as $key => $value) { print "\t".$key." = ".$value."
    \n"; } print "

    \n>"; } print "

    isError = ".$attribute->isError()."

    \n"; print "

    lastError = ".$attribute->lastError()."

    \n"; print '
    '; } function print_node($node) { print "

    ".getMEssage($_GET['module'])."

    "; print "

    id = ".$node->getID()."

    \n"; print "

    father = ".$node->getParentID()."

    \n"; print "

    mac = ".$node->getMac()."

    \n"; print "

    name = ".$node->getName()."

    \n"; if ($node->isNode()) print "

    isNode = true

    \n"; else print "

    isNode = false

    \n"; if ($node->isError()) print "

    isError = true

    \n"; else print "

    isError = false

    \n"; print "

    lastError = ".$node->lastError()."

    \n"; print '
    '; } function node_error($node) { if ($node->isError()) { print "

    ".$node->lastError()."

    \n"; return true; } return false; } } ?>ltsp-cluster-control-2.0.3/Admin/util/setupView.php0000664000175000017500000002234412026403127022554 0ustar stgraberstgraber"; }else{ if($type == "PASSWORD") return "**********"; else return "".$value.""; } } function getPrinter($name,$type,$value) { if($_POST['modify']|| $_POST['save']){ return ""; }else{ return "".$value.""; } } function getLangageName( $langage_file ){ include $langage_file; return $lang_name; } ?>

    "; echo ""; if($CONFIG['first_setup_lock']!="TRUE"){ echo ""; } echo "

    "; } ?>

    "; if($_POST['modify'] || $_POST['save']){ echo ""; }else{ echo getInput('lang', 'TEXT'); } ?>




















     

    role if($_POST['modify'] || $_POST['save']){ $countGroup = 0; foreach ($GROUP_ROLE as $group=>$role) { $countGroup++;?>

    $role) {?> $value) { if($roleName ==$role){ ?> =>





    NONE

    ltsp-cluster-control-2.0.3/Admin/util/entityBrowserView.php0000664000175000017500000000534012026403127024271 0ustar stgraberstgrabermessage) { ?>

    message) ?>

    ">

    printErrors(); ?>

    allGroups) || !empty($this->allUsers)) {?>

    $value) { if ($name != $this->entity_id) { ?>

    1){ ?> []
    ltsp-cluster-control-2.0.3/Admin/util/entity.php0000664000175000017500000000210512026403127022066 0ustar stgraberstgrabergetPermissions(); $am = new AttributesManager($ub->getNode(),array("custom","entity"),array(USER_TYPE,GROUP_TYPE),$perm); break; case 'print': $ub->printView(); $am->printView(); break; } ?> ltsp-cluster-control-2.0.3/Admin/util/HWGroupFinder.php0000664000175000017500000000640312026403127023242 0ustar stgraberstgrabernotFound = false; $this->hardware = $hardware; // Retrieve all hwgroups in the node scope if (!$node->getRightval()) return; $where='N.leftval<' . $node->getRightval() . ' AND N.rightval>=' . $node->getRightval() . ' ORDER BY N.leftval DESC'; $from='nodes N INNER JOIN nodes NH ON NH.id_parent=N.id AND NH.nodetype='.HWGROUP_TYPE.' INNER JOIN hwgroupsrule H ON H.nodes_id=NH.id'; $hwgrules = $this->getFromDB("NH.*, H.*",$where,$from,false,true); // Test matching groups if (is_array($hwgrules)) { foreach ($hwgrules as $hwg) { $hwgr = new HWGroupRule($hwg); if (!$tab[$hwgr->getNodeID()]=="no" && $hwgr->match($hardware)) $tab[$hwgr->getNodeID()]="yes"; else $tab[$hwgr->getNodeID()]="no"; } // Set selected groups foreach ($tab as $key=>$value) { if ($value=="yes") $this->nodesIds[] = $key; } } } /** * Return true if not found * * @access public * @return int */ function notFound() { return $this->notFound; } /** * Get the nodes found * * @access public * @return int */ function getNodesIds() { return $this->nodesIds; } /** * Return yes if the object exists * To be used just after the construction * * @access public * @return float */ function isError() { return $this->isError; } /** * Get the last error * * @access public * @return float */ function lastError() { return $this->lastError; } /** * GetFromDB * * @access private * @return array */ function getFromDB($column,$where,$from="nodes",$isFatal=true,$multiple = false) { $query='SELECT '.$column.' FROM '.$from.' WHERE '.$where; if ($multiple) { $result = select($query.";"); } else { $result = singleResultSelect($query); } if (!$result) { $this->lastError = getMessage('not_found').$query; $this->notFound = true; if ($isFatal) $this->isError = true; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error').$result." : ".$query; if ($isFatal) $this->isError = true; return NULL; } return $result; } } ?> ltsp-cluster-control-2.0.3/Admin/util/listManagerView.php0000664000175000017500000000541012026403127023655 0ustar stgraberstgrabereditableAttributes)){ ?>
    " />
    " /> dictionary); $index++) { ?>
    " />
    " /> " /> " /> " /> " /> " />
    printErrors();?> ltsp-cluster-control-2.0.3/Admin/util/SessionData.php0000664000175000017500000000070112026403127022767 0ustar stgraberstgraberusername = $username; $this->groups = $groups; } function getUsername() { return $this->username; } function getGroups() { return $this->groups; } } ltsp-cluster-control-2.0.3/Admin/util/stats.php0000664000175000017500000000157412026403127021721 0ustar stgraberstgraber".getMessage('stats_no_frames')."".getMessage('stats_module').""; } ?>ltsp-cluster-control-2.0.3/Admin/util/text-fr.php0000664000175000017500000007447612026403127022167 0ustar stgraberstgraberLa requête était : "; $MESSAGES['no_db_password'][$lang] = "Le mot de passe de l'usager utilisé pour la connexion à la base de données du configurateur n'est pas bien définit.
    Vous pouvez le définir sous : « Paramètres du configurateur » --> « Base de donnée du configurateur » ou vous pouvez le définir manuellement dans le fichier « config.php » sur le configurateur avec l'attribut « db_password ».
    La requête était : "; $MESSAGES['no_db_name'][$lang] = "Le nom de la base de données du configurateur n'est pas bien définit.
    Vous pouvez le définir sous : « Paramètres du configurateur » --> « Base de donnée du configurateur » ou vous pouvez le définir manuellement dans le fichier « config.php » sur le configurateur avec l'attribut « db_name ».
    La requête était : "; $MESSAGES['db_error'][$lang] = "Erreur de requête sur la base de donnée : "; //////////////////////////////////////////////////////////////////// // Module names //////////////////////////////////////////////////////////////////// $MESSAGES['configuration_module'][$lang] = "Configuration des terminaux"; $MESSAGES['nodesManager_module'][$lang] = "Gestion de l'arborescence"; $MESSAGES['entity_module'][$lang] = "Configuration Groupe/usager"; $MESSAGES['managelist_module'][$lang] = "Liste des valeurs des attributs"; $MESSAGES['info_module'][$lang] = "Infos techniques"; $MESSAGES['logs_module'][$lang] = "Journal des activités des terminaux"; $MESSAGES['stats_module'][$lang] = "Rapports"; $MESSAGES['printing_module'][$lang] = "Gestion des imprimantes"; $MESSAGES['setup_module'][$lang] = "Paramètres du configurateur"; $MESSAGES['configuration_module_short'][$lang] = "Terminaux"; $MESSAGES['nodesManager_module_short'][$lang] = "Arborescence"; $MESSAGES['entity_module_short'][$lang] = "Groupe/Usager"; $MESSAGES['managelist_module_short'][$lang] = "Attributs"; $MESSAGES['info_module_short'][$lang] = "Infos techniques"; $MESSAGES['logs_module_short'][$lang] = "Journal des activités"; $MESSAGES['stats_module_short'][$lang] = "Rapports"; $MESSAGES['printing_module_short'][$lang] = "Imprimantes"; $MESSAGES['setup_module_short'][$lang] = "Paramètres"; //////////////////////////////////////////////////////////////////// // Configurator setup section //////////////////////////////////////////////////////////////////// // General setup messages $MESSAGES['new_cfg_created'][$lang] = "Le nouveau fichier de configuation a été écrit."; $MESSAGES['cannot_open_cfg_file'][$lang] = "Impossible d'ouvrir le fichier config.php en écriture."; $MESSAGES['exit'][$lang] = "Verrouiller"; $MESSAGES['modify'][$lang] = "Enregistrer"; $MESSAGES['lock_setup'][$lang] = "Quitter"; $MESSAGES['cfg_val_true'][$lang] = "Oui"; $MESSAGES['cfg_val_false'][$lang] = "Non"; $MESSAGES['test'][$lang] = "Tester"; // Language configuration section $MESSAGES['cfg_lang_section'][$lang] = "Langue"; $MESSAGES['cfg_language'][$lang] = "Langue de l'interface du configurateur"; $MESSAGES['cfg_charset'][$lang] = "Table des caractères à utiliser (Par défaut UTF-8) :"; // Configurator Security section $MESSAGES['cfg_configurator_security_section'][$lang] = "Sécurité du configurateur"; $MESSAGES['use_https'][$lang] = "Accéder à l'interface du configurateur via une connexion sécurisée (https)"; $MESSAGES['need_https'][$lang] = 'Cette page doit utiliser une connexion sécurisée (https).'; // Terminals Security section $MESSAGES['cfg_terminal_security_section'][$lang] = "Securité des terminaux"; $MESSAGES['cfg_terminal_password'][$lang] = "Mot de passe des terminaux"; $MESSAGES['cfg_terminal_auth'][$lang] = "Activation de l'authentification des terminaux"; // Configurator database section $MESSAGES['cfg_db_section'][$lang] = "Base de données du configurateur"; $MESSAGES['cfg_db_server'][$lang] = "Adresse de la base de données (Valeur par défaut : localhost)"; $MESSAGES['cfg_db_user'][$lang] = "Utilisateur utilisé pour la connexion à la base de données (Valeur par défaut : mille)"; $MESSAGES['cfg_db_password'][$lang] = "Mot de passe de l'utilisateur utilisé pour la connexion à la base de données (Valeur par défaut : mille)"; $MESSAGES['cfg_db_name'][$lang] = "Nom de la base de données (Valeur par défaut : millev2)"; $MESSAGES['cfg_db_type'][$lang] = "Type de base de données (Valeur par défaut : postgres7)"; // Authentification configuration section $MESSAGES['cfg_auth_section'][$lang] = "Système d'authentification pour l'accès à l'interface du configurateur"; $MESSAGES['cfg_auth_name'][$lang] = "Sélectionner le mécanisme d'authentication pour l'accès à l'interace Web du configurateur"; // LDAP configuration (subsection of Authentification configuration) $MESSAGES['cfg_ldap_section'][$lang] = "Configuration des paramètres pour l'authentification LDAP"; $MESSAGES['cfg_ldap_host'][$lang] = "URL du serveur LDAP (Valeur par défaut : ldaps://ldap)"; $MESSAGES['cfg_ldap_basedn'][$lang] = "Base de recherche :"; $MESSAGES['cfg_ldap_object_class'][$lang] = "Classe object des utilisateurs (facultatif)"; $MESSAGES['cfg_ldap_group_object_class'][$lang] = "Classe object des groupes (facultatif)"; $MESSAGES['cfg_ldap_group'][$lang] = "Nom de l'attribut des groupes"; $MESSAGES['cfg_ldap_binddn'][$lang] = "Usager LDAP pour accèder à l'informations des utilisateurs (Par défault c'est le même qu'à la connection"; $MESSAGES['cfg_ldap_bindpw'][$lang] = "Mot de passe de l'usager précédant (Par défault c'est le même qu'à la connection)"; $MESSAGES['cfg_ldap_uidAttribute'][$lang] = "Attribut utilisé pour la recherche d'un usager : "; $MESSAGES['cfg_ldap_version'][$lang] = "version du protocole LDAP (Valeur par défaut : 3)"; $MESSAGES['test_ldap'][$lang] = "Entrez votre nom d'usager et mot de passe afin de tester la configuration LDAP"; // LDAP user and group rights association section $MESSAGES['ldap_group_role'][$lang] = "Association des droits pour les utilisateurs et les groupes « Oubligatoire »"; // Load balancer section $MESSAGES['cfg_loadbalancer_section'][$lang] = "Système de répartition de la charge"; $MESSAGES['cfg_loadbalancer'][$lang] = "URL (Valeur par défaut : localhost:8001)"; // printer servers section $MESSAGES['printer_server_section'][$lang] = "Serveurs d'impression (Cups)"; //////////////////////////////////////////////////////////////////// // Login Screen //////////////////////////////////////////////////////////////////// $MESSAGES['index_title'][$lang] = 'Connexion au système de configuration Mille-Xterm'; $MESSAGES['no_language_file'][$lang] = "Le fichier text-.php n'a pas été trouvé sur le serveur, la langue n'est pas supporté."; $MESSAGES['ask_uid'][$lang] = 'Entrez votre nom d\'usager : '; $MESSAGES['ask_password'][$lang] = 'Enter your password : '; $MESSAGES['connect'][$lang] = 'Se connecter'; $MESSAGES['bad_login'][$lang] = 'Nom d\'usager ou mot de passe invalide.'; $MESSAGES['good_login'][$lang] = 'Connexion de l\'usager réussie.'; //////////////////////////////////////////////////////////////////// // Search node Module //////////////////////////////////////////////////////////////////// $MESSAGES['id_or_mac'][$lang] = "Rerchercher un élément par son adresse MAC ou son numéro d'identification"; $MESSAGES['find'][$lang] = "Rechercher"; $MESSAGES['go'][$lang] = "Atteindre"; $MESSAGES['search_inv'][$lang] = "Rerchercher un élément par son numéro d'inventaire:"; //////////////////////////////////////////////////////////////////// // Configuration module //////////////////////////////////////////////////////////////////// $MESSAGES['source'][$lang] = "Sélection de l'élément à gérer"; $MESSAGES['nodes_editor_change_tree_name'][$lang] = "Modification du nom de l'arborescence"; $MESSAGES['nodes_editor_manage_actual_nodes'][$lang] = "Gérer les enfants de cet arborescence"; $MESSAGES['nodes_editor_deselect'][$lang] = "Désélectionner"; $MESSAGES['config_attributes_listing'][$lang] = "Configuration actuelle"; $MESSAGES['config_delete'][$lang] = "Supprimer"; $MESSAGES['config_modify'][$lang] = "Modifier"; $MESSAGES['config_cancel'][$lang] = "Désélectionner"; $MESSAGES['config_select_tree'][$lang] = "Sélection de l'arborescence"; //////////////////////////////////////////////////////////////////// // User and group module //////////////////////////////////////////////////////////////////// $MESSAGES['add_user_group'][$lang] = "Ajouter un "; $MESSAGES['user'][$lang] = "Usager"; $MESSAGES['group'][$lang] = "Groupe"; $MESSAGES['users'][$lang] = "Usagers"; $MESSAGES['groups'][$lang] = "Groupes"; $MESSAGES['search_user_group'][$lang] = "Nom de l'usager ou du groupe"; $MESSAGES['invalide_node_name'][$lang] = "Nom invalide :"; $MESSAGES['db_duplicate_value'][$lang] = "La valeur entrée existe déjà !"; //////////////////////////////////////////////////////////////////// // Ldap messages at Login Screen //////////////////////////////////////////////////////////////////// $MESSAGES['ldap_cant_connect'][$lang] = "Impossible de contacter le serveur LDAP à l'adresse : ".$CONFIG['ldap_host']; $MESSAGES['ldap_connected'][$lang] = "Vous êtes déjà connecté au serveur LDAP."; $MESSAGES['ldap_not_connected'][$lang] = "Impossible de fermer la connexion au serveur LDAP."; $MESSAGES['ldap_version_not_supported'][$lang] = "Le serveur LDAP ne semble pas supporter la version ".$CONFIG['ldap_version']." du protocole LDAP"; $MESSAGES['ldap_user_bind'][$lang] = "Paramêtre binddn ou bindpw manquant dans le fichier de configuration, connection avec l'usager"; $MESSAGES['ldap_no_basedn'][$lang] = "La base de recherche de LDAP (basedn) n'est pas définit ou ne semble pas être valide.
    Vous pouvez la définir sous : « " .getMessage('setup_module')." » --> « ".getMessage('cfg_auth_section')." » --> « ".getMessage('cfg_ldap_section')." » ou vous pouvez la définir manuellement dans le fichier « ".$CONFIG['rootInstall']."util/config.php » sur le configurateur avec l'attribut « ldap_basedn »."; $MESSAGES['ldap_cant_bind'][$lang] = "Impossible de contacter le serveur LDAP à l'adresse : ".$CONFIG['ldap_host']."
    Assurez-vous que le serveur LDAP fonctionne bien et que votre configuration est adéquate.
    Vous pouvez modifier la configuration sous : « " .getMessage('setup_module')." » --> « ".getMessage('cfg_auth_section')." » --> « ".getMessage('cfg_ldap_section')." » ou vous pouvez la modifier manuellement dans le fichier « ".$CONFIG['rootInstall']."util/config.php » sur le serveur du configurateuravec l'attribut « ldap_host »."; $MESSAGES['ldap_no_host'][$lang] = "Il n'y a pas d'hôte de définit pour le serveur LDAP.
    Vous pouvez le définir sous : « Paramètres du configurateur » --> « Base de donnée du configurateur » ou vous pouvez le définir manuellement dans le fichier « ".$CONFIG['rootInstall']."util/config.php » sur le configurateur avec l'attribut « ldap_host »."; $MESSAGES['ldap_no_group'][$lang] = "Il n'y a pas de groupe LDAP de définit.
    Vous pouvez la définir sous : « Paramètres du configurateur » --> « Base de donnée du configurateur » ou vous pouvez la définir manuellement dans le fichier « ".$CONFIG['rootInstall']."util/config.php » sur le configurateur avec l'attribut « ldap_group »."; //////////////////////////////////////////////////////////////////// // Group/User Module //////////////////////////////////////////////////////////////////// $MESSAGES['entity_add_entity_message'][$lang] = "Ajouter des utilisateurs et des groupes"; $MESSAGES['entity_manage_user_group'][$lang] = "Gérer les utilisateurs et les groupes"; $MESSAGES['newDefaultValueListAttribute'][$lang] = ""; //////////////////////////////////////////////////////////////////// // Report module //////////////////////////////////////////////////////////////////// $MESSAGES['stats_node_selector_msg'][$lang] = "Sélectionnez les éléments que vous désirez traiter"; $MESSAGES['stats_true_conditions'][$lang] = "Sélectionnez les conditions auxquelles les attributs des éléments doivent correspondre"; $MESSAGES['stats_false_conditions'][$lang] = "Sélectionnez les conditions auxquelles les attributs des éléments ne doivent pas correspondre"; $MESSAGES['stats_add_cond'][$lang] = "Ajouter"; $MESSAGES['stats_add_value'][$lang] = "Ajouter"; $MESSAGES['stats_selected_value'][$lang] = "Condition(s) sélectionnée(s) :"; $MESSAGES['stats_select_what'][$lang] = "Traiter les : "; $MESSAGES['stats_terminals'][$lang] = "Terminaux"; $MESSAGES['stats_contexts'][$lang] = "Contextes"; $MESSAGES['stats_contexts_n_terminals'][$lang] = "Terminaux et les Contextes"; $MESSAGES['stats_use_heritage'][$lang] = "Prendre en compte des attributs hérités : "; $MESSAGES['stats_yes'][$lang] = "Oui"; $MESSAGES['stats_no'][$lang] = "Non"; $MESSAGES['stats_send'][$lang] = "Continuer"; $MESSAGES['stats_validate'][$lang] = "Ok"; $MESSAGES['stats_configuration'][$lang] = "Attributs de configuration"; $MESSAGES['stats_network'][$lang] = "Attributs réseau"; $MESSAGES['stats_hardware'][$lang] = "Attributs matériels"; $MESSAGES['stats_select_attr_title'][$lang] = "Sélectionez les attributs que vous désriez afficher leur valeur dans le rapport"; $MESSAGES['stats_select_attr_config'][$lang] = "Attributs de configuration :"; $MESSAGES['stats_select_attr_hardware'][$lang] = "Attributs matériels :"; $MESSAGES['stats_select_attr_network'][$lang] = "Attributs réseau :"; $MESSAGES['stats_select_attr_type'][$lang] = "Afficher sous forme de :"; $MESSAGES['stats_generate'][$lang] = "Générer le rapport"; $MESSAGES['stats_select_attr_type_context'][$lang] = "Contexte"; $MESSAGES['stats_select_attr_type_table'][$lang] = "Tableau"; $MESSAGES['stats_attribute'][$lang] = "Attributs"; $MESSAGES['stats_report_no_attr'][$lang] = "Il n'y aucun attribut à afficher parmis ceux qui ont été sélectionnés."; $MESSAGES['stats_report_err_cond'][$lang] = "Cet élément ne répond pas aux conditions fixés"; $MESSAGES['stats_equals'][$lang] = "Est égal à"; $MESSAGES['stats_unequals'][$lang] = "N'est pas égal à"; $MESSAGES['stats_greater'][$lang] = "Est plus grand que"; $MESSAGES['stats_greater_equals'][$lang] = "Est plus grand ou égal à"; $MESSAGES['stats_lower'][$lang] = "Est plus petit que"; $MESSAGES['stats_lower_equals'][$lang] = "Est plus petit ou égal à"; $MESSAGES['stats_no_node'][$lang] = "Vous n'avez pas sélectionner d'éléments à traiter"; $MESSAGES['stats_and'][$lang] = "ET"; $MESSAGES['stats_or'][$lang] = "OU"; $MESSAGES['stats_node'][$lang] = "Élément"; $MESSAGES['stats_path'][$lang] = "Emplacement"; $MESSAGES['stats_no_frames'][$lang] = "Votre navigateur ne supporte pas les iframes. Pour accèder au module de rapports, suivez le lien suivant: "; //////////////////////////////////////////////////////////////////// // Printer Module //////////////////////////////////////////////////////////////////// $MESSAGES['printer_manage'][$lang] = "Gérer"; $MESSAGES['printer_manage_list'][$lang] = "Sélection des serveurs d'impression à gérer"; $MESSAGES['printer_server_list'][$lang] = "Liste des imprimantes du serveur"; $MESSAGES['printer_add'][$lang] = "Ajouter"; $MESSAGES['printer_delete'][$lang] = "Supprimer"; $MESSAGES['printer_database'][$lang] = "Imprimantes installés dans la base de données du configurateur"; $MESSAGES['printer_servers'][$lang] = "Imprimantes disponibles"; $MESSAGES['printer_standalone_list'][$lang] = "Liste des imprimantes indépendantes"; $MESSAGES['printer_add_a_standalone'][$lang] = "Ajout d'imprimantes indépendantes"; $MESSAGES['printer_no_printer_standalone'][$lang] = "Il n'y a aucune imprimante indépendante définie."; $MESSAGES['printer_warning_standalone'][$lang] = "Attention : Il est possible que des imprimantes soient dans la liste des imprimantes indépendantes si leur serveur ne répond pas.
    Ces imprimantes réapparaîtrons dans la liste de ce serveur lorsque celui-ci sera disponible à nouveau."; $MESSAGES['printer_no_server'][$lang] = "Le serveur ne répond pas."; $MESSAGES['printer_dead_server'][$lang] = "Le nom DNS du serveur existe mais le serveur ne répond pas."; $MESSAGES['printer_no_printer_server'][$lang] = "Il n'y a pas de serveur d'impression configuré.

    Si vous le désirez, vous pouvez en ajouter à l'emplacement suivant : « ".getMessage('setup_module')." » --> « ".getMessage('printer_server_section')." »
    Vous pouvez néanmoins utiliser la « ".getMessage('printer_standalone_list')." »"; $MESSAGES['printer_check_all'][$lang] = "Tout sélectionner"; //////////////////////////////////////////////////////////////////// // Log Module //////////////////////////////////////////////////////////////////// $MESSAGES['logs_ts'][$lang] = "Date et heure"; $MESSAGES['logs_id'][$lang] = "ID du noeud du terminal"; $MESSAGES['logs_mac'][$lang] = "Adresse MAC"; $MESSAGES['logs_ip'][$lang] = "Adresse du terminal"; $MESSAGES['logs_bootservip'][$lang] = "Adresse du serveur de démarrage"; $MESSAGES['logs_appservip'][$lang] = "Adresse du serveur d'application "; $MESSAGES['logs_username'][$lang] = "Nom de l'utilisateur"; $MESSAGES['logs_code'][$lang] = "Événement"; $MESSAGES['logs_bootservretry'][$lang] = "Entrée Démarrage"; $MESSAGES['logs_appservretry'][$lang] = "Entrée Application"; $MESSAGES['logs_prev'][$lang] = "Précédente"; $MESSAGES['logs_next'][$lang] = "Suivante"; $MESSAGES['logs_nb_logs_message'][$lang] = "Résultats par page"; $MESSAGES['logs_filter_message'][$lang] = "Gestion des filtres"; $MESSAGES['logs_table_message'][$lang] = "Résultats"; $MESSAGES['logs_validate'][$lang] = "Appliquer"; $MESSAGES['logs_code_booting'][$lang] = "Démarrage du terminal"; $MESSAGES['logs_code_GDM'][$lang] = "Écran de connexion"; $MESSAGES['logs_code_logging'][$lang] = "Connexion de l'utilisateur"; $MESSAGES['logs_code_unlogging'][$lang] = "Déconnexion de l'utilisateur"; $MESSAGES['logs_msg_filter_seizure'][$lang] = "Saisie des filtres"; $MESSAGES['logs_msg_active_filters'][$lang] = "Filtres actifs"; $MESSAGES['logs_code_msg_legend'][$lang] = "Légende des événements"; $MESSAGES['logs_equals'][$lang] = "="; $MESSAGES['logs_greater'][$lang] = ">"; $MESSAGES['logs_gt_equals'][$lang] = ">="; $MESSAGES['logs_smaller'][$lang] = "<"; $MESSAGES['logs_sm_equals'][$lang] = "<="; $MESSAGES['logs_not_equals'][$lang] = "!="; $MESSAGES['logs_send_add_filter'][$lang] = "Ajouter le filtre"; $MESSAGES['logs_send_remove_filter'][$lang] = "Supprimer tous les filtres"; //////////////////////////////////////////////////////////////////// // Attribute Names & Values //////////////////////////////////////////////////////////////////// //$MESSAGES['SOUND'][$lang] = "Activer le son"; //$MESSAGES['SOUND_Y'][$lang] = "Oui"; //$MESSAGES['SOUND_N'][$lang] = "Non"; //////////////////////////////////////////////////////////////////// // Message to use when asked message is not defined // // DO NOT REMOVE OR CHANGE THE NAME OF THIS MESSAGE, // YOU WILL GET INFINIT RECURSION IN GETMESSAGE FUNCTION //////////////////////////////////////////////////////////////////// $MESSAGES['messages_error'][$lang] = 'This message is not set in text-fr.php'; unset($lang); /////////////////////////////////////////////////////////////////// // Old Messages - If you want to delete some message and you are not sure // if this message is still in use, add the message temporaly here and // comment it. Don't forget to add the remove date... /////////////////////////////////////////////////////////////////// // ******** Message removed 24-07-2006 ************ // $MESSAGES['printer_selected'][$lang] = "Imprimante sélectionnée: "; // $MESSAGES['selected_printer'][$lang] = "Selected printer"; // $MESSAGES['no_printer_selected'][$lang] = "No printer selected."; // $MESSAGES['assign_printer_to_local'][$lang] = "Assign a printer to a local"; // $MESSAGES['assign'][$lang] = "Assigner"; // $MESSAGES['node_selected'][$lang] = "Selected node:"; // $MESSAGES['printer_selected'][$lang] = "Selected printer:"; // $MESSAGES['add'][$lang] = "Add"; // $MESSAGES['delete'][$lang] = "Delete"; // $MESSAGES['add_a_printer'][$lang] = "Add a printer"; // $MESSAGES['printer_name'][$lang] = "Printer name"; // $MESSAGES['printer_description'][$lang] = "Description"; // $MESSAGES['printer_not_found'][$lang] = "Printer not found"; // $MESSAGES['delete_printer_ok'][$lang] = "Printer deleted."; // $MESSAGES['add_printer_ok'][$lang] = "Printer added."; // $MESSAGES['printer_priceperpage'][$lang] = "$/page"; // $MESSAGES['printer_priceperjob'][$lang] = "$/job"; // $MESSAGES['cannot_update_dico'][$lang] = "Cannot update dictionary: "; // $MESSAGES['sync'][$lang] = "Synchronize"; // $MESSAGES['sync_dict'][$lang] = "Synchronize the dictionary"; // $MESSAGES['sync_users'][$lang] = "Synchronize PyKota users"; // $MESSAGES['printer_servers_list'][$lang] = "Printer servers list"; // $MESSAGES['no_printer_servers_list'][$lang] = "No printer server configured
    You can add one under Parameter --> Printing"; // $MESSAGES['cannot_get_status'][$lang] = "Cannot get status : "; // $MESSAGES['cannot_set_status'][$lang] = "Cannot set status : "; // $MESSAGES['id_printer'][$lang] = "Write the name, the ID or a regular expression for choosing your ptinter:"; // $MESSAGES['setup_title'][$lang] = 'Configurator setup'; // $MESSAGES['cfg_ldap_people'][$lang] = "Enter LDAP user base (Default is ou=People)"; // $MESSAGES['logs_note'][$lang] = "Terminals activity: from most recent to the oldest"; // $MESSAGES['logs_display'][$lang] = "\$Display"; ?> ltsp-cluster-control-2.0.3/Admin/util/managelist.php0000664000175000017500000000150512026403127022701 0ustar stgraberstgraberprintView(); break; } ?> ltsp-cluster-control-2.0.3/Admin/util/logs.php0000664000175000017500000000144012026403127021517 0ustar stgraberstgraberprint_logs(); break; endswitch; ?> ltsp-cluster-control-2.0.3/Admin/util/LDAPAuth.php0000664000175000017500000001305512026403127022122 0ustar stgraberstgraber * - Creation */ require_once 'functions.php'; require_once 'SessionData.php'; class Auth { var $uid; // Username var $pass; // Password var $connection; // Connection object, return true if connected; var $role; // Role admin|user|nobody var $userData; function Auth($uid, $pass) { $this->uid = $uid; $this->pass = $pass; } function connect() { global $CONFIG; // Check if connection already exist if ($this->connection) return getMessage('ldap_connected'); // Check for host configuration if (!isset ($CONFIG['ldap_host'])) return getMessage('ldap_no_host'); // Connect to LDAP $this->connection = ldap_connect($CONFIG['ldap_host']); if (!$this->connection) return getMessage('ldap_cant_connect') . " : " . $this->connecion; // Defaulting to LDAP version 3 if (!isset ($CONFIG['ldap_version'])) $CONFIG['ldap_version'] = 3; // Setting ldap protocol to use if (!ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $CONFIG['ldap_version'])) return getMessage('ldap_version_not_supported'); return NULL; } function disconnect() { // Check if connection exists if (!($this->connection)) return getMessage('ldap_not_connected'); // Close the connection ldap_close($this->connection); // Clean var $this->connection = NULL; return NULL; } function authenticate() { global $CONFIG; global $WARNINGS; // Check if basedn is defined if (!isset ($CONFIG['ldap_basedn'])) { $this->disconnect(); return getMessage('ldap_no_basedn'); } //Check if ldap_uidAttribute is defined if (!isset ($CONFIG['ldap_uidAttribute'])) { $CONFIG['ldap_uidAttribute'] = 'uid'; } // Check if ldap_group is defined if (!isset ($CONFIG['ldap_group'])) { $this->disconnect(); return getMessage('ldap_no_group'); } //check if password is not empty if (!isset ($this->pass) || strlen($this->pass) < 1) { $this->disconnect(); return getMessage('bad_login'); } // Check if user can bind if ($error = $this->connect()) return $error; /* FIXME * A bad login is sent when we get protocol error. */ // // Binding to read group and user informations if (!@ ldap_bind($this->connection, $CONFIG['ldap_binddn'], $CONFIG['ldap_bindpw'])) { $this->disconnect(); return getMessage('ldap_cant_bind'); } $searchBase = $CONFIG['ldap_basedn']; $filter = $CONFIG['ldap_uidAttribute'] . "=" . $this->uid; if (isset ($CONFIG['ldap_object_class'])) { $filter = "(&(" . $filter . ")(objectclass=" . $CONFIG['ldap_object_class'] . "))"; } $searchResult = @ ldap_search($this->connection, $searchBase, $filter); $entries = @ldap_get_entries($this->connection, $searchResult); //$entry = @ldap_first_entry($this->connection, $searchResult); $dn = $entries[0]["dn"]; //$entry=$entries[0]; //$values = @ldap_get_values($this->connection,$entry,$CONFIG['ldap_group']); $attribute = strtolower($CONFIG['ldap_group']); $groups=array(); for ($j = 0; $j < $entries[0][$attribute]['count']; $j++) { //first index is the group name $arrString = preg_replace("/.*=/", "", preg_split('@[,]+@', $entries[0][$attribute][$j])); $groups[$j] = strtolower($arrString[0]); } if (!$entries["count"]) { return getMessage('bad_login'); } $this->disconnect; $this->connect; if (!@ ldap_bind($this->connection, $dn, $this->pass)) { $this->disconnect(); return getMessage('bad_login'); } // Authentificatiion is done $this->disconnect(); $this->userData = new SessionData($this->uid,$groups); return NULL; } function getRole() { return $this->role; } function getUserData() { return $this->userData; } function isValidEntity($entityName,$entityType){ global $CONFIG; $this->connect(); // Binding to read group and user informations if (!@ ldap_bind($this->connection, $CONFIG['ldap_binddn'], $CONFIG['ldap_bindpw'])) { $this->disconnect(); return getMessage('ldap_cant_bind'); } $searchBase = $CONFIG['ldap_basedn']; $filter=""; if($entityType == GROUP_TYPE){ $filter = $CONFIG['ldap_uidAttribute']. "=" .$entityName; if (isset ($CONFIG['ldap_group_object_class'])) { $filter = "(&(" . $filter . ")(objectclass=" . $CONFIG['ldap_group_object_class'] . "))"; } }else if($entityType == USER_TYPE){ $filter = $CONFIG['ldap_uidAttribute']. "=" .$entityName; if (isset ($CONFIG['ldap_object_class'])) { $filter = "(&(" . $filter . ")(objectclass=" . $CONFIG['ldap_object_class'] . "))"; } }else{ return false; } //if (isset ($CONFIG['ldap_object_class'])) { // $filter = "(&(" . $filter . ")(objectclass=" . $CONFIG['ldap_object_class'] . "))"; //} $searchResult = @ ldap_search($this->connection, $searchBase, $filter); $entries = @ldap_get_entries($this->connection, $searchResult); $isValid = false; if ($entries["count"]) { $isValid = true; } $this->disconnect(); return $isValid; } } ltsp-cluster-control-2.0.3/Admin/util/info.php0000664000175000017500000000144012026403127021506 0ustar stgraberstgraberprint_Info(); break; endswitch; ?> ltsp-cluster-control-2.0.3/Admin/util/loginView.php0000664000175000017500000000256412026403127022526 0ustar stgraberstgraber

    ltsp-cluster-control-2.0.3/Admin/util/printing.php0000664000175000017500000000145512026403127022413 0ustar stgraberstgraberprint_printing(); break; } ?> ltsp-cluster-control-2.0.3/Admin/util/config.php0000664000175000017500000000165212026403127022025 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Admin/util/printerView.php0000664000175000017500000000273412026403127023100 0ustar stgraberstgraber

    print_printer_resume() ?>
    getPriceperpage() ?> ; getPriceperjob() ?>
    getDescription() ?>

    ltsp-cluster-control-2.0.3/Admin/util/AttributeDef.php0000664000175000017500000001637212026403127023147 0ustar stgraberstgraber * - Creation */ require_once 'Attribute.php'; require_once 'dbFunctions.php'; class AttributeDef { var $def_id; var $name; var $type; var $mask; var $editable; var $selection; var $lastError; var $isError; var $notFound; function AttributeDef($id) { $this->isError = false; $this->noFound = false; if (is_numeric($id)) { if (!$attributeDef = $this->getFromDB("*", "id=".$id)) return; } else if (is_array($id)) { $attributeDef = $id; } //get something like static object else if($id=="static"){ //do nothing } else { $this->isError = true; $this->lastError = getMessage('bad_id')."id=".$id; return; } $this->def_id = $attributeDef['id']; $this->name = $attributeDef['name']; $this->type = $attributeDef['attributetype']; $this->mask = $attributeDef['mask']; $this->editable = $attributeDef['editable']; } // private function getFromDB($column,$where,$from="attributesDef",$isFatal=true, $multiple = false) { if ($multiple) { $result = select('SELECT '.$column.' FROM '.$from.' WHERE '.$where); } else { $result = singleResultSelect('SELECT '.$column.' FROM '.$from.' WHERE '.$where); } if (!$result) { if (($from == "attributesDef") && $isFatal) $this->lastError = getMessage('attribute_not_found')." : ".$where; else $this->lastError = getMessage('not_found').'SELECT '.$column.' FROM '.$from.' WHERE '.$where; $this->notFound = true; if ($isFatal) $this->isError = true; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error').$result." : ".'SELECT '.$column.' FROM '.$from.' WHERE '.$where; if ($isFatal) $this->isError = true; return NULL; } else return $result; } // private function updateDB($toSet,$table="attributesDef", $where = "id") { if ($where == "id") $where .= "=".$this->id; if ($error = write("UPDATE ".$table." SET ".$toSet." WHERE id=".$this->id)) { $this->lastError = getMessage('db_write_error').$error." : "."UPDATE ".$table." SET ".$toSet." WHERE ".$where; return false; } else return true; } ////////////////////////////////////////////////////////////////// // Getters ////////////////////////////////////////////////////////////////// function getAttributeDefID() { return $this->def_id; } function getName() { return $this->name; } function getType() { return $this->type; } function getValue() { return NULL; } function getMask() { return $this->mask; } function getEditable() { return $this->editable; } // Use Lazy loading for selection function getSelection() { if (!is_array($this->selection) && ($this->type >= 1 || $this->editable)) { $dictionary = $this->getFromDB("value", "attributesdef_id=".$this->def_id." ORDER BY sortval,value", "attributesDefDict", true, true); if (is_null($dictionary)){ if($this->notFound) $this->lastError=null; return; } foreach ($dictionary as $value) { $this->selection[$value['value']] = false; } } return $this->selection; } function isError() { return $this->isError; } function lastError() { return $this->lastError; } function notFound() { return $this->NotFound; } ////////////////////////////////////////////////////////////////// // Setters ////////////////////////////////////////////////////////////////// function buildAttribute ($node,$value) { if ($this->type == 0) { if (!ereg($this->mask,$value)) { $this->lastError = getMessage('invalide_value').$this->name." = ".$value; return false; } } $insertQuery = "INSERT INTO Attributes (nodes_id,attributesdef_id,value)" . "VALUES (".$node->getID().",".$this->def_id.",'')"; if ($error = write($insertQuery)) { $this->lastError = getMessage('db_error').$error." : ".$insertQuery; return false; } if (!$result = $this->getFromDB("*","nodes_id=".$node->getID()." AND attributesdef_id=".$this->def_id,"attributes")) return false; $attr = new Attribute($result); if ($attr->isError()) { $this->lastError = $attr->lastError(); return false; } $attr->setValue($value); return $attr; } /** * This function delete a specific value from the dictionary table (attributesdefdict) */ function deleteDictValue($value) { $error = NULL; delete("DELETE FROM attributesdefdict WHERE attributesdef_id=".$this->def_id." AND value=".qstr($value).""); if ($error) $error.= " : "; $error .= delete("DELETE FROM attributesdefdict WHERE attributesdef_id=".$this->def_id." AND value=".qstr($value).""); return $error; } /** * This function insert a specific value to the dictionary table (attributesdefdict) */ function insertDictValue($value) { $error = NULL; //Validation of value if (!ereg($this->mask,$value)) { $this->lastError = getMessage('invalide_value').$this->name." = ".$value."(".$this->mask.")"; return $this->lastError; } if (!(strlen($value) > 0)) { $this->lastError = getMessage('error_creating_def').getMessage('empty_def_name'); return $this->lastError; } //sortval is not managed. New attribute list is always at last position //$result = singleResultSelect("SELECT MAX(sortval) as nextsortval FROM attributesdefdict WHERE attributesdef_id=".$this->def_id); //$sortval=1+$result['nextsortval']; $sortval=0; $insertQuery ="INSERT INTO attributesdefdict (attributesdef_id,value,sortval) VALUES (".$this->def_id.",".qstr($value).",".$sortval.")"; if ($error = write($insertQuery)) { $this->lastError = getMessage('db_error').$error." : ".$insertQuery; return $this->lastError; }else{ return null; } } /** * This function update the dictionary table (attributesdefdict) * $oldValue is one of the primary key */ function updateDictValue($value,$oldValue) { $error = NULL; //Validation of value if (!ereg($this->mask,$value)) { $this->lastError = getMessage('invalide_value').$this->name." = ".$value."(".$this->mask.")"; return $this->lastError; } if (!(strlen($value) > 0)) { $this->lastError = getMessage('error_creating_def').getMessage('empty_def_name'); return $this->lastError; } //sortval is not managed. New attribute list is always at last position $updateQuery ="UPDATE attributesdefdict SET value=".qstr($value)." WHERE attributesdef_id=".$this->def_id." AND value=".qstr($oldValue).""; if ($error = write($updateQuery)) { $this->lastError = getMessage('db_write_error').$error." : ".$updateQuery; return $this->lastError; }else{ return $this->lastError; } } } ?> ltsp-cluster-control-2.0.3/Admin/util/HWGroupManager.php0000664000175000017500000000752312026403127023411 0ustar stgraberstgraberisError = true; return; } if ($node->isError) { $this->isError = true; return; } $this->node = $node; $this->isError = false; $hg = new HWGroupRule($node->getID()); $this->operators = $hg->getOperators(); ///////////////////////// // Actions ///////////////////////// // Cancel if (isset($_POST['cancel'])||(!isset($_POST['delete_hwg'])&&!isset($_POST['add_hwg'])&&!isset($_POST['modify_hwg']))) { unset($GLOBALS['_POST']); $this->hwGroupRules = $node->getHwGroupsRules(); } // Add an hw Group Rule if (isset($_POST['add_hwg'])) { $this->hwGroupRules = $node->getHwGroupsRules(); $hwGroupRule = new HWGroupRule($node->getID(),$_POST['hwGroupKey'],$_POST['hwGroupValue'],$_POST['hwGroupOperator']); if(!$hwGroupRule->insertDB()){ $this->errors[]=$hwGroupRule->lastError; }else{ $this->hwGroupRules[] = $hwGroupRule; logAdminAccess(array("ADD HARDWARE GROUP RULE","NODE ID : ".$node->getID(),"NAME : ".$node->getName(),"RULE : ".$hwGroupRule->getHwKey().$hwGroupRule->getOperator().$hwGroupRule->getHwValue())); } unset($_POST['add_hwg']); } // Deleting hw Group Rule if (isset($_POST['delete_hwg'])) { if (is_array($_POST['selection'])) { foreach ($_POST['selection'] as $id) { $hgToDelete = new HWGroupRule($node->getID(),$_POST['key'.$id],$_POST['value'.$id],$_POST['operator'.$id]); if ($error = $hgToDelete->delete()) { $this->errors[] = $error; unset($error); }else{ $this->hwGroupRules = $node->getHwGroupsRules(); logAdminAccess(array("DELETE HARDWARE GROUP RULE","NODE ID : ".$node->getID(),"NAME : ".$node->getName(),"RULE : ".$hgToDelete->getHwKey().$hgToDelete->getOperator().$hgToDelete->getHwValue())); } } } unset($_POST['delete_hwg']); } // Modify attributes if (isset($_POST['modify_hwg'])) { foreach($_POST as $postKey => $postValue) { //get the input name (key*, value*, operator*) if(substr($postKey, 0, 3) == "key"){ $hwGroupToUpdate = new HWGroupRule($node->getID(),$_POST['key'.$postKey{3}],$_POST['value'.$postKey{3}],$_POST['operator'.$postKey{3}]); $list[] = $hwGroupToUpdate; } } $hg->updateList($list); if($hg->isError()){ $this->errors[] = $hg->lastError; }else{ logAdminAccess(array("MODIFY HARDWARE GROUP RULE","NODE ID : ".$node->getID(),"NAME : ".$node->getName())); } $this->hwGroupRules = $node->getHwGroupsRules(); unset($_POST['modify_hwg']); } } function isError() { return $this->isError; } function printErrors() { if (isset($this->errors[0])) print "

    \n"; else return; foreach ($this->errors as $error) { print "".$error."
    \n"; } print "

    \n"; } function printView() { if ($this->isError) { $this->printErrors(); return; } include 'HWGroupManagerView.php'; } } ?> ltsp-cluster-control-2.0.3/Admin/util/nodesMoveCmdView.php0000664000175000017500000000164012026403127023773 0ustar stgraberstgraber

    printErrors(); ?>
    ltsp-cluster-control-2.0.3/Admin/util/printersListManagerView.php0000664000175000017500000000730312026403127025407 0ustar stgraberstgraberprintErrors(); ?>

    printerServers)){ echo "
    "; foreach ($this->printerServers as $printerServer) { echo ""; echo "".$printerServer."
    "; }?> " />
    \n"; echo getMessage("printer_no_printer_server"); echo "

    \n"; } ?>
    $printerServer ){ ?>

    errors[ $server_name ] ) ){ ?>



    \n"; echo $this->errors[ $server_name ]; } echo "

    \n"; ?>

    ">

    0 ){ echo "

    \n"; echo getMessage('printer_warning_standalone'); echo "

    \n"; echo "
    "; echo ""; foreach( $_SESSION['ghost_printers'] as $printer ){ echo ""; } echo "
    "; echo ""; echo $printer; echo "
    "; echo ""; echo ""; echo "
    "; } else { echo "

    \n"; echo getMessage("printer_no_printer_standalone"); echo "

    \n"; } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/0000775000175000017500000000000012026403130022227 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/print_report.php0000664000175000017500000000734412026403127025505 0ustar stgraberstgraberclose(); } // Shows the childs of a node if( isset( $_GET['open'] ) ){ $tree[ $_GET['open'] ]->open(); } printRapport( $tree[0] ); if( $shown_nodes == 0 ){ echo getMessage('stats_no_node'); } function printRapport( $node ){ global $valid_nodes, $shown_nodes; // if a node isn't checked, don't show it. if( $node->status > 0 ){ $shown_nodes ++; global $tree, $shown_page; $conditions = $_SESSION['conditions']; $useHeritage = $_SESSION['useHeritage']; $config_info = $node->attributes[ "config" ]; $hardware_info = $node->attributes[ "hardware" ]; $network_info = $node->attributes[ "network" ]; $showHR = false; // The CSS is different if the node is a Context or a Terminal if( $node->type == 0 ){ $css = "context"; } else { $css = "terminal"; } $title = getNodeFullPath( $node ); echo "
    "; echo ""; echo "id."'"; } echo ">-"; echo ""; echo "".$node->toString().""; echo ""; if( $node->is_opened ){ echo "
    "; echo ""; echo getMessage('stats_attribute'); echo ""; // if a Node has a Status of 2, show it's informations if( ( count( $config_info ) + count( $hardware_info ) + count( $network_info ) ) == 0 ){ echo getMessage('stats_report_no_attr'); } else if( $node->status == 2 && in_array( $title."/".$node->toString(), $valid_nodes ) ){ if( count( $config_info ) > 0 ){ $showHR = true; foreach( $config_info as $nom => $config ){ echo $nom." : ".$config."
    "; } } // We only test Terminals for those Attributes if( $node->type == 1 ){ if( count( $hardware_info ) > 0 ){ if( $showHR ){ echo "
    "; $showHR = false; } $showHR = true; foreach( $hardware_info as $nom => $hardware ){ echo $nom." : ".$hardware."
    "; } } if( count( $network_info ) > 0 ){ if( $showHR ){ echo "
    "; $showHR = false; } foreach( $network_info as $nom => $network ){ echo $nom." : ".$network."
    "; } } } } else { echo getMessage('stats_report_err_cond'); } echo "
    "; $childs = $node->returnChild( $tree ); for( $i = 0; $i < count( $childs ); $i++ ){ printRapport( $tree[ $childs[ $i ] ] ); } } echo "
    "; } } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/node_chooser.php0000664000175000017500000001202312026403127025413 0ustar stgraberstgraberis_opened ){ $tree[ $index ]->open(); } } // Hides the childs of a node if( isset( $_GET['close'] ) ){ $index = $_GET['close']; if( $tree[ $index ]->is_opened ){ $tree[ $index ]->close(); } } // Checks a node and all it's childs + verifies the status of the parents if( isset( $_GET['check'] ) ){ $index = $_GET['check']; if( !$tree[ $index ]->is_checked() ){ checkChild($index); changeParentStatus($index); } } // Unchecks a node and all it's childs + verifies the status of the parents if( isset( $_GET['uncheck'] ) ){ $index = $_GET['uncheck']; if( $tree[ $index ]->is_checked() ){ uncheckChild($index); changeParentStatus($index); } } // Node_Kind is for the end of the Request, only this kind of node's information will be shown // 0 = Contexts, 1 = Terminals, 2 = All if( isset( $_GET['node_kind'] ) ){ $_SESSION['node_kind'] = $_GET['node_kind']; } // Puts every child (and grand-childs) of an ID to checked function checkChild( $id ){ global $tree; if( !$tree[ $id ]->is_checked() ){ $tree[ $id ]->status = 2; $childs = $tree[ $id ]->returnChild( $tree ); for( $i = 0; $i < count( $childs ); $i++){ checkChild( $tree[ $childs[$i] ]->id ); } } } // Puts every child (and grand-childs) of an ID to unchecked function uncheckChild( $id ){ global $tree; if( $tree[ $id ]->is_checked() ){ $tree[ $id ]->status = 0; $childs = $tree[ $id ]->returnChild( $tree ); for( $i = 0; $i < count( $childs ); $i++){ uncheckChild( $tree[ $childs[$i] ]->id ); } } } // Verifies the childs of a node to change its status accordingly // Statuses : 0 unchecked or no sons checked / 1 checked or some sons checked / 2 checked and all sons checked function changeParentStatus( $id ){ global $tree; $id_parent = $tree[ $id ]->id_parent; $childs = $tree[ $id_parent]->returnChild( $tree ); $nb_checked = 0; for( $i = 0; $i < count( $childs ); $i++ ){ $nb_checked += $tree[ $childs[$i] ]->status; } // Because this tests only parent-nodes, it is sure that it has childs if( $nb_checked == 0 ){ // All childs Statuses are at 0 $tree[ $id_parent ]->status = 0; } else if( $nb_checked == count( $childs ) * 2 ){ // All childs Statuses are at 2 $tree[ $id_parent ]->status = 2; } else { $tree[ $id_parent ]->status = 1; } // Don't roll around Root (who points itself) if( $id_parent <> $id ){ changeParentStatus( $id_parent ); } } // Prints the info of the ID, looks if it has childs, if it does, prints them recursively function printTree( $id ){ global $tree; global $shown_page; $node = $tree[ $id ]; $childs = $node->returnChild( $tree ); $mode = $_SESSION['node_kind']; // Open is the ± sign, Check is the check box $showOpen = $showCheck = true; // Mode 1 : Terminals only if( $mode == 1 && $node->type == 0 && count( $childs ) == 0 ){ $showCheck = false; // Mode 2 : Contexts only } else if( $mode == 0 && $node->type == 1 ) { $showCheck = false; } if( count( $childs ) == 0 ){ $showOpen = false; } echo "
    • "; if( $showOpen ){ echo "-"; } if( $node->type == 0 ){ echo "".$node->toString().""; } else { echo $node->toString(); } if( $showCheck ){ echo ""; if( is_int( $node->status ) ){ echo ""; echo ""; } if( $node->is_opened ){ for( $i = 0; $i < count( $childs ); $i++ ){ printTree( $childs[ $i ] ); } } echo "
    "; } $_SESSION['tree'] = $tree; ?> Step 1
    ltsp-cluster-control-2.0.3/Admin/util/statistics/validate_condition.php0000664000175000017500000000653112026403127026612 0ustar stgraberstgraberis_checked() && validate( $node ) ){ $valid_nodes[] = getNodeFullPath( $node )."/".$node->toString(); } $childs = $node->returnChild( $tree ); foreach( $childs as $child ){ validate_condition( $child ); } } // This fonctions Compares the Node's Value with the Condition's Value with El Comparator chosen at the Condition_Chooser Screen // the default is "=" function compareConditions( $comparator, $valueNode, $valueCond ){ $retour = false; switch ($comparator){ case "!=" : $retour = $valueNode != $valueCond; break; case "<" : $retour = $valueNode < $valueCond; break; case "<=" : $retour = $valueNode <= $valueCond; break; case ">" : $retour = $valueNode > $valueCond; break; case ">=" : $retour = $valueNode >= $valueCond; break; default : $retour = $valueNode == $valueCond; break; } return $retour; } function validate( $node ){ $conditions = $_SESSION['conditions']; global $conform_cond; $nb_condition_valid = 0; foreach( $conditions as $condition ){ // All conditions must be true but some values in a condition can be true // Condition => Logical AND // Value => Logical OR $value_valid = false; if( !isset( $conform_cond[ $condition->name ] ) ){ $conform_cond[ $condition->name ] = array(); } for( $i = 0; $i < count( $condition->value ); $i++ ){ $value = $condition->value[$i]; switch ($condition->category){ case 0 : $sql = "Select attributes.value From attributesdef, attributes Where attributesdef.name = '".$condition->name."' AND attributes.Nodes_ID = '".$node->id."' AND attributesdef.ID = attributes.AttributesDef_ID"; break; case 1 : $sql = "Select HwValue From computershw Where HwKey = '".$condition->name."' AND Nodes_ID = '".$node->id."'"; break; case 2 : $sql = "Select ".$condition->name." From status Where id = '".$node->id."'"; break; } $query = pg_query( $sql ); // If the query returns any information, look if it's valid if( pg_num_rows( $query ) > 0 ){ $row = pg_fetch_row( $query ); if( compareConditions( $condition->comparator[$i], $row[0], $value ) ){ $value_valid = true; $conform_cond[ $condition->name ][] = $node->id; } // Else, if we're using Heritage, look at the parent to know if the child is valid } else { if( in_array( $node->id_parent, $conform_cond[ $condition->name ] ) && $_SESSION['useHeritage'] ){ $value_valid = true; $conform_cond[ $condition->name ][] = $node->id; } } } // Each values if( $value_valid ){ $nb_condition_valid++; } } // Each conditions if( $nb_condition_valid == count( $conditions ) ){ $is_valid = true; } else { $is_valid = false; } return $is_valid; } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/validate_node.php0000664000175000017500000000171612026403127025551 0ustar stgraberstgraberclearAttributes(); if( $node->is_checked() ){ $node->open(); // If the users chose to show only Contexts and the node isn't a context, don't show it if( $_SESSION['node_kind'] == 0 AND $node->type <> 0 ){ $node->status = 0; // If the user chose to show only Nodes and the node isn't a node, show it but without informations } else if ( $_SESSION['node_kind'] == 1 AND $node->type <> 1 ){ $node->status = 1; // Else, show the node } else { $node->status = 2; } } $new_tree[ $node->id ] = $node; } $_SESSION['tree'] = $new_tree; ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/functions/0000775000175000017500000000000012026403130024237 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/returnList.php0000664000175000017500000000110112026403127027122 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/isList.php0000664000175000017500000000112212026403127026221 0ustar stgraberstgraber'Y' AND value<>'N' GROUP BY name"; $result = pg_query($query) or die('Échec requête : ' . pg_last_error()); if( pg_num_rows( $result ) > 0 ){ $retour = true; } return $retour; } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/functions/returnCategory.php0000664000175000017500000000107712026403127030000 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/isYesNo.php0000664000175000017500000000121012026403127026341 0ustar stgraberstgraber 0 ){ $retour = true; } return $retour; } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/functions/returnType.php0000664000175000017500000000115412026403127027140 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/add_new_condition.php0000664000175000017500000000124512026403127030427 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/add_new_condition_value.php0000664000175000017500000000136512026403127031626 0ustar stgraberstgrabervalue ) ){ $conditions[ $condition ]->value[] = $value; $conditions[ $condition ]->comparator[] = $comparator; } } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/functions/connect.php0000664000175000017500000000117712026403127026415 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/getNodeFullPath.php0000664000175000017500000000103512026403127030002 0ustar stgraberstgraberid_parent; do{ $node = $tree[ $next_id ]; $retour = "/".$node->toString().$retour; $next_id = $node->id_parent; }while( $node->id <> $next_id ); return htmlentities( $retour, ENT_QUOTES ); } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/functions/isMat.php0000664000175000017500000000101012026403127026023 0ustar stgraberstgraber 0 ){ $retour = true; } return $retour; } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/functions/returnID.php0000664000175000017500000000115112026403127026510 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/isConf.php0000664000175000017500000000101112026403127026170 0ustar stgraberstgraber 0 ){ $retour = true; } return $retour; } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/functions/conditionIsSelected.php0000664000175000017500000000107212026403127030711 0ustar stgraberstgrabername ){ $retour = true; } } return $retour; } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/functions/isChecked.php0000664000175000017500000000066212026403127026644 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/set_new_session.php0000664000175000017500000000115712026403127030171 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/functions/create_nodes.php0000664000175000017500000000157512026403127027421 0ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/validate_attribute.php0000664000175000017500000000666112026403127026633 0ustar stgraberstgraberid_parent; if( $id_parent <> $node->id && isset( $tree[ $id_parent ]->attributes[ "config" ][ $config_name ] ) ){ $value = $tree[ $id_parent ]->attributes[ "config" ][ $config_name ]; if( $value <> "" ){ $retour = $value; } } return $retour; } function validate_attribute( $node_id ){ global $tree, $configInfo, $hardwareInfo, $networkInfo; $useHeritage = $_SESSION['useHeritage']; $node = $tree[ $node_id ]; $node->clearAttributes(); if( $node->is_checked() ){ foreach( $configInfo as $config ){ $sql = "Select Value From attributesdef, attributes Where attributesdef.Name = '".$config."' AND attributes.Nodes_ID = '".$node->id."' AND attributesdef.ID = attributes.AttributesDef_ID"; $query = pg_query( $sql ); if( pg_num_rows( $query ) > 0 ){ $row = pg_fetch_row( $query ); $value = $row[0]; } else { if( $useHeritage ){ $value = getParentsConfig( $config, $node ); } else { $value = "---"; } } $node->attributes["config"][ $config ] = $value; } foreach( $hardwareInfo as $hardware ){ if( !isset( $node->attributes["hardware"][ $hardware ] ) ){ $sql = "Select HwValue From computershw Where HwKey = '".$hardware."' AND Nodes_ID = '".$node->id."'"; $query = pg_query( $sql ); if( $row = pg_fetch_row( $query ) ){ $value = $row[0]; } else { if( $useHeritage ){ $value = getParentsConfig( $hardware, $node->id ); } else { $value = "---"; } } $node->attributes["hardware"][ $hardware ] = $value; } } foreach( $networkInfo as $network ){ if( !isset( $node->attributes["network"][ $network ] ) ){ $sql = "Select ".$network." From status Where id = '".$node->id."'"; $query = pg_query( $sql ); if( $row = pg_fetch_row( $query ) ){ $value = $row[0]; } else { if( $useHeritage ){ $value = getParentsConfig( $network, $node->id ); } else { $value = "---"; } } $node->attributes[ "network" ][ $network ] = $value; } } $tree[ $node_id ] = $node; $childs = $node->returnChild( $tree ); foreach( $childs as $child_id ){ validate_attribute( $child_id ); } } } validate_attribute( 0 ); $_SESSION['tree'] = $tree; ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/images/0000775000175000017500000000000012026403130023474 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/images/delete.gif0000664000175000017500000000155612026403127025442 0ustar stgraberstgraberGIF87a÷€€€€€€€€€ÀÀÀÀÜÀ¦Êð333333""")))UUUMMMBBB999ÿ|€ÿPPÖ“ÌìÿïÖÆççÖ­©3ÿf™Ì333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌfÿ™ÿÌÿÿ33ÿf3™3Ì3ÿ33ÿ333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌff™f3™ff™f™™fÌ™fÿ™fÌf3Ìf™ÌfÌÌfÿÌfÿf3ÿf™ÿfÌÿfÿÌÌÿ™™™3™™™Ì™™33™f™Ì3™ÿ™f™3f™f3™™f™Ìf™ÿ3™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌf™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÌ™™ÿ™Ìÿ™ÿÿ™Ì3™fÌ™ÌÌÌ3™33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌff™™fÌÌfÌÿf™™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿ™™ÿÌÌÿÌÿÿÌ3Ìfÿ™ÿ3Ì33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÌ™fÿÌfÿÿfÌ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿ3ÿÿfÿÌ™ÿÿÌÿÿÿfffÿfÿÿfffÿÿfÿfÿÿ¥!___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ!ù,@KH°à?^X !/v6L¸!D‡^̘q#E†#òªøÑâ¿“(SªÉ1¡Ç‘I>d)ãK’2_¶œÉ®§ÏŸ?;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/terminal.gif0000664000175000017500000000020712026403127026003 0ustar stgraberstgraberGIF89aÂÿÿÿÿÿÆÆÆ„„„ÿ„ÿÿÿ!ù,LxªÓÞ+A«&žº¿˜Æ$ fPD{Šjë6è2ÊÄ›ZÙ† 08©Mx½‹Ñàc:i ƒ@J^ Ö㘿AnMÃБ%AE;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/plus.gif0000664000175000017500000000112212026403127025150 0ustar stgraberstgraberGIF89aÆ^ÖÖÖãããÆÆÆûûûàààáááØØØîîîÙÙÙñññâââúúúÀÀÀíííðððäääÞÞÞËËËÝÝÝóóóÌÌÌ———||| ÂÂÂÜÜܳ³³ýýýÑÑѨ¨¨ùùùøøø÷÷÷öööõõõçççéééôôôÕÕÕëëë»»»ïïïÒÒÒþþþaaasssòòòƒƒƒJJJ{{{›››¸¸¸×××’’’ßßß$$$¼¼¼\\\¯¯¯zzzÊÊÊêêꢢ¢ååå¹¹¹oooCCC***ÏÏÏÅÅŬ¬¬cccˆˆˆ···´´´±±± %%% –––¿¿¿„„„¥¥¥®®®ÎÎÎ333ÿÿÿÇÇÇÚÚÚÔÔÔppp###ÓÓÓ°°°ºººÛÛÛèèèÄÄÄæææÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ù,¯€‚ƒ„……   †‚ % /"#*…hk k`&kjƒK ("H5%Z‚Vj !2UY ih)jgjG1NJERe)?7WF0T3O@_Xjj8;cfCIb'LhP.S=6[<ì:.´8Mƒ$< @ G  RHÁšhVPð`M£?$ÒICâ£ÉA;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/images/0000775000175000017500000000000012026403130024741 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/images/images/delete.gif0000664000175000017500000000155612026403127026707 0ustar stgraberstgraberGIF87a÷€€€€€€€€€ÀÀÀÀÜÀ¦Êð333333""")))UUUMMMBBB999ÿ|€ÿPPÖ“ÌìÿïÖÆççÖ­©3ÿf™Ì333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌfÿ™ÿÌÿÿ33ÿf3™3Ì3ÿ33ÿ333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌff™f3™ff™f™™fÌ™fÿ™fÌf3Ìf™ÌfÌÌfÿÌfÿf3ÿf™ÿfÌÿfÿÌÌÿ™™™3™™™Ì™™33™f™Ì3™ÿ™f™3f™f3™™f™Ìf™ÿ3™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌf™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÌ™™ÿ™Ìÿ™ÿÿ™Ì3™fÌ™ÌÌÌ3™33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌff™™fÌÌfÌÿf™™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿ™™ÿÌÌÿÌÿÿÌ3Ìfÿ™ÿ3Ì33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÌ™fÿÌfÿÿfÌ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿ3ÿÿfÿÌ™ÿÿÌÿÿÿfffÿfÿÿfffÿÿfÿfÿÿ¥!___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ!ù,@KH°à?^X !/v6L¸!D‡^̘q#E†#òªøÑâ¿“(SªÉ1¡Ç‘I>d)ãK’2_¶œÉ®§ÏŸ?;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/images/terminal.gif0000664000175000017500000000020712026403127027250 0ustar stgraberstgraberGIF89aÂÿÿÿÿÿÆÆÆ„„„ÿ„ÿÿÿ!ù,LxªÓÞ+A«&žº¿˜Æ$ fPD{Šjë6è2ÊÄ›ZÙ† 08©Mx½‹Ñàc:i ƒ@J^ Ö㘿AnMÃБ%AE;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/images/plus.gif0000664000175000017500000000112212026403127026415 0ustar stgraberstgraberGIF89aÆ^ÖÖÖãããÆÆÆûûûàààáááØØØîîîÙÙÙñññâââúúúÀÀÀíííðððäääÞÞÞËËËÝÝÝóóóÌÌÌ———||| ÂÂÂÜÜܳ³³ýýýÑÑѨ¨¨ùùùøøø÷÷÷öööõõõçççéééôôôÕÕÕëëë»»»ïïïÒÒÒþþþaaasssòòòƒƒƒJJJ{{{›››¸¸¸×××’’’ßßß$$$¼¼¼\\\¯¯¯zzzÊÊÊêêꢢ¢ååå¹¹¹oooCCC***ÏÏÏÅÅŬ¬¬cccˆˆˆ···´´´±±± %%% –––¿¿¿„„„¥¥¥®®®ÎÎÎ333ÿÿÿÇÇÇÚÚÚÔÔÔppp###ÓÓÓ°°°ºººÛÛÛèèèÄÄÄæææÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ù,¯€‚ƒ„……   †‚ % /"#*…hk k`&kjƒK ("H5%Z‚Vj !2UY ih)jgjG1NJERe)?7WF0T3O@_Xjj8;cfCIb'LhP.S=6[<ì:.´8Mƒ$< @ G  RHÁšhVPð`M£?$ÒICâ£ÉA;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/images/check2.gif0000664000175000017500000000152012026403127026573 0ustar stgraberstgraberGIF89a ÷€€€€€€€€€ÀÀÀÀÜÀ¦Êð333333""")))UUUMMMBBB999ÿ|€ÿPPÖ“ÌìÿïÖÆççÖ­©3ÿf™Ì333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌfÿ™ÿÌÿÿ33ÿf3™3Ì3ÿ33ÿ333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌff™f3™ff™f™™fÌ™fÿ™fÌf3Ìf™ÌfÌÌfÿÌfÿf3ÿf™ÿfÌÿfÿÌÌÿ™™™3™™™Ì™™33™f™Ì3™ÿ™f™3f™f3™™f™Ìf™ÿ3™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌf™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÌ™™ÿ™Ìÿ™ÿÿ™Ì3™fÌ™ÌÌÌ3™33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌff™™fÌÌfÌÿf™™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿ™™ÿÌÌÿÌÿÿÌ3Ìfÿ™ÿ3Ì33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÌ™fÿÌfÿÿfÌ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿ3ÿÿfÿÌ™ÿÿÌÿÿÿfffÿfÿÿfffÿÿfÿfÿÿ¥!___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ, 5H࿃þ¨!C† !BT(@D‹':ĸÐâDŽ;zùQcÈŒ&M^,È@@;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/images/check1.gif0000664000175000017500000000152712026403127026601 0ustar stgraberstgraberGIF89a ÷€€€€€€€€€ÀÀÀÀÜÀ¦Êð333333""")))UUUMMMBBB999ÿ|€ÿPPÖ“ÌìÿïÖÆççÖ­©3ÿf™Ì333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌfÿ™ÿÌÿÿ33ÿf3™3Ì3ÿ33ÿ333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌff™f3™ff™f™™fÌ™fÿ™fÌf3Ìf™ÌfÌÌfÿÌfÿf3ÿf™ÿfÌÿfÿÌÌÿ™™™3™™™Ì™™33™f™Ì3™ÿ™f™3f™f3™™f™Ìf™ÿ3™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌf™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÌ™™ÿ™Ìÿ™ÿÿ™Ì3™fÌ™ÌÌÌ3™33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌff™™fÌÌfÌÿf™™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿ™™ÿÌÌÿÌÿÿÌ3Ìfÿ™ÿ3Ì33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÌ™fÿÌfÿÿfÌ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿ3ÿÿfÿÌ™ÿÿÌÿÿÿfffÿfÿÿfffÿÿfÿfÿÿ¥!___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ, <Hàƒ¨!>| 4<ðð Æ#b„hQ¢ÂŒArìH±"HŽ$™ò$ʉ Ê;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/images/check0.gif0000664000175000017500000000151012026403127026570 0ustar stgraberstgraberGIF89a ÷€€€€€€€€€ÀÀÀÀÜÀ¦Êð333333""")))UUUMMMBBB999ÿ|€ÿPPÖ“ÌìÿïÖÆççÖ­©3ÿf™Ì333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌfÿ™ÿÌÿÿ33ÿf3™3Ì3ÿ33ÿ333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌff™f3™ff™f™™fÌ™fÿ™fÌf3Ìf™ÌfÌÌfÿÌfÿf3ÿf™ÿfÌÿfÿÌÌÿ™™™3™™™Ì™™33™f™Ì3™ÿ™f™3f™f3™™f™Ìf™ÿ3™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌf™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÌ™™ÿ™Ìÿ™ÿÿ™Ì3™fÌ™ÌÌÌ3™33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌff™™fÌÌfÌÿf™™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿ™™ÿÌÌÿÌÿÿÌ3Ìfÿ™ÿ3Ì33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÌ™fÿÌfÿÿfÌ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿ3ÿÿfÿÌ™ÿÿÌÿÿÿfffÿfÿÿfffÿÿfÿfÿÿ¥!___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ, -H࿃þ¨°!Æ B<(qbEˆ˜ˆ0£B7r\X°¤À€;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/images/context.gif0000664000175000017500000000157112026403127027126 0ustar stgraberstgraberGIF89a瀀€€€€€€€ÀÀÀÀÜÀ¦Êð*UªÔ****U**ª*ÔUU*UUUUªUÔ*UªÔªª*ªUªªªªÔÔÔ*ÔUÔÔªÔÔ****U**ª*Ô*******U****ª**Ô*U*U**UU*U*Uª*UÔ****U**ª*Ô*ª*ª**ªU*ª*ªª*ªÔ*Ô*Ô**ÔU*Ô*Ôª*ÔÔUU*UUUUªUÔU*U**U*UU*U*ªU*ÔUUUU*UUUUUUUªUUÔUU*UUUUªUÔUªUª*UªUUªUªªUªÔUÔUÔ*UÔUUÔUÔªUÔÔ*UªÔ****U**ª*ÔUU*UUUUªUÔ*UªÔªª*ªUªªªªÔÔÔ*ÔUÔÔªÔÔªª*ªUªªªªÔª*ª**ª*Uª*ª*ªª*ÔªUªU*ªUUªUªUªªUÔªª*ªUªªªªÔªªªª*ªªUªªªªªªªÔªÔªÔ*ªÔUªÔªÔªªÔÔÔÔ*ÔUÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ùÿ,Vÿ HP €ƒ *ü ˜C "lø0"Dƒƒ]T¸qâÆ‚ zØÑãž“If][[Z8ƒJ0XZZHS=‚ ]]^ ^XR‚6<):3++VW15 &‚IP,F,924L.%‚*-'##)NA?O@ Þ%B""E ]^ƒX G ¸Ü#Ä% ‚*º@(`À ‚B¾x™€`‚—,Y}Ù¸‘ÇA;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/check2.gif0000664000175000017500000000152012026403127025326 0ustar stgraberstgraberGIF89a ÷€€€€€€€€€ÀÀÀÀÜÀ¦Êð333333""")))UUUMMMBBB999ÿ|€ÿPPÖ“ÌìÿïÖÆççÖ­©3ÿf™Ì333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌfÿ™ÿÌÿÿ33ÿf3™3Ì3ÿ33ÿ333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌff™f3™ff™f™™fÌ™fÿ™fÌf3Ìf™ÌfÌÌfÿÌfÿf3ÿf™ÿfÌÿfÿÌÌÿ™™™3™™™Ì™™33™f™Ì3™ÿ™f™3f™f3™™f™Ìf™ÿ3™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌf™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÌ™™ÿ™Ìÿ™ÿÿ™Ì3™fÌ™ÌÌÌ3™33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌff™™fÌÌfÌÿf™™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿ™™ÿÌÌÿÌÿÿÌ3Ìfÿ™ÿ3Ì33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÌ™fÿÌfÿÿfÌ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿ3ÿÿfÿÌ™ÿÿÌÿÿÿfffÿfÿÿfffÿÿfÿfÿÿ¥!___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ, 5H࿃þ¨!C† !BT(@D‹':ĸÐâDŽ;zùQcÈŒ&M^,È@@;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/check1.gif0000664000175000017500000000152712026403127025334 0ustar stgraberstgraberGIF89a ÷€€€€€€€€€ÀÀÀÀÜÀ¦Êð333333""")))UUUMMMBBB999ÿ|€ÿPPÖ“ÌìÿïÖÆççÖ­©3ÿf™Ì333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌfÿ™ÿÌÿÿ33ÿf3™3Ì3ÿ33ÿ333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌff™f3™ff™f™™fÌ™fÿ™fÌf3Ìf™ÌfÌÌfÿÌfÿf3ÿf™ÿfÌÿfÿÌÌÿ™™™3™™™Ì™™33™f™Ì3™ÿ™f™3f™f3™™f™Ìf™ÿ3™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌf™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÌ™™ÿ™Ìÿ™ÿÿ™Ì3™fÌ™ÌÌÌ3™33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌff™™fÌÌfÌÿf™™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿ™™ÿÌÌÿÌÿÿÌ3Ìfÿ™ÿ3Ì33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÌ™fÿÌfÿÿfÌ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿ3ÿÿfÿÌ™ÿÿÌÿÿÿfffÿfÿÿfffÿÿfÿfÿÿ¥!___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ, <Hàƒ¨!>| 4<ðð Æ#b„hQ¢ÂŒArìH±"HŽ$™ò$ʉ Ê;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/check0.gif0000664000175000017500000000151012026403127025323 0ustar stgraberstgraberGIF89a ÷€€€€€€€€€ÀÀÀÀÜÀ¦Êð333333""")))UUUMMMBBB999ÿ|€ÿPPÖ“ÌìÿïÖÆççÖ­©3ÿf™Ì333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌfÿ™ÿÌÿÿ33ÿf3™3Ì3ÿ33ÿ333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌff™f3™ff™f™™fÌ™fÿ™fÌf3Ìf™ÌfÌÌfÿÌfÿf3ÿf™ÿfÌÿfÿÌÌÿ™™™3™™™Ì™™33™f™Ì3™ÿ™f™3f™f3™™f™Ìf™ÿ3™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌf™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÌ™™ÿ™Ìÿ™ÿÿ™Ì3™fÌ™ÌÌÌ3™33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌff™™fÌÌfÌÿf™™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿ™™ÿÌÌÿÌÿÿÌ3Ìfÿ™ÿ3Ì33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÌ™fÿÌfÿÿfÌ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿ3ÿÿfÿÌ™ÿÿÌÿÿÿfffÿfÿÿfffÿÿfÿfÿÿ¥!___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøÿûð  ¤€€€ÿÿÿÿÿÿÿÿÿÿÿÿ, -H࿃þ¨°!Æ B<(qbEˆ˜ˆ0£B7r\X°¤À€;ltsp-cluster-control-2.0.3/Admin/util/statistics/images/context.gif0000664000175000017500000000157112026403127025661 0ustar stgraberstgraberGIF89a瀀€€€€€€€ÀÀÀÀÜÀ¦Êð*UªÔ****U**ª*ÔUU*UUUUªUÔ*UªÔªª*ªUªªªªÔÔÔ*ÔUÔÔªÔÔ****U**ª*Ô*******U****ª**Ô*U*U**UU*U*Uª*UÔ****U**ª*Ô*ª*ª**ªU*ª*ªª*ªÔ*Ô*Ô**ÔU*Ô*Ôª*ÔÔUU*UUUUªUÔU*U**U*UU*U*ªU*ÔUUUU*UUUUUUUªUUÔUU*UUUUªUÔUªUª*UªUUªUªªUªÔUÔUÔ*UÔUUÔUÔªUÔÔ*UªÔ****U**ª*ÔUU*UUUUªUÔ*UªÔªª*ªUªªªªÔÔÔ*ÔUÔÔªÔÔªª*ªUªªªªÔª*ª**ª*Uª*ª*ªª*ÔªUªU*ªUUªUªUªªUÔªª*ªUªªªªÔªªªª*ªªUªªªªªªªÔªÔªÔ*ªÔUªÔªÔªªÔÔÔÔ*ÔUÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ùÿ,Vÿ HP €ƒ *ü ˜C "lø0"Dƒƒ]T¸qâÆ‚ zØÑãž“If][[Z8ƒJ0XZZHS=‚ ]]^ ^XR‚6<):3++VW15 &‚IP,F,924L.%‚*-'##)NA?O@ Þ%B""E ]^ƒX G ¸Ü#Ä% ‚*º@(`À ‚B¾x™€`‚—,Y}Ù¸‘ÇA;ltsp-cluster-control-2.0.3/Admin/util/statistics/footer_selection.php0000664000175000017500000000323712026403127026316 0ustar stgraberstgraber
    ' />
    ' />
    ltsp-cluster-control-2.0.3/Admin/util/statistics/style.css0000664000175000017500000000214512026403127024111 0ustar stgraberstgraber/* This is the Cascading Style Sheet of the Statistics Module from the Mille Project */ body { padding : 0px; margin : 0px; } .terminal-rapport { background-color : #B0C4DE; } .terminal-rapport-infos { background-color : #5793C5; } .context-rapport { background-color : #778899; color : #000000; font-weight : bold; } .context-rapport-infos { background-color : #5793C5; } legend.titre-attribut-rapport { font-size : 12px; background-color : darkgrey; } legend.titre-terminal-rapport { font-size : 14px; } legend { font-size : 12px; } fieldset { font-size : 10px; -moz-border-radius : 15px; } img { border : 0px; margin-left : 7px; margin-right : 7px; } span { color : #006666; text-decoration : none; font-weight : normal; } li { list-style-type : none; } div.footer-space { color : green; position: fixed; background-color : white; bottom : 0px; width : 100%; height : 25px; border-top : 5px solid grey } table { empty-cells : show; white-space : nowrap; } td { text-align: center; } #BTN_submit { position : absolute; right : 5px; } .and-or-MSG { font-size : smaller; }ltsp-cluster-control-2.0.3/Admin/util/statistics/attribute_chooser.php0000664000175000017500000000676312026403127026507 0ustar stgraberstgraber Step 2
    \n"; } echo "\n"; if( $k % 2 != 0 ){ echo "\n"; } $k++; } ?>
    ".$lineconf[0]."
    \n"; } ?>
    ".$linemat[0]."
    \n"; } ?>
    ".pg_field_name($resultres,$j)."
    ltsp-cluster-control-2.0.3/Admin/util/statistics/condition_chooser.php0000664000175000017500000001640512026403127026464 0ustar stgraberstgraber "" && isset( $_POST['condition'] ) <> "" ){ add_new_condition_value( $_POST['addVal'], $_POST['scallable'], $_POST['condition'] ); } // Remove a Condition if( isset( $_GET['delCond'] ) ){ $id_cond = $_GET['delCond']; $tmpTab = array(); foreach( $conditions as $condition ){ if( $id_cond <> $condition->name ){ $tmpTab[$condition->name] = $condition; } } $conditions = $tmpTab; } // Remove a value from a condition if( isset( $_GET['delVal'] ) && isset( $_GET['condition'] ) ){ $condition = $_GET['condition']; $value = $_GET['delVal']; $condition_value = $conditions[$condition]->value; $condition_comp = $conditions[$condition]->comparator; $valueTab = array(); $compTab = array(); for( $i = 0; $i < count( $condition_value ); $i++ ){ if( $value <> $i ){ $valueTab[] = $condition_value[ $i ]; $compTab[] = $condition_comp[ $i ]; } } $conditions[$condition]->value = $valueTab; $conditions[$condition]->comparator = $compTab; } unset( $_GET ); unset( $_POST ); // Fetch all the values on the DB $queryconf="SELECT name FROM attributesdef GROUP BY name ORDER BY name"; $resultconf = pg_query($queryconf) or die('Échec requête : ' . pg_last_error()); $querymat="SELECT hwkey FROM computershw GROUP BY hwkey ORDER BY hwkey"; $resultmat = pg_query($querymat) or die('Échec requête : ' . pg_last_error()); $queryres="SELECT * FROM status WHERE id=1"; $resultres = pg_query($queryres) or die('Échec requête : ' . pg_last_error()); echo ""; echo ""; echo ""; echo "Step 3"; echo ""; echo ""; echo ""; echo ""; echo getMessage('stats_true_conditions'); // Print the drop-down box with all those values echo "
    \n"; echo "\n"; echo "\n"; echo "
    "; // Print all the Conditions $first_condition = true; if (is_array($conditions)) { foreach( $conditions as $condition ){ $condition_name = $condition->name; $options = array(); if( $first_condition ){ $first_condition = false; } else { echo "
    ".getMessage('stats_and')."
    "; } echo "
    "; echo ""; echo $condition_name." "; echo ""; echo ""; echo ""; echo ""; // Print the form elements to change the Condition's value echo "
    "; echo "\n"; if( $condition->type == 0 ){ echo ""; } else { echo "\n"; } echo ""; echo ""; echo "
    "; // Print the values of the conditions if( $condition->value <> array() && $condition->value <> "" ){ echo "

    ".getMessage('stats_selected_value')."

    "; for( $j = 0; $j < count( $condition->value ); $j++ ){ if( $j > 0 ){ echo "
    ".getMessage('stats_or')."
    "; } $value = $condition->value[$j]; $comparator = $condition->comparator[$j]; if( $value == "Y" ){ $value = getMessage('stats_yes'); }else if( $value == "N" ){ $value = getMessage('stats_no'); } echo $condition_name." ".$comparator." ".$value." "; echo ""; echo ""; echo ""; } } echo "
    "; } } $_SESSION['conditions'] = $conditions; echo ""; echo ""; ?> ltsp-cluster-control-2.0.3/Admin/util/statistics/selection.html0000664000175000017500000000041012026403127025103 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Admin/util/statistics/header.php0000664000175000017500000000137112026403127024200 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Admin/util/statistics/index.php0000664000175000017500000000302512026403127024055 0ustar stgraberstgraber Configurateur ltsp-cluster-control-2.0.3/Admin/util/statistics/print_table.php0000664000175000017500000000406312026403127025254 0ustar stgraberstgraber"; echo "".getMessage('stats_node').""; echo "".getMessage('stats_path').""; if( count( $config_info ) > 0 ){ echo "".getMessage('stats_configuration').""; } if( count( $hardware_info ) > 0 ){ echo "".getMessage('stats_hardware').""; } if( count( $network_info ) > 0 ){ echo "".getMessage('stats_network').""; } echo ""; echo ""; foreach( $config_info as $nom_config ){ echo "".$nom_config.""; } foreach( $hardware_info as $nom_hardware ){ echo "".$nom_hardware.""; } foreach( $network_info as $nom_network ){ echo "".$nom_network.""; } echo ""; foreach( $tree as $node ){ $node_path = getNodeFullPath( $node ); if( in_array( $node_path."/".$node->toString(), $valid_nodes ) ){ $config_info = $node->attributes[ "config" ]; $hardware_info = $node->attributes[ "hardware" ]; $network_info = $node->attributes[ "network" ]; echo ""; echo "".$node->toString().""; echo "".$node_path.""; foreach( $config_info as $config ){ echo "".$config.""; } foreach( $hardware_info as $hardware ){ echo "".$hardware.""; } foreach( $network_info as $network ){ echo "".$network.""; } echo ""; } } echo ""; ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/class/0000775000175000017500000000000012026403130023334 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Admin/util/statistics/class/nodes_stats.php0000664000175000017500000000421112026403127026377 0ustar stgraberstgraberid = $id; $this->id_parent = $id_parent; $this->name = $name; $this->type = $type; $this->is_opened = false; $this->status = 0; $this->clearAttributes(); } function close(){ $this->is_opened = false; } function open(){ $this->is_opened = true; } // If the status of a node is higher than 0, it is checked function is_checked(){ $retour = false; if( $this->status > 0 ){ $retour = true; } return $retour; } // Returns an array of the IDs from the direct childs of a node // MODIFICATION : In alphabetical order function returnChild( $tree ){ $childs = array(); foreach( $tree as $node ){ if( $node->id_parent == $this->id && $node->id <> $this->id ){ //$childs[] = $node->id; // Get the node's name to be able to sort it $childs[ $node->id ] = $node->name; } } // Sort the childs and return only the IDs asort( $childs ); return array_keys( $childs ); } // Returns what will be shown when the node will be printed function toString(){ return $this->name; } // Empties the array of attributes of the node function clearAttributes(){ $this->attributes = array(); $this->attributes[ "config" ] = array(); $this->attributes[ "hardware" ] = array(); $this->attributes[ "network" ] = array(); } } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/class/conditions.php0000664000175000017500000000150512026403127026225 0ustar stgraberstgraber=, >) function condition( $name, $category, $type, $id ){ $this->name = $name; $this->category = $category; $this->type = $type; $this->id = $id; $this->comparator = array(); $this->value = array(); } } ?>ltsp-cluster-control-2.0.3/Admin/util/statistics/class/nodes.php0000664000175000017500000000357012026403127025170 0ustar stgraberstgraberid = $id; $this->id_parent = $id_parent; $this->name = $name; $this->type = $type; $this->is_opened = false; $this->status = 0; $this->clearAttributes(); } function close(){ $this->is_opened = false; } function open(){ $this->is_opened = true; } // If the status of a node is higher than 0, it is checked function is_checked(){ $retour = false; if( $this->status > 0 ){ $retour = true; } return $retour; } // Returns an array of the IDs from the direct childs of a node function returnChild( $tree ){ $childs = array(); foreach( $tree as $node ){ if( $node->id_parent == $this->id && $node->id <> $this->id ){ $childs[] = $node->id; } } return $childs; } // Returns what will be shown when the node will be printed function toString(){ return $this->name; } // Empties the array of attributes of the node function clearAttributes(){ $this->attributes = array(); $this->attributes[ "config" ] = array(); $this->attributes[ "hardware" ] = array(); $this->attributes[ "network" ] = array(); } } ?>ltsp-cluster-control-2.0.3/Admin/util/HWGroupRule.php0000664000175000017500000001214312026403127022740 0ustar stgraberstgraberisError = false; $this->noFound = false; if (is_numeric($nodeId)) { $this->node_id = $nodeId; if(isset($hwkey))$this->hwkey = $hwkey; if(isset($hwvalue))$this->hwvalue = $hwvalue; if(isset($operator))$this->operator = trim($operator); } else if (is_array($nodeId)) { $cols = $nodeId; $this->node_id = $cols['nodes_id']; $this->hwkey = $cols['hwkey']; $this->hwvalue = $cols['hwvalue']; $this->operator = trim($cols['operator']); } else { $this->isError = true; $this->lastError = getMessage('bad_id')."node_id=".$nodeId; return; } } // private function updateDB($toSet,$table="hwgroupsrule", $where = "id") { if ($where == "id") $where = "nodes_id=".$this->node_id." AND hwkey=".qstr($this->hwkey)." AND hwvalue=".qstr($this->hwvalue); $query = "UPDATE ".$table." SET ".$toSet." WHERE ".$where; if ($error = write($query)) { $this->lastError = getMessage('db_write_error').$error." : ".$query; return false; } else return true; } /* * Return true if the hardware list match the rule * * (PDubois)Patrick Dubois - Modifications - July 10, 2008 * Bugfix - Added null array check to fix configuration panel * error. When viewing a node without hardware (ie: categories or groups) * PHP would report an invalid argument error for 'foreach' below. */ function match($hwList) { if ( ! is_null($hwList) ) { $match=false; foreach ($hwList as $hw) { if ($hw["hwkey"] == $this->hwkey && $match==false) { if ($this->hwvalue == '' || $this->hwvalue == '*') $match=true; else if ($this->operator == '=' || $this->operator == '==' || $this->operator == '!=') $match=($hw["hwvalue"] == $this->hwvalue); else if ($this->operator == '>') $match=($hw["hwvalue"] > $this->hwvalue); else if ($this->operator == '>=') $match=($hw["hwvalue"] >= $this->hwvalue); else if ($this->operator == '<') $match=($hw["hwvalue"] < $this->hwvalue); else if ($this->operator == '<=') $match=($hw["hwvalue"] <= $this->hwvalue); else if ($this->operator == 'in') $match=(strpos($hw["hwvalue"],$this->hwvalue)>=0); } } if ($this->operator == '!=') $match=!$match; return $match; }// end if else { $match=false; return $match; } } /** * Update hwg list */ function updateList($list){ startTrans(); $this->deleteAll(); foreach($list as $hwGroup){ $hwGroup->insertDB(); } completeTrans(); } ////////////////////////////////////////////////////////////////// // Getters ////////////////////////////////////////////////////////////////// function getNodeID() { return $this->node_id; } function getHwKey() { return $this->hwkey; } function getHwValue() { return $this->hwvalue; } function getOperator() { return $this->operator; } function isError() { return $this->isError; } function lastError() { return $this->lastError; } function notFound() { return $this->NotFound; } ////////////////////////////////////////////////////////////////// // Setters ////////////////////////////////////////////////////////////////// function delete() { $error = NULL; $error .= delete("DELETE FROM hwgroupsrule WHERE nodes_id=".$this->node_id." AND hwkey=".qstr($this->hwkey)." AND hwvalue=".qstr($this->hwvalue)); return $error; } function deleteAll() { if($error = delete("DELETE FROM hwgroupsrule WHERE nodes_id=".$this->node_id)){ $this->lastError = $error; $this->isError=true; return false; }else{ return true; } } function setValue($newHwkey, $newHwvalue, $newOperator) { if ($this->isError) return false; if (!$this->updateDB("hwkey=".qstr($newHwkey).",hwvalue=".qstr($newHwkey).",operator=".$newOperator)) return false; $this->hwkey = $newHwkey; $this->hwvalue = $newHwvalue; $this->operator = $newOperator; return true; } function insertDB() { $values = $this->node_id.",".qstr($this->hwkey).",".qstr($this->hwvalue).",".qstr($this->operator); $query = "INSERT INTO hwgroupsrule(nodes_id,hwkey,hwvalue,operator) VALUES(".$values.")"; if ($error = write($query)) { $this->lastError = getMessage('db_write_error').$error." : ".$query; $this->isError=true; return false; } else return true; } function getOperators(){ $opList = array("=","!=",">",">=","<","<=","in"); return $opList; } } ?> ltsp-cluster-control-2.0.3/Admin/util/nodesBrowserView.php0000664000175000017500000000745512026403127024076 0ustar stgraberstgraber


    printErrors(); ?>

    type == COMPUTER_TYPE && $this->node->mac=="00:00:00:00:00:00") { echo getMessage("noaccess"); exit; } ?>

    parents)) { $currend_node_id = $_GET[$this->node_id]; foreach ($this->parents as $parent) { $_GET[$this->node_id] = $parent->getID(); if (!($termonly && $this->type == COMPUTER_TYPE)) echo ""; echo "[".$parent->getName()."]"; if (!($termonly && $this->type == COMPUTER_TYPE)) echo ""; echo " "; } $_GET[$this->node_id] = $currend_node_id; } ?> [ node->isNode()) print $this->node->getName(); else if ($this->node->nodetype == COMPUTER_TYPE) print $this->node->getMac(); else if ($this->node->nodetype == HWGROUP_TYPE) print $this->node->getName(); ?> ] type == NODE_TYPE) { $isEmpty = true; if (is_array($this->childrens)) { foreach ($this->childrens as $child) { if ($child->isNode()) { $isEmpty = false; break; } } } if ($isEmpty) { $this->childrens = NULL; } } if($this->node->isNode() && is_array($this->childrens)) { ?> $value) { if ($name != $this->node_id) { ?>

    ltsp-cluster-control-2.0.3/Admin/util/SubnetNodeFinder.php0000664000175000017500000001117012026403127023752 0ustar stgraberstgraber *
  • IP of the computer * * * Example of valid initialisation : * * * $finder=new SubnetNodeFinder("10.1.0.9"); * * * @access public */ function SubnetNodeFinder($ipaddr) { $this->notFound = false; $this->ip = $ipaddr; // Build IN clause content including all possibility $inClause=""; foreach (array(8,16,18,19,20,21,22,23,24,25,26,27,28,29,30,32) as $i) { $inClause = $inClause.",'".$this->getSubnetDef($i,$ipaddr)."'"; } $inClause = substr($inClause, 1); // Retrieve corresponding subnets $where="attributesdef_id=(SELECT id FROM attributesdef WHERE name='NODE_SUBNET') ". "AND value IN (".$inClause.")"; $result=$this->getFromDB("nodes_id, value",$where,"attributes",true,true); if ($result) { // Keep higher value $highLine=NULL; $highVal=0; foreach ($result as $ptr) { list($ipVal, $maskVal) = split('[\/]',$ptr['value']); $curVal=intval($maskVal); if ($curVal >= $highVal) { $highLine=$ptr; $highVal=$curVal; } } } if (!$highLine) { // No node found $this->notFound = true; } else { $this->subnet = $highLine['value']; $this->nodeid = $highLine['nodes_id']; } } /** * Compute the subnet for a specific mask width * * @access private * @return int */ function getSubnetDef($width, $ipaddr) { // Split ip addr in 4 parts (0.1.2.3) $parts=split('[.]',$ipaddr); // Compute mask for the the last part $lastPart = (int) floor($width / 8); $lastBits = $width % 8; $lastMask = 0; if ($lastBits > 0) { $lastMask = 1; for ($i = 0; $i < $lastBits-1; $i++) { $lastMask = ($lastMask << 1) + 1; } for ($i = $lastBits; $i < 8; $i++) { $lastMask = ($lastMask << 1); } } // Apply mask to ip $parts[$lastPart] = intval($parts[$lastPart]) & $lastMask; for ($i = $lastPart+1; $i<4; $i++) { $parts[$i]=0; } return $parts[0].'.'.$parts[1].'.'.$parts[2].'.'.$parts[3].'/'.$width; } /** * Return true if not found * * @access public * @return int */ function notFound() { return $this->notFound; } /** * Get the node ID * * @access public * @return int */ function getNodeID() { return $this->nodeid; } /** * Get the subnet string * * @access public * @return int */ function getSubnet() { return $this->subnet; } /** * Return yes if the object exists * To be used just after the construction * * @access public * @return float */ function isError() { return $this->isError; } /** * Get the last error * * @access public * @return float */ function lastError() { return $this->lastError; } /** * GetFromDB * * @access private * @return array */ function getFromDB($column,$where,$from="attributes",$isFatal=true,$multiple = false) { $query='SELECT '.$column.' FROM '.$from.' WHERE '.$where; if ($multiple) { $result = select($query.";"); } else { $result = singleResultSelect($query); } if (!$result) { $this->lastError = getMessage('not_found').$query; $this->notFound = true; if ($isFatal) $this->isError = true; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error').$result." : ".$query; if ($isFatal) $this->isError = true; return NULL; } return $result; } } // class SubnetNodeFinder ?> ltsp-cluster-control-2.0.3/Admin/util/nodesManager.php0000664000175000017500000000333712026403127023165 0ustar stgraberstgraberload(NODE_TYPE,"destination","node_id_dest","nb_find_dest"); if (!$termonly) { $source = new NodesBrowser(NODE_TYPE,"source"); $perm = $source->getPermissions(); $ne = new NodesEditor($source->getNode(),$dest->getNode(),$perm); $source->load(NODE_TYPE,"source"); } else { // Load type 1 nodebrowser in termonly mode $source = new NodesBrowser(); $ne = new NodesMoveCmd($source->getNode(),$dest->getNode()); $source->load(); } break; case 'print': $source->printView(); if (!$termonly) { $ne->printView(); $dest->printView(); } else { // Different order in termonly mode $dest->printView(); $ne->printView(); } break; } ?> ltsp-cluster-control-2.0.3/Admin/util/check.php0000664000175000017500000000177212026403127021640 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Admin/util/update.php0000664000175000017500000000027312026403127022040 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Admin/util/ModulesBrowser.php0000664000175000017500000000527212026403127023536 0ustar stgraberstgraber $name) { $this->currentModule = $name; break; } } else $this->currentModule = $_GET['module']; // Loading module if role has permission to ... if(in_array($this->currentModule, $ROLE[$_SESSION['userRole']])){ $module_action = "build"; include $MODULES[$this->currentModule]; } // Printing module navigator $this->printBrowser(); echo "
    "; // Printing module $module_action = "print"; include $MODULES[$this->currentModule]; echo "
    "; } function printBrowser() { global $MODULES,$termonly,$termonly_modules,$ROLE,$GROUP_ROLE; echo "

    LTSP-Cluster Control Center

    "; echo ""; echo "

    "; echo getMessage($_GET['module']); $image = "./images/".$_GET['module'].".png"; if( file_exists( $image ) ) echo ""; echo "

    "; //if(!$termonly) echo "
    "; } } ?>ltsp-cluster-control-2.0.3/Admin/util/printingView.php0000664000175000017500000001110012026403127023232 0ustar stgraberstgraber

    printErrors(); ?> printInfos(); ?> printDebug(); ?>


    prt_filter) ?> nbpage ; $i++) { echo " | "; if ($i == $this->numpage) { echo $i+1; } else { $_GET['numpage'] = $i; echo ''.($i+1).''; } } ?>


    isSelected) { print $this->prt->print_printer(); ?>



    Available printers by CUPS
    "; foreach ($avail_printers as $printer){ print "$printer"."
    "; } ?>


    nodeIsSelected) $this->node->print_node_resume(); ?>
    isSelected) $this->prt->print_printer_resume(); ?>

    nodeIsSelected && $this->isSelected) { ?>


    ltsp-cluster-control-2.0.3/Admin/util/NodesEditor.php0000664000175000017500000001330212026403127022772 0ustar stgraberstgraberisError OR $dest->isError) { $this->isError = true; return; } $this->permissions = $perm; ///////////////////////////// // Actions ///////////////////////////// // Cancel if (isset($_POST['ne_cancel'])) { unset($GLOBALS['_POST']); } // Move elseif (isset($_POST['ne_move'])) { //To be valid : canwrite on destination and source if (is_array($_POST['selection'])) { foreach ($_POST['selection'] as $id) { //canwrite on source $this->hasPermission = $this->permissions->canWriteNode(); if($this->hasPermission == 1){ //canwrite on destination $destPermission = new Permissions($dest->getID()); $this->hasPermission = $destPermission->canWriteNode(); if($this->hasPermission == 0){ break; } }else{ break; } } if($this->hasPermission == 0){ $this->errors[] = getMessage('no_permission_to_move_node'); }else{ foreach ($_POST['selection'] as $id) { $node = new Node($id); if ($node->isError()) $this->errors[] = $node->lastError()." : id=".$id; elseif (!$node->setParent($dest->getID())) { $this->errors[] = $node->lastError()." : id=".$id; }else{ logAdminAccess(array("MOVE NODE","SOURCE : ".$id,"DESTINATION : ".$dest->getID())); } } } } } // Delete elseif (isset($_POST['ne_delete'])) { if (is_array($_POST['selection'])) { //To be valid : canwrite on source foreach ($_POST['selection'] as $id) { $this->hasPermission = $this->permissions->canWriteNode(); if($this->hasPermission == 0){ break; } } if($this->hasPermission == 0){ $this->errors[] = getMessage('no_permission_to_delete_node').$id; }else{ foreach ($_POST['selection'] as $id) { $node = new Node($id); if ($node->isError()) $this->errors[] = $node->lastError()." : id=".$id; elseif (!$node->delete()) { $this->errors[] = $node->lastError(); }else{ logAdminAccess(array("DELETE NODE","NODE_ID : ".$id)); } } } } } // Rename elseif (isset($_POST['ne_change_name'])) { $this->hasPermission = $this->permissions->canWriteNode(); if($this->hasPermission==1){ if (!$source->setName($_POST['ne_node_name'])) { $this->errors[] = $source->lastError(); }else{ logAdminAccess(array("RENAME NODE","NODE_ID : ".$source->getID())); } }else{ //if we don't have the permission to write $this->errors[] = getMessage('no_permission_to_write_node').$source->getID(); $_POST['ne_node_name'] = $source->getName(); } } //edit create child form - check permission if (isset($_POST['ne_new_child']) || isset($_POST['ne_new_hwgroup'])) { $this->hasPermission = $this->permissions->canAddNode(); if($this->hasPermission==0){ $this->errors[] = getMessage('no_permission_to_add_node').$source->getID(); unset($_POST['ne_new_child']); } } // Create child elseif (isset($_POST['ne_create_child'])) { $this->hasPermission = $this->permissions->canAddNode(); if($this->hasPermission==1){ //Add node if(isset($_POST['ne_new_node_action'])){ if (!$source->createChildNode($_POST['ne_new_node_name'])) { $this->errors[] = $source->lastError(); $_POST['ne_new_child'] = true; }else{ logAdminAccess(array("CREATE CHILD NODE","NODE_ID : ".$source->getID(),"NODE_NAME : ".$_POST['ne_new_node_name'])); } unset($_POST['ne_new_node_name']); //Add hwgroup }else if(isset($_POST['ne_new_hwgroup_action'])){ if (!$source->createChildHWGroup($_POST['ne_new_node_name'])) { $this->errors[] = $source->lastError(); $_POST['ne_new_child'] = true; }else{ logAdminAccess(array("CREATE CHILD NODE","NODE_ID : ".$source->getID(),"NODE_NAME : ".$_POST['ne_new_node_name'])); } unset($_POST['ne_new_hwgroup_action']); } }else{ $this->errors[] = getMessage('no_permission_to_add_node').$source->getID(); } } $this->source = $source; $this->dest = $dest; $this->childrens = $source->getChildrens(); if (!isset($_POST['ne_node_name'])) $_POST['ne_node_name'] = $source->getName(); } /** * Print errors * * @access public */ function printErrors() { if (isset($this->errors[0])) print "

    \n"; else return; foreach ($this->errors as $error) { print "".$error."
    \n"; } print "

    \n"; } /** * Print the browser HTML view * * @access public * @return stdout */ function printView() { if ($this->isError) { $this->printErrors(); } else { include 'nodesEditorView.php'; } } } ?> ltsp-cluster-control-2.0.3/Admin/util/PrintingBrowser.php0000664000175000017500000003746312026403127023727 0ustar stgraberstgraberdebugLevel = 1; /* Request: Delete a printer */ if (isset($_POST['do_delete']) && (1==$_POST['do_delete'])) { if($this->delete_a_printer($_POST['delete_printerid'])) { unset($_GET['printer_id']); unset($_POST['printer_id']); } } /* Request: Add a printer */ if (isset($_POST['do_add']) && (1==$_POST['do_add'])) { if ($this->add_a_printer($_POST['add_printername'], $_POST['add_description'], $_POST['add_priceperpage'], $_POST['add_priceperjob'])) { $_GET['printer_id'] = $_POST['add_printername']; unset($_POST['printer_id']); } } /* Request: Update the dictionary */ /* Automatically called when adding/removing a printer. */ if (isset($_POST['do_sync_dict']) && (1==$_POST['do_sync_dict'])) { $this->updateDict(); } /* Request: Update users */ if (isset($_POST['do_sync_users']) && (1==$_POST['do_sync_users'])) { $this->updateUsers(); } /* Request: Update quota */ if (isset($_POST['do_sync_quota']) && (1==$_POST['do_sync_quota'])) { /* WARNING!!! This function is under developpement * and its spec is not defined!! */ $this->updateQuota(); } /* Build the printer object */ $this->PrintingBrowser_buildprinterobject(); /* Build the node object */ $this->PrintingBrowser_buildnodeobject(); /* Search the SQL regexp */ $this->getPrinterListFromDB(); } /** * Build the Printer Object * * Called by the constructor * * @access private * @return none */ function PrintingBrowser_buildprinterobject() { $prtOK = false; unset($this->prt_filter); /* By default, the regexp is all (%) */ if (!isset($_GET['printer_filter'])) { $_GET['printer_filter'] = '%'; } if (isset($_POST['printer_id'])) { /* The user select a printer */ $prtOK = $this->buildPrinter($_POST['printer_id']); if ($prtOK) { /* the user manage to find his printer */ $_GET['printer_id'] = $_POST['printer_id']; } else { /* the user fail to find his printer: help him */ $_GET['printer_filter'] = $_POST['printer_id']; $this->prt_filter = $_POST['printer_id']; } } /* the user fail to find a new printer; select the * previously selected one */ if (isset($_GET['printer_id']) && !$prtOK) { $prtOK = $this->buildPrinter($_GET['printer_id']); } if ($prtOK) { $this->isSelected = true; } else { $this->isSelected = false; unset($_GET['printer_id']); } if (!isset($this->prt_filter)) { $this->prt_filter = $_GET['printer_filter']; } } /** * Build the Node Object * * Called by the constructor * * @access private * @return none */ function PrintingBrowser_buildnodeobject() { $this->node = new Node(trim($_GET['node_id'])); if ($this->node->isError()) { $this->nodeIsSelected = false; unset($_GET['node_id']); } else { $this->nodeIsSelected = true; } } /** * Delete a printer * * @access public * @return boolean */ function delete_a_printer($printerid) { /* First, delete printergroups that reference this printer */ $sql_query = "DELETE FROM printergroupsmembers where printerid=".$printerid; if ($error = delete($sql_query)) { $this->errors[] = getMessage('db_write_error').$error." : ".$sql_query; return false; } /* then delete the printer */ $sql_query = "DELETE FROM printers where id=".$printerid; if ($error = delete($sql_query)) { $this->errors[] = getMessage('db_write_error').$error." : ".$sql_query; return false; } else { $this->updateDict(); $this->infos[] = getMessage('delete_printer_ok'); return true; } } /** * Add a printer * * @access public * @return boolean */ function add_a_printer($printername, $description, $priceperpage, $priceperjob) { if (!is_string($description)) {$description="";} if (!is_numeric($priceperpage)) {$priceperpage=0;} if (!is_numeric($priceperjob)) {$priceperjob=0;} $sql_query = "INSERT INTO printers (printername, description, priceperpage, priceperjob)" ." VALUES ('".$printername."','".$description."',".$priceperpage.",".$priceperjob.")"; if ($error = write($sql_query)) { $this->errors[] = getMessage('db_write_error').$error." : ".$sql_query; return false; } else { $this->updateDict(); $this->infos[] = getMessage('add_printer_ok'); return true; } } /** * Put all printers in the group allprinters * * @access private * @return boolean */ function updateQuota() { /* Ajoute toutes les imprimantes dans le groupe allprinters */ $this->debug[] = "enter into updateQuota"; $sql_query_allprinters = "SELECT id FROM printers WHERE printername='allprinters'"; $r = singleResultSelect($sql_query_allprinters); if (NULL==$r) { /* allprinters doesn't exist... add it. */ $sql_query = "INSERT INTO printers" ." (printername, description, priceperpage, priceperjob)" ." VALUES ('allprinters', 'group for all printers', 0, 0"; if ($error = write($sql_query)) { $this->errors[] = getMessage('db_write_error').$error." : ".$sql_query; return false; } } else { $this->debug[] = "allprinters already exist :)"; } $sql_query = "SELECT * from printers WHERE printername!='allprinters'"; $printersList = select($sql_query); if (!is_array($printersList) && !is_null($printersList)) { $this->errors[] = getMessage('db_write_error') . $printersList; } else if (!is_null($printersList)) { foreach ($printersList as $a_printer) { $this->debug[] = "adding the printer ".$a_printer['printername']; $sql_query = "INSERT INTO printergroupsmembers" ." (groupid, printerid)" ." VALUES ((".$sql_query_allprinters."), " .$a_printer['id'].")"; write($sql_query); /* this produce errors if already exists... don't care */ } } } /** * Update the users * * @access public * @return none */ function updateUsers() { /* We can't remove all users in the PyKota database and then put * them again because they are reference on them. Instead we * have to check one by one the list... */ $getent_users = split("\n", rtrim(shell_exec("getent passwd|cut -d: -f1"))); foreach($getent_users as $u) { $sql_query = "SELECT * FROM users" ." WHERE username='".$u."'"; if (NULL==singleResultSelect($sql_query)) { /* Add the user */ $sql_query = "INSERT INTO users" ." (username)" ." VALUES ('".$u."')"; write($sql_query); $this->debug[] = "User ".$u." : ADDED in PyKota database"; } else { $this->debug[] = "User ".$u." : OK"; } } } /** * Update the dictionary * * Automatically called when adding/deleting a printer * * @access public * @return none */ function updateDict() { /* We can't remove all words in the dictionnaire and then put them again because * they are reference on them. Instead we have to check one by one the list... */ $this->debug[] = "enter into updateDict"; /* Check if the attribute LDM_PRINTER_LIST exists */ $sql_query = "SELECT name FROM attributesdef WHERE name='LDM_PRINTER_LIST'"; $r = singleResultSelect($sql_query); if (NULL==$r) { $this->debug[] = "LDM_PRINTER_LIST undefined"; $this->errors[] = getMessage('cannot_update_dico'); } /* select all printers from the dict... */ $sql_query = "SELECT def.id AS id, dict.value AS printername" ." FROM attributesdefdict AS dict, attributesdef AS def" ." WHERE dict.attributesdef_id = def.id" ." AND def.name = 'LDM_PRINTER_LIST'"; $wordsList = select($sql_query); /* ... and delete these that are still not relevant */ if (!is_array($wordsList) && !is_null($wordsList)) { $this->errors[] = getMessage('cannot_update_dico') . $wordsList; } else if (!is_null($wordsList)) { foreach ($wordsList as $a_printer) { /* if $a_printer['printername'] still not exist, delete it. */ $sql_query = "SELECT * FROM printers WHERE printername='".$a_printer['printername']."'"; if (NULL==singleResultSelect($sql_query)) { $sql_query = "DELETE FROM attributesselect" ." WHERE value='".$a_printer['printername']."'" ." AND attributesdef_id=" ."(SELECT id FROM attributesdef". " WHERE name='LDM_PRINTER_LIST')"; $error = delete($sql_query); if ($error) { $this->errors[] = getMessage('cannot_update_dico') . $error." - ".$sql_query; } $sql_query = "DELETE FROM attributesdefdict" ." WHERE value='".$a_printer['printername']."'" ." AND attributesdef_id=" ."(SELECT id FROM attributesdef". " WHERE name='LDM_PRINTER_LIST')"; $error = delete($sql_query); if ($error) { $this->errors[] = getMessage('cannot_update_dico') . $error." - ".$sql_query; } $this->debug[] = "Dictionary printer ".$a_printer['printername']." : DELETED"; } else { $this->debug[] = "Dictionary printer ".$a_printer['printername']." : OK"; } } } /* select all printers form Pykota... */ $sql_query = "SELECT * FROM printers"; $wordsList = select($sql_query); /* ... and add these that misses */ if (!is_array($wordsList) && !is_null($wordsList)) { $this->errors[] = getMessage('cannot_update_dico').$wordsList; } else if (!is_null($wordsList)) { foreach ($wordsList as $a_printer) { /* if $a_printer['printername'] didn't exist, create it. */ $sql_query = "SELECT dict.value" ." FROM attributesdefdict as dict, attributesdef AS def" ." WHERE dict.attributesdef_id = def.id" ." AND def.name = 'LDM_PRINTER_LIST'" ." AND dict.value = '".$a_printer['printername']."'"; if (NULL==singleResultSelect($sql_query)) { $sql_query = "INSERT INTO attributesdefdict" ." (attributesdef_id, value, sortval)" ." VALUES ((SELECT id from attributesdef where name='LDM_PRINTER_LIST'), '" .$a_printer['printername']."', 0)"; write($sql_query); $this->debug[] = "Pykota printer ".$a_printer['printername']." : ADDED"; } else { $this->debug[] = "Pykota printer ".$a_printer['printername']." : OK"; } } } } /** * Get the the current page printer list with the regexp * * @access private * @return boolean */ function getPrinterListFromDB() { $itemPerPage=5; /* Get the page number requested */ if (isset($_GET['numpage']) && (is_numeric($_GET['numpage']))) { $this->numpage = $_GET['numpage']; } else { $this->numpage = 0; } /* Get the total number of pages */ $sql_query = "SELECT count(*) as c FROM printers" ." WHERE printername" ." LIKE '".$this->prt_filter."'"; $r = singleResultSelect($sql_query); $this->nbpage = ceil($r['c'] / $itemPerPage); /* Check if we are under the limit */ if ($this->numpage > $this->nbpage) { $this->numpage = 0; } if ($this->numpage < 0) { $this->numpage = 0; } /* Get the page requested */ $sql_query = "SELECT *" ." FROM printers" ." WHERE (printername LIKE '".$this->prt_filter."')" ." ORDER BY printers.printername" ." LIMIT ".$itemPerPage." OFFSET ".$this->numpage*$itemPerPage ; $this->prt_filter_result = select($sql_query); } /** * Assign a node to a printer. This function is obselete. * * @access private * @return none */ function assign_prt_node($n, $p) { /* The user want to assign a printer to a local */ //print "*".$_POST['assign_node'] . "*
    \n"; //print "*".$_POST['assign_printer'] . "*
    \n"; $assigned_node = new Node($n); $assigned_printer = new Printer($p); /* Check if Node is correctly created */ if ($assigned_node->isError()) { $this->errors[] = $assigned_node->lastError(); return; } /* Check if Printer is correctly created */ if ($assigned_printer->isError()) { $this->errors[] = $assigned_printer->lastError(); return; } /* Check if the record already exists */ if (NULL==$assigned_printer->getFromDB("*","printerid=".$assigned_printer->getID()." AND nodeid=".$assigned_node->getID(),"printernode")) { /* The record doesn't exist yet... INSERT INTO */ $sql_query = "INSERT INTO printernode (printerid, nodeid) VALUES (" .$assigned_printer->getID().", " .$assigned_node->getID().")"; } //print "
    ".$sql_query."
    "; write($sql_query); } /** * Print the list of errors * * @access public * @return none */ function printErrors() { if (isset($this->errors[0])) print "

    \n"; else return; foreach ($this->errors as $error) { print "".$error."
    \n"; } print "

    \n"; } /** * Print the list of user's informations * * @access public * @return none */ function printInfos() { if (isset($this->infos[0])) print "

    \n"; else return; foreach ($this->infos as $error) { print "".$error."
    \n"; } print "

    \n"; } /** * Print the list of debugging message * * No effect if debugLevel is set to 0 * * @access public * @return none */ function printDebug() { if ($this->debugLevel > 0) { if (isset($this->debug[0])) print "

    \n"; else return; foreach ($this->debug as $error) { print "Debug: ".$error."
    \n"; } print "

    \n"; } } /** * Print the module, with printingView.php * * @access public * @return none */ function print_printing() { include 'printingView.php'; } /** * Create the printer object * * @access private * @return boolean */ function buildPrinter($id){ $this->prt = new Printer($id); if ($this->prt->isError()) { $this->errors[] = $this->prt->lastError(); } return !$this->prt->isError(); } } ?> ltsp-cluster-control-2.0.3/Admin/util/ListManager.php0000664000175000017500000000715512026403127022772 0ustar stgraberstgraberisError = false; ///////////////////////// // Actions ///////////////////////// // Cancel if (isset ($_POST['cancel'])) { unset ($GLOBALS['_POST']); } // Generating all attribute list $this->editableAttributes = $this->getEditableAttributes(); if (isset ($_POST['save_def'])) { $attributeDef = new AttributeDef($_POST['modAttributeDef']); $index=0; foreach ($_POST['textfield'] as $value) { $oldValue=$_POST['hiddenfield'][$index]; $index++; if ($error = $attributeDef->updateDictValue($value,$oldValue)) { $this->errors[] = $error; unset($error); } } } if (isset ($_POST['del_def'])) { if (is_array($_POST['selection'])) { $attributeDef = new AttributeDef($_POST['modAttributeDef']); foreach ($_POST['selection'] as $value) { $attributeDef->deleteDictValue($value); } } } if (isset ($_POST['save_new_def'])) { $attributeDef = new AttributeDef($_POST['modAttributeDef']); if ($error = $attributeDef->insertDictValue($_POST['newDictValue'])) { $this->errors[] = $error; unset($error); } } // Change attributesdefdict if (isset ($_POST['mod_def'])) { $this->dictionary = $this->getDictionaryValue($_POST['modAttributeDef']); } } function getEditableAttributes() { $attributes = select("SELECT id,name FROM attributesDef WHERE editable=1 ORDER BY name"); if (!is_null($attributes) && !is_array($attributes)) { $this->errors[] = getMessage('db_error') . $attributes; //$this->isError = true; return NULL; } if (is_array($attributes)) { foreach ($attributes as $attribute) { $attributesAssoc[$attribute['id']] = $attribute['name']; } } return $attributesAssoc; } function getDictionaryValue($attributesdefId) { $query = "SELECT value FROM attributesdefdict WHERE attributesdef_id=" . $attributesdefId . "ORDER BY sortval,value"; $dictionaryValues = select($query); if (!is_null($dictionaryValues) && !is_array($dictionaryValues)) { $this->errors[] = getMessage('db_error') . $dictionaryValues; //$this->isError = true; return NULL; } for ($index = 0; $index < sizeof($dictionaryValues); $index++) { $result[$index] = $dictionaryValues[$index]["value"]; } return $result; } function isError() { return $this->isError; } function printErrors() { if (isset ($this->errors[0])) print "

    \n"; else return; foreach ($this->errors as $error) { print "" . $error . "
    \n"; } print "

    \n"; } function printView() { if ($this->isError) { $this->printErrors(); return; } include 'listManagerView.php'; } } ?> ltsp-cluster-control-2.0.3/Admin/util/roles-config.php0000664000175000017500000000174212026403127023147 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Admin/util/config-default.php0000664000175000017500000001152212026403127023444 0ustar stgraberstgraber set auth_name to EmptyAuth # ldap -> set auth_name to LDAPAuth #$CONFIG['auth_name']='LDAPAuth'; */ $CONFIG_DEFAULT['auth_name']='EmptyAuth'; //////////////////////////////////////////////////////////////////// // Terminal security //////////////////////////////////////////////////////////////////// /** * Terminal password */ $CONFIG_DEFAULT['terminal_password'] = 'c3g7ms2hbzereycb'; /** Terminal auth */ $CONFIG_DEFAULT['terminal_auth'] = 'false'; //////////////////////////////////////////////////////////////////// // Database //////////////////////////////////////////////////////////////////// /** * User to bind to database (no default) */ $CONFIG_DEFAULT['db_user'] = 'mille'; /** User database password (no default) */ $CONFIG_DEFAULT['db_password'] = 'mille'; /** * Server domain name or ip (no default) */ $CONFIG_DEFAULT['db_server'] = 'localhost'; /** * Database name (no default) */ $CONFIG_DEFAULT['db_name'] = 'millev2'; /** Database type (default is postgres7) */ $CONFIG_DEFAULT['db_type'] = 'postgres7'; //////////////////////////////////////////////////////////////////// // Logs and staus //////////////////////////////////////////////////////////////////// /** * Maximum Time in seconds that should pass between to boot server change * (default to 120 seconds) */ $CONFIG_DEFAULT['bootServRetry_time'] = 120; /** Maximum Time in seconds that should pass between the choice of a * bootServer and the assignation to an applicationServer * (default to 120 seconds) */ $CONFIG_DEFAULT['appServRetry_time'] = 120; /** * Set automatically the root of the Configurator installation. Do not * adjust manually ! */ $CONFIG_DEFAULT['rootInstall']= basePathDefault(); /** * Load balancer default value */ $CONFIG_DEFAULT['loadbalancer']= 'localhost:8001'; /** * Use https */ $CONFIG_DEFAULT['use_https']= 'true'; function basePathDefault() { return realpath(dirname(__File__)."/../")."/"; } ?> ltsp-cluster-control-2.0.3/Admin/util/text-zh.php0000664000175000017500000005155012026403127022165 0ustar stgraberstgraber您å¯ä»¥åœ¨\" é…ç½® \"--> é…置数æ®åº“中添加 ,或手动编辑config.php文件。
    查询请求是"; $MESSAGES['no_db_password'][$lang] = "用户密ç ç¡®å®žï¼Œæ— æ³•访问数æ®åº“
    您å¯ä»¥åœ¨\" é…ç½® \"--> é…置数æ®åº“中添加 ,或手动编辑config.php文件。
    查询请求是"; $MESSAGES['no_db_name'][$lang] = "æ•°æ®åº“å称缺失<
    您å¯ä»¥åœ¨\" é…ç½® \"--> é…置数æ®åº“中添加 ,或手动编辑config.php文件。
    查询请求是"; $MESSAGES['db_error'][$lang] = "æ•°æ®åº“查询出错: "; //////////////////////////////////////////////////////////////////// // Module names //////////////////////////////////////////////////////////////////// $MESSAGES['configuration_module'][$lang] = "é…ç½®"; $MESSAGES['nodesManager_module'][$lang] = "节点管ç†å™¨"; $MESSAGES['entity_module'][$lang] = "组/用户"; $MESSAGES['managelist_module'][$lang] = "属性列表值"; $MESSAGES['info_module'][$lang] = "技术信æ¯"; $MESSAGES['logs_module'][$lang] = "终端日志"; $MESSAGES['printing_module'][$lang] = "æ‰“å°æœºç®¡ç†å™¨"; $MESSAGES['stats_module_short'][$lang] = "报告"; $MESSAGES['setup_module'][$lang] = "控制中心的é…ç½®"; $MESSAGES['configuration_module_short'][$lang] = "é…ç½®"; $MESSAGES['nodesManager_module_short'][$lang] = "节点"; $MESSAGES['entity_module_short'][$lang] = "组/用户"; $MESSAGES['managelist_module_short'][$lang] = "属性列表值"; $MESSAGES['info_module_short'][$lang] = "技术信æ¯"; $MESSAGES['logs_module_short'][$lang] = "终端日志"; $MESSAGES['printing_module_short'][$lang] = "æ‰“å°æœºç®¡ç†å™¨"; $MESSAGES['stats_module_short'][$lang] = "报告"; $MESSAGES['setup_module_short'][$lang] = "控制中心的é…ç½®"; //////////////////////////////////////////////////////////////////// // Configurator setup section //////////////////////////////////////////////////////////////////// // General setup messages $MESSAGES['new_cfg_created'][$lang] = "已创建新的é…置文件。"; $MESSAGES['cannot_open_cfg_file'][$lang] = "无法写入到config.phpé…置文件。"; $MESSAGES['exit'][$lang] = "退出"; $MESSAGES['lock_setup'][$lang] = "é”定"; $MESSAGES['modify'][$lang] = "ä¿å­˜"; $MESSAGES['cfg_val_true'][$lang] = "是"; $MESSAGES['cfg_val_false'][$lang] = "å¦"; $MESSAGES['test'][$lang] = "测试"; // Language configuration section $MESSAGES['cfg_lang_section'][$lang] = "语言"; $MESSAGES['cfg_language'][$lang] = "é…置界é¢çš„语言"; $MESSAGES['cfg_charset'][$lang] = "用于é…置器Web界é¢çš„字符集编ç "; // Configurator Security section $MESSAGES['cfg_configurator_security_section'][$lang] = "é…置器安全"; $MESSAGES['use_https'][$lang] = "对é…置器Web界é¢ä½¿ç”¨https"; $MESSAGES['need_https'][$lang] = '此页é¢éœ€è¦ä¸€ä¸ªHTTPS连接。'; // Terminals Security section $MESSAGES['cfg_terminal_security_section'][$lang] = "终端安全"; $MESSAGES['cfg_terminal_password'][$lang] = "终端密ç "; $MESSAGES['cfg_terminal_auth'][$lang] = "终端认è¯"; // Configurator database section $MESSAGES['cfg_db_section'][$lang] = "é…置器数æ®åº“"; $MESSAGES['cfg_db_server'][$lang] = "åŒ…å«æ•°æ®åº“çš„æœåŠ¡å™¨çš„åœ°å€"; $MESSAGES['cfg_db_user'][$lang] = "æ•°æ®åº“的用户åç§°"; $MESSAGES['cfg_db_password'][$lang] = "æ•°æ®åº“的密ç ï¼ˆé»˜è®¤ä¸ºç©ºï¼‰"; $MESSAGES['cfg_db_name'][$lang] = "æ•°æ®åº“å"; $MESSAGES['cfg_db_type'][$lang] = "æ•°æ®åº“类型"; // Authentification configuration section $MESSAGES['cfg_auth_section'][$lang] = "认è¯ç³»ç»Ÿ"; $MESSAGES['cfg_auth_name'][$lang] = "针对é…置器Web界é¢çš„è¾“å…¥è®¤è¯æœåŠ¡"; // LDAP configuration (subsection of Authentification configuration) $MESSAGES['cfg_ldap_section'][$lang] = "LDAP é…ç½®"; $MESSAGES['cfg_ldap_host'][$lang] = " LDAP æœåС噍URL网å€"; $MESSAGES['cfg_ldap_basedn'][$lang] = "LDAP æœç´¢åŸº"; $MESSAGES['cfg_ldap_object_class'][$lang] = "用户对象类(éžå¼ºåˆ¶ï¼‰"; $MESSAGES['cfg_ldap_group_object_class'][$lang] = "组对象类(éžå¼ºåˆ¶ï¼‰"; $MESSAGES['cfg_ldap_group'][$lang] = "LDAP属性组"; $MESSAGES['cfg_ldap_binddn'][$lang] = "读å–用户和组的LDAP用户DN(默认作为用户绑定)"; $MESSAGES['cfg_ldap_bindpw'][$lang] = "剿¬¡ç”¨æˆ·å¯†ç "; $MESSAGES['cfg_ldap_uidAttribute'][$lang] = "ç”¨æ¥æœç´¢ç”¨æˆ·çš„属性"; $MESSAGES['cfg_ldap_version'][$lang] = "LDAP å议版本(默认为3)"; $MESSAGES['test_ldap'][$lang] = "输入您的LDAP登录å和密ç ä»¥æµ‹è¯•您的LDAPé…ç½®"; // LDAP user and group rights association section $MESSAGES['ldap_group_role'][$lang] = "LDAP用户和组æƒé™å…³è”"; // Load balancer section $MESSAGES['cfg_loadbalancer_section'][$lang] = "è´Ÿè½½å‡è¡¡å™¨"; $MESSAGES['cfg_loadbalancer'][$lang] = "URL (默认值 : localhost:8001)"; // printer servers section $MESSAGES['printer_server_section'][$lang] = "æ‰“å°æœºæœåС噍(Cups)"; //////////////////////////////////////////////////////////////////// // Login Screen //////////////////////////////////////////////////////////////////// $MESSAGES['index_title'][$lang] = 'é…置器登录'; $MESSAGES['no_language_file'][$lang] = "æœåŠ¡å™¨ä¸Šæœªæ‰¾åˆ°text-.phpæ–‡ä»¶ï¼Œä¸æ”¯æŒçš„语言。"; $MESSAGES['ask_uid'][$lang] = '请输入您的用户å: '; $MESSAGES['ask_password'][$lang] = '请输入您的密ç : '; $MESSAGES['connect'][$lang] = '连接'; $MESSAGES['bad_login'][$lang] = 'éžæ³•ç™»å½•åæˆ–密ç .'; $MESSAGES['good_login'][$lang] = '用户登录æˆåŠŸã€‚'; //////////////////////////////////////////////////////////////////// // Search node Module //////////////////////////////////////////////////////////////////// $MESSAGES['id_or_mac'][$lang] = "通过ID或MACåœ°å€æ‰¾åˆ°èŠ‚ç‚¹: "; $MESSAGES['find'][$lang] = "找到"; $MESSAGES['go'][$lang] = "转到"; $MESSAGES['search_inv'][$lang] = "通过库存清å•ç¼–å·æ‰¾åˆ°èŠ‚ç‚¹: "; //////////////////////////////////////////////////////////////////// // Configuration module //////////////////////////////////////////////////////////////////// $MESSAGES['source'][$lang] = "è¦ç®¡ç†çš„组件æº"; $MESSAGES['nodes_editor_change_tree_name'][$lang] = "节点属性"; $MESSAGES['nodes_editor_manage_actual_nodes'][$lang] = "å­èŠ‚ç‚¹"; $MESSAGES['nodes_editor_deselect'][$lang] = "åå‘选择"; $MESSAGES['config_attributes_listing'][$lang] = "当å‰é…ç½®"; $MESSAGES['config_delete'][$lang] = "删除"; $MESSAGES['config_modify'][$lang] = "修改"; $MESSAGES['config_cancel'][$lang] = "åå‘选择"; $MESSAGES['config_select_tree'][$lang] = "é历树"; //////////////////////////////////////////////////////////////////// // User and group module //////////////////////////////////////////////////////////////////// $MESSAGES['add_user_group'][$lang] = "添加一个 "; $MESSAGES['user'][$lang] = "用户"; $MESSAGES['group'][$lang] = "组"; $MESSAGES['users'][$lang] = "用户"; $MESSAGES['groups'][$lang] = "组"; $MESSAGES['search_user_group'][$lang] = "用户或组åç§° "; $MESSAGES['invalide_node_name'][$lang] = "éžæ³•åç§° :"; $MESSAGES['db_duplicate_value'][$lang] = "é‡å¤å€¼"; //////////////////////////////////////////////////////////////////// // Ldap messages at Login Screen //////////////////////////////////////////////////////////////////// $MESSAGES['ldap_cant_connect'][$lang] = '无法在URL: '.$CONFIG['ldap_host'].' 连接到指定LDAPæœåС噍'; $MESSAGES['ldap_connected'][$lang] = '您已ç»è¿žæŽ¥åˆ°LDAPæœåŠ¡å™¨ã€‚'; $MESSAGES['ldap_not_connected'][$lang] = '无法关闭LDAP连接。'; $MESSAGES['ldap_version_not_supported'][$lang] = 'æ­¤LDAPæœåС噍䏿”¯æŒLDAP版本'.$CONFIG['ldap_version'].' protocol.'; $MESSAGES['ldap_user_bind'][$lang] = '在é…ç½®ä¸­ç¼ºå¤±å‚æ•°binddn 或 bindpw ,作为用户绑定'; $MESSAGES['ldap_no_basedn'][$lang] = '在é…ç½®ä¸­ç¼ºå¤±å‚æ•°basedn.'; $MESSAGES['ldap_cant_bind'][$lang] = 'ä¸èƒ½ç»‘定到LDAPæœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥bindnæ˜¯å¦æ­£ç¡®ã€‚'; $MESSAGES['ldap_no_host'][$lang] = '在é…置中没有指定的LDAP主机。'; $MESSAGES['ldap_no_group'][$lang] = '在é…置中没有指定的LDAP组属性。'; //////////////////////////////////////////////////////////////////// // Group/User Module //////////////////////////////////////////////////////////////////// $MESSAGES['entity_add_entity_message'][$lang] = "添加用户和组"; $MESSAGES['entity_manage_user_group'][$lang] = "管ç†ç”¨æˆ·å’Œç»„"; $MESSAGES['newDefaultValueListAttribute'][$lang] = ""; //////////////////////////////////////////////////////////////////// // Report module //////////////////////////////////////////////////////////////////// $MESSAGES['stats_module'][$lang] = "报告"; $MESSAGES['stats_node_selector_msg'][$lang] = "选择è¦å¤„ç†çš„元素"; $MESSAGES['stats_true_conditions'][$lang] = "选择使元素的属性必须相关的æ¡ä»¶"; $MESSAGES['stats_false_conditions'][$lang] = "选择使元素的属性必须ä¸ç›¸å…³çš„æ¡ä»¶"; $MESSAGES['stats_add_cond'][$lang] = "添加"; $MESSAGES['stats_add_value'][$lang] = "添加"; $MESSAGES['stats_selected_value'][$lang] = "选定的æ¡ä»¶"; $MESSAGES['stats_select_what'][$lang] = "å…±åŒå·¥ä½œ : "; $MESSAGES['stats_terminals'][$lang] = "终端"; $MESSAGES['stats_contexts'][$lang] = "上下文"; $MESSAGES['stats_contexts_n_terminals'][$lang] = "终端与上下文"; $MESSAGES['stats_use_heritage'][$lang] = "考虑继承的属性"; $MESSAGES['stats_yes'][$lang] = "是"; $MESSAGES['stats_no'][$lang] = "å¦"; $MESSAGES['stats_send'][$lang] = "ç»§ç»­"; $MESSAGES['stats_validate'][$lang] = "对"; $MESSAGES['stats_configuration'][$lang] = "é…置属性"; $MESSAGES['stats_network'][$lang] = "网络属性"; $MESSAGES['stats_hardware'][$lang] = "硬件属性"; $MESSAGES['stats_select_attr_title'][$lang] = "选择您希望在报告中显示的属性"; $MESSAGES['stats_select_attr_config'][$lang] = "é…置属性:"; $MESSAGES['stats_select_attr_hardware'][$lang] = "硬件属性:"; $MESSAGES['stats_select_attr_network'][$lang] = "网络属性:"; $MESSAGES['stats_select_attr_type'][$lang] = "显示报告为:"; $MESSAGES['stats_generate'][$lang] = "ç”ŸæˆæŠ¥å‘Š"; $MESSAGES['stats_select_attr_type_context'][$lang] = "上下文"; $MESSAGES['stats_select_attr_type_table'][$lang] = "表"; $MESSAGES['stats_attribute'][$lang] = "属性"; $MESSAGES['stats_report_no_attr'][$lang] = "对于这些选定的内容没有属性显示。"; $MESSAGES['stats_equals'][$lang] = "等于"; $MESSAGES['stats_unequals'][$lang] = "ä¸ç­‰äºŽ"; $MESSAGES['stats_greater'][$lang] = "大于"; $MESSAGES['stats_greater_equals'][$lang] = "大于或等于"; $MESSAGES['stats_lower'][$lang] = "å°äºŽ"; $MESSAGES['stats_lower_equals'][$lang] = "å°äºŽæˆ–等于"; $MESSAGES['stats_no_node'][$lang] = "没有选择进行处ç†çš„属性."; $MESSAGES['stats_and'][$lang] = "与"; $MESSAGES['stats_or'][$lang] = "或"; $MESSAGES['stats_node'][$lang] = "部件"; $MESSAGES['stats_path'][$lang] = "路径"; //////////////////////////////////////////////////////////////////// // Printer Module //////////////////////////////////////////////////////////////////// $MESSAGES['printer_manage'][$lang] = "生效"; $MESSAGES['printer_manage_list'][$lang] = "è¦ç®¡ç†çš„æ‰“å°æœºæœåС噍"; $MESSAGES['printer_server_list'][$lang] = "æ‰“å°æœºåˆ—表 "; $MESSAGES['printer_add'][$lang] = "添加"; $MESSAGES['printer_delete'][$lang] = "删除"; $MESSAGES['printer_database'][$lang] = "在é…置器数æ®åº“中的已ç»å®‰è£…çš„æ‰“å°æœº"; $MESSAGES['printer_servers'][$lang] = "å¯ç”¨æ‰“å°æœº"; $MESSAGES['printer_standalone_list'][$lang] = "å•ç‹¬çš„æ‰“å°æœºåˆ—表"; $MESSAGES['printer_add_a_standalone'][$lang] = "添加å•ç‹¬çš„æ‰“å°æœº"; $MESSAGES['printer_no_printer_standalone'][$lang] = "没有定义的å•ç‹¬æ‰“å°æœºã€‚"; $MESSAGES['printer_warning_standalone'][$lang] = "è­¦å‘Šï¼šä¸€å°æ‰“å°æœºåœ¨å…¶æœåŠ¡å™¨ç¦»çº¿æ˜¯å¯ä»¥å­˜åœ¨äºŽå•ç‹¬æ‰“å°æœºåˆ—表。
    è¿™äº›æ‰“å°æœºå°†åœ¨æœåŠ¡å™¨ä¸Šçº¿æ—¶å›žåˆ°æœåŠ¡å™¨åˆ—è¡¨ã€‚"; $MESSAGES['printer_no_server'][$lang] = "存在DNSå,但是没有æ¥è‡ªæœåŠ¡å™¨çš„ç­”å¤"; $MESSAGES['printer_dead_server'][$lang] = "没有æ¥è‡ªæœåŠ¡å™¨çš„ç­”å¤"; $MESSAGES['printer_no_printer_server'][$lang] = "æ²¡æœ‰å®šä¹‰çš„æ‰“å°æœºæœåŠ¡å™¨ã€‚

    如果你需è¦ï¼Œä½ å¯ä»¥åœ¨è¿™é‡Œè¿›è¡Œæ·»åŠ ï¼š: \" ".getMessage('setup_module')." \" --> \" ".getMessage('printer_server_section')." \"
    然而,你ä»ç„¶å¯ä»¥ä½¿ç”¨\" ".getMessage('printer_standalone_list')." \""; $MESSAGES['printer_check_all'][$lang] = "全选"; //////////////////////////////////////////////////////////////////// // Log Module //////////////////////////////////////////////////////////////////// $MESSAGES['logs_note'][$lang] = "终端行动:从最近的到最è€çš„"; $MESSAGES['logs_ts'][$lang] = "日期和时间"; $MESSAGES['logs_id'][$lang] = "终端
    节点 ID"; $MESSAGES['logs_mac'][$lang] = "MAC 地å€"; $MESSAGES['logs_ip'][$lang] = "终端
    地å€"; $MESSAGES['logs_bootservip'][$lang] = "å¯åЍæœåС噍
    地å€"; $MESSAGES['logs_appservip'][$lang] = "应用æœåС噍
    地å€"; $MESSAGES['logs_display'][$lang] = "\$Display显示"; $MESSAGES['logs_username'][$lang] = "用户åç§°"; $MESSAGES['logs_code'][$lang] = "事件"; $MESSAGES['logs_bootservretry'][$lang] = "Bootserverå¯åЍæœåŠ¡å™¨å­—æ®µ"; $MESSAGES['logs_appservretry'][$lang] = "Appserver应用æœåŠ¡å™¨å­—æ®µ"; $MESSAGES['logs_prev'][$lang] = "上一个"; $MESSAGES['logs_next'][$lang] = "下一个"; $MESSAGES['logs_nb_logs_message'][$lang] = "æ¯é¡µç»“æžœ"; $MESSAGES['logs_filter_message'][$lang] = "过滤器"; $MESSAGES['logs_table_message'][$lang] = "结果"; $MESSAGES['logs_validate'][$lang] = "生效"; $MESSAGES['logs_code_booting'][$lang] = "终端å¯åЍ"; $MESSAGES['logs_code_GDM'][$lang] = "登录å±å¹•"; $MESSAGES['logs_code_logging'][$lang] = "用户登入"; $MESSAGES['logs_code_unlogging'][$lang] = "用户登出"; $MESSAGES['logs_msg_filter_seizure'][$lang] = "过滤器抓å–"; $MESSAGES['logs_msg_active_filters'][$lang] = "活动的过滤器"; $MESSAGES['logs_code_msg_legend'][$lang] = "事件标识"; $MESSAGES['logs_equals'][$lang] = "="; $MESSAGES['logs_greater'][$lang] = ">"; $MESSAGES['logs_gt_equals'][$lang] = ">="; $MESSAGES['logs_smaller'][$lang] = "<"; $MESSAGES['logs_sm_equals'][$lang] = "<="; $MESSAGES['logs_not_equals'][$lang] = "!="; $MESSAGES['logs_send_add_filter'][$lang] = "添加过滤器"; $MESSAGES['logs_send_remove_filter'][$lang] = "移除所有过滤器"; $MESSAGES['messages_error'][$lang] = 'è¿™ä¸ªæ¶ˆæ¯æ²¡æœ‰åœ¨text-en.php文件中设定'; unset($lang); ?> ltsp-cluster-control-2.0.3/Admin/util/EmptyAuth.php0000664000175000017500000000264312026403127022501 0ustar stgraberstgraber * - Creation */ class Auth { var $uid; // Username var $pass; // Password var $connection; // Connection object, return true if connected; var $role; // Role admin|user|nobody var $userData; function Auth($uid, $pass) { $this->uid = $uid; $this->pass = $pass; } function connect() { return NULL; } function disconnect() { // return NULL; } function authenticate() { $groups=array(); $groups[0]="Superadmin"; $this->userData = new SessionData("Superadmin",$groups); //print($this->uid."->".$groups[0]); return NULL; } function getUserData() { return $this->userData; } function isValidEntity($entityName,$entityType){ return true; } } ?> ltsp-cluster-control-2.0.3/Admin/util/dbFunctions.php0000664000175000017500000001411312026403127023032 0ustar stgraberstgraberdebug = true; require_once '/usr/share/php/adodb/adodb.inc.php'; require_once '/usr/share/php/adodb/adodb-errorpear.inc.php'; require_once 'functions.php'; /** * Create a new connection to the database if needed * * This function reads database configuration from configuration file * and create a connection. It return NULL if connection is good, a * message if not. * * @param object A referenced var where to place the new connection */ function makeDBConnexion() { global $CONFIG; global $dbConnexion; // If connecxion is already active, nothing to do. if ($dbConnexion) return NULL; // Test if configuration exist if (!isset($CONFIG['db_user'])) return getMessage('no_db_user'); // Authorize empty password if (!isset($CONFIG['db_password'])){ $CONFIG['db_password'] = ""; } if (!isset($CONFIG['db_server'])) return getMessage('no_db_server'); if (!isset($CONFIG['db_name'])) return getMessage('no_db_name'); if (!isset($CONFIG['db_type'])) $CONFIG['db_type'] = 'postgres7'; // Connection to Database $dbConnexion = ADONewConnection($CONFIG['db_type']); $dbConnexion->PConnect($CONFIG['db_server'],$CONFIG['db_user'],$CONFIG['db_password'],$CONFIG['db_name']); if ($error = ADODB_Pear_Error()) return getMessage('db_connexion_failed')." : ".$error->getUserInfo(); $dbConnexion->SetFetchMode(ADODB_FETCH_ASSOC); // To enable DEBUG MODE for ADODB (Very usefull !) // Uncomment the following line // $dbConnexion->debug = true; return NULL; } /** * Do a select and return first entry, null if no entry * * Do a select and return first entry, null if no entry, * a string if an erro occured. * * @param string Sql query */ function singleResultSelect($query) { global $ADODB_Last_PEAR_Error; if (!eregi("^select ",$query)) return getMessage('not_a_select'); if ($error = makeDBConnexion()) return $error; global $dbConnexion; $recordSet = &$dbConnexion->Execute($query); if ($error = ADODB_Pear_Error()) { $ADODB_Last_PEAR_Error=false; return $error->getUserInfo(); } if (!$recordSet) return NULL; return $recordSet->fields; } /** * Do a select and return all entries, null if no entry * * Do a select and return all entries, null if no entry * * @param string Sql query */ function select($query) { global $ADODB_Last_PEAR_Error; if (!eregi("^select ",$query)) return getMessage('not_a_select'); if ($error = makeDBConnexion()) return $error; global $dbConnexion; $recordSet = &$dbConnexion->Execute($query); if ($error = ADODB_Pear_Error()) { $ADODB_Last_PEAR_Error=false; return $error->getUserInfo(); } if (!$recordSet) return NULL; while (!$recordSet->EOF) { $result[] = $recordSet->fields; $recordSet->MoveNext(); } return $result; } /** * Do delete and return true if it work * * Do delete and return true if it work * * @param string SQL query */ function delete($query) { global $ADODB_Last_PEAR_Error; if (!eregi("^delete ",$query)) return getMessage('not_a_delete'); if ($error = makeDBConnexion()) return $error; global $dbConnexion; $dbConnexion->Execute($query); if ($error = ADODB_Pear_Error()) { $ADODB_Last_PEAR_Error=false; return $error->getUserInfo(); } return NULL; } /** * Do udpate and return true if it work * * Do udpate and return true if it work * * @param string SQL query */ function write($query) { global $ADODB_Last_PEAR_Error; if (!eregi("^update ",$query) && !eregi("^insert ",$query)) return getMessage('not_an_update'); if ($error = makeDBConnexion()) return $error; global $dbConnexion; $dbConnexion->Execute($query); if ($error = ADODB_Pear_Error()) { $ADODB_Last_PEAR_Error=false; return $error->getUserInfo(); } return NULL; } /** * Start transactions * * Begin transactions in smart transaction mode */ function startTrans(){ if ($error = makeDBConnexion()) return $error; global $dbConnexion; $dbConnexion->StartTrans(); } /** * Has Faild transaction * * Check if a the current transaction has failed. Return true id it does; * * @return bool Transaction as failed */ function hasFailedTrans() { if ($error = makeDBConnexion()) return $error; global $dbConnexion; return $dbConnexion->HasFailedTrans(); } /** * Genrate failure in transaction */ function failTrans() { if ($error = makeDBConnexion()) return $error; global $dbConnexion; $dbConnexion->FailTrans(); } /** * Complete Transaction * * End transactions in smart mode. */ function completeTrans(){ if ($error = makeDBConnexion()) return $error; global $dbConnexion; $dbConnexion->CompleteTrans(); } /** * Convert unix time to DBtime * * Convert unix time to DBtime * * @param string Time in second since 1970 */ function UnixToDB($timeStamp) { if ($error = makeDBConnexion()) return NULL; global $dbConnexion; return $dbConnexion->DBTimeStamp($timeStamp); } /** * Convert DBtime to unix * * Convert DBtime to unix * * @param string Time from DB */ function DBToUnix($timeStamp) { if ($error = makeDBConnexion()) return NULL; global $dbConnexion; return $dbConnexion->UnixTimeStamp($timeStamp); } /** * Quote String to avoid sql injection * * @param string */ function qstr($string) { if ($error = makeDBConnexion()) return NULL; global $dbConnexion; return $dbConnexion->qstr($string); } ?> ltsp-cluster-control-2.0.3/Admin/util/HWGroupManagerView.php0000664000175000017500000000563512026403127024246 0ustar stgraberstgraber getHwKey()) { $key = "value=".qstr($hwGroupRule->getHwKey()).""; } else { $key = ""; } if ($hwGroupRule->getHwValue()) { $value = "value=".qstr($hwGroupRule->getHwValue()).""; } else { $value = ""; } ?> /> getOperators(); if(!empty($opers)){ ?> />

    hwGroupRules)){ $id=0; foreach ($this->hwGroupRules as $hwGroupRule) { printHwGroupInput($hwGroupRule,++$id); } } ?>

    hwGroupRules)) { ?>

    operators)){ ?> " />

    printErrors(); ?>
    ltsp-cluster-control-2.0.3/Admin/util/AttributesManager.php0000664000175000017500000001661012026403127024201 0ustar stgraberstgraberpermissions = $permissions; if (strtolower(get_class($node)) != "node"){ $this->isError = true; return; } if ($node->isError) { $this->isError = true; return; } $this->attributeClass = $attributeClass; $this->nodeTypes = $nodeTypes; $this->isError = false; ///////////////////////// // Node type validation ///////////////////////// if(!in_array($node->nodetype,$nodeTypes)){ $this->errors[] =getMessage("invalid_uga_node"); $this->showAttributesView = "false"; return NULL; } ///////////////////////// // Actions ///////////////////////// // Cancel if (isset($_POST['cancel'])) { unset($GLOBALS['_POST']); } $this->attributes = $node->getAttributes(); // remove attribute with cannot read permission if(!empty($this->attributes)){ foreach ($this->attributes as $key=>$attribute) { $hasPermission = $this->permissions->canReadAttribute($attribute->getName(),$attribute->getAttClass()); if($hasPermission==0){ unset($this->attributes[$key]); } } } if (is_array($_POST['newAttributes'])) { foreach ($_POST['newAttributes'] as $attribute) { $this->attributes[$attribute] = new AttributeDef($attribute); } } // Add an attribute if (isset($_POST['add_attr'])) { $_POST['newAttributes'][] = $_POST['newAttribute']; $this->attributes[$_POST['newAttribute']] = new AttributeDef($_POST['newAttribute']); unset($_POST['newAttribute']); } // Deleting attributes if (isset($_POST['delete_attr'])) { if (is_array($_POST['selection'])) { //validate permission $hasPermission=-1; $cannotDelete=""; foreach ($_POST['selection'] as $id) { if (strtolower(get_class($this->attributes[$id]))== "attribute") { $hasPermission = $permissions->canDeleteAttribute($this->attributes[$id]->getName(),$this->attributes[$id]->getAttClass()); if($hasPermission == 0){ $cannotDelete=$this->attributes[$id]->getName(); break; } } //If the attribute is new (it is not save in database, you can delete it) if (strtolower(get_class($this->attributes[$id]))== "attributedef") { unset($this->attributes[$id]); } } if($hasPermission == 1){ foreach ($_POST['selection'] as $id) { if (strtolower(get_class($this->attributes[$id]))== "attribute") { if ($error = $this->attributes[$id]->delete()) { $this->errors[] = $error; unset($error); }else{ logAdminAccess(array("DELETE ATTRIBUTE","NODE ID : ".$this->attributes[$id]->getNodeID(),"ATTRIBUTE NAME : ".$this->attributes[$id]->getName())); } } unset($this->attributes[$id]); } }else if($hasPermission == 0){ $this->errors[] = getMessage("no_permission_to_delete_attribute").$cannotDelete; } } } // Modify attributes if (isset($_POST['modify_attr']) && $this->attributes) { foreach($this->attributes as $id => $attr) { $postValue=$_POST[$attr->getName()]; //get the list value (if selected) if (isset($_POST["list".$attr->getName()]) && $_POST["list".$attr->getName()]!="-1") { //Careful, the name is hardcoded with the string "list" in attributesManagerView $postValue=$_POST["list".$attr->getName()]; } if (strtolower(get_class($attr))== "attribute") { //Check if any changes if($_POST["hidden".$attr->getName()] != $postValue){ $hasPermission = $permissions->canWriteAttribute($attr->getName(),$attr->getAttClass()); if($hasPermission == 1){ if (!$this->attributes[$id]->setValue($postValue)) { $this->errors[] = $this->attributes[$id]->lastError(); } else { logAdminAccess(array("MODIFY ATTRIBUTE","NODE ID : ".$this->attributes[$id]->getNodeID(),"ATTRIBUTE NAME : ".$this->attributes[$id]->getName())); unset($_POST[$attr->getName()]); } }else{ $this->errors[] = getMessage("no_permission_to_write_attribute").$attr->getName(); unset($_POST[$attr->getName()]); } } } elseif (strtolower(get_class($attr))== "attributedef") { if (!$realAttr = $this->attributes[$id]->buildAttribute($node,$postValue)) { $this->errors[] = $this->attributes[$id]->lastError(); } else { logAdminAccess(array("ADD ATTRIBUTE","NODE ID : ".$realAttr->getNodeID(),"ATTRIBUTE NAME : ".$realAttr->getName())); $this->attributes[$realAttr->getAttributeDefID()] = $realAttr; unset($_POST[$realAttr->getName()]); } } } } // Generating all attribute list $this->allAttributes = $this->getAllAttributes($node->nodetype); if (is_array($this->attributes)) { foreach ($this->attributes as $attribute) { unset($this->allAttributes[$attribute->getAttributeDefID()]); } } //Show hardware specification if($node->nodetype == COMPUTER_TYPE){ $this->hardware = $node->getHardware(); $this->node = $node; } } function getAllAttributes($type) { //Generate IN condition $inCondition=""; for ($index = 0; $index < sizeof($this->attributeClass); $index++) { $inCondition = $inCondition."".qstr($this->attributeClass[$index]).""; if($index <(sizeof($this->attributeClass))-1){ $inCondition = $inCondition.","; } } $attributes = select("SELECT id,name,attributeClass FROM attributesDef WHERE attributeclass IN(".$inCondition.") ORDER BY name"); if (!is_null($attributes) && !is_array($attributes)) { $this->errors[] = getMessage('db_error').$attributes; $this->isError = true; return NULL; } if (is_array($attributes)) { foreach ($attributes as $attribute) { //Include only attribute with read and add permission $hasPermission = $this->permissions->canAddAttribute($attribute['name'],$attribute['attributeclass']); if($hasPermission==1){ $attributesAssoc[$attribute['id']] = $attribute['name']; } } } return $attributesAssoc; } function isError() { return $this->isError; } function printErrors() { if (isset($this->errors[0])) print "

    \n"; else return; foreach ($this->errors as $error) { print "".$error."
    \n"; } print "

    \n"; } function printView() { if ($this->isError) { $this->printErrors(); return; } if($this->showAttributesView != 'false') include 'attributesManagerView.php'; } } ?> ltsp-cluster-control-2.0.3/Admin/util/modules-config.php0000664000175000017500000000230612026403127023470 0ustar stgraberstgraber_module and module PHP file to be * included into modules var. * * Author: Nicolas Dufresne */ $MODULES['configuration_module'] = 'configuration.php'; $MODULES['entity_module'] = 'entity.php'; $MODULES['managelist_module'] = 'managelist.php'; $MODULES['nodesManager_module'] = 'nodesManager.php'; $MODULES['printing_module'] = 'managePrinterslist.php'; $MODULES['setup_module'] = 'setup.php'; $MODULES['logs_module'] = 'logs.php'; $MODULES['info_module'] = 'info.php'; $MODULES['stats_module'] = 'stats.php'; ?> ltsp-cluster-control-2.0.3/Admin/util/Attribute.php0000664000175000017500000001755512026403127022534 0ustar stgraberstgraber * - Creation */ require_once 'AttributeDef.php'; require_once 'dbFunctions.php'; class Attribute { var $node_id; var $def_id; var $value; var $name; var $type; var $attClass; var $mask; var $editable; var $selection; var $isError; var $notFound; function Attribute($nodeId,$defId=NULL) { $this->isError = false; $this->noFound = false; if (is_numeric($nodeId)) { if (!$attribute = $this->getFromDB("*", "nodes_id=".$nodeId." AND attributesdef_id = ".$defId)) return; } else if (is_array($nodeId)) { $attribute = $nodeId; } else { $this->isError = true; $this->lastError = getMessage('bad_id')."nodeid=".$nodeId.", defid=".$defId; return; } //$this->id = $attribute['id']; $this->value = $attribute['value']; $this->node_id = $attribute['nodes_id']; $this->def_id = $attribute['attributesdef_id']; if (isset($attribute['name'])) { $definition = $attribute; } else { $definition = $this->getFromDB("*", "id=".$this->def_id, "attributesDef"); } $this->name = $definition['name']; $this->type = $definition['attributetype']; $this->attClass = $definition['attributeclass']; $this->mask = $definition['mask']; $this->editable = $definition['editable']; } // private function getFromDB($column,$where,$from="attributes",$isFatal=true, $multiple = false) { $query = 'SELECT '.$column.' FROM '.$from.' WHERE '.$where; if ($multiple) { $result = select($query); } else { $result = singleResultSelect($query); } if (!$result) { if (($from == "attributes") && $isFatal) $this->lastError = getMessage('attribute_not_found')." : ".$where; else $this->lastError = getMessage('not_found').$query; $this->notFound = true; if ($isFatal) $this->isError = true; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error').$result." : ".$query; if ($isFatal) $this->isError = true; return NULL; } else return $result; } // private function updateDB($toSet,$table="attributes", $where = "id") { if ($where == "id") $where = "nodes_id=".$this->node_id." AND attributesdef_id = ".$this->def_id; $query = "UPDATE ".$table." SET ".$toSet." WHERE ".$where; if ($error = write($query)) { $this->lastError = getMessage('db_write_error').$error." : ".$query; return false; } else return true; } ////////////////////////////////////////////////////////////////// // Getters ////////////////////////////////////////////////////////////////// function getNodeID() { return $this->node_id; } function getAttributeDefID() { return $this->def_id; } function getName() { return $this->name; } function getAttClass() { return $this->attClass; } function getValue() { if ($this->isError) return NULL; if ($this->type < 2) { return $this->value; } else { $this->getSelection(); if (is_array($this->selection)) { foreach ($this->selection as $value => $selected) { if ($selected) { if ($result) $result .= ","; $result .= $value; } } } return $result; } } function getType() { return $this->type; } function getMask() { return $this->mask; } function getEditable() { return $this->editable; } // Use Lazy loading for selection function getSelection() { if (!is_array($this->selection) && ($this->type >= 1 || $this->editable)) { $column = "value"; $where = "attributesdef_id=".$this->def_id." ORDER BY sortval,value"; $tableName = "attributesDefDict"; $dictionary = $this->getFromDB($column, $where, $tableName, true, true); if (is_null($dictionary)) return; if ($this->type == 1) { $selected[0]['value'] = $this->value; } if ($this->type == 2) { $column = "value"; $where = "attributesdef_id=".$this->def_id." AND nodes_id=".$this->node_id; $tableName = "attributesSelect"; $selected = $this->getFromDB($column, $where, $tableName, true, true); if (is_null($selected)) { if ($this->notFound) { $this->isError = false; } else return; } } foreach ($dictionary as $value) { $this->selection[$value['value']] = false; } if (is_array($selected)) { foreach ($selected as $value) { $this->selection[$value['value']] = true; } } } return $this->selection; } function isError() { return $this->isError; } function lastError() { return $this->lastError; } function notFound() { return $this->NotFound; } ////////////////////////////////////////////////////////////////// // Setters ////////////////////////////////////////////////////////////////// function delete() { $error = NULL; if ($this->type == 2) { delete("DELETE FROM attributesSelect WHERE nodes_id=".$this->node_id." AND attributesdef_id=".$this->def_id); if ($error) $error.= " : "; } $error .= delete("DELETE FROM attributes WHERE nodes_id=".$this->node_id." AND attributesdef_id=".$this->def_id); return $error; } function setValue($newValue) { if ($this->isError) return false; switch ($this->type) { case 0: if (ereg($this->mask,$newValue)) { if (!$this->updateDB("value=".qstr($newValue)."")) return false; $this->value = $newValue; return true; } $this->lastError = getMessage('invalide_value').$this->name." = ".$newValue; return false; case 1: $newValue = $newValue[0]; $this->getSelection(); if (isset($this->selection[$newValue])) { if (!$this->updateDB("value=".qstr($newValue)."")) return false; $this->selection[$this->value] = false; $this->selection[$newValue] = true; $this->value = $newValue; return true; } return false; case 2: $temp = $newValue; unset($newValue); if (is_array($temp)) { foreach ($temp as $value) { $newValue[$value] = true; } } $this->getSelection(); $temp = $this->selection; foreach ($temp as $value => $selected) { $temp[$value] = false; } // Complete newArray temp one if (is_array($newValue)) { $newValue = array_merge($temp, $newValue); } else { $newValue = $temp; } // Check if new element accidently added foreach ($newValue as $value => $selected) { if (!isset($this->selection[$value])) { $this->lastError = getMessage('invalide_value').$value; return false; } } startTrans(); $deleteQuery = "DELETE FROM attributesSelect WHERE nodes_id=".$this->node_id." AND attributesdef_id=".$this->def_id; $errors[] = delete($deleteQuery); foreach ($newValue as $value => $selected) { if ($selected) { $query = "INSERT INTO attributesSelect (nodes_id,attributesdef_id,value) VALUES "; $query .= "(".$this->node_id.",".$this->def_id.",".qstr($value).")"; $errors[] = write($query); } } $failed = hasFailedTrans(); completeTrans(); if ($failed) { $this->lastError = getMessage('db_error'); foreach ($errors as $error) { $this->lastError .= " : ".$error; } return false; } else { $this->selection = $newValue; return true; } break; } } } ?> ltsp-cluster-control-2.0.3/Admin/util/text-en.php0000664000175000017500000005103312026403127022142 0ustar stgraberstgraberYou can add it in : \" Configurator Settings \" --> Configurator database or edit it manually in the config.php file.
    The query was"; $MESSAGES['no_db_password'][$lang] = "Missing the user password to access to the database
    You can add it in : \" Configurator Settings \" --> \" Configurator database \" or edit it manually in the config.php file.
    The query was"; $MESSAGES['no_db_name'][$lang] = "Missing database name<
    You can add it in : Configurator Settings --> Configurator database or edit it manually in the config.php file.
    The query was"; $MESSAGES['db_error'][$lang] = "Database query error : "; //////////////////////////////////////////////////////////////////// // Module names //////////////////////////////////////////////////////////////////// $MESSAGES['configuration_module'][$lang] = "Configuration"; $MESSAGES['nodesManager_module'][$lang] = "Nodes manager"; $MESSAGES['entity_module'][$lang] = "Group/user"; $MESSAGES['managelist_module'][$lang] = "Attributes lists values"; $MESSAGES['info_module'][$lang] = "Technical Infos"; $MESSAGES['logs_module'][$lang] = "Terminal Logs"; $MESSAGES['printing_module'][$lang] = "Printers manager"; $MESSAGES['stats_module_short'][$lang] = "Reports"; $MESSAGES['setup_module'][$lang] = "Control Center's settings"; $MESSAGES['configuration_module_short'][$lang] = "Configuration"; $MESSAGES['nodesManager_module_short'][$lang] = "Nodes"; $MESSAGES['entity_module_short'][$lang] = "Group/User"; $MESSAGES['managelist_module_short'][$lang] = "Attributes lists values"; $MESSAGES['info_module_short'][$lang] = "Technical infos"; $MESSAGES['logs_module_short'][$lang] = "Terminal logs"; $MESSAGES['printing_module_short'][$lang] = "Printers manager"; $MESSAGES['stats_module_short'][$lang] = "Reports"; $MESSAGES['setup_module_short'][$lang] = "Control Center's settings"; //////////////////////////////////////////////////////////////////// // Configurator setup section //////////////////////////////////////////////////////////////////// // General setup messages $MESSAGES['new_cfg_created'][$lang] = "The new configuration file has been created."; $MESSAGES['cannot_open_cfg_file'][$lang] = "Can't write the config.php config file."; $MESSAGES['exit'][$lang] = "Quit"; $MESSAGES['lock_setup'][$lang] = "Lock"; $MESSAGES['modify'][$lang] = "Save"; $MESSAGES['cfg_val_true'][$lang] = "Yes"; $MESSAGES['cfg_val_false'][$lang] = "No"; $MESSAGES['test'][$lang] = "Test"; // Language configuration section $MESSAGES['cfg_lang_section'][$lang] = "Language"; $MESSAGES['cfg_language'][$lang] = "Language for configurator interface"; $MESSAGES['cfg_charset'][$lang] = "Charset code for configurator web interface"; // Configurator Security section $MESSAGES['cfg_configurator_security_section'][$lang] = "Configurator security"; $MESSAGES['use_https'][$lang] = "Use https for configurator web interface"; $MESSAGES['need_https'][$lang] = 'This page needs an HTTPS connection.'; // Terminals Security section $MESSAGES['cfg_terminal_security_section'][$lang] = "Terminals security"; $MESSAGES['cfg_terminal_password'][$lang] = "Terminal password"; $MESSAGES['cfg_terminal_auth'][$lang] = "Terminal authentication"; // Configurator database section $MESSAGES['cfg_db_section'][$lang] = "Configurator database"; $MESSAGES['cfg_db_server'][$lang] = "Address of the server with the database"; $MESSAGES['cfg_db_user'][$lang] = "User name for database"; $MESSAGES['cfg_db_password'][$lang] = "Password for database (Default is empty)"; $MESSAGES['cfg_db_name'][$lang] = "Database name"; $MESSAGES['cfg_db_type'][$lang] = "Databasse type"; // Authentification configuration section $MESSAGES['cfg_auth_section'][$lang] = "Authentication system"; $MESSAGES['cfg_auth_name'][$lang] = "Enter authentication service for the configurator Web inteface"; // LDAP configuration (subsection of Authentification configuration) $MESSAGES['cfg_ldap_section'][$lang] = "LDAP configuration"; $MESSAGES['cfg_ldap_host'][$lang] = "URL of LDAP server"; $MESSAGES['cfg_ldap_basedn'][$lang] = "LDAP search base"; $MESSAGES['cfg_ldap_object_class'][$lang] = "User object class (not mandatory)"; $MESSAGES['cfg_ldap_group_object_class'][$lang] = "Group object class (not mandatory)"; $MESSAGES['cfg_ldap_group'][$lang] = "LDAP attribute group"; $MESSAGES['cfg_ldap_binddn'][$lang] = "LDAP user DN for reading the users and groups (Default is to bind as user)"; $MESSAGES['cfg_ldap_bindpw'][$lang] = "Previous user password"; $MESSAGES['cfg_ldap_uidAttribute'][$lang] = "Attribute used to search for user"; $MESSAGES['cfg_ldap_version'][$lang] = "LDAP protocol version (Default is 3)"; $MESSAGES['test_ldap'][$lang] = "Enter your LDAP login and password to test your ldap configuration"; // LDAP user and group rights association section $MESSAGES['ldap_group_role'][$lang] = "LDAP user and group rights association"; // Load balancer section $MESSAGES['cfg_loadbalancer_section'][$lang] = "Load balancer"; $MESSAGES['cfg_loadbalancer'][$lang] = "URL (Default value : localhost:8001)"; // printer servers section $MESSAGES['printer_server_section'][$lang] = "Printers servers (Cups)"; //////////////////////////////////////////////////////////////////// // Login Screen //////////////////////////////////////////////////////////////////// $MESSAGES['index_title'][$lang] = 'Configurator login'; $MESSAGES['no_language_file'][$lang] = "File text-.php not found on server, language not supported."; $MESSAGES['ask_uid'][$lang] = 'Enter your user name : '; $MESSAGES['ask_password'][$lang] = 'Enter your password : '; $MESSAGES['connect'][$lang] = 'Connect'; $MESSAGES['bad_login'][$lang] = 'Invalid login or password.'; $MESSAGES['good_login'][$lang] = 'User login successfull.'; //////////////////////////////////////////////////////////////////// // Search node Module //////////////////////////////////////////////////////////////////// $MESSAGES['id_or_mac'][$lang] = "Find a node by ID or MAC address : "; $MESSAGES['find'][$lang] = "Find"; $MESSAGES['go'][$lang] = "Go"; $MESSAGES['search_inv'][$lang] = "Find a node by its inventory number : "; //////////////////////////////////////////////////////////////////// // Configuration module //////////////////////////////////////////////////////////////////// $MESSAGES['source'][$lang] = "Source of element to manage"; $MESSAGES['nodes_editor_change_tree_name'][$lang] = "Node properties"; $MESSAGES['nodes_editor_manage_actual_nodes'][$lang] = "Childs"; $MESSAGES['nodes_editor_deselect'][$lang] = "Deselect"; $MESSAGES['config_attributes_listing'][$lang] = "Current configuration"; $MESSAGES['config_delete'][$lang] = "Delete"; $MESSAGES['config_modify'][$lang] = "Modify"; $MESSAGES['config_cancel'][$lang] = "Unckeck"; $MESSAGES['config_select_tree'][$lang] = "Browse the tree"; //////////////////////////////////////////////////////////////////// // User and group module //////////////////////////////////////////////////////////////////// $MESSAGES['add_user_group'][$lang] = "Add a "; $MESSAGES['user'][$lang] = "User"; $MESSAGES['group'][$lang] = "Group"; $MESSAGES['users'][$lang] = "Users"; $MESSAGES['groups'][$lang] = "Groups"; $MESSAGES['search_user_group'][$lang] = "User or group name"; $MESSAGES['invalide_node_name'][$lang] = "Invalid name :"; $MESSAGES['db_duplicate_value'][$lang] = "Duplicate value"; //////////////////////////////////////////////////////////////////// // Ldap messages at Login Screen //////////////////////////////////////////////////////////////////// $MESSAGES['ldap_cant_connect'][$lang] = 'Cannot contact the specified LDAP server at URL : '.$CONFIG['ldap_host']; $MESSAGES['ldap_connected'][$lang] = 'You are already connected to LDAP server.'; $MESSAGES['ldap_not_connected'][$lang] = 'Unable to close the LDAP connection.'; $MESSAGES['ldap_version_not_supported'][$lang] = 'The LDAP Server does not support LDAP version '.$CONFIG['ldap_version'].' protocol.'; $MESSAGES['ldap_user_bind'][$lang] = 'Missing parameter binddn or bindpw in configuration, binding as user'; $MESSAGES['ldap_no_basedn'][$lang] = 'Missing parameter basedn in configuration.'; $MESSAGES['ldap_cant_bind'][$lang] = 'Cannot bind to ldap server, verify that bindn is correct.'; $MESSAGES['ldap_no_host'][$lang] = 'No LDAP host specified in configuration.'; $MESSAGES['ldap_no_group'][$lang] = 'No LDAP attribute group specified in configuration.'; //////////////////////////////////////////////////////////////////// // Group/User Module //////////////////////////////////////////////////////////////////// $MESSAGES['entity_add_entity_message'][$lang] = "Add users and groups"; $MESSAGES['entity_manage_user_group'][$lang] = "Manage users and groups"; $MESSAGES['newDefaultValueListAttribute'][$lang] = ""; //////////////////////////////////////////////////////////////////// // Report module //////////////////////////////////////////////////////////////////// $MESSAGES['stats_module'][$lang] = "Reports"; $MESSAGES['stats_node_selector_msg'][$lang] = "Select the elements to treat"; $MESSAGES['stats_true_conditions'][$lang] = "Select the conditions to which the attributes of the elements must correspond"; $MESSAGES['stats_false_conditions'][$lang] = "Select the conditions to which the attributes of the elements must not correspond"; $MESSAGES['stats_add_cond'][$lang] = "Add"; $MESSAGES['stats_add_value'][$lang] = "Add"; $MESSAGES['stats_selected_value'][$lang] = "Selected condition"; $MESSAGES['stats_select_what'][$lang] = "Work with : "; $MESSAGES['stats_terminals'][$lang] = "Terminals"; $MESSAGES['stats_contexts'][$lang] = "Contexts"; $MESSAGES['stats_contexts_n_terminals'][$lang] = "Terminals and contexts"; $MESSAGES['stats_use_heritage'][$lang] = "Consider inherited attributes"; $MESSAGES['stats_yes'][$lang] = "Yes"; $MESSAGES['stats_no'][$lang] = "No"; $MESSAGES['stats_send'][$lang] = "Continue"; $MESSAGES['stats_validate'][$lang] = "Ok"; $MESSAGES['stats_configuration'][$lang] = "Configuratinon attributes"; $MESSAGES['stats_network'][$lang] = "Network attributes"; $MESSAGES['stats_hardware'][$lang] = "Hardware attributes"; $MESSAGES['stats_select_attr_title'][$lang] = "Select the attributes you want to show in the report"; $MESSAGES['stats_select_attr_config'][$lang] = "Configuration attributes :"; $MESSAGES['stats_select_attr_hardware'][$lang] = "Hardware attributes :"; $MESSAGES['stats_select_attr_network'][$lang] = "Network attributes :"; $MESSAGES['stats_select_attr_type'][$lang] = "Show report as :"; $MESSAGES['stats_generate'][$lang] = "Generate report"; $MESSAGES['stats_select_attr_type_context'][$lang] = "Context"; $MESSAGES['stats_select_attr_type_table'][$lang] = "Tables"; $MESSAGES['stats_attribute'][$lang] = "Attributes"; $MESSAGES['stats_report_no_attr'][$lang] = "No attributes to show with those which were selected."; $MESSAGES['stats_equals'][$lang] = "Is equal to"; $MESSAGES['stats_unequals'][$lang] = "Is not equal to"; $MESSAGES['stats_greater'][$lang] = "Is greater than"; $MESSAGES['stats_greater_equals'][$lang] = "Is greater or equal than"; $MESSAGES['stats_lower'][$lang] = "Is lower than"; $MESSAGES['stats_lower_equals'][$lang] = "Is lower or equal than"; $MESSAGES['stats_no_node'][$lang] = "No attributes have been selected to treat."; $MESSAGES['stats_and'][$lang] = "AND"; $MESSAGES['stats_or'][$lang] = "OR"; $MESSAGES['stats_node'][$lang] = "Element"; $MESSAGES['stats_path'][$lang] = "Path"; //////////////////////////////////////////////////////////////////// // Printer Module //////////////////////////////////////////////////////////////////// $MESSAGES['printer_manage'][$lang] = "Apply"; $MESSAGES['printer_manage_list'][$lang] = "Printer server to manage"; $MESSAGES['printer_server_list'][$lang] = "Printer list of "; $MESSAGES['printer_add'][$lang] = "Add"; $MESSAGES['printer_delete'][$lang] = "Delete"; $MESSAGES['printer_database'][$lang] = "Installed printer in the configurator data base"; $MESSAGES['printer_servers'][$lang] = "Aviables printers"; $MESSAGES['printer_standalone_list'][$lang] = "Standalones printers list"; $MESSAGES['printer_add_a_standalone'][$lang] = "Add standalones printers"; $MESSAGES['printer_no_printer_standalone'][$lang] = "There's no standalone printer defined."; $MESSAGES['printer_warning_standalone'][$lang] = "Warning : A printer can be in the standalones printers list if his server is not online.
    These printers will back in the server list when the server will be online"; $MESSAGES['printer_no_server'][$lang] = "The DNS name exist but there's no answer from the server"; $MESSAGES['printer_dead_server'][$lang] = "There's so answer from server."; $MESSAGES['printer_no_printer_server'][$lang] = "There is no printer server defined.

    If you want, you can add at this place : \" ".getMessage('setup_module')." \" --> \" ".getMessage('printer_server_section')." \"
    Nevertheless, you can still use the \" ".getMessage('printer_standalone_list')." \""; $MESSAGES['printer_check_all'][$lang] = "Select All"; //////////////////////////////////////////////////////////////////// // Log Module //////////////////////////////////////////////////////////////////// $MESSAGES['logs_note'][$lang] = "Terminals activity: from most recent to the oldest"; $MESSAGES['logs_ts'][$lang] = "Date and time"; $MESSAGES['logs_id'][$lang] = "Terminal
    Node ID"; $MESSAGES['logs_mac'][$lang] = "MAC Address"; $MESSAGES['logs_ip'][$lang] = "Terminal
    Address"; $MESSAGES['logs_bootservip'][$lang] = "Boot Server
    Address"; $MESSAGES['logs_appservip'][$lang] = "Application Server
    Address"; $MESSAGES['logs_display'][$lang] = "\$Display"; $MESSAGES['logs_username'][$lang] = "User Name"; $MESSAGES['logs_code'][$lang] = "Event"; $MESSAGES['logs_bootservretry'][$lang] = "Bootserver entry"; $MESSAGES['logs_appservretry'][$lang] = "Appserver entry"; $MESSAGES['logs_prev'][$lang] = "Prev"; $MESSAGES['logs_next'][$lang] = "Next"; $MESSAGES['logs_nb_logs_message'][$lang] = "Results per page"; $MESSAGES['logs_filter_message'][$lang] = "Filters"; $MESSAGES['logs_table_message'][$lang] = "Results"; $MESSAGES['logs_validate'][$lang] = "Apply"; $MESSAGES['logs_code_booting'][$lang] = "Terminal booting"; $MESSAGES['logs_code_GDM'][$lang] = "Login screen"; $MESSAGES['logs_code_logging'][$lang] = "User login"; $MESSAGES['logs_code_unlogging'][$lang] = "User Logout"; $MESSAGES['logs_msg_filter_seizure'][$lang] = "Filter seizure"; $MESSAGES['logs_msg_active_filters'][$lang] = "Active filters"; $MESSAGES['logs_code_msg_legend'][$lang] = "Event legend"; $MESSAGES['logs_equals'][$lang] = "="; $MESSAGES['logs_greater'][$lang] = ">"; $MESSAGES['logs_gt_equals'][$lang] = ">="; $MESSAGES['logs_smaller'][$lang] = "<"; $MESSAGES['logs_sm_equals'][$lang] = "<="; $MESSAGES['logs_not_equals'][$lang] = "!="; $MESSAGES['logs_send_add_filter'][$lang] = "Add filter"; $MESSAGES['logs_send_remove_filter'][$lang] = "Remove all filters"; $MESSAGES['messages_error'][$lang] = 'This message is not set in text-en.php'; unset($lang); ?> ltsp-cluster-control-2.0.3/Admin/util/Permission.php0000664000175000017500000000400612026403127022704 0ustar stgraberstgraber * - Creation */ class Permission { var $nodeId; var $attribute; var $scope; var $canadd; var $candelete; var $canread; var $canwrite; function Permission($nodeId, $attribute,$scope, $canadd, $candelete, $canread, $canwrite) { $this->nodeId=$nodeId; $this->attribute= $attribute; $this->scope=$scope; $this->canadd=$canadd; $this->candelete=$candelete; $this->canread=$canread; $this->canwrite=$canwrite; } /** getters **/ function getNodeId() { return $this->nodeId; } function getAttribute() { return $this->attribute; } function getScope() { return $this->scope; } function getCanadd() { return $this->canadd; } function getCandelete() { return $this->candelete; } function getCanread() { return $this->canread; } function getCanwrite() { return $this->canwrite; } /** setters **/ function setNodeId($nodeId){ $this->nodeId = $nodeId; } function setAttribute($attribute){ $this->attribute = $attribute; } function setScope($scope){ $this->scope = $scope; } function setCanadd($canadd){ $this->canadd = $canadd; } function setCandelete($candelete){ $this->candelete = $candelete; } function setCanread($canread){ $this->canread = $canread; } function setCanwrite($canwrite){ $this->canwrite = $canwrite; } } ?>ltsp-cluster-control-2.0.3/Admin/util/Node.php0000664000175000017500000007752212026403127021456 0ustar stgraberstgraber *
  • ID of the node *
  • MAC adress of the node *
  • IP of the node * * * The first two cases read the database directly, the second one read * the state table and make the correspondance IP adress, MAC adress. * As a consequence, all IP address should be unique so that it can act * as another primary key for the node. * Example of valid initialisation : * * * $node=new Node(0); // Use the node ID initialisation * $node=new Node(00:05:5D:FE:FC:E2); //Use the node MAC initialisation * $node=new Node("192.168.2.232"); //Use the status table * // (of course, IP should have been registred before !) * * * @access public */ function Node($id = "Default") { global $CONFIG; $this->ok = true; $this->noFound = false; $defaultNodeID = false; if ($id == "Default") { if (is_numeric($CONFIG['default_node'])) { $id = $CONFIG['default_node']; $defaultNodeID = true; } else { $id = 0; } } if (is_numeric($id)) { $node = $this->getFromDB("*", "id=" . $id); if ($this->notFound() && $defaultNodeID) { $id = 0; $node = $this->getFromDB("*", "id=" . $id); } } elseif (is_array($id)) { $node = $id; } elseif ($this->isMac($id) && $id != "00:00:00:00:00:00") { $id = strtoupper($id); $node = $this->getFromDB("*", "mac='" . $id . "'"); } elseif ($this->isIP($id)) { $node = $this->getFromDB("*", "S.ip='" . $id . "'", "status S INNER JOIN nodes N on S.id=N.id"); } elseif ($this->isDNS($id)) { $id = gethostbyname($id); $node = $this->getFromDB("*", "S.ip='" . $id . "'", "status S INNER JOIN nodes N on S.id=N.id"); } else { $node = $this->getFromDB("*", "name=" . qstr($id) . ""); if (!$node) { $this->ok = false; $this->lastError = getMessage('bad_node_id') . " : id=" . $id; } } $this->id = $node['id']; $this->name = $node['name']; $this->id_parent = $node['id_parent']; $this->leftval = $node['leftval']; $this->rightval = $node['rightval']; $this->mac = $node['mac']; $this->reference = $node['reference']; $this->nodetype = $node['nodetype']; } /////////////////////////////////////////////////////////////////// // Status functions /////////////////////////////////////////////////////////////////// /** * Return true if it is node, false if it is a computer, user, group or hardware group * * @access public * @return boolean */ function isNode() { return $this->nodetype == NODE_TYPE; } /** * Return true if it is entity * * @access public * @return boolean */ function isEntity() { return $this->nodetype == GROUP_TYPE || $this->nodetype == USER_TYPE; } /** * Return true if it is computer * * @access public * @return boolean */ function isComputer() { return $this->nodetype == COMPUTER_TYPE; } /** * Return true if it is hwGroup * * @access public * @return boolean */ function isHwGroup() { return $this->nodetype == HWGROUP_TYPE; } /** * Return false if no error, true otherwise * * @access public * @return boolean */ function isError() { return !$this->ok; } /** * Return the last error as string * * @access public * @return string */ function lastError() { return $this->lastError; } /** * True if node was not found during construction, false otherwise. * * @access private * @return boolean */ function notFound() { return $this->notFound; } /** * True if is a MAC, false otherwise. * * @access public * @return boolean */ function isMac($mac) { return eregi("^([0-9a-f]{2}:){5}[0-9a-f]{2}$", $mac); } /** * True if is a IP, false otherwise. * * @access private * @return boolean */ function isIP($ip) { return ereg("^([0-2]{0,1}[0-9]{1,2}\.){3}[0-2]{0,1}[0-9]{1,2}$", $ip); } /** * True if is a DNS address, false otherwise. * * @access private * @return boolean */ function isDNS($ip) { return ereg("^(.*\.){2}.*$", $ip); } /////////////////////////////////////////////////////////////////// // Database functions with error management /////////////////////////////////////////////////////////////////// /** * Function to read node information from the DB * * @access private * @return mixed : NULL or assoc */ function getFromDB($column, $where, $from = "nodes", $isFatal = true) { if (!$result = singleResultSelect('SELECT ' . $column . ' FROM ' . $from . ' WHERE ' . $where)) { if (($from == "nodes" || $from == "status") && $isFatal) $this->lastError = getMessage('node_not_found') . " : " . $where; else $this->lastError = getMessage('not_found') . 'SELECT ' . $column . ' FROM ' . $from . ' WHERE ' . $where; $this->notFound = true; if ($isFatal) $this->ok = false; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error') . $result . " : " . 'SELECT ' . $column . ' FROM ' . $from . ' WHERE ' . $where; if ($isFatal) $this->ok = false; return NULL; } else return $result; } /** * Function to update node information in the DB * * @access private * @return boolean */ function updateDB($toSet, $table = "nodes") { if ($error = write("UPDATE " . $table . " SET " . $toSet . " WHERE id=" . $this->id)) { $this->lastError = getMessage('db_write_error') . $error . " : " . "UPDATE " . $table . " SET " . $toSet . " WHERE id=" . $this->id; return false; } else return true; } /** * Function to insert node information in the DB * * @access private * @return boolean */ function insertDB($data, $table = "nodes") { if (!$this->ok) return false; if (!is_array($data)) return false; foreach ($data as $name => $value) { if ($list) $list .= ","; $list .= $name; if ($dataList) $dataList .= ","; $value = qstr($value); $dataList .= $value; } if ($error = write("INSERT INTO " . $table . " (" . $list . ") VALUES (" . $dataList . ")")) { $this->lastError = getMessage('db_write_error') . $error . " : " . "INSERT INTO " . $table . " (" . $list . ") VALUES (" . $dataList . ")"; return false; } else return true; } /** * Function to update the node status in the DB * Please use the setStatus method for a public usage * * @access private * @return boolean */ function updateStatus($status, $isNew = false) { if (!$this->ok) return false; if (!is_array($status)) return false; if ($isNew) return $this->insertDB($status, "status"); foreach ($status as $name => $value) { if ($toSet) $toSet .= ","; $value = qstr($value); $toSet .= $name . "=" . $value; } return $this->updateDB($toSet, "status"); } /** * Function to insert a log. * Please use the setStatus method for a public usage. Internal method * * @access private * @return boolean */ function insertLog($status) { if (!$this->ok) return false; if (!is_array($status)) return false; $status['id'] = $this->id; $status['mac'] = $this->mac; unset ($status['ts_lastbootservip']); unset ($status['ts_lastappservip']); unset ($status['publickey']); unset ($status['termaccess']); $status['ts'] = UnixToDB(time()); return $this->insertDB($status, "log"); } /////////////////////////////////////////////////////////////////// // Node getters /////////////////////////////////////////////////////////////////// /** * get the node Id * * @access public * @return int */ function getID() { return $this->id; } /** * get the leftval * * @access public * @return int */ function getLeftval() { return $this->leftval; } /** * get the rightval * * @access public * @return int */ function getRightval() { return $this->rightval; } /** * get the node parent Id * * @access public * @return int */ function getParentID() { return $this->id_parent; } /** * get the node name * * @access public * @return string */ function getName() { return $this->name; } /** * get the node reference * * @access public * @return string */ function getReference() { return $this->reference; } /** * get the node MAC * * @access public * @return string */ function getMac() { return $this->mac; } /** * get the node status * * @access public * @return assoc */ function getStatus() { if (!$this->ok) return NULL; if (!$this->isComputer()) { $this->lastError = getMessage('cannot_get_status') . getMessage('not_computer'); return NULL; } return $this->getFromDB("*", "id=" . $this->id, "status", false); } /** * get the node childrens * * @access public * @return mixed : NULL or array of childrens */ function getChildrens() { if ($this->isError()) return NULL; if (!$this->isNode()) return NULL; $childrens = select('SELECT * FROM nodes WHERE id_parent=' . $this->id . ' AND nodetype IN ('.NODE_TYPE.','.COMPUTER_TYPE.','.HWGROUP_TYPE.','.GROUP_TYPE.','.USER_TYPE.') ORDER BY mac,name'); if (!is_array($childrens) && !is_null($childrens)) { $this->lastError = getMessage('db_error') . $childrens; return NULL; } if (is_null($childrens)) { $this->lastError = ""; return NULL; } foreach ($childrens as $child) { // Remove exception where root is root's child if ($child['id'] != 0) $childrenList[] = new Node($child); } return $childrenList; } /** * get the parent node * * @access public * @return Node */ function getParent() { if ($this->isError()) return NULL; return new Node($this->id_parent); } /** * get all parents nodes * * @access public * @return array of Node */ function getParents() { $parents = select('SELECT * FROM nodes WHERE leftval<'.$this->rightval.' and rightval>'.$this->rightval.' ORDER BY leftval'); if (!is_array($parents)) { return NULL; } foreach ($parents as $parent) { $parentList[] = new Node($parent); } return $parentList; } /** * Get attribute by name * * @access public * @return array of Attribute */ function getAttribute($name) { if ($this->isError()) return NULL; $attributes = select("SELECT * FROM nodes N INNER JOIN attributes A ON A.nodes_id=N.id ". " INNER JOIN attributesDef AD ON A.attributesdef_id=AD.id " . " WHERE N.leftval<" . $this->rightval . " AND N.rightval>=" . $this->rightval . " AND AD.name=". qstr($name) ." ORDER BY N.leftval"); if (!is_array($attributes) && !is_null($attributes)) { $this->lastError = getMessage('db_error') . $attributes; return NULL; } if (is_null($attributes)) { $this->lastError = ""; return NULL; } return new Attribute($attributes[0]); } /** * Get all attributes implemented by this node * * @access public * @return array of Attribute */ function getAttributes() { if ($this->isError()) return NULL; $attributes = select('SELECT * FROM attributes A LEFT JOIN attributesDef AD ON A.attributesdef_id=AD.id ' . ' WHERE A.nodes_id=' . $this->id); if (!is_array($attributes) && !is_null($attributes)) { $this->lastError = getMessage('db_error') . $attributes; return NULL; } if (is_null($attributes)) { $this->lastError = ""; return NULL; } foreach ($attributes as $attribute) { $attributesList[$attribute['attributesdef_id']] = new Attribute($attribute); } return $attributesList; } /** * Get HWGroups * * @access public * @return array of Attribute */ function getHwGroupsRules() { if ($this->isError()) return NULL; if (!$this->isHwGroup()) { $this->lastError = getMessage('not_hwgroup'); return NULL; } $rules = select('SELECT * FROM hwgroupsrule WHERE nodes_id=' . $this->id); if (!is_array($rules) && !is_null($rules)) { $this->lastError = getMessage('db_error') . $rules; return NULL; } if (is_null($rules)) { $this->lastError = ""; return NULL; } foreach ($rules as $r) { $list[] = new HWGroupRule($r); } return $list; } /** * Get the computer hardware. */ function getHardware() { if (!$this->isComputer()) { $this->lastError = getMessage('cannot_set_status') . getMessage('not_computer'); return NULL; } $hwList = select('SELECT hwkey, hwvalue FROM computershw WHERE nodes_id=' . $this->id); return $hwList; } /** * (PDubois)Patrick Dubois - Created July 9th, 2008. * * This returns a boolean indicating this node belongs to a hardware group. * * */ function hasHWgroup(){ $hwgFinder = new HWGroupFinder($this, $this->getHardware()); if ( ! $hwgFinder->notFound() ) { return true; }else { return false; } } /** * (PDubois)Patrick Dubois - Created July 9th, 2008. * * This returns an array of node IDs containing the IDs * of all hardware groups the client may belong to. * * */ function getHWgroupIDs(){ $hwgFinder = new HWGroupFinder($this, $this->getHardware()); if ( ! $hwgFinder->notFound() ) { return $hwgFinder->getNodesIds(); }else { return $node->getID(); } } /** * Get the herited LTS file * * This will return the complete LTS file for this node. * * @access public * @return assoc name => value */ function getExtendedLTS($nodesIds) { if (!is_array($nodesIds)) { return $this->getLTS(); } foreach ($nodesIds as $id) { if (!empty($id)) { $inClause .= ",".$id; } } if (empty($inClause)) { return $this->getLTS(); } $inClause = substr($inClause, 1); $attributes = select('SELECT * FROM nodes N INNER JOIN attributes A ON A.nodes_id=N.id '. 'LEFT JOIN attributesDef AD ON A.attributesdef_id=AD.id ' . 'WHERE (N.leftval<' . $this->rightval . ' AND N.rightval>=' . $this->rightval . ') ' . 'OR (N.id IN (' . $inClause . ')) ' . 'ORDER BY N.leftval'); if (!is_array($attributes)) { return NULL; } # Group attributes by type $computerAttr=array(); $hwgroupAttr=array(); $groupAttr=array(); $userAttr=array(); foreach ($attributes as $attr) { $attribute = new Attribute($attr); switch ($attr['nodetype']) { case NODE_TYPE: case COMPUTER_TYPE: $computerAttr[] = $attribute; break; case HWGROUP_TYPE: $hwgroupAttr[] = $attribute; break; case GROUP_TYPE: $groupAttr[] = $attribute; break; case USER_TYPE: $userAttr[] = $attribute; break; } } # Build attribute list, lasts attributes overrides firsts attributes $allAttr = array_merge($computerAttr,$groupAttr,$userAttr,$hwgroupAttr); foreach ($allAttr as $attr) { $LTS[$attr->getName()] = $attr->getValue(); } if (is_array($LTS)) { return $LTS; } } /** * Get the herited LTS file * * This will return the complete LTS file for this node. The result * depend on parent LTS implementation * * @access public * @return assoc name => value */ function getLTS() { $attributes = select('SELECT * FROM nodes N INNER JOIN attributes A ON A.nodes_id=N.id '. 'LEFT JOIN attributesDef AD ON A.attributesdef_id=AD.id ' . ' WHERE N.leftval<' . $this->rightval . ' AND N.rightval>=' . $this->rightval . ' ORDER BY N.leftval'); if (!is_array($attributes)) { return NULL; } foreach ($attributes as $attr) { $attribute = new Attribute($attr); $LTS[$attribute->getName()] = $attribute->getValue(); } if (is_array($LTS)) { return $LTS; } } /////////////////////////////////////////////////////////////////// // Node setters /////////////////////////////////////////////////////////////////// /** * Delete this node * * If is in trash delete it, otherwise, put it in trash * * @access public * @return bool True if success, false otherwise */ function delete() { startTrans(); $rtv = $this->_delete(); completeTrans(); return $rtv; } /** * Delete this node (no transaction) * * If is in trash delete it, otherwise, put it in trash * * @access private * @return bool True if success, false otherwise */ function _delete() { if ($this->id == -1) { $this->lastError = getMessage('cannot_delete_trash'); return false; } if (!$this->isNode()) { if ($error = delete('DELETE FROM status WHERE id=' . $this->id)) { $this->lastError = $error; return false; } } if ($this->isInTrash()) { $result = $this->_destroy(); return $result; } $result = $this->setParent(-1); return $result; } /** * Destroy this node from DB * * @access public * @return True if Success */ function destroy() { startTrans(); $rtv = $this->_destroy(); completeTrans(); return $rtv; } /** * Destroy this node from DB * * @access private * @return True if Success */ function _destroy() { if ($this->id == -1) { $this->lastError = getMessage('cannot_delete_trash'); return false; } $ok = true; $childrens = $this->getChildrens(); if (is_array($childrens)) { foreach ($childrens as $child) { if (!$ok = $child->_delete()) { $this->lastError = $child->lastError(); break; } } } if ($ok) { $attributes = $this->getAttributes(); if (is_array($attributes)) { foreach ($attributes as $attribute) { if (!$ok = $attribute->delete()) { $this->lastError = $attribute->lastError(); break; } } } } if ($ok) { if ($error = delete('DELETE FROM nodes where id=' . $this->id)) { $this->lastError = $error; $ok = false; } } if ($ok) { $this->ok = false; $this->lastError = getMessage('deleted_node'); } return $ok; } /** * Is int trash * * @access public * @return bool True if in trash */ function isInTrash() { $parents = $this->getParents(); if (isset ($parents[1])) { return ($parents[1]->getID() == -1); } return false; } /** * set the node name * * @access public * @return boolean */ function setName($name) { if (strlen($name) == 0 && $this->isNode()) { $this->lastError = getMessage('empty_node_name'); return false; } elseif (strlen($name) > 254) { $this->lastError = getMessage('too_long_node_name'); return false; } else { if ($this->updateDB("name=" . qstr($name) . "")) { $this->name = $name; return true; } return false; } } /** * insert a Node. Need a name * * @access public * @return boolean */ function insertNode($name) { if ($error = write("INSERT into nodes (id_parent,name) values (" . $this->id . "," . qstr($name) . ")")) { $this->lastError = getMessage('db_write_error') . $error; return false; } else { // This won't work on another DB than PostgreSQL $id = singleResultSelect("SELECT currval('nodes_id_seq')"); $id = $id['currval']; return $id; } } /** * insert a computer. Need a its MAC adress * * @access public * @return boolean */ function insertComputer($mac) { if ($error = write("INSERT into nodes (id_parent,mac,nodetype) values (" . $this->id . "," . qstr($mac) . "," . COMPUTER_TYPE . ")")) { $this->lastError = getMessage('db_write_error') . $error; return false; } else { return true; } } /** * insert a Node. Need a name * * @access public * @return boolean */ function insertHWGroup($name) { if ($error = write("INSERT into nodes (id_parent,name,nodetype) values (" . $this->id . "," . qstr($name) . ",".HWGROUP_TYPE.")")) { $this->lastError = getMessage('db_write_error') . $error; return false; } else { // This won't work on another DB than PostgreSQL $id = singleResultSelect("SELECT currval('nodes_id_seq')"); $id = $id['currval']; return $id; } } /** * insert a entity (person or group) * * @access public * @return boolean */ function insertEntity($reference, $nodeType) { //The unique constraint (nodes_reference_type_unique_idx) don't do the job (may a bug in adodb)' $refCounts = singleResultSelect("SELECT count(*) as refcount FROM nodes WHERE nodetype=".$nodeType."AND reference=".qstr($reference)."" ); $refCount = $refCounts["refcount"]; if($refCount == 0){ // Parent is always root node id=0 if ($error = write("INSERT into nodes (id_parent,reference,nodetype) values (" . 0 . "," . qstr($reference) . ",$nodeType)")) { $this->lastError = getMessage('db_write_error') . $error; return $this->lastError; } else { // This won't work on another DB than PostgreSQL $id = singleResultSelect("SELECT currval('nodes_id_seq')"); $id = $id['currval']; return $id; } }else{ $this->lastError = getMessage('db_duplicate_value'); return $this->lastError; } } /** * delete a entity (person or group) * no trash for entity * * @access public * @return boolean */ function deleteEntity() { if($this->nodetype == GROUP_TYPE || $this->nodetype == USER_TYPE){ $this->destroy(); } } /** * move a node. Need it's parent ID * * @access public * @return boolean */ function setParent($id_parent) { if ($this->id == 0) { $this->lastError = getMessage('cannot_move_root'); return false; } if ($this->id == -1) { $this->lastError = getMessage('cannot_delete_trash'); return false; } $newParent = new Node($id_parent); if ($newParent->isError()) { $this->lastError = getMessage('error_moving_node') . $newParent->lastError(); return false; } if (!$newParent->isNode()) { $this->lastError = getMessage('error_moving_node') . getMessage('parent_not_a_node'); return false; } if ($this->id == $newParent->getID()) { $this->lastError = getMessage('error_moving_node') . getMessage('same_node_and_parent'); return false; } $parent = $newParent->getParent(); while ($parent->getID()) { if ($parent->getID() == $this->id) { $this->lastError = getMessage('error_moving_node') . getMessage('parent_in_node_tree'); return false; } $parent = $parent->getParent(); } if ($this->updateDB("id_parent=" . $id_parent)) { $this->id_parent = $id_parent; return true; } else return false; } /** * Create a child node. Need a name. * * @access public * @return boolean */ function createChildNode($name) { if ($this->isError()) return false; if (!$this->isNode()) { $this->lastError = getMessage('error_creating_node') . getMessage('parent_not_a_node'); return false; } if (!(strlen($name) > 0)) { $this->lastError = getMessage('error_creating_node') . getMessage('empty_node_name'); return false; } if ($id = $this->insertNode($name)) return new Node($id); else return false; } /** * insert a child computer. Need a its MAC adress * * @access public * @return boolean */ function createChildComputer($mac) { if ($this->isError()) return false; if (!$this->isNode()) { $this->lastError = getMessage('error_creating_computer') . getMessage('parent_not_a_node'); return false; } if (!$this->isMac($mac)) { $this->lastError = getMessage('error_creating_computer') . $mac . getMessage('not_a_mac'); return false; } $test = new Node($mac); if (!$test->isError()) { $this->lastError = getMessage('error_creating_computer') . $mac . getMessage('computer_exists'); return false; } if ($this->insertComputer($mac)) { return new Node($mac); } else return false; } /** * insert a child hwgroup. Need a its Name * * @access public * @return boolean */ function createChildHWGroup($hwgroup) { if ($this->isError()) return false; if (!$this->isNode()) { $this->lastError = getMessage('error_creating_hwgroup') . getMessage('parent_not_a_node'); return false; } if ($id = $this->insertHWGroup($hwgroup)) { return new Node($id); } else return false; } /** * Update the computer hardware. */ function setHardware($hwList) { if (!$this->isComputer()) { $this->lastError = getMessage('cannot_set_status') . getMessage('not_computer'); return NULL; } $update = True; $db_hwList = $this->getHardware(); if (count($db_hwList) == count($hwList)) { $update = False; $new_hwList = array(); $new_db_hwList = array(); foreach ($hwList as $hw) { array_push($new_hwList, $hw["hwkey"].":".$hw["hwvalue"]); } arsort($new_hwList); foreach ($db_hwList as $hw){ array_push($new_db_hwList, $hw["hwkey"].":".$hw["hwvalue"]); } if (count(array_intersect($new_db_hwList,$new_hwList)) != count($new_hwList)) { //update db $update = True; } } if ($update) { $query = "DELETE FROM computershw WHERE nodes_id=" . $this->id . ";"; //delete("DELETE FROM computershw WHERE nodes_id=" . $this->id); foreach ($hwList as $hw) { $query .= "INSERT into computershw (nodes_id,hwkey,hwvalue) values (" . $this->id . "," . qstr($hw["hwkey"]) . "," . qstr($hw["hwvalue"]) . ");"; //write("INSERT into computershw (nodes_id,hwkey,hwvalue) values (" . $this->id . "," . qstr($hw["hwkey"]) . "," . qstr($hw["hwvalue"]) . ")"); } //Here I use delete so the statement is executed all in once. this add the values as well. delete($query); } } /** * Update the status of a computer. * * Need some information. *
      *
    • code 1 : Computer has booted. Need bootserverip, ip *
    • code 2 : Computer has an app server. Need appserverip, plus previous *
    • code 3 : User login. Need display, username, plus previous *
    • code 4 : User logout. Need previous *
    * * Example code * $node = new Node($mac); * $status = $node->getStatus(); * $status['code'] = 1; * $status['bootservip'] = "192.168.2.2"; * $status['ip'] = "192.168.100"; * if ($node->setStatus($status)) { * print "Good job!!\n"; * } * else * { * print "Oops, try again...\n"; * } * * * @access public * @return boolean */ function setStatus($status, $log = true) { if (!$this->ok) return false; if (!$this->isComputer()) { $this->lastError = getMessage('cannot_set_status') . getMessage('not_computer'); return NULL; } // DB error will be trapped when writing $realStatus = $this->getStatus(); // Validating if (!$this->validateStatus($status)) return false; // Defaulting config if (!is_numeric($_CONFIG['bootServRetry_time'])) $_CONFIG['bootServRetry_time'] = 45; if (!is_numeric($_CONFIG['appServRetry_time'])) $_CONFIG['appServRetry_time'] = 10; if (!$realStatus) { $noRealStatus = true; $status['id'] = $this->id; $status['mac'] = $this->mac; $realStatus['ts_lastbootservip'] = 0; $realStatus['ts_lastappservip'] = 0; $realStatus['bootservretry'] = 0; $realStatus['appservretry'] = 0; } else { $noRealStatus = false; unset ($status['id']); unset ($status['mac']); } switch ($status['code']) { case 1 : if ((time() - $realStatus['ts_lastbootservip']) < $_CONFIG['bootServRetry_time']) { $status['bootservretry'] = $realStatus['bootservretry'] + 1; } else { $status['bootservretry'] = 1; } // Initialising data $status['appservip'] = "0.0.0.0"; $status['display'] = '-1'; $status['username'] = ""; $status['appservretry'] = 0; $status['ts_lastappservip'] = UnixToDB(0); if (strtotime($status['ts_lastbootservip'])+10 >= time()) $skip=1; $status['ts_lastbootservip'] = UnixToDB(time()); $status['termaccess'] = 0; // Remove upsalete status if ($noRealStatus) { delete("DELETE FROM status WHERE ip=" . qstr($status['ip']) . ""); } else { delete("DELETE FROM status WHERE ip=" . qstr($status['ip']) . " and id <> " . $this->id . ""); } break; case 2 : if ((time() - $realStatus['ts_lastappservip']) < $_CONFIG['appServRetry_time']) { $status['appservretry'] = $realStatus['appservretry'] + 1; } else { $status['appservretry'] = 1; } // Initialising data $status['username'] = ""; $status['display'] = '-1'; $status['ts_lastappservip'] = UnixToDB(time()); $status['termaccess'] = 0; break; case 3 : write("UPDATE status SET username=Null WHERE username='".$status['username']."' AND ip!='".$status['ip']."'"); break; case 4 : $status['termaccess'] = 0; break; } if ($skip == 1) return true; if (!$this->updateStatus($status, $noRealStatus)) return false; if ($log) return $this->insertLog($status); return true; } /** * Validate the status receive * * This receive a status and validate that all data * are valide. * * @access private * @return bool True if valide */ function validateStatus(& $status) { switch ($status['code']) { case 4 : case 3 : if (strlen($status['username']) == 0) { $this->lastError = getMessage('cannot_set_status') . getMessage('empty_username'); return false; } if ($status['display'] == '-1') { $this->lastError = getMessage('cannot_set_status') . getMessage('bad_status') . "display=" . $status['display']; return false; } case 2 : if (!$this->isIP($status['appservip']) || $status['appservip'] == "0.0.0.0") { $this->lastError = getMessage('cannot_set_status') . getMessage('bad_ip') . "appServIp=" . $status['appservip']; return false; } case 1 : if (!$this->isIP($status['ip'])) { $this->lastError = getMessage('cannot_set_status') . getMessage('bad_ip') . "ip=" . $status['ip']; return false; } if (!$this->isIP($status['bootservip'])) { $this->lastError = getMessage('cannot_set_status') . getMessage('bad_ip') . "bootservip=" . $status['bootservip']; return false; } break; default : $this->lastError = getMessage('cannot_set_status') . getMessage('bad_number') . "code=" . $status['code']; return false; break; } return true; } } // class Nodes ?> ltsp-cluster-control-2.0.3/Admin/util/random.php0000664000175000017500000000050712026403127022036 0ustar stgraberstgraber0){$i--;} fclose($fp); $index=rand(0,$i); $mylog=date('Y-m-d H:i:s')." $REMOTE_ADDR, ".$servers[$index]; exec("echo $mylog >>/tmp/logz"); echo $liste_appservers[$index]."\n"; ?> ltsp-cluster-control-2.0.3/Admin/util/Permissions.php0000664000175000017500000002365712026403127023104 0ustar stgraberstgraber * - Creation */ require_once 'dbFunctions.php'; require_once 'Permission.php'; class Permissions { var $listPermissions; // array of permissions var $attributesList; //all attributes with one permission function Permissions($nodeId) { $this->setPermissions($this->getPermissionsFromDB($nodeId),$nodeId); } /** This function clean up permissionList in order to respect the following rules : * * 1- If they are permissions set at different level of hierarchy, * the closest permission will be apply * 2- If a user obtain two permissions on the same node from two different groups, * the most privilegious permission will be selected. * */ function setPermissions($permissions,$nodeId){ $this->attributeList=array(); $previousId; $previousAttribute; $ignoreNextSameId = false; //remember all attributes $newIndex=0; for ($index = 0; $index < sizeof($permissions); $index++) { //default-> it's a new attribute... if(empty($this->attributesList) || !in_array($permissions[$index]->getAttribute(),$this->attributesList)){ $previousId = $permissions[$index]->getNodeId(); $previousAttribute = $permissions[$index]->getAttribute(); $permissions[$index]->setNodeId($nodeId); $this->listPermissions[$newIndex] = $permissions[$index]; $this->attributesList[$newIndex] = $permissions[$index]->getAttribute(); $newIndex++; $ignoreNextSameId = false; continue; } //If the permission attribute is already define for another node continue... (rule #1) if(in_array($permissions[$index]->getAttribute(),$this->attributesList) && $previousId != $permissions[$index]->getNodeId()){ $previousId = $permissions[$index]->getNodeId(); $previousAttribute = $permissions[$index]->getAttribute(); $ignoreNextSameId = true; continue; } //If it's the same attribute and the same node the most privilegious permission will be selected. rule #2 if(!$ignoreNextSameId && in_array($permissions[$index]->getAttribute(),$this->attributesList) && $previousId == $permissions[$index]->getNodeId()){ $previousId = $permissions[$index]->getNodeId(); $previousAttribute = $permissions[$index]->getAttribute(); //update previous permission with this one $this->listPermissions[$newIndex-1] = $this->mergePermissions($this->listPermissions[$newIndex-1],$permissions[$index]); $ignoreNextSameId = false; continue; } } } /** * This function get all permission for a specific node */ function getPermissionsFromDB($nodeId){ $sessionData = $_SESSION['groups']; //Superadmin role bypass all permissions if($_SESSION['userRole'] == "Superadmin"){ $listPerms[] = new Permission(0,'*',1,1,1,1,1); $listPerms[] = new Permission(0,"",1,1,1,1,1); return $listPerms; } //Generate IN condition $groups = $sessionData->getGroups(); $inCondition=""; for ($index = 0; $index < sizeof($groups); $index++) { $inCondition = $inCondition."'".$groups[$index]."'"; if($index <(sizeof($groups))-1){ $inCondition = $inCondition.","; } } $request = "SELECT id, attributes, scope, canadd, candelete, canread, canwrite ". "FROM nodes,permissions ". "WHERE leftval<=(select leftval from nodes where id=".$nodeId.") ". "AND rightval >=(select rightval from nodes where id=".$nodeId.") ". "AND id = nodes_id ". "AND (scope = 1 OR nodes_id = ".$nodeId.") ". "AND (". " (granteekey IN (".$inCondition.") AND granteetype =2)". " OR". " (granteekey ='".$sessionData->getUsername()."' AND granteetype =1)". " ) ". "ORDER BY rightval, attributes"; $perms = select($request); if (!is_array($perms) && !is_null($perms)) { $this->lastError = getMessage('db_error') . $perms; return NULL; } if (is_null($perms)) { $this->lastError = ""; return NULL; } for ($index = 0; $index < sizeof($perms); $index++) { $permission = new Permission($perms[$index]["id"],$perms[$index]["attributes"],$perms[$index]["scope"],$perms[$index]["canadd"],$perms[$index]["candelete"],$perms[$index]["canread"],$perms[$index]["canwrite"]); $listPerms[$index] = $permission; } return $listPerms; } /** * This function applied rule 2 - If a user obtain two permissions on the same node from * two different groups, the most privilegious permission will be selected. */ function mergePermissions($perm1, $perm2){ if(!$perm1->getScope())$perm1->setScope($perm2->getScope()); if(!$perm1->getCanadd())$perm1->setCanadd($perm2->getCanadd()); if(!$perm1->getCandelete())$perm1->setCandelete($perm2->getCandelete()); if(!$perm1->getCanread())$perm1->setCanread($perm2->getCanread()); if(!$perm1->getCanwrite())$perm1->setCanwrite($perm2->getCanwrite()); return $perm1; } /** * Get index permission for nodes... */ function getNodeIndex(){ $returnValue = -1; for ($index = 0; $index < sizeof($this->listPermissions); $index++) { //if attribute is empty it is the node permission if($this->listPermissions[$index]->getAttribute() == ""){ $returnValue=$index; break; } } return $returnValue; } /** * This function return the permission to use (index of listPermissions) for the attribute * 1. if attribute name is in $attributesList * 2. if attribute name begin with an attriubte in $attributesList contain XXXX* (ex. SCREEN_* match SCREEN_01) * 3. if $attributeClass.$name isi defined. * 4. if permission on all attribute is defined... (ex. *) * */ function getIndexPermission($name, $attributeClass){ // 1.if attribute name is in $attributesList $returnValue = -1; //index value return if no permission is -1 for ($index = 0; $index < sizeof($this->listPermissions); $index++) { if($this->listPermissions[$index]->getAttribute() == $name){ $returnValue = $index; break; } } // 2. if attribute name begin with an attriubte in $attributesList contain XXXX* if($returnValue == -1){ for ($index = 0; $index < sizeof($this->listPermissions); $index++) { //MUST CONTAINT * at last position $stringToCompare = $this->listPermissions[$index]->getAttribute(); if(strlen($stringToCompare)>1 && $stringToCompare{strlen($stringToCompare)-1}=='*' ){ $stringToCompare = substr($stringToCompare,0,strlen($stringToCompare)-1); if(strpos($name,$stringToCompare)!==false){ $returnValue = $index; break; } } } } //3. if $attributeClass.$name is defined. if($returnValue == -1){ for ($index = 0; $index < sizeof($this->listPermissions); $index++) { if($this->listPermissions[$index]->getAttribute() == $attributeClass.'.*'){ $returnValue = $index; break; } } } //4. if permission on all attribute is defined... (ex. *) if($returnValue == -1){ for ($index = 0; $index < sizeof($this->listPermissions); $index++) { if($this->listPermissions[$index]->getAttribute() == '*'){ $returnValue = $index; break; } } } return $returnValue; } /** * This function validate attribute delete rights */ function canDeleteAttribute($name, $attributeClass){ $index = $this->getIndexPermission($name, $attributeClass); $returnValue = 0;//Default no permission if($index != -1){ $returnValue = $this->listPermissions[$index]->getCandelete(); } return $returnValue; } /** * This function validate attribute add rights * */ function canAddAttribute($name, $attributeClass){ $index = $this->getIndexPermission($name, $attributeClass); $returnValue = 0;//Default no permission if($index != -1){ $returnValue=$this->listPermissions[$index]->getCanadd(); } return $returnValue; } /** * This function validate attribute read rights * */ function canReadAttribute($name, $attributeClass){ $index = $this->getIndexPermission($name, $attributeClass); $returnValue = 0;//Default no permission if($index != -1){ $returnValue=$this->listPermissions[$index]->getCanread(); } return $returnValue; } /** * This function validate attribute modify rights * */ function canWriteAttribute($name, $attributeClass){ $index = $this->getIndexPermission($name, $attributeClass); $returnValue = 0;//Default no permission if($index != -1){ $returnValue=$this->listPermissions[$index]->getCanwrite(); } return $returnValue; } /** * This function validate attribute modify rights * */ function canReadNode(){ $index = $this->getNodeIndex(); $returnValue = 0;//Default no permission if($index != -1){ $returnValue=$this->listPermissions[$index]->getCanread(); } return $returnValue; } /** * This function validate attribute modify rights * */ function canWriteNode(){ $index = $this->getNodeIndex(); $returnValue = 0;//Default no permission if($index != -1){ $returnValue=$this->listPermissions[$index]->getCanwrite(); } return $returnValue; } /** * This function validate attribute modify rights * */ function canAddNode(){ $index = $this->getNodeIndex(); $returnValue = 0;//Default no permission if($index != -1){ $returnValue=$this->listPermissions[$index]->getCanadd(); } return $returnValue; } } ?> ltsp-cluster-control-2.0.3/Admin/util/EntityBrowser.php0000664000175000017500000001425212026403127023400 0ustar stgraberstgraberload($type, $message, $entity_id, $nb_find); } /** * Load the browser (keeping Errors) * @access public */ function load($type = USER_TYPE, $message = NULL, $entity_id = "entity_id", $nb_find = "nb_find") { $this->isError = false; $nodeOK = false; switch ($type) { case USER_TYPE: case GROUP_TYPE: break; default: $this->errors[] = getMessage('invalide_nodes_browser_type').$type; $this->isError = true; return false; } if (isset($_GET[$entity_id]) && !$nodeOK) { if($_GET[$entity_id] == 0){ $_GET[$entity_id] = $this->resetNode(); } $nodeOK = $this->buildNode($_GET[$entity_id]); if ($nodeOK) { //if (!$this->node->isNode() && $type == NODE_TYPE) $this->node = $this->node->getParent(); $_GET[$entity_id] = $this->node->getID(); } } if (!$nodeOK) { $nodeOK = $this->buildNode($this->resetNode()); $_GET[$entity_id] = $this->node->getID(); } if (isset($_POST['addEntity'])) { $auth = new Auth("",""); //Check if value is not empty if(strlen(trim($_POST['entityToAdd'])) > 0){ if($auth->isValidEntity($_POST['entityToAdd'],$_POST['user_group'])){ $result = $this->node->insertEntity(strtolower($_POST['entityToAdd']),$_POST['user_group']); //result is id or error message if($result>0){ $nodeOK = $this->buildNode($_GET[$result]); if ($nodeOK) { unset($this->errors); $_GET[$entity_id] = $this->node->getID(); } }else{ $this->errors[] = $result; } }else{ $this->errors[]=""; $this->errors[] = getMessage('invalide_node_name').$_POST['entityToAdd']; } }else{ $this->errors[] = getMessage('empty_node_name'); } unset($_POST['addEntity']); } if (isset($_GET['deleteEntity'])) { $this->node->deleteEntity(); unset($_GET['deleteEntity']); $newEntityId = $this->resetNode(); if($newEntityId > 1){ //reset node $nodeOK = $this->buildNode($newEntityId); if ($nodeOK) { $_GET[$entity_id] = $this->node->getID(); } } } $this->entity_id = $entity_id; $this->nb_find = $nb_find; $this->type = $type; $this->message = $message; $this->allGroups = $this->getEntityNodes(GROUP_TYPE); $this->allUsers = $this->getEntityNodes(USER_TYPE); return true; } /** * Print errors * * @access public */ function printErrors() { if (isset($this->errors[0])) print "

    \n"; else return; foreach ($this->errors as $error) { print "".$error."
    \n"; } print "

    \n"; } function isError() { return $this->isError; } /** * Return selected node * * This function returns the selected node. It returns NULL if a * isFatalError is true. * * @access public * @return Node */ function getNode(){ return $this->node; } /** * Build the node * * This function build a node and test for errors * * @access private * @param int/mac/ip Default 0 * @return bool; */ function buildNode($id = "Default") { //JMD: remove spaces that got in there by copy-paste $id = trim($id); if ($id == "Default") { $this->node = new Node(); } else { $this->node = new Node($id); } $this->permissions = new Permissions($this->node->getID()); //Check for invalide_nodes_type switch ($this->node->nodetype) { case NODE_TYPE: case COMPUTER_TYPE: case HWGROUP_TYPE: break; default: break; } if ($this->node->isError()) $this->errors[] = $this->node->lastError(); return !$this->node->isError(); } /** * Get all group/user nodes * * @access public * @return */ function getEntityNodes($nodetype){ $entityNodes = select("SELECT id, reference FROM nodes WHERE nodetype=".$nodetype." ORDER BY reference"); if (!is_null($entityNodes) && !is_array($entityNodes)) { $this->errors[] = getMessage('db_error').$entityNodes; $this->isError = true; return NULL; } if (is_array($entityNodes)) { foreach ($entityNodes as $entityNode) { $entitiesAssoc[$entityNode['id']] = $entityNode['reference']; } } return $entitiesAssoc; } /** * Reset node id * * @access public * @return */ function resetNode(){ $nodes_id = singleResultSelect("SELECT MIN(id) as minid FROM nodes WHERE nodetype=".GROUP_TYPE." OR nodetype=".USER_TYPE ); return $nodes_id["minid"]; } /** * Print the browser HTML view * * @access public * @return stdout */ function printView() { global $termonly; if ($this->isError) { $this->printErrors(); } else { include 'entityBrowserView.php'; } } /** * getter for permissions */ function getPermissions(){ return $this->permissions; } } ?> ltsp-cluster-control-2.0.3/Admin/util/NodesBrowser.php0000664000175000017500000001210612026403127023170 0ustar stgraberstgraberload($type, $message, $node_id, $nb_find); } /** * Load the browser (keeping Errors) * @access public */ function load($type = COMPUTER_TYPE, $message = NULL, $node_id = "node_id", $nb_find = "nb_find") { $this->isError = false; $nodeOK = false; // Don't allow empty search if (isset($_POST[$nb_find]) && $_POST[$nb_find]=="") { unset($_POST[$nb_find]); } if (isset($_POST[$nb_find])) { $nodeOK = $this->buildNode( strtr( $_POST[$nb_find], "-", ":" ) ); if ($nodeOK) { if (!$this->node->isNode() && $type == NODE_TYPE) $this->node = $this->node->getParent(); $_GET[$node_id] = $this->node->getID(); } } // Allow search by the GET method (to access a node directly with links) if (isset($_GET[$nb_find])) { $nodeOK = $this->buildNode( strtr( $_GET[$nb_find], "-", ":" ) ); if ($nodeOK) { if (!$this->node->isNode() && $type == NODE_TYPE) $this->node = $this->node->getParent(); $_GET[$node_id] = $this->node->getID(); unset($_GET[$nb_find]); // Remove nb_find from _GET } } if (isset($_GET[$node_id]) && !$nodeOK) { $nodeOK = $this->buildNode($_GET[$node_id]); if ($nodeOK) { if (!$this->node->isNode() && $type == NODE_TYPE) $this->node = $this->node->getParent(); $_GET[$node_id] = $this->node->getID(); } } if (!$nodeOK) { $nodeOK = $this->buildNode(); $_GET[$node_id] = $this->node->getID(); } if ($nodeOK) { $this->parents = $this->node->getParents(); $this->childrens = $this->node->getChildrens(); } else { $this->isFatalError = true; } $this->node_id = $node_id; $this->nb_find = $nb_find; $this->type = $type; $this->message = $message; return true; } /** * Print errors * * @access public */ function printErrors() { if (isset($this->errors[0])) print "

    \n"; else return; foreach ($this->errors as $error) { print "".$error."
    \n"; } print "

    \n"; } function isError() { return $this->isError; } /** * Return selected node * * This function returns the selected node. It returns NULL if a * isFatalError is true. * * @access public * @return Node */ function getNode(){ return $this->node; } /** * Build the node * * This function build a node and test for errors * * @access private * @param int/mac/ip Default 0 * @return bool; */ function buildNode($id = "Default") { //JMD: remove spaces that got in there by copy-paste $id = trim($id); if ($id == "Default") { $this->node = new Node(); } else { $this->node = new Node($id); } $this->permissions = new Permissions($this->node->getID()); //Must have permission to read node $this->hasPermission = $this->permissions->canReadNode(); if($this->hasPermission==0){ //if we don't have the permission to read the node the default node is return' $this->errors[] = getMessage('no_permission_to_read_node').$this->node->getID(); $this->node = new Node(); } //Check for invalide_nodes_type switch ($this->node->nodetype) { case USER_TYPE: case GROUP_TYPE: $this->errors[] = getMessage('invalide_nodes_type'); break; default: break; } if ($this->node->isError()) $this->errors[] = $this->node->lastError(); return !$this->node->isError(); } /** * Print the browser HTML view * * @access public * @return stdout */ function printView() { global $termonly; if ($this->isError) { $this->printErrors(); } else { include 'nodesBrowserView.php'; } } /** * getter for permissions */ function getPermissions(){ return $this->permissions; } } ?> ltsp-cluster-control-2.0.3/Admin/util/load_module.php0000664000175000017500000000166712026403127023052 0ustar stgraberstgraberprint_load(); break; endswitch; ?> ltsp-cluster-control-2.0.3/Admin/util/LogsViewer.php0000664000175000017500000002214212026403127022643 0ustar stgraberstgraberconversion_attributes = array( 'ts' => getMessage('logs_ts'), 'id' => getMessage('logs_id'), 'mac' => getMessage('logs_mac'), 'ip' => getMessage('logs_ip'), 'bootservip' => getMessage('logs_bootservip'), 'appservip' => getMessage('logs_appservip'), 'username' => getMessage('logs_username'), 'code' => getMessage('logs_code') ); $this->conversion_comparator = array( '=' => getMEssage('logs_equals'), '>' => getMEssage('logs_greater'), '>=' => getMEssage('logs_gt_equals'), '<' => getMEssage('logs_smaller'), '<=' => getMEssage('logs_sm_equals'), '<>' => getMEssage('logs_not_equals') ); // Verify that current is set, otherwise assign a default value if( isset( $_GET["logs_page"] ) ) $this->current = $_GET["logs_page"]; else $this->current = 0; // Verify that logs_per_page is set, otherwise assign a default value if( isset( $_GET['logs_per_page'] ) ) if( $_GET["logs_per_page"] > 25000 ) $this->logs_per_page = 25000; else $this->logs_per_page = abs( round( $_GET["logs_per_page"] ) ); else $this->logs_per_page = 100; // Add conditions to the Filter of logs if( isset( $_POST['logs_add_condition'] ) && $_POST['logs_value'] <> "" ){ $filter = $_SESSION['logs_filters']; $condition = $_POST['logs_condition']; $comparator = $_POST['logs_comparator']; $value = $_POST['logs_value']; $filter[] = $condition." ".$comparator." '".$value."'"; $_SESSION['logs_filters'] = $filter; } else if( isset( $_POST['logs_remove_condition'] ) ){ $_SESSION['logs_filters'] = array(); } // Creation of the Where with the Filters if( isset( $_SESSION['logs_filters'] ) && count( $_SESSION['logs_filters'] ) > 0 ){ $where = "WHERE"; $filter = current( $_SESSION['logs_filters'] ); $is_first_filter = true; do{ if( $is_first_filter ) $is_first_filter = false; else $where .= " AND"; $where .= " ".$filter; }while( $filter = next( $_SESSION['logs_filters'] ) ); } // Compute page information $this->start = $this->current * $this->logs_per_page; $this->attributes = select("SELECT * FROM log $where ORDER BY id_key DESC LIMIT $this->logs_per_page OFFSET $this->start;"); $this->numRows = singleResultSelect("SELECT COUNT(*) FROM log $where"); if ( !is_array( $this->attributes ) && !is_null( $this->attributes ) ){ die( $this->attributes ); } } function print_nav(){ $last_page = ceil( $this->numRows['count'] / $this->logs_per_page ); // Prev logs page print "

    "; echo "[ "; if( ($this->start-$this->logs_per_page) >=0 ) { $newPrev = $this->current - 1; print "".getMessage('logs_prev').""; } else print getMessage('logs_prev'); echo " ] "; // Middle Navigation for( $page = 0; $page < $last_page; $page++ ){ $nb_shown_marks = 5; if( $page == 0 || $page == $last_page - 1 || ( $page <= $this->current + $nb_shown_marks && $page >= $this->current - $nb_shown_marks ) ){ echo "[ "; if( $page <> $this->current ){ echo "logs_per_page .">".( $page + 1 ).""; } else { echo $page+1; } echo " ] "; } } // Next logs page echo "[ "; if( ($this->start + $this->logs_per_page) < $this->numRows["count"]) { $newCurrent = $this->current + 1; print "" . getMessage('logs_next').""; } else print getMessage('logs_next'); echo " ]"; print "

    "; } function logs_per_page_selector(){ print "

    "; echo "

    "; echo ""; echo ""; echo ""; echo "
    "; print "

    "; } function print_filters(){ print "
    "; print "\n"; print "\n"; print "\n"; print ""; if( isset( $_SESSION['logs_filters'] ) && count( $_SESSION['logs_filters'] ) > 0 ){ echo "

    ".getMessage('logs_msg_active_filters')."

    "; print "

    "; foreach( $_SESSION['logs_filters'] as $filter ){ print str_replace(array_keys( $this->conversion_attributes ), array_values( $this->conversion_attributes ), str_replace(array_keys( $this->conversion_comparator ), array_values( $this->conversion_comparator ), $filter ) )."
    "; } print "

    "; print ""; } print "
    "; } function print_logs() { echo "

    ".getMessage('logs_filter_message')."

    "; $this->print_filters(); echo "

    ".getMessage('logs_nb_logs_message')."

    "; $this->logs_per_page_selector(); echo "

    ".getMessage('logs_table_message')."

    "; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
    ".getMessage('logs_code_msg_legend')."
    1".getMessage('logs_code_booting')."
    2".getMessage('logs_code_GDM')."
    3".getMessage('logs_code_logging')."
    4".getMessage('logs_code_unlogging')."
    "; $this->print_nav(); print ''; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; //print "\n"; print "\n"; print "\n"; //print "\n"; //print "\n"; print ""; if (is_array($this->attributes)) { foreach ($this->attributes as $element) { switch ( $element['code'] ){ case "1" : $code = getMessage('logs_code_booting'); break; case "2" : $code = getMessage('logs_code_GDM'); break; case "3" : $code = getMessage('logs_code_logging'); break; case "4" : $code = getMessage('logs_code_unlogging'); break; default : $code = $element[code]; break; } print ""; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; print "\n"; //print "\n"; print "\n"; // Added if to be sure the empty-cells show ( 2007, Mars 3 ) print "\n"; //print "\n"; //print "\n"; print ''; } } print '
    ".getMEssage('logs_ts')." ".getMEssage('logs_id')."".getMEssage('logs_mac')."".getMEssage('logs_ip')."".getMEssage('logs_bootservip')."".getMEssage('logs_appservip')."".getMEssage('logs_display')."".getMEssage('logs_username')."".getMEssage('logs_code')."".getMEssage('logs_bootservretry')."".getMEssage('logs_appservretry')."
    $element[ts]$element[id]$element[mac]$element[ip]$element[bootservip]$element[appservip]$element[display]".( ( strlen( $element[username] ) > 0 ) ? $element[username] : " " )."$code$element[bootservretry]$element[appservretry]
    '; $this->print_nav(); } } ?> ltsp-cluster-control-2.0.3/Admin/util/nodesEditorView.php0000664000175000017500000000601612026403127023671 0ustar stgraberstgraber

    printErrors(); ?>
    ltsp-cluster-control-2.0.3/Admin/util/entityRole-config.php0000664000175000017500000000014112026403127024151 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Admin/util/attributesManagerView.php0000664000175000017500000001016512026403127025073 0ustar stgraberstgraber getName(),false); echo ""; if( isMessage("url_wiki")) { echo "".$message." ="; } else { echo $message." ="; } echo ""; switch($attribute->getType()) { case 0: $value = "value=".qstr($attribute->getValue()).""; ?> /> /> getEditable()){ $selection = $attribute->getSelection(); ?> getSelection(); if (is_array($_POST[$attribute->getName()])) { foreach ($_POST[$attribute->getName()] as $value) { $previousSelection[$value] = true; } $selection = array_merge($selection,$previousSelection); } ?>

    attributes is not empty do; // Sort the attributes with their names //usort ($this->allAttributes, "sortAttributesByLangName"); if ( ! empty($this->attributes)){ usort ($this->attributes, "sortObjectsByLangName"); if (is_array($this->attributes)){ foreach ($this->attributes as $attribute) { printAttributeInput($attribute); } } } ?>

    attributes)) { ?>

    allAttributes)){ ?> allAttributes ); echo "-->"; ?> " />

    node->nodetype == COMPUTER_TYPE && !empty($this->hardware)){ ?>

    hardware as $hardware){ print $hardware['hwkey']."='".$hardware['hwvalue']."'
    "; } ?>
    printErrors(); ?>
    ltsp-cluster-control-2.0.3/Admin/util/errorsView.php0000664000175000017500000000251412026403127022725 0ustar stgraberstgraber\n"; foreach ($ERRORS as $error) { print "$error
    \n"; } if (is_array($ERRORS[0])) print "

    \n"; } if (is_array($WARNINGS)) { if (is_array($WARNINGS[0])) print "

    \n"; foreach ($WARNINGS as $warning) { echo "$warning
    "; } if (is_array($WARNINGS [0])) print "

    \n"; } if (is_array($CONFIRMATIONS)) { if (is_array($CONFIRMATIONS[0])) print "

    \n"; foreach ($CONFIRMATIONS as $confirmation) { echo "$confirmation
    "; } if (is_array($CONFIRMATIONS[0])) print "

    \n"; } ?> ltsp-cluster-control-2.0.3/Admin/util/managePrinterslist.php0000664000175000017500000000146512026403127024435 0ustar stgraberstgraberprintView(); break; } ?> ltsp-cluster-control-2.0.3/Admin/util/configuration.php0000664000175000017500000000277312026403127023434 0ustar stgraberstgrabergetPermissions(); $am = new AttributesManager($nb->getNode(),array("ltsp","mille","custom"),array(NODE_TYPE,COMPUTER_TYPE,HWGROUP_TYPE),$perm); $node = $nb->getNode(); if($node->nodetype == HWGROUP_TYPE && $perm->canWriteNode()==1){ $hw = new HWGroupManager($nb->getNode()); } $ltsParser = new LTSParser($nb->getNode()); break; case 'print': $nb->printView(); $am->printView(); $node = $nb->getNode(); $perm = $nb->getPermissions(); if($node->nodetype == HWGROUP_TYPE && $perm->canWriteNode()==1){ $hw->printView(); } $ltsParser->printView(); break; } ?> ltsp-cluster-control-2.0.3/Admin/util/PrintersListManager.php0000664000175000017500000002007012026403127024510 0ustar stgraberstgraberisError = false; global $CONFIG; if( !is_null( $CONFIG['printer_servers'] ) ){ $this->printerServers = $CONFIG['printer_servers']; } else { $this->printerServers = array(); } ///////////////////////// // Actions ///////////////////////// //--- Synchronize ---// if( isset( $_POST['rem_printer'] ) && !empty( $_POST['on_server'] ) ){ $this->rem_Printers( $_POST['on_server'] ); $this->synchronizeList( array_keys( $_SESSION[ 'printerList' ] ) ); } if( isset( $_POST['add_printer'] ) && !empty( $_POST['on_db'] ) ){ $this->add_Printers( $_POST['on_db'] ); $this->synchronizeList( array_keys( $_SESSION[ 'printerList' ] ) ); } if ( isset ( $_POST['synchronize'] ) ) { if( isset( $_POST['printer_server'] ) ){ $this->synchronizeList( $_POST['printer_server'] ); } else { $_SESSION[ 'printerList' ] = array(); } } //--- Ghost Printers ---// if( isset( $_POST['add_ghost_printer'] ) ){ $this->add_Printers( array( $_POST['add_ghost_printer'] ) ); } if( isset( $_POST['rem_ghost_printer'] ) ){ $this->rem_Printers( $_POST['ghost_printer'] ); } $_SESSION['ghost_printers'] = $this->getGhostPrinters(); } // Adds a list of printers to Printer_List and Default_Printer function add_Printers( $printer_list ){ $attributesDef_PL = $this->getPrintersID(); // Definition of the Printer_List Attribute $attributesDef_DP = $this->getDefaultPrintersID(); // Definition of the Default_Printer Attribute foreach( $printer_list as $printer ){ $attributesDef_PL->insertDictValue( $printer ); $attributesDef_DP->insertDictValue( $printer ); } } // Removes a list of printers from Printer_List and Default_Printer function rem_Printers( $printer_list ){ $attributesDef_PL = $this->getPrintersID(); // Definition of the Printer_List Attribute $attributesDef_DP = $this->getDefaultPrintersID(); // Definition of the Default_Printer Attribute foreach( $printer_list as $printer ){ $attributesDef_PL->deleteDictValue( $printer ); $attributesDef_DP->deleteDictValue( $printer ); } } // Returns the ID used in the BD to designate Printers function getPrintersID(){ $attributesDef = new AttributeDef("static"); $printerListId = $attributesDef->getFromDB("id","name='LDM_PRINTER_LIST'"); $attributesDef = new AttributeDef($printerListId["id"]); return $attributesDef; } // Returns the ID used in the DB to designate Default Printers function getDefaultPrintersID(){ $attributesDef = new AttributeDef("static"); $printerListId = $attributesDef->getFromDB("id","name='LDM_PRINTER_DEFAULT'"); $attributesDef = new AttributeDef($printerListId["id"]); return $attributesDef; } // Returns the Printers from a specific Server function getPrintersFromServer( $printerServer ){ $tmp_printers = ""; $ping = substr( trim( shell_exec("ping -c 1 -w 3 ".$printerServer." ; echo $?") ), -1, 1 ); switch( $ping ){ case "0" : $tmp_printers = shell_exec('lpstat -h '.$printerServer. ' -U root -a|cut -d" " -f1'); break; case "1" : $this->errors[$printerServer] = getMessage('printer_no_server'); break; default : $this->errors[$printerServer] = getMessage('printer_dead_server'); break; } return explode("\n",trim($tmp_printers)); } // This function gets all the printers that are floating around without being attached to a server function getGhostPrinters(){ $ghost_printers = $printersFromServer = array(); // First, we get all the printers from the servers foreach( $this->printerServers as $printerServer ){ $printersFromServer = $this->getPrintersFromServer( $printerServer ); if(!empty($previous_printers) && !empty($printersFromServer)){ $printersFromServer = array_merge($previous_printers,$printersFromServer); } $previous_printers = $printersFromServer; } // Then, we get all the printers from the database $attributesDef = $this->getPrintersID(); $databaseValues = $attributesDef->getFromDB("value","attributesdef_id=".$attributesDef->def_id,"attributesdefdict",true,true); if( !is_null( $databaseValues ) ){ foreach( $databaseValues as $printer ){ // If a computer is in the database but not on the servers, it's a ghost if( !in_array( $printer['value'], $printersFromServer ) ){ $ghost_printers[] = $printer['value']; } } } return $ghost_printers; } function synchronizeList( $serverList ) { // Step 1 : Get all printers from the Dictionary $_SESSION[ 'printerList' ] = $printerDict = array(); $attributesDef = $this->getPrintersID(); $printersFromDatabase = $attributesDef->getFromDB("value","attributesdef_id=".$attributesDef->def_id,"attributesdefdict",true,true); if( !is_null( $printersFromDatabase ) ){ foreach($printersFromDatabase as $printerName){ $printerDict[] = $printerName['value']; } } // Step 2 : Get the printer's server foreach( $serverList as $printerServer ){ // Step 3 : Get their printers $_SESSION[ 'printerList' ][ $printerServer ][ 'onServer' ] = $_SESSION[ 'printerList' ][ $printerServer ][ 'onDB' ] = array(); $printersFromServer = $this->getPrintersFromServer( $printerServer ); // Step 4 : For each priner, look if the printers have already been put in the DB (have been synchronized) foreach( $printersFromServer as $printer ){ if( stripos( urlencode( $printer ), "%09" ) === false ){ if( !in_array( $printer, $printerDict ) ){ $_SESSION[ 'printerList' ][ $printerServer ][ 'onServer' ][] = $printer; } else { $_SESSION[ 'printerList' ][ $printerServer ][ 'onDB' ][] = $printer; } } } } /* ** PREVIOUS CODE ** //$tmp_printers = shell_exec('lpstat -a|cut -d" " -f1'); //$printersFromServer = explode("\n",trim($tmp_printers)); foreach( $this->printerServers as $printerServer ){ $tmp_printers = shell_exec('lpstat -h '.$printerServer. ' -a|cut -d" " -f1'); $printersFromServer = explode("\n",trim($tmp_printers)); if(!empty($previous_printers) && !empty($printersFromServer)){ $printersFromServer = array_merge($previous_printers,$printersFromServer); } $previous_printers=$printersFromServer; } $attributesDef = new AttributeDef("static"); $printerListId = $attributesDef->getFromDB("id","name='LDM_PRINTER_LIST'"); $attributesDef = new AttributeDef($printerListId["id"]); $printersInDatabase = $attributesDef->getFromDB("value","attributesdef_id=".$printerListId['id'],"attributesdefdict",true,true); foreach($printersInDatabase as $printerName){ $printerNames[] = $printerName['value']; } foreach($printersFromServer as $newPrinter){ if(!in_array($newPrinter,$printerNames)){ $error = $attributesDef->insertDictValue($newPrinter); if(strlen($error)>1){ $this->errors[] = $error; } } } //Print succes in error if(!$this->errors){ $this->errors[] = "Succes"; } */ } function isError() { return $this->isError; } function printErrors() { if (isset ($this->errors[0])){ print "

    \n"; foreach ($this->errors as $error) { print $error . "
    \n"; } print "

    \n"; } } function printView() { if ($this->isError) { $this->printErrors(); return; } include 'printersListManagerView.php'; } } ?> ltsp-cluster-control-2.0.3/Admin/util/Load.php0000664000175000017500000000555412026403127021444 0ustar stgraberstgraberliste_appservers[$i] = rtrim(fgets($fp, 1024))) $i++; fclose($fp); } function print_load() { if(empty($_GET['action'])) { print("

    Charge sur les serveurs d'application

    "); for($i = 0; $i < count($this->liste_appservers); $i++) { if(!empty($this->liste_appservers[$i])) { print("

    Appserver ".$this->liste_appservers[$i]."

    "); @include("http://".$this->liste_appservers[$i]."/state.php"); } } print("

    Editer la liste

    "); } else { if($_GET['action'] == "edit") $this->edit_list(); } } function edit_list() { $fp = fopen("util/config_xapp.txt","r"); $list = ""; while($tmp = rtrim(fgets($fp, 1024))) { if(!empty($tmp)) { $list .= trim($tmp); $list .= "\n"; } } print("

    Editer la liste des serveurs d'application disponible :

    "); print("

    "); } } ?> ltsp-cluster-control-2.0.3/Admin/util/text-ru.php0000664000175000017500000006730512026403127022177 0ustar stgraberstgraberÐ’Ñ‹ можете добавить в : \" ÐаÑтройках конфигуратора \" --> База данных конфигуратора или вручную Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€ÑƒÑ config.php.
    ЗапроÑ"; $MESSAGES['no_db_password'][$lang] = "ТребуетÑÑ Ð¿Ð°Ñ€Ð¾Ð»ÑŒ Ð´Ð»Ñ Ð´Ð¾Ñтупа к базе данных
    Ð’Ñ‹ можете добавить в : \" ÐаÑтройках конфигуратора \" --> \"База данных конфигуратора\" или вручную Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€ÑƒÑ Ñ„Ð°Ð¹Ð» config.php.
    ЗапроÑ"; $MESSAGES['no_db_name'][$lang] = "ТребуетÑÑ Ð¸Ð¼Ñ Ð±Ð°Ð·Ñ‹ данных
    Ð’Ñ‹ можете добавить в : \" ÐаÑтройках конфигуратора \" --> \"База данных конфигуратора\" или вручную Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€ÑƒÑ Ñ„Ð°Ð¹Ð» config.php.
    ЗапроÑ"; $MESSAGES['db_error'][$lang] = "Ошибка запрÑа к базе данных : "; //////////////////////////////////////////////////////////////////// // Ð˜Ð¼Ñ Ð¼Ð¾Ð´ÑƒÐ»ÐµÐ¹ //Module names //////////////////////////////////////////////////////////////////// $MESSAGES['configuration_module'][$lang] = "КонфигурациÑ"; $MESSAGES['nodesManager_module'][$lang] = "Управление узлами"; $MESSAGES['entity_module'][$lang] = "Группа/пользователь"; $MESSAGES['managelist_module'][$lang] = "СпиÑок значений аттрибутов"; $MESSAGES['info_module'][$lang] = "ТехничеÑÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ"; $MESSAGES['logs_module'][$lang] = "Логи терминалов"; $MESSAGES['printing_module'][$lang] = "Управление принтерами"; $MESSAGES['stats_module_short'][$lang] = "Отчеты"; $MESSAGES['setup_module'][$lang] = "ÐаÑтройки центра управлениÑ"; $MESSAGES['configuration_module_short'][$lang] = "КонфигурациÑ"; $MESSAGES['nodesManager_module_short'][$lang] = "Узлы"; $MESSAGES['entity_module_short'][$lang] = "Группа/Пользователь"; $MESSAGES['managelist_module_short'][$lang] = "СпиÑок значений аттрибутов"; $MESSAGES['info_module_short'][$lang] = "ТехничеÑÐºÐ°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ"; $MESSAGES['logs_module_short'][$lang] = "Логи терминалов"; $MESSAGES['printing_module_short'][$lang] = "Управление принтерами"; $MESSAGES['stats_module_short'][$lang] = "Отчеты"; $MESSAGES['setup_module_short'][$lang] = "ÐаÑтройки центра управлениÑ"; //////////////////////////////////////////////////////////////////// // Ð¡ÐµÐºÑ†Ð¸Ñ ÑƒÑтановки конфигуратора //Configurator setup section //////////////////////////////////////////////////////////////////// // Общие ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ÑƒÑтановки //General setup messages $MESSAGES['new_cfg_created'][$lang] = "Ðовый конфигурационный файл Ñоздан."; $MESSAGES['cannot_open_cfg_file'][$lang] = "Ðе могу запиÑать config.php конфигурационный файл."; $MESSAGES['exit'][$lang] = "Выход"; $MESSAGES['lock_setup'][$lang] = "Блокировка"; $MESSAGES['modify'][$lang] = "Сохранить"; $MESSAGES['cfg_val_true'][$lang] = "Да"; $MESSAGES['cfg_val_false'][$lang] = "Ðет"; $MESSAGES['test'][$lang] = "ТеÑÑ‚"; // Ð¡ÐµÐºÑ†Ð¸Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° Ñзыка //Language configuration section $MESSAGES['cfg_lang_section'][$lang] = "Язык"; $MESSAGES['cfg_language'][$lang] = "Язык интерфейÑа конфигуратора"; $MESSAGES['cfg_charset'][$lang] = "Кодировка Ð´Ð»Ñ Ð’Ñб интерфейÑа конфигуратора"; // Ð¡ÐµÐºÑ†Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑти конфигуратора //Configurator Security section $MESSAGES['cfg_configurator_security_section'][$lang] = "БезопаÑноÑть конфигуратора"; $MESSAGES['use_https'][$lang] = "ИÑпользовать https Ð´Ð»Ñ Ð’Ñб-интерфейÑа канфигуратора"; $MESSAGES['need_https'][$lang] = 'Эта Ñтраница требует HTTPS подключение.'; // Ð¡ÐµÐºÑ†Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑти терминалов //Terminals Security section $MESSAGES['cfg_terminal_security_section'][$lang] = "БезопаÑноÑть терминалов"; $MESSAGES['cfg_terminal_password'][$lang] = "Пароль терминала"; $MESSAGES['cfg_terminal_auth'][$lang] = "ÐÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ Ñ‚ÐµÑ€Ð¼Ð¸Ð½Ð°Ð»Ð°"; // Ð¡ÐµÐºÑ†Ð¸Ñ Ð±Ð°Ð·Ñ‹ данных кофигуратора //Configurator database section $MESSAGES['cfg_db_section'][$lang] = "База конфигуратора"; $MESSAGES['cfg_db_server'][$lang] = "ÐÐ´Ñ€ÐµÑ Ñервера Ñ Ð±Ð°Ð·Ð¾Ð¹ данных";//Address of the server with the database"; $MESSAGES['cfg_db_user'][$lang] = "Пользователь базы данных"; $MESSAGES['cfg_db_password'][$lang] = "Пароль Ð´Ð»Ñ Ð±Ð°Ð·Ñ‹ данных(По умолчанию пуÑтой)"; $MESSAGES['cfg_db_name'][$lang] = "Ð˜Ð¼Ñ Ð±Ð°Ð·Ñ‹ данных"; $MESSAGES['cfg_db_type'][$lang] = "Тип базы данных"; // Ð¡ÐµÐºÑ†Ð¸Ñ Ð½Ð°Ñтройки проверки подлинноÑти//Authentification configuration section $MESSAGES['cfg_auth_section'][$lang] = "Проверка подлинноÑти ÑиÑтемы"; $MESSAGES['cfg_auth_name'][$lang] = "Введите Ñлужбы проверки подлинноÑти Ð´Ð»Ñ Ð²ÐµÐ±-конфигуратора"; // ÐаÑтройка LDAP //LDAP configuration (subsection of Authentification configuration) $MESSAGES['cfg_ldap_section'][$lang] = "LDAP конфигурациÑ"; $MESSAGES['cfg_ldap_host'][$lang] = "URL of LDAP Ñервера"; $MESSAGES['cfg_ldap_basedn'][$lang] = "ПоиÑк в базе LDAP"; $MESSAGES['cfg_ldap_object_class'][$lang] = "Объект клаÑÑа пользователь(не обÑзательно)"; $MESSAGES['cfg_ldap_group_object_class'][$lang] = "Объект клаÑÑа группа(не обÑзательно)"; $MESSAGES['cfg_ldap_group'][$lang] = "Ðттрибуты групп LDAP "; $MESSAGES['cfg_ldap_binddn'][$lang] = "LDAP DN Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ и групп (ПривÑзка к пользователю по умолчанию)"; $MESSAGES['cfg_ldap_bindpw'][$lang] = "Предыдущий пароль пользователÑ"; $MESSAGES['cfg_ldap_uidAttribute'][$lang] = "Ðттрибуты иÑпользуемые Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка пользователÑ"; $MESSAGES['cfg_ldap_version'][$lang] = "ВерÑÐ¸Ñ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð° LDAP (По умолчанию 3)"; $MESSAGES['test_ldap'][$lang] = "Введите ваши учетные данные LDAP Ð´Ð»Ñ Ñ‚ÐµÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð²Ð°ÑˆÐµÐ¹ ldap конфигурации"; // Ð¡ÐµÐºÑ†Ð¸Ñ Ð½Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð°Ð² //LDAP user and group rights association section $MESSAGES['ldap_group_role'][$lang] = "Ðазначение прав Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ группы LDAP"; // Ð¡ÐµÐºÑ†Ð¸Ñ Ð±Ð°Ð»Ð°Ð½Ñировщика нагрузки //Load balancer section $MESSAGES['cfg_loadbalancer_section'][$lang] = "БаланÑировщик нагрузки"; $MESSAGES['cfg_loadbalancer'][$lang] = "URL (По умолчанию : localhost:8001)"; // Ð¡ÐµÐºÑ†Ð¸Ñ Ð¿Ñ€Ð¸Ð½Ñ‚-Ñерверов //printer servers section $MESSAGES['printer_server_section'][$lang] = "Принт-Ñерверы (Cups)"; //////////////////////////////////////////////////////////////////// // Экран входа //Login Screen //////////////////////////////////////////////////////////////////// $MESSAGES['index_title'][$lang] = 'Пользователь конфигуратора'; $MESSAGES['no_language_file'][$lang] = "Файл text-.php не найден на Ñервере, Ñзык не поддерживаетÑÑ."; $MESSAGES['ask_uid'][$lang] = 'Введите ваше Ð¸Ð¼Ñ : '; $MESSAGES['ask_password'][$lang] = 'Введите ваш пароль : '; $MESSAGES['connect'][$lang] = 'Подключить'; $MESSAGES['bad_login'][$lang] = 'Ðеверное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ пароль.'; $MESSAGES['good_login'][$lang] = 'УÑпешный вход пользователÑ.'; //////////////////////////////////////////////////////////////////// // Модуль поиÑка узлов //Search node Module //////////////////////////////////////////////////////////////////// $MESSAGES['id_or_mac'][$lang] = "ПоиÑк узла по ID или MAC адреÑу : "; $MESSAGES['find'][$lang] = "ПоиÑк"; $MESSAGES['go'][$lang] = "Перейти"; $MESSAGES['search_inv'][$lang] = "ПоиÑк узла по инвентарному номеру : "; //////////////////////////////////////////////////////////////////// // Модуль конфигурации //Configuration module //////////////////////////////////////////////////////////////////// $MESSAGES['source'][$lang] = "Управление иÑточниками"; $MESSAGES['nodes_editor_change_tree_name'][$lang] = "СвойÑтва узла"; $MESSAGES['nodes_editor_manage_actual_nodes'][$lang] = "Подчиненные"; $MESSAGES['nodes_editor_deselect'][$lang] = "СброÑить"; $MESSAGES['config_attributes_listing'][$lang] = "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ"; $MESSAGES['config_delete'][$lang] = "Удалить"; $MESSAGES['config_modify'][$lang] = "Изменить"; $MESSAGES['config_cancel'][$lang] = "Отменить"; $MESSAGES['config_select_tree'][$lang] = "ПроÑмотр дерева"; //////////////////////////////////////////////////////////////////// // Модуль пользователей и групп //User and group module //////////////////////////////////////////////////////////////////// $MESSAGES['add_user_group'][$lang] = "Добавить "; $MESSAGES['user'][$lang] = "Пользователь"; $MESSAGES['group'][$lang] = "Группа"; $MESSAGES['users'][$lang] = "Пользователи"; $MESSAGES['groups'][$lang] = "Группы"; $MESSAGES['search_user_group'][$lang] = "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸Ð»Ð¸ группы"; $MESSAGES['invalide_node_name'][$lang] = "Ðеверное Ð¸Ð¼Ñ :"; $MESSAGES['db_duplicate_value'][$lang] = "Дублированное значение"; //////////////////////////////////////////////////////////////////// // Ldap ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ñтраницы входа //Ldap messages at Login Screen //////////////////////////////////////////////////////////////////// $MESSAGES['ldap_cant_connect'][$lang] = 'Ðе удаетÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒÑÑ Ðº указанному LDAP Ñерверу по адреÑу : '.$CONFIG['ldap_host']; $MESSAGES['ldap_connected'][$lang] = 'Ð’Ñ‹ уже подключены к LDAP Ñерверу.'; $MESSAGES['ldap_not_connected'][$lang] = 'Ðе возможно закрыть LDAP подключение.'; $MESSAGES['ldap_version_not_supported'][$lang] = 'LDAP Ñервер не поддерживает LDAP протокол верÑии '.$CONFIG['ldap_version'].' .'; $MESSAGES['ldap_user_bind'][$lang] = 'ОтÑутÑтвует параметр BaseDN или bindpw в конфигурации, ÑвÑзанный Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼'; $MESSAGES['ldap_no_basedn'][$lang] = 'ОтÑутÑтвует параметр BaseDN в конфигурации.'; $MESSAGES['ldap_cant_bind'][$lang] = 'Ðевозможно привÑзать к LDAP-Ñерверу, проверьте привÑзку.'; $MESSAGES['ldap_no_host'][$lang] = 'Ðе указан LDAP хоÑÑ‚ в конфигурации.'; $MESSAGES['ldap_no_group'][$lang] = 'Ðе указан LDAP аттрибут группы в конфигурации.'; //////////////////////////////////////////////////////////////////// // Модуль группы/пользователь //Group/User Module //////////////////////////////////////////////////////////////////// $MESSAGES['entity_add_entity_message'][$lang] = "Добавить пользователей и группы"; $MESSAGES['entity_manage_user_group'][$lang] = "Изменить пользователей и группы"; $MESSAGES['newDefaultValueListAttribute'][$lang] = ""; //////////////////////////////////////////////////////////////////// // Модуль отчетов //Report module //////////////////////////////////////////////////////////////////// $MESSAGES['stats_module'][$lang] = "Отчеты"; $MESSAGES['stats_node_selector_msg'][$lang] = "Выбрать елементы Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ"; $MESSAGES['stats_true_conditions'][$lang] = "Выбрать уÑловиÑ, в которых атрибуты Ñлементов должны ÑоответÑтвовать"; $MESSAGES['stats_false_conditions'][$lang] = "Выбрать уÑловиÑ, в которых атрибуты Ñлементов не должны ÑоответÑтвовать"; $MESSAGES['stats_add_cond'][$lang] = "Добавить"; $MESSAGES['stats_add_value'][$lang] = "Добавить"; $MESSAGES['stats_selected_value'][$lang] = "Выбранные уÑловиÑ"; $MESSAGES['stats_select_what'][$lang] = "Работает Ñ : "; $MESSAGES['stats_terminals'][$lang] = "Терминалы"; $MESSAGES['stats_contexts'][$lang] = "КонтекÑÑ‚"; $MESSAGES['stats_contexts_n_terminals'][$lang] = "Терминалы и контекÑÑ‚"; $MESSAGES['stats_use_heritage'][$lang] = "ПроÑмотр наÑледуемых аттрибутов"; $MESSAGES['stats_yes'][$lang] = "Да"; $MESSAGES['stats_no'][$lang] = "Ðет"; $MESSAGES['stats_send'][$lang] = "Продолжить"; $MESSAGES['stats_validate'][$lang] = "Ok"; $MESSAGES['stats_configuration'][$lang] = "Ðттрибуты конфигурации"; $MESSAGES['stats_network'][$lang] = "Сетевые аттрибуты"; $MESSAGES['stats_hardware'][$lang] = "Ðттрибуты оборудованиÑ"; $MESSAGES['stats_select_attr_title'][$lang] = "Выберите атрибуты, которые вы хотите показать в отчете"; $MESSAGES['stats_select_attr_config'][$lang] = "Ðттрибуты конфигуратора :"; $MESSAGES['stats_select_attr_hardware'][$lang] = "Ðттрибуты Ð¾Ð±Ð¾Ñ€ÑƒÐ´Ð¾Ð²Ð°Ð½Ð¸Ñ :"; $MESSAGES['stats_select_attr_network'][$lang] = "Сетевые аттрибуты :"; $MESSAGES['stats_select_attr_type'][$lang] = "Показать отчет как :"; $MESSAGES['stats_generate'][$lang] = "Отчет"; $MESSAGES['stats_select_attr_type_context'][$lang] = "КонтекÑÑ‚"; $MESSAGES['stats_select_attr_type_table'][$lang] = "Таблицы"; $MESSAGES['stats_attribute'][$lang] = "Ðттрибуты"; $MESSAGES['stats_report_no_attr'][$lang] = "Ðет выбранных аттрибутов Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра."; $MESSAGES['stats_equals'][$lang] = "Равно"; $MESSAGES['stats_unequals'][$lang] = "Ðе равно"; $MESSAGES['stats_greater'][$lang] = "Больше"; $MESSAGES['stats_greater_equals'][$lang] = "Больше или равно"; $MESSAGES['stats_lower'][$lang] = "Меньше"; $MESSAGES['stats_lower_equals'][$lang] = "Меньше или равно"; $MESSAGES['stats_no_node'][$lang] = "Ðет аттрибутов Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ."; $MESSAGES['stats_and'][$lang] = "И"; $MESSAGES['stats_or'][$lang] = "ИЛИ"; $MESSAGES['stats_node'][$lang] = "Элемент"; $MESSAGES['stats_path'][$lang] = "Путь"; //////////////////////////////////////////////////////////////////// // Модуль принтера //Printer Module //////////////////////////////////////////////////////////////////// $MESSAGES['printer_manage'][$lang] = "Применить"; $MESSAGES['printer_manage_list'][$lang] = "Управление принтер Ñерверов"; $MESSAGES['printer_server_list'][$lang] = "СпиÑок принтеров "; $MESSAGES['printer_add'][$lang] = "Добавить"; $MESSAGES['printer_delete'][$lang] = "Удалить"; $MESSAGES['printer_database'][$lang] = "УÑтановленый принтер в конфигураторе базы данных"; $MESSAGES['printer_servers'][$lang] = "ДоÑтупные принтера"; $MESSAGES['printer_standalone_list'][$lang] = "СпиÑок автономных принтеров"; $MESSAGES['printer_add_a_standalone'][$lang] = "Добавить автономный принтер"; $MESSAGES['printer_no_printer_standalone'][$lang] = "Ðе задан автономный принтер."; $MESSAGES['printer_warning_standalone'][$lang] = "Внимание : Принтер может быть в ÑпиÑке автономных принтеров, еÑли его Ñервер находитÑÑ Ð² автономном режиме.
    Эти Ñерверы поÑвÑÑ‚ÑÑ Ð² ÑпиÑке Ñервера, когда Ñервер принтра будет подключен"; $MESSAGES['printer_no_server'][$lang] = "DNS-Ð¸Ð¼Ñ ÑущеÑтвует, но нет ответа от Ñервера"; $MESSAGES['printer_dead_server'][$lang] = "Отвер Ñервера."; $MESSAGES['printer_no_printer_server'][$lang] = "Принт-Ñервер не определен.

    еÑли вы хотите, можете добавить на здеÑÑŒ : \" ".getMessage('setup_module')." \" --> \" ".getMessage('printer_server_section')." \"
    Тем не менее, вы можете иÑпользовать \" ".getMessage('printer_standalone_list')." \""; $MESSAGES['printer_check_all'][$lang] = "Выбрать вÑе"; //////////////////////////////////////////////////////////////////// // Модуль журнала //Log Module //////////////////////////////////////////////////////////////////// $MESSAGES['logs_note'][$lang] = "ÐктивноÑть терминалов: от новых к Ñтарым"; $MESSAGES['logs_ts'][$lang] = "Дата и времÑ"; $MESSAGES['logs_id'][$lang] = "ID узла
    терминала"; $MESSAGES['logs_mac'][$lang] = "MAC адреÑ"; $MESSAGES['logs_ip'][$lang] = "ÐдреÑ
    терминала"; $MESSAGES['logs_bootservip'][$lang] = "ÐÐ´Ñ€ÐµÑ Ñервера
    загрузки"; $MESSAGES['logs_appservip'][$lang] = "ÐÐ´Ñ€ÐµÑ Ñервера
    приложений"; $MESSAGES['logs_display'][$lang] = "\$Display"; $MESSAGES['logs_username'][$lang] = "ИмÑ
    пользователÑ"; $MESSAGES['logs_code'][$lang] = "Событие"; $MESSAGES['logs_bootservretry'][$lang] = "ЗапиÑи Ñервера загрузки"; $MESSAGES['logs_appservretry'][$lang] = "ЗапиÑи Ñервера приложений"; $MESSAGES['logs_prev'][$lang] = "Предыдущий"; $MESSAGES['logs_next'][$lang] = "Следующий"; $MESSAGES['logs_nb_logs_message'][$lang] = "Результатов на Ñтранице"; $MESSAGES['logs_filter_message'][$lang] = "Фильтры"; $MESSAGES['logs_table_message'][$lang] = "Результаты"; $MESSAGES['logs_validate'][$lang] = "Применить"; $MESSAGES['logs_code_booting'][$lang] = "Загрузка терминала"; $MESSAGES['logs_code_GDM'][$lang] = "Страница входа"; $MESSAGES['logs_code_logging'][$lang] = "Вход пользователÑ"; $MESSAGES['logs_code_unlogging'][$lang] = "Выход пользователÑ"; $MESSAGES['logs_msg_filter_seizure'][$lang] = "Фильтр захвата"; $MESSAGES['logs_msg_active_filters'][$lang] = "Ðктивные фильтры"; $MESSAGES['logs_code_msg_legend'][$lang] = "Легенда Ñобытий"; $MESSAGES['logs_equals'][$lang] = "="; $MESSAGES['logs_greater'][$lang] = ">"; $MESSAGES['logs_gt_equals'][$lang] = ">="; $MESSAGES['logs_smaller'][$lang] = "<"; $MESSAGES['logs_sm_equals'][$lang] = "<="; $MESSAGES['logs_not_equals'][$lang] = "!="; $MESSAGES['logs_send_add_filter'][$lang] = "Добавить фильтр"; $MESSAGES['logs_send_remove_filter'][$lang] = "Удалить вÑе фильтры"; $MESSAGES['messages_error'][$lang] = 'Это Ñообщение не уÑтановлено в text-ru.php'; unset($lang); ?> ltsp-cluster-control-2.0.3/Admin/util/Printer.php0000664000175000017500000001170712026403127022205 0ustar stgraberstgraber *
  • ID of the printer *
  • Printer name * * * Example of valid initialisation : * * * $prt=new Printer(7); // Use the Printer ID initialisation * $prt=new Printer("printer01"); //Use the printer name initialisation * * * @access public */ function Printer($id) { $this->ok = true; if (is_numeric($id)) $prt = $this->getFromDB("*", "id=".$id); elseif (is_string($id)) $prt = $this->getFromDB("*","printername='".$id."'"); else { $this->ok = false; $this->lastError = getMessage('bad_printer_id')." : id=".$id; } $this->id = $prt['id']; $this->printername = $prt['printername']; $this->description = $prt['description']; $this->priceperpage = $prt['priceperpage']; $this->priceperjob = $prt['priceperjob']; } /** * Get the printer ID * * @access public * @return int */ function getID() { return $this->id; } /** * Get the printer name * * @access public * @return string */ function getPrinterName() { return $this->printername; } /** * Get the printer description * * @access public * @return string */ function getDescription() { return $this->description; } /** * Get the printer price per page * * @access public * @return float */ function getPriceperpage() { return $this->priceperpage; } /** * Get the printer price per job * * @access public * @return float */ function getPriceperjob() { return $this->priceperjob; } /** * Return yes if the object exists * To be used just after the construction * * @access public * @return float */ function isError() { return !$this->ok; } /** * Get the last error * * @access public * @return float */ function lastError() { return $this->lastError; } /** * GetFromDB * * @access private * @return array */ function getFromDB($column,$where,$from="printers") { $sql_query='SELECT '.$column.' FROM '.$from.' WHERE '.$where; if (!$result = singleResultSelect($sql_query)) { $this->lastError = getMessage('printer_not_found')." : ".htmlspecialchars($where); $this->ok = false; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error').htmlspecialchars($result)." : ".htmlspecialchars($sql_query); $this->ok = false; return NULL; } else return $result; } /** * Change the printer name * * Return false if error. * * @access public * @return unknown */ function setPrinterName($name) { if (strlen($name) > 0) { $this->printername = $name; return $this->updatePrinter("printername='".$name."'"); } else { $this->lastError = getMessage('empty_printer_name'); return false; } } /** * updatePrinter * * @access private * @return unknown */ function updatePrinter($toSet, $from="printers") { if ($error = write("UPDATE ".$from." SET ".$toSet." WHERE id=".$this->id)) { $this->lastError = getMessage('db_write_error').htmlspecialchars($error); return false; } else return true; } /** * Print all informations about the printer with printerView.php * * @access public * @return none */ function print_printer() { include 'printerView.php'; } /** * Print just a little informations about the printer * * @access public * @return none */ function print_printer_resume() { print $this->getPrinterName()." (#".$this->getId().")"; } } // class Printer ?>ltsp-cluster-control-2.0.3/Admin/util/functions.php0000664000175000017500000002122112026403127022562 0ustar stgraberstgraber * - Creation */ /////////////////////////////////////////////////////////////////// // Including files /////////////////////////////////////////////////////////////////// global $first_start; require_once 'config.php'; require_once 'text-en.php'; require_once 'entityRole-config.php'; require_once 'roles-config.php'; require_once 'LogsViewer.php'; if (!$first_start) { include "config.php"; if (isset($CONFIG['lang']) && $CONFIG['lang'] != 'en') { if (is_readable("util/text-".$CONFIG['lang'].".php")) include 'text-'.$CONFIG['lang'].'.php'; else $ERRORS[] = getMessage('no_language_file'); } } /** * Return the _GET list in URL format * * This function is used to send again all GEt parameter. * * @param char Used to divide parameters (default &) */ function getGETParam($separator = '&') { $parameters = NULL; foreach ($_GET as $key => $value) { if ($parameters) $parameters .= $separator; $parameters .= $key.'='.$value; } return $parameters; } /** * Function that redirect to a other page * * This function redirect to the chosen page. As default it * redirect to the root with all preceeding GET parameters. * * @param string PHP filename and path to redirect to (default "") * @param bool Tel if GET paramters will be send (default true) */ function ltsp_goto($page = "",$send_param = true) { global $CONFIG; $param = NULL; if ($send_param) { if ($_SESSION['auth_state'] && !ereg('PHPSESSID=',getGETParam())) { if (getGETParam()) $param .= '&'; } if (getGETParam()) $param .= getGETParam(); if ($param) $param = '?'.$param; } if($_SERVER['HTTP_X_FORWARDED_HOST']) $prefix=$_SERVER['HTTP_X_FORWARDED_HOST']; else $prefix=$_SERVER['HTTP_HOST']; if($CONFIG["use_https"]=="false"){ header("Location: http://".$prefix.ereg_replace('/[^/]*\.php$','/',$_SERVER['PHP_SELF']).$page.$param); }else{ header("Location: https://".$prefix.ereg_replace('/[^/]*\.php$','/',$_SERVER['PHP_SELF']).$page.$param); } } /** * Redirect to https socket if needed * * This function test if the connection with browser uses secure * HTTPS socket. If not it redirects to https with all the same * GET parameters. */ function use_https() { if ($_SERVER['HTTPS'] != 'on') { if ($param = getGETParam()) $param = '?'.$param; header("Location: https://".$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'].$param); return false; } return true; } /** * Prints HTML header with a custum title message. * * This function prints a HTML header to the page. It sets a custum title and * define charset from the configuration file. * * @param string HTML page title */ function printHead($title_message) { global $CONFIG; // Printing license ?> '."\n"; print ''."\n"; print ''."\n"; print ''; print ''."\n"; print getMessage($title_message)."\n"; print ''."\n"; print ''."\n"; print ''."\n"; } /** * Returns a message using language configuration * * This function is an abstration layer to the multilangual support. * It takes message name and obtain the good string from messages * table. If the string doesn not exist it return the default message. * * @param string Message name */ function getMessage($messageName) { global $MESSAGES; global $CONFIG; // Try configured language if (isset($MESSAGES[$messageName][$CONFIG['lang']])) { return $MESSAGES[$messageName][$CONFIG['lang']]; } // Try default language elseif (isset($MESSAGES[$messageName]['en'])) { return $MESSAGES[$messageName]['en']; } // When not defined else return $messageName.": ".getMessage('messages_error'); } /** * Returns true if message is available * * This function check if a message is define. * * @param string Message name * @return bool True if message exist */ function isMessage($messageName) { global $MESSAGES; global $CONFIG; // Try configured language if (isset($MESSAGES[$messageName][$CONFIG['lang']])) { return true; } // Try default language elseif (isset($MESSAGES[$messageName]['en'])) { return true; } // When not defined else return false; } /** * Check if the user has an authenticated session on server. * * This function start a session and check if it is a valide session. * If not it cleans the session and return false. */ if (!$first_start) { function isSession() { session_start(); if (!$_SESSION['auth_state']) { ltsp_goto(); session_unset(); session_destroy(); } return true; } } /** * This function return the absolute inclide path * * This function return the absolute path of the libraries. * It adds possibility for other applications to link against * the Admin libraries. * * @return string Absolute libraries path */ function basePath() { return realpath(dirname(__File__)."/../")."/"; } /** * This function get the userRole. * * The role must be in permisssion order. The first role define must be the * admin role. This is for the case with a user with more than 1 group. */ function getUserRole($userData){ global $ROLE,$GROUP_ROLE; $isUserRoleSet = false; foreach ($ROLE as $roleName=>$role) { foreach($userData->getGroups() as $group=>$groupName){ if(strtolower($GROUP_ROLE[$groupName]) == strtolower($roleName)){ $userRole = $roleName; $isUserRoleSet = true; break; } } if($isUserRoleSet){ break; } } return $userRole; } /** * This function log operation on attributes and nodes (add, delete, modify, etc) */ function logAdminAccess($operation) { $conf = array('mode' => 0666, 'timeFormat' => '%x %X'); #$adminAccessLog = new LogsViewer('file', 'Log/admin_access.log', 'ident', $conf); $line = ','; foreach ($operation as $key=>$value) { $line .= "$value,"; } $sessionData = $_SESSION['groups']; $line .= $sessionData->getUsername(); #$adminAccessLog->log($line); } /** * Check ldap connection */ function setLdapAuth(){ // Testing ldap $auth = new Auth($_POST['login'],$_POST['password']); $error = $auth->authenticate(); unset($CONFIG['login']); unset($CONFIG['password']); return $error; } /** * This function is from AttributeManager but since it will be * useful elsewhere, it was ported here. * * Return the value of an value if it exists in the lang file */ function getValueMessage($attributeName, $value) { if (isMessage($attributeName."_".$value)) { return getMessage($attributeName."_".$value); } return $value; } function getNameMessage($attrName,$putSign = false) { if (isMessage($attrName)) { return getMessage($attrName); } else { if ($putSign) $equalSign = " = "; else $equalSign = ""; return $attrName.$equalSign; } } /** * Those are used to sort attributes by their name in the right langage */ function sortAttributesByLangName( $attA, $attB ){ return strcasecmp(getNameMessage( $attA ), getNameMessage( $attB )); } function sortObjectsByLangName( $attA, $attB ){ return strcasecmp(getNameMessage( $attA->getName() ), getNameMessage( $attB->getName() )); } ?> ltsp-cluster-control-2.0.3/Admin/util/SecurityRulesFinder.php0000664000175000017500000000736512026403127024541 0ustar stgraberstgraber *
  • IP of the computer * * * Example of valid initialisation : * * * $finder=new SecurityRulesFinder("10.1.0.9"); * * * @access public */ function SecurityRulesFinder($ipaddr) { $this->notFound = false; $this->ip = $ipaddr; $node = new Node($this->ip); $this->nodeid=$node->getID(); $parentId=$node->getParentID(); $columns="S.ip, N.mac, S.username, S.termaccess, S.publickey"; $from ="nodes N INNER JOIN status S ON S.id = N.id "; $where="N.id_parent=".$parentId." AND S.termaccess>0"; $result=$this->getFromDB($columns,$where,$from,true,true); if (!empty($result)) { foreach ($result as $res) { if ($res["termaccess"] > 1) { $this->authorizedIps[] = $res["ip"]; if ($res["termaccess"] > 1 && !empty($res["publickey"])) { $this->authorizedKeys[] = $res["publickey"]; } } } } } /** * Return true if not found * * @access public * @return int */ function notFound() { return $this->notFound; } /** * Get the autorized ips * * @access public * @return array */ function getAuthorizedIps() { return $this->authorizedIps; } /** * Get the autorized keys * * @access public * @return array */ function getAuthorizedKeys() { return $this->authorizedKeys; } /** * Get the node ID * * @access public * @return int */ function getNodeID() { return $this->nodeid; } /** * Return yes if the object exists * To be used just after the construction * * @access public * @return float */ function isError() { return $this->isError; } /** * Get the last error * * @access public * @return float */ function lastError() { return $this->lastError; } /** * GetFromDB * * @access private * @return array */ function getFromDB($column,$where,$from="attributes",$isFatal=true,$multiple = false) { $query='SELECT '.$column.' FROM '.$from.' WHERE '.$where; if ($multiple) { $result = select($query.";"); } else { $result = singleResultSelect($query); } if (!$result) { $this->lastError = getMessage('not_found').$query; $this->notFound = true; if ($isFatal) $this->isError = true; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error').$result." : ".$query; if ($isFatal) $this->isError = true; return NULL; } return $result; } } // class SecurityRulesFinder ?> ltsp-cluster-control-2.0.3/Admin/util/EntityNodeFinder.php0000664000175000017500000000706512026403127023776 0ustar stgraberstgraber *
  • IP of the computer * * * Example of valid initialisation : * * * $username = "user1"; * $groups = array(); * $finder=new EntityNodeFinder($username, $groups); * * * @access public */ function EntityNodeFinder($username,$groups) { $this->notFound = false; $this->username = $username; $this->groups = $groups; // Build WHERE statement $where=""; if (!empty($username)) { $where .= "(nodetype=" . USER_TYPE . " AND reference=" . qstr($username) . ") "; } foreach ($groups as $g) { if (!empty($where)) $where .= " OR "; $where .= "(nodetype=" . GROUP_TYPE . " AND reference=" . qstr($g) . ") "; } // Execute query $result=$this->getFromDB("id",$where,"nodes",true,true); if (!is_array($result) && !is_null($result)) { $this->lastError = getMessage('db_error') . $result; return NULL; } if (is_null($result)) { $this->lastError = ""; return NULL; } // Set the result foreach ($result as $r) { $this->nodesIds[] = $r["id"]; } } /** * Return true if not found * * @access public * @return int */ function notFound() { return $this->notFound; } /** * Get the nodes found * * @access public * @return int */ function getNodesIds() { return $this->nodesIds; } /** * Return yes if the object exists * To be used just after the construction * * @access public * @return float */ function isError() { return $this->isError; } /** * Get the last error * * @access public * @return float */ function lastError() { return $this->lastError; } /** * GetFromDB * * @access private * @return array */ function getFromDB($column,$where,$from="nodes",$isFatal=true,$multiple = false) { $query='SELECT '.$column.' FROM '.$from.' WHERE '.$where; if ($multiple) { $result = select($query.";"); } else { $result = singleResultSelect($query); } if (!$result) { $this->lastError = getMessage('not_found').$query; $this->notFound = true; if ($isFatal) $this->isError = true; return NULL; } elseif (!is_array($result)) { $this->lastError = getMessage('db_error').$result." : ".$query; if ($isFatal) $this->isError = true; return NULL; } return $result; } } ?> ltsp-cluster-control-2.0.3/Admin/util/LTSParser.php0000664000175000017500000000400412026403127022371 0ustar stgraberstgrabertext output * when print method is called. */ class LTSParser { var $lts; var $isError; function LTSParser($node) { if (strtolower(get_class($node)) != "node"){ $this->isError = true; return; } if ($node->isError()) { return; } /** * (PDubois)Patrick Dubois - July 9th, 2008 * Added the following if condition to make sure * the node would include hardware group attributes if any. * * Does this node have any matching hardware groups? * Yes -> get extended LTS. [ $node->getExtendedLTS() ] * No -> get simple LTS. [ $node->getLTS() ] * **/ /** ORIGINAL CODE : -- $this->lts = $node->getLTS(); $this->isError = false; -- **/ if ( $node->hasHWgroup() ){ $this->lts = $node->getExtendedLTS($node->getHWgroupIDs()); } // end if else{ $this->lts = $node->getLTS(); } // end else } function printView($preOn = true) { if ($this->isError) return; if ($preOn){ print "

    ".getMessage('config_attributes_listing')."

    "; print "
    \n";
    	    }
    	    if (is_array($this->lts)) {
    		foreach ($this->lts as $name => $value) {
    		    print "\t".$name."='".$value."'\n";
    		}
    	    }
    
    	    if ($preOn) print "
    \n"; } function isError(){ return $this->isError; } } ltsp-cluster-control-2.0.3/Admin/util/NodesMoveCmd.php0000664000175000017500000000402712026403127023102 0ustar stgraberstgraberisError OR $dest->isError) { $this->isError = true; return; } ///////////////////////////// // Actions ///////////////////////////// // Cancel if (isset($_POST['ne_cancel'])) { unset($GLOBALS['_POST']); } // Move elseif (isset($_POST['ne_move'])) { if ($node->isError()) $this->errors[] = $node->lastError()." : id=".$id; elseif (!$node->setParent($dest->getID())) { $this->errors[] = $node->lastError()." : id=".$id; } } $this->node = $node; $this->dest = $dest; if (!isset($_POST['ne_node_name'])) $_POST['ne_node_name'] = $node->getName(); } /** * Print errors * * @access public */ function printErrors() { if (isset($this->errors[0])) print "

    \n"; else return; foreach ($this->errors as $error) { print "".$error."
    \n"; } print "

    \n"; } /** * Print the browser HTML view * * @access public * @return stdout */ function printView() { if ($this->isError) { $this->printErrors(); } else { include 'nodesMoveCmdView.php'; } } } ?> ltsp-cluster-control-2.0.3/Admin/util/setup.php0000664000175000017500000001504212026403127021716 0ustar stgraberstgraber * - Creation */ switch($module_action) { case 'build': break; default: require_once 'functions.php'; require_once "LDAPAuth.php"; require_once 'entityRole-config.php'; require_once 'roles-config.php'; require_once 'SessionData.php'; global $GROUP_ROLE,$ROLE; #if (!use_https()) die(getMessage('need_https')); global $CONFIG; if($CONFIG['first_setup_lock'] == "TRUE"){ $preserveLock=TRUE; } if($_POST['save']){ require_once 'Node.php'; $valide = true; unset($GLOBALS[CONFIG]); unset($CONFIG); global $CONFIG; foreach ($_POST as $name=>$value) { if ($value) { $CONFIG[$name] = $value; } } // Some message depend on config, refreshing include 'text-en.php'; // Testing language file if (!$valide = is_readable("util/text-".$CONFIG['lang'].".php")) { $ERRORS[] = getMessage('no_language_file'); } // Testing database config $root = new Node(0); if ($root->isError()) { $ERRORS[] = $root->lastError(); $valide = false; } if ($valide) { $handle = fopen("util/config.php","w"); if ($handle) { fwrite($handle," $value) { //get Printer servers list if(substr($name,0,15) == "printer_servers" && $value){ $printerServers[] = $value; }else if(substr($name,0,10) == "group_ldap" && strlen($value)>1){ $ldapGroupRole[$value]=$_POST["role_".$name]; }else if(substr($name,0,15) == "role_group_ldap" && $value){ //this is a role, it is process with the group (previous if) }else if($value) fwrite($handle,"\t".'$CONFIG[\''.$name.'\'] = "'.$value.'";'."\n"); } $hasPrinterServers = FALSE; $printerCount=0; if(is_array($printerServers)){ foreach($printerServers as $printerServer){ $printerCount++; if($printerCount == 1){ $hasPrinterServers = TRUE; $printerServersStr = '$CONFIG[\'printer_servers\'] = array("'.$printerServer.'"'; }else{ $printerServersStr = $printerServersStr.',"'.$printerServer.'"'; } $CONFIG['printer_servers'][] = $printerServer; } } if($printerCount > 0){ $printerServersStr = $printerServersStr.');'; fwrite($handle,"\t".$printerServersStr."\n"); } fwrite($handle,"\t".'$CONFIG[\'rootInstall\']="'.basePath()."\";\n"); fwrite($handle,"\n?>\n"); fclose($handle); //if ($first_start) { if ($_POST['first_setup_lock']=="TRUE") { ltsp_goto(); break; } else { $CONFIRMATIONS[] = getMessage('new_cfg_created'); } //write the group->role in the entityRole-config.php file ifi ldap is use*************** $roleHandle = fopen("util/entityRole-config.php","w"); if ($roleHandle) { fwrite($roleHandle," $roleToAdd) { $groupCount++; $hasGroups = TRUE; $groupRoleStr = '$GROUP_ROLE[\''.strtolower($groupToAdd).'\'] ="'.$roleToAdd."\";\n"; fwrite($roleHandle,$groupRoleStr); $GROUP_ROLE[$groupToAdd] = $roleToAdd; } } fwrite($roleHandle,"\n?>\n"); fclose($roleHandle); } } else { $ERRORS[] = getMessage('cannot_open_cfg_file'); } } // Dropping to default //unset($GLOBALS[CONFIG]); //unset($CONFIG); global $CONFIG; if (is_readable("config.php")) { include "config.php"; } //test ldap user }else if($_POST['test']){ //testing authentification service // Testing ldap $auth = new Auth($_POST['login'],$_POST['password']); $error = $auth->authenticate(); unset($CONFIG['login']); unset($CONFIG['password']); if(!empty($error)){ $ERRORS[] = $error; }else{ $CONFIRMATIONS[]=getMessage('group_role_msg'); $user = $auth->userData; $gr = $user->getGroups(); if(empty($gr)){ $CONFIRMATIONS[]=getMessage('no_group_role_msg'); }else{ foreach($user->getGroups() as $group){ if($GROUP_ROLE[strtolower($group)]){ $CONFIRMATIONS[] = $group."--->".$GROUP_ROLE[strtolower($group)]; }else{ $CONFIRMATIONS[] = $group."--->".getMessage('no_role_msg'); } } } } }else if($_POST['lock_setup']){ //we only need to change first_setup_lock form false to true $CONFIG['first_setup_lock']="TRUE"; $handle = fopen("util/config.php","w"); if ($handle) { fwrite($handle," $value){ //printers are in a array if(is_array($value)){ $valueStr="array("; $count=0; foreach($value as $val){ $count++; if($count == 1){ $valueStr = $valueStr.'"'.$val.'"'; }else{ $valueStr = $valueStr.','.'"'.$val.'"'; } } $valueStr = $valueStr.")"; fwrite($handle,"\t".'$CONFIG[\''.$name.'\'] = '.$valueStr.';'."\n"); }else if($value) fwrite($handle,"\t".'$CONFIG[\''.$name.'\'] = "'.$value.'";'."\n"); } fwrite($handle,"\n?>\n"); ltsp_goto(); break; } } include "errorsView.php"; include "setupView.php"; break; } ?> ltsp-cluster-control-2.0.3/Admin/inventory.php0000664000175000017500000000223712026403127021640 0ustar stgraberstgraber LTSP Cluster Control - inventaire
    INVENTORY_NUMBER:
    "; exit; } $number=$_GET['number']; //if we got here the configuration is correct. require_once 'util/config.php'; $db = pg_connect("host=".$CONFIG['db_server']." dbname=".$CONFIG['db_name']." user=".$CONFIG['db_user']." password=".$CONFIG['db_password']); $query = "SELECT status.id FROM status LEFT JOIN attributes ON status.id=attributes.nodes_id LEFT JOIN attributesdef ON attributes.attributesdef_id=attributesdef.id WHERE attributesdef.name='INVENTORY_NUMBER' AND attributes.value='$number';"; $result = pg_query($query); $line=pg_fetch_array($result); $id=$line[0]; if ($id) { header("Location: /ltsp-cluster-control/Admin/admin.php?node_id=$id&module=configuration_module"); } else { header("Location: /ltsp-cluster-control/Admin/admin.php?node_id=0&module=configuration_module"); } ?> ltsp-cluster-control-2.0.3/Admin/index.php0000664000175000017500000000401312026403127020704 0ustar stgraberstgraberauthenticate()) $ERRORS[] = $error; else { session_start(); $_SESSION['auth_state'] = true; $_SESSION['groups'] = $auth->getUserData(); if($CONFIG['auth_name'] == "EmptyAuth"){ $_SESSION['userRole']="Superadmin"; }else{ $_SESSION['userRole']=getUserRole($auth->getUserData()); } ltsp_goto('admin.php'); die(getMessage('good_login')); } } // Print standard header printHead('admin_title'); // Print page include "util/loginView.php"; ?> ltsp-cluster-control-2.0.3/Tech/0000775000175000017500000000000012026403130016713 5ustar stgraberstgraberltsp-cluster-control-2.0.3/Tech/css0000777000175000017500000000000012026403127021405 2../Admin/cssustar stgraberstgraberltsp-cluster-control-2.0.3/Tech/admin.php0000777000175000017500000000000012026403127023561 2../Admin/admin.phpustar stgraberstgraberltsp-cluster-control-2.0.3/Tech/util0000777000175000017500000000000012026403127021757 2../Admin/utilustar stgraberstgraberltsp-cluster-control-2.0.3/Tech/perms.php0000664000175000017500000000015112026403127020555 0ustar stgraberstgraber ltsp-cluster-control-2.0.3/Tech/index.php0000777000175000017500000000000012026403127023617 2../Admin/index.phpustar stgraberstgraberltsp-cluster-control-2.0.3/DB/0000775000175000017500000000000012026403130016315 5ustar stgraberstgraberltsp-cluster-control-2.0.3/DB/functions.sql0000664000175000017500000002200412026403127021052 0ustar stgraberstgraber/* Copyright 2006, CRIM, Stephane Bond This file is part of the MILLE-XTERM distribution. See the MILLE-XTERM (english) and/or the MILLE (french) project web site http://www.revolutionlinux.com/mille-xterm/ http://www.mille.ca/ The MILLE-XTERM framework is covered by the GNU General Public License. See the COPYING file in the top-level MILLE-XTERM directory. Software packages that are included in the MILLE-XTERM distribution have their own licenses. ------------------------------------------------------------------------- This script creates function and triggers to manage the nodes nstree structure. Nstree are described in this article : - http://www.sitepoint.com/article/hierarchical-data-database Trigger implementation example : - http://openacs.org/forums/message-email?message_id=16799 Revisions history: - 10 feb 2006: Creation */ /* The rebuild_tree(parent, left) function set leftval and rightval values of "parent" and his childs. The first left value ef the nested set are specified by the left parameter. Tree is traversed recursively. Function returns the last right value of the set + 1. */ -- -- DROP FUNCTION rebuild_tree (INTEGER, INTEGER); -- CREATE LANGUAGE plpgsql; CREATE FUNCTION rebuild_tree (INTEGER, INTEGER) RETURNS INTEGER AS ' DECLARE v_parent ALIAS FOR $1; v_left ALIAS FOR $2; v_right INTEGER; child RECORD; BEGIN -- The right value of this node is the left value + 1 v_right := v_left + 1; -- Get all children of this node ordered by id FOR child IN SELECT id FROM nodes WHERE id_parent = v_parent AND id != id_parent ORDER BY id LOOP -- Recursive execution of this function for each child of this node v_right := rebuild_tree(child.id, v_right); END LOOP; -- We`ve got the left value, and now that we`ve processed -- the children of this node we also know the right value UPDATE nodes SET leftval = v_left, rightval = v_right WHERE id = v_parent; RETURN v_right + 1; END; ' LANGUAGE 'plpgsql'; /* The rebuild_tree() function execute rebuild_tree(parent, left) on all root nodes */ -- -- DROP FUNCTION rebuild_tree(); -- CREATE FUNCTION rebuild_tree () RETURNS BOOLEAN AS ' DECLARE v_next INTEGER; child RECORD; BEGIN v_next := 1; -- Get all root nodes FOR child IN SELECT id FROM nodes WHERE id = id_parent LOOP v_next := rebuild_tree(child.id, v_next); END LOOP; RETURN true; END; ' LANGUAGE 'plpgsql'; /* The nodes_delete() trigger function update the nested tree for a leaf deletion. Deletion is canceled if the node contains a subtree */ -- -- DROP FUNCTION nodes_delete() CASCADE; -- CREATE FUNCTION nodes_delete () RETURNS OPAQUE AS ' BEGIN -- Prevent deletion of non empty nodes IF (OLD.rightval - OLD.leftval) != 1 THEN RAISE EXCEPTION ''Can not delete non-empty node : %'', OLD.id; RETURN NULL; ELSE UPDATE nodes SET leftval = leftval - 2 WHERE leftval > OLD.rightval; UPDATE nodes SET rightval = rightval - 2 WHERE rightval > OLD.rightval; RETURN OLD; END IF; END; ' LANGUAGE 'plpgsql'; CREATE TRIGGER nodes_delete_tr BEFORE DELETE ON nodes FOR EACH ROW EXECUTE PROCEDURE nodes_delete() ; /* The nodes_insert() trigger function update the tree for the new node insertion */ -- -- DROP FUNCTION nodes_insert() CASCADE; -- CREATE FUNCTION nodes_insert () RETURNS OPAQUE AS ' DECLARE v_max_rightval INTEGER; v_parent_rightval INTEGER; BEGIN -- We differentiate two cases, depending on whether the newly -- inserted has parent or not. IF NEW.id = NEW.id_parent THEN SELECT coalesce(max(rightval),0) INTO v_max_rightval FROM nodes; NEW.leftval := v_max_rightval + 1; NEW.rightval := v_max_rightval + 2; ELSE -- New node is inserted at the right node of the parent, -- shifting everything two places to the right. SELECT rightval INTO v_parent_rightval FROM nodes WHERE id = NEW.id_parent; UPDATE nodes SET leftval = leftval + 2 WHERE leftval > v_parent_rightval; UPDATE nodes SET rightval = rightval + 2 WHERE rightval >= v_parent_rightval; NEW.leftval := v_parent_rightval; NEW.rightval := v_parent_rightval + 1; END IF; RETURN NEW; END; ' LANGUAGE 'plpgsql'; CREATE TRIGGER nodes_insert_tr BEFORE INSERT ON nodes FOR EACH ROW EXECUTE PROCEDURE nodes_insert() ; /* The nodes_update_pre() function raise an exception if the update broke the tree integrity. A node can not be moved inside one of his child */ CREATE FUNCTION nodes_update_pre () RETURNS OPAQUE AS ' DECLARE v_result BOOLEAN; BEGIN -- Exit if parent is not updated IF OLD.id_parent = NEW.id_parent THEN RETURN NEW; END IF; -- Can not move a node inside one of his child IF NEW.id != NEW.id_parent THEN SELECT true INTO v_result FROM nodes WHERE id = NEW.id_parent AND leftval BETWEEN OLD.leftval AND OLD.rightval; IF FOUND THEN RAISE EXCEPTION ''Can not move a node inside one of his child''; RETURN NULL; END IF; END IF; RETURN NEW; END; ' LANGUAGE 'plpgsql'; CREATE TRIGGER nodes_update_tr_pre BEFORE UPDATE ON nodes FOR EACH ROW EXECUTE PROCEDURE nodes_update_pre() ; /* The nodes_update_post() function update the tree after the update operation. Operation must be done "after update" because the updated record will be re-updated by the algorithm. This leads to 3 cases: 1. parent changes from leaf to root 2. parent changes from root to leaf 3. parent changes from leaf to leaf */ -- -- DROP FUNCTION nodes_update_post () CASCADE; -- /* -- contains bugs when moving child to the root level CREATE FUNCTION nodes_update_post () RETURNS OPAQUE AS ' DECLARE v_max_rightval INTEGER; v_nested_set_width INTEGER; v_shift_offset INTEGER; v_parent_leftval INTEGER; v_parent_rightval INTEGER; BEGIN -- Exit if parent is not updated IF OLD.id_parent = NEW.id_parent THEN RETURN NEW; END IF; -- Prepare move SELECT max(rightval) INTO v_max_rightval FROM nodes; v_nested_set_width := OLD.rightval - OLD.leftval + 1; v_shift_offset := v_max_rightval - OLD.leftval + 1; -- Shift nested subset out of its parent. UPDATE nodes SET leftval = leftval + v_shift_offset, rightval = rightval + v_shift_offset WHERE leftval >= OLD.leftval AND rightval <= OLD.rightval; -- Case 1 : change a leaf node to a root node IF OLD.id != OLD.id_parent AND NEW.id = NEW.id_parent THEN -- Since we have already lifted our subset out of its -- position, we will simply renumber the nodes to fill the gaps. UPDATE nodes SET leftval = leftval - v_nested_set_width WHERE leftval > OLD.rightval; UPDATE nodes SET rightval = rightval - v_nested_set_width WHERE rightval > OLD.rightval; RETURN NEW; END IF; -- Case 2 and 3 : move into a leaf IF NEW.id != NEW.id_parent THEN -- The tricky part here is that we must pay attention whether -- the gap is to the left or to the right of inserting point. SELECT leftval, rightval INTO v_parent_leftval, v_parent_rightval FROM nodes WHERE id = NEW.id_parent; -- Where will this subset be moved? IF v_parent_rightval < OLD.leftval THEN -- Gap is to the right of inserting point UPDATE nodes SET leftval = leftval + v_nested_set_width WHERE leftval > v_parent_rightval AND leftval < OLD.leftval; UPDATE nodes SET rightval = rightval + v_nested_set_width WHERE rightval >= v_parent_rightval AND rightval < OLD.leftval; -- Place the subset under its new parent v_shift_offset := v_max_rightval - v_parent_rightval + 1; ELSE -- The gap is to the LEFT of inserting point UPDATE nodes SET leftval = leftval - v_nested_set_width WHERE leftval <= v_parent_leftval AND leftval > OLD.rightval; UPDATE nodes SET rightval = rightval - v_nested_set_width WHERE rightval < v_parent_leftval AND rightval > OLD.rightval; v_shift_offset := v_max_rightval + v_nested_set_width - v_parent_leftval; END IF; UPDATE nodes SET rightval = rightval - v_shift_offset, leftval = leftval - v_shift_offset WHERE leftval > v_max_rightval; RETURN NEW; END IF; END; ' LANGUAGE 'plpgsql'; */ CREATE FUNCTION nodes_update_post () RETURNS OPAQUE AS ' DECLARE v_result BOOLEAN; BEGIN -- Exit if parent is not updated IF OLD.id_parent = NEW.id_parent THEN RETURN NEW; END IF; v_result := rebuild_tree(); RETURN NEW; END; ' LANGUAGE 'plpgsql'; CREATE TRIGGER nodes_update_tr_post AFTER UPDATE ON nodes FOR EACH ROW EXECUTE PROCEDURE nodes_update_post() ; /* Rebuild the tree after triggers creation */ SELECT rebuild_tree(); ltsp-cluster-control-2.0.3/DB/schema.sql0000664000175000017500000003576512026403127020324 0ustar stgraberstgraber/* Copyright 2004, Revolution Linux Inc., Nicolas Dufresne, Yves Trudeau Copyright 2006, CRIM, Stephane Bond This file is part of the MILLE-XTERM distribution. See the MILLE-XTERM (english) and/or the MILLE (french) project web site http://www.revolutionlinux.com/mille-xterm/ http://www.mille.ca/ The MILLE-XTERM framework is covered by the GNU General Public License. See the COPYING file in the top-level MILLE-XTERM directory. Software packages that are included in the MILLE-XTERM distribution have their own licenses. ------------------------------------------------------------------------- This script creates the tables needed for the Mille-XTERM configurator. Revisions history: - 13 jul 2004: Creation - 10 feb 2006: Major update, nodes structure optimisation, support for permissions and inventory Last changes : Release 1.0 - Add hwgroups column to status - Add tables for inventory and hwgroups : computers, computershw, pciids, hwgroupsrule - Add permissions table - Add attributesDefDesc for localized strings - Add attributeClass to the attributesDef table - Add nested set algorithme (leftval, rightval and triggers) to improve queries on nodes tree - Support for different node type : change isnode to nodetype and add reference column to the nodes table */ /* The nodes table contains the tree of nodes, an entry can be a node or a leaf depending of the value of nodeType. If the entry is a node, the fields MAC and reference are not used. id_parent is a circular reference to id. - id_parent is the ancestor in the tree. For the root node, id_parent = id - leftval and rightval, used for the nested set algorithm - name is the name of the node - nodetype take the following values : 0 = node : a node in the tree, can contain childs nodes ans leafs 1 = computer : leaf with mac address 2 = hwgroup : hardware group defined with a set of rules 3 = user : user present in an external system (reference field contains username) 4 = group : group present in an external system (reference field contains groupname) - MAC is the mac address of the node when nodetype = 1 - reference is the key of the entity in the external system */ CREATE TABLE nodes ( id SERIAL PRIMARY KEY, id_parent INTEGER NOT NULL REFERENCES nodes (id), leftval INTEGER NOT NULL DEFAULT 0, rightval INTEGER NOT NULL DEFAULT 0, name VARCHAR(50) DEFAULT '', nodetype INTEGER DEFAULT 0, mac VARCHAR(17) DEFAULT '00:00:00:00:00:00', reference VARCHAR(254) CONSTRAINT invalidName CHECK (nodetype <> 0 OR LENGTH(name) > 0) CONSTRAINT invalidMac CHECK (nodetype <> 1 OR mac::text > '00:00:00:00:00:00'::text) CONSTRAINT invalidReference CHECK ((nodetype <> 2 AND nodetype <> 3) OR LENGTH(reference) > 0) CONSTRAINT invalidType CHECK (nodetype >= 0 AND nodetype <= 4) ); CREATE INDEX nodes_name_IDX ON nodes (name); CREATE INDEX nodes_mac_IDX ON nodes (mac); CREATE INDEX nodes_reference_IDX ON nodes (reference); CREATE INDEX nodes_nodetype_IDX ON nodes (nodetype); CREATE INDEX nodes_leftrightval_IDX ON nodes (leftval, rightval); CREATE INDEX nodes_id_parent ON nodes (id_parent, id); CREATE UNIQUE INDEX nodes_reference_type_unique_IDX ON nodes (nodetype,reference); -- nodes needs a root node_group with id = 0 INSERT INTO nodes (id,id_parent,name) VALUES (0,0,'RootNode'); INSERT INTO nodes (id,id_parent,name) VALUES (-1,0,'Trash'); /* The attributesDef table contains the definition of the attributes - name is the name of the attribute - attributeClass is the category of attribute (i.e. "ltsp", "profile", "inventory", ...) - attributeType is the type of attribute: 0 = String with mask (default), 1 = list, 2 = selection When attributeType = 1 (list), the possible values are found in attributesDefDict List of facultatives values can be present in attributesDefDict when attributeType = 0 - mask is the mask to apply to the value in regular expression - ediatble : can be edited online */ CREATE TABLE attributesDef ( id SERIAL PRIMARY KEY, name VARCHAR(50) UNIQUE, attributeClass VARCHAR(50) DEFAULT 'ltsp', attributeType INTEGER DEFAULT 0 CHECK ( attributeType >=0 AND attributeType <= 2), mask VARCHAR(254) DEFAULT E'^[^\']{0,254}$', editable INTEGER DEFAULT 0 CHECK (editable = 1 OR editable = 0)); CREATE INDEX attributesDef_name_IDX ON attributesDef (name); /* The attributesDefDesc table contains localized descriptions of attributes - attributesdef_id reference attributesDef - locale is the language code of the string (i.e. "en_US", "fr_CA") - locname is the localizen name of the attribute - desc is a long description of the attribute. Can be used for contextual help */ CREATE TABLE attributesDefDesc ( attributesdef_id INTEGER NOT NULL REFERENCES attributesDef (id), locale CHAR(5) NOT NULL, locname VARCHAR(50), description VARCHAR(254), PRIMARY KEY (attributesdef_id, locale)); /* The attributes table contains the attributes of a group or a node - nodes_id is the nodes owner of this attributes - attributesDef_id is the definition of the attributes - value is the actual value of the attributes - cumulative, in multiselect mode, cumulate values of parents instead of replacing it */ CREATE TABLE attributes ( nodes_id INTEGER NOT NULL REFERENCES nodes (id), attributesDef_id INTEGER NOT NULL REFERENCES attributesDef (id), value VARCHAR(254), cumulative INTEGER DEFAULT 0 CHECK (cumulative = 1 OR cumulative = 0), PRIMARY KEY (nodes_id, attributesDef_id)); CREATE INDEX attributes_value_IDX ON attributes (value,attributesDef_id); /* The attributesDefDict contains the possible values of an attributes when its attributeType = 1 (list) - attributesDef_id is the attribute definition of type list owner of the value - sortval is a hint for sorting the list */ CREATE TABLE attributesDefDict ( attributesDef_id INTEGER NOT NULL REFERENCES attributesDef (id), value VARCHAR(254), sortval INTEGER, PRIMARY KEY (attributesDef_id,value)); CREATE INDEX attributesDefDict_attributes_id_IDX ON attributesDefDict (attributesDef_id); /* The attributesSelect contains results from a type 2 attributesType (muliselect list) - nodes_id references an node attributes - attributesDef_id references attributes definition - attributesDefDict_id references an element from attributes definition dictionary */ CREATE TABLE attributesSelect ( nodes_id INTEGER, attributesDef_id INTEGER, value VARCHAR(254), FOREIGN KEY (nodes_id,attributesDef_id) REFERENCES attributes (nodes_id,attributesDef_id), FOREIGN KEY (attributesDef_id,value) REFERENCES attributesDefDict (attributesDef_id,value) ON DELETE cascade ON UPDATE cascade, PRIMARY KEY (nodes_id,attributesDef_id,value)); /* The permissions table store administration privileges on the structure - granteetype 1 = username 2 = groupname - granteekey is the user or group name who have permissions - attributes specify an attribute name or pattern affected by permissions. Example : "" = permissions on tree modifications (edit hierarchy, add child, ...) "*" = permissions on all attributes "ltsp.*" = permission on all ltsp attributes "SECRREN_01" = permission only on attribute "SECRREN_01" "SECRREN_*" = all attributes begining with "SECRREN_" - scope of the permission 0 = the current node only 1 = the current node and his subtree - canadd new attribute / child node - candelete existing attribute / child node - canread attribute / child node - canwrite allow attributes modifications If they are permissions set at different level of hierarchy, the closest permission will be apply If a user obtain two permission on the same node from two different groups, the most privilegious permission will be selected. */ CREATE TABLE permissions ( nodes_id INTEGER NOT NULL REFERENCES nodes (id), granteetype INTEGER NOT NULL CHECK (granteetype = 1 OR granteetype = 2), granteekey VARCHAR(254) NOT NULL, attributes VARCHAR(50) NOT NULL, scope INTEGER CHECK (scope = 1 OR scope = 0), canadd INTEGER CHECK (canadd = 1 OR canadd = 0), candelete INTEGER CHECK (candelete = 1 OR candelete = 0), canread INTEGER CHECK (canread = 1 OR canread = 0), canwrite INTEGER CHECK (canwrite = 1 OR canwrite = 0), PRIMARY KEY (nodes_id, granteetype, granteekey, attributes)); CREATE INDEX permissions_granteekey_IDX ON permissions (granteekey); /* The status table store actual status of leaves. - mac, the mac address of the node accessing the configurator (mandatory) - nodeIpAdd, the ip address of the node accessing the configurator if available - nfsIp, the ip address of the nfs server - xServIp, the ip address of the X server (needed for code = 2 and 3) - display, the X display number of the leave accessing the configurator if available - username, the name of the user on the node accessing the configurator if available - code, the request asked to the configurator. Currently supported values are: 1 = Node asks for config (giving ip and nfsIp) 2 = Starting X session for display manager 3 = Starting X session for user session 4 = Logoff - hwgroups, list of currently used hardware groups separated by coma (field computed on the code 1 request) - publickey, public key of active session - termAccess, Access level on terminals. Currently supported values are: 0 = None 1 = Can access terminals of same node (FireWall rule) 2 = Can open session on terminals of same node (ssh key) 3 = Can open session on all terminals (for remote control assistance) - lastBootServIp, timestamp of last nfsIp modification - lastAppServIp, timestamp of last nfsIp modification */ CREATE TABLE status ( id INTEGER NOT NULL PRIMARY KEY REFERENCES nodes (id), mac VARCHAR(17) NOT NULL CONSTRAINT macNotUnique UNIQUE, ip VARCHAR(15) NOT NULL CONSTRAINT ipNotUnique UNIQUE, bootServIp VARCHAR(15) NOT NULL, appServIp VARCHAR(15) DEFAULT '0.0.0.0', display VARCHAR(50) DEFAULT '-1', username VARCHAR(50) DEFAULT '', code INTEGER NOT NULL CHECK (code > 0 AND code <= 4), bootServRetry INTEGER DEFAULT 0, appServRetry INTEGER DEFAULT 0, hwgroups VARCHAR(254) DEFAULT '', termAccess INTEGER DEFAULT 0, publickey TEXT DEFAULT '', ts_lastBootServIp TIMESTAMP DEFAULT 'now', ts_lastAppServIp TIMESTAMP DEFAULT '-infinity' CONSTRAINT invalidTermAccess CHECK (termAccess = 0 OR (code = 3 AND termAccess >=0 AND termAccess <=3)) CONSTRAINT invalidAppServIp CHECK (code = 1 OR (code > 1 AND appServIP > '0.0.0.0')) CONSTRAINT invalidDisplay CHECK (code = 1 OR code= 2 OR (code > 2 AND LENGTH(display) > 0 AND display != '-1')) CONSTRAINT invalidUsername CHECK (code < 3 OR (code >= 3 AND LENGTH(username) > 0)) CONSTRAINT notALeave CHECK (mac > '00:00:00:00:00:00')); CREATE INDEX status_id_IDX ON status (id); CREATE INDEX status_ip_IDX ON status (ip); CREATE INDEX status_appServIp_IDX ON status (appServIp); CREATE INDEX status_bootServIp_IDX ON status (bootServIp); CREATE INDEX status_username_IDX ON status (username); CREATE INDEX status_code_IDX ON status (code); /* The log table store the log of access to the configurator. - mac, the mac address of the node accessing the configurator (mandatory) - ip, the ip address of the node accessing the configurator if available - bootServIp, the ip address of the nfs server - appServIp, the ip address of the X server (needed for code = 2 and 3) - display, the X display number of the leave accessing the configurator if available - username, the name of the user on the node accessing the configurator if available - hwgroups, list of currently used hardware groups separated by coma (field computed on the code 1 request) - code, the request asked to the configurator. Currently supported values are: 1 = Node asks for config (giving ip, bootServIp) 2 = Starting X session for display manager 3 = Starting X session for user session 4 = Logout X session */ CREATE TABLE log ( id_key SERIAL PRIMARY KEY, id INTEGER NOT NULL, mac VARCHAR(17) NOT NULL, ip VARCHAR(15) NOT NULL, bootServIp VARCHAR(15) NOT NULL, appServIp VARCHAR(15) DEFAULT '0.0.0.0', display INTEGER DEFAULT -1, username VARCHAR(50) DEFAULT '', code INTEGER NOT NULL CHECK (code > 0 AND code <= 4), bootServRetry INTEGER DEFAULT 0, appServRetry INTEGER DEFAULT 0, hwgroups VARCHAR(254) DEFAULT '', ts TIMESTAMP DEFAULT 'now' CONSTRAINT invalidAppServIp CHECK (code = 1 OR (code > 1 AND appServIP > '0.0.0.0')) CONSTRAINT invalidDisplay CHECK (code = 1 OR code= 2 OR (code > 2 AND display != '-1')) CONSTRAINT invalidUsername CHECK (code < 3 OR (code >= 3 AND LENGTH(username) > 0)) CONSTRAINT notALeave CHECK (mac > '00:00:00:00:00:00')); CREATE INDEX log_mac_IDX ON log (mac); CREATE INDEX log_ip_IDX ON log (ip); CREATE INDEX log_appServIp_IDX ON log (appServIp); CREATE INDEX log_bootServIp_IDX ON log (bootServIp); CREATE INDEX log_username_IDX ON log (username); CREATE INDEX log_TS_IDX ON log (ts); /* Table computershw contains list of hardware specification - nodes_id is a reference to a node of type 1 (computer) - hwkey is the identifier of the hardware attribute (i.e. "cpufreq", "pcidevice", "memsize", "biosvendor", "cdrom", ...) - hwvalue is the value of the hardware attribute */ CREATE TABLE computershw ( nodes_id INTEGER REFERENCES nodes (id) ON DELETE cascade, hwkey VARCHAR(50), hwvalue VARCHAR(254), PRIMARY KEY (nodes_id, hwkey, hwvalue)); /* Table hwgroupsrule contains a rule - nodes_id is a reference to a node of type 4 (hwgroup) - hwkey is the key used for the rule - hwvalue is the value to compare at the rule processing "*" = any value - operator, support theses values : "=" = a computer must have the exact key/value to be member ">" = a computer must have the attribute with a value ">" then "<" = a computer must have the attribute with a value "<" then "~" = a computer must not have the attribute with the specified value A hwgroup node can habe multiple rules. A computer must respect all rules to be a member of the hwgroup. */ CREATE TABLE hwgroupsrule ( nodes_id INTEGER REFERENCES nodes (id) ON DELETE cascade, hwkey VARCHAR(50), hwvalue VARCHAR(254), operator CHAR(2), PRIMARY KEY (nodes_id, hwkey, hwvalue)); /* Table hwkeysdesc contains localized description of hwkeys - hwkey, the reference to the hwkey - locale is the language code of the string (i.e. "en_US", "fr_CA") - locname is the localized name of the hwkey Presence of hwkeysdesc is facultative. New hwkey can be added by the inventory system without insertin in this table. */ CREATE TABLE hwkeysdesc ( hwkey VARCHAR(50), locale CHAR(5), locname VARCHAR(50), PRIMARY KEY (hwkey, locale)); /* Table pciids contains the name of pci device - pciid, the numerical id of a device - name, the corresponding name of the device */ CREATE TABLE pciids ( pciid VARCHAR(50) PRIMARY KEY, name VARCHAR(254)); ltsp-cluster-control-2.0.3/COPYING0000664000175000017500000004307612026403127017103 0ustar stgraberstgraber GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.