summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog131
-rw-r--r--TODO3
-rw-r--r--docs/bare_scire.sql1060
-rw-r--r--docs/jobs_flow/get_job.pngbin0 -> 178611 bytes
-rw-r--r--docs/jobs_flow/get_jobs.pngbin0 -> 137964 bytes
-rw-r--r--docs/jobs_flow/get_jstatus.pngbin0 -> 63815 bytes
-rw-r--r--docs/jobs_flow/run_jobs.pngbin0 -> 183262 bytes
-rw-r--r--docs/jobs_flow/scirec_main.pngbin0 -> 99422 bytes
-rw-r--r--docs/jobs_flow/svg/get_job.svg800
-rw-r--r--docs/jobs_flow/svg/get_jobs.svg863
-rw-r--r--docs/jobs_flow/svg/get_jstatus.svg428
-rw-r--r--docs/jobs_flow/svg/run_jobs.svg1194
-rw-r--r--docs/jobs_flow/svg/scirec_main.svg628
-rw-r--r--docs/moria.sql96
-rw-r--r--docs/moria2.sql23
-rw-r--r--docs/phpgacl_seed.sql104
-rw-r--r--docs/scire.conf7
-rw-r--r--docs/scire.sql551
-rw-r--r--docs/scire2.sql47
-rw-r--r--docs/scire3.sql20
-rw-r--r--docs/scire4.sql7
-rw-r--r--docs/scire_client_backend_details.txt27
-rw-r--r--docs/scire_server_backend_details.txt45
-rw-r--r--docs/screenshots/cron.jpgbin0 -> 40250 bytes
-rw-r--r--docs/screenshots/edit_user.pngbin0 -> 76007 bytes
-rw-r--r--docs/screenshots/edit_user2.pngbin0 -> 73697 bytes
-rw-r--r--docs/screenshots/login.pngbin0 -> 40659 bytes
-rw-r--r--docs/screenshots/user_addgroup.pngbin0 -> 51148 bytes
-rw-r--r--docs/screenshots/user_assign_permission.pngbin0 -> 69676 bytes
-rw-r--r--docs/screenshots/users.pngbin0 -> 60126 bytes
-rw-r--r--docs/screenshots/users_groups.pngbin0 -> 54422 bytes
-rw-r--r--docs/screenshots/usertour/Users.pngbin0 -> 62140 bytes
-rw-r--r--docs/screenshots/usertour/clients.pngbin0 -> 57973 bytes
-rw-r--r--docs/screenshots/usertour/clients2.pngbin0 -> 54264 bytes
-rw-r--r--docs/screenshots/usertour/clients_pending.pngbin0 -> 52025 bytes
-rw-r--r--docs/screenshots/usertour/clients_permissions.pngbin0 -> 75734 bytes
-rw-r--r--docs/screenshots/usertour/delete_user.pngbin0 -> 9942 bytes
-rw-r--r--docs/screenshots/usertour/edit_user.pngbin0 -> 38110 bytes
-rw-r--r--docs/screenshots/usertour/login.pngbin0 -> 17635 bytes
-rw-r--r--docs/screenshots/usertour/settings.pngbin0 -> 57032 bytes
-rw-r--r--docs/screenshots/usertour/settings1.pngbin0 -> 129596 bytes
-rw-r--r--docs/screenshots/usertour/settings_clients.pngbin0 -> 26821 bytes
-rw-r--r--docs/screenshots/usertour/ui_perms.pngbin0 -> 75475 bytes
-rw-r--r--docs/screenshots/usertour/ui_perms_addperm.pngbin0 -> 62875 bytes
-rw-r--r--docs/screenshots/usertour/user_addgroup.pngbin0 -> 14607 bytes
-rw-r--r--docs/screenshots/usertour/user_assign_permission.pngbin0 -> 74807 bytes
-rw-r--r--docs/screenshots/usertour/users_addgroup.pngbin0 -> 46968 bytes
-rw-r--r--docs/screenshots/usertour/users_editgroup.pngbin0 -> 20470 bytes
-rw-r--r--docs/screenshots/usertour/users_groups.pngbin0 -> 50868 bytes
-rw-r--r--docs/screenshots/usertour/users_groups2.pngbin0 -> 54701 bytes
-rw-r--r--docs/screenshots/usertour/users_permissions.pngbin0 -> 75771 bytes
-rwxr-xr-xdocs/server_be_job_transfer.txt29
-rw-r--r--scire/.lib/DB.php232
-rwxr-xr-xscire/.lib/DB_functions.php541
-rw-r--r--scire/.lib/Session.php116
-rw-r--r--scire/.lib/common.php73
-rw-r--r--scire/.lib/config.php.example25
-rw-r--r--scire/.lib/functions.php147
-rw-r--r--scire/.lib/module_common.php4
-rw-r--r--scire/.lib/oldDB.php.blackace190
-rw-r--r--scire/.lib/phpGACL.php47
-rw-r--r--scire/.lib/smarty.php34
-rw-r--r--scire/.smarty/.svnignore1
-rw-r--r--scire/.smarty/templates/access_error.tpl9
-rwxr-xr-xscire/.smarty/templates/add_job.tpl351
-rw-r--r--scire/.smarty/templates/admin.tpl29
-rwxr-xr-xscire/.smarty/templates/assign_permission.tpl217
-rwxr-xr-xscire/.smarty/templates/client.tpl255
-rwxr-xr-xscire/.smarty/templates/clients.tpl72
-rw-r--r--scire/.smarty/templates/clients_groups.tpl74
-rw-r--r--scire/.smarty/templates/footer.tpl9
-rw-r--r--scire/.smarty/templates/header.tpl91
-rw-r--r--scire/.smarty/templates/index.tpl8
-rw-r--r--scire/.smarty/templates/job.tpl307
-rwxr-xr-xscire/.smarty/templates/jobs.tpl46
-rw-r--r--scire/.smarty/templates/login.tpl39
-rw-r--r--scire/.smarty/templates/message.tpl6
-rwxr-xr-xscire/.smarty/templates/modules.tpl4
-rw-r--r--scire/.smarty/templates/modules/Exporter/index.tpl36
-rw-r--r--scire/.smarty/templates/modules/quickstart/index.tpl86
-rw-r--r--scire/.smarty/templates/permissions.tpl94
-rw-r--r--scire/.smarty/templates/script.tpl107
-rw-r--r--scire/.smarty/templates/script_library.tpl32
-rwxr-xr-xscire/.smarty/templates/settings.tpl50
-rw-r--r--scire/.smarty/templates/settings_page.tpl32
-rwxr-xr-xscire/.smarty/templates/ui_permissions.tpl196
-rwxr-xr-xscire/.smarty/templates/user.tpl216
-rwxr-xr-xscire/.smarty/templates/users.tpl37
-rw-r--r--scire/.smarty/templates/users_groups.tpl74
-rwxr-xr-xscire/2col_leftNav.css307
-rwxr-xr-xscire/DBInterface.php174
-rwxr-xr-xscire/ExportedData.php35
-rwxr-xr-xscire/Exporter.php56
-rw-r--r--scire/access_error.php11
-rw-r--r--scire/add_job.php119
l---------scire/admin/2col_leftNav.css1
-rw-r--r--scire/admin/add_client.php60
-rw-r--r--scire/admin/add_permission.php29
-rw-r--r--scire/admin/admin_checklogin.php10
-rw-r--r--scire/admin/admin_smarty.php45
-rw-r--r--scire/admin/assign_permissions.php129
-rw-r--r--scire/admin/create_clientgroup.php38
-rw-r--r--scire/admin/create_user.php57
-rw-r--r--scire/admin/create_usergroup.php35
-rw-r--r--scire/admin/delete_client.php27
-rw-r--r--scire/admin/delete_clientgroup.php46
-rw-r--r--scire/admin/delete_permission.php36
-rw-r--r--scire/admin/delete_user.php27
-rw-r--r--scire/admin/delete_usergroup.php48
-rw-r--r--scire/admin/edit_client.php35
-rw-r--r--scire/admin/edit_clientgroup.php48
-rw-r--r--scire/admin/edit_permission.php38
-rw-r--r--scire/admin/edit_user.php26
-rw-r--r--scire/admin/edit_usergroup.php46
-rw-r--r--scire/admin/phpgacl_code.php28
-rw-r--r--scire/admin/s.gifbin0 -> 51 bytes
l---------scire/admin/tux_large.png1
-rwxr-xr-xscire/assign_permission.php136
-rw-r--r--scire/calendar/calendar.html169
-rw-r--r--scire/calendar/calendar3.js165
-rw-r--r--scire/calendar/img/cal.gifbin0 -> 127 bytes
-rw-r--r--scire/calendar/img/icon_demo.gifbin0 -> 160 bytes
-rw-r--r--scire/calendar/img/icon_docs.gifbin0 -> 151 bytes
-rw-r--r--scire/calendar/img/icon_download.gifbin0 -> 157 bytes
-rw-r--r--scire/calendar/img/icon_forum.gifbin0 -> 204 bytes
-rw-r--r--scire/calendar/img/icon_home.gifbin0 -> 198 bytes
-rw-r--r--scire/calendar/img/logo.gifbin0 -> 660 bytes
-rw-r--r--scire/calendar/img/next.gifbin0 -> 214 bytes
-rw-r--r--scire/calendar/img/next_year.gifbin0 -> 256 bytes
-rw-r--r--scire/calendar/img/pixel.gifbin0 -> 67 bytes
-rw-r--r--scire/calendar/img/prev.gifbin0 -> 212 bytes
-rw-r--r--scire/calendar/img/prev_year.gifbin0 -> 259 bytes
-rw-r--r--scire/calendar/img/tc.gifbin0 -> 8301 bytes
-rwxr-xr-xscire/client.php207
-rwxr-xr-xscire/clients.php231
-rw-r--r--scire/cron.php672
-rw-r--r--scire/cron2.php467
-rw-r--r--scire/favicon.icobin0 -> 894 bytes
-rw-r--r--scire/images/scire.pngbin0 -> 6706 bytes
-rw-r--r--scire/images/scire_trans.pngbin0 -> 6752 bytes
-rw-r--r--scire/images/sort_asc.pngbin0 -> 102 bytes
-rw-r--r--scire/images/sort_desc.pngbin0 -> 98 bytes
-rwxr-xr-xscire/index.php21
-rw-r--r--scire/job.php274
-rwxr-xr-xscire/jobs.php77
-rw-r--r--scire/light_blue.css126
-rw-r--r--scire/login.php66
-rw-r--r--scire/main_checklogin.php10
-rw-r--r--scire/main_smarty.php25
-rw-r--r--scire/mockups/mockup.html511
-rw-r--r--scire/mockups/mockup_jobs.html569
-rw-r--r--scire/mockups/mockup_users.html507
-rw-r--r--scire/mockups/mockup_users_edit.html560
-rw-r--r--scire/modules.php25
-rw-r--r--scire/phpgacl/Cache_Lite/Hashed_Cache_Lite.php184
-rw-r--r--scire/phpgacl/Cache_Lite/LICENSE458
-rw-r--r--scire/phpgacl/Cache_Lite/Lite.php615
-rw-r--r--scire/phpgacl/gacl.class.php629
-rw-r--r--scire/phpgacl/gacl_api.class.php3899
-rw-r--r--scire/quickstart/index.php37
-rw-r--r--scire/quickstart/sample_data.csv5
-rw-r--r--scire/s.gifbin0 -> 51 bytes
-rw-r--r--scire/script.php129
-rw-r--r--scire/script_library.php24
-rwxr-xr-xscire/settings.php256
-rw-r--r--scire/simpletestCron.php129
-rw-r--r--scire/std_grey.css121
-rwxr-xr-xscire/tux_large.pngbin0 -> 33191 bytes
-rwxr-xr-xscire/ui_permissions.php133
-rwxr-xr-xscire/user.php192
-rwxr-xr-xscire/users.php159
-rw-r--r--webgli/TODO27
-rw-r--r--webgli/XMLParser.php117
-rwxr-xr-xwebgli/banner-800x64.pngbin0 -> 18229 bytes
-rw-r--r--webgli/bootloader.php95
-rw-r--r--webgli/clientconfig.php168
-rw-r--r--webgli/configfiles.php93
-rw-r--r--webgli/daemons.php54
-rw-r--r--webgli/etc_portage.php57
-rw-r--r--webgli/extrapackages.php63
-rw-r--r--webgli/globaluse.php54
-rw-r--r--webgli/images/CVS/Entries16
-rw-r--r--webgli/images/CVS/Repository1
-rw-r--r--webgli/images/CVS/Root1
-rw-r--r--webgli/images/arrow_l.gifbin0 -> 60 bytes
-rw-r--r--webgli/images/arrow_r.gifbin0 -> 61 bytes
-rw-r--r--webgli/images/header.pngbin0 -> 14606 bytes
-rw-r--r--webgli/images/header_bg.pngbin0 -> 351 bytes
-rw-r--r--webgli/images/icon-harddisk-noia_48x48.pngbin0 -> 5140 bytes
-rw-r--r--webgli/images/partition_bg.pngbin0 -> 260 bytes
-rw-r--r--webgli/images/partition_drag.pngbin0 -> 172 bytes
-rw-r--r--webgli/images/spacer.pngbin0 -> 109 bytes
-rw-r--r--webgli/images/tab_n_l.pngbin0 -> 221 bytes
-rw-r--r--webgli/images/tab_n_m.pngbin0 -> 338 bytes
-rw-r--r--webgli/images/tab_n_r.pngbin0 -> 322 bytes
-rw-r--r--webgli/images/tab_s_l.pngbin0 -> 188 bytes
-rw-r--r--webgli/images/tab_s_ml.pngbin0 -> 360 bytes
-rw-r--r--webgli/images/tab_s_mr.pngbin0 -> 461 bytes
-rw-r--r--webgli/images/tab_s_r.pngbin0 -> 300 bytes
-rw-r--r--webgli/index.php31
-rw-r--r--webgli/kernel.php77
-rw-r--r--webgli/localuse.php58
-rw-r--r--webgli/makedotconf.php103
-rw-r--r--webgli/networkmounts.php33
-rw-r--r--webgli/portagetree.php35
-rw-r--r--webgli/review.php197
-rw-r--r--webgli/services.php51
-rw-r--r--webgli/stageselection.php55
-rw-r--r--webgli/templates/.bootloader.tpl.swpbin0 -> 12288 bytes
-rw-r--r--webgli/templates/bootloader.tpl42
-rw-r--r--webgli/templates/bottom.tpl6
-rw-r--r--webgli/templates/clientconfig.tpl86
-rw-r--r--webgli/templates/configfiles.tpl76
-rw-r--r--webgli/templates/daemons.tpl31
-rw-r--r--webgli/templates/etc_portage.tpl30
-rw-r--r--webgli/templates/extrapackages.tpl42
-rw-r--r--webgli/templates/globaluse.tpl37
-rw-r--r--webgli/templates/header.tpl60
-rw-r--r--webgli/templates/index.tpl1
-rw-r--r--webgli/templates/kernel.tpl42
-rw-r--r--webgli/templates/localuse.tpl39
-rw-r--r--webgli/templates/makedotconf.tpl62
-rw-r--r--webgli/templates/networkmounts.tpl51
-rw-r--r--webgli/templates/portagetree.tpl34
-rw-r--r--webgli/templates/review.tpl5
-rw-r--r--webgli/templates/services.tpl26
-rw-r--r--webgli/templates/stageselection.tpl34
-rw-r--r--webgli/templates/timezone.tpl15
-rw-r--r--webgli/timezone.php71
-rw-r--r--webgli/webgli.css107
-rw-r--r--webgli/webgli.js80
-rw-r--r--webgli/webgliCF.php62
-rw-r--r--webgli/webgliIP.php313
-rw-r--r--webgli/webgliUtility.php224
234 files changed, 26212 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..0720c0e
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,131 @@
+# ChangeLog for Scire
+# Copyright 2006-2006 Gentoo Foundation; Distributed under the GPL v2
+# $Id$
+
+ 9 Dec 2006; Andrew Gaffney <agaffney@gentoo.org>
+ server/SecureXMLRPCServer.py:
+ switch to ForkingMixIn instead of ThreadingMixIn to prevent cert info from
+ bleeding between connection instances.
+ reverse order of inherited classes so MixIn works properly
+
+ 15 Jul 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ Updating the scire server and client programs with their current
+ development copy. All changes from previous version have been
+ made by Matt Disney as part of the Summer of Code. These are
+ somewhat large updates involving database connectivity using
+ python's ADOdb module and function calls between the server and
+ client. Many thanks to Matt for the contribution.
+
+ 15 Jul 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ Adding a Python-port of PHP-GACL's acl_check function,
+ written by Brian Coca. This is submitted with his permission.
+ this will take an ADOdb object (or config info), and then return
+ the result of acl_check() queries as in PHP. Many thanks to
+ Brian for the port.
+
+ 14 Jun 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ various updates around the board. mainly focusing on client and user
+ pages. some DB updates and asthetic changes.
+ preparing for user sessions
+
+ 04 Jun 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding some mockup HTML files made by blackace.
+ need templates for those files.
+
+ 04 Jun 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ updated some scire database interface files
+ fixed some queries
+ fixed the exporter pages (as useless as they are now).
+
+ 04 Jun 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ the database tables are most current on the wiki
+ they have been sync'd to svn. sample DB code too.
+
+ 21 May 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ updating Changelog. Lots of updates tonight.
+ Fixed up blackace's templates.
+ migrated index and login pages, admin to follow soon.
+ updates to moria.sql for session table.
+
+ 07 May 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding a lot of webgli screens, some of which are done
+ the details of the status of webgli is in /webgli/TODO
+
+ 05 May 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding a few documents to moria since that seems like a good
+ place to put them
+
+ 23 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ webgli: adding portage screen
+
+ 23 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding the rest of the converted admin pages.
+ conversion should be complete.
+ webgli: adding initial screens of makedotconf
+
+ 22 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ initial scire files and directory added. more will come soon
+ Lots more general updates. Getting things converted over and simplified.
+
+ 22 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ updated globaluse and Utility
+ adding initial localuse screens
+
+ 17 Apr 2006; Andrew Gaffney <agaffney@gentoo.org>
+ webgli/XMLParser.php:
+ moved common code from webgliIP.php
+ webgli/webgliIP.php:
+ moved common code to XMLParser.php
+ webgli/webgliCF.php:
+ initial commit
+
+ 17 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding globaluse screen
+ will need to rearrange stuff so it works better
+ without sharing between pages.
+ minor touchups to other files
+
+ 16 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding etc_portage and extrapackages screens
+ edited daemons and config files
+ added functions to webgliUtility
+
+ 15 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding initial daemon screen
+
+ 15 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding initial files for configfiles screen
+ small updates to the other screens.
+
+ 15 Apr 2006; Andrew Gaffney <agaffney@gentoo.org>
+ webgli/webgliIP.php:
+ begin conversion
+ working version
+ output self-closing tag is value is empty
+ webgli/XMLParser.php:
+ initial XML parser superclass
+ move initialization code to parse()
+ working version
+ webgli/configfiles.php:
+ converted IP code
+
+ 15 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ adding client config screens to webgli
+
+ 15 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ added temp copy of webgli stuff
+
+ 12 Apr 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ Changing project name to Scire in various files.
+
+ 26 Mar 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ Adding current state of my webserver GIMLI directory
+ includes phpGACL code and smarty, both of which
+ are necessary to install. nothing works either
+ without the database
+
+ 24 Mar 2006; Preston Cody <codeman@gentoo.org> ChangeLog:
+ Testing echangelog. Adding two db table creation commands.
+
+ 23 Mar 2006; Andrew Gaffney <agaffney@gentoo.org> ChangeLog:
+ initial ChangeLog commit
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..dfaa6d1
--- /dev/null
+++ b/TODO
@@ -0,0 +1,3 @@
+TODO LIST FOR Scire
+User Management Section:
+ <blackace> codeman: it also seems somewhat strange that I can't edit group membership from the edit group screen
diff --git a/docs/bare_scire.sql b/docs/bare_scire.sql
new file mode 100644
index 0000000..689bb73
--- /dev/null
+++ b/docs/bare_scire.sql
@@ -0,0 +1,1060 @@
+use scire;
+-- MySQL dump 10.10
+--
+-- Host: localhost Database: scire
+-- ------------------------------------------------------
+-- Server version 5.0.26-log
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `GLI_profiles`
+--
+
+DROP TABLE IF EXISTS `GLI_profiles`;
+CREATE TABLE `GLI_profiles` (
+ `profileid` int(11) NOT NULL auto_increment,
+ `profile_name` varchar(255) NOT NULL default '',
+ `location` varchar(255) NOT NULL default '',
+ `description` varchar(255) default NULL,
+ PRIMARY KEY (`profileid`),
+ UNIQUE KEY `profile_name` (`profile_name`)
+) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `GLI_profiles`
+--
+
+LOCK TABLES `GLI_profiles` WRITE;
+/*!40000 ALTER TABLE `GLI_profiles` DISABLE KEYS */;
+INSERT INTO `GLI_profiles` VALUES (1,'printerserver','/scire/gli_profiles/printerserver.xml','A typical printer server install profile. has like cups and shit.'),(2,'mta','/scire/gli_profiles/mta.xml','A typical MTA install profile. has like very little except mailers.');
+/*!40000 ALTER TABLE `GLI_profiles` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `clients`
+--
+
+DROP TABLE IF EXISTS `clients`;
+CREATE TABLE `clients` (
+ `clientid` int(11) NOT NULL,
+ `assetid` varchar(64) default NULL,
+ `cert` text,
+ `hostname` varchar(64) NOT NULL default '',
+ `mac` varchar(17) NOT NULL default '',
+ `ip` varchar(15) NOT NULL default '',
+ `gli_profile` int(11) default NULL,
+ `osid` int(11) default NULL,
+ `status` varchar(20) default NULL,
+ `contact` int(11) default NULL,
+ `installtime` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ `digest` varchar(128) default NULL,
+ PRIMARY KEY (`clientid`),
+ UNIQUE KEY `assetid` (`assetid`),
+ UNIQUE KEY `digest` (`digest`),
+ KEY `osid` (`osid`),
+ KEY `gli_profile` (`gli_profile`),
+ KEY `contact` (`contact`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `clients`
+--
+
+LOCK TABLES `clients` WRITE;
+/*!40000 ALTER TABLE `clients` DISABLE KEYS */;
+/*!40000 ALTER TABLE `clients` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_acl`
+--
+
+DROP TABLE IF EXISTS `gacl_acl`;
+CREATE TABLE `gacl_acl` (
+ `id` int(11) NOT NULL default '0',
+ `section_value` varchar(230) NOT NULL default 'system',
+ `allow` int(11) NOT NULL default '0',
+ `enabled` int(11) NOT NULL default '0',
+ `return_value` text,
+ `note` text,
+ `updated_date` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ KEY `gacl_enabled_acl` (`enabled`),
+ KEY `gacl_section_value_acl` (`section_value`),
+ KEY `gacl_updated_date_acl` (`updated_date`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_acl`
+--
+
+LOCK TABLES `gacl_acl` WRITE;
+/*!40000 ALTER TABLE `gacl_acl` DISABLE KEYS */;
+INSERT INTO `gacl_acl` VALUES (3,'system',1,1,'1','',1156105535),(2,'system',1,1,'1','',1156105485),(4,'system',1,1,'1','',1156105622),(1,'system',1,1,'1','',1156105457),(6,'system',1,1,'1','',1156041570),(7,'system',1,1,'1','',1156105434),(5,'system',1,1,'1','',1156105677);
+/*!40000 ALTER TABLE `gacl_acl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_acl_sections`
+--
+
+DROP TABLE IF EXISTS `gacl_acl_sections`;
+CREATE TABLE `gacl_acl_sections` (
+ `id` int(11) NOT NULL default '0',
+ `value` varchar(230) NOT NULL default '',
+ `order_value` int(11) NOT NULL default '0',
+ `name` varchar(230) NOT NULL default '',
+ `hidden` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `gacl_value_acl_sections` (`value`),
+ KEY `gacl_hidden_acl_sections` (`hidden`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_acl_sections`
+--
+
+LOCK TABLES `gacl_acl_sections` WRITE;
+/*!40000 ALTER TABLE `gacl_acl_sections` DISABLE KEYS */;
+INSERT INTO `gacl_acl_sections` VALUES (1,'system',1,'System',0);
+/*!40000 ALTER TABLE `gacl_acl_sections` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_acl_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_acl_seq`;
+CREATE TABLE `gacl_acl_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_acl_seq`
+--
+
+LOCK TABLES `gacl_acl_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_acl_seq` DISABLE KEYS */;
+INSERT INTO `gacl_acl_seq` VALUES (8);
+/*!40000 ALTER TABLE `gacl_acl_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aco`
+--
+
+DROP TABLE IF EXISTS `gacl_aco`;
+CREATE TABLE `gacl_aco` (
+ `id` int(11) NOT NULL default '0',
+ `section_value` varchar(240) NOT NULL default '0',
+ `value` varchar(240) NOT NULL default '',
+ `order_value` int(11) NOT NULL default '0',
+ `name` varchar(255) NOT NULL default '',
+ `hidden` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `gacl_section_value_value_aco` (`section_value`,`value`),
+ KEY `gacl_hidden_aco` (`hidden`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aco`
+--
+
+LOCK TABLES `gacl_aco` WRITE;
+/*!40000 ALTER TABLE `gacl_aco` DISABLE KEYS */;
+INSERT INTO `gacl_aco` VALUES (13,'scire_ui','Edit User Info',1,'Edit User Info',0),(14,'scire_ui','Add User',1,'Add User',0),(15,'scire_ui','Add Client',1,'Add Client',0),(16,'scire_ui','View Clients',1,'View Clients',0),(17,'scire_ui','View Pending Clients',1,'View Pending Clients',0),(18,'scire_ui','Approve/Reject Pending Clients',1,'Approve/Reject Pending Clients',0),(19,'scire_ui','View Jobs',1,'View Jobs',0),(20,'scire_ui','Add Job',1,'Add Job',0);
+/*!40000 ALTER TABLE `gacl_aco` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aco_map`
+--
+
+DROP TABLE IF EXISTS `gacl_aco_map`;
+CREATE TABLE `gacl_aco_map` (
+ `acl_id` int(11) NOT NULL default '0',
+ `section_value` varchar(230) NOT NULL default '0',
+ `value` varchar(230) NOT NULL default '',
+ PRIMARY KEY (`acl_id`,`section_value`,`value`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aco_map`
+--
+
+LOCK TABLES `gacl_aco_map` WRITE;
+/*!40000 ALTER TABLE `gacl_aco_map` DISABLE KEYS */;
+INSERT INTO `gacl_aco_map` VALUES (6,'scire_ui','Add User'),(7,'scire_ui','Add Client'),(1,'scire_ui','View Clients'),(2,'scire_ui','View Pending Clients'),(3,'scire_ui','Approve/Reject Pending Clients'),(4,'scire_ui','View Jobs'),(5,'scire_ui','Add Job');
+/*!40000 ALTER TABLE `gacl_aco_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aco_sections`
+--
+
+DROP TABLE IF EXISTS `gacl_aco_sections`;
+CREATE TABLE `gacl_aco_sections` (
+ `id` int(11) NOT NULL default '0',
+ `value` varchar(230) NOT NULL default '',
+ `order_value` int(11) NOT NULL default '0',
+ `name` varchar(230) NOT NULL default '',
+ `hidden` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `gacl_value_aco_sections` (`value`),
+ KEY `gacl_hidden_aco_sections` (`hidden`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aco_sections`
+--
+
+LOCK TABLES `gacl_aco_sections` WRITE;
+/*!40000 ALTER TABLE `gacl_aco_sections` DISABLE KEYS */;
+INSERT INTO `gacl_aco_sections` VALUES (1,'scire_ui',1,'scire_ui',0);
+/*!40000 ALTER TABLE `gacl_aco_sections` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aco_sections_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_aco_sections_seq`;
+CREATE TABLE `gacl_aco_sections_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aco_sections_seq`
+--
+
+LOCK TABLES `gacl_aco_sections_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_aco_sections_seq` DISABLE KEYS */;
+INSERT INTO `gacl_aco_sections_seq` VALUES (2);
+/*!40000 ALTER TABLE `gacl_aco_sections_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aco_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_aco_seq`;
+CREATE TABLE `gacl_aco_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aco_seq`
+--
+
+LOCK TABLES `gacl_aco_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_aco_seq` DISABLE KEYS */;
+INSERT INTO `gacl_aco_seq` VALUES (21);
+/*!40000 ALTER TABLE `gacl_aco_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aro`
+--
+
+DROP TABLE IF EXISTS `gacl_aro`;
+CREATE TABLE `gacl_aro` (
+ `id` int(11) NOT NULL default '0',
+ `section_value` varchar(240) NOT NULL default '0',
+ `value` varchar(240) NOT NULL default '',
+ `order_value` int(11) NOT NULL default '0',
+ `name` varchar(255) NOT NULL default '',
+ `hidden` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `gacl_section_value_value_aro` (`section_value`,`value`),
+ KEY `gacl_hidden_aro` (`hidden`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aro`
+--
+
+LOCK TABLES `gacl_aro` WRITE;
+/*!40000 ALTER TABLE `gacl_aro` DISABLE KEYS */;
+INSERT INTO `gacl_aro` VALUES (1,'users','root',0,'root',0),(2,'users','codeman',1,'codeman',0);
+/*!40000 ALTER TABLE `gacl_aro` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aro_groups`
+--
+
+DROP TABLE IF EXISTS `gacl_aro_groups`;
+CREATE TABLE `gacl_aro_groups` (
+ `id` int(11) NOT NULL default '0',
+ `parent_id` int(11) NOT NULL default '0',
+ `lft` int(11) NOT NULL default '0',
+ `rgt` int(11) NOT NULL default '0',
+ `name` varchar(255) NOT NULL default '',
+ `value` varchar(255) NOT NULL default '',
+ PRIMARY KEY (`id`,`value`),
+ UNIQUE KEY `gacl_value_aro_groups` (`value`),
+ KEY `gacl_parent_id_aro_groups` (`parent_id`),
+ KEY `gacl_lft_rgt_aro_groups` (`lft`,`rgt`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aro_groups`
+--
+
+LOCK TABLES `gacl_aro_groups` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_groups` DISABLE KEYS */;
+INSERT INTO `gacl_aro_groups` VALUES (1,0,1,2,'Company Name','Company Name');
+/*!40000 ALTER TABLE `gacl_aro_groups` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aro_groups_id_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_aro_groups_id_seq`;
+CREATE TABLE `gacl_aro_groups_id_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aro_groups_id_seq`
+--
+
+LOCK TABLES `gacl_aro_groups_id_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_groups_id_seq` DISABLE KEYS */;
+INSERT INTO `gacl_aro_groups_id_seq` VALUES (2);
+/*!40000 ALTER TABLE `gacl_aro_groups_id_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aro_groups_map`
+--
+
+DROP TABLE IF EXISTS `gacl_aro_groups_map`;
+CREATE TABLE `gacl_aro_groups_map` (
+ `acl_id` int(11) NOT NULL default '0',
+ `group_id` int(11) NOT NULL default '0',
+ PRIMARY KEY (`acl_id`,`group_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aro_groups_map`
+--
+
+LOCK TABLES `gacl_aro_groups_map` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_groups_map` DISABLE KEYS */;
+INSERT INTO `gacl_aro_groups_map` VALUES (1,1),(4,1);
+/*!40000 ALTER TABLE `gacl_aro_groups_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aro_map`
+--
+
+DROP TABLE IF EXISTS `gacl_aro_map`;
+CREATE TABLE `gacl_aro_map` (
+ `acl_id` int(11) NOT NULL default '0',
+ `section_value` varchar(230) NOT NULL default '0',
+ `value` varchar(230) NOT NULL default '',
+ PRIMARY KEY (`acl_id`,`section_value`,`value`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aro_map`
+--
+
+LOCK TABLES `gacl_aro_map` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_map` DISABLE KEYS */;
+/*!40000 ALTER TABLE `gacl_aro_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aro_sections`
+--
+
+DROP TABLE IF EXISTS `gacl_aro_sections`;
+CREATE TABLE `gacl_aro_sections` (
+ `id` int(11) NOT NULL default '0',
+ `value` varchar(230) NOT NULL default '',
+ `order_value` int(11) NOT NULL default '0',
+ `name` varchar(230) NOT NULL default '',
+ `hidden` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `gacl_value_aro_sections` (`value`),
+ KEY `gacl_hidden_aro_sections` (`hidden`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aro_sections`
+--
+
+LOCK TABLES `gacl_aro_sections` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_sections` DISABLE KEYS */;
+INSERT INTO `gacl_aro_sections` VALUES (1,'users',1,'users',0);
+/*!40000 ALTER TABLE `gacl_aro_sections` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aro_sections_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_aro_sections_seq`;
+CREATE TABLE `gacl_aro_sections_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aro_sections_seq`
+--
+
+LOCK TABLES `gacl_aro_sections_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_sections_seq` DISABLE KEYS */;
+INSERT INTO `gacl_aro_sections_seq` VALUES (1);
+/*!40000 ALTER TABLE `gacl_aro_sections_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_aro_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_aro_seq`;
+CREATE TABLE `gacl_aro_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_aro_seq`
+--
+
+LOCK TABLES `gacl_aro_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_seq` DISABLE KEYS */;
+INSERT INTO `gacl_aro_seq` VALUES (2);
+/*!40000 ALTER TABLE `gacl_aro_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_axo`
+--
+
+DROP TABLE IF EXISTS `gacl_axo`;
+CREATE TABLE `gacl_axo` (
+ `id` int(11) NOT NULL default '0',
+ `section_value` varchar(240) NOT NULL default '0',
+ `value` varchar(240) NOT NULL default '',
+ `order_value` int(11) NOT NULL default '0',
+ `name` varchar(255) NOT NULL default '',
+ `hidden` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `gacl_section_value_value_axo` (`section_value`,`value`),
+ KEY `gacl_hidden_axo` (`hidden`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_axo`
+--
+
+LOCK TABLES `gacl_axo` WRITE;
+/*!40000 ALTER TABLE `gacl_axo` DISABLE KEYS */;
+INSERT INTO `gacl_axo` VALUES (1,'scire_ui','scire_ui',1,'scire_ui',0);
+/*!40000 ALTER TABLE `gacl_axo` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_axo_groups`
+--
+
+DROP TABLE IF EXISTS `gacl_axo_groups`;
+CREATE TABLE `gacl_axo_groups` (
+ `id` int(11) NOT NULL default '0',
+ `parent_id` int(11) NOT NULL default '0',
+ `lft` int(11) NOT NULL default '0',
+ `rgt` int(11) NOT NULL default '0',
+ `name` varchar(255) NOT NULL default '',
+ `value` varchar(255) NOT NULL default '',
+ PRIMARY KEY (`id`,`value`),
+ UNIQUE KEY `gacl_value_axo_groups` (`value`),
+ KEY `gacl_parent_id_axo_groups` (`parent_id`),
+ KEY `gacl_lft_rgt_axo_groups` (`lft`,`rgt`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_axo_groups`
+--
+
+LOCK TABLES `gacl_axo_groups` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_groups` DISABLE KEYS */;
+INSERT INTO `gacl_axo_groups` VALUES (1,0,1,2,'Company Name','Company Name');
+/*!40000 ALTER TABLE `gacl_axo_groups` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_axo_groups_id_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_axo_groups_id_seq`;
+CREATE TABLE `gacl_axo_groups_id_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_axo_groups_id_seq`
+--
+
+LOCK TABLES `gacl_axo_groups_id_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_groups_id_seq` DISABLE KEYS */;
+INSERT INTO `gacl_axo_groups_id_seq` VALUES (2);
+/*!40000 ALTER TABLE `gacl_axo_groups_id_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_axo_groups_map`
+--
+
+DROP TABLE IF EXISTS `gacl_axo_groups_map`;
+CREATE TABLE `gacl_axo_groups_map` (
+ `acl_id` int(11) NOT NULL default '0',
+ `group_id` int(11) NOT NULL default '0',
+ PRIMARY KEY (`acl_id`,`group_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_axo_groups_map`
+--
+
+LOCK TABLES `gacl_axo_groups_map` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_groups_map` DISABLE KEYS */;
+/*!40000 ALTER TABLE `gacl_axo_groups_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_axo_map`
+--
+
+DROP TABLE IF EXISTS `gacl_axo_map`;
+CREATE TABLE `gacl_axo_map` (
+ `acl_id` int(11) NOT NULL default '0',
+ `section_value` varchar(230) NOT NULL default '0',
+ `value` varchar(230) NOT NULL default '',
+ PRIMARY KEY (`acl_id`,`section_value`,`value`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_axo_map`
+--
+
+LOCK TABLES `gacl_axo_map` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_map` DISABLE KEYS */;
+INSERT INTO `gacl_axo_map` VALUES (6,'scire_ui','scire_ui'),(7,'scire_ui','scire_ui'),(1,'scire_ui','scire_ui'),(2,'scire_ui','scire_ui'),(3,'scire_ui','scire_ui'),(4,'scire_ui','scire_ui'),(5,'scire_ui','scire_ui');
+/*!40000 ALTER TABLE `gacl_axo_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_axo_sections`
+--
+
+DROP TABLE IF EXISTS `gacl_axo_sections`;
+CREATE TABLE `gacl_axo_sections` (
+ `id` int(11) NOT NULL default '0',
+ `value` varchar(230) NOT NULL default '',
+ `order_value` int(11) NOT NULL default '0',
+ `name` varchar(230) NOT NULL default '',
+ `hidden` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `gacl_value_axo_sections` (`value`),
+ KEY `gacl_hidden_axo_sections` (`hidden`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_axo_sections`
+--
+
+LOCK TABLES `gacl_axo_sections` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_sections` DISABLE KEYS */;
+INSERT INTO `gacl_axo_sections` VALUES (2,'clients',1,'clients',0),(1,'scire_ui',2,'scire_ui',0);
+/*!40000 ALTER TABLE `gacl_axo_sections` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_axo_sections_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_axo_sections_seq`;
+CREATE TABLE `gacl_axo_sections_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_axo_sections_seq`
+--
+
+LOCK TABLES `gacl_axo_sections_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_sections_seq` DISABLE KEYS */;
+INSERT INTO `gacl_axo_sections_seq` VALUES (3);
+/*!40000 ALTER TABLE `gacl_axo_sections_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_axo_seq`
+--
+
+DROP TABLE IF EXISTS `gacl_axo_seq`;
+CREATE TABLE `gacl_axo_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_axo_seq`
+--
+
+LOCK TABLES `gacl_axo_seq` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_seq` DISABLE KEYS */;
+INSERT INTO `gacl_axo_seq` VALUES (2);
+/*!40000 ALTER TABLE `gacl_axo_seq` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_groups_aro_map`
+--
+
+DROP TABLE IF EXISTS `gacl_groups_aro_map`;
+CREATE TABLE `gacl_groups_aro_map` (
+ `group_id` int(11) NOT NULL default '0',
+ `aro_id` int(11) NOT NULL default '0',
+ PRIMARY KEY (`group_id`,`aro_id`),
+ KEY `gacl_aro_id` (`aro_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_groups_aro_map`
+--
+
+LOCK TABLES `gacl_groups_aro_map` WRITE;
+/*!40000 ALTER TABLE `gacl_groups_aro_map` DISABLE KEYS */;
+/*!40000 ALTER TABLE `gacl_groups_aro_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_groups_axo_map`
+--
+
+DROP TABLE IF EXISTS `gacl_groups_axo_map`;
+CREATE TABLE `gacl_groups_axo_map` (
+ `group_id` int(11) NOT NULL default '0',
+ `axo_id` int(11) NOT NULL default '0',
+ PRIMARY KEY (`group_id`,`axo_id`),
+ KEY `gacl_axo_id` (`axo_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_groups_axo_map`
+--
+
+LOCK TABLES `gacl_groups_axo_map` WRITE;
+/*!40000 ALTER TABLE `gacl_groups_axo_map` DISABLE KEYS */;
+/*!40000 ALTER TABLE `gacl_groups_axo_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `gacl_phpgacl`
+--
+
+DROP TABLE IF EXISTS `gacl_phpgacl`;
+CREATE TABLE `gacl_phpgacl` (
+ `name` varchar(230) NOT NULL default '',
+ `value` varchar(230) NOT NULL default '',
+ PRIMARY KEY (`name`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `gacl_phpgacl`
+--
+
+LOCK TABLES `gacl_phpgacl` WRITE;
+/*!40000 ALTER TABLE `gacl_phpgacl` DISABLE KEYS */;
+INSERT INTO `gacl_phpgacl` VALUES ('version','3.3.6'),('schema_version','2.1');
+/*!40000 ALTER TABLE `gacl_phpgacl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `hardware`
+--
+
+DROP TABLE IF EXISTS `hardware`;
+CREATE TABLE `hardware` (
+ `clientid` int(11) NOT NULL default '0',
+ `processor` varchar(32) default NULL,
+ `memory` varchar(32) default NULL,
+ `hd` varchar(32) default NULL,
+ `cpu` varchar(64) default NULL,
+ `mhz` varchar(32) default NULL,
+ PRIMARY KEY (`clientid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `hardware`
+--
+
+LOCK TABLES `hardware` WRITE;
+/*!40000 ALTER TABLE `hardware` DISABLE KEYS */;
+/*!40000 ALTER TABLE `hardware` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `hardware_history`
+--
+
+DROP TABLE IF EXISTS `hardware_history`;
+CREATE TABLE `hardware_history` (
+ `clientid` int(11) NOT NULL default '0',
+ `changedate` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ `field_name` varchar(30) default NULL,
+ `oldvalue` varchar(255) default NULL,
+ `newvalue` varchar(255) default NULL,
+ PRIMARY KEY (`clientid`,`changedate`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `hardware_history`
+--
+
+LOCK TABLES `hardware_history` WRITE;
+/*!40000 ALTER TABLE `hardware_history` DISABLE KEYS */;
+/*!40000 ALTER TABLE `hardware_history` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `job_conditions`
+--
+
+DROP TABLE IF EXISTS `job_conditions`;
+CREATE TABLE `job_conditions` (
+ `jobid` int(11) NOT NULL default '0',
+ `clientid` int(11) NOT NULL default '0',
+ `job_dependency` int(11) NOT NULL default '0',
+ `start_time` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+ `start_period` timestamp NOT NULL default '0000-00-00 00:00:00',
+ `end_period` timestamp NOT NULL default '0000-00-00 00:00:00',
+ `run_interval` int(11) default NULL,
+ `last_run` int(11) default NULL,
+ `last_run_date` timestamp NOT NULL default '0000-00-00 00:00:00',
+ PRIMARY KEY (`jobid`,`clientid`),
+ KEY `clientid` (`clientid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `job_conditions`
+--
+
+LOCK TABLES `job_conditions` WRITE;
+/*!40000 ALTER TABLE `job_conditions` DISABLE KEYS */;
+/*!40000 ALTER TABLE `job_conditions` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `job_history`
+--
+
+DROP TABLE IF EXISTS `job_history`;
+CREATE TABLE `job_history` (
+ `jobid` int(11) NOT NULL default '0',
+ `clientid` int(11) NOT NULL default '0',
+ `eventtime` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ `status` varchar(20) NOT NULL default '',
+ `eventmsg` varchar(255) default NULL,
+ PRIMARY KEY (`jobid`,`clientid`,`eventtime`),
+ KEY `clientid` (`clientid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `job_history`
+--
+
+LOCK TABLES `job_history` WRITE;
+/*!40000 ALTER TABLE `job_history` DISABLE KEYS */;
+/*!40000 ALTER TABLE `job_history` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `jobs`
+--
+
+DROP TABLE IF EXISTS `jobs`;
+CREATE TABLE `jobs` (
+ `jobid` int(11) NOT NULL auto_increment,
+ `priority` int(11) NOT NULL default '0',
+ `created` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ `creator` int(11) NOT NULL default '0',
+ `permission` int(11) NOT NULL default '0',
+ `script` int(11) NOT NULL default '0',
+ `description` varchar(255) default NULL,
+ `pending` int(11) default NULL,
+ `failed` int(11) default NULL,
+ PRIMARY KEY (`jobid`),
+ KEY `creator` (`creator`),
+ KEY `permission` (`permission`),
+ KEY `script` (`script`)
+) ENGINE=MyISAM AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `jobs`
+--
+
+LOCK TABLES `jobs` WRITE;
+/*!40000 ALTER TABLE `jobs` DISABLE KEYS */;
+/*!40000 ALTER TABLE `jobs` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `jobs_clients`
+--
+
+DROP TABLE IF EXISTS `jobs_clients`;
+CREATE TABLE `jobs_clients` (
+ `jobid` int(11) NOT NULL default '0',
+ `clientid` int(11) NOT NULL default '0',
+ `groupid` int(11) NOT NULL default '0',
+ PRIMARY KEY (`jobid`,`clientid`,`groupid`),
+ KEY `groupid` (`groupid`),
+ KEY `clientid` (`clientid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `jobs_clients`
+--
+
+LOCK TABLES `jobs_clients` WRITE;
+/*!40000 ALTER TABLE `jobs_clients` DISABLE KEYS */;
+/*!40000 ALTER TABLE `jobs_clients` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `modules`
+--
+
+DROP TABLE IF EXISTS `modules`;
+CREATE TABLE `modules` (
+ `id` int(11) NOT NULL default '0',
+ `name` varchar(50) default NULL,
+ `long_name` varchar(150) default NULL,
+ `description` varchar(250) default NULL,
+ `path` varchar(90) default NULL,
+ `author` varchar(50) default NULL,
+ `distribution` varchar(50) default NULL,
+ `category` varchar(30) default NULL,
+ `homepage` varchar(90) default NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `modules`
+--
+
+LOCK TABLES `modules` WRITE;
+/*!40000 ALTER TABLE `modules` DISABLE KEYS */;
+INSERT INTO `modules` VALUES (1,'Quickstart','Quickstart Installation Mangement Daemon','Description goes here and all that good stuff.','quickstart/index.php','Preston Cody','gentoo','deployment','http://www.gentoo.org/proj/en/releng/gli/'),(2,'Exporter','Server Information Exporter','This is a utility that will take selected data from the central server about machines and export it into an XML format.','/Exporter/index.php','Preston Cody',NULL,'information','http://www.gentoo.org/proj/en/releng/gli/');
+/*!40000 ALTER TABLE `modules` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `os`
+--
+
+DROP TABLE IF EXISTS `os`;
+CREATE TABLE `os` (
+ `osid` int(11) NOT NULL auto_increment,
+ `osname` varchar(128) NOT NULL default '',
+ `update_script` int(11) default NULL,
+ `install_script` int(11) default NULL,
+ `uninstall_script` int(11) default NULL,
+ `rollback_script` int(11) default NULL,
+ `packagelist_script` int(11) default NULL,
+ PRIMARY KEY (`osid`),
+ KEY `update_script` (`update_script`),
+ KEY `install_script` (`install_script`),
+ KEY `uninstall_script` (`uninstall_script`),
+ KEY `rollback_script` (`rollback_script`),
+ KEY `packagelist_script` (`packagelist_script`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `os`
+--
+
+LOCK TABLES `os` WRITE;
+/*!40000 ALTER TABLE `os` DISABLE KEYS */;
+INSERT INTO `os` VALUES (1,'Gentoo Linux',100,101,102,103,104);
+/*!40000 ALTER TABLE `os` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `permissions`
+--
+
+DROP TABLE IF EXISTS `permissions`;
+CREATE TABLE `permissions` (
+ `permid` int(11) NOT NULL,
+ `name` varchar(128) NOT NULL default '',
+ `description` varchar(255) default NULL,
+ `creator` int(11) NOT NULL default '0',
+ `created` timestamp NOT NULL default CURRENT_TIMESTAMP,
+ `permcategory` varchar(128) NOT NULL default 'Default',
+ PRIMARY KEY (`permid`),
+ UNIQUE KEY `name` (`name`),
+ KEY `creator` (`creator`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `permissions`
+--
+
+LOCK TABLES `permissions` WRITE;
+/*!40000 ALTER TABLE `permissions` DISABLE KEYS */;
+/*!40000 ALTER TABLE `permissions` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `scripts`
+--
+
+DROP TABLE IF EXISTS `scripts`;
+CREATE TABLE `scripts` (
+ `scriptid` int(11) NOT NULL auto_increment,
+ `name` varchar(128) NOT NULL default '',
+ `description` varchar(255) default NULL,
+ `location` varchar(255) default NULL,
+ `script_data` text,
+ `log_location` varchar(255) default NULL,
+ `success_code` varchar(32) default NULL,
+ `run_as` varchar(255) default NULL,
+ `priority` int(11) default NULL,
+ `permission` int(11) default NULL,
+ `pp_location` varchar(255) default NULL,
+ `pp_script_data` text,
+ PRIMARY KEY (`scriptid`),
+ KEY `permission` (`permission`)
+) ENGINE=MyISAM AUTO_INCREMENT=107 DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `scripts`
+--
+
+LOCK TABLES `scripts` WRITE;
+/*!40000 ALTER TABLE `scripts` DISABLE KEYS */;
+INSERT INTO `scripts` VALUES (100,'Gentoo Update Script','This script will run emerge sync and emerge -u world, logging the results.','','#!/bin/bash \n emerge sync \n emerge -u world','/var/log/scire/updatelog.txt','0','root',5,1,'',''),(101,'Gentoo Install Package Script','This script will run emerge on a given package and log the results.','','#!/bin/bash\nemerge --nocolor --nospinner --quiet -u world','/var/log/scire/installlog.txt','0','root',2,1,'',''),(102,'Gentoo Uninstall Package Script','This script will run emerge unmerge on a given package and log the results.','','#!/bin/bash \n emerge unmerge','/var/log/scire/uninstalllog.txt','0','root',2,1,'',''),(103,'Gentoo Rollback Script','This script will roll back a given package to its previous version, logging the results.','','#!/bin/bash \n emerge -C && emerge ','/var/log/scire/rollbacklog.txt','0','root',1,1,'',''),(104,'Gentoo PackageList Script','This script will return a list of packages installed on the system and the current version of those packages.','','#!/bin/bash \n %%tag1%% %%tag2%%','/var/log/scire/packagelistlog.txt','0','nobody',8,1,'',''),(105,'install_vim','This will emerge vim for gentoo','Embedded','#!/bin/bash\r\nemerge vim\r\n ','','0','root',1,0,'Embedded',''),(106,'install ufed','this installs ufed, a stupid little prog that helps with USE flags','Embedded','#!/bin/bash\r\nemerge ufed','','0','root',1,0,'Embedded','');
+/*!40000 ALTER TABLE `scripts` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `sessions`
+--
+
+DROP TABLE IF EXISTS `sessions`;
+CREATE TABLE `sessions` (
+ `sessionid` varchar(255) NOT NULL default '',
+ `expiration` int(10) unsigned NOT NULL default '0',
+ `data` text,
+ PRIMARY KEY (`sessionid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `sessions`
+--
+
+LOCK TABLES `sessions` WRITE;
+/*!40000 ALTER TABLE `sessions` DISABLE KEYS */;
+/*!40000 ALTER TABLE `sessions` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `settings`
+--
+
+DROP TABLE IF EXISTS `settings`;
+CREATE TABLE `settings` (
+ `userid` int(11) NOT NULL default '0',
+ `setting_name` varchar(64) NOT NULL default '',
+ `setting_value` varchar(255) default NULL,
+ PRIMARY KEY (`userid`,`setting_name`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `settings`
+--
+
+LOCK TABLES `settings` WRITE;
+/*!40000 ALTER TABLE `settings` DISABLE KEYS */;
+INSERT INTO `settings` VALUES (1,'start_page','clients.php'),(1,'theme','std_grey'),(1,'notification','phone'),(1,'per_page','2'),(1,'clients_page_sorton','hostname'),(1,'clients_page_fields','ip,osname,username,groups,hostname,status'),(1,'jobs_page_fields','hostname,priority,created,description,username,scriptname,pending,permname,failed'),(1,'users_page_fields','username,real_name,comment,groups,status'),(1,'users_page_sorton','username'),(1,'jobs_page_sorton','hostname'),(1,'jobs_page_sortdir','asc');
+/*!40000 ALTER TABLE `settings` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `software`
+--
+
+DROP TABLE IF EXISTS `software`;
+CREATE TABLE `software` (
+ `clientid` int(11) NOT NULL default '0',
+ `package` varchar(128) NOT NULL default '',
+ `current_ver` varchar(64) default NULL,
+ `rollback_ver` varchar(64) default NULL,
+ PRIMARY KEY (`package`),
+ KEY `clientid` (`clientid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `software`
+--
+
+LOCK TABLES `software` WRITE;
+/*!40000 ALTER TABLE `software` DISABLE KEYS */;
+/*!40000 ALTER TABLE `software` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `users`
+--
+
+DROP TABLE IF EXISTS `users`;
+CREATE TABLE `users` (
+ `userid` int(11) NOT NULL,
+ `username` varchar(64) NOT NULL,
+ `password` varchar(255) NOT NULL,
+ `email` varchar(128) NOT NULL,
+ `phone` varchar(128) default NULL,
+ `pager` varchar(128) default NULL,
+ `real_name` varchar(255) default NULL,
+ `comment` varchar(255) default NULL,
+ PRIMARY KEY (`userid`),
+ UNIQUE KEY `username` (`username`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `users`
+--
+
+LOCK TABLES `users` WRITE;
+/*!40000 ALTER TABLE `users` DISABLE KEYS */;
+INSERT INTO `users` VALUES (1,'root','444mwGdhEKuO.','root@localhost.com','','','Root User','This is the comment for the root user.'),(2,'codeman','444mwGdhEKuO.','codeman@localhost.com','','555-1212','Preston Cody','Project lead and developer.');
+/*!40000 ALTER TABLE `users` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2007-03-26 0:59:36
diff --git a/docs/jobs_flow/get_job.png b/docs/jobs_flow/get_job.png
new file mode 100644
index 0000000..061deeb
--- /dev/null
+++ b/docs/jobs_flow/get_job.png
Binary files differ
diff --git a/docs/jobs_flow/get_jobs.png b/docs/jobs_flow/get_jobs.png
new file mode 100644
index 0000000..40d2593
--- /dev/null
+++ b/docs/jobs_flow/get_jobs.png
Binary files differ
diff --git a/docs/jobs_flow/get_jstatus.png b/docs/jobs_flow/get_jstatus.png
new file mode 100644
index 0000000..6f8b841
--- /dev/null
+++ b/docs/jobs_flow/get_jstatus.png
Binary files differ
diff --git a/docs/jobs_flow/run_jobs.png b/docs/jobs_flow/run_jobs.png
new file mode 100644
index 0000000..80fc69d
--- /dev/null
+++ b/docs/jobs_flow/run_jobs.png
Binary files differ
diff --git a/docs/jobs_flow/scirec_main.png b/docs/jobs_flow/scirec_main.png
new file mode 100644
index 0000000..d116076
--- /dev/null
+++ b/docs/jobs_flow/scirec_main.png
Binary files differ
diff --git a/docs/jobs_flow/svg/get_job.svg b/docs/jobs_flow/svg/get_job.svg
new file mode 100644
index 0000000..76e6356
--- /dev/null
+++ b/docs/jobs_flow/svg/get_job.svg
@@ -0,0 +1,800 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2280"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ sodipodi:docbase="/home/disney/gentoo/diagrams"
+ sodipodi:docname="get_job.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_job.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:modified="TRUE">
+ <defs
+ id="defs2282">
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient11111"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3233">
+ <stop
+ style="stop-color:#cccccc;stop-opacity:1;"
+ offset="0"
+ id="stop3235" />
+ <stop
+ style="stop-color:#cccccc;stop-opacity:0;"
+ offset="1"
+ id="stop3237" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient23523"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path4305"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#ffffff"
+ borderopacity="0.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="0"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="-76.913763"
+ inkscape:cy="656.78425"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:window-width="1398"
+ inkscape:window-height="654"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata2285">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient23523);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path23517"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,-347.20102,452.62247)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-302.91742"
+ y="493.30472"
+ id="text23519"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-302.91742"
+ y="493.30472"
+ id="tspan23521">Start</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.80471,507.35331 L -279.75242,534.62211"
+ id="path23525"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3223"
+ width="113.46721"
+ height="113.47605"
+ x="305.53931"
+ y="645.06244"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-279.53696"
+ y="573.79559"
+ id="text10618"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-276.99008"
+ y="573.79559"
+ style="font-size:16px;font-family:Courier 10 Pitch"
+ id="tspan10624"><tspan
+ id="tspan2313"
+ style="font-size:16px;font-family:Bitstream Vera Sans">Is the </tspan></tspan><tspan
+ sodipodi:role="line"
+ x="-279.53696"
+ y="592.14761"
+ style="font-size:16px;font-family:Courier 10 Pitch"
+ id="tspan2315">origjob</tspan><tspan
+ sodipodi:role="line"
+ x="-279.53696"
+ y="613.79559"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan10626">parameter</tspan><tspan
+ sodipodi:role="line"
+ x="-279.53696"
+ y="633.79559"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2317"> provided?</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-166.46484"
+ y="564.505"
+ id="text2319"><tspan
+ sodipodi:role="line"
+ id="tspan2321"
+ x="-166.46484"
+ y="564.505">Yes, so the function is</tspan><tspan
+ sodipodi:role="line"
+ x="-166.46484"
+ y="589.505"
+ id="tspan2323">being used in query mode.</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10616"
+ width="150.00647"
+ height="88.946548"
+ x="117.20412"
+ y="561.43317"
+ transform="matrix(0.9999996,8.8502961e-4,-5.7801643e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="191.38034"
+ y="592.75128"
+ id="text10704"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="193.60886"
+ y="592.75128"
+ id="tspan10710"
+ style="font-size:14px;font-family:Bitstream Vera Sans">Query DB for </tspan><tspan
+ sodipodi:role="line"
+ x="191.38034"
+ y="610.25128"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan2351">specific instance of</tspan><tspan
+ sodipodi:role="line"
+ x="191.38034"
+ y="626.30929"
+ style="font-size:14px;font-family:Courier 10 Pitch"
+ id="tspan2343">origjob</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.86947,669.07712 L -279.81718,696.34592"
+ id="path10867"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2377"
+ width="150.00647"
+ height="88.946548"
+ x="-354.05209"
+ y="702.18213"
+ transform="matrix(0.9999996,8.850316e-4,-5.7802041e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-279.95724"
+ y="739.08331"
+ id="text2379"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-279.95724"
+ y="739.08331"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan2385">Query DB for</tspan><tspan
+ sodipodi:role="line"
+ x="-279.95724"
+ y="764.08331"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan2410">job data</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.86934,790.72987 L -279.81705,817.99867"
+ id="path2412"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2414"
+ width="150.00647"
+ height="88.946548"
+ x="-353.98157"
+ y="823.83484"
+ transform="matrix(0.9999996,8.8503319e-4,-5.7802359e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-279.95712"
+ y="850.73608"
+ id="text2416"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-279.95712"
+ y="850.73608"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2424">Cast job data as</tspan><tspan
+ sodipodi:role="line"
+ x="-277.09189"
+ y="873.23608"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2430">string to avoid </tspan><tspan
+ sodipodi:role="line"
+ x="-279.95712"
+ y="895.73608"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2434">XML-RPC issues</tspan></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2436"
+ width="113.46721"
+ height="113.47622"
+ x="662.06061"
+ y="1002.0456"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-279.95685"
+ y="979.06274"
+ id="text2438"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-277.40997"
+ y="979.06274"
+ style="font-size:16px;font-family:Courier 10 Pitch"
+ id="tspan2440"><tspan
+ id="tspan2442"
+ style="font-size:16px;font-family:Bitstream Vera Sans">Is the </tspan></tspan><tspan
+ sodipodi:role="line"
+ x="-279.95685"
+ y="997.41476"
+ style="font-size:16px;font-family:Courier 10 Pitch"
+ id="tspan2444">origjob</tspan><tspan
+ sodipodi:role="line"
+ x="-279.95685"
+ y="1019.0627"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2446">parameter</tspan><tspan
+ sodipodi:role="line"
+ x="-279.95685"
+ y="1039.0627"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2448"> provided?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.9322,1074.3443 L -279.87991,1101.6131"
+ id="path2450"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -280.04804,912.5057 L -279.99575,939.7745"
+ id="path2452"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2456"
+ width="113.46721"
+ height="113.47698"
+ x="804.86346"
+ y="1144.8442"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.94502,1236.5604 L -279.89273,1263.8292"
+ id="path2470"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2472"
+ width="113.46721"
+ height="113.47713"
+ x="946.83398"
+ y="1286.6479"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-279.84827"
+ y="1302.4607"
+ id="text2474"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-277.30139"
+ y="1302.4607"
+ style="font-size:16px;font-family:Courier 10 Pitch"
+ id="tspan2476"><tspan
+ id="tspan2478"
+ style="font-size:16px;font-family:Bitstream Vera Sans">Is the </tspan></tspan><tspan
+ sodipodi:role="line"
+ x="-279.84827"
+ y="1320.8127"
+ style="font-size:16px;font-family:Courier 10 Pitch"
+ id="tspan2480">dup</tspan><tspan
+ sodipodi:role="line"
+ x="-279.84827"
+ y="1342.4607"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2482">parameter</tspan><tspan
+ sodipodi:role="line"
+ x="-279.84827"
+ y="1362.4607"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2484">True?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.82362,1397.7423 L -279.77133,1425.0111"
+ id="path2486"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-278.39359"
+ y="1154.4877"
+ id="text2500"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-275.52835"
+ y="1154.4877"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10622">Is the job's </tspan><tspan
+ sodipodi:role="line"
+ x="-278.39359"
+ y="1175.1337"
+ style="font-size:18px;font-family:Courier 10 Pitch"
+ id="tspan2503">run_interval</tspan><tspan
+ sodipodi:role="line"
+ x="-278.39359"
+ y="1199.4877"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2505">value &gt; 0?</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2507"
+ width="150.00647"
+ height="88.946548"
+ x="-353.22171"
+ y="1431.0809"
+ transform="matrix(0.9999996,8.850343e-4,-5.7802581e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-279.54843"
+ y="1457.9829"
+ id="text2509"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-279.54843"
+ y="1457.9829"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2530">Insert new duped</tspan><tspan
+ sodipodi:role="line"
+ x="-277.00156"
+ y="1477.9829"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2526">job in DB with </tspan><tspan
+ sodipodi:role="line"
+ x="-279.54843"
+ y="1497.9829"
+ style="font-size:16px;font-family:Courier 10 Pitch"
+ id="tspan2538"><tspan
+ id="tspan2542"
+ style="font-size:16px;font-family:Bitstream Vera Sans">correct </tspan>origjob</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.63935,1519.7525 L -279.58706,1547.0213"
+ id="path2517"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2544"
+ width="150.00647"
+ height="88.946548"
+ x="-353.13437"
+ y="1553.1658"
+ transform="matrix(0.9999996,8.8503481e-4,-5.7802683e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-279.5318"
+ y="1580.068"
+ id="text2546"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-279.5318"
+ y="1580.068"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2548">Insert new duped</tspan><tspan
+ sodipodi:role="line"
+ x="-276.98492"
+ y="1600.068"
+ style="font-size:16px;font-family:Bitstream Vera Sans"
+ id="tspan2550">job in DB with </tspan><tspan
+ sodipodi:role="line"
+ x="-279.5318"
+ y="1620.068"
+ style="font-size:16px;font-family:Courier 10 Pitch"
+ id="tspan2552"><tspan
+ id="tspan2554"
+ style="font-size:16px;font-family:Bitstream Vera Sans">correct </tspan>origjob</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.62272,1641.8376 L -279.57043,1669.1064"
+ id="path2556"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient11111);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path11105"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,-347.77245,1782.3802)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-325.22742"
+ y="1820.0522"
+ id="text11107"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-325.22742"
+ y="1820.0522"
+ id="tspan11109"
+ style="font-size:12px">Return job data</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2619"
+ width="150.00647"
+ height="88.946548"
+ x="-352.93814"
+ y="1674.4956"
+ transform="matrix(0.9999996,8.8503536e-4,-5.7802793e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:14;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-279.40585"
+ y="1701.3982"
+ id="text2621"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-279.40585"
+ y="1701.3982"
+ style="font-size:14;font-family:Bitstream Vera Sans"
+ id="tspan2627">Recursively call</tspan><tspan
+ sodipodi:role="line"
+ x="-279.40585"
+ y="1718.8982"
+ style="font-size:14;font-family:Bitstream Vera Sans"
+ id="tspan2638"><tspan
+ style="font-family:Courier 10 Pitch"
+ id="tspan2650">get_job</tspan> to get data</tspan><tspan
+ sodipodi:role="line"
+ x="-279.40585"
+ y="1737.8402"
+ style="font-size:14;font-family:Bitstream Vera Sans"
+ id="tspan2646">for inserted job</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -279.49679,1763.1678 L -279.4445,1790.4366"
+ id="path2631"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00222671px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -186.42746,604.50504 L 111.40559,604.50504"
+ id="path2652"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00240564px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 190.71429,650.22173 L 190.71429,872.71692"
+ id="path3623"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00644386px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 191.42535,872.71933 L -198.50476,872.71933"
+ id="path3625"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M -186.37315,1009.6832 L -93.944187,1009.6832"
+ id="path5568"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M -186.87823,1171.8622 L -95.459416,1171.8127"
+ id="path5570"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M -186.62568,1332.8622 L -95.711954,1332.9321"
+ id="path5572"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00111866px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M -89.145962,1008.9256 L -89.286273,1816.8616"
+ id="path6543"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.98884124px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M -88.991702,1816.8622 L -220.11431,1816.8622"
+ id="path6545"
+ inkscape:connector-type="polyline" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-272.60464"
+ y="689.51062"
+ id="text2278"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan2280"
+ x="-272.60464"
+ y="689.51062">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-170.89035"
+ y="1002.6535"
+ id="text7518"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan7520"
+ x="-170.89035"
+ y="1002.6535">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-171.17606"
+ y="1160.9392"
+ id="text7522"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan7524"
+ x="-171.17606"
+ y="1160.9392">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-172.60463"
+ y="1325.2249"
+ id="text7526"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan7528"
+ x="-172.60463"
+ y="1325.2249">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-627.14288"
+ y="1395.2192"
+ id="text7530"><tspan
+ sodipodi:role="line"
+ id="tspan7532"
+ x="-627.14288"
+ y="1395.2192">Yes, so get_job has been called</tspan><tspan
+ sodipodi:role="line"
+ x="-627.14288"
+ y="1420.2192"
+ id="tspan7534">in execution mode for a recurring </tspan><tspan
+ sodipodi:role="line"
+ x="-627.14288"
+ y="1445.2192"
+ id="tspan7536">job.</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-326"
+ y="1093.7908"
+ id="text7538"><tspan
+ sodipodi:role="line"
+ id="tspan7540"
+ x="-326"
+ y="1093.7908">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-328.7825"
+ y="1256.082"
+ id="text7542"><tspan
+ sodipodi:role="line"
+ id="tspan7544"
+ x="-328.7825"
+ y="1256.082">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-181.82745"
+ y="350.91531"
+ id="text7546"><tspan
+ sodipodi:role="line"
+ id="tspan7548"
+ x="-181.82745"
+ y="350.91531">NB: <tspan
+ style="font-family:Courier 10 Pitch"
+ id="tspan7550">get_job()</tspan> has 2 modes. One is a query mode,</tspan><tspan
+ sodipodi:role="line"
+ x="-181.82745"
+ y="377.9753"
+ id="tspan7554">which will simply return information about a job. The</tspan><tspan
+ sodipodi:role="line"
+ x="-181.82745"
+ y="402.9753"
+ id="tspan7556">other is execution mode. In this approach, recurring</tspan><tspan
+ sodipodi:role="line"
+ x="-181.82745"
+ y="427.9753"
+ id="tspan7558">jobs are duplicated into unique job IDs that are tied </tspan><tspan
+ sodipodi:role="line"
+ x="-181.82745"
+ y="452.9753"
+ id="tspan7560">back to the original job via the <tspan
+ style="font-family:Courier 10 Pitch"
+ id="tspan7562">origjob</tspan> field. In exec</tspan><tspan
+ sodipodi:role="line"
+ x="-181.82745"
+ y="480.03528"
+ id="tspan7564">mode, a recurring job is duplicated into a new ID before</tspan><tspan
+ sodipodi:role="line"
+ x="-181.82745"
+ y="505.03528"
+ id="tspan7566">returning the info from its query.</tspan></text>
+ </g>
+</svg>
diff --git a/docs/jobs_flow/svg/get_jobs.svg b/docs/jobs_flow/svg/get_jobs.svg
new file mode 100644
index 0000000..192fce4
--- /dev/null
+++ b/docs/jobs_flow/svg/get_jobs.svg
@@ -0,0 +1,863 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg10403"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ sodipodi:docbase="/home/disney/gentoo/diagrams"
+ sodipodi:docname="get_jobs.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:modified="true">
+ <defs
+ id="defs10405">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3233">
+ <stop
+ style="stop-color:#cccccc;stop-opacity:1;"
+ offset="0"
+ id="stop3235" />
+ <stop
+ style="stop-color:#cccccc;stop-opacity:0;"
+ offset="1"
+ id="stop3237" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient10361"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path4305"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient23523"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#ffffff"
+ borderopacity="0.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="0"
+ inkscape:zoom="1.4"
+ inkscape:cx="134.45269"
+ inkscape:cy="35.224154"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1398"
+ inkscape:window-height="654"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata10408">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3223"
+ width="113.46721"
+ height="113.47578"
+ x="661.54346"
+ y="807.16095"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2160"
+ width="150.00647"
+ height="88.946548"
+ x="-191.84828"
+ y="470.84952"
+ transform="matrix(0.9999996,8.8501993e-4,-5.7799707e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -122.61932,559.41825 L -122.56703,586.68705"
+ id="path4416"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-115.59786"
+ y="502.84668"
+ id="text3139"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-115.59786"
+ y="502.84668"
+ id="tspan3145">Get client ID:</tspan><tspan
+ sodipodi:role="line"
+ x="-115.59786"
+ y="520.4242"
+ id="tspan10531"
+ style="font-size:14px;font-family:Courier 10 Pitch">srvmod client.py:</tspan><tspan
+ sodipodi:role="line"
+ x="-115.59786"
+ y="537.9242"
+ id="tspan10533"
+ style="font-size:14px;font-family:Courier 10 Pitch">get_clientid</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10535"
+ width="150.00647"
+ height="88.946548"
+ x="-191.8132"
+ y="591.80951"
+ transform="matrix(0.9999996,8.8501995e-4,-5.7799711e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-118.58022"
+ y="615.93799"
+ id="text10554"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-118.58022"
+ y="615.93799"
+ id="tspan10556">Init looping</tspan><tspan
+ sodipodi:role="line"
+ x="-115.39663"
+ y="640.93799"
+ id="tspan10572">pointer to DB </tspan><tspan
+ sodipodi:role="line"
+ x="-118.58022"
+ y="665.93799"
+ id="tspan10560"
+ style="font-size:20px;font-family:Bitstream Vera Sans">query results</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10581"
+ width="150.00647"
+ height="88.946548"
+ x="-189.41798"
+ y="713.28467"
+ transform="matrix(0.9999996,8.8502052e-4,-5.7799825e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-116.25535"
+ y="737.41522"
+ id="text10583"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-113.07175"
+ y="737.41522"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan10596">Load job from </tspan><tspan
+ sodipodi:role="line"
+ x="-113.07175"
+ y="762.41522"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan10602">DB into </tspan><tspan
+ sodipodi:role="line"
+ x="-116.25535"
+ y="785.35524"
+ style="font-size:20px;font-family:Courier 10 Pitch"
+ id="tspan10604">jobs_dict</tspan><tspan
+ sodipodi:role="line"
+ x="-116.25535"
+ y="810.35524"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan10598" /></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10616"
+ width="150.00647"
+ height="88.946548"
+ x="236.93985"
+ y="849.13074"
+ transform="matrix(0.9999996,8.85029e-4,-5.7801521e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-119.9763"
+ y="882.09253"
+ id="text10618"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-117.11107"
+ y="882.09253"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10622">Is the job's </tspan><tspan
+ sodipodi:role="line"
+ x="-119.9763"
+ y="902.73854"
+ style="font-size:18px;font-family:Courier 10 Pitch"
+ id="tspan10624">run_interval</tspan><tspan
+ sodipodi:role="line"
+ x="-119.9763"
+ y="927.09253"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10626">value &gt; 0?</tspan></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10636"
+ width="0"
+ height="18.182745"
+ x="150.51273"
+ y="513.95087"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10640"
+ width="113.46721"
+ height="113.47796"
+ x="1134.6199"
+ y="1278.9987"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-120.89916"
+ y="1400.8124"
+ id="text10642"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-118.03393"
+ y="1400.8124"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10648">Does </tspan><tspan
+ sodipodi:role="line"
+ x="-118.03393"
+ y="1423.3124"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10655">the client </tspan><tspan
+ sodipodi:role="line"
+ x="-118.03393"
+ y="1445.8124"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10657">already have </tspan><tspan
+ sodipodi:role="line"
+ x="-120.89916"
+ y="1468.3124"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10667">the job?</tspan></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10669"
+ width="113.46721"
+ height="113.47795"
+ x="1285.3126"
+ y="1430.3282"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-121.4402"
+ y="1586.36"
+ id="text10671"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-121.4402"
+ y="1586.36"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10690">More</tspan><tspan
+ sodipodi:role="line"
+ x="-121.4402"
+ y="1608.86"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10694">DB records</tspan><tspan
+ sodipodi:role="line"
+ x="-121.4402"
+ y="1631.36"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10700">in query?</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="308.94965"
+ y="864.55475"
+ id="text10704"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="311.17816"
+ y="864.55475"
+ id="tspan10710"
+ style="font-size:14px;font-family:Bitstream Vera Sans">Query DB for </tspan><tspan
+ sodipodi:role="line"
+ x="311.17816"
+ y="882.05475"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10717">largest job ID </tspan><tspan
+ sodipodi:role="line"
+ x="308.94965"
+ y="899.55475"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10719">with current job</tspan><tspan
+ sodipodi:role="line"
+ x="311.17816"
+ y="917.05475"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10721">as the origjob: </tspan><tspan
+ sodipodi:role="line"
+ x="308.94965"
+ y="933.11276"
+ style="font-size:14px;font-family:Courier 10 Pitch"
+ id="tspan10733">newjob</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="14.804216"
+ y="862.0365"
+ id="text10723"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="14.804216"
+ y="862.0365"
+ id="tspan10727">Yes, so this is a </tspan><tspan
+ sodipodi:role="line"
+ x="14.804216"
+ y="887.0365"
+ id="tspan10729">recurring job.</tspan></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10739"
+ width="113.46721"
+ height="113.47813"
+ x="1068.4481"
+ y="688.2597"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="311.21585"
+ y="1036.2333"
+ id="text10741"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="311.21585"
+ y="1036.2333"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10749">Does</tspan><tspan
+ sodipodi:role="line"
+ x="311.21585"
+ y="1052.2913"
+ style="font-size:14px;font-family:Courier 10 Pitch"
+ id="tspan10751">newjob</tspan><tspan
+ sodipodi:role="line"
+ x="311.21585"
+ y="1071.2333"
+ style="font-size:14px;font-family:Courier 10 Pitch"
+ id="tspan10762"><tspan
+ style="font-family:Bitstream Vera Sans"
+ id="tspan10764">have an </tspan>eventtime</tspan><tspan
+ sodipodi:role="line"
+ x="311.21585"
+ y="1090.1753"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10766">value?</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10768"
+ width="150.00647"
+ height="88.946548"
+ x="243.21637"
+ y="1388.5536"
+ transform="matrix(0.9999996,8.8502356e-4,-5.7800433e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="315.98819"
+ y="1413.0701"
+ id="text10770"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="319.17178"
+ y="1413.0701"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan10776">Add job to </tspan><tspan
+ sodipodi:role="line"
+ x="315.98819"
+ y="1438.0701"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan10785">queue for</tspan><tspan
+ sodipodi:role="line"
+ x="315.98819"
+ y="1463.0701"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan10787">client</tspan><tspan
+ sodipodi:role="line"
+ x="315.98819"
+ y="1488.0701"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan10778" /></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-8.3630829"
+ y="1420.2061"
+ id="text3163"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan3165"
+ x="-8.3630829"
+ y="1420.2061">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-83.309662"
+ y="1526.4396"
+ id="text9291"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-83.309662"
+ y="1526.4396"
+ id="tspan9293">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="319.12906"
+ y="1148.8682"
+ id="text10793"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="319.12906"
+ y="1148.8682"
+ id="tspan10795">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-111.10352"
+ y="1696.9423"
+ id="text10797"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan10799"
+ x="-111.10352"
+ y="1696.9423">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="6.3235712"
+ y="1092.3763"
+ id="text10801"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan10803"
+ x="6.3235712"
+ y="1092.3763">No, so it hasn't been</tspan><tspan
+ sodipodi:role="line"
+ x="6.3235712"
+ y="1117.3763"
+ id="tspan10805">run yet and should run</tspan><tspan
+ sodipodi:role="line"
+ x="6.3235712"
+ y="1142.3763"
+ id="tspan10807">unconditionally.</tspan></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10823"
+ width="113.46721"
+ height="113.47874"
+ x="1224.9142"
+ y="844.56018"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="311.33508"
+ y="1213.8826"
+ id="text10825"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="313.5636"
+ y="1213.8826"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10835">Has </tspan><tspan
+ sodipodi:role="line"
+ x="313.5636"
+ y="1231.3826"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10847">enough time </tspan><tspan
+ sodipodi:role="line"
+ x="311.33508"
+ y="1248.8826"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10849">elapsed since the</tspan><tspan
+ sodipodi:role="line"
+ x="311.33508"
+ y="1266.3826"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10851">last run?</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="418.03711"
+ y="1232.7932"
+ id="text10853"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan10855"
+ x="418.03711"
+ y="1232.7932">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="164.24954"
+ y="1232.079"
+ id="text10857"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="164.24954"
+ y="1232.079"
+ id="tspan10859">Yes</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -121.52266,679.89644 L -121.47037,707.16524"
+ id="path10861"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -120.04804,802.84357 L -119.99575,830.11237"
+ id="path10867"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99117851px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -27.119056,899.06781 L 231.02244,898.94707"
+ id="path10871"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.95675451px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 311.7902,938.82266 L 312.27103,992.2825"
+ id="path11844"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.98423362px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 220,1239.505 L -113.57143,1238.7908"
+ id="path12815"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.98957765px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M -119.76524,963.62234 L -119.28571,1364.505"
+ id="path13786"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99212563px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 218.73448,1062.4585 L -113.65224,1063.0765"
+ id="path14757"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99006528px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M -26.016101,1435.3512 L 235.56992,1434.0922"
+ id="path15728"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.95567065px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -119.17781,1499.6674 L -119.30971,1537.473"
+ id="path16699"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-247.21107"
+ y="1594.9423"
+ id="text17670"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-247.21107"
+ y="1594.9423"
+ id="tspan17672">Yes</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99190581px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 314.28571,1477.5046 L 314.28571,1602.3644"
+ id="path17674"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.01234651px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 460.71429,1607.3622 L -21.29938,1607.505"
+ id="path17676"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.86938626px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 312.53745,1127.2528 L 313.02377,1170.8967"
+ id="path19620"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99093974px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 406.92463,1239.801 L 460.93252,1239.801"
+ id="path19622"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99699807px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 460.62953,1239.7441 L 460.71429,1602.2671"
+ id="path19624"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.02519643px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M -212.88247,1607.3622 L -270.68898,1607.3622"
+ id="path21564"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99970818px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M -270,1606.6482 L -270,752.86106"
+ id="path21566"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.97189611px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M -270.72833,752.36218 L -195.42768,752.36218"
+ id="path21568"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient10361);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path10355"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,-186.24601,1714.6711)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-141.96242"
+ y="1754.639"
+ id="text10357"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-141.96242"
+ y="1754.639"
+ id="tspan10365">Stop</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#TriangleOutL)"
+ d="M -120,1671.5857 L -119.70308,1724.1136"
+ id="path22546"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient23523);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path23517"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,-189.58721,383.91771)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-145.3036"
+ y="424.59995"
+ id="text23519"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-145.3036"
+ y="424.59995"
+ id="tspan23521">Start</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M -122.1909,438.64855 L -122.13861,465.91735"
+ id="path23525"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-111.17606"
+ y="985.22491"
+ id="text2278"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan2280"
+ x="-111.17606"
+ y="985.22491">No</tspan></text>
+ </g>
+</svg>
diff --git a/docs/jobs_flow/svg/get_jstatus.svg b/docs/jobs_flow/svg/get_jstatus.svg
new file mode 100644
index 0000000..c671682
--- /dev/null
+++ b/docs/jobs_flow/svg/get_jstatus.svg
@@ -0,0 +1,428 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg10622"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ sodipodi:docbase="/home/disney/gentoo/diagrams"
+ sodipodi:docname="get_jstatus.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jstatus.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:modified="TRUE">
+ <defs
+ id="defs10624">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3233">
+ <stop
+ style="stop-color:#cccccc;stop-opacity:1;"
+ offset="0"
+ id="stop3235" />
+ <stop
+ style="stop-color:#cccccc;stop-opacity:0;"
+ offset="1"
+ id="stop3237" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient23523"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path4305"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient11111"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#ffffff"
+ borderopacity="0.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="0"
+ inkscape:zoom="0.49497475"
+ inkscape:cx="239.47794"
+ inkscape:cy="600.33586"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:window-width="1398"
+ inkscape:window-height="654"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata10627">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2160"
+ width="150.00647"
+ height="88.946548"
+ x="-34.910034"
+ y="116.74475"
+ transform="matrix(0.9999996,8.8501994e-4,-5.7799709e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 34.523535,205.45245 L 34.575825,232.72125"
+ id="path4416"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="41.544994"
+ y="148.88087"
+ id="text3139"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="41.544994"
+ y="148.88087"
+ id="tspan3145">Get client ID:</tspan><tspan
+ sodipodi:role="line"
+ x="41.544994"
+ y="166.45839"
+ id="tspan10531"
+ style="font-size:14px;font-family:Courier 10 Pitch">srvmod client.py:</tspan><tspan
+ sodipodi:role="line"
+ x="41.544994"
+ y="183.95839"
+ id="tspan10533"
+ style="font-size:14px;font-family:Courier 10 Pitch">get_clientid()</tspan></text>
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient23523);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path23517"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,-32.444355,29.951909)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="11.839252"
+ y="70.634148"
+ id="text23519"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="11.839252"
+ y="70.634148"
+ id="tspan23521">Start</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 34.951955,84.682749 L 35.004245,111.95155"
+ id="path23525"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10766"
+ width="150.00647"
+ height="88.946548"
+ x="-34.696831"
+ y="238.45732"
+ transform="matrix(0.9999996,8.8502042e-4,-5.7799805e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 34.666391,327.1654 L 34.718681,354.4342"
+ id="path10768"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="41.687851"
+ y="270.59381"
+ id="text10770"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="41.687851"
+ y="270.59381"
+ id="tspan10778"
+ style="font-size:18">Get job details:</tspan><tspan
+ sodipodi:role="line"
+ x="41.687851"
+ y="287.66483"
+ id="tspan10774"
+ style="font-size:14px;font-family:Courier 10 Pitch">srvmod job.py:</tspan><tspan
+ sodipodi:role="line"
+ x="41.687851"
+ y="305.16483"
+ id="tspan10776"
+ style="font-size:14px;font-family:Courier 10 Pitch">get_job()</tspan></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3223"
+ width="113.46721"
+ height="113.47631"
+ x="338.06894"
+ y="295.57553"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="34.891605"
+ y="407.79559"
+ id="text10618"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="37.75684"
+ y="407.79559"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10622">Is the job's </tspan><tspan
+ sodipodi:role="line"
+ x="34.891605"
+ y="428.44161"
+ style="font-size:18px;font-family:Courier 10 Pitch"
+ id="tspan10624">run_interval</tspan><tspan
+ sodipodi:role="line"
+ x="34.891605"
+ y="452.79559"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10626">value &gt; 0?</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="175.03906"
+ y="389.30832"
+ id="text10723"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="175.03906"
+ y="389.30832"
+ id="tspan10727">Yes, so this is a </tspan><tspan
+ sodipodi:role="line"
+ x="175.03906"
+ y="414.30832"
+ id="tspan10729">recurring job.</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99117851px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 128.64161,424.48186 L 386.78311,424.36112"
+ id="path10871"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10616"
+ width="150.00647"
+ height="88.946548"
+ x="391.95554"
+ y="378.19"
+ transform="matrix(0.9999996,8.8502906e-4,-5.7801533e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="466.23749"
+ y="399.75131"
+ id="text10704"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="466.23749"
+ y="399.75131"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan10733">Query DB, replace</tspan><tspan
+ sodipodi:role="line"
+ x="466.23749"
+ y="417.25131"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan11133">current job ID with</tspan><tspan
+ sodipodi:role="line"
+ x="468.466"
+ y="434.75131"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan11127">largest job ID where </tspan><tspan
+ sodipodi:role="line"
+ x="466.23749"
+ y="452.25131"
+ style="font-size:14px;font-family:Bitstream Vera Sans"
+ id="tspan11137">current job==origjob</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 34.802227,488.18449 L 34.854517,515.45329"
+ id="path10920"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2324"
+ width="150.00647"
+ height="88.946548"
+ x="-34.05862"
+ y="520.53436"
+ transform="matrix(0.9999996,8.8502096e-4,-5.7799913e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 35.141472,609.24375 L 35.193762,636.51255"
+ id="path2326"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="40.162949"
+ y="546.67218"
+ id="text2328"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="40.162949"
+ y="546.67218"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan2344">Query DB</tspan><tspan
+ sodipodi:role="line"
+ x="40.162949"
+ y="571.67218"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan11101">for job status</tspan><tspan
+ sodipodi:role="line"
+ x="40.162949"
+ y="596.67218"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan11103">to return</tspan></text>
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient11111);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path11105"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,-33.207898,626.85979)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="-12.662875"
+ y="666.53186"
+ id="text11107"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="-12.662875"
+ y="666.53186"
+ id="tspan11109"
+ style="font-size:16px">Return/Stop</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00114262px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 469.7215,467.86275 L 469.9729,560.66986"
+ id="path11141"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99832714px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 470.47938,560.41789 L 121.20111,560.41789"
+ id="path11143"
+ inkscape:connector-type="polyline" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="41.681084"
+ y="506.94226"
+ id="text2278"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan2280"
+ x="41.681084"
+ y="506.94226">No</tspan></text>
+ </g>
+</svg>
diff --git a/docs/jobs_flow/svg/run_jobs.svg b/docs/jobs_flow/svg/run_jobs.svg
new file mode 100644
index 0000000..d623959
--- /dev/null
+++ b/docs/jobs_flow/svg/run_jobs.svg
@@ -0,0 +1,1194 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2280"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ sodipodi:docbase="/home/disney/gentoo/diagrams"
+ sodipodi:docname="run_jobs.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/run_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:modified="TRUE">
+ <defs
+ id="defs2282">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient8529">
+ <stop
+ style="stop-color:#ccffff;stop-opacity:1;"
+ offset="0"
+ id="stop8531" />
+ <stop
+ style="stop-color:#ccffff;stop-opacity:0;"
+ offset="1"
+ id="stop8533" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3233">
+ <stop
+ style="stop-color:#cccccc;stop-opacity:1;"
+ offset="0"
+ id="stop3235" />
+ <stop
+ style="stop-color:#cccccc;stop-opacity:0;"
+ offset="1"
+ id="stop3237" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient23523"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path4305"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8529"
+ id="linearGradient8535"
+ x1="100"
+ y1="130.93361"
+ x2="170"
+ y2="130.60306"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.9990606,0,0.12269)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient10488"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#ffffff"
+ borderopacity="0.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="0"
+ inkscape:zoom="1.7632169"
+ inkscape:cx="372.04724"
+ inkscape:cy="-808.4065"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:window-width="1398"
+ inkscape:window-height="654"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata2285">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:#ccffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99426967;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2492"
+ width="533.36627"
+ height="555.08984"
+ x="139.39818"
+ y="442.35931" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient23523);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path23517"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,182.65612,6.0510447)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="226.93974"
+ y="46.733276"
+ id="text23519"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="226.93974"
+ y="46.733276"
+ id="tspan23521">Start</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.05243,60.781884 L 250.10472,88.050684"
+ id="path23525"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2160"
+ width="150.00647"
+ height="88.946548"
+ x="180.07655"
+ y="93.410286"
+ transform="matrix(0.9999996,8.8501995e-4,-5.7799711e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 249.52354,182.30825 L 249.57583,209.57705"
+ id="path4416"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="256.54501"
+ y="125.73669"
+ id="text3139"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="256.54501"
+ y="125.73669"
+ id="tspan3145">Get job details:</tspan><tspan
+ sodipodi:role="line"
+ x="256.54501"
+ y="143.3142"
+ id="tspan10531"
+ style="font-size:14px;font-family:Courier 10 Pitch">srvmod job.py:</tspan><tspan
+ sodipodi:role="line"
+ x="256.54501"
+ y="160.8142"
+ id="tspan10533"
+ style="font-size:14px;font-family:Courier 10 Pitch">get_job()</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2304"
+ width="150.00647"
+ height="88.946548"
+ x="181.57532"
+ y="214.83754"
+ transform="matrix(0.9999996,8.8501995e-4,-5.7799711e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.95211,303.73683 L 251.0044,331.00563"
+ id="path2306"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="257.97357"
+ y="247.16527"
+ id="text2308"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="257.97357"
+ y="247.16527"
+ id="tspan2310">Sanity check</tspan><tspan
+ sodipodi:role="line"
+ x="257.97357"
+ y="272.16527"
+ id="tspan2314"
+ style="font-size:20px;font-family:Bitstream Vera Sans">(stub)</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2324"
+ width="150.00647"
+ height="88.946548"
+ x="180.35963"
+ y="335.83865"
+ transform="matrix(0.9999996,8.8502034e-4,-5.7799789e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 249.66639,424.73683 L 249.71868,452.00563"
+ id="path2326"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="254.68787"
+ y="362.16525"
+ id="text2328"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="257.87146"
+ y="362.16525"
+ id="tspan2330">Write script </tspan><tspan
+ sodipodi:role="line"
+ x="254.68787"
+ y="387.16525"
+ id="tspan2334"
+ style="font-size:20px;font-family:Bitstream Vera Sans">to temp file</tspan><tspan
+ sodipodi:role="line"
+ x="254.68787"
+ y="412.16525"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan2344">to run later</tspan></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3223"
+ width="113.46721"
+ height="113.47588"
+ x="554.32941"
+ y="250.68132"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="249.82019"
+ y="505.15274"
+ id="text10618"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="249.82019"
+ y="505.15274"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10622">Has the job</tspan><tspan
+ sodipodi:role="line"
+ x="249.82019"
+ y="527.65274"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2369">been cancelled on</tspan><tspan
+ sodipodi:role="line"
+ x="249.82019"
+ y="550.15274"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan10626">the server?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 249.80911,586.43427 L 249.8614,613.70307"
+ id="path2378"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2380"
+ width="113.46721"
+ height="113.47592"
+ x="697.00842"
+ y="393.34079"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="249.82033"
+ y="665.08112"
+ id="text2382"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="249.82033"
+ y="665.08112"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2397">Are there</tspan><tspan
+ sodipodi:role="line"
+ x="249.82033"
+ y="687.58112"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2404">dependencies</tspan><tspan
+ sodipodi:role="line"
+ x="249.82033"
+ y="710.08112"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2406">for the job?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 249.95196,748.29142 L 250.00425,775.56022"
+ id="path2408"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 343.42923,683.83878 L 370.69803,683.78649"
+ id="path2410"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2412"
+ width="150.00647"
+ height="88.946548"
+ x="376.81927"
+ y="636.77484"
+ transform="matrix(0.9999996,8.8501997e-4,-5.7799715e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="453.28125"
+ y="658.20386"
+ id="text2414"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="455.82812"
+ y="658.20386"
+ id="tspan2422"
+ style="font-size:16px">Get job status of </tspan><tspan
+ sodipodi:role="line"
+ x="453.28125"
+ y="678.20386"
+ id="tspan2426"
+ style="font-size:16px">dependencies:</tspan><tspan
+ sodipodi:role="line"
+ x="453.28125"
+ y="694.76837"
+ id="tspan2418"
+ style="font-size:14px;font-family:Courier 10 Pitch">srvmod job.py:</tspan><tspan
+ sodipodi:role="line"
+ x="453.28125"
+ y="712.26837"
+ id="tspan2420"
+ style="font-size:14px;font-family:Courier 10 Pitch">get_jstatus()</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 454.90518,726.5057 L 454.95747,753.7745"
+ id="path2428"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2430"
+ width="113.46721"
+ height="113.47611"
+ x="944.67792"
+ y="391.73999"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="454.96313"
+ y="803.08105"
+ id="text2432"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="457.82837"
+ y="803.08105"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2445">Was the </tspan><tspan
+ sodipodi:role="line"
+ x="454.96313"
+ y="825.58105"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2449">dependency job</tspan><tspan
+ sodipodi:role="line"
+ x="454.96313"
+ y="848.08105"
+ style="font-size:18px;font-family:Bitstream Vera Sans"
+ id="tspan2451">successful?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 362.6422,823.48165 L 335.3734,823.42936"
+ id="path2453"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2455"
+ width="150.00647"
+ height="88.946548"
+ x="180.9938"
+ y="781.2691"
+ transform="matrix(0.9999996,8.8502034e-4,-5.7799789e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.0431,870.16782 L 250.09539,897.43662"
+ id="path2457"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="252.03412"
+ y="817.69775"
+ id="text2459"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="255.21771"
+ y="817.69775"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan2465">Run </tspan><tspan
+ sodipodi:role="line"
+ x="252.03412"
+ y="842.69775"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan2472">script</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2474"
+ width="150.00647"
+ height="88.946548"
+ x="181.11292"
+ y="902.69281"
+ transform="matrix(0.9999996,8.8502036e-4,-5.7799793e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.09204,991.59165 L 250.14433,1018.8605"
+ id="path2476"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="252.08305"
+ y="939.12158"
+ id="text2478"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="252.08305"
+ y="939.12158"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan2482">Log script</tspan><tspan
+ sodipodi:role="line"
+ x="252.08305"
+ y="964.12158"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan2486">output locally</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="599.02045"
+ y="467.48386"
+ id="text3463"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ x="599.02045"
+ y="467.48386"
+ id="tspan3467"
+ style="font-family:Courier 10 Pitch">scirec.py:</tspan><tspan
+ sodipodi:role="line"
+ x="599.02045"
+ y="492.48386"
+ id="tspan3471"
+ style="font-family:Courier 10 Pitch">run_job()</tspan></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3473"
+ width="113.46721"
+ height="113.47613"
+ x="1053.8943"
+ y="749.37567"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="250.48044"
+ y="1068.2316"
+ id="text3475"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="253.66403"
+ y="1068.2316"
+ style="font-size:20;font-family:Bitstream Vera Sans"
+ id="tspan3481">Job </tspan><tspan
+ sodipodi:role="line"
+ x="250.48044"
+ y="1093.2316"
+ style="font-size:20;font-family:Bitstream Vera Sans"
+ id="tspan3488">status:</tspan><tspan
+ sodipodi:role="line"
+ x="250.48044"
+ y="1118.2316"
+ style="font-size:20;font-family:Bitstream Vera Sans"
+ id="tspan3490">failed?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.46979,1153.6834 L 250.52208,1180.9522"
+ id="path3492"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3494"
+ width="113.46721"
+ height="113.47615"
+ x="1196.2568"
+ y="891.71887"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="250.4805"
+ y="1222.8724"
+ id="text3496"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="253.66409"
+ y="1222.8724"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan3498">Job </tspan><tspan
+ sodipodi:role="line"
+ x="250.4805"
+ y="1247.8724"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan3500">status:</tspan><tspan
+ sodipodi:role="line"
+ x="250.4805"
+ y="1272.8724"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan3502">cancelled?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.46985,1315.3953 L 250.52214,1342.6641"
+ id="path3504"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3506"
+ width="113.46721"
+ height="113.47615"
+ x="1338.5422"
+ y="1033.9851"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="254.5211"
+ y="1408.7405"
+ id="text3508"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="257.38634"
+ y="1408.7405"
+ style="font-size:18;font-family:Bitstream Vera Sans"
+ id="tspan3518">Return code == </tspan><tspan
+ sodipodi:role="line"
+ x="254.5211"
+ y="1431.2405"
+ style="font-size:18;font-family:Bitstream Vera Sans"
+ id="tspan3514">job success?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.46985,1599.0196 L 250.52214,1626.2884"
+ id="path3516"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3539"
+ width="150.00647"
+ height="88.946548"
+ x="181.48566"
+ y="1631.8379"
+ transform="matrix(0.9999996,8.8502139e-4,-5.7799999e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.04309,1720.7368 L 250.09538,1748.0056"
+ id="path3541"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="252.03412"
+ y="1668.2667"
+ id="text3543"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="252.03412"
+ y="1668.2667"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan3547">Remove job</tspan><tspan
+ sodipodi:role="line"
+ x="252.03412"
+ y="1693.2667"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan3551">from queue</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="397.85715"
+ y="1628.7908"
+ id="text3553"><tspan
+ sodipodi:role="line"
+ id="tspan3555"
+ x="397.85715"
+ y="1628.7908"></tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3559"
+ width="150.00647"
+ height="88.946548"
+ x="182.46498"
+ y="1753.5513"
+ transform="matrix(0.9999996,8.8502168e-4,-5.7800057e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.95201,1842.4512 L 251.0043,1869.72"
+ id="path3561"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="252.94302"
+ y="1777.9811"
+ id="text3563"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="256.12662"
+ y="1777.9811"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan3567">Remove </tspan><tspan
+ sodipodi:role="line"
+ x="256.12662"
+ y="1802.9811"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan3571">script </tspan><tspan
+ sodipodi:role="line"
+ x="252.94302"
+ y="1827.9811"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan3573">temp file</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99646091px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 342.85537,521.64613 L 578.5732,522.36395"
+ id="path3575"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 579.28571,521.6479 L 580,1010.2193"
+ id="path3577"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99780935px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 580.71539,1010.2193 L 255.09344,1010.2193"
+ id="path3579"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline;marker-end:url(#TriangleOutL)"
+ d="M 455,888.07647 L 455.71429,1005.2193"
+ id="path4550"
+ inkscape:connector-type="polyline" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect5521"
+ width="150.00647"
+ height="88.946548"
+ x="182.47363"
+ y="1509.4076"
+ transform="matrix(0.9999996,8.8502074e-4,-5.7799869e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="253.0932"
+ y="1545.8375"
+ id="text5523"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="256.27679"
+ y="1545.8375"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan5545">Store job </tspan><tspan
+ sodipodi:role="line"
+ x="253.0932"
+ y="1570.8375"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan5549">status in DB</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect5529"
+ width="150.00647"
+ height="88.946548"
+ x="378.36115"
+ y="1367.1019"
+ transform="matrix(0.9999996,8.850204e-4,-5.7799801e-4,0.9999998,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="453.06277"
+ y="1392.0345"
+ id="text5531"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="456.24637"
+ y="1392.0345"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan5535">Store job </tspan><tspan
+ sodipodi:role="line"
+ x="456.24637"
+ y="1417.0345"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan5553">status and </tspan><tspan
+ sodipodi:role="line"
+ x="453.06277"
+ y="1442.0345"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan5555">output in DB</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 250.46979,1476.9322 L 250.52208,1504.201"
+ id="path5537"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="258.03711"
+ y="603.93182"
+ id="text2278"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan2280"
+ x="258.03711"
+ y="603.93182">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="259.71814"
+ y="764.54608"
+ id="text5559"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan5561"
+ x="259.71814"
+ y="764.54608">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="459.72833"
+ y="910.00806"
+ id="text5563"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan5565"
+ x="459.72833"
+ y="910.00806">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="255.67752"
+ y="1172.6477"
+ id="text5567"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan5569"
+ x="255.67752"
+ y="1172.6477">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="256.68768"
+ y="1336.2924"
+ id="text5571"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan5573"
+ x="256.68768"
+ y="1336.2924">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="344.57095"
+ y="1406.9423"
+ id="text5575"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan5577"
+ x="344.57095"
+ y="1406.9423">No</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99075466px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 342.84287,1412.0243 L 371.8248,1411.9722"
+ id="path5579"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00171554px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 449.51788,1088.7082 L 449.51788,1361.4309"
+ id="path5581"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99763852px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 344.45966,1088.7277 L 450.02532,1088.7277"
+ id="path6552"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 157.5838,1250.3521 L 115.15739,1250.3521"
+ id="path6554"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 115.15739,1249.847 L 115.66247,1552.3877"
+ id="path6556"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.01842511px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 115.52439,1551.8622 L 175.68747,1551.8622"
+ id="path6558"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 450.52804,1456.9283 L 449.51788,1677.1415"
+ id="path7529"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.99602062px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 449.50199,1676.8622 L 335.81691,1676.8622"
+ id="path7531"
+ inkscape:connector-type="polyline" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect8502"
+ width="113.46721"
+ height="113.47622"
+ x="1803.416"
+ y="1498.1364"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="251.02336"
+ y="1930.1797"
+ id="text8504"
+ sodipodi:linespacing="125%"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="251.02336"
+ y="1930.1797"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan8510">Next</tspan><tspan
+ sodipodi:role="line"
+ x="251.02336"
+ y="1955.1797"
+ style="font-size:20px;font-family:Bitstream Vera Sans"
+ id="tspan8519">job?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96277702px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 251.0127,2004.7025 L 251.06499,2031.9713"
+ id="path8512"
+ inkscape:connector-type="polyline"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96521723px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 157.9438,1939.7811 L 99.764462,1939.7812"
+ id="path8521"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:url(#linearGradient8535);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.99953014px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 94.954339,1939.5954 L 94.954339,131.10259"
+ id="path8523"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.01607728px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1;display:inline"
+ d="M 94.373749,131.29503 L 174.16591,131.29503"
+ id="path8538"
+ inkscape:connector-type="polyline" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="253.89648"
+ y="2023.0903"
+ id="text10478"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan10480"
+ x="253.89648"
+ y="2023.0903">No</tspan></text>
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient10488);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path10482"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,183.18716,2022.8558)"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="227.47078"
+ y="2063.5381"
+ id="text10484"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="227.47078"
+ y="2063.5381"
+ id="tspan10486">Stop</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="344.49756"
+ y="516.75269"
+ id="text10793"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="344.49756"
+ y="516.75269"
+ id="tspan10795">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="338.79611"
+ y="679.52338"
+ id="text10492"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="338.79611"
+ y="679.52338"
+ id="tspan10494">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="334.85608"
+ y="817.3396"
+ id="text10496"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="334.85608"
+ y="817.3396"
+ id="tspan10498">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="342.85608"
+ y="1083.5693"
+ id="text10500"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="342.85608"
+ y="1083.5693"
+ id="tspan10502">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="123.54951"
+ y="1245.2357"
+ id="text10504"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="123.54951"
+ y="1245.2357"
+ id="tspan10506">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="256.65002"
+ y="1497.0481"
+ id="text10508"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="256.65002"
+ y="1497.0481"
+ id="tspan10510">Yes</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="118.20661"
+ y="1932.9142"
+ id="text10512"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/get_jobs.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ x="118.20661"
+ y="1932.9142"
+ id="tspan10514">Yes</tspan></text>
+ </g>
+</svg>
diff --git a/docs/jobs_flow/svg/scirec_main.svg b/docs/jobs_flow/svg/scirec_main.svg
new file mode 100644
index 0000000..13f3c9e
--- /dev/null
+++ b/docs/jobs_flow/svg/scirec_main.svg
@@ -0,0 +1,628 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="410.23392"
+ height="1251.2834"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ sodipodi:docbase="/home/disney/gentoo/diagrams"
+ sodipodi:docname="scirec_main.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0"
+ inkscape:export-filename="/home/disney/gentoo/diagrams/scirec_main.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ sodipodi:modified="true">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="TriangleInL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleInL"
+ style="overflow:visible">
+ <path
+ id="path4314"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(-0.8,-0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path4305"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutM"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutM"
+ style="overflow:visible">
+ <path
+ id="path4302"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.4,0.4)" />
+ </marker>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3233">
+ <stop
+ style="stop-color:#cccccc;stop-opacity:1;"
+ offset="0"
+ id="stop3235" />
+ <stop
+ style="stop-color:#cccccc;stop-opacity:0;"
+ offset="1"
+ id="stop3237" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient3239"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3233"
+ id="linearGradient10361"
+ gradientUnits="userSpaceOnUse"
+ x1="110.35865"
+ y1="84.70903"
+ x2="122.83298"
+ y2="205.02553" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="273.09642"
+ inkscape:cy="616.90193"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:window-width="1398"
+ inkscape:window-height="654"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ showguides="false"
+ inkscape:object-paths="true"
+ inkscape:grid-bbox="false" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(18.999994,-21.506585)">
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect4414"
+ width="113.46721"
+ height="113.47571"
+ x="593.90295"
+ y="502.76419"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)" />
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3223"
+ width="113.46721"
+ height="113.47566"
+ x="229.24068"
+ y="136.78836"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3217"
+ width="150.00647"
+ height="88.946548"
+ x="0.83566481"
+ y="507.79147"
+ transform="matrix(0.9999996,8.8501992e-4,-5.7799705e-4,0.9999998,0,0)" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2160"
+ width="150.00647"
+ height="88.946548"
+ x="0.59579605"
+ y="92.791626"
+ transform="matrix(0.9999996,8.8501991e-4,-5.7799703e-4,0.9999998,0,0)" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient3239);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path3133"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,7.2984399,7.2380794)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="51.582031"
+ y="47.205933"
+ id="text3135"><tspan
+ sodipodi:role="line"
+ id="tspan3137"
+ x="51.582031"
+ y="47.205933">Start</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="73.070572"
+ y="116.94228"
+ id="text3139"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3141"
+ x="76.254166"
+ y="116.94228">Process </tspan><tspan
+ sodipodi:role="line"
+ x="73.070572"
+ y="141.94228"
+ id="tspan3143">CLI</tspan><tspan
+ sodipodi:role="line"
+ x="73.070572"
+ y="166.94228"
+ id="tspan3145">options</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="188.03711"
+ y="262.07898"
+ id="text3163"><tspan
+ sodipodi:role="line"
+ id="tspan3165"
+ x="188.03711"
+ y="262.07898">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="78.490501"
+ y="542.4967"
+ id="text3179"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ x="78.490501"
+ y="542.4967"
+ id="tspan3183">Init XML-RPC</tspan><tspan
+ sodipodi:role="line"
+ x="78.490501"
+ y="567.4967"
+ id="tspan3185">client object</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3219"
+ width="150.00647"
+ height="88.946548"
+ x="239.63451"
+ y="227.64088"
+ transform="matrix(0.9999996,8.8501998e-4,-5.7799717e-4,0.9999998,0,0)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="75.07811"
+ y="257.07898"
+ id="text3147"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3149"
+ x="75.07811"
+ y="257.07898">Does</tspan><tspan
+ sodipodi:role="line"
+ x="75.07811"
+ y="282.07898"
+ id="tspan3151">keypair</tspan><tspan
+ sodipodi:role="line"
+ x="75.07811"
+ y="307.07898"
+ id="tspan3153">exist?</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="74.21563"
+ y="652.0788"
+ id="text3189"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3191"
+ x="76.444145"
+ y="652.0788"
+ style="font-size:14px">Client </tspan><tspan
+ sodipodi:role="line"
+ x="74.21563"
+ y="669.5788"
+ id="tspan3193"
+ style="font-size:14px">status defined?</tspan><tspan
+ sodipodi:role="line"
+ x="74.21563"
+ y="685.63681"
+ id="tspan10369"
+ style="font-size:14px;font-family:Courier 10 Pitch">svrmod client.py:</tspan><tspan
+ sodipodi:role="line"
+ x="74.21563"
+ y="703.13681"
+ style="font-size:14px;font-family:Courier 10 Pitch"
+ id="tspan10375">register_client()</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="314.32617"
+ y="262.20593"
+ id="text3167"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3169"
+ x="314.32617"
+ y="262.20593">Generate</tspan><tspan
+ sodipodi:role="line"
+ x="314.32617"
+ y="287.20593"
+ id="tspan3171">keypair</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3227"
+ width="150.00647"
+ height="88.946548"
+ x="240.91367"
+ y="642.57904"
+ transform="matrix(0.9999996,8.8501995e-4,-5.7799711e-4,0.9999998,0,0)" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3229"
+ width="150.00647"
+ height="88.946548"
+ x="0.76919514"
+ y="392.79153"
+ transform="matrix(0.9999996,8.8501992e-4,-5.7799705e-4,0.9999998,0,0)" />
+ <text
+ xml:space="preserve"
+ style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="314.74188"
+ y="657.42694"
+ id="text3195"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ x="316.9704"
+ y="657.42694"
+ id="tspan3205">Add with client info </tspan><tspan
+ sodipodi:role="line"
+ x="316.9704"
+ y="674.92694"
+ id="tspan10385">as pending: </tspan><tspan
+ sodipodi:role="line"
+ x="314.74188"
+ y="687.40995"
+ id="tspan10387"
+ style="font-family:Courier 10 Pitch;font-size:10">scirec.py: sys_info(),</tspan><tspan
+ sodipodi:role="line"
+ x="314.74188"
+ y="699.90995"
+ id="tspan10389"
+ style="font-family:Courier 10 Pitch;font-size:10">svrmod client.py:</tspan><tspan
+ sodipodi:role="line"
+ x="314.74188"
+ y="712.40995"
+ id="tspan10391"
+ style="font-family:Courier 10 Pitch;font-size:10">add_client()</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="70.576187"
+ y="427.5575"
+ id="text3173"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3175"
+ x="70.576187"
+ y="427.5575">Load</tspan><tspan
+ sodipodi:role="line"
+ x="70.576187"
+ y="452.5575"
+ id="tspan3177">certificate</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3231"
+ width="150.00647"
+ height="88.946548"
+ x="1.0119539"
+ y="812.79138"
+ transform="matrix(0.9999996,8.8501994e-4,-5.7799709e-4,0.9999998,0,0)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="76.506531"
+ y="845.15253"
+ id="text3207"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ x="76.506531"
+ y="845.15253"
+ id="tspan3213">Get list of jobs:</tspan><tspan
+ sodipodi:role="line"
+ x="76.506531"
+ y="862.73004"
+ id="tspan10395"
+ style="font-size:14px;font-family:Courier 10 Pitch">svrmod job.py:</tspan><tspan
+ sodipodi:role="line"
+ x="76.506531"
+ y="880.23004"
+ id="tspan10397"
+ style="font-size:14px;font-family:Courier 10 Pitch">get_jobs()</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.93400759px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 75.390735,62.333068 L 75.443236,87.897726"
+ id="path4416"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.91477418px;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 75.69892,182.25337 L 75.800832,203.08282"
+ id="path5407"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.96590352px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 170.36077,272.37417 L 234.09696,272.38295"
+ id="path7349"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.9155761px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 75.833192,337.27561 L 75.667824,387.67812"
+ id="path8320"
+ inkscape:connector-type="polyline" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="88.681641"
+ y="366.94226"
+ id="text9291"><tspan
+ sodipodi:role="line"
+ x="88.681641"
+ y="366.94226"
+ id="tspan9293">Yes</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00151396px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 314.42583,317.35732 L 314.28647,436.86143"
+ id="path9297"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.98845464px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInL);stroke-opacity:1;display:inline"
+ d="M 154.99774,437.11555 C 208.09565,436.95944 261.19356,436.80333 314.29148,436.64722"
+ id="path9299" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.91477418px;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 74.02484,481.8528 L 74.126752,502.68225"
+ id="path10273"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.91477418px;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 74.659688,597.38937 L 74.7616,618.21882"
+ id="path10275"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.9822917px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 168.47328,687.40895 L 234.53071,687.41771"
+ id="path10277"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.00151396px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 314.67383,731.91373 L 314.53447,851.41784"
+ id="path10279"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.98845464px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInL);stroke-opacity:1;display:inline"
+ d="M 155.24574,851.67196 C 208.34365,851.51585 261.44156,851.35974 314.53948,851.20363"
+ id="path10281" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.9590643px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 75.157506,751.4981 L 74.99312,807.1327"
+ id="path10283"
+ inkscape:connector-type="polyline" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="186.68108"
+ y="672.36774"
+ id="text10285"><tspan
+ sodipodi:role="line"
+ id="tspan10287"
+ x="186.68108"
+ y="672.36774">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="91.503204"
+ y="786.65344"
+ id="text10289"><tspan
+ sodipodi:role="line"
+ x="91.503204"
+ y="786.65344"
+ id="tspan10291">Yes</tspan></text>
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10293"
+ width="150.00647"
+ height="88.946548"
+ x="1.2730629"
+ y="927.82153"
+ transform="matrix(0.9999996,8.8501997e-4,-5.7799715e-4,0.9999998,0,0)" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.91477418px;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 75.622686,901.55047 L 75.724598,922.37992"
+ id="path10295"
+ inkscape:connector-type="polyline" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="73.479355"
+ y="953.41827"
+ id="text10297"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ x="73.479355"
+ y="953.41827"
+ id="tspan10301">Run jobs:</tspan><tspan
+ sodipodi:role="line"
+ x="73.479355"
+ y="970.99579"
+ id="tspan10399"
+ style="font-family:Courier 10 Pitch;font-size:14">scirec.py:</tspan><tspan
+ sodipodi:role="line"
+ x="73.479355"
+ y="988.49579"
+ id="tspan10401"
+ style="font-family:Courier 10 Pitch;font-size:14">run_jobs()</tspan><tspan
+ sodipodi:role="line"
+ x="73.479355"
+ y="1005.9958"
+ id="tspan10305" /></text>
+ <rect
+ style="fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.13471448;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10307"
+ width="113.46721"
+ height="113.47575"
+ x="963.49048"
+ y="871.35999"
+ transform="matrix(0.8229751,0.5680775,-0.8230865,0.5679161,0,0)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="73.562241"
+ y="1106.3645"
+ id="text10309"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ x="73.562241"
+ y="1106.3645"
+ id="tspan10313">Daemon</tspan><tspan
+ sodipodi:role="line"
+ x="73.562241"
+ y="1131.3645"
+ id="tspan10321">mode?</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.91477418px;stroke-linecap:butt;stroke-linejoin:miter;marker-mid:none;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 75.265542,1016.6219 L 75.367454,1037.4513"
+ id="path10317"
+ inkscape:connector-type="polyline" />
+ <rect
+ style="font-size:20px;fill:#cccccc;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.98150337;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect10323"
+ width="150.00647"
+ height="88.946548"
+ x="241.35118"
+ y="1062.8234"
+ transform="matrix(0.9999996,8.8501999e-4,-5.7799719e-4,0.9999998,0,0)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="315.23236"
+ y="1096.4672"
+ id="text10325"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ x="315.23236"
+ y="1096.4672"
+ id="tspan10331">Sleep for</tspan><tspan
+ sodipodi:role="line"
+ x="315.23236"
+ y="1121.4672"
+ id="tspan10341">poll_int</tspan></text>
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.9822917px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 168.98987,1106.6394 L 235.0473,1106.6482"
+ id="path10333"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.9590643px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#TriangleOutL);stroke-opacity:1"
+ d="M 75.515,1171.2599 L 75.350614,1226.8945"
+ id="path10335"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.04544771px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+ d="M 315.51117,872.71982 L 315.41575,1062.8907"
+ id="path10343"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:0.98845464px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#TriangleInL);stroke-opacity:1;display:inline"
+ d="M 156.04099,873.57188 C 209.1389,873.41577 262.23681,873.25966 315.33473,873.10355"
+ id="path10345" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="99.103874"
+ y="1206.9929"
+ id="text10347"><tspan
+ sodipodi:role="line"
+ id="tspan10349"
+ x="99.103874"
+ y="1206.9929">No</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="184.37054"
+ y="1093.8558"
+ id="text10351"><tspan
+ sodipodi:role="line"
+ x="184.37054"
+ y="1093.8558"
+ id="tspan10353">Yes</tspan></text>
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient10361);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path10355"
+ sodipodi:cx="105.05586"
+ sodipodi:cy="52.311161"
+ sodipodi:rx="83.842659"
+ sodipodi:ry="30.304577"
+ d="M 188.89852 52.311161 A 83.842659 30.304577 0 1 1 21.213203,52.311161 A 83.842659 30.304577 0 1 1 188.89852 52.311161 z"
+ transform="matrix(0.6478283,0,0,0.6632677,5.5132681,1217.6659)" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="49.796856"
+ y="1257.6338"
+ id="text10357"><tspan
+ sodipodi:role="line"
+ x="49.796856"
+ y="1257.6338"
+ id="tspan10365">Stop</tspan></text>
+ </g>
+</svg>
diff --git a/docs/moria.sql b/docs/moria.sql
new file mode 100644
index 0000000..cbe0a7a
--- /dev/null
+++ b/docs/moria.sql
@@ -0,0 +1,96 @@
+--create database moria;
+use moria;
+drop table if exists modules;
+create table modules ( id INT NOT NULL default '0',
+name VARCHAR(50),
+long_name VARCHAR(150),
+description VARCHAR(250),
+main_content VARCHAR(90),
+author VARCHAR(50),
+distribution VARCHAR(50),
+category VARCHAR(30),
+homepage VARCHAR(90),
+PRIMARY KEY (id)
+) TYPE=MyISAM;
+
+drop table if exists clients;
+create table clients (
+client_id INT NOT NULL AUTO_INCREMENT,
+hostname VARCHAR(30) NOT NULL default 'hostname',
+mac VARCHAR(17) NOT NULL default '00:01:02:03:04:05',
+ip VARCHAR(15) NOT NULL default 'dhcp',
+profile VARCHAR(30),
+distribution VARCHAR(50),
+administrator VARCHAR(50),
+status VARCHAR(100),
+PRIMARY KEY (client_id)
+) TYPE=MyISAM;
+
+drop table if exists profiles;
+create table profiles (
+profile_name VARCHAR(30),
+filename VARCHAR(90) NOT NULL,
+description VARCHAR(250),
+distribution VARCHAR(50),
+PRIMARY KEY (profile_name)
+) TYPE=MyISAM;
+
+drop table if exists groups;
+create table groups (
+profile_name VARCHAR(30) NOT NULL,
+machine_id INT NOT NULL
+) TYPE=MyISAM;
+
+drop table if exists users;
+create table users (
+username VARCHAR(30) NOT NULL,
+password VARCHAR(50) NOT NULL default 'invalid',
+real_name VARCHAR(60),
+comment VARCHAR(90),
+PRIMARY KEY (username)
+) TYPE=MyISAM;
+
+drop table if exists permissions;
+create table permissions (
+perm_name VARCHAR(30) NOT NULL,
+description VARCHAR(90),
+creator VARCHAR(30),
+PRIMARY KEY (perm_name)
+) TYPE=MyISAM;
+
+
+
+--INSERT INTO jobs (client, cliengroup, jobtype, priority, jobparam) VALUES ("boxa", "webserver", "pkgupdate", 2, "apache")
+--INSERT INTO jobs (client, cliengroup, jobtype, priority, jobparam) VALUES ("boxa", "webserver", "cfgupdate", 3, "scp://server/etc/apache2/httpd2.conf")
+--INSERT INTO jobs (client, cliengroup, jobtype, priority, jobparam) VALUES ("boxa", "webserver", "runscript", 4, "scp://server/etc/apache2/updatesomething.sh")
+
+drop table if exists jobs;
+create table jobs (
+job_id INT NOT NULL,
+client_id INT NOT NULL,
+jobtype VARCHAR(30) NOT NULL,
+priority INT NOT NULL default 5,
+jobparam VARCHAR(300),
+timecreated TIMESTAMP NOT NULL,
+timetosend TIMESTAMP NOT NULL,
+timesent TIMESTAMP,
+timedone TIMESTAMP,
+status VARCHAR(50) NOT NULL,
+created_by VARCHAR(30) NOT NULL,
+description VARCHAR(250),
+PRIMARY KEY (job_id)
+) TYPE=MyISAM;
+
+-- by Blackace
+DROP TABLE IF EXISTS sessions;
+CREATE TABLE sessions (
+ sessionid varchar(255) character set utf8 collate utf8_bin NOT NULL default '',
+ expiration int(10) unsigned NOT NULL default '0',
+ data text,
+ PRIMARY KEY (sessionid)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+drop table if exists user_preferences;
+
+grant all on moria.* to hobbit identified by 'hobbitpassword';
+grant all on moria.* to hobbit@localhost identified by 'hobbitpassword';
diff --git a/docs/moria2.sql b/docs/moria2.sql
new file mode 100644
index 0000000..6bb6439
--- /dev/null
+++ b/docs/moria2.sql
@@ -0,0 +1,23 @@
+use moria;
+INSERT INTO modules values (1,'GLIMD','Gentoo Linux Installation Mangement Daemon','Description goes here and all that good stuff.','glimd.txt','Preston Cody','gentoo','deployment','http://www.gentoo.org/proj/en/releng/gli/');
+INSERT INTO modules values (2,'Exporter','Server Information Exporter','This is a utility that will take selected data from the central server about machines and export it into an XML format.','Exporter.php','Preston Cody',NULL,'information','http://www.gentoo.org/proj/en/releng/gli/');
+
+INSERT INTO clients values (1, 'testhostlead', '00:0a:0b:0c:0d:0e', '192.168.3.4', 'printerserver', 'gentoo', 'Preston Cody', 'Installed');
+
+INSERT INTO clients values (2, 'testhostslave', '00:0a:0a:0a:0d:0e', '192.168.3.5', 'printerserver', 'gentoo', 'Preston Cody', 'Not Installed');
+
+INSERT INTO clients values (3, 'testhostmtalead', '0b:0b:0b:0c:0d:0e', '192.168.3.6', 'mta', 'gentoo', 'Preston Cody', 'Installed');
+
+INSERT INTO clients values (4, 'testhostmtaslave', '0c:0c:0c:0c:0d:0e', '192.168.3.7', 'mta', 'gentoo', 'Preston Cody', 'Installed');
+
+INSERT INTO profiles values ('printerserver', 'printerserverprofile.xml', 'Printer Servers use this profile', 'gentoo');
+
+INSERT INTO profiles values ('mta', 'mtaprofile.xml', 'MTAs use this profile', 'gentoo');
+
+INSERT INTO users values ('root','444mwGdhEKuO.','Root User');
+
+INSERT INTO jobs values (1, 1, 'Update', 5, 'emerge sync', NOW(), NOW(), NOW(), NOW(), 'Scheduled', 'root', 'Regular Update');
+INSERT INTO jobs values (2, 1, 'Install Packages', 5, 'emerge cups', NOW(), NOW(), NOW(), NOW(), 'In Progress', 'root', 'Adding cups');
+INSERT INTO jobs values (3, 2, 'Install Packages', 6, 'emerge cups', NOW(), NOW(), NOW(), NOW(), 'Failed', 'root', 'Adding cups');
+INSERT INTO jobs values (4, 3, 'Update', 2, 'glsa-check', NOW(), NOW(), NOW(), NOW(), 'In Progress', 'root', 'Security Update');
+INSERT INTO jobs values (5, 3, 'Install Packages', 5, 'emerge postrix', NOW(), NOW(), NOW(), NOW(), 'Scheduled', 'root', 'Adding postfix, cause its an mta duh.');
diff --git a/docs/phpgacl_seed.sql b/docs/phpgacl_seed.sql
new file mode 100644
index 0000000..f882df7
--- /dev/null
+++ b/docs/phpgacl_seed.sql
@@ -0,0 +1,104 @@
+use scire;
+--
+-- Dumping data for table `gacl_acl`
+--
+
+LOCK TABLES `gacl_acl` WRITE;
+/*!40000 ALTER TABLE `gacl_acl` DISABLE KEYS */;
+INSERT INTO `gacl_acl` VALUES (3,'system',1,1,'1','',1156105535),(14,'system',1,1,'1','',1175446075),(4,'system',1,1,'1','',1156105622),(1,'system',1,1,'1','',1156105457),(6,'system',1,1,'1','',1156041570),(7,'system',1,1,'1','',1175469155),(5,'system',1,1,'1','',1156105677),(9,'system',1,1,'1','',1174872568),(13,'system',1,1,'1','',1175444039),(15,'system',1,1,'1','',1175446991),(16,'system',1,1,'1','',1175447252),(17,'system',1,1,'1','',1175447319),(18,'system',1,1,'1','',1175449945),(19,'system',1,1,'1','',1175449997),(20,'system',1,1,'1','',1175451002),(21,'system',1,1,'1','',1175451021),(22,'system',1,1,'1','',1175451722),(23,'system',1,1,'1','',1175462168),(24,'system',1,1,'1','',1175469539);
+/*!40000 ALTER TABLE `gacl_acl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+LOCK TABLES `gacl_aco` WRITE;
+/*!40000 ALTER TABLE `gacl_aco` DISABLE KEYS */;
+INSERT INTO `gacl_aco` VALUES (13,'scire_ui','Edit User Info',1,'Edit User',0),(14,'scire_ui','Add User',1,'Add User',0),(15,'scire_ui','Add Client',1,'Add Client',0),(16,'scire_ui','View Clients',1,'View Clients',0),(17,'scire_ui','View Pending Clients',1,'View Pending Clients',0),(18,'scire_ui','Approve/Reject Pending Clients',1,'Approve/Reject Pending Clients',0),(19,'scire_ui','View Jobs',1,'View Jobs',0),(20,'scire_ui','Add Job',1,'Add Job',0),(22,'scire_ui','View Users',1,'View Users',0),(23,'Tests','Test Permission 1',1,'Test Permission 1',0),(24,'scire_ui','Add ClientGroup',1,'Add ClientGroup',0),(25,'scire_ui','Edit ClientGroup',1,'Edit ClientGroup',0),(26,'scire_ui','Delete ClientGroup',1,'Delete ClientGroup',0),(27,'scire_ui','Assign Permission',1,'Assign Permission',0),(28,'scire_ui','View Permissions',1,'View Permissions',0),(29,'scire_ui','Edit Client',1,'Edit Client',0),(30,'scire_ui','Delete Client',1,'Delete Client',0),(31,'scire_ui','Change User Pass/Name',1,'Change User Pass/Name',0),(32,'scire_ui','Add UserGroup',1,'Add UserGroup',0);
+/*!40000 ALTER TABLE `gacl_aco` ENABLE KEYS */;
+UNLOCK TABLES;
+LOCK TABLES `gacl_aco_map` WRITE;
+/*!40000 ALTER TABLE `gacl_aco_map` DISABLE KEYS */;
+INSERT INTO `gacl_aco_map` VALUES (1,'scire_ui','View Clients'),(3,'scire_ui','Approve/Reject Pending Clients'),(4,'scire_ui','View Jobs'),(5,'scire_ui','Add Job'),(6,'scire_ui','Add User'),(7,'scire_ui','Add Client'),(9,'scire_ui','View Users'),(13,'scire_ui','Add Client'),(14,'scire_ui','View Pending Clients'),(15,'scire_ui','Add ClientGroup'),(16,'scire_ui','Edit ClientGroup'),(17,'scire_ui','Delete ClientGroup'),(18,'scire_ui','Assign Permission'),(19,'scire_ui','View Permissions'),(20,'scire_ui','Edit Client'),(21,'scire_ui','Delete Client'),(22,'scire_ui','View Clients'),(23,'scire_ui','Change User Pass/Name'),(24,'scire_ui','Add UserGroup');
+/*!40000 ALTER TABLE `gacl_aco_map` ENABLE KEYS */;
+UNLOCK TABLES;
+LOCK TABLES `gacl_aco_sections` WRITE;
+/*!40000 ALTER TABLE `gacl_aco_sections` DISABLE KEYS */;
+INSERT INTO `gacl_aco_sections` VALUES (1,'scire_ui',1,'scire_ui',0),(3,'Tests',1,'Tests',0);
+/*!40000 ALTER TABLE `gacl_aco_sections` ENABLE KEYS */;
+UNLOCK TABLES;
+
+
+LOCK TABLES `gacl_aro` WRITE;
+/*!40000 ALTER TABLE `gacl_aro` DISABLE KEYS */;
+INSERT INTO `gacl_aro` VALUES (1,'users','root',0,'root',0),(2,'users','codeman',1,'codeman',0);
+/*!40000 ALTER TABLE `gacl_aro` ENABLE KEYS */;
+UNLOCK TABLES;
+
+
+LOCK TABLES `gacl_aro_map` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_map` DISABLE KEYS */;
+INSERT INTO `gacl_aro_map` VALUES (7,'users','codeman'),(14,'users','codeman'),(22,'users','codeman'),(24,'users','codeman');
+/*!40000 ALTER TABLE `gacl_aro_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+LOCK TABLES `gacl_aro_groups` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_groups` DISABLE KEYS */;
+INSERT INTO `gacl_aro_groups` VALUES (1,0,1,4,'Company Name','Company Name'),(3,1,2,3,'test','test');
+/*!40000 ALTER TABLE `gacl_aro_groups` ENABLE KEYS */;
+UNLOCK TABLES;
+
+
+LOCK TABLES `gacl_aro_groups_map` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_groups_map` DISABLE KEYS */;
+INSERT INTO `gacl_aro_groups_map` VALUES (1,1),(4,1),(9,1),(13,1),(14,1),(15,1),(16,1),(17,1),(18,1),(20,1),(21,1),(24,1);
+/*!40000 ALTER TABLE `gacl_aro_groups_map` ENABLE KEYS */;
+UNLOCK TABLES;
+LOCK TABLES `gacl_aro_sections` WRITE;
+/*!40000 ALTER TABLE `gacl_aro_sections` DISABLE KEYS */;
+INSERT INTO `gacl_aro_sections` VALUES (1,'users',1,'users',0);
+/*!40000 ALTER TABLE `gacl_aro_sections` ENABLE KEYS */;
+UNLOCK TABLES;
+
+
+
+
+LOCK TABLES `gacl_axo` WRITE;
+/*!40000 ALTER TABLE `gacl_axo` DISABLE KEYS */;
+INSERT INTO `gacl_axo` VALUES (1,'scire_ui','scire_ui',1,'scire_ui',0),(3,'clients','testclient',1,'testclient',0),(5,'clients','testclient2',1,'testclient2',0);
+/*!40000 ALTER TABLE `gacl_axo` ENABLE KEYS */;
+UNLOCK TABLES;
+LOCK TABLES `gacl_axo_groups` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_groups` DISABLE KEYS */;
+INSERT INTO `gacl_axo_groups` VALUES (1,0,1,2,'Company Name','Company Name');
+/*!40000 ALTER TABLE `gacl_axo_groups` ENABLE KEYS */;
+UNLOCK TABLES;
+LOCK TABLES `gacl_axo_map` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_map` DISABLE KEYS */;
+INSERT INTO `gacl_axo_map` VALUES (1,'scire_ui','scire_ui'),(3,'scire_ui','scire_ui'),(4,'scire_ui','scire_ui'),(5,'scire_ui','scire_ui'),(6,'scire_ui','scire_ui'),(7,'scire_ui','scire_ui'),(9,'scire_ui','scire_ui'),(13,'scire_ui','scire_ui'),(14,'scire_ui','scire_ui'),(15,'scire_ui','scire_ui'),(16,'scire_ui','scire_ui'),(17,'scire_ui','scire_ui'),(18,'scire_ui','scire_ui'),(19,'scire_ui','scire_ui'),(20,'scire_ui','scire_ui'),(21,'scire_ui','scire_ui'),(22,'scire_ui','scire_ui'),(23,'scire_ui','scire_ui'),(24,'scire_ui','scire_ui');
+/*!40000 ALTER TABLE `gacl_axo_map` ENABLE KEYS */;
+UNLOCK TABLES;
+LOCK TABLES `gacl_axo_sections` WRITE;
+/*!40000 ALTER TABLE `gacl_axo_sections` DISABLE KEYS */;
+INSERT INTO `gacl_axo_sections` VALUES (2,'clients',1,'clients',0),(1,'scire_ui',2,'scire_ui',0);
+/*!40000 ALTER TABLE `gacl_axo_sections` ENABLE KEYS */;
+UNLOCK TABLES;
+LOCK TABLES `gacl_groups_aro_map` WRITE;
+/*!40000 ALTER TABLE `gacl_groups_aro_map` DISABLE KEYS */;
+INSERT INTO `gacl_groups_aro_map` VALUES (1,1);
+/*!40000 ALTER TABLE `gacl_groups_aro_map` ENABLE KEYS */;
+UNLOCK TABLES;
+LOCK TABLES `gacl_groups_axo_map` WRITE;
+/*!40000 ALTER TABLE `gacl_groups_axo_map` DISABLE KEYS */;
+INSERT INTO `gacl_groups_axo_map` VALUES (1,3),(1,5);
+/*!40000 ALTER TABLE `gacl_groups_axo_map` ENABLE KEYS */;
+UNLOCK TABLES;
+
+-- SEQUENCES
+
+INSERT INTO `gacl_acl_seq` VALUES (24);
+INSERT INTO `gacl_aco_seq` VALUES (32);
+INSERT INTO `gacl_aco_sections_seq` VALUES (3);
+INSERT INTO `gacl_aro_groups_id_seq` VALUES (3);
+INSERT INTO `gacl_aro_sections_seq` VALUES (1);
+INSERT INTO `gacl_aro_seq` VALUES (3);
+INSERT INTO `gacl_axo_groups_id_seq` VALUES (2);
+INSERT INTO `gacl_axo_sections_seq` VALUES (3);
+INSERT INTO `gacl_axo_seq` VALUES (5);
diff --git a/docs/scire.conf b/docs/scire.conf
new file mode 100644
index 0000000..3f55d1d
--- /dev/null
+++ b/docs/scire.conf
@@ -0,0 +1,7 @@
+[db]
+type: mysql
+host: localhost
+db: scire
+user: hobbit
+passwd: moria
+
diff --git a/docs/scire.sql b/docs/scire.sql
new file mode 100644
index 0000000..6bd41ba
--- /dev/null
+++ b/docs/scire.sql
@@ -0,0 +1,551 @@
+CREATE DATABASE IF NOT EXISTS scire;
+GRANT SELECT, INSERT, UPDATE, DELETE, LOCK TABLES ON scire.* TO 'scire' IDENTIFIED BY 'scire';
+GRANT SELECT, INSERT, UPDATE, DELETE, LOCK TABLES ON scire.* TO 'scire'@'localhost' IDENTIFIED BY 'scire';
+ALTER DATABASE scire DEFAULT CHARACTER SET latin1;
+USE scire;
+
+DROP TABLE IF EXISTS users;
+CREATE TABLE users (
+ userid INT NOT NULL PRIMARY KEY,
+ username VARCHAR(64) NOT NULL UNIQUE,
+ password VARCHAR(255) NOT NULL,
+ email VARCHAR(128) NOT NULL,
+ phone VARCHAR(128) NULL,
+ pager VARCHAR(128) NULL,
+ real_name VARCHAR(255),
+ comment VARCHAR(255)
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS clients;
+CREATE TABLE clients (
+ clientid INT NOT NULL PRIMARY KEY,
+ assetid VARCHAR(64) UNIQUE,
+ digest VARCHAR(128) UNIQUE,
+ hostname VARCHAR(64) NOT NULL,
+ mac VARCHAR(17) NOT NULL,
+ ip VARCHAR(15) NOT NULL,
+ gli_profile INT,
+ osid INT,
+ status INT,
+ contact INT,
+ installtime TIMESTAMP NOT NULL DEFAULT NOW(), # date the clients first was set up
+ FOREIGN KEY (osid) REFERENCES os.osid,
+ FOREIGN KEY (status) REFERENCES client_status.statusid,
+ FOREIGN KEY (gli_profile) REFERENCES GLI_profiles.profileid,
+ FOREIGN KEY (contact) REFERENCES users.userid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS client_status;
+CREATE TABLE client_status (
+ statusid INT NOT NULL,
+ statusname VARCHAR(30),
+ PRIMARY KEY (statusid)
+) ENGINE = MyISAM;
+
+
+DROP TABLE IF EXISTS permissions;
+CREATE TABLE permissions (
+ permid INT NOT NULL PRIMARY KEY,
+ name VARCHAR(128) NOT NULL UNIQUE,
+ description VARCHAR(255),
+ permcategory VARCHAR(128) NOT NULL DEFAULT 'Default',
+ creator INT NOT NULL,
+ created TIMESTAMP NOT NULL DEFAULT NOW(),
+ FOREIGN KEY (creator) REFERENCES users.userid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS jobs;
+CREATE TABLE jobs (
+ jobid INT NOT NULL PRIMARY KEY,
+ priority INT NOT NULL DEFAULT 0,
+ created TIMESTAMP NOT NULL DEFAULT NOW(),
+ creator INT NOT NULL,
+ permission INT NOT NULL,
+ script INT NOT NULL,
+ description VARCHAR(255),
+ pending INT,
+ failed INT,
+ INDEX (creator),
+ FOREIGN KEY (creator) REFERENCES users.userid,
+ FOREIGN KEY (permission) REFERENCES permissions.permid,
+ FOREIGN KEY (script) REFERENCES scripts.scriptid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS job_history;
+CREATE TABLE job_history (
+ jobid INT NOT NULL,
+ clientid INT NOT NULL,
+ eventtime TIMESTAMP NOT NULL DEFAULT NOW(),
+ statusid INT NOT NULL,
+ eventmsg VARCHAR(255),
+ PRIMARY KEY (jobid, clientid, eventtime,statusid),
+ FOREIGN KEY (jobid) REFERENCES jobs.jobid,
+ FOREIGN KEY (clientid) REFERENCES clients.clientid,
+ FOREIGN KEY (statusid) REFERENCES jobs_status.statusid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS jobs_status;
+CREATE TABLE jobs_status (
+ statusid INT NOT NULL,
+ statusname VARCHAR(30),
+ PRIMARY KEY (statusid)
+) ENGINE = MyISAM;
+
+
+DROP TABLE IF EXISTS jobs_clients;
+CREATE TABLE jobs_clients (
+ jobid INT NOT NULL,
+ clientid INT,
+ groupid INT,
+ PRIMARY KEY (jobid, clientid, groupid),
+ FOREIGN KEY (jobid) REFERENCES jobs.jobid,
+ FOREIGN KEY (groupid) REFERENCES groups.gropuid,
+ FOREIGN KEY (clientid) REFERENCES clients.clientid
+) ENGINE = MyISAM;
+# Either clienid or groupid is required, if 1 is provided the other MUST be NULL
+
+DROP TABLE IF EXISTS recurring_jobs_clients;
+CREATE TABLE recurring_jobs_clients (
+ jobid INT NOT NULL,
+ clientid INT,
+ groupid INT,
+ PRIMARY KEY (jobid, clientid, groupid),
+ FOREIGN KEY (jobid) REFERENCES jobs.jobid,
+ FOREIGN KEY (groupid) REFERENCES groups.gropuid,
+ FOREIGN KEY (clientid) REFERENCES clients.clientid
+) ENGINE = MyISAM;
+# Either clienid or groupid is required, if 1 is provided the other MUST be NULL
+
+DROP TABLE IF EXISTS job_conditions;
+CREATE TABLE job_conditions (
+ jobid INT NOT NULL,
+ job_dependency INT,
+ deploy_time DATETIME,
+ expiration_time DATETIME,
+ run_schedule VARCHAR(255), #a cron-like string showing the schedule to run. min interval of 1 minute.
+ validity_period INT, # how many minutes will the job be available
+ last_run INT,
+ last_run_date DATETIME,
+# conditions here (TBD)
+# other types of dependencies:
+# right now time and proccess (other jobs)
+# might also include data (partition full?)
+
+ PRIMARY KEY (jobid),
+ FOREIGN KEY (jobid) REFERENCES jobs.jobid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS scripts;
+CREATE TABLE scripts (
+ scriptid INT NOT NULL PRIMARY KEY,
+ name VARCHAR(128) NOT NULL,
+ description VARCHAR(255),
+ location VARCHAR(255),
+ script_data TEXT,
+ log_location VARCHAR(255),
+ success_code VARCHAR(32),
+ run_as VARCHAR(255),
+ priority INT,
+ permission INT,
+ pp_location VARCHAR(255),
+ pp_script_data TEXT,
+ return_output INT DEFAULT 0,
+ FOREIGN KEY (permission) REFERENCES permissions.permid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS os;
+CREATE TABLE os (
+ osid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ osname VARCHAR(128) NOT NULL,
+ update_script INT,
+ install_script INT,
+ uninstall_script INT,
+ rollback_script INT,
+ packagelist_script INT,
+ FOREIGN KEY (update_script) REFERENCES scripts.scriptid,
+ FOREIGN KEY (install_script) REFERENCES scripts.scriptid,
+ FOREIGN KEY (uninstall_script) REFERENCES scripts.scriptid,
+ FOREIGN KEY (rollback_script) REFERENCES scripts.scriptid,
+ FOREIGN KEY (packagelist_script) REFERENCES scripts.scriptid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS sessions;
+CREATE TABLE sessions (
+ sessionid VARCHAR(255) NOT NULL DEFAULT '' PRIMARY KEY,
+ expiration INT(10) UNSIGNED NOT NULL DEFAULT '0',
+ data TEXT
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS settings;
+CREATE TABLE settings (
+ userid INT NOT NULL,
+ setting_name VARCHAR(64),
+ setting_value VARCHAR(255),
+ PRIMARY KEY (userid, setting_name),
+ FOREIGN KEY (userid) REFERENCES users.userid
+
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS hardware;
+CREATE TABLE hardware (
+ clientid INT NOT NULL PRIMARY KEY,
+ processor VARCHAR(32),
+ memory VARCHAR(32), # size of the installed memory in MB
+ hd VARCHAR(32), # size of harddisk in MB
+# partitions: data about the partitions
+ cpu VARCHAR(64), # type of cpu
+ mhz VARCHAR(32), # speed of the cpu
+# netcards: product names of the installed network cards
+# graficcard: information about the grafic card
+# soundcard: name of the sound card
+# isa: information about ISA components
+# dmi: DMI information
+# ram ,
+#.. steal the rest from Zen or m23
+ FOREIGN KEY (clientid) REFERENCES clients.clientid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS hardware_history;
+CREATE TABLE hardware_history (
+ clientid INT NOT NULL,
+ changedate TIMESTAMP NOT NULL DEFAULT NOW(),
+ field_name VARCHAR(30),
+ oldvalue VARCHAR(255),
+ newvalue VARCHAR(255),
+ PRIMARY KEY (clientid,changedate),
+ FOREIGN KEY (clientid) REFERENCES clients.clientid
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS software;
+CREATE TABLE software (
+ clientid INT NOT NULL,
+ package VARCHAR(128) NOT NULL PRIMARY KEY,
+ current_ver VARCHAR(64),
+ rollback_ver VARCHAR(64),
+ #dependencies
+ FOREIGN KEY (clientid) REFERENCES clients.clientid
+) ENGINE = MyISAM;
+
+
+
+DROP TABLE IF EXISTS GLI_profiles;
+CREATE TABLE GLI_profiles (
+ profileid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ profile_name VARCHAR(255) NOT NULL UNIQUE,
+ location VARCHAR(255) NOT NULL,
+ description VARCHAR(255)
+) ENGINE = MyISAM;
+
+DROP TABLE IF EXISTS dyn_tags;
+CREATE TABLE dyn_tags (
+ scriptid INT NOT NULL,
+ tag VARCHAR(30) NOT NULL,
+ tag_value VARCHAR(255),
+ PRIMARY KEY (scriptid, tag),
+ FOREIGN KEY (scriptid) REFERENCES scripts.scriptid
+) ENGINE = MyISAM;
+
+drop table if exists modules;
+create table modules (
+id INT NOT NULL default '0',
+name VARCHAR(50),
+long_name VARCHAR(150),
+description VARCHAR(250),
+path VARCHAR(90),
+author VARCHAR(50),
+distribution VARCHAR(50),
+category VARCHAR(30),
+homepage VARCHAR(90),
+PRIMARY KEY (id)
+) TYPE=MyISAM;
+
+
+#########PHPGACL CODE##########
+DROP TABLE IF EXISTS gacl_phpgacl;
+CREATE TABLE gacl_phpgacl (
+ name VARCHAR(230) NOT NULL,
+ value VARCHAR(230) NOT NULL,
+ PRIMARY KEY (name)
+);
+
+DELETE FROM gacl_phpgacl WHERE name='version';
+
+INSERT INTO gacl_phpgacl (name,value) VALUES ('version','3.3.6');
+
+DELETE FROM gacl_phpgacl WHERE name='schema_version';
+
+INSERT INTO gacl_phpgacl (name,value) VALUES ('schema_version','2.1');
+
+DROP TABLE IF EXISTS gacl_acl;
+CREATE TABLE gacl_acl (
+ id INTEGER NOT NULL DEFAULT 0,
+ section_value VARCHAR(230) NOT NULL DEFAULT 'system',
+ allow INTEGER NOT NULL DEFAULT 0,
+ enabled INTEGER NOT NULL DEFAULT 0,
+ return_value TEXT,
+ note TEXT,
+ updated_date INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (id)
+);
+
+ALTER TABLE gacl_acl ADD INDEX gacl_enabled_acl (enabled);
+
+ALTER TABLE gacl_acl ADD INDEX gacl_section_value_acl (section_value);
+
+ALTER TABLE gacl_acl ADD INDEX gacl_updated_date_acl (updated_date);
+
+DROP TABLE IF EXISTS gacl_acl_sections;
+CREATE TABLE gacl_acl_sections (
+ id INTEGER NOT NULL DEFAULT 0,
+ value VARCHAR(230) NOT NULL,
+ order_value INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(230) NOT NULL,
+ hidden INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (id)
+);
+
+ALTER TABLE gacl_acl_sections ADD UNIQUE INDEX gacl_value_acl_sections (value);
+
+ALTER TABLE gacl_acl_sections ADD INDEX gacl_hidden_acl_sections (hidden);
+
+DELETE FROM gacl_acl_sections WHERE id=1 AND value='system';
+
+INSERT INTO gacl_acl_sections (id,value,order_value,name) VALUES (1,'system',1,'System');
+
+DELETE FROM gacl_acl_sections WHERE id=2 AND value='user';
+
+INSERT INTO gacl_acl_sections (id,value,order_value,name) VALUES (2,'user',2,'User');
+
+DROP TABLE IF EXISTS gacl_aco;
+CREATE TABLE gacl_aco (
+ id INTEGER NOT NULL DEFAULT 0,
+ section_value VARCHAR(240) NOT NULL DEFAULT '0',
+ value VARCHAR(240) NOT NULL,
+ order_value INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(255) NOT NULL,
+ hidden INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (id)
+);
+
+ALTER TABLE gacl_aco ADD UNIQUE INDEX gacl_section_value_value_aco (section_value, value);
+
+ALTER TABLE gacl_aco ADD INDEX gacl_hidden_aco (hidden);
+
+DROP TABLE IF EXISTS gacl_aco_map;
+CREATE TABLE gacl_aco_map (
+ acl_id INTEGER NOT NULL DEFAULT 0,
+ section_value VARCHAR(230) NOT NULL DEFAULT '0',
+ value VARCHAR(230) NOT NULL,
+ PRIMARY KEY (acl_id, section_value, value)
+);
+
+DROP TABLE IF EXISTS gacl_aco_sections;
+CREATE TABLE gacl_aco_sections (
+ id INTEGER NOT NULL DEFAULT 0,
+ value VARCHAR(230) NOT NULL,
+ order_value INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(230) NOT NULL,
+ hidden INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (id)
+);
+
+ALTER TABLE gacl_aco_sections ADD UNIQUE INDEX gacl_value_aco_sections (value);
+
+ALTER TABLE gacl_aco_sections ADD INDEX gacl_hidden_aco_sections (hidden);
+
+DROP TABLE IF EXISTS gacl_aro;
+CREATE TABLE gacl_aro (
+ id INTEGER NOT NULL DEFAULT 0,
+ section_value VARCHAR(240) NOT NULL DEFAULT '0',
+ value VARCHAR(240) NOT NULL,
+ order_value INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(255) NOT NULL,
+ hidden INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (id)
+);
+
+ALTER TABLE gacl_aro ADD UNIQUE INDEX gacl_section_value_value_aro (section_value, value);
+
+ALTER TABLE gacl_aro ADD INDEX gacl_hidden_aro (hidden);
+
+DROP TABLE IF EXISTS gacl_aro_map;
+CREATE TABLE gacl_aro_map (
+ acl_id INTEGER NOT NULL DEFAULT 0,
+ section_value VARCHAR(230) NOT NULL DEFAULT '0',
+ value VARCHAR(230) NOT NULL,
+ PRIMARY KEY (acl_id, section_value, value)
+);
+
+DROP TABLE IF EXISTS gacl_aro_sections;
+CREATE TABLE gacl_aro_sections (
+ id INTEGER NOT NULL DEFAULT 0,
+ value VARCHAR(230) NOT NULL,
+ order_value INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(230) NOT NULL,
+ hidden INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (id)
+);
+
+ALTER TABLE gacl_aro_sections ADD UNIQUE INDEX gacl_value_aro_sections (value);
+
+ALTER TABLE gacl_aro_sections ADD INDEX gacl_hidden_aro_sections (hidden);
+
+DROP TABLE IF EXISTS gacl_axo;
+CREATE TABLE gacl_axo (
+ id INTEGER NOT NULL DEFAULT 0,
+ section_value VARCHAR(240) NOT NULL DEFAULT '0',
+ value VARCHAR(240) NOT NULL,
+ order_value INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(255) NOT NULL,
+ hidden INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (id)
+);
+
+ALTER TABLE gacl_axo ADD UNIQUE INDEX gacl_section_value_value_axo (section_value, value);
+
+ALTER TABLE gacl_axo ADD INDEX gacl_hidden_axo (hidden);
+
+DROP TABLE IF EXISTS gacl_axo_map;
+CREATE TABLE gacl_axo_map (
+ acl_id INTEGER NOT NULL DEFAULT 0,
+ section_value VARCHAR(230) NOT NULL DEFAULT '0',
+ value VARCHAR(230) NOT NULL,
+ PRIMARY KEY (acl_id, section_value, value)
+);
+
+DROP TABLE IF EXISTS gacl_axo_sections;
+CREATE TABLE gacl_axo_sections (
+ id INTEGER NOT NULL DEFAULT 0,
+ value VARCHAR(230) NOT NULL,
+ order_value INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(230) NOT NULL,
+ hidden INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (id)
+);
+
+ALTER TABLE gacl_axo_sections ADD UNIQUE INDEX gacl_value_axo_sections (value);
+
+ALTER TABLE gacl_axo_sections ADD INDEX gacl_hidden_axo_sections (hidden);
+
+DROP TABLE IF EXISTS gacl_aro_groups;
+CREATE TABLE gacl_aro_groups (
+ id INTEGER NOT NULL DEFAULT 0,
+ parent_id INTEGER NOT NULL DEFAULT 0,
+ lft INTEGER NOT NULL DEFAULT 0,
+ rgt INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(255) NOT NULL,
+ value VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id, value)
+);
+
+ALTER TABLE gacl_aro_groups ADD INDEX gacl_parent_id_aro_groups (parent_id);
+
+ALTER TABLE gacl_aro_groups ADD UNIQUE INDEX gacl_value_aro_groups (value);
+
+ALTER TABLE gacl_aro_groups ADD INDEX gacl_lft_rgt_aro_groups (lft, rgt);
+
+DROP TABLE IF EXISTS gacl_groups_aro_map;
+CREATE TABLE gacl_groups_aro_map (
+ group_id INTEGER NOT NULL DEFAULT 0,
+ aro_id INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (group_id, aro_id)
+);
+
+ALTER TABLE gacl_groups_aro_map ADD INDEX gacl_aro_id (aro_id);
+
+DROP TABLE IF EXISTS gacl_aro_groups_map;
+CREATE TABLE gacl_aro_groups_map (
+ acl_id INTEGER NOT NULL DEFAULT 0,
+ group_id INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (acl_id, group_id)
+);
+
+DROP TABLE IF EXISTS gacl_axo_groups;
+CREATE TABLE gacl_axo_groups (
+ id INTEGER NOT NULL DEFAULT 0,
+ parent_id INTEGER NOT NULL DEFAULT 0,
+ lft INTEGER NOT NULL DEFAULT 0,
+ rgt INTEGER NOT NULL DEFAULT 0,
+ name VARCHAR(255) NOT NULL,
+ value VARCHAR(255) NOT NULL,
+ PRIMARY KEY (id, value)
+);
+
+ALTER TABLE gacl_axo_groups ADD INDEX gacl_parent_id_axo_groups (parent_id);
+
+ALTER TABLE gacl_axo_groups ADD UNIQUE INDEX gacl_value_axo_groups (value);
+
+ALTER TABLE gacl_axo_groups ADD INDEX gacl_lft_rgt_axo_groups (lft, rgt);
+
+DROP TABLE IF EXISTS gacl_groups_axo_map;
+CREATE TABLE gacl_groups_axo_map (
+ group_id INTEGER NOT NULL DEFAULT 0,
+ axo_id INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (group_id, axo_id)
+);
+
+ALTER TABLE gacl_groups_axo_map ADD INDEX gacl_axo_id (axo_id);
+
+DROP TABLE IF EXISTS gacl_axo_groups_map;
+CREATE TABLE gacl_axo_groups_map (
+ acl_id INTEGER NOT NULL DEFAULT 0,
+ group_id INTEGER NOT NULL DEFAULT 0,
+ PRIMARY KEY (acl_id, group_id)
+);
+
+
+#########SEQUENCES (both PHPGACL and scire)##########
+DROP TABLE IF EXISTS `gacl_acl_seq`;
+CREATE TABLE `gacl_acl_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `gacl_aco_sections_seq`;
+CREATE TABLE `gacl_aco_sections_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `gacl_aco_seq`;
+CREATE TABLE `gacl_aco_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `gacl_aro_groups_id_seq`;
+CREATE TABLE `gacl_aro_groups_id_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `gacl_aro_sections_seq`;
+CREATE TABLE `gacl_aro_sections_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `gacl_aro_seq`;
+CREATE TABLE `gacl_aro_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `gacl_axo_groups_id_seq`;
+CREATE TABLE `gacl_axo_groups_id_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `gacl_axo_sections_seq`;
+CREATE TABLE `gacl_axo_sections_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+DROP TABLE IF EXISTS `gacl_axo_seq`;
+CREATE TABLE `gacl_axo_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+
+DROP TABLE IF EXISTS `jobs_seq`;
+CREATE TABLE `jobs_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+DROP TABLE IF EXISTS `scripts_seq`;
+CREATE TABLE `scripts_seq` (
+ `id` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
diff --git a/docs/scire2.sql b/docs/scire2.sql
new file mode 100644
index 0000000..4d6251c
--- /dev/null
+++ b/docs/scire2.sql
@@ -0,0 +1,47 @@
+use scire;
+
+INSERT INTO users (userid, username, password, email, phone, pager, real_name, comment) values (1, 'root','444mwGdhEKuO.', 'root@localhost.com', '', '', 'Root User', 'This is the comment for the root user.');
+INSERT INTO users (userid, username, password, email, phone, pager, real_name, comment) values (2, 'codeman','444mwGdhEKuO.', 'codeman@localhost.com', '', '', 'Preston Cody', 'Project lead and developer.');
+
+INSERT INTO client_status (statusid, statusname) values (1, 'Pending');
+INSERT INTO client_status (statusid, statusname) values (2, 'Active');
+INSERT INTO client_status (statusid, statusname) values (3, 'Inactive');
+INSERT INTO client_status (statusid, statusname) values (4, 'Rejected');
+INSERT INTO client_status (statusid, statusname) values (5, 'Retired');
+
+INSERT INTO jobs_status (statusid, statusname) values (1, 'Pending');
+INSERT INTO jobs_status (statusid, statusname) values (2, 'Downloaded');
+INSERT INTO jobs_status (statusid, statusname) values (3, 'Running');
+INSERT INTO jobs_status (statusid, statusname) values (4, 'Failed');
+INSERT INTO jobs_status (statusid, statusname) values (5, 'Finished');
+INSERT INTO jobs_status (statusid, statusname) values (6, 'Cancelled');
+
+INSERT INTO `permissions` VALUES (0,'View Users','Able to list the users',1,'2007-03-26 01:29:28','Default'),(23,'Test Permission 1','this is only a test.',1,'2007-03-26 02:20:40','Default'),(24,'Add ClientGroup','In the clients section, lets you add a group of clients.',2,'2007-04-01 17:03:11','Default'),(25,'Edit ClientGroup','Allows editing of the name and parent of a clientgroup.',2,'2007-04-01 17:07:32','Default'),(26,'Delete ClientGroup','deleting of a clientgroup. clients within move to parent.',2,'2007-04-01 17:08:39','Default'),(27,'Assign Permission','allows assigning permissions of users to clients. This is a very important permission!',2,'2007-04-01 17:52:25','Default'),(28,'View Permissions','see the list of active permissions.',2,'2007-04-01 17:53:17','Default'),(29,'Edit Client','edit client information.',2,'2007-04-01 18:10:02','Default'),(30,'Delete Client','remove a client.',2,'2007-04-01 18:10:21','Default'),(31,'Change User Pass/Name','If set, the ability to change a user\'s password will be enabled.',1,'2007-04-01 21:16:08','Default'),(32,'Add UserGroup','allows creation of usergroups.',1,'2007-04-01 23:18:59','Default');
+
+INSERT INTO `scripts` VALUES (100,'Gentoo Update Script','This script will run emerge sync and emerge -u world, logging the results.','','#!/bin/bash \n emerge sync \n emerge -u world','/var/log/scire/updatelog.txt','0','root',5,1,'','',0),(101,'Gentoo Install Package Script','This script will run emerge on a given package and log the results.','','#!/bin/bash\nemerge --nocolor --nospinner --quiet -u world','/var/log/scire/installlog.txt','0','root',2,1,'','',0),(102,'Gentoo Uninstall Package Script','This script will run emerge unmerge on a given package and log the results.','','#!/bin/bash \n emerge unmerge','/var/log/scire/uninstalllog.txt','0','root',2,1,'','',0),(103,'Gentoo Rollback Script','This script will roll back a given package to its previous version, logging the results.','','#!/bin/bash \n emerge -C && emerge ','/var/log/scire/rollbacklog.txt','0','root',1,1,'','',0),(104,'Gentoo PackageList Script','This script will return a list of packages installed on the system and the current version of those packages.','','#!/bin/bash \n %%tag1%% %%tag2%%','/var/log/scire/packagelistlog.txt','0','nobody',8,1,'','',0),(105,'install_vim','This will emerge vim for gentoo','Embedded','#!/bin/bash\r\nemerge vim\r\n ','','0','root',1,0,'Embedded','',0),(106,'install ufed','this installs ufed, a stupid little prog that helps with USE flags','Embedded','#!/bin/bash\r\nemerge ufed','','0','root',1,0,'Embedded','',0),(107,'get package list','lists all installed gentoo packages and their versions. stores this info in the DB', 'Embedded', '#!/bin/bash\r\nfind /var/db/pkg -mindepth 2 -maxdepth 2 -type d | sed \'s:^/var/db/pkg/::;s:-\([0-9.]\+.*$\,0):|\1:\'','','0','nobody',5,0,'get_package_list','',0);
+
+INSERT INTO os (osid, osname, update_script, install_script, uninstall_script, rollback_script, packagelist_script) values (1,'Gentoo Linux',100 ,101 ,102 ,103, 104 );
+
+INSERT INTO GLI_profiles (profileid, profile_name, location, description) values (1, 'printerserver', '/scire/gli_profiles/printerserver.xml', 'A typical printer server install profile. has like cups and shit.');
+INSERT INTO GLI_profiles (profileid, profile_name, location, description) values (2, 'mta', '/scire/gli_profiles/mta.xml', 'A typical MTA install profile. has like very little except mailers.');
+
+INSERT INTO `clients` VALUES (3,'ASSET02','sampledigest','testclient','00:01:02:03:04:0A','1.2.3.4',1,1,2,2,'0000-00-00 00:00:00'),(5,'ASSET05','testdigest','testclient2','00:01:02:03:04:05','192.168.1.11',1,1,2,1,'0000-00-00 00:00:00');
+
+INSERT INTO jobs (jobid, priority, created, creator, permission, script, description, pending, failed) values (1, 1, NOW(), 2, 1, 100, 'Upgrading a package on mtalead', 1,0);
+INSERT INTO jobs_clients (jobid, clientid) values (1, 3);
+INSERT INTO job_conditions (jobid, job_dependency, run_schedule, validity_period) values (1, 0, '*/15 * * * *', 4);
+INSERT INTO jobs_seq VALUES (10);
+INSERT INTO scripts_seq VALUES (10);
+
+
+INSERT INTO settings (userid, setting_name, setting_value) values (1, 'start_page', 'users.php');
+INSERT INTO settings (userid, setting_name, setting_value) values (1, 'theme', 'light_blue');
+INSERT INTO settings (userid, setting_name, setting_value) values (2, 'clients_page_fields', 'hostname,ip,profile_name,osname,username,installtime,status');
+
+
+#INSERT INTO jobs values (2, 1, 'Install Packages', 5, 'emerge cups', NOW(), NOW(), NOW(), NOW(), 3, 'root', 'Adding cups');
+#INSERT INTO jobs values (3, 2, 'Install Packages', 6, 'emerge cups', NOW(), NOW(), NOW(), NOW(), 4, 'root', 'Adding cups');
+#INSERT INTO jobs values (4, 3, 'Update', 2, 'glsa-check', NOW(), NOW(), NOW(), NOW(), 3, 'root', 'Security Update');
+#INSERT INTO jobs values (5, 3, 'Install Packages', 5, 'emerge postfix', NOW(), NOW(), NOW(), NOW(), 1, 'root', 'Adding postfix, cause its an mta duh.');
+#INSERT INTO modules values (1,'Quickstart','Quickstart Installation Mangement Daemon','Description goes here and all that good stuff.','quickstart/index.php','Preston Cody','gentoo','deployment','http://www.gentoo.org/proj/en/releng/gli/');
+#INSERT INTO modules values (2,'Exporter','Server Information Exporter','This is a utility that will take selected data from the central server about machines and export it into an XML format.','Exporter/index.php','Preston Cody',NULL,'information','http://www.gentoo.org/proj/en/releng/gli/');
diff --git a/docs/scire3.sql b/docs/scire3.sql
new file mode 100644
index 0000000..0f2007b
--- /dev/null
+++ b/docs/scire3.sql
@@ -0,0 +1,20 @@
+drop table if exists user_pref;
+create table user_pref (
+user_id INT NOT NULL,
+jobs_layout VARCHAR(250),
+jobs_fields VARCHAR(250),
+PRIMARY KEY (user_id)
+) Type=MyISAM;
+--example. user_id = 1234
+-- jobs_layout = csv of field_ids = "5,7,8,1,2,55,24"
+-- jobs_fields = csv of sort order+direction. 0 = not sorted. = "0a,0a,1d,3a,2d,0a,0a"
+
+drop table if exists jobs_fields;
+create table jobs_fields (
+field_id INT NOT NULL,
+field_name VARCHAR(50),
+field_desc VARCHAR(200),
+PRIMARY KEY (field_id)
+) Type=MyISAM;
+--example (5, "Priority", "Shows the priority of the job.")
+
diff --git a/docs/scire4.sql b/docs/scire4.sql
new file mode 100644
index 0000000..36c3a4c
--- /dev/null
+++ b/docs/scire4.sql
@@ -0,0 +1,7 @@
+DROP TABLE IF EXISTS `sessions`;
+CREATE TABLE `sessions` (
+ `sessionid` varchar(255) character set utf8 collate utf8_bin NOT NULL default '',
+ `expiration` int(10) unsigned NOT NULL default '0',
+ `data` text,
+ PRIMARY KEY (`sessionid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
diff --git a/docs/scire_client_backend_details.txt b/docs/scire_client_backend_details.txt
new file mode 100644
index 0000000..428d564
--- /dev/null
+++ b/docs/scire_client_backend_details.txt
@@ -0,0 +1,27 @@
+The client program will be made as simple as possible, keeping the duplication
+of code to a minimum while allowing full functional control of the client
+machine. The RPC calls that the client program will make will need to be
+locked with a semaphore because the program will have multiple processes. The
+client program can be run in two modes, daemon and normal. In daemon mode, the
+client will start the XMLRPC server and keep it active indefinitatly. This
+mode will accept poll_now requests from the scire server. In normal mode,
+there will be a process of steps that will execute and then the program will
+end.
+
+The program will fork off a subprocess to handle polling and downloading of
+jobs. This process will register and make an RPC call to the scire server
+asking for jobs. If the scire server replies with jobs it will download the
+XML file and save it in the queue. When done downloading all jobs, the
+polling process will sleep for the interval of the poll_interval variable.
+After that time if the main process is not currently making an RPC call, and
+the client program is still running, it will poll the scire server again for
+jobs. This procedure will continue as long as the program is running.
+
+The main thread will stat the queue directory after forking the polling
+subprocess. It will look in sorted order at the queue and if it finds a job it
+will take the highest priority, oldest job first. When the job is complete it
+will send an RPC call (or wait until it is able to) to the scire server
+updating the status of the job, and then stat the queue directory again and
+execute the next job (if there is one). In normal mode it will continue in
+this process until at least one poll/download has completed and there are no
+remaining jobs and then quit. In daemon mode it will continue until stopped.
diff --git a/docs/scire_server_backend_details.txt b/docs/scire_server_backend_details.txt
new file mode 100644
index 0000000..0bcdbc8
--- /dev/null
+++ b/docs/scire_server_backend_details.txt
@@ -0,0 +1,45 @@
+Scire Server Backend Design Details:
+
+Single points of failure:
+Database. workaround: db replication
+one server daemon. workaround: run multiple server daemons connecting to the
+same databse. The configuration scripts will be made to handle failing over
+from a primary server daemon to an alternate.
+
+On startup, the server will need to check and deal with the possibility that
+it needs to recover from failure. This could include making a query to check
+for jobs that are to be sent to client programs running in daemon mode.
+This could also include checking for jobs that were sent but did not return a
+response saying they were received.
+
+After recovery procedures, the server program will start the XMLRPC server
+(over a secure socket of course), register itself to the network, and await
+connections.
+
+If a client program is configured to run in daemon mode (which is not
+advised), and a job is "pushed" to a client, this is done by sending a small
+RPC to the client program demanding that it ask for work immediately rather
+than on its normal schedule.
+
+Clients will be able to register/connect to the XMLRPC server for many
+purposes. Most will be to either ask for work or to report the status of a
+job that was sent to a client.
+
+Asking for work:
+When a client program registers and makes a connection to the server, it will
+fork a thread on the server program for that client. Max-threads will be
+define-able if necessary. Inside the thread, a query will be made to the
+database to find jobs waiting to be sent to that client. All pending jobs
+will be then checked against the ACL for the correct permissions. If the
+check fails, update the status in the database and log accordingly. If the
+check passes, reply to the client RPC by creating an XML job file on the fly
+from the contents of the database row. Await a reply from the client that it
+received this job and is waiting for more jobs. Send more jobs accordingly.
+If the client does not reply saying it receives a message, ???
+
+Updating the status of a job:
+Don't know about threads here. May not be necessary. The client will connect
+and state the job id# and the status of that job in an XML file. The server
+program will parse and process the contents and update the database. The
+server program will then reply to the client acknowledging the receipt of the
+status message.
diff --git a/docs/screenshots/cron.jpg b/docs/screenshots/cron.jpg
new file mode 100644
index 0000000..06261ee
--- /dev/null
+++ b/docs/screenshots/cron.jpg
Binary files differ
diff --git a/docs/screenshots/edit_user.png b/docs/screenshots/edit_user.png
new file mode 100644
index 0000000..fddac41
--- /dev/null
+++ b/docs/screenshots/edit_user.png
Binary files differ
diff --git a/docs/screenshots/edit_user2.png b/docs/screenshots/edit_user2.png
new file mode 100644
index 0000000..d0507d8
--- /dev/null
+++ b/docs/screenshots/edit_user2.png
Binary files differ
diff --git a/docs/screenshots/login.png b/docs/screenshots/login.png
new file mode 100644
index 0000000..df154ff
--- /dev/null
+++ b/docs/screenshots/login.png
Binary files differ
diff --git a/docs/screenshots/user_addgroup.png b/docs/screenshots/user_addgroup.png
new file mode 100644
index 0000000..3d3cbf9
--- /dev/null
+++ b/docs/screenshots/user_addgroup.png
Binary files differ
diff --git a/docs/screenshots/user_assign_permission.png b/docs/screenshots/user_assign_permission.png
new file mode 100644
index 0000000..f11d8c1
--- /dev/null
+++ b/docs/screenshots/user_assign_permission.png
Binary files differ
diff --git a/docs/screenshots/users.png b/docs/screenshots/users.png
new file mode 100644
index 0000000..f377636
--- /dev/null
+++ b/docs/screenshots/users.png
Binary files differ
diff --git a/docs/screenshots/users_groups.png b/docs/screenshots/users_groups.png
new file mode 100644
index 0000000..3f912d7
--- /dev/null
+++ b/docs/screenshots/users_groups.png
Binary files differ
diff --git a/docs/screenshots/usertour/Users.png b/docs/screenshots/usertour/Users.png
new file mode 100644
index 0000000..6ebf6d9
--- /dev/null
+++ b/docs/screenshots/usertour/Users.png
Binary files differ
diff --git a/docs/screenshots/usertour/clients.png b/docs/screenshots/usertour/clients.png
new file mode 100644
index 0000000..5d0779f
--- /dev/null
+++ b/docs/screenshots/usertour/clients.png
Binary files differ
diff --git a/docs/screenshots/usertour/clients2.png b/docs/screenshots/usertour/clients2.png
new file mode 100644
index 0000000..2b9530d
--- /dev/null
+++ b/docs/screenshots/usertour/clients2.png
Binary files differ
diff --git a/docs/screenshots/usertour/clients_pending.png b/docs/screenshots/usertour/clients_pending.png
new file mode 100644
index 0000000..677bc08
--- /dev/null
+++ b/docs/screenshots/usertour/clients_pending.png
Binary files differ
diff --git a/docs/screenshots/usertour/clients_permissions.png b/docs/screenshots/usertour/clients_permissions.png
new file mode 100644
index 0000000..79cd75c
--- /dev/null
+++ b/docs/screenshots/usertour/clients_permissions.png
Binary files differ
diff --git a/docs/screenshots/usertour/delete_user.png b/docs/screenshots/usertour/delete_user.png
new file mode 100644
index 0000000..3e5bce9
--- /dev/null
+++ b/docs/screenshots/usertour/delete_user.png
Binary files differ
diff --git a/docs/screenshots/usertour/edit_user.png b/docs/screenshots/usertour/edit_user.png
new file mode 100644
index 0000000..8dc6d05
--- /dev/null
+++ b/docs/screenshots/usertour/edit_user.png
Binary files differ
diff --git a/docs/screenshots/usertour/login.png b/docs/screenshots/usertour/login.png
new file mode 100644
index 0000000..21104ce
--- /dev/null
+++ b/docs/screenshots/usertour/login.png
Binary files differ
diff --git a/docs/screenshots/usertour/settings.png b/docs/screenshots/usertour/settings.png
new file mode 100644
index 0000000..da004d0
--- /dev/null
+++ b/docs/screenshots/usertour/settings.png
Binary files differ
diff --git a/docs/screenshots/usertour/settings1.png b/docs/screenshots/usertour/settings1.png
new file mode 100644
index 0000000..e6b6dd1
--- /dev/null
+++ b/docs/screenshots/usertour/settings1.png
Binary files differ
diff --git a/docs/screenshots/usertour/settings_clients.png b/docs/screenshots/usertour/settings_clients.png
new file mode 100644
index 0000000..187a0c0
--- /dev/null
+++ b/docs/screenshots/usertour/settings_clients.png
Binary files differ
diff --git a/docs/screenshots/usertour/ui_perms.png b/docs/screenshots/usertour/ui_perms.png
new file mode 100644
index 0000000..37cd2c0
--- /dev/null
+++ b/docs/screenshots/usertour/ui_perms.png
Binary files differ
diff --git a/docs/screenshots/usertour/ui_perms_addperm.png b/docs/screenshots/usertour/ui_perms_addperm.png
new file mode 100644
index 0000000..92e2b77
--- /dev/null
+++ b/docs/screenshots/usertour/ui_perms_addperm.png
Binary files differ
diff --git a/docs/screenshots/usertour/user_addgroup.png b/docs/screenshots/usertour/user_addgroup.png
new file mode 100644
index 0000000..6aa2e5e
--- /dev/null
+++ b/docs/screenshots/usertour/user_addgroup.png
Binary files differ
diff --git a/docs/screenshots/usertour/user_assign_permission.png b/docs/screenshots/usertour/user_assign_permission.png
new file mode 100644
index 0000000..0495c19
--- /dev/null
+++ b/docs/screenshots/usertour/user_assign_permission.png
Binary files differ
diff --git a/docs/screenshots/usertour/users_addgroup.png b/docs/screenshots/usertour/users_addgroup.png
new file mode 100644
index 0000000..6ef30cc
--- /dev/null
+++ b/docs/screenshots/usertour/users_addgroup.png
Binary files differ
diff --git a/docs/screenshots/usertour/users_editgroup.png b/docs/screenshots/usertour/users_editgroup.png
new file mode 100644
index 0000000..718314f
--- /dev/null
+++ b/docs/screenshots/usertour/users_editgroup.png
Binary files differ
diff --git a/docs/screenshots/usertour/users_groups.png b/docs/screenshots/usertour/users_groups.png
new file mode 100644
index 0000000..1d51cab
--- /dev/null
+++ b/docs/screenshots/usertour/users_groups.png
Binary files differ
diff --git a/docs/screenshots/usertour/users_groups2.png b/docs/screenshots/usertour/users_groups2.png
new file mode 100644
index 0000000..b72f6a9
--- /dev/null
+++ b/docs/screenshots/usertour/users_groups2.png
Binary files differ
diff --git a/docs/screenshots/usertour/users_permissions.png b/docs/screenshots/usertour/users_permissions.png
new file mode 100644
index 0000000..2d31129
--- /dev/null
+++ b/docs/screenshots/usertour/users_permissions.png
Binary files differ
diff --git a/docs/server_be_job_transfer.txt b/docs/server_be_job_transfer.txt
new file mode 100755
index 0000000..cebe361
--- /dev/null
+++ b/docs/server_be_job_transfer.txt
@@ -0,0 +1,29 @@
+make DB connection
+
+Validate client_id and token.
+Client will also send a list of job_id's it already has. store as ids_client_already_has.
+
+query = "SELECT * FROM jobs WHERE client_id="+client_id+" and status='pending' ORDER BY priority"
+foreach row in results:
+ if job_id in ids_client_already_has: continue
+ Serialize job. keep in memory. as jobs[job_id]
+ write job to disk as XML. md5 it. store in memory as md5s[job_id]
+ push job_id onto list of jobs_to_send.
+
+while jobs_to_send:
+ pop current_job from jobs_to_send
+ send jobs[current_job]
+ send md5s[current_job]
+ wait a bit for a response... if timeout, push current_job back onto jobs_to_send.
+ if response == "BadMD5":
+ log event to error log.
+ push current_job onto jobs_to_send
+ # job will get resent the next time around.
+ # moves to bottom of queue incase it is a recurring problem
+ # so it doesn't hold up all the other jobs?
+ # this is OK because it will be resorted by priority on the client's end.
+ if response == "OK":
+ query = "UPDATE jobs SET status='received' WHERE job_id="+current_job
+ continue #move onto next job. This is in the client's hands now.
+
+close DB connection. \ No newline at end of file
diff --git a/scire/.lib/DB.php b/scire/.lib/DB.php
new file mode 100644
index 0000000..1cbdd24
--- /dev/null
+++ b/scire/.lib/DB.php
@@ -0,0 +1,232 @@
+<?php
+
+require_once($ADOdb_path . 'adodb-exceptions.inc.php');
+require_once($ADOdb_path . 'adodb.inc.php');
+
+class DB {
+ private $dbi;
+ private $error;
+
+
+ #######################################################################
+ function __construct($db_host, $db_username, $db_password, $db_name, $db_type) {
+
+
+ try {
+ $dbi = NewADOConnection($db_type);
+ $dbi->Connect($db_host, $db_username, $db_password, $db_name);
+ $dbi->SetFetchMode(ADODB_FETCH_ASSOC);
+ } catch (exception $e) {
+ print_r($e);
+ }
+ $this->dbi = $dbi;
+ }
+
+ #######################################################################
+ function __get($name) {
+ switch ($name) {
+ case 'error':
+ return $this->error;
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+
+ #######################################################################
+ function __set($name, $value) {
+ return false;
+ }
+
+ function __isset($name) {
+ switch ($name) {
+ case 'error':
+ if ($this->error && strlen($this->error) > 0) {
+ return true;
+ }
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+
+ #######################################################################
+ function __unset($name) {
+ return false;
+ }
+
+ # $table = 'table1' OR array('table1', 'table2')
+ # $select = '*' OR 'column1' OR array('column1', 'column2')
+ # $query = 'SELECT * FROM table WHERE column = \'value\' OR column = (SELECT * FROM table2 WHERE column = \'value\')'
+ # $set = array('setcolumn' => 'value')
+ # $update = array('updatecolumn' => 'value')
+ # $where = '`matchcolumn` = \'criteria\''
+ # insert($table, $set)
+ # update($table, $update)
+ # update($table, $update, $where)
+ # delete($table, $where)
+ # select($select, $table)
+ # select($select, $table, $where)
+ # select($query)
+
+ #######################################################################
+ function __call($method, $args) {
+ $dbi = $this->dbi;
+ #print "DEBUG: $method <BR>";
+ #print_r($args);
+
+ switch ($method) {
+ case 'insert':
+ try {
+ $result = $dbi->AutoExecute($args[0], $args[1], 'INSERT');
+ } catch (exception $e) {
+ print_r($e);
+ }
+ if (!$result) {
+ print $dbi->ErrorMsg();
+ return false;
+ } else {
+ return $result;
+ }
+ break;
+ case 'update':
+ try {
+ $result = $dbi->AutoExecute($args[0], $args[1], 'UPDATE', $args[2] );
+ } catch (exception $e) {
+ print_r($e);
+ }
+ if (!$result) {
+ print $dbi->ErrorMsg();
+ return false;
+ } else {
+ return $result;
+ }
+ break;
+
+ break;
+ case 'delete':
+ if ($args && count($args) == 2) {
+ $query = strtoupper($method);
+ $query .= ' FROM `' . $args[0] . '`';
+ $query .= ' WHERE ' . $args[1];
+ #print $query . "<BR>"; #for debugging.
+ try {
+ # $sql = $dbi->Prepare($query);
+ $recordSet = $dbi->Execute($query);
+ } catch (exception $e) {
+ print_r($e);
+ }
+ if (!$recordSet) {
+ print $dbi->ErrorMsg();
+ return false;
+ } else {
+ return $recordSet->RecordCount();
+ }
+ } else {
+ return false;
+ }
+ break;
+ case 'select':
+ if ($args && (count($args) >= 1 && count($args) <= 3)) {
+ if (count($args) == 1) {
+ $query = $args[0];
+ } else {
+ $query = strtoupper($method);
+ if (is_array($args[0])) {
+ foreach ($args[0] as $value) {
+ $query .= ' ' . $value . ', ';
+ }
+ } else {
+ $query .= '*';
+ }
+ $query = preg_replace('/, $/', '', $query);
+ $query .= ' FROM ' . $args[1] ;
+ if (count($args) == 3) {
+ $query .= ' WHERE ' . $args[2];
+ }
+ }
+ #print $query; #for debugging.
+ try {
+ $sql = $dbi->Prepare($query);
+ $recordSet = $dbi->Execute($sql);
+ } catch (exception $e) {
+ print_r($e);
+ }
+ if (!$recordSet) {
+ print $dbi->ErrorMsg();
+ return false;
+ } else {
+ $rows = array();
+ while (!$recordSet->EOF) {
+ $rows[] = $recordSet->fields;
+ $recordSet->MoveNext();
+ }
+ $recordSet->Close(); # optional
+ #print_r($rows);
+ return $rows;
+ }
+
+ } else {
+ return false;
+ }
+ break;
+
+ case 'query':
+ if (count($args) > 2) {
+ return false;
+ }
+
+ $query = $args[0];
+ #print $query . "<BR>"; #for debugging.
+ try {
+ $sql = $dbi->Prepare($query);
+ if (count($args) == 2) {
+ $recordSet = $dbi->Execute($sql,$args[1]);
+ } else {
+ $recordSet = $dbi->Execute($sql);
+ }
+ } catch (exception $e) {
+ print_r($e);
+ }
+ if (!$recordSet) {
+ print $dbi->ErrorMsg();
+ return false;
+ } else {
+ $rows = array();
+ while (!$recordSet->EOF) {
+ #print_r($recordSet->fields);
+ $rows[] = $recordSet->fields;
+ $recordSet->MoveNext();
+ }
+ $recordSet->Close(); # optional
+ return $rows;
+ }
+ break;
+
+ case 'get_next_id':
+ if (!$args[0]) {
+ return false;
+ }
+ try {
+ $id = $dbi->GenID($args[0],10); #Generate an ID for the table, start at 10 if not defined yet.
+ } catch (exception $e) {
+ print_r($e);
+ }
+ return $id;
+ case 'now':
+ try {
+ $time = $dbi->DBDate(time());
+ } catch (exception $e) {
+ print_r($e);
+ }
+ default:
+ $this->error = 'unknown method';
+ return false;
+ break;
+ }
+ }
+}
+
+?>
diff --git a/scire/.lib/DB_functions.php b/scire/.lib/DB_functions.php
new file mode 100755
index 0000000..1278552
--- /dev/null
+++ b/scire/.lib/DB_functions.php
@@ -0,0 +1,541 @@
+<?php
+
+function get_scire_modules() {
+ global $db;
+ $result = $db->select('*', 'modules');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_module_list() {
+ global $db;
+ $result = $db->select(array('main_content', 'name'), 'modules');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_profile_list() {
+ global $db;
+ $result = $db->select('profile_name', 'GLI_profiles');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_group_clients($group) {
+ global $db;
+ $result = $db->select('*', 'clients', '`gli_profile` = \'' . $group . '\'');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_clients($orderby, $direction, $status='Active') {
+ global $db;
+ if ($status == "All") {
+ $where = ""; #Don't filter on status.
+ } elseif ($status) {
+ $where = " WHERE cs.statusname='$status' ";
+ } else {
+ $where = " WHERE cs.statusname='Active' ";
+ }
+ if ($orderby) {
+ $where .= "ORDER BY `$orderby` $direction";
+ } else {
+ $where .= '';
+ }
+ $result = $db->select('SELECT c.clientid, c.assetid, c.digest, c.hostname, c.mac, c.ip, cs.statusname as status, c.installtime, p.profile_name, o.osname, u.username FROM clients AS c LEFT JOIN GLI_profiles AS p ON (c.gli_profile=p.profileid) LEFT JOIN os AS o ON (c.osid=o.osid) LEFT JOIN users AS u ON (c.contact=u.userid) LEFT JOIN client_status AS cs ON (c.status=cs.statusid) '.$where);
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_client($clientid) {
+ global $db;
+ $result = $db->select('*', 'clients', '`clientid` = \'' . $clientid . '\'');
+ if ($result && count($result) > 0) {
+ return $result[0];
+ } else {
+ return false;
+ }
+}
+
+function get_client_statuses() {
+ global $db;
+ $result = $db->select('*', 'client_status');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function scire_add_client($clientid, $digest, $hostname, $mac, $ip, $profileid, $osid, $contact, $status, $installtime, $assetid) {
+#clientid, assetid, digest, cert, hostname, mac, ip, gli_profile, osid, status, contact, installtime
+ if (!$installtime) {$installtime = $db->now(); }
+ global $db;
+ #we need to add the client to the axo table first and then to the clients
+ $result = $db->insert('clients', array('clientid' => $clientid, 'digest' => $digest, 'hostname' => $hostname, 'mac' => $mac, 'ip' => $ip, 'gli_profile' => $profileid, 'osid' => $osid, 'contact' => $contact, 'status' => $status, 'installtime' => $installtime, 'assetid' => $assetid));
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_edit_client($clientid, $fields) {
+ global $db;
+ if (isset($fields['status'])) {
+ $res = $db->select(array('statusid'), 'client_status', '`statusname` = \'' . $fields['status'] . '\'');
+ var_dump($res);
+ if ($res && count($res)>0)
+ $fields['status'] = $res[0]['statusid'];
+ else
+ unset($fields['status']);
+ }
+ $result = $db->update('clients', $fields, "`clientid` = $clientid");
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_del_client($client_id) {
+ global $db;
+ $result = $db->delete('clients', "`clientid` = $client_id");
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function get_scire_users($orderby, $direction) {
+ #we don't want to store the password for security reasons. <- ???
+ global $db;
+ if ($orderby) {
+ $where = "1 ORDER BY `$orderby` $direction";
+ } else {
+ $where = '1';
+ }
+ $result = $db->select(array('userid', 'username', 'comment', 'real_name'), 'users', $where);
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_user($userid) {
+ global $db;
+ $result = $db->select('*', 'users', '`userid` = ' . $userid . '');
+ if ($result && count($result) > 0) {
+ return $result[0];
+ } else {
+ return false;
+ }
+}
+
+function scire_add_user($userid, $username, $password, $real_name, $comment, $email, $phone, $pager) {
+ global $db;
+ $result = $db->insert('users', array('userid' => $userid, 'username' => $username, 'password' => crypt($password, 447470567), 'comment' => $comment, 'real_name' => $real_name, 'email' => $email, 'phone' => $phone, 'pager' => $pager));
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_edit_user($userid, $fields) {
+ global $db;
+ $result = $db->update('users', $fields, '`userid` = \'' . $userid . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_del_user($userid) {
+ global $db;
+ $result = $db->delete('users', '`userid` = \'' . $userid . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_add_permission($permid, $perm_name, $desc, $created_by) {
+ global $db;
+ $result = $db->insert('permissions', array('permid' => $permid, 'name' => $perm_name, 'description' => $desc, 'creator' => $created_by));
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_edit_permission($perm_name, $desc) {
+ global $db;
+ $result = $db->update('permissions', array('description' => $desc), '`perm_name` = \'' . $perm_name . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_del_permission($perm_name) {
+ global $db;
+ $result = $db->delete('permissions', '`perm_name` = \'' . $perm_name . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function get_scire_permissions() {
+ global $db;
+ $result = $db->select('*', 'permissions');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_permission_by_name($permname) {
+ global $db;
+ $result = $db->select('*', 'permissions', "`name` = '$permname'");
+ if ($result && count($result) > 0) {
+ return $result[0];
+ } else {
+ return false;
+ }
+
+}
+function get_scire_ui_permissions() {
+ global $db;
+ $result = $db->select('*', 'permissions', "`permcategory` = 'scire_ui'");
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_gli_profiles() {
+ global $db;
+ $result = $db->select(array('profile_name','profileid'), 'GLI_profiles');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_oss() {
+ global $db;
+ $result = $db->select(array('osname','osid'), 'os');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_script($scriptid) {
+ global $db;
+ $scriptid = (int) $scriptid;
+ $result = $db->select('*', 'scripts', "`scriptid` = $scriptid");
+ if ($result && count($result) > 0) {
+ return $result[0];
+ } else {
+ return false;
+ }
+}
+
+function get_scire_scripts() {
+ global $db;
+ $result = $db->select('*', 'scripts');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_settings($userid) {
+ global $db;
+ $result = $db->select('*', 'settings', "`userid` = $userid");
+ if ($result && count($result) > 0) {
+ $result2 = array();
+ foreach($result as $row) {
+ $result2[$row['setting_name']] = $row['setting_value'];
+ }
+ return $result2;
+ } else {
+ return array();
+ }
+}
+
+function scire_set_setting($userid, $name, $value) {
+ global $db;
+ $result = $db->update('settings',array('setting_value' => $value), "`userid` = '$userid' AND `setting_name`='$name'");
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_add_setting($userid, $name, $value) {
+ global $db;
+ $result = $db->insert('settings',array('userid' => $userid, 'setting_name' => $name, 'setting_value' => $value ));
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_approve_client($clientid) {
+ global $db;
+ $clientid = (int) $clientid;
+ $res = $db->select(array('statusid'), 'client_status', '`statusname` = \'Active\'');
+
+ if ($clientid) {
+ $result = $db->update('clients',array('status' => $res[0]['statusid']), "`clientid` = '$clientid'");
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+ } else {
+ return false;
+ }
+}
+
+function scire_reject_client($clientid) {
+ global $db;
+ if (int($clientid) != $clientid) {return false;}
+ $res = $db->select(array('statusid'), 'client_status', '`statusname` = \'Rejected\'');
+
+ $result = $db->update('clients',array('status' => $res[0]['statusid']), "`clientid` = '$clientid'");
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_add_job($script, $priority, $creator, $permission, $description, $pending, $clients, $clientgroups, $job_dependency, $run_schedule, $validity_period) {
+ global $db;
+ #First make the job id
+ $jobid = $db->get_next_id('jobs_seq');
+ print "Got a Job ID, it is $jobid <br>";
+ $result = $db->insert('jobs', array('jobid' => $jobid, 'script' => $script, 'priority' => $priority, 'created' => $db->now(), 'creator' => $creator, 'permission' => $permission, 'description' => $description, 'pending' => $pending ));
+ if (!$result) {
+ return $db->error;
+ }
+
+ if ($run_schedule != "") {
+ print "Run schedule is $run_schedule<br>";
+ $cron = new CronParser($run_schedule);
+ $nextRun = $cron->calculateNextRun();
+ var_dump($nextRun);
+ $nextRun = mktime( $nextRun[1], $nextRun[0], 0, $nextRun[3], $nextRun[2], $nextRun[4] );
+ $expTime = $nextRun + ( $validity_period * 60);
+ $nextRun = strftime( '%Y-%m-%d %T', $nextRun );
+ $expTime = strftime( '%Y-%m-%d %T', $expTime );
+ } else {
+ $nextRun = strftime( '%Y-%m-%d %T', time());
+ $expTime = "";
+ }
+ # Add conditions
+ $result = $db->insert('job_conditions', array('jobid' => $jobid, 'job_dependency' => $job_dependency, 'run_schedule' => $run_schedule, 'deploy_time' => $nextRun, 'expiration_time' => $expTime, 'validity_period' => $validity_period));
+ if (!$result) {
+ return $db->error;
+ }
+
+ # Add history entry only if the job is assigned to a specific
+ # client. Managing groups require a different approach
+ #Now add the clients.
+ $status = get_statusid('Pending');
+ if ($clients) {
+ foreach ($clients as $client) {
+ $result = $db->insert('job_history', array('jobid' => $jobid, 'clientid' => $client,
+ 'statusid' => $status,
+ 'eventmsg' => 'Job created'));
+ if (!$result) {
+ return $db->error;
+ }
+ $result = $db->insert('jobs_clients', array('jobid' => $jobid, 'clientid' => $client));
+ if (!$result) {
+ return $db->error;
+ }
+ if ($run_schedule != "") {
+ $result = $db->insert('recurring_jobs_clients', array('jobid' => $jobid, 'clientid' => $client));
+ if (!$result) {
+ return $db->error;
+ }
+ }
+ }
+ }
+
+ if ($clientgroups) {
+ foreach ($clientgroups as $cgroup) {
+ $result = $db->insert('jobs_clients', array('jobid' => $jobid, 'groupid' => $cgroup));
+ if (!$result) {
+ return $db->error;
+ }
+ if ($run_schedule != "") {
+ $result = $db->insert('recurring_jobs_clients', array('jobid' => $jobid, 'groupid' => $cgroup));
+ if (!$result) {
+ return $db->error;
+ }
+ }
+ }
+ }
+ return 0; #Success
+}
+
+function get_scire_jobs($orderby, $direction, $status='Pending') {
+ global $db;
+
+ if ($status == "All") {
+ $where = ""; #Don't filter on pending status.
+ } elseif ($status == "Pending") {
+ $where = " AND j.pending > 0 ";
+ } else {
+ $where = " ";
+ }
+ if ($orderby) {
+ $where .= " ORDER BY `$orderby` $direction";
+ } else {
+ $where .= '';
+ }
+
+ $result = $db->select('SELECT j.*,jc.groupid,c.hostname,s.name as scriptname, u.username, p.name as permname '.
+ 'FROM jobs AS j '.
+ 'JOIN jobs_clients AS jc ON (j.jobid=jc.jobid) '.
+ 'JOIN clients AS c ON (jc.clientid=c.clientid) '.
+ 'LEFT JOIN scripts AS s ON (j.script=s.scriptid) '.
+ 'JOIN users AS u ON (j.creator=u.userid) '.
+ 'LEFT JOIN permissions AS p ON (j.permission=p.permid) '.
+ ' '.$where);
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_job($jobid) {
+ global $db;
+ # Falta el job history y el job clients
+ $result = $db->select('SELECT j.jobid, j.priority, j.script, j.description, u.username as creator, p.name as permission, jc.validity_period, jc.run_schedule ' .
+ 'FROM jobs AS j '.
+ 'JOIN users AS u ON (j.creator=u.userid) '.
+ 'LEFT JOIN job_conditions AS jc ON (j.jobid=jc.jobid) '.
+ 'LEFT JOIN permissions AS p ON (j.permission=p.permid) '.
+ ' WHERE j.jobid=\'' . (int) $jobid . '\'');
+ if ($result && count($result) > 0) {
+ return $result[0];
+ } else {
+ return false;
+ }
+}
+
+function scire_edit_job($jobid, $fields) {
+ global $db;
+ $jobConditions = array();
+ if (isset($fields["run_schedule"])) {
+ $jobConditions["run_schedule"] = $fields["run_schedule"];
+ unset($fields["run_schedule"]);
+ }
+ if (isset($fields["validity_period"])) {
+ $jobConditions["validity_period"] = $fields["validity_period"];
+ unset($fields["validity_period"]);
+ }
+ $result = $db->update('jobs', $fields, '`jobid` = \'' . $jobid . '\'');
+
+ if (count($jobConditions) > 0) {
+ $result = $result && $db->update('job_conditions', $jobConditions, '`jobid` = \'' . $jobid . '\'');
+ }
+
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function get_statusid($statusname) {
+ global $db;
+ $name = htmlentities($statusname);
+ $result = $db->select('SELECT statusid FROM jobs_status WHERE statusname = \'' . $name . '\'');
+
+ if ($result) {
+ var_dump( $result[0]['statusid'] );
+
+ return $result[0]['statusid'];
+ }
+ else {
+ return $db->error;
+ }
+}
+
+function scire_add_script($name, $desc, $location, $script_data, $log_location, $success_code, $run_as, $priority, $permission, $pp_location, $pp_script_data, $script_tags) {
+ global $db;
+ # First make the script ID
+ $scriptid = $db->get_next_id('scripts_seq');
+ print "Got a Script ID, it is $scriptid<br>";
+
+ $result = $db->insert('scripts', array('scriptid' => $scriptid, 'name' => $name, 'description' => $desc, 'location' => $location, 'script_data' => $script_data, 'log_location' => $log_location, 'success_code' => $success_code, 'run_as' => $run_as, 'priority' => $priority, 'permission' => $permission, 'pp_location' => $pp_location, 'pp_script_data' => $pp_script_data ));
+ if (!$result) {
+ return $db->error;
+ }
+
+ #Now add the tags.
+ if ($script_tags) {
+ foreach ($script_tags as $name => $value) {
+ $result = $db->insert('dyn_tags', array('scriptid' => $scriptid, 'tag' => $name, 'tag_value' => $value) );
+ if (!$result) {
+ return $db->error;
+ }
+ }
+ }
+
+ return 0; #Success
+}
+
+function get_dyn_tag_value($scriptid,$tag) {
+ global $db;
+ $scriptid = (int) $scriptid;
+ $result = $db->select('tag_value', 'dyn_tags', "`scriptid` = $scriptid AND `tag` = '$tag'");
+ if ($result && count($result) > 0) {
+ return $result[0]['tag_value'];
+ } else {
+ return false;
+ }
+}
+
+
+
+?>
diff --git a/scire/.lib/Session.php b/scire/.lib/Session.php
new file mode 100644
index 0000000..af12d18
--- /dev/null
+++ b/scire/.lib/Session.php
@@ -0,0 +1,116 @@
+<?php
+
+class Session {
+ private $db;
+ private $table;
+ private $maxidle;
+ private $error;
+ function __construct($db, $table) {
+ $this->db = $db;
+ $this->table = $table;
+ session_set_save_handler(array(&$this, '_open'), array(&$this, '_close'), array(&$this, '_read'), array(&$this, '_write'), array(&$this, '_destroy'), array(&$this, '_gc'));
+ session_start();
+ }
+ function __destruct() {
+ session_write_close();
+ }
+ function __get($name) {
+ switch ($name) {
+ case 'error':
+ return $this->error;
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+ function __set($name, $value) {
+ return false;
+ }
+ function __isset($name) {
+ switch ($name) {
+ case 'error':
+ if ($this->error && strlen($this->error) > 0) {
+ return true;
+ }
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+ function __unset($name) {
+ return false;
+ }
+ function _open($savepath, $sname) {
+ #$this->maxidle = get_cfg_var('session.gc_maxlifetime');
+ $this->maxidle = 3600;
+ }
+ function _close() {
+ $this->_gc($this->maxidle);
+ }
+ function _read($sid) {
+ $result = $this->db->select(array('data'), $this->table, '`sessionid` = \'' . $sid . '\' AND `expiration` > \'' . time() . '\'');
+ if ($result && (count($result) > 0 && array_key_exists('data', $result[0]))) {
+ return $result[0]['data'];
+ } else {
+ $this->error = $this->db->error;
+ return '';
+ }
+ }
+ function _write($sid, $sdata) {
+ $expiration = time() + $this->maxidle;
+ $result = $this->db->query("INSERT INTO `".$this->table."` (`sessionid`,`expiration`, `data`) VALUES (?,?,?) ON DUPLICATE KEY UPDATE `expiration`=?, `data`=?", array($sid, $expiration, $sdata, $expiration, $sdata) );
+ #$result = $this->db->insert($this->table, array('sessionid' => $sid, 'expiration' => $expiration, 'data' => $sdata), array('expiration' => $expiration, 'data' => $sdata));
+ if ($result) {
+ return true;
+ } else {
+ $this->error = $this->db->error;
+ return false;
+ }
+ }
+ function _destroy($sid) {
+ $username = '';
+ $result = $this->db->select(array('data'), $this->table, '`sessionid` = \'' . $sid . '\'');
+ if ($result && (count($result) > 0 && array_key_exists('data', $result[0]))) {
+ if (preg_match('/^.*username\|s:[0-9]+:"([^"]+)".*$/', $result[0]['data'], $matches)) {
+ $username = $matches[1];
+ }
+ }
+ $result = $this->db->delete($this->table, '`sessionid` = \'' . $sid . '\'');
+ if ($result) {
+ if (strlen($username) > 0) {
+ $result = $this->db->delete($this->table, '`data` regexp \'^.*username\|s:[0-9]+:"' . $username . '".*$\'');
+ if ($result) {
+ return true;
+ } else {
+ $this->error = $this->db->error;
+ return false;
+ }
+ } else {
+ return true;
+ }
+ } else {
+ $this->error = $this->db->error;
+ return false;
+ }
+ }
+ function _gc($smaxidle) {
+ $result = $this->db->delete($this->table, '`expiration` < \'' . time() . '\'');
+ if ($result) {
+ return true;
+ } else {
+ $this->error = $this->db->error;
+ return false;
+ }
+ }
+ function destroy() {
+ $_SESSION = array();
+ if (isset($_COOKIE[session_name()])) {
+ setcookie(session_name(), '', time()-420000, '/');
+ }
+ session_destroy();
+ }
+}
+
+?>
diff --git a/scire/.lib/common.php b/scire/.lib/common.php
new file mode 100644
index 0000000..032597f
--- /dev/null
+++ b/scire/.lib/common.php
@@ -0,0 +1,73 @@
+<?php
+
+$CONFIG_DIR='/etc/scire';
+
+# Validate the path if it exists.
+if (isset($path)) {
+ if ($path != "../") {
+ header('Content-type: text/html; charset=UTF-8');
+ $smarty->assign('title', 'Path Error');
+ $smarty->assign('message', 'invalid path. stop trying to hack me you mofo!');
+ $smarty->display('message.tpl');
+ exit(0);
+ }
+} else {
+ $path = "";
+}
+
+# Configuration
+
+require_once($CONFIG_DIR.'/config.php');
+
+# Functions
+require_once('functions.php');
+
+# Clean config
+$basedir = normalize_path($basedir);
+$baseurl = normalize_path($baseurl);
+$smarty_dir = normalize_path($smarty_dir);
+
+# Smarty
+require_once('smarty.php');
+
+# Database class
+require_once('DB.php');
+$db = new DB($db_host, $db_username, $db_password, $db_name, $db_type);
+if (isset($db->error)) {
+ header('Content-type: text/html; charset=UTF-8');
+ $smarty->assign('title', 'Database Error');
+ $smarty->assign('message', $db->error);
+ $smarty->display('message.tpl');
+ exit(0);
+}
+
+# Database functions
+require_once('DB_functions.php');
+
+# Session class
+require_once('Session.php');
+$session = new Session($db, $db_sessions_table);
+if (isset($session->error)) {
+ header('Content-type: text/html; charset=UTF-8');
+ $smarty->assign('title', 'Session Error');
+ $smarty->assign('message', $session->error);
+ $smarty->display('message.tpl');
+ exit(0);
+}
+
+# ACL class
+require_once('phpGACL.php');
+
+# Check login
+if (!isset($_SESSION['username'])) {
+ header('Location: ' . $baseurl . 'login.php?afterlogin=' . urlencode($_SERVER['REQUEST_URI']));
+ exit(0);
+} else {
+ $smarty->assign('userid', $_SESSION['userid']);
+ $smarty->assign('username', $_SESSION['username']);
+ $smarty->assign('useremail', $_SESSION['useremail']);
+ #Set Theme
+ $smarty->assign('theme', $_SESSION['settings']['theme']);
+}
+
+?>
diff --git a/scire/.lib/config.php.example b/scire/.lib/config.php.example
new file mode 100644
index 0000000..f9b4674
--- /dev/null
+++ b/scire/.lib/config.php.example
@@ -0,0 +1,25 @@
+<?php
+
+# Base directory
+$basedir = '/var/www/localhost/htdocs/scire/';
+
+# Base URL
+$baseurl = '/scire/';
+
+# Database
+$db_name = 'scire';
+$db_host = 'localhost';
+$db_username = 'USERNAME GOES HERE';
+$db_password = 'PASSWORD GOES HERE';
+$db_sessions_table = 'sessions';
+
+# ADOdb path
+$ADOdb_path = '/usr/share/php5/adodb/';
+$db_type = 'mysql';
+
+# Smarty directory
+$smarty_dir = '/usr/share/php/smarty/';
+
+# Permissions filter
+$scire_ui_section = "scire_ui";
+?>
diff --git a/scire/.lib/functions.php b/scire/.lib/functions.php
new file mode 100644
index 0000000..7a1996f
--- /dev/null
+++ b/scire/.lib/functions.php
@@ -0,0 +1,147 @@
+<?php
+
+function normalize_path($path) {
+ if ($path && strlen($path) > 0) {
+ return preg_replace('/^(.*?)[\/]?$/', '$1/', $path);
+ } else {
+ return $path;
+ }
+}
+
+function dumper($var) {
+ ob_start();
+ var_dump($var);
+ return ob_get_clean();
+}
+
+function pre_var_dump($var) {
+ print "<pre>";
+ var_dump($var);
+ print "</pre>";
+}
+
+function add_leftbar(&$leftbar_menu, $entry_name, $entry_link) {
+ $temp_menu_entry['name'] = $entry_name;
+ $temp_menu_entry['link'] = $entry_link;
+ array_push($leftbar_menu, $temp_menu_entry);
+}
+
+function get_clients_fields() {
+ $fields['hostname'] = array('name' => 'Hostname', 'sortable' => True);
+ $fields['ip'] = array('name' => 'IP Address', 'sortable' => True);
+ $fields['mac'] = array('name' => 'MAC Address', 'sortable' => True);
+ $fields['digest'] = array('name' => 'Cert Digest', 'sortable' => False);
+ $fields['profile_name'] = array('name' => 'GLI Profile', 'sortable' => True);
+ $fields['osname'] = array('name' => 'OS Name', 'sortable' => True);
+ $fields['username'] = array('name' => 'User Contact', 'sortable' => True);
+ $fields['installtime'] = array('name' => 'Install Time', 'sortable' => True);
+ $fields['status'] = array('name' => 'Status', 'sortable' => True);
+ $fields['groups'] = array('name' => 'Client Groups', 'sortable' => False);
+ return $fields;
+}
+
+function get_default_clients_fields() {
+ return 'hostname,ip,profile_name,osname,username,status,groups';
+}
+
+function get_users_fields() {
+ $fields['username'] = array('name' => 'Username', 'sortable' => True);
+ $fields['real_name'] = array('name' => 'Real Name', 'sortable' => True);
+ $fields['comment'] = array('name' => 'Comment', 'sortable' => False);
+ $fields['status'] = array('name' => 'Status', 'sortable' => True);
+ $fields['groups'] = array('name' => 'User Groups', 'sortable' => False);
+ return $fields;
+}
+
+function get_default_users_fields() {
+ return 'username,real_name,comment,status,groups';
+}
+
+function get_jobs_fields() {
+ $fields['hostname'] = array('name' => 'Hostname', 'sortable' => True);
+ $fields['priority'] = array('name' => 'Priority', 'sortable' => True);
+ $fields['created'] = array('name' => 'Created', 'sortable' => True);
+ $fields['username'] = array('name' => 'Created By', 'sortable' => True);
+ $fields['scriptname'] = array('name' => 'Script Name', 'sortable' => True);
+ $fields['pending'] = array('name' => '# Pending', 'sortable' => True);
+ $fields['failed'] = array('name' => '# Failed', 'sortable' => True);
+ $fields['permname'] = array('name' => 'Permission', 'sortable' => True);
+ $fields['description'] = array('name' => 'Description', 'sortable' => False);
+ return $fields;
+}
+
+function get_default_jobs_fields() {
+ return 'hostname,scriptname,priority,created,permname,pending,failed';
+}
+
+function get_priorities() {
+ return array('1','2','3','4','5','6','7','8','9');
+}
+
+function get_cron_times() {
+ # Minutes array
+ $minutes = array(
+# "*" => "Every minute",
+# "*/2" => "Every other minute",
+ "*/5" => "Every five minutes",
+ "*/10" => "Every ten minutes",
+ "*/15" => "Every fifteen minutes",
+ );
+ foreach (range(0,59) as $val) {
+ $minutes[(string)$val] = $val;
+ }
+ $minutes["other"] = "other";
+
+ # Hours array
+ $hours = array(
+ "*" => "Every hour",
+ "*/2" => "Every other hour");
+ foreach (range(0,11) as $val) {
+ $hours[(string)$val] = (string)$val . " A.M.";
+ }
+ $hours["12"] = "12 Noon";
+ foreach (range(13,23) as $val) {
+ $hours[(string)$val] = (string)($val-12) . " P.M.";
+ }
+ $hours["other"] = "other";
+
+ # Days
+ $days = array(
+ "*" => "Every day",
+ "*/2" => "Every other day");
+ foreach (range(1,31) as $val) {
+ $days[(string)$val] = (string)($val);
+ }
+ $days["other"] = "other";
+
+ # Weekdays
+ $weekdays = array(
+ "*" => "Every weekday",
+ "0" => "Sunday",
+ "1" => "Monday",
+ "2" => "Tuesday",
+ "3" => "Wednesday",
+ "4" => "Thursday",
+ "5" => "Friday",
+ "6" => "Saturday");
+ $weekdays["other"] = "other";
+
+ # Months
+ $months = array("*" => "Every month",
+ "1" => "January",
+ "2" => "February",
+ "3" => "March",
+ "4" => "April",
+ "5" => "May",
+ "6" => "June",
+ "7" => "July",
+ "8" => "August",
+ "9" => "October",
+ "10" => "September",
+ "11" => "November",
+ "12" => "December");
+ $months["other"] = "other";
+ return array($minutes,$hours,$days,$weekdays,$months);
+}
+
+?>
diff --git a/scire/.lib/module_common.php b/scire/.lib/module_common.php
new file mode 100644
index 0000000..1c51549
--- /dev/null
+++ b/scire/.lib/module_common.php
@@ -0,0 +1,4 @@
+<?php
+$path = "../";
+require_once('common.php');
+?>
diff --git a/scire/.lib/oldDB.php.blackace b/scire/.lib/oldDB.php.blackace
new file mode 100644
index 0000000..a0deb28
--- /dev/null
+++ b/scire/.lib/oldDB.php.blackace
@@ -0,0 +1,190 @@
+<?php
+
+class DB {
+ private $db;
+ private $error;
+ function __construct($host, $user, $pass, $db) {
+ if ($this->db = @mysql_connect($host, $user, $pass)) {
+ if (!@mysql_select_db($db, $this->db)) {
+ $this->error = 'mysql select db failed';
+ if ($mysqlerror = mysql_error($this->db)) {
+ $this->error .= ' (' . $mysqlerror . ')';
+ }
+ }
+ } else {
+ $this->error = 'mysql connect failed';
+ if ($mysqlerror = mysql_error()) {
+ $this->error .= ' (' . $mysqlerror . ')';
+ }
+ }
+ }
+ function __get($name) {
+ switch ($name) {
+ case 'error':
+ return $this->error;
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+ function __set($name, $value) {
+ return false;
+ }
+ function __isset($name) {
+ switch ($name) {
+ case 'error':
+ if ($this->error && strlen($this->error) > 0) {
+ return true;
+ }
+ break;
+ default:
+ return false;
+ break;
+ }
+ }
+ function __unset($name) {
+ return false;
+ }
+ # $table = 'table1' OR array('table1', 'table2')
+ # $select = '*' OR 'column1' OR array('column1', 'column2')
+ # $query = 'SELECT * FROM table WHERE column = \'value\' OR column = (SELECT * FROM table2 WHERE column = \'value\')'
+ # $set = array('setcolumn' => 'value')
+ # $update = array('updatecolumn' => 'value')
+ # $where = '`matchcolumn` = \'criteria\''
+ # insert($table, $set)
+ # insert($table, $set, $update)
+ # update($table, $update)
+ # update($table, $update, $where)
+ # delete($table, $where)
+ # select($select, $table)
+ # select($select, $table, $where)
+ # select($query)
+ function __call($method, $args) {
+ switch ($method) {
+ case 'insert':
+ case 'update':
+ if ($args && (count($args) == 2 || count($args) == 3)) {
+ $query = strtoupper($method);
+ if ($method == 'insert') {
+ $query .= ' INTO';
+ }
+ $query .= ' `' . $args[0] . '` SET ';
+ foreach ($args[1] as $column => $value) {
+ $query .= '`' . $column . '`=\'' . $value . '\', ';
+ }
+ $query = preg_replace('/, $/', '', $query);
+ if (count($args) == 3) {
+ if ($method == 'insert') {
+ $query .= ' ON DUPLICATE KEY UPDATE ';
+ foreach ($args[2] as $column => $value) {
+ if ($value == "NOW") {
+ $query .= '`' . $colnum . '` = NOW(), ';
+ } else {
+ $query .= '`' . $column . '`=\'' . $value . '\', ';
+ }
+ }
+ $query = preg_replace('/, $/', '', $query);
+ } elseif ($method == 'update') {
+ $query .= ' WHERE ' . $args[2];
+ }
+ }
+ #print $query; #for debugging.
+ if (@mysql_query($query, $this->db)) {
+ return mysql_affected_rows($this->db);
+ } else {
+ $this->error = 'mysql ' . $method . ' failed';
+ if ($mysqlerror = mysql_error($this->db)) {
+ $this->error .= ' (' . $mysqlerror . ')';
+ }
+ return false;
+ }
+ } else {
+ return false;
+ }
+ break;
+ case 'delete':
+ if ($args && count($args) == 2) {
+ $query = strtoupper($method);
+ $query .= ' FROM `' . $args[0] . '`';
+ $query .= ' WHERE ' . $args[1];
+ if (@mysql_query($query, $this->db)) {
+ return mysql_affected_rows($this->db);
+ } else {
+ $this->error = 'mysql ' . $method . ' failed';
+ if ($mysqlerror = mysql_error($this->db)) {
+ $this->error .= ' (' . $mysqlerror . ')';
+ }
+ return false;
+ }
+ } else {
+ return false;
+ }
+ break;
+ case 'select':
+ if ($args && (count($args) >= 1 && count($args) <= 3)) {
+ if (count($args) == 1) {
+ $query = $args[0];
+ } else {
+ $query = strtoupper($method);
+ if (is_array($args[0])) {
+ foreach ($args[0] as $value) {
+ $query .= ' ' . $value . ', ';
+ }
+ } else {
+ $query .= '*';
+ }
+ $query = preg_replace('/, $/', '', $query);
+ $query .= ' FROM ' . $args[1] ;
+ if (count($args) == 3) {
+ $query .= ' WHERE ' . $args[2];
+ }
+ }
+ #print $query; #for debugging.
+ if ($result = @mysql_query($query, $this->db)) {
+ $rows = array();
+ while ($row = @mysql_fetch_assoc($result)) {
+ $rows[] = $row;
+ }
+ mysql_free_result($result);
+ return $rows;
+ } else {
+ $this->error = 'mysql ' . $method . ' failed';
+ if ($mysqlerror = mysql_error($this->db)) {
+ $this->error .= ' (' . $mysqlerror . ')';
+ }
+ return false;
+ }
+ } else {
+ return false;
+ }
+ break;
+ case 'query':
+ if (count($args) == 1) {
+ $query = $args[0];
+ } else {
+ return false;
+ }
+ print $query . "<BR>"; #for debugging.
+ if ($result = @mysql_query($query, $this->db)) {
+ $rows = array();
+ while ($row = @mysql_fetch_assoc($result)) {
+ $rows[] = $row;
+ }
+ mysql_free_result($result);
+ return $rows;
+ } else {
+ $this->error = 'mysql ' . $method . ' failed';
+ if ($mysqlerror = mysql_error($this->db)) {
+ $this->error .= ' (' . $mysqlerror . ')';
+ }
+ return false;
+ }
+ default:
+ $this->error = 'unknown method';
+ return false;
+ }
+ }
+}
+
+?>
diff --git a/scire/.lib/phpGACL.php b/scire/.lib/phpGACL.php
new file mode 100644
index 0000000..dfceebf
--- /dev/null
+++ b/scire/.lib/phpGACL.php
@@ -0,0 +1,47 @@
+<?php
+
+require_once($path . './phpgacl/gacl.class.php');
+require_once($path . './phpgacl/gacl_api.class.php');
+
+$gacl_options = array(
+ 'db_type' => 'mysql',
+ 'db_host' => $db_host,
+ 'db_user' => $db_username,
+ 'db_password' => $db_password,
+ 'db_name' => $db_name,
+ 'db_table_prefix' => 'gacl_',
+# 'caching' => 'FALSE',
+ 'smarty_dir' => preg_replace('/\/$/', '', $smarty_dir),
+ 'smarty_template_dir' => 'templates',
+ 'smarty_compile_dir' => 'templates_c'
+);
+
+$acl = new gacl_api($gacl_options); #can be gacl_api
+
+function check_access($permname) {
+ global $acl;
+ global $scire_ui_section;
+ if ($_SESSION['username'] == "root") { return True; } #godmode
+ if ($acl->acl_check($scire_ui_section, $permname, "users", $_SESSION['username'],$scire_ui_section, $scire_ui_section) ) {
+ return True;
+ } else {
+ return False;
+ }
+ return False;
+}
+
+function check_action_access($permname) { #Same as above but aborts the page for you.
+ global $acl;
+ global $scire_ui_section;
+ if ($_SESSION['username'] == "root") { return True; } #iddqd
+ $result = $acl->acl_check($scire_ui_section, $permname, "users", $_SESSION['username'],$scire_ui_section, $scire_ui_section);
+ if ($result) {
+ #print "Access Granted! $result";
+ return True;
+ } else {
+ header('Location: ' . $baseurl . 'access_error.php?perm=' . urlencode($permname));
+ exit(0);
+ #print "DENIED! " + $result;
+ }
+}
+?>
diff --git a/scire/.lib/smarty.php b/scire/.lib/smarty.php
new file mode 100644
index 0000000..4d9d3c5
--- /dev/null
+++ b/scire/.lib/smarty.php
@@ -0,0 +1,34 @@
+<?php
+
+require_once($smarty_dir . 'Smarty.class.php');
+
+$smarty = new Smarty();
+$smarty->template_dir = $basedir . '.smarty/templates';
+$smarty->compile_dir = $basedir . '.smarty/templates_c';
+$smarty->cache_dir = $basedir . '.smarty/cache';
+$smarty->config_dir = $basedir . '.smarty/config';
+
+$smarty->assign('baseurl', $baseurl);
+
+# Top navigation bar
+$topbar_left = array(
+ array('name' => 'Overview', 'link' => 'index.php'),
+ array('name' => 'Jobs', 'link' => 'jobs.php'),
+ array('name' => 'Clients', 'link' => 'clients.php')
+);
+
+$topbar_right = array(
+ array('name' => 'Settings', 'link' => 'settings.php'),
+ array('name' => 'Help', 'link' => 'help.php')
+);
+
+#if ($_SESSION['username'] eq 'is in the administrators group') {
+ $topbar_left[] = array('name' => 'Users', 'link' => 'users.php');
+#}
+$topbar_left[] = array('name' => 'Script Library', 'link' => 'script_library.php');
+$topbar_left[] = array('name' => 'Modules', 'link' => 'modules.php');
+
+$smarty->assign('topbar_left', $topbar_left);
+$smarty->assign('topbar_right', $topbar_right);
+
+?>
diff --git a/scire/.smarty/.svnignore b/scire/.smarty/.svnignore
new file mode 100644
index 0000000..198e853
--- /dev/null
+++ b/scire/.smarty/.svnignore
@@ -0,0 +1 @@
+templates_c
diff --git a/scire/.smarty/templates/access_error.tpl b/scire/.smarty/templates/access_error.tpl
new file mode 100644
index 0000000..f38e992
--- /dev/null
+++ b/scire/.smarty/templates/access_error.tpl
@@ -0,0 +1,9 @@
+{include file="header.tpl" title="Access Denied"}
+<p>
+An error has occurred.<br>
+Unfortunatly, {$user} does not have sufficient permission to perform this action.<br>
+The requried permission was: {$perm}<br>
+Why don't you complain to your admin?
+{$message|escape:"htmlall"}
+</p>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/add_job.tpl b/scire/.smarty/templates/add_job.tpl
new file mode 100755
index 0000000..bee7e2f
--- /dev/null
+++ b/scire/.smarty/templates/add_job.tpl
@@ -0,0 +1,351 @@
+{include file="header.tpl" title="Add A Job"}
+<form action="" method="post" name="add_jobform">
+ Step 1: select a script.<br>
+ Step 2: select a client or multiple clients and/or clientgroups.<br>
+ Step 3: set
+<hr>
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td align="left" valign="top">
+ <table class="box" width="90%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Script Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="scripts">Scripts:</label></td>
+ </tr>
+ <tr>
+ {if isset($get.scriptid)}
+
+ <td>Selected script:</td>
+ <td><input type="hidden" name="script" value="{$script.scriptid}">{$script.name}</td>
+ {else}
+ <td>Categories will go here</td>
+ <td>
+ <select name="script" size="10" >
+ {foreach from=$scripts item=script key=key}
+ <option value="{$script.scriptid}">
+ {$script.name}</option>
+ {/foreach}
+ </select>
+ </td>
+ {/if}
+ </tr>
+ {if !isset($get.scriptid)}
+ <tr>
+ <td colspan="2">Or just type in the ID of the script: <input type="text" name="scriptID" ></td>
+ </tr>
+ {/if}
+ <tr>
+ <td colspan="2"><hr><h4>Override Script default values:</h4><br>
+ Permission: <select size="1" name="permission">
+ {foreach from=$perms item=perm key=id}
+ <option value="{$perm}"
+ {if isset($script.permission)}
+ {if $perm eq $script.permission} selected {/if}
+ {/if}
+ >{$perm}</option>
+ {/foreach}
+ </select><br>
+
+ Set Priority: <select size="1" name="priority">
+ {foreach from=$priorities item=priority key=id}
+ <option value="{$priority}"
+ {if isset($script.priority)}
+ {if $priority eq $script.priority} selected {/if}
+ {/if}
+ >{$priority}</option>
+ {/foreach}
+ </select><br>
+ Log Location: <input type="text" name="log_location" value="{$script.log_location}"><br>
+ Success Code: (not worrying bout this now)<br>
+ Set dynamic content: <br>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+
+ <td align="right" valign="top">
+ <table class="box" width="50%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Client Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ {if isset($get.clientid)}
+
+ <td>Selected client:</td>
+ <td><input type="hidden" name="clients[]" value="{$client.hostname}">{$client.hostname}</td>
+ {elseif isset($get.cgroupid)}
+ <td>Selected clientgroup:</td>
+ <td><input type="hidden" name="cgroups[]" value="{$get.cgroupid}">NAME HERE</td>
+ {else}
+ <td><label for="clientgroups">Clientgroups:</label></td>
+ <td><label for="clients">Clients:</label></td>
+ </tr>
+ <tr>
+ <td>
+ <select name="clientgroups[]" size="18" multiple="multiple">
+ {foreach from=$cgroups item=cgroup key=id}
+ <option value="{$id}">{$cgroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ <td>
+ <select name="clients[]" size="18" multiple="multiple">
+ {section loop=$clients name=clients}
+ <option value="{$clients[clients].clientid}">{$clients[clients].hostname}</option>
+ {/section}
+ </select>
+ </td>
+ {/if}
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ Input staging client hostname (optional): <input type="text" name="staging"><br>
+ Staging success: <input type="radio" name="staging_success" value="result">Positive Result Code <input type="radio" name="staging_success" value="user">Manually approved
+ </td>
+ </tr>
+ </table>
+ <hr>
+ <table>
+ {if $dyn_tags}
+ <tr>
+ <th>Dynamic Tag</th><th>Value</th>
+ </tr>
+ {foreach from=$dyn_tags item=tag key=tagnum}
+ <tr>
+ <td>Tag: <b>{$tag}</b></td><td><input type="text" name="tag_{$tag}" value="{$tag_values[$tag]}" /></td>
+ </tr>
+ {/foreach}
+ {/if}
+</table>
+<hr>
+Job Description: <br><textarea name="description" rows="3" cols="40"></textarea><br>
+<hr>
+Recurring stuff here. <b>You need to select all of them to get it to save the schedule!</b><br>
+<table>
+<tr><td>Minute(s):<br>
+<select multiple name=minute1 size=10>
+<!-- <option value=*> Every Minute
+<option value=*/2> Every Other Minute -->
+<option value=*/5> Every Five Minutes
+<option value=*/10> Every Ten Minutes
+<option value=*/15> Every Fifteen Minutes
+<option value=0> 0
+<option value=1> 1
+
+<option value=2> 2
+<option value=3> 3
+<option value=4> 4
+<option value=5> 5
+<option value=6> 6
+<option value=7> 7
+<option value=8> 8
+<option value=9> 9
+<option value=10> 10
+
+<option value=11> 11
+<option value=12> 12
+<option value=13> 13
+<option value=14> 14
+<option value=15> 15
+<option value=16> 16
+<option value=17> 17
+<option value=18> 18
+<option value=19> 19
+
+<option value=20> 20
+<option value=21> 21
+<option value=22> 22
+<option value=23> 23
+<option value=24> 24
+<option value=25> 25
+<option value=26> 26
+<option value=27> 27
+<option value=28> 28
+
+<option value=29> 29
+<option value=30> 30
+<option value=31> 31
+<option value=32> 32
+<option value=33> 33
+<option value=34> 34
+<option value=35> 35
+<option value=36> 36
+<option value=37> 37
+
+<option value=38> 38
+<option value=39> 39
+<option value=40> 40
+<option value=41> 41
+<option value=42> 42
+<option value=43> 43
+<option value=44> 44
+<option value=45> 45
+<option value=46> 46
+
+<option value=47> 47
+<option value=48> 48
+<option value=49> 49
+<option value=50> 50
+<option value=51> 51
+<option value=52> 52
+<option value=53> 53
+<option value=54> 54
+<option value=55> 55
+
+<option value=56> 56
+<option value=57> 57
+<option value=58> 58
+<option value=59> 59
+</select><br>
+</td>
+<td>Hour(s):<br>
+<select multiple name=hour1 size=5>
+<option value=*> Every Hour
+<option value=*/2> Every Other Hour
+
+<option value=*/4> Every Four Hours
+<option value=*/6> Every Six Hours
+<option value=0> 0 = 12 AM/Midnight
+<option value=1> 1 = 1 AM
+<option value=2> 2 = 2 AM
+<option value=3> 3 = 3 AM
+<option value=4> 4 = 4 AM
+<option value=5> 5 = 5 AM
+<option value=6> 6 = 6 AM
+
+<option value=7> 7 = 7 AM
+<option value=8> 8 = 8 AM
+<option value=9> 9 = 9 AM
+<option value=10> 10 = 10 AM
+<option value=11> 11 = 11 AM
+<option value=12> 12 = 12 PM/Noon
+<option value=13> 13 = 1 PM
+<option value=14> 14 = 2 PM
+<option value=15> 15 = 3 PM
+
+<option value=16> 16 = 4 PM
+<option value=17> 17 = 5 PM
+<option value=18> 18 = 6 PM
+<option value=19> 19 = 7 PM
+<option value=20> 20 = 8 PM
+<option value=21> 21 = 9 PM
+<option value=22> 22 = 10 PM
+<option value=23> 23 = 11 PM
+</select>
+
+<br><br>Day(s):<br>
+<select multiple name=day1 size=5>
+<option value=*> Every Day
+<option value=1> 1
+<option value=2> 2
+<option value=3> 3
+<option value=4> 4
+<option value=5> 5
+<option value=6> 6
+
+<option value=7> 7
+<option value=8> 8
+<option value=9> 9
+<option value=10> 10
+<option value=11> 11
+<option value=12> 12
+<option value=13> 13
+<option value=14> 14
+<option value=15> 15
+
+<option value=16> 16
+<option value=17> 17
+<option value=18> 18
+<option value=19> 19
+<option value=20> 20
+<option value=21> 21
+<option value=22> 22
+<option value=23> 23
+<option value=24> 24
+
+<option value=25> 25
+<option value=26> 26
+<option value=27> 27
+<option value=28> 28
+<option value=29> 29
+<option value=30> 30
+<option value=31> 31
+</select><br><br>
+</td><td>Months(s):<br>
+
+<select multiple name=month1 size=5>
+<option value=*> Every Month
+<option value=1> January
+<option value=2> February
+<option value=3> March
+<option value=4> April
+<option value=5> May
+<option value=6> June
+<option value=7> July
+
+<option value=8> August
+<option value=9> September
+<option value=10> October
+<option value=11> November
+<option value=12> December
+</select>
+<br><br>Weekday(s):<br>
+<select multiple name=weekday1 size=5>
+<option value=*> Every Weekday
+<option value=0> Sunday
+
+<option value=1> Monday
+<option value=2> Tuesday
+<option value=3> Wednesday
+<option value=4> Thursday
+<option value=5> Friday
+<option value=6> Saturday
+</select>
+</td></tr>
+<tr><td>
+<hr>
+<label for="validity_period">Validity Period (in minutes?): </label><input type="text" name="validity_period" />
+</td></tr>
+
+<tr><td>
+<script language="JavaScript" src="calendar/calendar3.js"></script><!-- Date only with year scrolling -->
+<label for="deploy_time">Start time: <input type="Text" name="deploy_time" value="">
+ <a href="javascript:cal1.popup();"><img src="calendar/img/cal.gif" width="16" height="16" border="0" alt="Click Here to Pick up the date"></a></label>
+</td>
+<td>
+<label for="expiration_time">End time: <input type="Text" name="expiration_time" value="">
+ <a href="javascript:cal2.popup();"><img src="calendar/img/cal.gif" width="16" height="16" border="0" alt="Click Here to Pick up the date"></a></label>
+<script language="JavaScript">
+ <!-- // create calendar object(s) just after form tag closed
+ // specify form element as the only parameter (document.forms['formname'].elements['inputname']);
+ // note: you can have as many calendar objects as you need for your application
+ var cal1 = new calendar3(document.forms['add_jobform'].elements['deploy_time']);
+ cal1.year_scroll = false;
+ cal1.time_comp = true;
+ var cal2 = new calendar3(document.forms['add_jobform'].elements['expiration_time']);
+ cal2.year_scroll = false;
+ cal2.time_comp = true;
+ //-->
+ </script>
+</td>
+</tr>
+</table>
+<hr>
+Job dependency stuff here.<B>CODE ME</B><br>
+<!-- Set notification email address: <input type="radio" name="notify_addr" value="{$useremail}">{$useremail}</input><input type="radio" name="notify_addr" value="new"><input type="text" name="notify_new"></input> -->
+<input type="submit" name="ADD" value="ADD JOB!!!">
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/admin.tpl b/scire/.smarty/templates/admin.tpl
new file mode 100644
index 0000000..e03cfb7
--- /dev/null
+++ b/scire/.smarty/templates/admin.tpl
@@ -0,0 +1,29 @@
+{include file="header.tpl" title="Scire - Administration Page"}
+Admin-y page here.
+List of administrative tasks:
+<hr>
+<table>
+<tr><td><a href="admin/create_user.php">Create a User</a></td></tr>
+<tr><td><a href="admin/edit_user.php">Edit a User</a></td></tr>
+<tr><td><a href="admin/delete_user.php">Delete a User</a></td></tr>
+<tr><td></td></tr>
+<tr><td><a href="admin/create_usergroup.php">Create a UserGroup</a></td></tr>
+<tr><td><a href="admin/edit_usergroup.php">Edit a UserGroup</a></td></tr>
+<tr><td><a href="admin/delete_usergroup.php">Delete a UserGroup</a></td></tr>
+<tr><td></td></tr>
+<tr><td><a href="admin/add_permission.php">Add Permission</a></td></tr>
+<tr><td><a href="admin/edit_permission.php">Edit Permission</a></td></tr>
+<tr><td><a href="admin/delete_permission.php">Delete Permission</a></td></tr>
+<tr><td></td></tr>
+<tr><td><a href="admin/add_client.php">Add Client Manually</a></td></tr>
+<tr><td><a href="admin/edit_client.php">Edit Clients</a></td></tr>
+<tr><td><a href="admin/delete_client.php">Delete Client from Scire</a></td></tr>
+<tr><td></td></tr>
+<tr><td><a href="admin/create_clientgroup.php">Create a ClientGroup</a></td></tr>
+<tr><td><a href="admin/edit_clientgroup.php">Edit a ClientGroup</a></td></tr>
+<tr><td><a href="admin/delte_clientgroup.php">Delete a ClientGroup</a></td></tr>
+<tr><td></td></tr>
+<tr><td><a href="admin/assign_permissions.php">Assign Permissions</a></td></tr>
+</table>
+<hr>
+Maybe some Certificate Authority tasks?
diff --git a/scire/.smarty/templates/assign_permission.tpl b/scire/.smarty/templates/assign_permission.tpl
new file mode 100755
index 0000000..3b219e6
--- /dev/null
+++ b/scire/.smarty/templates/assign_permission.tpl
@@ -0,0 +1,217 @@
+{include file="header.tpl" title="Assign A Permission"}
+<form action="" method="post" name="add_permform">
+{if $Action eq "delete"}
+<b>Are you absolutely SURE you want to delete this ACL?</b>
+<input type="hidden" name="aclid" value="{$aclid}">
+<input type="submit" name="delete_confirm" value="Yes, that's why I clicked 'Delete', duh!"><input type="submit" name="delete_cancel" value="No wait!">
+{else}
+Instructions:<br>
+1. Select a set of users and/or usergroups (any combination, they are exclusive)<br>
+2. Select a permission category and then the permission to use, or choose to create a new one<br>
+3. Select a set of clients and/or clientgroups (again, groups are exclusive from individual clients)<br>
+4. Select options below and give a note for the permission.
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td align="left" valign="top">
+ <table class="box" width="50%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">User Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="usergroups">Usergroups:</label></td>
+ <td><label for="users">Users:</label></td>
+ </tr>
+ <tr>
+ {if isset($get.username)}
+ <td>Selected User:</td>
+ <td><input type="hidden" name="users[]" value="{$get.username}">{$get.username}</td>
+ {elseif isset($get.usergroup)}
+ {else}
+ <td>
+ <select name="usergroups[]" size="18" multiple="multiple">
+ {foreach from=$ugroups item=ugroup key=id}
+ <option value="{$id}"
+ {if isset($acl)}
+ {foreach from=$acl.aro_groups item=group key=groupid}
+ {if $id eq $group} selected {/if}
+ {/foreach}
+ {/if}
+ >{$ugroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ <td>
+ <select name="users[]" size="18" multiple="multiple">
+ {section loop=$users name=users}
+ <option value="{$users[users].username}"
+ {if isset($acl)}
+ {foreach from=$acl.aro.users item=user key=key2}
+ {if $users[users].username eq $user} selected {/if}
+ {/foreach}
+ {/if}
+ >{$users[users].username}</option>
+ {/section}
+ </select>
+ </td>
+ {/if}
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="50%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Permission Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="perm_category">Category:</label> </td>
+ </tr>
+ <tr>
+ <td>
+ <select name="perm_category">
+ {foreach from=$perm_categories item=cat }
+ <option value="{$cat}"
+ {if isset($acl)}
+ {foreach from=$acl.aco item=ignore key=perm_category}
+ {if $cat eq $perm_category} selected {/if}
+ {/foreach}
+ {/if}
+ >{$cat}</option>
+ {/foreach}
+ <option value="new">New (specify below)</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="perm">Permissions (choose an existing or create a new one):</label></td>
+ </tr>
+ <tr>
+ <td>
+ <select name="perm" size="7">
+ {foreach from=$perms item=perm key=id}
+ <option value="{$perm}"
+ {if isset($acl)}
+ {foreach from=$acl.aco item=ignore key=perm_category}
+ {if $perm eq $acl.aco.$perm_category[0]} selected {/if}
+ {/foreach}
+ {/if}
+ >{$perm}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="newpermname">New Category (optional):</label><input name="newpermcat" type="text" size="20"></td>
+ </tr>
+ <tr>
+ <td><label for="newpermname">New Permission Name:</label><input name="newpermname" type="text" size="20"></td>
+ </tr>
+ <tr>
+ <td><label for="newpermdesc">New Permission Description:</label></td>
+ </tr>
+ <tr>
+ <td><textarea name="newpermdesc" rows="3" cols="20"></textarea></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table
+ </td>
+ <td align="right" valign="top">
+ <table class="box" width="50%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Client Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="clientgroups">Clientgroups:</label></td>
+ <td><label for="clients">Clients:</label></td>
+ </tr>
+ <tr>
+ {if isset($get.hostname)}
+ <td>Selected Client:</td>
+ <td><input type="hidden" name="clients[]" value="{$get.hostname}">{$get.hostname}</td>
+ {elseif isset($get.clientgroup)}
+ {else}
+ <td>
+ <select name="clientgroups[]" size="18" multiple="multiple">
+ {foreach from=$cgroups item=cgroup key=id}
+ <option value="{$id}"
+ {if isset($acl)}
+ {foreach from=$acl.axo_groups item=group key=groupid}
+ {if $id eq $group} selected {/if}
+ {/foreach}
+ {/if}
+ >{$cgroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ <td>
+ <select name="clients[]" size="18" multiple="multiple">
+ {section loop=$clients name=clients}
+ <option value="{$clients[clients].hostname}"
+ {if isset($acl)}
+ {foreach from=$acl.axo.clients item=client key=key2}
+ {if $clients[clients].hostname eq $client} selected {/if}
+ {/foreach}
+ {/if}
+ >{$clients[clients].hostname}</option>
+ {/section}
+ </select>
+ </td>
+ {/if}
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="center"><input type="radio" name="allow" value="1"
+ {if isset($acl)}
+ {if $acl.allow} checked {/if}
+ {else}
+ checked
+ {/if}
+ >Allow
+ <input type="radio" name="allow" value="0"
+ {if isset($acl)}
+ {if (!$acl.allow)} checked {/if}
+ {/if}
+ >Deny</td>
+ <td align="center"><input type="checkbox" name="active" value="1"
+ {if isset($acl)}
+ {if $acl.enabled} checked {/if}
+ {else}
+ checked
+ {/if}
+ >Active (vs. hidden)</td>
+ <td align="right" valign="bottom">
+ <label for="note">Note:</label><input type="text" name="note"
+ {if isset($acl)}
+ value="{$acl.note}"
+ {/if}
+ >
+ {if isset($acl)}
+ <input type="hidden" name="editing" value="{$acl.acl_id}">
+ <input type="submit" name="editperm_submit" value="Update Permission">
+ {else}
+ <input type="submit" name="addperm_submit" value="Assign Permission">
+ {/if}
+ </td>
+ </tr>
+</table>
+{/if}
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/client.tpl b/scire/.smarty/templates/client.tpl
new file mode 100755
index 0000000..39d4bd1
--- /dev/null
+++ b/scire/.smarty/templates/client.tpl
@@ -0,0 +1,255 @@
+{include file="header.tpl" title="Clients"}
+<form action="" method="post" name="edit_clientform">
+{if $Action eq "addgroup"}
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr><td class="boxtitle">Add client to group</td></tr>
+ <tr>
+ <td colspan="2" align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle" width="15">Add</td><td class="boxtitle">Group Name</td>
+ </tr>
+ {foreach from=$groups name=ugroup item=item key=id}
+ <tr>
+ <td><input type="checkbox" name="addgroupid[]" value="{$id}"
+ {if isset($ingroups)} {if in_array($id, $ingroups)} checked {/if} {/if}
+ ></td>
+ <td>{$item}</td>
+ </tr>
+ {/foreach}
+ <tr><td>
+ <input type="hidden" name="clientid" value="{$clientid}">
+ <input type="submit" name="addgroup_confirm" value="Save Changes">
+ </td></tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+{elseif $Action eq "create"}
+<table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td colspan="2" align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Client</td><td class="boxtitle">Groups</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="addhostname">*Hostname:</label></td>
+ <td><input type="text" id="addhostname" name="addhostname" /></td>
+ <td><label for="ip">*IP Address:</label></td>
+ <td><input type="text" id="ip" name="ip" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="assetid">Asset ID:</label></td>
+ <td><input type="text" id="assetid" name="assetid" /></td>
+ <td><label for="mac">*MAC:</label></td>
+ <td><input type="text" id="mac" name="mac" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="digest">Digest (DO NOT EDIT):</label></td>
+ <td colspan="3"><input type="text" id="digest" name="digest" size="58"></td>
+ </tr>
+ <tr>
+ <td><label for="gli_profile">GLI Profile:</label></td>
+ <td><select name="gli_profile" size="1">
+ {section name=p loop=$gli_profiles}
+ <option value="{$gli_profiles[p].profileid}">{$gli_profiles[p].profile_name}</option>
+ {/section}
+ </select>
+ </td>
+ <td><label for="status">Status:</label></td>
+ <td><select id="status" name="status" size="1">
+ {section name=s loop=$client_statuses}
+ <option value="{$client_statuses[s].statusid}">{$client_statuses[s].statusname}</option>
+ {/section}
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="osid">OS:</label></td>
+ <td><select name="osid" size="1">
+ {section name=o loop=$oss}
+ <option value="{$oss[o].osid}">{$oss[o].osname}</option>
+ {/section}
+ </select>
+ </td>
+ <td><label for="contact">Contact:</label></td>
+ <td><select name="contact" size="1">
+ {section name=con loop=$users}
+ <option value="{$users[con].userid}">{$users[con].username}</option>
+ {/section}
+ </select></td>
+ </tr>
+ <tr>
+ <td><label for="installtime">Install Time <br>(leave blank for NOW):</label></td>
+ <td colspan="3"><input type="text" id="installtime" name="installtime" size="25"/></td>
+ </tr>
+ </table>
+ <p><input type="submit" name="AddClientSubmit" value="Add Client" /></p>
+ </td>
+ <td>
+ <table>
+ <tr><td>Assign client to the following groups:</td></tr>
+ <tr><td>
+ <select name="groups[]" size="10" multiple="multiple" id="groups">
+ {foreach from=$groups item=ugroup key=id}
+ <option value="{$id}">{$ugroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr></table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+{elseif $Action eq "edit"}
+<h1>EDITING</h1>
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td colspan="2" align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Client</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="addhostname">*Hostname:</label></td>
+ <td><input type="text" id="edithostname" name="edithostname" value="{$client.hostname}" /></td>
+ <td><label for="ip">*IP Address:</label></td>
+ <td><input type="text" id="ip" name="ip" value="{$client.ip}" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="assetid">Asset ID:</label></td>
+ <td><input type="text" id="assetid" name="assetid" value="{$client.assetid}" /></td>
+ <td><label for="mac">*MAC:</label></td>
+ <td><input type="text" id="mac" name="mac" value="{$client.mac}" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="digest">Digest (DO NOT EDIT):</label></td>
+ <td colspan="3"><input type="text" id="digest" name="digest" size="55" value="{$client.digest}" /></td>
+ </tr>
+ <tr>
+ <td><label for="gli_profile">GLI Profile:</label></td>
+ <td><select name="gli_profile" size="1">
+ {section name=p loop=$gli_profiles}
+ <option value="{$gli_profiles[p].profileid}" {if $gli_profiles[p].profileid eq $client.gli_profile} selected {/if}
+ >{$gli_profiles[p].profile_name}</option>
+ {/section}
+ </select>
+ </td>
+ <td><label for="status">Status:</label></td>
+ <td><select id="status" name="status" size="1">
+ {section name=s loop=$client_statuses}
+ <option value="{$client_statuses[s].statusid}" {if $client_statuses[s].statusid eq $client.status} selected {/if}>{$client_statuses[s].statusname}</option>
+ {/section}
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="osid">OS:</label></td>
+ <td><select name="osid" size="1">
+ {section name=o loop=$oss}
+ <option value="{$oss[o].osid}" {if $oss[o].osid eq $client.osid} selected {/if}
+ >{$oss[o].osname}</option>
+ {/section}
+ </select>
+ </td>
+ <td><label for="contact">Contact:</label></td>
+ <td><select name="contact" size="1">
+ {section name=con loop=$users}
+ <option value="{$users[con].userid}" {if $users[con].userid eq $client.contact} selected {/if}
+ >{$users[con].username}</option>
+ {/section}
+ </select></td>
+ </tr>
+ <tr>
+ <td><label for="installtime">Install Time <br>(leave blank for NOW):</label></td>
+ <td colspan="3"><input type="text" id="installtime" name="installtime" size="25" value="{$client.installtime}" /></td>
+ </tr>
+ </table><input type="hidden" name="clientid" value="{$client.clientid}">
+ <p><input type="submit" name="EditClientSubmit" value="Save Changes" /></form></p>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Groups</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Groupname</th>
+ <th>Actions</th>
+ </tr>
+ {section name=group loop=$groups}
+ <tr>
+ <td>{$groups[group].name}{if $groups[group].parent} (subgroup of {$groups[group].parent}){/if}</td>
+ <td><form id="form1" name="form1" method="post" action=""><input type="hidden" name="group_id" value="{$groups[group].id}"><input type="submit" name="remove_ug" value="Remove"></form></td>
+ </tr>
+ {/section}
+ <tr><td><a href="client.php?clientid={$client.clientid}&Action=addgroup">Add client to a group</a></td></tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Permissions</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Category -> Permission</th>
+ <th>From User(s)</th>
+ <th>Actions</th>
+ </tr>
+ {foreach from=$acls item=acl key=k}
+ <tr>
+ <td>{foreach from=$acl.aco item=perm key=category}{$category} -> {$perm[0]}{/foreach}</td>
+ <td>
+ {if $acl.aro} <!-- we have individual users -->
+ {foreach from=$acl.aro.users item=user key=key2}
+ <font style="background-color:#A0F8FF">User: {$user}</font><br>
+ {/foreach}
+ {/if}
+ {foreach from=$acl.aro_groups item=group key=groupid}
+ <font style="background-color:#FFFACD">UserGroup: {$ugroups[$group]} </font><br>
+ {/foreach}
+ </td>
+ <td><form id="form1" name="form1" method="post" action=""><input type="hidden" name="perm_id" value="{$acl.acl_id}" /><input type="submit" name="submit" value="Remove" /></form></td>
+ </tr>
+ {/foreach}
+ <tr><td><a href="assign_permission.php?hostname={$client.hostname}">Assign a permission for this client</a></td></tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+{elseif $Action eq "delete"}
+<h1>DELETING</h1>
+<b>Are you absolutely SURE you want to delete client {$client.hostname}?</b>
+<input type="hidden" name="clientid" value="{$client.clientid}">
+<input type="submit" name="delete_confirm" value="Yes, get rid of the bastard!"><input type="submit" name="delete_cancel" value="No wait!">
+{/if}
+
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/clients.tpl b/scire/.smarty/templates/clients.tpl
new file mode 100755
index 0000000..8626c4e
--- /dev/null
+++ b/scire/.smarty/templates/clients.tpl
@@ -0,0 +1,72 @@
+{include file="header.tpl" title="Clients"}
+<form action="" method="post" name="clientsform">
+<p>
+ <strong>Search filter:
+ <input type="text" name="searchfield">
+ </strong>
+ {if check_access("View Pending Clients")}
+ <strong>Status Filter:
+ <select name="statusfilter" size="1">
+ {html_options values=$statusfilters output=$statusfilters selected=$View}
+ </select>
+ <input type="submit" name="submit" value="Update">
+ </strong>
+ {/if}
+</p>
+{if $clients}
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Clients</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ {foreach from=$fields item=i key=k}
+ <th>
+ <a href="clients.php{if $f_attr[$i].sortable}?sorton={$i}&sortdir={if $sorton eq $i and $sortdir eq "desc"}asc{else}desc{/if}{/if}">{$f_attr[$i].name}</a> {if $f_attr[$i].sortable}<img src="images/sort_{if $sorton eq $i and $sortdir eq "desc"}desc{else}asc{/if}.png">{/if}
+ </th>
+ {/foreach}
+
+ <th>Actions</th>
+ {if $View eq "Pending"}
+ <th>Approve/Deny</th>
+ {/if}
+ </tr>
+ {section name=clients loop=$clients}
+ <tr>
+ {foreach from=$fields item=item key=key}
+ {if $item eq "hostname"}
+ <td><a href="client.php?clientid={$clients[clients].clientid}&Action=edit">{$clients[clients].hostname}</a></td>
+ {else}
+ <td>{$clients[clients].$item}</td>
+ {/if}
+ {/foreach}
+ <td>
+ {if check_access("Edit Client") }
+ <a href="client.php?clientid={$clients[clients].clientid}&Action=edit">Edit</a>
+ {/if}
+ {if ($View eq "Pending") and check_access("Approve/Reject Pending Clients")}
+ <a href="client.php?clientid={$clients[clients].clientid}&Action=assign">Assign</a>
+ {else}
+ <a href="client.php?clientid={$clients[clients].clientid}&Action=delete">Delete</a>
+ {/if}
+ </td>
+ {if $View eq "Pending" and check_access("Approve/Reject Pending Clients")}
+ <td>
+ <input type="checkbox" name="pending_ids[]" value="{$clients[clients].clientid}">
+ </td>
+ {/if}
+ </tr>
+ {/section}
+
+ </td></tr>
+
+ </table>
+ {if $View eq "Pending" and check_access("Approve/Reject Pending Clients")}
+ <tr>
+ <td align="right"><input type="submit" name="pend_approve" value="Approve">
+ <input type="submit" name="pend_reject" value="Reject"></td>
+ </tr>
+ {/if}
+{/if}
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/clients_groups.tpl b/scire/.smarty/templates/clients_groups.tpl
new file mode 100644
index 0000000..bb9c776
--- /dev/null
+++ b/scire/.smarty/templates/clients_groups.tpl
@@ -0,0 +1,74 @@
+{include file="header.tpl" title="Clients"}
+<form action="" method="post" name="clientsgroupsform">
+{if $Action eq "create"}
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Create a Client Group</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Add Client Group</td><td class="boxtitle">Parent Group</td>
+ </tr>
+ <tr>
+ <td>
+ <label for="addgroupname">Name:</label>
+ <input type="text" name="addgroupname" id="addgroupname">
+ </td>
+ <td>
+ <select name="parentgroup" id="parentgroup">
+ {foreach item=cgroup key=ckey from=$groups}
+ <option value="{$ckey}">{$cgroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ <tr><td>as a subgroup of ---></td></tr>
+ <tr><td></td><td><input type="submit" name="addgroup" value="Add Client Group"></td></tr>
+ </table>
+ </table>
+ {elseif $Action eq "edit"}
+ <input type="hidden" name="groupid" value="{$groupid}">
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Edit Client Group {$groupdata[3]}</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Edit Client Group</td><td class="boxtitle">Parent Group</td>
+ </tr>
+ <tr>
+ <td>
+ <label for="editgroupname">Name:</label>
+ <input type="text" name="editgroupname" id="editgroupname" value="{$groupdata[3]}">
+ </td>
+ <td>
+ <select name="parentgroup" id="parentgroup">
+ {foreach item=cgroup key=ckey from=$groups}
+ <option value="{$ckey}" {if $groupdata[1] == $ckey} selected {/if}>{$cgroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ <tr><td>as a subgroup of ---></td></tr>
+ <tr><td></td><td><input type="submit" name="editgroup" value="Save Changes"></td></tr>
+ </table>
+ </table>
+ {elseif $Action eq "delete"}
+ <h1>Delete</h1>
+ <b>Are you absolutely SURE you want to delete this group?</b>
+ <input type="hidden" name="delgroup" value="{$groupid}">
+<input type="submit" name="delgroup_confirm" value="Yes, remove the group"><input type="submit" name="delete_cancel" value="No wait! Cancel!">
+ {else}
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Client Groups</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr><td class="boxtitle">Group Name</td><td class="boxtitle">Edit</td><td class="boxtitle">Delete</td></tr>
+ {foreach item=group key=key from=$groups}
+ <tr><td>{$group}</td><td><a href="clients.php?View=groups&Action=edit&groupid={$key}">Edit</a></td><td><a href="clients.php?View=groups&Action=delete&groupid={$key}">Delete</a></td></tr>
+ {/foreach}
+ {/if} <!-- action -->
+
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/footer.tpl b/scire/.smarty/templates/footer.tpl
new file mode 100644
index 0000000..010c5f8
--- /dev/null
+++ b/scire/.smarty/templates/footer.tpl
@@ -0,0 +1,9 @@
+ <!-- end content -->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/scire/.smarty/templates/header.tpl b/scire/.smarty/templates/header.tpl
new file mode 100644
index 0000000..d0d40b5
--- /dev/null
+++ b/scire/.smarty/templates/header.tpl
@@ -0,0 +1,91 @@
+{assign var="baseurl" value=$baseurl|default:"/"}
+{assign var="leftbar" value=$leftbar|default:"off"}
+{assign var="title" value=$title|default:""}
+{assign var="subtitle" value=$subtitle|default:""}
+{assign var="desc" value=$desc|default:""}
+{assign var="theme" value=$theme|default:"std_grey"}
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"/>
+ <title>Scire{if ($title ne "")} - {$title}{if ($subtitle ne "")} - {$subtitle}{/if}{/if}</title>
+ <link rel="icon" href="{$baseurl}favicon.ico" type="image/x-icon" />
+ <link rel="shortcut icon" href="{$baseurl}favicon.ico" type="image/x-icon" />
+ <link rel="stylesheet" href="{$baseurl}{$theme}.css" type="text/css" />
+
+{if isset($head)}{$head}{/if}
+ </head>
+ <body link="#000000" alink="#ffffff">
+ <table width="100%" bgcolor="#ffffff" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td colspan="2">
+ <table id="logobar" width="100%" border="0" cellspacing="0" cellpadding="10">
+ <tr>
+ <td width="80">
+ <a href="{$baseurl}index.php"><img src="{$baseurl}images/scire_trans.png" alt="Scire" border="0" width="80" height="80" /></a>
+ </td>
+ <td align="right" valign="top">
+ <form id="search" name="search" method="post" action="{$baseurl}search.php">
+ <label for="s">Search:</label>
+ <input type="text" id="s" name="s" size="16" />
+ <input type="submit" name="g" value="go" />
+ </form>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="topbar" colspan="2" height="22">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><font color="#ffffff">&nbsp;{section name=topbar_left loop=$topbar_left}<a href="{$baseurl}{$topbar_left[topbar_left].link}"><font color="#ffffff">{$topbar_left[topbar_left].name}</font></a>{if !$smarty.section.topbar_left.last} | {/if}{/section}</font></td>
+ <td align="right"><font color="#ffffff">{if isset($username)}<a href="{$baseurl}login.php?logout=True"><font color="#ffffff">Logout [{$username}]</font></a> | {/if}{section name=topbar_right loop=$topbar_right}<a href="{$baseurl}{$topbar_right[topbar_right].link}"><font color="#ffffff">{$topbar_right[topbar_right].name}</font></a>{if !$smarty.section.topbar_right.last} | {/if}{/section}&nbsp;</font></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+{if $leftbar eq "on"}
+ <td id="leftbar" valign="top" bgcolor="#a6afc2">
+{if isset($leftbar_menu)}
+ <ul id="menu">
+{section name=leftbar_menu loop=$leftbar_menu}
+ <li><a class="menuitem" href="{$baseurl}{$leftbar_menu[leftbar_menu].link}">{$leftbar_menu[leftbar_menu].name}</a></li>
+{/section}
+ </ul>
+{/if}
+{if isset($leftbar_submenu)}
+ <p></p>
+ <ul id="submenu">
+{if isset($leftbar_submenu_title) && $leftbar_submenu_title ne ""}
+ <li>{$leftbar_submenu_title}</li>
+{/if}
+{section name=leftbar_submenu loop=$leftbar_submenu}
+ <li><a class="menuitem" href="{$baseurl}{$leftbar_submenu[leftbar_submenu].link}">{$leftbar_submenu[leftbar_submenu].name}</a></li>
+{/section}
+ </ul>
+{/if}
+ </td>
+{/if}
+ <td width="100%" valign="top">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td id="header" bgcolor="#d8d4e2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+{if $title ne ""} <h1>{$title}{if $subtitle ne ""} - {$subtitle}{/if}</h1>{/if}
+{if $desc ne ""} <h2>{$desc}</h2>{/if}
+ </td>
+ <td align="right" valign="top">
+{if isset($status)} <p>{$status}</p>{/if}
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="content" height="100%" valign="top" bgcolor="#ffffff">
+ <!-- begin content -->
diff --git a/scire/.smarty/templates/index.tpl b/scire/.smarty/templates/index.tpl
new file mode 100644
index 0000000..bb57553
--- /dev/null
+++ b/scire/.smarty/templates/index.tpl
@@ -0,0 +1,8 @@
+{include file="header.tpl" title="Main Page"}
+<p>
+Welcome to Scire, {$user}<br>
+This is the index page. It has index-y stuff on it. ok?
+back off man it's not finished.
+{$message|escape:"htmlall"}
+</p>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/job.tpl b/scire/.smarty/templates/job.tpl
new file mode 100644
index 0000000..8919f02
--- /dev/null
+++ b/scire/.smarty/templates/job.tpl
@@ -0,0 +1,307 @@
+{include file="header.tpl" title="Jobs"}
+{if $Action eq "create"}
+<h1>Add a Job</h1>
+<form action="" method="post" name="add_jobform">
+<table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td align="left" valign="top">
+ <table class="box" width="90%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Script Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="scripts">Scripts:</label></td>
+ </tr>
+ <tr>
+ {if isset($get.scriptid)}
+
+ <td>Selected script:</td>
+ <td><input type="hidden" name="script" value="{$script.scriptid}">{$script.name}</td>
+ {else}
+ <td>Categories will go here</td>
+ <td>
+ <select name="script" size="1" >
+ {foreach from=$scripts item=script key=key}
+ <option value="{$script.scriptid}">
+ {$script.name}</option>
+ {/foreach}
+ </select>
+ </td>
+ {/if}
+ </tr>
+ {if !isset($get.scriptid)}
+ <tr>
+ <td colspan="2">Or just type in the ID of the script: <input type="text" name="scriptID" ></td>
+ </tr>
+ {/if}
+ <tr>
+ <td colspan="2"><hr><h4>Override Script default values:</h4><br>
+ Permission: <select size="1" name="permission">
+ {foreach from=$perms item=perm key=id}
+ <option value="{$perm}"
+ {if isset($script.permission)}
+ {if $perm eq $script.permission} selected {/if}
+ {/if}
+ >{$perm}</option>
+ {/foreach}
+ </select><br>
+
+ Set Priority: <select size="1" name="priority">
+ {foreach from=$priorities item=priority key=id}
+ <option value="{$priority}"
+ {if isset($script.priority)}
+ {if $priority eq $script.priority} selected {/if}
+ {/if}
+ >{$priority}</option>
+ {/foreach}
+ </select><br>
+ Log Location: <input type="text" name="log_location" value="{$script.log_location}"><br>
+ Success Code: (not worrying bout this now)<br>
+ Set dynamic content: <br>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+
+ <td align="right" valign="top">
+ <table class="box" width="50%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Client Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ {if isset($get.clientid)}
+
+ <td>Selected client:</td>
+ <td><input type="hidden" name="clients[]" value="{$client.hostname}">{$client.hostname}</td>
+ {elseif isset($get.cgroupid)}
+ <td>Selected clientgroup:</td>
+ <td><input type="hidden" name="cgroups[]" value="{$get.cgroupid}">NAME HERE</td>
+ {else}
+ <td><label for="clientgroups">Clientgroups:</label></td>
+ <td><label for="clients">Clients:</label></td>
+ </tr>
+ <tr>
+ <td>
+ <select name="clientgroups[]" size="18" multiple="multiple">
+ {foreach from=$cgroups item=cgroup key=id}
+ <option value="{$id}">{$cgroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ <td>
+ <select name="clients[]" size="18" multiple="multiple">
+ {section loop=$clients name=clients}
+ <option value="{$clients[clients].clientid}">{$clients[clients].hostname}</option>
+ {/section}
+ </select>
+ </td>
+ {/if}
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ Input staging client hostname (optional): <input type="text" name="staging"><br>
+ Staging success: <input type="radio" name="staging_success" value="result">Positive Result Code <input type="radio" name="staging_success" value="user">Manually approved
+ </td>
+ </tr>
+ </table>
+ <hr>
+ <table>
+ {if $dyn_tags}
+ <tr>
+ <th>Dynamic Tag</th><th>Value</th>
+ </tr>
+ {foreach from=$dyn_tags item=tag key=tagnum}
+ <tr>
+ <td>Tag: <b>{$tag}</b></td><td><input type="text" name="tag_{$tag}" value="{$tag_values[$tag]}" /></td>
+ </tr>
+ {/foreach}
+ {/if}
+</table>
+<hr>
+Job Description: <br><textarea name="description" rows="3" cols="40"></textarea><br>
+<table><tr>
+ <td><label for="runs_chedule">Run schedule:</label></td>
+ <td><input type="text" id="run_schedule" name="run_schedule" size="25" value="{$job.run_schedule}" /></td>
+ <td><label for="validity_period">Validity Period:<br>(in minutes)</label></td>
+ <td><input type="text" id="validity_period" name="validity_period" size="25" value="{$job.validity_period}" /></td>
+</tr></table>
+ <fieldset>
+ <legend>Run Schedule</legend>
+ <table>
+ <tr>
+ <td>
+ <p>Minute(s):</p>
+ {html_options name=minutes options=$minutes selected=$selectedMinute size=6}
+ </td>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td>
+ <p>Hour(s):</p>
+ {html_options name=hours options=$hours selected=$selectedHour size=6}
+ </td>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td>
+ <p>Month(s):</p>
+ {html_options name=months options=$months selected=$selectedMonth size=6}
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <p>Day(s):</p>
+ {html_options name=days options=$days selected=$selectedDay size=6}
+ </td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td>
+ <p>Weekday(s):</p>
+ {html_options name=weekdays options=$weekdays selected=$selectedWeekday size=6}
+ </td>
+ </tr>
+ </table>
+
+ </fieldset>
+<table>
+<tr><td>
+<script language="JavaScript" src="calendar/calendar3.js"></script><!-- Date only with year scrolling -->
+<label for="deploy_time">Start time: <input type="Text" name="deploy_time" value="">
+ <a href="javascript:cal1.popup();"><img src="calendar/img/cal.gif" width="16" height="16" border="0" alt="Click Here to Pick up the date"></a></label>
+</td>
+<td>
+<label for="expiration_time">End time: <input type="Text" name="expiration_time" value="">
+ <a href="javascript:cal2.popup();"><img src="calendar/img/cal.gif" width="16" height="16" border="0" alt="Click Here to Pick up the date"></a></label>
+<script language="JavaScript">
+ <!-- // create calendar object(s) just after form tag closed
+ // specify form element as the only parameter (document.forms['formname'].elements['inputname']);
+ // note: you can have as many calendar objects as you need for your application
+ var cal1 = new calendar3(document.forms['add_jobform'].elements['deploy_time']);
+ cal1.year_scroll = false;
+ cal1.time_comp = true;
+ var cal2 = new calendar3(document.forms['add_jobform'].elements['expiration_time']);
+ cal2.year_scroll = false;
+ cal2.time_comp = true;
+ //-->
+ </script>
+</td>
+</tr>
+</table>
+<hr>
+Job dependency stuff here.<B>CODE ME</B><br>
+<!-- Set notification email address: <input type="radio" name="notify_addr" value="{$useremail}">{$useremail}</input><input type="radio" name="notify_addr" value="new"><input type="text" name="notify_new"></input> -->
+<input type="submit" name="ADD" value="ADD JOB!!!">
+</form>
+{elseif $Action eq "edit"}
+<h1>Edit Job</h1>
+<form action="" method="post" name="edit_jobform">
+<table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td colspan="2" align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Job</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="addpriority">*Priority:</label></td>
+ <td><input type="text" id="editpriority" name="editpriority" value="{$job.priority}" /></td>
+ <td><label for="creator">Creator:</label></td>
+ <td><input type="text" id="creator" disabled name="creator" value="{$job.creator}" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="permission:">Permission:</label></td>
+ <td><input type="text" id="permission" name="permission" value="{$job.permission}" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="description">Description:</label></td>
+ <td colspan="3"><textarea id="description" name="description" cols="55" rows="5" > {$job.description}</textarea></td>
+ </tr>
+ <tr>
+ <td><label for="script">Script:</label></td>
+ <td><select id="script" name="script" size="1">
+ {foreach item=sc from=$scripts }
+ {if $sc.scriptid eq $job.script}
+ <option value="{$sc.scriptid}" selected="selected">{$sc.name}</option>
+ {else}
+ <option value="{$sc.scriptid}">{$sc.name}</option>
+ {/if}
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="runs_chedule">Run schedule:</label></td>
+ <td><input type="text" id="run_schedule" name="run_schedule" size="25" value="{$job.run_schedule}" /></td>
+ <td><label for="validity_period">Validity Period:<br>(in minutes)</label></td>
+ <td><input type="text" id="validity_period" name="validity_period" size="25" value="{$job.validity_period}" /></td>
+ </tr>
+ </table>
+
+ <fieldset>
+ <legend>Run Schedule</legend>
+ <table>
+ <tr>
+ <td>
+ <p>Minute(s):</p>
+ {html_options name=minutes options=$minutes selected=$selectedMinute size=6}
+ </td>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td>
+ <p>Hour(s):</p>
+ {html_options name=hours options=$hours selected=$selectedHour size=6}
+ </td>
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
+ <td>
+ <p>Month(s):</p>
+ {html_options name=months options=$months selected=$selectedMonth size=6}
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <p>Day(s):</p>
+ {html_options name=days options=$days selected=$selectedDay size=6}
+ </td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td>
+ <p>Weekday(s):</p>
+ {html_options name=weekdays options=$weekdays selected=$selectedWeekday size=6}
+ </td>
+ </tr>
+ </table>
+
+ </fieldset>
+
+
+ <input type="hidden" name="jobid" value="{$job.jobid}">
+ <p><input type="submit" name="EditJobSubmit" value="Save Changes" /></form></p>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+{elseif $Action eq "delete"}
+<h1>DELETING</h1>
+<b>Are you absolutely SURE you want to delete job {$jobid}:<br>Description:{$job.description}?</b>
+<input type="hidden" name="jobid" value="{$jobid}">
+<input type="submit" name="delete_confirm" value="Yes, get rid of it!"><input type="submit" name="delete_cancel" value="No wait!">
+{/if}
+
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/jobs.tpl b/scire/.smarty/templates/jobs.tpl
new file mode 100755
index 0000000..9f9b586
--- /dev/null
+++ b/scire/.smarty/templates/jobs.tpl
@@ -0,0 +1,46 @@
+{include file="header.tpl" title="Jobs"}
+<form action="" method="post" name="jobsform">
+<p>
+ <strong>Search filter:
+ <input type="text" name="searchfield">
+ </strong>
+</p>
+{if $jobs}
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Jobs</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ {foreach from=$fields item=i key=k}
+ <th>
+ <a href="jobs.php{if $f_attr[$i].sortable}?sorton={$i}&sortdir={if $sorton eq $i and $sortdir eq "desc"}asc{else}desc{/if}{/if}">{$f_attr[$i].name}</a> {if $f_attr[$i].sortable}<img src="images/sort_{if $sorton eq $i and $sortdir eq "desc"}desc{else}asc{/if}.png">{/if}
+ </th>
+ {/foreach}
+
+ <th>Actions</th>
+ </tr>
+ {section name=jobs loop=$jobs}
+ <tr>
+ {foreach from=$fields item=item key=key}
+ {if $item eq "hostname"}
+ <td><a href="job.php?jobid={$jobs[jobs].jobid}&Action=edit">{$jobs[jobs].hostname}</a></td>
+ {else}
+ <td>{$jobs[jobs].$item}</td>
+ {/if}
+ {/foreach}
+ <td>
+ <a href="job.php?jobid={$jobs[jobs].jobid}&Action=view">View Details</a>
+ <a href="job.php?jobid={$jobs[jobs].jobid}&Action=edit">Edit</a>
+ <a href="job.php?jobid={$jobs[jobs].jobid}&Action=delete">Delete</a>
+
+ </td>
+ </tr>
+ {/section}
+
+ </td></tr>
+
+ </table>
+{/if}
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/login.tpl b/scire/.smarty/templates/login.tpl
new file mode 100644
index 0000000..d8c729c
--- /dev/null
+++ b/scire/.smarty/templates/login.tpl
@@ -0,0 +1,39 @@
+{include file="header.tpl" title="Login"}
+
+<div style="display: table; width: 100%; height: 100%; _position: relative; overflow: hidden;">
+<div style="_position: absolute; _top: 50%; display: table-cell; vertical-align: middle;">
+<div style="_position: relative; _top: -50%;">
+<table class="box" align="center" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Please Login to use Scire</td>
+ </tr>
+ <tr>
+ <td>
+ <form id="login" name="login" method="post" action="">
+ <table border="0" cellspacing="5" cellpadding="5">
+ <tr>
+
+ <td><label for="username">Username:</label></td>
+ <td><input type="text" id="username" name="username" value="" /></td>
+ </tr>
+ <tr>
+ <td><label for="passwd">Password:</label></td>
+ <td><input type="password" id="passwd" name="passwd" /></td>
+ </tr>
+ <tr>
+
+ <td colspan="2" align="center">
+ <input type="submit" name="submit" value="Login" />
+ </td>
+ </tr>
+ </table>
+ </form>
+ </td>
+ </tr>
+ </table>
+
+</div>
+</div>
+</div>
+
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/message.tpl b/scire/.smarty/templates/message.tpl
new file mode 100644
index 0000000..de37cdb
--- /dev/null
+++ b/scire/.smarty/templates/message.tpl
@@ -0,0 +1,6 @@
+{include file="header.tpl"}
+
+ <p>
+ {$message|escape:"htmlall"}
+ </p>
+{include file="footer.tpl"} \ No newline at end of file
diff --git a/scire/.smarty/templates/modules.tpl b/scire/.smarty/templates/modules.tpl
new file mode 100755
index 0000000..e70ed62
--- /dev/null
+++ b/scire/.smarty/templates/modules.tpl
@@ -0,0 +1,4 @@
+{include file="header.tpl" title="Modules"}
+<form action="" method="post" name="modulesform">
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/modules/Exporter/index.tpl b/scire/.smarty/templates/modules/Exporter/index.tpl
new file mode 100644
index 0000000..93cb8e5
--- /dev/null
+++ b/scire/.smarty/templates/modules/Exporter/index.tpl
@@ -0,0 +1,36 @@
+{include file="header.tpl" title="Server Information Exporter"}
+List of clients in group:
+<form name="form1" method="post" action="#">
+<select name="group" size="1">
+<option value=""></option>
+<!--
+foreach ($profile_list as $profile)
+ print "<option value=\"". $profile['profileid']."\">".$profile['profile_name']."</option>\n";
+?> -->
+</select>
+<input type="submit" name="ChangeView" value="Go, because i hate doing it with javascript.">
+</form>
+<form name="form2" method="post" action="ExportedData.php">
+<table><tr>
+ <th>HOSTNAME</th>
+ <th>STATUS</th>
+ <th>IP</th>
+ <th>MAC</th>
+ <th>ASSET ID</th>
+ <th>INSTALL TIME</th>
+ </tr>
+<!--
+foreach ($clients as $client)
+ print "<tr><td>".$client['hostname']."</td>\n";
+ print "<td>".$client['status']."</td>\n";
+ print "<td>".$client['ip']."</td>\n";
+ print "<td>".$client['mac']."</td>\n";
+ print "<td>".$client['assetid']."</td>\n";
+ print "<td>".$client['installtime']."</td>\n";
+?> -->
+</table>
+<hr>
+<input type="submit" name="ExportToXML" value="Export To XML">
+<input type="submit" name="ExportToCSV" value="Export To CSV">
+<input type="submit" name="ExportToTXT" value="Export To TXT">
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/modules/quickstart/index.tpl b/scire/.smarty/templates/modules/quickstart/index.tpl
new file mode 100644
index 0000000..8440724
--- /dev/null
+++ b/scire/.smarty/templates/modules/quickstart/index.tpl
@@ -0,0 +1,86 @@
+{include file="header.tpl" title="Quickstart Server"}
+<h3>Quickstart Server Status Overview</h3>
+<form name="form1" method="post" action="#">
+List of clients currently installing:<br>
+<table class="table" border="2">
+ <tr>
+ <th>MAC</th>
+ <th>IP</th>
+ <th>PROFILE</th>
+ <th>STATUS</th>
+ </tr>
+{foreach from=$clients item=client key=key}
+ {if $client.status eq 'Installing'}
+ <tr>
+ <td>{$client.mac}</td>
+ <td>{$client.ip}</td>
+ <td>{$client.profile}</td>
+ <td>{$client.status}</td>
+ </tr>
+
+ {/if}
+{/foreach}
+</table>
+List of clients pending installation:<br>
+<table class="table">
+ <tr>
+ <th>MAC</th>
+ <th>IP</th>
+ <th>PROFILE</th>
+ <th>STATUS</th>
+ </tr>
+{foreach from=$clients item=client key=key}
+ {if $client.status eq 'Scheduled for Install'}
+ <tr>
+ <td>{$client.mac}</td>
+ <td>{$client.ip}</td>
+ <td>{$client.profile}</td>
+ <td>{$client.status}</td>
+ </tr>
+
+ {/if}
+{/foreach}
+</table>
+List of completed installations:<br>
+<table class="table">
+ <tr>
+ <th>MAC</th>
+ <th>IP</th>
+ <th>PROFILE</th>
+ <th>STATUS</th>
+ </tr>
+{foreach from=$clients item=client key=key}
+ {if $client.status eq 'Install Complete'}
+ <tr>
+ <td>{$client.mac}</td>
+ <td>{$client.ip}</td>
+ <td>{$client.profile}</td>
+ <td>{$client.status}</td>
+ </tr>
+
+ {/if}
+{/foreach}
+</table>
+List of available profiles:<br>
+<table class="table">
+ <tr>
+ <th>Profile ID</th>
+ <th>Profile Name</th>
+ <th>Filename/URI</th>
+ <th>Description</th>
+ </tr>
+{foreach from=$profiles item=profile key=key}
+ <tr>
+ <td>{$profile.profileid}</td>
+ <td>{$profile.profile_name}</td>
+ <td>{$profile.location}</td>
+ <td>{$profile.description}</td>
+ </tr>
+
+{/foreach}
+</table>
+
+
+<input type="submit" name="Submit" value="Submit">
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/permissions.tpl b/scire/.smarty/templates/permissions.tpl
new file mode 100644
index 0000000..d6b1103
--- /dev/null
+++ b/scire/.smarty/templates/permissions.tpl
@@ -0,0 +1,94 @@
+{include file="header.tpl" title="Permissions"}
+<form action="" method="post" name="userspermsform">
+<table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Permissions</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>{if $type eq "clients"}Client(s){else}User(s){/if}</th>
+ <th>Perm. Name</th>
+ <th>{if $type eq "clients"}from User(s){else}on Client(s){/if}</th>
+ <th width="7%">Allow/Deny</th>
+ <th>Active</th>
+ <th>Actions</th>
+ </tr>
+ {foreach from=$acls item=acl key=k}
+ <tr bgcolor="{cycle values="#eeeeee,#dddddd"}">
+ <td>
+ {if $type eq "clients"}
+ {if $acl.axo} <!-- we have individual clients -->
+ {foreach from=$acl.axo.clients item=client key=key2}
+ <font style="background-color:#A0F8FF">Client: {$client}</font><br>
+ {/foreach}
+ {/if}
+ {foreach from=$acl.axo_groups item=group key=groupid}
+ <font style="background-color:#FFFACD">ClientGroup: {$cgroups[$group]} </font><br>
+ {/foreach}
+ {else}
+
+ {if $acl.aro} <!-- we have individual users -->
+ {foreach from=$acl.aro.users item=user key=key2}
+ <font style="background-color:#A0F8FF">User: {$user}</font><br>
+ {/foreach}
+ {/if}
+ {foreach from=$acl.aro_groups item=group key=groupid}
+ <font style="background-color:#FFFACD">UserGroup: {$ugroups[$group]} </font><br>
+ {/foreach}
+ {/if}
+ </td>
+ <td>
+ {foreach from=$acl.aco item=ignore key=perm_category}
+ {$acl.aco.$perm_category[0]}
+ {/foreach}
+ </td>
+ <td>
+ {if $type eq "clients"}
+ {if $acl.aro} <!-- we have individual users -->
+ {foreach from=$acl.aro.users item=user key=key2}
+ <font style="background-color:#A0F8FF">User: {$user}</font><br>
+ {/foreach}
+ {/if}
+ {foreach from=$acl.aro_groups item=group key=groupid}
+ <font style="background-color:#FFFACD">UserGroup: {$ugroups[$group]} </font><br>
+ {/foreach}
+ {else}
+ {if $acl.axo} <!-- we have individual clients -->
+ {foreach from=$acl.axo.clients item=client key=key2}
+ <font style="background-color:#A0F8FF">Client: {$client}</font><br>
+ {/foreach}
+ {/if}
+ {foreach from=$acl.axo_groups item=group key=groupid}
+ <font style="background-color:#FFFACD">ClientGroup: {$cgroups[$group]} </font><br>
+ {/foreach}
+ {/if}
+ </td>
+ {if $acl.allow}
+ <td style="background-color: #008000">Allow</td>
+ {else}
+ <td style="background-color: #DC143C">Deny</td>
+ {/if}
+ <td>
+ {if $acl.enabled}Yes{else}No{/if}
+ </td>
+ <td>
+ <a href="assign_permission.php?Action=edit&aclid={$acl.acl_id}">Edit</a>
+ <a href="assign_permission.php?Action=delete&aclid={$acl.acl_id}">Delete</a>
+ </td>
+ </tr>
+ {/foreach}
+
+ </table><hr>
+ </tr>
+ <tr>
+ <table><tr>
+ <td>
+ Blue = Single User/Client<br>
+ Tan = UserGroup/ClientGroup
+ </td>
+ <td align="right"><a href="assign_permission.php">Assign a Permission</a></td>
+ </tr>
+ </table>
+ </tr>
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/script.tpl b/scire/.smarty/templates/script.tpl
new file mode 100644
index 0000000..c4f19ec
--- /dev/null
+++ b/scire/.smarty/templates/script.tpl
@@ -0,0 +1,107 @@
+{include file="header.tpl" title="Script"}
+<form action="" method="post" name="scriptform">
+{if $Action eq "create"}
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Create a Script</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><label for="addname">*Script Name:</label></td>
+ <td><input type="text" id="addname" name="addname" value="{$addname}" /></td>
+ </tr><tr>
+ <td><label for="desc">*Description:</label></td>
+ <td><input type="text" id="desc" name="desc" size="50" value="{$desc}" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="runas">System user to run as (can be overwritten by job):</label></td>
+ <td colspan="3">Manual: <input type="text" id="runas" name="runas" value="{$runas}" /></td>
+ </tr>
+ <tr>
+ <td><input type="radio" name="runas_radio" value="root">root
+ <input type="radio" name="runas_radio" value="nobody">nobody</td>
+ <td><input type="radio" name="runas_radio" value="httpd">httpd
+ <input type="radio" name="runas_radio" value="apache">apache</td>
+ </tr>
+ <tr>
+ <td><label for="priority">Recommended Priority:</label></td>
+ <td><select name="priority" size="1">
+ {foreach from=$priorities item=pri key=key}
+ <option value="{$pri}" {if $pri eq $priority}selected{/if}>{$pri}</option>
+ {/foreach}
+ </select>
+ </td>
+ <td><label for="permission">Recommended Permission:</label></td>
+ <td>
+ <select name="permission" size="7">
+ {foreach from=$perms item=perm key=id}
+ <option value="{$perm.id}" {if $perm.id eq $permission}selected{/if}>{$perm.name}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><hr></td>
+ </tr>
+ <tr>
+ <td>*Actual Script to run on client: </td>
+ <td><input type="radio" name="script_data_type" value="load" disabled>Load from file <input type="upload" name="script_data_upload"></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td><input type="radio" name="script_data_type" value="manual" checked>Input manually below</td>
+ </tr>
+ <tr>
+ <td colspan="2"><textarea name="script_data_manual" rows="10" cols="80" >
+{$script_data}
+ </textarea> </td>
+ </tr>
+
+ <tr>
+ <td><input type="submit" name="continue" value="Find Dynamic Tags">this button will take input above and parse and look for dynamic tags. it will then generate the table below
+ </td>
+ </tr>
+
+ </table>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ {if $dyn_tags}
+ <tr>
+ <th>Dynamic Tag</th><th>Default Value</th>
+ </tr>
+ {foreach from=$dyn_tags item=tag key=tagnum}
+ <tr>
+ <td>Tag: <b>{$tag}</b></td><td><input type="text" name="tag_{$tag}" value="" /></td>
+ </tr>
+ {/foreach}
+ <tr>
+ <td><hr></td>
+ </tr>
+ {/if}
+ <tr>
+ <td>Success return code (default 0): <input type="text" name="success_code" value="0">
+ </td>
+ </tr>
+ <tr>
+ <td>Post Processing Script:</td><td><input type="radio" name="pps_type" value="none" checked>No post-processing needed, this script just returns.</td>
+ </tr>
+ <tr>
+ <td></td><td><input type="radio" name="pps_type" value="load" disabled >Load from file: <input type="upload" name="pps_load"></td>
+ </tr>
+ <tr>
+ <td></td><td><input type="radio" name="pps_type" value="manual" >Input Manually below</td>
+ </tr>
+ <tr>
+ <td colspan="2"><textarea name="pps_data" rows="6" cols="80"></textarea></td>
+ </tr>
+
+ </table>
+ </td></tr>
+ <input type="submit" name="add_script" value="Add Script">
+{/if}
+
+
+
+
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/script_library.tpl b/scire/.smarty/templates/script_library.tpl
new file mode 100644
index 0000000..be796f5
--- /dev/null
+++ b/scire/.smarty/templates/script_library.tpl
@@ -0,0 +1,32 @@
+{include file="header.tpl" title="Script Library"}
+<form action="" method="post" name="scriptsform">
+
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle" colspan="6">Scripts</td></tr>
+ <tr class="table">
+ <th>Name</th><th>Description</th><th>Last Used</th><th>OS</th><th>Permissions</th><th>Actions</th>
+ </tr>
+ {foreach from=$scripts item=script key=key}
+ <tr class="table">
+ <td>{$script.name}</td>
+ <td>{$script.description}</td>
+ <td>LAST USED HERE</td>
+ <td>ADD OS TO SCRIPT TABLE</td>
+ <td>{$script.permission}</td>
+ <td><a href="job.php?Action=create&scriptid={$script.scriptid}">Create Job</a>|<a href="script.php?Action=Edit&scriptid={$script.scriptid}">Edit</a>|<a href="script.php?Action=Delete&scriptid={$script.scriptid}">Delete</a><a href="script.php?Action=Copy&scriptid={$script.scriptid}">Copy as New</a></td>
+ </tr>
+ {/foreach}
+ <tr class="table">
+ <td>Install Package</td>
+ <td>This will install a specified package to the client.</td>
+ <td>Today</td>
+ <td>Gentoo</td>
+ <td>Install</td>
+ <td><a href="add_job.php?scriptid=1">Create Job</a>|<a href="script.php?Action=Edit&scriptid=1">Edit</a>|<a href="script.php?Action=Delete&scriptid=1">Delete</a><a href="script.php?Action=Copy%scriptid=1">Copy as New</a></td>
+
+ </tr>
+
+ </table>
+
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/settings.tpl b/scire/.smarty/templates/settings.tpl
new file mode 100755
index 0000000..a4d4742
--- /dev/null
+++ b/scire/.smarty/templates/settings.tpl
@@ -0,0 +1,50 @@
+{include file="header.tpl" title="Settings"}
+<form action="" method="post" name="settingsform">
+
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Settings</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><label for="start_page">Start Page:</label></td>
+ <td><input type="text" name="start_page" value="{$start_page}"></td>
+ </tr>
+ <tr>
+ <td><label for="theme">Theme:</label></td>
+ <td><select name="theme">
+ {section name=theme loop=$themes}
+ <option value="{$themes[theme].link}" {if $themes[theme].link eq $theme} selected {/if}
+ >{$themes[theme].name}</option>
+ {/section}
+ </select></td>
+ </tr>
+ <tr>
+ <td><label for="language">Language (not yet available):</label></td>
+ <td><select name="language">
+ {section name=lang loop=$languages}
+ <option value="{$languages[lang].value}">{$languages[lang].name}</option>
+ {/section}
+ </select></td>
+ </tr>
+ <tr>
+ <td><label for="notification">Send Notifications to:</label></td>
+ <td><input type="radio" name="notification" value="phone" {if $notification eq "phone"} checked {/if}>Phone</td>
+ <td><input type="radio" name="notification" value="pager" {if $notification eq "pager"} checked {/if}>Pager</td>
+ </tr>
+ <tr>
+ <td><label for="per_page">Max Jobs/Clients to show per page:</label></td>
+ <td><input type="radio" name="per_page" value="2" {if $per_page eq "2"} checked {/if}>25</td>
+ <td><input type="radio" name="per_page" value="3" {if $per_page eq "3"} checked {/if}>50</td>
+ <td><input type="radio" name="per_page" value="10" {if $per_page eq "10"} checked {/if}>100</td>
+ </tr>
+ <tr>
+ <td><label for="vacation">On Vacation, contact:</label>
+
+ </td></tr>
+ <tr><td><input type="submit" name="save_settings" value="Save Settings"></td>
+ </tr>
+ </table>
+
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/settings_page.tpl b/scire/.smarty/templates/settings_page.tpl
new file mode 100644
index 0000000..1700377
--- /dev/null
+++ b/scire/.smarty/templates/settings_page.tpl
@@ -0,0 +1,32 @@
+{include file="header.tpl" title="$View Page Settings"}
+<form action="" method="post" name="settingsform">
+
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle" width="3%">Sort On</td><td class="boxtitle" width="10%">View Order (blank to not show)</td><td class="boxtitle">Field Name</td></tr>
+ {foreach from=$fields item=item key=key}
+ <tr class="table">
+ <td>{if $item.sortable}
+ <input type="radio" name="sorton" value="{$key}"
+ {if $sorton eq $key} checked {/if}
+ >{/if}
+ </td>
+ <td><input type="text" name="{$View}_{$key}"
+ value="{if $curr_list[$key]}{$curr_list[$key]}{/if}"
+ size="5"></td>
+ <td>{$item.name}</td>
+ </tr>
+ {/foreach}
+ <tr>
+ <td><label for="sortdir">Sort Direction:</label></td>
+ <td>
+ <select name="sortdir">
+ <option value="asc" {if $sortdir eq "asc"} selected {/if}>Ascending</option>
+ <option value="desc" {if $sortdir eq "desc"} selected {/if}>Descending</option>
+ </select>
+ </td>
+ </tr>
+ <tr><td><input type="submit" name="save_{$View}_settings" value="Save Settings"></td></tr>
+ </table>
+
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/ui_permissions.tpl b/scire/.smarty/templates/ui_permissions.tpl
new file mode 100755
index 0000000..b6f7b13
--- /dev/null
+++ b/scire/.smarty/templates/ui_permissions.tpl
@@ -0,0 +1,196 @@
+{include file="header.tpl" title="Scire User Interface Permissions"}
+<form action="" method="post" name="ui_permform">
+{if $Action eq "delete"}
+<b>Are you absolutely SURE you want to delete this ACL?</b>
+<input type="hidden" name="aclid" value="{$aclid}">
+<input type="submit" name="delete_confirm" value="Yes, that's why I clicked 'Delete', duh!"><input type="submit" name="delete_cancel" value="No wait!">
+{elseif $Action eq "add" or $Action eq "edit"}
+<table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td align="center" valign="top">
+ <table class="box" width="50%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">User Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="usergroups">Usergroups:</label></td>
+ <td><label for="users">Users:</label></td>
+ </tr>
+ <tr>
+ {if isset($get.username)}
+ <td>Selected User:</td>
+ <td><input type="hidden" name="users[]" value="{$get.username}">{$get.username}</td>
+ {elseif isset($get.usergroup)}
+ {else}
+ <td>
+ <select name="usergroups[]" size="18" multiple="multiple">
+ {foreach from=$ugroups item=ugroup key=id}
+ <option value="{$id}"
+ {if isset($acl)}
+ {foreach from=$acl.aro_groups item=group key=groupid}
+ {if $id eq $group} selected {/if}
+ {/foreach}
+ {/if}
+ >{$ugroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ <td>
+ <select name="users[]" size="18" multiple="multiple">
+ {section loop=$users name=users}
+ <option value="{$users[users].username}"
+ {if isset($acl)}
+ {foreach from=$acl.aro.users item=user key=key2}
+ {if $users[users].username eq $user} selected {/if}
+ {/foreach}
+ {/if}
+ >{$users[users].username}</option>
+ {/section}
+ </select>
+ </td>
+ {/if}
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="50%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Permission Selection</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="perm">Permissions (choose an existing or create a new one):</label></td>
+ </tr>
+ <tr>
+ <td>
+ <select name="perm" size="7">
+ {foreach from=$perms item=perm key=id}
+ <option value="{$perm}"
+ {if isset($acl)}
+ {foreach from=$acl.aco item=ignore key=perm_category}
+ {if $perm eq $acl.aco.$perm_category[0]} selected {/if}
+ {/foreach}
+ {/if}
+ >{$perm}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="newpermname">New Permission Name:</label><input name="newpermname" type="text" size="20"></td>
+ </tr>
+ <tr>
+ <td><label for="newpermdesc">New Permission Description:</label></td>
+ </tr>
+ <tr>
+ <td><textarea name="newpermdesc" rows="3" cols="20"></textarea></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table
+ </td>
+ </tr>
+ <tr>
+ <td align="center"><input type="radio" name="allow" value="1"
+ {if isset($acl)}
+ {if $acl.allow} checked {/if}
+ {else}
+ checked
+ {/if}
+ >Allow
+ <input type="radio" name="allow" value="0"
+ {if isset($acl)}
+ {if (!$acl.allow)} checked {/if}
+ {/if}
+ >Deny</td>
+ <td align="center"><input type="checkbox" name="active" value="1"
+ {if isset($acl)}
+ {if $acl.enabled} checked {/if}
+ {else}
+ checked
+ {/if}
+ >Active (vs. hidden)</td>
+ <td align="right" valign="bottom">
+ <label for="note">Note:</label><input type="text" name="note"
+ {if isset($acl)}
+ value="{$acl.note}"
+ {/if}
+ >
+ {if isset($acl)}
+ <input type="hidden" name="editing" value="{$acl.acl_id}">
+ <input type="submit" name="editperm_submit" value="Update Permission">
+ {else}
+ <input type="submit" name="addperm_submit" value="Assign Permission">
+ {/if}
+ </td>
+ </tr>
+</table>
+{else}
+<table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Scire User Interface Permissions</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>User(s)</th>
+ <th>Perm. Name</th>
+ <th width="7%">Allow/Deny</th>
+ <th>Active</th>
+ <th>Actions</th>
+ </tr>
+ {foreach from=$acls item=acl key=k}
+ <tr bgcolor="{cycle values="#eeeeee,#dddddd"}">
+ <td>
+ {if $acl.aro} <!-- we have individual users -->
+ {foreach from=$acl.aro.users item=user key=key2}
+ <font style="background-color:#A0F8FF">User: {$user}</font><br>
+ {/foreach}
+ {/if}
+ {foreach from=$acl.aro_groups item=group key=groupid}
+ <font style="background-color:#FFFACD">UserGroup: {$ugroups[$group]} </font><br>
+ {/foreach}
+ </td>
+ <td>
+ {foreach from=$acl.aco item=ignore key=perm_category}
+ {$acl.aco.$perm_category[0]}
+ {/foreach}
+ </td>
+ {if $acl.allow}
+ <td style="background-color: #008000">Allow</td>
+ {else}
+ <td style="background-color: #DC143C">Deny</td>
+ {/if}
+ <td>
+ {if $acl.enabled}Yes{else}No{/if}
+ </td>
+ <td>
+ <a href="ui_permissions.php?Action=edit&aclid={$acl.acl_id}">Edit</a>
+ <a href="ui_permissions.php?Action=delete&aclid={$acl.acl_id}">Delete</a>
+ </td>
+ </tr>
+ {/foreach}
+
+ </table><hr>
+ </tr>
+ <tr>
+ <table><tr>
+ <td>
+ Blue = Single User/Client<br>
+ Tan = UserGroup/ClientGroup
+ </td>
+ <td align="right"><a href="ui_permissions.php?Action=add">Assign a Permission</a></td>
+ </tr>
+ </table>
+ </tr>
+{/if}
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/user.tpl b/scire/.smarty/templates/user.tpl
new file mode 100755
index 0000000..6599bae
--- /dev/null
+++ b/scire/.smarty/templates/user.tpl
@@ -0,0 +1,216 @@
+{include file="header.tpl" title="Users"}
+<form action="" method="post" name="edit_userform">
+{if $Action eq "addgroup"}
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr><td class="boxtitle">Add user to group</td></tr>
+ <tr>
+ <td colspan="2" align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle" width="15">Add</td><td class="boxtitle">Group Name</td>
+ </tr>
+ {foreach from=$groups name=ugroup item=item key=id}
+ <tr>
+ <td><input type="checkbox" name="addgroupid[]" value="{$id}"
+ {if isset($ingroups)} {if in_array($id, $ingroups)} checked {/if} {/if}
+ ></td>
+ <td>{$item}</td>
+ </tr>
+ {/foreach}
+ <tr><td>
+ <input type="hidden" name="userid" value="{$userid}">
+ <input type="submit" name="addgroup_confirm" value="Save Changes">
+ </td></tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+{elseif $Action eq "create"}
+<table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td colspan="2" align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">User</td><td class="boxtitle">Groups</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="addusername">*Username:</label></td>
+ <td><input type="text" id="addusername" name="addusername" /></td>
+ <td><label for="passwd">*Password:</label></td>
+ <td><input type="password" id="passwd" name="passwd" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="real_name">Real name:</label></td>
+ <td><input type="text" id="real_name" name="real_name" /></td>
+ <td><label for="passwd2">Confirm Password:</label></td>
+ <td><input type="password" id="passwd2" name="passwd2" /></td>
+
+ </tr>
+ <tr>
+ <td><label for="comment">Comment:</label></td>
+ <td><input type="text" id="comment" name="comment" /></td>
+ <td><label for="status">Status:</label></td>
+ <td><select id="status" name="status" size="1">
+ <option value="active" selected="selected">Active</option>
+ <option value="disabled">Disabled</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="email">*Email Address:</label></td>
+ <td><input type="text" id="email" name="email" /></td>
+ <td><label for="phone">Phone:</label></td>
+ <td><input type="text" id="phone" name="phone" /></td>
+ </tr>
+ <tr>
+ <td><label for="pager">Pager:</label></td>
+ <td><input type="text" id="pager" name="pager" /></td>
+ </tr>
+ </table>
+ <p><input type="submit" name="AddUserSubmit" value="Add User" /></p>
+ </td>
+ <td>
+ <table>
+ <tr><td>Assign user to the following groups:</td></tr>
+ <tr><td>
+ <select name="groups[]" size="10" multiple="multiple" id="groups">
+ {foreach from=$groups item=ugroup key=id}
+ <option value="{$id}">{$ugroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr></table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+{elseif $Action eq "edit"}
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td colspan="2" align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">User</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ {if check_access("Change User Pass/Name") }
+ <td><label for="editusername">*Username:</label></td>
+ <td><input type="text" id="editusername" name="editusername" value="{$user.username}"></td>
+ {else}
+ <td><label for="editusername">*Username:</label></td>
+ <td><input type="hidden" id="editusername" name="editusername" value="{$user.username}">{$user.username}</td>
+ {/if}
+ <td><label for="passwd">*Password:</label></td>
+ <td><input type="password" id="passwd" name="passwd" {if !check_access("Change User Pass/Name") }disabled {/if}/></td>
+ </tr>
+ <tr>
+ <td><label for="real_name">Real name:</label></td>
+ <td><input type="text" id="real_name" name="real_name" value="{$user.real_name}" /></td>
+ <td><label for="passwd2">Confirm Password:</label></td>
+ <td><input type="password" id="passwd2" name="passwd2" {if !check_access("Change User Pass/Name") }disabled {/if}/></td>
+ </tr>
+ <tr>
+ <td><label for="comment">Comment:</label></td>
+ <td><input type="text" id="comment" name="comment" value="{$user.comment}" /></td>
+ <td><label for="status">Status:</label></td>
+ <td>
+ <select id="status" name="status" size="1">
+ <option value="active" selected="selected">Active</option>
+ <option value="disabled">Disabled</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="email">*Email Address:</label></td>
+ <td><input type="text" id="email" name="email" value="{$user.email}" /></td>
+ <td><label for="phone">Phone:</label></td>
+ <td><input type="text" id="phone" name="phone" value="{$user.phone}" /></td>
+ </tr>
+ <tr>
+ <td><label for="pager">Pager:</label></td>
+ <td><input type="text" id="pager" name="pager" value="{$user.pager}" /></td>
+ </tr>
+ </table><input type="hidden" name="userid" value="{$user.userid}">
+ <p><input type="submit" name="EditUserSubmit" value="Update" /></p>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Groups</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Groupname</th>
+ <th>Actions</th>
+ </tr>
+ {section name=group loop=$groups}
+ <tr>
+ <td>{$groups[group].name}{if $groups[group].parent} (subgroup of {$groups[group].parent}){/if}</td>
+ <td><input type="submit" name="rmug_{$groups[group].id}" value="Remove"></td>
+ </tr>
+ {/section}
+ <tr><td><a href="user.php?userid={$user.userid}&Action=addgroup">Add user to a group</a></td></tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Permissions</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Category -> Permission</th>
+ <th>On Client(s)</th>
+ <th>Actions</th>
+ </tr>
+ {foreach from=$acls item=acl key=k}
+ <tr>
+ <td>{foreach from=$acl.aco item=perm key=category}{$category} -> {$perm[0]}{/foreach}</td>
+ <td>
+ {if $acl.axo} <!-- we have individual clients -->
+ {foreach from=$acl.axo.clients item=client key=key2}
+ <font style="background-color:#A0F8FF">Client: {$client}</font><br>
+ {/foreach}
+ {/if}
+ {foreach from=$acl.axo_groups item=group key=groupid}
+ <font style="background-color:#FFFACD">ClientGroup: {$cgroups[$group]} </font><br>
+ {/foreach}
+ </td>
+ <td><form id="form1" name="form1" method="post" action=""><input type="hidden" name="perm_id" value="{$acl.acl_id}" /><input type="submit" name="submit" value="Remove" /></form></td>
+ </tr>
+ {/foreach}
+ <tr><td><a href="assign_permission.php?username={$user.username}">Assign a permission for this user</a></td></tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+{elseif $Action eq "delete"}
+<b>Are you absolutely SURE you want to delete user {$user.username}?</b>
+<input type="hidden" name="userid" value="{$user.userid}">
+<input type="submit" name="delete_confirm" value="Yes, get rid of the bastard!"><input type="submit" name="delete_cancel" value="No wait!">
+{/if}
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/users.tpl b/scire/.smarty/templates/users.tpl
new file mode 100755
index 0000000..f197a55
--- /dev/null
+++ b/scire/.smarty/templates/users.tpl
@@ -0,0 +1,37 @@
+{include file="header.tpl" title="Users"}
+<form action="" method="post" name="usersform">
+<p><strong>Search filter:
+ <input type="text" name="searchfield">
+</strong></p>
+{if $users}
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Users</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ {foreach from=$fields item=i key=k}
+ <th>
+ <a href="users.php{if $f_attr[$i].sortable}?sorton={$i}&sort={if $sorton eq $i and $sortdir eq "desc"}asc{else}desc{/if}{/if}">{$f_attr[$i].name}</a> {if $f_attr[$i].sortable}<img src="images/sort_{if $sorton eq $i and $sortdir eq "desc"}desc{else}asc{/if}.png">{/if}
+ </th>
+ {/foreach}
+ <th>Actions</th>
+ </tr>
+ {section name=users loop=$users}
+ <tr>
+ {foreach from=$fields item=item key=key}
+ {if $item eq "username"}
+ <td><a href="user.php?userid={$users[users].userid}&Action=edit">{$users[users].username}</a></td>
+ {else}
+ <td>{$users[users].$item}</td>
+ {/if}
+ {/foreach}
+ <td><a href="user.php?userid={$users[users].userid}&Action=edit">Edit</a> <a href="user.php?userid={$users[users].userid}&Action=delete">Delete</a></td>
+ </tr>
+ {/section}
+
+ </td></tr>
+ </table>
+{/if}
+</form>
+{include file="footer.tpl"}
diff --git a/scire/.smarty/templates/users_groups.tpl b/scire/.smarty/templates/users_groups.tpl
new file mode 100644
index 0000000..f838ffc
--- /dev/null
+++ b/scire/.smarty/templates/users_groups.tpl
@@ -0,0 +1,74 @@
+{include file="header.tpl" title="Users"}
+<form action="" method="post" name="usersgroupsform">
+{if $Action eq "create"}
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Create a User Group</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Add User Group</td><td class="boxtitle">Parent Group</td>
+ </tr>
+ <tr>
+ <td>
+ <label for="addgroupname">Name:</label>
+ <input type="text" name="addgroupname" id="addgroupname">
+ </td>
+ <td>
+ <select name="parentgroup" id="parentgroup">
+ {foreach item=cgroup key=ckey from=$groups}
+ <option value="{$ckey}">{$cgroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ <tr><td>as a subgroup of ---></td></tr>
+ <tr><td></td><td><input type="submit" name="addgroup" value="Add User Group"></td></tr>
+ </table>
+ </table>
+ {elseif $Action eq "edit"}
+ <input type="hidden" name="groupid" value="{$groupid}">
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">Edit User Group {$groupdata[3]}</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Edit User Group</td><td class="boxtitle">Parent Group</td>
+ </tr>
+ <tr>
+ <td>
+ <label for="editgroupname">Name:</label>
+ <input type="text" name="editgroupname" id="editgroupname" value="{$groupdata[3]}">
+ </td>
+ <td>
+ <select name="parentgroup" id="parentgroup">
+ {foreach item=cgroup key=ckey from=$groups}
+ <option value="{$ckey}" {if $groupdata[1] == $ckey} selected {/if}>{$cgroup}</option>
+ {/foreach}
+ </select>
+ </td>
+ </tr>
+ <tr><td>as a subgroup of ---></td></tr>
+ <tr><td></td><td><input type="submit" name="editgroup" value="Save Changes"></td></tr>
+ </table>
+ </table>
+ {elseif $Action eq "delete"}
+ <h1>Delete</h1>
+ <b>Are you absolutely SURE you want to delete this group?</b>
+ <input type="hidden" name="delgroup" value="{$groupid}">
+<input type="submit" name="delgroup_confirm" value="Yes, remove the group"><input type="submit" name="delete_cancel" value="No wait! Cancel!">
+ {else}
+ <table class="box" width="100%" border="1" cellpadding="0" cellspacing="0">
+ <tr><td class="boxtitle">User Groups</td></tr>
+ <tr><td>
+
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr><td class="boxtitle">Group Name</td><td class="boxtitle">Edit</td><td class="boxtitle">Delete</td></tr>
+ {foreach item=group key=key from=$groups}
+ <tr><td>{$group}</td><td><a href="users.php?View=groups&Action=edit&groupid={$key}">Edit</a></td><td><a href="users.php?View=groups&Action=delete&groupid={$key}">Delete</a></td></tr>
+ {/foreach}
+ {/if} <!-- action -->
+
+</form>
+{include file="footer.tpl"}
diff --git a/scire/2col_leftNav.css b/scire/2col_leftNav.css
new file mode 100755
index 0000000..5ced7bd
--- /dev/null
+++ b/scire/2col_leftNav.css
@@ -0,0 +1,307 @@
+/***********************************************/
+/* 2col_leftNav.css */
+/* Use with template 2col_leftNav.html */
+/***********************************************/
+
+/***********************************************/
+/* HTML tag styles */
+/***********************************************/
+
+body{
+ font-family: Arial,sans-serif;
+ color: #333333;
+ line-height: 1.166;
+ margin: 0px;
+ padding: 0px;
+}
+
+a:link, a:visited, a:hover {
+ color: #006699;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+/* overrides decoration from previous rule for hovered links */
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: Arial,sans-serif;
+ margin: 0px;
+ padding: 0px;
+}
+
+h1{
+ font-family: Verdana,Arial,sans-serif;
+ font-size: 120%;
+ color: #334d55;
+}
+
+h2{
+ font-size: 114%;
+ color: #006699;
+}
+
+h3{
+ font-size: 100%;
+ color: #334d55;
+}
+
+h4{
+ font-size: 100%;
+ font-weight: normal;
+ color: #333333;
+}
+
+h5{
+ font-size: 100%;
+ color: #334d55;
+}
+
+ul{
+ list-style-type: square;
+}
+
+ul ul{
+ list-style-type: disc;
+}
+
+ul ul ul{
+ list-style-type: none;
+}
+
+label{
+ font: bold 100% Arial,sans-serif;
+ color: #334d55;
+}
+
+
+/***********************************************/
+/* Layout Divs */
+/***********************************************/
+
+#masthead{
+ margin: 0;
+ padding: 10px 0px;
+ border-bottom: 1px solid #cccccc;
+ width: 100%;
+}
+
+#navBar{
+ margin: 0 85% 0 0;
+ padding: 0px;
+ background-color: #eeeeee;
+ border-right: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+}
+
+#content{
+ float:right;
+ width: 75%;
+ margin: 0;
+ padding: 0 3% 0 0;
+}
+
+
+/***********************************************/
+/*Component Divs */
+/***********************************************/
+
+#siteName{
+ margin: 0px;
+ padding: 0px 0px 10px 10px;
+}
+
+
+/*************** #pageName styles **************/
+
+#pageName{
+ padding: 0px 0px 10px 10px;
+}
+
+
+/************* #globalNav styles **************/
+
+#globalNav{
+color: #cccccc;
+padding: 0px 0px 0px 10px;
+white-space: nowrap;
+}
+/* 'nowrap' prevents links from line-wrapping if there are too many to fit in one line
+ this will force a horizontal scrollbar if there isn't enough room for all links
+ remove rule or change value to 'normal' if you want the links to line-wrap */
+
+#globalNav img{
+ display: block;
+}
+
+#globalNav a {
+ font-size: 90%;
+ padding: 0px 4px 0px 0px;
+}
+
+
+/************* #breadCrumb styles *************/
+
+#breadCrumb{
+ font-size: 80%;
+ padding: 5px 0px 5px 10px;
+}
+
+
+/************** .feature styles ***************/
+
+.feature{
+ padding: 0px 0px 10px 10px;
+ font-size: 80%;
+}
+
+.feature h3{
+ padding: 30px 0px 5px 0px;
+ text-align: center;
+}
+
+.feature img{
+ float: left;
+ padding: 0px 10px 0px 0px;
+ margin: 0 5px 5px 0;
+}
+/* adjust margins to change separation between the feature image and text flowing around it */
+
+
+/************** .story styles *****************/
+
+.story{
+ clear: both;
+ padding: 10px 0px 0px 10px;
+ font-size: 80%;
+}
+
+.story p{
+ padding: 0px 0px 10px 0px;
+}
+
+
+/************* #siteInfo styles ***************/
+
+#siteInfo{
+ clear: both;
+ border: 1px solid #cccccc;
+ font-size: 75%;
+ color: #cccccc;
+ padding: 10px 10px 10px 10px;
+ margin-top: 0px;
+}
+/* negative top margin pulls siteinfo up so its top border overlaps (and thus lines up with)
+ the bottom border of the navBar in cases where they "touch" */
+
+#siteInfo img{
+ padding: 4px 4px 4px 0px;
+ vertical-align: middle;
+}
+
+
+/************* #search styles ***************/
+
+#search{
+ padding: 5px 0px 5px 10px;
+ border-bottom: 1px solid #cccccc;
+ font-size: 90%;
+}
+
+#search form{
+ margin: 0px;
+ padding: 0px;
+}
+
+#search label{
+ display: block;
+ margin: 0px;
+ padding: 0px;
+}
+
+
+/*********** #navBar link styles ***********/
+
+#navBar ul a:link, #navBar ul a:visited {display: block;}
+#navBar ul {list-style: none; margin: 0; padding: 0;}
+
+/* hack to fix IE/Win's broken rendering of block-level anchors in lists */
+#navBar li {border-bottom: 1px solid #EEE;}
+
+/* fix for browsers that don't need the hack */
+html>body #navBar li {border-bottom: none;}
+
+
+/*********** #sectionLinks styles ***********/
+
+#sectionLinks{
+ position: relative;
+ margin: 0px;
+ padding: 0px;
+ border-bottom: 1px solid #cccccc;
+ font-size: 90%;
+}
+
+#sectionLinks h3{
+ padding: 10px 0px 2px 10px;
+}
+
+#sectionLinks a:link{
+ padding: 2px 0px 2px 10px;
+ border-top: 1px solid #cccccc;
+ width: 100%;
+ voice-family: "\"}\"";
+ voice-family:inherit;
+ width: auto;
+}
+
+#sectionLinks a:visited{
+ border-top: 1px solid #cccccc;
+ padding: 2px 0px 2px 10px;
+}
+
+#sectionLinks a:hover{
+ border-top: 1px solid #cccccc;
+ background-color: #dddddd;
+ padding: 2px 0px 2px 10px;
+}
+
+
+/*********** .relatedLinks styles ***********/
+
+.relatedLinks{
+ margin: 0px;
+ padding: 0px 0px 10px 10px;
+ font-size: 90%;
+}
+
+.relatedLinks h3{
+ padding: 10px 0px 2px 0px;
+}
+
+
+/************** #advert styles **************/
+
+#advert{
+ padding: 10px 0px 0px 10px;
+ font-size: 80%;
+ border-top: 1px solid #cccccc;
+}
+
+#advert img{
+ display: block;
+}
+
+
+/************** #headlines styles **************/
+
+#headlines{
+ margin: 0px;
+ padding: 10px 0px 20px 10px;
+ font-size: 80%;
+}
+
+#headlines p{
+ padding: 5px 0px 5px 0px;
+}
diff --git a/scire/DBInterface.php b/scire/DBInterface.php
new file mode 100755
index 0000000..ea0658a
--- /dev/null
+++ b/scire/DBInterface.php
@@ -0,0 +1,174 @@
+<?php
+
+function get_scire_modules() {
+ global $db;
+ $result = $db->select('*', 'modules');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_module_list() {
+ global $db;
+ $result = $db->select(array('main_content', 'name'), 'modules');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_profile_list() {
+ global $db;
+ $result = $db->select('profile_name', 'profiles');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_group_clients($group) {
+ global $db;
+ $result = $db->select('*', 'clients', '`profile` = \'' . $group . '\'');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_all_clients() {
+ global $db;
+ $result = $db->select('*', 'clients');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_client($client_id) {
+ global $db;
+ $result = $db->select('*', 'clients', '`client_id` = \'' . $client_id . '\'');
+ if ($result && count($result) > 0) {
+ return $result[0];
+ } else {
+ return false;
+ }
+}
+
+function scire_add_client($hostname, $mac, $ip, $profile, $distribution, $admin, $status) {
+ global $db;
+ $result = $db->insert('clients', array('hostname' => $hostname, 'mac' => $mac, 'ip' => $ip, 'profile' => $profile, 'distribution' => $distribution, 'administrator' => $admin, 'status' => $status));
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_edit_client($client_id, $fields) {
+ global $db;
+ $result = $db->update('clients', $fields, '`client_id` = \'' . $client_id . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_del_client($client_id) {
+ global $db;
+ $result = $db->delete('clients', '`client_id` = \'' . $client_id . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function get_scire_users() {
+ #we don't want to store the password for security reasons. <- ???
+ global $db;
+ $result = $db->select(array('username', 'comment', 'real_name'), 'users');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+function get_scire_user($username) {
+ global $db;
+ $result = $db->select('*', 'users', '`username` = \'' . $username . '\'');
+ if ($result && count($result) > 0) {
+ return $result[0];
+ } else {
+ return false;
+ }
+}
+
+function scire_add_user($username, $password, $real_name, $comment) {
+ global $db;
+ $result = $db->insert('users', array('username' => $username, 'password' => crypt($password, 447470567), 'comment' => $comment, 'real_name' => $real_name));
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_del_user($username) {
+ global $db;
+ $result = $db->delete('users', '`username` = \'' . $username . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_add_permission($perm_name, $desc, $created_by) {
+ global $db;
+ $result = $db->insert('permissions', array('perm_name' => $perm_name, 'description' => $desc, 'creator' => $created_by));
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_edit_permission($perm_name, $desc) {
+ global $db;
+ $result = $db->update('permissions', array('description' => $desc), '`perm_name` = \'' . $perm_name . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function scire_del_permission($perm_name) {
+ global $db;
+ $result = $db->delete('permissions', '`perm_name` = \'' . $perm_name . '\'');
+ if ($result) {
+ return true;
+ } else {
+ return $db->error;
+ }
+}
+
+function get_scire_permissions() {
+ global $db;
+ $result = $db->select('*', 'permissions');
+ if ($result && count($result) > 0) {
+ return $result;
+ } else {
+ return array();
+ }
+}
+
+?>
diff --git a/scire/ExportedData.php b/scire/ExportedData.php
new file mode 100755
index 0000000..622f738
--- /dev/null
+++ b/scire/ExportedData.php
@@ -0,0 +1,35 @@
+<?
+#This will be a core component and thus just show within scire.
+include('.lib/common.php');
+
+
+$clients = array();
+if ($_POST['group']) {
+ print $_POST['group'];
+ $clients = get_group_clients($_POST['group']);
+} else {
+ print "ALL";
+ $clients = get_all_clients();
+}
+if ($_POST['ExportToCSV']) {
+ print "This is a fake CSV. It has no header row.<br>";
+ foreach ($clients as $client) {
+ for ($i=0;$i< count($client);$i++) {
+ print "$client[$i],";
+ }
+ print "<br>";
+ }
+}
+elseif ($_POST['ExportToXML']) {
+}
+elseif ($_POST['ExportToTXT']) {
+ print "This is a fake tab-delimited TXT. It has no header row.<br><pre>";
+ foreach ($clients as $client) {
+ for ($i=0;$i< count($client);$i++) {
+ print "$client[$i]\t";
+ }
+ print "<br>";
+ }
+ print "</pre>";
+}
+?>
diff --git a/scire/Exporter.php b/scire/Exporter.php
new file mode 100755
index 0000000..1609cdf
--- /dev/null
+++ b/scire/Exporter.php
@@ -0,0 +1,56 @@
+
+<?
+include('.lib/common.php');
+
+$clients = array();
+if ($_POST['group']) {
+ print $_POST['group'];
+ $clients = get_group_clients($_POST['group']);
+} else {
+ print "ALL";
+ $clients = get_all_clients();
+ var_dump($clients);
+}
+
+#Get a list of the groups to put in the select box.
+$profile_list = get_profile_list();
+
+?>
+<h2>Server Information Exporter</h2>List of clients in group:
+<form name="form1" method="post" action="#">
+<select name="group" size="1">
+<option value=""></option>
+<?
+foreach ($profile_list as $profile)
+{
+ print "<option value=\"". $profile['profileid']."\">".$profile['profile_name']."</option>\n";
+}
+?>
+</select>
+<input type="submit" name="ChangeView" value="Go, because i hate doing it with javascript.">
+</form>
+<form name="form2" method="post" action="ExportedData.php">
+<table><tr>
+ <th>HOSTNAME</th>
+ <th>STATUS</th>
+ <th>IP</th>
+ <th>MAC</th>
+ <th>ASSET ID</th>
+ <th>INSTALL TIME</th>
+ </tr>
+<?
+foreach ($clients as $client)
+{
+ print "<tr><td>".$client['hostname']."</td>\n";
+ print "<td>".$client['status']."</td>\n";
+ print "<td>".$client['ip']."</td>\n";
+ print "<td>".$client['mac']."</td>\n";
+ print "<td>".$client['assetid']."</td>\n";
+ print "<td>".$client['installtime']."</td>\n";
+}
+?>
+</table>
+<hr>
+<input type="submit" name="ExportToXML" value="Export To XML">
+<input type="submit" name="ExportToCSV" value="Export To CSV">
+<input type="submit" name="ExportToTXT" value="Export To TXT">
diff --git a/scire/access_error.php b/scire/access_error.php
new file mode 100644
index 0000000..6e37b26
--- /dev/null
+++ b/scire/access_error.php
@@ -0,0 +1,11 @@
+<?php
+
+include('./.lib/common.php');
+
+if ($_GET['perm']) {
+ $smarty->assign('perm',$_GET['perm']);
+}
+
+$smarty->display('access_error.tpl');
+
+?>
diff --git a/scire/add_job.php b/scire/add_job.php
new file mode 100644
index 0000000..a5266e0
--- /dev/null
+++ b/scire/add_job.php
@@ -0,0 +1,119 @@
+<?php
+include('.lib/common.php');
+include('cron2.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+
+add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "jobs.php");
+
+$status = "";
+
+#####################################################
+#Deal with submitted forms.
+if ($_POST['ADD']) {
+ if ($_POST['script']) {
+ $script = get_scire_script($_POST['script']);
+ if ($_POST['permission']) {
+ $permission = $_POST['permission'];
+ $permission = get_scire_permission_by_name($permission);
+ $permission = $permission['permid'];
+ # print "Permission is: $permission";
+ } else {
+ $permission = $script['permission'];
+ }
+ if ($_POST['priority']) {
+ $priority = $_POST['priority'];
+ } else {
+ $priority = $script['priority'];
+ }
+ } else { $status .= "ERROR: No script selected!"; }
+ if ($_POST['description']) {
+ $description = $_POST['description'];
+ } else {
+ $description = "No description provided.";
+ }
+ $pending = sizeof($_POST['clients']) + sizeof($_POST['clientgroups']);
+
+ if (!$status and ($pending or $_POST['clientgroups'])) { #We have a script and clients;
+ # Get the schedule! All fields are required or else you're SOL
+ $scheduleComplete = $_POST["minute1"] and $_POST["hour1"] and
+ $_POST["day1"] and $_POST["month1"] and $_POST["weekday1"];
+ if ($scheduleComplete) {
+ $str = implode(" ", array($_POST["minute1"], $_POST["hour1"],
+ $_POST["day1"], $_POST["month1"], $_POST["weekday1"]));
+ } else {
+ $str = "";
+ }
+# pre_var_dump($_POST);
+# pre_var_dump($scheduleComplete);
+ pre_var_dump($str);
+
+ try {
+ $result = scire_add_job($_POST['script'], $priority, $_SESSION['userid'], $permission, $description, $pending, $_POST['clients'], $_POST['clientgroups'], $dependency, $str, $_POST['validity_period']);
+
+ if (!$result) {
+ $status .= "Job successfully added.";
+ } else {
+ $status .= "Error occurred during job addition. $result";
+ }
+ } catch (CronException $e) { print_r($e); }
+
+ }
+}
+
+
+########################################################
+if ($_GET['scriptid']) {
+ $_GET['scriptid'] = (int) $_GET['scriptid'];
+ $script = get_scire_script($_GET['scriptid']);
+ $smarty->assign('script', $script);
+# print $script['script_data'];
+ preg_match_all('/%%(.*?)%%/', $script['script_data'], $matches);
+ $smarty->assign('dyn_tags', $matches[1]);
+ foreach ($matches[1] as $tag) {
+ $tag_values[$tag] = get_dyn_tag_value($_GET['scriptid'],$tag);
+ }
+ $smarty->assign('tag_values', $tag_values);
+
+ pre_var_dump($tag_values);
+}
+
+if ($_GET['clientid']) {
+ $_GET['clientid'] = (int) $_GET['clientid'];
+ $client = get_scire_client($_GET['clientid']);
+ #$id = $acl->get_object_id("clients",$client['hostname'],'AXO'
+
+ $smarty->assign('client', $client);
+}
+########################################################
+
+$permissions = array();
+$all_permissions = $acl->get_objects(NULL, 1, 'ACO');
+foreach ($all_permissions as $categoryname => $cat) {
+ #print "Perm: $perm<br>Permname: $permname<br>";
+ if ($categoryname != $scire_ui_section) {
+ foreach ($cat as $perm) {
+ array_push($permissions, $perm);
+ }
+ }
+}
+$smarty->assign('perms', $permissions);
+#pre_var_dump($permissions);
+$smarty->assign('priorities', get_priorities());
+
+
+$scripts = get_scire_scripts();
+$smarty->assign('scripts', $scripts);
+
+$smarty->assign('cgroups', $acl->format_groups($acl->sort_groups('AXO'), TEXT));
+$clients = get_scire_clients('hostname', 'asc');
+$smarty->assign('clients', $clients);
+
+$smarty->assign('get', $_GET);
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display('add_job.tpl');
+#var_dump($clients);
+?>
diff --git a/scire/admin/2col_leftNav.css b/scire/admin/2col_leftNav.css
new file mode 120000
index 0000000..064a6ba
--- /dev/null
+++ b/scire/admin/2col_leftNav.css
@@ -0,0 +1 @@
+../2col_leftNav.css \ No newline at end of file
diff --git a/scire/admin/add_client.php b/scire/admin/add_client.php
new file mode 100644
index 0000000..67d3576
--- /dev/null
+++ b/scire/admin/add_client.php
@@ -0,0 +1,60 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ ####################################################
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+
+ if($_POST['submit']) {
+ if (!$_POST['hostname']) { $status .= "ERROR: Hostname required! "; }
+ if (!$_POST['mac']) { $status .= "ERROR: Hostname required! "; }
+ if (!$_POST['ip']) { $status .= "ERROR: Hostname required! "; }
+ if ($_POST['hostname'] and $_POST['mac'] and $_POST['ip'])
+ {
+ #Add the client now.
+ $status .= scire_add_client($_POST['hostname'], $_POST['mac'], $_POST['ip'], $_POST['profile'], $_POST['distribution'], $_POST['administrator'], $_POST['status']);
+ if (!$status) { $status = "User added to DB successfully.";}
+ $obj_id = $gacl_api->add_object("clients", $_POST['hostname'], $_POST['hostname'], 1, 0, 'AXO');
+ print "Object id: $obj_id <BR>";
+
+ if ($_POST['groups']) {
+ print "Adding client to groups ".$_POST['groups'];
+ foreach( $_POST['groups'] as $group) {
+ $worked = $gacl_api->add_group_object($group, "clients", $_POST['hostname'], 'AXO');
+ if ($worked) {
+ print "Group $group Addition successfull.<br>";
+ } else {
+ print "ERROR adding group $group <br>";
+ }
+ }
+ }
+ }
+ }
+
+
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('axo'), TEXT);
+
+ $ids = array();
+ $groupnames = array();
+ foreach($formatted_groups as $id => $name) {
+ print "ID: $id Name: $name <br>";
+ array_push($ids, $id);
+ array_push($groupnames, $name);
+ }
+
+ ###################################################
+ $smarty->assign('ids',$ids);
+ $smarty->assign('groupnames', $groupnames);
+
+ $smarty->display('admin/add_client.tpl');
+
+
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/add_permission.php b/scire/admin/add_permission.php
new file mode 100644
index 0000000..11028bf
--- /dev/null
+++ b/scire/admin/add_permission.php
@@ -0,0 +1,29 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ ####################################################
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+
+ if($_POST['permname'] and $_POST['permdesc']) {
+ #Add the user now.
+ $status .= scire_add_permission($_POST['permname'], $_POST['permdesc'],$_SESSION['userid']);
+ if(!$status) {$status = "User added to DB successfully.";}
+ $obj_id = $gacl_api->add_object("perms", $_POST['permname'], $_POST['permname'], 1, 0, 'ACO');
+ print "Object id: $obj_id <BR>";
+ }
+
+ ###################################################
+
+ $smarty->display('admin/add_permission.tpl');
+
+
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/admin_checklogin.php b/scire/admin/admin_checklogin.php
new file mode 100644
index 0000000..91847d7
--- /dev/null
+++ b/scire/admin/admin_checklogin.php
@@ -0,0 +1,10 @@
+<?php
+session_start();
+if(!isset($_SESSION['userid'])) {
+ #print "<h1>NO MATCH</h1>";
+ header("Location: ../login.php");
+}
+else {
+ print "Welcome $_SESSION[userid]<br>";
+}
+?>
diff --git a/scire/admin/admin_smarty.php b/scire/admin/admin_smarty.php
new file mode 100644
index 0000000..6e15c92
--- /dev/null
+++ b/scire/admin/admin_smarty.php
@@ -0,0 +1,45 @@
+<?php
+ #This is the code to set up the SMARTY templates for the Admin pages.
+ # it has ../ on things and sets the leftbar to show the admin list.
+ $smarty = new Smarty;
+ $smarty->template_dir = '../templates';
+ $smarty->compile_dir = '../templates_c';
+ $smarty->cache_dir = '../cache';
+ $smarty->config_dir = '../configs';
+ $smarty->assign('topbar', array(
+ array('name'=> 'Login', 'link' => '../login.php'),
+ array('name'=> 'Clients', 'link' => '../clients.php'),
+ array('name'=> 'Jobs/Tasks', 'link' => '../jobs.php'),
+ array('name'=> 'Modules', 'link' => '../modules.php'),
+ array('name'=> 'Admin', 'link' => '../admin.php')));
+ $smarty->assign('left_section_header',"Admin Functions");
+ $smarty->assign('leftnav', array(
+ array("create_user.php", "Create a User"),
+ array("edit_user.php","Edit a User"),
+ array("delete_user.php","Delete a User"),
+ array("",""),
+ array("create_usergroup.php","Create a UserGroup"),
+ array("edit_usergroup.php","Edit a UserGroup"),
+ array("delete_usergroup.php","Delete a UserGroup"),
+ array("",""),
+ array("add_permission.php","Add Permission"),
+ array("edit_permission.php","Edit Permission"),
+ array("delete_permission.php","Delete Permission"),
+ array("",""),
+ array("add_client.php","Add Client Manually"),
+ array("edit_client.php","Edit Clients"),
+ array("delete_client.php","Delete Client from Scire"),
+ array("",""),
+ array("create_clientgroup.php","Create a ClientGroup"),
+ array("edit_clientgroup.php","Edit a ClientGroup"),
+ array("delete_clientgroup.php","Delete a ClientGroup"),
+ array("",""),
+ array("assign_permissions.php","Assign Permissions"),
+ array("",""),
+ ));
+
+
+ if($status) {
+ $smarty->assign('error', $status);
+ }
+?>
diff --git a/scire/admin/assign_permissions.php b/scire/admin/assign_permissions.php
new file mode 100644
index 0000000..7af39d4
--- /dev/null
+++ b/scire/admin/assign_permissions.php
@@ -0,0 +1,129 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ ####################################################
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ ###################################################
+ #Deal with submitted form
+ if ($_POST['id']) {
+ $type = $_POST['id'][0];
+ $idnum = substr($_POST['id'],2);
+ print "Type: $type ID: $idnum <br>";
+ $smarty->assign('type', $type);
+ $smarty->assign('idnum', $idnum);
+
+ if( $type == "u") {
+ print "found user";
+ $selected_user_data = $gacl_api->get_object_data($idnum, 'ARO');
+ $smarty->assign('selected_name', $selected_user_data[0][3]);
+ }
+ elseif ($type == "g") {
+ $selected_group_data = $gacl_api->get_group_data($idnum, 'ARO');
+ $smarty->assign('selected_name', $selected_group_data[3]);
+ }
+ $clients = $gacl_api->format_groups($gacl_api->sort_groups('axo'), TEXT);
+ $smarty->assign('clientgroups',$clients);
+
+ $client_ids = array();
+ $client_groupnames = array();
+ foreach($clients as $id => $name) {
+ print "ID: $id Name: $name <br>";
+ array_push($client_ids, $id);
+ array_push($client_groupnames, $name);
+ }
+
+
+
+ #This is an ugly hack to get the users and their groups.
+ $all_clients = $gacl_api->get_objects("clients",1,'AXO');
+ $clientinfo = array();
+ foreach ($all_clients as $client) {
+ foreach ($client as $clientdata) {
+ $id = $gacl_api->get_object_id("clients",$clientdata,'AXO');
+ $groups = $gacl_api->get_object_groups($id,'AXO');
+ array_push($clientinfo, array($id,$clientdata,$groups));
+ }
+ }
+ $smarty->assign('clients', $clientinfo);
+
+
+
+
+
+ #For the <select> list of groups.
+ $smarty->assign('client_ids',$client_ids);
+ $smarty->assign('client_groupnames', $client_groupnames);
+
+ $permissions = $gacl_api->get_objects("perms",1, 'ACO');
+ $permissionsinfo = array();
+ foreach ($permissions as $eachpermission) {
+ foreach ($eachpermission as $singlepermission) {
+ $id = $gacl_api->get_object_id("perms",$singlepermission, 'ACO');
+ array_push($permissionsinfo, array($id, $singlepermission));
+ }
+ }
+ $smarty->assign('permissions',$permissionsinfo);
+ }
+ ###################################################
+ #Deal with part 2 submitted form
+ if ($_POST['permissions'] and $_POST['clients']) {
+ print "Perms: ".$_POST['permissions']." <br>User: ".$_POST['selected_name'];
+ $aco_array = array();
+ $aro_array = array();
+ $axo_array = array();
+ $axo_group_array = array();
+ $aro_group_array = array();
+
+ $aco_array['perms'] = $_POST['permissions'];
+ if($_POST['type'] == "u") {
+ $aro_array['users'] = array($_POST['selected_name']);
+ } elseif ($_POST['type'] == "g") {
+ $aro_group_array = array($_POST['idnum']);
+ } else {
+ print "ERROR NO TYPE";
+ exit;
+ }
+
+ $axo_group_array = $_POST['clients'];
+ $worked = $gacl_api->add_acl($aco_array, $aro_array,$aro_group_array,$axo_array,$axo_group_array,1,1,1,"Test ACL","system");
+ if($worked) {
+ print "Addition Successfull! $worked";
+ } else {
+ print "BAD BAD BAD";
+ }
+ # foreach( $_POST['permissions'] as $perm_to_add) {
+
+ # }
+ # foreach $_POST['clients'] as $client_to_add) {
+
+ # }
+ }
+
+ ###################################################
+ #Get the usergroups.
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('aro'), HTML);
+ $smarty->assign('usergroups',$formatted_groups);
+
+ #This is an ugly hack to get the users and their groups.
+ $all_users = $gacl_api->get_objects("users",1,'ARO');
+ $userinfo = array();
+ foreach ($all_users as $user) {
+ foreach ($user as $userdata) {
+ $id = $gacl_api->get_object_id("users",$userdata,'ARO');
+ $groups = $gacl_api->get_object_groups($id,'ARO');
+ array_push($userinfo, array($id,$userdata,$groups));
+ }
+ }
+ $smarty->assign('users', $userinfo);
+
+ $smarty->display('admin/assign_permissions.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/create_clientgroup.php b/scire/admin/create_clientgroup.php
new file mode 100644
index 0000000..27de3cc
--- /dev/null
+++ b/scire/admin/create_clientgroup.php
@@ -0,0 +1,38 @@
+<?php
+ include('Smarty.class.php');
+ include('../Frodo.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ ### Deal with submitted form here
+ if ($_POST['groupname'] and $_POST['parentgroup']) {
+ #Add the group as a subgroup. This is all done in the gacl_api.
+ $newgroup_id = $gacl_api->add_group($_POST['groupname'], $_POST['groupname'], $_POST['parentgroup'], 'AXO');
+ print "Group added successfully, new group id is: $newgroup_id<br>";
+ }
+
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('axo'), TEXT);
+ $ids = array();
+ $groupnames = array();
+ foreach($formatted_groups as $id => $name) {
+ print "ID: $id Name: $name <br>";
+ array_push($ids, $id);
+ array_push($groupnames, $name);
+ }
+
+
+ #For the <select> list of groups.
+ $smarty->assign('ids',$ids);
+ $smarty->assign('groupnames', $groupnames);
+
+ $smarty->display('admin/create_clientgroup.tpl');
+
+
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/create_user.php b/scire/admin/create_user.php
new file mode 100644
index 0000000..225fa41
--- /dev/null
+++ b/scire/admin/create_user.php
@@ -0,0 +1,57 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ ####################################################
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+
+ if($_POST['username']) {
+ if ($_POST['passwd'] == $_POST['passwd2']) {
+ #Add the user now.
+ $status .= scire_add_user($_POST['username'], $_POST['passwd'], $_POST['realname'], $_POST['comment']);
+ # $status = "User added to DB successfully.";
+ $obj_id = $gacl_api->add_object("users", $_POST['username'], $_POST['username'], 1, 0, 'ARO');
+ print "Object id: $obj_id <BR>";
+
+ if ($_POST['groups']) {
+ print "Adding user to groups ".$_POST['groups'];
+ foreach( $_POST['groups'] as $group) {
+ $worked = $gacl_api->add_group_object($group, "users", $_POST['username'], 'ARO');
+ if ($worked) {
+ print "Group $group Addition successfull.<br>";
+ } else {
+ print "ERROR adding group $group <br>";
+ }
+ }
+ }
+ }
+ else
+ {
+ $status = "ERROR: Passwords do not match.";
+ }
+
+ }
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('aro'), TEXT);
+
+ $ids = array();
+ $groupnames = array();
+ foreach($formatted_groups as $id => $name) {
+ print "ID: $id Name: $name <br>";
+ array_push($ids, $id);
+ array_push($groupnames, $name);
+ }
+
+ ###################################################
+ $smarty->assign('ids',$ids);
+ $smarty->assign('groupnames', $groupnames);
+
+ $smarty->display('admin/create_user.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/create_usergroup.php b/scire/admin/create_usergroup.php
new file mode 100644
index 0000000..2de2b78
--- /dev/null
+++ b/scire/admin/create_usergroup.php
@@ -0,0 +1,35 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ ### Deal with submitted form here
+ if ($_POST['groupname'] and $_POST['parentgroup']) {
+ #Add the group as a subgroup. This is all done in the gacl_api.
+ $newgroup_id = $gacl_api->add_group($_POST['groupname'], $_POST['groupname'], $_POST['parentgroup'], 'ARO');
+ print "Group added successfully, new group id is: $newgroup_id<br>";
+ }
+
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('aro'), TEXT);
+ $ids = array();
+ $groupnames = array();
+ foreach($formatted_groups as $id => $name) {
+ print "ID: $id Name: $name <br>";
+ array_push($ids, $id);
+ array_push($groupnames, $name);
+ }
+
+ #For the <select> list of groups.
+ $smarty->assign('ids',$ids);
+ $smarty->assign('groupnames', $groupnames);
+
+ $smarty->display('admin/create_usergroup.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/delete_client.php b/scire/admin/delete_client.php
new file mode 100644
index 0000000..2dd46f3
--- /dev/null
+++ b/scire/admin/delete_client.php
@@ -0,0 +1,27 @@
+<?php
+
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ $status = "";
+ if($_POST['delsubmit'] and $_POST['delclient'] and $_POST['iamsure']) {
+ include('phpgacl_code.php');
+ $client_id = $_POST['delclient'];
+ $client_data = get_scire_client($client_id);
+
+ $status = scire_del_client($client_id);
+
+ $id = $gacl_api->get_object_id("clients", $client_data['hostname'], 'AXO');
+ $gacl_api->del_object($id, 'AXO', TRUE);
+ }
+
+ $clients = get_all_clients();
+ $smarty->assign('clients', $clients);
+
+ $smarty->display('admin/delete_client.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/delete_clientgroup.php b/scire/admin/delete_clientgroup.php
new file mode 100644
index 0000000..4e2d53b
--- /dev/null
+++ b/scire/admin/delete_clientgroup.php
@@ -0,0 +1,46 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ #Load Smarty templates.
+ include('admin_smarty.php');
+
+ ### Deal with submitted form here
+ if($_POST['delsubmit'] and $_POST['delgroup'] and $_POST['iamsure']) {
+ #Check if the group has children.
+ $result = $gacl_api->del_group($_POST['delgroup'],TRUE, 'AXO');
+ if ($result) {
+ $status = "Group deleted successfully.";
+ } else {
+ $status = "ERROR: Group could not be successfully deleted.";
+ }
+
+ }
+
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('axo'), HTML);
+ $formatted_groups2 = $gacl_api->format_groups($gacl_api->sort_groups('axo'), TEXT);
+
+ $ids = array();
+ $groupnames = array();
+ foreach($formatted_groups2 as $id => $name) {
+ #print "ID: $id Name: $name <br>";
+ array_push($ids, $id);
+ array_push($groupnames, $name);
+ }
+
+ #For the <select> list of groups.
+ $smarty->assign('ids',$ids);
+ $smarty->assign('groupnames', $groupnames);
+
+ $smarty->assign('editgroup', $editgroup);
+ $smarty->assign('editgroupdata', $editgroupdata);
+ $smarty->assign('clientgroups', $formatted_groups);
+
+ $smarty->display('admin/delete_clientgroup.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/delete_permission.php b/scire/admin/delete_permission.php
new file mode 100644
index 0000000..84e5751
--- /dev/null
+++ b/scire/admin/delete_permission.php
@@ -0,0 +1,36 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ ####################################################
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+
+ if($_POST['delperm'] and $_POST['delsubmit'] and $_POST['iamsure']) {
+ #Delete the user.
+ $status .= scire_del_permission($_POST['delperm']);
+ if(!$status) {$status = "User deleted from DB successfully. ";}
+ #Get the obj ID for edit
+ $obj_id = $gacl_api->get_object_id("perms",$_POST['delperm'],'ACO');
+ $result = $gacl_api->del_object($obj_id, 'ACO', TRUE);
+ if($result) {
+ $status .= "Permission deleted from ACLs successfully. ";
+ } else {
+ $status .= "ERROR: Permission could not be delted from the ACLs! ";
+ }
+ }
+
+ ###################################################
+ $permissions = get_scire_permissions();
+ $smarty->assign('permissions', $permissions);
+
+ $smarty->display('admin/delete_permission.tpl');
+
+
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/delete_user.php b/scire/admin/delete_user.php
new file mode 100644
index 0000000..52567dd
--- /dev/null
+++ b/scire/admin/delete_user.php
@@ -0,0 +1,27 @@
+<?php
+
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the gacl_api
+
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ if($_POST['delsubmit'] and $_POST['deluser'] and $_POST['iamsure']) {
+
+ $status = scire_del_user($_POST['deluser']);
+ $id = $gacl_api->get_object_id("users", $_POST['deluser'], 'ARO');
+ $gacl_api->del_object($id, 'ARO', TRUE);
+ }
+
+
+ $users = get_scire_users();
+ $smarty->assign('users', $users);
+
+ $smarty->display('admin/delete_user.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/delete_usergroup.php b/scire/admin/delete_usergroup.php
new file mode 100644
index 0000000..e67132f
--- /dev/null
+++ b/scire/admin/delete_usergroup.php
@@ -0,0 +1,48 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ #Load Smarty templates.
+ include('admin_smarty.php');
+
+ ### Deal with submitted form here
+ if($_POST['delsubmit'] and $_POST['delgroup'] and $_POST['iamsure']) {
+ #Check if the group has children.
+ $result = $gacl_api->del_group($_POST['delgroup'],TRUE, 'ARO');
+ if ($result) {
+ $status = "Group deleted successfully.";
+ } else {
+ $status = "ERROR: Group could not be successfully deleted.";
+ }
+
+ }
+
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('aro'), HTML);
+ $formatted_groups2 = $gacl_api->format_groups($gacl_api->sort_groups('aro'), TEXT);
+
+ $ids = array();
+ $groupnames = array();
+ foreach($formatted_groups2 as $id => $name) {
+ #print "ID: $id Name: $name <br>";
+ array_push($ids, $id);
+ array_push($groupnames, $name);
+ }
+
+
+ #For the <select> list of groups.
+ $smarty->assign('ids',$ids);
+ $smarty->assign('groupnames', $groupnames);
+
+ $smarty->assign('editgroup', $editgroup);
+ $smarty->assign('editgroupdata', $editgroupdata);
+
+ $smarty->assign('usergroups', $formatted_groups);
+
+ $smarty->display('admin/delete_usergroup.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/edit_client.php b/scire/admin/edit_client.php
new file mode 100644
index 0000000..8b71038
--- /dev/null
+++ b/scire/admin/edit_client.php
@@ -0,0 +1,35 @@
+<?php
+
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ if($_POST['savesubmit']) {
+ if (!$_POST['hostname']) { $status .= "ERROR: Hostname required! "; }
+ if (!$_POST['mac']) { $status .= "ERROR: Hostname required! "; }
+ if (!$_POST['ip']) { $status .= "ERROR: Hostname required! "; }
+ if ($_POST['hostname'] and $_POST['mac'] and $_POST['ip'])
+ {
+ $status .= scire_edit_client($_POST['client_id'], $_POST['hostname'], $_POST['mac'], $_POST['ip'], $_POST['profile'], $_POST['distribution'], $_POST['administrator'], $_POST['status']);
+ if (!$status) { $status = "User added to DB successfully.";}
+ }
+ }
+
+ if($_POST['editsubmit'] and $_POST['editclient'])
+ {
+ $client_id = $_POST['editclient'];
+ $client_data = get_scire_client($client_id);
+ $smarty->assign('cdata', $client_data);
+ #Get list of groups. make a SELECT
+
+ }
+ else{
+ $clients = get_all_clients();
+ $smarty->assign('clients', $clients);
+ }
+ $smarty->display('admin/edit_client.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/edit_clientgroup.php b/scire/admin/edit_clientgroup.php
new file mode 100644
index 0000000..d378874
--- /dev/null
+++ b/scire/admin/edit_clientgroup.php
@@ -0,0 +1,48 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ ### Deal with submitted form here
+ if ($_POST['editgroup']) {
+ $editgroup = $_POST['editgroup'];
+ $editgroupdata = $gacl_api->get_group_data($editgroup, 'AXO');
+ }
+
+ if ($_POST['groupname'] and $_POST['parentgroup']) {
+ $newgroup_id = $gacl_api->edit_group($_POST['groupid'], $_POST['groupname'], $_POST['groupname'], $_POST['parentgroup'], 'AXO');
+ print "Group edited successfully, group id is: $newgroup_id<br>";
+ }
+
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('axo'), HTML);
+ $formatted_groups2 = $gacl_api->format_groups($gacl_api->sort_groups('axo'), TEXT);
+
+ $ids = array();
+ $groupnames = array();
+ foreach($formatted_groups2 as $id => $name) {
+ #print "ID: $id Name: $name <br>";
+ array_push($ids, $id);
+ array_push($groupnames, $name);
+ }
+
+
+
+ #For the <select> list of groups.
+ $smarty->assign('ids',$ids);
+ $smarty->assign('groupnames', $groupnames);
+
+ $smarty->assign('editgroup', $editgroup);
+ $smarty->assign('editgroupdata', $editgroupdata);
+
+ $smarty->assign('clientgroups', $formatted_groups);
+
+ $smarty->display('admin/edit_clientgroup.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/edit_permission.php b/scire/admin/edit_permission.php
new file mode 100644
index 0000000..800e47f
--- /dev/null
+++ b/scire/admin/edit_permission.php
@@ -0,0 +1,38 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ ####################################################
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ if($_POST['permname'] and $_POST['permdesc']) {
+ #Add the user now.
+ $status .= gimli_edit_permission($_POST['permname'], $_POST['permdesc']);
+ if(!$status) {$status = "User edited to DB successfully.";}
+ #Get the obj ID for edit
+ $obj_id = $gacl_api->get_object_id("perms",$_POST['permname'],'ACO');
+ $result = $gacl_api->edit_object($obj_id, "perms", $_POST['permname'], $_POST['permname'], 1, 0, 'ACO');
+ print "Object id: $obj_id <BR>";
+ }
+
+ ###################################################
+ if($_POST['submit'] and $_POST['editperm'])
+ {
+ $permname = $_POST['editperm'];
+ $smarty->assign('permname', $_POST['editperm']);
+ $smarty->assign('permdesc', $_POST[$permname.'_desc']);
+ }
+ else{
+ $permissions = get_gimli_permissions();
+ $smarty->assign('permissions', $permissions);
+ }
+
+ $smarty->display('admin/edit_permission.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/edit_user.php b/scire/admin/edit_user.php
new file mode 100644
index 0000000..7142e9f
--- /dev/null
+++ b/scire/admin/edit_user.php
@@ -0,0 +1,26 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+
+ if($_POST['savesubmit'] and $_POST['roledesc']) {
+ #$status = scire_edit_user($_POST['rolename'], $_POST['roledesc']);
+ }
+
+ if($_POST['editsubmit'] and $_POST['edituser'])
+ {
+ $edituser = $_POST['edituser'];
+ $smarty->assign('username', $_POST['edituser']);
+ $smarty->assign('userdesc', $_POST[$edituser.'_desc']);
+ }
+ else{
+ $users = get_scire_users();
+ $smarty->assign('users', $users);
+ }
+ $smarty->display('admin/edit_user.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/edit_usergroup.php b/scire/admin/edit_usergroup.php
new file mode 100644
index 0000000..0003888
--- /dev/null
+++ b/scire/admin/edit_usergroup.php
@@ -0,0 +1,46 @@
+<?php
+ include('Smarty.class.php');
+ include('../DBInterface.php');
+ include('admin_checklogin.php');
+
+ # PHPGACL CODE
+ $status = "";
+ include('phpgacl_code.php'); #load the GACL_API
+
+ #Load Smarty Template
+ include('admin_smarty.php');
+
+ ### Deal with submitted form here
+ if ($_POST['editgroup']) {
+ $editgroup = $_POST['editgroup'];
+ $editgroupdata = $gacl_api->get_group_data($editgroup, 'ARO');
+ }
+
+ if ($_POST['groupname'] and $_POST['parentgroup']) {
+ $newgroup_id = $gacl_api->edit_group($_POST['groupid'], $_POST['groupname'], $_POST['groupname'], $_POST['parentgroup'], 'ARO');
+ print "Group edited successfully, group id is: $newgroup_id<br>";
+ }
+
+ $formatted_groups = $gacl_api->format_groups($gacl_api->sort_groups('aro'), HTML);
+ $formatted_groups2 = $gacl_api->format_groups($gacl_api->sort_groups('aro'), TEXT);
+
+ $ids = array();
+ $groupnames = array();
+ foreach($formatted_groups2 as $id => $name) {
+ #print "ID: $id Name: $name <br>";
+ array_push($ids, $id);
+ array_push($groupnames, $name);
+ }
+
+ #For the <select> list of groups.
+ $smarty->assign('ids',$ids);
+ $smarty->assign('groupnames', $groupnames);
+
+ $smarty->assign('editgroup', $editgroup);
+ $smarty->assign('editgroupdata', $editgroupdata);
+
+ $smarty->assign('usergroups', $formatted_groups);
+
+ $smarty->display('admin/edit_usergroup.tpl');
+ $smarty->display('leftbar.tpl');
+?>
diff --git a/scire/admin/phpgacl_code.php b/scire/admin/phpgacl_code.php
new file mode 100644
index 0000000..d16165c
--- /dev/null
+++ b/scire/admin/phpgacl_code.php
@@ -0,0 +1,28 @@
+<?php
+ #################################################### PHPGACL CODE
+ require_once(dirname(__FILE__).'/../phpgacl/gacl.class.php');
+ require_once(dirname(__FILE__).'/../phpgacl/gacl_api.class.php');
+ require_once(dirname(__FILE__).'/../phpgacl/admin/gacl_admin_api.class.php');
+
+// phpGACL Configuration file.
+if ( !isset($config_file) ) {
+# $config_file = '../gacl.ini.php';
+ $config_file = dirname(__FILE__).'/../phpgacl/gacl.ini.php';
+}
+
+//Values supplied in $gacl_options array overwrite those in the config file.
+if ( file_exists($config_file) ) {
+ $config = parse_ini_file($config_file);
+
+ if ( is_array($config) ) {
+ if ( isset($gacl_options) ) {
+ $gacl_options = array_merge($config, $gacl_options);
+ } else {
+ $gacl_options = $config;
+ }
+ }
+ unset($config);
+}
+$gacl_api = new gacl_admin_api($gacl_options);
+###############################################
+?>
diff --git a/scire/admin/s.gif b/scire/admin/s.gif
new file mode 100644
index 0000000..5035948
--- /dev/null
+++ b/scire/admin/s.gif
Binary files differ
diff --git a/scire/admin/tux_large.png b/scire/admin/tux_large.png
new file mode 120000
index 0000000..f06f852
--- /dev/null
+++ b/scire/admin/tux_large.png
@@ -0,0 +1 @@
+../tux_large.png \ No newline at end of file
diff --git a/scire/assign_permission.php b/scire/assign_permission.php
new file mode 100755
index 0000000..06f0f62
--- /dev/null
+++ b/scire/assign_permission.php
@@ -0,0 +1,136 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+
+add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "users.php");
+
+
+$userid = "";
+
+
+#####################################################
+#Deal with submitted forms.
+
+###############################################
+#Adding a permission.
+if ($_POST['addperm_submit'] or $_POST['editperm_submit']) {
+ if ($_POST['newpermname'] and $_POST['newpermdesc']) { #Add a new permission FIXME add check of auth for this.
+ if ($_POST['perm_category'] == "new") {
+ if ($_POST['newpermcat']) { #Need to add a section
+ $acl->add_object_section($_POST['newpermcat'], $_POST['newpermcat'], 1, 0, 'ACO');
+ $_POST['perm_category'] = $_POST['newpermcat'];
+ } else { #BAD user
+ $status .= "ERROR: No new permission category specified. Using Default";
+ $_POST['perm_category'] = "Default";
+ }
+ }
+ $obj_id = $acl->add_object($_POST['perm_category'], $_POST['newpermname'], $_POST['newpermname'], 1, 0, 'ACO');
+ $status .= "Obj id: $obj_id";
+ $result = scire_add_permission($obj_id, $_POST['newpermname'],$_POST['newpermdesc'], $_SESSION['userid']);
+ if ($result == 1) { $status .= "Permission Addition successfull. "; }
+ $_POST['perm'] = $_POST['newpermname'];
+ }
+ #Permission should exist now.
+ $aco_array[$_POST['perm_category']] = array($_POST['perm']);
+ $aro_array = array();
+ $axo_array = array();
+ $axo_group_array = array();
+ $aro_group_array = array();
+# if ($_POST['usertype'] == "usergroups") {
+ $aro_group_array = $_POST['usergroups'];
+# } else {
+ $aro_array['users'] = $_POST['users'];
+# }
+
+# if ($_POST['clienttype'] == "clientgroups") {
+ $axo_group_array = $_POST['clientgroups'];
+# } else {
+ $axo_array['clients'] = $_POST['clients'];
+# }
+
+ if (!$_POST['active']) {
+ $_POST['active'] = 0;
+ }
+
+ if ($_POST['addperm_submit']) {
+ $worked = $acl->add_acl($aco_array, $aro_array,$aro_group_array,$axo_array,$axo_group_array,$_POST['allow'],$_POST['active'],1,$_POST['note'],"system");
+ if($worked) {
+ $status .= "<br><b>Addition Successfull! $worked</b>";
+ } else {
+ $status .= "<br><b>BAD BAD BAD $worked</b>";
+ }
+ } else {#Edit
+ $worked = $acl->edit_acl($_POST['editing'],$aco_array, $aro_array,$aro_group_array,$axo_array,$axo_group_array,$_POST['allow'],$_POST['active'],1,$_POST['note'],"system");
+ if($worked) {
+ $status .= "<br><b>Edit Successfull! $worked</b>";
+ } else {
+ $status .= "<br><b>BAD BAD BAD $worked</b>";
+ }
+ }
+
+}
+###############################################
+#Adding a permission.
+elseif ($_POST['delete_confirm']) {
+ $aclid = $_POST['aclid'];
+ $worked = $acl->del_acl($aclid);
+ if($worked) {
+ $status .= "<br><b>Deletion Successfull. $worked</b>";
+ } else {
+ $status .= "<br><b>BAD BAD BAD $worked</b>";
+ }
+ header('Location: ' . $baseurl . 'users.php?View=permissions');
+}
+elseif ($_POST['delete_cancel']) {
+ header('Location: ' . $baseurl . 'users.php?View=permissions');
+}
+
+
+########################################################
+if ($_GET['Action'] == "delete") {
+ $smarty->assign('aclid', $_GET['aclid']);
+}
+
+if ($_GET['aclid']) { #For Editing. Load the ACL data.
+ $smarty->assign('acl',$acl->get_acl($_GET['aclid']));
+}
+#$permissions = get_scire_permissions();
+
+#foreach ($permissions as $perm) {
+# $perm_categories[$perm['permcategory']] = 1;
+#}
+
+$permissions = array();
+$perm_categories = array();
+$all_permissions = $acl->get_objects(NULL, 1, 'ACO');
+foreach ($all_permissions as $categoryname => $cat) {
+ #print "Perm: $perm<br>Permname: $permname<br>";
+ if ($categoryname != $scire_ui_section) {
+ foreach ($cat as $perm) {
+ array_push($permissions, $perm);
+ }
+ array_push($perm_categories, $categoryname);
+ }
+}
+#pre_var_dump($permissions);
+#pre_var_dump($perm_categories);
+$smarty->assign('perm_categories',$perm_categories);
+$smarty->assign('perms', $permissions);
+
+$smarty->assign('ugroups', $acl->format_groups($acl->sort_groups('aro'), TEXT));
+$smarty->assign('cgroups', $acl->format_groups($acl->sort_groups('AXO'), TEXT));
+
+$users = get_scire_users('username', 'asc');
+$smarty->assign('users', $users);
+$clients = get_scire_clients('hostname', 'asc');
+$smarty->assign('clients', $clients);
+
+$smarty->assign('get', $_GET);
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display('assign_permission.tpl');
+#pre_var_dump($_POST);
+?>
diff --git a/scire/calendar/calendar.html b/scire/calendar/calendar.html
new file mode 100644
index 0000000..202fb41
--- /dev/null
+++ b/scire/calendar/calendar.html
@@ -0,0 +1,169 @@
+<!--
+Title: Tigra Calendar
+URL: http://www.softcomplex.com/products/tigra_calendar/
+Version: 3.4 (all formats)
+Date: 01/06/2007
+Note: Permission given to use this script in ANY kind of applications if
+ header lines are left unchanged.
+Note: Script consists of two files: calendar?.js and calendar.html
+-->
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+<title>Select Date, Please.</title>
+<style>
+ td {font-family: Tahoma, Verdana, sans-serif; font-size: 12px;}
+ td a {text-decoration: none;}
+</style>
+<script language="JavaScript">
+
+// months as they appear in the calendar's title
+var ARR_MONTHS = ["January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"];
+// week day titles as they appear on the calendar
+var ARR_WEEKDAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
+// day week starts from (normally 0-Su or 1-Mo)
+var NUM_WEEKSTART = 1;
+// path to the directory where calendar images are stored. trailing slash req.
+var STR_ICONPATH = 'img/';
+
+var re_urlCur = new RegExp('c=(\\-?\\d+)');
+var re_urlSel = new RegExp('s=(\\-?\\d+)');
+var re_id = new RegExp('id=(\\d+)');
+
+var dt_selected = (re_urlSel.exec(String(window.location))
+ ? new Date(new Number(RegExp.$1)) : new Date());
+var dt_current = (re_urlCur.exec(String(window.location))
+ ? new Date(new Number(RegExp.$1)) : dt_selected);
+var num_id = (re_id.exec(String(window.location))
+ ? new Number(RegExp.$1) : 0);
+
+var obj_caller = (window.opener ? window.opener.calendars[num_id] : null);
+
+if (obj_caller && obj_caller.year_scroll) {
+ // get same date in the previous year
+ var dt_prev_year = new Date(dt_current);
+ dt_prev_year.setFullYear(dt_prev_year.getFullYear() - 1);
+ if (dt_prev_year.getDate() != dt_current.getDate())
+ dt_prev_year.setDate(0);
+
+ // get same date in the next year
+ var dt_next_year = new Date(dt_current);
+ dt_next_year.setFullYear(dt_next_year.getFullYear() + 1);
+ if (dt_next_year.getDate() != dt_current.getDate())
+ dt_next_year.setDate(0);
+}
+
+// get same date in the previous month
+var dt_prev_month = new Date(dt_current);
+if (dt_prev_month.getMonth()) {
+ dt_prev_month.setMonth(dt_prev_month.getMonth() - 1);
+ if (dt_prev_month.getDate() != dt_current.getDate())
+ dt_prev_month.setDate(0);
+}
+else {
+ dt_prev_month.setFullYear(dt_prev_month.getFullYear() - 1);
+ dt_prev_month.setMonth(11);
+}
+
+// get same date in the next month
+var dt_next_month = new Date(dt_current);
+dt_next_month.setMonth(dt_next_month.getMonth() + 1);
+if (dt_next_month.getDate() != dt_current.getDate())
+ dt_next_month.setDate(0);
+
+// get first day to display in the grid for current month
+var dt_firstday = new Date(dt_current);
+dt_firstday.setDate(1);
+dt_firstday.setDate(1 - (7 + dt_firstday.getDay() - NUM_WEEKSTART) % 7);
+
+// function passing selected date to calling window
+function set_datetime(n_datetime, b_close) {
+ if (!obj_caller) return;
+
+ var dt_datetime = obj_caller.prs_time(
+ (document.cal ? document.cal.time.value : ''),
+ new Date(n_datetime)
+ );
+
+ if (!dt_datetime) return;
+ if (b_close) {
+
+ obj_caller.target.value = (document.cal
+ ? obj_caller.gen_tsmp(dt_datetime)
+ : obj_caller.gen_date(dt_datetime)
+ );window.close();
+ }
+ else obj_caller.popup(dt_datetime.valueOf());
+}
+
+</script>
+</head>
+<body bgcolor="#FFFFFF" marginheight="5" marginwidth="5" topmargin="5" leftmargin="5" rightmargin="5">
+<table class="clsOTable" cellspacing="0" border="0" width="100%">
+<tr><td bgcolor="#4682B4">
+<table cellspacing="1" cellpadding="3" border="0" width="100%">
+<tr><td colspan="7"><table cellspacing="0" cellpadding="0" border="0" width="100%">
+<tr>
+<script language="JavaScript">
+document.write(
+'<td nowrap>'+(obj_caller&&obj_caller.year_scroll?'<a href="javascript:set_datetime('+dt_prev_year.valueOf()+')"><img src="'+STR_ICONPATH+'prev_year.gif" width="16" height="16" border="0" alt="previous year"></a>&nbsp;':'')+'<a href="javascript:set_datetime('+dt_prev_month.valueOf()+')"><img src="'+STR_ICONPATH+'prev.gif" width="16" height="16" border="0" alt="previous month"></a></td>'+
+'<td align="center" width="100%"><font color="#ffffff">'+ARR_MONTHS[dt_current.getMonth()]+' '+dt_current.getFullYear() + '</font></td>'+
+'<td nowrap><a href="javascript:set_datetime('+dt_next_month.valueOf()+')"><img src="'+STR_ICONPATH+'next.gif" width="16" height="16" border="0" alt="next month"></a>'+(obj_caller && obj_caller.year_scroll?'&nbsp;<a href="javascript:set_datetime('+dt_next_year.valueOf()+')"><img src="'+STR_ICONPATH+'next_year.gif" width="16" height="16" border="0" alt="next year"></a>':'')+'</td>'
+);
+</script>
+</tr>
+</table></td></tr>
+<tr>
+<script language="JavaScript">
+
+// print weekdays titles
+for (var n=0; n<7; n++)
+ document.write('<td bgcolor="#87cefa" align="center"><font color="#ffffff">'+ARR_WEEKDAYS[(NUM_WEEKSTART+n)%7]+'</font></td>');
+document.write('</tr>');
+
+// print calendar table
+var dt_current_day = new Date(dt_firstday);
+while (dt_current_day.getMonth() == dt_current.getMonth() ||
+ dt_current_day.getMonth() == dt_firstday.getMonth()) {
+ // print row heder
+ document.write('<tr>');
+ for (var n_current_wday=0; n_current_wday<7; n_current_wday++) {
+ if (dt_current_day.getDate() == dt_selected.getDate() &&
+ dt_current_day.getMonth() == dt_selected.getMonth() &&
+ dt_current_day.getFullYear() == dt_selected.getFullYear())
+ // print current date
+ document.write('<td bgcolor="#ffb6c1" align="center" width="14%">');
+ else if (dt_current_day.getDay() == 0 || dt_current_day.getDay() == 6)
+ // weekend days
+ document.write('<td bgcolor="#dbeaf5" align="center" width="14%">');
+ else
+ // print working days of current month
+ document.write('<td bgcolor="#ffffff" align="center" width="14%">');
+
+ document.write('<a href="javascript:set_datetime('+dt_current_day.valueOf() +', true);">');
+
+ if (dt_current_day.getMonth() == this.dt_current.getMonth())
+ // print days of current month
+ document.write('<font color="#000000">');
+ else
+ // print days of other months
+ document.write('<font color="#606060">');
+
+ document.write(dt_current_day.getDate()+'</font></a></td>');
+ dt_current_day.setDate(dt_current_day.getDate()+1);
+ }
+ // print row footer
+ document.write('</tr>');
+}
+if (obj_caller && obj_caller.time_comp) {
+ document.write('<form onsubmit="javascript:set_datetime('+dt_current.valueOf()+', true)" name="cal"><tr><td colspan="7" bgcolor="#87CEFA"><font color="White" face="tahoma, verdana" size="2">Time: <input type="text" name="time" value="'+obj_caller.gen_time(this.dt_current)+'" size="8" maxlength="8"></font></td></tr></form>');
+ document.forms['cal'].elements['time'].focus();
+}
+</script>
+</table>
+</td></tr></table>
+</body>
+</html>
+
diff --git a/scire/calendar/calendar3.js b/scire/calendar/calendar3.js
new file mode 100644
index 0000000..9b88ed2
--- /dev/null
+++ b/scire/calendar/calendar3.js
@@ -0,0 +1,165 @@
+// Title: Tigra Calendar
+// URL: http://www.softcomplex.com/products/tigra_calendar/
+// Version: 3.4 (mySQL format)
+// Date: 07/12/2007
+// Note: Permission given to use this script in ANY kind of applications if
+// header lines are left unchanged.
+// Note: Script consists of two files: calendar?.js and calendar.html
+
+// if two digit year input dates after this year considered 20 century.
+var NUM_CENTYEAR = 30;
+// is time input control required by default
+var BUL_TIMECOMPONENT = false;
+// are year scrolling buttons required by default
+var BUL_YEARSCROLL = true;
+
+var calendars = [];
+var RE_NUM = /^\-?\d+$/;
+
+function calendar3(obj_target) {
+
+ // assigning methods
+ this.gen_date = cal_gen_date3;
+ this.gen_time = cal_gen_time3;
+ this.gen_tsmp = cal_gen_tsmp3;
+ this.prs_date = cal_prs_date3;
+ this.prs_time = cal_prs_time3;
+ this.prs_tsmp = cal_prs_tsmp3;
+ this.popup = cal_popup3;
+
+ // validate input parameters
+ if (!obj_target)
+ return cal_error("Error calling the calendar: no target control specified");
+ if (obj_target.value == null)
+ return cal_error("Error calling the calendar: parameter specified is not valid target control");
+ this.target = obj_target;
+ this.time_comp = BUL_TIMECOMPONENT;
+ this.year_scroll = BUL_YEARSCROLL;
+
+ // register in global collections
+ this.id = calendars.length;
+ calendars[this.id] = this;
+}
+
+function cal_popup3 (str_datetime) {
+ if (str_datetime)
+ this.dt_current = this.prs_tsmp(str_datetime);
+ else
+ this.dt_selected = this.dt_current = this.prs_tsmp(this.target.value);
+
+ if (!this.dt_current) return;
+
+ var obj_calwindow = window.open(
+ 'calendar/calendar.html?id=' + this.id + '&s=' + this.dt_selected.valueOf() + '&c=' + this.dt_current.valueOf(),
+ 'Calendar', 'width=200,height=' + (this.time_comp ? 215 : 190) +
+ ',status=no,resizable=no,top=200,left=200,dependent=yes,alwaysRaised=yes'
+ );
+ obj_calwindow.opener = window;
+ obj_calwindow.focus();
+}
+
+// timestamp generating function
+function cal_gen_tsmp3 (dt_datetime) {
+ return(this.gen_date(dt_datetime) + ' ' + this.gen_time(dt_datetime));
+}
+
+// date generating function
+function cal_gen_date3 (dt_datetime) {
+ return (
+ dt_datetime.getFullYear() + "-"
+ + (dt_datetime.getMonth() < 9 ? '0' : '') + (dt_datetime.getMonth() + 1) + "-"
+ + (dt_datetime.getDate() < 10 ? '0' : '') + dt_datetime.getDate()
+ );
+}
+// time generating function
+function cal_gen_time3 (dt_datetime) {
+ return (
+ (dt_datetime.getHours() < 10 ? '0' : '') + dt_datetime.getHours() + ":"
+ + (dt_datetime.getMinutes() < 10 ? '0' : '') + (dt_datetime.getMinutes()) + ":"
+ + (dt_datetime.getSeconds() < 10 ? '0' : '') + (dt_datetime.getSeconds())
+ );
+}
+
+// timestamp parsing function
+function cal_prs_tsmp3 (str_datetime) {
+ // if no parameter specified return current timestamp
+ if (!str_datetime)
+ return (new Date());
+
+ // if positive integer treat as milliseconds from epoch
+ if (RE_NUM.exec(str_datetime))
+ return new Date(str_datetime);
+
+ // else treat as date in string format
+ var arr_datetime = str_datetime.split(' ');
+ return this.prs_time(arr_datetime[1], this.prs_date(arr_datetime[0]));
+}
+
+// date parsing function
+function cal_prs_date3 (str_date) {
+
+ var arr_date = str_date.split('-');
+
+ if (arr_date.length != 3) return alert ("Invalid date format: '" + str_date + "'.\nFormat accepted is yyyy-mm-dd.");
+
+ if (!arr_date[0]) return alert ("Invalid date format: '" + str_date + "'.\nNo year value can be found.");
+ if (!RE_NUM.exec(arr_date[0])) return alert ("Invalid year value: '" + arr_date[0] + "'.\nAllowed values are unsigned integers.");
+
+ if (!arr_date[1]) return alert ("Invalid date format: '" + str_date + "'.\nNo month value can be found.");
+ if (!RE_NUM.exec(arr_date[1])) return alert ("Invalid month value: '" + arr_date[1] + "'.\nAllowed values are unsigned integers.");
+
+ if (!arr_date[2]) return alert ("Invalid date format: '" + str_date + "'.\nNo day of month value can be found.");
+ if (!RE_NUM.exec(arr_date[2])) return alert ("Invalid day of month value: '" + arr_date[2] + "'.\nAllowed values are unsigned integers.");
+
+
+
+ var dt_date = new Date();
+ dt_date.setDate(1);
+
+ if (arr_date[0] < 100) arr_date[0] = Number(arr_date[0]) + (arr_date[0] < NUM_CENTYEAR ? 2000 : 1900);
+ dt_date.setFullYear(arr_date[0]);
+
+
+ if (arr_date[1] < 1 || arr_date[1] > 12) return alert ("Invalid month value: '" + arr_date[1] + "'.\nAllowed range is 01-12.");
+ dt_date.setMonth(arr_date[1] - 1);
+
+
+ var dt_numdays = new Date(arr_date[0], arr_date[1], 0);
+ dt_date.setDate(arr_date[2]);
+ if (dt_date.getMonth() != (arr_date[1]-1)) return alert ("Invalid day of month value: '" + arr_date[2] + "'.\nAllowed range is 01-"+dt_numdays.getDate()+".");
+
+ return (dt_date)
+}
+
+// time parsing function
+function cal_prs_time3 (str_time, dt_date) {
+
+ if (!dt_date) return null;
+ var arr_time = String(str_time ? str_time : '').split(':');
+
+ if (!arr_time[0]) dt_date.setHours(0);
+ else if (RE_NUM.exec(arr_time[0]))
+ if (arr_time[0] < 24) dt_date.setHours(arr_time[0]);
+ else return cal_error ("Invalid hours value: '" + arr_time[0] + "'.\nAllowed range is 00-23.");
+ else return cal_error ("Invalid hours value: '" + arr_time[0] + "'.\nAllowed values are unsigned integers.");
+
+ if (!arr_time[1]) dt_date.setMinutes(0);
+ else if (RE_NUM.exec(arr_time[1]))
+ if (arr_time[1] < 60) dt_date.setMinutes(arr_time[1]);
+ else return cal_error ("Invalid minutes value: '" + arr_time[1] + "'.\nAllowed range is 00-59.");
+ else return cal_error ("Invalid minutes value: '" + arr_time[1] + "'.\nAllowed values are unsigned integers.");
+
+ if (!arr_time[2]) dt_date.setSeconds(0);
+ else if (RE_NUM.exec(arr_time[2]))
+ if (arr_time[2] < 60) dt_date.setSeconds(arr_time[2]);
+ else return cal_error ("Invalid seconds value: '" + arr_time[2] + "'.\nAllowed range is 00-59.");
+ else return cal_error ("Invalid seconds value: '" + arr_time[2] + "'.\nAllowed values are unsigned integers.");
+
+ dt_date.setMilliseconds(0);
+ return dt_date;
+}
+
+function cal_error (str_message) {
+ alert (str_message);
+ return null;
+}
diff --git a/scire/calendar/img/cal.gif b/scire/calendar/img/cal.gif
new file mode 100644
index 0000000..8526cf5
--- /dev/null
+++ b/scire/calendar/img/cal.gif
Binary files differ
diff --git a/scire/calendar/img/icon_demo.gif b/scire/calendar/img/icon_demo.gif
new file mode 100644
index 0000000..b6479eb
--- /dev/null
+++ b/scire/calendar/img/icon_demo.gif
Binary files differ
diff --git a/scire/calendar/img/icon_docs.gif b/scire/calendar/img/icon_docs.gif
new file mode 100644
index 0000000..f8c401c
--- /dev/null
+++ b/scire/calendar/img/icon_docs.gif
Binary files differ
diff --git a/scire/calendar/img/icon_download.gif b/scire/calendar/img/icon_download.gif
new file mode 100644
index 0000000..47d15f7
--- /dev/null
+++ b/scire/calendar/img/icon_download.gif
Binary files differ
diff --git a/scire/calendar/img/icon_forum.gif b/scire/calendar/img/icon_forum.gif
new file mode 100644
index 0000000..c99a254
--- /dev/null
+++ b/scire/calendar/img/icon_forum.gif
Binary files differ
diff --git a/scire/calendar/img/icon_home.gif b/scire/calendar/img/icon_home.gif
new file mode 100644
index 0000000..92a4f2e
--- /dev/null
+++ b/scire/calendar/img/icon_home.gif
Binary files differ
diff --git a/scire/calendar/img/logo.gif b/scire/calendar/img/logo.gif
new file mode 100644
index 0000000..6b5397d
--- /dev/null
+++ b/scire/calendar/img/logo.gif
Binary files differ
diff --git a/scire/calendar/img/next.gif b/scire/calendar/img/next.gif
new file mode 100644
index 0000000..bf02152
--- /dev/null
+++ b/scire/calendar/img/next.gif
Binary files differ
diff --git a/scire/calendar/img/next_year.gif b/scire/calendar/img/next_year.gif
new file mode 100644
index 0000000..ac12ea1
--- /dev/null
+++ b/scire/calendar/img/next_year.gif
Binary files differ
diff --git a/scire/calendar/img/pixel.gif b/scire/calendar/img/pixel.gif
new file mode 100644
index 0000000..46a2cf0
--- /dev/null
+++ b/scire/calendar/img/pixel.gif
Binary files differ
diff --git a/scire/calendar/img/prev.gif b/scire/calendar/img/prev.gif
new file mode 100644
index 0000000..211e1fa
--- /dev/null
+++ b/scire/calendar/img/prev.gif
Binary files differ
diff --git a/scire/calendar/img/prev_year.gif b/scire/calendar/img/prev_year.gif
new file mode 100644
index 0000000..d8145d5
--- /dev/null
+++ b/scire/calendar/img/prev_year.gif
Binary files differ
diff --git a/scire/calendar/img/tc.gif b/scire/calendar/img/tc.gif
new file mode 100644
index 0000000..576e148
--- /dev/null
+++ b/scire/calendar/img/tc.gif
Binary files differ
diff --git a/scire/client.php b/scire/client.php
new file mode 100755
index 0000000..9e29aba
--- /dev/null
+++ b/scire/client.php
@@ -0,0 +1,207 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+
+add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "clients.php");
+
+
+$clientid = "";
+
+
+
+#####################################################
+#Deal with submitted forms.
+
+###############################################
+#Adding a client to clientgroups.
+if ($_POST['addgroup_confirm']) {
+ $ingroups = $acl->get_object_groups($_POST['clientid'],'AXO');
+ $clientdata = $acl->get_object_data($_POST['clientid'], 'AXO');
+ $newgroups = $_POST['addgroupid'];
+ #remove first.
+ foreach ($ingroups as $ingroup) {
+ if (!in_array($ingroup, $newgroups)) {
+ $acl->del_group_object($ingroup, $clientdata[0][0], $clientdata[0][1], 'AXO');
+ }
+ }
+ foreach ($newgroups as $newgroup) {
+ print "newgroup: $newgroup";
+ $acl->add_group_object($newgroup, $clientdata[0][0], $clientdata[0][1], 'AXO');
+ }
+ $_GET['Action'] = "edit";
+ $_GET['clientid'] = $_POST['clientid'];
+}
+
+###############################################
+# Adding a client.
+if ($_POST['addhostname']) {
+ if ($_POST['addhostname'] and $_POST['ip'] and $_POST['mac']) {
+ check_action_access("Add Client");#Access check
+ #First just incase, we need to check if the object already exists (so we don't make duplicates)
+ $obj_id = "";
+ if ($acl->get_object_id("clients", $_POST['addhostname'], 'AXO') ) { #client already exists
+ $obj_id = $acl->get_object_id("clients", $_POST['addhostname'], 'AXO');
+ $status .= "Found existing object with objectid $obj_id <br>";
+ } else {
+ $obj_id = $acl->add_object("clients", $_POST['addhostname'], $_POST['addhostname'], 1, 0, 'AXO');
+ $status .= "Object id: $obj_id <BR>";
+ }
+ $result = scire_add_client($obj_id, $_POST['digest'], $_POST['addhostname'], $_POST['mac'], $_POST['ip'], $_POST['gli_profile'], $_POST['osid'], $_POST['contact'], $_POST['status'], $_POST['installtime'], $_POST['assetid']);
+ if ($result == 1) {
+ $status .= "Client Addition successfull<br>";
+ } else {
+ $status .= "Error during addition!: $result <br>";
+ }
+
+ if ($_POST['groups']) {
+ $status .= "Adding client to groups ".$_POST['groups'];
+ foreach( $_POST['groups'] as $group) {
+ $worked = $acl->add_group_object($group, "clients", $_POST['addhostname'], 'AXO');
+ if ($worked) {
+ $status .= "Group $group Addition successfull.<br>";
+ } else {
+ $status .= "ERROR adding group $group <br>";
+ }
+ }
+ }
+ } else {
+ $status = "Error required fields are not filled!";
+ }
+ #header('Location: ' . $baseurl . 'clients.php');
+}
+###############################################
+# Editing a client's information.
+if ($_POST['edithostname']) {
+ check_action_access("Edit Client");
+ $clientinfo = get_scire_client($_GET['clientid']);
+ $smarty->assign('client', $clientinfo);
+
+ if ($_POST['digest'] and ($_POST['digest'] != $clientinfo['digest'])) {
+ $fields['digest'] = $_POST['digest'];
+ }
+ if ($_POST['mac'] and ($_POST['mac'] != $clientinfo['mac'])){
+ $fields['mac'] = $_POST['mac'];
+ }
+ if ($_POST['ip'] and ($_POST['ip'] != $clientinfo['ip'])) {
+ $fields['ip'] = $_POST['ip'];
+ }
+ if ($_POST['gli_profile'] and ($_POST['gli_profile'] != $clientinfo['gli_profile'])) {
+ $fields['gli_profile'] = $_POST['gli_profile'];
+ }
+ if ($_POST['osid'] and ($_POST['osid'] != $clientinfo['osid'])) {
+ $fields['osid'] = $_POST['osid'];
+ }
+ if ($_POST['contact'] and ($_POST['contact'] != $clientinfo['contact'])) {
+ $fields['contact'] = $_POST['contact'];
+ }
+ if ($_POST['status'] and ($_POST['status'] != $clientinfo['status'])) {
+ $fields['status'] = $_POST['status'];
+ }
+ if ($_POST['installtime'] and ($_POST['installtime'] != $clientinfo['installtime'])) {
+ $fields['installtime'] = $_POST['installtime'];
+ }
+ if ($_POST['assetid'] and ($_POST['assetid'] != $clientinfo['assetid'])) {
+ $fields['assetid'] = $_POST['assetid'];
+ }
+ #special case for hostname, must change the ACLs
+ if ($_POST['edithostname'] and ($_POST['edithostname'] != $clientinfo['hostname'])) {
+ $fields['hostname'] = $_POST['edithostname'];
+ $result = $acl->edit_object($_POST['clientid'],"clients", $_POST['edithostname'], $_POST['edithostname'],1, 0, 'AXO');
+ }
+ $status = scire_edit_client($_POST['clientid'], $fields);
+ $_GET['Action'] = "edit";
+ $_GET['clientid'] = $_POST['clientid'];
+}
+
+###############################################
+# Delete a client.
+if ($_POST['delete_confirm']) {
+ check_action_access("Delete Client");
+ $status = scire_del_client($_POST['clientid']);
+ $acl->del_object($_POST['clientid'], 'AXO', TRUE); #True means erase referencing objects.
+ header('Location: ' . $baseurl . 'clients.php');
+}
+
+switch($_GET['Action']) {
+ case "addgroup":
+ $smarty->assign('desc', "Add a client to a client group.");
+ $smarty->assign('clientid', $_GET['clientid']);
+ $smarty->assign('groups', $acl->format_groups($acl->sort_groups('AXO'), TEXT));
+ $ingroups = array();
+ $ingroups = $acl->get_object_groups($_GET['clientid'],'AXO');
+ var_dump($ingroups);
+ $smarty->assign('ingroups', $ingroups);
+ case "create":
+ check_action_access("Add Client");#Access check
+ $smarty->assign('desc', "Add a client.");
+ $smarty->assign('groups', $acl->format_groups($acl->sort_groups('AXO'), TEXT));
+ $smarty->assign('gli_profiles', get_scire_gli_profiles());
+ $smarty->assign('oss', get_scire_oss());
+ $smarty->assign('users', get_scire_users('username', 'desc'));
+ break;
+ case "edit":
+ check_action_access("Edit Client");#Access check
+ $acls = array();
+ #make the topbar look good
+ $smarty->assign('desc', "Edit client information.");
+ $clientinfo = get_scire_client($_GET['clientid']);
+ $smarty->assign('client', $clientinfo);
+ $smarty->assign('clientid', $_GET['clientid']);
+ $smarty->assign('gli_profiles', get_scire_gli_profiles());
+ $smarty->assign('oss', get_scire_oss());
+ $smarty->assign('users', get_scire_users('username', 'desc'));
+
+ $clientgroups = array();
+ $groups = $acl->get_object_groups($_GET['clientid'],'AXO');
+ if ($groups) {
+ foreach ($groups as $group) {
+ $group_data = $acl->get_group_data($group, 'AXO');
+ $clientgroups_entry['name'] = $group_data[3];
+ $clientgroups_entry['id'] = $group_data[0];
+ if ($group_data[1]) {
+ $parent_group_data = $acl->get_group_data($group_data[1],'AXO');
+ $clientgroups_entry['parent'] = $parent_group_data[3];
+ } else {
+ $clientgroups_entry['parent'] = "";
+ }
+ array_push($clientgroups, $clientgroups_entry);
+ $result_acl_ids = $acl->search_acl(FALSE,FALSE,
+ FALSE,FALSE,FALSE,
+ FALSE,FALSE,$group_data[3],FALSE);
+ foreach ($result_acl_ids as $acl_id) {
+ array_push($acls, $acl->get_acl($acl_id));
+ }
+ }
+ }
+ $smarty->assign('groups', $clientgroups);
+
+ $ugroups = $acl->format_groups($acl->sort_groups('aro'), 'ARRAY');
+ $smarty->assign('ugroups', $ugroups);
+
+ #Format of search: aco_section, aco_value, aro_section, aro_value, aro_group_name, axo_section, axo_value, axo_group_name, return_value
+ $result_acl_ids = $acl->search_acl(FALSE,FALSE,
+ FALSE,FALSE,FALSE,
+ 'clients',$clientinfo['hostname'],FALSE,FALSE);
+ foreach ($result_acl_ids as $acl_id) {
+ array_push($acls, $acl->get_acl($acl_id));
+ }
+ #pre_var_dump($acls);
+ $smarty->assign('acls',$acls);
+ break;
+ case "delete":
+ check_action_access("Delete Client");#Access check
+ $clientinfo = get_scire_client($_GET['clientid']);
+ $smarty->assign('client', $clientinfo);
+ $smarty->assign('clientid', $_GET['clientid']);
+ break;
+}
+
+$smarty->assign('client_statuses', get_client_statuses() );
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display('client.tpl');
+#pre_var_dump($client_statuses);
+?>
diff --git a/scire/clients.php b/scire/clients.php
new file mode 100755
index 0000000..1f447b2
--- /dev/null
+++ b/scire/clients.php
@@ -0,0 +1,231 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+$leftbar_submenu = array();
+$template = "clients.tpl";
+$status = "";
+$smarty->assign('statusfilters', array('', 'Pending','Active','Inactive','Rejected','Retired', 'All'));
+check_action_access("View Clients");
+############################################
+## Deal with submitted forms first.
+if ($_POST['addgroupname']) { #Adding a group.
+ check_action_access("Add ClientGroup");
+ if (!$_POST['parentgroup']) {
+ $_POST['parentgroup'] = 0;
+ }
+ $newgroup_id = $acl->add_group($_POST['addgroupname'], $_POST['addgroupname'], $_POST['parentgroup'], 'AXO');
+ $_GET['Action'] = "added";
+ $_GET['View'] = "groups";
+ $status = "Client Group Added Successfully.";
+}
+if ($_POST['editgroupname']) {
+ check_action_access("Edit ClientGroup");
+ $group_id = $acl->edit_group($_POST['groupid'], $_POST['editgroupname'], $_POST['editgroupname'], $_POST['parentgroup'], 'AXO');
+ $_GET['Action'] = "edited";
+ $_GET['View'] = "groups";
+ $status = "Client Group Edited Successfully.";
+}
+if($_POST['delgroup_confirm']) {
+ check_action_access("Delete ClientGroup");
+ #Check if the group has children.
+ $result = $acl->del_group($_POST['delgroup'],TRUE, 'AXO');
+ if ($result) {
+ $status = "Group deleted successfully.";
+ } else {
+ $status = "ERROR: Group could not be successfully deleted.";
+ }
+ $_GET['Action'] = "deleted";
+ $_GET['View'] = "groups";
+}
+#Admin access only.
+if($_POST['pend_approve']) {
+ check_action_access("Approve/Reject Pending Clients");
+ foreach ($_POST['pending_ids'] as $pend_id) {
+ $result = scire_approve_client($pend_id);
+ if ($result) {
+ $status .= "Client $pend_id approved successfully.";
+ $clientinfo = get_scire_client($pend_id);
+ $obj_id = $acl->add_object("clients", $clientinfo['hostname'], $clientinfo['hostname'], 1, 0, 'AXO');
+ print "Object id: $obj_id <BR>";
+ } else {
+ $status .= "ERROR: Client $pend_id could not be successfully approved.";
+ }
+ }
+}
+if($_POST['pend_reject']) {
+ check_action_access("Approve/Reject Pending Clients");
+ foreach ($_POST['pending_ids'] as $pend_id) {
+ $result = scire_reject_client($pend_id);
+ if ($result) {
+ $status .= "Client $pend_id rejected!";
+ } else {
+ $status .= "ERROR: Client $pend_id could not be successfully rejected.";
+ }
+ }
+}
+
+
+if($_POST['statusfilter']) {
+ if ( check_access("View Pending Clients") ) {
+ $_GET['View'] = $_POST['statusfilter'];
+ }
+}
+
+$smarty->assign('desc', "View, create, edit, and delete clients");
+
+########################################
+# Generate content
+
+switch($_GET['View']) {
+ case "groups":
+ $template = "clients_groups.tpl";
+ switch($_GET['Action']) {
+ case "create":
+ add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "clients.php?View=groups");
+ $smarty->assign('groups', $acl->format_groups($acl->sort_groups('AXO'), TEXT));
+ break;
+ case "edit":
+ add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "clients.php?View=groups");
+ $smarty->assign('groups', $acl->format_groups($acl->sort_groups('AXO'), TEXT));
+ $smarty->assign('groupid', $_GET['groupid']);
+ $smarty->assign('groupdata', $acl->get_group_data($_GET['groupid'], 'AXO'));
+ break;
+ case "delete":
+ add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "clients.php?View=groups");
+ $smarty->assign('groupid', $_GET['groupid']);
+ break;
+ default: #Show clientgroups.
+ add_leftbar($leftbar_menu, "Clients", "clients.php");
+ add_leftbar($leftbar_menu, "Permissions", "clients.php?View=permissions");
+ $smarty->assign('leftbar_submenu_title', "Actions");
+ if ( check_access("Add ClientGroup") ) {
+ add_leftbar($leftbar_submenu, "Add Client Group", "clients.php?View=groups&Action=create");
+ }
+
+
+ $groups = $acl->format_groups($acl->sort_groups('AXO'), HTML);
+ $smarty->assign('groups', $groups);
+
+ break;
+ }
+ break;
+ case "permissions":
+ $smarty->assign('leftbar_submenu_title', "Actions");
+ check_action_access("View Permissions");
+ if ( check_access("Assign Permission") ) {
+ add_leftbar($leftbar_submenu, "Assign Permission", "assign_permission.php");
+ }
+ $template = "permissions.tpl";
+ $smarty->assign('type','clients');
+ $ugroups = $acl->format_groups($acl->sort_groups('aro'), 'ARRAY');
+ $smarty->assign('ugroups', $ugroups);
+ $cgroups = $acl->format_groups($acl->sort_groups('axo'), 'ARRAY');
+ $smarty->assign('cgroups', $cgroups);
+
+ #pre_var_dump($groups);
+
+ $acls = array();
+ #Format of search: aco_section, aco_value, aro_section, aro_value, aro_group_name, axo_section, axo_value, axo_group_name, return_value
+ $result_acl_ids = $acl->search_acl(FALSE,FALSE,
+ FALSE,FALSE,FALSE,
+ FALSE,FALSE,FALSE,FALSE);
+ foreach ($result_acl_ids as $acl_id) {
+ $this_acl = $acl->get_acl($acl_id);
+ if ($this_acl['aco']['scire_ui']) {
+ next;
+ } else {
+ array_push($acls, $this_acl);
+ }
+ }
+ #pre_var_dump($acls);
+ $smarty->assign('acls',$acls);
+ break;
+ case "Pending":
+ case "Inactive":
+ case "Rejected":
+ case "Retired":
+ case "All":
+ #Will need to grab only pending clients. Will need to hardcode the field list unless making settings for it.
+ add_leftbar($leftbar_menu, "View Groups", "clients.php?View=groups");
+ add_leftbar($leftbar_menu, "View Permissions", "clients.php?View=permissions");
+
+ #Set information about the fields (display name, sortable)
+ $f_attr = get_clients_fields();
+ $smarty->assign('f_attr', $f_attr);
+
+ if (!$_GET['sorton']) {
+ $_GET['sorton'] = 'installtime';
+ }
+ if (!$_GET['sortdir']) {
+ $_GET['sortdir'] = 'asc';
+ }
+ $smarty->assign('sorton', $_GET['sorton']);
+ $smarty->assign('sortdir', $_GET['sortdir']);
+
+ #Grab the field list.
+ $fields = explode(',', $_SESSION['settings']['clients_page_fields']);
+ $fields = array("hostname", "ip", "mac", "digest", "status", "installtime");
+ $smarty->assign('fields',$fields);
+
+ $clients = get_scire_clients($_GET['sorton'], $_GET['sortdir'], $_GET['View']);
+ $smarty->assign('clients', $clients);
+ break;
+ default: #Show clients.
+ add_leftbar($leftbar_menu, "View Groups", "clients.php?View=groups");
+ add_leftbar($leftbar_menu, "View Permissions", "clients.php?View=permissions");
+ $smarty->assign('leftbar_submenu_title', "Actions");
+ if ( check_access("Add Client") ) {
+ add_leftbar($leftbar_submenu, "Create Client", "client.php?Action=create");
+ }
+ ############################################
+ ## Deal with sorting for the query.
+ if (!$_GET['sorton']) {
+ $_GET['sorton'] = $_SESSION['settings']['clients_page_sorton'];
+ }
+ if (!$_GET['sortdir']) {
+ $_GET['sortdir'] = $_SESSION['settings']['clients_page_sortdir'];
+ }
+ $smarty->assign('sorton', $_GET['sorton']);
+ $smarty->assign('sortdir', $_GET['sortdir']);
+
+ $clients = get_scire_clients($_GET['sorton'], $_GET['sortdir']);
+ #var_dump($clients);
+ foreach ($clients as $key => $client) {
+ $id = $acl->get_object_id("clients",$client['hostname'],'AXO');
+ $groups = $acl->get_object_groups($id,'AXO');
+ $group_string = "";
+ if ($groups) {
+ foreach ($groups as $group) {
+ $group_data = $acl->get_group_data($group, 'AXO');
+ $group_string .= $group_data[3]. " | ";
+ }
+ }
+ $clients[$key]['groups'] = $group_string;
+ }
+
+ #Set information about the fields (display name, sortable)
+ $f_attr = get_clients_fields();
+ $smarty->assign('f_attr', $f_attr);
+
+ #Grab the field list.
+ if ($_SESSION['settings']['clients_page_fields']) {
+ $fields = explode(',', $_SESSION['settings']['clients_page_fields']);
+ } else {
+ $fields = explode(',', get_default_clients_fields());
+ }
+ $smarty->assign('fields',$fields);
+
+ $smarty->assign('clients', $clients);
+ break;
+}
+
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('leftbar_submenu', $leftbar_submenu);
+$smarty->assign('View', $_GET['View']);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display($template);
+#var_dump($_POST);
+?>
diff --git a/scire/cron.php b/scire/cron.php
new file mode 100644
index 0000000..10ba80d
--- /dev/null
+++ b/scire/cron.php
@@ -0,0 +1,672 @@
+<?php
+ /*
+ * Mick Sear, eCreate, May 2005
+ * http://www.ecreate.co.uk
+ * Modified by: Rodrigo Lazo, June 2007
+ * License: GPL
+ * Version: 1.1
+ */
+
+ /*
+ * Added functinality :
+ *
+ * - Input validation.
+ * - Support for step argument ("/")
+ * - Cron Exception for non-recoveral errors
+ * - Field expansion (given a month, generate all the possible
+ * values for every other field)
+ */
+
+ /*$cron = "15,33,48 1-10 * * *";
+ $cp = new CronParser($cron);
+ echo "Cron $cron last ran on:";
+ print_r($cp->getLastRan());
+ echo nl2br($cp->getDebug());*/
+
+ //
+ // Know bugs:
+ //
+ // It can't handle too complex step arguments.
+ //
+ // */12 or 1-3/4 are ok
+ // 1,4-5/20,2 or 1,2,3,4,5,10-30/5 isn't supported
+ //
+
+class CronException extends Exception {
+ // Redefine the exception so message isn't optional
+ public function __construct($message, $code = 0) {
+ // some code
+
+ // make sure everything is assigned properly
+ parent::__construct($message, $code);
+ }
+
+ // custom string representation of object
+ public function __toString() {
+ return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
+ }
+
+ }
+
+
+class CronParser{
+
+ var $bits = Array(); //exploded String like 0 1 * * *
+ var $now= Array(); //Array of cron-style entries for time()
+ var $lastRan; //Timestamp of last ran time.
+ var $taken;
+ var $debug;
+
+
+ function CronParser($string, $now = false, $validate_only = false){
+ $tstart = microtime();
+ $this->debug("<b>Working on cron schedule: $string</b>");
+ $this->bits = @explode(" ", $this->sanitize_input($string));
+ $this->validate();
+ if ($validate_only)
+ return;
+ if ($now)
+ $this->now = explode(",", $now);
+ else
+ $this->getNow();
+ $this->calcLastRan();
+ $this->calcNextRun();
+ $tend = microtime();
+ $this->taken = $tend-$tstart;
+ $this->debug("Parsing $string taken ".$this->taken." seconds");
+
+ }
+
+ function sanitize_input($string) {
+ $tmp = trim($string);
+ $output = "";
+ $jump = false;
+ for ($i=0; $i<strlen($tmp); $i++) {
+ if ($tmp[$i] != ' ') {
+ $output = $output . $tmp[$i];
+ $jump = false;
+ }
+ else
+ if (!$jump) {
+ $output = $output . $tmp[$i];
+ $jump = true;
+ }
+ }
+ return $output;
+ }
+
+ function validate(){
+ $min = array(0,0,1,1,0);
+ $max = array(59,23,31,12,7);
+ $pattern = "/^\d+((\d+)?(,\d)?(\-\d+($|\/\d+$)?)?)+$/";
+ $range_pattern = "/^\*(\/\d+)?$/";
+ if (count($this->bits) != 5){
+ throw new CronException("Wrong number of parameters.");
+ }
+ $i=0;
+ foreach ($this->bits as $piece){
+ if ($piece == "*" || preg_match($range_pattern, $piece)) {
+ continue;
+ }
+ if (!preg_match($pattern, $piece)){
+ throw new CronException("Bad formatted entry: " . $piece);
+ }
+ foreach (explode(",",$piece) as $molecule) {
+ foreach (explode("-", $molecule) as $atom) {
+ if ($atom > $max[$i] || $atom < $min[$i]){
+ throw new CronException("Parameter out of range: " . $atom);
+ }
+ }
+ }
+ $i++;
+ }
+ }
+
+ function expandValues(){
+ $sol = array();
+ $minutes = $this->bits[0];
+ $hours = $this->bits[1];
+ $months = $this->bits[3];
+
+ if ($minutes == "*") {
+ $minutes = range(0,59);
+ } else if (strstr($minutes, "*/")) {
+ $tmp = explode("/", $minutes);
+ $minutes = $this->expand_ranges("0-59/".$tmp[1]);
+ }
+ else {
+ $minutes = $this->expand_ranges($minutes);
+ }
+
+ if ($hours == "*") {
+ $hours = range(0, 23);
+ } else if (strstr($hours, "*/")) {
+ $tmp = explode("/", $hours);
+ $minutes = $this->expand_ranges("0-23/".$tmp[1]);
+ }
+ else {
+ $hours = $this->expand_ranges($hours);
+ }
+
+ if ($months == "*") {
+ $months = range(1,12);
+ } else if (strstr($months, "*/")) {
+ $tmp = explode("/", $months);
+ $minutes = $this->expand_ranges("0-12/".$tmp[1]);
+ }
+ else {
+ $months = $this->expand_ranges($months);
+ }
+
+ return array("minutes" => $minutes, "hours" => $hours, "months" => $months);
+
+ }
+
+ function getNextArray($arr, $current) {
+ if (is_array($arr)) {
+ foreach ($arr as $v) {
+ if ($v > $current)
+ return $v;
+ }
+ }
+ return false;
+ }
+
+ function calcNextRun(){
+ $lastRan = $this->getLastRan();
+ $values = $this->expandValues();
+ $days = $this->getDaysArray($lastRan[3]);
+
+ var_dump($values);
+ ob_start();var_dump($values);$output=ob_get_contents();ob_end_clean();
+
+ $this->debug("<b>NextRun!</b> dump" . $output);
+
+ ob_start();var_dump($days);$output=ob_get_contents();ob_end_clean();
+ $this->debug("<b>dias:</b> " . $output);
+
+ $minute = $this->getNextArray($values["minutes"], $lastRan[0]);
+ if ($minute) {
+ $this->nextRun = mktime($lastRan[1], $minute, 0, $lastRan[3], $lastRan[2], $lastRan[5]);
+ return;
+ }
+ else {
+ $minute = $values["minutes"][0];
+ }
+ $this->debug("Next minute -> " . $minute);
+
+
+ $hour = $this->getNextArray($values["hours"], $lastRan[1]);
+ if ($hour) {
+ $this->nextRun = mktime($hour, $minute, 0, $lastRan[3], $lastRan[2], $lastRan[5]);
+ return;
+ }
+ else {
+ $hour = $values["hours"][0];
+ }
+
+ $day = $this->getNextArray($days, $lastRan[2]);
+ if ($day) {
+ $this->nextRun = mktime($hour, $minute, 0, $lastRan[3], $day, $lastRan[5]);
+ return;
+ }
+
+ // In this case we don't have an else statement because we
+ // need to calculate the next month first so we know wich day is the needed
+
+ $month = $this->getNextArray($values["months"], $lastRan[3]);
+ if ($month) {
+ $day = $this->getDaysArray($month);
+ $this->nextRun = mktime($hour, $minute, 0,$month, $day, $lastRan[5]);
+ return;
+ }
+ else {
+ $month = $values["months"][0];
+ $day = $this->getDaysArray($month, $lastRan[5]+1);
+ $this->nextRun = mktime($hour, $minute, 0,$month, $day, $lastRan[5]+1);
+ }
+
+ ob_start();var_dump($this->nextRun);$output=ob_get_contents();ob_end_clean();
+ $this->debug("<b>output</b> " . $output);
+
+// var_dump($this->nextRan);
+ }
+
+ function getNow(){
+ $t = strftime("%M,%H,%d,%m,%w,%Y", time()); //Get the values for now in a format we can use
+ $this->now = explode(",", $t); //Make this an array
+ //$this->debug($this->now);
+ }
+
+ function getLastRan(){
+ return explode(",", strftime("%M,%H,%d,%m,%w,%Y", $this->lastRan)); //Get the values for now in a format we can use
+ }
+
+ function getNextRun(){
+ return explode(",", strftime("%M,%H,%d,%m,%w,%Y", $this->nextRun)); //Get the values for now in a format we can use
+ }
+
+ function getDebug(){
+ return $this->debug;
+ }
+
+ function debug($str){
+ if (is_array($str)){
+ $this->debug .= "\nArray: ";
+ foreach($str as $k=>$v){
+ $this->debug .= "$k=>$v, ";
+ }
+
+ } else {
+ $this->debug .= "\n$str";
+ }
+ //echo nl2br($this->debug);
+
+ }
+
+
+ function getExtremeMonth($extreme){
+
+ if ($extreme == "END"){
+ $year = $this->now[5] - 1;
+ } else {
+ $year = $this->now[5];
+ }
+
+ //Now determine start or end month in the last year
+ if ($this->bits[3] == "*" && $extreme == "END"){//Check month format
+ $month = 12;
+ } else if ($this->bits[3] == "*" && $extreme == "START"){
+ $month = 1;
+ } else {
+ $months = $this->expand_ranges($this->bits[3]);
+ if ($extreme == "END"){
+ sort($months);
+ } else {
+ rsort($months);
+ }
+ $month = array_pop($months);
+ }
+
+ //Now determine the latest day in the specified month
+ $day=$this->getExtremeOfMonth($month, $year, $extreme);
+ $this->debug("Got day $day for $extreme of $month, $year");
+ $hour = $this->getExtremeHour($extreme);
+ $minute = $this->getExtremeMinute($extreme);
+
+ return mktime($hour, $minute, 0, $month, $day, $year);
+ }
+
+ /**
+ * Assumes that value is not *, and creates an array of valid numbers that
+ * the string represents. Returns an array.
+ */
+ function expand_ranges($str){
+ //$this->debug("Expanding $str");
+ //echo var_dump($str);
+
+ if (strstr($str, "/")){
+ $val = explode("/", $str);
+ $str = $val[0];
+ $step = $val[1];
+ if (count($val) != 2) {
+ throw new CronException("Bad formatted entry (step): " . $str);
+ }
+ }
+
+ if (strstr($str, ",")){
+ $tmp1 = explode(",", $str);
+ //$this->debug($tmp1);
+ $count = count($tmp1);
+ for ($i=0;$i<$count;$i++){//Loop through each comma-separated value
+ if (strstr($tmp1[$i], "-")){ //If there's a range in this place, expand that too
+ $tmp2 = explode("-", $tmp1[$i]);
+ //$this->debug("Range:");
+ //$this->debug($tmp2);
+ for ($j=$tmp2[0];$j<=$tmp2[1];$j++){
+ $ret[] = $j;
+ }
+ } else {//Otherwise, just add the value
+ $ret[] = $tmp1[$i];
+ }
+ }
+ } else if (strstr($str, "-")){//There might only be a range, no comma sep values at all. Just loop these
+ $range = explode("-", $str);
+ for ($i=$range[0];$i<=$range[1];$i++){
+ $ret[] = $i;
+ }
+ } else {//Otherwise, it's a single value
+ $ret[] = $str;
+ return $ret;
+ }
+ sort($ret);
+ if (isset($step)) {
+ $sol = array();
+ foreach (range(0,count($ret),$step) as $i) {
+ $sol[] = $ret[$i];
+ }
+ $ret = $sol;
+ }
+ return $ret;
+ }
+
+ /**
+ * Given a string representation of a set of weekdays, returns an array of
+ * possible dates.
+ */
+ function getWeekDays($str, $month, $year){
+ $daysInMonth = $this->daysinmonth($month, $year);
+
+ if (strstr($str, ",")){
+ $tmp1 = explode(",", $str);
+ $count = count($tmp1);
+ for ($i=0;$i<$count;$i++){//Loop through each comma-separated value
+ if (strstr($tmp1[$i], "-")){ //If there's a range in this place, expand that too
+ $tmp2 = explode("-", $tmp1[$i]);
+
+ for ($j=$start;$j<=$tmp2[1];$j++){
+ for ($n=1;$n<=$daysInMonth;$n++){
+ if ($j == jddayofweek(gregoriantojd ( $month, $n, $year),0)){
+ $ret[] = $n;
+ }
+ }
+ }
+ } else {//Otherwise, just add the value
+ for ($n=1;$n<=$daysInMonth;$n++){
+ if ($tmp1[$i] == jddayofweek(gregoriantojd ( $month, $n, $year),0)){
+ $ret[] = $n;
+ }
+ }
+ }
+ }
+ } else if (strstr($str, "-")){//There might only be a range, no comma sep values at all. Just loop these
+ $range = explode("-", $str);
+ for ($i=$start;$i<=$range[1];$i++){
+ for ($n=1;$n<=$daysInMonth;$n++){
+ if ($i == jddayofweek(gregoriantojd ( $month, $n, $year),0)){
+ $ret[] = $n;
+ }
+ }
+ }
+ } else {//Otherwise, it's a single value
+ for ($n=1;$n<=$daysInMonth;$n++){
+ if ($str == jddayofweek(gregoriantojd ( $month, $n, $year),0)){
+ $ret[] = $n;
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ function daysinmonth($month, $year){
+ if(checkdate($month, 31, $year)) return 31;
+ if(checkdate($month, 30, $year)) return 30;
+ if(checkdate($month, 29, $year)) return 29;
+ if(checkdate($month, 28, $year)) return 28;
+ return 0; // error
+ }
+
+ /**
+ * Get the timestamp of the last ran time.
+ */
+ function calcLastRan(){
+ $values = $this->expandValues();
+ echo "Calculating last ran \n";
+ echo var_dump($this->now);
+ $now = mktime($this->now[1],$this->now[0],0,$this->now[3],$this->now[2],$this->now[5]);
+ echo "Now -> ";
+ echo var_dump($now[0]);
+ if ($now < $this->getExtremeMonth("START")){
+ echo "\nCron is not due to have this year\n";
+ //The cron isn't due to have run this year yet. Getting latest last year
+ $this->debug("Last ran last year");
+ $tsLatestLastYear = $this->getExtremeMonth("END");
+
+ $this->debug("Timestamp of latest scheduled time last year is ".$tsLatestLastYear);
+ $this->lastRan = $tsLatestLastYear;
+
+ $year = date("Y", $this->lastRan);
+ $month = date("m", $this->lastRan);
+ $day = date("d", $this->lastRan);
+ $hour = date("h", $this->lastRan);
+ $minute = date("i", $this->lastRan);
+
+
+ } else { //Cron was due to run this year. Determine when it was last due
+ echo "\nCron is this year\n";
+ $this->debug("Cron was due to run earlier this year");
+ $year = $this->now[5];
+ echo "Anho: ".$year;
+ /*
+ $arMonths = $this->expand_ranges($this->bits[3]);
+ */
+ $arMonths = $values["months"];
+ echo "\nMeses: ";
+ echo var_dump($arMonths);
+ echo "\nValue Meses: ";
+ echo var_dump($values["months"]);
+ if (!in_array($this->now[3], $arMonths) && $this->bits[3] != "*"){//Not due to run this month. Get latest of last month
+ $this->debug("Cron was not due to run this month at all. This month is ".$this->now[3]);
+ $this->debug("Months array: ");
+ $this->debug($arMonths);
+ sort($arMonths);
+ do{
+ $month = array_pop($arMonths);
+ } while($month > $this->now[3]);
+ $day = $this->getExtremeOfMonth($month, $this->now[5], "END");
+ $hour = $this->getExtremeHour("END");
+ $minute = $this->getExtremeMinute("END");
+ } else if ($now < $this->getExtremeOfMonth($this->now[3], $this->now[5], "START")){ //It's due in this month, but not yet.
+ $this->debug("It's due in this month, but not yet.");
+ sort($arMonths);
+ do{
+ $month = array_pop($arMonths);
+ } while($month > $this->now[3]);
+ $day = $this->getExtremeOfMonth($month, $this->now[5], "END");
+ $hour = $this->getExtremeHour("END");
+ $minute = $this->getExtremeMinute("END");
+ } else {//It has been due this month already
+ $this->debug("Cron has already been due to run this month (".$month = $this->now[3].")");
+ $month = $this->now[3];
+ $this->debug("Getting days array");
+ $days = $this->getDaysArray($this->now[3]);
+
+ if (!in_array($this->now[2], $days)){
+ $this->debug("Today not in the schedule. Getting latest last due day");
+ //No - Get latest last scheduled day
+ sort($days);
+ do{
+ $day = array_pop($days);
+ } while($day > $this->now[2]);
+
+ $hour = $this->getExtremeHour("END");
+ $minute = $this->getExtremeMinute("END");
+
+ } else if($this->now[1] < $this->getExtremeHour("START")){//Not due to run today yet
+ $this->debug("Cron due today, but not yet. Getting latest on last day");
+ sort($days);
+ do{
+ $day = array_pop($days);
+ } while($day >= $this->now[2]);
+
+ $hour = $this->getExtremeHour("END");
+ $minute = $this->getExtremeMinute("END");
+ } else {
+ $this->debug("Cron has already been due to run today");
+ $day = $this->now[2];
+ //Yes - Check if this hour is in the schedule?
+
+ $arHours = $this->expand_ranges($this->bits[1]);
+
+ if (!in_array($this->now[1], $arHours) && $this->bits[1] != "*"){
+ $this->debug("Cron not due in this hour, getting latest in last scheduled hour");
+ //No - Get latest last hour
+ sort($arHours);
+ do{
+ $hour = array_pop($arHours);
+ //$this->debug("hour is $hour, now is ".$this->now[1]);
+ } while($hour > $this->now[1]);
+
+ $minute = $this->getExtremeMinute("END");
+
+ } else if ($now < $this->getExtremeMinute("START") && $this->bits[1] != "*"){ //Not due to run this hour yet
+ sort($arHours);
+ do{
+ $hour = array_pop($arHours);
+ } while($hour >= $this->now[1]);
+ $minute = $this->getExtremeMinute("END");
+ } else {
+ //Yes, it is supposed to have run this hour already - Get last minute
+ $hour = $this->now[1];
+ if ($this->bits[0] != "*"){
+ $arMinutes = $this->expand_ranges($this->bits[0]);
+ $this->debug($arMinutes);
+ do{
+ $minute = array_pop($arMinutes);
+ } while($minute >= $this->now[0]);
+
+ //If the first time in the hour that the cron is due to run is later than now, return latest last hour
+ if($minute > $this->now[1] || $minute == ""){
+ $this->debug("Valid minute not set");
+ $minute = $this->getExtremeMinute("END"); //The minute will always be the last valid minute in an hour
+ //Get the last hour.
+ if ($this->bits[1] == "*"){
+ $hour = $this->now[1] - 1;
+ } else {
+ $arHours = $this->expand_ranges($this->bits[1]);
+ $this->debug("Array of hours:");
+ $this->debug($arHours);
+ sort($arHours);
+ do{
+ $hour = array_pop($arHours);
+ } while($hour >= $this->now[1]);
+ }
+ }
+
+ } else {
+ $minute = $this->now[0] -1;
+ }
+ }
+
+ }
+
+ }
+ }
+ echo "Last Ran calculated";
+ echo "\n##########################\n\n";
+ $this->debug("LAST RAN: $hour:$minute on $day/$month/$year");
+ //echo var_dump($this->getDebug());
+ $this->lastRan = mktime($hour, $minute, 0, $month, $day, $year);
+
+ }
+
+ function getExtremeOfMonth($month, $year, $extreme){
+ $daysInMonth = $this->daysinmonth($month, $year);
+ if ($this->bits[2] == "*"){
+ if ($this->bits[4] == "*"){//Is there a day range?
+ //$this->debug("There were $daysInMonth days in $month, $year");
+ if ($extreme == "END"){
+ $day = $daysInMonth;
+ } else {
+ $day=1;
+ }
+ } else {//There's a day range. Ignore the dateDay range and just get the list of possible weekday values.
+ $days = $this->getWeekDays($this->bits[4],$month, $year);
+ $this->debug($this->bits);
+ $this->debug("Days array for ".$this->bits[4].", $month, $year:");
+ $this->debug($days);
+ if ($extreme == "END"){
+ sort($days);
+ } else {
+ rsort($days);
+ }
+ $day = array_pop($days);
+ }
+ } else {
+ $days = $this->expand_ranges($this->bits[2]);
+ if ($extreme == "END"){
+ sort($days);
+ } else {
+ rsort($days);
+ }
+
+ do {
+ $day = array_pop($days);
+ } while($day > $daysInMonth);
+ }
+ //$this->debug("$extreme day is $day");
+ return $day;
+ }
+
+ function getDaysArray($month, $year=0){
+ if ($year == 0) {
+ $year = $this->now[5];
+ }
+ $this->debug("Getting days for $month");
+ $days = array();
+
+ if ($this->bits[4] != "*"){
+ $days = $this->getWeekDays($this->bits[4], $month, $year);
+ $this->debug("Weekdays:");
+ $this->debug($days);
+ }
+ if ($this->bits[2] != "*" && $this->bits[4] == "*") {
+ $days = $this->expand_ranges($this->bits[2]);
+ }
+ if ($this->bits[2] == "*" && $this->bits[4] == "*"){
+ //Just return every day of the month
+ $daysinmonth = $this->daysinmonth($month, $year);
+ $this->debug("Days in ".$month.", ".$year.": ".$daysinmonth);
+ for($i = 1;$i<=$daysinmonth;$i++){
+ $days[] = $i;
+ }
+ }
+ $this->debug($days);
+
+ return $days;
+ }
+
+ function getExtremeHour($extreme){
+ if ($this->bits[1] == "*"){
+ if ($extreme == "END"){
+ $hour = 23;
+ } else {
+ $hour = 0;
+ }
+ } else {
+ $hours = $this->expand_ranges($this->bits[1]);
+ if ($extreme == "END"){
+ sort($hours);
+ } else {
+ rsort($hours);
+ }
+ $hour = array_pop($hours);
+ }
+ //$this->debug("$extreme hour is $hour");
+ return $hour;
+ }
+
+ function getExtremeMinute($extreme){
+ if ($this->bits[0] == "*"){
+ if ($extreme == "END"){
+ $minute = 59;
+ } else {
+ $minute = 0;
+ }
+ } else {
+ $minutes = $this->expand_ranges($this->bits[0]);
+ if ($extreme == "END"){
+ sort($minutes);
+ } else {
+ rsort($minutes);
+ }
+ $minute = array_pop($minutes);
+ }
+ //$this->debug("$extreme minute is $minute");
+ return $minute;
+ }
+
+}
+
+?> \ No newline at end of file
diff --git a/scire/cron2.php b/scire/cron2.php
new file mode 100644
index 0000000..eee90f0
--- /dev/null
+++ b/scire/cron2.php
@@ -0,0 +1,467 @@
+<?php
+
+ /*
+ * Crontab-syntax support
+ * Single elements : * 12
+ * Multiple elements : 1,2,3 4,6,1
+ * Ranged elements: 1-4 9-12
+ * Steped ranges : 1-16/2 *\/2
+ *
+ * Not supported
+ * Compound elements : 1,4,9-14 2,4-29,31 3,9-15,29
+ */
+
+class CronException extends Exception {
+ // Redefine the exception so message isn't optional
+ public function __construct($message, $code = 0) {
+
+ // make sure everything is assigned properly
+ parent::__construct($message, $code);
+ }
+
+ // custom string representation of object
+ public function __toString() {
+ return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
+ }
+ }
+
+class Debug {
+ private $debugLevel;
+ private $debugMessage = "";
+ private $functionScope = "main";
+
+ public function __construct($debugLevel = 0) {
+ if ($debugLevel <= 0) {
+ $this->debugLevel = 0;
+ }
+ else if ($debugLevel >= 2) {
+ $this->debugLevel = 2;
+ }
+ else
+ $this->debugLevel = 1;
+ }
+
+ public function addDebugMessage($message, $function = "") {
+ // If we change of scope we need to record the new scope
+ if ($function != "")
+ $this->functionScope = $function;
+ // What level of debugging are we in?
+ if ($this->debugLevel == 0)
+ return;
+ if ($this->debugLevel >= 2) {
+ print $this->functionScope;
+ print "------------";
+ if (is_string($message))
+ print $message;
+ else
+ echo var_dump($message);
+ print "------------";
+ }
+
+ $this->debugMessage .= "\n". $this->functionScope . ": ";
+ if (is_array($message)) {
+ ob_start();var_dump($message);$output=ob_get_contents();ob_end_clean();
+ $this->debugMessage .= $output;
+ } else
+ $this->debugMessage .= $message;
+ }
+
+ public function __toString() {
+ echo $this->debugMessage;
+ }
+}
+
+class CronParser {
+ private $input;
+ private $elements = array();
+ private $isValid = true;
+ private $_elementsRanges;
+ private $_elementPattern;
+ private $_elementRangePattern;
+ private $_elementRangeStepPattern;
+ private $_now;
+ public $debug;
+
+ function __construct($str, $debug = 1) {
+ $this->_initialize();
+ $this->debug = new Debug($debug);
+ $this->input = $str;
+ $this->_preprocessInput();
+ }
+
+ /*! Initialize some variables
+ */
+ private function _initialize() {
+ $this->isValid = false;
+ $this->_elementsRanges = array (
+ "minutes" => array (
+ "min" => 0,
+ "max" => 59),
+ "hours" => array (
+ "min" => 0,
+ "max" => 23),
+ "days" => array (
+ "min" => 1,
+ "max" => 31),
+ "months" => array (
+ "min" => 1,
+ "max" => 12),
+ "weekdays" => array(
+ "min" => 0,
+ "max" => 6));
+ // This patter may add experimental support to compound elements
+ //$this->_elementPattern = "/^\d+((\d+)?(,\d)?(\-\d+($|\/\d+$)?)?)+$/";
+ $this->_elementPattern = "/^\d+(,\d+)*$/";
+ $this->_elementRangeStepPattern = "/^(\*|\d+-\d+)\/\d+$/";
+ $this->_elementRangePattern = "/^\d+-\d+$/";
+ }
+
+ /*! Preprocess the input so it can be used
+ *
+ * This preprocessing involves: triming, eliminating useless
+ * blank spaces between elements of the entry, validation,
+ * ranges expansion, step calculation.
+ */
+ private function _preprocessInput() {
+ $this->debug->addDebugMessage("Entering function", "preprocessInput");
+
+ // Trim extra space from the beginning and end of $input
+ $tmp = trim($this->input);
+ $output= "";
+ $this->debug->addDebugMessage("Finished triming : " . $tmp);
+
+ // Eliminate extra spaces inside $input
+ $jump = false;
+ for ($i=0; $i<strlen($tmp); $i++) {
+ if ($tmp[$i] != ' ') {
+ $output = $output . $tmp[$i];
+ $jump = false;
+ }
+ else
+ if (!$jump) {
+ $output = $output . $tmp[$i];
+ $jump = true;
+ }
+ }
+ $this->debug->addDebugMessage("Cleaning finished : " . $output);
+
+ // Split $input into its elements
+ $tmp = explode(" ", $output);
+ if (count($tmp) != 5)
+ throw new CronException("Wrong number of parameters." . $output);
+ $this->elements = array ( "minutes" => $tmp[0],
+ "hours" => $tmp[1],
+ "days" => $tmp[2],
+ "months" => $tmp[3],
+ "weekdays" => $tmp[4]);
+ $this->debug->addDebugMessage("Input splitted : ");
+ $this->debug->addDebugMessage($this->elements);
+
+ // Validate input and expand values
+ foreach (array("minutes", "hours", "days", "months", "weekdays") as $elementName) {
+ $currentElement =& $this->elements[$elementName];
+ $currentRange =& $this->_elementsRanges[$elementName];
+ // It is the whole range?
+ if ($currentElement == "*")
+ {
+ // Days calculation is different
+ if (in_array($elementName, array("days", "weekdays")))
+ continue;
+
+ $currentElement = range($currentRange["min"],
+ $currentRange["max"]);
+ }
+ // It is a range with a step?
+ else if (preg_match($this->_elementRangeStepPattern, $currentElement)) {
+ $pieces = explode("/", $currentElement);
+ // if an asterix range
+ if ($pieces[0] == "*") {
+ $totalRange = range($currentRange["min"],
+ $currentRange["max"]);
+ }
+ // it *has* to be an numeric range
+ else {
+ $atoms = explode("-", $pieces[0]);
+ $atoms[0] = (int)$atoms[0];
+ $atoms[1] = (int)$atoms[1];
+ if ($atoms[0] > $atoms[1] ||
+ $atoms[0] < $currentRange["min"] || $atoms[0] > $currentRange["max"] ||
+ $atoms[1] < $currentRange["min"] || $atoms[1] > $currentRange["max"]) {
+ throw new CronException("Bad formatted entry(range): " . $currentElement);
+ }
+ $totalRange = range($atoms[0], $atoms[1]);
+ }
+ $sol = array();
+ // now use the step to filter the range
+ foreach (range(0,count($totalRange),(int)$pieces[1]) as $i) {
+ if (isset($totalRange[$i]))
+ $sol[] = $totalRange[$i];
+ }
+ $currentElement = $sol;
+ }
+ // it is a range withouth step
+ else if (preg_match($this->_elementRangePattern, $currentElement)) {
+ $atoms = explode("-", $currentElement);
+ $atoms[0] = (int)$atoms[0];
+ $atoms[1] = (int)$atoms[1];
+ if ($atoms[0] > $atoms[1] ||
+ $atoms[0] < $currentRange["min"] || $atoms[0] > $currentRange["max"] ||
+ $atoms[1] < $currentRange["min"] || $atoms[1] > $currentRange["max"]) {
+ throw new CronException("Bad formatted entry(range): " . $currentElement);
+ }
+ $currentElement = range($atoms[0], $atoms[1]);
+ }
+ // It is an element
+ else if (preg_match($this->_elementPattern, $currentElement)){
+ $sol = array();
+ if (preg_match("/^\d+$/", $currentElement)) {
+ if ((int)$currentElement > $currentRange["max"] || (int)$currentElement < $currentRange["min"]){
+ throw new CronException("Parameter out of range: " . $atom . " of " . $this->input);
+ }
+ $currentElement = array((int)$currentElement);
+ }
+ else {
+ foreach (explode(",",$currentElement) as $atom) {
+ if ((int)$atom > $currentRange["max"] || (int)$atom < $currentRange["min"]){
+ throw new CronException("Parameter out of range: " . $atom . " of " . $this->input);
+ }
+ $sol[] = (int)$atom;
+ }
+ $currentElement = $sol;
+ }
+ }
+ else {
+ throw new CronException("Bad formatted entry (element): " . $currentElement);
+ }
+ }
+ $this->isValid = true;
+ }
+
+ /*! Defines the $now of the class
+ *
+ * The only pourpuse of this function is to let the user define
+ * what time should the class take as reference to calculate Next
+ * and Prev
+ */
+ public function setNow(&$now) {
+ $this->_now = explode(",", $now);
+ }
+
+ /*! Returns the reference NOW time
+ *
+ * This function returns the reference NOW that is used by the
+ * class to make its computations. If the var is not set by the
+ * getNow method, it return time() properly formatted;
+ */
+ public function getNow() {
+ if (isset($this->_now)) {
+ return $this->_now;
+ }
+ else {
+ $t = strftime("%M,%H,%d,%m,%w,%Y", time()); //Get the values for now in a format we can use
+ return explode(",", $t); //Make this an array
+ }
+ }
+
+
+ private function getWeekDays($month, $year){
+ $ret = array();
+ echo"gettingWeekdays: all days";
+ $days = range($this->_elementsRanges["days"]["min"],
+ $this->daysInMonth($month, $year));
+ var_dump($days);
+ foreach ($days as $day){
+ if (in_array(jddayofweek(gregoriantojd($month, $day, $year),0), $this->elements["weekdays"])){
+ $ret[] = $day;
+ }
+ }
+ echo "sol:";
+ var_dump($ret);
+ return $ret;
+ }
+
+ /*! Computes the last day of a Month
+ *
+ * Given a month and a year, this function calculates the last
+ * day of the month. It supports leap years (february 29)
+ */
+ private function daysInMonth($month, $year){
+ if(checkdate($month, 31, $year)) return 31;
+ if(checkdate($month, 30, $year)) return 30;
+ if(checkdate($month, 29, $year)) return 29;
+ if(checkdate($month, 28, $year)) return 28;
+ return 0; // error
+ }
+
+ /*! Computes the Days of a Month
+ *
+ * Given a month, it calculates the days that fulfill the
+ * requirements of the cron string
+ */
+ private function getDaysArray($month, $year = 0) {
+ $now = $this->getNow();
+ if ($year == 0) {
+ $year = $now[5];
+ }
+// $this->debug("Getting days for $month");
+ $days = array();
+
+ if (is_array($this->elements["weekdays"])) {
+ $days = $this->getWeekDays($month, $year);
+// $this->debug("Weekdays:");
+// $this->debug($days);
+ if (is_array($this->elements["days"])) {
+ $days += $this->elements["days"];
+ }
+ }
+ else {
+ if (is_array($this->elements["days"]))
+ $days = $this->elements["days"];
+ else
+ $days = range($this->_elementsRanges["days"]["min"],
+ $this->daysInMonth($month, $year));
+ }
+// $this->debug($days);
+ return $days;
+ }
+
+ /*! Retrieves the next element of the array
+ *
+ * Given an array and an element, it calculates the next element
+ * of the array and returns it, false otherwise
+ */
+ private function getNextArray($arr, $current) {
+ if (is_array($arr)) {
+ foreach ($arr as $v) {
+ if ($v >= $current)
+ return $v;
+ }
+ }
+ return false;
+ }
+
+ /*! Retrieves the next element of the array
+ *
+ * Given an array and an element, it calculates the previous element
+ * of the array and returns it, false otherwise
+ */
+ private function getPrevArray($arr, $current) {
+ if (is_array($arr)) {
+ foreach ($arr as $v) {
+ if ($v <= $current)
+ return $v;
+ }
+ }
+ return false;
+ }
+
+ private function getNextMonth(&$sol){
+ //month
+ $tmp = $this->getNextArray($this->elements["months"], $sol["month"]);
+ echo "next month: " ;
+ echo var_dump($tmp);
+ if ($tmp === false) {
+ $days = $this->getDaysArray($this->elements["months"][0], $sol["year"]+1);
+ return array($this->elements["minutes"][0],
+ $this->elements["hours"][0],
+ $days[0],
+ $this->elements["months"][0],
+ $sol["year"]+1);
+ }
+ else if ($tmp != $sol["month"]) {
+ $days = $this->getDaysArray($tmp, $sol["year"]);
+ return array($this->elements["minutes"][0],
+ $this->elements["hours"][0],
+ $days[0],
+ $tmp,
+ $sol["year"]);
+ }
+ $sol["month"] = $tmp;
+ return $this->getNextDay($sol);
+ }
+
+ private function getNextDay(&$sol) {
+ $tmp = $this->getNextArray($this->getDaysArray($sol["month"], $year), $sol["day"]);
+ echo "next day:";
+ echo var_dump($tmp);
+ if ($tmp === false) {
+ $sol["month"] += 1;
+ $sol["day"] = $this->_elementsRanges["days"]["min"];
+ return $this->getNextMonth($sol);
+ }
+ else if ($tmp != $sol["day"]) {
+ return array($this->elements["minutes"][0],
+ $this->elements["hours"][0],
+ $tmp,
+ $sol["month"],
+ $sol["year"]);
+ }
+ $sol["day"] = $tmp;
+ return $this->getNextHour($sol);
+
+ }
+
+ private function getNextHour(&$sol) {
+ $tmp = $this->getNextArray($this->elements["hours"], $sol["hour"]);
+ echo "next hour:";
+ echo var_dump($tmp);
+ if ($tmp === false) {
+ $sol["day"] += 1;
+ $sol["hour"] = $this->_elementsRanges["hours"]["min"];
+ return $this->getNextDay($sol);
+ }
+ else if ($tmp != $sol["hour"]) {
+ return array($this->elements["minutes"][0],
+ $tmp,
+ $sol["day"],
+ $sol["month"],
+ $sol["year"]);
+ }
+ $sol["hour"] = $tmp;
+ return $this->getNextMinute($sol);
+ }
+
+ private function getNextMinute(&$sol) {
+ $tmp = $this->getNextArray($this->elements["minutes"], $sol["minute"]);
+ echo "next minute:";
+ echo var_dump($tmp);
+ if ($tmp === false) {
+ $sol["hour"] += 1;
+ $sol["minute"] = $this->_elementsRanges["minutes"]["min"];
+ return $this->getNextHour($sol);
+ }
+ return array($tmp,
+ $sol["hour"],
+ $sol["day"],
+ $sol["month"],
+ $sol["year"]);
+ }
+
+ public function calculateNextRun() {
+ if (!$this->isValid) {
+ throw new CronException("Invalid input");
+ }
+ $tmp = $this->getNow();
+ $sol = array (
+ "minute" => $tmp[0],
+ "hour" => $tmp[1],
+ "day" => $tmp[2],
+ "month" => $tmp[3],
+ "weekday" => $tmp[4],
+ "year" => $tmp[5]);
+ echo "now :";
+ echo var_dump($sol);
+ return $this->getNextMonth($sol);
+
+ }
+
+ public function calculatePrevRun() {
+ if (!$this->isValid) {
+ throw new CronException("Invalid input");
+ }
+ }
+
+
+}
+
+?> \ No newline at end of file
diff --git a/scire/favicon.ico b/scire/favicon.ico
new file mode 100644
index 0000000..0d01a39
--- /dev/null
+++ b/scire/favicon.ico
Binary files differ
diff --git a/scire/images/scire.png b/scire/images/scire.png
new file mode 100644
index 0000000..cf63903
--- /dev/null
+++ b/scire/images/scire.png
Binary files differ
diff --git a/scire/images/scire_trans.png b/scire/images/scire_trans.png
new file mode 100644
index 0000000..e25d580
--- /dev/null
+++ b/scire/images/scire_trans.png
Binary files differ
diff --git a/scire/images/sort_asc.png b/scire/images/sort_asc.png
new file mode 100644
index 0000000..aacd970
--- /dev/null
+++ b/scire/images/sort_asc.png
Binary files differ
diff --git a/scire/images/sort_desc.png b/scire/images/sort_desc.png
new file mode 100644
index 0000000..5d2ec1d
--- /dev/null
+++ b/scire/images/sort_desc.png
Binary files differ
diff --git a/scire/index.php b/scire/index.php
new file mode 100755
index 0000000..525a2a9
--- /dev/null
+++ b/scire/index.php
@@ -0,0 +1,21 @@
+<?php
+
+include('./.lib/common.php');
+
+#Database structure for scire modules
+#Table: modules
+#Desc:
+# id = unique int; auto_increment
+# name = varchar(20)
+# long_name = varchar(90)
+# description = varchar(500)
+# path = varchar(90) # path to the page.
+# author = varchar(50)
+# creation_date =
+# distribution = varchar(30)
+# group? like categorizing them?
+# homepage = varchar(90) #misc modules should have a website
+
+$smarty->display('index.tpl');
+
+?>
diff --git a/scire/job.php b/scire/job.php
new file mode 100644
index 0000000..8adc957
--- /dev/null
+++ b/scire/job.php
@@ -0,0 +1,274 @@
+<?php
+include('.lib/common.php');
+include('cron2.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+
+add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "jobs.php");
+
+
+$jobid = "";
+
+list($minutes,$hours,$days,$weekdays,$months) = get_cron_times();
+
+
+function scheduleUIHelper($cronString) {
+ $bits = explode(" ", $cronString);
+ if ($bits[0] != $_POST["minutes"] and $_POST["minutes"] != "other") {
+ $bits[0] = $_POST["minutes"];
+ }
+ if ($bits[1] != $_POST["hours"] and $_POST["hours"] != "other") {
+ $bits[1] = $_POST["hours"];
+ }
+ if ($bits[2] != $_POST["days"] and $_POST["days"] != "other") {
+ $bits[2] = $_POST["days"];
+ }
+ if ($bits[3] != $_POST["months"] and $_POST["months"] != "other") {
+ $bits[3] = $_POST["months"];
+ }
+ if ($bits[4] != $_POST["weekdays"] and $_POST["weekdays"] != "other") {
+ $bits[4] = $_POST["weekdays"];
+ }
+ print_r($bits);
+
+ return implode(" ",$bits);
+}
+
+#####################################################
+#Deal with submitted forms.
+
+if ($_POST['ADD']) {
+ check_action_access("Add Job");
+ if ($_POST['script']) {
+ $script = get_scire_script($_POST['script']);
+ if ($_POST['permission']) {
+ $permission = $_POST['permission'];
+ $permission = get_scire_permission_by_name($permission);
+ $permission = $permission['permid'];
+ # print "Permission is: $permission";
+ } else {
+ $permission = $script['permission'];
+ }
+ if ($_POST['priority']) {
+ $priority = $_POST['priority'];
+ } else {
+ $priority = $script['priority'];
+ }
+ } else { $status .= "ERROR: No script selected!"; }
+ if ($_POST['description']) {
+ $description = $_POST['description'];
+ } else {
+ $description = "No description provided.";
+ }
+ $pending = sizeof($_POST['clients']) + sizeof($_POST['clientgroups']);
+
+ if (!$status and ($pending or $_POST['clientgroups'])) { #We have a script and clients;
+ # Get the schedule! All fields are required or else you're SOL
+ $scheduleComplete = $_POST["minute1"] and $_POST["hour1"] and
+ $_POST["day1"] and $_POST["month1"] and $_POST["weekday1"];
+ if ($scheduleComplete) {
+ $str = implode(" ", array($_POST["minute1"], $_POST["hour1"],
+ $_POST["day1"], $_POST["month1"], $_POST["weekday1"]));
+ } else {
+ $str = "";
+ }
+# pre_var_dump($_POST);
+# pre_var_dump($scheduleComplete);
+ pre_var_dump($str);
+
+ try {
+ $result = scire_add_job($_POST['script'], $priority, $_SESSION['userid'], $permission, $description, $pending, $_POST['clients'], $_POST['clientgroups'], $dependency, $str, $_POST['validity_period']);
+
+ if (!$result) {
+ $status .= "Job successfully added.";
+ } else {
+ $status .= "Error occurred during job addition. $result";
+ }
+ } catch (CronException $e) { print_r($e); }
+
+ }
+}
+
+###############################################
+
+
+###############################################
+# Editing a job's information.
+if ($_POST['EditJobSubmit']) {
+ check_action_access("Edit Job");
+ $jobinfo = get_scire_job($_GET['jobid']);
+ $smarty->assign('job', $jobinfo);
+
+ if (isset($_POST['editpriority']) and ($_POST['editpriority'] != $jobinfo['priority'])) {
+ $fields['priority'] = $_POST['editpriority'];
+ }
+ if ($_POST['permission'] and ($_POST['permission'] != $jobinfo['permission'])){
+ $fields['permission'] = $_POST['permission'];
+ }
+ if ($_POST['description'] and ($_POST['description'] != $jobinfo['description'])) {
+ $fields['description'] = trim($_POST['description']);
+ }
+ if ($_POST['script'] and ($_POST['script'] != $jobinfo['script'])) {
+ $fields['script'] = $_POST['script'];
+ }
+ if ($_POST['run_schedule'] and ($_POST['run_schedule'] != $jobinfo['run_schedule'])) {
+ try{
+ $c = new CronParser($_POST['run_schedule']);
+ $fields['run_schedule'] = $_POST['run_schedule'];
+ } catch (CronException $e) {}
+ } else {
+ $isScheduleUI = $_POST["minutes"] and $_POST["hours"] and $_POST["days"] and $_POST["months"] and $_POST["weekdays"];
+ if ($isScheduleUI)
+ try{
+ $tmp = scheduleUIHelper($jobinfo["run_schedule"]);
+ $c = new CronParser($tmp);
+ $fields['run_schedule'] = $tmp;
+ } catch (CronException $e) {}
+ }
+ if ($_POST['validity_period'] and ($_POST['validity_period'] != $jobinfo['validity_period'])) {
+ $fields['validity_period'] = $_POST['validity_period'];
+ }
+ $status = scire_edit_job($_POST['jobid'], $fields);
+ $_GET['Action'] = "edit";
+ $_GET['jobid'] = $_POST['jobid'];
+}
+
+###############################################
+# Delete a job.
+if ($_POST['delete_confirm']) {
+ check_action_access("Delete Job");
+# $status = scire_del_job($_POST['jobid']);
+ header('Location: ' . $baseurl . 'jobs.php');
+}
+if ($_POST['delete_cancel']) {
+ header('Location: ' . $baseurl . 'jobs.php');
+}
+
+########################################################
+################## MAIN SWITCH #########################
+switch($_GET['Action']) {
+ case "create":
+ check_action_access("Add Job"); #Access check
+ add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "jobs.php");
+
+ if ($_GET['scriptid']) {
+ $_GET['scriptid'] = (int) $_GET['scriptid'];
+ $script = get_scire_script($_GET['scriptid']);
+ $smarty->assign('script', $script);
+ # print $script['script_data'];
+ preg_match_all('/%%(.*?)%%/', $script['script_data'], $matches);
+ $smarty->assign('dyn_tags', $matches[1]);
+ foreach ($matches[1] as $tag) {
+ $tag_values[$tag] = get_dyn_tag_value($_GET['scriptid'],$tag);
+ }
+ $smarty->assign('tag_values', $tag_values);
+
+ pre_var_dump($tag_values);
+ }
+
+ if ($_GET['clientid']) {
+ $_GET['clientid'] = (int) $_GET['clientid'];
+ $client = get_scire_client($_GET['clientid']);
+ #$id = $acl->get_object_id("clients",$client['hostname'],'AXO'
+
+ $smarty->assign('client', $client);
+ }
+ ########################################################
+
+ $permissions = array();
+ $all_permissions = $acl->get_objects(NULL, 1, 'ACO');
+ foreach ($all_permissions as $categoryname => $cat) {
+ #print "Perm: $perm<br>Permname: $permname<br>";
+ if ($categoryname != $scire_ui_section) {
+ foreach ($cat as $perm) {
+ array_push($permissions, $perm);
+ }
+ }
+ }
+ $smarty->assign('perms', $permissions);
+ #pre_var_dump($permissions);
+ $smarty->assign('priorities', get_priorities());
+
+
+ $scripts = get_scire_scripts();
+ $smarty->assign('scripts', $scripts);
+
+ $smarty->assign('cgroups', $acl->format_groups($acl->sort_groups('AXO'), TEXT));
+ $clients = get_scire_clients('hostname', 'asc');
+ $smarty->assign('clients', $clients);
+ $smarty->assign('minutes', $minutes);
+ $smarty->assign('hours', $hours);
+ $smarty->assign('days', $days);
+ $smarty->assign('months', $months);
+ $smarty->assign('weekdays', $weekdays);
+
+ break;
+ case "edit":
+ check_action_access("Edit Job");#Access check
+ $acls = array();
+ #make the topbar look good
+ $smarty->assign('desc', "Edit client information.");
+ $jobinfo = get_scire_job($_GET['jobid']);
+ $smarty->assign('job', $jobinfo);
+ $smarty->assign('jobid', $_GET['jobid']);
+ $smarty->assign('scripts', get_scire_scripts());
+// $cron = new CronParser("*/2 7-18/3 * * *");
+// $smarty->assign('cron', $cron);
+ $smarty->assign('minutes', $minutes);
+ $smarty->assign('hours', $hours);
+ $smarty->assign('days', $days);
+ $smarty->assign('months', $months);
+ $smarty->assign('weekdays', $weekdays);
+
+ $bits = explode(" ", $jobinfo["run_schedule"]);
+ $smarty->assign('selectedMinute', array_key_exists($bits[0], $minutes) ? $bits[0] : "other" );
+ $smarty->assign('selectedHour', array_key_exists($bits[1], $hours) ? $bits[1] : "other" );
+ $smarty->assign('selectedDay', array_key_exists($bits[2], $days) ? $bits[2] : "other" );
+ $smarty->assign('selectedMonth', array_key_exists($bits[3], $months) ? $bits[3] : "other" );
+ $smarty->assign('selectedWeekday', array_key_exists($bits[4], $minutes) ? $bits[4] : "other" );
+
+// $smarty->assign('gli_profiles', get_scire_gli_profiles());
+// $smarty->assign('oss', get_scire_oss());
+// $smarty->assign('users', get_scire_users('username', 'desc'));
+
+// $clientgroups = array();
+ $groups = $acl->get_object_groups($_GET['jobid'],'AXO');
+ if ($groups) {
+ foreach ($groups as $group) {
+ $group_data = $acl->get_group_data($group, 'AXO');
+ $clientgroups_entry['name'] = $group_data[3];
+ $clientgroups_entry['id'] = $group_data[0];
+ if ($group_data[1]) {
+ $parent_group_data = $acl->get_group_data($group_data[1],'AXO');
+ $clientgroups_entry['parent'] = $parent_group_data[3];
+ } else {
+ $clientgroups_entry['parent'] = "";
+ }
+ array_push($clientgroups, $clientgroups_entry);
+ $result_acl_ids = $acl->search_acl(FALSE,FALSE,
+ FALSE,FALSE,FALSE,
+ FALSE,FALSE,$group_data[3],FALSE);
+ foreach ($result_acl_ids as $acl_id) {
+ array_push($acls, $acl->get_acl($acl_id));
+ }
+ }
+ }
+ $smarty->assign('groups', $clientgroups);
+
+ case "delete":
+ check_action_access("Delete Job");#Access check
+ $jobinfo = get_scire_job($_GET['jobid']);
+ $smarty->assign('job', $jobinfo);
+ #pre_var_dump($jobinfo);
+ $smarty->assign('jobid', $_GET['jobid']);
+ break;
+}
+
+$smarty->assign('get', $_GET);
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display('job.tpl');
+#pre_var_dump($_POST);
+?>
diff --git a/scire/jobs.php b/scire/jobs.php
new file mode 100755
index 0000000..d54f674
--- /dev/null
+++ b/scire/jobs.php
@@ -0,0 +1,77 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+$leftbar_submenu = array();
+$template = "jobs.tpl";
+$error_msg = "";
+
+check_action_access("View Jobs");
+############################################
+## Deal with submitted forms first.
+
+#Set information about the fields (display name, sortable)
+$f_attr = get_jobs_fields();
+$smarty->assign('f_attr', $f_attr);
+
+if (!$_GET['sorton']) {
+ $_GET['sorton'] = 'jobid';
+}
+if (!$_GET['sortdir']) {
+ $_GET['sortdir'] = 'asc';
+}
+$smarty->assign('sorton', $_GET['sorton']);
+$smarty->assign('sortdir', $_GET['sortdir']);
+
+#Grab the field list.
+if ($_SESSION['settings']['jobs_page_fields']) {
+ $fields = explode(',', $_SESSION['settings']['jobs_page_fields']);
+} else {
+ $fields = explode(',', get_default_jobs_fields());
+}
+#$fields = array("hostname", "ip", "mac", "digest", "status", "installtime");
+$smarty->assign('fields',$fields);
+
+$jobs = get_scire_jobs($_GET['sorton'], $_GET['sortdir'], 'All');
+$smarty->assign('jobs', $jobs);
+
+
+#$jobs = $db->select(array("c.hostname", "j.*"), #FROM
+# "clients c, jobs j, jobs_clients jc", #WHERE
+# "j.jobid = jc.jobid AND jc.clientid = c.clientid");
+#print "<pre>";
+#pre_var_dump($jobs); #For debugging.
+#$client_groups = array();
+foreach( $jobs as $key => $job) {
+ $id = $acl->get_object_id("clients",$job['hostname'],'AXO');
+ $groups = $acl->get_object_groups($id,'AXO');
+ $group_string = "";
+ if ($groups) {
+ foreach ($groups as $group) {
+ $group_data = $acl->get_group_data($group, 'AXO');
+ $group_string .= $group_data[3]. " | ";
+ $client_groups["$group"] = $group_data[3];
+ }
+ }
+ $jobs[$key]['groups'] = $group_string;
+}
+#print "</pre>";
+
+$smarty->assign('jobs', $jobs);
+
+if ($_POST['searchfield']) {
+ $error_msg .= "Um, yeah... not done yet.";
+}
+
+#Gather groups of clients. it's a phpgacl command.
+$smarty->assign('leftbar_submenu_title', "Actions");
+if ( check_access("Add Job") ) {
+ add_leftbar($leftbar_submenu, "Add Job", "add_job.php");
+}
+$smarty->assign('client_groups', $client_groups);
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('leftbar_submenu', $leftbar_submenu);
+
+$smarty->display('jobs.tpl');
+?>
diff --git a/scire/light_blue.css b/scire/light_blue.css
new file mode 100644
index 0000000..5995f3b
--- /dev/null
+++ b/scire/light_blue.css
@@ -0,0 +1,126 @@
+ html {
+ margin: 0px;
+ }
+ body {
+ margin: 0px;
+ font-family: Bitstream Vera Sans, Helvetica, Sans;
+ font-size: 10pt;
+ }
+ form {
+ margin: 0px;
+ padding: 0px;
+ }
+ p {
+ margin: 5px;
+ }
+ h1 {
+ margin: 5px;
+ margin-bottom: 0px;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ h2 {
+ margin: 5px;
+ font-size: 1.1em;
+ font-weight: normal;
+ }
+ #logobar {
+ background: url("images/lightning.png") no-repeat;
+ }
+ #topbar {
+ border-top: 1px solid #000000;
+ background-color: #1E1E74;
+ }
+ #topbar table tr td a {
+ text-decoration: none;
+ }
+ #topbar table tr td a:hover {
+ color: #ffffff;
+ text-decoration: underline;
+ font-weight: bold;
+ }
+ #leftbar {
+ background-color: #ffffff;
+ border-top: 1px solid #000000;
+ }
+ #header {
+ border-top: 1px solid #000000;
+ }
+ #content {
+ padding: 7px 5px 5px;
+ }
+ #menu,#submenu {
+ width: 150px;
+ margin: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ border-right: 1px solid #ffffff;
+ list-style: none;
+ }
+ #menu li {
+ width: 150px;
+ border-bottom: 1px solid #ffffff;
+ }
+ #submenu li {
+ width: 140px;
+ margin-left: 10px;
+ border-bottom: 1px solid #ffffff;
+ }
+ a.menuitem {
+ display: block;
+ position: relative;
+ margin: 0px;
+ padding: 1px;
+ padding-left: 4px;
+ background-color: #36D3F0;
+ color: #000000;
+ text-decoration: none;
+ }
+ a.menuitem:hover {
+ color: #ffffff;
+ font-weight: bold;
+ }
+ .box {
+ border: 1px solid #000000;
+ font-size: 0.8em;
+ }
+ .box td {
+ border: none;
+ }
+ td.boxtitle {
+ padding: 5px;
+ border-top: 1px solid #d1ddf5;
+ border-right: 1px solid #7a818f;
+ border-bottom: 1px solid #7a818f;
+ border-left: 1px solid #d1ddf5;
+ background-color: #36D3F0;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ .table {
+ border: none;
+ border-spacing: 5px;
+ }
+ .table th {
+ padding: 2px 5px 0px;
+ border: none;
+ text-align: left;
+ }
+ .table td {
+ padding: 5px 5px 0px;
+ border: none;
+ border-top: 1px dotted #7a818f;
+ }
+ .optiongroup td {
+ padding-top: 5px;
+ border: none;
+ }
+ .optiongroup td:first-child {
+ padding-left: 5px;
+ }
+ .optiongroup td:last-child {
+ padding-right: 5px;
+ }
+ .optiongroup tr:last-child td {
+ padding-bottom: 5px;
+ }
diff --git a/scire/login.php b/scire/login.php
new file mode 100644
index 0000000..264fbdc
--- /dev/null
+++ b/scire/login.php
@@ -0,0 +1,66 @@
+<?php
+# Configuration
+$CONFIG_DIR='/etc/scire';
+require_once($CONFIG_DIR.'/config.php');
+
+# Functions
+require_once('.lib/functions.php');
+
+# Clean config
+$basedir = normalize_path($basedir);
+$baseurl = normalize_path($baseurl);
+$smarty_dir = normalize_path($smarty_dir);
+
+# Smarty
+require_once('.lib/smarty.php');
+
+# Database class
+require_once('.lib/DB.php');
+$db = new DB($db_host, $db_username, $db_password, $db_name, $db_type);
+if (isset($db->error)) {
+ header('Content-type: text/html; charset=UTF-8');
+ $smarty->assign('title', 'Database Error');
+ $smarty->assign('message', $db->error);
+ $smarty->display('message.tpl');
+ exit(0);
+}
+
+# Database functions
+require_once('.lib/DB_functions.php');
+
+# Session class
+require_once('.lib/Session.php');
+$session = new Session($db, $db_sessions_table);
+if (isset($session->error)) {
+ header('Content-type: text/html; charset=UTF-8');
+ $smarty->assign('title', 'Session Error');
+ $smarty->assign('message', $session->error);
+ $smarty->display('message.tpl');
+ exit(0);
+}
+
+if ($_GET['logout']) {
+ unset($_SESSION['userid']);
+ unset($_SESSION['username']);
+}
+if ($_POST['username']) {
+ $user = $db->select(array('userid', 'username','password','email'), "users", "username='".$_POST['username']."'");
+ if($user[0]['username']) {
+ if ($_POST['passwd'] and (crypt($_POST['passwd'],447470567) == $user[0]['password'])) {
+ $_SESSION['userid'] = $user[0]['userid'];
+ $_SESSION['username'] = $user[0]['username'];
+ $_SESSION['useremail'] = $user[0]['email'];
+ $_SESSION['settings'] = get_scire_settings($_SESSION['userid']);
+ header("Location: " . ($_GET['afterlogin'] ? $_GET['afterlogin'] : "index.php"));
+ exit;
+ } else {
+ print "<h1>Invalid password supplied!</h1>";
+ }
+ } else {
+ print "<h1>Invalid user supplied!</h1>";
+ }
+}
+
+$smarty->display('login.tpl');
+
+?>
diff --git a/scire/main_checklogin.php b/scire/main_checklogin.php
new file mode 100644
index 0000000..f386b07
--- /dev/null
+++ b/scire/main_checklogin.php
@@ -0,0 +1,10 @@
+<?php
+session_start();
+if(!isset($_SESSION['userid'])) {
+ #print "<h1>NO MATCH</h1>";
+ header("Location: login.php?afterlogin=" . url_encode($_SERVER['REQUEST_URI']));
+}
+else {
+ print "Welcome $_SESSION[userid]<br>";
+}
+?>
diff --git a/scire/main_smarty.php b/scire/main_smarty.php
new file mode 100644
index 0000000..3ac86c4
--- /dev/null
+++ b/scire/main_smarty.php
@@ -0,0 +1,25 @@
+<?php
+ #This is the code to set up the SMARTY templates for the Main pages.
+ # it has ./ on things and sets the leftbar to show the admin list.
+ $smarty = new Smarty;
+ $smarty->template_dir = './templates';
+ $smarty->compile_dir = './templates_c';
+ $smarty->cache_dir = './cache';
+ $smarty->config_dir = './configs';
+ $smarty->assign('topbar', array(
+ array('name'=> 'Login', 'link' => 'login.php'),
+ array('name'=> 'Clients', 'link' => 'clients.php'),
+ array('name'=> 'Jobs/Tasks', 'link' => 'jobs.php'),
+ array('name'=> 'Modules', 'link' => 'modules.php'),
+ array('name'=> 'Admin', 'link' => 'admin.php')));
+ $smarty->assign('left_section_header',"Module List");
+
+ $module_list = array();
+ $module_list = get_scire_module_list();
+ #print_r($module_list);
+ $smarty->assign('leftnav', $module_list);
+
+ if($status) {
+ $smarty->assign('error', $status);
+ }
+?>
diff --git a/scire/mockups/mockup.html b/scire/mockups/mockup.html
new file mode 100644
index 0000000..e2de62a
--- /dev/null
+++ b/scire/mockups/mockup.html
@@ -0,0 +1,511 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"/>
+ <title>Scire</title>
+ <link rel="icon" href="favicon.ico" type="image/x-icon" />
+ <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
+ <style type="text/css">
+ <!--
+ html {
+ margin: 0px;
+ }
+ body {
+ margin: 0px;
+ font-family: Bitstream Vera Sans, Helvetica, Sans;
+ font-size: 10pt;
+ }
+ form {
+ margin: 0px;
+ padding: 0px;
+ }
+ p {
+ margin: 5px;
+ }
+ h1 {
+ margin: 5px;
+ margin-bottom: 0px;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ h2 {
+ margin: 5px;
+ font-size: 1.1em;
+ font-weight: normal;
+ }
+ #topbar {
+ border-top: 1px solid #000000;
+ }
+ #topbar table tr td a {
+ text-decoration: none;
+ }
+ #topbar table tr td a:hover {
+ color: #ffffff;
+ text-decoration: underline;
+ }
+ #leftbar {
+ background-color: #ffffff;
+ border-top: 1px solid #000000;
+ }
+ #header {
+ border-top: 1px solid #000000;
+ }
+ #content {
+ padding: 7px 5px 5px;
+ }
+ #menu,#submenu {
+ width: 150px;
+ margin: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ border-right: 1px solid #ffffff;
+ list-style: none;
+ }
+ #menu li {
+ width: 150px;
+ border-bottom: 1px solid #ffffff;
+ }
+ #submenu li {
+ width: 140px;
+ margin-left: 10px;
+ border-bottom: 1px solid #ffffff;
+ }
+ a.menuitem {
+ display: block;
+ position: relative;
+ margin: 0px;
+ padding: 1px;
+ padding-left: 4px;
+ background-color: #a6afc2;
+ color: #000000;
+ text-decoration: none;
+ }
+ a.menuitem:hover {
+ color: #ffffff;
+ }
+ .box {
+ border: 1px solid #000000;
+ font-size: 0.8em;
+ }
+ .box td {
+ border: none;
+ }
+ td.boxtitle {
+ padding: 5px;
+ border-top: 1px solid #d1ddf5;
+ border-right: 1px solid #7a818f;
+ border-bottom: 1px solid #7a818f;
+ border-left: 1px solid #d1ddf5;
+ background-color: #a5acba;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ .table {
+ border: none;
+ border-spacing: 5px;
+ }
+ .table th {
+ padding: 2px 5px 0px;
+ border: none;
+ text-align: left;
+ }
+ .table td {
+ padding: 5px 5px 0px;
+ border: none;
+ border-top: 1px dotted #7a818f;
+ }
+ .optiongroup td {
+ padding-top: 5px;
+ border: none;
+ }
+ .optiongroup td:first-child {
+ padding-left: 5px;
+ }
+ .optiongroup td:last-child {
+ padding-right: 5px;
+ }
+ .optiongroup tr:last-child td {
+ padding-bottom: 5px;
+ }
+ -->
+ </style>
+ </head>
+ <body link="#000000" alink="#ffffff">
+ <table width="100%" bgcolor="#ffffff" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td colspan="2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="10">
+ <tr>
+ <td width="80">
+ <a href="#"><img src="scire-logo.png" alt="Scire" border="0" width="80" height="80" /></a>
+ </td>
+ <td align="right" valign="top">
+ <form action="#">
+ <label for="search">Search:</label>
+ <input id="search" name="search" type="text" size="16" />
+ <input id="submit" name="submit" type="button" value="go" />
+ </form>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="topbar" colspan="2" height="22" bgcolor="#494949">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><font color="#ffffff">&nbsp;<a href="#"><font color="#ffffff">Overview</font></a> | <a href="mockup_jobs.html"><font color="#ffffff">Jobs</font></a> | <a href="#"><font color="#ffffff">Clients</font></a> | <a href="mockup_users.html"><font color="#ffffff">Users</font></a></font></td>
+ <td align="right"><font color="#ffffff"><a href="#"><font color="#ffffff">Logout</font></a> | <a href="#"><font color="#ffffff">Settings</font></a> | <a href="#"><font color="#ffffff">Help</font></a>&nbsp;</font></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+<!-- <td id="leftbar" valign="top" bgcolor="#a6afc2">
+ <ul id="menu">
+ <li><a class="menuitem" href="#">Groups</a></li>
+ <li><a class="menuitem" href="#">Permissions</a></li>
+ </ul>
+ <p></p>
+ <ul id="submenu">
+ <li>Actions</li>
+ <li><a class="menuitem" href="#">Create User</a></li>
+ </ul>
+ </td> -->
+ <td width="100%" valign="top">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td id="header" bgcolor="#d8d4e2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <h1>Overview</h1>
+ <h2>Welcome to Scire</h2>
+ </td>
+ <td align="right" valign="top">
+<!-- <p>OK</p>-->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="content" height="100%" valign="top" bgcolor="#ffffff">
+ <!-- begin admin
+ <ul>
+ <li><a href="admin/create_user.php">Create a User</a></li>
+ <li><a href="admin/edit_user.php">Edit a User</a></li>
+ <li><a href="admin/delete_user.php">Delete a User</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/create_usergroup.php">Create a UserGroup</a></li>
+ <li><a href="admin/edit_usergroup.php">Edit a UserGroup</a></li>
+ <li><a href="admin/delete_usergroup.php">Delete a UserGroup</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/add_permission.php">Add Permission</a></li>
+ <li><a href="admin/edit_permission.php">Edit Permission</a></li>
+ <li><a href="admin/delete_permission.php">Delete Permission</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/add_client.php">Add Client Manually</a></li>
+ <li><a href="admin/edit_client.php">Edit Clients</a></li>
+ <li><a href="admin/delete_client.php">Delete Client from Scire</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/create_clientgroup.php">Create a ClientGroup</a></li>
+ <li><a href="admin/edit_clientgroup.php">Edit a ClientGroup</a></li>
+ <li><a href="admin/delte_clientgroup.php">Delete a ClientGroup</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/assign_permissions.php">Assign Permissions</a></li>
+ </ul> end admin -->
+ <!-- begin add client
+ <form id="form1" name="form1" method="post" action="">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="hostname">Hostname:</label></td>
+ <td><input type="text" id="hostname" name="hostname" /></td>
+ </tr>
+ <tr>
+ <td><label for="mac">MAC:</label></td>
+ <td><input type="text" id="mac" name="mac" maxlength="17" /></td>
+ </tr>
+ <tr>
+ <td><label for="ip">IP:</label></td>
+ <td><input type="text" id="ip" name="ip" maxlength="15" /></td>
+ </tr>
+ <tr>
+ <td><label for="profile">Gentoo Profile Name (optional):</label></td>
+ <td><input type="text" id="profile" name="profile" /></td>
+ </tr>
+ <tr>
+ <td><label for="distribution">Distribution (optional):</label></td>
+ <td><input type="text" id="distribution" name="distribution" maxlength="50" /></td>
+ </tr>
+ <tr>
+ <td><label for="administrator">Administrator (optional):</label></td>
+ <td><input type="text" id="administrator" name="administrator" maxlength="50" /></td>
+ </tr>
+ <tr>
+ <td><label for="status">Status:</label></td>
+ <td><input type="text" id="status" name="status" maxlength="100" /></td>
+ </tr>
+ </table>
+ </td>
+ <td width="25%">
+ <label for="groups">Groups:</label><br />
+ <select id="groups" name="groups" size="14" multiple="multiple">
+ <option>{html_options values=$ids output=$groupnames selected="1"}</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <input type="submit" name="submit" value="Add Client" />
+ </form> end add client -->
+ <!-- begin permission
+ <form id="form1" name="form1" method="post" action="">
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="permname">Name:</label></td>
+ <td><input type="text" id="permname" name="permname" /></td>
+ </tr>
+ <tr>
+ <td><label for="permdesc">Description:</label></td>
+ <td><input type="text" id="permdesc" name="permdesc" /></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table class="box" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Built-in Abilities/Scripts:</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="optiongroup" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><input type="checkbox" id="update_gentoo" name="scripts" value="update_gentoo" /></td>
+ <td><label for="update_gentoo">Gentoo update</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="update_debian" name="scripts" value="update_debian" /></td>
+ <td><label for="update_debian">Debian update</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="upgrade_debian" name="scripts" value="upgrade_debian" /></td>
+ <td><label for="upgrade_debian">Debian upgrade</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="emerge_gentoo" name="scripts" value="emerge_gentoo" /></td>
+ <td><label for="emerge_gentoo">Gentoo emerge</label></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <p><input type="submit" name="submit" value="Add Permission" /></p>
+ </form> end permission -->
+ <!-- begin overview -->
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Recent Jobs</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Job Name</th>
+ <th>Last Run</th>
+ </tr>
+ <tr>
+ <td>glsa-check</td>
+ <td>2 days, 1 hour, 57 minutes</td>
+ </tr>
+ <tr>
+ <td>start sshd</td>
+ <td>1 day, 14 hours, 29 minutes</td>
+ </tr>
+ <tr>
+ <td>backup</td>
+ <td>29 minutes</td>
+ </tr>
+ <tr>
+ <td>rotate logs</td>
+ <td>22 minutes</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Stale Clients</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Time Since Last Poll</th>
+ <th>Client</th>
+ </tr>
+ <tr>
+ <td>3 hours, 42 minutes</td>
+ <td>lark</td>
+ </tr>
+ <tr>
+ <td>3 hours, 48 minutes</td>
+ <td>cockatoo</td>
+ </tr>
+ <tr>
+ <td>4 hours, 1 minute</td>
+ <td>woodpecker</td>
+ </tr>
+ <tr>
+ <td>3 days, 14 hours, 2 minutes</td>
+ <td>toucan</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Logins</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>User</th>
+ <th>Time Since Login</th>
+ </tr>
+ <tr>
+ <td>blackace</td>
+ <td>15 minutes</td>
+ </tr>
+ <tr>
+ <td>agaffney</td>
+ <td>32 minutes</td>
+ </tr>
+ <tr>
+ <td>codeman</td>
+ <td>1 hour, 1 minute</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top" colspan="3">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Security Announcements</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Type</th>
+ <th>Severity</th>
+ <th>Package</th>
+ <th>Summary</th>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>High</td>
+ <td>net-misc/rsync</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-05.xml">rsync: Potential integer overflow</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>Normal</td>
+ <td>www-apps/phpwebsite</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-04.xml">phpWebSite: Local file inclusion</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>Normal</td>
+ <td>app-antivirus/clamav</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-03.xml">ClamAV: Buffer overflow in Freshclam</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>High</td>
+ <td>x11-base/xorg-x11</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-02.xml">X.Org: Buffer overflow in XRender extension</a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table> <!-- end overview -->
+ <!-- begin users
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Users</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Username</th>
+ <th>Realname</th>
+ <th>Comment</th>
+ <th>Groups</th>
+ <th>Status</th>
+ <th>Actions</th>
+ </tr>
+ <tr>
+ <td>agaffney</td>
+ <td>Andrew Gaffney</td>
+ <td>Mr. Python</td>
+ <td>Users, Admins</td>
+ <td>Active</td>
+ <td><form id="form1" name="form1" method="post" action=""><input type="hidden" name="id" value="1" /><input type="submit" name="submit" value="Edit" /><input type="submit" name="submit" value="Delete" /></form></td>
+ </tr>
+ <tr>
+ <td>blackace</td>
+ <td>Nicholas D. Wolfwood</td>
+ <td>Mr. Ripurcodeanuone</td>
+ <td>Users, Admins</td>
+ <td>Active</td>
+ <td><form id="form2" name="form2" method="post" action=""><input type="hidden" name="id" value="2" /><input type="submit" name="submit" value="Edit" /><input type="submit" name="submit" value="Delete" /></form></td>
+ </tr>
+ <tr>
+ <td>codeman</td>
+ <td>Preston Cody</td>
+ <td>Mr. Enterprise</td>
+ <td>Users, Admins</td>
+ <td>Active</td>
+ <td><form id="form3" name="form3" method="post" action=""><input type="hidden" name="id" value="3" /><input type="submit" name="submit" value="Edit" /><input type="submit" name="submit" value="Delete" /></form></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table> end users -->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/scire/mockups/mockup_jobs.html b/scire/mockups/mockup_jobs.html
new file mode 100644
index 0000000..40a5d6c
--- /dev/null
+++ b/scire/mockups/mockup_jobs.html
@@ -0,0 +1,569 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"/>
+ <title>Scire</title>
+ <link rel="icon" href="favicon.ico" type="image/x-icon" />
+ <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
+ <style type="text/css">
+ <!--
+ html {
+ margin: 0px;
+ }
+ body {
+ margin: 0px;
+ font-family: Bitstream Vera Sans, Helvetica, Sans;
+ font-size: 10pt;
+ }
+ form {
+ margin: 0px;
+ padding: 0px;
+ }
+ p {
+ margin: 5px;
+ }
+ h1 {
+ margin: 5px;
+ margin-bottom: 0px;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ h2 {
+ margin: 5px;
+ font-size: 1.1em;
+ font-weight: normal;
+ }
+ #topbar {
+ border-top: 1px solid #000000;
+ }
+ #topbar table tr td a {
+ text-decoration: none;
+ }
+ #topbar table tr td a:hover {
+ color: #ffffff;
+ text-decoration: underline;
+ }
+ #leftbar {
+ background-color: #ffffff;
+ border-top: 1px solid #000000;
+ }
+ #header {
+ border-top: 1px solid #000000;
+ }
+ #content {
+ padding: 7px 5px 5px;
+ }
+ #menu,#submenu {
+ width: 150px;
+ margin: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ border-right: 1px solid #ffffff;
+ list-style: none;
+ }
+ #menu li {
+ width: 150px;
+ border-bottom: 1px solid #ffffff;
+ }
+ #submenu li {
+ width: 140px;
+ margin-left: 10px;
+ border-bottom: 1px solid #ffffff;
+ }
+ a.menuitem {
+ display: block;
+ position: relative;
+ margin: 0px;
+ padding: 1px;
+ padding-left: 4px;
+ background-color: #a6afc2;
+ color: #000000;
+ text-decoration: none;
+ }
+ a.menuitem:hover {
+ color: #ffffff;
+ }
+ .box {
+ border: 1px solid #000000;
+ font-size: 0.8em;
+ }
+ .box td {
+ border: none;
+ }
+ td.boxtitle {
+ padding: 5px;
+ border-top: 1px solid #d1ddf5;
+ border-right: 1px solid #7a818f;
+ border-bottom: 1px solid #7a818f;
+ border-left: 1px solid #d1ddf5;
+ background-color: #a5acba;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ .table {
+ border: none;
+ border-spacing: 5px;
+ }
+ .table th {
+ padding: 2px 5px 0px;
+ border: none;
+ text-align: left;
+ }
+ .table td {
+ padding: 5px 5px 0px;
+ border: none;
+ border-top: 1px dotted #7a818f;
+ }
+ .optiongroup td {
+ padding-top: 5px;
+ border: none;
+ }
+ .optiongroup td:first-child {
+ padding-left: 5px;
+ }
+ .optiongroup td:last-child {
+ padding-right: 5px;
+ }
+ .optiongroup tr:last-child td {
+ padding-bottom: 5px;
+ }
+ -->
+ </style>
+ </head>
+ <body link="#000000" alink="#ffffff">
+ <table width="100%" bgcolor="#ffffff" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td colspan="2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="10">
+ <tr>
+ <td width="80">
+ <a href="#"><img src="scire-logo.png" alt="Scire" border="0" width="80" height="80" /></a>
+ </td>
+ <td align="right" valign="top">
+ <form action="#">
+ <label for="search">Search:</label>
+ <input id="search" name="search" type="text" size="16" />
+ <input id="submit" name="submit" type="button" value="go" />
+ </form>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="topbar" colspan="2" height="22" bgcolor="#494949">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><font color="#ffffff">&nbsp;<a href="mockup.html"><font color="#ffffff">Overview</font></a> | <a href="mockup_jobs.html"><font color="#ffffff">Jobs</font></a> | <a href="#"><font color="#ffffff">Clients</font></a> | <a href="mockup_users.html"><font color="#ffffff">Users</font></a></font></td>
+ <td align="right"><font color="#ffffff"><a href="#"><font color="#ffffff">Logout</font></a> | <a href="#"><font color="#ffffff">Settings</font></a> | <a href="#"><font color="#ffffff">Help</font></a>&nbsp;</font></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="leftbar" valign="top" bgcolor="#a6afc2">
+ <ul id="menu">
+ <li><a class="menuitem" href="#">Create Job</a></li>
+ </ul>
+ </td>
+ <td width="100%" valign="top">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td id="header" bgcolor="#d8d4e2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <h1>Jobs</h1>
+ <h2>View, create, edit, and delete jobs</h2>
+ </td>
+ <td align="right" valign="top">
+<!-- <p>OK</p>-->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="content" height="100%" valign="top" bgcolor="#ffffff">
+ <!-- begin admin
+ <ul>
+ <li><a href="admin/create_user.php">Create a User</a></li>
+ <li><a href="admin/edit_user.php">Edit a User</a></li>
+ <li><a href="admin/delete_user.php">Delete a User</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/create_usergroup.php">Create a UserGroup</a></li>
+ <li><a href="admin/edit_usergroup.php">Edit a UserGroup</a></li>
+ <li><a href="admin/delete_usergroup.php">Delete a UserGroup</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/add_permission.php">Add Permission</a></li>
+ <li><a href="admin/edit_permission.php">Edit Permission</a></li>
+ <li><a href="admin/delete_permission.php">Delete Permission</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/add_client.php">Add Client Manually</a></li>
+ <li><a href="admin/edit_client.php">Edit Clients</a></li>
+ <li><a href="admin/delete_client.php">Delete Client from Scire</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/create_clientgroup.php">Create a ClientGroup</a></li>
+ <li><a href="admin/edit_clientgroup.php">Edit a ClientGroup</a></li>
+ <li><a href="admin/delte_clientgroup.php">Delete a ClientGroup</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/assign_permissions.php">Assign Permissions</a></li>
+ </ul> end admin -->
+ <!-- begin add client
+ <form id="form1" name="form1" method="post" action="">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="hostname">Hostname:</label></td>
+ <td><input type="text" id="hostname" name="hostname" /></td>
+ </tr>
+ <tr>
+ <td><label for="mac">MAC:</label></td>
+ <td><input type="text" id="mac" name="mac" maxlength="17" /></td>
+ </tr>
+ <tr>
+ <td><label for="ip">IP:</label></td>
+ <td><input type="text" id="ip" name="ip" maxlength="15" /></td>
+ </tr>
+ <tr>
+ <td><label for="profile">Gentoo Profile Name (optional):</label></td>
+ <td><input type="text" id="profile" name="profile" /></td>
+ </tr>
+ <tr>
+ <td><label for="distribution">Distribution (optional):</label></td>
+ <td><input type="text" id="distribution" name="distribution" maxlength="50" /></td>
+ </tr>
+ <tr>
+ <td><label for="administrator">Administrator (optional):</label></td>
+ <td><input type="text" id="administrator" name="administrator" maxlength="50" /></td>
+ </tr>
+ <tr>
+ <td><label for="status">Status:</label></td>
+ <td><input type="text" id="status" name="status" maxlength="100" /></td>
+ </tr>
+ </table>
+ </td>
+ <td width="25%">
+ <label for="groups">Groups:</label><br />
+ <select id="groups" name="groups" size="14" multiple="multiple">
+ <option>{html_options values=$ids output=$groupnames selected="1"}</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <input type="submit" name="submit" value="Add Client" />
+ </form> end add client -->
+ <!-- begin permission
+ <form id="form1" name="form1" method="post" action="">
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="permname">Name:</label></td>
+ <td><input type="text" id="permname" name="permname" /></td>
+ </tr>
+ <tr>
+ <td><label for="permdesc">Description:</label></td>
+ <td><input type="text" id="permdesc" name="permdesc" /></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table class="box" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Built-in Abilities/Scripts:</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="optiongroup" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><input type="checkbox" id="update_gentoo" name="scripts" value="update_gentoo" /></td>
+ <td><label for="update_gentoo">Gentoo update</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="update_debian" name="scripts" value="update_debian" /></td>
+ <td><label for="update_debian">Debian update</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="upgrade_debian" name="scripts" value="upgrade_debian" /></td>
+ <td><label for="upgrade_debian">Debian upgrade</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="emerge_gentoo" name="scripts" value="emerge_gentoo" /></td>
+ <td><label for="emerge_gentoo">Gentoo emerge</label></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <p><input type="submit" name="submit" value="Add Permission" /></p>
+ </form> end permission -->
+ <!-- begin overview
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Recent Jobs</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Job Name</th>
+ <th>Last Run</th>
+ </tr>
+ <tr>
+ <td>glsa-check</td>
+ <td>2 days, 1 hour, 57 minutes</td>
+ </tr>
+ <tr>
+ <td>start sshd</td>
+ <td>1 day, 14 hours, 29 minutes</td>
+ </tr>
+ <tr>
+ <td>backup</td>
+ <td>29 minutes</td>
+ </tr>
+ <tr>
+ <td>rotate logs</td>
+ <td>22 minutes</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Stale Clients</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Time Since Last Poll</th>
+ <th>Client</th>
+ </tr>
+ <tr>
+ <td>3 hours, 42 minutes</td>
+ <td>lark</td>
+ </tr>
+ <tr>
+ <td>3 hours, 48 minutes</td>
+ <td>cockatoo</td>
+ </tr>
+ <tr>
+ <td>4 hours, 1 minute</td>
+ <td>woodpecker</td>
+ </tr>
+ <tr>
+ <td>3 days, 14 hours, 2 minutes</td>
+ <td>toucan</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Logins</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>User</th>
+ <th>Time Since Login</th>
+ </tr>
+ <tr>
+ <td>blackace</td>
+ <td>15 minutes</td>
+ </tr>
+ <tr>
+ <td>admin</td>
+ <td>32 minutes</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top" colspan="3">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Security Announcements</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Type</th>
+ <th>Severity</th>
+ <th>Package</th>
+ <th>Summary</th>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>High</td>
+ <td>net-misc/rsync</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-05.xml">rsync: Potential integer overflow</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>Normal</td>
+ <td>www-apps/phpwebsite</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-04.xml">phpWebSite: Local file inclusion</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>Normal</td>
+ <td>app-antivirus/clamav</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-03.xml">ClamAV: Buffer overflow in Freshclam</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>High</td>
+ <td>x11-base/xorg-x11</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-02.xml">X.Org: Buffer overflow in XRender extension</a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table> end overview -->
+ <!-- begin jobs -->
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Filter</td>
+ </tr>
+ <tr>
+ <td>
+ <form id="form1" name="form1" method="post" action="">
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="field1">Field:</label></td>
+ <td>
+ <select id="field1" name="field1" size="1">
+ <option value="Client" selected="selected">Client</option>
+ <option value="Assignees">Assignees</option>
+ <option value="Priority">Priority</option>
+ <option value="Permission">Permission</option>
+ <option value="Status">Status</option>
+ <option value="Description">Description</option>
+ </select>
+ </td>
+ <td>
+ <select id="op1" name="op1" size="1">
+ <option value="==" selected="selected">Equals</option>
+ <option value="!=">Not Equals</option>
+ <option value="=~">Contains</option>
+ <option value="!~">Not Contains</option>
+ </select>
+ </td>
+ <td><input type="text" id="value1" name="value1" value="testhost" /></td>
+ <td>
+ And
+ <input type="submit" name="submit" value="Remove" />
+ </td>
+ </tr>
+ <tr>
+ <td><label for="field2">Field:</label></td>
+ <td>
+ <select id="field2" name="field2" size="1">
+ <option value="Client" selected="selected">Client</option>
+ <option value="Assignees">Assignees</option>
+ <option value="Priority">Priority</option>
+ <option value="Permission">Permission</option>
+ <option value="Status">Status</option>
+ <option value="Description">Description</option>
+ </select>
+ </td>
+ <td>
+ <select id="op2" name="op2" size="1">
+ <option value="==" selected="selected">Equals</option>
+ <option value="!=">Not Equals</option>
+ <option value="=~">Contains</option>
+ <option value="!~">Not Contains</option>
+ </select>
+ </td>
+ <td><input type="text" id="value2" name="value2" value="" /></td>
+ <td>
+ <input type="submit" name="submit" value="And" />
+ <input type="submit" name="submit" value="Or" />
+ <input type="submit" name="submit" value="New Group" />
+ </td>
+ </tr>
+ <tr>
+ <td colspan="5">
+ <input type="submit" name="submit" value="Update" />
+ <input type="submit" name="submit" value="Clear" />
+ </td>
+ </tr>
+ </table>
+ </form>
+ </td>
+ </tr>
+ </table>
+ <p></p>
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Jobs</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Client</th>
+ <th>Assignees</th>
+ <th>Priority</th>
+ <th>Permission</th>
+ <th>Status</th>
+ <th>Description</th>
+ <th>Actions</th>
+ </tr>
+ <tr>
+ <td>testhost</td>
+ <td>Cheetahmail Network, MTAs</td>
+ <td>5</td>
+ <td>Update packages</td>
+ <td>Scheduled</td>
+ <td>Regular update</td>
+ <td><form id="form1" name="form1" method="post" action=""><input type="hidden" name="id" value="1" /><input type="submit" name="submit" value="Edit" /><input type="submit" name="submit" value="Delete" /></form></td>
+ </tr>
+ <tr>
+ <td>testhost</td>
+ <td>Cheetahmail Network, MTAs</td>
+ <td>5</td>
+ <td>Install packages</td>
+ <td>In Progress</td>
+ <td>Adding cups</td>
+ <td><form id="form2" name="form2" method="post" action=""><input type="hidden" name="id" value="1" /><input type="submit" name="submit" value="Edit" /><input type="submit" name="submit" value="Delete" /></form></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table> <!-- end jobs -->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/scire/mockups/mockup_users.html b/scire/mockups/mockup_users.html
new file mode 100644
index 0000000..6945636
--- /dev/null
+++ b/scire/mockups/mockup_users.html
@@ -0,0 +1,507 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"/>
+ <title>Scire</title>
+ <link rel="icon" href="favicon.ico" type="image/x-icon" />
+ <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
+ <style type="text/css">
+ <!--
+ html {
+ margin: 0px;
+ }
+ body {
+ margin: 0px;
+ font-family: Bitstream Vera Sans, Helvetica, Sans;
+ font-size: 10pt;
+ }
+ form {
+ margin: 0px;
+ padding: 0px;
+ }
+ p {
+ margin: 5px;
+ }
+ h1 {
+ margin: 5px;
+ margin-bottom: 0px;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ h2 {
+ margin: 5px;
+ font-size: 1.1em;
+ font-weight: normal;
+ }
+ #topbar {
+ border-top: 1px solid #000000;
+ }
+ #topbar table tr td a {
+ text-decoration: none;
+ }
+ #topbar table tr td a:hover {
+ color: #ffffff;
+ text-decoration: underline;
+ }
+ #leftbar {
+ background-color: #ffffff;
+ border-top: 1px solid #000000;
+ }
+ #header {
+ border-top: 1px solid #000000;
+ }
+ #content {
+ padding: 7px 5px 5px;
+ }
+ #menu,#submenu {
+ width: 150px;
+ margin: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ border-right: 1px solid #ffffff;
+ list-style: none;
+ }
+ #menu li {
+ width: 150px;
+ border-bottom: 1px solid #ffffff;
+ }
+ #submenu li {
+ width: 140px;
+ margin-left: 10px;
+ border-bottom: 1px solid #ffffff;
+ }
+ a.menuitem {
+ display: block;
+ position: relative;
+ margin: 0px;
+ padding: 1px;
+ padding-left: 4px;
+ background-color: #a6afc2;
+ color: #000000;
+ text-decoration: none;
+ }
+ a.menuitem:hover {
+ color: #ffffff;
+ }
+ .box {
+ border: 1px solid #000000;
+ font-size: 0.8em;
+ }
+ .box td {
+ border: none;
+ }
+ td.boxtitle {
+ padding: 5px;
+ border-top: 1px solid #d1ddf5;
+ border-right: 1px solid #7a818f;
+ border-bottom: 1px solid #7a818f;
+ border-left: 1px solid #d1ddf5;
+ background-color: #a5acba;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ .table {
+ border: none;
+ border-spacing: 5px;
+ }
+ .table th {
+ padding: 2px 5px 0px;
+ border: none;
+ text-align: left;
+ }
+ .table td {
+ padding: 5px 5px 0px;
+ border: none;
+ border-top: 1px dotted #7a818f;
+ }
+ .optiongroup td {
+ padding-top: 5px;
+ border: none;
+ }
+ .optiongroup td:first-child {
+ padding-left: 5px;
+ }
+ .optiongroup td:last-child {
+ padding-right: 5px;
+ }
+ .optiongroup tr:last-child td {
+ padding-bottom: 5px;
+ }
+ -->
+ </style>
+ </head>
+ <body link="#000000" alink="#ffffff">
+ <table width="100%" bgcolor="#ffffff" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td colspan="2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="10">
+ <tr>
+ <td width="80">
+ <a href="#"><img src="scire-logo.png" alt="Scire" border="0" width="80" height="80" /></a>
+ </td>
+ <td align="right" valign="top">
+ <form action="#">
+ <label for="search">Search:</label>
+ <input id="search" name="search" type="text" size="16" />
+ <input id="submit" name="submit" type="button" value="go" />
+ </form>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="topbar" colspan="2" height="22" bgcolor="#494949">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><font color="#ffffff">&nbsp;<a href="mockup.html"><font color="#ffffff">Overview</font></a> | <a href="#"><font color="#ffffff">Jobs</font></a> | <a href="#"><font color="#ffffff">Clients</font></a> | <a href="#"><font color="#ffffff">Users</font></a></font></td>
+ <td align="right"><font color="#ffffff"><a href="#"><font color="#ffffff">Logout</font></a> | <a href="#"><font color="#ffffff">Settings</font></a> | <a href="#"><font color="#ffffff">Help</font></a>&nbsp;</font></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="leftbar" valign="top" bgcolor="#a6afc2">
+ <ul id="menu">
+ <li><a class="menuitem" href="#">Groups</a></li>
+ <li><a class="menuitem" href="#">Permissions</a></li>
+ </ul>
+ <p></p>
+ <ul id="submenu">
+ <li>Actions</li>
+ <li><a class="menuitem" href="#">Create User</a></li>
+ </ul>
+ </td>
+ <td width="100%" valign="top">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td id="header" bgcolor="#d8d4e2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <h1>Users</h1>
+ <h2>View, create, edit, and delete users</h2>
+ </td>
+ <td align="right" valign="top">
+<!-- <p>OK</p>-->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="content" height="100%" valign="top" bgcolor="#ffffff">
+ <!-- begin admin
+ <ul>
+ <li><a href="admin/create_user.php">Create a User</a></li>
+ <li><a href="admin/edit_user.php">Edit a User</a></li>
+ <li><a href="admin/delete_user.php">Delete a User</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/create_usergroup.php">Create a UserGroup</a></li>
+ <li><a href="admin/edit_usergroup.php">Edit a UserGroup</a></li>
+ <li><a href="admin/delete_usergroup.php">Delete a UserGroup</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/add_permission.php">Add Permission</a></li>
+ <li><a href="admin/edit_permission.php">Edit Permission</a></li>
+ <li><a href="admin/delete_permission.php">Delete Permission</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/add_client.php">Add Client Manually</a></li>
+ <li><a href="admin/edit_client.php">Edit Clients</a></li>
+ <li><a href="admin/delete_client.php">Delete Client from Scire</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/create_clientgroup.php">Create a ClientGroup</a></li>
+ <li><a href="admin/edit_clientgroup.php">Edit a ClientGroup</a></li>
+ <li><a href="admin/delte_clientgroup.php">Delete a ClientGroup</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/assign_permissions.php">Assign Permissions</a></li>
+ </ul> end admin -->
+ <!-- begin add client
+ <form id="form1" name="form1" method="post" action="">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="hostname">Hostname:</label></td>
+ <td><input type="text" id="hostname" name="hostname" /></td>
+ </tr>
+ <tr>
+ <td><label for="mac">MAC:</label></td>
+ <td><input type="text" id="mac" name="mac" maxlength="17" /></td>
+ </tr>
+ <tr>
+ <td><label for="ip">IP:</label></td>
+ <td><input type="text" id="ip" name="ip" maxlength="15" /></td>
+ </tr>
+ <tr>
+ <td><label for="profile">Gentoo Profile Name (optional):</label></td>
+ <td><input type="text" id="profile" name="profile" /></td>
+ </tr>
+ <tr>
+ <td><label for="distribution">Distribution (optional):</label></td>
+ <td><input type="text" id="distribution" name="distribution" maxlength="50" /></td>
+ </tr>
+ <tr>
+ <td><label for="administrator">Administrator (optional):</label></td>
+ <td><input type="text" id="administrator" name="administrator" maxlength="50" /></td>
+ </tr>
+ <tr>
+ <td><label for="status">Status:</label></td>
+ <td><input type="text" id="status" name="status" maxlength="100" /></td>
+ </tr>
+ </table>
+ </td>
+ <td width="25%">
+ <label for="groups">Groups:</label><br />
+ <select id="groups" name="groups" size="14" multiple="multiple">
+ <option>{html_options values=$ids output=$groupnames selected="1"}</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <input type="submit" name="submit" value="Add Client" />
+ </form> end add client -->
+ <!-- begin permission
+ <form id="form1" name="form1" method="post" action="">
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="permname">Name:</label></td>
+ <td><input type="text" id="permname" name="permname" /></td>
+ </tr>
+ <tr>
+ <td><label for="permdesc">Description:</label></td>
+ <td><input type="text" id="permdesc" name="permdesc" /></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table class="box" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Built-in Abilities/Scripts:</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="optiongroup" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><input type="checkbox" id="update_gentoo" name="scripts" value="update_gentoo" /></td>
+ <td><label for="update_gentoo">Gentoo update</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="update_debian" name="scripts" value="update_debian" /></td>
+ <td><label for="update_debian">Debian update</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="upgrade_debian" name="scripts" value="upgrade_debian" /></td>
+ <td><label for="upgrade_debian">Debian upgrade</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="emerge_gentoo" name="scripts" value="emerge_gentoo" /></td>
+ <td><label for="emerge_gentoo">Gentoo emerge</label></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <p><input type="submit" name="submit" value="Add Permission" /></p>
+ </form> end permission -->
+ <!-- begin overview
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Recent Jobs</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Job Name</th>
+ <th>Last Run</th>
+ </tr>
+ <tr>
+ <td>glsa-check</td>
+ <td>2 days, 1 hour, 57 minutes</td>
+ </tr>
+ <tr>
+ <td>start sshd</td>
+ <td>1 day, 14 hours, 29 minutes</td>
+ </tr>
+ <tr>
+ <td>backup</td>
+ <td>29 minutes</td>
+ </tr>
+ <tr>
+ <td>rotate logs</td>
+ <td>22 minutes</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Stale Clients</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Time Since Last Poll</th>
+ <th>Client</th>
+ </tr>
+ <tr>
+ <td>3 hours, 42 minutes</td>
+ <td>lark</td>
+ </tr>
+ <tr>
+ <td>3 hours, 48 minutes</td>
+ <td>cockatoo</td>
+ </tr>
+ <tr>
+ <td>4 hours, 1 minute</td>
+ <td>woodpecker</td>
+ </tr>
+ <tr>
+ <td>3 days, 14 hours, 2 minutes</td>
+ <td>toucan</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Logins</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>User</th>
+ <th>Time Since Login</th>
+ </tr>
+ <tr>
+ <td>blackace</td>
+ <td>15 minutes</td>
+ </tr>
+ <tr>
+ <td>admin</td>
+ <td>32 minutes</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top" colspan="3">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Security Announcements</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Type</th>
+ <th>Severity</th>
+ <th>Package</th>
+ <th>Summary</th>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>High</td>
+ <td>net-misc/rsync</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-05.xml">rsync: Potential integer overflow</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>Normal</td>
+ <td>www-apps/phpwebsite</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-04.xml">phpWebSite: Local file inclusion</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>Normal</td>
+ <td>app-antivirus/clamav</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-03.xml">ClamAV: Buffer overflow in Freshclam</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>High</td>
+ <td>x11-base/xorg-x11</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-02.xml">X.Org: Buffer overflow in XRender extension</a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table> end overview -->
+ <!-- begin users -->
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Users</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Username</th>
+ <th>Realname</th>
+ <th>Comment</th>
+ <th>Groups</th>
+ <th>Status</th>
+ <th>Actions</th>
+ </tr>
+ <tr>
+ <td>agaffney</td>
+ <td>Andrew Gaffney</td>
+ <td>Mr. Python</td>
+ <td>Users, Admins</td>
+ <td>Active</td>
+ <td><form id="form1" name="form1" method="post" action=""><input type="hidden" name="id" value="1" /><input type="submit" name="submit" value="Edit" /><input type="submit" name="submit" value="Delete" /></form></td>
+ </tr>
+ <tr>
+ <td>blackace</td>
+ <td>Nicholas D. Wolfwood</td>
+ <td>Mr. Ripurcodeanuone</td>
+ <td>Users, Admins</td>
+ <td>Active</td>
+ <td><form id="form2" name="form2" method="post" action=""><input type="hidden" name="id" value="2" /><input type="submit" name="submit" value="Edit" /><input type="submit" name="submit" value="Delete" /></form></td>
+ </tr>
+ <tr>
+ <td>codeman</td>
+ <td>Preston Cody</td>
+ <td>Mr. Enterprise</td>
+ <td>Users, Admins</td>
+ <td>Active</td>
+ <td><form id="form3" name="form3" method="post" action=""><input type="hidden" name="id" value="3" /><input type="submit" name="submit" value="Edit" /><input type="submit" name="submit" value="Delete" /></form></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table> <!-- end users -->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/scire/mockups/mockup_users_edit.html b/scire/mockups/mockup_users_edit.html
new file mode 100644
index 0000000..6e7fb46
--- /dev/null
+++ b/scire/mockups/mockup_users_edit.html
@@ -0,0 +1,560 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"/>
+ <title>Scire</title>
+ <link rel="icon" href="favicon.ico" type="image/x-icon" />
+ <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
+ <style type="text/css">
+ <!--
+ html {
+ margin: 0px;
+ }
+ body {
+ margin: 0px;
+ font-family: Bitstream Vera Sans, Helvetica, Sans;
+ font-size: 10pt;
+ }
+ form {
+ margin: 0px;
+ padding: 0px;
+ }
+ p {
+ margin: 5px;
+ }
+ h1 {
+ margin: 5px;
+ margin-bottom: 0px;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ h2 {
+ margin: 5px;
+ font-size: 1.1em;
+ font-weight: normal;
+ }
+ #topbar {
+ border-top: 1px solid #000000;
+ }
+ #topbar table tr td a {
+ text-decoration: none;
+ }
+ #topbar table tr td a:hover {
+ color: #ffffff;
+ text-decoration: underline;
+ }
+ #leftbar {
+ background-color: #ffffff;
+ border-top: 1px solid #000000;
+ }
+ #header {
+ border-top: 1px solid #000000;
+ }
+ #content {
+ padding: 7px 5px 5px;
+ }
+ #menu,#submenu {
+ width: 150px;
+ margin: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ border-right: 1px solid #ffffff;
+ list-style: none;
+ }
+ #menu li {
+ width: 150px;
+ border-bottom: 1px solid #ffffff;
+ }
+ #submenu li {
+ width: 140px;
+ margin-left: 10px;
+ border-bottom: 1px solid #ffffff;
+ }
+ a.menuitem {
+ display: block;
+ position: relative;
+ margin: 0px;
+ padding: 1px;
+ padding-left: 4px;
+ background-color: #a6afc2;
+ color: #000000;
+ text-decoration: none;
+ }
+ a.menuitem:hover {
+ color: #ffffff;
+ }
+ .box {
+ border: 1px solid #000000;
+ font-size: 0.8em;
+ }
+ .box td {
+ border: none;
+ }
+ td.boxtitle {
+ padding: 5px;
+ border-top: 1px solid #d1ddf5;
+ border-right: 1px solid #7a818f;
+ border-bottom: 1px solid #7a818f;
+ border-left: 1px solid #d1ddf5;
+ background-color: #a5acba;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ .table {
+ border: none;
+ border-spacing: 5px;
+ }
+ .table th {
+ padding: 2px 5px 0px;
+ border: none;
+ text-align: left;
+ }
+ .table td {
+ padding: 5px 5px 0px;
+ border: none;
+ border-top: 1px dotted #7a818f;
+ }
+ .optiongroup td {
+ padding-top: 5px;
+ border: none;
+ }
+ .optiongroup td:first-child {
+ padding-left: 5px;
+ }
+ .optiongroup td:last-child {
+ padding-right: 5px;
+ }
+ .optiongroup tr:last-child td {
+ padding-bottom: 5px;
+ }
+ -->
+ </style>
+ </head>
+ <body link="#000000" alink="#ffffff">
+ <table width="100%" bgcolor="#ffffff" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td colspan="2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="10">
+ <tr>
+ <td width="80">
+ <a href="#"><img src="scire-logo.png" alt="Scire" border="0" width="80" height="80" /></a>
+ </td>
+ <td align="right" valign="top">
+ <form action="#">
+ <label for="search">Search:</label>
+ <input id="search" name="search" type="text" size="16" />
+ <input id="submit" name="submit" type="button" value="go" />
+ </form>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="topbar" colspan="2" height="22" bgcolor="#494949">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><font color="#ffffff">&nbsp;<a href="mockup.html"><font color="#ffffff">Overview</font></a> | <a href="#"><font color="#ffffff">Jobs</font></a> | <a href="#"><font color="#ffffff">Clients</font></a> | <a href="#"><font color="#ffffff">Users</font></a></font></td>
+ <td align="right"><font color="#ffffff"><a href="#"><font color="#ffffff">Logout</font></a> | <a href="#"><font color="#ffffff">Settings</font></a> | <a href="#"><font color="#ffffff">Help</font></a>&nbsp;</font></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="leftbar" valign="top" bgcolor="#a6afc2">
+ <ul id="menu">
+ <li><a class="menuitem" href="#">Groups</a></li>
+ <li><a class="menuitem" href="#">Permissions</a></li>
+ </ul>
+ <p></p>
+ <ul id="submenu">
+ <li><a class="menuitem" href="#">&#171;&nbsp;Return</a></li>
+ </ul>
+ </td>
+ <td width="100%" valign="top">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td id="header" bgcolor="#d8d4e2">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <h1>Users</h1>
+ <h2>Edit user</h2>
+ </td>
+ <td align="right" valign="top">
+<!-- <p>OK</p>-->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td id="content" height="100%" valign="top" bgcolor="#ffffff">
+ <!-- begin admin
+ <ul>
+ <li><a href="admin/create_user.php">Create a User</a></li>
+ <li><a href="admin/edit_user.php">Edit a User</a></li>
+ <li><a href="admin/delete_user.php">Delete a User</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/create_usergroup.php">Create a UserGroup</a></li>
+ <li><a href="admin/edit_usergroup.php">Edit a UserGroup</a></li>
+ <li><a href="admin/delete_usergroup.php">Delete a UserGroup</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/add_permission.php">Add Permission</a></li>
+ <li><a href="admin/edit_permission.php">Edit Permission</a></li>
+ <li><a href="admin/delete_permission.php">Delete Permission</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/add_client.php">Add Client Manually</a></li>
+ <li><a href="admin/edit_client.php">Edit Clients</a></li>
+ <li><a href="admin/delete_client.php">Delete Client from Scire</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/create_clientgroup.php">Create a ClientGroup</a></li>
+ <li><a href="admin/edit_clientgroup.php">Edit a ClientGroup</a></li>
+ <li><a href="admin/delte_clientgroup.php">Delete a ClientGroup</a></li>
+ </ul>
+ <ul>
+ <li><a href="admin/assign_permissions.php">Assign Permissions</a></li>
+ </ul> end admin -->
+ <!-- begin add client
+ <form id="form1" name="form1" method="post" action="">
+ <table width="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="hostname">Hostname:</label></td>
+ <td><input type="text" id="hostname" name="hostname" /></td>
+ </tr>
+ <tr>
+ <td><label for="mac">MAC:</label></td>
+ <td><input type="text" id="mac" name="mac" maxlength="17" /></td>
+ </tr>
+ <tr>
+ <td><label for="ip">IP:</label></td>
+ <td><input type="text" id="ip" name="ip" maxlength="15" /></td>
+ </tr>
+ <tr>
+ <td><label for="profile">Gentoo Profile Name (optional):</label></td>
+ <td><input type="text" id="profile" name="profile" /></td>
+ </tr>
+ <tr>
+ <td><label for="distribution">Distribution (optional):</label></td>
+ <td><input type="text" id="distribution" name="distribution" maxlength="50" /></td>
+ </tr>
+ <tr>
+ <td><label for="administrator">Administrator (optional):</label></td>
+ <td><input type="text" id="administrator" name="administrator" maxlength="50" /></td>
+ </tr>
+ <tr>
+ <td><label for="status">Status:</label></td>
+ <td><input type="text" id="status" name="status" maxlength="100" /></td>
+ </tr>
+ </table>
+ </td>
+ <td width="25%">
+ <label for="groups">Groups:</label><br />
+ <select id="groups" name="groups" size="14" multiple="multiple">
+ <option>{html_options values=$ids output=$groupnames selected="1"}</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <input type="submit" name="submit" value="Add Client" />
+ </form> end add client -->
+ <!-- begin permission
+ <form id="form1" name="form1" method="post" action="">
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="permname">Name:</label></td>
+ <td><input type="text" id="permname" name="permname" /></td>
+ </tr>
+ <tr>
+ <td><label for="permdesc">Description:</label></td>
+ <td><input type="text" id="permdesc" name="permdesc" /></td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <table class="box" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Built-in Abilities/Scripts:</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="optiongroup" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td><input type="checkbox" id="update_gentoo" name="scripts" value="update_gentoo" /></td>
+ <td><label for="update_gentoo">Gentoo update</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="update_debian" name="scripts" value="update_debian" /></td>
+ <td><label for="update_debian">Debian update</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="upgrade_debian" name="scripts" value="upgrade_debian" /></td>
+ <td><label for="upgrade_debian">Debian upgrade</label></td>
+ </tr>
+ <tr>
+ <td><input type="checkbox" id="emerge_gentoo" name="scripts" value="emerge_gentoo" /></td>
+ <td><label for="emerge_gentoo">Gentoo emerge</label></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <p><input type="submit" name="submit" value="Add Permission" /></p>
+ </form> end permission -->
+ <!-- begin overview
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Recent Jobs</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Job Name</th>
+ <th>Last Run</th>
+ </tr>
+ <tr>
+ <td>glsa-check</td>
+ <td>2 days, 1 hour, 57 minutes</td>
+ </tr>
+ <tr>
+ <td>start sshd</td>
+ <td>1 day, 14 hours, 29 minutes</td>
+ </tr>
+ <tr>
+ <td>backup</td>
+ <td>29 minutes</td>
+ </tr>
+ <tr>
+ <td>rotate logs</td>
+ <td>22 minutes</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Stale Clients</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Time Since Last Poll</th>
+ <th>Client</th>
+ </tr>
+ <tr>
+ <td>3 hours, 42 minutes</td>
+ <td>lark</td>
+ </tr>
+ <tr>
+ <td>3 hours, 48 minutes</td>
+ <td>cockatoo</td>
+ </tr>
+ <tr>
+ <td>4 hours, 1 minute</td>
+ <td>woodpecker</td>
+ </tr>
+ <tr>
+ <td>3 days, 14 hours, 2 minutes</td>
+ <td>toucan</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Logins</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>User</th>
+ <th>Time Since Login</th>
+ </tr>
+ <tr>
+ <td>blackace</td>
+ <td>15 minutes</td>
+ </tr>
+ <tr>
+ <td>admin</td>
+ <td>32 minutes</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top" colspan="3">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Security Announcements</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Type</th>
+ <th>Severity</th>
+ <th>Package</th>
+ <th>Summary</th>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>High</td>
+ <td>net-misc/rsync</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-05.xml">rsync: Potential integer overflow</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>Normal</td>
+ <td>www-apps/phpwebsite</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-04.xml">phpWebSite: Local file inclusion</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>Normal</td>
+ <td>app-antivirus/clamav</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-03.xml">ClamAV: Buffer overflow in Freshclam</a></td>
+ </tr>
+ <tr>
+ <td>GLSA</td>
+ <td>High</td>
+ <td>x11-base/xorg-x11</td>
+ <td><a href="http://security.gentoo.org/glsa/glsa-200605-02.xml">X.Org: Buffer overflow in XRender extension</a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table> end overview -->
+ <!-- begin users -->
+ <table width="100%" border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td colspan="2" align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">User</td>
+ </tr>
+ <tr>
+ <td>
+ <table border="0" cellspacing="0" cellpadding="5">
+ <tr>
+ <td><label for="username">Username:</label></td>
+ <td><input type="text" id="username" name="username" value="agaffney" /></td>
+ <td><label for="passwd">Password:</label></td>
+ <td><input type="password" id="passwd" name="passwd" /></td>
+ </tr>
+ <tr>
+ <td><label for="realname">Realname:</label></td>
+ <td><input type="text" id="realname" name="realname" value="Andrew Gaffney" /></td>
+ <td><label for="passwd2">Confirm Password:</label></td>
+ <td><input type="password" id="passwd2" name="passwd2" /></td>
+ </tr>
+ <tr>
+ <td><label for="comment">Comment:</label></td>
+ <td><input type="text" id="comment" name="comment" value="Mr. Ewhaaaaa" /></td>
+ <td><label for="status">Status:</label></td>
+ <td>
+ <select id="status" name="status" size="1">
+ <option value="active" selected="selected">Active</option>
+ <option value="disabled">Disabled</option>
+ </select>
+ </td>
+ </tr>
+ </table>
+ <p><input type="submit" name="submit" value="Update" /></p>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Groups</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Groupname</th>
+ <th>Actions</th>
+ </tr>
+ <tr>
+ <td>Admins</td>
+ <td><form id="form1" name="form1" method="post" action=""><input type="hidden" name="id" value="1" /><input type="submit" name="submit" value="Remove" /></form></td>
+ </tr>
+ <tr>
+ <td>Users</td>
+ <td><form id="form2" name="form2" method="post" action=""><input type="hidden" name="id" value="2" /><input type="submit" name="submit" value="Remove" /></form></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td align="center" valign="top">
+ <table class="box" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <td class="boxtitle">Permissions</td>
+ </tr>
+ <tr>
+ <td>
+ <table class="table" width="100%" border="1" cellspacing="0" cellpadding="0">
+ <tr>
+ <th>Permission</th>
+ <th>On</th>
+ <th>Actions</th>
+ </tr>
+ <tr>
+ <td>Install packages</td>
+ <td>@frontend, workstation12</td>
+ <td><form id="form1" name="form1" method="post" action=""><input type="hidden" name="id" value="1" /><input type="submit" name="submit" value="Remove" /></form></td>
+ </tr>
+ <tr>
+ <td>Update packages</td>
+ <td>@db, @frontend, workstation12</td>
+ <td><form id="form2" name="form2" method="post" action=""><input type="hidden" name="id" value="2" /><input type="submit" name="submit" value="Remove" /></form></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ <!-- end users -->
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/scire/modules.php b/scire/modules.php
new file mode 100644
index 0000000..2f83c16
--- /dev/null
+++ b/scire/modules.php
@@ -0,0 +1,25 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+$leftbar_submenu = array();
+$template = "modules.tpl";
+$status = "";
+$smarty->assign('desc', "Modules available to Scire.");
+
+$modules = get_scire_modules();
+
+foreach ($modules as $module) {
+ add_leftbar($leftbar_menu, $module['name'], $module['path']);
+}
+
+
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('leftbar_submenu', $leftbar_submenu);
+$smarty->assign('View', $_GET['View']);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display($template);
+#var_dump($_POST);
+?>
diff --git a/scire/phpgacl/Cache_Lite/Hashed_Cache_Lite.php b/scire/phpgacl/Cache_Lite/Hashed_Cache_Lite.php
new file mode 100644
index 0000000..894952f
--- /dev/null
+++ b/scire/phpgacl/Cache_Lite/Hashed_Cache_Lite.php
@@ -0,0 +1,184 @@
+<?php
+/*
+ * phpGACL - Generic Access Control List - Hashed Directory Caching.
+ * Copyright (C) 2002 Mike Benoit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For questions, help, comments, discussion, etc., please join the
+ * phpGACL mailing list. http://sourceforge.net/mail/?group_id=57103
+ *
+ * You may contact the author of phpGACL by e-mail at:
+ * ipso@snappymail.ca
+ *
+ * The latest version of phpGACL can be obtained from:
+ * http://phpgacl.sourceforge.net/
+ *
+ */
+
+if ( !class_exists('Cache_Lite') ) {
+ require_once(dirname(__FILE__) .'/Lite.php');
+}
+
+define('DIR_SEP',DIRECTORY_SEPARATOR);
+
+class Hashed_Cache_Lite extends Cache_Lite
+{
+ /**
+ * Make a file name (with path)
+ *
+ * @param string $id cache id
+ * @param string $group name of the group
+ * @access private
+ */
+ function _setFileName($id, $group)
+ {
+ // CRC32 with SUBSTR is still faster then MD5.
+ $encoded_id = substr(crc32($id),1);
+ // $encoded_id = md5($id);
+
+ // Generate just the directory, so it can be created.
+ // Groups will have their own top level directory, for quick/easy purging of an entire group.
+ $dir = $this->_cacheDir.$group.'/'.substr($encoded_id,0,3);
+ $this->_create_dir_structure($dir);
+
+ $this->_file = $dir.'/'.$encoded_id;
+ }
+
+ /**
+ * Create full directory structure, Ripped straight from the Smarty Template engine.
+ * Version: 2.3.0
+ * Copyright: 2001,2002 ispi of Lincoln, Inc.
+ *
+ * @param string $dir Full directory.
+ * @access private
+ */
+ function _create_dir_structure($dir)
+ {
+ if (!@file_exists($dir)) {
+ $dir_parts = preg_split('![\/]+!', $dir, -1, PREG_SPLIT_NO_EMPTY);
+ $new_dir = ($dir{0} == DIR_SEP) ? DIR_SEP : '';
+ foreach ($dir_parts as $dir_part) {
+ $new_dir .= $dir_part;
+ if (!file_exists($new_dir) && !mkdir($new_dir, 0771)) {
+ Cache_Lite::raiseError('Cache_Lite : problem creating directory \"$dir\" !', -3);
+ return false;
+ }
+ $new_dir .= DIR_SEP;
+ }
+ }
+ }
+
+ function _remove_dir_structure($dir,$remove_dir = false)
+ {
+ if (in_array(substr($dir,-1),array(DIR_SEP,'/','\\'))) {
+ $dir = substr($dir,0,-1);
+ }
+
+ if (!($dh = opendir($dir))) {
+ $this->raiseError('Cache_Lite : Unable to open cache directory !', -4);
+ return false;
+ }
+
+ while ($file = readdir($dh)) {
+ if ($file == '.' || $file == '..') {
+ continue;
+ }
+ $file = $dir . DIR_SEP . $file;
+ if (is_dir($file)) {
+ $this->_remove_dir_structure($file,true);
+ continue;
+ }
+ if (is_file($file)) {
+ if (!@unlink($file)) {
+ closedir($dh);
+ $this->raiseError('Cache_Lite : Unable to remove cache !', -3);
+ return false;
+ }
+ continue;
+ }
+ }
+
+ closedir($dh);
+
+ if ($remove_dir) {
+ clearstatcache();
+ if (!@rmdir($dir)) {
+ $this->raiseError('Cache_Lite : Unable to remove cache directory !', -4);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Clean the cache
+ *
+ * if no group is specified all cache files will be destroyed
+ * else only cache files of the specified group will be destroyed
+ *
+ * @param string $group name of the cache group
+ * @return boolean true if no problem
+ * @access public
+ */
+ function clean($group = false)
+ {
+ if ($group) {
+ $motif = $this->_cacheDir.$group.'/';
+
+ if ($this->_memoryCaching) {
+ foreach ($this->_memoryCachingArray as $key => $value) {
+ if (strpos($key, $motif, 0)) {
+ unset($this->_memoryCachingArray[$key]);
+ }
+ }
+ $this->_memoryCachingCounter = count($this->_memoryCachingArray);
+ if ($this->_onlyMemoryCaching) {
+ return true;
+ }
+ }
+
+ return $this->_remove_dir_structure($motif);
+ }
+
+ if ($this->_memoryCaching) {
+ $this->_memoryCachingArray = array();
+ $this->_memoryCachingCounter = 0;
+ if ($this->_onlyMemoryCaching) {
+ return true;
+ }
+ }
+
+ if (!($dh = opendir($this->_cacheDir))) {
+ $this->raiseError('Cache_Lite : Unable to open cache directory !', -4);
+ return false;
+ }
+
+ while ($file = readdir($dh)) {
+ if ($file == '.' || $file == '..') {
+ continue;
+ }
+ $file = $this->_cacheDir . $file;
+ if (is_dir($file) && !$this->_remove_dir_structure($file,true)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
+
+// end of script
diff --git a/scire/phpgacl/Cache_Lite/LICENSE b/scire/phpgacl/Cache_Lite/LICENSE
new file mode 100644
index 0000000..27950e8
--- /dev/null
+++ b/scire/phpgacl/Cache_Lite/LICENSE
@@ -0,0 +1,458 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/scire/phpgacl/Cache_Lite/Lite.php b/scire/phpgacl/Cache_Lite/Lite.php
new file mode 100644
index 0000000..3341fb1
--- /dev/null
+++ b/scire/phpgacl/Cache_Lite/Lite.php
@@ -0,0 +1,615 @@
+<?php
+
+/**
+* Fast, light and safe Cache Class
+*
+* Cache_Lite is a fast, light and safe cache system. It's optimized
+* for file containers. It is fast and safe (because it uses file
+* locking and/or anti-corruption tests).
+*
+* There are some examples in the 'docs/examples' file
+* Technical choices are described in the 'docs/technical' file
+*
+* A tutorial is available in english at this url :
+* http://www.pearfr.org/index.php/en/article/cache_lite
+* (big thanks to Pierre-Alain Joye for the translation)
+*
+* The same tutorial is also available in french at this url :
+* http://www.pearfr.org/index.php/fr/article/cache_lite
+*
+* Memory Caching is from an original idea of
+* Mike BENOIT <ipso@snappymail.ca>
+*
+* @package Cache_Lite
+* @category Caching
+* @version $Id: Lite.php,v 1.1 2004/11/08 00:47:05 ipso Exp $
+* @author Fabien MARTY <fab@php.net>
+*/
+
+define('CACHE_LITE_ERROR_RETURN', 1);
+define('CACHE_LITE_ERROR_DIE', 8);
+
+class Cache_Lite
+{
+
+ // --- Private properties ---
+
+ /**
+ * Directory where to put the cache files
+ * (make sure to add a trailing slash)
+ *
+ * @var string $_cacheDir
+ */
+ var $_cacheDir = '/tmp/';
+
+ /**
+ * Enable / disable caching
+ *
+ * (can be very usefull for the debug of cached scripts)
+ *
+ * @var boolean $_caching
+ */
+ var $_caching = true;
+
+ /**
+ * Cache lifetime (in seconds)
+ *
+ * @var int $_lifeTime
+ */
+ var $_lifeTime = 3600;
+
+ /**
+ * Enable / disable fileLocking
+ *
+ * (can avoid cache corruption under bad circumstances)
+ *
+ * @var boolean $_fileLocking
+ */
+ var $_fileLocking = true;
+
+ /**
+ * Timestamp of the last valid cache
+ *
+ * @var int $_refreshTime
+ */
+ var $_refreshTime;
+
+ /**
+ * File name (with path)
+ *
+ * @var string $_file
+ */
+ var $_file;
+
+ /**
+ * Enable / disable write control (the cache is read just after writing to detect corrupt entries)
+ *
+ * Enable write control will lightly slow the cache writing but not the cache reading
+ * Write control can detect some corrupt cache files but maybe it's not a perfect control
+ *
+ * @var boolean $_writeControl
+ */
+ var $_writeControl = true;
+
+ /**
+ * Enable / disable read control
+ *
+ * If enabled, a control key is embeded in cache file and this key is compared with the one
+ * calculated after the reading.
+ *
+ * @var boolean $_writeControl
+ */
+ var $_readControl = true;
+
+ /**
+ * Type of read control (only if read control is enabled)
+ *
+ * Available values are :
+ * 'md5' for a md5 hash control (best but slowest)
+ * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
+ * 'strlen' for a length only test (fastest)
+ *
+ * @var boolean $_readControlType
+ */
+ var $_readControlType = 'crc32';
+
+ /**
+ * Pear error mode (when raiseError is called)
+ *
+ * (see PEAR doc)
+ *
+ * @see setToDebug()
+ * @var int $_pearErrorMode
+ */
+ var $_pearErrorMode = CACHE_LITE_ERROR_RETURN;
+
+ /**
+ * Current cache id
+ *
+ * @var string $_id
+ */
+ var $_id;
+
+ /**
+ * Current cache group
+ *
+ * @var string $_group
+ */
+ var $_group;
+
+ /**
+ * Enable / Disable "Memory Caching"
+ *
+ * NB : There is no lifetime for memory caching !
+ *
+ * @var boolean $_memoryCaching
+ */
+ var $_memoryCaching = false;
+
+ /**
+ * Enable / Disable "Only Memory Caching"
+ * (be carefull, memory caching is "beta quality")
+ *
+ * @var boolean $_onlyMemoryCaching
+ */
+ var $_onlyMemoryCaching = false;
+
+ /**
+ * Memory caching array
+ *
+ * @var array $_memoryCachingArray
+ */
+ var $_memoryCachingArray = array();
+
+ /**
+ * Memory caching counter
+ *
+ * @var int $memoryCachingCounter
+ */
+ var $_memoryCachingCounter = 0;
+
+ /**
+ * Memory caching limit
+ *
+ * @var int $memoryCachingLimit
+ */
+ var $_memoryCachingLimit = 1000;
+
+ /**
+ * File Name protection
+ *
+ * if set to true, you can use any cache id or group name
+ * if set to false, it can be faster but cache ids and group names
+ * will be used directly in cache file names so be carefull with
+ * special characters...
+ *
+ * @var boolean $fileNameProtection
+ */
+ var $_fileNameProtection = true;
+
+ /**
+ * Enable / disable automatic serialization
+ *
+ * it can be used to save directly datas which aren't strings
+ * (but it's slower)
+ *
+ * @var boolean $_serialize
+ */
+ var $_automaticSerialization = false;
+
+ // --- Public methods ---
+
+ /**
+ * Constructor
+ *
+ * $options is an assoc. Available options are :
+ * $options = array(
+ * 'cacheDir' => directory where to put the cache files (string),
+ * 'caching' => enable / disable caching (boolean),
+ * 'lifeTime' => cache lifetime in seconds (int),
+ * 'fileLocking' => enable / disable fileLocking (boolean),
+ * 'writeControl' => enable / disable write control (boolean),
+ * 'readControl' => enable / disable read control (boolean),
+ * 'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string),
+ * 'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int),
+ * 'memoryCaching' => enable / disable memory caching (boolean),
+ * 'onlyMemoryCaching' => enable / disable only memory caching (boolean),
+ * 'memoryCachingLimit' => max nbr of records to store into memory caching (int),
+ * 'fileNameProtection' => enable / disable automatic file name protection (boolean),
+ * 'automaticSerialization' => enable / disable automatic serialization (boolean)
+ * );
+ *
+ * @param array $options options
+ * @access public
+ */
+ function Cache_Lite($options = array(NULL))
+ {
+ $availableOptions = array('automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode');
+ foreach($options as $key => $value) {
+ if(in_array($key, $availableOptions)) {
+ $property = '_'.$key;
+ $this->$property = $value;
+ }
+ }
+ $this->_refreshTime = time() - $this->_lifeTime;
+ }
+
+ /**
+ * Test if a cache is available and (if yes) return it
+ *
+ * @param string $id cache id
+ * @param string $group name of the cache group
+ * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
+ * @return string data of the cache (or false if no cache available)
+ * @access public
+ */
+ function get($id, $group = 'default', $doNotTestCacheValidity = false)
+ {
+ $this->_id = $id;
+ $this->_group = $group;
+ $data = false;
+ if ($this->_caching) {
+ $this->_setFileName($id, $group);
+ if ($this->_memoryCaching) {
+ if (isset($this->_memoryCachingArray[$this->_file])) {
+ if ($this->_automaticSerialization) {
+ return unserialize($this->_memoryCachingArray[$this->_file]);
+ } else {
+ return $this->_memoryCachingArray[$this->_file];
+ }
+ } else {
+ if ($this->_onlyMemoryCaching) {
+ return false;
+ }
+ }
+ }
+ if ($doNotTestCacheValidity) {
+ if (file_exists($this->_file)) {
+ $data = $this->_read();
+ }
+ } else {
+ if ((file_exists($this->_file)) && (@filemtime($this->_file) > $this->_refreshTime)) {
+ $data = $this->_read();
+ }
+ }
+ if (($data) and ($this->_memoryCaching)) {
+ $this->_memoryCacheAdd($this->_file, $data);
+ }
+ if (($this->_automaticSerialization) and (is_string($data))) {
+ $data = unserialize($data);
+ }
+ return $data;
+ }
+ return false;
+ }
+
+ /**
+ * Save some data in a cache file
+ *
+ * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on)
+ * @param string $id cache id
+ * @param string $group name of the cache group
+ * @return boolean true if no problem
+ * @access public
+ */
+ function save($data, $id = NULL, $group = 'default')
+ {
+ if ($this->_caching) {
+ if ($this->_automaticSerialization) {
+ $data = serialize($data);
+ }
+ if (isset($id)) {
+ $this->_setFileName($id, $group);
+ }
+ if ($this->_memoryCaching) {
+ $this->_memoryCacheAdd($this->_file, $data);
+ if ($this->_onlyMemoryCaching) {
+ return true;
+ }
+ }
+ if ($this->_writeControl) {
+ if (!$this->_writeAndControl($data)) {
+ @touch($this->_file, time() - 2*abs($this->_lifeTime));
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return $this->_write($data);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove a cache file
+ *
+ * @param string $id cache id
+ * @param string $group name of the cache group
+ * @return boolean true if no problem
+ * @access public
+ */
+ function remove($id, $group = 'default')
+ {
+ $this->_setFileName($id, $group);
+ if ($this->_memoryCaching) {
+ if (isset($this->_memoryCachingArray[$this->_file])) {
+ unset($this->_memoryCachingArray[$this->_file]);
+ $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1;
+ }
+ if ($this->_onlyMemoryCaching) {
+ return true;
+ }
+ }
+ if (!@unlink($this->_file)) {
+ $this->raiseError('Cache_Lite : Unable to remove cache !', -3);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Clean the cache
+ *
+ * if no group is specified all cache files will be destroyed
+ * else only cache files of the specified group will be destroyed
+ *
+ * @param string $group name of the cache group
+ * @return boolean true if no problem
+ * @access public
+ */
+ function clean($group = false)
+ {
+ if ($this->_fileNameProtection) {
+ $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_';
+ } else {
+ $motif = ($group) ? 'cache_'.$group.'_' : 'cache_';
+ }
+ if ($this->_memoryCaching) {
+ while (list($key, $value) = each($this->_memoryCachingArray)) {
+ if (strpos($key, $motif, 0)) {
+ unset($this->_memoryCachingArray[$key]);
+ $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1;
+ }
+ }
+ if ($this->_onlyMemoryCaching) {
+ return true;
+ }
+ }
+ if (!($dh = opendir($this->_cacheDir))) {
+ $this->raiseError('Cache_Lite : Unable to open cache directory !', -4);
+ return false;
+ }
+ while ($file = readdir($dh)) {
+ if (($file != '.') && ($file != '..')) {
+ $file = $this->_cacheDir . $file;
+ if (is_file($file)) {
+ if (strpos($file, $motif, 0)) {
+ if (!@unlink($file)) {
+ $this->raiseError('Cache_Lite : Unable to remove cache !', -3);
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Set to debug mode
+ *
+ * When an error is found, the script will stop and the message will be displayed
+ * (in debug mode only).
+ *
+ * @access public
+ */
+ function setToDebug()
+ {
+ $this->_pearErrorMode = CACHE_LITE_ERROR_DIE;
+ }
+
+ /**
+ * Set a new life time
+ *
+ * @param int $newLifeTime new life time (in seconds)
+ * @access public
+ */
+ function setLifeTime($newLifeTime)
+ {
+ $this->_lifeTime = $newLifeTime;
+ $this->_refreshTime = time() - $newLifeTime;
+ }
+
+ /**
+ *
+ * @access public
+ */
+ function saveMemoryCachingState($id, $group = 'default')
+ {
+ if ($this->_caching) {
+ $array = array(
+ 'counter' => $this->_memoryCachingCounter,
+ 'array' => $this->_memoryCachingState
+ );
+ $data = serialize($array);
+ $this->save($data, $id, $group);
+ }
+ }
+
+ /**
+ *
+ * @access public
+ */
+ function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false)
+ {
+ if ($this->_caching) {
+ if ($data = $this->get($id, $group, $doNotTestCacheValidity)) {
+ $array = unserialize($data);
+ $this->_memoryCachingCounter = $array['counter'];
+ $this->_memoryCachingArray = $array['array'];
+ }
+ }
+ }
+
+ /**
+ * Return the cache last modification time
+ *
+ * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY !
+ *
+ * @return int last modification time
+ */
+ function lastModified() {
+ return filemtime($this->_file);
+ }
+
+ /**
+ * Trigger a PEAR error
+ *
+ * To improve performances, the PEAR.php file is included dynamically.
+ * The file is so included only when an error is triggered. So, in most
+ * cases, the file isn't included and perfs are much better.
+ *
+ * @param string $msg error message
+ * @param int $code error code
+ * @access public
+ */
+ function raiseError($msg, $code)
+ {
+ include_once('PEAR.php');
+ PEAR::raiseError($msg, $code, $this->_pearErrorMode);
+ }
+
+ // --- Private methods ---
+
+ /**
+ *
+ * @access private
+ */
+ function _memoryCacheAdd($id, $data)
+ {
+ $this->_memoryCachingArray[$this->_file] = $data;
+ if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) {
+ list($key, $value) = each($this->_memoryCachingArray);
+ unset($this->_memoryCachingArray[$key]);
+ } else {
+ $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1;
+ }
+ }
+
+ /**
+ * Make a file name (with path)
+ *
+ * @param string $id cache id
+ * @param string $group name of the group
+ * @access private
+ */
+ function _setFileName($id, $group)
+ {
+ if ($this->_fileNameProtection) {
+ $this->_file = ($this->_cacheDir.'cache_'.md5($group).'_'.md5($id));
+ } else {
+ $this->_file = $this->_cacheDir.'cache_'.$group.'_'.$id;
+ }
+ }
+
+ /**
+ * Read the cache file and return the content
+ *
+ * @return string content of the cache file
+ * @access private
+ */
+ function _read()
+ {
+ $fp = @fopen($this->_file, "rb");
+ if ($this->_fileLocking) @flock($fp, LOCK_SH);
+ if ($fp) {
+ clearstatcache(); // because the filesize can be cached by PHP itself...
+ $length = @filesize($this->_file);
+ $mqr = get_magic_quotes_runtime();
+ set_magic_quotes_runtime(0);
+ if ($this->_readControl) {
+ $hashControl = @fread($fp, 32);
+ $length = $length - 32;
+ }
+ $data = @fread($fp, $length);
+ set_magic_quotes_runtime($mqr);
+ if ($this->_fileLocking) @flock($fp, LOCK_UN);
+ @fclose($fp);
+ if ($this->_readControl) {
+ $hashData = $this->_hash($data, $this->_readControlType);
+ if ($hashData != $hashControl) {
+ @touch($this->_file, time() - 2*abs($this->_lifeTime));
+ return false;
+ }
+ }
+ return $data;
+ }
+ $this->raiseError('Cache_Lite : Unable to read cache !', -2);
+ return false;
+ }
+
+ /**
+ * Write the given data in the cache file
+ *
+ * @param string $data data to put in cache
+ * @return boolean true if ok
+ * @access private
+ */
+ function _write($data)
+ {
+ $fp = @fopen($this->_file, "wb");
+ if ($fp) {
+ if ($this->_fileLocking) @flock($fp, LOCK_EX);
+ if ($this->_readControl) {
+ @fwrite($fp, $this->_hash($data, $this->_readControlType), 32);
+ }
+ $len = strlen($data);
+ @fwrite($fp, $data, $len);
+ if ($this->_fileLocking) @flock($fp, LOCK_UN);
+ @fclose($fp);
+ return true;
+ }
+ $this->raiseError('Cache_Lite : Unable to write cache !', -1);
+ return false;
+ }
+
+ /**
+ * Write the given data in the cache file and control it just after to avoir corrupted cache entries
+ *
+ * @param string $data data to put in cache
+ * @return boolean true if the test is ok
+ * @access private
+ */
+ function _writeAndControl($data)
+ {
+ $this->_write($data);
+ $dataRead = $this->_read($data);
+ return ($dataRead==$data);
+ }
+
+ /**
+ * Make a control key with the string containing datas
+ *
+ * @param string $data data
+ * @param string $controlType type of control 'md5', 'crc32' or 'strlen'
+ * @return string control key
+ * @access private
+ */
+ function _hash($data, $controlType)
+ {
+ switch ($controlType) {
+ case 'md5':
+ return md5($data);
+ case 'crc32':
+ return sprintf('% 32d', crc32($data));
+ case 'strlen':
+ return sprintf('% 32d', strlen($data));
+ default:
+ $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5);
+ }
+ }
+
+}
+
+?>
diff --git a/scire/phpgacl/gacl.class.php b/scire/phpgacl/gacl.class.php
new file mode 100644
index 0000000..b8832a1
--- /dev/null
+++ b/scire/phpgacl/gacl.class.php
@@ -0,0 +1,629 @@
+<?php
+// $Id: gacl.class.php,v 1.53 2005/10/13 19:53:08 ipso Exp $
+
+/**
+ * phpGACL - Generic Access Control List
+ * Copyright (C) 2002,2003 Mike Benoit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For questions, help, comments, discussion, etc., please join the
+ * phpGACL mailing list. http://sourceforge.net/mail/?group_id=57103
+ *
+ * You may contact the author of phpGACL by e-mail at:
+ * ipso@snappymail.ca
+ *
+ * The latest version of phpGACL can be obtained from:
+ * http://phpgacl.sourceforge.net/
+ *
+ * @package phpGACL
+ */
+
+/*
+ * Path to ADODB.
+ */
+if ( !defined('ADODB_DIR') ) {
+ define('ADODB_DIR', $ADOdb_path);
+}
+
+/**
+* phpGACL main class
+*
+* Class gacl should be used in applications where only querying the phpGACL
+* database is required.
+*
+* @package phpGACL
+* @author Mike Benoit <ipso@snappymail.ca>
+*/
+class gacl {
+ /*
+ --- phpGACL Configuration path/file ---
+ */
+ var $config_file = './gacl.ini.php';
+
+ /*
+ --- Private properties ---
+ */
+ /** @var boolean Enables Debug output if true */
+ var $_debug = FALSE;
+# var $_debug = True;
+ /*
+ --- Database configuration. ---
+ */
+ /** @var string Prefix for all the phpgacl tables in the database */
+ var $_db_table_prefix = 'gacl_';
+
+ /** @var string The database type, based on available ADODB connectors - mysql, postgres7, sybase, oci8po See here for more: http://php.weblogs.com/adodb_manual#driverguide */
+ var $_db_type = '';
+
+ /** @var string The database server */
+ var $_db_host = '';
+
+ /** @var string The database user name */
+ var $_db_user = '';
+
+ /** @var string The database user password */
+ var $_db_password = '';
+
+ /** @var string The database name */
+ var $_db_name = '';
+
+ /** @var object An ADODB database connector object */
+ var $_db = '';
+
+ /*
+ * NOTE: This cache must be manually cleaned each time ACL's are modified.
+ * Alternatively you could wait for the cache to expire.
+ */
+
+ /** @var boolean Caches queries if true */
+ var $_caching = FALSE;
+
+ /** @var boolean Force cache to expire */
+ var $_force_cache_expire = TRUE;
+
+ /** @var string The directory for cache file to eb written (ensure write permission are set) */
+ var $_cache_dir = '/tmp/phpgacl_cache'; // NO trailing slash
+
+ /** @var int The time for the cache to expire in seconds - 600 == Ten Minutes */
+ var $_cache_expire_time=600;
+
+ /** @var string A switch to put acl_check into '_group_' mode */
+ var $_group_switch = '_group_';
+
+ /**
+ * Constructor
+ * @param array An arry of options to oeverride the class defaults
+ */
+ function gacl($options = NULL) {
+
+ $available_options = array('db','debug','items_per_page','max_select_box_items','max_search_return_items','db_table_prefix','db_type','db_host','db_user','db_password','db_name','caching','force_cache_expire','cache_dir','cache_expire_time');
+
+ //Values supplied in $options array overwrite those in the config file.
+ if ( file_exists($this->config_file) ) {
+ $config = parse_ini_file($this->config_file);
+
+ if ( is_array($config) ) {
+ $gacl_options = array_merge($config, $options);
+ }
+
+ unset($config);
+ }
+
+ if (is_array($options)) {
+ foreach ($options as $key => $value) {
+ $this->debug_text("Option: $key");
+
+ if (in_array($key, $available_options) ) {
+ $this->debug_text("Valid Config options: $key");
+ $property = '_'.$key;
+ $this->$property = $value;
+ } else {
+ $this->debug_text("ERROR: Config option: $key is not a valid option");
+ }
+ }
+ }
+
+ require_once( ADODB_DIR .'/adodb.inc.php');
+ require_once( ADODB_DIR .'/adodb-pager.inc.php');
+
+ //Use NUM for slight performance/memory reasons.
+ //Leave this in for backwards compatibility with older ADODB installations.
+ //If your using ADODB v3.5+ feel free to comment out the following line if its giving you problems.
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if (is_object($this->_db)) {
+ $this->db = &$this->_db;
+ } else {
+ $this->db = ADONewConnection($this->_db_type);
+ $this->db->SetFetchMode(ADODB_FETCH_NUM);
+ $this->db->PConnect($this->_db_host, $this->_db_user, $this->_db_password, $this->_db_name);
+ }
+ $this->db->debug = $this->_debug;
+
+ if ( $this->_caching == TRUE ) {
+ if (!class_exists('Hashed_Cache_Lite')) {
+ require_once(dirname(__FILE__) .'/Cache_Lite/Hashed_Cache_Lite.php');
+ }
+
+ /*
+ * Cache options. We default to the highest performance. If you run in to cache corruption problems,
+ * Change all the 'false' to 'true', this will slow things down slightly however.
+ */
+
+ $cache_options = array(
+ 'caching' => $this->_caching,
+ 'cacheDir' => $this->_cache_dir.'/',
+ 'lifeTime' => $this->_cache_expire_time,
+ 'fileLocking' => TRUE,
+ 'writeControl' => FALSE,
+ 'readControl' => FALSE,
+ 'memoryCaching' => TRUE,
+ 'automaticSerialization' => FALSE
+ );
+ $this->Cache_Lite = new Hashed_Cache_Lite($cache_options);
+ }
+
+ return true;
+ }
+
+ /**
+ * Prints debug text if debug is enabled.
+ * @param string THe text to output
+ * @return boolean Always returns true
+ */
+ function debug_text($text) {
+
+ if ($this->_debug) {
+ echo "$text<br>\n";
+ }
+
+ return true;
+ }
+
+ /**
+ * Prints database debug text if debug is enabled.
+ * @param string The name of the function calling this method
+ * @return string Returns an error message
+ */
+ function debug_db($function_name = '') {
+ if ($function_name != '') {
+ $function_name .= ' (): ';
+ }
+
+ return $this->debug_text ($function_name .'database error: '. $this->db->ErrorMsg() .' ('. $this->db->ErrorNo() .')');
+ }
+
+ /**
+ * Wraps the actual acl_query() function.
+ *
+ * It is simply here to return TRUE/FALSE accordingly.
+ * @param string The ACO section value
+ * @param string The ACO value
+ * @param string The ARO section value
+ * @param string The ARO section
+ * @param string The AXO section value (optional)
+ * @param string The AXO section value (optional)
+ * @param integer The group id of the ARO ??Mike?? (optional)
+ * @param integer The group id of the AXO ??Mike?? (optional)
+ * @return boolean TRUE if the check succeeds, false if not.
+ */
+ function acl_check($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value=NULL, $axo_value=NULL, $root_aro_group=NULL, $root_axo_group=NULL) {
+ $acl_result = $this->acl_query($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value, $axo_value, $root_aro_group, $root_axo_group);
+
+ return $acl_result['allow'];
+ }
+
+ /**
+ * Wraps the actual acl_query() function.
+ *
+ * Quick access to the return value of an ACL.
+ * @param string The ACO section value
+ * @param string The ACO value
+ * @param string The ARO section value
+ * @param string The ARO section
+ * @param string The AXO section value (optional)
+ * @param string The AXO section value (optional)
+ * @param integer The group id of the ARO (optional)
+ * @param integer The group id of the AXO (optional)
+ * @return string The return value of the ACL
+ */
+ function acl_return_value($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value=NULL, $axo_value=NULL, $root_aro_group=NULL, $root_axo_group=NULL) {
+ $acl_result = $this->acl_query($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value, $axo_value, $root_aro_group, $root_axo_group);
+
+ return $acl_result['return_value'];
+ }
+
+ /**
+ * Handles ACL lookups over arrays of AROs
+ * @param string The ACO section value
+ * @param string The ACO value
+ * @param array An named array of arrays, each element in the format aro_section_value=>array(aro_value1,aro_value1,...)
+ * @return mixed The same data format as inputted.
+ \*======================================================================*/
+ function acl_check_array($aco_section_value, $aco_value, $aro_array) {
+ /*
+ Input Array:
+ Section => array(Value, Value, Value),
+ Section => array(Value, Value, Value)
+
+ */
+
+ if (!is_array($aro_array)) {
+ $this->debug_text("acl_query_array(): ARO Array must be passed");
+ return false;
+ }
+
+ foreach($aro_array as $aro_section_value => $aro_value_array) {
+ foreach ($aro_value_array as $aro_value) {
+ $this->debug_text("acl_query_array(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
+
+ if( $this->acl_check($aco_section_value, $aco_value, $aro_section_value, $aro_value) ) {
+ $this->debug_text("acl_query_array(): ACL_CHECK True");
+ $retarr[$aro_section_value][] = $aro_value;
+ } else {
+ $this->debug_text("acl_query_array(): ACL_CHECK False");
+ }
+ }
+ }
+
+ return $retarr;
+
+ }
+
+ /**
+ * The Main function that does the actual ACL lookup.
+ * @param string The ACO section value
+ * @param string The ACO value
+ * @param string The ARO section value
+ * @param string The ARO section
+ * @param string The AXO section value (optional)
+ * @param string The AXO section value (optional)
+ * @param string The value of the ARO group (optional)
+ * @param string The value of the AXO group (optional)
+ * @param boolean Debug the operation if true (optional)
+ * @return array Returns as much information as possible about the ACL so other functions can trim it down and omit unwanted data.
+ */
+ function acl_query($aco_section_value, $aco_value, $aro_section_value, $aro_value, $axo_section_value=NULL, $axo_value=NULL, $root_aro_group=NULL, $root_axo_group=NULL, $debug=NULL) {
+
+ $cache_id = 'acl_query_'.$aco_section_value.'-'.$aco_value.'-'.$aro_section_value.'-'.$aro_value.'-'.$axo_section_value.'-'.$axo_value.'-'.$root_aro_group.'-'.$root_axo_group.'-'.$debug;
+
+ $retarr = $this->get_cache($cache_id);
+
+ if (!$retarr) {
+ /*
+ * Grab all groups mapped to this ARO/AXO
+ */
+ $aro_group_ids = $this->acl_get_groups($aro_section_value, $aro_value, $root_aro_group, 'ARO');
+
+ if (is_array($aro_group_ids) AND !empty($aro_group_ids)) {
+ $sql_aro_group_ids = implode(',', $aro_group_ids);
+ }
+
+ if ($axo_section_value != '' AND $axo_value != '') {
+ $axo_group_ids = $this->acl_get_groups($axo_section_value, $axo_value, $root_axo_group, 'AXO');
+
+ if (is_array($axo_group_ids) AND !empty($axo_group_ids)) {
+ $sql_axo_group_ids = implode(',', $axo_group_ids);
+ }
+ }
+
+ /*
+ * This query is where all the magic happens.
+ * The ordering is very important here, as well very tricky to get correct.
+ * Currently there can be duplicate ACLs, or ones that step on each other toes. In this case, the ACL that was last updated/created
+ * is used.
+ *
+ * This is probably where the most optimizations can be made.
+ */
+
+ $order_by = array();
+
+ $query = '
+ SELECT a.id,a.allow,a.return_value
+ FROM '. $this->_db_table_prefix .'acl a
+ LEFT JOIN '. $this->_db_table_prefix .'aco_map ac ON ac.acl_id=a.id';
+
+ if ($aro_section_value != $this->_group_switch) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'aro_map ar ON ar.acl_id=a.id';
+ }
+
+ if ($axo_section_value != $this->_group_switch) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'axo_map ax ON ax.acl_id=a.id';
+ }
+
+ /*
+ * if there are no aro groups, don't bother doing the join.
+ */
+ if (isset($sql_aro_group_ids)) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'aro_groups_map arg ON arg.acl_id=a.id
+ LEFT JOIN '. $this->_db_table_prefix .'aro_groups rg ON rg.id=arg.group_id';
+ }
+
+ // this join is necessary to weed out rules associated with axo groups
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'axo_groups_map axg ON axg.acl_id=a.id';
+
+ /*
+ * if there are no axo groups, don't bother doing the join.
+ * it is only used to rank by the level of the group.
+ */
+ if (isset($sql_axo_group_ids)) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'axo_groups xg ON xg.id=axg.group_id';
+ }
+
+ //Move the below line to the LEFT JOIN above for PostgreSQL's sake.
+ //AND ac.acl_id=a.id
+ $query .= '
+ WHERE a.enabled=1
+ AND (ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value='. $this->db->quote($aco_value) .')';
+
+ // if we are querying an aro group
+ if ($aro_section_value == $this->_group_switch) {
+ // if acl_get_groups did not return an array
+ if ( !isset ($sql_aro_group_ids) ) {
+ $this->debug_text ('acl_query(): Invalid ARO Group: '. $aro_value);
+ return FALSE;
+ }
+
+ $query .= '
+ AND rg.id IN ('. $sql_aro_group_ids .')';
+
+ $order_by[] = '(rg.rgt-rg.lft) ASC';
+ } else {
+ $query .= '
+ AND ((ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value='. $this->db->quote($aro_value) .')';
+
+ if ( isset ($sql_aro_group_ids) ) {
+ $query .= ' OR rg.id IN ('. $sql_aro_group_ids .')';
+
+ $order_by[] = '(CASE WHEN ar.value IS NULL THEN 0 ELSE 1 END) DESC';
+ $order_by[] = '(rg.rgt-rg.lft) ASC';
+ }
+
+ $query .= ')';
+ }
+
+
+ // if we are querying an axo group
+ if ($axo_section_value == $this->_group_switch) {
+ // if acl_get_groups did not return an array
+ if ( !isset ($sql_axo_group_ids) ) {
+ $this->debug_text ('acl_query(): Invalid AXO Group: '. $axo_value);
+ return FALSE;
+ }
+
+ $query .= '
+ AND xg.id IN ('. $sql_axo_group_ids .')';
+
+ $order_by[] = '(xg.rgt-xg.lft) ASC';
+ } else {
+ $query .= '
+ AND (';
+
+ if ($axo_section_value == '' AND $axo_value == '') {
+ $query .= '(ax.section_value IS NULL AND ax.value IS NULL)';
+ } else {
+ $query .= '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value='. $this->db->quote($axo_value) .')';
+ }
+
+ if (isset($sql_axo_group_ids)) {
+ $query .= ' OR xg.id IN ('. $sql_axo_group_ids .')';
+
+ $order_by[] = '(CASE WHEN ax.value IS NULL THEN 0 ELSE 1 END) DESC';
+ $order_by[] = '(xg.rgt-xg.lft) ASC';
+ } else {
+ $query .= ' AND axg.group_id IS NULL';
+ }
+
+ $query .= ')';
+ }
+
+ /*
+ * The ordering is always very tricky and makes all the difference in the world.
+ * Order (ar.value IS NOT NULL) DESC should put ACLs given to specific AROs
+ * ahead of any ACLs given to groups. This works well for exceptions to groups.
+ */
+
+ $order_by[] = 'a.updated_date DESC';
+
+ $query .= '
+ ORDER BY '. implode (',', $order_by) . '
+ ';
+
+ // we are only interested in the first row
+ $rs = $this->db->SelectLimit($query, 1);
+
+ if (!is_object($rs)) {
+ $this->debug_db('acl_query');
+ return FALSE;
+ }
+
+ $row =& $rs->FetchRow();
+
+ /*
+ * Return ACL ID. This is the key to "hooking" extras like pricing assigned to ACLs etc... Very useful.
+ */
+ if (is_array($row)) {
+ // Permission granted?
+ // This below oneliner is very confusing.
+ //$allow = (isset($row[1]) AND $row[1] == 1);
+
+ //Prefer this.
+ if ( isset($row[1]) AND $row[1] == 1 ) {
+ $allow = TRUE;
+ } else {
+ $allow = FALSE;
+ }
+
+ $retarr = array('acl_id' => &$row[0], 'return_value' => &$row[2], 'allow' => $allow);
+ } else {
+ // Permission denied.
+ $retarr = array('acl_id' => NULL, 'return_value' => NULL, 'allow' => FALSE);
+ }
+
+ /*
+ * Return the query that we ran if in debug mode.
+ */
+ if ($debug == TRUE) {
+ $retarr['query'] = &$query;
+ }
+
+ //Cache data.
+ $this->put_cache($retarr, $cache_id);
+ }
+
+ $this->debug_text("<b>acl_query():</b> ACO Section: $aco_section_value ACO Value: $aco_value ARO Section: $aro_section_value ARO Value $aro_value ACL ID: ". $retarr['acl_id'] .' Result: '. $retarr['allow']);
+ return $retarr;
+ }
+
+ /**
+ * Grabs all groups mapped to an ARO. You can also specify a root_group for subtree'ing.
+ * @param string The section value or the ARO or ACO
+ * @param string The value of the ARO or ACO
+ * @param integer The group id of the group to start at (optional)
+ * @param string The type of group, either ARO or AXO (optional)
+ */
+ function acl_get_groups($section_value, $value, $root_group=NULL, $group_type='ARO') {
+
+ switch(strtolower($group_type)) {
+ case 'axo':
+ $group_type = 'axo';
+ $object_table = $this->_db_table_prefix .'axo';
+ $group_table = $this->_db_table_prefix .'axo_groups';
+ $group_map_table = $this->_db_table_prefix .'groups_axo_map';
+ break;
+ default:
+ $group_type = 'aro';
+ $object_table = $this->_db_table_prefix .'aro';
+ $group_table = $this->_db_table_prefix .'aro_groups';
+ $group_map_table = $this->_db_table_prefix .'groups_aro_map';
+ break;
+ }
+
+ //$profiler->startTimer( "acl_get_groups()");
+
+ //Generate unique cache id.
+ $cache_id = 'acl_get_groups_'.$section_value.'-'.$value.'-'.$root_group.'-'.$group_type;
+
+ $retarr = $this->get_cache($cache_id);
+
+ if (!$retarr) {
+
+ // Make sure we get the groups
+ $query = '
+ SELECT DISTINCT g2.id';
+
+ if ($section_value == $this->_group_switch) {
+ $query .= '
+ FROM ' . $group_table . ' g1,' . $group_table . ' g2';
+
+ $where = '
+ WHERE g1.value=' . $this->db->quote( $value );
+ } else {
+ $query .= '
+ FROM '. $object_table .' o,'. $group_map_table .' gm,'. $group_table .' g1,'. $group_table .' g2';
+
+ $where = '
+ WHERE (o.section_value='. $this->db->quote($section_value) .' AND o.value='. $this->db->quote($value) .')
+ AND gm.'. $group_type .'_id=o.id
+ AND g1.id=gm.group_id';
+ }
+
+ /*
+ * If root_group_id is specified, we have to narrow this query down
+ * to just groups deeper in the tree then what is specified.
+ * This essentially creates a virtual "subtree" and ignores all outside groups.
+ * Useful for sites like sourceforge where you may seperate groups by "project".
+ */
+ if ( $root_group != '') {
+ //It is important to note the below line modifies the tables being selected.
+ //This is the reason for the WHERE variable.
+ $query .= ','. $group_table .' g3';
+
+ $where .= '
+ AND g3.value='. $this->db->quote( $root_group ) .'
+ AND ((g2.lft BETWEEN g3.lft AND g1.lft) AND (g2.rgt BETWEEN g1.rgt AND g3.rgt))';
+ } else {
+ $where .= '
+ AND (g2.lft <= g1.lft AND g2.rgt >= g1.rgt)';
+ }
+
+ $query .= $where;
+
+ // $this->debug_text($query);
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('acl_get_groups');
+ return FALSE;
+ }
+
+ $retarr = array();
+
+ //Unbuffered query?
+ while (!$rs->EOF) {
+ $retarr[] = reset($rs->fields);
+ $rs->MoveNext();
+ }
+
+ //Cache data.
+ $this->put_cache($retarr, $cache_id);
+ }
+
+ return $retarr;
+ }
+
+ /**
+ * Uses PEAR's Cache_Lite package to grab cached arrays, objects, variables etc...
+ * using unserialize() so it can handle more then just text string.
+ * @param string The id of the cached object
+ * @return mixed The cached object, otherwise FALSE if the object identifier was not found
+ */
+ function get_cache($cache_id) {
+
+ if ( $this->_caching == TRUE ) {
+ $this->debug_text("get_cache(): on ID: $cache_id");
+
+ if ( is_string($this->Cache_Lite->get($cache_id) ) ) {
+ return unserialize($this->Cache_Lite->get($cache_id) );
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Uses PEAR's Cache_Lite package to write cached arrays, objects, variables etc...
+ * using serialize() so it can handle more then just text string.
+ * @param mixed A variable to cache
+ * @param string The id of the cached variable
+ */
+ function put_cache($data, $cache_id) {
+
+ if ( $this->_caching == TRUE ) {
+ $this->debug_text("put_cache(): Cache MISS on ID: $cache_id");
+
+ return $this->Cache_Lite->save(serialize($data), $cache_id);
+ }
+
+ return false;
+ }
+}
+?>
diff --git a/scire/phpgacl/gacl_api.class.php b/scire/phpgacl/gacl_api.class.php
new file mode 100644
index 0000000..70833fc
--- /dev/null
+++ b/scire/phpgacl/gacl_api.class.php
@@ -0,0 +1,3899 @@
+<?php
+/**
+ * phpGACL - Generic Access Control List
+ * Copyright (C) 2002,2003 Mike Benoit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * For questions, help, comments, discussion, etc., please join the
+ * phpGACL mailing list. http://sourceforge.net/mail/?group_id=57103
+ *
+ * You may contact the author of phpGACL by e-mail at:
+ * ipso@snappymail.ca
+ *
+ * The latest version of phpGACL can be obtained from:
+ * http://phpgacl.sourceforge.net/
+ *
+ * @package phpGACL
+ *
+ */
+
+/*
+ *
+ * For examples, see example.php or the Administration interface,
+ * as it makes use of nearly every API Call.
+ *
+ */
+/**
+ * gacl_api Extended API Class
+ *
+ * Class gacl_api should be used for applications that must interface directly with
+ * phpGACL's data structures, objects, and rules.
+ *
+ * @package phpGACL
+ * @author Mike Benoit <ipso@snappymail.ca>
+ *
+ */
+
+class gacl_api extends gacl {
+
+ /*
+ *
+ * Misc helper functions.
+ *
+ */
+
+ /**
+ * showarray()
+ *
+ * Dump all contents of an array in HTML (kinda)
+ *
+ * @param array
+ *
+ */
+ function showarray($array) {
+ echo "<br><pre>\n";
+ var_dump($array);
+ echo "</pre><br>\n";
+ }
+
+ /**
+ * count_all()
+ *
+ * Recursively counts elements in an array and sub-arrays.
+ *
+ * This is different from count($arg, COUNT_RECURSIVE)
+ * in PHP >= 4.2.0, which includes sub-arrays in the count.
+ *
+ * @return int The returned count is a count of all scalar elements found.
+ *
+ * @param array Array to count
+ */
+ function count_all($arg = NULL) {
+ switch (TRUE) {
+ case is_scalar($arg):
+ case is_object($arg):
+ // single object
+ return 1;
+ case is_array($arg):
+ // call recursively for all elements of $arg
+ $count = 0;
+ foreach ($arg as $val) {
+ $count += $this->count_all($val);
+ }
+ return $count;
+ }
+ return FALSE;
+ }
+
+ /**
+ * get_version()
+ *
+ * Grabs phpGACL version from the database.
+ *
+ * @return string Version of phpGACL
+ */
+ function get_version() {
+ $query = "select value from ".$this->_db_table_prefix."phpgacl where name = 'version'";
+ $version = $this->db->GetOne($query);
+
+ return $version;
+ }
+
+ /**
+ * get_schema_version()
+ *
+ * Grabs phpGACL schema version from the database.
+ *
+ * @return string Schema Version
+ */
+ function get_schema_version() {
+ $query = "select value from ".$this->_db_table_prefix."phpgacl where name = 'schema_version'";
+ $version = $this->db->GetOne($query);
+
+ return $version;
+ }
+
+ /*
+ *
+ * ACL
+ *
+ */
+
+ /**
+ * consolidated_edit_acl()
+ *
+ * Add's an ACL but checks to see if it can consolidate it with another one first.
+ *
+ * This ONLY works with ACO's and ARO's. Groups, and AXO are excluded.
+ * As well this function is designed for handling ACLs with return values,
+ * and consolidating on the return_value, in hopes of keeping the ACL count to a minimum.
+ *
+ * A return value of false must _always_ be handled outside this function.
+ * As this function will remove AROs from ACLs and return false, in most cases
+ * you will need to a create a completely new ACL on a false return.
+ *
+ * @return bool Special boolean return value. See note.
+ *
+ * @param string ACO Section Value
+ * @param string ACO Value
+ * @param string ARO Section Value
+ * @param string ARO Value
+ * @param string Return Value of ACL
+ */
+ function consolidated_edit_acl($aco_section_value, $aco_value, $aro_section_value, $aro_value, $return_value) {
+
+ $this->debug_text("consolidated_edit_acl(): ACO Section Value: $aco_section_value ACO Value: $aco_value ARO Section Value: $aro_section_value ARO Value: $aro_value Return Value: $return_value");
+
+ $acl_ids = array();
+
+ if (empty($aco_section_value) ) {
+ $this->debug_text("consolidated_edit_acl(): ACO Section Value ($aco_section_value) is empty, this is required!");
+ return false;
+ }
+
+ if (empty($aco_value) ) {
+ $this->debug_text("consolidated_edit_acl(): ACO Value ($aco_value) is empty, this is required!");
+ return false;
+ }
+
+ if (empty($aro_section_value) ) {
+ $this->debug_text("consolidated_edit_acl(): ARO Section Value ($aro_section_value) is empty, this is required!");
+ return false;
+ }
+
+ if (empty($aro_value) ) {
+ $this->debug_text("consolidated_edit_acl(): ARO Value ($aro_value) is empty, this is required!");
+ return false;
+ }
+
+ if (empty($return_value) ) {
+ $this->debug_text("consolidated_edit_acl(): Return Value ($return_value) is empty, this is required!");
+ return false;
+ }
+
+ //See if a current ACL exists with the current objects, excluding return value
+ $current_acl_ids = $this->search_acl($aco_section_value, $aco_value, $aro_section_value, $aro_value, FALSE, FALSE, FALSE, FALSE, FALSE);
+ //showarray($current_acl_ids);
+
+ if (is_array($current_acl_ids)) {
+ $this->debug_text("add_consolidated_acl(): Found current ACL_IDs, counting ACOs");
+
+ foreach ($current_acl_ids as $current_acl_id) {
+ //Check to make sure these ACLs only have a single ACO mapped to them.
+ $current_acl_array = &$this->get_acl($current_acl_id);
+
+ //showarray($current_acl_array);
+ $this->debug_text("add_consolidated_acl(): Current Count: ".$this->count_all($current_acl_array['aco'])."");
+
+ if ( $this->count_all($current_acl_array['aco']) == 1) {
+ $this->debug_text("add_consolidated_acl(): ACL ID: $current_acl_id has 1 ACO.");
+
+ //Test to see if the return values match, if they do, no need removing or appending ARO. Just return true.
+ if ($current_acl_array['return_value'] == $return_value) {
+ $this->debug_text("add_consolidated_acl(): ACL ID: $current_acl_id has 1 ACO, and the same return value. No need to modify.");
+ return true;
+ }
+
+ $acl_ids[] = $current_acl_id;
+ }
+
+ }
+ }
+
+ //showarray($acl_ids);
+ $acl_ids_count = count($acl_ids);
+
+ //If acl_id's turns up more then one ACL, lets remove the ARO from all of them in hopes to
+ //eliminate any conflicts.
+ if (is_array($acl_ids) AND $acl_ids_count > 0) {
+ $this->debug_text("add_consolidated_acl(): Removing specified ARO from existing ACL.");
+
+ foreach ($acl_ids as $acl_id) {
+ //Remove ARO from current ACLs, so we don't create conflicting ACLs later on.
+ if (!$this->shift_acl($acl_id, array($aro_section_value => array($aro_value)) ) ) {
+ $this->debug_text("add_consolidated_acl(): Error removing specified ARO from ACL ID: $acl_id");
+ return false;
+ }
+ }
+ } else {
+ $this->debug_text("add_consolidated_acl(): Didn't find any current ACLs with a single ACO. ");
+ }
+ //unset($acl_ids);
+ $acl_ids = array();
+ unset($acl_ids_count);
+
+ //At this point there should be no conflicting ACLs, searching for an existing ACL with the new values.
+ $new_acl_ids = $this->search_acl($aco_section_value, $aco_value, FALSE, FALSE, NULL, NULL, NULL, NULL, $return_value);
+ $new_acl_count = count($new_acl_ids);
+ //showarray($new_acl_ids);
+
+ if (is_array($new_acl_ids)) {
+ $this->debug_text("add_consolidated_acl(): Found new ACL_IDs, counting ACOs");
+
+ foreach ($new_acl_ids as $new_acl_id) {
+ //Check to make sure these ACLs only have a single ACO mapped to them.
+ $new_acl_array = &$this->get_acl($new_acl_id);
+ //showarray($new_acl_array);
+ $this->debug_text("add_consolidated_acl(): New Count: ".$this->count_all($new_acl_array['aco'])."");
+ if ( $this->count_all($new_acl_array['aco']) == 1) {
+
+ $this->debug_text("add_consolidated_acl(): ACL ID: $new_acl_id has 1 ACO, append should be able to take place.");
+ $acl_ids[] = $new_acl_id;
+ }
+
+ }
+ }
+
+ //showarray($acl_ids);
+ $acl_ids_count = count($acl_ids);
+
+ if (is_array($acl_ids) AND $acl_ids_count == 1) {
+ $this->debug_text("add_consolidated_acl(): Appending specified ARO to existing ACL.");
+
+ $acl_id=$acl_ids[0];
+
+ if (!$this->append_acl($acl_id, array($aro_section_value => array($aro_value)) ) ) {
+ $this->debug_text("add_consolidated_acl(): Error appending specified ARO to ACL ID: $acl_id");
+ return false;
+ }
+
+ $this->debug_text("add_consolidated_acl(): Hot damn, ACL consolidated!");
+ return true;
+ } elseif($acl_ids_count > 1) {
+ $this->debug_text("add_consolidated_acl(): Found more then one ACL with a single ACO. Possible conflicting ACLs.");
+ return false;
+ } elseif ($acl_ids_count == 0) {
+ $this->debug_text("add_consolidated_acl(): No existing ACLs found, create a new one.");
+
+ if (!$this->add_acl( array( $aco_section_value => array($aco_value) ),
+ array( $aro_section_value => array($aro_value) ),
+ NULL,
+ NULL,
+ NULL,
+ TRUE,
+ TRUE,
+ $return_value,
+ NULL)
+ ) {
+ $this->debug_text("add_consolidated_acl(): Error adding new ACL for ACO Section: $aco_section_value ACO Value: $aco_value Return Value: $return_value");
+ return false;
+ }
+
+ $this->debug_text("add_consolidated_acl(): ADD_ACL() successfull, returning True.");
+ return true;
+ }
+
+ $this->debug_text("add_consolidated_acl(): Returning false.");
+ return false;
+ }
+
+ /**
+ * search_acl()
+ *
+ * Searches for ACL's with specified objects mapped to them.
+ *
+ * NULL values are included in the search, if you want to ignore
+ * for instance aro_groups use FALSE instead of NULL.
+ *
+ * @return array containing ACL IDs if search is successful
+ *
+ * @param string ACO Section Value
+ * @param string ACO Value
+ * @param string ARO Section Value
+ * @param string ARO Value
+ * @param string ARO Group Name
+ * @param string AXO Section Value
+ * @param string AXO Value
+ * @param string AXO Group Name
+ * @param string Return Value
+ */
+ function search_acl($aco_section_value=NULL, $aco_value=NULL, $aro_section_value=NULL, $aro_value=NULL, $aro_group_name=NULL, $axo_section_value=NULL, $axo_value=NULL, $axo_group_name=NULL, $return_value=NULL) {
+ $this->debug_text("search_acl(): aco_section_value: $aco_section_value aco_value: $aco_value, aro_section_value: $aro_section_value, aro_value: $aro_value, aro_group_name: $aro_group_name, axo_section_value: $axo_section_value, axo_value: $axo_value, axo_group_name: $axo_group_name, return_value: $return_value");
+
+ $query = '
+ SELECT a.id
+ FROM '. $this->_db_table_prefix .'acl a';
+
+ $where_query = array();
+
+ // ACO
+ if ($aco_section_value !== FALSE AND $aco_value !== FALSE) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'aco_map ac ON a.id=ac.acl_id';
+
+ if ($aco_section_value == NULL AND $aco_value == NULL) {
+ $where_query[] = '(ac.section_value IS NULL AND ac.value IS NULL)';
+ } else {
+ $where_query[] = '(ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value='. $this->db->quote($aco_value) .')';
+ }
+ }
+
+ // ARO
+ if ($aro_section_value !== FALSE AND $aro_value !== FALSE) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'aro_map ar ON a.id=ar.acl_id';
+
+ if ($aro_section_value == NULL AND $aro_value == NULL) {
+ $where_query[] = '(ar.section_value IS NULL AND ar.value IS NULL)';
+ } else {
+ $where_query[] = '(ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value='. $this->db->quote($aro_value) .')';
+ }
+ }
+
+ // AXO
+ if ($axo_section_value !== FALSE AND $axo_value !== FALSE) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'axo_map ax ON a.id=ax.acl_id';
+
+ if ($axo_section_value == NULL AND $axo_value == NULL) {
+ $where_query[] = '(ax.section_value IS NULL AND ax.value IS NULL)';
+ } else {
+ $where_query[] = '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value='. $this->db->quote($axo_value) .')';
+ }
+ }
+
+ // ARO Group
+ if ($aro_group_name !== FALSE) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'aro_groups_map arg ON a.id=arg.acl_id
+ LEFT JOIN '. $this->_db_table_prefix .'aro_groups rg ON arg.group_id=rg.id';
+
+ if ($aro_group_name == NULL) {
+ $where_query[] = '(rg.name IS NULL)';
+ } else {
+ $where_query[] = '(rg.name='. $this->db->quote($aro_group_name) .')';
+ }
+ }
+
+ // AXO Group
+ if ($axo_group_name !== FALSE) {
+ $query .= '
+ LEFT JOIN '. $this->_db_table_prefix .'axo_groups_map axg ON a.id=axg.acl_id
+ LEFT JOIN '. $this->_db_table_prefix .'axo_groups xg ON axg.group_id=xg.id';
+
+ if ($axo_group_name == NULL) {
+ $where_query[] = '(xg.name IS NULL)';
+ } else {
+ $where_query[] = '(xg.name='. $this->db->quote($axo_group_name) .')';
+ }
+ }
+ if ($return_value != FALSE) {
+ if ($return_value == NULL) {
+ $where_query[] = '(a.return_value IS NULL)';
+ } else {
+ $where_query[] = '(a.return_value='. $this->db->quote($return_value) .')';
+ }
+ }
+
+ if (count($where_query) > 0) {
+ $query .= '
+ WHERE '. implode (' AND ', $where_query);
+ }
+
+ return $this->db->GetCol($query);
+ }
+
+ /**
+ * append_acl()
+ *
+ * Appends objects on to a specific ACL.
+ *
+ * @return bool TRUE if successful, FALSE otherwise.
+ *
+ * @param int ACL ID #
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ */
+ function append_acl($acl_id, $aro_array=NULL, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $aco_array=NULL) {
+ $this->debug_text("append_acl(): ACL_ID: $acl_id");
+
+ $update = 0;
+
+ if (empty($acl_id)) {
+ $this->debug_text("append_acl(): No ACL_ID specified! ACL_ID: $acl_id");
+ return false;
+ }
+
+ //Grab ACL data.
+ $acl_array = &$this->get_acl($acl_id);
+
+ //Append each object type seperately.
+ if (is_array($aro_array) AND count($aro_array) > 0) {
+ $this->debug_text("append_acl(): Appending ARO's");
+
+ while (list($aro_section_value,$aro_value_array) = @each($aro_array)) {
+ foreach ($aro_value_array as $aro_value) {
+ if ( count($acl_array['aro'][$aro_section_value]) != 0 ) {
+ if (!in_array($aro_value, $acl_array['aro'][$aro_section_value])) {
+ $this->debug_text("append_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
+ $acl_array['aro'][$aro_section_value][] = $aro_value;
+ $update=1;
+ } else {
+ $this->debug_text("append_acl(): Duplicate ARO, ignoring... ");
+ }
+ } else { //Array is empty so add this aro value.
+ $acl_array['aro'][$aro_section_value][] = $aro_value;
+ $update = 1;
+ }
+ }
+ }
+ }
+
+ if (is_array($aro_group_ids) AND count($aro_group_ids) > 0) {
+ $this->debug_text("append_acl(): Appending ARO_GROUP_ID's");
+
+ while (list(,$aro_group_id) = @each($aro_group_ids)) {
+ if (!is_array($acl_array['aro_groups']) OR !in_array($aro_group_id, $acl_array['aro_groups'])) {
+ $this->debug_text("append_acl(): ARO Group ID: $aro_group_id");
+ $acl_array['aro_groups'][] = $aro_group_id;
+ $update = 1;
+ } else {
+ $this->debug_text("append_acl(): Duplicate ARO_Group_ID, ignoring... ");
+ }
+ }
+ }
+
+ if (is_array($axo_array) AND count($axo_array) > 0) {
+ $this->debug_text("append_acl(): Appending AXO's");
+
+ while (list($axo_section_value,$axo_value_array) = @each($axo_array)) {
+ foreach ($axo_value_array as $axo_value) {
+ if (!in_array($axo_value, $acl_array['axo'][$axo_section_value])) {
+ $this->debug_text("append_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value");
+ $acl_array['axo'][$axo_section_value][] = $axo_value;
+ $update = 1;
+ } else {
+ $this->debug_text("append_acl(): Duplicate AXO, ignoring... ");
+ }
+
+ }
+ }
+ }
+
+ if (is_array($axo_group_ids) AND count($axo_group_ids) > 0) {
+ $this->debug_text("append_acl(): Appending AXO_GROUP_ID's");
+ while (list(,$axo_group_id) = @each($axo_group_ids)) {
+ if (!is_array($acl_array['axo_groups']) OR !in_array($axo_group_id, $acl_array['axo_groups'])) {
+ $this->debug_text("append_acl(): AXO Group ID: $axo_group_id");
+ $acl_array['axo_groups'][] = $axo_group_id;
+ $update = 1;
+ } else {
+ $this->debug_text("append_acl(): Duplicate ARO_Group_ID, ignoring... ");
+ }
+ }
+ }
+
+ if (is_array($aco_array) AND count($aco_array) > 0) {
+ $this->debug_text("append_acl(): Appending ACO's");
+
+ while (list($aco_section_value,$aco_value_array) = @each($aco_array)) {
+ foreach ($aco_value_array as $aco_value) {
+ if (!in_array($aco_value, $acl_array['aco'][$aco_section_value])) {
+ $this->debug_text("append_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value");
+ $acl_array['aco'][$aco_section_value][] = $aco_value;
+ $update = 1;
+ } else {
+ $this->debug_text("append_acl(): Duplicate ACO, ignoring... ");
+ }
+ }
+ }
+ }
+
+ if ($update == 1) {
+ $this->debug_text("append_acl(): Update flag set, updating ACL.");
+ //function edit_acl($acl_id, $aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $allow=1, $enabled=1, $return_value=NULL, $note=NULL) {
+ return $this->edit_acl($acl_id, $acl_array['aco'], $acl_array['aro'], $acl_array['aro_groups'], $acl_array['axo'], $acl_array['axo_groups'], $acl_array['allow'], $acl_array['enabled'], $acl_array['return_value'], $acl_array['note']);
+ }
+
+ //Return true if everything is duplicate and no ACL id updated.
+ $this->debug_text("append_acl(): Update flag not set, NOT updating ACL.");
+ return true;
+ }
+
+ /**
+ * shift_acl()
+ *
+ * Opposite of append_acl(). Removes objects from a specific ACL. (named after PHP's array_shift())
+ *
+ * @return bool TRUE if successful, FALSE otherwise.
+ *
+ * @param int ACL ID #
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ */
+ function shift_acl($acl_id, $aro_array=NULL, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $aco_array=NULL) {
+ $this->debug_text("shift_acl(): ACL_ID: $acl_id");
+
+ $update = 0;
+
+ if (empty($acl_id)) {
+ $this->debug_text("shift_acl(): No ACL_ID specified! ACL_ID: $acl_id");
+ return false;
+ }
+
+ //Grab ACL data.
+ $acl_array = &$this->get_acl($acl_id);
+
+ //showarray($acl_array);
+ //Remove each object type seperately.
+ if (is_array($aro_array) AND count($aro_array) > 0) {
+ $this->debug_text("shift_acl(): Removing ARO's");
+
+ while (list($aro_section_value,$aro_value_array) = @each($aro_array)) {
+ foreach ($aro_value_array as $aro_value) {
+ $this->debug_text("shift_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value");
+
+ //Only search if aro array contains data.
+ if ( count($acl_array['aro'][$aro_section_value]) != 0 ) {
+ $aro_key = array_search($aro_value, $acl_array['aro'][$aro_section_value]);
+
+ if ($aro_key !== FALSE) {
+ $this->debug_text("shift_acl(): Removing ARO. ($aro_key)");
+ unset($acl_array['aro'][$aro_section_value][$aro_key]);
+ $update = 1;
+ } else {
+ $this->debug_text("shift_acl(): ARO doesn't exist, can't remove it.");
+ }
+ }
+
+ }
+ }
+ }
+
+ if (is_array($aro_group_ids) AND count($aro_group_ids) > 0) {
+ $this->debug_text("shift_acl(): Removing ARO_GROUP_ID's");
+
+ while (list(,$aro_group_id) = @each($aro_group_ids)) {
+ $this->debug_text("shift_acl(): ARO Group ID: $aro_group_id");
+ $aro_group_key = array_search($aro_group_id, $acl_array['aro_groups']);
+
+ if ($aro_group_key !== FALSE) {
+ $this->debug_text("shift_acl(): Removing ARO Group. ($aro_group_key)");
+ unset($acl_array['aro_groups'][$aro_group_key]);
+ $update = 1;
+ } else {
+ $this->debug_text("shift_acl(): ARO Group doesn't exist, can't remove it.");
+ }
+ }
+ }
+
+ if (is_array($axo_array) AND count($axo_array) > 0) {
+ $this->debug_text("shift_acl(): Removing AXO's");
+
+ while (list($axo_section_value,$axo_value_array) = @each($axo_array)) {
+ foreach ($axo_value_array as $axo_value) {
+ $this->debug_text("shift_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value");
+ $axo_key = array_search($axo_value, $acl_array['axo'][$axo_section_value]);
+
+ if ($axo_key !== FALSE) {
+ $this->debug_text("shift_acl(): Removing AXO. ($axo_key)");
+ unset($acl_array['axo'][$axo_section_value][$axo_key]);
+ $update = 1;
+ } else {
+ $this->debug_text("shift_acl(): AXO doesn't exist, can't remove it.");
+ }
+ }
+ }
+ }
+
+ if (is_array($axo_group_ids) AND count($axo_group_ids) > 0) {
+ $this->debug_text("shift_acl(): Removing AXO_GROUP_ID's");
+
+ while (list(,$axo_group_id) = @each($axo_group_ids)) {
+ $this->debug_text("shift_acl(): AXO Group ID: $axo_group_id");
+ $axo_group_key = array_search($axo_group_id, $acl_array['axo_groups']);
+
+ if ($axo_group_key !== FALSE) {
+ $this->debug_text("shift_acl(): Removing AXO Group. ($axo_group_key)");
+ unset($acl_array['axo_groups'][$axo_group_key]);
+ $update = 1;
+ } else {
+ $this->debug_text("shift_acl(): AXO Group doesn't exist, can't remove it.");
+ }
+ }
+ }
+
+ if (is_array($aco_array) AND count($aco_array) > 0) {
+ $this->debug_text("shift_acl(): Removing ACO's");
+
+ while (list($aco_section_value,$aco_value_array) = @each($aco_array)) {
+ foreach ($aco_value_array as $aco_value) {
+ $this->debug_text("shift_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value");
+ $aco_key = array_search($aco_value, $acl_array['aco'][$aco_section_value]);
+
+ if ($aco_key !== FALSE) {
+ $this->debug_text("shift_acl(): Removing ACO. ($aco_key)");
+ unset($acl_array['aco'][$aco_section_value][$aco_key]);
+ $update = 1;
+ } else {
+ $this->debug_text("shift_acl(): ACO doesn't exist, can't remove it.");
+ }
+ }
+ }
+ }
+
+ if ($update == 1) {
+ //We know something was changed, so lets see if no ACO's or no ARO's are left assigned to this ACL, if so, delete the ACL completely.
+ //$this->showarray($acl_array);
+ $this->debug_text("shift_acl(): ACOs: ". $this->count_all($acl_array['aco']) ." AROs: ".$this->count_all($acl_array['aro'])."");
+
+ if ( $this->count_all($acl_array['aco']) == 0
+ OR ( $this->count_all($acl_array['aro']) == 0
+ AND ( $this->count_all($acl_array['axo']) == 0 OR $acl_array['axo'] == FALSE)
+ AND (count($acl_array['aro_groups']) == 0 OR $acl_array['aro_groups'] == FALSE)
+ AND (count($acl_array['axo_groups']) == 0 OR $acl_array['axo_groups'] == FALSE)
+ ) ) {
+ $this->debug_text("shift_acl(): No ACOs or ( AROs AND AXOs AND ARO Groups AND AXO Groups) left assigned to this ACL (ID: $acl_id), deleting ACL.");
+
+ return $this->del_acl($acl_id);
+ }
+
+ $this->debug_text("shift_acl(): Update flag set, updating ACL.");
+
+ return $this->edit_acl($acl_id, $acl_array['aco'], $acl_array['aro'], $acl_array['aro_groups'], $acl_array['axo'], $acl_array['axo_groups'], $acl_array['allow'], $acl_array['enabled'], $acl_array['return_value'], $acl_array['note']);
+ }
+
+ //Return true if everything is duplicate and no ACL id updated.
+ $this->debug_text("shift_acl(): Update flag not set, NOT updating ACL.");
+ return true;
+ }
+
+ /**
+ * get_acl()
+ *
+ * Grabs ACL data.
+ *
+ * @return bool FALSE if not found, or Associative Array with the following items:
+ *
+ * - 'aco' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * - 'aro' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * - 'axo' => Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * - 'aro_groups' => Array of Group IDs
+ * - 'axo_groups' => Array of Group IDs
+ * - 'acl_id' => int ACL ID #
+ * - 'allow' => int Allow flag
+ * - 'enabled' => int Enabled flag
+ * - 'return_value' => string Return Value
+ * - 'note' => string Note
+ *
+ * @param int ACL ID #
+ */
+ function get_acl($acl_id) {
+
+ $this->debug_text("get_acl(): ACL_ID: $acl_id");
+
+ if (empty($acl_id)) {
+ $this->debug_text("get_acl(): No ACL_ID specified! ACL_ID: $acl_id");
+ return false;
+ }
+
+ //Grab ACL information
+ $query = "select id, allow, enabled, return_value, note from ".$this->_db_table_prefix."acl where id = ".$acl_id."";
+ $acl_row = $this->db->GetRow($query);
+
+ // return false if not found
+ if (!$acl_row) {
+ $this->debug_text("get_acl(): No ACL found for that ID! ACL_ID: $acl_id");
+ return false;
+ }
+
+ list($retarr['acl_id'], $retarr['allow'], $retarr['enabled'], $retarr['return_value'], $retarr['note']) = $acl_row;
+
+ //Grab selected ACO's
+ $query = "select distinct a.section_value, a.value, c.name, b.name from ".$this->_db_table_prefix."aco_map a, ".$this->_db_table_prefix."aco b, ".$this->_db_table_prefix."aco_sections c
+ where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
+ $rs = $this->db->Execute($query);
+ $rows = $rs->GetRows();
+
+ $retarr['aco'] = array();
+ while (list(,$row) = @each($rows)) {
+ list($section_value, $value, $section, $aco) = $row;
+ $this->debug_text("Section Value: $section_value Value: $value Section: $section ACO: $aco");
+
+ $retarr['aco'][$section_value][] = $value;
+
+ }
+ //showarray($aco);
+
+ //Grab selected ARO's
+ $query = "select distinct a.section_value, a.value, c.name, b.name from ".$this->_db_table_prefix."aro_map a, ".$this->_db_table_prefix."aro b, ".$this->_db_table_prefix."aro_sections c
+ where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
+ $rs = $this->db->Execute($query);
+ $rows = $rs->GetRows();
+
+ $retarr['aro'] = array();
+ while (list(,$row) = @each($rows)) {
+ list($section_value, $value, $section, $aro) = $row;
+ $this->debug_text("Section Value: $section_value Value: $value Section: $section ARO: $aro");
+
+ $retarr['aro'][$section_value][] = $value;
+
+ }
+ //showarray($options_aro);
+
+ //Grab selected AXO's
+ $query = "select distinct a.section_value, a.value, c.name, b.name from ".$this->_db_table_prefix."axo_map a, ".$this->_db_table_prefix."axo b, ".$this->_db_table_prefix."axo_sections c
+ where ( a.section_value=b.section_value AND a.value = b.value) AND b.section_value=c.value AND a.acl_id = $acl_id";
+ $rs = $this->db->Execute($query);
+ $rows = $rs->GetRows();
+
+ $retarr['axo'] = array();
+ while (list(,$row) = @each($rows)) {
+ list($section_value, $value, $section, $axo) = $row;
+ $this->debug_text("Section Value: $section_value Value: $value Section: $section AXO: $axo");
+
+ $retarr['axo'][$section_value][] = $value;
+
+ }
+ //showarray($options_aro);
+
+ //Grab selected ARO groups.
+ $retarr['aro_groups'] = array();
+ $query = "select distinct group_id from ".$this->_db_table_prefix."aro_groups_map where acl_id = $acl_id";
+ $retarr['aro_groups'] = $this->db->GetCol($query);
+ //showarray($selected_groups);
+
+ //Grab selected AXO groups.
+ $retarr['axo_groups'] = array();
+ $query = "select distinct group_id from ".$this->_db_table_prefix."axo_groups_map where acl_id = $acl_id";
+ $retarr['axo_groups'] = $this->db->GetCol($query);
+ //showarray($selected_groups);
+
+ return $retarr;
+ }
+
+ /**
+ * is_conflicting_acl()
+ *
+ * Checks for conflicts when adding a specific ACL.
+ *
+ * @return bool Returns true if conflict is found.
+ *
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param array Array of ACL IDs to ignore from the result set.
+ *
+ */
+ function is_conflicting_acl($aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $ignore_acl_ids=NULL) {
+ //Check for potential conflicts. Ignore groups, as groups will almost always have "conflicting" ACLs.
+ //Thats part of inheritance.
+
+ if (!is_array($aco_array)) {
+ $this->debug_text('is_conflicting_acl(): Invalid ACO Array.');
+ return FALSE;
+ }
+
+ if (!is_array($aro_array)) {
+ $this->debug_text('is_conflicting_acl(): Invalid ARO Array.');
+ return FALSE;
+ }
+
+ $query = '
+ SELECT a.id
+ FROM '. $this->_db_table_prefix .'acl a
+ LEFT JOIN '. $this->_db_table_prefix .'aco_map ac ON ac.acl_id=a.id
+ LEFT JOIN '. $this->_db_table_prefix .'aro_map ar ON ar.acl_id=a.id
+ LEFT JOIN '. $this->_db_table_prefix .'axo_map ax ON ax.acl_id=a.id
+ LEFT JOIN '. $this->_db_table_prefix .'axo_groups_map axg ON axg.acl_id=a.id
+ LEFT JOIN '. $this->_db_table_prefix .'axo_groups xg ON xg.id=axg.group_id
+ ';
+
+ //ACO
+ foreach ($aco_array as $aco_section_value => $aco_value_array) {
+ $this->debug_text("is_conflicting_acl(): ACO Section Value: $aco_section_value ACO VALUE: $aco_value_array");
+ //showarray($aco_array);
+
+ if (!is_array($aco_value_array)) {
+ $this->debug_text('is_conflicting_acl(): Invalid Format for ACO Array item. Skipping...');
+ continue;
+ // return TRUE;
+ }
+ //Move the below line in to the LEFT JOIN above for PostgreSQL sake.
+ //'ac1' => 'ac.acl_id=a.id',
+ $where_query = array(
+ 'ac2' => '(ac.section_value='. $this->db->quote($aco_section_value) .' AND ac.value IN (\''. implode ('\',\'', $aco_value_array) .'\'))'
+ );
+
+ //ARO
+ foreach ($aro_array as $aro_section_value => $aro_value_array) {
+ $this->debug_text("is_conflicting_acl(): ARO Section Value: $aro_section_value ARO VALUE: $aro_value_array");
+
+ if (!is_array($aro_value_array))
+ {
+ $this->debug_text('is_conflicting_acl(): Invalid Format for ARO Array item. Skipping...');
+ continue;
+ // return TRUE;
+ }
+
+ $this->debug_text("is_conflicting_acl(): Search: ACO Section: $aco_section_value ACO Value: $aco_value_array ARO Section: $aro_section_value ARO Value: $aro_value_array");
+
+ //Move the below line in to the LEFT JOIN above for PostgreSQL sake.
+ //$where_query['ar1'] = 'ar.acl_id=a.id';
+ $where_query['ar2'] = '(ar.section_value='. $this->db->quote($aro_section_value) .' AND ar.value IN (\''. implode ('\',\'', $aro_value_array) .'\'))';
+
+ if (is_array($axo_array) AND count($axo_array) > 0) {
+ foreach ($axo_array as $axo_section_value => $axo_value_array) {
+ $this->debug_text("is_conflicting_acl(): AXO Section Value: $axo_section_value AXO VALUE: $axo_value_array");
+
+ if (!is_array($axo_value_array)) {
+ $this->debug_text('is_conflicting_acl(): Invalid Format for AXO Array item. Skipping...');
+ continue;
+ // return TRUE;
+ }
+
+ $this->debug_text("is_conflicting_acl(): Search: ACO Section: $aco_section_value ACO Value: $aco_value_array ARO Section: $aro_section_value ARO Value: $aro_value_array AXO Section: $axo_section_value AXO Value: $axo_value_array");
+
+ //$where_query['ax1'] = 'ax.acl_id=x.id';
+ $where_query['ax1'] = 'ax.acl_id=a.id';
+ $where_query['ax2'] = '(ax.section_value='. $this->db->quote($axo_section_value) .' AND ax.value IN (\''. implode ('\',\'', $axo_value_array) .'\'))';
+
+ $where = 'WHERE ' . implode(' AND ', $where_query);
+
+ $conflict_result = $this->db->GetCol($query . $where);
+
+ if (is_array($conflict_result) AND !empty($conflict_result)) {
+ // showarray($conflict_result);
+
+ if (is_array($ignore_acl_ids)) {
+ $conflict_result = array_diff($conflict_result, $ignore_acl_ids);
+ }
+
+ if (count($conflict_result) > 0) {
+ $conflicting_acls_str = implode(',', $conflict_result);
+ $this->debug_text("is_conflicting_acl(): Conflict FOUND!!! ACL_IDS: ($conflicting_acls_str)");
+ return TRUE;
+ }
+ }
+ }
+ } else {
+ $where_query['ax1'] = '(ax.section_value IS NULL AND ax.value IS NULL)';
+ $where_query['ax2'] = 'xg.name IS NULL';
+
+ $where = 'WHERE ' . implode(' AND ', $where_query);
+
+ $conflict_result = $this->db->GetCol($query . $where);
+
+ if (is_array($conflict_result) AND !empty($conflict_result)) {
+ // showarray($conflict_result);
+
+ if (is_array($ignore_acl_ids)) {
+ $conflict_result = array_diff($conflict_result, $ignore_acl_ids);
+ }
+
+ if (count($conflict_result) > 0) {
+ $conflicting_acls_str = implode(',', $conflict_result);
+ $this->debug_text("is_conflicting_acl(): Conflict FOUND!!! ACL_IDS: ($conflicting_acls_str)");
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ $this->debug_text('is_conflicting_acl(): No conflicting ACL found.');
+ return FALSE;
+ }
+
+ /**
+ * add_acl()
+ *
+ * Add's an ACL. ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
+ *
+ * @return bool Return ACL ID of new ACL if successful, FALSE otherewise.
+ *
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param int Allow flag
+ * @param int Enabled flag
+ * @param string Return Value
+ * @param string Note
+ * @param string ACL Section Value
+ * @param int ACL ID # Specific Request
+
+ */
+ function add_acl($aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $allow=1, $enabled=1, $return_value=NULL, $note=NULL, $section_value=NULL, $acl_id=FALSE ) {
+
+ $this->debug_text("add_acl():");
+
+ if (count($aco_array) == 0) {
+ $this->debug_text("Must select at least one Access Control Object");
+ return false;
+ }
+
+ if (count($aro_array) == 0 AND count($aro_group_ids) == 0) {
+ $this->debug_text("Must select at least one Access Request Object or Group");
+ return false;
+ }
+
+ if (empty($allow)) {
+ $allow=0;
+ }
+
+ if (empty($enabled)) {
+ $enabled=0;
+ }
+
+ if (!empty($section_value)
+ AND !$this->get_object_section_section_id(NULL, $section_value, 'ACL')) {
+ $this->debug_text("add_acl(): Section Value: $section_value DOES NOT exist in the database.");
+ return false;
+ }
+
+ //Unique the group arrays. Later one we unique ACO/ARO/AXO arrays.
+ if (is_array($aro_group_ids)) {
+ $aro_group_ids = array_unique($aro_group_ids);
+ }
+ if (is_array($axo_group_ids)) {
+ $axo_group_ids = array_unique($axo_group_ids);
+ }
+
+ //Check for conflicting ACLs.
+ if ($this->is_conflicting_acl($aco_array,$aro_array,$aro_group_ids,$axo_array,$axo_group_ids,array($acl_id))) {
+ $this->debug_text("add_acl(): Detected possible ACL conflict, not adding ACL!");
+ return false;
+ }
+
+ //Edit ACL if acl_id is set. This is simply if we're being called by edit_acl().
+ if ($this->get_acl($acl_id) == FALSE) {
+ if ( empty($section_value) ) {
+ $section_value='system';
+ if( !$this->get_object_section_section_id(NULL, $section_value, 'ACL') ) {
+ // Use the acl section with the lowest order value.
+ $acl_sections_table = $this->_db_table_prefix .'acl_sections';
+ $acl_section_order_value = $this->db->GetOne("SELECT min(order_value) from $acl_sections_table");
+
+ $query = "
+ SELECT value
+ FROM $acl_sections_table
+ WHERE order_value = $acl_section_order_value
+ ";
+ $section_value = $this->db->GetOne($query);
+
+ if ( empty($section_value) ) {
+ $this->debug_text("add_acl(): No valid acl section found.");
+ return false;
+ } else {
+ $this->debug_text("add_acl(): Using default section value: $section_value.");
+ }
+ }
+ }
+
+ //ACL not specified, so create acl_id
+ if (empty($acl_id)) {
+ //Create ACL row first, so we have the acl_id
+ $acl_id = $this->db->GenID($this->_db_table_prefix.'acl_seq',10);
+
+ //Double check the ACL ID was generated.
+ if (empty($acl_id)) {
+ $this->debug_text("add_acl(): ACL_ID generation failed!");
+ return false;
+ }
+ }
+
+ //Begin transaction _after_ GenID. Because on the first run, if GenID has to create the sequence,
+ //the transaction will fail.
+ $this->db->BeginTrans();
+
+ $query = 'INSERT INTO '.$this->_db_table_prefix.'acl (id,section_value,allow,enabled,return_value,note,updated_date) VALUES('. $acl_id .','. $this->db->quote($section_value) .','. $allow .','. $enabled .','. $this->db->quote($return_value) .', '. $this->db->quote($note) .','. time() .')';
+ $result = $this->db->Execute($query);
+ } else {
+ $section_sql = '';
+ if ( !empty($section_value) ) {
+ $section_sql = 'section_value='. $this->db->quote ($section_value) .',';
+ }
+
+ $this->db->BeginTrans();
+
+ //Update ACL row, and remove all mappings so they can be re-inserted.
+ $query = '
+ UPDATE '. $this->_db_table_prefix .'acl
+ SET ' . $section_sql . '
+ allow='. $allow .',
+ enabled='. $enabled .',
+ return_value='. $this->db->quote($return_value) .',
+ note='. $this->db->quote($note) .',
+ updated_date='. time() .'
+ WHERE id='. $acl_id;
+ $result = $this->db->Execute($query);
+
+ if ($result) {
+ $this->debug_text("Update completed without error, delete mappings...");
+ //Delete all mappings so they can be re-inserted.
+ foreach (array('aco_map', 'aro_map', 'axo_map', 'aro_groups_map', 'axo_groups_map') as $map) {
+ $query = 'DELETE FROM '. $this->_db_table_prefix . $map .' WHERE acl_id='. $acl_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs))
+ {
+ $this->debug_db('add_acl');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ if (!is_object($result)) {
+ $this->debug_db('add_acl');
+ $this->db->RollBackTrans();
+ return false;
+ }
+
+ $this->debug_text("Insert or Update completed without error, insert new mappings.");
+ // Insert ACO/ARO/AXO mappings
+ foreach (array('aco', 'aro', 'axo') as $map) {
+ $map_array = ${$map .'_array'};
+
+ if (!is_array ($map_array)) {
+ continue;
+ }
+
+ foreach ($map_array as $section_value => $value_array) {
+ $this->debug_text ('Insert: '. strtoupper($map) .' Section Value: '. $section_value .' '. strtoupper($map) .' VALUE: '. $value_array);
+ // $this->showarray ($aco_value_array);
+
+ if (!is_array($value_array)) {
+ $this->debug_text ('add_acl (): Invalid Format for '. strtoupper ($map) .' Array item. Skipping...');
+ continue;
+ // return true;
+ }
+
+ $value_array = array_unique($value_array);
+
+ foreach ($value_array as $value) {
+ $object_id = &$this->get_object_id($section_value, $value, $map);
+
+ if (empty($object_id))
+ {
+ $this->debug_text('add_acl(): '. strtoupper($map) . " Object Section Value: $section_value Value: $value DOES NOT exist in the database. Skipping...");
+ $this->db->RollBackTrans();
+ return false;
+ }
+
+ $query = 'INSERT INTO '. $this->_db_table_prefix . $map .'_map (acl_id,section_value,value) VALUES ('. $acl_id .', '. $this->db->quote($section_value) .', '. $this->db->quote($value) .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs))
+ {
+ $this->debug_db('add_acl');
+ $this->db->RollBackTrans();
+ return false;
+ }
+ }
+ }
+ }
+
+ // Insert ARO/AXO GROUP mappings
+ foreach (array('aro', 'axo') as $map) {
+ $map_group_ids = ${$map .'_group_ids'};
+
+ if (!is_array($map_group_ids)) {
+ continue;
+ }
+
+ foreach ($map_group_ids as $group_id) {
+ $this->debug_text ('Insert: '. strtoupper($map) .' GROUP ID: '. $group_id);
+
+ $group_data = &$this->get_group_data($group_id, $map);
+
+ if (empty($group_data)) {
+ $this->debug_text('add_acl(): '. strtoupper($map) . " Group: $group_id DOES NOT exist in the database. Skipping...");
+ $this->db->RollBackTrans();
+ return false;
+ }
+
+ $query = 'INSERT INTO '. $this->_db_table_prefix . $map .'_groups_map (acl_id,group_id) VALUES ('. $acl_id .', '. $group_id .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_acl');
+ $this->db->RollBackTrans();
+ return false;
+ }
+ }
+ }
+
+ $this->db->CommitTrans();
+
+ if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
+ //Expire all cache.
+ $this->Cache_Lite->clean('default');
+ }
+
+ //Return only the ID in the first row.
+ return $acl_id;
+ }
+
+ /**
+ * edit_acl()
+ *
+ * Edit's an ACL, ACO_IDS, ARO_IDS, GROUP_IDS must all be arrays.
+ *
+ * @return bool Return TRUE if successful, FALSE otherewise.
+ *
+ * @param int ACL ID # to edit
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ * @param array Array of Group IDs
+ * @param int Allow flag
+ * @param int Enabled flag
+ * @param string Return Value
+ * @param string Note
+ * @param string ACL Section Value
+ */
+ function edit_acl($acl_id, $aco_array, $aro_array, $aro_group_ids=NULL, $axo_array=NULL, $axo_group_ids=NULL, $allow=1, $enabled=1, $return_value=NULL, $note=NULL, $section_value=NULL) {
+
+ $this->debug_text("edit_acl():");
+
+ if (empty($acl_id) ) {
+ $this->debug_text("edit_acl(): Must specify a single ACL_ID to edit");
+ return false;
+ }
+ if (count($aco_array) == 0) {
+ $this->debug_text("edit_acl(): Must select at least one Access Control Object");
+ return false;
+ }
+
+ if (count($aro_array) == 0 AND count($aro_group_ids) == 0) {
+ $this->debug_text("edit_acl(): Must select at least one Access Request Object or Group");
+ return false;
+ }
+
+ if (empty($allow)) {
+ $allow=0;
+ }
+
+ if (empty($enabled)) {
+ $enabled=0;
+ }
+
+ //if ($this->add_acl($aco_array, $aro_array, $group_ids, $allow, $enabled, $acl_id)) {
+ if ($this->add_acl($aco_array, $aro_array, $aro_group_ids, $axo_array, $axo_group_ids, $allow, $enabled, $return_value, $note, $section_value, $acl_id)) {
+ return true;
+ } else {
+ $this->debug_text("edit_acl(): error in add_acl()");
+ return false;
+ }
+ }
+
+ /**
+ * del_acl()
+ *
+ * Deletes a given ACL
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise.
+ *
+ * @param int ACL ID # to delete
+ */
+ function del_acl($acl_id) {
+
+ $this->debug_text("del_acl(): ID: $acl_id");
+
+ if (empty($acl_id) ) {
+ $this->debug_text("del_acl(): ACL_ID ($acl_id) is empty, this is required");
+ return false;
+ }
+
+ $this->db->BeginTrans();
+
+ // Delete all mappings to the ACL first
+ foreach (array('aco_map', 'aro_map', 'axo_map', 'aro_groups_map', 'axo_groups_map') as $map) {
+ $query = 'DELETE FROM '. $this->_db_table_prefix . $map .' WHERE acl_id='. $acl_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('del_acl');
+ $this->db->RollBackTrans();
+ return false;
+ }
+ }
+
+ // Delete the ACL
+ $query = 'DELETE FROM '. $this->_db_table_prefix .'acl WHERE id='. $acl_id;
+ $this->debug_text('delete query: '. $query);
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('del_acl');
+ $this->db->RollBackTrans();
+ return false;
+ }
+
+ $this->debug_text("del_acl(): deleted ACL ID: $acl_id");
+ $this->db->CommitTrans();
+
+ if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
+ //Expire all cache.
+ $this->Cache_Lite->clean('default');
+ }
+
+ return TRUE;
+ }
+
+
+ /*
+ *
+ * Groups
+ *
+ */
+
+ /**
+ * sort_groups()
+ *
+ * Grabs all the groups from the database doing preliminary grouping by parent
+ *
+ * @return array Returns 2-Dimensional array: $array[<parent_id>][<group_id>] = <group_name>
+ *
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function sort_groups($group_type='ARO') {
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $table = $this->_db_table_prefix .'aro_groups';
+ break;
+ }
+
+ //Grab all groups from the database.
+ $query = 'SELECT id, parent_id, name FROM '. $table .' ORDER BY parent_id, name';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('sort_groups');
+ return false;
+ }
+
+ /*
+ * Save groups in an array sorted by parent. Should be make it easier for later on.
+ */
+ $sorted_groups = array();
+
+ while ($row = $rs->FetchRow()) {
+ $id = &$row[0];
+ $parent_id = &$row[1];
+ $name = &$row[2];
+
+ $sorted_groups[$parent_id][$id] = $name;
+ }
+
+ return $sorted_groups;
+ }
+
+ /**
+ * format_groups()
+ *
+ * Takes the array returned by sort_groups() and formats for human
+ * consumption. Recursively calls itself to produce the desired output.
+ *
+ * @return array Array of formatted text, ordered by group id, formatted according to $type
+ *
+ * @param array Output from gacl_api->sorted_groups($group_type)
+ * @param array Output type desired, either 'TEXT', 'HTML', or 'ARRAY'
+ * @param int Root of tree to produce
+ * @param int Current level of depth
+ * @param array Pass the current formatted groups object for appending via recursion.
+ */
+ function format_groups($sorted_groups, $type='TEXT', $root_id=0, $level=0, $formatted_groups=NULL) {
+ if ( !is_array ($sorted_groups) ) {
+ return FALSE;
+ }
+
+ if ( !is_array ($formatted_groups) ) {
+ $formatted_groups = array ();
+ }
+
+ //$this->showarray($formatted_groups);
+
+ //while (list($id,$name) = @each($sorted_groups[$root_id])) {
+ if (isset($sorted_groups[$root_id])) {
+ //$last_id = end( array_keys($sorted_groups[$root_id]));
+ //PHP5 compatibility
+ $keys = array_keys($sorted_groups[$root_id]);
+ $last_id = end($keys);
+ unset($keys);
+
+ foreach ($sorted_groups[$root_id] as $id => $name) {
+ switch (strtoupper($type)) {
+ case 'TEXT':
+ /*
+ * Formatting optimized for TEXT (combo box) output.
+ */
+
+ if ( is_numeric($level) ) {
+ $level = str_repeat('&nbsp;&nbsp; ', $level);
+ }
+
+ if ( strlen($level) >= 8 ) {
+ if ( $id == $last_id ) {
+ $spacing = substr($level, 0, -8) .'\'- ';
+ $level = substr($level, 0, -8) .'&nbsp;&nbsp; ';
+ } else {
+ $spacing = substr($level, 0, -8) .'|- ';
+ }
+ } else {
+ $spacing = $level;
+ }
+
+ $next = $level .'|&nbsp; ';
+ $text = $spacing.$name;
+ break;
+ case 'HTML':
+ /*
+ * Formatting optimized for HTML (tables) output.
+ */
+ $width= $level * 20;
+ $spacing = "<img src=\"s.gif\" width=\"$width\">";
+ $next = $level + 1;
+ $text = $spacing." ".$name;
+ break;
+ case 'ARRAY':
+ $next = $level;
+ $text = $name;
+ break;
+ default:
+ return FALSE;
+ }
+
+ $formatted_groups[$id] = $text;
+ /*
+ * Recurse if we can.
+ */
+
+ //if (isset($sorted_groups[$id]) AND count($sorted_groups[$id]) > 0) {
+ if (isset($sorted_groups[$id]) ) {
+ //$this->debug_text("format_groups(): Recursing! Level: $level");
+ $formatted_groups = $this->format_groups($sorted_groups, $type, $id, $next, $formatted_groups);
+ } else {
+ //$this->debug_text("format_groups(): Found last branch!");
+ }
+ }
+ }
+
+ //$this->debug_text("format_groups(): Returning final array.");
+
+ return $formatted_groups;
+ }
+
+ /**
+ * get_group_id()
+ *
+ * Gets the group_id given the name or value.
+ *
+ * Will only return one group id, so if there are duplicate names, it will return false.
+ *
+ * @return int Returns Group ID if found and Group ID is unique in database, otherwise, returns FALSE
+ *
+ * @param string Group Value
+ * @param string Group Name
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function get_group_id($value = NULL, $name = NULL, $group_type = 'ARO') {
+
+ $this->debug_text("get_group_id(): Value: $value, Name: $name, Type: $group_type" );
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $table = $this->_db_table_prefix .'aro_groups';
+ break;
+ }
+
+ $name = trim($name);
+ $value = trim($value);
+
+ if (empty($name) AND empty($value) ) {
+ $this->debug_text("get_group_id(): name and value, at least one is required");
+ return false;
+ }
+
+ $query = 'SELECT id FROM '. $table .' WHERE ';
+ if ( !empty($value) ) {
+ $query .= ' value='. $this->db->quote($value);
+ } else {
+ $query .= ' name='. $this->db->quote($name);
+ }
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_group_id');
+ return false;
+ }
+
+ $row_count = $rs->RecordCount();
+
+ if ($row_count > 1) {
+ $this->debug_text("get_group_id(): Returned $row_count rows, can only return one. Please make your names unique.");
+ return false;
+ }
+
+ if ($row_count == 0) {
+ $this->debug_text("get_group_id(): Returned $row_count rows");
+ return false;
+ }
+
+ $row = $rs->FetchRow();
+
+ //Return the ID.
+ return $row[0];
+ }
+
+ /**
+ * get_group_children()
+ *
+ * Gets a groups child IDs
+ *
+ * @return array Array of Child ID's of the referenced group
+ *
+ * @param int Group ID #
+ * @param int Group Type, either 'ARO' or 'AXO'
+ * @param string Either 'RECURSE' or 'NO_RECURSE', to recurse while fetching group children.
+ */
+ function get_group_children($group_id, $group_type = 'ARO', $recurse = 'NO_RECURSE') {
+ $this->debug_text("get_group_children(): Group_ID: $group_id Group Type: $group_type Recurse: $recurse");
+
+ switch (strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $group_type = 'aro';
+ $table = $this->_db_table_prefix .'aro_groups';
+ }
+
+ if (empty($group_id)) {
+ $this->debug_text("get_group_children(): ID ($group_id) is empty, this is required");
+ return FALSE;
+ }
+
+ $query = '
+ SELECT g1.id
+ FROM '. $table .' g1';
+
+ //FIXME-mikeb: Why is group_id in quotes?
+ switch (strtoupper($recurse)) {
+ case 'RECURSE':
+ $query .= '
+ LEFT JOIN '. $table .' g2 ON g2.lft<g1.lft AND g2.rgt>g1.rgt
+ WHERE g2.id='. $group_id;
+ break;
+ default:
+ $query .= '
+ WHERE g1.parent_id='. $group_id;
+ }
+
+ $query .= '
+ ORDER BY g1.value';
+
+ return $this->db->GetCol($query);
+ }
+
+ /**
+ * get_group_data()
+ *
+ * Gets the group data given the GROUP_ID.
+ *
+ * @return array Returns numerically indexed array with the following columns:
+ * - array[0] = (int) Group ID #
+ * - array[1] = (int) Parent Group ID #
+ * - array[2] = (string) Group Value
+ * - array[3] = (string) Group Name
+ * - array[4] = (int) lft MPTT Value
+ * - array[5] = (int) rgt MPTT Value
+ *
+ * @param int Group ID #
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function get_group_data($group_id, $group_type = 'ARO') {
+
+ $this->debug_text("get_group_data(): Group_ID: $group_id Group Type: $group_type");
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $group_type = 'aro';
+ $table = $this->_db_table_prefix .'aro_groups';
+ break;
+ }
+
+ if (empty($group_id) ) {
+ $this->debug_text("get_group_data(): ID ($group_id) is empty, this is required");
+ return false;
+ }
+
+ $query = 'SELECT id, parent_id, value, name, lft, rgt FROM '. $table .' WHERE id='. $group_id;
+ //$rs = $this->db->Execute($query);
+ $row = $this->db->GetRow($query);
+
+ if ($row) {
+ return $row;
+ }
+
+ $this->debug_text("get_object_data(): Group does not exist.");
+ return false;
+ }
+
+ /**
+ * get_group_parent_id()
+ *
+ * Grabs the parent_id of a given group
+ *
+ * @return int Parent ID of the Group
+ *
+ * @param int Group ID #
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function get_group_parent_id($id, $group_type='ARO') {
+
+ $this->debug_text("get_group_parent_id(): ID: $id Group Type: $group_type");
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $table = $this->_db_table_prefix .'aro_groups';
+ break;
+ }
+
+ if (empty($id) ) {
+ $this->debug_text("get_group_parent_id(): ID ($id) is empty, this is required");
+ return false;
+ }
+
+ $query = 'SELECT parent_id FROM '. $table .' WHERE id='. $id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_group_parent_id');
+ return false;
+ }
+
+ $row_count = $rs->RecordCount();
+
+ if ($row_count > 1) {
+ $this->debug_text("get_group_parent_id(): Returned $row_count rows, can only return one. Please make your names unique.");
+ return false;
+ }
+
+ if ($row_count == 0) {
+ $this->debug_text("get_group_parent_id(): Returned $row_count rows");
+ return false;
+ }
+
+ $row = $rs->FetchRow();
+
+ //Return the ID.
+ return $row[0];
+ }
+
+
+ /**
+ * get_root_group_id ()
+ *
+ * Grabs the id of the root group for the specified tree
+ *
+ * @return int Root Group ID #
+ *
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function get_root_group_id($group_type='ARO') {
+
+ $this->debug_text('get_root_group_id(): Group Type: '. $group_type);
+
+ switch (strtolower($group_type)) {
+ case 'axo':
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ case 'aro':
+ $table = $this->_db_table_prefix .'aro_groups';
+ break;
+ default:
+ $this->debug_text('get_root_group_id(): Invalid Group Type: '. $group_type);
+ return FALSE;
+ }
+
+ $query = 'SELECT id FROM '. $table .' WHERE parent_id=0';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_root_group_id');
+ return FALSE;
+ }
+
+ $row_count = $rs->RecordCount();
+
+ switch ($row_count) {
+ case 1:
+ $row = $rs->FetchRow();
+ // Return the ID.
+ return $row[0];
+ case 0:
+ $this->debug_text('get_root_group_id(): Returned 0 rows, you do not have a root group defined yet.');
+ return FALSE;
+ }
+
+ $this->debug_text('get_root_group_id(): Returned '. $row_count .' rows, can only return one. Your tree is very broken.');
+ return FALSE;
+ }
+
+ /*======================================================================*\
+ Function: map_path_to_root()
+ Purpose: Maps a unique path to root to a specific group. Each group can only have
+ one path to root.
+ \*======================================================================*/
+ /** REMOVED **/
+ /*======================================================================*\
+ Function: put_path_to_root()
+ Purpose: Writes the unique path to root to the database. There should really only be
+ one path to root for each level "deep" the groups go. If the groups are branched
+ 10 levels deep, there should only be 10 unique path to roots. These of course
+ overlap each other more and more the closer to the root/trunk they get.
+ \*======================================================================*/
+ /** REMOVED **/
+ /*======================================================================*\
+ Function: clean_path_to_root()
+ Purpose: Cleans up any paths that are not being used.
+ \*======================================================================*/
+ /** REMOVED **/
+ /*======================================================================*\
+ Function: get_path_to_root()
+ Purpose: Generates the path to root for a given group.
+ \*======================================================================*/
+ /** REMOVED **/
+
+ /**
+ * add_group()
+ *
+ * Inserts a group, defaults to be on the "root" branch.
+ *
+ * Since v3.3.x you can only create one group with Parent_ID=0
+ * So, its a good idea to create a "Virtual Root" group with Parent_ID=0
+ * Then assign other groups to that.
+ *
+ * @return int New Group ID # if successful, FALSE if otherwise.
+ *
+ * @param string Group Value
+ * @param string Group Name
+ * @param int Parent Group ID #
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function add_group($value, $name, $parent_id=0, $group_type='ARO') {
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $group_type = 'aro';
+ $table = $this->_db_table_prefix .'aro_groups';
+ break;
+ }
+
+ $this->debug_text("add_group(): Name: $name Value: $value Parent ID: $parent_id Group Type: $group_type");
+
+ $name = trim($name);
+ $value = trim($value);
+
+ if ( $name == '' ) {
+ $this->debug_text("add_group(): name ($name) OR parent id ($parent_id) is empty, this is required");
+ return false;
+ }
+
+ //This has to be outside the transaction, because the first time it is run, it will say the sequence
+ //doesn't exist. Then try to create it, but the transaction will already by aborted by then.
+ $insert_id = $this->db->GenID($this->_db_table_prefix.$group_type.'_groups_id_seq',10);
+ if ( $value === '' ) {
+ $value = $insert_id;
+ }
+
+ $this->db->BeginTrans();
+
+ // special case for root group
+ if ($parent_id == 0) {
+ // check a root group is not already defined
+ $query = 'SELECT id FROM '. $table .' WHERE parent_id=0';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_group');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+
+ if ($rs->RowCount() > 0) {
+ $this->debug_text('add_group (): A root group already exists.');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+
+ $parent_lft = 0;
+ $parent_rgt = 1;
+ } else {
+ if (empty($parent_id)) {
+ $this->debug_text("add_group (): parent id ($parent_id) is empty, this is required");
+ $this->db->RollbackTrans();
+ return FALSE;
+ }
+
+ // grab parent details from database
+ $query = 'SELECT id, lft, rgt FROM '. $table .' WHERE id='. $parent_id;
+ $row = $this->db->GetRow($query);
+
+ if (!is_array($row)) {
+ $this->debug_db('add_group');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+
+ if (empty($row)) {
+ $this->debug_text('add_group (): Parent ID: '. $parent_id .' not found.');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+
+ $parent_lft = &$row[1];
+ $parent_rgt = &$row[2];
+
+ // make room for the new group
+ $query = 'UPDATE '. $table .' SET rgt=rgt+2 WHERE rgt>='. $parent_rgt;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_group');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+
+ $query = 'UPDATE '. $table .' SET lft=lft+2 WHERE lft>'. $parent_rgt;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_group');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+ }
+
+ $query = 'INSERT INTO '. $table .' (id,parent_id,name,value,lft,rgt) VALUES ('. $insert_id .','. $parent_id .','. $this->db->quote($name) .','. $this->db->quote($value) .','. $parent_rgt .','. ($parent_rgt + 1) .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_group');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+
+ $this->db->CommitTrans();
+
+ $this->debug_text('add_group (): Added group as ID: '. $insert_id);
+ return $insert_id;
+ }
+
+ /**
+ * get_group_objects()
+ *
+ * Gets all objects assigned to a group.
+ *
+ * If $option == 'RECURSE' it will get all objects in child groups as well.
+ * defaults to omit child groups.
+ *
+ * @return array Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+
+ *
+ * @param int Group ID #
+ * @param string Group Type, either 'ARO' or 'AXO'
+ * @param string Option, either 'RECURSE' or 'NO_RECURSE'
+ */
+ function get_group_objects($group_id, $group_type='ARO', $option='NO_RECURSE') {
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $object_table = $this->_db_table_prefix .'axo';
+ $group_table = $this->_db_table_prefix .'axo_groups';
+ $map_table = $this->_db_table_prefix .'groups_axo_map';
+ break;
+ default:
+ $group_type = 'aro';
+ $object_table = $this->_db_table_prefix .'aro';
+ $group_table = $this->_db_table_prefix .'aro_groups';
+ $map_table = $this->_db_table_prefix .'groups_aro_map';
+ break;
+ }
+
+ $this->debug_text("get_group_objects(): Group ID: $group_id");
+
+ if (empty($group_id)) {
+ $this->debug_text("get_group_objects(): Group ID: ($group_id) is empty, this is required");
+ return false;
+ }
+
+ $query = '
+ SELECT o.section_value,o.value';
+
+ if ($option == 'RECURSE') {
+ $query .= '
+ FROM '. $group_table .' g2
+ JOIN '. $group_table .' g1 ON g1.lft>=g2.lft AND g1.rgt<=g2.rgt
+ JOIN '. $map_table .' gm ON gm.group_id=g1.id
+ JOIN '. $object_table .' o ON o.id=gm.'. $group_type .'_id
+ WHERE g2.id='. $group_id;
+ } else {
+ $query .= '
+ FROM '. $map_table .' gm
+ JOIN '. $object_table .' o ON o.id=gm.'. $group_type .'_id
+ WHERE gm.group_id='. $group_id;
+ }
+
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_group_objects');
+ return false;
+ }
+
+ $this->debug_text("get_group_objects(): Got group objects, formatting array.");
+
+ $retarr = array();
+
+ //format return array.
+ while ($row = $rs->FetchRow()) {
+ $section = &$row[0];
+ $value = &$row[1];
+
+ $retarr[$section][] = $value;
+ }
+
+ return $retarr;
+ }
+
+ /**
+ * add_group_object()
+ *
+ * Assigns an Object to a group
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise.
+ *
+ * @param int Group ID #
+ * @param string Object Section Value
+ * @param string Object Value
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function add_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $table = $this->_db_table_prefix .'groups_axo_map';
+ $object_table = $this->_db_table_prefix .'axo';
+ $group_table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $group_type = 'aro';
+ $table = $this->_db_table_prefix .'groups_aro_map';
+ $object_table = $this->_db_table_prefix .'aro';
+ $group_table = $this->_db_table_prefix .'aro_groups';
+ break;
+ }
+
+ $this->debug_text("add_group_object(): Group ID: $group_id Section Value: $object_section_value Value: $object_value Group Type: $group_type");
+
+ $object_section_value = trim($object_section_value);
+ $object_value = trim($object_value);
+
+ if (empty($group_id) OR empty($object_value) OR empty($object_section_value)) {
+ $this->debug_text("add_group_object(): Group ID: ($group_id) OR Value ($object_value) OR Section value ($object_section_value) is empty, this is required");
+ return false;
+ }
+
+ // test to see if object & group exist and if object is already a member
+ $query = '
+ SELECT o.id AS id,g.id AS group_id,gm.group_id AS member
+ FROM '. $object_table .' o
+ LEFT JOIN '. $group_table .' g ON g.id='. $group_id .'
+ LEFT JOIN '. $table .' gm ON (gm.'. $group_type .'_id=o.id AND gm.group_id=g.id)
+ WHERE (o.section_value='. $this->db->quote($object_section_value) .' AND o.value='. $this->db->quote($object_value) .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_group_object');
+ return FALSE;
+ }
+
+ if ($rs->RecordCount() != 1) {
+ $this->debug_text('add_group_object(): Value ('. $object_value .') OR Section value ('. $object_section_value .') is invalid. Does this object exist?');
+ return FALSE;
+ }
+
+ $row = $rs->FetchRow();
+
+ if ($row[1] != $group_id) {
+ $this->debug_text('add_group_object(): Group ID ('. $group_id .') is invalid. Does this group exist?');
+ return FALSE;
+ }
+
+ //Group_ID == Member
+ if ($row[1] == $row[2]) {
+ $this->debug_text('add_group_object(): Object: ('. $object_section_value .' -> '. $object_value .') is already a member of Group: ('. $group_id .')');
+ //Object is already assigned to group. Return true.
+ return TRUE;
+ }
+
+ $object_id = $row[0];
+
+ $query = 'INSERT INTO '. $table .' (group_id,'. $group_type .'_id) VALUES ('. $group_id .','. $object_id .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_group_object');
+ return FALSE;
+ }
+
+ $this->debug_text('add_group_object(): Added Object: '. $object_id .' to Group ID: '. $group_id);
+
+ if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
+ //Expire all cache.
+ $this->Cache_Lite->clean('default');
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * del_group_object()
+ *
+ * Removes an Object from a group.
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise
+ *
+ * @param int Group ID #
+ * @param string Object Section Value
+ * @param string Object Value
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function del_group_object($group_id, $object_section_value, $object_value, $group_type='ARO') {
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $table = $this->_db_table_prefix .'groups_axo_map';
+ break;
+ default:
+ $group_type = 'aro';
+ $table = $this->_db_table_prefix .'groups_aro_map';
+ break;
+ }
+
+ $this->debug_text("del_group_object(): Group ID: $group_id Section value: $object_section_value Value: $object_value");
+
+ $object_section_value = trim($object_section_value);
+ $object_value = trim($object_value);
+
+ if (empty($group_id) OR empty($object_value) OR empty($object_section_value)) {
+ $this->debug_text("del_group_object(): Group ID: ($group_id) OR Section value: $object_section_value OR Value ($object_value) is empty, this is required");
+ return false;
+ }
+
+ if (!$object_id = $this->get_object_id($object_section_value, $object_value, $group_type)) {
+ $this->debug_text ("del_group_object (): Group ID ($group_id) OR Value ($object_value) OR Section value ($object_section_value) is invalid. Does this object exist?");
+ return FALSE;
+ }
+
+ $query = 'DELETE FROM '. $table .' WHERE group_id='. $group_id .' AND '. $group_type .'_id='. $object_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('del_group_object');
+ return false;
+ }
+
+ $this->debug_text("del_group_object(): Deleted Value: $object_value to Group ID: $group_id assignment");
+
+ if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
+ //Expire all cache.
+ $this->Cache_Lite->clean('default');
+ }
+
+ return true;
+ }
+
+ /**
+ * edit_group()
+ *
+ * Edits a group
+ *
+ * @returns bool Returns TRUE if successful, FALSE otherwise
+ *
+ * @param int Group ID #
+ * @param string Group Value
+ * @param string Group Name
+ * @param int Parent ID #
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function edit_group($group_id, $value=NULL, $name=NULL, $parent_id=NULL, $group_type='ARO') {
+ $this->debug_text("edit_group(): ID: $group_id Name: $name Value: $value Parent ID: $parent_id Group Type: $group_type");
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $group_type = 'aro';
+ $table = $this->_db_table_prefix .'aro_groups';
+ break;
+ }
+
+ if (empty($group_id) ) {
+ $this->debug_text('edit_group(): Group ID ('. $group_id .') is empty, this is required');
+ return FALSE;
+ }
+
+ if ( !is_array($curr = $this->get_group_data($group_id, $group_type)) ) {
+ $this->debug_text('edit_group(): Invalid Group ID: '. $group_id);
+ return FALSE;
+ }
+
+ $name = trim($name);
+
+ // don't set name if it is unchanged
+ if ($name == $curr[3]) {
+ unset($name);
+ }
+
+ // don't set parent_id if it is unchanged
+ if ($parent_id == $curr[1]) {
+ unset($parent_id);
+ }
+
+ if (!empty($parent_id)) {
+ if ($group_id == $parent_id) {
+ $this->debug_text('edit_group(): Groups can\'t be a parent to themselves. Incest is bad. ;)');
+ return FALSE;
+ }
+
+ //Make sure we don't re-parent to our own children.
+ //Grab all children of this group_id.
+ $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
+ if (is_array($children_ids)) {
+ if (@in_array($parent_id, $children_ids) ) {
+ $this->debug_text('edit_group(): Groups can\'t be re-parented to their own children, this would be incestuous!');
+ return FALSE;
+ }
+ }
+ unset($children_ids);
+
+ // make sure parent exists
+ if (!$this->get_group_data($parent_id, $group_type)) {
+ $this->debug_text('edit_group(): Parent Group ('. $parent_id .') doesn\'t exist');
+ return FALSE;
+ }
+ }
+
+ $set = array();
+
+ // update name if it is specified.
+ if (!empty($name)) {
+ $set[] = 'name='. $this->db->quote($name);
+ }
+
+ // update parent_id if it is specified.
+ if (!empty($parent_id)) {
+ $set[] = 'parent_id='. $parent_id;
+ }
+
+ // update value if it is specified.
+ if (!empty($value)) {
+ $set[] = 'value='. $this->db->quote($value);
+ }
+
+ if (empty($set)) {
+ $this->debug_text('edit_group(): Nothing to update.');
+ return FALSE;
+ }
+
+ $this->db->BeginTrans();
+
+ $query = 'UPDATE '. $table .' SET '. implode(',', $set) .' WHERE id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('edit_group');
+ $this->db->RollbackTrans();
+ return FALSE;
+ }
+
+ $this->debug_text('edit_group(): Modified group ID: '. $group_id);
+
+ // rebuild group tree if parent_id has changed
+ if (!empty($parent_id)) {
+ if (!$this->_rebuild_tree($table, $this->get_root_group_id($group_type))) {
+ $this->db->RollbackTrans();
+ return FALSE;
+ }
+ }
+
+ $this->db->CommitTrans();
+
+ if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
+ // Expire all cache.
+ $this->Cache_Lite->clean('default');
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * rebuild_tree ()
+ *
+ * rebuilds the group tree for the given type
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise
+ *
+ * @param string Group Type, either 'ARO' or 'AXO'
+ * @param int Group ID #
+ * @param int Left value of Group
+ */
+ function rebuild_tree($group_type = 'ARO', $group_id = NULL, $left = 1) {
+ $this->debug_text("rebuild_tree(): Group Type: $group_type Group ID: $group_id Left: $left");
+
+ switch (strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $table = $this->_db_table_prefix .'axo_groups';
+ break;
+ default:
+ $group_type = 'aro';
+ $table = $this->_db_table_prefix .'aro_groups';
+ break;
+ }
+
+ if (!isset($group_id)) {
+ if ($group_id = $this->get_root_group_id($group_type)) {
+ $left = 1;
+ $this->debug_text('rebuild_tree(): No Group ID Specified, using Root Group ID: '. $group_id);
+ } else {
+ $this->debug_text('rebuild_tree(): A Root group could not be found, are there any groups defined?');
+ return FALSE;
+ }
+ }
+
+ $this->db->BeginTrans();
+ $rebuilt = $this->_rebuild_tree($table, $group_id, $left);
+
+ if ($rebuilt === FALSE) {
+ $this->debug_text('rebuild_tree(): Error rebuilding tree!');
+ $this->db->RollBackTrans();
+ return FALSE;
+ }
+
+ $this->db->CommitTrans();
+ $this->debug_text('rebuild_tree(): Tree rebuilt.');
+ return TRUE;
+ }
+ /**
+ * _rebuild_tree ()
+ *
+ * Utility recursive function called by rebuild_tree()
+ *
+ * @return int Returns right value of this node + 1
+ *
+ * @param string Table name of group type
+ * @param int Group ID #
+ * @param int Left value of Group
+ */
+ function _rebuild_tree($table, $group_id, $left = 1) {
+ $this->debug_text("_rebuild_tree(): Table: $table Group ID: $group_id Left: $left");
+
+ // get all children of this node
+ $query = 'SELECT id FROM '. $table .' WHERE parent_id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('_rebuild_tree');
+ return FALSE;
+ }
+
+ // the right value of this node is the left value + 1
+ $right = $left + 1;
+
+ while ($row = $rs->FetchRow()) {
+ // recursive execution of this function for each
+ // child of this node
+ // $right is the current right value, which is
+ // incremented by the rebuild_tree function
+ $right = $this->_rebuild_tree($table, $row[0], $right);
+
+ if ($right === FALSE) {
+ return FALSE;
+ }
+ }
+
+ // we've got the left value, and now that we've processed
+ // the children of this node we also know the right value
+ $query = 'UPDATE '. $table .' SET lft='. $left .', rgt='. $right .' WHERE id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('_rebuild_tree');
+ return FALSE;
+ }
+
+ // return the right value of this node + 1
+ return $right + 1;
+ }
+
+ /**
+ * del_group()
+ *
+ * deletes a given group
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise.
+ *
+ * @param int Group ID #
+ * @param bool If TRUE, child groups of this group will be reparented to the current group's parent.
+ * @param string Group Type, either 'ARO' or 'AXO'
+ */
+ function del_group($group_id, $reparent_children=TRUE, $group_type='ARO') {
+
+ switch(strtolower(trim($group_type))) {
+ case 'axo':
+ $group_type = 'axo';
+ $table = $this->_db_table_prefix .'axo_groups';
+ $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
+ $groups_object_map_table = $this->_db_table_prefix .'groups_axo_map';
+ break;
+ default:
+ $group_type = 'aro';
+ $table = $this->_db_table_prefix .'aro_groups';
+ $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
+ $groups_object_map_table = $this->_db_table_prefix .'groups_aro_map';
+ break;
+ }
+
+ $this->debug_text("del_group(): ID: $group_id Reparent Children: $reparent_children Group Type: $group_type");
+
+ if (empty($group_id) ) {
+ $this->debug_text("del_group(): Group ID ($group_id) is empty, this is required");
+ return false;
+ }
+
+ // Get details of this group
+ $query = 'SELECT id, parent_id, name, lft, rgt FROM '. $table .' WHERE id='. $group_id;
+ $group_details = $this->db->GetRow($query);
+
+ if (!is_array($group_details)) {
+ $this->debug_db('del_group');
+ return false;
+ }
+
+ $parent_id = $group_details[1];
+
+ $left = $group_details[3];
+ $right = $group_details[4];
+
+ $this->db->BeginTrans();
+
+ // grab list of all children
+ $children_ids = $this->get_group_children($group_id, $group_type, 'RECURSE');
+
+ // prevent deletion of root group & reparent of children if it has more than one immediate child
+ if ($parent_id == 0) {
+ $query = 'SELECT count(*) FROM '. $table .' WHERE parent_id='. $group_id;
+ $child_count = $this->db->GetOne($query);
+
+ if (($child_count > 1) AND $reparent_children) {
+ $this->debug_text ('del_group (): You cannot delete the root group and reparent children, this would create multiple root groups.');
+ $this->db->RollbackTrans();
+ return FALSE;
+ }
+ }
+
+ $success = FALSE;
+
+ /*
+ * Handle children here.
+ */
+ switch (TRUE) {
+ // there are no child groups, just delete group
+ case !is_array($children_ids):
+ case count($children_ids) == 0:
+ // remove acl maps
+ $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // remove group object maps
+ $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // remove group
+ $query = 'DELETE FROM '. $table .' WHERE id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // move all groups right of deleted group left by width of deleted group
+ $query = 'UPDATE '. $table .' SET lft=lft-'. ($right-$left+1) .' WHERE lft>'. $right;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ $query = 'UPDATE '. $table .' SET rgt=rgt-'. ($right-$left+1) .' WHERE rgt>'. $right;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ $success = TRUE;
+ break;
+ case $reparent_children == TRUE:
+ // remove acl maps
+ $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // remove group object maps
+ $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // remove group
+ $query = 'DELETE FROM '. $table .' WHERE id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // set parent of immediate children to parent group
+ $query = 'UPDATE '. $table .' SET parent_id='. $parent_id .' WHERE parent_id='. $group_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // move all children left by 1
+ $query = 'UPDATE '. $table .' SET lft=lft-1, rgt=rgt-1 WHERE lft>'. $left .' AND rgt<'. $right;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // move all groups right of deleted group left by 2
+ $query = 'UPDATE '. $table .' SET lft=lft-2 WHERE lft>'. $right;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ $query = 'UPDATE '. $table .' SET rgt=rgt-2 WHERE rgt>'. $right;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ $success = TRUE;
+ break;
+ default:
+ // make list of group and all children
+ $group_ids = $children_ids;
+ $group_ids[] = $group_id;
+
+ // remove acl maps
+ $query = 'DELETE FROM '. $groups_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // remove group object maps
+ $query = 'DELETE FROM '. $groups_object_map_table .' WHERE group_id IN ('. implode (',', $group_ids) .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // remove groups
+ $query = 'DELETE FROM '. $table .' WHERE id IN ('. implode (',', $group_ids) .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ // move all groups right of deleted group left by width of deleted group
+ $query = 'UPDATE '. $table .' SET lft=lft-'. ($right - $left + 1) .' WHERE lft>'. $right;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ $query = 'UPDATE '. $table .' SET rgt=rgt-'. ($right - $left + 1) .' WHERE rgt>'. $right;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ break;
+ }
+
+ $success = TRUE;
+ }
+
+ // if the delete failed, rollback the trans and return false
+ if (!$success) {
+
+ $this->debug_db('del_group');
+ $this->db->RollBackTrans();
+ return false;
+ }
+
+ $this->debug_text("del_group(): deleted group ID: $group_id");
+ $this->db->CommitTrans();
+
+ if ($this->_caching == TRUE AND $this->_force_cache_expire == TRUE) {
+ //Expire all cache.
+ $this->Cache_Lite->clean('default');
+ }
+
+ return true;
+
+ }
+
+
+ /*
+ *
+ * Objects (ACO/ARO/AXO)
+ *
+ */
+
+ /**
+ * get_object()
+ *
+ * Grabs all Objects's in the database, or specific to a section_value
+ *
+ * @return ADORecordSet Returns recordset directly, with object ID only selected:
+ *
+ * @param string Filter to this section value
+ * @param int Returns hidden objects if 1, leaves them out otherwise.
+ * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
+ */
+ function get_object($section_value = null, $return_hidden=1, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ break;
+ case 'acl':
+ $object_type = 'acl';
+ $table = $this->_db_table_prefix .'acl';
+ break;
+ default:
+ $this->debug_text('get_object(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("get_object(): Section Value: $section_value Object Type: $object_type");
+
+ $query = 'SELECT id FROM '. $table;
+
+ $where = array();
+
+ if (!empty($section_value)) {
+ $where[] = 'section_value='. $this->db->quote($section_value);
+ }
+
+ if ($return_hidden==0 AND $object_type != 'acl') {
+ $where[] = 'hidden=0';
+ }
+
+ if (!empty($where)) {
+ $query .= ' WHERE '. implode(' AND ', $where);
+ }
+
+ $rs = $this->db->GetCol($query);
+
+ if (!is_array($rs)) {
+ $this->debug_db('get_object');
+ return false;
+ }
+
+ // Return Object IDs
+ return $rs;
+ }
+ /**
+ * get_ungrouped_objects()
+ *
+ * Grabs ID's of all Objects (ARO's and AXO's only) in the database not assigned to a Group.
+ *
+ * This function is useful for applications that synchronize user databases with an outside source.
+ * If syncrhonization doesn't automatically place users in an appropriate group, this function can
+ * quickly identify them so that they can be assigned to the correct group.
+ *
+ * @return array Returns an array of object ID's
+ *
+ * @param int Returns hidden objects if 1, does not if 0.
+ * @param string Object Type, either 'ARO' or 'AXO' (groupable types)
+ */
+
+ function get_ungrouped_objects($return_hidden=1, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ break;
+ default:
+ $this->debug_text('get_ungrouped_objects(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("get_ungrouped_objects(): Object Type: $object_type");
+
+ $query = 'SELECT id FROM '. $table. ' a
+ LEFT JOIN ' . $this->_db_table_prefix. 'groups_'.$object_type.'_map b ON a.id = b.'. $object_type .'_id';
+
+ $where = array();
+ $where[] = 'b.group_id IS NULL';
+
+ if ($return_hidden==0) {
+ $where[] = 'a.hidden=0';
+ }
+
+ if (!empty($where)) {
+ $query .= ' WHERE '. implode(' AND ', $where);
+ }
+
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_ungrouped_objects');
+ return false;
+ }
+
+ while(!$rs->EOF) {
+ $retarr[] = $rs->fields[0];
+ $rs->MoveNext();
+ }
+
+ // Return Array of object IDS
+ return $retarr;
+ }
+
+
+ /**
+ * get_objects ()
+ *
+ * Grabs all Objects in the database, or specific to a section_value
+ *
+ * @return array Returns objects in format suitable for add_acl and is_conflicting_acl
+ * - i.e. Associative array, item={Section Value}, key={Array of Object Values} i.e. ["<Section Value>" => ["<Value 1>", "<Value 2>", "<Value 3>"], ...]
+ *
+ * @param string Filter for section value
+ * @param int Returns hidden objects if 1, does not if 0
+ * @param string Object Type, either 'ACO', 'ARO', 'AXO'
+ */
+ function get_objects($section_value = NULL, $return_hidden = 1, $object_type = NULL) {
+ switch (strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ break;
+ default:
+ $this->debug_text('get_objects(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("get_objects(): Section Value: $section_value Object Type: $object_type");
+
+ $query = 'SELECT section_value,value FROM '. $table;
+
+ $where = array();
+
+ if (!empty($section_value)) {
+ $where[] = 'section_value='. $this->db->quote($section_value);
+ }
+
+ if ($return_hidden==0) {
+ $where[] = 'hidden=0';
+ }
+
+ if (!empty($where)) {
+ $query .= ' WHERE '. implode(' AND ', $where);
+ }
+
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_objects');
+ return FALSE;
+ }
+
+ $retarr = array();
+
+ while ($row = $rs->FetchRow()) {
+ $retarr[$row[0]][] = $row[1];
+ }
+
+ // Return objects
+ return $retarr;
+ }
+
+ /**
+ * get_object_data()
+ *
+ * Gets all data pertaining to a specific Object.
+ *
+ * @return array Returns 2-Dimensional array of rows with columns = ( section_value, value, order_value, name, hidden )
+ *
+ * @param int Object ID #
+ * @param string Object Type, either 'ACO', 'ARO', 'AXO'
+ */
+ function get_object_data($object_id, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ break;
+ default:
+ $this->debug_text('get_object_data(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("get_object_data(): Object ID: $object_id Object Type: $object_type");
+
+ if (empty($object_id) ) {
+ $this->debug_text("get_object_data(): Object ID ($object_id) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("get_object_data(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ $query = 'SELECT section_value,value,order_value,name,hidden FROM '. $table .' WHERE id='. $object_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_object_data');
+ return false;
+ }
+
+ if ($rs->RecordCount() < 1) {
+ $this->debug_text('get_object_data(): Returned '. $row_count .' rows');
+ return FALSE;
+ }
+
+ // Return all objects
+ return $rs->GetRows();
+ }
+
+ /**
+ * get_object_id()
+ *
+ * Gets the object_id given the section_value AND value of the object.
+ *
+ * @return int Object ID #
+ *
+ * @param string Object Section Value
+ * @param string Object Value
+ * @param string Object Type, either 'ACO', 'ARO', 'AXO'
+ */
+ function get_object_id($section_value, $value, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ break;
+ default:
+ $this->debug_text('get_object_id(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("get_object_id(): Section Value: $section_value Value: $value Object Type: $object_type");
+
+ $section_value = trim($section_value);
+ $value = trim($value);
+
+ if (empty($section_value) AND empty($value) ) {
+ $this->debug_text("get_object_id(): Section Value ($value) AND value ($value) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("get_object_id(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ $query = 'SELECT id FROM '. $table .' WHERE section_value='. $this->db->quote($section_value) .' AND value='. $this->db->quote($value);
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_object_id');
+ return false;
+ }
+
+ $row_count = $rs->RecordCount();
+
+ if ($row_count > 1) {
+ $this->debug_text("get_object_id(): Returned $row_count rows, can only return one. This should never happen, the database may be missing a unique key.");
+ return false;
+ }
+
+ if ($row_count == 0) {
+ $this->debug_text("get_object_id(): Returned $row_count rows");
+ return false;
+ }
+
+ $row = $rs->FetchRow();
+
+ //Return the ID.
+ return $row[0];
+ }
+
+ /**
+ * get_object_section_value()
+ *
+ * Gets the object_section_value given object id
+ *
+ * @return string Object Section Value
+ *
+ * @param int Object ID #
+ * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
+ */
+ function get_object_section_value($object_id, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ break;
+ default:
+ $this->debug_text('get_object_section_value(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("get_object_section_value(): Object ID: $object_id Object Type: $object_type");
+
+ if (empty($object_id) ) {
+ $this->debug_text("get_object_section_value(): Object ID ($object_id) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("get_object_section_value(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ $query = 'SELECT section_value FROM '. $table .' WHERE id='. $object_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_object_section_value');
+ return false;
+ }
+
+ $row_count = $rs->RecordCount();
+
+ if ($row_count > 1) {
+ $this->debug_text("get_object_section_value(): Returned $row_count rows, can only return one.");
+ return false;
+ }
+
+ if ($row_count == 0) {
+ $this->debug_text("get_object_section_value(): Returned $row_count rows");
+ return false;
+ }
+
+ $row = $rs->FetchRow();
+
+ //Return the ID.
+ return $row[0];
+ }
+
+ /**
+ * get_object_groups()
+ *
+ * Gets all groups an object is a member of.
+ *
+ * If $option == 'RECURSE' it will get all ancestor groups.
+ * defaults to only get direct parents.
+ *
+ * @return array Array of Group ID #'s, or FALSE if Failed
+ *
+ * @param int Object ID #
+ * @param string Object Type, either 'ARO' or 'AXO'
+ * @param string Option, either 'RECURSE', or 'NO_RECURSE'
+ */
+ function get_object_groups($object_id, $object_type = 'ARO', $option = 'NO_RECURSE') {
+ $this->debug_text('get_object_groups(): Object ID: '. $object_id .' Object Type: '. $object_type .' Option: '. $option);
+
+ switch(strtolower(trim($object_type))) {
+ case 'axo':
+ $object_type = 'axo';
+ $group_table = $this->_db_table_prefix .'axo_groups';
+ $map_table = $this->_db_table_prefix .'groups_axo_map';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $group_table = $this->_db_table_prefix .'aro_groups';
+ $map_table = $this->_db_table_prefix .'groups_aro_map';
+ break;
+ default:
+ $this->debug_text('get_object_groups(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ if (empty($object_id)) {
+ $this->debug_text('get_object_groups(): Object ID: ('. $object_id .') is empty, this is required');
+ return FALSE;
+ }
+
+ if (strtoupper($option) == 'RECURSE') {
+ $query = '
+ SELECT DISTINCT g.id AS group_id
+ FROM '. $map_table .' gm
+ LEFT JOIN '. $group_table .' g1 ON g1.id=gm.group_id
+ LEFT JOIN '. $group_table .' g ON g.lft<=g1.lft AND g.rgt>=g1.rgt';
+ } else {
+ $query = '
+ SELECT gm.group_id
+ FROM '. $map_table .' gm';
+ }
+
+ $query .= '
+ WHERE gm.'. $object_type .'_id='. $object_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_object_groups');
+ return FALSE;
+ }
+
+ $retarr = array();
+
+ while ($row = $rs->FetchRow()) {
+ $retarr[] = $row[0];
+ }
+
+ return $retarr;
+ }
+
+ /**
+ * add_object()
+ *
+ * Inserts a new object
+ *
+ * @return int Returns the ID # of the new object if successful, FALSE otherwise
+ *
+ * @param string Object Section Value
+ * @param string Object Name
+ * @param string Object Value
+ * @param int Display Order
+ * @param int Hidden Flag, either 1 to hide, or 0 to show.
+ * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
+ */
+ function add_object($section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ $object_sections_table = $this->_db_table_prefix .'aco_sections';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ $object_sections_table = $this->_db_table_prefix .'aro_sections';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ $object_sections_table = $this->_db_table_prefix .'axo_sections';
+ break;
+ default:
+ $this->debug_text('add_object(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("add_object(): Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
+
+ $section_value = trim($section_value);
+ $name = trim($name);
+ $value = trim($value);
+ $order = trim($order);
+ $hidden = intval($hidden);
+
+ if ($order == NULL OR $order == '') {
+ $order = 0;
+ }
+
+ if (empty($name) OR empty($section_value) ) {
+ $this->debug_text("add_object(): name ($name) OR section value ($section_value) is empty, this is required");
+ return false;
+ }
+
+ if (strlen($name) >= 255 OR strlen($value) >= 230 ) {
+ $this->debug_text("add_object(): name ($name) OR value ($value) is too long.");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("add_object(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ // Test to see if the section is invalid or object already exists.
+ $query = '
+ SELECT CASE WHEN o.id IS NULL THEN 0 ELSE 1 END AS object_exists
+ FROM '. $object_sections_table .' s
+ LEFT JOIN '. $table .' o ON (s.value=o.section_value AND o.value='. $this->db->quote($value) .')
+ WHERE s.value='. $this->db->quote($section_value);
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_object');
+ return FALSE;
+ }
+
+ if ($rs->RecordCount() != 1) {
+ // Section is invalid
+ $this->debug_text("add_object(): Section Value: $section_value Object Type ($object_type) does not exist, this is required");
+ return false;
+ }
+
+ $row = $rs->FetchRow();
+
+ if ($row[0] == 1) {
+ //Object is already created.
+ return true;
+ }
+
+ $insert_id = $this->db->GenID($this->_db_table_prefix.$object_type.'_seq',10);
+ $query = 'INSERT INTO '. $table .' (id,section_value,value,order_value,name,hidden) VALUES('. $insert_id .','. $this->db->quote($section_value) .','. $this->db->quote($value) .','. $order .','. $this->db->quote($name) .','. $hidden .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_object');
+ return false;
+ }
+
+ $this->debug_text("add_object(): Added object as ID: $insert_id");
+ return $insert_id;
+ }
+
+ /**
+ * edit_object()
+ *
+ * Edits a given Object
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise
+ *
+ * @param int Object ID #
+ * @param string Object Section Value
+ * @param string Object Name
+ * @param string Object Value
+ * @param int Display Order
+ * @param int Hidden Flag, either 1 to hide, or 0 to show
+ * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
+ */
+ function edit_object($object_id, $section_value, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ $object_map_table = $this->_db_table_prefix .'aco_map';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ $object_map_table = $this->_db_table_prefix .'aro_map';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ $object_map_table = $this->_db_table_prefix .'axo_map';
+ break;
+ }
+
+ $this->debug_text("edit_object(): ID: $object_id Section Value: $section_value Value: $value Order: $order Name: $name Object Type: $object_type");
+
+ $section_value = trim($section_value);
+ $name = trim($name);
+ $value = trim($value);
+ $order = trim($order);
+ $hidden = intval($hidden);
+
+ if (empty($object_id) OR empty($section_value) ) {
+ $this->debug_text("edit_object(): Object ID ($object_id) OR Section Value ($section_value) is empty, this is required");
+ return false;
+ }
+
+ if (empty($name) ) {
+ $this->debug_text("edit_object(): name ($name) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("edit_object(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ $this->db->BeginTrans();
+
+ //Get old value incase it changed, before we do the update.
+ $query = 'SELECT value, section_value FROM '. $table .' WHERE id='. $object_id;
+ $old = $this->db->GetRow($query);
+
+ $query = '
+ UPDATE '. $table .'
+ SET section_value='. $this->db->quote($section_value) .',
+ value='. $this->db->quote($value) .',
+ order_value='. $this->db->quote($order) .',
+ name='. $this->db->quote($name) .',
+ hidden='. $hidden .'
+ WHERE id='. $object_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('edit_object');
+ $this->db->RollbackTrans();
+ return false;
+ }
+
+ $this->debug_text('edit_object(): Modified '. strtoupper($object_type) .' ID: '. $object_id);
+
+ if ($old[0] != $value OR $old[1] != $section_value) {
+ $this->debug_text("edit_object(): Value OR Section Value Changed, update other tables.");
+
+ $query = '
+ UPDATE '. $object_map_table .'
+ SET value='. $this->db->quote($value) .',
+ section_value='. $this->db->quote($section_value) .'
+ WHERE section_value='. $this->db->quote($old[1]) .'
+ AND value='. $this->db->quote($old[0]);
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('edit_object');
+ $this->db->RollbackTrans();
+ return FALSE;
+ }
+
+ $this->debug_text ('edit_object(): Modified Map Value: '. $value .' Section Value: '. $section_value);
+ }
+
+ $this->db->CommitTrans();
+
+ return TRUE;
+ }
+
+ /**
+ * del_object()
+ *
+ * Deletes a given Object and, if instructed to do so, erase all referencing objects
+ *
+ * ERASE feature by: Martino Piccinato
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise.
+ *
+ * @param int Object ID #
+ * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
+ * @param bool Erases all referencing objects if TRUE, leaves them alone otherwise.
+ */
+ function del_object($object_id, $object_type=NULL, $erase=FALSE) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ $object_map_table = $this->_db_table_prefix .'aco_map';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ $object_map_table = $this->_db_table_prefix .'aro_map';
+ $groups_map_table = $this->_db_table_prefix .'aro_groups_map';
+ $object_group_table = $this->_db_table_prefix .'groups_aro_map';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ $object_map_table = $this->_db_table_prefix .'axo_map';
+ $groups_map_table = $this->_db_table_prefix .'axo_groups_map';
+ $object_group_table = $this->_db_table_prefix .'groups_axo_map';
+ break;
+ default:
+ $this->debug_text('del_object(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("del_object(): ID: $object_id Object Type: $object_type, Erase all referencing objects: $erase");
+
+ if (empty($object_id) ) {
+ $this->debug_text("del_object(): Object ID ($object_id) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("del_object(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ $this->db->BeginTrans();
+
+ // Get Object section_value/value (needed to look for referencing objects)
+ $query = 'SELECT section_value,value FROM '. $table .' WHERE id='. $object_id;
+ $object = $this->db->GetRow($query);
+
+ if (empty($object)) {
+ $this->debug_text('del_object(): The specified object ('. strtoupper($object_type) .' ID: '. $object_id .') could not be found.');
+ $this->db->RollbackTrans();
+ return FALSE;
+ }
+
+ $section_value = $object[0];
+ $value = $object[1];
+
+ // Get ids of acl referencing the Object (if any)
+ $query = "SELECT acl_id FROM $object_map_table WHERE value='$value' AND section_value='$section_value'";
+ $acl_ids = $this->db->GetCol($query);
+
+ if ($erase) {
+ // We were asked to erase all acl referencing it
+
+ $this->debug_text("del_object(): Erase was set to TRUE, delete all referencing objects");
+
+ if ($object_type == "aro" OR $object_type == "axo") {
+ // The object can be referenced in groups_X_map tables
+ // in the future this branching may become useless because
+ // ACO might me "groupable" too
+
+ // Get rid of groups_map referencing the Object
+ $query = 'DELETE FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $object_id;
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('edit_object');
+ $this->db->RollBackTrans();
+ return false;
+ }
+ }
+
+ if (!empty($acl_ids)) {
+ //There are acls actually referencing the object
+
+ if ($object_type == 'aco') {
+ // I know it's extremely dangerous but
+ // if asked to really erase an ACO
+ // we should delete all acl referencing it
+ // (and relative maps)
+
+ // Do this below this branching
+ // where it uses $orphan_acl_ids as
+ // the array of the "orphaned" acl
+ // in this case all referenced acl are
+ // orhpaned acl
+
+ $orphan_acl_ids = $acl_ids;
+ } else {
+ // The object is not an ACO and might be referenced
+ // in still valid acls regarding also other object.
+ // In these cases the acl MUST NOT be deleted
+
+ // Get rid of $object_id map referencing erased objects
+ $query = "DELETE FROM $object_map_table WHERE section_value='$section_value' AND value='$value'";
+ $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('edit_object');
+ $this->db->RollBackTrans();
+ return false;
+ }
+
+ // Find the "orphaned" acl. I mean acl referencing the erased Object (map)
+ // not referenced anymore by other objects
+
+ $sql_acl_ids = implode(",", $acl_ids);
+
+ $query = '
+ SELECT a.id
+ FROM '. $this->_db_table_prefix .'acl a
+ LEFT JOIN '. $object_map_table .' b ON a.id=b.acl_id
+ LEFT JOIN '. $groups_map_table .' c ON a.id=c.acl_id
+ WHERE b.value IS NULL
+ AND b.section_value IS NULL
+ AND c.group_id IS NULL
+ AND a.id in ('. $sql_acl_ids .')';
+ $orphan_acl_ids = $this->db->GetCol($query);
+
+ } // End of else section of "if ($object_type == "aco")"
+
+ if ($orphan_acl_ids) {
+ // If there are orphaned acls get rid of them
+
+ foreach ($orphan_acl_ids as $acl) {
+ $this->del_acl($acl);
+ }
+ }
+
+ } // End of if ($acl_ids)
+
+ // Finally delete the Object itself
+ $query = "DELETE FROM $table WHERE id='$object_id'";
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('edit_object');
+ $this->db->RollBackTrans();
+ return false;
+ }
+
+ $this->db->CommitTrans();
+ return true;
+
+ } // End of "if ($erase)"
+
+ $groups_ids = FALSE;
+
+ if ($object_type == 'axo' OR $object_type == 'aro') {
+ // If the object is "groupable" (may become unnecessary,
+ // see above
+
+ // Get id of groups where the object is assigned:
+ // you must explicitly remove the object from its groups before
+ // deleting it (don't know if this is really needed, anyway it's safer ;-)
+
+ $query = 'SELECT group_id FROM '. $object_group_table .' WHERE '. $object_type .'_id='. $object_id;
+ $groups_ids = $this->db->GetCol($query);
+ }
+
+ if ( ( isset($acl_ids) AND !empty($acl_ids) ) OR ( isset($groups_ids) AND !empty($groups_ids) ) ) {
+ // The Object is referenced somewhere (group or acl), can't delete it
+
+ $this->debug_text("del_object(): Can't delete the object as it is being referenced by GROUPs (".@implode($groups_ids).") or ACLs (".@implode($acl_ids,",").")");
+ $this->db->RollBackTrans();
+ return false;
+ } else {
+ // The Object is NOT referenced anywhere, delete it
+
+ $query = "DELETE FROM $table WHERE id='$object_id'";
+ $rs = $this->db->Execute($query);
+
+ if ( !is_object($rs) ) {
+ $this->debug_db('edit_object');
+ $this->db->RollBackTrans();
+ return false;
+ }
+
+ $this->db->CommitTrans();
+ return true;
+ }
+
+ $this->db->RollbackTrans();
+ return false;
+ }
+
+ /*
+ *
+ * Object Sections
+ *
+ */
+
+ /**
+ * get_object_section_section_id()
+ *
+ * Gets the object_section_id given the name AND/OR value of the section.
+ *
+ * Will only return one section id, so if there are duplicate names it will return false.
+ *
+ * @return int Object Section ID if the object section is found AND is unique, or FALSE otherwise.
+ *
+ * @param string Object Name
+ * @param string Object Value
+ * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
+ *
+ */
+ function get_object_section_section_id($name = NULL, $value = NULL, $object_type = NULL) {
+ $this->debug_text("get_object_section_section_id(): Value: $value Name: $name Object Type: $object_type");
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ case 'aro':
+ case 'axo':
+ case 'acl':
+ $object_type = strtolower(trim($object_type));
+ $table = $this->_db_table_prefix . $object_type;
+ $object_sections_table = $this->_db_table_prefix . $object_type .'_sections';
+ break;
+ default:
+ $this->debug_text('get_object_section_section_id(): Invalid Object Type ('. $object_type . ')');
+ return FALSE;
+ }
+
+ $name = trim($name);
+ $value = trim($value);
+
+ if (empty($name) AND empty($value) ) {
+ $this->debug_text('get_object_section_section_id(): Both Name ('. $name .') and Value ('. $value .') are empty, you must specify at least one.');
+ return FALSE;
+ }
+
+ $query = 'SELECT id FROM '. $object_sections_table;
+ $where = ' WHERE ';
+
+ // limit by value if specified
+ if (!empty($value)) {
+ $query .= $where .'value='. $this->db->quote($value);
+ $where = ' AND ';
+ }
+
+ // only use name if asked, this is SLOW
+ if (!empty($name)) {
+ $query .= $where .'name='. $this->db->quote($name);
+ }
+
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('get_object_section_section_id');
+ return FALSE;
+ }
+
+ $row_count = $rs->RecordCount();
+
+ // If only one row is returned
+ if ($row_count == 1) {
+ // Return only the ID in the first row.
+ $row = $rs->FetchRow();
+ return $row[0];
+ }
+
+ // If more than one row is returned
+ // should only ever occur when using name as values are unique.
+ if ($row_count > 1) {
+ $this->debug_text('get_object_section_section_id(): Returned '. $row_count .' rows, can only return one. Please search by value not name, or make your names unique.');
+ return FALSE;
+ }
+
+ // No rows returned, no matching section found
+ $this->debug_text('get_object_section_section_id(): Returned '. $row_count .' rows, no matching section found.');
+ return FALSE;
+ }
+
+ /**
+ * add_object_section()
+ *
+ * Inserts an object Section
+ *
+ * @return int Object Section ID of new section
+ *
+ * @param string Object Name
+ * @param string Object Value
+ * @param int Display Order
+ * @param int Hidden flag, hides section if 1, shows section if 0
+ * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
+ */
+ function add_object_section($name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $object_sections_table = $this->_db_table_prefix .'aco_sections';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $object_sections_table = $this->_db_table_prefix .'aro_sections';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $object_sections_table = $this->_db_table_prefix .'axo_sections';
+ break;
+ case 'acl':
+ $object_type = 'acl';
+ $object_sections_table = $this->_db_table_prefix .'acl_sections';
+ break;
+ }
+
+ $this->debug_text("add_object_section(): Value: $value Order: $order Name: $name Object Type: $object_type");
+
+ $name = trim($name);
+ $value = trim($value);
+ $order = trim($order);
+ $hidden = intval($hidden);
+
+ if ($order == NULL OR $order == '') {
+ $order = 0;
+ }
+
+ if (empty($name) ) {
+ $this->debug_text("add_object_section(): name ($name) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("add_object_section(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ $insert_id = $this->db->GenID($this->_db_table_prefix.$object_type.'_sections_seq',10);
+ $query = 'insert into '. $object_sections_table .' (id,value,order_value,name,hidden) VALUES( '. $insert_id .', '. $this->db->quote($value) .', '. $order .', '. $this->db->quote($name) .', '. $hidden .')';
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('add_object_section');
+ return false;
+ } else {
+ $this->debug_text("add_object_section(): Added object_section as ID: $insert_id");
+ return $insert_id;
+ }
+ }
+
+ /**
+ * edit_object_section()
+ *
+ * Edits a given Object Section
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise
+ *
+ * @param int Object Section ID #
+ * @param string Object Section Name
+ * @param string Object Section Value
+ * @param int Display Order
+ * @param int Hidden Flag, hide object section if 1, show if 0
+ * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
+ */
+ function edit_object_section($object_section_id, $name, $value=0, $order=0, $hidden=0, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco';
+ $object_sections_table = $this->_db_table_prefix .'aco_sections';
+ $object_map_table = $this->_db_table_prefix .'aco_map';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro';
+ $object_sections_table = $this->_db_table_prefix .'aro_sections';
+ $object_map_table = $this->_db_table_prefix .'aro_map';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo';
+ $object_sections_table = $this->_db_table_prefix .'axo_sections';
+ $object_map_table = $this->_db_table_prefix .'axo_map';
+ break;
+ case 'acl':
+ $object_type = 'acl';
+ $table = $this->_db_table_prefix .'acl';
+ $object_sections_table = $this->_db_table_prefix .'acl_sections';
+ break;
+ default:
+ $this->debug_text('edit_object_section(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("edit_object_section(): ID: $object_section_id Value: $value Order: $order Name: $name Object Type: $object_type");
+
+ $name = trim($name);
+ $value = trim($value);
+ $order = trim($order);
+ $hidden = intval($hidden);
+
+ if (empty($object_section_id) ) {
+ $this->debug_text("edit_object_section(): Section ID ($object_section_id) is empty, this is required");
+ return false;
+ }
+
+ if (empty($name) ) {
+ $this->debug_text("edit_object_section(): name ($name) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("edit_object_section(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ $this->db->BeginTrans();
+
+ //Get old value incase it changed, before we do the update.
+ $query = "select value from $object_sections_table where id=$object_section_id";
+ $old_value = $this->db->GetOne($query);
+
+ $query = "update $object_sections_table set
+ value='$value',
+ order_value='$order',
+ name='$name',
+ hidden=$hidden
+ where id=$object_section_id";
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('edit_object_section');
+
+ $this->db->RollbackTrans();
+
+ return false;
+ } else {
+ $this->debug_text("edit_object_section(): Modified aco_section ID: $object_section_id");
+
+ if ($old_value != $value) {
+ $this->debug_text("edit_object_section(): Value Changed, update other tables.");
+
+ $query = "update $table set
+ section_value='$value'
+ where section_value = '$old_value'";
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('edit_object_section');
+
+ $this->db->RollbackTrans();
+
+ return false;
+ } else {
+ if (!empty($object_map_table)) {
+ $query = "update $object_map_table set
+ section_value='$value'
+ where section_value = '$old_value'";
+ $rs = $this->db->Execute($query);
+
+ if ( !is_object($rs) ) {
+ $this->debug_db('edit_object_section');
+
+ $this->db->RollbackTrans();
+
+ return false;
+ } else {
+ $this->debug_text("edit_object_section(): Modified ojbect_map value: $value");
+
+ $this->db->CommitTrans();
+ return true;
+ }
+ } else {
+ //ACL sections, have no mapping table. Return true.
+
+ $this->db->CommitTrans();
+
+ return true;
+ }
+ }
+ }
+
+ $this->db->CommitTrans();
+ return true;
+ }
+ }
+
+ /**
+ * del_object_section()
+ *
+ * Deletes a given Object Section and, if explicitly asked, all the section objects
+ *
+ * ERASE feature by: Martino Piccinato
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise
+ *
+ * @param int Object Section ID # to delete
+ * @param string Object Type, either 'ACO', 'ARO', 'AXO', or 'ACL'
+ * @param bool Erases all section objects assigned to the section
+ */
+ function del_object_section($object_section_id, $object_type=NULL, $erase=FALSE) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $object_sections_table = $this->_db_table_prefix .'aco_sections';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $object_sections_table = $this->_db_table_prefix .'aro_sections';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $object_sections_table = $this->_db_table_prefix .'axo_sections';
+ break;
+ case 'acl':
+ $object_type = 'acl';
+ $object_sections_table = $this->_db_table_prefix .'acl_sections';
+ break;
+ }
+
+ $this->debug_text("del_object_section(): ID: $object_section_id Object Type: $object_type, Erase all: $erase");
+
+ if (empty($object_section_id) ) {
+ $this->debug_text("del_object_section(): Section ID ($object_section_id) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("del_object_section(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ // Get the value of the section
+ $query="SELECT value FROM $object_sections_table WHERE id='$object_section_id'";
+ $section_value = $this->db->GetOne($query);
+
+ // Get all objects ids in the section
+ $object_ids = $this->get_object($section_value, 1, $object_type);
+
+ if($erase) {
+ // Delete all objects in the section and for
+ // each object delete the referencing object
+ // (see del_object method)
+ if (is_array($object_ids)) {
+ foreach ($object_ids as $id) {
+ if ( $object_type === 'acl' ) {
+ $this->del_acl($id);
+ } else {
+ $this->del_object($id, $object_type, TRUE);
+ }
+ }
+ }
+ }
+
+ if($object_ids AND !$erase) {
+ // There are objects in the section and we
+ // were not asked to erase them: don't delete it
+
+ $this->debug_text("del_object_section(): Could not delete the section ($section_value) as it is not empty.");
+
+ return false;
+
+ } else {
+ // The section is empty (or emptied by this method)
+
+ $query = "DELETE FROM $object_sections_table where id='$object_section_id'";
+ $rs = $this->db->Execute($query);
+
+ if (!is_object($rs)) {
+ $this->debug_db('del_object_section');
+ return false;
+ } else {
+ $this->debug_text("del_object_section(): deleted section ID: $object_section_id Value: $section_value");
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+ /**
+ * get_section_data()
+ *
+ * Gets the section data given the Section Value
+ *
+ * @return array Returns numerically indexed array with the following columns:
+ * - array[0] = (int) Section ID #
+ * - array[1] = (string) Section Value
+ * - array[2] = (int) Section Order
+ * - array[3] = (string) Section Name
+ * - array[4] = (int) Section Hidden?
+ * @param string Section Value
+ * @param string Object Type, either 'ACO', 'ARO', or 'AXO'
+ */
+ function get_section_data($section_value, $object_type=NULL) {
+
+ switch(strtolower(trim($object_type))) {
+ case 'aco':
+ $object_type = 'aco';
+ $table = $this->_db_table_prefix .'aco_sections';
+ break;
+ case 'aro':
+ $object_type = 'aro';
+ $table = $this->_db_table_prefix .'aro_sections';
+ break;
+ case 'axo':
+ $object_type = 'axo';
+ $table = $this->_db_table_prefix .'axo_sections';
+ break;
+ default:
+ $this->debug_text('get_section_data(): Invalid Object Type: '. $object_type);
+ return FALSE;
+ }
+
+ $this->debug_text("get_section_data(): Section Value: $section_value Object Type: $object_type");
+
+ if (empty($section_value) ) {
+ $this->debug_text("get_section_data(): Section Value ($section_value) is empty, this is required");
+ return false;
+ }
+
+ if (empty($object_type) ) {
+ $this->debug_text("get_section_data(): Object Type ($object_type) is empty, this is required");
+ return false;
+ }
+
+ $query = "SELECT id, value, order_value, name, hidden FROM '. $table .' WHERE value='$section_value'";
+ $row = $this->db->GetRow($query);
+
+ if ($row) {
+ return $row;
+ }
+
+ $this->debug_text("get_section_data(): Section does not exist.");
+ return false;
+ }
+
+ /**
+ * clear_database()
+ *
+ * Deletes all data from the phpGACL tables. USE WITH CAUTION.
+ *
+ * @return bool Returns TRUE if successful, FALSE otherwise
+ *
+ */
+ function clear_database(){
+
+ $tablesToClear = array(
+ $this->_db_table_prefix.'acl',
+ $this->_db_table_prefix.'aco',
+ $this->_db_table_prefix.'aco_map',
+ $this->_db_table_prefix.'aco_sections',
+ $this->_db_table_prefix.'aro',
+ $this->_db_table_prefix.'aro_groups',
+ $this->_db_table_prefix.'aro_groups_map',
+ $this->_db_table_prefix.'aro_map',
+ $this->_db_table_prefix.'aro_sections',
+ $this->_db_table_prefix.'axo',
+ $this->_db_table_prefix.'axo_groups',
+ $this->_db_table_prefix.'axo_groups_map',
+ $this->_db_table_prefix.'axo_map',
+ $this->_db_table_prefix.'axo_sections',
+ $this->_db_table_prefix.'groups_aro_map',
+ $this->_db_table_prefix.'groups_axo_map'
+ );
+
+ // Get all the table names and loop
+ $tableNames = $this->db->MetaTables('TABLES');
+ $query = array();
+ foreach ($tableNames as $key => $value){
+ if (in_array($value, $tablesToClear) ) {
+ $query[] = 'TRUNCATE TABLE '.$value.';';
+ }
+ }
+
+ // Loop the queries and return.
+ foreach ($query as $key => $value){
+ $result = $this->db->Execute($value);
+ }
+
+ return TRUE;
+ }
+
+}
+?>
diff --git a/scire/quickstart/index.php b/scire/quickstart/index.php
new file mode 100644
index 0000000..40c8528
--- /dev/null
+++ b/scire/quickstart/index.php
@@ -0,0 +1,37 @@
+<?
+include('../.lib/module_common.php');
+$mod_path = "modules/quickstart";
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+
+add_leftbar($leftbar_menu, "Edit Profiles", "$mod_path/profiles.php");
+add_leftbar($leftbar_menu, "Install Client", "$mod_path/install_client.php");
+
+$clients = array();
+#The first thing we need to do is parse the quickstart server data file.
+#Find the file.
+$fh = fopen("sample_data.csv", "r");
+#Open and loot.
+if ($fh) {
+ while(!feof($fh)) {
+ $line = trim(fgets($fh));
+ #File is a CSV with MAC,profile,status
+ list($client['mac'], $client['ip'], $client['profile'], $client['status']) = explode(",",$line);
+ array_push($clients,$client);
+ }
+ fclose($fh);
+}
+
+
+
+#Get a list of the groups to put in the select box.
+$profile_list = get_profile_list();
+
+$smarty->assign('clients',$clients);
+$smarty->assign('profiles',$profile_list);
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->display($mod_path."/index.tpl");
+#pre_var_dump($clients);
+#var_dump($profile_list);
+?>
diff --git a/scire/quickstart/sample_data.csv b/scire/quickstart/sample_data.csv
new file mode 100644
index 0000000..f736047
--- /dev/null
+++ b/scire/quickstart/sample_data.csv
@@ -0,0 +1,5 @@
+00:01:02:03:04:0A,1.2.3.4,MTA,Install Complete
+AA:BB:CC:DD:EE:FF,65.43.2.1,sample_profile,Scheduled for Install
+00:01:02:03:04:05,192.168.1.11,sample_profile,Installing
+AA:AB:CC:DD:EE:FF,95.43.2.1,sample_profile,Scheduled for Install
+AA:AA:CC:DD:EE:FF,99.43.2.1,sample_profile,Installing
diff --git a/scire/s.gif b/scire/s.gif
new file mode 100644
index 0000000..5035948
--- /dev/null
+++ b/scire/s.gif
Binary files differ
diff --git a/scire/script.php b/scire/script.php
new file mode 100644
index 0000000..f2ab1d3
--- /dev/null
+++ b/scire/script.php
@@ -0,0 +1,129 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+$leftbar_submenu = array();
+$smarty->assign('desc', "Manage scripts.");
+#add_leftbar($leftbar_menu, "Main Settings", "settings.php");
+#add_leftbar($leftbar_menu, "Clients Page", "settings.php?View=Clients");
+$smarty->assign('leftbar_submenu_title', "Actions");
+add_leftbar($leftbar_submenu, "Add Script", "script.php?Action=create");
+
+if ($_POST['add_script']) {
+ #What are the required fields?
+ #name, description, location, script_data,log_location, success_code, run_as, priority, permission, pp_location, pp_script_data.
+ if ($_POST['addname'] and $_POST['desc']) {
+ $script['name'] = $_POST['addname'];
+ $script['desc'] = $_POST['desc'];
+ } else {
+ $status .= "Error: name or description missing!";
+ }
+ if ($_POST['script_data_type']) {
+ $script['location'] = "Embedded";
+ if ($_POST['script_data_type'] == "load") {
+ $script['script_data'] = $_POST['script_data_upload']; #FIXME how is this done?
+ } elseif ($_POST['script_data_type'] == "manual") {
+ $script['script_data'] = $_POST['script_data_manual'];
+ $script['script_data'] = preg_replace('/\r\n/',"\n",$script['script_data']);
+ }
+ } else {
+ $status .= "Error: You must select a script type (Load from file or manual input!";
+ }
+ if ($_POST['runas_radio']) {
+ $script['run_as'] = $_POST['runas_radio'];
+ } elseif ($_POST['runas']) {
+ $script['run_as'] = $_POST['runas'];
+ } else {
+ $status .= "No run_as selected, defaulting to root!!! ";
+ $script['run_as'] = "root";
+ }
+ if ($_POST['priority']) {
+ $script['priority'] = $_POST['priority'];
+ } else {
+ $status .= "No priority selected, defaulting to 5. ";
+ $script['priority'] = "5";
+ }
+ if ($_POST['success_code']) {
+ $script['success_code'] = $_POST['success_code'];
+ } else {
+ $status .= "No success code selected, defaulting to 0. ";
+ $script['success_code'] = "0";
+ }
+ if ($_POST['permission']) {
+ $script['permission'] = $_POST['permission'];
+ }
+ if ($_POST['pps_type']) {
+ $script['pp_location'] = "Embedded";
+ if ($_POST['pps_type'] == "load") {
+ $script['pp_script_data'] = $_POST['pps_load']; #FIXME how is this done?
+ } elseif ($_POST['pps_type'] == "manual") {
+ $script['pp_script_data'] = $_POST['pps_data'];
+ }
+ }
+
+ #Look for tags.
+
+ foreach ($_POST as $name => $value) {
+ if (substr($name,0, 4) == "tag_" and $value) {
+ $temp = substr($name,4);
+ $script_tags[$temp] = $value;
+ }
+ }
+ #Ok, i think we got everything, now lets add it
+ $result = scire_add_script($script['name'], $script['desc'], $script['location'], $script['script_data'], $script['log_location'], $script['success_code'], $script['run_as'], $script['priority'], $script['permission'], $script['pp_location'], $script['pp_script_data'], $script_tags);
+ if (!$result) { #success
+ $status .= "Scipt addition successfull!";
+ } else {
+ $status .= "BAD BAD! Error during query. $result";
+ }
+} #/if add_script
+elseif ($_POST['continue']) {
+ #They pressed the continue button, so just repost the fields, and then add tags as we find them.
+ if ($_POST['addname']) { $smarty->assign('addname', $_POST['addname']); }
+ if ($_POST['desc']) { $smarty->assign('desc', $_POST['desc']); }
+ if ($_POST['runas_radio']) { $smarty->assign('runas', $_POST['runas_radio']); }
+ if ($_POST['runas']) { $smarty->assign('runas', $_POST['runas']); }
+ if ($_POST['priority']) { $smarty->assign('priority', $_POST['priority']); }
+ if ($_POST['permission']) { $smarty->assign('permission', $_POST['permission']); }
+ if ($_POST['script_data_manual']) { $script_data = $_POST['script_data_manual']; }
+ #if ($_POST['script_data_upload']) { $script_data = #FIXME some way get this file and parse it. potential security issue? }
+
+ preg_match_all('/%%(.*?)%%/', $script_data, $matches);
+# pre_var_dump($dyn_tag);
+# pre_var_dump($matches);
+ $smarty->assign('dyn_tags', $matches[1]);
+
+}
+
+$permissions = array();
+$perm_categories = array();
+$smarty->assign('priorities', get_priorities() );
+$all_permissions = $acl->get_objects(NULL, 1, 'ACO');
+foreach ($all_permissions as $categoryname => $cat) {
+ #print "Perm: $perm<br>Permname: $permname<br>";
+ if ($categoryname != $scire_ui_section) {
+ foreach ($cat as $perm) {
+ $tmp_perm[id] = $acl->get_object_id($categoryname,$perm,'ACO');
+ $tmp_perm[name] = $perm;
+ array_push($permissions, $tmp_perm);
+ }
+ array_push($perm_categories, $categoryname);
+ }
+}
+if (!$script_data) {
+ $script_data = '#!/bin/bash' . "\n" . 'emerge sync';
+}
+$smarty->assign('script_data', $script_data);
+
+$smarty->assign('perm_categories',$perm_categories);
+$smarty->assign('perms', $permissions);
+
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('leftbar_submenu', $leftbar_submenu);
+$smarty->assign('View', $_GET['View']);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display('script.tpl');
+#var_dump($all_permissions);
+?>
diff --git a/scire/script_library.php b/scire/script_library.php
new file mode 100644
index 0000000..9b6266f
--- /dev/null
+++ b/scire/script_library.php
@@ -0,0 +1,24 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+$leftbar_submenu = array();
+$smarty->assign('desc', "Manage scripts.");
+#add_leftbar($leftbar_menu, "Main Settings", "settings.php");
+#add_leftbar($leftbar_menu, "Clients Page", "settings.php?View=Clients");
+$smarty->assign('leftbar_submenu_title', "Actions");
+add_leftbar($leftbar_submenu, "Add Script", "script.php?Action=create");
+
+$scripts = get_scire_scripts();
+$smarty->assign('scripts', $scripts);
+
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('leftbar_submenu', $leftbar_submenu);
+$smarty->assign('View', $_GET['View']);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display('script_library.tpl');
+var_dump($_POST);
+pre_var_dump($scripts);
+?>
diff --git a/scire/settings.php b/scire/settings.php
new file mode 100755
index 0000000..7851a0a
--- /dev/null
+++ b/scire/settings.php
@@ -0,0 +1,256 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+$leftbar_submenu = array();
+$template = "settings.tpl";
+$status = "";
+$smarty->assign('desc', "Edit user settings.");
+
+$themes = array();
+array_push($themes, array('name' => 'Standard Grey', 'link' => 'std_grey'));
+array_push($themes, array('name' => 'Light Blue', 'link' => 'light_blue'));
+$smarty->assign('themes',$themes);
+
+############################################
+## Deal with submitted forms first.
+if ($_POST['save_settings']) {
+ #$settings = $_SESSION['settings'];
+ foreach ($_POST as $settingname => $value) {
+ if ($settingname != "save_settings") { #SKIP
+ if (isset($_SESSION['settings'][$settingname])) {
+ if ($value != $_SESSION['settings'][$settingname]) { #The value doesn't match, we need to update.
+ #update the SESSION value.
+ $_SESSION['settings'][$settingname] = $value;
+ #writeback to the DB as well to keep in sync.
+ scire_set_setting($_SESSION['userid'], $settingname, $value);
+ }
+ } else { #New setting. store it.
+ $_SESSION['settings'][$settingname] = $value;
+ #writeback to the DB as well to keep in sync.
+ scire_add_setting($_SESSION['userid'], $settingname, $value);
+ }
+ }
+ }
+}
+######################################## POST
+if ($_POST['save_Jobs_settings']) {
+ pre_var_dump($_POST);
+ foreach ($_POST as $name => $value) {
+ if ($name == "sorton") {
+ if ($value != $_SESSION['settings']['jobs_page_sorton']) { #The value doesn't match, we need to update.
+ scire_set_setting($_SESSION['userid'], 'jobs_page_sorton', $value);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'jobs_page_sorton', $value);
+ }
+ $_SESSION['settings']['jobs_page_sorton'] = $value;
+ }
+ elseif ($name == "sortdir") {
+ if ($value != $_SESSION['settings']['jobs_page_sortdir']) { #The value doesn't match, we need to update.
+ scire_set_setting($_SESSION['userid'], 'jobs_page_sortdir', $value);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'jobs_page_sortdir', $value);
+ }
+ $_SESSION['settings']['jobs_page_sortdir'] = $value;
+ }
+ elseif (substr($name,0, 4) == "Jobs" and $value) {
+ $temp = substr($name,5);
+ $jobs_page_fields[$temp] = $value;
+ print "Adding field $name ... $value";
+ }
+ }
+ #Done with looping
+ pre_var_dump($jobs_page_fields);
+ asort($jobs_page_fields);
+ $keys = array_keys($jobs_page_fields);
+ $fields_string = join(',', $keys);
+
+ #print $fields_string;
+ if ($fields_string != $_SESSION['settings']['jobs_page_fields']) {
+ scire_set_setting($_SESSION['userid'], 'jobs_page_fields', $fields_string);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'jobs_page_fields', $fields_string);
+ }
+ $_SESSION['settings']['jobs_page_fields'] = $fields_string;
+}
+
+########################################
+if ($_POST['save_Clients_settings']) {
+ foreach ($_POST as $name => $value) {
+ if ($name == "sorton") {
+ if ($value != $_SESSION['settings']['clients_page_sorton']) { #The value doesn't match, we need to update.
+ scire_set_setting($_SESSION['userid'], 'clients_page_sorton', $value);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'clients_page_sorton', $value);
+ }
+ $_SESSION['settings']['clients_page_sorton'] = $value;
+ }
+ elseif ($name == "sortdir") {
+ if ($value != $_SESSION['settings']['clients_page_sortdir']) { #The value doesn't match, we need to update.
+ scire_set_setting($_SESSION['userid'], 'clients_page_sortdir', $value);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'clients_page_sortdir', $value);
+ }
+ $_SESSION['settings']['clients_page_sortdir'] = $value;
+ }
+ elseif (substr($name,0, 7) == "Clients" and $value) {
+ $temp = substr($name,8);
+ $clients_page_fields[$temp] = $value;
+ }
+ }
+ #Done with looping
+ asort($clients_page_fields);
+ $keys = array_keys($clients_page_fields);
+ $fields_string = join(',', $keys);
+
+ #print $fields_string;
+ if ($fields_string != $_SESSION['settings']['clients_page_fields']) {
+ scire_set_setting($_SESSION['userid'], 'clients_page_fields', $fields_string);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'clients_page_fields', $fields_string);
+ }
+ $_SESSION['settings']['clients_page_fields'] = $fields_string;
+}
+########################################
+if ($_POST['save_Users_settings']) {
+ foreach ($_POST as $name => $value) {
+ if ($name == "sorton") {
+ if ($value != $_SESSION['settings']['users_page_sorton']) { #The value doesn't match, we need to update.
+ scire_set_setting($_SESSION['userid'], 'users_page_sorton', $value);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'users_page_sorton', $value);
+ }
+ $_SESSION['settings']['users_page_sorton'] = $value;
+ }
+ elseif ($name == "sortdir") {
+ if ($value != $_SESSION['settings']['users_page_sortdir']) { #The value doesn't match, we need to update.
+ scire_set_setting($_SESSION['userid'], 'users_page_sortdir', $value);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'users_page_sortdir', $value);
+ }
+ $_SESSION['settings']['users_page_sortdir'] = $value;
+ }
+ elseif (substr($name,0, 5) == "Users" and $value) {
+ $temp = substr($name,6);
+ $users_page_fields[$temp] = $value;
+ }
+ }
+ #Done with looping
+ asort($users_page_fields);
+ $keys = array_keys($users_page_fields);
+ $fields_string = join(',', $keys);
+
+ #print $fields_string;
+ if ($fields_string != $_SESSION['settings']['users_page_fields']) {
+ scire_set_setting($_SESSION['userid'], 'users_page_fields', $fields_string);
+ } else {
+ scire_add_setting($_SESSION['userid'], 'users_page_fields', $fields_string);
+ }
+ $_SESSION['settings']['users_page_fields'] = $fields_string;
+}
+
+
+
+switch($_GET['View']) {
+ case "Clients":
+ $template = "settings_page.tpl";
+
+ $settings = $_SESSION['settings'];
+ $clients_setting_list = array('clients_page_fields', 'clients_page_sorton', 'clients_page_sortdir');
+ foreach ($clients_setting_list as $clients_set) {
+ if ($settings[$clients_set]) {
+ $smarty->assign($clients_set, $settings[$clients_set]);
+ }
+ }
+ $fields = get_clients_fields();
+ $smarty->assign('fields', $fields);
+
+
+ foreach (explode(',',$_SESSION['settings']['clients_page_fields']) as $key=> $curr_fieldname) {
+ $curr_list[$curr_fieldname] = ($key+1);
+ }
+ var_dump($curr_list);
+ $smarty->assign('curr_list', $curr_list);
+ $smarty->assign('sorton', $_SESSION['settings']['clients_page_sorton']);
+ $smarty->assign('sortdir', $_SESSION['settings']['clients_page_sortdir']);
+ break;
+
+ case "Users":
+ $template = "settings_page.tpl";
+
+ $settings = $_SESSION['settings'];
+ $users_setting_list = array('users_page_fields', 'users_page_sorton', 'users_page_sortdir');
+ foreach ($users_setting_list as $users_set) {
+ if ($settings[$users_set]) {
+ $smarty->assign($users_set, $settings[$users_set]);
+ }
+ }
+ $fields = get_users_fields();
+ $smarty->assign('fields', $fields);
+
+ foreach (explode(',',$_SESSION['settings']['users_page_fields']) as $key=> $curr_fieldname) {
+ $curr_list[$curr_fieldname] = ($key+1);
+ }
+ var_dump($curr_list);
+ $smarty->assign('curr_list', $curr_list);
+ $smarty->assign('sorton', $_SESSION['settings']['users_page_sorton']);
+ $smarty->assign('sortdir', $_SESSION['settings']['users_page_sortdir']);
+ break;
+
+ case "Jobs":
+ $template = "settings_page.tpl";
+ $settings = $_SESSION['settings'];
+ $jobs_setting_list = array('jobs_page_fields', 'jobs_page_sorton', 'jobs_page_sortdir');
+ foreach ($jobs_setting_list as $jobs_set) {
+ if ($settings[$jobs_set]) {
+ $smarty->assign($jobs_set, $settings[$jobs_set]);
+ }
+ }
+ $fields = get_jobs_fields();
+ $smarty->assign('fields', $fields);
+
+ foreach (explode(',',$_SESSION['settings']['jobs_page_fields']) as $key=> $curr_fieldname) {
+ $curr_list[$curr_fieldname] = ($key+1);
+ }
+ var_dump($curr_list);
+ $smarty->assign('curr_list', $curr_list);
+ $smarty->assign('sorton', $_SESSION['settings']['jobs_page_sorton']);
+ $smarty->assign('sortdir', $_SESSION['settings']['jobs_page_sortdir']);
+ break;
+
+ default: #Show users.
+
+
+ #$smarty->assign('leftbar_submenu_title', "Actions");
+ #add_leftbar($leftbar_submenu, "Create User", "user.php?Action=create");
+
+ ############################################
+ ## Deal with sorting for the query.
+ $settings = $_SESSION['settings'];
+ $main_setting_list = array('start_page', 'theme', 'language', 'notification', 'per_page', 'vacation');
+ foreach ($main_setting_list as $main_set) {
+ if ($settings[$main_set]) {
+ $smarty->assign($main_set, $settings[$main_set]);
+ }
+ }
+
+ dumper($settings);
+ break;
+}
+
+add_leftbar($leftbar_menu, "Main Settings", "settings.php");
+add_leftbar($leftbar_menu, "Jobs Page", "settings.php?View=Jobs");
+add_leftbar($leftbar_menu, "Clients Page", "settings.php?View=Clients");
+add_leftbar($leftbar_menu, "Users Page", "settings.php?View=Users");
+add_leftbar($leftbar_menu, "UI Permissions", "ui_permissions.php");
+add_leftbar($leftbar_menu, "Pending Clients", "clients.php?View=Pending");
+
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('leftbar_submenu', $leftbar_submenu);
+$smarty->assign('View', $_GET['View']);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display($template);
+#var_dump($_POST);
+?>
diff --git a/scire/simpletestCron.php b/scire/simpletestCron.php
new file mode 100644
index 0000000..27b0e82
--- /dev/null
+++ b/scire/simpletestCron.php
@@ -0,0 +1,129 @@
+<?php
+
+require_once('simpletest/unit_tester.php');
+require_once('simpletest/reporter.php');
+
+require_once 'cron2.php';
+
+// May 2007
+// Mo Tu We Th Fr Sa Su
+// 1 2 3 4 5 6
+// 7 8 9 10 11 12 13
+// 14 15 16 17 18 19 20
+// 21 22 23 24 25 26 27
+// 28 29 30 31
+
+class CronTest extends UnitTestCase {
+ var $now;
+
+ function CronTest(){
+ $this->UnitTestCase();
+ }
+
+ function setUp() {
+ $this->now = strftime("%M,%H,%d,%m,%w,%Y", mktime(10,0,0,5,25,2007));
+ }
+
+ function tearDown() {
+ unset($this->now);
+ }
+
+ function testCorrectInputValidation() {
+ $test_cases = array("* * * * *",
+ " * * * * *" );
+ $fail = true;
+ foreach ($test_cases as $case) {
+ try {
+ $t = new CronParser($case);
+ } catch (CronException $ce) {
+ $this->assertFalse($fail);
+ $this->fail('Wrong formated input: ' . $case);
+ }
+ }
+ $this->assertNoErrors();
+ }
+
+ function testIncorrectInputValidation() {
+ $test_cases = array("*-*-*-*",
+ "5-10 2 -2 5",
+ " * * * *");
+ $fail = $true;
+ foreach ($test_cases as $case) {
+ try {
+ $t = new CronParser($case);
+ } catch (CronException $ce) {
+ continue;
+ }
+ $this->assertFalse($fail);
+ }
+ $this->assertNoErrors();
+ }
+
+ function testCorrectInputRange() {
+ $t = new CronParser("0 0 1 1 0");
+ $this->assertNoErrors();
+ }
+
+ function test_IncorrectInputRange() {
+ $test_cases = array("-1 -4 -6 90 80",
+ "0 0 0 0 0",
+ "3/5 22 1 12 8",
+ "1/4 * 20-11 1 1",
+ "12/2 2 2 * *");
+ $fail = true;
+ foreach ($test_cases as $case) {
+ try {
+ $t = new CronParser($case);
+ } catch (CronException $ce) {
+ continue;
+ }
+ $this->assertFalse($fail, "error: ".$case);
+ }
+ $this->assertNoErrors();
+ }
+
+ function test_EventCalculation() {
+ $test_cases = array ( array (
+ "test" => "*/15 * * * *" ,
+ "next" => array(0,10,25,5,2007),
+ "prev" => array(45,9,25,5,2007)
+ ),
+ array (
+ "test" => "2 * * * *" ,
+ "next" => array(2,10,25,5,2007),
+ "prev" => array(2,9,25,5,2007)
+ ),
+ array (
+ "test" => "1-30/15 * * * *" ,
+ "next" => array(1,10,25,5,2007),
+ "prev" => array(16,9,25,5,2007)
+ ),
+ array (
+ "test" => "0 2,7 * * 1-5" ,
+ "next" => array(0,2,28,5,2007),
+ "prev" => array(0,7,25,5,2007)
+ ),
+ array (
+ "test" => "9 2,9,22 */4 */3 *",
+ "next" => array(9,2,1,7,2007),
+ "prev" => array(9,22,29,4,2007)
+ ),
+ );
+
+ foreach ($test_cases as $case) {
+ $t = new CronParser($case["test"]);
+ $t->setNow($this->now);
+// echo $case["test"];
+// $this->assertSame(explode(",",$case["prev"]), $t->getLastRan());
+ $this->assertEqual($case["next"], $t->calculateNextRun());
+ }
+
+ }
+
+}
+
+
+$test = &new CronTest();
+$test->run(new HtmlReporter());
+
+?> \ No newline at end of file
diff --git a/scire/std_grey.css b/scire/std_grey.css
new file mode 100644
index 0000000..9c7fa8e
--- /dev/null
+++ b/scire/std_grey.css
@@ -0,0 +1,121 @@
+ html {
+ margin: 0px;
+ }
+ body {
+ margin: 0px;
+ font-family: Bitstream Vera Sans, Helvetica, Sans;
+ font-size: 10pt;
+ }
+ form {
+ margin: 0px;
+ padding: 0px;
+ }
+ p {
+ margin: 5px;
+ }
+ h1 {
+ margin: 5px;
+ margin-bottom: 0px;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ h2 {
+ margin: 5px;
+ font-size: 1.1em;
+ font-weight: normal;
+ }
+ #topbar {
+ border-top: 1px solid #000000;
+ background-color: #494949;
+ }
+ #topbar table tr td a {
+ text-decoration: none;
+ }
+ #topbar table tr td a:hover {
+ color: #ffffff;
+ text-decoration: underline;
+ }
+ #leftbar {
+ background-color: #ffffff;
+ border-top: 1px solid #000000;
+ }
+ #header {
+ border-top: 1px solid #000000;
+ }
+ #content {
+ padding: 7px 5px 5px;
+ }
+ #menu,#submenu {
+ width: 150px;
+ margin: 0px;
+ margin-bottom: 10px;
+ padding: 0px;
+ border-right: 1px solid #ffffff;
+ list-style: none;
+ }
+ #menu li {
+ width: 150px;
+ border-bottom: 1px solid #ffffff;
+ }
+ #submenu li {
+ width: 140px;
+ margin-left: 10px;
+ border-bottom: 1px solid #ffffff;
+ }
+ a.menuitem {
+ display: block;
+ position: relative;
+ margin: 0px;
+ padding: 1px;
+ padding-left: 4px;
+ background-color: #a6afc2;
+ color: #000000;
+ text-decoration: none;
+ }
+ a.menuitem:hover {
+ color: #ffffff;
+ }
+ .box {
+ border: 1px solid #000000;
+ font-size: 0.8em;
+ }
+ .box td {
+ border: none;
+ }
+ td.boxtitle {
+ padding: 5px;
+ border-top: 1px solid #d1ddf5;
+ border-right: 1px solid #7a818f;
+ border-bottom: 1px solid #7a818f;
+ border-left: 1px solid #d1ddf5;
+ background-color: #a5acba;
+ font-size: 1.2em;
+ font-weight: bold;
+ }
+ .table {
+ border: none;
+ border-spacing: 5px;
+ }
+ .table th {
+ padding: 2px 5px 0px;
+ border: none;
+ text-align: left;
+ }
+ .table td {
+ padding: 5px 5px 0px;
+ border: none;
+ border-top: 1px dotted #7a818f;
+ }
+ .optiongroup td {
+ padding-top: 5px;
+ border: none;
+ }
+ .optiongroup td:first-child {
+ padding-left: 5px;
+ }
+ .optiongroup td:last-child {
+ padding-right: 5px;
+ }
+ .optiongroup tr:last-child td {
+ padding-bottom: 5px;
+ }
diff --git a/scire/tux_large.png b/scire/tux_large.png
new file mode 100755
index 0000000..cfe8c5a
--- /dev/null
+++ b/scire/tux_large.png
Binary files differ
diff --git a/scire/ui_permissions.php b/scire/ui_permissions.php
new file mode 100755
index 0000000..3f2793a
--- /dev/null
+++ b/scire/ui_permissions.php
@@ -0,0 +1,133 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+$leftbar_submenu = array();
+add_leftbar($leftbar_menu, "&#171;Settings", "settings.php");
+
+
+$userid = "";
+
+#####################################################
+#Deal with submitted forms.
+
+###############################################
+#Adding a permission.
+if ($_POST['addperm_submit'] or $_POST['editperm_submit']) {
+ if ($_POST['newpermname'] and $_POST['newpermdesc']) { #Add a new permission FIXME add check of auth for this.
+ $obj_id = $acl->add_object($scire_ui_section, $_POST['newpermname'], $_POST['newpermname'], 1, 0, 'ACO');
+ $status .= "Obj id: $obj_id";
+ $result = scire_add_permission($obj_id, $_POST['newpermname'],$_POST['newpermdesc'], $_SESSION['userid']);
+ if ($result == 1) { $status .= "Permission Addition successfull. "; }
+
+ $_POST['perm'] = $_POST['newpermname'];
+ }
+ #Permission should exist now.
+ $aco_array[$scire_ui_section] = array($_POST['perm']);
+ $aro_array = array();
+ $axo_array[$scire_ui_section] = array($scire_ui_section);
+ $axo_group_array = array();
+ $aro_group_array = array();
+# if ($_POST['usertype'] == "usergroups") {
+ $aro_group_array = $_POST['usergroups'];
+# } else {
+ $aro_array['users'] = $_POST['users'];
+# }
+
+ if (!$_POST['active']) {
+ $_POST['active'] = 0;
+ }
+# pre_var_dump($aco_array);
+# pre_var_dump($axo_array);
+# pre_var_dump($aro_array);
+# pre_var_dump($aro_group_array);
+ if ($_POST['addperm_submit']) {
+ $worked = $acl->add_acl($aco_array, $aro_array,$aro_group_array,$axo_array,$axo_group_array,$_POST['allow'],$_POST['active'],1,$_POST['note'],"system");
+ if($worked) {
+ $status .= "<br><b>Addition Successfull! $worked</b>";
+ } else {
+ $status .= "<br><b>Addition BAD $worked</b>";
+ }
+ } else {#Edit
+ $worked = $acl->edit_acl($_POST['editing'],$aco_array, $aro_array,$aro_group_array,$axo_array,$axo_group_array,$_POST['allow'],$_POST['active'],1,$_POST['note'],"system");
+ if($worked) {
+ $status .= "<br><b>Edit Successfull! $worked</b>";
+ } else {
+ $status .= "<br><b>Edit BAD $worked</b>";
+ }
+ }
+
+}
+###############################################
+#Adding a permission.
+elseif ($_POST['delete_confirm']) {
+ $aclid = $_POST['aclid'];
+ $worked = $acl->del_acl($aclid);
+ if($worked) {
+ $status .= "<br><b>Deletion Successfull. $worked</b>";
+ } else {
+ $status .= "<br><b>BAD BAD BAD $worked</b>";
+ }
+ header('Location: ' . $baseurl . 'ui_permissions.php?Action=view');
+}
+elseif ($_POST['delete_cancel']) {
+ header('Location: ' . $baseurl . 'ui_permissions.php?Action=view');
+}
+
+
+########################################################
+switch ($_GET['Action']) {
+ case "delete":
+ $smarty->assign('aclid', $_GET['aclid']);
+ break;
+ case "edit":
+ $smarty->assign('acl',$acl->get_acl($_GET['aclid']));
+ #continue on to get the stuff from add.
+ case "add":
+ add_leftbar($leftbar_menu, "&#171;UI Permissions", "ui_permissions.php");
+ $ui_permissions = $acl->get_objects($scire_ui_section, 1, 'ACO');
+ $ui_permissions = $ui_permissions[$scire_ui_section];
+ #pre_var_dump($ui_permissions);
+ $smarty->assign('perms', $ui_permissions);
+ $smarty->assign('ugroups', $acl->format_groups($acl->sort_groups('aro'), TEXT));
+ break;
+ case "view":
+ default:
+ $smarty->assign('leftbar_submenu_title', "Actions");
+ add_leftbar($leftbar_submenu, "Add UI Permission", "ui_permissions.php?Action=add");
+ $template = "permissions.tpl";
+ $smarty->assign('type','users');
+ $ugroups = $acl->format_groups($acl->sort_groups('aro'), 'ARRAY');
+ $smarty->assign('ugroups', $ugroups);
+
+ $acls = array();
+ #Format of search: aco_section, aco_value, aro_section, aro_value, aro_group_name, axo_section, axo_value, axo_group_name, return_value
+ $result_acl_ids = $acl->search_acl('UI Permissions',FALSE,
+ FALSE,FALSE,FALSE,
+ 'scire_ui','scire_ui',FALSE,FALSE);
+ foreach ($result_acl_ids as $acl_id) {
+ array_push($acls, $acl->get_acl($acl_id));
+ }
+ #pre_var_dump($acls);
+ $smarty->assign('acls',$acls);
+ break;
+}
+
+
+
+
+
+
+$users = get_scire_users('username', 'asc');
+$smarty->assign('users', $users);
+
+
+$smarty->assign('get', $_GET);
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('leftbar_submenu', $leftbar_submenu);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display('ui_permissions.tpl');
+#pre_var_dump($_POST);
+?>
diff --git a/scire/user.php b/scire/user.php
new file mode 100755
index 0000000..154caec
--- /dev/null
+++ b/scire/user.php
@@ -0,0 +1,192 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+
+add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "users.php");
+
+
+$userid = "";
+
+#####################################################
+#Deal with submitted forms.
+
+###############################################
+#Adding a user to usergroups.
+if ($_POST['addgroup_confirm']) {
+ $ingroups = $acl->get_object_groups($_POST['userid'],'ARO');
+ $userdata = $acl->get_object_data($_POST['userid'], 'ARO');
+ $newgroups = $_POST['addgroupid'];
+ #remove first.
+ if ($ingroups) {
+ foreach ($ingroups as $ingroup) {
+ if (!in_array($ingroup, $newgroups)) {
+ $acl->del_group_object($ingroup, $userdata[0][0], $userdata[0][1], 'ARO');
+ }
+ }
+ }
+ if ($newgroups) {
+ foreach ($newgroups as $newgroup) {
+ print "newgroup: $newgroup";
+ $acl->add_group_object($newgroup, $userdata[0][0], $userdata[0][1], 'ARO');
+ }
+ }
+ $_GET['Action'] = "edit";
+ $_GET['userid'] = $_POST['userid'];
+}
+
+###############################################
+# Adding a user.
+if ($_POST['addusername']) {
+ if ($_POST['passwd'] == $_POST['passwd2']) {
+ if ($_POST['addusername'] and $_POST['passwd'] and $_POST['email']) {
+ $obj_id = "";
+ if ($acl->get_object_id("users", $_POST['addusername'], 'ARO') ) { #client already exists
+ $obj_id = $acl->get_object_id("users", $_POST['addusername'], 'ARO');
+ $status .= "Found existing object with objectid $obj_id <br>";
+ } else {
+ $obj_id = $acl->add_object("users", $_POST['addusername'], $_POST['addusername'], 1, 0, 'ARO');
+ $status .= "Object id: $obj_id <BR>";
+ }
+ $result = scire_add_user($obj_id, $_POST['addusername'], $_POST['passwd'], $_POST['real_name'], $_POST['comment'], $_POST['email'], $_POST['phone'], $_POST['pager']);
+ if ($result == 1) {
+ $status .= "User Addition successfull";
+ } else {
+ $status .= "Error during addition!: $result <br>";
+ }
+ if ($_POST['groups']) {
+ $status .= "Adding user to groups ".$_POST['groups'];
+ foreach( $_POST['groups'] as $group) {
+ $worked = $acl->add_group_object($group, "users", $_POST['addusername'], 'ARO');
+ if ($worked) {
+ $status .= "Group $group Addition successfull.<br>";
+ } else {
+ $status .= "ERROR adding group $group <br>";
+ }
+ }
+ }
+ } else {
+ $status = "Error required fields are not filled!";
+ }
+ } else {
+ $status = "Error passwords do not match!";
+ }
+ #header('Location: ' . $baseurl . 'users.php');
+}
+###############################################
+# Editing a user's information.
+if ($_POST['editusername']) {
+ $userinfo = get_scire_user($_GET['userid']);
+ $smarty->assign('user', $userinfo);
+
+ if ($_POST['real_name'] and ($_POST['real_name'] != $userinfo['real_name'])) {
+ $fields['real_name'] = $_POST['real_name'];
+ }
+ if ($_POST['comment'] and ($_POST['comment'] != $userinfo['comment'])){
+ $fields['comment'] = $_POST['comment'];
+ }
+ if ($_POST['email'] and ($_POST['email'] != $userinfo['email'])) {
+ $fields['email'] = $_POST['email'];
+ }
+ if ($_POST['phone'] and ($_POST['phone'] != $userinfo['phone'])) {
+ $fields['phone'] = $_POST['phone'];
+ }
+ if ($_POST['pager'] and ($_POST['pager'] != $userinfo['pager'])) {
+ $fields['pager'] = $_POST['pager'];
+ }
+ #special case for hostname, must change the ACLs
+ if ($_POST['editusername'] and ($_POST['editusername'] != $userinfo['username'])) {
+ $fields['username'] = $_POST['editusername'];
+ $result = $acl->edit_object($_POST['userid'],"users", $_POST['editusername'], $_POST['editusername'],1, 0, 'ARO');
+ }
+
+ if ($_POST['passwd'] and ($_POST['passwd'] == $_POST['passwd2']) ) {
+ check_action_access("Change User Pass/Name");
+ $fields['password'] = crypt($_POST['passwd'], 447470567);
+ }
+ $status = scire_edit_user($_POST['userid'], $fields);
+ $_GET['Action'] = "edit";
+ $_GET['userid'] = $_POST['userid'];
+}
+
+###############################################
+# Delete a user.
+if ($_POST['delete_confirm']) {
+ $status = scire_del_user($_POST['userid']);
+ $acl->del_object($_POST['userid'], 'ARO', TRUE); #True means erase referencing objects.
+ header('Location: ' . $baseurl . 'users.php');
+}
+
+switch($_GET['Action']) {
+ case "addgroup":
+ $smarty->assign('userid', $_GET['userid']);
+ $smarty->assign('groups', $acl->format_groups($acl->sort_groups('aro'), TEXT));
+ $ingroups = array();
+ $ingroups = $acl->get_object_groups($_GET['userid'],'ARO');
+ #var_dump($ingroups);
+ $smarty->assign('ingroups', $ingroups);
+ case "create":
+ $smarty->assign('desc', "Add a user.");
+ $smarty->assign('groups', $acl->format_groups($acl->sort_groups('aro'), TEXT));
+ break;
+ case "edit":
+ $acls = array();
+ #make the topbar look good
+ $userid = $_GET['userid'];
+ $smarty->assign('desc', "Edit user information.");
+ $userinfo = get_scire_user($userid);
+ $smarty->assign('user', $userinfo);
+
+ $usergroups = array();
+ #$id = $acl->get_object_id("users",$userinfo['username'],'ARO');
+ $smarty->assign('userid', $userid);
+ $groups = $acl->get_object_groups($userid,'ARO');
+ if ($groups) {
+ foreach ($groups as $group) {
+ $group_data = $acl->get_group_data($group, 'ARO');
+ $usergroups_entry['name'] = $group_data[3];
+ $usergroups_entry['id'] = $group_data[0];
+ if ($group_data[1]) {
+ $parent_group_data = $acl->get_group_data($group_data[1],'ARO');
+ $usergroups_entry['parent'] = $parent_group_data[3];
+ } else {
+ $usergroups_entry['parent'] = "";
+ }
+ array_push($usergroups, $usergroups_entry);
+ $result_acl_ids = $acl->search_acl(FALSE,FALSE,
+ FALSE,FALSE,FALSE,
+ FALSE,FALSE,$group_data[3],FALSE);
+ foreach ($result_acl_ids as $acl_id) {
+ array_push($acls, $acl->get_acl($acl_id));
+ }
+ }
+ }
+ $smarty->assign('groups', $usergroups);
+ $cgroups = $acl->format_groups($acl->sort_groups('axo'), 'ARRAY');
+ $smarty->assign('cgroups', $cgroups);
+ #Format of search: aco_section, aco_value, aro_section, aro_value, aro_group_name, axo_section, axo_value, axo_group_name, return_value
+ $result_acl_ids = $acl->search_acl(FALSE,FALSE,
+ 'users',$userinfo['username'],FALSE,
+ FALSE,FALSE,FALSE,FALSE);
+ foreach ($result_acl_ids as $acl_id) {
+ array_push($acls, $acl->get_acl($acl_id));
+ }
+ #pre_var_dump($acls);
+ $smarty->assign('acls',$acls);
+ break;
+ case "delete":
+ $userinfo = get_scire_user($_GET['userid']);
+ $smarty->assign('user', $userinfo);
+ #$id = $acl->get_object_id("users",$userinfo['username'],'ARO');
+ $smarty->assign('userid', $_GET['userid']);
+ break;
+}
+
+
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display('user.tpl');
+#var_dump($_POST);
+?>
diff --git a/scire/users.php b/scire/users.php
new file mode 100755
index 0000000..c5dcd45
--- /dev/null
+++ b/scire/users.php
@@ -0,0 +1,159 @@
+<?php
+include('.lib/common.php');
+
+$smarty->assign('leftbar', "on");
+$leftbar_menu = array();
+$leftbar_submenu = array();
+$template = "users.tpl";
+$status = "";
+
+############################################
+## Deal with submitted forms first.
+if ($_POST['addgroupname']) { #Adding a group.
+ $newgroup_id = $acl->add_group($_POST['addgroupname'], $_POST['addgroupname'], $_POST['parentgroup'], 'ARO');
+ $_GET['Action'] = "created";
+ $_GET['View'] = "groups";
+ $status = "User Group Created Successfully.";
+}
+if ($_POST['editgroupname']) {
+ $group_id = $acl->edit_group($_POST['groupid'], $_POST['editgroupname'], $_POST['editgroupname'], $_POST['parentgroup'], 'ARO');
+ $_GET['Action'] = "edited";
+ $_GET['View'] = "groups";
+ $status = "User Group Edited Successfully.";
+}
+if($_POST['delgroup_confirm']) {
+ #Check if the group has children.
+ $result = $acl->del_group($_POST['delgroup'],TRUE, 'ARO');
+ if ($result) {
+ $status = "Group deleted successfully.";
+ } else {
+ $status = "ERROR: Group could not be successfully deleted.";
+ }
+ $_GET['Action'] = "deleted";
+ $_GET['View'] = "groups";
+}
+
+
+
+
+
+$smarty->assign('desc', "View, create, edit, and delete users");
+
+
+switch($_GET['View']) {
+ case "groups":
+ check_action_access("View Users");
+ $template = "users_groups.tpl";
+ switch($_GET['Action']) {
+ case "create":
+ add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "users.php?View=groups");
+ $smarty->assign('groups', $acl->format_groups($acl->sort_groups('aro'), TEXT));
+ break;
+ case "edit":
+ add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "users.php?View=groups");
+ $smarty->assign('groups', $acl->format_groups($acl->sort_groups('aro'), TEXT));
+ $smarty->assign('groupid', $_GET['groupid']);
+ $smarty->assign('groupdata', $acl->get_group_data($_GET['groupid'], 'ARO'));
+ break;
+ case "delete":
+ add_leftbar($leftbar_menu, "&#171;&#171;Cancel", "users.php?View=groups");
+ $smarty->assign('groupid', $_GET['groupid']);
+ break;
+ default: #Show usergroups.
+ add_leftbar($leftbar_menu, "Users", "users.php");
+ add_leftbar($leftbar_menu, "Permissions", "users.php?View=permissions");
+ $smarty->assign('leftbar_submenu_title', "Actions");
+ if ( check_access("Add UserGroup") ) {
+ add_leftbar($leftbar_submenu, "Create User Group", "users.php?View=groups&Action=create");
+ }
+
+ $groups = $acl->format_groups($acl->sort_groups('aro'), HTML);
+ $smarty->assign('groups', $groups);
+
+ break;
+ }
+ break;
+ case "permissions":
+ $smarty->assign('leftbar_submenu_title', "Actions");
+ add_leftbar($leftbar_submenu, "Assign Permission", "assign_permission.php");
+ $template = "permissions.tpl";
+ $smarty->assign('type','users');
+ $ugroups = $acl->format_groups($acl->sort_groups('aro'), 'ARRAY');
+ $smarty->assign('ugroups', $ugroups);
+ $cgroups = $acl->format_groups($acl->sort_groups('axo'), 'ARRAY');
+ $smarty->assign('cgroups', $cgroups);
+
+ #pre_var_dump($groups);
+
+ $acls = array();
+ #Format of search: aco_section, aco_value, aro_section, aro_value, aro_group_name, axo_section, axo_value, axo_group_name, return_value
+ $result_acl_ids = $acl->search_acl(FALSE,FALSE,
+ FALSE,FALSE,FALSE,
+ FALSE,FALSE,FALSE,FALSE);
+ foreach ($result_acl_ids as $acl_id) {
+ $this_acl = $acl->get_acl($acl_id);
+ if ($this_acl['aco']['scire_ui']) {
+ next;
+ } else {
+ array_push($acls, $this_acl);
+ }
+ }
+ #pre_var_dump($acls);
+ $smarty->assign('acls',$acls);
+ break;
+
+ default: #Show users.
+ add_leftbar($leftbar_menu, "Groups", "users.php?View=groups");
+ add_leftbar($leftbar_menu, "Permissions", "users.php?View=permissions");
+ $smarty->assign('leftbar_submenu_title', "Actions");
+ add_leftbar($leftbar_submenu, "Create User", "user.php?Action=create");
+
+ ############################################
+ ## Deal with sorting for the query.
+ if (!$_GET['sorton']) {
+ $_GET['sorton'] = $_SESSION['settings']['users_page_sorton'];
+ }
+ if (!$_GET['sortdir']) {
+ $_GET['sortdir'] = $_SESSION['settings']['users_page_sortdir'];
+ }
+ $smarty->assign('sorton', $_GET['sorton']);
+ $smarty->assign('sortdir', $_GET['sortdir']);
+
+ $users = get_scire_users($_GET['sorton'], $_GET['sort']);
+ foreach ($users as $key => $user) {
+ #$id = $acl->get_object_id("users",$user['username'],'ARO');
+ $groups = $acl->get_object_groups($user['userid'],'ARO');
+ $group_string = "";
+ if ($groups) {
+ foreach ($groups as $group) {
+ $group_data = $acl->get_group_data($group, 'ARO');
+ $group_string .= $group_data[3]. " | ";
+ }
+ }
+ $users[$key]['groups'] = $group_string;
+ }
+
+ #Set information about the fields (display name, sortable)
+ $f_attr = get_users_fields();
+ $smarty->assign('f_attr', $f_attr);
+
+ #Grab the field list.
+ if ($_SESSION['settings']['users_page_fields']) {
+ $fields = explode(',', $_SESSION['settings']['users_page_fields']);
+ } else {
+ $fields = explode(',', get_default_users_fields());
+ }
+ $smarty->assign('fields',$fields);
+
+ $smarty->assign('users', $users);
+ break;
+}
+
+$smarty->assign('leftbar_menu', $leftbar_menu);
+$smarty->assign('leftbar_submenu', $leftbar_submenu);
+$smarty->assign('View', $_GET['View']);
+$smarty->assign('Action', $_GET['Action']);
+$smarty->assign('status', $status);
+$smarty->display($template);
+#var_dump($_POST);
+?>
diff --git a/webgli/TODO b/webgli/TODO
new file mode 100644
index 0000000..0a73f32
--- /dev/null
+++ b/webgli/TODO
@@ -0,0 +1,27 @@
+for agaffney:
+ uribrowser
+ etc_portage value-only saving to etc_files
+ partitioning section of Review
+
+Incomplete pages:
+ Welcome - modes. need to save to session var.
+ Client Config - needs to load values. new layout
+ Partitioning - not yet done at all.
+ URI Browser
+ Global/local USE - doesn't load/save values
+ Make.conf - doesn't load.
+ etc/portage - doesn't save or load.
+ Bootloader - half done.
+ Networking - not done at all.
+ Users
+ Review - half done.
+
+Working pages:
+ Network Mounts - i think. untested.
+ Stage Selection
+ Portage Tree
+ Config Files
+ Timezone
+ Daemons
+ Extra Packages
+ Services
diff --git a/webgli/XMLParser.php b/webgli/XMLParser.php
new file mode 100644
index 0000000..4e36346
--- /dev/null
+++ b/webgli/XMLParser.php
@@ -0,0 +1,117 @@
+<?
+
+class XMLParser {
+
+ function start_handler($parser, $name, $attr) {
+ $tmpxmlpath = $this->xmlpath ? explode("/", $this->xmlpath) : array();
+ $tmpxmlpath[] = $name;
+ $this->xmlpath = implode("/", $tmpxmlpath);
+ $this->attrs[] = $attr;
+ }
+
+ function end_handler($parser, $name) {
+ if(array_key_exists($this->xmlpath, $this->xmlpaths)) {
+ if($this->values[$this->xmlpaths[$this->xmlpath]]) {
+ $this->chardata = trim($this->chardata);
+ switch($this->values[$this->xmlpaths[$this->xmlpath]]['type']) {
+ case 'string':
+ case 'uri':
+ break;
+ case 'bool':
+ $this->chardata = $this->chardata == "True" ? 1 : 0;
+ break;
+ case 'int':
+ $this->chardata = intval($this->chardata);
+ break;
+ case 'array':
+ $this->chardata = explode(" ", $this->chardata);
+ if(count($this->chardata) == 1 && !$this->chardata[0]) $this->chardata = array();
+ break;
+ }
+ $this->set($this->xmlpaths[$this->xmlpath], $this->chardata);
+ } else {
+ call_user_func(array($this, $this->xmlpaths[$this->xmlpath]), trim($this->chardata), array_pop($this->attrs));
+ }
+ } else {
+ # This probably isn't good
+ }
+ $this->chardata = "";
+ $tmpxmlpath = explode("/", $this->xmlpath);
+ array_pop($tmpxmlpath);
+ $this->xmlpath = implode("/", $tmpxmlpath);
+ }
+
+ function char_handler($parser, $data) {
+ $this->chardata .= $data;
+ }
+
+ function parse($xmlfile) {
+ $this->parser = xml_parser_create();
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
+ xml_set_object($this->parser, $this);
+ xml_set_element_handler($this->parser, 'start_handler', 'end_handler');
+ xml_set_character_data_handler($this->parser, 'char_handler');
+ $this->attrs = array();
+ $this->xmlpath = "";
+ $this->chardata = "";
+ $file_contents = file_get_contents($xmlfile);
+ if(!$file_contents) return false;
+ xml_parse($this->parser, $file_contents);
+ xml_parser_free($this->parser);
+ return true;
+ }
+
+ function get($name) {
+ return $this->values[$name]['value'];
+ }
+
+ function set($name, $value) {
+ $this->values[$name]['value'] = $value;
+ }
+
+ function _serialize($xmlroot) {
+ $this->xmldoc = "<?xml version=\"1.0\"?>\n";
+ $this->xmldoc .= "<{$xmlroot}>\n";
+
+ foreach($this->values as $name => $value) {
+ if($value['serialize_func']) {
+ call_user_func(array($this, $value['serialize_func']));
+ } else {
+ $xmlname = "";
+ foreach($this->xmlpaths as $xmlpath => $valname) {
+ if($name == $valname) {
+ $tmpxmlpath = explode("/", $xmlpath);
+ $xmlname = $tmpxmlpath[count($tmpxmlpath)-1];
+ break;
+ }
+ }
+ if(!$xmlname) continue;
+ $data = $this->get($name);
+ if($data) {
+ switch($value['type']) {
+ case 'string':
+ case 'uri':
+ $this->xmldoc .= sprintf("\t<%s>\n\t\t%s\n\t</%s>\n", $xmlname, $data, $xmlname);
+ break;
+ case 'bool':
+ $this->xmldoc .= sprintf("\t<%s>\n\t\t%s\n\t</%s>\n", $xmlname, $data ? "True" : "False", $xmlname);
+ break;
+ case 'int':
+ $this->xmldoc .= sprintf("\t<%s>\n\t\t%d\n\t</%s>\n", $xmlname, intval($data), $xmlname);
+ break;
+ case 'array':
+ $this->xmldoc .= sprintf("\t<%s>\n\t\t%s\n\t</%s>\n", $xmlname, implode(" ", $data), $xmlname);
+ break;
+ }
+ } else {
+ $this->xmldoc .= sprintf("\t<%s/>\n", $xmlname);
+ }
+ }
+ }
+
+ $this->xmldoc .= "</{$xmlroot}>\n";
+ return $this->xmldoc;
+ }
+}
+
+?>
diff --git a/webgli/banner-800x64.png b/webgli/banner-800x64.png
new file mode 100755
index 0000000..fa60b92
--- /dev/null
+++ b/webgli/banner-800x64.png
Binary files differ
diff --git a/webgli/bootloader.php b/webgli/bootloader.php
new file mode 100644
index 0000000..b8ee33e
--- /dev/null
+++ b/webgli/bootloader.php
@@ -0,0 +1,95 @@
+<?php
+
+include('webgliIP.php');
+include('webgliCF.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+$cf = new ClientConfiguration();
+$cf->parse('testcc.xml');
+
+$error_msg = "";
+
+if ($_POST['setbootloader']) {
+ if ($_POST['bootloader']) {
+ $ip->set("bootloader_pkg",$_POST['bootloader']);
+ $error_msg .= "ERROR: Could not set the bootloader pkg!";
+ }
+ if ($_POST['bootmbr']) {
+ $ip->set("bootloader_mbr",True);
+ $error_msg .= "ERROR: Could not set the bootloader MBR flag to TRUE";
+ if ($_POST['boot_drive_choice']) {
+ $ip->set("boot_device",$_POST['boot_drive_choice']);
+ $error_msg .= "ERROR! Could not set the boot device! ".$_POST['boot_drive_choice'];
+ }
+ }
+ else {
+ $ip->set("bootloader_mbr",False);
+ $error_msg .= "ERROR: Could not set the bootloader MBR flag to FALSE.";
+ }
+ if ($_POST['bootargs']) {
+ $ip->set("bootloader_kernel_args",$_POST['bootargs']);
+ $error_msg .= "ERROR: Could not set the bootloader kernel arguments!";
+ }
+
+ if (!$error_msg) {
+ $error_msg = "Values saved successfully";
+ }
+}
+$arch = $cf->get("architecture_template");
+
+$boot_device = $ip->get("boot_device");
+ #Bootloader code yanked from the x86ArchTemplate
+ $devices = $ip->get("partition_tables");
+ $foundboot = False;
+ $drives = array_keys($devices);
+ sort($drives);
+ foreach ($drives as $drive) {
+ $partlist = $devices[$drive];
+ sort($partlist);
+ foreach( $partlist as $part) {
+ if ($part["mountpoint"] == "/boot") {
+ print "found! <br>";
+ $boot_device = $drive;
+ $foundboot = True;
+ }
+ if ( ($part["mountpoint"] == "/") and (!$foundboot)) {
+ $boot_device = $drive;
+ print "set! $boot_device<br>";
+ }
+ }
+ }
+}
+print "Boot device: $boot_device <br>";
+print substr($boot_device,-1);
+/*
+bootloader = shared_info.install_profile.get_boot_loader_pkg()
+$arch_loaders = array('x86': [
+ ("grub",(u"GRand Unified Bootloader, newer, RECOMMENDED")),
+ ("lilo",(u"LInux LOader, older, traditional.(detects windows partitions)"))],
+ 'amd64': [
+ ("grub",(u"GRand Unified Bootloader, newer, RECOMMENDED"))]} #FIXME ADD OTHER ARCHS
+boot_loaders = arch_loaders[arch]
+boot_loaders.append(("none", (u"Do not install a bootloader. (System may be unbootable!)")))
+bootargs = shared_info.install_profile.get_bootloader_kernel_args()
+*/
+ $bootloaders = array();
+ array_push($bootloaders, array("grub", "GRand Unified Bootloader, newer, RECOMMENDED") );
+ array_push($bootloaders, array("lilo", "LInux LOader, older, traditional.(detects windows partitions)") );
+
+ $smarty->assign('boot_device', $boot_device);
+ $smarty->assign('bootargs', $bootargs);
+ $smarty->assign('bootloaders', $bootloaders);
+ $smarty->assign('advanced', True); #FIXME
+
+ $smarty->display('bootloader.tpl');
+?>
diff --git a/webgli/clientconfig.php b/webgli/clientconfig.php
new file mode 100644
index 0000000..9f9d578
--- /dev/null
+++ b/webgli/clientconfig.php
@@ -0,0 +1,168 @@
+<?php
+include('webgliCF.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+#phpinfo();
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+$error_msg = "";
+
+
+$cf = new ClientConfiguration();
+$cf->parse('testcc.xml') or $error_msg .= "No configuration could be loaded.";
+
+
+
+
+if ($_POST['SaveCC']) {
+ if ($_POST['ArchType']) {
+ $error_msg .= "Found an architecture: you submitted " . $_POST['ArchType']. "<BR>\n";
+ $cf->set("architecture_template", $_POST['ArchType']);
+ #$error_msg .= "ERROR: Could not set the Architecture Template<br>\n";
+ }
+ if ($_POST['Logfile']) {
+ $error_msg .= "Found a logfile: you submitted " . $_POST['Logfile'] . "<BR>\n";
+ $cf->set("log_file",$_POST['Logfile']);
+ #$error_msg .= "ERROR: Could not set the Logfile <BR>\n";
+ }
+ if ($_POST['RootMountPoint']) {
+ $error_msg .= "Found a root mount point: you submitted " . $_POST['RootMountPoint'] . "<BR>\n";
+ $cf->set("root_mount_point",$_POST['RootMountPoint']);
+ #$error_msg .= "ERROR: Could not set the Root Mount Point<BR>\n";
+ }
+ if ($_POST['Network_Iface']) {
+ $error_msg .= "Found a network interface: you submitted " . $_POST['Network_Iface'] . "<BR>\n";
+ $cf->set("network_interface", $_POST['Network_Iface']);
+ #$error_msg .= "ERROR: Could not set the Network Interface<BR>\n";
+ }
+ if ($_POST['Network_Type']) {
+ $error_msg .= "Found a Network Type: you submitted " . $_POST['Network_Type'] . "<BR>\n";
+ $cf->set("network_type", $_POST['Network_Type']);
+ #$error_msg .= "ERROR: Could not set the Network Type<BR>\n";
+ }
+ if ($_POST['dhcp_options']) {
+ $error_msg .= "Found DHCP Options. You submitted " . $_POST['dhcp_options'] . "<BR>\n";
+ $cf->set("network_dhcp_options", $_POST['dhcp_options']);
+ #$error_msg .= "ERROR: Could not set the dhcp options<br>\n";
+ }
+ if ($_POST['ip']) {
+ $error_msg .= "Found an IP: you submitted " . $_POST['ip'] . "<BR>\n";
+ $cf->set("network_ip",$_POST['ip']);
+ #$error_msg .= "ERROR: Could not set the IP<BR>\n";
+ }
+ if ($_POST['broadcast']) {
+ $error_msg .= "Found an broadcast IP: you submitted " . $_POST['broadcast'] . "<BR>\n";
+ $cf->set("network_broadcast", $_POST['broadcast']);
+ #$error_msg .= "ERROR: Could not set the broadcast IP<BR>\n";
+ }
+ if ($_POST['netmask']) {
+ $error_msg .= "Found an netmask IP: you submitted " . $_POST['netmask'] . "<BR>\n";
+ $cf->set("network_netmask", $_POST['netmask']);
+ #$error_msg .= "ERROR: Could not set the netmask IP<BR>\n";
+ }
+ if ($_POST['gateway']) {
+ $error_msg .= "Found an gateway IP: you submitted " . $_POST['gateway'] . "<BR>\n";
+ $cf->set("network_gateway",$_POST['gateway']);
+ #$error_msg .= "ERROR: Could not set the gateway IP<BR>\n";
+ }
+ if ($_POST['http_proxy']) {
+ $error_msg .= "Found an HTTP Proxy IP: you submitted " . $_POST['http_proxy'] . "<BR>\n";
+ $cf->set("http_proxy", $_POST['http_proxy']);
+ #$error_msg .= "ERROR: Could not set the HTTP Proxy IP<BR>\n";
+ }
+ if ($_POST['ftp_proxy']) {
+ $error_msg .= "Found an FTP Proxy IP: you submitted " . $_POST['ftp_proxy'] . "<BR>\n";
+ $cf->set("ftp_proxy", $_POST['ftp_proxy']);
+ #$error_msg .= "ERROR: Could not set the FTP Proxy IP<BR>\n";
+ }
+ if ($_POST['rsync_proxy']) {
+ $error_msg .= "Found an RSYNC Proxy IP: you submitted " . $_POST['rsync_proxy'] . "<BR>\n";
+ $cf->set("rsync_proxy",$_POST['rsync_proxy']);
+ #$error_msg .= "ERROR: Could not set the RSYNC Proxy IP<BR>\n";
+ }
+ $dns_servers = array();
+ if ($_POST['dnsserver']) {
+ $error_msg .= "Found an DNS server: you submitted " . $_POST['dnsserver'] . "<BR>\n";
+ array_push($dns_servers, $_POST['dnsserver']);
+ }
+ if ($_POST['dnsserver2']) {
+ $error_msg .= "Found an alternate DNS server: you submitted " . $_POST['dnsserver2'] . "<BR>\n";
+ array_push($dns_servers, $_POST['dnsserver2']);
+ }
+ if ($dns_servers) {
+ $cf->set("dns_servers", $dns_servers);
+ $error_msg .= "ERROR: Could not set the DNS Server<BR>\n";
+ }
+ if ($_POST['EnableSSH']) {
+ $error_msg .= "Found an Enable SSH Flag: you set it to " . $_POST['EnableSSH'] . "<BR>\n";
+ $cf->set("enable_ssh", $_POST['EnableSSH']);
+ #$error_msg .= "ERROR: Could not set the SSH flag<BR>\n";
+ }
+ if ($_POST['Verbose']) {
+ $error_msg .= "Found an Verbose Mode Flag: you set it to " . $_POST['Verbose'] . "<BR>\n";
+ $cf->set("verbose", $_POST['Verbose']);
+ #$error_msg .= "ERROR: Could not set the Verbose mode flag<BR>\n";
+ }
+ if ($_POST['RootPass1'] and $_POST['RootPass2']) {
+ $error_msg .= "Found a root password1: you submitted " . $_POST['RootPass1'] . "<BR>\n";
+ $error_msg .= "Found a root password2: you submitted " . $_POST['RootPass2'] . "<BR>\n";
+ if ($_POST['RootPass1'] == $_POST['RootPass2']) {
+ $error_msg .= "Trying to set the root password. <br>";
+ $cf->set("root_passwd",hash_password($_POST['RootPass1']));
+ $error_msg .= "ERROR: Could not set the root password<BR>\n";
+ } else {
+ $error_msg .= "ERROR: Passwords DO NOT MATCH!<BR>\n";
+ }
+ }
+ if ($_POST['Modules']) {
+ $error_msg .= "Found an Additional Module: you submitted " . $_POST['Modules'] . "<BR>\n";
+ $cf->set("kernel_modules", $_POST['Modules']);
+ #$error_msg .= "ERROR: Could not set the Kernel Modules<BR>\n";
+ }
+ if ($_POST['SaveCC']) {
+ $error_msg .= "Trying to save the profile. <br>\n";
+ #SAVE VALUES
+ file_put_contents('testcc.xml', $cf->serialize()); #PHP 5 only
+ #$error_msg .= "ERROR: Could not save the profile!<BR>\n";
+ }
+ if ($error_msg == "") {
+ $error_msg = "Values saved successfully";
+ }
+}
+$smarty->assign('error_msg',$error_msg);
+#########################################
+$smarty->assign('advanced', True);
+
+$subarches['i386'] = 'x86';
+$subarches['i486'] = 'x86';
+$subarches['i586'] = 'x86';
+$subarches['i686'] = 'x86';
+$subarches['x86_64'] = 'amd64';
+$subarches['parisc'] = 'hppa';
+$smarty->assign('subarches', $subarches);
+
+#Choose the architecture for the Install.
+#import platform
+#arch = platform.machine()
+#if arch in subarches:
+# arch = subarches[arch]
+#Arch selection string here.<br>
+
+$arches["x86"] = "x86 (Pentium and Athlon Series)";
+$arches["amd64"] = "AMD Athlon 64 and Opteron";
+$arches["ppc"] = "PPC (New World) Macs";
+$arches["sparc"] = "Sparc (don't know how to be more specific yet";
+$arches["alpha"] = "Alpha";
+$arches["hppa"] = "HPPA";
+$smarty->assign('arches', $arches);
+
+$modules = list_modules();
+$smarty->assign('modules', $modules);
+
+$smarty->display('clientconfig.tpl');
+
+?>
diff --git a/webgli/configfiles.php b/webgli/configfiles.php
new file mode 100644
index 0000000..00d6c9f
--- /dev/null
+++ b/webgli/configfiles.php
@@ -0,0 +1,93 @@
+<?php
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+#phpinfo();
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+$etc_files = $ip->get("etc_files");
+
+#var_dump($etc_files);
+$error_msg = "";
+
+if ($_POST['SaveConfigFiles']) {
+ if(!array_key_exists("conf.d/keymaps", $etc_files)) {
+ if($_POST['keymap'] || $_POST['windowkeys'] || $_POST['ext_keymap']) {
+ $etc_files['conf.d/keymaps'] = array();
+ }
+ }
+ if(!array_key_exists("conf.d/consolefont", $etc_files)) {
+ if($_POST['font']) {
+ $etc_files['conf.d/consolefont'] = array();
+ }
+ }
+ if(!array_key_exists("conf.d/clock", $etc_files)) {
+ if($_POST['clock']) {
+ $etc_files['conf.d/clock'] = array();
+ }
+ }
+ if(!array_key_exists("rc.conf", $etc_files)) {
+ if($_POST['editor'] || $_POST['disp_manager'] || $_POST['xsession']) {
+ $etc_files['rc.conf'] = array();
+ }
+ }
+ if($_POST['keymap']) $etc_files['conf.d/keymaps']['KEYMAP'] = $_POST['keymap'];
+ if($_POST['windowkeys']) $etc_files['conf.d/keymaps']['SET_WINDOWSKEYS'] = $_POST['windowkeys'];
+ if($_POST['ext_keymap']) $etc_files['conf.d/keymaps']['EXTENDED_KEYMAPS'] = $_POST['ext_keymap'];
+ if($_POST['font']) $etc_files['conf.d/consolefont']['CONSOLEFONT'] = $_POST['font'];
+ if($_POST['clock']) $etc_files['conf.d/clock']['CLOCK'] = $_POST['clock'];
+ if($_POST['editor']) $etc_files['rc.conf']['EDITOR'] = $_POST['editor'];
+ if($_POST['disp_manager']) $etc_files['rc.conf']['DISPLAYMANAGER'] = $_POST['disp_manager'];
+ if($_POST['xsession']) $etc_files['rc.conf']['XSESSION'] = $_POST['xsession'];
+# var_dump($etc_files);
+ $ip->set("etc_files", $etc_files);
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+
+ if(!$error_msg) {
+ $error_msg = "Values saved successfully";
+ }
+}
+
+if (array_key_exists("conf.d/clock", $etc_files) and $etc_files['conf.d/clock']['CLOCK']) {
+ $smarty->assign('clock', $etc_files['conf.d/clock']['CLOCK']);
+}
+if (array_key_exists("conf.d/keymaps", $etc_files)) {
+ if ($etc_files['conf.d/keymaps']['KEYMAP']) {
+ $smarty->assign('keymap',$etc_files['conf.d/keymaps']['KEYMAP']);
+ }
+ if ($etc_files['conf.d/keymaps']['SET_WINDOWSKEYS']) {
+ $smarty->assign('windowkeys',$etc_files['conf.d/keymaps']['SET_WINDOWSKEYS']);
+ }
+ if ($etc_files['conf.d/keymaps']['EXTENDED_KEYMAPS']) {
+ $smarty->assign('ext_keymap',$etc_files['conf.d/keymaps']['EXTENDED_KEYMAPS']);
+ }
+}
+if (array_key_exists("conf.d/consolefont", $etc_files) and $etc_files['conf.d/consolefont']['CONSOLEFONT']) {
+ $smarty->assign('font',$etc_files['conf.d/consolefont']['CONSOLEFONT']);
+}
+if (array_key_exists("rc.conf", $etc_files)) {
+ if ($etc_files['rc.conf']['EDITOR']) {
+ $smarty->assign('editor',$etc_files['rc.conf']['EDITOR']);
+ }
+ if ($etc_files['rc.conf']['DISPLAYMANAGER']) {
+ $smarty->assign('disp_manager',$etc_files['rc.conf']['DISPLAYMANAGER']);
+ }
+ if ($etc_files['rc.conf']['XSESSION']) {
+ $smarty->assign('xsession',$etc_files['rc.conf']['XSESSION']);
+ }
+}
+
+$keymap_list = generate_keymap_list();
+$font_list = generate_consolefont_list();
+$smarty->assign('keymap_list', $keymap_list);
+$smarty->assign('font_list',$font_list);
+
+$smarty->display('configfiles.tpl');
+?>
diff --git a/webgli/daemons.php b/webgli/daemons.php
new file mode 100644
index 0000000..2c5f27e
--- /dev/null
+++ b/webgli/daemons.php
@@ -0,0 +1,54 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+$error_msg = "";
+if ($_POST['savedaemons']) {
+ if ($_POST['logger']) {
+ $ip->set("logging_daemon_pkg", $_POST['logger']);
+ $error_msg .= "ERROR: Could not set logger!<br>\n";
+ }
+ if ($_POST['cron']) {
+ $ip->set("cron_daemon_pkg", $_POST['cron']);
+ $error_msg .= "ERROR: Could not set cron daemon!<br>\n";
+ }
+ if ($error_msg == "") {
+ $error_msg = "Values saved successfully";
+ }
+ #SAVE VALUES
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+}
+
+#Load profile
+$cron = $ip->get("cron_daemon_pkg");
+$logger = $ip->get("logging_daemon_pkg");
+
+$smarty->assign('cron',$cron);
+$smarty->assign('logger',$logger);
+
+$cron_daemons['vixie-cron'] = "Paul Vixie's cron daemon, fully featured, RECOMMENDED.";
+$cron_daemons['dcron'] = "A cute little cron from Matt Dillon.";
+$cron_daemons['fcron'] = "A scheduler with extended capabilities over cron & anacron.";
+$cron_daemons['none'] = "Don't use a cron daemon. (NOT Recommended!)";
+
+$log_daemons['syslog-ng'] = "An advanced system logger. (default)";
+$log_daemons['metalog'] = "A Highly-configurable system logger.";
+$log_daemons['syslogkd'] = "The traditional set of system logging daemons.";
+
+$smarty->assign('cron_daemons',$cron_daemons);
+$smarty->assign('log_daemons',$log_daemons);
+
+$smarty->display('daemons.tpl');
+?>
diff --git a/webgli/etc_portage.php b/webgli/etc_portage.php
new file mode 100644
index 0000000..b446e3c
--- /dev/null
+++ b/webgli/etc_portage.php
@@ -0,0 +1,57 @@
+<?php
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+$error_msg = "";
+$etc_files = $ip->get("etc_files");
+$smarty->assign('dynamic', $ip->get("dynamic_stage3"));
+
+if ($_POST['save']) {
+ if ( !$_POST['currentfile'] ) {
+ $error_msg .= "ERROR you must select a file to edit!<br>";
+ }
+ $file = $_POST['currentfile'];
+ #if (array_key_exists($file,$etc_files)) {
+ $etc_files[$file] = $_POST['filecontents'];
+ #} else {
+ # $etc_files[$file] =
+ #etc_files[file].append($_POST['filecontents'])
+ $ip->set("etc_files",$etc_files);
+ #SAVE VALUES
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+ if ( !$error_msg ) { $error_msg = "Values saved successfully"; }
+}
+if ($_POST['fileeditsubmit']) {
+ if ($_POST['editfile']) {
+ $file_to_edit = $_POST['editfile'];
+ $smarty->assign('file_to_edit',$file_to_edit);
+ if (array_key_exists($file_to_edit,$etc_files)) {
+ $previous_contents = join("\n",$etc_files[$file_to_edit]);
+ } else {
+ $previous_contents = "";
+ }
+ }
+}
+
+#get portage file list here
+$file_list["portage/package.mask"] = "A list of DEPEND atoms to mask.";
+$file_list["portage/package.unmask"] = "A list of packages to unmask.";
+$file_list["portage/package.keywords"] = "Per-package KEYWORDS (like ACCEPT_KEYWORDS).";
+$file_list["portage/package.use"] = "Per-package USE flags.";
+$smarty->assign('file_list',$file_list);
+$smarty->assign('error_msg',$error_msg);
+$smarty->assign('previous_contents',$previous_contents);
+$smarty->display('etc_portage.tpl');
+
+?>
diff --git a/webgli/extrapackages.php b/webgli/extrapackages.php
new file mode 100644
index 0000000..3a3fba6
--- /dev/null
+++ b/webgli/extrapackages.php
@@ -0,0 +1,63 @@
+<?php
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+#phpinfo();
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+$error_msg = "";
+
+if ($_POST['packages']) {
+ $ip->set("install_packages", $_POST['packages']);
+ #SERIALIZE
+ $fh = fopen('test.xml','w');
+ fwrite($fh, $ip->serialize());
+ fclose($fh);
+}
+if ($_POST['manualpackages']) {
+ $packages = explode(',',$_POST['manualpackages']);
+ if ($packages) {
+ $ip->set("install_packages", $packages);
+ #SERIALIZE
+ $fh = fopen('test.xml','w');
+ fwrite($fh, $ip->serialize());
+ fclose($fh);
+ }
+}
+if (!$error_msg) {
+ $error_msg = "Values saved successfully";
+}
+$smarty->assign('error_msg',$error_msg);
+
+$install_packages = array();
+$install_packages = $ip->get("install_packages");
+print "Install Packages:";
+var_dump($install_packages);
+$smarty->assign('install_packages',$install_packages);
+$smarty->assign('current_package_list', join(',',$install_packages));
+
+$grp_list = get_grp_pkgs_from_cd();
+$package_list = get_install_package_list();
+$smarty->assign('grp_list',$grp_list);
+$smarty->assign('package_list',$package_list);
+
+$show_groups = array();
+#figure out how to show groups
+foreach ($_POST as $item => $param) {
+ if( stristr($item,'show') and ($param == "Expand")) {
+ $show_groups[substr($item, 5)] = "Expand";
+ }
+}
+#print_r($show_groups);
+$smarty->assign('show_groups',$show_groups);
+
+$smarty->display('extrapackages.tpl');
+?>
diff --git a/webgli/globaluse.php b/webgli/globaluse.php
new file mode 100644
index 0000000..8d105dd
--- /dev/null
+++ b/webgli/globaluse.php
@@ -0,0 +1,54 @@
+<?php
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+#phpinfo();
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+$etc_files = $ip->get("etc_files");
+$smarty->assign('dynamic',$ip->get("dynamic_stage3"));
+
+$error_msg = "";
+$global_use_flags = "";
+$original_flags = "";
+
+/* This is done in localuse.php
+if ($_POST['saveglobaluse']) {
+ if ($_POST['flags']) {
+ $global_use_flags = join(' ',$_POST['flags']);
+ $global_use_flags .= " "; #extra space for next screen.
+
+ $ip->set("etc_files",$etc_files);
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+ }
+}
+*/
+
+#First set the USE flags, this is a biggie.
+if (array_key_exists("make.conf",$etc_files) and $etc_files['make.conf']['USE']) {
+ $original_flags = $etc_files['make.conf']['USE'];
+} else {
+ exec("portageq envvar USE",$output);
+ print $output;
+ #system_use_flags = GLIUtility.spawn("portageq envvar USE", return_output=True)[1].strip().split()
+}
+
+
+$use_flags = array();
+$use_desc = get_global_use_flags();
+#sort($use_desc);
+$smarty->assign('use_desc',$use_desc);
+#populate the choices list
+#sorted_use = use_desc.keys()
+#sorted_use.sort()
+#present the GLOBAL checkbox list
+
+$smarty->display('globaluse.tpl');
+?>
diff --git a/webgli/images/CVS/Entries b/webgli/images/CVS/Entries
new file mode 100644
index 0000000..5dbc73e
--- /dev/null
+++ b/webgli/images/CVS/Entries
@@ -0,0 +1,16 @@
+/header.png/1.1/Sun Oct 23 18:16:11 2005//
+/spacer.png/1.1/Sun Oct 23 18:16:11 2005//
+/tab_n_l.png/1.1/Sun Oct 23 18:16:11 2005//
+/tab_n_m.png/1.1/Sun Oct 23 18:16:11 2005//
+/tab_n_r.png/1.1/Sun Oct 23 18:16:11 2005//
+/tab_s_l.png/1.1/Sun Oct 23 18:16:11 2005//
+/tab_s_ml.png/1.1/Sun Oct 23 18:16:11 2005//
+/tab_s_mr.png/1.1/Sun Oct 23 18:16:11 2005//
+/tab_s_r.png/1.1/Sun Oct 23 18:16:11 2005//
+/icon-harddisk-noia_48x48.png/1.1/Fri Nov 11 00:21:00 2005//
+/header_bg.png/1.2/Sun Dec 4 03:33:55 2005//
+/arrow_l.gif/1.1/Thu Jan 26 03:36:56 2006//
+/arrow_r.gif/1.1/Thu Jan 26 03:36:56 2006//
+/partition_bg.png/1.1/Thu Jan 26 03:36:56 2006//
+/partition_drag.png/1.1/Thu Jan 26 03:36:56 2006//
+D
diff --git a/webgli/images/CVS/Repository b/webgli/images/CVS/Repository
new file mode 100644
index 0000000..7c54577
--- /dev/null
+++ b/webgli/images/CVS/Repository
@@ -0,0 +1 @@
+gentoo/src/installer/src/net/server/html/images
diff --git a/webgli/images/CVS/Root b/webgli/images/CVS/Root
new file mode 100644
index 0000000..3079522
--- /dev/null
+++ b/webgli/images/CVS/Root
@@ -0,0 +1 @@
+codeman@cvs.gentoo.org:/var/cvsroot
diff --git a/webgli/images/arrow_l.gif b/webgli/images/arrow_l.gif
new file mode 100644
index 0000000..6e91fea
--- /dev/null
+++ b/webgli/images/arrow_l.gif
Binary files differ
diff --git a/webgli/images/arrow_r.gif b/webgli/images/arrow_r.gif
new file mode 100644
index 0000000..da5867d
--- /dev/null
+++ b/webgli/images/arrow_r.gif
Binary files differ
diff --git a/webgli/images/header.png b/webgli/images/header.png
new file mode 100644
index 0000000..22da58c
--- /dev/null
+++ b/webgli/images/header.png
Binary files differ
diff --git a/webgli/images/header_bg.png b/webgli/images/header_bg.png
new file mode 100644
index 0000000..d8b1063
--- /dev/null
+++ b/webgli/images/header_bg.png
Binary files differ
diff --git a/webgli/images/icon-harddisk-noia_48x48.png b/webgli/images/icon-harddisk-noia_48x48.png
new file mode 100644
index 0000000..a6c27af
--- /dev/null
+++ b/webgli/images/icon-harddisk-noia_48x48.png
Binary files differ
diff --git a/webgli/images/partition_bg.png b/webgli/images/partition_bg.png
new file mode 100644
index 0000000..dc63f2b
--- /dev/null
+++ b/webgli/images/partition_bg.png
Binary files differ
diff --git a/webgli/images/partition_drag.png b/webgli/images/partition_drag.png
new file mode 100644
index 0000000..beae23d
--- /dev/null
+++ b/webgli/images/partition_drag.png
Binary files differ
diff --git a/webgli/images/spacer.png b/webgli/images/spacer.png
new file mode 100644
index 0000000..8728643
--- /dev/null
+++ b/webgli/images/spacer.png
Binary files differ
diff --git a/webgli/images/tab_n_l.png b/webgli/images/tab_n_l.png
new file mode 100644
index 0000000..91bad72
--- /dev/null
+++ b/webgli/images/tab_n_l.png
Binary files differ
diff --git a/webgli/images/tab_n_m.png b/webgli/images/tab_n_m.png
new file mode 100644
index 0000000..51a60e7
--- /dev/null
+++ b/webgli/images/tab_n_m.png
Binary files differ
diff --git a/webgli/images/tab_n_r.png b/webgli/images/tab_n_r.png
new file mode 100644
index 0000000..fa4ab52
--- /dev/null
+++ b/webgli/images/tab_n_r.png
Binary files differ
diff --git a/webgli/images/tab_s_l.png b/webgli/images/tab_s_l.png
new file mode 100644
index 0000000..735c22a
--- /dev/null
+++ b/webgli/images/tab_s_l.png
Binary files differ
diff --git a/webgli/images/tab_s_ml.png b/webgli/images/tab_s_ml.png
new file mode 100644
index 0000000..5491ad6
--- /dev/null
+++ b/webgli/images/tab_s_ml.png
Binary files differ
diff --git a/webgli/images/tab_s_mr.png b/webgli/images/tab_s_mr.png
new file mode 100644
index 0000000..f0678b3
--- /dev/null
+++ b/webgli/images/tab_s_mr.png
Binary files differ
diff --git a/webgli/images/tab_s_r.png b/webgli/images/tab_s_r.png
new file mode 100644
index 0000000..1cfc705
--- /dev/null
+++ b/webgli/images/tab_s_r.png
Binary files differ
diff --git a/webgli/index.php b/webgli/index.php
new file mode 100644
index 0000000..34e81b5
--- /dev/null
+++ b/webgli/index.php
@@ -0,0 +1,31 @@
+<?php
+
+include('Smarty.class.php');
+#require_once('Frodo.php');
+#if(!isset($_SESSION['userid'])) {
+ #print "<h1>NO MATCH</h1>";
+# header("Location: login.php");
+#}
+#else {
+# print "Welcome $_SESSION[userid]<br>";
+#}
+
+$smarty = new Smarty;
+#phpinfo();
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+
+$smarty->assign('advanced',True);
+$smarty->display('index.tpl');
+
+
+# print "Welcome to WebGLI. This is the index page. It has index-y stuff on it. ok?";
+
+
+
+
+
+?>
diff --git a/webgli/kernel.php b/webgli/kernel.php
new file mode 100644
index 0000000..820d44d
--- /dev/null
+++ b/webgli/kernel.php
@@ -0,0 +1,77 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+#CHANGE THIS TO A SESSION VAR.
+$smarty->assign('advanced',True);
+
+$error_msg = "";
+print_r($_POST);
+
+if ($_POST['setkernel']) {
+ if ($_POST['manualsources']) {
+ $ip->set("kernel_source_pkg", $_POST['manualsources']);
+ #$error_msg .= "ERROR: Could not set the kernel sources!" . $_POST['manualsources'];
+ }
+ elseif ($_POST['sources']) {
+ $ip->set("kernel_source_pkg", $_POST['sources']);
+ #$error_msg .= "ERROR: Could not set the kernel sources!" . $_POST['sources'];
+ }
+
+ if ($_POST['build_method']) {
+ $ip->set("kernel_build_method", $_POST['build_method']);
+ #$error_msg .= "ERROR: Could not set the kernel build method!";
+ if ($_POST['configuri']) {
+ $ip->set("kernel_config_uri", $_POST['configuri']);
+ # $error_msg .= "ERROR: Could not set the kernel config URI!";
+ }
+ }
+
+ if ($_POST['bootsplash']) {
+ $ip->set("kernel_bootsplash", $_POST['bootsplash']);
+ #$error_msg .= "ERROR: Could not set the kernel bootsplash!" . $_POST['bootsplash'];
+ }
+ #SAVE VALUES
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+ if (!$error_msg) {
+ $error_msg = "Values saved successfully";
+ }
+}
+
+$sources = $ip->get("kernel_source_pkg");
+$build_method = $ip->get("kernel_build_method");
+$bootsplash = $ip->get("kernel_bootsplash");
+$configuri = $ip->get("kernel_config_uri");
+
+$kernels["livecd-kernel"] = array("Livecd Kernel","Use the running kernel (fastest)");
+$kernels["vanilla-sources"] = array("Vanilla (normal)","Normal. The Unaltered Linux Kernel ver 2.6+ (safest) (recommended)");
+$kernels["gentoo-sources"] = array("Gentoo","Gentoo's optimized 2.6+ kernel. (less safe)");
+$kernels["hardened-sources"] = array("Hardened","Hardened sources for the 2.6 kernel tree");
+$kernels["grsec-sources"] = array("grsec","Vanilla sources with grsecurity patches");
+if ($sources == "livecd-kernel" or $sources == "vanilla-sources" or $sources == "gentoo-sources" or $sources == "hardened-sources" or $sources == "grsec-sources") {
+ $cust_source = False;
+} else {
+ $cust_source = True;
+}
+$smarty->assign("error_msg", $error_msg);
+$smarty->assign("sources", $sources);
+$smarty->assign("build_method",$build_method);
+$smarty->assign("bootsplash",$bootsplash);
+$smarty->assign("configuri",$configuri);
+$smarty->assign("kernels",$kernels);
+$smarty->assign("cust_source",$cust_source);
+
+$smarty->display("kernel.tpl");
+?>
diff --git a/webgli/localuse.php b/webgli/localuse.php
new file mode 100644
index 0000000..a80aa51
--- /dev/null
+++ b/webgli/localuse.php
@@ -0,0 +1,58 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+$smarty->assign('dynamic',$ip->get("dynamic_stage3"));
+
+$error_msg = "";
+$global_use_flags = "";
+$total_flags = "";
+$original_flags = "";
+
+if ($_POST['saveglobaluse']) {
+ if ($_POST['flags']) {
+ $global_use_flags = join(' ',$_POST['flags']);
+ $global_use_flags .= " "; #extra space for next screen.
+ $smarty->assign('global_use_flags',$global_use_flags);
+# $ip->set("etc_files",$etc_files);
+# file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+ }
+}
+
+if ($_POST['savelocaluse']) {
+ if ($_POST['flags']) {
+ $local_use_flags = join(' ',$_POST['flags']);
+ }
+ if ($_POST['globalflags']) {
+ $total_flags = $_POST['globalflags'] . $local_use_flags;
+ } else {
+ $total_flags = $local_use_flags;
+ }
+ #get the make.conf
+ $etc_files = $ip->get("etc_files");
+ if (array_key_exists("make.conf",$etc_files)) {
+ $etc_files['make.conf']['USE'] = $total_flags;
+ }
+ else {
+ $etc_files['make.conf'] = array();
+ $etc_files['make.conf']['USE'] = $total_flags;
+ }
+ $ip->set("etc_files",$etc_files);
+}
+$use_local_desc = get_local_use_flags();
+$smarty->assign('use_local_desc',$use_local_desc);
+
+$smarty->display('localuse.tpl');
+?>
diff --git a/webgli/makedotconf.php b/webgli/makedotconf.php
new file mode 100644
index 0000000..4ba5bc6
--- /dev/null
+++ b/webgli/makedotconf.php
@@ -0,0 +1,103 @@
+<?php
+include('webgliIP.php');
+include('webgliCF.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+$cf = new ClientConfiguration();
+#$cf->parse('testcc.xml');
+$etc_files = $ip->get("etc_files");
+$smarty->assign('dynamic', $ip->get("dynamic_stage3"));
+
+$error_msg = "";
+if ($_POST['savemakeconf']) {
+ $cflags = "";
+ $features = " ";
+ if (!array_key_exists("make.conf", $etc_files)) {
+ $etc_files['make.conf'] = array();
+ }
+
+ if ($_POST['proc'] and $_POST['m_thing'] and ($_POST['m_thing'] != "-O0") ) {
+ $cflags .= " ".$_POST['m_thing']."=".$_POST['proc'];
+ }
+ if ($_POST['optim1']) {
+ $cflags .= " ".$_POST['optim1'];
+ }
+ if ($_POST['optim2']) {
+ foreach ($_POST['optim2'] as $param) {
+ $cflags .= " ".$param;
+ }
+ }
+ if ($_POST['optim3']) {
+ $cflags .= " ".$_POST['optim3'];
+ }
+ if ($cflags) {
+ $etc_files['make.conf']['CFLAGS'] = $cflags;
+ }
+
+ if ($_POST['chost']) {
+ $etc_files['make.conf']['CHOST'] = $_POST['chost'];
+ }
+ if ($_POST['unstable']) {
+ $etc_files['make.conf']['ACCEPT_KEYWORDS'] = "~" . $cf->get("architecture_template");
+ }
+ if ($_POST['features']) {
+ $features .= join(" ",$_POST['features']);
+ }
+ if ($_POST['manfeatures']) {
+ $features .= " ".$_POST['manfeatures'];
+ }
+ if ($features) {
+ $etc_files['make.conf']['FEATURES'] = $features;
+ }
+ if (strpos($features,"distcc")) {
+ #Add distcc to the services list.
+ $services = $ip->get("services");
+ if (!in_array("distccd",$services)) {
+ array_push($services, "distccd");
+ }
+ $ip->set("services", $services) or
+ $error_msg .= "ERROR! Could not set the services list.";
+ #Set the distcc flag to emerge earlier than other packages.
+ $ip->set("install_distcc", 1) or
+ $error_msg .= "ERROR! Could not set the install distcc flag!";
+ if ($_POST['distcc']) {
+ $etc_files['make.conf']['DISTCC_HOSTS'] = $_POST['distcc'];
+ }
+ }
+ if ($_POST['makeopts']) {
+ $etc_files['make.conf']['MAKEOPTS'] = $_POST['makeopts'];
+ }
+ $ip->set("etc_files",$etc_files) or
+ $error_msg .= "ERROR! Could not set the make_conf correctly!";
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+ if (!$error_msg) $error_msg = "Values saved successfully";
+}
+
+$arch_procs['x86'] = array("i386", "i486", "i586", "pentium", "pentium-mmx", "i686", "pentiumpro", "pentium2", "pentium3", "pentium3m", "pentium-m", "pentium4", "pentium4m", "prescott", "nocona", "k6", "k6-2", "k6-3", "athlon", "athlon-tbird", "athlon-4", "athlon-xp", "athlon-mp", "k8", "opteron", "athlon64", "athlon-fx", "winchip-c6", "winchip2", "c3", "c3-2");
+
+$smarty->assign('procs',$arch_procs[$cf->get("architecture_template")]);
+
+$smarty->assign('bigO', array(" ","-O1","-O2 (Recommended)", "-O3", "-O4", "-O5"));
+
+$arch_chost_options["x86"] = array('i386-pc-linux-gnu', 'i486-pc-linux-gnu', 'i586-pc-linux-gnu', 'i686-pc-linux-gnu');
+$arch_chost_options["amd64"] = array('x86_64-pc-linux-gnu');
+$arch_chost_options["alpha"] = array('alpha-unknown-linux-gnu');
+$arch_chost_options["ppc"] = array('powerpc-unknown-linux-gnu');
+$arch_chost_options["ppc64"] = array('powerpc64-unknown-linux-gnu');
+$arch_chost_options["sparc"] = array('sparc-unknown-linux-gnu');
+$arch_chost_options["sparc64"] = array('sparc-unknown-linux-gnu');
+$arch_chost_options["hppa"] = array('hppa1.1-unknown-linux-gnu', 'hppa2.0-unknown-linux-gnu');
+$arch_chost_options["mips"] = array('mips-unknown-linux-gnu');
+$smarty->assign('arch_chost_options', $arch_chost_options[$cf->get("architecture_template")]);
+
+$smarty->display('makedotconf.tpl');
diff --git a/webgli/networkmounts.php b/webgli/networkmounts.php
new file mode 100644
index 0000000..cba721a
--- /dev/null
+++ b/webgli/networkmounts.php
@@ -0,0 +1,33 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+$error_msg = "";
+$network_mounts = $ip->get("network_mounts");
+# THE PYHTML WAY DID DEEP COPY HERE.
+if ($_POST['addnfs']) {
+ if (!$_POST['hostname']) $error_msg .= "ERROR: Hostname not found.";
+ if (!$_POST['export']) $error_msg .= "ERROR: Export not found.";
+ if (!$_POST['mountpoint']) $error_msg .= "ERROR: Mountpoint not found.";
+ array_push($network_mounts, array('export'=> $_POST['export'], 'host'=> $_POST['hostname'], 'mountopts'=> $_POST['mountopts'], 'mountpoint'=> $_POST['mountpoint'], 'type'=> 'nfs'));
+ $ip->set("network_mounts",$network_mounts) or
+ $error_msg .= "ERROR: Could not add network mount.";
+}
+elseif ($_POST['Search']) {
+ $error_msg .= "Function not yet implemented! Very sorry about that!";
+}
+$smarty->assign('network_mounts',$network_mounts);
+$smarty->display('networkmounts.tpl');
+?>
diff --git a/webgli/portagetree.php b/webgli/portagetree.php
new file mode 100644
index 0000000..ad8b9b3
--- /dev/null
+++ b/webgli/portagetree.php
@@ -0,0 +1,35 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+$error_msg = "";
+if ($_POST['saveportage']) {
+ if ($_POST['portagetype']) {
+ $ip->set("portage_tree_sync_type", $_POST['portagetype']) or
+ $error_msg .= "ERROR: Could not set the portage tree sync type";
+ }
+ if ($_POST['snapshoturi']) {
+ $ip->set("portage_tree_snapshot_uri", $_POST['snapshoturi']) or
+ $error_msg .= "ERROR: Could not set the portage snapshot URI";
+ }
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+}
+
+$smarty->assign('synctype',$ip->get("portage_tree_sync_type"));
+$smarty->assign('snapshoturi',$ip->get("portage_tree_snapshot_uri"));
+$smarty->assign('dynamic', $ip->get("dynamic_stage3"));
+
+$smarty->display('portagetree.tpl');
+?>
diff --git a/webgli/review.php b/webgli/review.php
new file mode 100644
index 0000000..4b1af32
--- /dev/null
+++ b/webgli/review.php
@@ -0,0 +1,197 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+$error_msg = "";
+$data = "";
+$data .= "Look carefully at the following settings to check for mistakes.\nThese are the installation settings you have chosen:\n\n";
+
+#Partitioning
+$data .= "Partitioning: \n Key: Minor, Pri/Ext, Filesystem, MkfsOpts, Mountpoint, MountOpts, Size.\n";
+$devices = $ip->get("partition_tables"); #shared_info.install_profile.get_partition_tables()
+#var_dump($devices);
+$drives = array_keys($devices);
+sort($drives);
+foreach ($drives as $drive) {
+ $data .= " Drive: $drive\n";
+ $partlist = $devices[$drive];
+ sort($partlist);
+ #tmpparts = devices[drive] #.get_partitions()
+ foreach( $partlist as $part) {
+ #tmppart = tmpparts[part]
+ $entry = " ";
+ if ($part["type"] == "free") { #tmppart.get_type() == "free":
+ #partschoice = "New"
+ $entry .= " - Unallocated space (";
+ $entry .= $part["mb"] . "MB)"; #str(tmppart.get_mb()) . "MB)"
+ } elseif ($part["type"] == "extended") {
+ $entry .= $part["minor"]; #tmppart.get_minor()))
+ $entry .= " - Extended Partition (" . $part["mb"] . "MB)"; # str(tmppart.get_mb())
+ } else {
+ $entry .= $part["minor"] . " - "; #str(int(tmppart.get_minor())) . " - "
+ if ($part["minor"] > 4) { #tmppart.is_logical():
+ $entry .= "Logical (";
+ } else {
+ $entry .= "Primary (";
+ }
+ $entry .= $part["type"] . ", "; #tmppart.get_type() . ", "
+ $entry .= $part["mkfsopts"] . ", "; #(tmppart.get_mkfsopts() or "none") . ", "
+ if ($part["mountpoint"]) {
+ $entry .= $part["mountpoint"];
+ } else {
+ $entry .= "none";
+ }
+ $entry .= ", "; #(tmppart.get_mountpoint() or "none") . ", "
+ if ($part["mountopts"]) {
+ $entry .= $part["mountopts"];
+ } else {
+ $entry .= "none";
+ }
+ $entry .= ", "; #(tmppart.get_mountopts() or "none") . ", "
+ $entry .= $part["mb"] . "MB)"; #str(tmppart.get_mb()) . "MB)"
+ }
+ $data .= $entry . "\n";
+ }
+}
+/*
+#Network Mounts:
+network_mounts = copy.deepcopy(shared_info.install_profile.get_network_mounts())
+$data .= "\nNetwork Mounts: \n"
+for mount in network_mounts:
+ $data .= " ".mount['host'].":".mount['export']."\n"
+*/
+#Install Stage:
+$data .= "\nInstall Stage: " . $ip->get("install_stage") . "\n";
+if ($ip->get("dynamic_stage3")) {
+ $data .= " Tarball will be generated on the fly from the CD.\n";
+} else {
+ $data .= " Tarball URI: " . $ip->get("stage_tarball_uri") . "\n";
+}
+
+#Portage Tree Sync Type:
+$data .= "\nPortage Tree Sync Type: " . $ip->get("portage_tree_sync_type") . "\n";
+if ( $ip->get("portage_tree_sync_type") == "snapshot") {
+ $data .= " Portage snapshot URI: " . $ip->get("portage_tree_snapshot_uri") . "\n";
+}
+
+#Kernel Settings:
+$data .= "\nKernel Settings:\n";
+$data .= " Kernel Sources: " . $ip->get("kernel_source_pkg") . "\n";
+if ($ip->get("kernel_source_pkg") != "livecd-kernel") {
+ $data .= " Kernel Build Method: " . $ip->get("kernel_build_method") . "\n";
+ if ( $ip->get("kernel_build_method") == "genkernel") {
+ $data .= " Kernel Bootsplash Option: " . $ip->get("kernel_bootsplash") . "\n";
+ }
+}
+if ( $ip->get("kernel_config_uri")) {
+ $data .= " Kernel Configuration URI: " . $ip->get("kernel_config_uri") . "\n";
+}
+
+#Bootloader Settings:
+$data .= "\nBootloader Settings:\n";
+$data .= " Bootloader package: " . $ip->get("boot_loader_pkg") . "\n";
+if ( $ip->get("boot_loader_pkg") != "none") {
+ $data .= " Install bootloader to MBR: " . $ip->get("boot_loader_mbr") . "\n";
+ $data .= " Bootloader kernel arguments: " . $ip->get("bootloader_kernel_args") . "\n";
+}
+
+#Timezone:
+$data .= "\nTimezone: " . $ip->get("time_zone") . "\n";
+/*
+#Networking Settings:
+$data .= "\nNetworking Settings: \n"
+interfaces = shared_info.install_profile.get_network_interfaces()
+for iface in interfaces:
+ if interfaces[iface][0] == 'dhcp':
+ $data .= " " . iface . _(u": Settings: DHCP. Options: ") . interfaces[iface][1] . "\n"
+ else:
+ $data .= " " . iface . _(u"IP: ") . interfaces[iface][0] . _(u" Broadcast: ") . interfaces[iface][1] . _(u" Netmask: ") . interfaces[iface][2] . "\n"
+default_gateway = shared_info.install_profile.get_default_gateway()
+if default_gateway:
+ $data .= " Default Gateway: " . default_gateway[0] . "/" . default_gateway[1] . "\n"
+$data .= " Hostname: " . shared_info.install_profile.get_hostname() . "\n"
+if shared_info.install_profile.get_domainname():
+ $data .= " Domainname: " .shared_info.install_profile.get_domainname() . "\n"
+if shared_info.install_profile.get_nisdomainname():
+ $data .= " NIS Domainname: " .shared_info.install_profile.get_nisdomainname() . "\n"
+if shared_info.install_profile.get_dns_servers():
+ for dns_server in shared_info.install_profile.get_dns_servers():
+ $data .= " DNS Server: " .dns_server . "\n"
+if shared_info.install_profile.get_http_proxy():
+ $data .= " HTTP Proxy: " .shared_info.install_profile.get_http_proxy() . "\n"
+if shared_info.install_profile.get_ftp_proxy():
+ $data .= " FTP Proxy: " .shared_info.install_profile.get_ftp_proxy() . "\n"
+if shared_info.install_profile.get_rsync_proxy():
+ $data .= " RSYNC Proxy: " .shared_info.install_profile.get_rsync_proxy() . "\n"
+*/
+#Cron Daemon:
+$data .= "\nCron Daemon: " . $ip->get("cron_daemon_pkg") . "\n";
+
+#Logger:
+$data .= "\nLogging Daemon: " . $ip->get("logging_daemon_pkg") . "\n";
+
+#Extra packages:
+if ($ip->get("install_packages")) {
+ $data .= "\nExtra Packages: ";
+ $data .= explode(' ',$ip->get("install_packages"));
+ $data .= "\n";
+}
+
+
+#Services:
+if ( $ip->get("services")) {
+ $data .= "\nAdditional Services: ";
+ $data .= explode(' ',$ip->get("services"));
+ $data .= "\n";
+}
+
+#Other Configuration Settings (rc.conf):
+#Make.conf Settings:
+$data .= "\nConfiguration Files Settings:\n";
+$etc_files = $ip->get("etc_files");
+foreach ($etc_files as $name => $file) {
+ $data .= " File: $name \n";
+ if (is_array($file)) {
+ foreach ($file as $var => $value) {# name in etc_files[etc_file]:
+ $data .= " Variable: $var Value: $value\n";# . etc_files[etc_file][name] . "\n"
+ }
+ } else {
+ foreach( $file as $entry) {# entry in etc_files[etc_file]:
+ $data .= " Value: $entry \n";
+ }
+ }
+}
+
+/*
+#Additional Users:
+$data .= "\nAdditional Users:\n"
+users = {}
+for user in shared_info.install_profile.get_users():
+ users[user[0]] = (user[0], user[1], user[2], user[3], user[4], user[5], user[6])
+for user in users:
+ $data .= " Username: " . user
+ $data .= "\n Group Membership: " . ",".join(users[user][2])
+ $data .= "\n Shell: " . users[user][3]
+ $data .= "\n Home Directory: " . users[user][4]
+ if users[user][5]:
+ $data .= "\n User Id: " . users[user][5]
+ if users[user][6]:
+ $data .= "\n User Comment: " . users[user][6]
+*/
+
+$smarty->assign('data', $data);
+$smarty->display('review.tpl');
+
+?>
diff --git a/webgli/services.php b/webgli/services.php
new file mode 100644
index 0000000..1826727
--- /dev/null
+++ b/webgli/services.php
@@ -0,0 +1,51 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+if ($_POST['saveservices']) {
+ if ($_POST['servicesmanual']) {
+ $services = explode(',',$_POST['servicesmanual']);
+
+ } elseif ($_POST['services']) {
+ $services = $_POST['services'];
+ }
+ if ($services) {
+ $ip->set("services",$services);
+ #SAVE VALUES
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+ #$error_msg .= "ERROR! Could not set the services list.";
+ }
+ if (!$error_msg) $error_msg = "Values saved successfully";
+}
+$smarty->assign('services', $ip->get("services"));
+# I don't want to do this anymore. $smarty->assign('manualservices', join(',',$ip->get("services")));
+
+$choices['alsasound'] = "ALSA Sound Daemon";
+$choices['apache'] = "Common web server (version 1.x)";
+$choices['apache2'] = "Common web server (version 2.x)";
+$choices['distccd'] = "Distributed Compiling System";
+$choices['esound'] = "ESD Sound Daemon";
+$choices['hdparm'] = "Hard Drive Tweaking Utility";
+$choices['local'] = "Run scripts found in /etc/conf.d/local.start";
+$choices['portmap'] = "Port Mapping Service";
+$choices['proftpd'] = "Common FTP server";
+$choices['sshd'] = "SSH Daemon (allows remote logins)";
+$choices['xfs'] = "X Font Server";
+$choices['xdm'] = "X Daemon";
+$smarty->assign('choices',$choices);
+$smarty->assign('error_msg',$error_msg);
+$smarty->display('services.tpl');
+
+?>
diff --git a/webgli/stageselection.php b/webgli/stageselection.php
new file mode 100644
index 0000000..3027105
--- /dev/null
+++ b/webgli/stageselection.php
@@ -0,0 +1,55 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+$error_msg = "";
+
+if ($_POST['savestage']) {
+# print "YES I CLICKED SAVE<br>"
+ if ($_POST['stage']) {
+# print "YES THERE IS A STAGE<br>"
+ if ($_POST['stage'] == "3+GRP") {
+ $_POST['stage'] = "3";
+ $ip->set("grp_install", True) or
+ $error_msg .= "ERROR COULD NOT SET GRP INSTALL";
+ } else {
+ $ip->set("grp_install", False) or
+ $error_msg .= "ERROR COULD NOT SET GRP INSTALL";
+ }
+ $ip->set("install_stage", $_POST['stage']) or
+ $error_msg .= "ERROR: could not set the install stage";
+ }
+ if ($_POST['tarballuri']) {
+ $ip->set("stage_tarball_uri", $_POST['tarballuri']) or
+ $error_msg .= "ERROR: Could not set the tarball URI";
+ if ($_POST['dynamic']) {
+ $ip->set("dynamic_stage3",True);
+ $ip->set("portage_tree_sync_type","snapshot");
+ // cd_snapshot_uri = GLIUtility.get_cd_snapshot_uri()
+ $ip->set("portage_tree_snapshot_uri",$cd_snapshot_uri);
+ } else {
+ $ip->set("dynamic_stage3",False) or
+ $error_msg .= "ERROR: Could not set dynamic stage 3.<br>";
+ }
+ }
+ #SERIALIZE
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+}
+$smarty->assign('stage',$ip->get("install_stage"));
+$smarty->assign('grp_install',$ip->get("grp_install"));
+$smarty->assign('dynamic',$ip->get("dynamic_stage3"));
+$smarty->assign('tarball', $ip->get("stage_tarball_uri"));
+$smarty->display('stageselection.tpl');
+?>
diff --git a/webgli/templates/.bootloader.tpl.swp b/webgli/templates/.bootloader.tpl.swp
new file mode 100644
index 0000000..791978d
--- /dev/null
+++ b/webgli/templates/.bootloader.tpl.swp
Binary files differ
diff --git a/webgli/templates/bootloader.tpl b/webgli/templates/bootloader.tpl
new file mode 100644
index 0000000..828f312
--- /dev/null
+++ b/webgli/templates/bootloader.tpl
@@ -0,0 +1,42 @@
+{include file="header.tpl" title="WebGLI - Bootloader", advanced=$advanced}
+<p>Bootloader Settings:</p>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+<form name="Bloader" method="post" action="" enctype="multipart/form-data">
+<p>To boot successfully into your new Linux system, a bootloader will be needed. If you already have a bootloader you want to use you can select None here. The bootloader choices available are dependent on what GLI supports and what architecture your system is. Choose a bootloader:</p>
+<table width="100%" border="1">
+{section name=bl loop=$bootloaders}
+<tr><td><input name="bootloader" type="radio" value="{$bootloaders[bl][0]}" {if $bootloaders[bl][0] == $bootloader} checked {/if} > {$bootloaders[bl][0]}</td><td>{$bootloaders[bl][1]}</td></tr>
+{/section}
+</table>
+{if $advanced}
+ <hr>
+ Most bootloaders have the ability to install to either the Master Boot Record (MBR) or some other partition. Most people will want their bootloader installed on the MBR for successful boots, but if you have special circumstances, you can have the bootloader installed to the /boot partition instead. Do you want the boot loader installed in the MBR? (YES is RECOMMENDED)
+ <p>
+
+<input name="bootmbr" type="checkbox" id="bootmbr" value="True" {if $bootmbr} checked {/if}> Install to MBR </p>
+{/if}
+
+{if (!$boot_device)}
+<br> You need to partition before you can select the boot device.<br>
+{/if}
+{if ($boot_device and (substr($boot_device,-1) != "a")) }
+ Your boot device may not be correct. It is currently set to {$boot_device}, but this device may not be the first to boot. Usually boot devices end in 'a' such as hda or sda.
+ <br>Please confirm your boot device.<br>
+ {section name=bootdevices loop=bootdevices}
+ <input type="radio" name="boot_drive_choice" value="{$bootdevices}">{$bootdevices}<br>
+ {/section}
+{/if}
+
+<br>
+{if $advanced}
+ <p>If you have any additional optional arguments you want to pass to the kernel at boot, type them here:
+ <input name="bootargs" type="text" id="bootargs" value="{$bootargs}">
+ </p>
+{/if}
+<p>
+<input name="setbootloader" type="submit" id="setbootloader" value="Save Bootloader Settings">
+</p>
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/bottom.tpl b/webgli/templates/bottom.tpl
new file mode 100644
index 0000000..99c2255
--- /dev/null
+++ b/webgli/templates/bottom.tpl
@@ -0,0 +1,6 @@
+ </td>
+ </tr>
+</table>
+
+</body>
+</html>
diff --git a/webgli/templates/clientconfig.tpl b/webgli/templates/clientconfig.tpl
new file mode 100644
index 0000000..78bc855
--- /dev/null
+++ b/webgli/templates/clientconfig.tpl
@@ -0,0 +1,86 @@
+{include file="header.tpl" title="WebGLI - Client Configuration", advanced=$advanced}
+<h2>Client Config</h2>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+<form name="CConfig" action="" method="POST" enctype="multipart/form-data">
+{if $advanced}
+ <table border="2">
+ <tr>
+ <td>
+ Please select the architecture of the computer that gentoo will be installed on. For pentium and AMD 32-bit processors, choose x86.<br>
+ {foreach item=thisarch from=$arches key=key}
+ <input type="radio" name="ArchType" value="{$key}">{$thisarch}<br>
+ {/foreach}
+ </td>
+ <td width="15"></td>
+ <td>The installer logs all important events during the install process to a logfile for debugging purposes.
+ The file gets copied to the new system once the install is complete.
+ Enter the desired filename and path for the install log (the default is recommended):<br><input name="Logfile" type="text" maxlength="80" value="/var/log/installer.log">
+ <hr>Enter the mount point to be used to mount the partition(s) where the new system will be installed. The default is /mnt/gentoo and is greatly recommended, but any mount point will do.<br><input name="RootMountPoint" type="text" maxlength="80" value="/mnt/gentoo">
+ <hr>Debug Mode: <input name="Verbose" type="radio" value="True">Yes <input name="Verbose" type="radio" value="False" checked>No</td>
+ </tr>
+ </table>
+{/if}
+
+<hr>
+<table border="1">
+ <tr>
+ <td width="50%">In order to complete most installs, an active Internet connection is required. Setup one network connection for GLI to use to connect to the Internet if doing a network install. If your desired device does not show up in the list, you can select Other and input the device name manually. <br>
+ <select name="Network_Iface" size="4">
+ <option value="device">NEED WAY OF ADDING DEVICES</option>
+ </select>
+
+ <select name="Network_Type" size="3"><option value="dhcp">DHCP</option><option value="static">Manual Config</option><option value="None">None (Networkless)</option></select>
+ </td>
+ <td width="50%">Networking Info for Manual Configurations:<br>
+ Enter your IP address: <input name="ip" type="text" maxlength="15" value="192.168."><br>
+ Enter your Broadcast address: <input name="broadcast" type="text" maxlength="15" value=".255"><br>
+ Enter your Netmask: <input name="netmask" type="text" maxlength="15" value="255.255.255.0"><br>
+ Enter your default gateway: <input name="gateway" type="text" maxlength="15" value=".1"><br>
+ <hr>Info for DHCP Configurations:<br>DHCP Options: <input type="text" name="dhcp_options" >
+ <hr>Enter a DNS server: <input name="dnsserver" type="text" maxlength="15" value="128.118.25.3"><br>
+ Alternate DNS server: <input name="dnsserver2" type="text" maxlength="15" value=""></td>
+ </tr>
+</table>
+{if $advanced}
+ Proxy Information (if necessary):<br>
+ HTTP Proxy URI: <input name="http_proxy" type="text" value=""><br>
+ FTP Proxy URI: <input name="ftp_proxy" type="text" value=""><br>
+ RSYNC Proxy URI: <input name="rsync_proxy" type="text" value="">
+{/if}
+
+<hr>Do you want SSH enabled during the install? This will allow you to login remotely during the installation process. If choosing Yes, be sure you select a new LiveCD root password!<br>
+Enable SSH?: <input name="EnableSSH" type="radio" value="True">Yes
+<input name="EnableSSH" type="radio" value="False" checked="checked">No
+<hr>If you want to be able to login to your machine from another console during the installation,
+you will want to enter a new root password for the LiveCD.
+Note that this can be different from your new system's root password.
+Presss Enter twice to skip this step.<br>
+Enter Password:<input name="RootPass1" type="password" maxlength="80" value=""><br>
+Re-enter Password to verify:<input name="RootPass2" type="password" maxlength="80" value=""><br>
+
+{if $advanced}
+ <hr>List of loaded modules:. <br>
+ {section name=mod loop=$modules}
+ <br>{$modules[mod]}
+ {/section}
+<br>Additional Modules to Load (space-separated list): <input name="Modules" type="text" maxlength="80" value=""><br>
+{/if}
+<!-- #Save Client Configuration File. THIS SHOULD BE A POPUP -->
+<hr><br>Save Client Configuration File:<br>
+<input name="SaveCC" type="submit" value="Save Client Configuration">
+
+<!-- #Print buttons for Next/Previous/Help/Save -->
+<hr>
+<table>
+ <tr>
+ <td><input name="LoadCC" type="button" value="Load"></td>
+ <td><input name="SaveCC" type="button" value="Save"></td>
+ <td><input name="Help" type="button" value="Help"></td>
+ <td><input name="Previous" type="button" value="Previous"></td>
+ <td><input name="Next" type="button" value="Next"></td>
+ </tr>
+</table>
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/configfiles.tpl b/webgli/templates/configfiles.tpl
new file mode 100644
index 0000000..3848ee1
--- /dev/null
+++ b/webgli/templates/configfiles.tpl
@@ -0,0 +1,76 @@
+{include file="header.tpl" title="WebGLI - Configuration Files"}
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+<form action="" method="POST" enctype="multipart/form-data">
+<table cellspacing="0" cellpadding="0" width="790" height="600" border="1">
+ <tr height="33%">
+ <td>
+ <table width="100%" height="100%" border="1">
+ <tr>
+ <td width="50%">
+ <table width="100%" height="100%" border="1">
+ <tr>
+ <td><b>Clock:</b><br>Should CLOCK be set to UTC or local?<br><input type="radio" name="clock" value="UTC" {if $clock == "UTC"} checked {/if}>UTC<br>
+ <input type="radio" name="clock" value="local" {if $clock == "local"} checked {/if}>Local
+ </td>
+ </tr>
+ <tr>
+ <td><b>Default Editor:</b><br>Choose your default editor:<br>
+ <input type="radio" name="editor" value="/bin/nano" {if $editor == "/bin/nano"} checked {/if}>/bin/nano (Default editor)<br>
+ <input type="radio" name="editor" value="/usr/bin/vim" {if $editor == "/usr/bin/vim"} checked {/if}>/usr/bin/vim (vi improved editor)<br>
+ <input type="radio" name="editor" value="/usr/bin/emacs" {if $editor == "/usr/bin/emacs"} checked {/if}>/usr/bin/emacs (The emacs editor)
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td width="50%"><b>Display Manager:</b><br>Choose your display manager for Xorg-x11 (note you must make sure that package also gets installed for it to work):<br>
+ <input type="radio" name="disp_manager" value="xdm" {if $disp_manager == "xdm"} checked {/if}>xdm (X Display Manager (NOT recommended))<br>
+ <input type="radio" name="disp_manager" value="gdm" {if $disp_manager == "gdm"} checked {/if}>gdm (Gnome Display Manager)<br>
+ <input type="radio" name="disp_manager" value="kdm" {if $disp_manager == "kdm"} checked {/if}>kdm (KDE Display Manager)
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr height="66%">
+ <td>
+ <table width="100%" height="100%" border="1">
+ <tr>
+ <td width="50%"><b>Keymap</b><br>Choose your desired keymap:<br>
+ <select name="keymap">
+ <option value=""> </option>
+{section name=key loop=$keymap_list}
+ <option value="{$keymap_list[key]}" {if $keymap_list[key] == $keymap} selected {/if}>{$keymap_list[key]}</option>
+{/section}
+ </select><br>
+ <br><b>Windowkeys</b><br>Should we first load the 'windowkeys' console keymap?
+ <input type="radio" name="windowkeys" value="yes" {if $windowkeys == "yes"} checked {/if}> Yes <input type="radio" name="windowkeys" value="no" {if $windowkeys == "no"} checked {/if}> No <br>
+ <br><b>Extended Keymaps</b><br>This sets the maps to load for extended keyboards. Most users will leave this as is.<br>
+ <input type="text" name="ext_keymap" value="{$ext_keymap}"><br>
+ </td>
+ <td width="50%">
+ <table width="100%" height="100%" border="1">
+ <tr>
+ <td><b>Console Font</b><br>Choose your desired console font:<br>
+ <select name="font">
+ <option value=""> </option>
+ {section name=key loop=$font_list}
+ <option value="{$font_list[key]}" {if $font == $font_list[key]} selected {/if} >{$font_list[key]}</option>
+ {/section}
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td><b>Xsession</b><br>Choose what window manager you want to start default with X if run with xdm, startx, or xinit. (common options are Gnome or Xsession: <input type="text" name="xsession" value="{$xsession}"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+<input type="submit" name="SaveConfigFiles" value="Save Values">
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/daemons.tpl b/webgli/templates/daemons.tpl
new file mode 100644
index 0000000..7000d7a
--- /dev/null
+++ b/webgli/templates/daemons.tpl
@@ -0,0 +1,31 @@
+{include file="header.tpl" title="WebGLI - Daemons", advanced=$advanced}
+<h2>Cron and Logging Daemons:</h2>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+<form name="daemons" method="post" action="" enctype="multipart/form-data">
+<p>Choose which cron daemon to use for your system. While it is possible to not choose a cron daemon and still have a working system, this is NOT recommended and is considered a VERY BAD THING.<br>
+Choose your cron daemon:</p>
+<table width="100%" border="1">
+{foreach item=thiscron from=$cron_daemons key=key}
+ <tr>
+ <td><input name="cron" type="radio" value="{$key}" {if $cron eq $key} checked {/if}>{$key}</td>
+ <td>{$thiscron}</td>
+ </tr>
+{/foreach}
+</table>
+<br>
+<hr>
+<p>Choose which logging daemon to use for your system. A logger is required by the Gentoo Manual.<br>
+Choose your logging daemon:</p>
+<table width="100%" border="1">
+{foreach item=thislog from=$log_daemons key=key}
+ <tr>
+ <td><input name="logger" type="radio" value="{$key}" {if $logger eq $key} checked {/if}>{$key}</td>
+ <td>{$thislog}</td>
+ </tr>
+{/foreach}
+</table>
+<input type="submit" name="savedaemons" value="Save Daemons">
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/etc_portage.tpl b/webgli/templates/etc_portage.tpl
new file mode 100644
index 0000000..29bc1ea
--- /dev/null
+++ b/webgli/templates/etc_portage.tpl
@@ -0,0 +1,30 @@
+{include file="header.tpl" title="WebGLI - etc/portage", advanced=$advanced}
+<h3>etc/portage/* Settings:</h3>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+<form name="etcportage" method="post" action="" enctype="multipart/form-data">
+<p>Pick a file to edit:</p>
+<table width="100%" border="1">
+ <tr>
+ <th scope="col">Edit</th>
+ <th scope="col">Filename</th>
+ <th scope="col">Description</th>
+ </tr>
+{foreach item=thisfile from=$file_list key=key}
+ <tr>
+ <td><input name="editfile" type="radio" value="{$key}"></td>
+ <td>{$key}</td>
+ <td>{$thisfile}</td>
+ </tr>
+{/foreach}
+</table><br>
+<input name="fileeditsubmit" type="submit" value="EDIT">
+{if $file_to_edit}
+ <hr> Currently editing file: {$file_to_edit}<br>
+ <input type="hidden" name="currentfile" value="{$file_to_edit}">
+ <textarea name="filecontents" rows=6 cols=80>{$previous_contents}</textarea><br>
+ <input type="submit" name="save" value="Save Changes">
+{/if}
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/extrapackages.tpl b/webgli/templates/extrapackages.tpl
new file mode 100644
index 0000000..02e6eb4
--- /dev/null
+++ b/webgli/templates/extrapackages.tpl
@@ -0,0 +1,42 @@
+{include file="header.tpl" title="WebGLI - Extra Packages", advanced=$advanced}
+<h3>Extra Packages:</h3>
+<form name="packages" action="" method="POST" enctype="multipart/form-data">
+
+{foreach item=param from=$show_groups key=key}
+ {if ($param == "Expand")}
+ <input type="hidden" name="show_{$key}" value="{$param}">
+ {/if}
+{/foreach}
+
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+Your current package list is: { $current_package_list }
+<table width="100%" border="1">
+{foreach from=$package_list item=highlevel key=key}
+ <tr><th scope="col"><input type="submit" name="show_{$key}" value="{if $show_groups.$key == "Expand"}Collapse{else}Expand{/if}"></th><td>Package Name</td><th scope="col">{$key}: {$highlevel[0]}</th></tr>
+ <!-- #now show the packages in the group -->
+ {if $show_groups.$key == "Expand"}
+ {foreach item=pkg key=pkgkey from=$highlevel[1]}
+ <tr><td></td>
+ <td> <input type="checkbox" name="packages[]" value="{$pkgkey}"
+ {section loop=$install_packages name=ipkg}
+ {if $install_packages[ipkg] == $pkgkey} checked {/if}
+ {/section}
+ > {$pkgkey}</td><td>{$pkg}</td></tr>
+ {/foreach}
+ {else}
+ {foreach item=pkg key=pkgkey from=$highlevel[1]}
+ {section loop=$install_packages name=ipkg}
+ {if $install_packages[ipkg] == $pkgkey}
+ <tr><td></td><td> <input type="checkbox" name="packages[]" value="{$pkgkey}" checked>{$pkgkey}</td><td>{$pkg}</td></tr>
+ {/if}
+ {/section}
+ {/foreach}
+ {/if}
+{/foreach}
+</table>
+<br>Manually specify a comma-separated list of packages (overwrites checked list):<input type="text" name="manualpackages"><br>
+<input type="submit" name="SavePackages" value="Save Packages">
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/globaluse.tpl b/webgli/templates/globaluse.tpl
new file mode 100644
index 0000000..a995086
--- /dev/null
+++ b/webgli/templates/globaluse.tpl
@@ -0,0 +1,37 @@
+{include file="header.tpl" title="WebGLI - Global USE Flags", advanced=$advanced}
+<h2>Configuration Files Settings</h2>
+<p>Make.conf Settings:</p>
+{if $dynamic}
+<b>You have selected a dynamic stage3 installation. This setting forbids you from changing your USE flags until after the installation to prevent breaking the stage3 creation process.</b>
+{else}
+The installer will now gather information regarding the contents of /etc/make.conf
+One of the unique (and best) features of Gentoo is the ability to
+define flags (called USE flags) that define what components are
+compiled into applications. For example, you can enable the alsa
+flag and programs that have alsa capability will use it.
+The result is a finely tuned OS with no unnecessary components to
+slow you down.
+The installer divides USE flag selection into two screens, one for
+global USE flags and one for local flags specific to each program.
+Please be patient while the screens load. It may take awhile.
+<form action="localuse.php" method="POST" enctype="multipart/form-data">
+<h3>Global USE Flags:</h3><table width="100%" border="1">
+ <tr>
+ <th scope="col">Active</th>
+ <th scope="col">Flag</th>
+ <th scope="col">Description</th>
+ </tr>
+{foreach item=desc key=flag from=$use_desc}
+ <tr>
+ <td><input name="flags[]" type="checkbox" value="{$flag}">
+ <!-- if $flag in system_use_flags: print "checked" ?>> --></td>
+ <td>{$flag}</td>
+ <td>{$desc}</td>
+ </tr>
+{/foreach}
+</table>
+<br>
+<input name="saveglobaluse" type="submit" id="saveglobaluse" value="Save Global USE Settings">
+</form>
+{/if}
+{include file="bottom.tpl"}
diff --git a/webgli/templates/header.tpl b/webgli/templates/header.tpl
new file mode 100644
index 0000000..3046784
--- /dev/null
+++ b/webgli/templates/header.tpl
@@ -0,0 +1,60 @@
+{assign var=advanced value=1}
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title>{$title|default:"WebGLI"}</title>
+<link rel="stylesheet" href="webgli.css" type="text/css" />
+ <script language="JavaScript" SRC="webgli.js">
+ </script>
+</head>
+<body>
+
+<table id="layout" width="100%" height="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr id="header">
+ <td colspan="2">
+ <table width="100%" height="100%" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td width="50%">
+ <img src="images/header_bg.png" border="0" width="100%" height="64">
+ </td>
+ <td>
+ <img src="images/header.png" alt="Gentoo Linux Installer" border="0" width="400" height="64">
+ </td>
+ <td width="50%">
+ <img src="images/header_bg.png" border="0" width="100%" height="64">
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <ul id="steps">
+ <li><a class="step" href="/webgli/index.php">Welcome</a></li>
+ <li><a class="step" href="/webgli/clientconfig.php">Client Config</a></li>
+ <li><a class="step" href="/webgli/partitioning.php">Partitioning</a></li>
+ <li><a class="step" href="/webgli/networkmounts.php">Network Mounts</a></li>
+ <li><a class="step" href="/webgli/stageselection.php">Stage Selection</a></li>
+ <li><a class="step" href="/webgli/portagetree.php">Portage Tree</a></li>
+ <li><a class="step" href="/webgli/globaluse.php">Global USE Flags</a></li>
+ <li><a class="step" href="/webgli/localuse.php">Local USE Flags</a></li>
+{if $advanced}
+ <li><a class="step" href="/webgli/makedotconf.php">Make.conf</a></li>
+ <li><a class="step" href="/webgli/configfiles.php">Config Files</a></li>
+ <li><a class="step" href="/webgli/etc_portage.php">etc/portage</a></li>
+{/if}
+ <li><a class="step" href="/webgli/kernel.php">Kernel</a></li>
+ <li><a class="step" href="/webgli/bootloader.php">Bootloader</a></li>
+ <li><a class="step" href="/webgli/timezone.php">Timezone</a></li>
+ <li><a class="step" href="/webgli/networking.php">Networking</a></li>
+ <li><a class="step" href="/webgli/daemons.php">Daemons</a></li>
+ <li><a class="step" href="/webgli/extrapackages.php">Extra Packages</a></li>
+ <li><a class="step" href="/webgli/services.php">Services</a></li>
+ <li><a class="step" href="/webgli/users.php">Users</a></li>
+ <li><a class="step" href="/webgli/review.php">Review</a></li>
+ </ul>
+ <ul id="menu">
+ <li><a href="/webgli/saveprofile.php">Save Profile</a></li>
+ <li><a href="/webgli/loadprofile.php">Load Profile</a></li>
+ </ul>
+ </td>
+ <td id="content" width="100%" valign="top">
diff --git a/webgli/templates/index.tpl b/webgli/templates/index.tpl
new file mode 100644
index 0000000..6e334f4
--- /dev/null
+++ b/webgli/templates/index.tpl
@@ -0,0 +1 @@
+{include file="header.tpl" title="WebGLI - Main Page", advanced=$advanced}
diff --git a/webgli/templates/kernel.tpl b/webgli/templates/kernel.tpl
new file mode 100644
index 0000000..afb3931
--- /dev/null
+++ b/webgli/templates/kernel.tpl
@@ -0,0 +1,42 @@
+{include file="header.tpl" title="WebGLI - Daemons", advanced=$advanced}
+<h2>Kernel Settings:</h2>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+<form name="kernel" method="post" action="" enctype="multipart/form-data">
+<p>Choose which kernel sources to use for your system. If using a previously-made kernel configuration, make sure the sources match the kernel used to create the configuration.</p>
+<table width="100%" border="1">
+{foreach item=thissource from=$kernels key=key}
+ <tr>
+ <td><input name="sources" type="radio" value="{$key}" {if $sources eq $key} checked {/if}>{$key}</td>
+ <td>{$thissource[0]}</td>
+ <td>{$thissource[1]}</td>
+ </tr>
+{/foreach}
+{if $advanced}
+ <tr>
+ <td><input name="sources" type="radio" value="Other">Other</td>
+ <td>Specify your own here: <input name="manualsources" type="text" id="manualsources" value="{if $cust_source} {$sources}{/if}"></td>
+ </tr>
+{/if}
+</table>
+<hr>
+{if $advanced}
+<table width="507" border="1">
+ <tr>
+ <td colspan="2" scope="col"><p>There are currently two ways the installer can compile a kernel for your new system. You can either provide a previously-made kernel configuration file and use the traditional kernel-compiling procedure (no initrd) or have genkernel automatically create your kernel for you (with initrd).</p>
+ <p>If you do not have a previously-made kernel configuration, YOU MUST CHOOSE Genkernel. Choose which method you want to use:</p></td>
+ </tr>
+ <tr>
+ <td width="143" scope="col"><input name="build_method" type="radio" value="genkernel" {if $build_method == "genkernel"} checked {/if}>Genkernel</td>
+ <td width="348" scope="col"><input name="build_method" type="radio" value="custom" {if $build_method == "custom"} checked {/if}>Traditional (requires a config!)</td>
+ </tr>
+</table>
+<p><input name="bootsplash" type="checkbox" id="bootsplash" value="True" {if $bootsplash} checked {/if}>Display the bootsplash screen on startup </p><p>If you have a custom kernel configuration, enter its location (otherwise just leave blank):
+<input name="configuri" type="text" id="configuri" value="{$configuri}">
+<input name="browseuri" type="button" id="browseuri" value="Browse" onClick="window.open('/webgli/URIBrowser?screen=kernel&baseuri=' + document.kernel.configuri.value, 'uribrowser', 'width=500,height=500,toolbars=no,statusbar=no,menubar=no,scrollbars=yes')">
+</p>
+{/if}
+<p><input name="setkernel" type="submit" id="setkernel" value="Save Kernel Settings"></p>
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/localuse.tpl b/webgli/templates/localuse.tpl
new file mode 100644
index 0000000..e32e5dc
--- /dev/null
+++ b/webgli/templates/localuse.tpl
@@ -0,0 +1,39 @@
+{include file="header.tpl" title="WebGLI - Local USE Flags", advanced=$advanced}
+<h2>Configuration Files Settings</h2>
+<p>Make.conf Settings:</p>
+{if $dynamic}
+<b>You have selected a dynamic stage3 installation. This setting forbids you from changing your USE flags until after the installation to prevent breaking the stage3 creation process.</b>
+{else}
+The installer will now gather information regarding the contents of /etc/make.conf
+One of the unique (and best) features of Gentoo is the ability to
+define flags (called USE flags) that define what components are
+compiled into applications. For example, you can enable the alsa
+flag and programs that have alsa capability will use it.
+The result is a finely tuned OS with no unnecessary components to
+slow you down.
+The installer divides USE flag selection into two screens, one for
+global USE flags and one for local flags specific to each program.
+Please be patient while the screens load. It may take awhile.
+<form action="" method="POST" enctype="multipart/form-data">
+<input type="hidden" name="globalflags" value="{$global_use_flags}">
+<h3>Local USE Flags:</h3>
+<table width="100%" border="1">
+ <tr>
+ <th scope="col">Active</th>
+ <th scope="col">Flag</th>
+ <th scope="col">Description</th>
+ </tr>
+ {foreach item=desc key=flag from=$use_local_desc}
+ <tr>
+ <td><input name="flags[]" type="checkbox" value="{$flag}">
+ <!-- if $flag in system_use_flags: print "checked" ?>> --></td>
+ <td>{$flag}</td>
+ <td>{$desc}</td>
+ </tr>
+{/foreach}
+</table>
+<br>
+<input name="savelocaluse" type="submit" id="savelocaluse" value="Save Local USE Settings">
+</form>
+{/if}
+{include file="bottom.tpl"}
diff --git a/webgli/templates/makedotconf.tpl b/webgli/templates/makedotconf.tpl
new file mode 100644
index 0000000..4adbb6b
--- /dev/null
+++ b/webgli/templates/makedotconf.tpl
@@ -0,0 +1,62 @@
+{include file="header.tpl" title="WebGLI - Make.conf Settings", advanced=$advanced}
+<b>Make.conf Settings:</b><br>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+{if $dynamic}
+<b>You have selected a dynamic stage3 installation. This setting forbids you from changing some make.conf settings until after the installation to prevent breaking the stage3 creation process.</b>
+{else}
+<b>NOTE: Your old values are NOT loaded here. Do not save these settings without making sure all values are what you want. To keep your old values just skip this step.</b>
+<form action="" method="POST" enctype="multipart/form-data">
+<h3>CFLAGS Settings: </h3>
+<table width="100%" border="1">
+ <tr>
+ <td scope="col"><div align="left">Processor:<select name="proc" id="proc">
+
+{section name=proc loop=$procs}
+ <option value="{$procs[proc]}">{$procs[proc]}</option>
+{/section}
+ </select><br><input type="radio" name="m_thing" value="-march">-march <input type="radio" name="m_thing" value="-mcpu">-mcpu <input type="radio" name="m_thing" value="-mtune">-mtune </div></td>
+ <td scope="col">Optimizations: <select name="optim1" id="optim1">
+{section name=bigo loop=$bigO}
+ <option value="-O{$smarty.section.bigo.index }">{$bigO[bigo]}</option>
+{/section}
+ </select></td>
+ </tr>
+ <tr>
+ <td>Common CFLAGS:<br><input name="optim2[]" type="checkbox" value="-pipe">-pipe<br><input name="optim2[]" type="checkbox" value="-fomit-frame-pointer">-fomit-frame-pointer</td>
+ <td>Additional CFLAGS: <input name="optim3" type="text" id="optim3" size="60"></td>
+ </tr>
+</table>
+<hr>
+<h3>CHOST Setting:</h3>
+<select name="chost" size="4" id="chost" {if $dynamic} disabled {/if}>
+{section name=key loop=$arch_chost_options}
+<option value="{$arch_chost_options[key]}">{$arch_chost_options[key]}</option>
+{/section}
+</select>
+<hr>
+<table width="100%" border="1">
+ <tr>
+ <td scope="col"><input name="unstable" type="checkbox" id="unstable" value="unstable" {if $dynamic} disabled {/if}> Use unstable (~arch) </td>
+ <td scope="col"><input name="features[]" type="checkbox" id="binary" value="buildpkg"> Build binary packages (buildpkg)</td>
+ <td scope="col"><input name="features[]" type="checkbox" id="ccache" value="ccache"> ccache</td>
+ <td scope="col"><input name="features[]" type="checkbox" id="sandbox" value="sandbox"> sandbox</td>
+ </tr>
+ <tr>
+ <td scope="col"><input name="features[]" type="checkbox" id="distlocks" value="distlocks"> distlocks</td>
+ <td scope="col"><input name="features[]" type="checkbox" id="prelink" value="prelink"> prelink</td>
+ <td scope="col">More Features: <input name="manfeatures" type="text" id="manfeatures" size="10"></td>
+ <td scope="col">MAKEOPTS: <input name="makeopts" type="text" id="makeopts" value="-j2" size="10" maxlength="5"></td>
+ </tr>
+ <tr>
+ <td scope="col"><input name="features[]" type="checkbox" id="distcc" value="distcc"> Distcc</td>
+ <td>Distcc Config Line:<input name="distcc" type="text" size="80"></td>
+ </tr>
+</table>
+<p>
+<input name="savemakeconf" type="submit" id="savemakeconf" value="Save Make.Conf Settings">
+</p>
+</form>
+{/if}
+{include file="bottom.tpl"}
diff --git a/webgli/templates/networkmounts.tpl b/webgli/templates/networkmounts.tpl
new file mode 100644
index 0000000..5e147ee
--- /dev/null
+++ b/webgli/templates/networkmounts.tpl
@@ -0,0 +1,51 @@
+{include file="header.tpl" title="WebGLI - Network Mounts", advanced=$advanced}
+</h3>Network Mounts</h3>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+If you have any network shares you would like to mount during the install and for your new system, define them here. Select a network mount to edit or add a new mount. Currently GLI only supports NFS mounts.
+<form name="netmount" action="" method="POST" enctype="multipart/form-data">
+<p>If you have any network shares you would like to mount during the install and for your new system, define them here. Select a network mount to edit or add a new mount. Currently GLI only supports NFS mounts.</p>
+<table width="511" border="1">
+ <tr>
+ <td width="31">Edit</td>
+ <td width="31">Type</td>
+ <td width="79">Hostname/IP</td>
+ <td width="79">Export</td>
+ <td width="70">Mountpoint</td>
+ <td width="103">Mount Options </td>
+ </tr>
+{section name=i loop=$network_mounts} <!-- for i,netmount in enumerate(network_mounts): -->
+ <tr>
+ <td><input name="edit_nfs" type="radio" id="edit_nfs" value="{$i}">Edit</td>
+ <td>{$network_mounts[i].type }</td>
+ <td>{$network_mounts[i].host }</td>
+ <td>{$network_mounts[i].export }</td>
+ <td>{$network_mounts[i].mountpoint }</td>
+ <td>{$network_mounts[i].mountopts }</td>
+ </tr>
+{/section}
+</table>
+<hr>
+<p>&nbsp; </p>
+<table width="100%" border="1">
+ <tr>
+ <td><p>Enter the IP/hostname: <input name="hostname" type="text" id="hostname"> <input type="Submit" name="Search" value="Search"></p>
+ <p>Enter the export name: <input name="export" type="text" id="export"></p>
+ <p>OR</p>
+ <p>Choose the export from the list of found exports: <select name="exports" size="1" id="exports"></select></p>
+ </td>
+ <td><p>Enter the mountpoint: <input name="mountpoint" type="text" id="mountpoint"></p>
+ <p>Enter any special mount options: <input name="mountopts" type="text" id="mountopts"></p>
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td><input name="addnfs" type="submit" id="addnfs" value="Add New NFS Mount"></td>
+ </tr>
+</table>
+<p>&nbsp;</p>
+<p>&nbsp;</p>
+<p>&nbsp;</p>
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/portagetree.tpl b/webgli/templates/portagetree.tpl
new file mode 100644
index 0000000..15a412a
--- /dev/null
+++ b/webgli/templates/portagetree.tpl
@@ -0,0 +1,34 @@
+{include file="header.tpl" title="WebGLI - Portage Tree", advanced=$advanced}
+<p>Portage Tree Sync Type:</p>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+{if $dynamic}
+<p><b>Since you are doing a dynamic stage3 install, it requires the use of the portage snapshot contained on the livecd. This has been auto-set.</b></p>
+{else}
+<form name="portage" action="" method="POST" enctype="multipart/form-data">
+<p>Which method do you want to use to sync the portage tree for the installation? If choosing a snapshot you will need to provide the URI for the snapshot if it is not on the livecd.</p>
+<table width="100%" border="1">
+ <tr>
+ <td><input name="portagetype" type="radio" value="sync" {if $synctype == "sync"} checked {/if}>Sync</td>
+ <td>Normal. Use emerge sync RECOMMENDED!</td>
+ </tr>
+ <tr>
+ <td><input name="portagetype" type="radio" value="webrsync" {if $synctype == "webrsync"} checked {/if}>Webrsync</td>
+ <td>HTTP daily snapshot. Use when rsync is firewalled.</td>
+ </tr>
+ <tr>
+ <td><input name="portagetype" type="radio" value="snapshot" {if $synctype == "snapshot"} checked {/if}>Snapshot</td>
+ <td>Use a portage snapshot, either a local file or a URL</td>
+ </tr>
+ <tr>
+ <td><input name="portagetype" type="radio" value="none" {if $synctype == "none"} checked {/if}>None</td>
+ <td>Extra cases such as if /usr/portage is an NFS mount</td>
+ </tr>
+</table>
+<p>Snapshot URI (if doing shapshot): <input name="snapshoturi" type="text" id="snapshoturi" size="90" value="{$snapshoturi}"> or </p>
+<input type="button" value="Browse the mirrors for the URL" onClick="window.open('/webgli/URIBrowser?screen=portage&baseuri=' + document.portage.snapshoturi.value, 'uribrowser', 'width=500,height=500,toolbars=no,statusbar=no,menubar=no,scrollbars=yes')">
+<p><input type="submit" name="saveportage" value="Save Portage Settings">
+</form>
+{/if}
+{include file="bottom.tpl"}
diff --git a/webgli/templates/review.tpl b/webgli/templates/review.tpl
new file mode 100644
index 0000000..b05dfce
--- /dev/null
+++ b/webgli/templates/review.tpl
@@ -0,0 +1,5 @@
+{include file="header.tpl" title="WebGLI - Review", advanced=$advanced}
+<pre>
+{$data}
+</pre>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/services.tpl b/webgli/templates/services.tpl
new file mode 100644
index 0000000..8d782d9
--- /dev/null
+++ b/webgli/templates/services.tpl
@@ -0,0 +1,26 @@
+{include file="header.tpl" title="WebGLI - Services", advanced=$advanced}
+<h3>Services</h3>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+Choose the services you want started on bootup. Note that depending on what packages are selected, some services listed will not exist.
+<form name="services" method="post" action="" enctype="multipart/form-data">
+<table border="1">
+ <tr>
+ <td>Activate</td>
+ <td>Service</td>
+ <td>Description</td>
+ </tr>
+{foreach from=$choices item=value key=key}
+ <tr>
+ <td><input type="checkbox" name="services[]" value="{$key}" {if in_array($key,$services) } checked {/if}></td>
+ <td>{$key}</td>
+ <td>{$value}</td>
+ </tr>
+{/foreach}
+</table>
+<hr>You can also opt to enter your services in a comma-separated list (NOTE Manual list overwrites checked selections!):
+<input type="text" name="servicesmanual" value="{$manualservices}"><br>
+<input type="submit" name="saveservices" value="Save Services">
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/stageselection.tpl b/webgli/templates/stageselection.tpl
new file mode 100644
index 0000000..f11eb0a
--- /dev/null
+++ b/webgli/templates/stageselection.tpl
@@ -0,0 +1,34 @@
+{include file="header.tpl" title="WebGLI - Stage Selection", advanced=$advanced}
+<h4>Stage selection:</h4>
+{if $error_msg }
+<br><br>{$error_msg}<br><br>
+{/if}
+<form name="stage" action="" method="POST" enctype="multipart/form-data">
+<p>Which stage do you want to start at?</p>
+<table width="100%" border="1">
+ <tr>
+ <td><input name="stage" type="radio" value="1" {if $stage == 1} checked {/if}>1</td>
+ <td>Stage1 is used when you want to bootstrap&amp;build from scratch.</td>
+ </tr>
+ <tr>
+ <td><input name="stage" type="radio" value="2" {if $stage == 2} checked {/if}>2</td>
+ <td>Stage2 is used for building from a bootstrapped semi-compiled state.</td>
+ </tr>
+ <tr>
+ <td><input name="stage" type="radio" value="3" {if ($stage == 3) and (!$grp_install)} checked {/if}>3</td>
+ <td>Stage3 is a basic system that has been built for you (no compiling).</td>
+ </tr>
+ <tr>
+ <td><input name="stage" type="radio" value="3+GRP" {if ($stage == 3) and $grp_install} checked {/if}>3 + GRP </td>
+ <td>A Stage3 install but using binaries from the LiveCD when able.</td>
+ </tr>
+</table>
+<p>
+<input name="dynamic" type="checkbox" id="dynamic" value="true" {if $dynamic} checked {/if}>
+Generate a dynamic stage3 on the fly using the files on the LiveCD? (faster for slow Internet connections, slower for fast connections and slow drives) </p>
+<p>Stage Tarball URI: <input name="tarballuri" type="text" id="tarballuri" size="90" value="{$tarball}"> or
+<input type="button" value="Browse the mirrors for the URL" onClick="window.open('/webgli/URIBrowser?screen=stage&baseuri=' + document.stage.tarballuri.value, 'uribrowser', 'width=500,height=500,toolbars=no,statusbar=no,menubar=no,scrollbars=yes')">
+(requires net connectivity)</p>
+<p><input type="submit" name="savestage" value="Save Stage Selection">
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/templates/timezone.tpl b/webgli/templates/timezone.tpl
new file mode 100644
index 0000000..fc3477d
--- /dev/null
+++ b/webgli/templates/timezone.tpl
@@ -0,0 +1,15 @@
+{include file="header.tpl" title="WebGLI - Timezone Selection", advanced=$advanced}
+<h2>Timezone Setup </h2>
+{if $error_msg}
+<br>{$error_msg}<br><br>
+{/if}
+Your current timezone is: {$current}<br>
+Timezones:<br>
+<form name="Timezone" method="post" action="" enctype="multipart/form-data">
+<input type="hidden" name="tzback" value="{$tzback}"><br>
+{section name=tz loop=$tzlist}
+<a href="timezone.php?zonepath={$zonepath}{$tzlist[tz]}">{$tzlist[tz]}</a><br>
+{/section}
+<br><input type="submit" name="back" value="Back">
+</form>
+{include file="bottom.tpl"}
diff --git a/webgli/timezone.php b/webgli/timezone.php
new file mode 100644
index 0000000..4363e92
--- /dev/null
+++ b/webgli/timezone.php
@@ -0,0 +1,71 @@
+<?php
+
+include('webgliIP.php');
+include('webgliUtility.php');
+
+include('Smarty.class.php');
+$smarty = new Smarty;
+
+$smarty->template_dir = './templates';
+$smarty->compile_dir = './templates_c';
+$smarty->cache_dir = './cache';
+$smarty->config_dir = './configs';
+
+$ip = new InstallProfile();
+$ip->parse('test.xml');
+
+
+$error_msg = "";
+if ($_GET['zonepath']) {
+ $zonepath = $_GET['zonepath'];
+ if (is_dir($zonepath)) {
+ $zonepath .= "/";
+ }
+ print "I got me a zonepath: $zonepath";
+
+ if ( substr($zonepath,-1) != '/') {
+ $ip->set("time_zone",substr($zonepath,20));
+ $error_msg .= "Timezone saved.<br>";
+ #$error_msg .= "ERROR: Could not set that timezone!";
+ #SAVE VALUES
+ file_put_contents('test.xml', $ip->serialize()); #PHP 5 only
+ }
+
+} else {
+ $zonepath = "/usr/share/zoneinfo/";
+}
+if ($_POST['back']) {
+ $zonepath = $_POST['tzback'];
+}
+
+$smarty->assign('tzback',"/usr/share/zoneinfo/");
+$smarty->assign('zonepath', $zonepath);
+
+$skiplist = array("zone.tab","iso3166.tab","posixrules", '../', './' );
+if (is_dir($zonepath)) {
+ $temp_tzlist = scandir($zonepath); #PHP 5 only.
+
+} else {
+ $temp_tzlist = array();
+}
+$tzlist = array();
+foreach ($temp_tzlist as $tz) {
+ if (!in_array($tz, $skiplist) ) {
+ if (is_dir($tz)) {
+ $tz .= "/";
+ }
+ array_push($tzlist, $tz);
+ }
+}
+sort($tzlist);
+
+#print "TZList: ";
+#print_r($tzlist);
+#print "Zonepath: ";
+#print_r($zonepath);
+
+$smarty->assign('current',$ip->get("time_zone"));
+$smarty->assign('error_msg',$error_msg);
+$smarty->assign('tzlist',$tzlist);
+$smarty->display('timezone.tpl');
+?>
diff --git a/webgli/webgli.css b/webgli/webgli.css
new file mode 100644
index 0000000..41f253b
--- /dev/null
+++ b/webgli/webgli.css
@@ -0,0 +1,107 @@
+html {
+ margin: 0px;
+}
+body {
+ margin: 0px;
+ font-family: Bitstream Vera Sans, Helvetica, Sans;
+ font-size: 10pt;
+}
+table {
+ border-spacing: 0px;
+}
+td {
+ padding: 0px;
+}
+p {
+ margin-top: 0px;
+ margin-bottom: 5px;
+}
+ul {
+ margin: 0px;
+ padding: 0px;
+ border-top: 1px solid #ffffff;
+ border-bottom: 10px solid #ffffff;
+}
+li {
+ width: 150px;
+ border-right: 1px solid #ffffff;
+ border-bottom: 1px solid #ffffff;
+}
+#content {
+ padding-top: 7px;
+ padding-left: 7px;
+}
+.title {
+ font-size: 1.2em;
+ font-weight: bold;
+}
+a.step {
+ display: block;
+ position: relative;
+ width: 100%;
+ padding: 1px;
+ background-color: #d8d4e2;
+ color: #000000;
+ text-decoration: none;
+}
+a.step:hover {
+ background: #7e60e2 url("images/arrow_l.gif") no-repeat scroll right;
+}
+.currentstep {
+ padding: 1px;
+ background: #ffffff url("images/arrow_r.gif") no-repeat scroll right;
+ font-weight: bold;
+ cursor: default;
+}
+a.menuitem {
+ display: block;
+ position: relative;
+ padding: 1px;
+ background-color: #d8d4e2;
+ color: #000000;
+ text-decoration: none;
+}
+a.menuitem:hover {
+ background: #7e60e2 url("images/arrow_l.gif") no-repeat scroll right;
+}
+.partition {
+ display: table;
+ background: #d8d4e2 url("images/partition_bg.png") no-repeat;
+}
+.partition_drag {
+ padding-right: 15px;
+ height: 30px;
+ background: transparent url("images/partition_drag.png") no-repeat scroll top right;
+ cursor: w-resize;
+ overflow: hidden;
+ position: relative;
+}
+.partition_drag[class] {
+ position: static;
+ display: table;
+}
+.partition_inner {
+ cursor: default;
+ position: absolute;
+ top: 50%;
+}
+.partition_inner[class] {
+ position: static;
+ display: table-cell;
+ vertical-align: middle;
+}
+.partition_free {
+ height: 18px;
+ margin-left: 6px;
+ border-right: 4px solid #d8d4e2;
+ background-color: #ffffff;
+ position: relative;
+ top: -50%;
+}
+.partition_free[class] {
+ position: static;
+}
+.partition_used {
+ height: 18px;
+ background-color: #00ffff;
+}
diff --git a/webgli/webgli.js b/webgli/webgli.js
new file mode 100644
index 0000000..00dd4ab
--- /dev/null
+++ b/webgli/webgli.js
@@ -0,0 +1,80 @@
+ function browserType() {
+ var type;
+ if (document.layers) {
+ type = 'nn4';
+ }
+ if (document.all) {
+ type = 'ie';
+ }
+ if (window.navigator.userAgent.toLowerCase().match("gecko")) {
+ type = 'gecko';
+ }
+ return type;
+ }
+ var browser_type = browserType();
+ function findLayer(name) {
+ var layer;
+ if (browser_type == 'gecko') {
+ layer = eval('document.getElementById(\'' + name + '\')');
+ } else if (browser_type == 'ie') {
+ layer = eval('document.all[\'' + name + '\']');
+ } else {
+ layer = eval('document.layers[\'' + name + '\']');
+ }
+ return layer;
+ }
+ var resizeOb = new Object();
+ function resizeStart(event) {
+ var x;
+ if (browser_type == 'ie') {
+ resizeOb.layer = window.event.srcElement;
+ x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
+ } else {
+ resizeOb.layer = event.target;
+ x = event.clientX + window.scrollX;
+ }
+ resizeOb.startX = x;
+ resizeOb.startW = parseInt(resizeOb.layer.style.width, 10);
+ if (isNaN(resizeOb.startW)) {
+ resizeOb.startW = 0;
+ }
+ if (browser_type == 'ie') {
+ document.attachEvent("onmousemove", resizeMove);
+ document.attachEvent("onmouseup", resizeStop);
+ window.event.cancelBubble = true;
+ window.event.returnValue = false;
+ } else {
+ document.addEventListener("mousemove", resizeMove, true);
+ document.addEventListener("mouseup", resizeStop, true);
+ event.preventDefault();
+ }
+ }
+ function resizeMove(event) {
+ var x, w;
+ if (browser_type == 'ie') {
+ x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
+ } else {
+ x = event.clientX + window.scrollX;
+ }
+ w = (resizeOb.startW + (x - resizeOb.startX));
+ if (w <= (parseInt(resizeOb.layer.parentNode.style.width, 10) - (15 + 4))) {
+ if (w >= (parseInt(findLayer('partition_used').style.width, 10) + 10)) {
+ resizeOb.layer.style.width = w + 'px';
+ }
+ }
+ if (browser_type == 'ie') {
+ window.event.cancelBubble = true;
+ window.event.returnValue = false;
+ } else {
+ event.preventDefault();
+ }
+ }
+ function resizeStop(event) {
+ if (browser_type == 'ie') {
+ document.detachEvent("onmousemove", resizeMove);
+ document.detachEvent("onmouseup", resizeStop);
+ } else {
+ document.removeEventListener("mousemove", resizeMove, true);
+ document.removeEventListener("mouseup", resizeStop, true);
+ }
+ }
diff --git a/webgli/webgliCF.php b/webgli/webgliCF.php
new file mode 100644
index 0000000..1d90b5f
--- /dev/null
+++ b/webgli/webgliCF.php
@@ -0,0 +1,62 @@
+<?
+require_once('XMLParser.php');
+
+class ClientConfiguration extends XMLParser {
+
+ function ClientConfiguration() {
+ $this->xmldoc = "";
+
+ $this->values = array(
+ 'architecture_template' => array( 'type' => 'string', 'value' => 'x86' ),
+ 'dns_servers' => array( 'type' => 'array', 'value' => array() ),
+ 'enable_ssh' => array( 'type' => 'bool', 'value' => 0 ),
+ 'ftp_proxy' => array( 'type' => 'string', 'value' => "" ),
+ 'http_proxy' => array( 'type' => 'string', 'value' => "" ),
+ 'install_mode' => array( 'type' => 'string', 'value' => "" ),
+ 'interactive' => array( 'type' => 'bool', 'value' => 0 ),
+ 'kernel_modules' => array( 'type' => 'array', 'value' => array() ),
+ 'log_file' => array( 'type' => 'string', 'value' => "/var/log/installer.log" ),
+ 'network_broadcast' => array( 'type' => 'string', 'value' => "" ),
+ 'network_dhcp_options' => array( 'type' => 'string', 'value' => "" ),
+ 'network_interface' => array( 'type' => 'string', 'value' => "" ),
+ 'network_ip' => array( 'type' => 'string', 'value' => "" ),
+ 'network_gateway' => array( 'type' => 'string', 'value' => "" ),
+ 'network_netmask' => array( 'type' => 'string', 'value' => "" ),
+ 'network_type' => array( 'type' => 'string', 'value' => "" ),
+ 'profile_uri' => array( 'type' => 'uri', 'value' => "" ),
+ 'root_mount_point' => array( 'type' => 'string', 'value' => "/mnt/gentoo" ),
+ 'root_passwd' => array( 'type' => 'string', 'value' => "" ),
+ 'rsync_proxy' => array( 'type' => 'string', 'value' => "" ),
+ 'verbose' => array( 'type' => 'bool', 'value' => 0 ),
+ );
+
+ $this->xmlpaths = array(
+ 'client-configuration/architecture-template' => 'architecture_template',
+ 'client-configuration/dns-servers' => 'dns_servers',
+ 'client-configuration/enable-ssh' => 'enable_ssh',
+ 'client-configuration/ftp-proxy' => 'ftp_proxy',
+ 'client-configuration/http-proxy' => 'http_proxy',
+ 'client-configuration/install-mode' => 'install_mode',
+ 'client-configuration/interactive' => 'interactive',
+ 'client-configuration/kernel-modules' => 'kernel_modules',
+ 'client-configuration/log-file' => 'log_file',
+ 'client-configuration/network-broadcast' => 'network_broadcast',
+ 'client-configuration/network-interface' => 'network_interface',
+ 'client-configuration/network-ip' => 'network_ip',
+ 'client-configuration/network-dhcp-options' => 'network_dhcp_options',
+ 'client-configuration/network-gateway' => 'network_gateway',
+ 'client-configuration/network-type' => 'network_type',
+ 'client-configuration/profile-uri' => 'profile_uri',
+ 'client-configuration/root-mount-point' => 'root_mount_point',
+ 'client-configuration/root-passwd' => 'root_passwd',
+ 'client-configuration/rsync-proxy' => 'rsync_proxy',
+ 'client-configuration/verbose' => 'verbose',
+ );
+ }
+
+ function serialize() {
+ return $this->_serialize("client-configuration");
+ }
+
+}
+?>
diff --git a/webgli/webgliIP.php b/webgli/webgliIP.php
new file mode 100644
index 0000000..60dcbe9
--- /dev/null
+++ b/webgli/webgliIP.php
@@ -0,0 +1,313 @@
+<?
+require_once('XMLParser.php');
+
+class InstallProfile extends XMLParser {
+ /*
+ An object representation of a profile.
+ InstallProfile is an object representation of a parsed installation
+ profile file.
+ */
+
+ ##
+ # Initializes all variables to default values and adds handlers.
+ # Configuration information - profile data
+ # All variables must be declared here with a default value to ensure
+ # the XML will correctly serialize.
+
+ function InstallProfile() {
+ $this->_temp_etc_file = array();
+ $this->_temp_partition_table = array();
+ $this->xmldoc = "";
+
+ $this->values = array(
+ 'boot_device' => array( 'type' => 'string', value => '' ),
+ 'bootloader_kernel_args' => array( 'type' => 'string', 'value' => "" ),
+ 'bootloader_mbr' => array( 'type' => 'bool', 'value' => 1 ),
+ 'bootloader_pkg' => array( 'type' => 'string', 'value' => 'grub' ),
+ 'cron_daemon_pkg' => array( 'type' => 'string', 'value' => 'vixie-cron' ),
+ 'default_gateway' => array( 'type' => 'array', 'value' => array(), 'serialize_func' => 'serialize_default_gateway' ),
+ 'dns_servers' => array( 'type' => 'array', 'value' => array() ),
+ 'domainname' => array( 'type' => 'string', 'value' => "localdomain" ),
+ 'dynamic_stage3' => array( 'type' => 'bool', 'value' => 0 ),
+ 'etc_files' => array( 'type' => 'array', 'value' => array(), 'serialize_func' => 'serialize_etc_files' ),
+ 'ftp_proxy' => array( 'type' => 'string', 'value' => "" ),
+ 'grp_install' => array( 'type' => 'bool', 'value' => 0 ),
+ 'hostname' => array( 'type' => 'string', 'value' => "localhost" ),
+ 'http_proxy' => array( 'type' => 'string', 'value' => "" ),
+ 'install_distcc' => array( 'type' => 'bool', 'value' => 0 ),
+ 'install_packages' => array( 'type' => 'array', 'value' => array() ),
+ 'install_pcmcia_cs' => array( 'type' => 'bool', 'value' => 0 ),
+ 'install_rp_pppoe' => array( 'type' => 'bool', 'value' => 0 ),
+ 'install_stage' => array( 'type' => 'int', 'value' => 3 ),
+ 'logging_daemon_pkg' => array( 'type' => 'string', 'value' => 'syslog-ng' ),
+ 'kernel_bootsplash' => array( 'type' => 'bool', 'value' => 0 ),
+ 'kernel_build_method' => array( 'type' => 'string', 'value' => 'genkernel' ),
+ 'kernel_config_uri' => array( 'type' => 'uri', 'value' => '' ),
+ 'kernel_modules' => array( 'type' => 'array', 'value' => array() ),
+ 'kernel_initrd' => array( 'type' => 'bool', 'value' => 1 ),
+ 'kernel_source_pkg' => array( 'type' => 'string', 'value' => "livecd-kernel" ),
+ 'mta_pkg' => array( 'type' => 'string', 'value' => "" ),
+ 'network_mounts' => array( 'type' => 'array', 'value' => array(), 'serialize_func' => 'serialize_network_mounts' ),
+ 'network_interfaces' => array( 'type' => 'array', 'value' => array(), 'serialize_func' => 'serialize_network_interfaces' ),
+ 'nisdomainname' => array( 'type' => 'string', 'value' => "" ),
+ 'partition_tables' => array( 'type' => 'array', 'value' => array(), 'serialize_func' => 'serialize_partition_tables' ),
+ 'portage_tree_snapshot_uri' => array( 'type' => 'uri', 'value' => "" ),
+ 'portage_tree_sync_type' => array( 'type' => 'string', 'value' => "sync" ),
+ 'post_install_script_uri' => array( 'type' => 'uri', 'value' => "" ),
+ 'root_pass_hash' => array( 'type' => 'string', 'value' => "" ),
+ 'rsync_proxy' => array( 'type' => 'string', 'value' => "" ),
+ 'services' => array( 'type' => 'array', 'value' => array() ),
+ 'stage_tarball_uri' => array( 'type' => 'uri', 'value' => "" ),
+ 'time_zone' => array( 'type' => 'string', 'value' => "UTC" ),
+ 'users' => array( 'type' => 'array', 'value' => array(), 'serialize_func' => 'serialize_users' ),
+ );
+
+ $this->xmlpaths = array(
+ 'gli-profile/bootloader' => 'bootloader_pkg',
+ 'gli-profile/boot-device' => 'boot_device',
+ 'gli-profile/bootloader-kernel-args' => 'bootloader_kernel_args',
+ 'gli-profile/bootloader-mbr' => 'bootloader_mbr',
+ 'gli-profile/cron-daemon' => 'cron_daemon_pkg',
+ 'gli-profile/default-gateway' => 'parse_default_gateway',
+ 'gli-profile/dns-servers' => 'dns_servers',
+ 'gli-profile/domainname' => 'domainname',
+ 'gli-profile/dynamic-stage3' => 'dynamic_stage3',
+ 'gli-profile/etc-files/file' => 'parse_etc_files_file',
+ 'gli-profile/etc-files/file/entry' => 'parse_etc_files_file_entry',
+ 'gli-profile/ftp-proxy' => 'ftp_proxy',
+ 'gli-profile/grp-install' => 'grp_install',
+ 'gli-profile/hostname' => 'hostname',
+ 'gli-profile/http-proxy' => 'http_proxy',
+ 'gli-profile/install-distcc' => 'install_distcc',
+ 'gli-profile/install-packages' => 'install_packages',
+ 'gli-profile/install-pcmcia-cs' => 'install_pcmcia_cs',
+ 'gli-profile/install-rp-pppoe' => 'install_rp_pppoe',
+ 'gli-profile/install-stage' => 'install_stage',
+ 'gli-profile/kernel-bootsplash' => 'kernel_bootsplash',
+ 'gli-profile/kernel-build-method' => 'kernel_build_method',
+ 'gli-profile/kernel-config' => 'kernel_config_uri',
+ 'gli-profile/kernel-initrd' => 'kernel_initrd',
+ 'gli-profile/kernel-modules' => 'kernel_modules',
+ 'gli-profile/kernel-source' => 'kernel_source_pkg',
+ 'gli-profile/logging-daemon' => 'logging_daemon_pkg',
+ 'gli-profile/mta' => 'mta_pkg',
+ 'gli-profile/network-interfaces/device' => 'parse_network_interface',
+ 'gli-profile/network-mounts/netmount' => 'parse_netmount',
+ 'gli-profile/nisdomainname' => 'nisdomainname',
+ 'gli-profile/partitions/device' => 'parse_partitions_device',
+ 'gli-profile/partitions/device/partition' => 'parse_partitions_device_partition',
+ 'gli-profile/portage-snapshot' => 'portage_tree_snapshot_uri',
+ 'gli-profile/portage-tree-sync' => 'portage_tree_sync_type',
+ 'gli-profile/post-install-script-uri' => 'post_install_script_uri',
+ 'gli-profile/root-pass-hash' => 'root_pass_hash',
+ 'gli-profile/rsync-proxy' => 'rsync_proxy',
+ 'gli-profile/services' => 'services',
+ 'gli-profile/stage-tarball' => 'stage_tarball_uri',
+ 'gli-profile/time-zone' => 'time_zone',
+ 'gli-profile/users/user' => 'parse_user',
+ );
+ }
+
+ function serialize() {
+ return $this->_serialize("gli-profile");
+ }
+
+ function parse_default_gateway($gateway, $attr) {
+ $this->set("default_gateway", array($attr['interface'], $gateway));
+ }
+
+ function serialize_default_gateway() {
+ $gw = $this->get("default_gateway");
+ return sprintf("\t<default-gateway interface=\"%s\">\n\t\t%s\n\t</default-gateway>\n", $gw[0], $gw[1]);
+ }
+
+ function parse_etc_files_file_entry($value, $attr) {
+ if($attr['name']) {
+ if(!$this->_temp_etc_file) $this->_temp_etc_file = array();
+ $this->_temp_etc_file[$attr['name']] = $value;
+ } else {
+ if(!$this->_temp_etc_file) $this->_temp_etc_file = array();
+ $this->_temp_etc_file[] = $value;
+ }
+ }
+
+ function parse_etc_files_file($value, $attr) {
+ $etc_files = $this->get("etc_files");
+ $etc_files[$attr['name']] = $this->_temp_etc_file;
+ $this->_temp_etc_file = array();
+ $this->set("etc_files", $etc_files);
+ }
+
+ function serialize_etc_files() {
+ $etc_files = $this->get("etc_files");
+ if($etc_files) {
+ $this->xmldoc .= "\t<etc-files>\n";
+ foreach($etc_files as $etc_file => $values) {
+ $this->xmldoc .= sprintf("\t\t<file name=\"%s\">\n", $etc_file);
+ $isalist = (array_keys($values) === range(0, count($values) - 1)) ? true : false;
+ foreach($values as $name => $value) {
+ $this->xmldoc .= "\t\t\t<entry";
+ if($isalist) {
+ $this->xmldoc .= sprintf(">\n\t\t\t\t%s\n", $value);
+ } else {
+ $this->xmldoc .= sprintf(" name=\"%s\">\n\t\t\t\t%s\n", $name, $value);
+ }
+ $this->xmldoc .= "\t\t\t</entry>\n";
+ }
+ $this->xmldoc .= "\t\t</file>\n";
+ }
+ $this->xmldoc .= "\t</etc-files>\n";
+ }
+ }
+
+ function parse_network_interface($device, $attr) {
+ $options = null;
+ $ip = $broadcast = $netmask = $dhcp_options = null;
+ $dhcp = true;
+
+ foreach($attr as $name => $value) {
+ switch($name) {
+ case 'ip':
+ $ip = $value;
+ break;
+ case 'broadcast':
+ $broadcast = $value;
+ break;
+ case 'netmask':
+ $netmask = $value;
+ break;
+ case 'options':
+ $dhcp_options = $value;
+ break;
+ }
+ }
+
+ if($ip != 'dhcp') {
+ $dhcp = false;
+ $options = array($ip, $broadcast, $netmask);
+ } else {
+ $options = array('dhcp', $dhcp_options, '');
+ }
+
+ $network_interfaces = $this->get("network_interfaces");
+ $network_interfaces[$device] = $options;
+ $this->set("network_interfaces", $network_interfaces);
+ }
+
+ function serialize_network_interfaces() {
+ $interfaces = $this->get("network_interfaces");
+ if($interfaces) {
+ $this->xmldoc .= "\t<network-interfaces>\n";
+ foreach($interfaces as $iname => $interface) {
+ if($interface[0] == 'dhcp') {
+ $attrs = "ip=\"dhcp\"";
+ if($interface[1]) {
+ $dhcp_options = sprintf("options=\"%s\"", $interface[1]);
+ $attrs .= " " . $dhcp_options;
+ }
+ $this->xmldoc .= sprintf("\t\t<device %s>%s</device>\n", $attrs, $iname);
+ } else {
+ $this->xmldoc .= sprintf("\t\t<device ip=\"%s\" broadcast=\"%s\" netmask=\"%s\">%s</device>\n", $interface[0], $interface[1], $interface[2], $iname);
+ }
+ }
+ $this->xmldoc .= "\t</network-interfaces>\n";
+ }
+ }
+
+ function parse_netmount($unused, $attr) {
+ $netmount_entry = array('export' => '', 'host' => '', 'mountopts' => '', 'mountpoint' => '', 'type' => '');
+ foreach($attr as $name => $value) {
+ $netmount_entry[$name] = $value;
+ }
+ $network_mounts = $this->get("network_mounts");
+ $network_mounts[] = $netmount_entry;
+ $this->set("network_mounts", $network_mounts);
+ }
+
+ function serialize_network_mounts() {
+ $network_mounts = $this->get("network_mounts");
+ if($network_mounts) {
+ $this->xmldoc .= "\t<network-mounts>\n";
+ foreach($network_mounts as $mount) {
+ $this->xmldoc .= sprintf("\t\t<netmount host=\"%s\" export=\"%s\" type=\"%s\" mountpoint=\"%s\" mountopts=\"%s\"/>\n", $mount['host'], $mount['export'], $mount['type'], $mount['mountpoint'], $mount['mountopts']);
+ }
+ $this->xmldoc .= "\t</network-mounts>\n";
+ }
+ }
+
+ function parse_partitions_device($unused, $attr) {
+ $devnode = "";
+ $disklable = "";
+ foreach($attr as $name => $value) {
+ if($name == "devnode") {
+ $devnode = $value;
+ } elseif($name == "disklabel") {
+ $disklabel = $value;
+ }
+ }
+ $partition_tables = $this->get("partition_tables");
+ $partition_tables[$devnode] = $this->_temp_partition_table;
+ $this->_temp_partition_table = array();
+ $this->set("partition_tables", $partition_tables);
+ }
+
+ function parse_partitions_device_partition($unused, $attr) {
+ $part_entry = array();
+ foreach($attr as $name => $value) {
+ $part_entry[$name] = $value;
+ }
+ $part_entry['format'] = $part_entry['format'] == "True" ? true : false;
+ $part_entry['resized'] = $part_entry['resized'] == "True" ? true : false;
+# if GLIUtility.is_numeric(part_entry['mb']): part_entry['mb'] = long(part_entry['mb'])
+# if GLIUtility.is_numeric(part_entry['minor']):
+# part_entry['minor'] = float(part_entry['minor'])
+# if int(part_entry['minor']) == part_entry['minor']:
+# part_entry['minor'] = int(part_entry['minor'])
+# if GLIUtility.is_numeric(part_entry['origminor']): part_entry['origminor'] = int(part_entry['origminor'])
+ $this->_temp_partition_table[] = $part_entry;
+ }
+
+ function serialize_partition_tables() {
+ $partitions = $this->get("partition_tables");
+ if($partitions) {
+ $this->xmldoc .= "\t<partitions>\n";
+ foreach($partitions as $device => $parts) {
+ $this->xmldoc .= sprintf("\t\t<device devnode=\"%s\" disklabel=\"%s\">\n", $device, "msdos"); #partitions[device].get_disklabel())
+ foreach($parts as $part) {
+ $this->xmldoc .= sprintf("\t\t\t<partition minor=\"%s\" origminor=\"%s\" mb=\"%s\" type=\"%s\" mountpoint=\"%s\" mountopts=\"%s\" format=\"%s\" mkfsopts=\"%s\" resized=\"%s\"/>\n", $part['minor'], $part['origminor'], $part['mb'], $part['type'], $part['mountpoint'], $part['mountopts'], $part['format'], $part['mkfsopts'], $part['resized']);
+ }
+ $this->xmldoc .= "\t\t</device>\n";
+ }
+ $this->xmldoc .= "\t</partitions>\n";
+ }
+ }
+
+ function parse_user($username, $attr) {
+ $tmp_user = array();
+ foreach($attr as $name => $value) {
+ $tmp_user[$name] = $value;
+ }
+ $users = $this->get("users");
+ $users[] = array($username, $tmp_user['hash'], $tmp_user['groups'], $tmp_user['shell'], $tmp_user['homedir'], $tmp_user['uid'], $tmp_user['comment']);
+ $this->set("users", $users);
+ }
+
+ function serialize_users() {
+ $users = $this->get("users");
+ if($users) {
+ $this->xmldoc .= "\t<users>\n";
+ foreach($users as $user) {
+ $attrstr = "";
+ if($user[1]) $attrstr .= sprintf("hash=\"%s\" ", $user[1]);
+ if($user[2]) $attrstr .= sprintf("groups=\"%s\" ", implode(",", $user[2]));
+ if($user[3]) $attrstr .= sprintf("shell=\"%s\" ", $user[3]);
+ if($user[4]) $attrstr .= sprintf("homedir=\"%s\" ", $user[4]);
+ if($user[5]) $attrstr .= sprintf("uid=\"%s\" ", $user[5]);
+ if($user[6]) $attrstr .= sprintf("comment=\"%s\" ", $user[6]);
+ $this->xmldoc .= sprintf("\t\t<user %s>\n\t\t\t%s\n\t\t</user>\n", trim($attrstr), $user[0]);
+ }
+ $this->xmldoc .= "\t</users>\n";
+ }
+ }
+}
+?>
diff --git a/webgli/webgliUtility.php b/webgli/webgliUtility.php
new file mode 100644
index 0000000..a3a4057
--- /dev/null
+++ b/webgli/webgliUtility.php
@@ -0,0 +1,224 @@
+<?php
+#Utility functions for WebGLI
+
+##
+# Will take a password and return it hashed in md5 format
+# @param password the password to be hashed
+function hash_password($password)
+{
+ $salt = "$1$";
+ $chars = "./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ for($i=0;$i<=8;$i++) { # in range(0, 8):
+ $salt .= $chars[rand(0,strlen($chars)-1)]; #chars[random.randint(0, len(chars)-1)]
+ }
+ $salt .= "$";
+ $passwd_hash = crypt($password, $salt);
+
+ return $passwd_hash;
+}
+
+function get_eth_devices()
+{
+ $eth_devices = system("/sbin/ifconfig -a | grep -e '^[A-Za-z]'| cut -d ' ' -f 1");
+ return split(' ',$eth_devices);
+}
+
+function list_modules()
+{
+ exec("lsmod | grep -v ^Module | cut -d ' ' -f 1 ", $modules);
+ return $modules;
+}
+
+function generate_keymap_list()
+{
+ $keymap_list = array();
+ $path = "/usr/share/keymaps";
+
+ # find /usr/share/keymaps -iname *.map.gz -printf "%f \n"
+ exec("find ".$path." -iname *.map.gz -printf \"%f \n\"",$output);
+ foreach ($output as $keymap) {
+ # strip the last 9 chars ( .map.gz\n )
+ $keymap = trim($keymap);
+ $keymap = substr($keymap,0,-7);
+ array_push($keymap_list, $keymap);
+ }
+ # sort the keymap list
+ sort($keymap_list);
+
+ return $keymap_list;
+}
+
+function generate_consolefont_list()
+{
+ $consolefont_list = array();
+ $path = "/usr/share/consolefonts";
+
+ # find /usr/share/consolefonts -iname *.gz -printf "%f \n"
+ exec("find ".$path." -iname *.gz -printf \"%f \n\"", $output);
+ foreach ($output as $consolefont) {
+ # strip the last 5 chars ( .gz\n )
+ $consolefont = trim($consolefont);
+ $consolefont = substr($consolefont,0,-3);
+
+ # test if its psfu or psf or fnt
+ # and remove it if necessary
+ if (substr($consolefont,-4) == "psfu") {
+ $consolefont = substr($consolefont,0,-5);
+ }
+ if (substr($consolefont,-3) == "psf") {
+ $consolefont = substr($consolefont,0,-4);
+ }
+ if (substr($consolefont,-3) =="fnt") {
+ $consolefont = substr($consolefont,0,-4);
+ }
+ array_push($consolefont_list, $consolefont);
+ }
+ # sort the keymap list
+ sort($consolefont_list);
+
+ return $consolefont_list;
+}
+/* We gave up on this feature I think
+function generate_consoletranslation_list()
+{
+ $consoletranslation_list = array();
+ $path = "/usr/share/consoletrans";
+
+ # find /usr/share/keymaps -iname *.trans -printf "%f \n"
+ exec("find ".$path." -iname *.trans -printf \"%f \n\"", $output);
+ foreach ($output as $consoletran) {
+ # strip the last 8 chars ( .trans\n )
+ $consoletran = trim($consoletran);
+ $consoletran = substr($consoletran,0,-8);
+ array_push($consoletranslation_list, $consoletran);
+ }
+ sort($consoletranslation_list);
+
+ return $consoletranslation_list;
+}
+*/
+
+function get_install_package_list()
+{
+ $install_package_list = array(
+ 'Desktop' => array("Popular Desktop Applications",
+ array("bittorrent"=> "tool for distributing files via a distributed network of nodes",
+ "evolution" => "A GNOME groupware application, a Microsoft Outlook workalike",
+ "gaim" => "GTK Instant Messenger client",
+ "gftp" => "Gnome based FTP Client",
+ "gimp" => "GNU Image Manipulation Program",
+ "inkscape" => "A SVG based generic vector-drawing program",
+ "koffice" => "An integrated office suite for KDE, the K Desktop Environment",
+ "mozilla" => "The Mozilla Web Browser",
+ "mozilla-firefox" => "The Mozilla Firefox Web Browser",
+ "mozilla-thunderbird" => "Thunderbird Mail Client",
+ "mplayer" => "Media Player for Linux",
+ "openoffice" => "OpenOffice.org, a full office productivity suite.",
+ "openoffice-bin" => "Same as OpenOffice but a binary package (no compiling!)",
+ "rhythmbox" => "Music management and playback software for GNOME",
+ "vlc" => "VLC media player - Video player and streamer",
+ "xchat" => "Graphical IRC Client",
+ "xine-ui" => "Xine movie player",
+ "xmms" => "X MultiMedia System" )),
+ 'Servers' => array("Applications often found on servers.",
+ array("apache" => "Apache Web Server",
+ "cups" => "The Common Unix Printing System",
+ "exim" => "A highly configurable, drop-in replacement for sendmail",
+ "iptables" => "Linux kernel (2.4+) firewall, NAT and packet mangling tools",
+ "mod_php" => "Apache module for PHP",
+ "mysql" => "A fast, multi-threaded, multi-user SQL database server",
+ "postfix" => "A fast and secure drop-in replacement for sendmail",
+ "postgresql" => "sophisticated Object-Relational DBMS",
+ "proftpd" => "ProFTP Server",
+ "samba" => "SAMBA client/server programs for UNIX",
+ "sendmail" => "Widely-used Mail Transport Agent (MTA)",
+ "traceroute" => "Utility to trace the route of IP packets" )),
+ 'X11' => array("Window managers and X selection.",
+ array("xorg-x11" => "An X11 implementation maintained by the X.Org Foundation",
+ "gnome" => "The Gnome Desktop Environment",
+ "kde" => "The K Desktop Environment",
+ "blackbox" => "A small, fast, full-featured window manager for X",
+ "enlightenment" => "Enlightenment Window Manager",
+ "fluxbox" => "Fluxbox is an X11 window manager featuring tabs and an iconbar",
+ "xfce4" => "XFCE Desktop Environment" )),
+ 'Misc' => array("Miscellaneous Applications you may want.",
+ array("emacs" => "An incredibly powerful, extensible text editor",
+ "ethereal" => "A commercial-quality network protocol analyzer",
+ "gkrellm" => "Single process stack of various system monitors",
+ "gvim" => "GUI version of the Vim text editor",
+ "keychain" => "ssh-agent manager",
+ "logrotate" => "Rotates, compresses, and mails system logs",
+ "ntp" => "Network Time Protocol suite/programs",
+ "rdesktop" => "A Remote Desktop Protocol Client",
+ "slocate" => "Secure way to index and quickly search for files on your system",
+ "ufed" => "Gentoo Linux USE flags editor",
+ "vim" => "Vim, an improved vi-style text editor" )),
+ 'Recommended' => array("Applications recommended by the GLI Team.",
+ array("anjuta" => "A versatile IDE for GNOME",
+ "chkrootkit" => "a tool to locally check for signs of a rootkit",
+ "crack-attack" => "Addictive OpenGL-based block game",
+ "gnupg" => "The GNU Privacy Guard, a GPL pgp replacement",
+ "net-snmp" => "Software for generating and retrieving SNMP data",
+ "netcat" => "the network swiss army knife",
+ "nmap" => "A utility for network exploration or security auditing",
+ "screen" => "full-screen window manager that multiplexes between several processes",
+ "xpdf" => "An X Viewer for PDF Files" ))
+ );
+ return $install_package_list;
+}
+
+function get_grp_pkgs_from_cd() {
+ if (!is_file("/usr/livecd/grppkgs.txt")) {
+ return "";
+ }
+ exec('cat /usr/livecd/grppkgs.txt',$output);
+ $output_arr = explode($output);
+ #remove the first part before a / for comparision
+ $results = array();
+ foreach ($output_arr as $pkg) {
+ array_push($results, substr($pkg, int(strpos($pkg,'/'))+1 )); #.append(pkg[(pkg.find('/')+1):])
+ }
+ return $results;
+}
+
+function get_global_use_flags() {
+ $fh = fopen("/usr/portage/profiles/use.desc", "r");
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+ if ( (!$line) or $line[0] == '#') {
+ continue;
+ }
+ $dash_pos = strpos($line, " - ");
+ if ($dash_pos == -1) {
+ continue;
+ }
+ $flagname = substr($line,0,$dash_pos);
+ $desc = substr($line,$dash_pos+3);
+ $use_desc[$flagname] = $desc;
+ }
+ fclose($fh);
+ return $use_desc;
+}
+
+function get_local_use_flags() {
+ $fh = fopen("/usr/portage/profiles/use.local.desc", "r");
+ while (!feof($fh)) {
+ $line = trim(fgets($fh));
+ if ( (!$line) or $line[0] == '#') {
+ continue;
+ }
+ $dash_pos = strpos($line, " - ");
+ if ($dash_pos == -1) {
+ continue;
+ }
+ $colon_pos = strpos($line,":");#, 0, dash_pos);
+ $pkg = substr($line,0,$colon_pos);
+ $flagname = substr($line,$colon_pos+1,$dash_pos); #line[colon_pos+1:dash_pos] or line[colon_pos+1]
+ $flagname = substr($line,$colon_pos+1, ($dash_pos-$colon_pos));
+ $desc = "(" . $pkg . ") " . substr($line,$dash_pos+3);
+ $use_local_desc[$flagname] = $desc;
+ }
+ fclose($fh);
+ return $use_local_desc;
+}
+?>