Merge lp:~dangarner/xibo/server-170-alpha2 into lp:xibo/1.7

Proposed by Dan Garner
Status: Merged
Merged at revision: 347
Proposed branch: lp:~dangarner/xibo/server-170-alpha2
Merge into: lp:xibo/1.7
Diff against target: 30604 lines (+23044/-3722)
174 files modified
example_oauth/index.php (+14/-11)
server/config/client.config.php (+1/-1)
server/config/config.class.php (+6/-4)
server/install/database/80.sql (+1/-6)
server/install/database/81.sql (+23/-0)
server/install/master/data.sql (+6/-7)
server/install/master/structure.sql (+5/-3)
server/lib/app/cache.class.php (+82/-0)
server/lib/app/debug.class.php (+180/-169)
server/lib/app/kit.class.php (+456/-445)
server/lib/app/modulemanager.class.php (+2/-5)
server/lib/app/permissionmanager.class.php (+1/-3)
server/lib/app/responsemanager.class.php (+3/-1)
server/lib/app/session.class.php (+11/-4)
server/lib/app/thememanager.class.php (+56/-0)
server/lib/app/translationengine.class.php (+69/-68)
server/lib/data/campaign.data.class.php (+3/-1)
server/lib/data/campaignsecurity.data.class.php (+9/-0)
server/lib/data/datasetdata.data.class.php (+4/-0)
server/lib/data/datasetgroupsecurity.data.class.php (+18/-40)
server/lib/data/display.data.class.php (+133/-2)
server/lib/data/displayprofile.data.class.php (+55/-0)
server/lib/data/layout.data.class.php (+10/-18)
server/lib/data/maintenance.data.class.php (+156/-15)
server/lib/data/media.data.class.php (+101/-5)
server/lib/data/region.data.class.php (+5/-10)
server/lib/data/schedule.data.class.php (+578/-516)
server/lib/data/stat.data.class.php (+121/-63)
server/lib/data/usergroup.data.class.php (+52/-0)
server/lib/include.php (+8/-2)
server/lib/modules/module.class.php (+53/-47)
server/lib/pages/admin.class.php (+37/-71)
server/lib/pages/campaign.class.php (+36/-29)
server/lib/pages/content.class.php (+6/-5)
server/lib/pages/display.class.php (+53/-73)
server/lib/pages/displaygroup.class.php (+15/-25)
server/lib/pages/index.class.php (+10/-0)
server/lib/pages/install.class.php (+7/-1)
server/lib/pages/layout.class.php (+102/-59)
server/lib/pages/log.class.php (+4/-2)
server/lib/pages/module.class.php (+5/-4)
server/lib/pages/oauth.class.php (+1/-0)
server/lib/pages/preview.class.php (+3/-1)
server/lib/pages/schedule.class.php (+13/-12)
server/lib/pages/stats.class.php (+153/-9)
server/lib/pages/template.class.php (+14/-25)
server/lib/pages/timeline.class.php (+239/-57)
server/lib/pages/user.class.php (+4/-3)
server/lib/service/rest.class.php (+15/-2)
server/lib/service/service.wsdl (+3/-2)
server/lib/service/xmdssoap.class.php (+120/-90)
server/lib/xmds.inc.php (+8/-5)
server/locale/dbtranslate.php (+4/-0)
server/maintenance.php (+119/-172)
server/manual/content/admin/release_notes_1.7.0-alpha2.php (+84/-0)
server/manual/content/routes.php (+1/-0)
server/manual/content/toc_developer_releasenotes.php (+1/-0)
server/manual/template.php (+1/-1)
server/modules/3rdparty/forecast.php (+38/-0)
server/modules/clock.module.php (+33/-48)
server/modules/datasetview.module.php (+41/-14)
server/modules/embedded.module.php (+247/-193)
server/modules/font.module.php (+187/-0)
server/modules/forecastio.module.php (+508/-0)
server/modules/module_user_general.php (+39/-14)
server/modules/preview/Html4TransitionalTemplate.html (+26/-0)
server/modules/preview/HtmlTemplate.html (+9/-3)
server/modules/preview/HtmlTemplateForGetResource.html (+0/-155)
server/modules/preview/HtmlTemplateSimple.html (+1/-1)
server/modules/preview/fonts.css (+11/-0)
server/modules/preview/html-preview.js (+1/-1)
server/modules/preview/vendor/jquery-cycle-2.1.6.min.js (+16/-0)
server/modules/preview/vendor/jquery.marquee.min.js (+5/-0)
server/modules/preview/xibo-dataset-render.js (+51/-0)
server/modules/preview/xibo-layout-scaler.js (+62/-0)
server/modules/preview/xibo-text-render.js (+43/-211)
server/modules/preview/xibo-webpage-render.js (+81/-69)
server/modules/text.module.php (+150/-102)
server/modules/theme/HtmlTemplateForClock.html (+1/-1)
server/modules/theme/HtmlTemplateForFlipClock.html (+1/-1)
server/modules/theme/forecastio/weather_icons/weather-icons.min.css (+23/-0)
server/modules/theme/forecastio/weather_icons/weathericons-regular-webfont.svg (+153/-0)
server/modules/ticker.module.php (+93/-39)
server/modules/webpage.module.php (+303/-189)
server/services.php (+4/-2)
server/theme/default/css/html-preview.css (+2/-2)
server/theme/default/html/campaign_form_layout_assign.php (+2/-19)
server/theme/default/html/campaign_form_layout_assign_list.php (+0/-39)
server/theme/default/html/footer.php (+27/-7)
server/theme/default/html/form_grid_pager.php (+0/-41)
server/theme/default/html/grid_pager.php (+14/-15)
server/theme/default/html/grid_render.php (+1/-0)
server/theme/default/html/header.php (+7/-6)
server/theme/default/html/layout_designer.php (+2/-5)
server/theme/default/html/schedule_page.php (+1/-1)
server/theme/default/html/settings_page.php (+103/-86)
server/theme/default/html/stats_page_availability.php (+47/-0)
server/theme/default/html/stats_page_grid.php (+0/-6)
server/theme/default/html/status_dashboard.php (+2/-2)
server/theme/default/html/table_render.php (+110/-48)
server/theme/default/js/xibo-calendar.js (+8/-7)
server/theme/default/js/xibo-cms.js (+347/-63)
server/theme/default/js/xibo-forms.js (+24/-10)
server/theme/default/libraries/bootstrap-ekko-lightbox/ekko-lightbox.min.css (+6/-0)
server/theme/default/libraries/bootstrap-ekko-lightbox/ekko-lightbox.min.js (+7/-0)
server/theme/default/libraries/calendar/js/language/de-DE.js (+0/-73)
server/theme/default/libraries/calendar/js/language/de.js (+73/-0)
server/theme/default/libraries/ckeditor/config.js (+4/-1)
server/theme/default/libraries/ckeditor/contents.css (+2/-2)
server/theme/default/libraries/jquery-message-queuing/jquery.ba-jqmq.min.js (+9/-0)
server/theme/default/libraries/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.css (+42/-0)
server/theme/default/libraries/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js (+958/-0)
server/theme/default/libraries/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.min.js (+2/-0)
server/theme/default/libraries/jquery-tablesorter/css/bootstrap.less (+316/-0)
server/theme/default/libraries/jquery-tablesorter/css/filter.formatter.css (+183/-0)
server/theme/default/libraries/jquery-tablesorter/css/metro.less (+351/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.black-ice.css (+186/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.blue.css (+221/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.bootstrap.css (+152/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.bootstrap_2.css (+150/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.dark.css (+187/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.default.css (+189/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.dropbox.css (+212/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.green.css (+203/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.grey.css (+245/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.ice.css (+201/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.jui.css (+156/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.less (+323/-0)
server/theme/default/libraries/jquery-tablesorter/css/theme.metro-dark.css (+192/-0)
server/theme/default/libraries/jquery-tablesorter/js/extras/jquery.quicksearch.js (+191/-0)
server/theme/default/libraries/jquery-tablesorter/js/extras/semver-mod.js (+1026/-0)
server/theme/default/libraries/jquery-tablesorter/js/extras/semver.js (+1011/-0)
server/theme/default/libraries/jquery-tablesorter/js/jquery.metadata.js (+116/-0)
server/theme/default/libraries/jquery-tablesorter/js/jquery.tablesorter.js (+1901/-0)
server/theme/default/libraries/jquery-tablesorter/js/jquery.tablesorter.min.js (+5/-0)
server/theme/default/libraries/jquery-tablesorter/js/jquery.tablesorter.widgets-filter-formatter-select2.js (+138/-0)
server/theme/default/libraries/jquery-tablesorter/js/jquery.tablesorter.widgets-filter-formatter.js (+1145/-0)
server/theme/default/libraries/jquery-tablesorter/js/jquery.tablesorter.widgets-filter-formatter.min.js (+6/-0)
server/theme/default/libraries/jquery-tablesorter/js/jquery.tablesorter.widgets.js (+1912/-0)
server/theme/default/libraries/jquery-tablesorter/js/jquery.tablesorter.widgets.min.js (+17/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-date-extract.js (+81/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-date-iso8601.js (+34/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-date-month.js (+33/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-date-two-digit-year.js (+74/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-date-weekday.js (+33/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-date.js (+36/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-duration.js (+40/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-feet-inch-fraction.js (+63/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-file-type.js (+73/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-ignore-articles.js (+61/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-image.js (+20/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-input-select.js (+161/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-ipv6.js (+76/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-metric.js (+77/-0)
server/theme/default/libraries/jquery-tablesorter/js/parsers/parser-roman.js (+117/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-alignChar.js (+145/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-build-table.js (+453/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-columnSelector.js (+317/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-cssStickyHeaders.js (+70/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-editable.js (+200/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-grouping.js (+249/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-headerTitles.js (+91/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-math.js (+413/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-output.js (+316/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-pager.js (+975/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-print.js (+123/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-reflow.js (+179/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-repeatheaders.js (+50/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-scroller.js (+218/-0)
server/theme/default/libraries/jquery-tablesorter/js/widgets/widget-staticRow.js (+124/-0)
server/theme/default/libraries/jquery/jquery.metadata.js (+0/-116)
server/theme/default/libraries/jquery/jquery.tablesorter.pack.js (+0/-6)
server/theme/default/libraries/jquery/jquery.tablesorter.pager.css (+0/-28)
server/theme/default/libraries/jquery/jquery.tablesorter.pager.js (+0/-2)
To merge this branch: bzr merge lp:~dangarner/xibo/server-170-alpha2
Reviewer Review Type Date Requested Status
Xibo Maintainters Pending
Review via email: mp+239095@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'example_oauth/index.php'
2--- example_oauth/index.php 2014-07-12 13:54:51 +0000
3+++ example_oauth/index.php 2014-10-21 16:06:16 +0000
4@@ -1,4 +1,7 @@
5 <?php
6+error_reporting(E_ALL);
7+ini_set('display_errors', 1);
8+
9 require_once('oauth-php/library/OAuthStore.php');
10 require_once('oauth-php/library/OAuthRequester.php');
11 require_once('oauth-php/library/OAuthRequestLogger.php');
12@@ -6,16 +9,16 @@
13
14 DEFINE('OAUTH_LOG_REQUEST', true);
15
16-$connection = array('server' => 'localhost',
17- 'username' => 'root',
18- 'password' => '',
19- 'database' => 'oauth_consumer');
20-
21-OAuthStore::instance('MySQL', $connection);
22-
23-DEFINE('SERVER_BASE', 'http://localhost/xibo/1.6/server-162/server/');
24-DEFINE('CONSUMER_KEY', 'e982575d2ab70546923b92e50c5b96ca053b407a8');
25-DEFINE('CONSUMER_SECRET', 'a891f97e69985230a2e0e869b9f875e3');
26+$connection = new PDO('mysql:host=localhost;dbname=oauth_consumer', 'root', 'root');
27+$connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
28+$connection->query("SET NAMES 'utf8'");
29+
30+OAuthStore::instance('PDO', array('conn' => $connection));
31+
32+DEFINE('LOCAL_BASE', 'http://172.28.128.3/example_oauth/index.php');
33+DEFINE('SERVER_BASE', 'http://unittest.xibo.co.uk/');
34+DEFINE('CONSUMER_KEY', '9beeb94ea11bfa15da1ab7b2b0fb543205436b27b');
35+DEFINE('CONSUMER_SECRET', 'fba59ef57d3331032a099cf04b1ebb2d');
36 //DEFINE('SERVER_BASE', 'http://unittest2.xibo.org.uk/api/');
37 //DEFINE('CONSUMER_KEY', '201798cda77e4e82e0488d0c8c2e43ae0519d180f');
38 //DEFINE('CONSUMER_SECRET', '9eb4aa8a51e4a393b3fb5ad6f1a75bae');
39@@ -92,7 +95,7 @@
40 }
41
42 // Callback to our (consumer) site, will be called when the user finished the authorization at the server
43- $callback_uri = '?action=Exchange&consumer_key='.rawurlencode(CONSUMER_KEY).'&usr_id='.intval($user_id);
44+ $callback_uri = LOCAL_BASE . '?action=Exchange&consumer_key='.rawurlencode(CONSUMER_KEY).'&usr_id='.intval($user_id);
45
46 // Now redirect to the autorization uri and get us authorized
47 if (!empty($token['authorize_uri']))
48
49=== modified file 'server/config/client.config.php'
50--- server/config/client.config.php 2014-09-16 16:41:43 +0000
51+++ server/config/client.config.php 2014-10-21 16:06:16 +0000
52@@ -272,7 +272,7 @@
53 'title' => __('Use CEF as the Web Browser'),
54 'type' => _CHECKBOX,
55 'fieldType' => 'checkbox',
56- 'default' => 1,
57+ 'default' => 0,
58 'helpText' => __('CEF is Chrome Embedded and offers up to date web rendering. If unselected the default Internet Explorer control will be used.'),
59 'enabled' => true,
60 'groupClass' => NULL
61
62=== modified file 'server/config/config.class.php'
63--- server/config/config.class.php 2014-08-16 12:51:07 +0000
64+++ server/config/config.class.php 2014-10-21 16:06:16 +0000
65@@ -56,7 +56,7 @@
66 * @return
67 * @param $setting Object[optional]
68 */
69- static function GetSetting($setting)
70+ static function GetSetting($setting, $default = NULL)
71 {
72 try {
73 $dbh = PDOConnect::init();
74@@ -65,12 +65,14 @@
75 $sth->execute(array('setting' => $setting));
76
77 if (!$result = $sth->fetch())
78- return false;
79+ return $default;
80
81 //Debug::LogEntry('audit', 'Retrieved setting ' . $result['value'] . ' for ' . $setting, 'Config', 'GetSetting');
82-
83+
84 // Validate as a string and return
85- return Kit::ValidateParam($result['value'], _STRING);
86+ $result = Kit::ValidateParam($result['value'], _STRING);
87+
88+ return ($result == '') ? $default : $result;
89 }
90 catch (Exception $e) {
91 trigger_error($e->getMessage());
92
93=== modified file 'server/install/database/80.sql'
94--- server/install/database/80.sql 2014-09-19 14:08:28 +0000
95+++ server/install/database/80.sql 2014-10-21 16:06:16 +0000
96@@ -41,11 +41,6 @@
97 PRIMARY KEY (`displayprofileid`)
98 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
99
100-INSERT INTO `displayprofile` (`displayprofileid`, `name`, `type`, `config`, `isdefault`, `userid`) VALUES
101-(1, 'Production', 'windows', '[{"name":"CollectInterval","value":"900","type":"int"},{"name":"PowerpointEnabled","value":0,"type":"checkbox"},{"name":"StatsEnabled","value":1,"type":"checkbox"},{"name":"SizeX","value":0,"type":"double"},{"name":"SizeY","value":0,"type":"double"},{"name":"OffsetX","value":0,"type":"double"},{"name":"OffsetY","value":0,"type":"double"},{"name":"ShowInTaskbar","value":1,"type":"checkbox"},{"name":"ClientInfomationCtrlKey","value":0,"type":"checkbox"},{"name":"ClientInformationKeyCode","value":"I","type":"word"},{"name":"CursorStartPosition","value":"Bottom Right","type":"string"},{"name":"DoubleBuffering","value":1,"type":"checkbox"},{"name":"EmptyLayoutDuration","value":"10","type":"int"},{"name":"EnableMouse","value":0,"type":"checkbox"},{"name":"EnableShellCommands","value":0,"type":"checkbox"},{"name":"ExpireModifiedLayouts","value":0,"type":"checkbox"},{"name":"LogLevel","value":"off","type":"word"},{"name":"LogToDiskLocation","value":"","type":"string"},{"name":"MaxConcurrentDownloads","value":"2","type":"int"},{"name":"ShellCommandAllowList","value":"","type":"string"},{"name":"UseCefWebBrowser","value":1,"type":"checkbox"},{"name":"SendCurrentLayoutAsStatusUpdate","value":0,"type":"checkbox"},{"name":"ScreenShotRequestInterval","value":0,"type":"int"}]', 1, 1),
102-(2, 'Production', 'android', '[{"name":"emailAddress","value":"","type":"string"},{"name":"settingsPassword","value":"","type":"string"},{"name":"collectInterval","value":"600","type":"int"},{"name":"orientation","value":0,"type":"int"},{"name":"startOnBoot","value":1,"type":"checkbox"},{"name":"actionBarMode","value":"1","type":"int"},{"name":"actionBarDisplayDuration","value":"60","type":"int"},{"name":"screenDimensions","value":"","type":"string"},{"name":"autoRestart","value":1,"type":"checkbox"},{"name":"startOnBootDelay","value":"60","type":"int"},{"name":"blacklistVideo","value":1,"type":"checkbox"},{"name":"storeHtmlOnInternal","value":0,"type":"checkbox"}]', 1, 1);
103-
104-
105 UPDATE layout SET background = SUBSTRING_INDEX(background, '.', 1) WHERE IFNULL(background, '') <> '';
106 ALTER TABLE `layout` CHANGE `background` `backgroundImageId` INT( 11 ) NULL DEFAULT NULL;
107
108@@ -178,6 +173,6 @@
109 ('DisplayProfile', 'Delete', 'manual/single.php?p=admin/displayprofiles#delete');
110
111
112-UPDATE `version` SET `app_ver` = '1.7.0-alpha', `XmdsVersion` = 4;
113+UPDATE `version` SET `app_ver` = '1.7.0-alpha', `XmdsVersion` = 4, `XlfVersion` = 2 ;
114 UPDATE `setting` SET `value` = 0 WHERE `setting` = 'PHONE_HOME_DATE';
115 UPDATE `version` SET `DBVersion` = '80';
116
117=== added file 'server/install/database/81.sql'
118--- server/install/database/81.sql 1970-01-01 00:00:00 +0000
119+++ server/install/database/81.sql 2014-10-21 16:06:16 +0000
120@@ -0,0 +1,23 @@
121+INSERT INTO `setting` (`setting` ,`value` ,`fieldType` ,`helptext` ,`options` ,`cat` ,`userChange` ,`title` ,`validation` ,`ordering` ,`default` ,`userSee` ,`type`)
122+VALUES (
123+ 'DATE_FORMAT', 'Y-m-d', 'text', 'The Date Format to use when displaying dates in the CMS.', NULL , 'regional', '1', 'Date Format', 'required', '30', 'Y-m-d', '1', 'string'
124+);
125+
126+INSERT INTO `setting` (`setting` ,`value` ,`fieldType` ,`helptext` ,`options` ,`cat` ,`userChange` ,`title` ,`validation` ,`ordering` ,`default` ,`userSee` ,`type`)
127+VALUES (
128+ 'DETECT_LANGUAGE', '1', 'checkbox', 'Detect the browser language?', NULL , 'regional', '1', 'Detect Language', '', '40', '1', '1', 'checkbox'
129+);
130+
131+ALTER TABLE `media` ADD `is_module` TINYINT NOT NULL DEFAULT '0';
132+
133+INSERT INTO `module` (`ModuleID`, `Module`, `Name`, `Enabled`, `RegionSpecific`, `Description`, `ImageUri`, `SchemaVersion`, `ValidExtensions`, `PreviewEnabled`, `assignable`) VALUES
134+(NULL, 'font', 'Font', '1', '0', 'A font to use in other Modules', 'forms/library.gif', '1', 'ttf,otf,eot,svg,woff', '0', '0');
135+
136+ALTER TABLE `stat` ADD INDEX ( `statDate` );
137+
138+ALTER TABLE `stat` CHANGE `layoutID` `layoutID` INT( 8 ) NULL;
139+ALTER TABLE `stat` CHANGE `end` `end` DATETIME NULL;
140+
141+UPDATE `version` SET `app_ver` = '1.7.0-alpha2', `XmdsVersion` = 4, `XlfVersion` = 2;
142+UPDATE `setting` SET `value` = 0 WHERE `setting` = 'PHONE_HOME_DATE';
143+UPDATE `version` SET `DBVersion` = '81';
144\ No newline at end of file
145
146=== modified file 'server/install/master/data.sql'
147--- server/install/master/data.sql 2014-09-19 12:55:15 +0000
148+++ server/install/master/data.sql 2014-10-21 16:06:16 +0000
149@@ -1,5 +1,5 @@
150 INSERT INTO `version` (`app_ver`, `XmdsVersion`, `XlfVersion`, `DBVersion`) VALUES
151-('1.7.0-alpha', 4, 1, 80);
152+('1.7.0-alpha2', 4, 2, 81);
153
154 INSERT INTO `group` (`groupID`, `group`, `IsUserSpecific`, `IsEveryone`) VALUES
155 (1, 'Users', 0, 0),
156@@ -113,7 +113,8 @@
157 (12, 'shellcommand', 'Shell Command', 1, 1, 'Execute a shell command on the client', 'forms/shellcommand.gif', 1, NULL, 1, 1, NULL, NULL),
158 (13, 'localvideo', 'Local Video', 1, 1, 'Play a video locally stored on the client', 'forms/video.gif', 1, NULL, 1, 1, NULL, NULL),
159 (14, 'genericfile', 'Generic File', 1, 0, 'A generic file to be stored in the library', 'forms/library.gif', 1, 'apk,js,html,htm', 0, 0, NULL, NULL),
160-(15, 'clock', 'Clock', 1, 1, 'Display a Clock', 'forms/library.gif', 1, NULL, 1, 1, 'html', '[]');
161+(15, 'clock', 'Clock', 1, 1, 'Display a Clock', 'forms/library.gif', 1, NULL, 1, 1, 'html', '[]'),
162+(16, 'font', 'Font', 1, 0, 'A font to use in other Modules', 'forms/library.gif', 1, 'ttf,otf,eot,svg,woff', 0, 0, NULL, NULL);
163
164 INSERT INTO `pagegroup` (`pagegroupID`, `pagegroup`) VALUES
165 (1, 'Schedule'),
166@@ -263,7 +264,9 @@
167 (70, 'EMBEDDED_STATUS_WIDGET', '', 'text', 'HTML to embed in an iframe on the Status Dashboard', NULL, 'general', 0, 'Status Dashboard Widget', '', 70, '', 1, 'htmlstring'),
168 (71, 'PROXY_HOST', '', 'text', 'The Proxy URL', NULL, 'network', 1, 'Proxy URL', '', 10, '', 1, 'string'),
169 (72, 'PROXY_PORT', '0', 'number', 'The Proxy Port', NULL, 'network', 1, 'Proxy Port', '', 20, '0', 1, 'int'),
170-(73, 'PROXY_AUTH', '', 'text', 'The Authentication information for this proxy. username:password', NULL, 'network', 1, 'Proxy Credentials', '', 30, '', 1, 'string');
171+(73, 'PROXY_AUTH', '', 'text', 'The Authentication information for this proxy. username:password', NULL, 'network', 1, 'Proxy Credentials', '', 30, '', 1, 'string'),
172+(74, 'DATE_FORMAT', 'Y-m-d', 'text', 'The Date Format to use when displaying dates in the CMS.', NULL , 'regional', '1', 'Date Format', 'required', 30, 'Y-m-d', '1', 'string'),
173+(75, 'DETECT_LANGUAGE', '1', 'checkbox', 'Detect the browser language?', NULL , 'regional', '1', 'Detect Language', '', 40, '1', 1, 'checkbox');
174
175 INSERT INTO `usertype` (`usertypeid`, `usertype`) VALUES
176 (1, 'Super Admin'),
177@@ -339,10 +342,6 @@
178 (1, 'Value'),
179 (2, 'Formula');
180
181-INSERT INTO `displayprofile` (`displayprofileid`, `name`, `type`, `config`, `isdefault`, `userid`) VALUES
182-(1, 'Production', 'windows', '[{"name":"CollectInterval","value":"900","type":"int"},{"name":"PowerpointEnabled","value":0,"type":"checkbox"},{"name":"StatsEnabled","value":1,"type":"checkbox"},{"name":"SizeX","value":0,"type":"double"},{"name":"SizeY","value":0,"type":"double"},{"name":"OffsetX","value":0,"type":"double"},{"name":"OffsetY","value":0,"type":"double"},{"name":"ShowInTaskbar","value":1,"type":"checkbox"},{"name":"ClientInfomationCtrlKey","value":0,"type":"checkbox"},{"name":"ClientInformationKeyCode","value":"I","type":"word"},{"name":"CursorStartPosition","value":"Bottom Right","type":"string"},{"name":"DoubleBuffering","value":1,"type":"checkbox"},{"name":"EmptyLayoutDuration","value":"10","type":"int"},{"name":"EnableMouse","value":0,"type":"checkbox"},{"name":"EnableShellCommands","value":0,"type":"checkbox"},{"name":"ExpireModifiedLayouts","value":0,"type":"checkbox"},{"name":"LogLevel","value":"off","type":"word"},{"name":"LogToDiskLocation","value":"","type":"string"},{"name":"MaxConcurrentDownloads","value":"2","type":"int"},{"name":"ShellCommandAllowList","value":"","type":"string"},{"name":"UseCefWebBrowser","value":1,"type":"checkbox"},{"name":"SendCurrentLayoutAsStatusUpdate","value":0,"type":"checkbox"},{"name":"ScreenShotRequestInterval","value":0,"type":"int"}]', 1, 1),
183-(2, 'Production', 'android', '[{"name":"emailAddress","value":"","type":"string"},{"name":"settingsPassword","value":"","type":"string"},{"name":"collectInterval","value":"600","type":"int"},{"name":"orientation","value":0,"type":"int"},{"name":"startOnBoot","value":1,"type":"checkbox"},{"name":"actionBarMode","value":"1","type":"int"},{"name":"actionBarDisplayDuration","value":"60","type":"int"},{"name":"screenDimensions","value":"","type":"string"},{"name":"autoRestart","value":1,"type":"checkbox"},{"name":"startOnBootDelay","value":"60","type":"int"},{"name":"blacklistVideo","value":1,"type":"checkbox"},{"name":"storeHtmlOnInternal","value":0,"type":"checkbox"}]', 1, 1);
184-
185 INSERT INTO `bandwidthtype` (`bandwidthtypeid`, `name`) VALUES
186 (1, 'Register'),
187 (2, 'Required Files'),
188
189=== modified file 'server/install/master/structure.sql'
190--- server/install/master/structure.sql 2014-09-16 10:59:55 +0000
191+++ server/install/master/structure.sql 2014-10-21 16:06:16 +0000
192@@ -321,6 +321,7 @@
193 `retired` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'Is retired?',
194 `isEdited` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'Is this the current record',
195 `editedMediaID` int(11) DEFAULT NULL COMMENT 'The Parent ID',
196+ `is_module` tinyint(4) NOT NULL DEFAULT '0',
197 PRIMARY KEY (`mediaID`)
198 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;
199
200@@ -530,12 +531,13 @@
201 `statDate` datetime NOT NULL COMMENT 'State entry date',
202 `scheduleID` int(8) NOT NULL,
203 `displayID` int(4) NOT NULL,
204- `layoutID` int(8) NOT NULL,
205+ `layoutID` int(8) NULL,
206 `mediaID` varchar(50) DEFAULT NULL,
207 `start` datetime NOT NULL,
208- `end` datetime NOT NULL,
209+ `end` datetime NULL,
210 `Tag` varchar(254) DEFAULT NULL,
211- PRIMARY KEY (`statID`)
212+ PRIMARY KEY (`statID`),
213+ KEY `statDate` (`statDate`)
214 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
215
216 CREATE TABLE IF NOT EXISTS `template` (
217
218=== added file 'server/lib/app/cache.class.php'
219--- server/lib/app/cache.class.php 1970-01-01 00:00:00 +0000
220+++ server/lib/app/cache.class.php 2014-10-21 16:06:16 +0000
221@@ -0,0 +1,82 @@
222+<?php
223+/*
224+ * Xibo - Digital Signage - http://www.xibo.org.uk
225+ * Copyright (C) 2009-2013 Daniel Garner
226+ *
227+ * This file is part of Xibo.
228+ *
229+ * Xibo is free software: you can redistribute it and/or modify
230+ * it under the terms of the GNU Affero General Public License as published by
231+ * the Free Software Foundation, either version 3 of the License, or
232+ * any later version.
233+ *
234+ * Xibo is distributed in the hope that it will be useful,
235+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
236+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
237+ * GNU Affero General Public License for more details.
238+ *
239+ * You should have received a copy of the GNU Affero General Public License
240+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
241+ *
242+ * A very simple file cache
243+ */
244+defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
245+
246+class Cache {
247+
248+ private static $_data;
249+ private static $_location;
250+
251+ private function __construct() {}
252+
253+ public static function put($key, $value, $expires) {
254+ if (!self::$_data)
255+ self::load();
256+
257+ $expires = time() + $expires;
258+
259+ self::$_data[$key] = array('value' => $value, 'expires' => $expires);
260+
261+ self::save();
262+ }
263+
264+ public static function get($key, $default = NULL) {
265+ if (!self::$_data)
266+ self::load();
267+
268+ if (!Cache::has($key))
269+ return $default;
270+
271+ $data = self::$_data[$key];
272+
273+ if ($data['expires'] < time()) {
274+ unset(self::$_data['key']);
275+ return $default;
276+ }
277+ else
278+ return $data['value'];
279+ }
280+
281+ public static function has($key) {
282+ if (!self::$_data)
283+ self::load();
284+
285+ return (isset(self::$_data[$key]) && self::$_data[$key] != null && self::$_data[$key]['expires'] >= time());
286+ }
287+
288+ private static function load() {
289+ self::$_location = Config::GetSetting('LIBRARY_LOCATION') . 'cache/cache';
290+
291+ if (!file_exists(self::$_location))
292+ self::$_data = array();
293+ else
294+ self::$_data = unserialize(file_get_contents(self::$_location));
295+ }
296+
297+ private static function save() {
298+ self::$_location = Config::GetSetting('LIBRARY_LOCATION') . 'cache/cache';
299+
300+ file_put_contents(self::$_location, serialize(self::$_data));
301+ }
302+}
303+?>
304
305=== modified file 'server/lib/app/debug.class.php'
306--- server/lib/app/debug.class.php 2014-01-18 09:47:41 +0000
307+++ server/lib/app/debug.class.php 2014-10-21 16:06:16 +0000
308@@ -22,174 +22,185 @@
309
310 class Debug
311 {
312- public function __construct()
313- {
314- if (!defined('AUDIT'))
315- {
316- // Get the setting from the DB and define it
317- if (Config::GetSetting('audit') != 'On')
318- {
319- define('AUDIT', false);
320- }
321- else
322- {
323- define('AUDIT', true);
324- }
325- }
326- }
327-
328- public function ErrorHandler($errno, $errmsg, $filename, $linenum, $vars) {
329-
330- // timestamp for the error entry
331- $dt = date("Y-m-d H:i:s (T)");
332-
333- // define an assoc array of error string
334- // in reality the only entries we should
335- // consider are E_WARNING, E_NOTICE, E_USER_ERROR,
336- // E_USER_WARNING and E_USER_NOTICE
337- $errortype = array(E_ERROR => 'Error', E_WARNING => 'Warning', E_PARSE =>
338- 'Parsing Error', E_NOTICE => 'Notice', E_CORE_ERROR => 'Core Error',
339- E_CORE_WARNING => 'Core Warning', E_COMPILE_ERROR => 'Compile Error',
340- E_COMPILE_WARNING => 'Compile Warning', E_USER_ERROR => 'User Error',
341- E_USER_WARNING => 'User Warning', E_USER_NOTICE => 'User Notice', E_STRICT =>
342- 'Runtime Notice', E_RECOVERABLE_ERROR => 'Recoverable Error', 8192 => 'Deprecated Call');
343-
344- // set of errors for which a var trace will be saved
345- $user_errors_halt = array(E_USER_ERROR);
346- $user_errors_inline = array(E_USER_WARNING);
347-
348- $err = "<errormsg>" . $errmsg . "</errormsg>\n";
349- $err .= "<errornum>" . $errno . "</errornum>\n";
350- $err .= "<errortype>" . $errortype[$errno] . "</errortype>\n";
351- $err .= "<scriptname>" . $filename . "</scriptname>\n";
352- $err .= "<scriptlinenum>" . $linenum . "</scriptlinenum>\n";
353-
354- // Log everything
355- Debug::LogEntry("error", $err);
356-
357- // Test to see if this is a HALT error or not (we do the same if we are in production or not!)
358- if (in_array($errno, $user_errors_halt))
359- {
360- // We have a halt error
361- Debug::LogEntry('audit', 'Creating a Response Manager to deal with the HALT Error.');
362-
363- $response = new ResponseManager();
364-
365- $response->SetError($errmsg);
366- $response->Respond();
367- }
368-
369- // Is Debug Enabled? (i.e. Development or Support)
370- if (error_reporting() != 0)
371- {
372- if (in_array($errno, $user_errors_inline))
373- {
374- // This is an inline error - therefore we really want to pop up a message box with this in it - so we know?
375- // For now we treat this like a halt error? Or do we just try and output some javascript to pop up an error
376- // surely the javascript idea wont work in ajax?
377- // or prehaps we add this to the session errormessage so we see it at a later date?
378- echo $errmsg;
379- die();
380- }
381- }
382-
383- // Must return false
384- return false;
385- }
386-
387- /**
388- * Mail an error - currently disabled
389- * @return
390- * @param $errmsg Object
391- * @param $err Object
392- */
393- function MailError($errmsg, $err)
394- {
395- return true;
396-
397- $to = 'info@xibo.org.uk';
398-
399- $from = Config::GetSetting("mail_from");
400- if ($from == "") return true;
401-
402- $subject = "Error message from Digital Signage System";
403- $message = wordwrap("$errmsg\n$err");
404-
405- $headers = "From: $from" . "\r\n" . "Reply-To: $from" . "\r\n" .
406- "X-Mailer: PHP/" . phpversion();
407-
408- if (!mail($to, $subject, $message, $headers)) trigger_error("Mail not accepted", E_USER_NOTICE);
409- return true;
410- }
411-
412- /**
413- * Write an Entry to the Log table
414- * @return
415- * @param $db Object
416- * @param $type Object
417- * @param $message Object
418- * @param $page Object[optional]
419- * @param $function Object[optional]
420- * @param $logdate Object[optional]
421- * @param $displayid Object[optional]
422- * @param $scheduleID Object[optional]
423- * @param $layoutid Object[optional]
424- * @param $mediaid Object[optional]
425- */
426- static function LogEntry($type, $message, $page = "", $function = "", $logdate = "", $displayid = 0, $scheduleID = 0, $layoutid = 0, $mediaid = 0)
427- {
428- if ($type == 'audit' && !AUDIT)
429- return;
430-
431- $currentdate = date("Y-m-d H:i:s");
432- $requestUri = Kit::GetParam('REQUEST_URI', $_SERVER, _STRING, 'Not Supplied');
433- $requestIp = Kit::GetParam('REMOTE_ADDR', $_SERVER, _STRING, 'Not Supplied');
434- $requestUserAgent = Kit::GetParam('HTTP_USER_AGENT', $_SERVER, _STRING, 'Not Supplied');
435+ public function __construct()
436+ {
437+ if (!defined('AUDIT'))
438+ {
439+ // Get the setting from the DB and define it
440+ if (Config::GetSetting('audit') != 'On')
441+ {
442+ define('AUDIT', false);
443+ }
444+ else
445+ {
446+ define('AUDIT', true);
447+ }
448+ }
449+ }
450+
451+ public function ErrorHandler($errno, $errmsg, $filename, $linenum, $vars) {
452+
453+ // timestamp for the error entry
454+ $dt = date("Y-m-d H:i:s (T)");
455+
456+ // define an assoc array of error string
457+ // in reality the only entries we should
458+ // consider are E_WARNING, E_NOTICE, E_USER_ERROR,
459+ // E_USER_WARNING and E_USER_NOTICE
460+ $errortype = array(E_ERROR => 'Error', E_WARNING => 'Warning', E_PARSE =>
461+ 'Parsing Error', E_NOTICE => 'Notice', E_CORE_ERROR => 'Core Error',
462+ E_CORE_WARNING => 'Core Warning', E_COMPILE_ERROR => 'Compile Error',
463+ E_COMPILE_WARNING => 'Compile Warning', E_USER_ERROR => 'User Error',
464+ E_USER_WARNING => 'User Warning', E_USER_NOTICE => 'User Notice', E_STRICT =>
465+ 'Runtime Notice', E_RECOVERABLE_ERROR => 'Recoverable Error', 8192 => 'Deprecated Call');
466+
467+ // set of errors for which a var trace will be saved
468+ $user_errors_halt = array(E_USER_ERROR);
469+ $user_errors_inline = array(E_USER_WARNING);
470+
471+ $err = "<errormsg>" . $errmsg . "</errormsg>\n";
472+ $err .= "<errornum>" . $errno . "</errornum>\n";
473+ $err .= "<errortype>" . $errortype[$errno] . "</errortype>\n";
474+ $err .= "<scriptname>" . $filename . "</scriptname>\n";
475+ $err .= "<scriptlinenum>" . $linenum . "</scriptlinenum>\n";
476+
477+ // Log everything
478+ Debug::LogEntry("error", $err);
479+
480+ // Test to see if this is a HALT error or not (we do the same if we are in production or not!)
481+ if (in_array($errno, $user_errors_halt))
482+ {
483+ // We have a halt error
484+ Debug::LogEntry('audit', 'Creating a Response Manager to deal with the HALT Error.');
485+
486+ $response = new ResponseManager();
487+
488+ $response->SetError($errmsg);
489+ $response->Respond();
490+ }
491+
492+ // Is Debug Enabled? (i.e. Development or Support)
493+ if (error_reporting() != 0)
494+ {
495+ if (in_array($errno, $user_errors_inline))
496+ {
497+ // This is an inline error - therefore we really want to pop up a message box with this in it - so we know?
498+ // For now we treat this like a halt error? Or do we just try and output some javascript to pop up an error
499+ // surely the javascript idea wont work in ajax?
500+ // or prehaps we add this to the session errormessage so we see it at a later date?
501+ echo $errmsg;
502+ die();
503+ }
504+ }
505+
506+ // Must return false
507+ return false;
508+ }
509+
510+ /**
511+ * Mail an error - currently disabled
512+ * @return
513+ * @param $errmsg Object
514+ * @param $err Object
515+ */
516+ function MailError($errmsg, $err)
517+ {
518+ return true;
519+
520+ $to = 'info@xibo.org.uk';
521+
522+ $from = Config::GetSetting("mail_from");
523+ if ($from == "") return true;
524+
525+ $subject = "Error message from Digital Signage System";
526+ $message = wordwrap("$errmsg\n$err");
527+
528+ $headers = "From: $from" . "\r\n" . "Reply-To: $from" . "\r\n" .
529+ "X-Mailer: PHP/" . phpversion();
530+
531+ if (!mail($to, $subject, $message, $headers)) trigger_error("Mail not accepted", E_USER_NOTICE);
532+ return true;
533+ }
534+
535+ /**
536+ * Write an Entry to the Log table
537+ * @return
538+ * @param $db Object
539+ * @param $type Object
540+ * @param $message Object
541+ * @param $page Object[optional]
542+ * @param $function Object[optional]
543+ * @param $logdate Object[optional]
544+ * @param $displayid Object[optional]
545+ * @param $scheduleID Object[optional]
546+ * @param $layoutid Object[optional]
547+ * @param $mediaid Object[optional]
548+ */
549+ static function LogEntry($type, $message, $page = "", $function = "", $logdate = "", $displayid = 0, $scheduleID = 0, $layoutid = 0, $mediaid = 0)
550+ {
551+ if ($type == 'audit' && !AUDIT)
552+ return;
553+
554+ $currentdate = date("Y-m-d H:i:s");
555+ $requestUri = Kit::GetParam('REQUEST_URI', $_SERVER, _STRING, 'Not Supplied');
556+ $requestIp = Kit::GetParam('REMOTE_ADDR', $_SERVER, _STRING, 'Not Supplied');
557+ $requestUserAgent = Kit::GetParam('HTTP_USER_AGENT', $_SERVER, _STRING, 'Not Supplied');
558 $requestUserAgent = substr($requestUserAgent, 0, 253);
559- $userid = Kit::GetParam('userid', _SESSION, _INT, 0);
560- $message = Kit::ValidateParam($message, _HTMLSTRING);
561-
562- if ($logdate == "")
563- $logdate = $currentdate;
564-
565- //Prepare the variables
566- if ($page == "")
567- $page = Kit::GetParam('p', _GET, _WORD);
568-
569- // Insert into the DB
570- try {
571- $dbh = PDOConnect::init();
572-
573- $SQL = 'INSERT INTO log (logdate, type, page, function, message, requesturi, remoteaddr, useragent, userid, displayid, scheduleid, layoutid, mediaid) ';
574- $SQL .= ' VALUES (:logdate, :type, :page, :function, :message, :requesturi, :remoteaddr, :useragent, :userid, :displayid, :scheduleid, :layoutid, :mediaid) ';
575-
576- $sth = $dbh->prepare($SQL);
577-
578- $params = array(
579- 'logdate' => $currentdate,
580- 'type' => $type,
581- 'page' => $page,
582- 'function' => $function,
583- 'message' => $message,
584- 'requesturi' => $requestUri,
585- 'remoteaddr' => $requestIp,
586- 'useragent' => $requestUserAgent,
587- 'userid' => $userid,
588- 'displayid' => $displayid,
589- 'scheduleid' => $scheduleID,
590- 'layoutid' => $layoutid,
591- 'mediaid' => $mediaid
592- );
593-
594- $sth->execute($params);
595- }
596- catch (PDOException $e) {
597- // In this case just silently log the error
598- error_log($message . '\n\n', 3, './err_log.xml');
599- error_log($e->getMessage() . '\n\n', 3, './err_log.xml');
600- }
601-
602- return true;
603- }
604+ $userid = Kit::GetParam('userid', _SESSION, _INT, 0);
605+ $message = Kit::ValidateParam($message, _HTMLSTRING);
606+
607+ if ($logdate == "")
608+ $logdate = $currentdate;
609+
610+ //Prepare the variables
611+ if ($page == "")
612+ $page = Kit::GetParam('p', _GET, _WORD);
613+
614+ // Insert into the DB
615+ try {
616+ $dbh = PDOConnect::init();
617+
618+ $SQL = 'INSERT INTO log (logdate, type, page, function, message, requesturi, remoteaddr, useragent, userid, displayid, scheduleid, layoutid, mediaid) ';
619+ $SQL .= ' VALUES (:logdate, :type, :page, :function, :message, :requesturi, :remoteaddr, :useragent, :userid, :displayid, :scheduleid, :layoutid, :mediaid) ';
620+
621+ $sth = $dbh->prepare($SQL);
622+
623+ $params = array(
624+ 'logdate' => $currentdate,
625+ 'type' => $type,
626+ 'page' => $page,
627+ 'function' => $function,
628+ 'message' => $message,
629+ 'requesturi' => $requestUri,
630+ 'remoteaddr' => $requestIp,
631+ 'useragent' => $requestUserAgent,
632+ 'userid' => $userid,
633+ 'displayid' => $displayid,
634+ 'scheduleid' => $scheduleID,
635+ 'layoutid' => $layoutid,
636+ 'mediaid' => $mediaid
637+ );
638+
639+ $sth->execute($params);
640+ }
641+ catch (PDOException $e) {
642+ // In this case just silently log the error
643+ error_log($message . '\n\n', 3, './err_log.xml');
644+ error_log($e->getMessage() . '\n\n', 3, './err_log.xml');
645+ }
646+
647+ return true;
648+ }
649+
650+ public static function Audit($message) {
651+ if (!AUDIT)
652+ return;
653+
654+ // Get the calling class / function
655+ $trace = debug_backtrace();
656+ $caller = $trace[1];
657+
658+ Debug::LogEntry('audit', $message, (isset($caller['class'])) ? $caller['class'] : 'Global', $caller['function']);
659+ }
660 }
661-?>
662\ No newline at end of file
663+?>
664
665=== modified file 'server/lib/app/kit.class.php'
666--- server/lib/app/kit.class.php 2014-09-19 12:55:15 +0000
667+++ server/lib/app/kit.class.php 2014-10-21 16:06:16 +0000
668@@ -45,381 +45,388 @@
669
670 class Kit
671 {
672- // Ends the current execution and issues a redirect - should only be called before headers have been sent (i.e. no output)
673- static function Redirect($page, $message = '')
674- {
675- $url = $page;
676- $ajax = Kit::GetParam('ajax', _REQUEST, _BOOL, false);
677-
678- if ($ajax)
679- {
680- echo json_encode($page);
681- die();
682- }
683-
684- // Header or JS redirect
685- if (headers_sent())
686- {
687- echo "<script>document.location.href='$url';</script>\n";
688- }
689- else
690- {
691- header( 'HTTP/1.1 302 Moved Temporarily' );
692- header( 'Location: ' . $url );
693- }
694-
695- die();
696- }
697-
698- /**
699- * Gets the appropriate Param, making sure its valid
700- * Based on code from Joomla! 1.5
701- * @return
702- * @param $param Object
703- * @param $source Object[optional]
704- * @param $type Object[optional]
705- * @param $default Object[optional]
706- */
707- static public function GetParam($param, $source = _POST, $type = _STRING, $default = '', $sanitize = true)
708- {
709- // lower case param (we dont care)
710- $param = strtolower($param);
711-
712- if (is_array($source))
713- {
714- $source = array_change_key_case($source);
715-
716- if(!isset($source[$param]))
717- {
718- $return = $default;
719- }
720- else
721- {
722- $return = $source[$param];
723- }
724- }
725- else
726- {
727- switch ($source)
728- {
729- case 'session':
730-
731- if (isset($_SESSION))
732- $_tempSESSION = array_change_key_case($_SESSION);
733-
734- if(!isset($_tempSESSION[$param]))
735- {
736- $return = $default;
737- }
738- else if ($type == _CHECKBOX)
739- {
740- // this means that it was defined correctly and it was set
741- $return = 1;
742- }
743- else
744- {
745- if ($_tempSESSION[$param] == '')
746- {
747- $return = $default;
748- }
749- else
750- {
751- $return = $_tempSESSION[$param];
752- }
753- }
754-
755- break;
756-
757- case 'request':
758-
759- $_tempREQUEST = array_change_key_case($_REQUEST);
760-
761- if(!isset($_tempREQUEST[$param]))
762- {
763- $return = $default;
764- }
765- else
766- {
767- if ($_tempREQUEST[$param] == '')
768- {
769- $return = $default;
770- }
771- else
772- {
773- $return = $_tempREQUEST[$param];
774- }
775- }
776-
777- break;
778-
779- case 'get':
780-
781- $_tempGET = array_change_key_case($_GET);
782-
783- if(!isset($_tempGET[$param]))
784- {
785- $return = $default;
786- }
787- else
788- {
789- if ($_tempGET[$param] == '')
790- {
791- $return = $default;
792- }
793- else
794- {
795- $return = $_tempGET[$param];
796- }
797- }
798-
799- break;
800-
801- case 'post':
802-
803- $_tempPOST = array_change_key_case($_POST);
804-
805- if(!isset($_tempPOST[$param]))
806- {
807- $return = $default;
808- }
809- else if ($type == _CHECKBOX)
810- {
811- // this means that it was defined correctly and it was set
812- $return = 1;
813- }
814- else
815- {
816- if ($_tempPOST[$param] == '')
817- {
818- $return = $default;
819- }
820- else
821- {
822- $return = $_tempPOST[$param];
823- }
824- }
825-
826- break;
827-
828- default:
829- return $default;
830- }
831- }
832-
833- // Validate this param
834- return Kit::ValidateParam($return, $type, $sanitize);
835- }
836-
837- /**
838- * Validates a Parameter
839- * Based on code from Joomla! 1.5
840- * @return
841- * @param $param Object
842- * @param $type Object
843- */
844- static function ValidateParam($param, $type, $sanitize = true)
845- {
846- // If we are a NULL always return a null??
847- //if ($param == NULL || $param == '')
848- // return NULL;
849-
850- // Store in return var
851- $return = $param;
852-
853- // Validate
854- // Handle the type constraint
855- switch ($type)
856- {
857- case _INT :
858-
859- if ($sanitize) {
860- // Only use the first integer value
861- if (!$return = filter_var($return, FILTER_SANITIZE_NUMBER_INT))
862- $return = 0;
863- }
864- else {
865- if (!$return = filter_var($return, FILTER_VALIDATE_INT))
866- trigger_error(sprintf(__('No integer match found for [%s] and return value is not an integer'), $param), E_USER_ERROR);
867- }
868-
869- break;
870-
871- case _DOUBLE :
872-
873- if ($sanitize) {
874- // Only use the first integer value
875- if (!$return = filter_var($return, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION))
876- $return = 0;
877- }
878- else {
879- if (!$return = filter_var($return, FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_FRACTION))
880- trigger_error(sprintf(__('No integer match found for %s, and return value is not an integer'), $param), E_USER_ERROR);
881- }
882-
883- break;
884-
885- case _BOOL :
886- $return = filter_var($return, FILTER_VALIDATE_BOOLEAN);
887- break;
888-
889- case _ARRAY :
890- if ($return == '')
891- {
892- $return = array();
893- break;
894- }
895-
896- if (!is_array($return))
897- {
898- $return = array($return);
899- }
900- break;
901-
902- case _ARRAY_INT:
903-
904- if ($return == '') {
905- $return = array();
906- }
907- else {
908- if ($sanitize) {
909- // Only use the first integer value
910- if (!$return = filter_var_array($return, FILTER_SANITIZE_NUMBER_INT))
911- $return = array();
912- }
913- else {
914- if (!$return = filter_var_array($return, FILTER_VALIDATE_INT))
915- trigger_error(sprintf(__('No integer found for %s, and return value is not an integer'), $param), E_USER_ERROR);
916- }
917- }
918- break;
919-
920- case _STRING :
921- case _PASSWORD :
922- $return = filter_var($return, FILTER_SANITIZE_STRING);
923- break;
924-
925- case _STRINGSPECIAL:
926- $return = filter_var($return, FILTER_SANITIZE_SPECIAL_CHARS);
927- break;
928-
929- case _HTMLSTRING :
930-
931- // decimal notation
932- $return = preg_replace_callback('/&#(\d+);/m', function($m){
933- return chr($m[1]);
934- }, $return);
935-
936- // convert hex
937- $return = preg_replace_callback('/&#x([a-f0-9]+);/mi', function($m){
938- return chr("0x".$m[1]);
939- }, $return);
940-
941- $return = (string) $return;
942- break;
943-
944- case _WORD :
945- $return = filter_var($return, FILTER_SANITIZE_STRING);
946- $return = (string) preg_replace( '/[^A-Z_\-]/i', '', $return );
947- break;
948-
949- case _USERNAME :
950- $return = filter_var($return, FILTER_SANITIZE_STRING);
951- $return = (string) preg_replace( '/[\x00-\x1F\x7F<>"\'%&]/', '', $return );
952- $return = strtolower($return);
953- break;
954-
955- case _FILENAME :
956- if ($return == '')
957- {
958- $return = '';
959- break;
960- }
961- // Remove non alphanumerics
962- $return = strtolower($return);
963- $code_entities_match = array('&quot;' ,'!' ,'@' ,'#' ,'$' ,'%' ,'^' ,'&' ,'*' ,'(' ,')' ,'+' ,'{' ,'}' ,'|' ,':' ,'"' ,'<' ,'>' ,'?' ,'[' ,']' ,'' ,';' ,"'" ,',' ,'_' ,'/' ,'*' ,'+' ,'~' ,'`' ,'=' ,' ' ,'---' ,'--','--');
964- $code_entities_replace = array('' ,'-' ,'-' ,'' ,'' ,'' ,'-' ,'-' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'-' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'-' ,'-' ,'-' ,'' ,'' ,'' ,'' ,'' ,'-' ,'-' ,'-','-');
965-
966- $return = str_replace($code_entities_match, $code_entities_replace, $return);
967- break;
968-
969- case _URI :
970- if ($return == '')
971- {
972- $return = '';
973- break;
974- }
975- $return = urlencode($return);
976- break;
977-
978- case _CHECKBOX:
979- if ($return == 'on') {
980- $return = 1;
981- }
982- if ($return == 'off' || $return == '') {
983- $return = 0;
984- }
985-
986- break;
987-
988- default :
989- // No casting necessary
990- if (!$sanitize)
991- trigger_error(sprintf(__('Unknown Type %s'), $type), E_USER_ERROR);
992-
993- break;
994- }
995-
996- return $return;
997- }
998-
999- /**
1000- * Gets a formatted Url
1001- * @return
1002- * @param $page Object[optional]
1003- */
1004- public static function GetURL($page = "")
1005- {
1006- $page = Kit::ValidateParam($page, _WORD);
1007- $fullUrl = 'http';
1008-
1009- if(isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on')
1010- {
1011- $fullUrl .= 's';
1012- }
1013-
1014- $fullUrl .= '://';
1015-
1016- if($_SERVER['SERVER_PORT']!='80')
1017- {
1018- $fullUrl .= $_SERVER['HTTP_HOST'].':'.$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
1019- }
1020- else
1021- {
1022- $fullUrl .= $_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];
1023- }
1024-
1025- // Append the page if its not empty
1026- if ($page != '')
1027- {
1028- $fullUrl .= '?p=' . $page;
1029- }
1030-
1031- return $fullUrl;
1032- }
1033+ // Ends the current execution and issues a redirect - should only be called before headers have been sent (i.e. no output)
1034+ static function Redirect($page, $message = '')
1035+ {
1036+ $url = $page;
1037+ $ajax = Kit::GetParam('ajax', _REQUEST, _BOOL, false);
1038+
1039+ if ($ajax)
1040+ {
1041+ echo json_encode($page);
1042+ die();
1043+ }
1044+
1045+ // Header or JS redirect
1046+ if (headers_sent())
1047+ {
1048+ echo "<script>document.location.href='$url';</script>\n";
1049+ }
1050+ else
1051+ {
1052+ header( 'HTTP/1.1 302 Moved Temporarily' );
1053+ header( 'Location: ' . $url );
1054+ }
1055+
1056+ die();
1057+ }
1058+
1059+ /**
1060+ * Gets the appropriate Param, making sure its valid
1061+ * Based on code from Joomla! 1.5
1062+ * @return
1063+ * @param $param Object
1064+ * @param $source Object[optional]
1065+ * @param $type Object[optional]
1066+ * @param $default Object[optional]
1067+ */
1068+ static public function GetParam($param, $source = _POST, $type = _STRING, $default = '', $sanitize = true)
1069+ {
1070+ // lower case param (we dont care)
1071+ $param = strtolower($param);
1072+
1073+ if (is_array($source))
1074+ {
1075+ $source = array_change_key_case($source);
1076+
1077+ if(!isset($source[$param]))
1078+ {
1079+ $return = $default;
1080+ }
1081+ else
1082+ {
1083+ $return = $source[$param];
1084+ }
1085+ }
1086+ else
1087+ {
1088+ switch ($source)
1089+ {
1090+ case 'session':
1091+
1092+ if (isset($_SESSION))
1093+ $_tempSESSION = array_change_key_case($_SESSION);
1094+
1095+ if(!isset($_tempSESSION[$param]))
1096+ {
1097+ $return = $default;
1098+ }
1099+ else if ($type == _CHECKBOX)
1100+ {
1101+ // this means that it was defined correctly and it was set
1102+ $return = 1;
1103+ }
1104+ else
1105+ {
1106+ if ($_tempSESSION[$param] == '')
1107+ {
1108+ $return = $default;
1109+ }
1110+ else
1111+ {
1112+ $return = $_tempSESSION[$param];
1113+ }
1114+ }
1115+
1116+ break;
1117+
1118+ case 'request':
1119+
1120+ $_tempREQUEST = array_change_key_case($_REQUEST);
1121+
1122+ if(!isset($_tempREQUEST[$param]))
1123+ {
1124+ $return = $default;
1125+ }
1126+ else
1127+ {
1128+ if ($_tempREQUEST[$param] == '')
1129+ {
1130+ $return = $default;
1131+ }
1132+ else
1133+ {
1134+ $return = $_tempREQUEST[$param];
1135+ }
1136+ }
1137+
1138+ break;
1139+
1140+ case 'get':
1141+
1142+ $_tempGET = array_change_key_case($_GET);
1143+
1144+ if(!isset($_tempGET[$param]))
1145+ {
1146+ $return = $default;
1147+ }
1148+ else
1149+ {
1150+ if ($_tempGET[$param] == '')
1151+ {
1152+ $return = $default;
1153+ }
1154+ else
1155+ {
1156+ $return = $_tempGET[$param];
1157+ }
1158+ }
1159+
1160+ break;
1161+
1162+ case 'post':
1163+
1164+ $_tempPOST = array_change_key_case($_POST);
1165+
1166+ if(!isset($_tempPOST[$param]))
1167+ {
1168+ $return = $default;
1169+ }
1170+ else if ($type == _CHECKBOX)
1171+ {
1172+ // this means that it was defined correctly and it was set
1173+ $return = 1;
1174+ }
1175+ else
1176+ {
1177+ if ($_tempPOST[$param] == '')
1178+ {
1179+ $return = $default;
1180+ }
1181+ else
1182+ {
1183+ $return = $_tempPOST[$param];
1184+ }
1185+ }
1186+
1187+ break;
1188+
1189+ default:
1190+ return $default;
1191+ }
1192+ }
1193+
1194+ // Validate this param
1195+ return Kit::ValidateParam($return, $type, $sanitize);
1196+ }
1197+
1198+ /**
1199+ * Validates a Parameter
1200+ * Based on code from Joomla! 1.5
1201+ * @return
1202+ * @param $param Object
1203+ * @param $type Object
1204+ */
1205+ static function ValidateParam($param, $type, $sanitize = true)
1206+ {
1207+ // If we are a NULL always return a null??
1208+ //if ($param == NULL || $param == '')
1209+ // return NULL;
1210+
1211+ // Store in return var
1212+ $return = $param;
1213+
1214+ // Validate
1215+ // Handle the type constraint
1216+ switch ($type)
1217+ {
1218+ case _INT :
1219+
1220+ if ($sanitize) {
1221+ // Only use the first integer value
1222+ if (!$return = filter_var($return, FILTER_SANITIZE_NUMBER_INT))
1223+ $return = 0;
1224+ }
1225+ else {
1226+ if (!$return = filter_var($return, FILTER_VALIDATE_INT))
1227+ trigger_error(sprintf(__('No integer match found for [%s] and return value is not an integer'), $param), E_USER_ERROR);
1228+ }
1229+
1230+ break;
1231+
1232+ case _DOUBLE :
1233+
1234+ if ($sanitize) {
1235+ // Only use the first integer value
1236+ if (!$return = filter_var($return, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION))
1237+ $return = 0;
1238+ }
1239+ else {
1240+ if (!$return = filter_var($return, FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_FRACTION))
1241+ trigger_error(sprintf(__('No integer match found for %s, and return value is not an integer'), $param), E_USER_ERROR);
1242+ }
1243+
1244+ break;
1245+
1246+ case _BOOL :
1247+ $return = filter_var($return, FILTER_VALIDATE_BOOLEAN);
1248+ break;
1249+
1250+ case _ARRAY :
1251+ if ($return == '')
1252+ {
1253+ $return = array();
1254+ break;
1255+ }
1256+
1257+ if (!is_array($return))
1258+ {
1259+ $return = array($return);
1260+ }
1261+ break;
1262+
1263+ case _ARRAY_INT:
1264+
1265+ if ($return == '') {
1266+ $return = array();
1267+ }
1268+ else {
1269+ if ($sanitize) {
1270+ // Only use the first integer value
1271+ if (!$return = filter_var_array($return, FILTER_SANITIZE_NUMBER_INT))
1272+ $return = array();
1273+ }
1274+ else {
1275+ if (!$return = filter_var_array($return, FILTER_VALIDATE_INT))
1276+ trigger_error(sprintf(__('No integer found for %s, and return value is not an integer'), $param), E_USER_ERROR);
1277+ }
1278+ }
1279+ break;
1280+
1281+ case _STRING :
1282+ case _PASSWORD :
1283+ $return = filter_var($return, FILTER_SANITIZE_STRING);
1284+ break;
1285+
1286+ case _STRINGSPECIAL:
1287+ $return = filter_var($return, FILTER_SANITIZE_SPECIAL_CHARS);
1288+ break;
1289+
1290+ case _HTMLSTRING :
1291+
1292+ // decimal notation
1293+ $return = preg_replace_callback('/&#(\d+);/m', function($m){
1294+ return chr($m[1]);
1295+ }, $return);
1296+
1297+ // convert hex
1298+ $return = preg_replace_callback('/&#x([a-f0-9]+);/mi', function($m){
1299+ return chr("0x".$m[1]);
1300+ }, $return);
1301+
1302+ $return = (string) $return;
1303+ break;
1304+
1305+ case _WORD :
1306+ $return = filter_var($return, FILTER_SANITIZE_STRING);
1307+ $return = (string) preg_replace( '/[^A-Z_\-]/i', '', $return );
1308+ break;
1309+
1310+ case _USERNAME :
1311+ $return = filter_var($return, FILTER_SANITIZE_STRING);
1312+ $return = (string) preg_replace( '/[\x00-\x1F\x7F<>"\'%&]/', '', $return );
1313+ $return = strtolower($return);
1314+ break;
1315+
1316+ case _FILENAME :
1317+ if ($return == '')
1318+ {
1319+ $return = '';
1320+ break;
1321+ }
1322+ // Remove non alphanumerics
1323+ $return = strtolower($return);
1324+ $code_entities_match = array('&quot;' ,'!' ,'@' ,'#' ,'$' ,'%' ,'^' ,'&' ,'*' ,'(' ,')' ,'+' ,'{' ,'}' ,'|' ,':' ,'"' ,'<' ,'>' ,'?' ,'[' ,']' ,'' ,';' ,"'" ,',' ,'_' ,'/' ,'*' ,'+' ,'~' ,'`' ,'=' ,' ' ,'---' ,'--','--');
1325+ $code_entities_replace = array('' ,'-' ,'-' ,'' ,'' ,'' ,'-' ,'-' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'-' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'-' ,'-' ,'-' ,'' ,'' ,'' ,'' ,'' ,'-' ,'-' ,'-','-');
1326+
1327+ $return = str_replace($code_entities_match, $code_entities_replace, $return);
1328+ break;
1329+
1330+ case _URI :
1331+ if ($return == '')
1332+ {
1333+ $return = '';
1334+ break;
1335+ }
1336+ $return = urlencode($return);
1337+ break;
1338+
1339+ case _CHECKBOX:
1340+ if ($return == 'on') {
1341+ $return = 1;
1342+ }
1343+ if ($return == 'off' || $return == '') {
1344+ $return = 0;
1345+ }
1346+
1347+ break;
1348+
1349+ default :
1350+ // No casting necessary
1351+ if (!$sanitize)
1352+ trigger_error(sprintf(__('Unknown Type %s'), $type), E_USER_ERROR);
1353+
1354+ break;
1355+ }
1356+
1357+ return $return;
1358+ }
1359+
1360+ /**
1361+ * Gets a formatted Url
1362+ * @return
1363+ * @param $page Object[optional]
1364+ */
1365+ public static function GetURL($page = "")
1366+ {
1367+ $page = Kit::ValidateParam($page, _WORD);
1368+ $fullUrl = 'http';
1369+
1370+ if(isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on')
1371+ {
1372+ $fullUrl .= 's';
1373+ }
1374+
1375+ $fullUrl .= '://';
1376+
1377+ if($_SERVER['SERVER_PORT']!='80')
1378+ {
1379+ $fullUrl .= $_SERVER['HTTP_HOST'].':'.$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
1380+ }
1381+ else
1382+ {
1383+ $fullUrl .= $_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];
1384+ }
1385+
1386+ // Append the page if its not empty
1387+ if ($page != '')
1388+ {
1389+ $fullUrl .= '?p=' . $page;
1390+ }
1391+
1392+ return $fullUrl;
1393+ }
1394
1395 /**
1396- * Ensures a the relevant file for a class is inclued
1397+ * Ensures a the relevant file for a class is included
1398 * @param <string> $class
1399 * @return <boolean> False on failure
1400 */
1401 static function ClassLoader($class)
1402- {
1403+ {
1404 if (class_exists($class))
1405 return;
1406
1407 $class = strtolower($class);
1408
1409- // It doesnt already exist - so lets look in some places to try and find it
1410+ if (strpos($class, 'manager')) {
1411+ // Load from app
1412+ if (file_exists('lib/app/' . $class . '.class.php')) {
1413+ include_once('lib/app/' . $class . '.class.php');
1414+ }
1415+ }
1416+
1417+ // It doesn't already exist - so lets look in some places to try and find it
1418 if (file_exists('lib/pages/' . $class . '.class.php'))
1419 {
1420 include_once('lib/pages/' . $class . '.class.php');
1421@@ -444,7 +451,7 @@
1422 {
1423 include_once('lib/service/' . $class . '.class.php');
1424 }
1425- }
1426+ }
1427
1428 /**
1429 * GetXiboRoot
1430@@ -570,85 +577,89 @@
1431 }
1432
1433 public static function ReturnBytes($val) {
1434-
1435- $val = trim($val);
1436- $last = strtolower($val[strlen($val)-1]);
1437- switch($last) {
1438- // The 'G' modifier is available since PHP 5.1.0
1439- case 'g':
1440- $val *= 1024;
1441- case 'm':
1442- $val *= 1024;
1443- case 'k':
1444- $val *= 1024;
1445- }
1446-
1447- return $val;
1448- }
1449-
1450- /**
1451- * Creates a form token
1452- * @return
1453- */
1454- public static function Token($tokenName = "token")
1455- {
1456- //Store in the users session
1457- $token = md5(uniqid() . SECRET_KEY . time());
1458-
1459- $_SESSION[$tokenName] = $token;
1460- $_SESSION[$tokenName.'_timeout'] = time();
1461-
1462- return '<input type="hidden" name="' . $tokenName . '" value="' . $token . '">';
1463- }
1464-
1465- /**
1466- * Checks a form token
1467- * @param string token
1468- * @return
1469- */
1470- public static function CheckToken($tokenName = "token")
1471- {
1472- if (!isset($_POST[$tokenName]) || !isset($_SESSION[$tokenName]))
1473- return false;
1474-
1475- if ($_POST[$tokenName] == $_SESSION[$tokenName])
1476- {
1477- // See if its still in Date
1478- if (($_SESSION[$tokenName.'_timeout'] + 1200) <= time())
1479- {
1480- return false;
1481- }
1482- return true;
1483- }
1484- else
1485- {
1486- unset($_SESSION[$tokenName]);
1487-
1488- Debug::LogEntry('error', "Form token incorrect from: ". $_SERVER['REMOTE_ADDR']. " with token [" . $_POST[$tokenName] . "] for session_id [" . session_id() . ']');
1489- return false;
1490- }
1491- }
1492-
1493- /**
1494- * Format Bytes
1495- * http://stackoverflow.com/questions/2510434/format-bytes-to-kilobytes-megabytes-gigabytes
1496- * @param [int] $size The file size in bytes
1497- * @param integer $precision The precision to go to
1498- * @return [string] The Formatted string with suffix
1499- */
1500- public static function formatBytes($size, $precision = 2) {
1501-
1502- if ($size == 0)
1503- return 0;
1504-
1505- $base = log($size) / log(1024);
1506- $suffixes = array('', 'k', 'M', 'G', 'T');
1507-
1508- return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
1509- }
1510-
1511- public static function uniqueId() {
1512- return uniqid(rand());
1513- }
1514+
1515+ $val = trim($val);
1516+ $last = strtolower($val[strlen($val)-1]);
1517+ switch($last) {
1518+ // The 'G' modifier is available since PHP 5.1.0
1519+ case 'g':
1520+ $val *= 1024;
1521+ case 'm':
1522+ $val *= 1024;
1523+ case 'k':
1524+ $val *= 1024;
1525+ }
1526+
1527+ return $val;
1528+ }
1529+
1530+ /**
1531+ * Creates a form token
1532+ * @return
1533+ */
1534+ public static function Token($tokenName = "token", $withInput = true)
1535+ {
1536+ //Store in the users session
1537+ $token = md5(uniqid() . SECRET_KEY . time());
1538+
1539+ $_SESSION[$tokenName] = $token;
1540+ $_SESSION[$tokenName.'_timeout'] = time();
1541+
1542+ if ($withInput)
1543+ return '<input type="hidden" name="' . $tokenName . '" value="' . $token . '">';
1544+ else
1545+ return $token;
1546+ }
1547+
1548+ /**
1549+ * Checks a form token
1550+ * @param string token
1551+ * @return
1552+ */
1553+ public static function CheckToken($tokenName = "token")
1554+ {
1555+ if (!isset($_POST[$tokenName]) || !isset($_SESSION[$tokenName]))
1556+ return false;
1557+
1558+ if ($_POST[$tokenName] == $_SESSION[$tokenName])
1559+ {
1560+ // See if its still in Date
1561+ if (($_SESSION[$tokenName.'_timeout'] + 1200) <= time())
1562+ {
1563+ return false;
1564+ }
1565+ return true;
1566+ }
1567+ else
1568+ {
1569+ unset($_SESSION[$tokenName]);
1570+
1571+ Debug::LogEntry('error', "Form token incorrect from: ". $_SERVER['REMOTE_ADDR']. " with token [" . $_POST[$tokenName] . "] for session_id [" . session_id() . ']');
1572+ return false;
1573+ }
1574+ }
1575+
1576+ /**
1577+ * Format Bytes
1578+ * http://stackoverflow.com/questions/2510434/format-bytes-to-kilobytes-megabytes-gigabytes
1579+ * @param [int] $size The file size in bytes
1580+ * @param integer $precision The precision to go to
1581+ * @return [string] The Formatted string with suffix
1582+ */
1583+ public static function formatBytes($size, $precision = 2)
1584+ {
1585+ if ($size == 0)
1586+ return 0;
1587+
1588+ $base = log($size) / log(1024);
1589+ $suffixes = array('', 'k', 'M', 'G', 'T');
1590+
1591+ return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
1592+ }
1593+
1594+ public static function uniqueId()
1595+ {
1596+ return uniqid(rand());
1597+ }
1598 }
1599 ?>
1600
1601=== modified file 'server/lib/app/modulemanager.class.php'
1602--- server/lib/app/modulemanager.class.php 2014-03-08 14:41:11 +0000
1603+++ server/lib/app/modulemanager.class.php 2014-10-21 16:06:16 +0000
1604@@ -22,7 +22,6 @@
1605
1606 class ModuleManager
1607 {
1608- private $db;
1609 private $user;
1610
1611 public $message;
1612@@ -34,13 +33,11 @@
1613 /**
1614 * Constructs the Module Manager.
1615 * @return
1616- * @param $db Object
1617 * @param $user Object
1618 */
1619- public function __construct(database $db, User $user, $regionSpecific = -1, $module = '', $assignable = 1)
1620+ public function __construct(User $user, $regionSpecific = -1, $module = '', $assignable = 1)
1621 {
1622- $this->db =& $db;
1623- $this->user =& $user;
1624+ $this->user =& $user;
1625
1626 if (!$this->theMenu = $user->ModuleAuth($regionSpecific, $module, $assignable))
1627 {
1628
1629=== modified file 'server/lib/app/permissionmanager.class.php'
1630--- server/lib/app/permissionmanager.class.php 2014-01-18 09:47:41 +0000
1631+++ server/lib/app/permissionmanager.class.php 2014-10-21 16:06:16 +0000
1632@@ -22,7 +22,6 @@
1633
1634 class PermissionManager
1635 {
1636- private $db;
1637 private $user;
1638
1639 public $ownerId;
1640@@ -38,9 +37,8 @@
1641 * @param $db Object
1642 * @param $user Object
1643 */
1644- public function __construct(database $db, User $user)
1645+ public function __construct(User $user)
1646 {
1647- $this->db =& $db;
1648 $this->user =& $user;
1649
1650 $this->view = false;
1651
1652=== modified file 'server/lib/app/responsemanager.class.php'
1653--- server/lib/app/responsemanager.class.php 2014-08-11 18:44:46 +0000
1654+++ server/lib/app/responsemanager.class.php 2014-10-21 16:06:16 +0000
1655@@ -54,6 +54,7 @@
1656 public $focusInFirstInput;
1657 public $appendHiddenSubmit;
1658 public $modal;
1659+ public $nextToken;
1660
1661 public $login;
1662 public $clockUpdate;
1663@@ -199,7 +200,7 @@
1664 $this->message = $message;
1665 $this->refresh = $refresh;
1666 $this->refreshLocation = $refreshLocation;
1667-
1668+ $this->nextToken = Kit::Token();
1669 return;
1670 }
1671
1672@@ -317,6 +318,7 @@
1673 $response['refreshLocation']= $this->refreshLocation;
1674 $response['focusInFirstInput']= $this->focusInFirstInput;
1675 $response['modal'] = $this->modal;
1676+ $response['nextToken'] = $this->nextToken;
1677
1678 // Login
1679 $response['login'] = $this->login;
1680
1681=== modified file 'server/lib/app/session.class.php'
1682--- server/lib/app/session.class.php 2014-06-15 14:39:41 +0000
1683+++ server/lib/app/session.class.php 2014-10-21 16:06:16 +0000
1684@@ -160,8 +160,9 @@
1685 // we do not want to update the expiry time of a session if it is the Clock Timer going off
1686 $page = Kit::GetParam('p', _REQUEST, _WORD);
1687 $query = Kit::GetParam('q', _REQUEST, _WORD);
1688+ $autoRefresh = (isset($_REQUEST['autoRefresh']) && Kit::GetParam('autoRefresh', _REQUEST, _WORD, 'false') == 'true');
1689
1690- if (($page == 'clock' && $query == 'GetClock') || ($page == 'index' && $query == 'PingPong') || ($page == 'layout' && $query == 'LayoutStatus')) {
1691+ if ($autoRefresh || ($page == 'clock' && $query == 'GetClock') || ($page == 'index' && $query == 'PingPong') || ($page == 'layout' && $query == 'LayoutStatus')) {
1692
1693 // Update the existing session without the expiry
1694 $SQL = "UPDATE session SET session_data = :session_data WHERE session_id = :session_id ";
1695@@ -336,10 +337,16 @@
1696 * @param type $secondKey
1697 * @return boolean
1698 */
1699- public static function Get($key, $secondKey)
1700+ public static function Get($key, $secondKey = NULL)
1701 {
1702- if (isset($_SESSION[$key][$secondKey]))
1703- return $_SESSION[$key][$secondKey];
1704+ if ($secondKey != NULL) {
1705+ if (isset($_SESSION[$key][$secondKey]))
1706+ return $_SESSION[$key][$secondKey];
1707+ }
1708+ else {
1709+ if (isset($_SESSION[$key]))
1710+ return $_SESSION[$key];
1711+ }
1712
1713 return false;
1714 }
1715
1716=== modified file 'server/lib/app/thememanager.class.php'
1717--- server/lib/app/thememanager.class.php 2014-08-17 12:38:20 +0000
1718+++ server/lib/app/thememanager.class.php 2014-10-21 16:06:16 +0000
1719@@ -152,6 +152,46 @@
1720 }
1721
1722 /**
1723+ * Get Item Path
1724+ * @param string $item The Item required
1725+ */
1726+ public static function ItemPath($item) {
1727+
1728+ $theme = Theme::GetInstance();
1729+
1730+ // See if we have the requested file in the theme folder
1731+ if (file_exists('theme/' . $theme->name . '/' . $item)) {
1732+ return 'theme/' . $theme->name . '/' . $item;
1733+ }
1734+ // If not, then use the default folder
1735+ elseif (file_exists('theme/default/' . $item)) {
1736+ return 'theme/default/' . $item;
1737+ }
1738+ else
1739+ return '';
1740+ }
1741+
1742+ /**
1743+ * Get Item Path
1744+ * @param string $item The Item required
1745+ */
1746+ public static function Script($item) {
1747+
1748+ $theme = Theme::GetInstance();
1749+
1750+ // See if we have the requested file in the theme folder
1751+ if (file_exists('theme/' . $theme->name . '/' . $item)) {
1752+ return '<script src="theme/' . $theme->name . '/' . $item . '"></script>';
1753+ }
1754+ // If not, then use the default folder
1755+ elseif (file_exists('theme/default/' . $item)) {
1756+ return '<script src="theme/default/' . $item . '"></script>';
1757+ }
1758+ else
1759+ return '';
1760+ }
1761+
1762+ /**
1763 * Translate a string into the user language
1764 * @param string $string The String to Translate
1765 * @param array $args Variables to insert (will replace %d %s in order)
1766@@ -181,6 +221,22 @@
1767 return $return;
1768 }
1769
1770+ public static function SetTranslation($key, $value) {
1771+ // Get existing translations
1772+ $translations = Theme::Get('translations');
1773+
1774+ if ($translations == '') {
1775+ $translations = array();
1776+ }
1777+ else {
1778+ $translations = json_decode($translations, true);
1779+ }
1780+
1781+ $translations[$key] = $value;
1782+
1783+ Theme::Set('translations', json_encode($translations));
1784+ }
1785+
1786 public static function Prepare($string) {
1787 return htmlspecialchars($string);
1788 }
1789
1790=== modified file 'server/lib/app/translationengine.class.php'
1791--- server/lib/app/translationengine.class.php 2014-08-17 12:38:20 +0000
1792+++ server/lib/app/translationengine.class.php 2014-10-21 16:06:16 +0000
1793@@ -27,85 +27,86 @@
1794
1795 class TranslationEngine
1796 {
1797+ private static $locale;
1798+ private static $jsLocale;
1799+
1800 /**
1801 * Gets and Sets the Local
1802 * @return
1803 */
1804 public static function InitLocale($language = NULL)
1805 {
1806- $localeDir = 'locale';
1807- $default = ($language == NULL) ? Config::GetSetting('DEFAULT_LANGUAGE') : $language;
1808-
1809- global $transEngine;
1810- global $stream;
1811-
1812- //Debug::LogEntry('audit', 'IN', 'TranslationEngine', 'InitLocal');
1813-
1814- // Try to get the local firstly from _REQUEST (post then get)
1815- $lang = Kit::GetParam('lang', _REQUEST, _WORD, '');
1816-
1817- // Build an array of supported languages
1818- $supportedLangs = scandir($localeDir);
1819-
1820- if ($lang != '')
1821- {
1822- // Set the language
1823- //Debug::LogEntry('audit', 'Set the Language from REQUEST [' . $lang . ']', 'TranslationEngine', 'InitLocal');
1824-
1825- // Is this language supported?
1826- // if not just use the default (eb_GB).
1827- if (!in_array($lang . '.mo', $supportedLangs))
1828- {
1829- trigger_error(sprintf('Language not supported. %s', $lang));
1830-
1831- // Use the default language instead.
1832- $lang = $default;
1833- }
1834- }
1835- else
1836- {
1837- $langs = Kit::GetParam('HTTP_ACCEPT_LANGUAGE', $_SERVER, _STRING);
1838-
1839- if ($langs != '')
1840- {
1841- //Debug::LogEntry('audit', ' HTTP_ACCEPT_LANGUAGE [' . $langs . ']', 'TranslationEngine', 'InitLocal');
1842- $langs = explode(',', $langs);
1843-
1844- foreach ($langs as $lang)
1845- {
1846- // Remove any quality rating (as we aren't interested)
1847- $rawLang = explode(';', $lang);
1848- $lang = str_replace("-", "_", $rawLang[0]);
1849-
1850- if (in_array($lang . '.mo', $supportedLangs))
1851- {
1852- //Debug::LogEntry('audit', 'Obtained the Language from HTTP_ACCEPT_LANGUAGE [' . $lang . ']', 'TranslationEngine', 'InitLocal');
1853- break;
1854- }
1855-
1856- // Set lang as the default
1857- $lang = $default;
1858+ $localeDir = 'locale';
1859+ $default = ($language == NULL) ? Config::GetSetting('DEFAULT_LANGUAGE') : $language;
1860+
1861+ global $transEngine;
1862+ global $stream;
1863+
1864+ //Debug::LogEntry('audit', 'IN', 'TranslationEngine', 'InitLocal');
1865+ // Build an array of supported languages
1866+ $supportedLangs = scandir($localeDir);
1867+
1868+ // Try to get the local firstly from _REQUEST (post then get)
1869+ $lang = Kit::GetParam('lang', _REQUEST, _WORD, '');
1870+
1871+ // If we don't have a language, try from HTTP accept
1872+ if ($lang == '' && Config::GetSetting('DETECT_LANGUAGE') == 1) {
1873+ $langs = Kit::GetParam('HTTP_ACCEPT_LANGUAGE', $_SERVER, _STRING);
1874+
1875+ if ($langs != '') {
1876+ //Debug::LogEntry('audit', ' HTTP_ACCEPT_LANGUAGE [' . $langs . ']', 'TranslationEngine', 'InitLocal');
1877+ $langs = explode(',', $langs);
1878+
1879+ foreach ($langs as $lang) {
1880+ // Remove any quality rating (as we aren't interested)
1881+ $rawLang = explode(';', $lang);
1882+ $lang = str_replace('-', '_', $rawLang[0]);
1883+
1884+ if (in_array($lang . '.mo', $supportedLangs)) {
1885+ //Debug::LogEntry('audit', 'Obtained the Language from HTTP_ACCEPT_LANGUAGE [' . $lang . ']', 'TranslationEngine', 'InitLocal');
1886+ break;
1887 }
1888- }
1889- else
1890- {
1891+
1892+ // Set lang as the default
1893 $lang = $default;
1894 }
1895 }
1896-
1897- // We have the language
1898- //Debug::LogEntry('audit', 'Creating new file streamer for '. $localeDir . '/' . $lang . '.mo', 'TranslationEngine', 'InitLocal');
1899-
1900- if (!$stream = new CachedFileReader($localeDir . '/' . $lang . '.mo'))
1901- {
1902- trigger_error('Unable to translate this language');
1903- $transEngine = false;
1904-
1905- return;
1906- }
1907-
1908- $transEngine = new gettext_reader($stream);
1909+ }
1910+
1911+ // Are we still empty?
1912+ if ($lang == '')
1913+ $lang = $default;
1914+
1915+ // Sanitize it
1916+ $lang = str_replace('-', '_', $lang);
1917+ $jsLang = str_replace('_', '-', $lang);
1918+
1919+ // Check its valid
1920+ if (!in_array($lang . '.mo', $supportedLangs)) {
1921+ trigger_error(sprintf('Language not supported. %s', $lang));
1922+
1923+ // Fall back
1924+ $lang = 'en_GB';
1925+ }
1926+
1927+ //Debug::LogEntry('audit', 'Creating new file streamer for '. $localeDir . '/' . $lang . '.mo', 'TranslationEngine', 'InitLocal');
1928+ if (!$stream = new CachedFileReader($localeDir . '/' . $lang . '.mo')) {
1929+ $transEngine = false;
1930+ return;
1931+ }
1932+
1933+ $transEngine = new gettext_reader($stream);
1934+ self::$locale = $lang;
1935+ self::$jsLocale = str_replace('_', '-', $lang);
1936 }
1937+
1938+ public static function GetLocale() {
1939+ return self::$locale;
1940+ }
1941+
1942+ public static function GetJsLocale() {
1943+ return self::$jsLocale;
1944+ }
1945 }
1946
1947 /**
1948
1949=== modified file 'server/lib/data/campaign.data.class.php'
1950--- server/lib/data/campaign.data.class.php 2014-01-18 09:47:41 +0000
1951+++ server/lib/data/campaign.data.class.php 2014-10-21 16:06:16 +0000
1952@@ -97,12 +97,14 @@
1953 throw new Exception(__('Unable to Unlink'));
1954
1955 // Remove all permissions
1956- Kit::ClassLoader('campaignsecurity');
1957 $security = new CampaignSecurity($this->db);
1958
1959 if (!$security->UnlinkAll($campaignId))
1960 throw new Exception(__('Unable to set permissions'));
1961
1962+ // Remove from all Schedules
1963+ Schedule::DeleteScheduleForCampaign($campaignId);
1964+
1965 // Delete from the Campaign
1966 $sth = $dbh->prepare('DELETE FROM `campaign` WHERE CampaignID = :campaignid');
1967 $sth->execute(array(
1968
1969=== modified file 'server/lib/data/campaignsecurity.data.class.php'
1970--- server/lib/data/campaignsecurity.data.class.php 2014-01-18 09:47:41 +0000
1971+++ server/lib/data/campaignsecurity.data.class.php 2014-10-21 16:06:16 +0000
1972@@ -22,6 +22,15 @@
1973
1974 class CampaignSecurity extends Data
1975 {
1976+ public function GetPermissions($objectId)
1977+ {
1978+ $userGroup = new UserGroup();
1979+ if (!$result = $userGroup->GetPermissionsForObject('lkcampaigngroup', 'CampaignID', $objectId))
1980+ return $this->SetError($userGroup->GetErrorMessage());
1981+
1982+ return $result;
1983+ }
1984+
1985 /**
1986 * Links a Campaign to a Group
1987 * @return
1988
1989=== modified file 'server/lib/data/datasetdata.data.class.php'
1990--- server/lib/data/datasetdata.data.class.php 2014-08-06 11:57:27 +0000
1991+++ server/lib/data/datasetdata.data.class.php 2014-10-21 16:06:16 +0000
1992@@ -355,6 +355,10 @@
1993 $rowNumber++;
1994 }
1995
1996+ // Close the file
1997+ fclose($handle);
1998+
1999+ // Change the auto detect setting back
2000 ini_set('auto_detect_line_endings', false);
2001
2002 // Delete the temporary file
2003
2004=== modified file 'server/lib/data/datasetgroupsecurity.data.class.php'
2005--- server/lib/data/datasetgroupsecurity.data.class.php 2014-07-10 21:09:24 +0000
2006+++ server/lib/data/datasetgroupsecurity.data.class.php 2014-10-21 16:06:16 +0000
2007@@ -27,46 +27,24 @@
2008 if ($dataSetId == 0 || $dataSetId == '')
2009 return $this->SetError(25001, __('Missing dataSetId'));
2010
2011- try {
2012- $dbh = PDOConnect::init();
2013-
2014- $sth = $dbh->prepare('SELECT `group`.groupid, `group`.`group`, view, edit, del, `group`.isuserspecific
2015- FROM `group`
2016- LEFT OUTER JOIN lkdatasetgroup
2017- ON lkdatasetgroup.GroupID = group.GroupID
2018- AND lkdatasetgroup.DataSetID = :datasetid
2019- WHERE `group`.GroupID <> :groupid
2020- ORDER BY `group`.IsEveryone DESC, `group`.IsUserSpecific, `group`.`Group`');
2021-
2022- $sth->execute(array(
2023- 'datasetid' => $dataSetId,
2024- 'groupid' => $groupId
2025- ));
2026-
2027- $security = array();
2028-
2029- foreach($sth->fetchAll() as $row) {
2030- $security[] = array(
2031- 'groupid' => Kit::ValidateParam($row['groupid'], _INT),
2032- 'group' => Kit::ValidateParam($row['group'], _STRING),
2033- 'view' => Kit::ValidateParam($row['view'], _INT),
2034- 'edit' => Kit::ValidateParam($row['edit'], _INT),
2035- 'del' => Kit::ValidateParam($row['del'], _INT),
2036- 'isuserspecific' => Kit::ValidateParam($row['isuserspecific'], _INT),
2037- );
2038- }
2039-
2040- return $security;
2041- }
2042- catch (Exception $e) {
2043-
2044- Debug::LogEntry('error', $e->getMessage());
2045-
2046- if (!$this->IsError())
2047- $this->SetError(1, __('Unknown Error'));
2048-
2049- return false;
2050- }
2051+ $userGroup = new UserGroup();
2052+ if (!$result = $userGroup->GetPermissionsForObject('lkdatasetgroup', 'DataSetID', $dataSetId))
2053+ return $this->SetError($userGroup->GetErrorMessage());
2054+
2055+ $security = array();
2056+
2057+ foreach($result as $row) {
2058+ $security[] = array(
2059+ 'groupid' => Kit::ValidateParam($row['groupid'], _INT),
2060+ 'group' => Kit::ValidateParam($row['group'], _STRING),
2061+ 'view' => Kit::ValidateParam($row['view'], _INT),
2062+ 'edit' => Kit::ValidateParam($row['edit'], _INT),
2063+ 'del' => Kit::ValidateParam($row['del'], _INT),
2064+ 'isuserspecific' => Kit::ValidateParam($row['isuserspecific'], _INT),
2065+ );
2066+ }
2067+
2068+ return $security;
2069 }
2070
2071 /**
2072
2073=== modified file 'server/lib/data/display.data.class.php'
2074--- server/lib/data/display.data.class.php 2014-09-16 10:59:55 +0000
2075+++ server/lib/data/display.data.class.php 2014-10-21 16:06:16 +0000
2076@@ -63,6 +63,7 @@
2077 public $screenShotRequested;
2078
2079 public $displayGroupId;
2080+ private $_config;
2081
2082 public function Load() {
2083 try {
2084@@ -105,7 +106,7 @@
2085 $this->wakeOnLanTime = Kit::ValidateParam($row['WakeOnLanTime'], _STRING);
2086 $this->broadCastAddress = Kit::ValidateParam($row['BroadCastAddress'], _STRING);
2087 $this->secureOn = Kit::ValidateParam($row['SecureOn'], _STRING);
2088- $this->cidr = Kit::ValidateParam($row['Cidr'], _INT);
2089+ $this->cidr = Kit::ValidateParam($row['Cidr'], _STRING);
2090 $this->latitude = Kit::ValidateParam($row['Latitude'], _DOUBLE);
2091 $this->longitude = Kit::ValidateParam($row['Longitude'], _DOUBLE);
2092 $this->versionInstructions = Kit::ValidateParam($row['version_instructions'], _STRING);
2093@@ -656,7 +657,137 @@
2094
2095 return false;
2096 }
2097-
2098+ }
2099+
2100+ public function GetSetting($key, $default) {
2101+
2102+ if (!$this->SetConfig())
2103+ return false;
2104+
2105+ // Find
2106+ $return = $default;
2107+ foreach($this->_config as $row) {
2108+ if ($row['name'] == $key || $row['name'] == ucfirst($key)) {
2109+ //Debug::Audit('Found ' . $key . '. value= ' . $row['value']);
2110+ $return = $row['value'];
2111+ break;
2112+ }
2113+ }
2114+
2115+ return $return;
2116+ }
2117+
2118+ private function SetConfig() {
2119+ if ($this->_config == null) {
2120+ try {
2121+ $dbh = PDOConnect::init();
2122+
2123+ $displayProfile = new DisplayProfile();
2124+ $displayProfile->displayProfileId = $this->displayProfileId;
2125+
2126+ if ($displayProfile->displayProfileId == 0) {
2127+ // Load the default profile
2128+ $displayProfile->type = $this->clientType;
2129+ $displayProfile->LoadDefault();
2130+ }
2131+ else {
2132+ // Load the specified profile
2133+ $displayProfile->Load();
2134+ }
2135+
2136+ $this->_config = $displayProfile->config;
2137+
2138+ return true;
2139+ }
2140+ catch (Exception $e) {
2141+
2142+ Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__);
2143+
2144+ if (!$this->IsError())
2145+ $this->SetError(1, __('Unknown Error'));
2146+
2147+ return false;
2148+ }
2149+ }
2150+ }
2151+ /**
2152+ * Assess each Display to correctly set the logged in flag based on last accessed time
2153+ * @return
2154+ */
2155+ public static function ValidateDisplays() {
2156+ // Maintain an array of timed out displays
2157+ $timedOutDisplays = array();
2158+
2159+ try {
2160+ $dbh = PDOConnect::init();
2161+ $statObject = new Stat();
2162+
2163+ // Get a list of all displays and there last accessed / alert time out value
2164+ $sth = $dbh->prepare('SELECT displayid, display, lastaccessed, alert_timeout, client_type, displayprofileid, email_alert, loggedin FROM display');
2165+ $sthUpdate = $dbh->prepare('UPDATE display SET loggedin = 0 WHERE displayid = :displayid');
2166+
2167+ $sth->execute(array());
2168+
2169+ // Get the global time out (overrides the alert time out on the display if 0)
2170+ $globalTimeout = Config::GetSetting('MAINTENANCE_ALERT_TOUT') * 60;
2171+
2172+ $displays = $sth->fetchAll();
2173+
2174+ foreach ($displays as $row) {
2175+ $displayid = Kit::ValidateParam($row['displayid'], _INT);
2176+ $lastAccessed = Kit::ValidateParam($row['lastaccessed'], _INT);
2177+ $alertTimeout = Kit::ValidateParam($row['alert_timeout'], _INT);
2178+ $clientType = Kit::ValidateParam($row['client_type'], _WORD);
2179+ $loggedIn = Kit::ValidateParam($row['loggedin'], _INT);
2180+
2181+ // Get the config object
2182+ if ($alertTimeout == 0) {
2183+ $displayProfileId = (empty($row['displayprofileid']) ? 0 : Kit::ValidateParam($row['displayprofileid'], _INT));
2184+
2185+ $display = new Display();
2186+ $display->displayId = $displayid;
2187+ $display->displayProfileId = $displayProfileId;
2188+ $display->clientType = $clientType;
2189+ $timeoutToTestAgainst = $display->GetSetting('collectInterval', $globalTimeout);
2190+ }
2191+ else {
2192+ $timeoutToTestAgainst = $globalTimeout;
2193+ }
2194+
2195+ // Store the time out to test against
2196+ $row['timeout'] = $timeoutToTestAgainst;
2197+ $timeOut = $lastAccessed + $timeoutToTestAgainst;
2198+
2199+ // If the last time we accessed is less than now minus the time out
2200+ if ($timeOut < time()) {
2201+ Debug::Audit('Timed out display. Last Accessed: ' . date('Y-m-d h:i:s', $lastAccessed) . '. Time out: ' . date('Y-m-d h:i:s', $timeOut));
2202+
2203+ // If this is the first switch (i.e. the row was logged in before)
2204+ if ($loggedIn == 1) {
2205+
2206+ // Update the display and set it as logged out
2207+ $sthUpdate->execute(array('displayid' => $displayid));
2208+
2209+ // Log the down event
2210+ $statObject->displayDown($displayid, $lastAccessed);
2211+ }
2212+
2213+ // Store this row
2214+ $timedOutDisplays[] = $row;
2215+ }
2216+ }
2217+
2218+ return $timedOutDisplays;
2219+ }
2220+ catch (Exception $e) {
2221+
2222+ Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__);
2223+
2224+ if (!$this->IsError())
2225+ $this->SetError(1, __('Unknown Error'));
2226+
2227+ return false;
2228+ }
2229 }
2230
2231 /**
2232
2233=== modified file 'server/lib/data/displayprofile.data.class.php'
2234--- server/lib/data/displayprofile.data.class.php 2014-08-07 11:58:10 +0000
2235+++ server/lib/data/displayprofile.data.class.php 2014-10-21 16:06:16 +0000
2236@@ -39,6 +39,8 @@
2237
2238 public function Load() {
2239
2240+ Debug::Audit('Load ' . $this->displayProfileId);
2241+
2242 try {
2243 $dbh = PDOConnect::init();
2244
2245@@ -75,6 +77,59 @@
2246
2247 }
2248
2249+ public function LoadDefault() {
2250+
2251+ Debug::Audit('Load Default');
2252+
2253+ try {
2254+ $dbh = PDOConnect::init();
2255+
2256+ $sth = $dbh->prepare('SELECT * FROM `displayprofile` WHERE type = :type AND IsDefault = 1');
2257+ $sth->execute(array(
2258+ 'type' => $this->displayProfileId
2259+ ));
2260+
2261+ if (!$row = $sth->fetch()) {
2262+ // Return the client default
2263+ include_once('config/client.config.php');
2264+ $this->name = $CLIENT_CONFIG[$this->type]['synonym'];
2265+ $this->type = $this->type;
2266+ $this->config = $CLIENT_CONFIG[$this->type]['settings'];
2267+ $this->isDefault = 1;
2268+ $this->userId = 1;
2269+
2270+ // Just populate the values with the defaults if the values aren't set already
2271+ for ($i = 0; $i < count($this->config); $i++) {
2272+ $this->config[$i]['value'] = isset($this->config[$i]['value']) ? $this->config[$i]['value'] : $this->config[$i]['default'];
2273+ }
2274+ }
2275+ else {
2276+ $this->name = Kit::ValidateParam($row['name'], _STRING);
2277+ $this->type = Kit::ValidateParam($row['type'], _STRING);
2278+ $this->config = Kit::ValidateParam($row['config'], _HTMLSTRING);
2279+ $this->isDefault = Kit::ValidateParam($row['isdefault'], _INT);
2280+ $this->userId = Kit::ValidateParam($row['userid'], _INT);
2281+
2282+ // Load the client settings into an array
2283+ $this->config = ($this->config == '') ? array() : json_decode($this->config, true);
2284+
2285+ $this->isNew = false;
2286+ }
2287+
2288+ return true;
2289+ }
2290+ catch (Exception $e) {
2291+
2292+ Debug::LogEntry('error', $e->getMessage());
2293+
2294+ if (!$this->IsError())
2295+ $this->SetError(1, __('Unknown Error'));
2296+
2297+ return false;
2298+ }
2299+
2300+ }
2301+
2302 public function Save() {
2303
2304 // Validation.
2305
2306=== modified file 'server/lib/data/layout.data.class.php'
2307--- server/lib/data/layout.data.class.php 2014-09-16 16:41:43 +0000
2308+++ server/lib/data/layout.data.class.php 2014-10-21 16:06:16 +0000
2309@@ -19,19 +19,13 @@
2310 * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
2311 */
2312 defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
2313+Kit::ClassLoader('campaign');
2314
2315 class Layout extends Data
2316 {
2317 private $xml;
2318 private $DomXml;
2319
2320- public function __construct($db)
2321- {
2322- Kit::ClassLoader('campaign');
2323-
2324- parent::__construct($db);
2325- }
2326-
2327 /**
2328 * Add a layout
2329 * @param <type> $layout
2330@@ -543,10 +537,7 @@
2331 $campaign = new Campaign($this->db);
2332
2333 // Include to media data class?
2334- if ($copyMedia)
2335- {
2336- Kit::ClassLoader('media');
2337- Kit::ClassLoader('mediagroupsecurity');
2338+ if ($copyMedia) {
2339 $mediaObject = new Media($this->db);
2340 $mediaSecurity = new MediaGroupSecurity($this->db);
2341 }
2342@@ -554,11 +545,6 @@
2343 // We need the old campaignid
2344 $oldCampaignId = $campaign->GetCampaignId($oldLayoutId);
2345
2346- // Permissions model
2347- Kit::ClassLoader('campaignsecurity');
2348- Kit::ClassLoader('layoutregiongroupsecurity');
2349- Kit::ClassLoader('layoutmediagroupsecurity');
2350-
2351 // The Layout ID is the old layout
2352 $SQL = "";
2353 $SQL .= " INSERT INTO layout (layout, xml, userID, description, tags, templateID, retired, duration, backgroundImageId, createdDT, modifiedDT, status) ";
2354@@ -613,7 +599,7 @@
2355 if ($this->IsRegionSpecific($type))
2356 {
2357 // Generate a new media id
2358- $newMediaId = md5(uniqid());
2359+ $newMediaId = md5(Kit::uniqueId());
2360
2361 $mediaNode->setAttribute('id', $newMediaId);
2362
2363@@ -740,12 +726,14 @@
2364 if ($layoutId == 0)
2365 $this->ThrowError(__('No Layout selected'));
2366
2367+ // Security
2368 $sth = $dbh->prepare('DELETE FROM lklayoutmediagroup WHERE layoutid = :layoutid');
2369 $sth->execute(array('layoutid' => $layoutId));
2370
2371 $sth = $dbh->prepare('DELETE FROM lklayoutregiongroup WHERE layoutid = :layoutid');
2372 $sth->execute(array('layoutid' => $layoutId));
2373
2374+ // Media Links
2375 $sth = $dbh->prepare('DELETE FROM lklayoutmedia WHERE layoutid = :layoutid');
2376 $sth->execute(array('layoutid' => $layoutId));
2377
2378@@ -756,6 +744,10 @@
2379 // Remove the Campaign (will remove links to this layout - orphaning the layout)
2380 if (!$campaign->Delete($campaignId))
2381 $this->ThrowError(25008, __('Unable to delete campaign'));
2382+
2383+ // Remove the Layout from any display defaults
2384+ $sth = $dbh->prepare('UPDATE `display` SET defaultlayoutid = 4 WHERE defaultlayoutid = :layoutid');
2385+ $sth->execute(array('layoutid' => $layoutId));
2386
2387 // Remove the Layout (now it is orphaned it can be deleted safely)
2388 $sth = $dbh->prepare('DELETE FROM layout WHERE layoutid = :layoutid');
2389@@ -1236,7 +1228,7 @@
2390 $fileName = $libraryPath . 'temp/export_' . Kit::ValidateParam($row['layout'], _FILENAME) . '.zip';
2391
2392 $zip = new ZipArchive();
2393- $zip->open($fileName, ZIPARCHIVE::OVERWRITE);
2394+ $zip->open($fileName, ZIPARCHIVE::OVERWRITE);
2395 $zip->addFromString('layout.xml', $xml);
2396
2397 $params = array('layoutid' => $layoutId);
2398
2399=== modified file 'server/lib/data/maintenance.data.class.php'
2400--- server/lib/data/maintenance.data.class.php 2014-01-18 09:47:41 +0000
2401+++ server/lib/data/maintenance.data.class.php 2014-10-21 16:06:16 +0000
2402@@ -28,27 +28,78 @@
2403 */
2404 public function BackupDatabase($saveAs = "string")
2405 {
2406- // Always truncate the log first
2407- $this->db->query("TRUNCATE TABLE `log` ");
2408- $this->db->query("TRUNCATE TABLE `oauth_log` ");
2409-
2410+ // Check we can run mysql
2411+ if (!function_exists('exec'))
2412+ return $this->SetError(__('Exec is not available.'));
2413+
2414+ // Global database variables to seed into exec
2415 global $dbhost;
2416 global $dbuser;
2417 global $dbpass;
2418 global $dbname;
2419
2420- // Run mysqldump to a temporary file
2421-
2422 // get temporary file
2423- $tempFile = tempnam(Config::GetSetting('LIBRARY_LOCATION'), 'dmp');
2424-
2425- exec('mysqldump --opt --host=' . $dbhost . ' --user=' . $dbuser . ' --password=' . $dbpass . ' ' . $dbname . ' > ' . escapeshellarg($tempFile) . ' ');
2426-
2427- $sqlDump = file_get_contents($tempFile);
2428-
2429- unlink($tempFile);
2430-
2431- return $sqlDump;
2432+ $fileNameStructure = Config::GetSetting('LIBRARY_LOCATION') . 'structure.dump';
2433+ $fileNameData = Config::GetSetting('LIBRARY_LOCATION') . 'data.dump';
2434+ $zipFile = 'database.tar.gz';
2435+
2436+ // Run mysqldump structure to a temporary file
2437+ $command = 'mysqldump --opt --host=' . $dbhost . ' --user=' . $dbuser . ' --password=' . addslashes($dbpass) . ' ' . $dbname . ' --no-data > ' . escapeshellarg($fileNameStructure) . ' ';
2438+ exec($command);
2439+
2440+ // Run mysqldump data to a temporary file
2441+ $command = 'mysqldump --opt --host=' . $dbhost . ' --user=' . $dbuser . ' --password=' . addslashes($dbpass) . ' ' . $dbname . ' --ignore-table=' . $dbname . '.log --ignore-table=' . $dbname . '.oauth_log > ' . escapeshellarg($fileNameData) . ' ';
2442+ exec($command);
2443+
2444+ // Check it worked
2445+ if (!file_exists($fileNameStructure) || !file_exists($fileNameData))
2446+ return $this->SetError(__('Database dump failed.'));
2447+
2448+ // Zippy
2449+ Debug::Audit($zipFile);
2450+ $zip = new ZipArchive();
2451+ $zip->open($zipFile, ZIPARCHIVE::OVERWRITE);
2452+ $zip->addFile($fileNameStructure, 'structure.dump');
2453+ $zip->addFile($fileNameData, 'data.dump');
2454+ $zip->close();
2455+
2456+ // Remove the dump file
2457+ unlink($fileNameStructure);
2458+ unlink($fileNameData);
2459+
2460+ // Uncomment only if you are having permission issues
2461+ // chmod($zipFile, 0777);
2462+
2463+ // Push file back to browser
2464+ if (ini_get('zlib.output_compression')) {
2465+ ini_set('zlib.output_compression', 'Off');
2466+ }
2467+
2468+ $size = filesize($zipFile);
2469+
2470+ header('Content-Type: application/octet-stream');
2471+ header("Content-Transfer-Encoding: Binary");
2472+ header("Content-disposition: attachment; filename=\"" . basename($zipFile) . "\"");
2473+
2474+ //Output a header
2475+ header('Pragma: public');
2476+ header('Cache-Control: max-age=86400');
2477+ header('Expires: '. gmdate('D, d M Y H:i:s \G\M\T', time() + 86400));
2478+ header('Content-Length: ' . $size);
2479+
2480+ // Send via Apache X-Sendfile header?
2481+ if (Config::GetSetting('SENDFILE_MODE') == 'Apache') {
2482+ header("X-Sendfile: $zipFile");
2483+ exit();
2484+ }
2485+
2486+ // Return the file with PHP
2487+ // Disable any buffering to prevent OOM errors.
2488+ @ob_end_clean();
2489+ @ob_end_flush();
2490+ readfile($zipFile);
2491+
2492+ exit;
2493 }
2494
2495 /**
2496@@ -69,5 +120,95 @@
2497
2498 return true;
2499 }
2500+
2501+ public function TidyLibrary($tidyOldRevisions) {
2502+ // Also run a script to tidy up orphaned media in the library
2503+ $library = Config::GetSetting('LIBRARY_LOCATION');
2504+ $library = rtrim($library, '/') . '/';
2505+ $mediaObject = new Media();
2506+
2507+ Debug::Audit('Library Location: ' . $library);
2508+
2509+ // Dump the files in the temp folder
2510+ foreach (scandir($library . 'temp') as $item) {
2511+ if ($item == '.' || $item == '..')
2512+ continue;
2513+
2514+ Debug::Audit('Deleting temp file: ' . $item);
2515+
2516+ unlink($library . 'temp' . DIRECTORY_SEPARATOR . $item);
2517+ }
2518+
2519+ $media = array();
2520+ $unusedMedia = array();
2521+
2522+ // Run a query to get an array containing all of the media in the library
2523+ try {
2524+ $dbh = PDOConnect::init();
2525+
2526+ $sth = $dbh->prepare('
2527+ SELECT media.mediaid, media.storedAs, media.type, media.isedited, COUNT(lklayoutmedia.lklayoutmediaid) AS UsedInLayoutCount
2528+ FROM `media`
2529+ LEFT OUTER JOIN `lklayoutmedia`
2530+ ON lklayoutmedia.mediaid = media.mediaid
2531+ GROUP BY media.mediaid, media.storedAs ');
2532+
2533+ $sth->execute(array());
2534+
2535+ foreach ($sth->fetchAll() as $row) {
2536+ $media[$row['storedAs']] = $row;
2537+
2538+ // If its not used in a layout and its not a generic module, add to the unused array.
2539+ if ($tidyOldRevisions && $row['UsedInLayoutCount'] <= 0 && $row['isedited'] > 0 && $row['type'] != 'module' && $row['type'] != 'font')
2540+ $unusedMedia[$row['storedAs']] = $row;
2541+ }
2542+ }
2543+ catch (Exception $e) {
2544+
2545+ Debug::LogEntry('error', $e->getMessage());
2546+
2547+ if (!$this->IsError())
2548+ $this->SetError(1, __('Unknown Error'));
2549+
2550+ return false;
2551+ }
2552+
2553+ //Debug::Audit(var_export($media, true));
2554+ //Debug::Audit(var_export($unusedMedia, true));
2555+
2556+ // Get a list of all media files
2557+ foreach(scandir($library) as $file) {
2558+
2559+ if ($file == '.' || $file == '..')
2560+ continue;
2561+
2562+ if (is_dir($library . $file))
2563+ continue;
2564+
2565+ // Ignore thumbnails
2566+ if (strstr($file, 'tn_') || strstr($file, 'bg_'))
2567+ continue;
2568+
2569+ // Is this file in the system anywhere?
2570+ if (!array_key_exists($file, $media)) {
2571+ // Totally missing
2572+ Debug::Audit('Deleting file: ' . $file);
2573+
2574+ // If not, delete it
2575+ $mediaObject->DeleteMediaFile($file);
2576+ }
2577+ else if (array_key_exists($file, $unusedMedia)) {
2578+ // It exists but isn't being used any more
2579+ Debug::Audit('Deleting media: ' . $media[$file]['mediaid']);
2580+ $mediaObject->Delete($media[$file]['mediaid']);
2581+ }
2582+ else {
2583+ // Don't do anything, this file still exists
2584+ //Debug::Audit('Still exists: ' . $file);
2585+ }
2586+ }
2587+
2588+ return true;
2589+ }
2590 }
2591 ?>
2592
2593=== modified file 'server/lib/data/media.data.class.php'
2594--- server/lib/data/media.data.class.php 2014-07-24 16:23:27 +0000
2595+++ server/lib/data/media.data.class.php 2014-10-21 16:06:16 +0000
2596@@ -22,6 +22,8 @@
2597
2598 class Media extends Data
2599 {
2600+ private $_moduleFiles;
2601+
2602 private $moduleInfoLoaded;
2603 private $regionSpecific;
2604 private $validExtensions;
2605@@ -80,7 +82,7 @@
2606 $this->ThrowError(10, __('The name cannot be longer than 100 characters'));
2607
2608 // Test the duration (except for video and localvideo which can have a 0)
2609- if ($duration == 0 && $type != 'video' && $type != 'localvideo' && $type != 'genericfile')
2610+ if ($duration == 0 && $type != 'video' && $type != 'localvideo' && $type != 'genericfile' && $type != 'font')
2611 $this->ThrowError(11, __('You must enter a duration.'));
2612
2613 // Check the naming of this item to ensure it doesnt conflict
2614@@ -193,7 +195,7 @@
2615 if (strlen($name) > 100)
2616 $this->ThrowError(10, __('The name cannot be longer than 100 characters'));
2617
2618- if ($duration == 0 && $type != 'video' && $type != 'localvideo' && $type != 'genericfile')
2619+ if ($duration == 0 && $type != 'video' && $type != 'localvideo' && $type != 'genericfile' && $type != 'font')
2620 $this->ThrowError(11, __('You must enter a duration.'));
2621
2622 // Any media (not this one) already has this name?
2623@@ -330,8 +332,6 @@
2624 {
2625 Debug::LogEntry('audit', 'IN', 'Media', 'Delete');
2626
2627- Kit::ClassLoader('lkmediadisplaygroup');
2628-
2629 try {
2630 $dbh = PDOConnect::init();
2631
2632@@ -357,7 +357,6 @@
2633 $fileName = Kit::ValidateParam($row['StoredAs'], _STRING);
2634
2635 // Remove permission assignments
2636- Kit::ClassLoader('mediagroupsecurity');
2637 $security = new MediaGroupSecurity($this->db);
2638
2639 if (!$security->UnlinkAll($mediaId))
2640@@ -648,5 +647,102 @@
2641 return false;
2642 }
2643 }
2644+
2645+ public function AddModuleFile($file, $force = false) {
2646+ try {
2647+ $name = basename($file);
2648+
2649+ $moduleExists = $this->ModuleFileExists($name);
2650+
2651+ if (!$force && $moduleExists) {
2652+ return;
2653+ }
2654+
2655+ $dbh = PDOConnect::init();
2656+ $libraryFolder = Config::GetSetting('LIBRARY_LOCATION');
2657+
2658+ // Get the name
2659+ $storedAs = $libraryFolder . $name;
2660+
2661+ // Now copy the file
2662+ if (!@copy($file, $storedAs))
2663+ $this->ThrowError(15, 'Error storing file.');
2664+
2665+ // Calculate the MD5 and the file size
2666+ $md5 = md5_file($storedAs);
2667+ $fileSize = filesize($storedAs);
2668+
2669+ if ($moduleExists) {
2670+ $SQL = "UPDATE `media` SET md5 = :md5, filesize = :filesize WHERE storedAs = :storedas ";
2671+
2672+ $sth = $dbh->prepare($SQL);
2673+ $sth->execute(array(
2674+ 'storedas' => $name,
2675+ 'filesize' => $fileSize,
2676+ 'md5' => $md5
2677+ ));
2678+ }
2679+ else {
2680+ // All OK to insert this record
2681+ $SQL = "INSERT INTO media (name, type, duration, originalFilename, userID, retired, is_module, storedAs, FileSize, MD5) ";
2682+ $SQL .= "VALUES (:name, :type, :duration, :originalfilename, 1, :retired, 1, :storedas, :filesize, :md5) ";
2683+
2684+ $sth = $dbh->prepare($SQL);
2685+ $sth->execute(array(
2686+ 'name' => $name,
2687+ 'type' => 'module',
2688+ 'duration' => 10,
2689+ 'originalfilename' => $name,
2690+ 'retired' => 0,
2691+ 'storedas' => $name,
2692+ 'filesize' => $fileSize,
2693+ 'md5' => $md5
2694+ ));
2695+ }
2696+
2697+ $dbh->commit();
2698+
2699+ // Add to the cache
2700+ $this->_moduleFiles[] = $name;
2701+ }
2702+ catch (Exception $e) {
2703+
2704+ Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__);
2705+
2706+ if (!$this->IsError())
2707+ $this->SetError(1, __('Unknown Error'));
2708+
2709+ return false;
2710+ }
2711+ }
2712+
2713+ public function ModuleFileExists($file) {
2714+ try {
2715+ if ($this->_moduleFiles == NULL || count($this->_moduleFiles) < 1) {
2716+ $dbh = PDOConnect::init();
2717+
2718+ $sth = $dbh->prepare('SELECT storedAs FROM `media` WHERE type = :type');
2719+ $sth->execute(array(
2720+ 'type' => 'module'
2721+ ));
2722+
2723+ $this->_moduleFiles = array();
2724+
2725+ foreach ($sth->fetchAll() as $moduleFile)
2726+ $this->_moduleFiles[] = $moduleFile['storedAs'];
2727+ }
2728+
2729+ return (in_array($file, $this->_moduleFiles));
2730+ }
2731+ catch (Exception $e) {
2732+
2733+ Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__);
2734+
2735+ if (!$this->IsError())
2736+ $this->SetError(1, __('Unknown Error'));
2737+
2738+ return false;
2739+ }
2740+ }
2741 }
2742 ?>
2743
2744=== modified file 'server/lib/data/region.data.class.php'
2745--- server/lib/data/region.data.class.php 2014-08-11 19:57:05 +0000
2746+++ server/lib/data/region.data.class.php 2014-10-21 16:06:16 +0000
2747@@ -20,6 +20,9 @@
2748 */
2749 defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
2750
2751+require_once("lib/pages/module.class.php");
2752+Kit::ClassLoader('layout');
2753+
2754 class Region extends Data
2755 {
2756 // Caching
2757@@ -27,14 +30,6 @@
2758 private $layoutDocument;
2759
2760 public $delayFinalise = false;
2761-
2762- public function __construct(database $db)
2763- {
2764- $this->db =& $db;
2765-
2766- require_once("lib/pages/module.class.php");
2767- Kit::ClassLoader('layout');
2768- }
2769
2770 /**
2771 * Gets the Xml for the specified layout
2772@@ -44,7 +39,7 @@
2773 public function GetLayoutXml($layoutid)
2774 {
2775 if ($this->layoutXml == '') {
2776- $layout = new Layout($this->db);
2777+ $layout = new Layout();
2778 $this->layoutXml = $layout->GetLayoutXml($layoutid);
2779 }
2780
2781@@ -97,7 +92,7 @@
2782
2783 //Do we have a region ID provided?
2784 if ($regionid == '')
2785- $regionid = uniqid();
2786+ $regionid = Kit::uniqid();
2787
2788 // Validation
2789 if (!is_numeric($width) || !is_numeric($height) || !is_numeric($top) || !is_numeric($left))
2790
2791=== modified file 'server/lib/data/schedule.data.class.php'
2792--- server/lib/data/schedule.data.class.php 2014-09-05 16:07:36 +0000
2793+++ server/lib/data/schedule.data.class.php 2014-10-21 16:06:16 +0000
2794@@ -22,29 +22,29 @@
2795
2796 class Schedule extends Data
2797 {
2798- /**
2799- * Add
2800- * @return
2801- * @param $displayGroupIDs Object
2802- * @param $fromDT Object
2803- * @param $toDT Object
2804- * @param $layoutID Object
2805- * @param $recType Object
2806- * @param $recDetail Object
2807- * @param $recToDT Object
2808- * @param $isPriority Object
2809- * @param $userID Object
2810- * @param $displayOrder Object
2811- */
2812- public function Add($displayGroupIDs, $fromDT, $toDT, $campaignId, $recType, $recDetail, $recToDT, $isPriority, $userID, $displayOrder = 0)
2813- {
2814- Debug::LogEntry('audit', 'IN', 'Schedule', 'Add');
2815-
2816+ /**
2817+ * Add
2818+ * @return
2819+ * @param $displayGroupIDs Object
2820+ * @param $fromDT Object
2821+ * @param $toDT Object
2822+ * @param $layoutID Object
2823+ * @param $recType Object
2824+ * @param $recDetail Object
2825+ * @param $recToDT Object
2826+ * @param $isPriority Object
2827+ * @param $userID Object
2828+ * @param $displayOrder Object
2829+ */
2830+ public function Add($displayGroupIDs, $fromDT, $toDT, $campaignId, $recType, $recDetail, $recToDT, $isPriority, $userID, $displayOrder = 0)
2831+ {
2832+ Debug::LogEntry('audit', 'IN', 'Schedule', 'Add');
2833+
2834 try {
2835 $dbh = PDOConnect::init();
2836
2837 // Validation
2838- if (count($displayGroupIDs) == 0)
2839+ if (count($displayGroupIDs) == 0)
2840 return $this->SetError(25001, __('No display groups selected'));
2841
2842 if ($userID == 0)
2843@@ -54,121 +54,124 @@
2844 if ($recDetail == 0)
2845 $recDetail = 1;
2846
2847- // make the displayid_list from the selected displays.
2848- $displayGroupIDList = implode(",", $displayGroupIDs);
2849-
2850- // Parameters for the query
2851- $params = array(
2852- 'campaignid' => $campaignId,
2853- 'displaygroupids' => $displayGroupIDList,
2854- 'userid' => $userID,
2855- 'is_priority' => $isPriority,
2856- 'fromdt' => $fromDT,
2857- 'todt' => $toDT,
2858- 'displayorder' => $displayOrder
2859- );
2860-
2861- $SQL = "";
2862- $SQL .= "INSERT INTO `schedule` (CampaignId, DisplayGroupIDs, userID, is_priority, FromDT, ToDT, DisplayOrder ";
2863-
2864- // Columns for Recurrence
2865- if ($recType != '' && $recType != 'null') {
2866- $SQL .= ", recurrence_type, recurrence_detail, recurrence_range ";
2867- }
2868-
2869- $SQL .= ") ";
2870- $SQL .= " VALUES ( :campaignid, :displaygroupids, :userid, :is_priority, :fromdt, :todt, :displayorder ";
2871-
2872- // Values for Recurrence
2873- if ($recType != '' && $recType != 'null')
2874- {
2875- $SQL .= ", :recurrence_type, :recurrence_detail, :recurrence_range ";
2876- $params['recurrence_type'] = $recType;
2877- $params['recurrence_detail'] = $recDetail;
2878- $params['recurrence_range'] = $recToDT;
2879- }
2880-
2881- $SQL .= ")";
2882-
2883- $sth = $dbh->prepare($SQL);
2884+ // make the displayid_list from the selected displays.
2885+ $displayGroupIDList = implode(",", $displayGroupIDs);
2886+
2887+ // Parameters for the query
2888+ $params = array(
2889+ 'campaignid' => $campaignId,
2890+ 'displaygroupids' => $displayGroupIDList,
2891+ 'userid' => $userID,
2892+ 'is_priority' => $isPriority,
2893+ 'fromdt' => $fromDT,
2894+ 'todt' => $toDT,
2895+ 'displayorder' => $displayOrder
2896+ );
2897+
2898+ $SQL = "";
2899+ $SQL .= "INSERT INTO `schedule` (CampaignId, DisplayGroupIDs, userID, is_priority, FromDT, ToDT, DisplayOrder ";
2900+
2901+ // Columns for Recurrence
2902+ if ($recType != '' && $recType != 'null') {
2903+ $SQL .= ", recurrence_type, recurrence_detail, recurrence_range ";
2904+ }
2905+
2906+ $SQL .= ") ";
2907+ $SQL .= " VALUES ( :campaignid, :displaygroupids, :userid, :is_priority, :fromdt, :todt, :displayorder ";
2908+
2909+ // Values for Recurrence
2910+ if ($recType != '' && $recType != 'null')
2911+ {
2912+ // Check that we have an end date
2913+ if ($recToDT == '' || $recToDT == 0)
2914+ $this->ThrowError(__('Please provide an until date or set repeats to None'));
2915+
2916+ $SQL .= ", :recurrence_type, :recurrence_detail, :recurrence_range ";
2917+ $params['recurrence_type'] = $recType;
2918+ $params['recurrence_detail'] = $recDetail;
2919+ $params['recurrence_range'] = $recToDT;
2920+ }
2921+
2922+ $SQL .= ")";
2923+
2924+ $sth = $dbh->prepare($SQL);
2925 $sth->execute($params);
2926-
2927- // Get the event id
2928- $eventID = $dbh->lastInsertId();
2929-
2930- // Make sure we dont just have one...
2931- if (!is_array($displayGroupIDs))
2932- $displayGroupIDs = array($displayGroupIDs);
2933-
2934- // Create a detail record for each display group
2935- foreach ($displayGroupIDs as $displayGroupID)
2936- {
2937- // Add the parent detail record for this event
2938- if (!$this->AddDetail($displayGroupID, $fromDT, $toDT, $userID, $eventID))
2939- throw new Exception("Error Processing Request", 1);
2940-
2941- // Is there any recurrance to take care of?
2942- if ($recType != '' && $recType != 'null') {
2943- // Set the temp starts
2944- $t_start_temp = $fromDT;
2945- $t_end_temp = $toDT;
2946-
2947- Debug::LogEntry('audit', sprintf('Recurrence detected until %d. Recurrence period is %s and interval is %s.', $recToDT, $recDetail, $recType), 'Schedule', 'Add');
2948-
2949- //loop until we have added the recurring events for the schedule
2950- while ($t_start_temp < $recToDT)
2951- {
2952- // add the appropriate time to the start and end
2953- switch ($recType)
2954- {
2955- case 'Minute':
2956- $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp) + $recDetail, date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp), date("Y", $t_start_temp));
2957- $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp) + $recDetail, date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp), date("Y", $t_end_temp));
2958- break;
2959-
2960- case 'Hour':
2961- $t_start_temp = mktime(date("H", $t_start_temp) + $recDetail, date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp), date("Y", $t_start_temp));
2962- $t_end_temp = mktime(date("H", $t_end_temp) + $recDetail, date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp), date("Y", $t_end_temp));
2963- break;
2964-
2965- case 'Day':
2966- $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp)+$recDetail, date("Y", $t_start_temp));
2967- $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp)+$recDetail, date("Y", $t_end_temp));
2968- break;
2969-
2970- case 'Week':
2971- $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp) + ($recDetail * 7), date("Y", $t_start_temp));
2972- $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp) + ($recDetail * 7), date("Y", $t_end_temp));
2973- break;
2974-
2975- case 'Month':
2976- $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp)+$recDetail ,date("d", $t_start_temp), date("Y", $t_start_temp));
2977- $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp)+$recDetail ,date("d", $t_end_temp), date("Y", $t_end_temp));
2978- break;
2979-
2980- case 'Year':
2981- $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp), date("Y", $t_start_temp)+$recDetail);
2982- $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp), date("Y", $t_end_temp)+$recDetail);
2983- break;
2984- }
2985-
2986- // after we have added the appropriate amount, are we still valid
2987- if ($t_start_temp > $recToDT) break;
2988-
2989- if (!$this->AddDetail($displayGroupID, $t_start_temp, $t_end_temp, $userID, $eventID))
2990- throw new Exception("Error Processing Request", 1);
2991- }
2992- }
2993- }
2994+
2995+ // Get the event id
2996+ $eventID = $dbh->lastInsertId();
2997+
2998+ // Make sure we dont just have one...
2999+ if (!is_array($displayGroupIDs))
3000+ $displayGroupIDs = array($displayGroupIDs);
3001+
3002+ // Create a detail record for each display group
3003+ foreach ($displayGroupIDs as $displayGroupID)
3004+ {
3005+ // Add the parent detail record for this event
3006+ if (!$this->AddDetail($displayGroupID, $fromDT, $toDT, $userID, $eventID))
3007+ throw new Exception("Error Processing Request", 1);
3008+
3009+ // Is there any recurrance to take care of?
3010+ if ($recType != '' && $recType != 'null') {
3011+ // Set the temp starts
3012+ $t_start_temp = $fromDT;
3013+ $t_end_temp = $toDT;
3014+
3015+ Debug::LogEntry('audit', sprintf('Recurrence detected until %d. Recurrence period is %s and interval is %s.', $recToDT, $recDetail, $recType), 'Schedule', 'Add');
3016+
3017+ //loop until we have added the recurring events for the schedule
3018+ while ($t_start_temp < $recToDT)
3019+ {
3020+ // add the appropriate time to the start and end
3021+ switch ($recType)
3022+ {
3023+ case 'Minute':
3024+ $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp) + $recDetail, date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp), date("Y", $t_start_temp));
3025+ $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp) + $recDetail, date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp), date("Y", $t_end_temp));
3026+ break;
3027+
3028+ case 'Hour':
3029+ $t_start_temp = mktime(date("H", $t_start_temp) + $recDetail, date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp), date("Y", $t_start_temp));
3030+ $t_end_temp = mktime(date("H", $t_end_temp) + $recDetail, date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp), date("Y", $t_end_temp));
3031+ break;
3032+
3033+ case 'Day':
3034+ $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp)+$recDetail, date("Y", $t_start_temp));
3035+ $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp)+$recDetail, date("Y", $t_end_temp));
3036+ break;
3037+
3038+ case 'Week':
3039+ $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp) + ($recDetail * 7), date("Y", $t_start_temp));
3040+ $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp) + ($recDetail * 7), date("Y", $t_end_temp));
3041+ break;
3042+
3043+ case 'Month':
3044+ $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp)+$recDetail ,date("d", $t_start_temp), date("Y", $t_start_temp));
3045+ $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp)+$recDetail ,date("d", $t_end_temp), date("Y", $t_end_temp));
3046+ break;
3047+
3048+ case 'Year':
3049+ $t_start_temp = mktime(date("H", $t_start_temp), date("i", $t_start_temp), date("s", $t_start_temp) ,date("m", $t_start_temp) ,date("d", $t_start_temp), date("Y", $t_start_temp)+$recDetail);
3050+ $t_end_temp = mktime(date("H", $t_end_temp), date("i", $t_end_temp), date("s", $t_end_temp) ,date("m", $t_end_temp) ,date("d", $t_end_temp), date("Y", $t_end_temp)+$recDetail);
3051+ break;
3052+ }
3053+
3054+ // after we have added the appropriate amount, are we still valid
3055+ if ($t_start_temp > $recToDT) break;
3056+
3057+ if (!$this->AddDetail($displayGroupID, $t_start_temp, $t_end_temp, $userID, $eventID))
3058+ throw new Exception("Error Processing Request", 1);
3059+ }
3060+ }
3061+ }
3062
3063 // Notify (dont error)
3064- Kit::ClassLoader('Display');
3065 $displayObject = new Display($this->db);
3066 $displayObject->NotifyDisplays($campaignId);
3067-
3068- Debug::LogEntry('audit', 'OUT', 'Schedule', 'Add');
3069-
3070- return true;
3071+
3072+ Debug::LogEntry('audit', 'OUT', 'Schedule', 'Add');
3073+
3074+ return true;
3075 }
3076 catch (Exception $e) {
3077
3078@@ -179,8 +182,8 @@
3079
3080 return false;
3081 }
3082- }
3083-
3084+ }
3085+
3086 /**
3087 * Edits a Schedule
3088 * @param <type> $eventID
3089@@ -196,400 +199,459 @@
3090 * @param <int> $displayOrder
3091 * @return <type>
3092 */
3093- public function Edit($eventID, $displayGroupIDs, $fromDT, $toDT, $campaignId, $rec_type, $rec_detail, $recToDT, $isPriority, $userid, $displayOrder)
3094- {
3095- Debug::LogEntry('audit', 'IN', 'Schedule', 'Edit');
3096+ public function Edit($eventID, $displayGroupIDs, $fromDT, $toDT, $campaignId, $rec_type, $rec_detail, $recToDT, $isPriority, $userid, $displayOrder)
3097+ {
3098+ Debug::LogEntry('audit', 'IN', 'Schedule', 'Edit');
3099
3100 // Cant have a 0 increment as it creates a loop
3101 if ($rec_detail == 0)
3102 $rec_detail = 1;
3103-
3104- // What we are really going to do here is delete and re-add... just because it is easier to get the logic right
3105- // and it means the same logic will be applied across both functions.
3106-
3107- // Delete the old schedule
3108- if (!$this->Delete($eventID))
3109- return false;
3110-
3111- // Add the new one
3112- if (!$this->Add($displayGroupIDs, $fromDT, $toDT, $campaignId, $rec_type, $rec_detail, $recToDT, $isPriority, $userid, $displayOrder))
3113- return false;
3114-
3115- Debug::LogEntry('audit', 'OUT', 'Schedule', 'Edit');
3116-
3117- return true;
3118- }
3119-
3120- /**
3121- * Deletes a scheduled event
3122- * @return
3123- * @param $eventID Object
3124- */
3125- public function Delete($eventID)
3126- {
3127- Debug::LogEntry('audit', 'IN', 'Schedule', 'Delete');
3128-
3129- try {
3130- $dbh = PDOConnect::init();
3131-
3132- if (!$this->DeleteScheduleForEvent($eventID))
3133- throw new Exception("Error Processing Request", 1);
3134-
3135- // Delete all Schedule records for this DisplayGroupID
3136- $sth = $dbh->prepare('DELETE FROM schedule WHERE eventID = :eventid');
3137- $sth->execute(array(
3138- 'eventid' => $eventID
3139- ));
3140-
3141- Debug::LogEntry('audit', 'OUT', 'Schedule', 'Delete');
3142-
3143- return true;
3144- }
3145- catch (Exception $e) {
3146-
3147- Debug::LogEntry('error', $e->getMessage());
3148-
3149- if (!$this->IsError())
3150- $this->SetError(25016,__('Unable to delete schedule record for this Event.'));
3151-
3152- return false;
3153- }
3154- }
3155-
3156- /**
3157- * Adds a Schedule Detail record. This can optionally be linked to a Schedule Event record.
3158- * @return
3159- * @param $displayGroupID Object
3160- * @param $layoutID Object
3161- * @param $fromDT Object
3162- * @param $toDT Object
3163- * @param $userID Object
3164- * @param $isPriority Object
3165- * @param $eventID Object[optional]
3166- */
3167- public function AddDetail($displayGroupID, $fromDT, $toDT, $userID, $eventID)
3168- {
3169- Debug::LogEntry('audit', 'IN', 'Schedule', 'AddDetail');
3170-
3171- try {
3172- $dbh = PDOConnect::init();
3173-
3174- // The parameters for the INSERT
3175- $params = array(
3176- 'displaygroupid' => $displayGroupID,
3177- 'fromdt' => $fromDT,
3178- 'todt' => $toDT,
3179- 'userid' => $userID
3180- );
3181-
3182- // Insert statement
3183- $SQL = "INSERT INTO schedule_detail (DisplayGroupID, FromDT, ToDT, userID";
3184-
3185- // Extras for Event ID
3186- if ($eventID != '')
3187- {
3188- $SQL .= ", eventID";
3189- $params['eventid'] = $eventID;
3190- }
3191-
3192- $SQL .= ") ";
3193-
3194- // Values
3195- $SQL .= "VALUES (:displaygroupid, :fromdt, :todt, :userid";
3196-
3197- if ($eventID != '')
3198- $SQL .= ", :eventid";
3199-
3200- $SQL .= ")";
3201-
3202- // Execute the SQL
3203- $sth = $dbh->prepare($SQL);
3204- $sth->execute($params);
3205-
3206- Debug::LogEntry('audit', 'OUT', 'Schedule', 'AddDetail');
3207-
3208- return true;
3209- }
3210- catch (Exception $e) {
3211-
3212- Debug::LogEntry('error', $e->getMessage());
3213-
3214- if (!$this->IsError())
3215- $this->SetError(25002, __('Could not update Layout on Schedule'));
3216-
3217- return false;
3218- }
3219- }
3220-
3221- /**
3222- * Deletes all the Schedule records for a display group
3223- * @return
3224- * @param $displayGroupID Object
3225- */
3226- public function DeleteScheduleForDisplayGroup($displayGroupID)
3227- {
3228- Debug::LogEntry('audit', 'IN', 'DisplayGroup', 'DeleteScheduleForDisplayGroup');
3229-
3230- try {
3231- $dbh = PDOConnect::init();
3232-
3233- // Delete all Schedule records for this DisplayGroupID
3234- $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE DisplayGroupID = :displaygroupid');
3235- $sth->execute(array(
3236- 'displaygroupid' => $displayGroupID
3237- ));
3238-
3239- // Tidy up the schedule table. There might be orphaned records because of this delete
3240- $this->TidyScheduleTable();
3241-
3242- Debug::LogEntry('audit', 'OUT', 'DisplayGroup', 'DeleteScheduleForDisplayGroup');
3243-
3244- return true;
3245- }
3246- catch (Exception $e) {
3247-
3248- Debug::LogEntry('error', $e->getMessage());
3249-
3250- if (!$this->IsError())
3251- $this->SetError(25015,__('Unable to delete schedule records for this Display Group.'));
3252-
3253- return false;
3254- }
3255- }
3256-
3257- /**
3258- * Removes any orphaned records from the Schedule Table
3259- * Usually called as a result of an open-ended delete (such as deleting an entire display group)
3260- */
3261- private function TidyScheduleTable() {
3262- Debug::LogEntry('audit', 'IN', 'DisplayGroup', 'TidyScheduleTable');
3263-
3264- try {
3265- $dbh = PDOConnect::init();
3266-
3267- $sth = $dbh->prepare('DELETE FROM `schedule` WHERE EventID NOT IN (SELECT EventID FROM `schedule_detail`)');
3268- $sth->execute();
3269-
3270- return true;
3271- }
3272- catch (Exception $e) {
3273-
3274- Debug::LogEntry('error', $e->getMessage());
3275-
3276- if (!$this->IsError())
3277- $this->SetError(1, __('Unknown Error'));
3278-
3279- return false;
3280- }
3281- }
3282-
3283- /**
3284- * Deletes all the Schedule records for an EventID
3285- * @return
3286- * @param $displayGroupID Object
3287- */
3288- public function DeleteScheduleForEvent($eventID) {
3289- Debug::LogEntry('audit', 'IN', 'DisplayGroup', 'DeleteScheduleForEvent');
3290-
3291- try {
3292- $dbh = PDOConnect::init();
3293-
3294- // Delete all Schedule records for this DisplayGroupID
3295- $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE EventID = :eventid');
3296- $sth->execute(array(
3297- 'eventid' => $eventID
3298- ));
3299-
3300- Debug::LogEntry('audit', 'OUT', 'DisplayGroup', 'DeleteScheduleForEvent');
3301-
3302- return true;
3303- }
3304- catch (Exception $e) {
3305-
3306- Debug::LogEntry('error', $e->getMessage());
3307-
3308- if (!$this->IsError())
3309- $this->SetError(25016,__('Unable to delete schedule records for this Event.'));
3310-
3311- return false;
3312- }
3313- }
3314-
3315- /**
3316- * Deletes all the Schedule records for an EventID and DisplayGroupID
3317- * @return
3318- * @param $displayGroupID Object
3319- */
3320- public function DeleteScheduleForEventAndGroup($eventID, $displayGroupID) {
3321- Debug::LogEntry('audit', 'IN', 'DisplayGroup', 'DeleteScheduleForEventAndGroup');
3322-
3323- try {
3324- $dbh = PDOConnect::init();
3325-
3326- // Delete all Schedule records for this DisplayGroupID
3327- $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE EventID = :eventid AND DisplayGroupID = :displaygroupid');
3328- $sth->execute(array(
3329- 'displaygroupid' => $displayGroupID,
3330- 'eventid' => $eventID
3331- ));
3332-
3333- Debug::LogEntry('audit', 'OUT', 'DisplayGroup', 'DeleteScheduleForEventAndGroup');
3334-
3335- return true;
3336- }
3337- catch (Exception $e) {
3338-
3339- Debug::LogEntry('error', $e->getMessage());
3340-
3341- if (!$this->IsError())
3342- $this->SetError(25016,__('Unable to delete schedule records for this Event and DisplayGroup.'));
3343-
3344- return false;
3345- }
3346- }
3347-
3348- /**
3349- * Deletes the event detail record provided
3350- * @return
3351- * @param $eventDetailID Object
3352- */
3353- public function DeleteEventDetail($eventDetailID) {
3354- Debug::LogEntry('audit', 'IN', 'Schedule', 'DeleteEventDetail');
3355-
3356- try {
3357- $dbh = PDOConnect::init();
3358-
3359- // Delete all Schedule records for this EventDetail
3360- $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE schedule_detailID = :schedule_detailid');
3361- $sth->execute(array(
3362- 'schedule_detailid' => $eventDetailID
3363- ));
3364-
3365- Debug::LogEntry('audit', 'OUT', 'Schedule', 'DeleteEventDetail');
3366-
3367- return true;
3368- }
3369- catch (Exception $e) {
3370-
3371- Debug::LogEntry('error', $e->getMessage());
3372-
3373- if (!$this->IsError())
3374- $this->SetError(25016,__('Unable to delete schedule records for this Event.'));
3375-
3376- return false;
3377- }
3378- }
3379-
3380- public function DeleteDisplayGroupFromEvent($eventID, $displayGroupID)
3381- {
3382- Debug::LogEntry('audit', 'IN', 'Schedule', 'EditDisplayGroupsForEvent');
3383-
3384- try {
3385- $dbh = PDOConnect::init();
3386-
3387- // Read the display groups from the event
3388- $SQL = sprintf('', $eventID);
3389- $sth = $dbh->prepare('SELECT DisplayGroupIDs FROM schedule WHERE EventID = :eventid');
3390- $sth->execute(array(
3391- 'eventid' => $eventID
3392- ));
3393-
3394- if (!$row = $sth->fetch())
3395- $this->ThrowError(25034,__('Error retriving information necessary to delete this event'));
3396-
3397- // Get the Display Group IDs
3398- $displayGroupIDs = Kit::ValidateParam($row['DisplayGroupIDs'], _STRING);
3399-
3400- // Load into an array and remove the one in $displayGroupID
3401- $displayGroupIDs = explode(',', $displayGroupIDs);
3402- $key = array_search($displayGroupID, $displayGroupIDs);
3403-
3404- if ($key !== true) {
3405- unset($displayGroupIDs[$key]);
3406- }
3407- else {
3408- Debug::LogEntry('audit', 'Display Group ID is already removed from the Event - this is strange.', 'Schedule', 'EditDisplayGroupsForEvent');
3409- return true;
3410- }
3411-
3412- // Save the list back to the event
3413- $displayGroupIDList = implode(',', $displayGroupIDs);
3414-
3415- // Delete all Schedule records for this EventDetail
3416- $sth = $dbh->prepare('UPDATE schedule SET DisplayGroupIDs = :displaygroupids WHERE EventID = :eventid');
3417- $sth->execute(array(
3418- 'eventid' => $eventID,
3419- 'displaygroupids' => $displayGroupIDList
3420- ));
3421-
3422- Debug::LogEntry('audit', 'OUT', 'Schedule', 'EditDisplayGroupsForEvent');
3423-
3424- return true;
3425- }
3426- catch (Exception $e) {
3427-
3428- Debug::LogEntry('error', $e->getMessage());
3429-
3430- if (!$this->IsError())
3431- $this->SetError(25036,__('Unable to edit the display groups for this Event.'));
3432-
3433- return false;
3434- }
3435- }
3436-
3437- /**
3438- * Gets an array of display group ids for the given event
3439- * @param [int] $eventId The Event ID
3440- */
3441- public function DisplayGroupsForEvent($eventId) {
3442- $eventId = Kit::ValidateParam($eventId, _INT);
3443-
3444- try {
3445- $dbh = PDOConnect::init();
3446-
3447- $sth = $dbh->prepare('SELECT DISTINCT DisplayGroupID FROM `schedule_detail` WHERE EventID = :eventid');
3448- $sth->execute(array(
3449- 'eventid' => $eventId
3450- ));
3451-
3452- $ids = array();
3453-
3454- while ($row = $sth->fetch()) {
3455- $ids[] = Kit::ValidateParam($row['DisplayGroupID'], _INT);
3456- }
3457-
3458- return $ids;
3459- }
3460- catch (Exception $e) {
3461-
3462- Debug::LogEntry('error', $e->getMessage());
3463-
3464- if (!$this->IsError())
3465- $this->SetError(1, __('Unknown Error'));
3466-
3467- return false;
3468- }
3469- }
3470+
3471+ // What we are really going to do here is delete and re-add... just because it is easier to get the logic right
3472+ // and it means the same logic will be applied across both functions.
3473+
3474+ // Delete the old schedule
3475+ if (!$this->Delete($eventID))
3476+ return false;
3477+
3478+ // Add the new one
3479+ if (!$this->Add($displayGroupIDs, $fromDT, $toDT, $campaignId, $rec_type, $rec_detail, $recToDT, $isPriority, $userid, $displayOrder))
3480+ return false;
3481+
3482+ Debug::LogEntry('audit', 'OUT', 'Schedule', 'Edit');
3483+
3484+ return true;
3485+ }
3486+
3487+ /**
3488+ * Deletes a scheduled event
3489+ * @return
3490+ * @param $eventID Object
3491+ */
3492+ public function Delete($eventID)
3493+ {
3494+ Debug::LogEntry('audit', 'IN', 'Schedule', 'Delete');
3495+
3496+ try {
3497+ $dbh = PDOConnect::init();
3498+
3499+ if (!$this->DeleteScheduleForEvent($eventID))
3500+ throw new Exception("Error Processing Request", 1);
3501+
3502+ // Delete all Schedule records for this DisplayGroupID
3503+ $sth = $dbh->prepare('DELETE FROM schedule WHERE eventID = :eventid');
3504+ $sth->execute(array(
3505+ 'eventid' => $eventID
3506+ ));
3507+
3508+ Debug::LogEntry('audit', 'OUT', 'Schedule', 'Delete');
3509+
3510+ return true;
3511+ }
3512+ catch (Exception $e) {
3513+
3514+ Debug::LogEntry('error', $e->getMessage());
3515+
3516+ if (!$this->IsError())
3517+ $this->SetError(25016,__('Unable to delete schedule record for this Event.'));
3518+
3519+ return false;
3520+ }
3521+ }
3522+
3523+ /**
3524+ * Adds a Schedule Detail record. This can optionally be linked to a Schedule Event record.
3525+ * @return
3526+ * @param $displayGroupID Object
3527+ * @param $layoutID Object
3528+ * @param $fromDT Object
3529+ * @param $toDT Object
3530+ * @param $userID Object
3531+ * @param $isPriority Object
3532+ * @param $eventID Object[optional]
3533+ */
3534+ public function AddDetail($displayGroupID, $fromDT, $toDT, $userID, $eventID)
3535+ {
3536+ Debug::LogEntry('audit', 'IN', 'Schedule', 'AddDetail');
3537+
3538+ try {
3539+ $dbh = PDOConnect::init();
3540+
3541+ // The parameters for the INSERT
3542+ $params = array(
3543+ 'displaygroupid' => $displayGroupID,
3544+ 'fromdt' => $fromDT,
3545+ 'todt' => $toDT,
3546+ 'userid' => $userID
3547+ );
3548+
3549+ // Insert statement
3550+ $SQL = "INSERT INTO schedule_detail (DisplayGroupID, FromDT, ToDT, userID";
3551+
3552+ // Extras for Event ID
3553+ if ($eventID != '')
3554+ {
3555+ $SQL .= ", eventID";
3556+ $params['eventid'] = $eventID;
3557+ }
3558+
3559+ $SQL .= ") ";
3560+
3561+ // Values
3562+ $SQL .= "VALUES (:displaygroupid, :fromdt, :todt, :userid";
3563+
3564+ if ($eventID != '')
3565+ $SQL .= ", :eventid";
3566+
3567+ $SQL .= ")";
3568+
3569+ // Execute the SQL
3570+ $sth = $dbh->prepare($SQL);
3571+ $sth->execute($params);
3572+
3573+ Debug::LogEntry('audit', 'OUT', 'Schedule', 'AddDetail');
3574+
3575+ return true;
3576+ }
3577+ catch (Exception $e) {
3578+
3579+ Debug::LogEntry('error', $e->getMessage());
3580+
3581+ if (!$this->IsError())
3582+ $this->SetError(25002, __('Could not update Layout on Schedule'));
3583+
3584+ return false;
3585+ }
3586+ }
3587+
3588+ /**
3589+ * Deletes all the Schedule records for a display group
3590+ * @return
3591+ * @param $displayGroupID Object
3592+ */
3593+ public function DeleteScheduleForDisplayGroup($displayGroupID)
3594+ {
3595+ Debug::LogEntry('audit', 'IN', 'DisplayGroup', 'DeleteScheduleForDisplayGroup');
3596+
3597+ try {
3598+ $dbh = PDOConnect::init();
3599+
3600+ // Delete all Schedule records for this DisplayGroupID
3601+ $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE DisplayGroupID = :displaygroupid');
3602+ $sth->execute(array(
3603+ 'displaygroupid' => $displayGroupID
3604+ ));
3605+
3606+ // Tidy up the schedule table. There might be orphaned records because of this delete
3607+ $this->TidyScheduleTable();
3608+
3609+ Debug::LogEntry('audit', 'OUT', 'DisplayGroup', 'DeleteScheduleForDisplayGroup');
3610+
3611+ return true;
3612+ }
3613+ catch (Exception $e) {
3614+
3615+ Debug::LogEntry('error', $e->getMessage());
3616+
3617+ if (!$this->IsError())
3618+ $this->SetError(25015,__('Unable to delete schedule records for this Display Group.'));
3619+
3620+ return false;
3621+ }
3622+ }
3623+
3624+ /**
3625+ * Deletes all the Schedule records for a display group
3626+ * @return
3627+ * @param $displayGroupID Object
3628+ */
3629+ public static function DeleteScheduleForCampaign($campaignId)
3630+ {
3631+ try {
3632+ $dbh = PDOConnect::init();
3633+
3634+ // Delete all Schedule Detail records for this campaignId
3635+ $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE EventID IN (SELECT EventID FROM `schedule` WHERE CampaignID = :campaignId)');
3636+ $sth->execute(array(
3637+ 'campaignId' => $campaignId
3638+ ));
3639+
3640+ // Delete all Schedule records for this campaignId
3641+ $sth = $dbh->prepare('DELETE FROM schedule WHERE CampaignId = :campaignId');
3642+ $sth->execute(array(
3643+ 'campaignId' => $campaignId
3644+ ));
3645+
3646+ return true;
3647+ }
3648+ catch (Exception $e) {
3649+
3650+ Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__);
3651+
3652+ if (!$this->IsError())
3653+ $this->SetError(25015,__('Unable to delete schedule records for Campaign.'));
3654+
3655+ return false;
3656+ }
3657+ }
3658+
3659+ /**
3660+ * Removes any orphaned records from the Schedule Table
3661+ * Usually called as a result of an open-ended delete (such as deleting an entire display group)
3662+ */
3663+ private static function TidyScheduleTable()
3664+ {
3665+ try {
3666+ $dbh = PDOConnect::init();
3667+
3668+ $sth = $dbh->prepare('DELETE FROM `schedule` WHERE EventID NOT IN (SELECT EventID FROM `schedule_detail`)');
3669+ $sth->execute();
3670+
3671+ return true;
3672+ }
3673+ catch (Exception $e) {
3674+
3675+ Debug::LogEntry('error', $e->getMessage());
3676+
3677+ if (!$this->IsError())
3678+ $this->SetError(1, __('Unknown Error'));
3679+
3680+ return false;
3681+ }
3682+ }
3683+
3684+ /**
3685+ * Removes any orphaned records from the Schedule Table
3686+ * Usually called as a result of an open-ended delete (such as deleting an entire display group)
3687+ */
3688+ private static function TidyScheduleDetailTable()
3689+ {
3690+ try {
3691+ $dbh = PDOConnect::init();
3692+
3693+ $sth = $dbh->prepare('DELETE FROM `schedule_detail` WHERE EventID NOT IN (SELECT EventID FROM `schedule`)');
3694+ $sth->execute();
3695+
3696+ return true;
3697+ }
3698+ catch (Exception $e) {
3699+
3700+ Debug::LogEntry('error', $e->getMessage());
3701+
3702+ if (!$this->IsError())
3703+ $this->SetError(1, __('Unknown Error'));
3704+
3705+ return false;
3706+ }
3707+ }
3708+
3709+ /**
3710+ * Deletes all the Schedule records for an EventID
3711+ * @return
3712+ * @param $displayGroupID Object
3713+ */
3714+ public function DeleteScheduleForEvent($eventID) {
3715+ Debug::LogEntry('audit', 'IN', 'DisplayGroup', 'DeleteScheduleForEvent');
3716+
3717+ try {
3718+ $dbh = PDOConnect::init();
3719+
3720+ // Delete all Schedule records for this DisplayGroupID
3721+ $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE EventID = :eventid');
3722+ $sth->execute(array(
3723+ 'eventid' => $eventID
3724+ ));
3725+
3726+ Debug::LogEntry('audit', 'OUT', 'DisplayGroup', 'DeleteScheduleForEvent');
3727+
3728+ return true;
3729+ }
3730+ catch (Exception $e) {
3731+
3732+ Debug::LogEntry('error', $e->getMessage());
3733+
3734+ if (!$this->IsError())
3735+ $this->SetError(25016,__('Unable to delete schedule records for this Event.'));
3736+
3737+ return false;
3738+ }
3739+ }
3740+
3741+ /**
3742+ * Deletes all the Schedule records for an EventID and DisplayGroupID
3743+ * @return
3744+ * @param $displayGroupID Object
3745+ */
3746+ public function DeleteScheduleForEventAndGroup($eventID, $displayGroupID) {
3747+ Debug::LogEntry('audit', 'IN', 'DisplayGroup', 'DeleteScheduleForEventAndGroup');
3748+
3749+ try {
3750+ $dbh = PDOConnect::init();
3751+
3752+ // Delete all Schedule records for this DisplayGroupID
3753+ $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE EventID = :eventid AND DisplayGroupID = :displaygroupid');
3754+ $sth->execute(array(
3755+ 'displaygroupid' => $displayGroupID,
3756+ 'eventid' => $eventID
3757+ ));
3758+
3759+ Debug::LogEntry('audit', 'OUT', 'DisplayGroup', 'DeleteScheduleForEventAndGroup');
3760+
3761+ return true;
3762+ }
3763+ catch (Exception $e) {
3764+
3765+ Debug::LogEntry('error', $e->getMessage());
3766+
3767+ if (!$this->IsError())
3768+ $this->SetError(25016,__('Unable to delete schedule records for this Event and DisplayGroup.'));
3769+
3770+ return false;
3771+ }
3772+ }
3773+
3774+ /**
3775+ * Deletes the event detail record provided
3776+ * @return
3777+ * @param $eventDetailID Object
3778+ */
3779+ public function DeleteEventDetail($eventDetailID) {
3780+ Debug::LogEntry('audit', 'IN', 'Schedule', 'DeleteEventDetail');
3781+
3782+ try {
3783+ $dbh = PDOConnect::init();
3784+
3785+ // Delete all Schedule records for this EventDetail
3786+ $sth = $dbh->prepare('DELETE FROM schedule_detail WHERE schedule_detailID = :schedule_detailid');
3787+ $sth->execute(array(
3788+ 'schedule_detailid' => $eventDetailID
3789+ ));
3790+
3791+ Debug::LogEntry('audit', 'OUT', 'Schedule', 'DeleteEventDetail');
3792+
3793+ return true;
3794+ }
3795+ catch (Exception $e) {
3796+
3797+ Debug::LogEntry('error', $e->getMessage());
3798+
3799+ if (!$this->IsError())
3800+ $this->SetError(25016,__('Unable to delete schedule records for this Event.'));
3801+
3802+ return false;
3803+ }
3804+ }
3805+
3806+ public function DeleteDisplayGroupFromEvent($eventID, $displayGroupID)
3807+ {
3808+ Debug::LogEntry('audit', 'IN', 'Schedule', 'EditDisplayGroupsForEvent');
3809+
3810+ try {
3811+ $dbh = PDOConnect::init();
3812+
3813+ // Read the display groups from the event
3814+ $SQL = sprintf('', $eventID);
3815+ $sth = $dbh->prepare('SELECT DisplayGroupIDs FROM schedule WHERE EventID = :eventid');
3816+ $sth->execute(array(
3817+ 'eventid' => $eventID
3818+ ));
3819+
3820+ if (!$row = $sth->fetch())
3821+ $this->ThrowError(25034,__('Error retriving information necessary to delete this event'));
3822+
3823+ // Get the Display Group IDs
3824+ $displayGroupIDs = Kit::ValidateParam($row['DisplayGroupIDs'], _STRING);
3825+
3826+ // Load into an array and remove the one in $displayGroupID
3827+ $displayGroupIDs = explode(',', $displayGroupIDs);
3828+ $key = array_search($displayGroupID, $displayGroupIDs);
3829+
3830+ if ($key !== true) {
3831+ unset($displayGroupIDs[$key]);
3832+ }
3833+ else {
3834+ Debug::LogEntry('audit', 'Display Group ID is already removed from the Event - this is strange.', 'Schedule', 'EditDisplayGroupsForEvent');
3835+ return true;
3836+ }
3837+
3838+ // Save the list back to the event
3839+ $displayGroupIDList = implode(',', $displayGroupIDs);
3840+
3841+ // Delete all Schedule records for this EventDetail
3842+ $sth = $dbh->prepare('UPDATE schedule SET DisplayGroupIDs = :displaygroupids WHERE EventID = :eventid');
3843+ $sth->execute(array(
3844+ 'eventid' => $eventID,
3845+ 'displaygroupids' => $displayGroupIDList
3846+ ));
3847+
3848+ Debug::LogEntry('audit', 'OUT', 'Schedule', 'EditDisplayGroupsForEvent');
3849+
3850+ return true;
3851+ }
3852+ catch (Exception $e) {
3853+
3854+ Debug::LogEntry('error', $e->getMessage());
3855+
3856+ if (!$this->IsError())
3857+ $this->SetError(25036,__('Unable to edit the display groups for this Event.'));
3858+
3859+ return false;
3860+ }
3861+ }
3862+
3863+ /**
3864+ * Gets an array of display group ids for the given event
3865+ * @param [int] $eventId The Event ID
3866+ */
3867+ public function DisplayGroupsForEvent($eventId) {
3868+ $eventId = Kit::ValidateParam($eventId, _INT);
3869+
3870+ try {
3871+ $dbh = PDOConnect::init();
3872+
3873+ $sth = $dbh->prepare('SELECT DISTINCT DisplayGroupID FROM `schedule_detail` WHERE EventID = :eventid');
3874+ $sth->execute(array(
3875+ 'eventid' => $eventId
3876+ ));
3877+
3878+ $ids = array();
3879+
3880+ while ($row = $sth->fetch()) {
3881+ $ids[] = Kit::ValidateParam($row['DisplayGroupID'], _INT);
3882+ }
3883+
3884+ return $ids;
3885+ }
3886+ catch (Exception $e) {
3887+
3888+ Debug::LogEntry('error', $e->getMessage());
3889+
3890+ if (!$this->IsError())
3891+ $this->SetError(1, __('Unknown Error'));
3892+
3893+ return false;
3894+ }
3895+ }
3896 }
3897
3898 class Event
3899 {
3900- public $eventID;
3901- public $eventDetailID;
3902- public $fromDT;
3903- public $toDT;
3904- public $layout;
3905- public $layoutUri;
3906+ public $eventID;
3907+ public $eventDetailID;
3908+ public $fromDT;
3909+ public $toDT;
3910+ public $layout;
3911+ public $layoutUri;
3912 public $deleteUri;
3913- public $spanningDays;
3914- public $startDayNo;
3915- public $displayGroup;
3916- public $editPermission;
3917+ public $spanningDays;
3918+ public $startDayNo;
3919+ public $displayGroup;
3920+ public $editPermission;
3921 public $isdisplayspecific;
3922-
3923- public function __construct()
3924- {
3925-
3926- }
3927+
3928+ public function __construct()
3929+ {
3930+
3931+ }
3932 }
3933 ?>
3934\ No newline at end of file
3935
3936=== modified file 'server/lib/data/stat.data.class.php'
3937--- server/lib/data/stat.data.class.php 2014-01-18 09:47:41 +0000
3938+++ server/lib/data/stat.data.class.php 2014-10-21 16:06:16 +0000
3939@@ -22,68 +22,126 @@
3940
3941 class Stat extends data
3942 {
3943- public function Add($type, $fromDT, $toDT, $scheduleID, $displayID, $layoutID, $mediaID, $tag)
3944- {
3945- try {
3946- $dbh = PDOConnect::init();
3947-
3948- // Lower case the type for consistancy
3949- $type = strtolower($type);
3950-
3951- // Prepare a statement
3952- $sth = $dbh->prepare('INSERT INTO stat (Type, statDate, start, end, scheduleID, displayID, layoutID, mediaID, Tag) VALUES (:type, :statdate, :start, :end, :scheduleid, :displayid, :layoutid, :mediaid, :tag)');
3953-
3954- // Construct a parameters array to execute
3955- $params = array();
3956- $params['statdate'] = date("Y-m-d H:i:s");
3957- $params['type'] = $type;
3958- $params['start'] = $fromDT;
3959- $params['end'] = $toDT;
3960- $params['scheduleid'] = $scheduleID;
3961- $params['displayid'] = $displayID;
3962- $params['layoutid'] = $layoutID;
3963-
3964- // Optional parameters
3965- $params['mediaid'] = null;
3966- $params['tag'] = null;
3967-
3968- // We should run different SQL depending on what Type we are
3969- switch ($type)
3970- {
3971- case 'media':
3972- $params['mediaid'] = $mediaID;
3973-
3974- break;
3975-
3976- case 'layout':
3977- // Nothing additional to do
3978- break;
3979-
3980- case 'event':
3981-
3982- $params['layoutid'] = 0;
3983- $params['tag'] = $tag;
3984-
3985- break;
3986-
3987- default:
3988- // Nothing to do, just exit
3989- return true;
3990- }
3991-
3992- $sth->execute($params);
3993-
3994- return true;
3995- }
3996- catch (Exception $e) {
3997-
3998- Debug::LogEntry('error', $e->getMessage());
3999-
4000- if (!$this->IsError())
4001- $this->SetError(25000, 'Stat Insert Failed.');
4002-
4003- return false;
4004- }
4005- }
4006+ public function Add($type, $fromDT, $toDT, $scheduleID, $displayID, $layoutID, $mediaID, $tag)
4007+ {
4008+ try {
4009+ $dbh = PDOConnect::init();
4010+
4011+ // Lower case the type for consistency
4012+ $type = strtolower($type);
4013+
4014+ // Prepare a statement
4015+ $sth = $dbh->prepare('INSERT INTO stat (Type, statDate, start, end, scheduleID, displayID, layoutID, mediaID, Tag) VALUES (:type, :statdate, :start, :end, :scheduleid, :displayid, :layoutid, :mediaid, :tag)');
4016+
4017+ // Construct a parameters array to execute
4018+ $params = array();
4019+ $params['statdate'] = date("Y-m-d H:i:s");
4020+ $params['type'] = $type;
4021+ $params['start'] = $fromDT;
4022+ $params['end'] = $toDT;
4023+ $params['scheduleid'] = $scheduleID;
4024+ $params['displayid'] = $displayID;
4025+ $params['layoutid'] = $layoutID;
4026+
4027+ // Optional parameters
4028+ $params['mediaid'] = null;
4029+ $params['tag'] = null;
4030+
4031+ // We should run different SQL depending on what Type we are
4032+ switch ($type)
4033+ {
4034+ case 'media':
4035+ $params['mediaid'] = $mediaID;
4036+
4037+ break;
4038+
4039+ case 'layout':
4040+ // Nothing additional to do
4041+ break;
4042+
4043+ case 'event':
4044+
4045+ $params['layoutid'] = 0;
4046+ $params['tag'] = $tag;
4047+
4048+ break;
4049+
4050+ default:
4051+ // Nothing to do, just exit
4052+ return true;
4053+ }
4054+
4055+ $sth->execute($params);
4056+
4057+ return true;
4058+ }
4059+ catch (Exception $e) {
4060+
4061+ Debug::LogEntry('error', $e->getMessage());
4062+
4063+ if (!$this->IsError())
4064+ $this->SetError(25000, 'Stat Insert Failed.');
4065+
4066+ return false;
4067+ }
4068+ }
4069+
4070+ public function displayDown($displayId, $lastAccessed)
4071+ {
4072+ try {
4073+ $dbh = PDOConnect::init();
4074+
4075+ // Prepare a statement
4076+ $sth = $dbh->prepare('
4077+ INSERT INTO stat (Type, statDate, start, scheduleID, displayID)
4078+ VALUES (:type, :statdate, :start, :scheduleid, :displayid)');
4079+
4080+ // Construct a parameters array to execute
4081+ $params = array();
4082+ $params['type'] = 'displaydown';
4083+ $params['displayid'] = $displayId;
4084+ $params['statdate'] = date('Y-m-d H:i:s');
4085+ $params['start'] = $lastAccessed;
4086+ $params['scheduleid'] = 0;
4087+
4088+ $sth->execute($params);
4089+
4090+ return true;
4091+ }
4092+ catch (Exception $e) {
4093+
4094+ Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__);
4095+
4096+ if (!$this->IsError())
4097+ $this->SetError(1, __('Unknown Error'));
4098+
4099+ return false;
4100+ }
4101+ }
4102+
4103+ public function displayUp($displayId) {
4104+ try {
4105+ $dbh = PDOConnect::init();
4106+
4107+ Debug::Audit('Display Up: ' . $displayId);
4108+
4109+ $sth = $dbh->prepare('UPDATE stat SET end = :toDt WHERE displayId = :displayId AND end IS NULL');
4110+ $sth->execute(array(
4111+ 'toDt' => date('Y-m-d H:i:s'),
4112+ 'displayId' => $displayId
4113+ ));
4114+
4115+ return true;
4116+ }
4117+ catch (Exception $e) {
4118+
4119+ Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__);
4120+
4121+ if (!$this->IsError())
4122+ $this->SetError(1, __('Unknown Error'));
4123+
4124+ return false;
4125+ }
4126+ }
4127 }
4128 ?>
4129\ No newline at end of file
4130
4131=== modified file 'server/lib/data/usergroup.data.class.php'
4132--- server/lib/data/usergroup.data.class.php 2014-08-07 15:47:19 +0000
4133+++ server/lib/data/usergroup.data.class.php 2014-10-21 16:06:16 +0000
4134@@ -22,6 +22,58 @@
4135
4136 class UserGroup extends Data
4137 {
4138+ public function GetPermissionsForObject($object, $idCol, $objectId, $clause = '')
4139+ {
4140+ try {
4141+ $dbh = PDOConnect::init();
4142+
4143+ $params = array('id' => $objectId);
4144+ $SQL = 'SELECT joinedGroup.groupid, joinedGroup.group, view, edit, del, joinedGroup.isuserspecific ';
4145+ $SQL .= ' FROM (
4146+ SELECT `group`.*
4147+ FROM `group`
4148+ LEFT OUTER JOIN lkusergroup
4149+ ON lkusergroup.GroupID = group.GroupID
4150+ WHERE IsUserSpecific = 0
4151+ UNION ALL
4152+ SELECT `group`.*
4153+ FROM `group`
4154+ INNER JOIN lkusergroup
4155+ ON lkusergroup.GroupID = group.GroupID
4156+ AND IsUserSpecific = 1
4157+ INNER JOIN `user`
4158+ ON lkusergroup.UserID = user.UserID
4159+ AND retired = 0
4160+ ) joinedGroup ';
4161+ $SQL .= ' LEFT OUTER JOIN ' . $object;
4162+ $SQL .= ' ON ' . $object . '.GroupID = joinedGroup.GroupID ';
4163+
4164+ if ($clause != '') {
4165+ $SQL .= $clause;
4166+ }
4167+ else {
4168+ $SQL .= ' AND ' . $object . '.' . $idCol . ' = :id ';
4169+ $params = array('id' => $objectId);
4170+ }
4171+
4172+ $SQL .= 'ORDER BY joinedGroup.IsEveryone DESC, joinedGroup.IsUserSpecific, joinedGroup.`Group`; ';
4173+
4174+ $sth = $dbh->prepare($SQL);
4175+ $sth->execute($params);
4176+
4177+ return $sth->fetchAll();
4178+ }
4179+ catch (Exception $e) {
4180+
4181+ Debug::LogEntry('error', $e->getMessage());
4182+
4183+ if (!$this->IsError())
4184+ $this->SetError(1, __('Unknown Error'));
4185+
4186+ return false;
4187+ }
4188+ }
4189+
4190 /**
4191 * Adds a User Group to Xibo
4192 * @return
4193
4194=== modified file 'server/lib/include.php'
4195--- server/lib/include.php 2014-08-17 12:38:20 +0000
4196+++ server/lib/include.php 2014-10-21 16:06:16 +0000
4197@@ -20,7 +20,7 @@
4198 */
4199 defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
4200
4201-define('WEBSITE_VERSION', 80);
4202+define('WEBSITE_VERSION', 81);
4203
4204 // No errors reported until we read the settings from the DB
4205 error_reporting(0);
4206@@ -41,10 +41,11 @@
4207 require_once("lib/app/responsemanager.class.php");
4208 require_once("lib/app/datemanager.class.php");
4209 require_once("lib/app/app_functions.php");
4210+require_once("lib/data/data.class.php");
4211 require_once("lib/modules/module.interface.php");
4212 require_once("lib/modules/module.class.php");
4213-require_once("lib/data/data.class.php");
4214 require_once("lib/app/session.class.php");
4215+require_once("lib/app/cache.class.php");
4216 require_once("lib/app/thememanager.class.php");
4217 require_once("lib/pages/base.class.php");
4218
4219@@ -111,6 +112,11 @@
4220 // Error Handling (our error handler requires a DB connection
4221 set_error_handler(array(new Debug(), "ErrorHandler"));
4222
4223+// Define an auto-load function
4224+spl_autoload_register(function ($class) {
4225+ Kit::ClassLoader($class);
4226+});
4227+
4228 // Define the VERSION
4229 Config::Version();
4230
4231
4232=== modified file 'server/lib/modules/module.class.php'
4233--- server/lib/modules/module.class.php 2014-09-05 16:07:36 +0000
4234+++ server/lib/modules/module.class.php 2014-10-21 16:06:16 +0000
4235@@ -19,6 +19,7 @@
4236 * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
4237 */
4238 defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
4239+include_once('lib/data/media.data.class.php');
4240
4241 abstract class Module implements ModuleInterface
4242 {
4243@@ -37,6 +38,7 @@
4244 protected $previewEnabled;
4245 protected $validExtensions;
4246 protected $validExtensionsText;
4247+ protected $imageUri;
4248 protected $settings;
4249
4250 // The Schema Version of this code
4251@@ -51,6 +53,7 @@
4252 protected $deleteFromRegion;
4253 protected $width;
4254 protected $height;
4255+ protected $layoutSchemaVersion;
4256
4257 // Media information
4258 protected $mediaid;
4259@@ -145,6 +148,7 @@
4260 $this->validExtensionsText = Kit::ValidateParam($row['ValidExtensions'], _STRING);
4261 $this->previewEnabled = Kit::ValidateParam($row['PreviewEnabled'], _INT);
4262 $this->assignable = Kit::ValidateParam($row['assignable'], _INT);
4263+ $this->imageUri = Kit::ValidateParam($row['ImageUri'], _STRING);
4264 $this->render_as = Kit::ValidateParam($row['render_as'], _WORD);
4265 $this->settings = Kit::ValidateParam($row['settings'], _HTMLSTRING);
4266
4267@@ -155,7 +159,7 @@
4268 if ($this->settings == '')
4269 $this->settings = array();
4270 else
4271- $this->settings = json_decode($this->settings);
4272+ $this->settings = json_decode($this->settings, true);
4273
4274 // Translated name of this module
4275 $this->displayType = __(Kit::ValidateParam($row['Name'], _STRING));
4276@@ -200,6 +204,8 @@
4277
4278 $layoutDoc = new DOMDocument();
4279 $layoutDoc->loadXML($layoutXml);
4280+
4281+ $this->layoutSchemaVersion = (int)$layoutDoc->documentElement->getAttribute('schemaVersion');
4282
4283 $layoutXpath = new DOMXPath($layoutDoc);
4284
4285@@ -821,6 +827,7 @@
4286 case 'video':
4287 case 'localvideo':
4288 case 'genericfile':
4289+ case 'font':
4290 $defaultDuration = 0;
4291 break;
4292
4293@@ -837,7 +844,7 @@
4294 break;
4295
4296 default:
4297- $defaultDuration = '';
4298+ $defaultDuration = 10;
4299 }
4300
4301
4302@@ -979,6 +986,11 @@
4303 'r');
4304 }
4305
4306+ $formFields[] = FormManager::AddCheckbox('deleteOldVersion', __('Delete the old version.'),
4307+ ((Config::GetSetting('LIBRARY_MEDIA_UPDATEINALL_CHECKB') == 'Checked') ? 1 : 0),
4308+ __('Completely remove the old version of this media item if a new file is being uploaded.'),
4309+ '');
4310+
4311 // Add in any extra form fields we might have provided by the super-class
4312 if ($extraFormFields != NULL && is_array($extraFormFields)) {
4313 foreach($extraFormFields as $field) {
4314@@ -1085,7 +1097,6 @@
4315 }
4316
4317 // Hand off to the media module
4318- Kit::ClassLoader('media');
4319 $mediaObject = new Media($db);
4320
4321 // Stored As from the XML
4322@@ -1116,10 +1127,7 @@
4323 }
4324
4325 // Are we on a region
4326- if ($regionid != '')
4327- {
4328- Kit::ClassLoader('layoutmediagroupsecurity');
4329-
4330+ if ($regionid != '') {
4331 $security = new LayoutMediaGroupSecurity($db);
4332 $security->Copy($layoutid, $regionid, $mediaid, $new_mediaid);
4333 }
4334@@ -1176,6 +1184,12 @@
4335 if (Kit::GetParam('replaceInLayouts', _POST, _CHECKBOX) == 1)
4336 $this->ReplaceMediaInAllLayouts($mediaid, $this->mediaid, $this->duration);
4337
4338+ // Do we need to delete the old media item?
4339+ if ($tmpName != '' && Kit::GetParam('deleteOldVersion', _POST, _CHECKBOX) == 1) {
4340+ if (!$mediaObject->Delete($mediaid))
4341+ $this->response->message .= ' ' . __('Failed to remove old media');
4342+ }
4343+
4344 return $this->response;
4345 }
4346
4347@@ -1337,7 +1351,7 @@
4348
4349 // Default Hover window contains a thumbnail, media type and duration
4350 $output = '<div class="well">';
4351- $output .= '<div class="preview-module-image"><img alt="' . $this->displayType . ' thumbnail" src="theme/default/img/forms/' . $this->type . '.gif"></div>';
4352+ $output .= '<div class="preview-module-image"><img alt="' . $this->displayType . ' thumbnail" src="theme/default/img/' . $this->imageUri . '"></div>';
4353 $output .= '<div class="info">';
4354 $output .= ' <ul>';
4355 $output .= ' <li>' . $msgType . ': ' . $this->displayType . '</li>';
4356@@ -1371,52 +1385,37 @@
4357 if (!$this->auth->modifyPermissions)
4358 trigger_error(__('You do not have permissions to edit this media'), E_USER_ERROR);
4359
4360- // List of all Groups with a view/edit/delete checkbox
4361- $SQL = '';
4362- $SQL .= 'SELECT `group`.GroupID, `group`.`Group`, View, Edit, Del, `group`.IsUserSpecific ';
4363- $SQL .= ' FROM `group` ';
4364-
4365- if ($this->assignedMedia)
4366- {
4367- $SQL .= ' LEFT OUTER JOIN lklayoutmediagroup ';
4368- $SQL .= ' ON lklayoutmediagroup.GroupID = group.GroupID ';
4369- $SQL .= sprintf(" AND lklayoutmediagroup.MediaID = '%s' AND lklayoutmediagroup.RegionID = '%s' AND lklayoutmediagroup.LayoutID = %d ", $this->mediaid, $this->regionid, $this->layoutid);
4370- }
4371- else
4372- {
4373- $SQL .= ' LEFT OUTER JOIN lkmediagroup ';
4374- $SQL .= ' ON lkmediagroup.GroupID = group.GroupID ';
4375- $SQL .= sprintf(' AND lkmediagroup.MediaID = %d ', $this->mediaid);
4376- }
4377-
4378- $SQL .= ' WHERE `group`.GroupID <> %d ';
4379- $SQL .= 'ORDER BY `group`.IsEveryone DESC, `group`.IsUserSpecific, `group`.`Group` ';
4380-
4381- $SQL = sprintf($SQL, $user->getGroupFromId($user->userid, true));
4382-
4383- Debug::LogEntry('audit', $SQL, 'module', 'PermissionsForm');
4384-
4385- if (!$results = $db->query($SQL))
4386- {
4387- trigger_error($db->error());
4388- trigger_error(__('Unable to get permissions for this layout'), E_USER_ERROR);
4389- }
4390-
4391- while ($row = $db->get_assoc_row($results))
4392- {
4393- $groupId = $row['GroupID'];
4394- $rowClass = ($row['IsUserSpecific'] == 0) ? 'strong_text' : '';
4395+ // List of all Groups with a view / edit / delete check box
4396+ $permissions = new UserGroup();
4397+
4398+ if ($this->assignedMedia) {
4399+ if (!$result = $permissions->GetPermissionsForObject('lklayoutmediagroup', NULL, NULL, sprintf(" AND lklayoutmediagroup.MediaID = '%s' AND lklayoutmediagroup.RegionID = '%s' AND lklayoutmediagroup.LayoutID = %d ", $this->mediaid, $this->regionid, $this->layoutid)))
4400+ trigger_error($permissions->GetErrorMessage(), E_USER_ERROR);
4401+ }
4402+ else {
4403+ if (!$result = $permissions->GetPermissionsForObject('lkmediagroup', 'MediaID', $this->mediaid))
4404+ trigger_error($permissions->GetErrorMessage(), E_USER_ERROR);
4405+ }
4406+
4407+ if (count($result) <= 0)
4408+ trigger_error(__('Unable to get permissions'), E_USER_ERROR);
4409+
4410+ $checkboxes = array();
4411+
4412+ foreach ($result as $row) {
4413+ $groupId = $row['groupid'];
4414+ $rowClass = ($row['isuserspecific'] == 0) ? 'strong_text' : '';
4415
4416 $checkbox = array(
4417 'id' => $groupId,
4418- 'name' => Kit::ValidateParam($row['Group'], _STRING),
4419+ 'name' => Kit::ValidateParam($row['group'], _STRING),
4420 'class' => $rowClass,
4421 'value_view' => $groupId . '_view',
4422- 'value_view_checked' => (($row['View'] == 1) ? 'checked' : ''),
4423+ 'value_view_checked' => (($row['view'] == 1) ? 'checked' : ''),
4424 'value_edit' => $groupId . '_edit',
4425- 'value_edit_checked' => (($row['Edit'] == 1) ? 'checked' : ''),
4426+ 'value_edit_checked' => (($row['edit'] == 1) ? 'checked' : ''),
4427 'value_del' => $groupId . '_del',
4428- 'value_del_checked' => (($row['Del'] == 1) ? 'checked' : ''),
4429+ 'value_del_checked' => (($row['del'] == 1) ? 'checked' : ''),
4430 );
4431
4432 $checkboxes[] = $checkbox;
4433@@ -2118,6 +2117,13 @@
4434 return false;
4435 }
4436 }
4437+
4438+ public function GetSetting($setting, $default = NULL) {
4439+ if (isset($this->settings[$setting]))
4440+ return $this->settings[$setting];
4441+ else
4442+ return $default;
4443+ }
4444
4445 /**
4446 * Return file based media items to the browser for Download/Preview
4447
4448=== modified file 'server/lib/pages/admin.class.php'
4449--- server/lib/pages/admin.class.php 2014-09-16 16:41:43 +0000
4450+++ server/lib/pages/admin.class.php 2014-10-21 16:06:16 +0000
4451@@ -137,13 +137,13 @@
4452 'title' => __('Tidy Library'),
4453 'class' => 'XiboFormButton',
4454 'selected' => false,
4455- 'link' => 'index.php?p=admin&q=TidyLibrary',
4456+ 'link' => 'index.php?p=admin&q=TidyLibraryForm',
4457 'help' => __('Run through the library and remove and unnecessary files'),
4458 'onclick' => ''
4459 );
4460 }
4461
4462- return $menu;
4463+ return $menu;
4464 }
4465
4466 function Edit() {
4467@@ -153,8 +153,7 @@
4468 if (!Kit::CheckToken())
4469 trigger_error(__('Sorry the form has expired. Please refresh.'), E_USER_ERROR);
4470
4471- Kit::ClassLoader('setting');
4472- $data = new Setting($this->db);
4473+ $data = new Setting();
4474
4475 // Get all of the settings in an array
4476 $settings = Config::GetAll(NULL, array('userChange' => 1, 'userSee' => 1));
4477@@ -185,6 +184,7 @@
4478 }
4479
4480 $response->SetFormSubmitResponse(__('Settings Updated'), false);
4481+ $response->callBack = 'settingsUpdated';
4482 $response->Respond();
4483 }
4484
4485@@ -417,20 +417,10 @@
4486 public function BackupDatabase()
4487 {
4488 // We want to output a load of stuff to the browser as a text file.
4489- Kit::ClassLoader('maintenance');
4490 $maintenance = new Maintenance($this->db);
4491
4492- $dump = $maintenance->BackupDatabase();
4493-
4494- if ($dump == '')
4495- trigger_error(__('Unable to export database'), E_USER_ERROR);
4496-
4497- header('Content-Type: text/plaintext');
4498- header('Content-Disposition: attachment; filename="' . date('Y-m-d H:i:s') . '.bak"');
4499- header("Content-Transfer-Encoding: binary");
4500- header('Accept-Ranges: bytes');
4501- echo $dump;
4502- exit;
4503+ if (!$dump = $maintenance->BackupDatabase())
4504+ trigger_error($maintenance->GetErrorMessage(), E_USER_ERROR);
4505 }
4506
4507 /**
4508@@ -545,70 +535,46 @@
4509 return round($bytes, $precision) . ' ' . $units[$pow];
4510 }
4511
4512+ public function TidyLibraryForm()
4513+ {
4514+ $response = new ResponseManager();
4515+
4516+ Theme::Set('form_id', 'TidyLibraryForm');
4517+ Theme::Set('form_action', 'index.php?p=admin&q=TidyLibrary');
4518+
4519+ $formFields = array();
4520+
4521+ // Check box to also delete un-used media that has been revised.
4522+ $formFields[] = FormManager::AddCheckbox('tidyOldRevisions', __('Remove old revisions'), 0,
4523+ __('Cleaning up old revisions of media will result in any unused media revisions being permanently deleted.'), '');
4524+
4525+ $formFields[] = FormManager::AddMessage(__('Tidying the Library will delete any temporary files. Are you sure you want to proceed?'));
4526+
4527+ Theme::Set('form_fields', $formFields);
4528+
4529+ $response->SetFormRequestResponse(NULL, __('Tidy Library'), '350px', '275px');
4530+ $response->AddButton(__('Help'), 'XiboHelpRender("' . HelpManager::Link('Settings', 'TidyLibrary') . '")');
4531+ $response->AddButton(__('No'), 'XiboDialogClose()');
4532+ $response->AddButton(__('Yes'), '$("#TidyLibraryForm").submit()');
4533+ $response->Respond();
4534+ }
4535+
4536 /**
4537 * Tidies up the library
4538 */
4539 public function TidyLibrary()
4540 {
4541- $db =& $this->db;
4542 $response = new ResponseManager();
4543-
4544+ $tidyOldRevisions = (Kit::GetParam('tidyOldRevisions', _POST, _CHECKBOX) == 1);
4545 if (Config::GetSetting('SETTING_LIBRARY_TIDY_ENABLED') != 1)
4546 trigger_error(__('Sorry this function is disabled.'), E_USER_ERROR);
4547
4548- // Also run a script to tidy up orphaned media in the library
4549- $library = Config::GetSetting('LIBRARY_LOCATION');
4550- $library = rtrim($library, '/') . '/';
4551-
4552- Debug::LogEntry('audit', 'Library Location: ' . $library);
4553-
4554- // Dump the files in the temp folder
4555- foreach (scandir($library . 'temp') as $item)
4556- {
4557- if ($item == '.' || $item == '..')
4558- continue;
4559-
4560- Debug::LogEntry('audit', 'Deleting temp file: ' . $item);
4561-
4562- unlink($library . 'temp' . DIRECTORY_SEPARATOR . $item);
4563- }
4564-
4565- // Get a list of all media files
4566- foreach(scandir($library) as $file)
4567- {
4568- Debug::LogEntry('audit', 'Checking file: ' . $file);
4569-
4570- if ($file == '.' || $file == '..')
4571- continue;
4572-
4573- if (is_dir($library . $file))
4574- continue;
4575-
4576- $rowCount = $db->GetCountOfRows("SELECT * FROM media WHERE storedAs = '" . $file . "'");
4577-
4578- Debug::LogEntry('audit', 'Media count for file: ' . $file . ' is ' . $rowCount);
4579-
4580- // For each media file, check to see if the file still exists in the library
4581- if ($rowCount == 0)
4582- {
4583- Debug::LogEntry('audit', 'Deleting file: ' . $file);
4584-
4585- // If not, delete it
4586- unlink($library . $file);
4587-
4588- if (file_exists($library . 'tn_' . $file))
4589- {
4590- unlink($library . 'tn_' . $file);
4591- }
4592-
4593- if (file_exists($library . 'bg_' . $file))
4594- {
4595- unlink($library . 'bg_' . $file);
4596- }
4597- }
4598- }
4599-
4600- trigger_error(__('Library Tidy Complete'), E_USER_ERROR);
4601+ $maintenance = new Maintenance();
4602+ if (!$maintenance->TidyLibrary($tidyOldRevisions))
4603+ trigger_error($maintenance->GetErrorMessage(), E_USER_ERROR);
4604+
4605+ $response->SetFormSubmitResponse(__('Library Tidy Complete'));
4606+ $response->Respond();
4607 }
4608 }
4609 ?>
4610
4611=== modified file 'server/lib/pages/campaign.class.php'
4612--- server/lib/pages/campaign.class.php 2014-08-15 14:40:03 +0000
4613+++ server/lib/pages/campaign.class.php 2014-10-21 16:06:16 +0000
4614@@ -355,41 +355,30 @@
4615 Theme::Set('form_action', 'index.php?p=campaign&q=Permissions');
4616 Theme::Set('form_meta', '<input type="hidden" name="campaignId" value="' . $campaignId . '" />');
4617
4618- // List of all Groups with a view/edit/delete checkbox
4619- $SQL = '';
4620- $SQL .= 'SELECT `group`.GroupID, `group`.`Group`, View, Edit, Del, `group`.IsUserSpecific ';
4621- $SQL .= ' FROM `group` ';
4622- $SQL .= ' LEFT OUTER JOIN lkcampaigngroup ';
4623- $SQL .= ' ON lkcampaigngroup.GroupID = group.GroupID ';
4624- $SQL .= ' AND lkcampaigngroup.CampaignID = %d ';
4625- $SQL .= ' WHERE `group`.GroupID <> %d ';
4626- $SQL .= 'ORDER BY `group`.IsEveryone DESC, `group`.IsUserSpecific, `group`.`Group` ';
4627-
4628- $SQL = sprintf($SQL, $campaignId, $this->user->getGroupFromID($this->user->userid, true));
4629-
4630- if (!$results = $db->query($SQL))
4631- {
4632- trigger_error($db->error());
4633+ // List of all Groups with a view / edit / delete check box
4634+ $permissions = new CampaignSecurity();
4635+ if (!$result = $permissions->GetPermissions($campaignId))
4636+ trigger_error($permissions->GetErrorMessage(), E_USER_ERROR);
4637+
4638+ if (count($result) <= 0)
4639 trigger_error(__('Unable to get permissions for this Campaign'), E_USER_ERROR);
4640- }
4641
4642 $checkboxes = array();
4643
4644- while ($row = $db->get_assoc_row($results))
4645- {
4646- $groupId = $row['GroupID'];
4647- $rowClass = ($row['IsUserSpecific'] == 0) ? 'strong_text' : '';
4648+ foreach ($result as $row) {
4649+ $groupId = $row['groupid'];
4650+ $rowClass = ($row['isuserspecific'] == 0) ? 'strong_text' : '';
4651
4652 $checkbox = array(
4653 'id' => $groupId,
4654- 'name' => Kit::ValidateParam($row['Group'], _STRING),
4655+ 'name' => Kit::ValidateParam($row['group'], _STRING),
4656 'class' => $rowClass,
4657 'value_view' => $groupId . '_view',
4658- 'value_view_checked' => (($row['View'] == 1) ? 'checked' : ''),
4659+ 'value_view_checked' => (($row['view'] == 1) ? 'checked' : ''),
4660 'value_edit' => $groupId . '_edit',
4661- 'value_edit_checked' => (($row['Edit'] == 1) ? 'checked' : ''),
4662+ 'value_edit_checked' => (($row['edit'] == 1) ? 'checked' : ''),
4663 'value_del' => $groupId . '_del',
4664- 'value_del_checked' => (($row['Del'] == 1) ? 'checked' : ''),
4665+ 'value_del_checked' => (($row['del'] == 1) ? 'checked' : ''),
4666 );
4667
4668 $checkboxes[] = $checkbox;
4669@@ -593,7 +582,7 @@
4670 public function SetMembers()
4671 {
4672 // Check the token
4673- if (!Kit::CheckToken())
4674+ if (!Kit::CheckToken('assign_token'))
4675 trigger_error(__('Sorry the form has expired. Please refresh.'), E_USER_ERROR);
4676
4677 $db =& $this->db;
4678@@ -646,10 +635,10 @@
4679 $id = uniqid();
4680 Theme::Set('id', $id);
4681 Theme::Set('form_meta', '<input type="hidden" name="p" value="campaign"><input type="hidden" name="q" value="LayoutAssignView">');
4682- Theme::Set('pager', ResponseManager::Pager($id, 'form_grid_pager'));
4683+ Theme::Set('pager', ResponseManager::Pager($id, 'grid_pager'));
4684
4685 // Get the currently assigned layouts and put them in the "well"
4686- // // Layouts in group
4687+ // Layouts in group
4688 $SQL = "SELECT layout.Layoutid, ";
4689 $SQL .= " layout.layout, ";
4690 $SQL .= " CONCAT('LayoutID_', layout.LayoutID) AS list_id ";
4691@@ -669,11 +658,17 @@
4692
4693 Debug::LogEntry('audit', count($layoutsAssigned) . ' layouts assigned already');
4694
4695+ $formFields = array();
4696+ $formFields[] = FormManager::AddText('filter_name', __('Name'), NULL, NULL, 'l');
4697+ Theme::Set('form_fields', $formFields);
4698+
4699 // Set the layouts assigned
4700 Theme::Set('layouts_assigned', $layoutsAssigned);
4701+ Theme::Set('append', Theme::RenderReturn('campaign_form_layout_assign'));
4702
4703 // Call to render the template
4704- $output = Theme::RenderReturn('campaign_form_layout_assign');
4705+ Theme::Set('header_text', __('Choose Layouts'));
4706+ $output = Theme::RenderReturn('grid_render');
4707
4708 // Construct the Response
4709 $response->html = $output;
4710@@ -706,12 +701,24 @@
4711 // Get a list of media
4712 $layoutList = $user->LayoutList(NULL, array('layout' => $name));
4713
4714+ $cols = array(
4715+ array('name' => 'layout', 'title' => __('Name'))
4716+ );
4717+ Theme::Set('table_cols', $cols);
4718+
4719 $rows = array();
4720
4721 // Add some extra information
4722 foreach ($layoutList as $row) {
4723
4724 $row['list_id'] = 'LayoutID_' . $row['layoutid'];
4725+ $row['assign_icons'][] = array(
4726+ 'assign_icons_class' => 'layout_assign_list_select'
4727+ );
4728+ $row['dataAttributes'] = array(
4729+ array('name' => 'rowid', 'value' => $row['list_id']),
4730+ array('name' => 'litext', 'value' => $row['layout'])
4731+ );
4732
4733 $rows[] = $row;
4734 }
4735@@ -719,7 +726,7 @@
4736 Theme::Set('table_rows', $rows);
4737
4738 // Render the Theme
4739- $response->SetGridResponse(Theme::RenderReturn('campaign_form_layout_assign_list'));
4740+ $response->SetGridResponse(Theme::RenderReturn('table_render'));
4741 $response->callBack = 'LayoutAssignCallback';
4742 $response->pageSize = 5;
4743 $response->Respond();
4744
4745=== modified file 'server/lib/pages/content.class.php'
4746--- server/lib/pages/content.class.php 2014-09-15 16:57:34 +0000
4747+++ server/lib/pages/content.class.php 2014-10-21 16:06:16 +0000
4748@@ -164,7 +164,7 @@
4749 $cols[] = array('name' => 'thumbnail', 'title' => __('Thumbnail'));
4750
4751 $cols[] = array('name' => 'duration_text', 'title' => __('Duration'));
4752- $cols[] = array('name' => 'size_text', 'title' => __('Size'));
4753+ $cols[] = array('name' => 'size_text', 'title' => __('Size'), 'sorter' => 'filesize');
4754 $cols[] = array('name' => 'owner', 'title' => __('Owner'));
4755 $cols[] = array('name' => 'permissions', 'title' => __('Permissions'));
4756 $cols[] = array('name' => 'revised', 'title' => __('Revised?'), 'icons' => true);
4757@@ -188,8 +188,9 @@
4758 // Thumbnail URL
4759 $row['thumbnail'] = '';
4760
4761- if ($row['mediatype'] == 'image')
4762- $row['thumbnail'] = '<img src="index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=' . $row['mediaid'] . '&width=100&height=100&dynamic=true&thumb=true" alt="' . $row['media'] . '" />';
4763+ if ($row['mediatype'] == 'image') {
4764+ $row['thumbnail'] = '<a class="img-replace" data-toggle="lightbox" data-type="image" data-img-src="index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=' . $row['mediaid'] . '&width=100&height=100&dynamic=true&thumb=true" href="index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=' . $row['mediaid'] . '"><i class="fa fa-file-image-o"></i></a>';
4765+ }
4766
4767 $row['buttons'] = array();
4768
4769@@ -257,7 +258,7 @@
4770 $response = new ResponseManager();
4771
4772 // Get a list of the enabled modules and then create buttons for them
4773- if (!$enabledModules = new ModuleManager($db, $user, 0, '', -1))
4774+ if (!$enabledModules = new ModuleManager($user, 0, '', -1))
4775 trigger_error($enabledModules->message, E_USER_ERROR);
4776
4777 $buttons = array();
4778@@ -300,7 +301,7 @@
4779 $id = uniqid();
4780 Theme::Set('id', $id);
4781 Theme::Set('form_meta', '<input type="hidden" name="p" value="content"><input type="hidden" name="q" value="LibraryAssignView">');
4782- Theme::Set('pager', ResponseManager::Pager($id, 'form_grid_pager'));
4783+ Theme::Set('pager', ResponseManager::Pager($id, 'grid_pager'));
4784
4785 // Module types filter
4786 $modules = $this->user->ModuleAuth(0, '', 1);
4787
4788=== modified file 'server/lib/pages/display.class.php'
4789--- server/lib/pages/display.class.php 2014-09-16 10:59:55 +0000
4790+++ server/lib/pages/display.class.php 2014-10-21 16:06:16 +0000
4791@@ -27,14 +27,12 @@
4792 $this->db =& $db;
4793 $this->user =& $user;
4794
4795- Kit::ClassLoader('Display');
4796-
4797 $this->sub_page = Kit::GetParam('sp', _GET, _WORD, 'view');
4798 $this->ajax = Kit::GetParam('ajax', _REQUEST, _WORD, 'false');
4799 $displayid = Kit::GetParam('displayid', _REQUEST, _INT, 0);
4800
4801 // validate displays so we get a realistic view of the table
4802- $this->validateDisplays();
4803+ Display::ValidateDisplays();
4804 }
4805
4806 /**
4807@@ -56,12 +54,14 @@
4808 $filter_displaygroup = Session::Get('display', 'filter_displaygroup');
4809 $filter_display = Session::Get('display', 'filter_display');
4810 $filter_showThumbnail = Session::Get('display', 'filter_showThumbnail');
4811+ $filter_autoRefresh = Session::Get('display', 'filter_autoRefresh');
4812 }
4813 else {
4814 $filter_pinned = 0;
4815 $filter_displaygroup = NULL;
4816 $filter_display = NULL;
4817 $filter_showThumbnail = 0;
4818+ $filter_autoRefresh = 0;
4819 }
4820
4821 $formFields = array();
4822@@ -76,13 +76,26 @@
4823 $displayGroups,
4824 'displaygroupid',
4825 'displaygroup',
4826+ NULL,
4827+ 'd');
4828+
4829+ $formFields[] = FormManager::AddCombo(
4830+ 'filter_showThumbnail',
4831+ __('Thumbnails'),
4832+ $filter_showThumbnail,
4833+ array(
4834+ array('key' => 0, 'value' => __('None')),
4835+ array('key' => 1, 'value' => __('Always')),
4836+ array('key' => 2, 'value' => __('When Logged In')),
4837+ ),
4838+ 'key',
4839+ 'value',
4840 NULL,
4841- 'd');
4842-
4843- $formFields[] = FormManager::AddCheckbox('filter_showThumbnail', __('Show Thumbnails'),
4844- $filter_showThumbnail, NULL,
4845 't');
4846
4847+ $formFields[] = FormManager::AddNumber('filter_autoRefresh', __('Auto Refresh'), $filter_autoRefresh,
4848+ NULL, 'r');
4849+
4850 $formFields[] = FormManager::AddCheckbox('XiboFilterPinned', __('Keep Open'),
4851 $filter_pinned, NULL,
4852 'k');
4853@@ -141,7 +154,7 @@
4854 $displayObject->wakeOnLanTime = Kit::GetParam('wakeOnLanTime', _POST, _STRING);
4855 $displayObject->broadCastAddress = Kit::GetParam('broadCastAddress', _POST, _STRING);
4856 $displayObject->secureOn = Kit::GetParam('secureOn', _POST, _STRING);
4857- $displayObject->cidr = Kit::GetParam('cidr', _POST, _INT);
4858+ $displayObject->cidr = Kit::GetParam('cidr', _POST, _STRING);
4859 $displayObject->latitude = Kit::GetParam('latitude', _POST, _DOUBLE);
4860 $displayObject->longitude = Kit::GetParam('longitude', _POST, _DOUBLE);
4861 $displayObject->displayProfileId = Kit::GetParam('displayprofileid', _POST, _INT);
4862@@ -225,8 +238,8 @@
4863 __('Do you want to be notified by email if there is a problem with this display?'),
4864 'a');
4865
4866- $formFields[] = FormManager::AddNumber('alert_timeout', __('Alert Timeout'), $displayObject->alertTimeout,
4867- __('How long in minutes after the display last connected to the webservice should we send an alert. Set this value higher than the collection interval on the client. Set to 0 to use global default.'),
4868+ $formFields[] = FormManager::AddCheckbox('alert_timeout', __('Use the Global Timeout?'), $displayObject->alertTimeout,
4869+ __('Should this display be tested against the global time out or the client collection interval?'),
4870 'o');
4871
4872 Theme::Set('form_fields_maintenance', $formFields);
4873@@ -259,7 +272,7 @@
4874 __('The time this display should receive the WOL command, using the 24hr clock - e.g. 19:00. Maintenance must be enabled.'), 't');
4875
4876 $formFields[] = FormManager::AddText('cidr', __('Wake on LAN CIDR'), $displayObject->cidr,
4877- __('Enter a number within the range of 0 to 32 in the following field. Leave the following field empty, if no subnet mask should be used (CIDR = 0). If the remote host\'s broadcast address is unkown: Enter the host name or IP address of the remote host in Broad Cast Address and enter the CIDR subnet mask of the remote host in this field.'), 'c');
4878+ __('Enter a number within the range of 0 to 32 in the following field. Leave the following field empty, if no subnet mask should be used (CIDR = 0). If the remote host\'s broadcast address is unknown: Enter the host name or IP address of the remote host in Broad Cast Address and enter the CIDR subnet mask of the remote host in this field.'), 'c');
4879
4880 Theme::Set('form_fields_wol', $formFields);
4881
4882@@ -327,6 +340,7 @@
4883 $db =& $this->db;
4884 $user =& $this->user;
4885 $response = new ResponseManager();
4886+ $dateFormat = Config::GetSetting('DATE_FORMAT');
4887
4888 // Filter by Name
4889 $filter_display = Kit::GetParam('filter_display', _POST, _STRING);
4890@@ -337,9 +351,13 @@
4891 setSession('display', 'filter_displaygroup', $filter_displaygroupid);
4892
4893 // Thumbnail?
4894- $filter_showThumbnail = Kit::GetParam('filter_showThumbnail', _REQUEST, _CHECKBOX);
4895+ $filter_showThumbnail = Kit::GetParam('filter_showThumbnail', _REQUEST, _INT);
4896 setSession('display', 'filter_showThumbnail', $filter_showThumbnail);
4897
4898+ // filter_autoRefresh?
4899+ $filter_autoRefresh = Kit::GetParam('filter_autoRefresh', _REQUEST, _INT, 0);
4900+ setSession('display', 'filter_autoRefresh', $filter_autoRefresh);
4901+
4902 // Pinned option?
4903 setSession('display', 'DisplayFilter', Kit::GetParam('XiboFilterPinned', _REQUEST, _CHECKBOX, 'off'));
4904
4905@@ -358,22 +376,19 @@
4906 $cols = array(
4907 array('name' => 'displayid', 'title' => __('ID')),
4908 array('name' => 'licensed', 'title' => __('License'), 'icons' => true),
4909- array('name' => 'display', 'title' => __('Display')),
4910- array('name' => 'description', 'title' => __('Description')),
4911- array('name' => 'layout', 'title' => __('Default Layout')),
4912- array('name' => 'inc_schedule', 'title' => __('Interleave Default'), 'icons' => true),
4913- array('name' => 'email_alert', 'title' => __('Email Alert'), 'icons' => true),
4914+ array('name' => 'displayWithLink', 'title' => __('Display')),
4915+ array('name' => 'description', 'title' => __('Description'), 'hidden' => ($filter_showThumbnail == 1 || $filter_showThumbnail == 2)),
4916+ array('name' => 'layout', 'title' => __('Default Layout'), 'hidden' => ($filter_showThumbnail == 1 || $filter_showThumbnail == 2)),
4917+ array('name' => 'inc_schedule', 'title' => __('Interleave Default'), 'icons' => true, 'hidden' => ($filter_showThumbnail == 1 || $filter_showThumbnail == 2)),
4918+ array('name' => 'email_alert', 'title' => __('Email Alert'), 'icons' => true, 'hidden' => ($filter_showThumbnail == 1 || $filter_showThumbnail == 2)),
4919 array('name' => 'loggedin', 'title' => __('Logged In'), 'icons' => true),
4920 array('name' => 'lastaccessed', 'title' => __('Last Accessed')),
4921- array('name' => 'clientaddress', 'title' => __('IP Address')),
4922- array('name' => 'macaddress', 'title' => __('Mac Address'))
4923+ array('name' => 'clientaddress', 'title' => __('IP Address'), 'hidden' => ($filter_showThumbnail == 1)),
4924+ array('name' => 'macaddress', 'title' => __('Mac Address'), 'hidden' => ($filter_showThumbnail == 1)),
4925+ array('name' => 'screenShotRequested', 'title' => __('Screen shot?'), 'icons' => true, 'hidden' => ($filter_showThumbnail == 0)),
4926+ array('name' => 'thumbnail', 'title' => __('Thumbnail'), 'hidden' => ($filter_showThumbnail == 0))
4927 );
4928
4929- if ($filter_showThumbnail == 1) {
4930- $cols[] = array('name' => 'screenShotRequested', 'title' => __('Screen shot?'), 'icons' => true);
4931- $cols[] = array('name' => 'thumbnail', 'title' => __('Thumbnail'));
4932- }
4933-
4934 Theme::Set('table_cols', $cols);
4935 Theme::Set('rowClass', 'mediainventorystatus');
4936
4937@@ -387,11 +402,11 @@
4938 if ($linkTarget == '')
4939 $linkTarget = '_top';
4940
4941- $row['display'] = sprintf('<a href="' . $vncTemplate . '" title="VNC to ' . $row['display'] . '" target="' . $linkTarget . '">' . Theme::Prepare($row['display']) . '</a>', $row['clientaddress']);
4942+ $row['displayWithLink'] = sprintf('<a href="' . $vncTemplate . '" title="VNC to ' . $row['display'] . '" target="' . $linkTarget . '">' . Theme::Prepare($row['display']) . '</a>', $row['clientaddress']);
4943 }
4944
4945 // Format last accessed
4946- $row['lastaccessed'] = date("Y-m-d H:i:s", $row['lastaccessed']);
4947+ $row['lastaccessed'] = date($dateFormat, $row['lastaccessed']);
4948
4949 // Create some login lights
4950 $row['mediainventorystatus'] = ($row['mediainventorystatus'] == 1) ? 'success' : (($row['mediainventorystatus'] == 2) ? 'danger' : 'warning');
4951@@ -399,7 +414,10 @@
4952 // Thumbnail
4953 $row['thumbnail'] = '';
4954 if ($filter_showThumbnail == 1 && file_exists(Config::GetSetting('LIBRARY_LOCATION') . 'screenshots/' . $row['displayid'] . '_screenshot.jpg')) {
4955- $row['thumbnail'] = '<img class="display-screenshot" src="index.php?p=display&q=ScreenShot&DisplayId=' . $row['displayid'] . '" />';
4956+ $row['thumbnail'] = '<a data-toggle="lightbox" data-type="image" href="index.php?p=display&q=ScreenShot&DisplayId=' . $row['displayid'] . '"><img class="display-screenshot" src="index.php?p=display&q=ScreenShot&DisplayId=' . $row['displayid'] . '" /></a>';
4957+ }
4958+ else if ($filter_showThumbnail == 2) {
4959+ $row['thumbnail'] = '<i class="fa fa-times-circle"></i>';
4960 }
4961
4962 // Edit and Delete buttons first
4963@@ -454,7 +472,13 @@
4964 $row['buttons'][] = array(
4965 'id' => 'display_button_requestScreenShot',
4966 'url' => 'index.php?p=display&q=RequestScreenShotForm&displayId=' . $row['displayid'],
4967- 'text' => __('Request Screen Shot')
4968+ 'text' => __('Request Screen Shot'),
4969+ 'multi-select' => true,
4970+ 'dataAttributes' => array(
4971+ array('name' => 'multiselectlink', 'value' => 'index.php?p=display&q=RequestScreenShot'),
4972+ array('name' => 'rowtitle', 'value' => $row['display']),
4973+ array('name' => 'displayId', 'value' => $row['displayid'])
4974+ )
4975 );
4976
4977 $row['buttons'][] = array('linkType' => 'divider');
4978@@ -523,55 +547,11 @@
4979 $output = Theme::RenderReturn('table_render');
4980
4981 $response->SetGridResponse($output);
4982+ $response->refresh = Kit::GetParam('filter_autoRefresh', _REQUEST, _INT, 0);
4983 $response->Respond();
4984 }
4985
4986 /**
4987- * Assess each Display to correctly set the logged in flag based on last accessed time
4988- * @return
4989- */
4990- function validateDisplays()
4991- {
4992- $db =& $this->db;
4993-
4994- // Get the global timeout (overrides the alert timeout on the display if 0
4995- $globalTimeout = Config::GetSetting('MAINTENANCE_ALERT_TOUT');
4996-
4997- // Get a list of all displays and there last accessed / alert timeout value
4998- $SQL = "";
4999- $SQL .= "SELECT displayid, lastaccessed, alert_timeout FROM display ";
5000-
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches