Merge lp:~dangarner/xibo/server170 into lp:xibo/1.7
- server170
- Merge into tuttle
Proposed by
Dan Garner
Status: | Merged | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 355 | ||||||||||||||||||||||||||||||||||||||||
Proposed branch: | lp:~dangarner/xibo/server170 | ||||||||||||||||||||||||||||||||||||||||
Merge into: | lp:xibo/1.7 | ||||||||||||||||||||||||||||||||||||||||
Diff against target: |
6714 lines (+3283/-1421) 69 files modified
manual/generate.php (+4/-164) manual/manualgenerator.class.php (+211/-0) manual/source/en/install_environment.md (+7/-139) manual/source/en/install_environment_linux.md (+93/-0) manual/source/en/install_environment_windows_iis.md (+195/-0) manual/source/en/install_environment_windows_xampp.md (+47/-0) manual/source/en/release_notes.md (+1/-0) manual/source/en/release_notes_1.7.0-rc1.md (+53/-0) manual/source/fr/tour.md (+65/-0) manual/template/template.php (+21/-1) server/config/client.config.php (+24/-2) server/install/database/60.sql (+13/-0) server/install/database/80.sql (+1/-1) server/install/database/81.sql (+1/-1) server/install/database/83.sql (+5/-0) server/install/master/data.sql (+3/-3) server/install/master/structure.sql (+7/-7) server/lib/app/kit.class.php (+58/-0) server/lib/app/thememanager.class.php (+2/-2) server/lib/data/dataset.data.class.php (+27/-10) server/lib/data/datasetdata.data.class.php (+2/-2) server/lib/data/displayprofile.data.class.php (+2/-2) server/lib/data/layout.data.class.php (+8/-2) server/lib/data/media.data.class.php (+1/-6) server/lib/data/nonce.data.class.php (+11/-0) server/lib/data/userdata.data.class.php (+85/-0) server/lib/include.php (+1/-1) server/lib/modules/module.class.php (+47/-12) server/lib/pages/admin.class.php (+4/-7) server/lib/pages/content.class.php (+53/-48) server/lib/pages/dataset.class.php (+11/-1) server/lib/pages/display.class.php (+25/-16) server/lib/pages/layout.class.php (+8/-3) server/lib/pages/log.class.php (+2/-0) server/lib/pages/module.class.php (+40/-30) server/lib/pages/stats.class.php (+27/-3) server/lib/pages/timeline.class.php (+9/-2) server/lib/pages/user.class.php (+22/-35) server/lib/service/service_v3.wsdl (+0/-9) server/lib/service/xmdssoap3.class.php (+566/-599) server/lib/service/xmdssoap4.class.php (+39/-31) server/modules/3rdparty/twitter-oauth/OAuth.php (+872/-0) server/modules/3rdparty/twitter-oauth/twitteroauth.php (+243/-0) server/modules/clock.module.php (+0/-19) server/modules/datasetview.module.php (+0/-8) server/modules/embedded.module.php (+0/-14) server/modules/forecastio.module.php (+43/-37) server/modules/image.module.php (+1/-1) server/modules/module_template.php (+2/-8) server/modules/module_user_general.php (+41/-0) server/modules/text.module.php (+0/-14) server/modules/theme/forecastio/current-day.template.json (+7/-0) server/modules/theme/forecastio/daily.template.json (+7/-0) server/modules/theme/forecastio/picture.template.json (+7/-0) server/modules/theme/ticker/media-rss-with-title.template.json (+6/-0) server/modules/theme/ticker/prominent-title-with-desc-and-name-separator.template.json (+6/-0) server/modules/theme/ticker/title-only.template.json (+6/-0) server/modules/theme/twitter/tweet-only.template.json (+6/-0) server/modules/theme/twitter/tweet-with-profileimage-left.template.json (+6/-0) server/modules/theme/twitter/tweet-with-profileimage-right.template.json (+6/-0) server/modules/ticker.module.php (+55/-41) server/modules/twitter.module.php (+152/-53) server/modules/webpage.module.php (+0/-13) server/theme/default/config.php (+0/-1) server/theme/default/html/display_form_mediainventory.php (+0/-52) server/theme/default/html/library_form_media_add.php (+11/-4) server/theme/default/html/schedule_page.php (+1/-1) server/theme/default/js/xibo-forms.js (+0/-12) server/theme/default/libraries/jquery-file-upload/js/jquery.fileupload-ui.js (+4/-4) |
||||||||||||||||||||||||||||||||||||||||
To merge this branch: | bzr merge lp:~dangarner/xibo/server170 | ||||||||||||||||||||||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Xibo Maintainters | Pending | ||
Review via email: mp+245939@code.launchpad.net |
Commit message
Description of the change
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 'manual/generate.php' |
2 | --- manual/generate.php 2014-11-06 17:57:03 +0000 |
3 | +++ manual/generate.php 2015-01-09 11:27:10 +0000 |
4 | @@ -1,170 +1,10 @@ |
5 | <?php |
6 | include_once('libraries/parsedown/parsedown.php'); |
7 | +include_once('manualgenerator.class.php'); |
8 | include_once('template/template.php'); |
9 | |
10 | -$OUTPUT_ROOT = 'output/'; |
11 | - |
12 | // Generates a complete manual. |
13 | - |
14 | -// Copy the bootstrap, jquery folders and the img folder |
15 | -if (!is_dir($OUTPUT_ROOT . 'libraries')) |
16 | - mkdir($OUTPUT_ROOT . 'libraries'); |
17 | - |
18 | -xcopy('libraries/bootstrap', $OUTPUT_ROOT . 'libraries/bootstrap'); |
19 | -xcopy('libraries/jquery', $OUTPUT_ROOT . 'libraries/jquery'); |
20 | -xcopy('template/img', $OUTPUT_ROOT . 'img'); |
21 | -xcopy('template/manual.css', $OUTPUT_ROOT . 'manual.css'); |
22 | - |
23 | -$languages = array(); |
24 | - |
25 | -// Get a list of folders |
26 | -foreach (array_diff(scandir('source'), array('..', '.')) as $langDir) { |
27 | - |
28 | - if (is_dir('source/' . $langDir)) { |
29 | - echo 'Found ' . $langDir . PHP_EOL; |
30 | - |
31 | - // Make sure our output folder is empty |
32 | - if (is_dir($OUTPUT_ROOT . $langDir)) { |
33 | - delete($OUTPUT_ROOT . $langDir); |
34 | - sleep(3); |
35 | - } |
36 | - |
37 | - mkdir($OUTPUT_ROOT . $langDir); |
38 | - |
39 | - // Make sure a full suite of images is present. |
40 | - xcopy('source/en/img', $OUTPUT_ROOT . $langDir . '/img'); |
41 | - |
42 | - // And layer in any language specific replacements |
43 | - if (is_dir('source/' . $langDir . '/img')) |
44 | - xcopy('source/' . $langDir . '/img', $OUTPUT_ROOT . $langDir . '/img'); |
45 | - |
46 | - if ($langDir != 'en') |
47 | - $languages[] = $langDir; |
48 | - } |
49 | -} |
50 | - |
51 | -// Build a langs string |
52 | -$langsString = '<a href="../en/index.html">en</a>'; |
53 | -foreach ($languages as $lang) { |
54 | - $langsString .= ' | <a href="../' . $lang . '/index.html">' . $lang . '</a>'; |
55 | -} |
56 | - |
57 | -// Scan files in the EN folder: |
58 | -foreach (array_diff(scandir('source/en'), array('..', '.')) as $file) { |
59 | - if (stripos($file, '.md')) { |
60 | - // Process each file in turn |
61 | - processFile($langsString, $OUTPUT_ROOT, 'en', str_replace('.md', '', $file)); |
62 | - |
63 | - // Process for the other languages. |
64 | - foreach ($languages as $lang) { |
65 | - processFile($langsString, $OUTPUT_ROOT, $lang, str_replace('.md', '', $file)); |
66 | - } |
67 | - } |
68 | -} |
69 | - |
70 | -echo PHP_EOL; |
71 | - |
72 | -function processFile($langs, $folder, $lang, $file) { |
73 | - |
74 | - echo '.'; |
75 | - flush(); |
76 | - |
77 | - // Get the page content |
78 | - $pageContent = Parsedown::instance()->text(processReplacements($lang, file_get_contents_or_default($lang, $file . '.md'))); |
79 | - $toc = strtok($pageContent, "\n"); |
80 | - $toc = str_replace('-->', '', str_replace('<!--toc=', '', $toc)); |
81 | - |
82 | - // Header |
83 | - $string = processReplacements($lang, file_get_contents('template/header.html')); |
84 | - $string .= processReplacements($lang, file_get_contents('template/footer.html')); |
85 | - |
86 | - $string = str_replace('[[TOCNAME]]', $toc, $string); |
87 | - $string = str_replace('[[PAGE]]', $pageContent, $string); |
88 | - $string = str_replace('[[NAVBAR]]', file_get_contents_or_default($lang, '/toc/nav_bar.html'), $string); |
89 | - |
90 | - // Handle the TOC |
91 | - $string = str_replace('[[TOC]]', Parsedown::instance()->text(file_get_contents_or_default($lang, '/toc/' . $toc . '.md')), $string); |
92 | - |
93 | - // Replace the languages |
94 | - $string = str_replace('[[LANGS]]', $langs, $string); |
95 | - |
96 | - file_put_contents($folder . $lang . DIRECTORY_SEPARATOR . $file . '.html', $string); |
97 | -} |
98 | - |
99 | -function file_get_contents_or_default($lang, $file) { |
100 | - if (file_exists('source' . DIRECTORY_SEPARATOR . $lang . DIRECTORY_SEPARATOR . $file)) |
101 | - return file_get_contents('source' . DIRECTORY_SEPARATOR . $lang . DIRECTORY_SEPARATOR . $file); |
102 | - else |
103 | - return file_get_contents('source' . DIRECTORY_SEPARATOR . 'en' . DIRECTORY_SEPARATOR . $file); |
104 | -} |
105 | - |
106 | -function processReplacements($lang, $string) { |
107 | - // Replace the nav bar |
108 | - $string = str_replace('[[PRODUCTNAME]]', PRODUCT_NAME, $string); |
109 | - $string = str_replace('[[PRODUCTVERSION]]', PRODUCT_VERSION, $string); |
110 | - $string = str_replace('[[PRODUCTHOME]]', PRODUCT_HOME, $string); |
111 | - $string = str_replace('[[PRODUCTSUPPORTURL]]', PRODUCT_SUPPORT_URL, $string); |
112 | - $string = str_replace('[[PRODUCTFAQURL]]', PRODUCT_FAQ_URL, $string); |
113 | - |
114 | - return $string; |
115 | -} |
116 | - |
117 | -/** |
118 | - * Copy a file, or recursively copy a folder and its contents |
119 | - * @param string $source Source path |
120 | - * @param string $dest Destination path |
121 | - * @param string $permissions New folder creation permissions |
122 | - * @return bool Returns true on success, false on failure |
123 | - */ |
124 | -function xcopy($source, $dest, $permissions = 0755) |
125 | -{ |
126 | - // Check for symlinks |
127 | - if (is_link($source)) { |
128 | - return symlink(readlink($source), $dest); |
129 | - } |
130 | - |
131 | - // Simple copy for a file |
132 | - if (is_file($source)) { |
133 | - return copy($source, $dest); |
134 | - } |
135 | - |
136 | - // Make destination directory |
137 | - if (!is_dir($dest)) { |
138 | - mkdir($dest, $permissions); |
139 | - } |
140 | - |
141 | - // Loop through the folder |
142 | - $dir = dir($source); |
143 | - while (false !== $entry = $dir->read()) { |
144 | - // Skip pointers |
145 | - if ($entry == '.' || $entry == '..') { |
146 | - continue; |
147 | - } |
148 | - |
149 | - // Deep copy directories |
150 | - xcopy("$source/$entry", "$dest/$entry"); |
151 | - } |
152 | - |
153 | - // Clean up |
154 | - $dir->close(); |
155 | - return true; |
156 | -} |
157 | - |
158 | -function delete($path) |
159 | -{ |
160 | - if (is_dir($path) === true) { |
161 | - $files = array_diff(scandir($path), array('.', '..')); |
162 | - |
163 | - foreach ($files as $file) { |
164 | - delete(realpath($path) . '/' . $file); |
165 | - } |
166 | - |
167 | - return rmdir($path); |
168 | - } |
169 | - else if (is_file($path) === true) { |
170 | - return unlink($path); |
171 | - } |
172 | - |
173 | - return false; |
174 | -} |
175 | +$manual = new ManualGenerator(PRODUCT_NAME, PRODUCT_VERSION, PRODUCT_HOME, PRODUCT_SUPPORT_URL, PRODUCT_FAQ_URL); |
176 | +$manual->build('', 'output/'); |
177 | + |
178 | ?> |
179 | |
180 | === added file 'manual/manualgenerator.class.php' |
181 | --- manual/manualgenerator.class.php 1970-01-01 00:00:00 +0000 |
182 | +++ manual/manualgenerator.class.php 2015-01-09 11:27:10 +0000 |
183 | @@ -0,0 +1,211 @@ |
184 | +<?php |
185 | +/* |
186 | + * Xibo - Digital Signage - http://www.xibo.org.uk |
187 | + * Copyright (C) 2006-2014 Spring Signage Ltd |
188 | + * |
189 | + * This file is part of Xibo. |
190 | + * |
191 | + * Xibo is free software: you can redistribute it and/or modify |
192 | + * it under the terms of the GNU Affero General Public License as published by |
193 | + * the Free Software Foundation, either version 3 of the License, or |
194 | + * any later version. |
195 | + * |
196 | + * Xibo is distributed in the hope that it will be useful, |
197 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
198 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
199 | + * GNU Affero General Public License for more details. |
200 | + * |
201 | + * You should have received a copy of the GNU Affero General Public License |
202 | + * along with Xibo. If not, see <http://www.gnu.org/licenses/>. |
203 | + */ |
204 | +class ManualGenerator |
205 | +{ |
206 | + private $productName; |
207 | + private $productVersion; |
208 | + private $productHome; |
209 | + private $productSupportUrl; |
210 | + private $productFaqUrl; |
211 | + |
212 | + private $sourcePath; |
213 | + private $outputPath; |
214 | + |
215 | + public function __construct($productName, $productVersion, $productHome, $productSupportUrl, $productFaqUrl) |
216 | + { |
217 | + $this->productName = $productName; |
218 | + $this->productVersion = $productVersion; |
219 | + $this->productHome = $productHome; |
220 | + $this->productSupportUrl = $productSupportUrl; |
221 | + $this->productFaqUrl = $productFaqUrl; |
222 | + } |
223 | + |
224 | + public function build($sourcePath, $outputPath) |
225 | + { |
226 | + $this->outputPath = $outputPath; |
227 | + $this->sourcePath = $sourcePath; |
228 | + |
229 | + // Copy the bootstrap, jquery folders and the img folder |
230 | + if (!is_dir($this->outputPath . 'libraries')) |
231 | + mkdir($this->outputPath . 'libraries'); |
232 | + |
233 | + $this->xcopy($this->sourcePath . 'libraries/bootstrap', $this->outputPath . 'libraries/bootstrap'); |
234 | + $this->xcopy($this->sourcePath . 'libraries/jquery', $this->outputPath . 'libraries/jquery'); |
235 | + $this->xcopy($this->sourcePath . 'template/img', $this->outputPath . 'img'); |
236 | + $this->xcopy($this->sourcePath . 'template/manual.css', $this->outputPath . 'manual.css'); |
237 | + |
238 | + $languages = array(); |
239 | + |
240 | + // Get a list of folders |
241 | + foreach (array_diff(scandir($this->sourcePath . 'source'), array('..', '.')) as $langDir) { |
242 | + |
243 | + if (is_dir($this->sourcePath . 'source/' . $langDir)) { |
244 | + echo 'Found ' . $langDir . PHP_EOL; |
245 | + |
246 | + // Make sure our output folder is empty |
247 | + if (is_dir($this->outputPath . $langDir)) { |
248 | + $this->delete($this->outputPath . $langDir); |
249 | + sleep(3); |
250 | + } |
251 | + |
252 | + mkdir($this->outputPath . $langDir); |
253 | + |
254 | + // Make sure a full suite of images is present. |
255 | + $this->xcopy($this->sourcePath . 'source/en/img', $this->outputPath . $langDir . '/img'); |
256 | + |
257 | + // And layer in any language specific replacements |
258 | + if (is_dir($this->sourcePath . 'source/' . $langDir . '/img')) |
259 | + $this->xcopy($this->sourcePath . 'source/' . $langDir . '/img', $this->outputPath . $langDir . '/img'); |
260 | + |
261 | + if ($langDir != 'en') |
262 | + $languages[] = $langDir; |
263 | + } |
264 | + } |
265 | + |
266 | + // Build a langs string |
267 | + $langsString = '<a href="../en/index.html">en</a>'; |
268 | + foreach ($languages as $lang) { |
269 | + $langsString .= ' | <a href="../' . $lang . '/index.html">' . $lang . '</a>'; |
270 | + } |
271 | + |
272 | + // Scan files in the EN folder: |
273 | + foreach (array_diff(scandir($this->sourcePath . 'source/en'), array('..', '.')) as $file) { |
274 | + if (stripos($file, '.md')) { |
275 | + // Process each file in turn |
276 | + $this->processFile($langsString, $this->outputPath, 'en', str_replace('.md', '', $file)); |
277 | + |
278 | + // Process for the other languages. |
279 | + foreach ($languages as $lang) { |
280 | + $this->processFile($langsString, $this->outputPath, $lang, str_replace('.md', '', $file)); |
281 | + } |
282 | + } |
283 | + } |
284 | + |
285 | + echo PHP_EOL; |
286 | + } |
287 | + |
288 | + private function processFile($langs, $folder, $lang, $file) |
289 | + { |
290 | + echo '.'; |
291 | + flush(); |
292 | + |
293 | + // Get the page content |
294 | + $pageContent = Parsedown::instance()->text($this->processReplacements($lang, $this->file_get_contents_or_default($lang, $file . '.md'))); |
295 | + $toc = strtok($pageContent, "\n"); |
296 | + $toc = str_replace('-->', '', str_replace('<!--toc=', '', $toc)); |
297 | + |
298 | + // Header |
299 | + $string = $this->processReplacements($lang, file_get_contents($this->sourcePath . 'template/header.html')); |
300 | + $string .= $this->processReplacements($lang, file_get_contents($this->sourcePath . 'template/footer.html')); |
301 | + |
302 | + $string = str_replace('[[TOCNAME]]', $toc, $string); |
303 | + $string = str_replace('[[PAGE]]', $pageContent, $string); |
304 | + $string = str_replace('[[NAVBAR]]', $this->file_get_contents_or_default($lang, '/toc/nav_bar.html'), $string); |
305 | + |
306 | + // Handle the TOC |
307 | + $string = str_replace('[[TOC]]', Parsedown::instance()->text($this->file_get_contents_or_default($lang, '/toc/' . $toc . '.md')), $string); |
308 | + |
309 | + // Replace the languages |
310 | + $string = str_replace('[[LANGS]]', $langs, $string); |
311 | + |
312 | + file_put_contents($folder . $lang . DIRECTORY_SEPARATOR . $file . '.html', $string); |
313 | + } |
314 | + |
315 | + private function file_get_contents_or_default($lang, $file) |
316 | + { |
317 | + if (file_exists($this->sourcePath . 'source' . DIRECTORY_SEPARATOR . $lang . DIRECTORY_SEPARATOR . $file)) |
318 | + return file_get_contents($this->sourcePath . 'source' . DIRECTORY_SEPARATOR . $lang . DIRECTORY_SEPARATOR . $file); |
319 | + else |
320 | + return file_get_contents($this->sourcePath . 'source' . DIRECTORY_SEPARATOR . 'en' . DIRECTORY_SEPARATOR . $file); |
321 | + } |
322 | + |
323 | + private function processReplacements($lang, $string) |
324 | + { |
325 | + // Replace the nav bar |
326 | + $string = str_replace('[[PRODUCTNAME]]', $this->productName, $string); |
327 | + $string = str_replace('[[PRODUCTVERSION]]', $this->productVersion, $string); |
328 | + $string = str_replace('[[PRODUCTHOME]]', $this->productHome, $string); |
329 | + $string = str_replace('[[PRODUCTSUPPORTURL]]', $this->productSupportUrl, $string); |
330 | + $string = str_replace('[[PRODUCTFAQURL]]', $this->productFaqUrl, $string); |
331 | + |
332 | + return $string; |
333 | + } |
334 | + |
335 | + /** |
336 | + * Copy a file, or recursively copy a folder and its contents |
337 | + * @param string $source Source path |
338 | + * @param string $dest Destination path |
339 | + * @param string $permissions New folder creation permissions |
340 | + * @return bool Returns true on success, false on failure |
341 | + */ |
342 | + function xcopy($source, $dest, $permissions = 0755) |
343 | + { |
344 | + // Check for symlinks |
345 | + if (is_link($source)) { |
346 | + return symlink(readlink($source), $dest); |
347 | + } |
348 | + |
349 | + // Simple copy for a file |
350 | + if (is_file($source)) { |
351 | + return copy($source, $dest); |
352 | + } |
353 | + |
354 | + // Make destination directory |
355 | + if (!is_dir($dest)) { |
356 | + mkdir($dest, $permissions); |
357 | + } |
358 | + |
359 | + // Loop through the folder |
360 | + $dir = dir($source); |
361 | + while (false !== $entry = $dir->read()) { |
362 | + // Skip pointers |
363 | + if ($entry == '.' || $entry == '..') { |
364 | + continue; |
365 | + } |
366 | + |
367 | + // Deep copy directories |
368 | + $this->xcopy("$source/$entry", "$dest/$entry"); |
369 | + } |
370 | + |
371 | + // Clean up |
372 | + $dir->close(); |
373 | + return true; |
374 | + } |
375 | + |
376 | + function delete($path) |
377 | + { |
378 | + if (is_dir($path) === true) { |
379 | + $files = array_diff(scandir($path), array('.', '..')); |
380 | + |
381 | + foreach ($files as $file) { |
382 | + $this->delete(realpath($path) . '/' . $file); |
383 | + } |
384 | + |
385 | + return rmdir($path); |
386 | + } |
387 | + else if (is_file($path) === true) { |
388 | + return unlink($path); |
389 | + } |
390 | + |
391 | + return false; |
392 | + } |
393 | +} |
394 | +?> |
395 | |
396 | === added file 'manual/source/en/img/install_environment_windows_cms_install_step1.png' |
397 | Binary files manual/source/en/img/install_environment_windows_cms_install_step1.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_cms_install_step1.png 2015-01-09 11:27:10 +0000 differ |
398 | === added file 'manual/source/en/img/install_environment_windows_cms_install_step2.png' |
399 | Binary files manual/source/en/img/install_environment_windows_cms_install_step2.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_cms_install_step2.png 2015-01-09 11:27:10 +0000 differ |
400 | === added file 'manual/source/en/img/install_environment_windows_cms_install_step3.png' |
401 | Binary files manual/source/en/img/install_environment_windows_cms_install_step3.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_cms_install_step3.png 2015-01-09 11:27:10 +0000 differ |
402 | === added file 'manual/source/en/img/install_environment_windows_iismgr_install.png' |
403 | Binary files manual/source/en/img/install_environment_windows_iismgr_install.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_iismgr_install.png 2015-01-09 11:27:10 +0000 differ |
404 | === added file 'manual/source/en/img/install_environment_windows_mysql_install_step1.png' |
405 | Binary files manual/source/en/img/install_environment_windows_mysql_install_step1.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_mysql_install_step1.png 2015-01-09 11:27:10 +0000 differ |
406 | === added file 'manual/source/en/img/install_environment_windows_mysql_install_step2.png' |
407 | Binary files manual/source/en/img/install_environment_windows_mysql_install_step2.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_mysql_install_step2.png 2015-01-09 11:27:10 +0000 differ |
408 | === added file 'manual/source/en/img/install_environment_windows_mysql_install_step3.png' |
409 | Binary files manual/source/en/img/install_environment_windows_mysql_install_step3.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_mysql_install_step3.png 2015-01-09 11:27:10 +0000 differ |
410 | === added file 'manual/source/en/img/install_environment_windows_mysql_install_step4.png' |
411 | Binary files manual/source/en/img/install_environment_windows_mysql_install_step4.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_mysql_install_step4.png 2015-01-09 11:27:10 +0000 differ |
412 | === added file 'manual/source/en/img/install_environment_windows_mysql_install_step5.png' |
413 | Binary files manual/source/en/img/install_environment_windows_mysql_install_step5.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_mysql_install_step5.png 2015-01-09 11:27:10 +0000 differ |
414 | === added file 'manual/source/en/img/install_environment_windows_mysql_install_step6.png' |
415 | Binary files manual/source/en/img/install_environment_windows_mysql_install_step6.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_mysql_install_step6.png 2015-01-09 11:27:10 +0000 differ |
416 | === added file 'manual/source/en/img/install_environment_windows_php_install_step1.png' |
417 | Binary files manual/source/en/img/install_environment_windows_php_install_step1.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_php_install_step1.png 2015-01-09 11:27:10 +0000 differ |
418 | === added file 'manual/source/en/img/install_environment_windows_php_install_step2.png' |
419 | Binary files manual/source/en/img/install_environment_windows_php_install_step2.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_php_install_step2.png 2015-01-09 11:27:10 +0000 differ |
420 | === added file 'manual/source/en/img/install_environment_windows_php_install_step3.png' |
421 | Binary files manual/source/en/img/install_environment_windows_php_install_step3.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_php_install_step3.png 2015-01-09 11:27:10 +0000 differ |
422 | === added file 'manual/source/en/img/install_environment_windows_php_install_step4.png' |
423 | Binary files manual/source/en/img/install_environment_windows_php_install_step4.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_php_install_step4.png 2015-01-09 11:27:10 +0000 differ |
424 | === added file 'manual/source/en/img/install_environment_windows_php_install_step5.png' |
425 | Binary files manual/source/en/img/install_environment_windows_php_install_step5.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_php_install_step5.png 2015-01-09 11:27:10 +0000 differ |
426 | === added file 'manual/source/en/img/install_environment_windows_php_install_step6.png' |
427 | Binary files manual/source/en/img/install_environment_windows_php_install_step6.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_php_install_step6.png 2015-01-09 11:27:10 +0000 differ |
428 | === added file 'manual/source/en/img/install_environment_windows_phpmyadmin_install_step1.png' |
429 | Binary files manual/source/en/img/install_environment_windows_phpmyadmin_install_step1.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_phpmyadmin_install_step1.png 2015-01-09 11:27:10 +0000 differ |
430 | === added file 'manual/source/en/img/install_environment_windows_phpmyadmin_install_step2.png' |
431 | Binary files manual/source/en/img/install_environment_windows_phpmyadmin_install_step2.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_phpmyadmin_install_step2.png 2015-01-09 11:27:10 +0000 differ |
432 | === added file 'manual/source/en/img/install_environment_windows_phpmyadmin_install_step3.png' |
433 | Binary files manual/source/en/img/install_environment_windows_phpmyadmin_install_step3.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_phpmyadmin_install_step3.png 2015-01-09 11:27:10 +0000 differ |
434 | === added file 'manual/source/en/img/install_environment_windows_phpmyadmin_install_step4.png' |
435 | Binary files manual/source/en/img/install_environment_windows_phpmyadmin_install_step4.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_phpmyadmin_install_step4.png 2015-01-09 11:27:10 +0000 differ |
436 | === added file 'manual/source/en/img/install_environment_windows_phpmyadmin_install_step5.png' |
437 | Binary files manual/source/en/img/install_environment_windows_phpmyadmin_install_step5.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_phpmyadmin_install_step5.png 2015-01-09 11:27:10 +0000 differ |
438 | === added file 'manual/source/en/img/install_environment_windows_phpmyadmin_install_step6.png' |
439 | Binary files manual/source/en/img/install_environment_windows_phpmyadmin_install_step6.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_phpmyadmin_install_step6.png 2015-01-09 11:27:10 +0000 differ |
440 | === added file 'manual/source/en/img/install_environment_windows_phpmyadmin_install_step7.png' |
441 | Binary files manual/source/en/img/install_environment_windows_phpmyadmin_install_step7.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_phpmyadmin_install_step7.png 2015-01-09 11:27:10 +0000 differ |
442 | === added file 'manual/source/en/img/install_environment_windows_wpi_install.png' |
443 | Binary files manual/source/en/img/install_environment_windows_wpi_install.png 1970-01-01 00:00:00 +0000 and manual/source/en/img/install_environment_windows_wpi_install.png 2015-01-09 11:27:10 +0000 differ |
444 | === modified file 'manual/source/en/install_environment.md' |
445 | --- manual/source/en/install_environment.md 2014-10-30 12:30:48 +0000 |
446 | +++ manual/source/en/install_environment.md 2015-01-09 11:27:10 +0000 |
447 | @@ -1,141 +1,9 @@ |
448 | <!--toc=getting_started--> |
449 | # Choosing your Environment |
450 | - |
451 | -## <span id="Install_on_Linux"> Install on Linux </span> |
452 | - |
453 | -Linux makes a good home for a Xibo server. All of the software it needs to support it is provided by the major Linux distributions. We'll cover Ubuntu in detail here, as it's what I use. There are some notes further down for other distributions, however the whole procedure is very similar. |
454 | - |
455 | -### <span id="Setup_Apache_and_PHP"> Setup Apache and PHP </span> |
456 | - |
457 | -#### <span id="Ubuntu"> Ubuntu </span> |
458 | - |
459 | -* Install Apache 2.x Webserver |
460 | -``` |
461 | - sudo apt-get install apache2 |
462 | -``` |
463 | - |
464 | -* Install MySQL Server |
465 | -``` |
466 | - sudo apt-get install mysql-server |
467 | -``` |
468 | - |
469 | -* Install PHP5 : |
470 | -``` |
471 | - sudo apt-get install php5 php5-mysql php5-gd |
472 | -``` |
473 | - |
474 | -_On Ubuntu, DOM, libXML, gettext and JSON extension is already compiled on PHP5_ |
475 | - |
476 | -* Restart Apache 2 Webserver if necessary |
477 | -``` |
478 | - sudo /etc/init.d/apache2 restart |
479 | -``` |
480 | - |
481 | -#### <span id="CentOS_5.x_.2F_Redhat_RHEL_5.x"> CentOS 5.x / Redhat RHEL 5.x </span> |
482 | - |
483 | -JSON extension is not include in CentOS 5.x or Redhat RHEL 5.x but you can install it with this steps : |
484 | - |
485 | -* Install JSON PHP Extension |
486 | -``` |
487 | - yum install php-devel |
488 | -``` |
489 | - |
490 | -_If you have more than 8MB of memory limit for PHP, install with PEAR :_ |
491 | - |
492 | -``` |
493 | - pear install pecl/json |
494 | -``` |
495 | - |
496 | -_If you have less than 8MB of memory limit for PHP, PEAR failed to install... Use PECL : _ |
497 | - |
498 | -``` |
499 | - pecl install json |
500 | -``` |
501 | - |
502 | -* Active JSON extension : |
503 | -``` |
504 | - vim /etc/php.d/json.ini |
505 | -``` |
506 | -``` |
507 | - # Json Extension |
508 | - extension=json.so |
509 | -``` |
510 | - |
511 | -* Save file and restart the Apache webserver : |
512 | -``` |
513 | - /etc/init.d/httpd restart |
514 | -``` |
515 | - |
516 | -#### <span id="SuSe"> SuSe </span> |
517 | - |
518 | -* during web install library location says 'full path' but means relative to document root on suse linux |
519 | -``` |
520 | -for me this is /srv/www/htdocs/xlib in the box for full path, i put "xlib" |
521 | -``` |
522 | - |
523 | -### <span id="Install_Xibo"> Install Xibo </span> |
524 | - |
525 | -* Extract the tarball you downloaded inside your webserver's document root (eg /var/www/xibo) and ensure the webserver has permissions to read and write those files: |
526 | -``` |
527 | - cd /var/www |
528 | - sudo tar zxvf ~/xibo-1.0.5-server.tar.gz |
529 | - sudo mv xibo-1.0.5-server xibo |
530 | - sudo chown www-data.www-data -R xibo |
531 | -``` |
532 | - |
533 | -* Make a directory for the server library. Make sure the webserver has permission to write to this location: |
534 | -``` |
535 | - sudo mkdir /xibo-library |
536 | - sudo chown www-data.www-data -R /xibo-library |
537 | -``` |
538 | - |
539 | -* You should now use a webbrowser to visit your webserver - eg [http://myserver/xibo](http://myserver/xibo) |
540 | - |
541 | -* The process is fairly self explanatory. Follow the final part of the [Windows instructions](install_cms.html) for greater detail. |
542 | - |
543 | -## <span id="Install_on_Windows"> Install on Windows </span> |
544 | - |
545 | -This Windows install guide is focused mainly on someone who wants to use a Windows PC to be the server as well as the client, or perhaps has a spare Windows XP machine to use as a server. The instructions should work equally well on Windows Server operating systems. |
546 | - |
547 | -Xibo should also run under IIS, however it's not a platform the Xibo development team currently tests with. If you know your way around IIS, then the latter half of this guide plus the "What you need to know!" section should get you going. |
548 | - |
549 | -### <span id="Install_the_Webserver_.28XAMPP.29"> Install the Webserver (XAMPP) </span> |
550 | - |
551 | -We'll be using XAMPP to install Apache, MySQL, PHP (amongst other things) to support Xibo. This is convenient as it provides the whole system in a single installer, and can be un-installed via Add/Remove Programs at a later date if required. If you already have XAMPP installed, you can skip to the next section. |
552 | - |
553 | -You can download XAMPP from [Apache Friends](http://www.apachefriends.org/en/xampp.html). You need to download the full XAMPP Installer package for Windows systems. Save it to the Desktop. |
554 | - |
555 | -Once XAMPP Installer has downloaded, double click on it to run it. You may be prompted to allow the installer to run as the publisher could not be verified. Click "Run". |
556 | - |
557 | -You should get to the start of the install wizard. |
558 | - |
559 | -![](img/install_environment_Win32_xampp_install_start.jpg) |
560 | - |
561 | -By default, XAMPP installs to "c:\xampp". Unless you need to move it somewhere else, then that's a good choice. If you do select a different directory, remember it for the next step when we install Xibo. Click Install. |
562 | -The installer will now run, and extract a number of files. When it finishes, it will bring you to a command prompt. |
563 | - |
564 | -You'll now be asked a few questions about how XAMPP should install itself. At the following prompts, you may select all default options. |
565 | - |
566 | -![](img/install_environment_Capture-2.jpg) |
567 | -![](img/install_environment_Capture-3.jpg) |
568 | -![](img/install_environment_Capture-4.jpg) |
569 | -![](img/install_environment_Capture-6.jpg) |
570 | - |
571 | -Once the installation scripts complete, you should choose option 1 to load the XAMPP Control Panel. It should open up, and if everything went to plan, look like the screen shot. |
572 | - |
573 | -![](img/install_environment_Control_Panel_Running.jpg) |
574 | - |
575 | -At this point, you need to check the boxes next to "Svc" for both Apache and MySql. As you click each, it will prompt you to install the service for that item. Click OK. Then click the "Start" button on each of these items as well. |
576 | -Your screen should now look like the below: |
577 | - |
578 | -![](img/install_environment_Configured_Control_Panel.jpg) |
579 | - |
580 | -Before we install Xibo, we need to configure a few things on XAMPP to make it a bit more secure. From the XAMPP Control Panel, click the "Admin" button next to MySQL. This will load a web browser and take you to an application called PHPMyAdmin that was installed along with XAMPP. It will let us setup a password for the "root" MySQL account. The "root" account on MySQL has privileges to add new users, create databases etc so needs to have a strong password. |
581 | - |
582 | -From the PHPMyAdmin screen, click "Privileges" at the top of the screen. You'll see the database users that exist already listed. We're interested in the one called "root" that has "localhost" in the "Host" column. Click the blue "Edit Privileges" symbol to the right of the word "Yes". |
583 | - |
584 | -![](img/install_environment_Win32_phpmyadmin_privileges.png) |
585 | - |
586 | -Scroll down the page until you find the "Change Password" box. Enter a new password in both the password boxes and click "Go". On a piece of paper, write down "MySQL Admin User details. Username: root Password:" followed by the password you just chose. We'll need these later! |
587 | - |
588 | -![](img/install_environment_Win32_phpmyadmin_password.png) |
589 | \ No newline at end of file |
590 | +The [[PRODUCTNAME]] CMS can be run on any operating system that supports PHP/MySQL, the most common installation being "LAMP" (Linux, Apache, MySQL and PHP). |
591 | + |
592 | +The following pages contain basic guides to configuring the most common environments. |
593 | + |
594 | +- [Install on Linux](install_environment_linux.html) |
595 | +- [Install on Windows using XAMPP](install_environment_windows_xampp.html) |
596 | +- [Install on Windows using IIS](install_environment_windows_iis.html) |
597 | \ No newline at end of file |
598 | |
599 | === added file 'manual/source/en/install_environment_linux.md' |
600 | --- manual/source/en/install_environment_linux.md 1970-01-01 00:00:00 +0000 |
601 | +++ manual/source/en/install_environment_linux.md 2015-01-09 11:27:10 +0000 |
602 | @@ -0,0 +1,93 @@ |
603 | +<!--toc=getting_started--> |
604 | +#<span id="Install_on_Linux"> Install on Linux </span> |
605 | + |
606 | +Linux makes a good home for a Xibo server. All of the software it needs to support it is provided by the major Linux distributions. We'll cover Ubuntu in detail here, as it's what I use. There are some notes further down for other distributions, however the whole procedure is very similar. |
607 | + |
608 | +### <span id="Setup_Apache_and_PHP"> Setup Apache and PHP </span> |
609 | + |
610 | +#### <span id="Ubuntu"> Ubuntu </span> |
611 | + |
612 | +* Install Apache 2.x Webserver |
613 | +``` |
614 | + sudo apt-get install apache2 |
615 | +``` |
616 | + |
617 | +* Install MySQL Server |
618 | +``` |
619 | + sudo apt-get install mysql-server |
620 | +``` |
621 | + |
622 | +* Install PHP5 : |
623 | +``` |
624 | + sudo apt-get install php5 php5-mysql php5-gd |
625 | +``` |
626 | + |
627 | +_On Ubuntu, DOM, libXML, gettext and JSON extension is already compiled on PHP5_ |
628 | + |
629 | +* Restart Apache 2 Webserver if necessary |
630 | +``` |
631 | + sudo /etc/init.d/apache2 restart |
632 | +``` |
633 | + |
634 | +#### <span id="CentOS_5.x_.2F_Redhat_RHEL_5.x"> CentOS 5.x / Redhat RHEL 5.x </span> |
635 | + |
636 | +JSON extension is not include in CentOS 5.x or Redhat RHEL 5.x but you can install it with this steps : |
637 | + |
638 | +* Install JSON PHP Extension |
639 | +``` |
640 | + yum install php-devel |
641 | +``` |
642 | + |
643 | +_If you have more than 8MB of memory limit for PHP, install with PEAR :_ |
644 | + |
645 | +``` |
646 | + pear install pecl/json |
647 | +``` |
648 | + |
649 | +_If you have less than 8MB of memory limit for PHP, PEAR failed to install... Use PECL : _ |
650 | + |
651 | +``` |
652 | + pecl install json |
653 | +``` |
654 | + |
655 | +* Active JSON extension : |
656 | +``` |
657 | + vim /etc/php.d/json.ini |
658 | +``` |
659 | +``` |
660 | + # Json Extension |
661 | + extension=json.so |
662 | +``` |
663 | + |
664 | +* Save file and restart the Apache webserver : |
665 | +``` |
666 | + /etc/init.d/httpd restart |
667 | +``` |
668 | + |
669 | +#### <span id="SuSe"> SuSe </span> |
670 | + |
671 | +* during web install library location says 'full path' but means relative to document root on suse linux |
672 | +``` |
673 | +for me this is /srv/www/htdocs/xlib in the box for full path, i put "xlib" |
674 | +``` |
675 | + |
676 | +### <span id="Install_Xibo"> Install Xibo </span> |
677 | + |
678 | +* Extract the tarball you downloaded inside your webserver's document root (eg /var/www/xibo) and ensure the webserver has permissions to read and write those files: |
679 | +``` |
680 | + cd /var/www |
681 | + sudo tar zxvf ~/xibo-1.0.5-server.tar.gz |
682 | + sudo mv xibo-1.0.5-server xibo |
683 | + sudo chown www-data.www-data -R xibo |
684 | +``` |
685 | + |
686 | +* Make a directory for the server library. Make sure the webserver has permission to write to this location: |
687 | +``` |
688 | + sudo mkdir /xibo-library |
689 | + sudo chown www-data.www-data -R /xibo-library |
690 | +``` |
691 | + |
692 | +* You should now use a webbrowser to visit your webserver - eg [http://myserver/xibo](http://myserver/xibo) |
693 | + |
694 | +* The process is fairly self explanatory. Follow the final part of the [Windows instructions](install_cms.html) for greater detail. |
695 | + |
696 | |
697 | === added file 'manual/source/en/install_environment_windows_iis.md' |
698 | --- manual/source/en/install_environment_windows_iis.md 1970-01-01 00:00:00 +0000 |
699 | +++ manual/source/en/install_environment_windows_iis.md 2015-01-09 11:27:10 +0000 |
700 | @@ -0,0 +1,195 @@ |
701 | +<!--toc=getting_started--> |
702 | +# Install on Windows using IIS |
703 | +This guide is written by Piermaria Spinazzola. |
704 | + |
705 | +## Install Internet Information Services (IIS) Manager |
706 | +If you are using Windows Server you’ll need to install the role from "Server Manager". |
707 | + |
708 | +On Windows 7 and 8, open "Windows Features" and tick the box next to: |
709 | +1. Internet Information Services |
710 | + |
711 | +2. Web Management Tools |
712 | + |
713 | +3. World Wide Web Services (With all Sub-Features) |
714 | + |
715 | +4. Internet Information Services Hostable Web Core (With all Sub-Features) |
716 | +![IIS Manager Install](img/install_environment_windows_iismgr_install.png) |
717 | + |
718 | + Click OK, wait for the features to be installed and when finished reboot windows. |
719 | + |
720 | +## Install PHP |
721 | +To get started go on: [http://php.iis.net](http://php.iis.net), You will be prompted to the Microsoft IIS page for PHP. |
722 | + |
723 | +1. Click on install and when prompted on Run and start the installation using the Microsoft Web Platform Installer. |
724 | +![WPI Install](img/install_environment_windows_wpi_install.png) |
725 | + If WPI is already installed, just open on IIS and click on the icon under management. |
726 | +![Step 1](img/install_environment_windows_php_install_step1.png) |
727 | + |
728 | +2. Click on install a screen like the one below should appear, check that all components have been selected for installation. |
729 | +![Step 2](img/install_environment_windows_php_install_step2.png) |
730 | + |
731 | +3. At the end of the setup, click on Finish to exit the installer. |
732 | +![Step 3](img/install_environment_windows_php_install_step3.png) |
733 | + |
734 | +4. Close IIS |
735 | + |
736 | +5. Go in the PHP installation folder, should be: |
737 | + |
738 | + C:\Program Files (x86)\PHP\v5.3 |
739 | + Look for a file called "php.ini" is the php configuration file, once located, open it with text editor: |
740 | + |
741 | + By scrolling or searching the following strings of text check that the values are the ones shown below. |
742 | + |
743 | + ``` |
744 | + fastcgi.impersonate = 1 |
745 | + fastcgi.logging = 0 |
746 | + cgi.fix_pathinfo=1 |
747 | + cgi.force_redirect = 0 |
748 | + ``` |
749 | + |
750 | +6. Open IIS |
751 | + |
752 | +7. Click on Sites and Default Web Site |
753 | +![Step 4](img/install_environment_windows_php_install_step4.png) |
754 | + |
755 | +8. Click on PHP Manager |
756 | +![Step 5](img/install_environment_windows_php_install_step5.png) |
757 | + |
758 | +9. Click on Default Document and check that index.php is enabled. |
759 | + |
760 | +10. Go back and click on "Handler Mappings", if you can't see the line: |
761 | +![Step 6](img/install_environment_windows_php_install_step6.png) |
762 | + |
763 | +11. Click on "Add Module Mapping" and enter the following in the dialog: |
764 | + |
765 | + ``` |
766 | + Request path: *.php |
767 | + Module: FastCgiModule |
768 | + Executable: C:\[Path to PHP installation]\php-cgi.exe |
769 | + Name: PHP_via_FastCGI |
770 | + ``` |
771 | + |
772 | +12. Click "Request Restrictions" button and then configure the mapping to invoke handler only if request is mapped to a file or a folder; |
773 | + |
774 | +13. Go Back to Default Web Site and click on PHP Manager and click on "Enable or Disable and Extension" and in the actions pane click on "Open php.ini". Find the [ExtensionList] and add: |
775 | + |
776 | + a. extension=php_fileinfo.dll, or if the line is present, remove the ";" at the beginning. |
777 | + |
778 | + b. extension=php_mcrypt.dll, or if the line is present, remove the ";" at the beginning. |
779 | + |
780 | + c. Check that php_gd2.dll and php_mbstring.dll are both present. |
781 | + You probably want to allow larger files to be uploaded than is currently available with your default PHP configuration. |
782 | + |
783 | + d. Find the upload_max_filesize line and set with a value > 128M if you want to upload files into [[PRODUCTNAME]] bigger than the default size. |
784 | + |
785 | + e. Find the post_max_size line and set with a value > 128M if you want to post files into [[PRODUCTNAME]] bigger than the default size. |
786 | + |
787 | + f. Find the max_execution_time line and set with a value > 120 this in order to limit the maximum exectuion time of each script, the values is in seconds. |
788 | + |
789 | +14. Now Save the file using the same extension, close the text editor. |
790 | +15. Press Win + R and type iisreset.exe and hit enter. |
791 | + |
792 | +## Install MySQL |
793 | +[[PRODUCTNAME]] Performs better on MySQL Community Server Edition, I strongly suggest to use this version rather than MySQL Server. |
794 | + |
795 | +1. Go on http://dev.mysql.com/downloads/ and download the MyQL Community Server MSI installer. |
796 | + |
797 | +2. Once downloaded the installer, run it. |
798 | + |
799 | +3. Select the right installation for you, as for [[PRODUCTNAME]] we need on MySQL server, I will install the Server Only package. |
800 | +![Step 1](img/install_environment_windows_mysql_install_step1.png) |
801 | + |
802 | +4. Once Done, click next and select the right configuration for you server, for this tutorial as I assumed that server is shared with other services i’ve selected "Server Machine" as configuration type. |
803 | +![Step 2](img/install_environment_windows_mysql_install_step2.png) |
804 | + |
805 | + Tick the box "Show Advanced Options" and click next |
806 | + |
807 | +5. The next step is to set the "root" password, you can also create further users, with different responsibilities. |
808 | + Write down and store safely the "root" password you will always need it to let [[PRODUCTNAME]] access the my sql server and create a new DB. |
809 | +![Step 3](img/install_environment_windows_mysql_install_step3.png) |
810 | + |
811 | +6. Once done click next. |
812 | + |
813 | +7. Configure the Windows Service |
814 | +![Step 4](img/install_environment_windows_mysql_install_step4.png) |
815 | + |
816 | + Check that the MySQL server will run as a windows Service, if needed you can personalise the name. |
817 | + If the service needs to be run with a different account select it now otherwise keep the radio button on standard. |
818 | + TIP: in Windows Domain is good practice to create special windows account for special services. |
819 | + |
820 | +8. Once done click next. |
821 | + |
822 | +9. Configure Advanced Options: |
823 | +![Step 5](img/install_environment_windows_mysql_install_step5.png) |
824 | + |
825 | + In this page you can disable or enable the service logs and rename them. |
826 | + If you’re happy with the basic settings, click next. |
827 | + |
828 | +10. Apply Server Configuration |
829 | + |
830 | + The installer will now apply the selected configuration. |
831 | + |
832 | +11. Click Finish to exit the installer configurator. |
833 | + |
834 | +12. Now Click next again and then finish. |
835 | + |
836 | +## Install PHP My Admin |
837 | +PHPmyAdmin is a third party graphic interface for the MySQL server, this is not essential but useful if you want to manage and have a look at your MySQL Databases. |
838 | + |
839 | +1. Go at: http://www.phpmyadmin.net/home_page/downloads.php and download the latest version, save it on your disk. |
840 | + |
841 | +2. Once downloaded, open the Zip file and copy the content in your IIS default site folder, usually: "C:\inetpub\wwwroot" |
842 | +![Step 1](img/install_environment_windows_phpmyadmin_install_step1.png) |
843 | + |
844 | +3. Rename the folder with the following name: phpmyadmin and hit enter |
845 | + |
846 | +4. Open IIS |
847 | + |
848 | +5. Click on "Default Site" and right click on the "phpMyAdmin" Folder and from the drop down menu select "Convert to Application" |
849 | +![Step 2](img/install_environment_windows_phpmyadmin_install_step2.png) |
850 | + |
851 | +6. You can leave the default settings and click OK. |
852 | +![Step 3](img/install_environment_windows_phpmyadmin_install_step3.png) |
853 | + |
854 | +7. Now go to the directory that you copied the unzipped PHPMyAdmin folder to and open a file named config.sample.inc.php using WordPad |
855 | + |
856 | +8. Find the line $cfg[‘blowfish_secret’] = ‘Value’; you have to fill in this line with anything that you want. |
857 | + Tips: The maximum number of characters is 46 and it can be alphanumeric. |
858 | +![Step 4](img/install_environment_windows_phpmyadmin_install_step4.png) |
859 | + |
860 | +9. Go down to the section User for advanced features and uncomment (Remove the // from the front of the line) the two lines under that and change the pmapass to a different password, I will use password. |
861 | +![Step 5](img/install_environment_windows_phpmyadmin_install_step5.png) |
862 | + |
863 | +10. Next, go down to the next section Storage database and tables and uncomment all the lines under it, unless you want to disable access to Database areas (remove the // from the front of the line). |
864 | +![Step 6](img/install_environment_windows_phpmyadmin_install_step6.png) |
865 | + |
866 | +11. Now save and close the file. |
867 | + |
868 | +12. Open your browser and go to: http://localhost/phpmyadmin/ |
869 | + |
870 | +13. You should now see the following page: |
871 | + To login use your "root" username and password to get access. |
872 | + |
873 | +![Step 7](img/install_environment_windows_phpmyadmin_install_step7.png) |
874 | + |
875 | +## Install [[PRODUCTNAME]] |
876 | +1. Download the latest version of [[PRODUCTNAME]] from the website [[PRODUCTHOME]], save it on your disk. |
877 | + |
878 | +2. Once downloaded, open the Zip file and copy the content in your IIS default site folder, should be: "C:\inetpub\wwwroot" |
879 | + |
880 | +3. Rename the folder just copied with the following name: [[PRODUCTNAME]] |
881 | +![Step 1](img/install_environment_windows_cms_install_step1.png) |
882 | + |
883 | +4. Open IIS |
884 | + |
885 | +5. Click on "Default Site" and right click on the "[[PRODUCTNAME]]" Folder and from the drop down menu select "Convert to Application" |
886 | +![Step 2](img/install_environment_windows_cms_install_step2.png) |
887 | + |
888 | +6. You can leave the default settings and click OK. |
889 | +![Step 3](img/install_environment_windows_cms_install_step3.png) |
890 | + |
891 | +7. Now open your browser and type the following address http://localhost/[[PRODUCTNAME]]/ and follow the CMS installation guide you can find on the website. |
892 | + |
893 | +``` |
894 | +Rev 30.11.2014 v.1.0 – IIS 8.5, MySQL 5.6.21 Community Server Edition, PHP 5.3, Windows Server 2012. |
895 | +``` |
896 | \ No newline at end of file |
897 | |
898 | === added file 'manual/source/en/install_environment_windows_xampp.md' |
899 | --- manual/source/en/install_environment_windows_xampp.md 1970-01-01 00:00:00 +0000 |
900 | +++ manual/source/en/install_environment_windows_xampp.md 2015-01-09 11:27:10 +0000 |
901 | @@ -0,0 +1,47 @@ |
902 | +<!--toc=getting_started--> |
903 | +# <span id="Install_on_Windows"> Install on Windows </span> |
904 | + |
905 | +This Windows install guide is focused mainly on someone who wants to use a Windows PC to be the server as well as the client, or perhaps has a spare Windows XP machine to use as a server. The instructions should work equally well on Windows Server operating systems. |
906 | + |
907 | +Xibo should also run under IIS, however it's not a platform the Xibo development team currently tests with. If you know your way around IIS, then the latter half of this guide plus the "What you need to know!" section should get you going. |
908 | + |
909 | +### <span id="Install_the_Webserver_.28XAMPP.29"> Install the Webserver (XAMPP) </span> |
910 | + |
911 | +We'll be using XAMPP to install Apache, MySQL, PHP (amongst other things) to support Xibo. This is convenient as it provides the whole system in a single installer, and can be un-installed via Add/Remove Programs at a later date if required. If you already have XAMPP installed, you can skip to the next section. |
912 | + |
913 | +You can download XAMPP from [Apache Friends](http://www.apachefriends.org/en/xampp.html). You need to download the full XAMPP Installer package for Windows systems. Save it to the Desktop. |
914 | + |
915 | +Once XAMPP Installer has downloaded, double click on it to run it. You may be prompted to allow the installer to run as the publisher could not be verified. Click "Run". |
916 | + |
917 | +You should get to the start of the install wizard. |
918 | + |
919 | +![](img/install_environment_Win32_xampp_install_start.jpg) |
920 | + |
921 | +By default, XAMPP installs to "c:\xampp". Unless you need to move it somewhere else, then that's a good choice. If you do select a different directory, remember it for the next step when we install Xibo. Click Install. |
922 | +The installer will now run, and extract a number of files. When it finishes, it will bring you to a command prompt. |
923 | + |
924 | +You'll now be asked a few questions about how XAMPP should install itself. At the following prompts, you may select all default options. |
925 | + |
926 | +![](img/install_environment_Capture-2.jpg) |
927 | +![](img/install_environment_Capture-3.jpg) |
928 | +![](img/install_environment_Capture-4.jpg) |
929 | +![](img/install_environment_Capture-6.jpg) |
930 | + |
931 | +Once the installation scripts complete, you should choose option 1 to load the XAMPP Control Panel. It should open up, and if everything went to plan, look like the screen shot. |
932 | + |
933 | +![](img/install_environment_Control_Panel_Running.jpg) |
934 | + |
935 | +At this point, you need to check the boxes next to "Svc" for both Apache and MySql. As you click each, it will prompt you to install the service for that item. Click OK. Then click the "Start" button on each of these items as well. |
936 | +Your screen should now look like the below: |
937 | + |
938 | +![](img/install_environment_Configured_Control_Panel.jpg) |
939 | + |
940 | +Before we install Xibo, we need to configure a few things on XAMPP to make it a bit more secure. From the XAMPP Control Panel, click the "Admin" button next to MySQL. This will load a web browser and take you to an application called PHPMyAdmin that was installed along with XAMPP. It will let us setup a password for the "root" MySQL account. The "root" account on MySQL has privileges to add new users, create databases etc so needs to have a strong password. |
941 | + |
942 | +From the PHPMyAdmin screen, click "Privileges" at the top of the screen. You'll see the database users that exist already listed. We're interested in the one called "root" that has "localhost" in the "Host" column. Click the blue "Edit Privileges" symbol to the right of the word "Yes". |
943 | + |
944 | +![](img/install_environment_Win32_phpmyadmin_privileges.png) |
945 | + |
946 | +Scroll down the page until you find the "Change Password" box. Enter a new password in both the password boxes and click "Go". On a piece of paper, write down "MySQL Admin User details. Username: root Password:" followed by the password you just chose. We'll need these later! |
947 | + |
948 | +![](img/install_environment_Win32_phpmyadmin_password.png) |
949 | \ No newline at end of file |
950 | |
951 | === modified file 'manual/source/en/release_notes.md' |
952 | --- manual/source/en/release_notes.md 2014-11-25 14:27:02 +0000 |
953 | +++ manual/source/en/release_notes.md 2015-01-09 11:27:10 +0000 |
954 | @@ -5,6 +5,7 @@ |
955 | The current release notes are [[[PRODUCTVERSION]]](release_notes_[[PRODUCTVERSION]].html). |
956 | |
957 | ## Version 1.7 "Tuttle" |
958 | +* [1.7.0-rc1](release_notes_1.7.0-rc1.html) |
959 | * [1.7.0-beta](release_notes_1.7.0-beta.html) |
960 | * [1.7.0-alpha2](release_notes_1.7.0-alpha2.html) |
961 | * [1.7.0-alpha](release_notes_1.7.0-alpha.html) |
962 | |
963 | === added file 'manual/source/en/release_notes_1.7.0-rc1.md' |
964 | --- manual/source/en/release_notes_1.7.0-rc1.md 1970-01-01 00:00:00 +0000 |
965 | +++ manual/source/en/release_notes_1.7.0-rc1.md 2015-01-09 11:27:10 +0000 |
966 | @@ -0,0 +1,53 @@ |
967 | +<!--toc=getting_started--> |
968 | +# Xibo 1.7.0-beta - Codename "Tuttle"</span> |
969 | + |
970 | +This is a release candidate for Xibo working towards the release of Xibo 1.7.0, the next stable line of Xibo released. **This should NOT BE USED IN PRODUCTION.**. |
971 | + |
972 | +You can download this release from [https://launchpad.net/xibo/1.7/1.7.0-rc1](https://launchpad.net/xibo/1.7/1.7.0-rc1) |
973 | + |
974 | +This release builds on 1.7.0-beta, optimizing the improvements already made, fixing bugs and adding a few additional features. The most notable improvements are installable weather and twitter modules. |
975 | + |
976 | +## Requirements |
977 | + |
978 | +You must use the 1.7.0-rc1 or higher version of the Windows Display Client with this version of the Xibo CMS. The Ubuntu Client is not currently compatible with 1.7 series. |
979 | + |
980 | +Xibo requires PHP 5.3.3 or higher. A full list of module requirements is presented at the point of installation. |
981 | + |
982 | +### Layout Design |
983 | +The Layout format has been changed in 1.7 release and this beta contains a method of upgrading older Layouts to the new format. When viewing an older layout a notification will appear below the layout in the designer. Upgrading a Layout will alter the dimensions of the layout so that they match a particular resolution - it will **not** resize the media content and this will have to be done manually. |
984 | + |
985 | +### Xibo for Windows |
986 | + |
987 | +There are significant changes to the way display client settings are managed. All settings are now managed on the CMS except the settings required to connect to the CMS. You will need to manually migrate your settings into the CMS - we have provided sensible default values. See [display settings](index.php?toc=user_and_display&p=admin/displayprofiles) in the manual for more information. |
988 | + |
989 | +The .NET Framework requirement has been raised to v4. |
990 | + |
991 | +## Upgrading |
992 | + |
993 | +There are significant database schema changes between the 1.7 series of Xibo and prior releases. The upgrade wizard will take a prior database and convert it to a schema suitable for the 1.7 series to date. Note that this is a one-way conversion. **Please do not upgrade your production database to test Xibo 1.7 functionality, and then expect to run a prior series code base against that database.** |
994 | + |
995 | +* Clone your existing Xibo database and grant permissions (see [Release Notes:Clone Database](release_notes_clonedb.html "Clone Database") for details) |
996 | +* Backup settings.php from your installation |
997 | +* Manually take a backup of your database |
998 | +* Replace your existing installation with the new version from the tar.gz or zip file. **Do not copy over the top.** |
999 | +* Replace your backup settings.php file in your Xibo installation directory |
1000 | +* Browse to [http://your.server/path](http://your.server/path) as normal |
1001 | +* You will be prompted that an upgrade is required. |
1002 | +* Enter your xibo_admin password, and follow the upgrade wizard. |
1003 | +* The upgrade should run, and finally ask you to log in as you would normally. |
1004 | + |
1005 | +Instructions for cloning a Xibo database are available here [Clone Database](release_notes_clonedb.html "Clone Database"). |
1006 | + |
1007 | +## Help |
1008 | + |
1009 | +Please ask for help / advice in the Answers section of Launchpad: [https://answers.launchpad.net/xibo](https://answers.launchpad.net/xibo) |
1010 | + |
1011 | +Please report any bugs in the Bugs section of Launchpad: [https://bugs.launchpad.net/xibo](https://bugs.launchpad.net/xibo) (if you're not sure that what you have found is a bug, please ask in the Answers section first!) |
1012 | + |
1013 | +Please report any enhancement requests in the Blueprints section of Launchpad: [https://blueprints.launchpad.net/xibo](https://blueprints.launchpad.net/xibo) |
1014 | + |
1015 | +When asking for assistance with this release, please make it clear that you're using the development preview and not a stable release of Xibo. |
1016 | + |
1017 | +## Bug Fixes |
1018 | + |
1019 | +For a full list of bug fixes please refer to the Release Project Page: [https://launchpad.net/xibo/1.7/1.7.0-rc1](https://launchpad.net/xibo/1.7/1.7.0-rc1) |
1020 | \ No newline at end of file |
1021 | |
1022 | === added file 'manual/source/fr/tour.md' |
1023 | --- manual/source/fr/tour.md 1970-01-01 00:00:00 +0000 |
1024 | +++ manual/source/fr/tour.md 2015-01-09 11:27:10 +0000 |
1025 | @@ -0,0 +1,65 @@ |
1026 | +<!--toc=tour--> |
1027 | +#Vue d'ensemble de la plate-forme |
1028 | + |
1029 | +[[PRODUCTNAME]] est une application puissante et flexible dotée d'un noyau "ethos", dédiée à l'affichage dynamique, dont il est important de comprendre le fondement. |
1030 | + |
1031 | +Une solution [[PRODUCTNAME]] s'appuie sur quatre éléments: |
1032 | + |
1033 | +* Les afficheurs |
1034 | +* Les medias |
1035 | +* Les présentations |
1036 | +* La planification |
1037 | + |
1038 | +Que faut-il entendre par là ? Fondamentalement, [[PRODUCTNAME]] permet à de multiples afficheurs de diffuser des medias sur un grand nombre de présentations d'écran différentes, planifiés dans le temps. |
1039 | + |
1040 | +Ce manuel comprend des sections traitant de chacun de ces éléments, mais pour commencer examinons-les brièvement. |
1041 | + |
1042 | + |
1043 | +###Les afficheurs |
1044 | +Il s'agit de l'équipement relié à l'écran de télévision, de projecteur et de tablette qui diffusent réellement le contenu final. En d'autres termes, les afficheurs pilotent le contenu que les gens regarderont. Chaque afficheur a sa propre identification auprès du CMS de sorte qu'un contenu, une présentation et une planification spécifique peuvent lui être attribués. Chacun d'eux peut aussi être identifié à des fins statistiques. |
1045 | + |
1046 | +###Les medias |
1047 | +Le contenu du media constitue la clé de voûte d'une solution [[PRODUCTNAME]] et de nombreux types de contenu peuvent être utilisés. Ils se répartissent généralement en deux catégories. Le fichier média, chargé et stocké dans la bibliothèque, et le média de présentation auquel n'est pas associé de fichier mais qui au contraire est configuré directement à partir d'un modèle. Une image ou une vidéo correspond à un média de la bibliothèque et un flux RSS ou des données texte correspondent à des médias de présentation. |
1048 | + |
1049 | +###Présentations |
1050 | +Il s'agit de la présentation qui apparaît à l'écran. [[PRODUCTNAME]] permet de partager l'écran en différentes régions, chacune disposant de son propre déroulé chronologique pour la lecture des médias. Une présentation demeure à l'écran jusqu'à ce que les déroulés chronologiques aient été lus en entier, ensuite, on pourra charger une présentation totalement nouvelle, dotée de tailles et d'emplacements différents pour les régions ainsi que de chronologies différentes. Cette flexibilité est à l'origine du comportement dynamique d'un écran d'affichage [[PRODUCTNAME]]. |
1051 | + |
1052 | +###Planification |
1053 | +Lorsque les afficheurs ont été enregistrés, que le contenu d'un media est téléchargé et que les présentations sont conçues, il est temps de les assembler et de planifier les présentations sur les afficheurs. Chaque afficheur vérifie régulièrement les nouveaux contenus planifiés et télécharge les éléments planifiés avant leur reproduction. La planification est extrêmement flexible et peut s'effectuer par afficheur ou par groupes spécifiques, par présentations et campagnes spécifiques et de façon récurrente. Chaque afficheur dispose d'une présentation par défaut qui apparaît si rien d'autre n'est planifié. |
1054 | + |
1055 | +## Contenu - que peut afficher [[PRODUCTNAME]]? |
1056 | + |
1057 | +[[PRODUCTNAME]] peut lire un grand nombre de contenus sur fichier ainsi que des contenus depuis internet. |
1058 | + |
1059 | +* Texte |
1060 | +* Images |
1061 | +* Vidéo |
1062 | +* PowerPoint (client d'affichage Windows uniquement) |
1063 | +* Flash (client d'affichage Windows uniquement) |
1064 | +* RSS / Atom |
1065 | +* Fichier CSV (formatés) |
1066 | +* Pages Web |
1067 | +* Contenu personnalisé intégré |
1068 | + |
1069 | +On trouvera sur le site web de [[PRODUCTNAME]] une liste complète des fonctionnalités. |
1070 | + |
1071 | +## CMS - Comment gérer tout cela? |
1072 | + |
1073 | +La gestion d'une solution aussi souple que [[PRODUCTNAME]] nécessite un puissant CMS (content management system = système de gestion de contenu) pour offrir ces fonctions fondamentales de façon rationnelle et maîtrisée. Le CMS de [[PRODUCTNAME]] est doté de fonctionnalités telles que: |
1074 | + |
1075 | +* Groupes d'utilisateurs |
1076 | +* Définition de droits d'accès pour utilisateurs et groupes |
1077 | +* Groupes d'afficheurs |
1078 | +* Définition de droits d'accès pour des groupes d'afficheurs |
1079 | +* Définition de droits d'accès aux menus et aux pages |
1080 | +* Campagnes (groupes de présentations ordonnés) |
1081 | +* Modèles de présentations |
1082 | +* Statistiques concernant les afficheurs |
1083 | + |
1084 | +## Le Manuel |
1085 | + |
1086 | +Ce manuel est structuré en sections correspondant globalement aux principes de base et aux fonctions les plus évoluées du CMS. Nous commençons par la bibliothèque, les présentations et la planification, pour passer ensuite à la gestion des afficheurs et aux options pour utilisateurs et développeurs. |
1087 | + |
1088 | + |
1089 | +## Plus d'informations |
1090 | +Le site web de [[[PRODUCTNAME]] ]([[PRODUCTHOME]]) est une excellente ressource pour en savoir plus car il s'agit du site de la communauté d'utilisateurs (PRODUCTSUPPORTURL) pour la plate-forme. |
1091 | |
1092 | === modified file 'manual/template/template.php' |
1093 | --- manual/template/template.php 2014-10-27 18:25:50 +0000 |
1094 | +++ manual/template/template.php 2015-01-09 11:27:10 +0000 |
1095 | @@ -1,9 +1,29 @@ |
1096 | <?php |
1097 | +/* |
1098 | + * Xibo - Digital Signage - http://www.xibo.org.uk |
1099 | + * Copyright (C) 2006-2014 Spring Signage Ltd |
1100 | + * |
1101 | + * This file is part of Xibo. |
1102 | + * |
1103 | + * Xibo is free software: you can redistribute it and/or modify |
1104 | + * it under the terms of the GNU Affero General Public License as published by |
1105 | + * the Free Software Foundation, either version 3 of the License, or |
1106 | + * any later version. |
1107 | + * |
1108 | + * Xibo is distributed in the hope that it will be useful, |
1109 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1110 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1111 | + * GNU Affero General Public License for more details. |
1112 | + * |
1113 | + * You should have received a copy of the GNU Affero General Public License |
1114 | + * along with Xibo. If not, see <http://www.gnu.org/licenses/>. |
1115 | + */ |
1116 | + |
1117 | # Name of the product |
1118 | define('PRODUCT_NAME', 'Xibo'); |
1119 | |
1120 | # Product Version |
1121 | -define('PRODUCT_VERSION', '1.7.0-beta'); |
1122 | +define('PRODUCT_VERSION', '1.7.0'); |
1123 | |
1124 | # Home page URL |
1125 | define('PRODUCT_HOME', 'http://xibo.org.uk'); |
1126 | |
1127 | === modified file 'server/config/client.config.php' |
1128 | --- server/config/client.config.php 2014-11-14 15:43:58 +0000 |
1129 | +++ server/config/client.config.php 2015-01-09 11:27:10 +0000 |
1130 | @@ -285,7 +285,7 @@ |
1131 | 'fieldType' => 'checkbox', |
1132 | 'default' => 0, |
1133 | 'helpText' => __('When enabled the client will send the current layout to the CMS each time it changes. Warning: This is bandwidth intensive and should be disabled unless on a LAN.'), |
1134 | - 'enabled' => true, |
1135 | + 'enabled' => Theme::GetConfig('client_sendCurrentLayoutAsStatusUpdate_enabled', true), |
1136 | 'groupClass' => NULL |
1137 | ), |
1138 | array( |
1139 | @@ -296,7 +296,7 @@ |
1140 | 'fieldType' => 'number', |
1141 | 'default' => 0, |
1142 | 'helpText' => __('The duration between status screen shots in minutes. 0 to disable. Warning: This is bandwidth intensive.'), |
1143 | - 'enabled' => true, |
1144 | + 'enabled' => Theme::GetConfig('client_screenShotRequestInterval_enabled', true), |
1145 | 'groupClass' => NULL |
1146 | ) |
1147 | ) |
1148 | @@ -471,6 +471,28 @@ |
1149 | 'helpText' => __('Store all HTML resources on the Internal Storage? Should be selected if the device cannot display text, ticker, dataset media.'), |
1150 | 'enabled' => true, |
1151 | 'groupClass' => NULL |
1152 | + ), |
1153 | + array( |
1154 | + 'name' => 'sendCurrentLayoutAsStatusUpdate', |
1155 | + 'tabId' => 'advanced', |
1156 | + 'title' => __('Notify current layout'), |
1157 | + 'type' => _CHECKBOX, |
1158 | + 'fieldType' => 'checkbox', |
1159 | + 'default' => 0, |
1160 | + 'helpText' => __('When enabled the client will send the current layout to the CMS each time it changes. Warning: This is bandwidth intensive and should be disabled unless on a LAN.'), |
1161 | + 'enabled' => Theme::GetConfig('client_sendCurrentLayoutAsStatusUpdate_enabled', true), |
1162 | + 'groupClass' => NULL |
1163 | + ), |
1164 | + array( |
1165 | + 'name' => 'screenShotRequestInterval', |
1166 | + 'tabId' => 'advanced', |
1167 | + 'title' => __('Screen shot interval'), |
1168 | + 'type' => _INT, |
1169 | + 'fieldType' => 'number', |
1170 | + 'default' => 0, |
1171 | + 'helpText' => __('The duration between status screen shots in minutes. 0 to disable. Warning: This is bandwidth intensive.'), |
1172 | + 'enabled' => Theme::GetConfig('client_screenShotRequestInterval_enabled', true), |
1173 | + 'groupClass' => NULL |
1174 | ) |
1175 | ) |
1176 | ) |
1177 | |
1178 | === modified file 'server/install/database/60.sql' |
1179 | --- server/install/database/60.sql 2013-05-01 19:24:35 +0000 |
1180 | +++ server/install/database/60.sql 2015-01-09 11:27:10 +0000 |
1181 | @@ -32,6 +32,19 @@ |
1182 | |
1183 | INSERT INTO `pages` (`pageID`, `name`, `pagegroupID`) VALUES (NULL, 'timeline', '3'); |
1184 | |
1185 | +/* Get all of the current permission links between pages in the Layouts group and add a duplicate for the new time line page */ |
1186 | +INSERT INTO `lkpagegroup` (`pageID`, `groupID`) |
1187 | +SELECT DISTINCT newpage.pageID, lkpagegroup.groupID |
1188 | + FROM `lkpagegroup` |
1189 | + INNER JOIN `pages` |
1190 | + ON pages.pageID = lkpagegroup.pageID |
1191 | + CROSS JOIN ( |
1192 | + SELECT pageID |
1193 | + FROM `pages` |
1194 | + WHERE `name` = 'timeline' |
1195 | + ) newpage |
1196 | + WHERE pages.pagegroupID = 3; |
1197 | + |
1198 | UPDATE `module` SET `ImageUri` = REPLACE(ImageUri, 'img/forms/', 'forms/') WHERE ImageUri IS NOT NULL; |
1199 | |
1200 | UPDATE `menuitem` SET `Img` = REPLACE(Img, 'img/dashboard/', 'dashboard/') WHERE Img IS NOT NULL; |
1201 | |
1202 | === modified file 'server/install/database/80.sql' |
1203 | --- server/install/database/80.sql 2014-11-24 15:49:49 +0000 |
1204 | +++ server/install/database/80.sql 2015-01-09 11:27:10 +0000 |
1205 | @@ -45,7 +45,7 @@ |
1206 | ALTER TABLE `layout` CHANGE `background` `backgroundImageId` INT( 11 ) NULL DEFAULT NULL; |
1207 | |
1208 | INSERT INTO `lklayoutmedia` (mediaid, layoutid, regionid) |
1209 | -SELECT backgroundimageid, layoutid, 'background' FROM `layout` WHERE IFNULL(backgroundImageId, 0) <> 0; |
1210 | +SELECT backgroundimageid, layoutid, 'background' FROM `layout` INNER JOIN `media` ON media.mediaid = layout.backgroundImageId WHERE IFNULL(backgroundImageId, 0) <> 0; |
1211 | |
1212 | ALTER TABLE `setting` CHANGE `type` `fieldType` VARCHAR( 24 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; |
1213 | |
1214 | |
1215 | === modified file 'server/install/database/81.sql' |
1216 | --- server/install/database/81.sql 2014-11-11 21:42:27 +0000 |
1217 | +++ server/install/database/81.sql 2015-01-09 11:27:10 +0000 |
1218 | @@ -1,6 +1,6 @@ |
1219 | INSERT INTO `setting` (`setting` ,`value` ,`fieldType` ,`helptext` ,`options` ,`cat` ,`userChange` ,`title` ,`validation` ,`ordering` ,`default` ,`userSee` ,`type`) |
1220 | VALUES ( |
1221 | - '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' |
1222 | + 'DATE_FORMAT', 'Y-m-d H:i', 'text', 'The Date Format to use when displaying dates in the CMS.', NULL , 'regional', '1', 'Date Format', 'required', '30', 'Y-m-d', '1', 'string' |
1223 | ); |
1224 | |
1225 | INSERT INTO `setting` (`setting` ,`value` ,`fieldType` ,`helptext` ,`options` ,`cat` ,`userChange` ,`title` ,`validation` ,`ordering` ,`default` ,`userSee` ,`type`) |
1226 | |
1227 | === added file 'server/install/database/83.sql' |
1228 | --- server/install/database/83.sql 1970-01-01 00:00:00 +0000 |
1229 | +++ server/install/database/83.sql 2015-01-09 11:27:10 +0000 |
1230 | @@ -0,0 +1,5 @@ |
1231 | +ALTER TABLE `user` CHANGE `UserName` `UserName` VARCHAR( 50 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL; |
1232 | + |
1233 | +UPDATE `version` SET `app_ver` = '1.7.0-rc1', `XmdsVersion` = 4, `XlfVersion` = 2; |
1234 | +UPDATE `setting` SET `value` = 0 WHERE `setting` = 'PHONE_HOME_DATE'; |
1235 | +UPDATE `version` SET `DBVersion` = '83'; |
1236 | \ No newline at end of file |
1237 | |
1238 | === modified file 'server/install/master/data.sql' |
1239 | --- server/install/master/data.sql 2014-11-26 15:33:06 +0000 |
1240 | +++ server/install/master/data.sql 2015-01-09 11:27:10 +0000 |
1241 | @@ -1,5 +1,5 @@ |
1242 | INSERT INTO `version` (`app_ver`, `XmdsVersion`, `XlfVersion`, `DBVersion`) VALUES |
1243 | -('1.7.0-beta', 4, 2, 82); |
1244 | +('1.7.0-rc1', 4, 2, 83); |
1245 | |
1246 | INSERT INTO `group` (`groupID`, `group`, `IsUserSpecific`, `IsEveryone`) VALUES |
1247 | (1, 'Users', 0, 0), |
1248 | @@ -236,7 +236,7 @@ |
1249 | (44, 'MAINTENANCE_LOG_MAXAGE', '30', 'number', 'Maximum age for log entries. Set to 0 to keep logs indefinitely.', NULL, 'maintenance', 1, 'Max Log Age', '', 60, '30', 1, 'int'), |
1250 | (45, 'MAINTENANCE_STAT_MAXAGE', '30', 'number', 'Maximum age for statistics entries. Set to 0 to keep statistics indefinitely.', NULL, 'maintenance', 1, 'Max Statistics Age', '', 70, '30', 1, 'int'), |
1251 | (46, 'MAINTENANCE_ALERT_TOUT', '12', 'number', 'How long in minutes after the last time a client connects should we send an alert? Can be overridden on a per client basis.', NULL, 'maintenance', 1, 'Max Display Timeout', '', 80, '12', 1, 'int'), |
1252 | -(47, 'SHOW_DISPLAY_AS_VNCLINK', '0', 'checkbox', 'Turn the display name in display management into a VNC link using the IP address last collected. The %s is replaced with the IP address. Leave blank to disable.', NULL, 'displays', 1, 'Display a VNC Link?', '', 30, '0', 1, 'checkbox'), |
1253 | +(47, 'SHOW_DISPLAY_AS_VNCLINK', '0', 'text', 'Turn the display name in display management into a VNC link using the IP address last collected. The %s is replaced with the IP address. Leave blank to disable.', NULL, 'displays', '', 'Display a VNC Link?', '', 30, '', 1, 'string'), |
1254 | (48, 'SHOW_DISPLAY_AS_VNC_TGT', '_top', 'text', 'If the display name is shown as a link in display management, what target should the link have? Set _top to open the link in the same window or _blank to open in a new window.', NULL, 'displays', 1, 'Open VNC Link in new window?', '', 40, '_top', 1, 'string'), |
1255 | (49, 'MAINTENANCE_ALWAYS_ALERT', 'Off', 'dropdown', 'Should Xibo send an email if a display is in an error state every time the maintenance script runs?', 'On|Off', 'maintenance', 1, 'Send repeat Display Timeouts', '', 80, 'Off', 1, 'word'), |
1256 | (50, 'SCHEDULE_LOOKAHEAD', 'On', 'dropdown', 'Should Xibo send future schedule information to clients?', 'On|Off', 'general', 0, 'Send Schedule in advance?', '', 40, 'On', 1, 'word'), |
1257 | @@ -263,7 +263,7 @@ |
1258 | (71, 'PROXY_HOST', '', 'text', 'The Proxy URL', NULL, 'network', 1, 'Proxy URL', '', 10, '', 1, 'string'), |
1259 | (72, 'PROXY_PORT', '0', 'number', 'The Proxy Port', NULL, 'network', 1, 'Proxy Port', '', 20, '0', 1, 'int'), |
1260 | (73, 'PROXY_AUTH', '', 'text', 'The Authentication information for this proxy. username:password', NULL, 'network', 1, 'Proxy Credentials', '', 30, '', 1, 'string'), |
1261 | -(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'), |
1262 | +(74, 'DATE_FORMAT', 'Y-m-d H:i', 'text', 'The Date Format to use when displaying dates in the CMS.', NULL , 'regional', '1', 'Date Format', 'required', 30, 'Y-m-d', '1', 'string'), |
1263 | (75, 'DETECT_LANGUAGE', '1', 'checkbox', 'Detect the browser language?', NULL , 'regional', '1', 'Detect Language', '', 40, '1', 1, 'checkbox'), |
1264 | (76, 'DEFAULTS_IMPORTED', '0', 'text', 'Has the default layout been imported?', NULL, 'general', 0, 'Defaults Imported?', 'required', 100, '0', 0, 'checkbox'), |
1265 | (77, 'FORCE_HTTPS', '0', 'checkbox', 'Force the portal into HTTPS?', NULL, 'network', 1, 'Force HTTPS?', '', 70, '0', 1, 'checkbox'), |
1266 | |
1267 | === modified file 'server/install/master/structure.sql' |
1268 | --- server/install/master/structure.sql 2014-11-12 17:20:55 +0000 |
1269 | +++ server/install/master/structure.sql 2015-01-09 11:27:10 +0000 |
1270 | @@ -5,7 +5,7 @@ |
1271 | `Month` int(11) NOT NULL, |
1272 | `Size` bigint(20) NOT NULL, |
1273 | PRIMARY KEY (`DisplayID`, `Type`, `Month`) |
1274 | -) ENGINE=InnoDB DEFAULT CHARSET=latin1; |
1275 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
1276 | |
1277 | CREATE TABLE IF NOT EXISTS `blacklist` ( |
1278 | `BlackListID` int(11) NOT NULL AUTO_INCREMENT, |
1279 | @@ -111,7 +111,7 @@ |
1280 | `UserID` int(11) NOT NULL, |
1281 | PRIMARY KEY (`FileID`), |
1282 | KEY `UserID` (`UserID`) |
1283 | -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; |
1284 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; |
1285 | |
1286 | CREATE TABLE IF NOT EXISTS `group` ( |
1287 | `groupID` int(11) NOT NULL AUTO_INCREMENT, |
1288 | @@ -543,7 +543,7 @@ |
1289 | CREATE TABLE IF NOT EXISTS `user` ( |
1290 | `UserID` int(11) NOT NULL AUTO_INCREMENT, |
1291 | `usertypeid` int(8) NOT NULL, |
1292 | - `UserName` varchar(15) NOT NULL, |
1293 | + `UserName` varchar(50) NOT NULL, |
1294 | `UserPassword` varchar(128) NOT NULL, |
1295 | `loggedin` tinyint(1) NOT NULL DEFAULT '0', |
1296 | `lastaccessed` datetime DEFAULT NULL, |
1297 | @@ -558,7 +558,7 @@ |
1298 | |
1299 | CREATE TABLE IF NOT EXISTS `usertype` ( |
1300 | `usertypeid` int(8) NOT NULL, |
1301 | - `usertype` varchar(16) CHARACTER SET latin1 NOT NULL, |
1302 | + `usertype` varchar(16) CHARACTER SET utf8 NOT NULL, |
1303 | PRIMARY KEY (`usertypeid`) |
1304 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
1305 | |
1306 | @@ -627,7 +627,7 @@ |
1307 | `bandwidthtypeid` int(11) NOT NULL AUTO_INCREMENT, |
1308 | `name` varchar(25) NOT NULL, |
1309 | PRIMARY KEY (`bandwidthtypeid`) |
1310 | -) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ; |
1311 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=12 ; |
1312 | |
1313 | CREATE TABLE IF NOT EXISTS `tag` ( |
1314 | `tagId` int(11) NOT NULL AUTO_INCREMENT, |
1315 | @@ -640,14 +640,14 @@ |
1316 | `tagId` int(11) NOT NULL, |
1317 | `layoutId` int(11) NOT NULL, |
1318 | PRIMARY KEY (`lkTagLayoutId`) |
1319 | -) ENGINE=InnoDB DEFAULT CHARSET=utf32 AUTO_INCREMENT=1 ; |
1320 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; |
1321 | |
1322 | CREATE TABLE IF NOT EXISTS `lktagmedia` ( |
1323 | `lkTagMediaId` int(11) NOT NULL AUTO_INCREMENT, |
1324 | `tagId` int(11) NOT NULL, |
1325 | `mediaId` int(11) NOT NULL, |
1326 | PRIMARY KEY (`lkTagMediaId`) |
1327 | -) ENGINE=InnoDB DEFAULT CHARSET=utf16 AUTO_INCREMENT=1 ; |
1328 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; |
1329 | |
1330 | -- |
1331 | -- Constraints for dumped tables |
1332 | |
1333 | === modified file 'server/lib/app/kit.class.php' |
1334 | --- server/lib/app/kit.class.php 2014-11-25 11:09:21 +0000 |
1335 | +++ server/lib/app/kit.class.php 2015-01-09 11:27:10 +0000 |
1336 | @@ -689,5 +689,63 @@ |
1337 | if (Config::GetSetting('ISSUE_STS', 0) == 1) |
1338 | header("strict-transport-security: max-age=" . Config::GetSetting('STS_TTL', 600)); |
1339 | } |
1340 | + |
1341 | + /** |
1342 | + * Json Encode, handling and logging errors |
1343 | + * http://stackoverflow.com/questions/10199017/how-to-solve-json-error-utf8-error-in-php-json-decode |
1344 | + * @param mixed $mixed The item to encode |
1345 | + * @return mixed The Encoded Item |
1346 | + */ |
1347 | + public static function jsonEncode($mixed) |
1348 | + { |
1349 | + if (version_compare(PHP_VERSION, '5.4.0') >= 0) { |
1350 | + $encoded = json_encode($mixed, JSON_PRETTY_PRINT); |
1351 | + } |
1352 | + else { |
1353 | + $encoded = json_encode($mixed); |
1354 | + } |
1355 | + |
1356 | + switch (json_last_error()) { |
1357 | + case JSON_ERROR_NONE: |
1358 | + return $encoded; |
1359 | + case JSON_ERROR_DEPTH: |
1360 | + Debug::Audit('Maximum stack depth exceeded'); |
1361 | + return false; |
1362 | + case JSON_ERROR_STATE_MISMATCH: |
1363 | + Debug::Audit('Underflow or the modes mismatch'); |
1364 | + return false; |
1365 | + case JSON_ERROR_CTRL_CHAR: |
1366 | + Debug::Audit('Unexpected control character found'); |
1367 | + return false; |
1368 | + case JSON_ERROR_SYNTAX: |
1369 | + Debug::Audit('Syntax error, malformed JSON'); |
1370 | + return false; |
1371 | + case JSON_ERROR_UTF8: |
1372 | + $clean = Kit::utf8ize($mixed); |
1373 | + return Kit::jsonEncode($clean); |
1374 | + default: |
1375 | + Debug::Audit('Unknown error'); |
1376 | + return false; |
1377 | + } |
1378 | + } |
1379 | + |
1380 | + /** |
1381 | + * Utf8ize a string or array |
1382 | + * http://stackoverflow.com/questions/10199017/how-to-solve-json-error-utf8-error-in-php-json-decode |
1383 | + * @param mixed $mixed The item to uft8ize |
1384 | + * @return mixed The utf8ized item |
1385 | + */ |
1386 | + public static function utf8ize($mixed) |
1387 | + { |
1388 | + if (is_array($mixed)) { |
1389 | + foreach ($mixed as $key => $value) { |
1390 | + $mixed[$key] = Kit::utf8ize($value); |
1391 | + } |
1392 | + } |
1393 | + else if (is_string ($mixed)) { |
1394 | + return utf8_encode($mixed); |
1395 | + } |
1396 | + return $mixed; |
1397 | + } |
1398 | } |
1399 | ?> |
1400 | |
1401 | === modified file 'server/lib/app/thememanager.class.php' |
1402 | --- server/lib/app/thememanager.class.php 2014-10-15 16:22:31 +0000 |
1403 | +++ server/lib/app/thememanager.class.php 2015-01-09 11:27:10 +0000 |
1404 | @@ -281,13 +281,13 @@ |
1405 | return Theme::GetInstance()->name; |
1406 | } |
1407 | |
1408 | - public static function GetConfig($settingName) { |
1409 | + public static function GetConfig($settingName, $default = null) { |
1410 | $theme = Theme::GetInstance(); |
1411 | |
1412 | if (isset($theme->config[$settingName])) |
1413 | return $theme->config[$settingName]; |
1414 | else |
1415 | - return ''; |
1416 | + return $default; |
1417 | } |
1418 | |
1419 | /** |
1420 | |
1421 | === modified file 'server/lib/data/dataset.data.class.php' |
1422 | --- server/lib/data/dataset.data.class.php 2014-11-13 17:44:55 +0000 |
1423 | +++ server/lib/data/dataset.data.class.php 2015-01-09 11:27:10 +0000 |
1424 | @@ -22,6 +22,30 @@ |
1425 | |
1426 | class DataSet extends Data |
1427 | { |
1428 | + public function hasData($dataSetId) |
1429 | + { |
1430 | + try { |
1431 | + $dbh = PDOConnect::init(); |
1432 | + |
1433 | + // First check to see if we have any data |
1434 | + $sth = $dbh->prepare('SELECT * FROM `datasetdata` INNER JOIN `datasetcolumn` ON datasetcolumn.DataSetColumnID = datasetdata.DataSetColumnID WHERE datasetcolumn.DataSetID = :datasetid'); |
1435 | + $sth->execute(array( |
1436 | + 'datasetid' => $dataSetId |
1437 | + )); |
1438 | + |
1439 | + return ($sth->fetch()); |
1440 | + } |
1441 | + catch (Exception $e) { |
1442 | + |
1443 | + Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__); |
1444 | + |
1445 | + if (!$this->IsError()) |
1446 | + $this->SetError(1, __('Unknown Error')); |
1447 | + |
1448 | + return false; |
1449 | + } |
1450 | + } |
1451 | + |
1452 | /** |
1453 | * Add a data set |
1454 | * @param <type> $dataSet |
1455 | @@ -137,22 +161,15 @@ |
1456 | try { |
1457 | $dbh = PDOConnect::init(); |
1458 | |
1459 | - // First check to see if we have any data |
1460 | - $sth = $dbh->prepare('SELECT * FROM `datasetdata` INNER JOIN `datasetcolumn` ON datasetcolumn.DataSetColumnID = datasetdata.DataSetColumnID WHERE datasetcolumn.DataSetID = :datasetid'); |
1461 | - $sth->execute(array( |
1462 | - 'datasetid' => $dataSetId |
1463 | - )); |
1464 | + // Delete the Data |
1465 | + $data = new DataSetData(); |
1466 | + $data->DeleteAll($dataSetId); |
1467 | |
1468 | - if ($row = $sth->fetch()) |
1469 | - return $this->SetError(25005, __('There is data assigned to this data set, cannot delete.')); |
1470 | - |
1471 | // Delete security |
1472 | - Kit::ClassLoader('datasetgroupsecurity'); |
1473 | $security = new DataSetGroupSecurity($this->db); |
1474 | $security->UnlinkAll($dataSetId); |
1475 | |
1476 | // Delete columns |
1477 | - Kit::ClassLoader('datasetcolumn'); |
1478 | $dataSetObject = new DataSetColumn($this->db); |
1479 | if (!$dataSetObject->DeleteAll($dataSetId)) |
1480 | return $this->SetError(25005, __('Cannot delete dataset, columns could not be deleted.')); |
1481 | |
1482 | === modified file 'server/lib/data/datasetdata.data.class.php' |
1483 | --- server/lib/data/datasetdata.data.class.php 2014-10-15 15:13:38 +0000 |
1484 | +++ server/lib/data/datasetdata.data.class.php 2015-01-09 11:27:10 +0000 |
1485 | @@ -24,11 +24,11 @@ |
1486 | { |
1487 | private $updateWatermark; |
1488 | |
1489 | - public function __construct(database $db) { |
1490 | + public function __construct() { |
1491 | |
1492 | $this->updateWatermark = true; |
1493 | |
1494 | - parent::__construct($db); |
1495 | + parent::__construct(); |
1496 | } |
1497 | |
1498 | /** |
1499 | |
1500 | === modified file 'server/lib/data/displayprofile.data.class.php' |
1501 | --- server/lib/data/displayprofile.data.class.php 2014-11-14 15:43:58 +0000 |
1502 | +++ server/lib/data/displayprofile.data.class.php 2015-01-09 11:27:10 +0000 |
1503 | @@ -170,8 +170,8 @@ |
1504 | |
1505 | $count = $sth->fetchColumn(0) + (int)$this->isDefault; |
1506 | |
1507 | - if ($count != 1) |
1508 | - $this->ThrowError(__('Must have 1 default per display type.')); |
1509 | + if ($count > 1) |
1510 | + $this->ThrowError(__('Only 1 default per display type is allowed.')); |
1511 | |
1512 | return true; |
1513 | } |
1514 | |
1515 | === modified file 'server/lib/data/layout.data.class.php' |
1516 | --- server/lib/data/layout.data.class.php 2014-11-24 15:49:49 +0000 |
1517 | +++ server/lib/data/layout.data.class.php 2015-01-09 11:27:10 +0000 |
1518 | @@ -1682,9 +1682,12 @@ |
1519 | $this->ThrowError(__('Layout not found.')); |
1520 | |
1521 | // Open a ZIP file with the same name as the layout |
1522 | + File::EnsureLibraryExists(); |
1523 | $zip = new ZipArchive(); |
1524 | $fileName = $libraryPath . 'temp/export_' . Kit::ValidateParam($row['layout'], _FILENAME) . '.zip'; |
1525 | - $zip->open($fileName, ZIPARCHIVE::OVERWRITE); |
1526 | + $result = $zip->open($fileName, ZIPARCHIVE::OVERWRITE); |
1527 | + if ($result !== true) |
1528 | + $this->ThrowError(__('Can\'t create ZIP. Error Code: ' . $result)); |
1529 | |
1530 | // Add layout information to the ZIP |
1531 | $layout = array( |
1532 | @@ -1942,6 +1945,9 @@ |
1533 | 'mediaId' => $newMediaId, |
1534 | 'layoutId' => $layoutId |
1535 | )); |
1536 | + |
1537 | + // Link |
1538 | + $this->AddLk($layoutId, 'background', $newMediaId); |
1539 | } |
1540 | catch (Exception $e) { |
1541 | |
1542 | @@ -2020,7 +2026,7 @@ |
1543 | Debug::Audit('Found file: ' . $file); |
1544 | |
1545 | if (stripos($file, '.zip')) |
1546 | - $this->Import($folder . DIRECTORY_SEPARATOR . $file, NULL, 1, false, true, true, false); |
1547 | + $this->Import($folder . DIRECTORY_SEPARATOR . $file, NULL, 1, false, false, true, false); |
1548 | } |
1549 | } |
1550 | } |
1551 | |
1552 | === modified file 'server/lib/data/media.data.class.php' |
1553 | --- server/lib/data/media.data.class.php 2014-11-23 13:37:49 +0000 |
1554 | +++ server/lib/data/media.data.class.php 2015-01-09 11:27:10 +0000 |
1555 | @@ -170,9 +170,6 @@ |
1556 | |
1557 | Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__); |
1558 | |
1559 | - if (!$this->IsError()) |
1560 | - $this->SetError(1, __('Unknown Error')); |
1561 | - |
1562 | return false; |
1563 | } |
1564 | } |
1565 | @@ -832,8 +829,6 @@ |
1566 | */ |
1567 | public function addModuleFileFromUrl($url, $name, $expires, $moduleSystemFile = false, $force = false) |
1568 | { |
1569 | - Debug::Audit('Adding: ' . $url . ' with Name: ' . $name . '. Expiry: ' . date('Y-m-d h:i:s', $expires)); |
1570 | - |
1571 | // See if we already have it |
1572 | // It doesn't matter that we might have already done this, its cached. |
1573 | $media = $this->moduleFileExists($name); |
1574 | @@ -841,7 +836,7 @@ |
1575 | //Debug::Audit('Module File: ' . var_export($media, true)); |
1576 | |
1577 | if ($media === false || $force) { |
1578 | - Debug::Audit('Media not valid, forcing update.'); |
1579 | + Debug::Audit('Adding: ' . $url . ' with Name: ' . $name . '. Expiry: ' . date('Y-m-d h:i:s', $expires)); |
1580 | |
1581 | $fileName = Config::GetSetting('LIBRARY_LOCATION') . 'temp' . DIRECTORY_SEPARATOR . $name; |
1582 | |
1583 | |
1584 | === modified file 'server/lib/data/nonce.data.class.php' |
1585 | --- server/lib/data/nonce.data.class.php 2014-08-22 16:53:58 +0000 |
1586 | +++ server/lib/data/nonce.data.class.php 2015-01-09 11:27:10 +0000 |
1587 | @@ -132,6 +132,17 @@ |
1588 | $params['displayId'] = $displayId; |
1589 | break; |
1590 | |
1591 | + case 'oldfile': |
1592 | + if ($this->validateFileStatement == NULL) { |
1593 | + $this->validateFileStatement = $dbh->prepare(' |
1594 | + SELECT nonceId, nonce, expiry, lastUsed FROM `xmdsnonce` INNER JOIN `media` ON media.mediaid = xmdsnonce.fileId WHERE displayId = :displayId AND media.storedAs = :fileId'); |
1595 | + } |
1596 | + |
1597 | + $sth = $this->validateFileStatement; |
1598 | + $params['fileId'] = $fileId; |
1599 | + $params['displayId'] = $displayId; |
1600 | + break; |
1601 | + |
1602 | case 'layout': |
1603 | if ($this->validateLayoutStatement == NULL) { |
1604 | $this->validateLayoutStatement = $dbh->prepare(' |
1605 | |
1606 | === modified file 'server/lib/data/userdata.data.class.php' |
1607 | --- server/lib/data/userdata.data.class.php 2014-08-07 15:47:19 +0000 |
1608 | +++ server/lib/data/userdata.data.class.php 2015-01-09 11:27:10 +0000 |
1609 | @@ -35,6 +35,91 @@ |
1610 | class Userdata extends Data |
1611 | { |
1612 | public $userId; |
1613 | + public $userName; |
1614 | + public $userTypeId; |
1615 | + public $loggedIn; |
1616 | + public $email; |
1617 | + public $homePage; |
1618 | + public $lastAccessed; |
1619 | + public $newUserWizard; |
1620 | + public $retired; |
1621 | + |
1622 | + public static function entries($sortOrder = array(), $filterBy = array()) |
1623 | + { |
1624 | + $entries = array(); |
1625 | + |
1626 | + try { |
1627 | + $dbh = PDOConnect::init(); |
1628 | + |
1629 | + $params = array(); |
1630 | + $SQL = 'SELECT userId, userName, userTypeId, loggedIn, email, homePage, lastAccessed, newUserWizard, retired '; |
1631 | + $SQL .= ' FROM `user` '; |
1632 | + $SQL .= ' WHERE 1 = 1 '; |
1633 | + |
1634 | + // User Id Provided? |
1635 | + if (Kit::GetParam('userId', $filterBy, _INT) != 0) { |
1636 | + $SQL .= " AND user.userId = :userId "; |
1637 | + $params['userId'] = Kit::GetParam('userId', $filterBy, _INT); |
1638 | + } |
1639 | + |
1640 | + // User Type Provided |
1641 | + if (Kit::GetParam('userTypeId', $filterBy, _INT) != 0) { |
1642 | + $SQL .= " AND user.userTypeId = :userTypeId "; |
1643 | + $params['userTypeId'] = Kit::GetParam('userTypeId', $filterBy, _INT); |
1644 | + } |
1645 | + |
1646 | + // User Name Provided |
1647 | + if (Kit::GetParam('userName', $filterBy, _STRING) != 0) { |
1648 | + $SQL .= " AND user.userName LIKE :userName "; |
1649 | + $params['userName'] = '%' . Kit::GetParam('userName', $filterBy, _STRING) . '%'; |
1650 | + } |
1651 | + |
1652 | + // Groups Provided |
1653 | + $groups = Kit::GetParam('groupIds', $filterBy, _ARRAY_INT); |
1654 | + Debug::Audit(var_export($groups, true)); |
1655 | + if (count($groups) > 0) { |
1656 | + $SQL .= " AND user.groupIds IN (" . implode($groups, ',') . ") "; |
1657 | + } |
1658 | + |
1659 | + // Retired users? |
1660 | + if (Kit::GetParam('retired', $filterBy, _INT) != -1) { |
1661 | + $SQL .= " AND user.retired = :retired "; |
1662 | + $params['retired'] = Kit::GetParam('retired', $filterBy, _INT); |
1663 | + } |
1664 | + |
1665 | + // Sorting? |
1666 | + if (is_array($sortOrder)) |
1667 | + $SQL .= 'ORDER BY ' . implode(',', $sortOrder); |
1668 | + |
1669 | + //Debug::Audit(sprintf('Retrieving list of users with SQL: %s. Params: %s', $SQL, var_export($params, true))); |
1670 | + |
1671 | + $sth = $dbh->prepare($SQL); |
1672 | + $sth->execute($params); |
1673 | + |
1674 | + foreach ($sth->fetchAll() as $row) { |
1675 | + $user = new Userdata(); |
1676 | + $user->userId = Kit::ValidateParam($row['userId'], _INT); |
1677 | + $user->userName = Kit::ValidateParam($row['userName'], _STRING); |
1678 | + $user->userTypeId = Kit::ValidateParam($row['userTypeId'], _INT); |
1679 | + $user->loggedIn = Kit::ValidateParam($row['loggedIn'], _INT); |
1680 | + $user->email = Kit::ValidateParam($row['email'], _STRING); |
1681 | + $user->homePage = Kit::ValidateParam($row['homePage'], _STRING); |
1682 | + $user->lastAccessed = Kit::ValidateParam($row['lastAccessed'], _INT); |
1683 | + $user->newUserWizard = Kit::ValidateParam($row['newUserWizard'], _INT); |
1684 | + $user->retired = Kit::ValidateParam($row['retired'], _INT); |
1685 | + |
1686 | + $entries[] = $user; |
1687 | + } |
1688 | + |
1689 | + return $entries; |
1690 | + } |
1691 | + catch (Exception $e) { |
1692 | + |
1693 | + Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__); |
1694 | + |
1695 | + return false; |
1696 | + } |
1697 | + } |
1698 | |
1699 | public function Delete() { |
1700 | if (!isset($this->userId) || $this->userId == 0) |
1701 | |
1702 | === modified file 'server/lib/include.php' |
1703 | --- server/lib/include.php 2014-11-25 11:09:21 +0000 |
1704 | +++ server/lib/include.php 2015-01-09 11:27:10 +0000 |
1705 | @@ -20,7 +20,7 @@ |
1706 | */ |
1707 | defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser."); |
1708 | |
1709 | -define('WEBSITE_VERSION', 82); |
1710 | +define('WEBSITE_VERSION', 83); |
1711 | |
1712 | // No errors reported until we read the settings from the DB |
1713 | error_reporting(0); |
1714 | |
1715 | === modified file 'server/lib/modules/module.class.php' |
1716 | --- server/lib/modules/module.class.php 2014-11-24 15:49:49 +0000 |
1717 | +++ server/lib/modules/module.class.php 2015-01-09 11:27:10 +0000 |
1718 | @@ -30,7 +30,7 @@ |
1719 | public $auth; |
1720 | |
1721 | // Module Information |
1722 | - private $module_id; |
1723 | + protected $module_id; |
1724 | protected $render_as; |
1725 | public $displayType; |
1726 | protected $type; |
1727 | @@ -110,12 +110,12 @@ |
1728 | |
1729 | // Members used by forms (routed through the CMS) |
1730 | $this->showRegionOptions = Kit::GetParam('showRegionOptions', _REQUEST, _INT, 1); |
1731 | + |
1732 | + // Log |
1733 | + Debug::LogEntry('audit', 'Module created with MediaID: ' . $mediaid . ' LayoutID: ' . $layoutid . ' and RegionID: ' . $regionid); |
1734 | |
1735 | // Determine which type this module is |
1736 | - if (!$this->SetModuleInformation()) |
1737 | - return false; |
1738 | - |
1739 | - Debug::LogEntry('audit', 'Module created with MediaID: ' . $mediaid . ' LayoutID: ' . $layoutid . ' and RegionID: ' . $regionid); |
1740 | + $this->SetModuleInformation(); |
1741 | |
1742 | // Either the information from the region - or some blanks |
1743 | return ($this->SetMediaInformation($this->layoutid, $this->regionid, $this->mediaid, $this->lkid)); |
1744 | @@ -138,8 +138,9 @@ |
1745 | 'type' => $this->type |
1746 | )); |
1747 | |
1748 | - $row = $sth->fetch(); |
1749 | - |
1750 | + if (!$row = $sth->fetch()) |
1751 | + return; |
1752 | + |
1753 | $this->module_id = Kit::ValidateParam($row['ModuleID'], _INT); |
1754 | $this->schemaVersion = Kit::ValidateParam($row['SchemaVersion'], _INT); |
1755 | $this->regionSpecific = Kit::ValidateParam($row['RegionSpecific'], _INT); |
1756 | @@ -172,13 +173,40 @@ |
1757 | catch (Exception $e) { |
1758 | |
1759 | Debug::LogEntry('error', $e->getMessage()); |
1760 | - |
1761 | - return $this->SetError(__('Unable to create Module [No registered modules of this type] - please refer to the Module Documentation.')); |
1762 | + |
1763 | + if (!$this->IsError()) |
1764 | + $this->SetError(__('Unable to create Module [No registered modules of this type] - please refer to the Module Documentation.')); |
1765 | + |
1766 | + throw $e; |
1767 | } |
1768 | |
1769 | return true; |
1770 | } |
1771 | |
1772 | + protected final function saveSettings() |
1773 | + { |
1774 | + // Save |
1775 | + try { |
1776 | + $dbh = PDOConnect::init(); |
1777 | + |
1778 | + $sth = $dbh->prepare('UPDATE module SET settings = :settings WHERE moduleid = :moduleId'); |
1779 | + Debug::Audit(var_export(array( |
1780 | + 'moduleId' => $this->module_id, |
1781 | + 'settings' => json_encode($this->settings) |
1782 | + ), true)); |
1783 | + $sth->execute(array( |
1784 | + 'moduleId' => $this->module_id, |
1785 | + 'settings' => json_encode($this->settings) |
1786 | + )); |
1787 | + } |
1788 | + catch (Exception $e) { |
1789 | + |
1790 | + Debug::LogEntry('error', $e->getMessage()); |
1791 | + |
1792 | + trigger_error(__('Cannot Save Settings'), E_USER_ERROR); |
1793 | + } |
1794 | + } |
1795 | + |
1796 | /** |
1797 | * Gets the information about this Media on this region on this layout |
1798 | * @return |
1799 | @@ -194,6 +222,9 @@ |
1800 | |
1801 | if ($this->mediaid != '' && $this->regionid != '' && $this->layoutid != '') |
1802 | { |
1803 | + if ($this->module_id == 0) |
1804 | + $this->ThrowError(__('Module "' . $this->type . '" does not exist or is not installed. Please visit the module administration page or contact your administrator')); |
1805 | + |
1806 | // Existing media that is assigned to a layout |
1807 | $this->existingMedia = true; |
1808 | $this->assignedMedia = true; |
1809 | @@ -1362,8 +1393,12 @@ |
1810 | * @param <type> $width |
1811 | * @param <type> $height |
1812 | */ |
1813 | - public function Preview($width, $height) { |
1814 | - return '<div style="text-align:center;"><img alt="' . $this->type . ' thumbnail" src="theme/default/img/forms/' . $this->type . '.gif" /></div>'; |
1815 | + public function Preview($width, $height, $scaleOverride = 0) |
1816 | + { |
1817 | + if ($this->previewEnabled == 0) |
1818 | + return '<div style="text-align:center;"><img alt="' . $this->type . ' thumbnail" src="theme/default/img/forms/' . $this->type . '.gif" /></div>'; |
1819 | + |
1820 | + return $this->PreviewAsClient($width, $height, $scaleOverride); |
1821 | } |
1822 | |
1823 | /** |
1824 | @@ -1997,7 +2032,7 @@ |
1825 | |
1826 | protected function ThrowError($errNo, $errMessage = '') { |
1827 | $this->SetError($errNo, $errMessage); |
1828 | - throw new Exception(sprintf('Module Class: Error Number [%d] Error Message [%s]', $errNo, $errMessage)); |
1829 | + throw new Exception(sprintf('%s [%d]', $this->GetErrorMessage(), $this->GetErrorNumber())); |
1830 | } |
1831 | |
1832 | public function IsValid() { |
1833 | |
1834 | === modified file 'server/lib/pages/admin.class.php' |
1835 | --- server/lib/pages/admin.class.php 2014-11-25 11:09:21 +0000 |
1836 | +++ server/lib/pages/admin.class.php 2015-01-09 11:27:10 +0000 |
1837 | @@ -283,7 +283,7 @@ |
1838 | public function SetMaxDebug() |
1839 | { |
1840 | $response = new ResponseManager(); |
1841 | - $setting = new Setting($db); |
1842 | + $setting = new Setting(); |
1843 | |
1844 | if (!$setting->Edit('audit', 'audit')) |
1845 | trigger_error(__('Cannot set audit to On')); |
1846 | @@ -298,9 +298,8 @@ |
1847 | */ |
1848 | public function SetMinDebug() |
1849 | { |
1850 | - $db =& $this->db; |
1851 | $response = new ResponseManager(); |
1852 | - $setting = new Setting($db); |
1853 | + $setting = new Setting(); |
1854 | |
1855 | if (!$setting->Edit('audit', 'error')) |
1856 | trigger_error(__('Cannot set audit to Off'), E_USER_ERROR); |
1857 | @@ -315,9 +314,8 @@ |
1858 | */ |
1859 | public function SetServerProductionMode() |
1860 | { |
1861 | - $db =& $this->db; |
1862 | $response = new ResponseManager(); |
1863 | - $setting = new Setting($db); |
1864 | + $setting = new Setting(); |
1865 | |
1866 | if (!$setting->Edit('SERVER_MODE', 'Production')) |
1867 | { |
1868 | @@ -334,9 +332,8 @@ |
1869 | */ |
1870 | public function SetServerTestMode() |
1871 | { |
1872 | - $db =& $this->db; |
1873 | $response = new ResponseManager(); |
1874 | - $setting = new Setting($db); |
1875 | + $setting = new Setting(); |
1876 | |
1877 | if (!$setting->Edit('SERVER_MODE', 'Test')) |
1878 | { |
1879 | |
1880 | === modified file 'server/lib/pages/content.class.php' |
1881 | --- server/lib/pages/content.class.php 2014-10-31 12:25:45 +0000 |
1882 | +++ server/lib/pages/content.class.php 2015-01-09 11:27:10 +0000 |
1883 | @@ -57,54 +57,59 @@ |
1884 | Theme::Set('form_meta', '<input type="hidden" name="p" value="content"><input type="hidden" name="q" value="LibraryGrid">'); |
1885 | |
1886 | $formFields = array(); |
1887 | - $formFields[] = FormManager::AddText('filter_name', __('Name'), $filter_name, NULL, 'n'); |
1888 | - $formFields[] = FormManager::AddCombo( |
1889 | - 'filter_owner', |
1890 | - __('Owner'), |
1891 | - $filter_owner, |
1892 | - $db->GetArray("SELECT 0 AS UserID, 'All' AS UserName UNION SELECT DISTINCT user.UserID, user.UserName FROM `media` INNER JOIN `user` ON media.UserID = user.UserID "), |
1893 | - 'UserID', |
1894 | - 'UserName', |
1895 | - NULL, |
1896 | - 'o'); |
1897 | - |
1898 | - $types = $db->GetArray("SELECT Module AS moduleid, Name AS module FROM `module` WHERE RegionSpecific = 0 AND Enabled = 1 ORDER BY 2"); |
1899 | - array_unshift($types, array('moduleid' => '', 'module' => 'All')); |
1900 | - $formFields[] = FormManager::AddCombo( |
1901 | - 'filter_type', |
1902 | - __('Type'), |
1903 | - $filter_type, |
1904 | - $types, |
1905 | - 'moduleid', |
1906 | - 'module', |
1907 | - NULL, |
1908 | - 'y'); |
1909 | - |
1910 | - $formFields[] = FormManager::AddCombo( |
1911 | - 'filter_retired', |
1912 | - __('Retired'), |
1913 | - $filter_retired, |
1914 | - array(array('retiredid' => 1, 'retired' => 'Yes'), array('retiredid' => 0, 'retired' => 'No')), |
1915 | - 'retiredid', |
1916 | - 'retired', |
1917 | - NULL, |
1918 | - 'r'); |
1919 | - |
1920 | - $formFields[] = FormManager::AddCheckbox('filter_duration_in_seconds', __('Duration in Seconds'), |
1921 | - $filter_duration_in_seconds, NULL, |
1922 | - 's'); |
1923 | - |
1924 | - $formFields[] = FormManager::AddCheckbox('showTags', __('Show Tags'), |
1925 | - $showTags, NULL, |
1926 | - 't'); |
1927 | - |
1928 | - $formFields[] = FormManager::AddCheckbox('filter_showThumbnail', __('Show Thumbnails'), |
1929 | - $filter_showThumbnail, NULL, |
1930 | - 't'); |
1931 | - |
1932 | - $formFields[] = FormManager::AddCheckbox('XiboFilterPinned', __('Keep Open'), |
1933 | - $filter_pinned, NULL, |
1934 | - 'k'); |
1935 | + $formFields[] = FormManager::AddText('filter_name', __('Name'), $filter_name, NULL, 'n'); |
1936 | + |
1937 | + // Users we have permission to see |
1938 | + $users = $this->user->userList(); |
1939 | + array_unshift($users, array('userid' => '', 'username' => 'All')); |
1940 | + |
1941 | + $formFields[] = FormManager::AddCombo( |
1942 | + 'filter_owner', |
1943 | + __('Owner'), |
1944 | + $filter_owner, |
1945 | + $users, |
1946 | + 'userid', |
1947 | + 'username', |
1948 | + NULL, |
1949 | + 'o'); |
1950 | + |
1951 | + $types = $db->GetArray("SELECT Module AS moduleid, Name AS module FROM `module` WHERE RegionSpecific = 0 AND Enabled = 1 ORDER BY 2"); |
1952 | + array_unshift($types, array('moduleid' => '', 'module' => 'All')); |
1953 | + $formFields[] = FormManager::AddCombo( |
1954 | + 'filter_type', |
1955 | + __('Type'), |
1956 | + $filter_type, |
1957 | + $types, |
1958 | + 'moduleid', |
1959 | + 'module', |
1960 | + NULL, |
1961 | + 'y'); |
1962 | + |
1963 | + $formFields[] = FormManager::AddCombo( |
1964 | + 'filter_retired', |
1965 | + __('Retired'), |
1966 | + $filter_retired, |
1967 | + array(array('retiredid' => 1, 'retired' => 'Yes'), array('retiredid' => 0, 'retired' => 'No')), |
1968 | + 'retiredid', |
1969 | + 'retired', |
1970 | + NULL, |
1971 | + 'r'); |
1972 | + |
1973 | + $formFields[] = FormManager::AddCheckbox('filter_duration_in_seconds', __('Duration in Seconds'), |
1974 | + $filter_duration_in_seconds, NULL, |
1975 | + 's'); |
1976 | + |
1977 | + $formFields[] = FormManager::AddCheckbox('showTags', __('Show Tags'), |
1978 | + $showTags, NULL, |
1979 | + 't'); |
1980 | + |
1981 | + $formFields[] = FormManager::AddCheckbox('filter_showThumbnail', __('Show Thumbnails'), |
1982 | + $filter_showThumbnail, NULL, |
1983 | + 't'); |
1984 | + |
1985 | + $formFields[] = FormManager::AddCheckbox('XiboFilterPinned', __('Keep Open'), |
1986 | + $filter_pinned, NULL, |
1987 | + 'k'); |
1988 | |
1989 | // Call to render the template |
1990 | Theme::Set('header_text', __('Library')); |
1991 | |
1992 | === modified file 'server/lib/pages/dataset.class.php' |
1993 | --- server/lib/pages/dataset.class.php 2014-08-15 14:40:03 +0000 |
1994 | +++ server/lib/pages/dataset.class.php 2015-01-09 11:27:10 +0000 |
1995 | @@ -313,7 +313,12 @@ |
1996 | Theme::Set('form_action', 'index.php?p=dataset&q=DeleteDataSet'); |
1997 | Theme::Set('form_meta', '<input type="hidden" name="datasetid" value="' . $dataSetId . '" />'); |
1998 | |
1999 | - Theme::Set('form_fields', array(FormManager::AddMessage(__('Are you sure you want to delete?')))); |
2000 | + $formFields = array(); |
2001 | + $formFields[] = FormManager::AddMessage(__('Are you sure you want to delete?')); |
2002 | + $formFields[] = FormManager::AddCheckbox('deleteData', __('Delete any associated data?'), NULL, |
2003 | + __('Please tick the box if you would like to delete all the Data contained in this DataSet'), 'c'); |
2004 | + |
2005 | + Theme::Set('form_fields', $formFields); |
2006 | |
2007 | $response->SetFormRequestResponse(NULL, __('Delete this DataSet?'), '350px', '200px'); |
2008 | $response->AddButton(__('Help'), 'XiboHelpRender("' . HelpManager::Link('DataSet', 'Delete') . '")'); |
2009 | @@ -339,6 +344,11 @@ |
2010 | trigger_error(__('Access Denied')); |
2011 | |
2012 | $dataSetObject = new DataSet($db); |
2013 | + |
2014 | + if ($dataSetObject->hasData($dataSetId) && Kit::GetParam('deleteData', _POST, _CHECKBOX) == 0) |
2015 | + trigger_error(__('There is data assigned to this data set, cannot delete.'), E_USER_ERROR); |
2016 | + |
2017 | + // Proceed with the delete |
2018 | if (!$dataSetObject->Delete($dataSetId)) |
2019 | trigger_error($dataSetObject->GetErrorMessage(), E_USER_ERROR); |
2020 | |
2021 | |
2022 | === modified file 'server/lib/pages/display.class.php' |
2023 | --- server/lib/pages/display.class.php 2014-11-13 17:44:55 +0000 |
2024 | +++ server/lib/pages/display.class.php 2015-01-09 11:27:10 +0000 |
2025 | @@ -81,7 +81,7 @@ |
2026 | |
2027 | $formFields[] = FormManager::AddCombo( |
2028 | 'filter_showThumbnail', |
2029 | - __('Thumbnails'), |
2030 | + __('Screen Shot Thumbnails'), |
2031 | $filter_showThumbnail, |
2032 | array( |
2033 | array('key' => 0, 'value' => __('None')), |
2034 | @@ -374,8 +374,9 @@ |
2035 | |
2036 | $cols = array( |
2037 | array('name' => 'displayid', 'title' => __('ID')), |
2038 | + array('name' => 'displayWithLink', 'title' => __('Display')), |
2039 | + array('name' => 'status', 'title' => __('Status'), 'icons' => true), |
2040 | array('name' => 'licensed', 'title' => __('License'), 'icons' => true), |
2041 | - array('name' => 'displayWithLink', 'title' => __('Display')), |
2042 | array('name' => 'description', 'title' => __('Description'), 'hidden' => ($filter_showThumbnail == 1 || $filter_showThumbnail == 2)), |
2043 | array('name' => 'layout', 'title' => __('Default Layout'), 'hidden' => ($filter_showThumbnail == 1 || $filter_showThumbnail == 2)), |
2044 | array('name' => 'inc_schedule', 'title' => __('Interleave Default'), 'icons' => true, 'hidden' => ($filter_showThumbnail == 1 || $filter_showThumbnail == 2)), |
2045 | @@ -389,35 +390,38 @@ |
2046 | ); |
2047 | |
2048 | Theme::Set('table_cols', $cols); |
2049 | - Theme::Set('rowClass', 'mediainventorystatus'); |
2050 | + Theme::Set('rowClass', 'rowColor'); |
2051 | |
2052 | $rows = array(); |
2053 | |
2054 | - foreach($displays as $row) |
2055 | - { |
2056 | + foreach($displays as $row) { |
2057 | // VNC Template as display name? |
2058 | - if ($vncTemplate != '' && $row['clientaddress'] != '') |
2059 | - { |
2060 | + if ($vncTemplate != '' && $row['clientaddress'] != '') { |
2061 | if ($linkTarget == '') |
2062 | $linkTarget = '_top'; |
2063 | |
2064 | $row['displayWithLink'] = sprintf('<a href="' . $vncTemplate . '" title="VNC to ' . $row['display'] . '" target="' . $linkTarget . '">' . Theme::Prepare($row['display']) . '</a>', $row['clientaddress']); |
2065 | } |
2066 | + else { |
2067 | + $row['displayWithLink'] = $row['display']; |
2068 | + } |
2069 | |
2070 | // Format last accessed |
2071 | $row['lastaccessed'] = DateManager::getLocalDate($row['lastaccessed']); |
2072 | |
2073 | // Create some login lights |
2074 | - $row['mediainventorystatus'] = ($row['mediainventorystatus'] == 1) ? 'success' : (($row['mediainventorystatus'] == 2) ? 'danger' : 'warning'); |
2075 | + $row['rowColor'] = ($row['mediainventorystatus'] == 1) ? 'success' : (($row['mediainventorystatus'] == 2) ? 'danger' : 'warning'); |
2076 | + $row['status'] = ($row['mediainventorystatus'] == 1) ? 1 : (($row['mediainventorystatus'] == 2) ? 0 : -1); |
2077 | |
2078 | // Thumbnail |
2079 | $row['thumbnail'] = ''; |
2080 | - if ($filter_showThumbnail == 1 && file_exists(Config::GetSetting('LIBRARY_LOCATION') . 'screenshots/' . $row['displayid'] . '_screenshot.jpg')) { |
2081 | + // If we aren't logged in, and we are showThumbnail == 2, then show a circle |
2082 | + if ($filter_showThumbnail == 2 && $row['loggedin'] == 0) { |
2083 | + $row['thumbnail'] = '<i class="fa fa-times-circle"></i>'; |
2084 | + } |
2085 | + else if ($filter_showThumbnail <> 0 && file_exists(Config::GetSetting('LIBRARY_LOCATION') . 'screenshots/' . $row['displayid'] . '_screenshot.jpg')) { |
2086 | $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>'; |
2087 | } |
2088 | - else if ($filter_showThumbnail == 2) { |
2089 | - $row['thumbnail'] = '<i class="fa fa-times-circle"></i>'; |
2090 | - } |
2091 | |
2092 | // Edit and Delete buttons first |
2093 | if ($row['edit'] == 1) { |
2094 | @@ -710,6 +714,14 @@ |
2095 | if (!$document->loadXML($mediaInventoryXml)) |
2096 | trigger_error(__('Invalid Media Inventory'), E_USER_ERROR); |
2097 | |
2098 | + $cols = array( |
2099 | + array('name' => 'id', 'title' => __('ID')), |
2100 | + array('name' => 'type', 'title' => __('Type')), |
2101 | + array('name' => 'complete', 'title' => __('Complete')), |
2102 | + array('name' => 'last_checked', 'title' => __('Last Checked')) |
2103 | + ); |
2104 | + Theme::Set('table_cols', $cols); |
2105 | + |
2106 | // Need to parse the XML and return a set of rows |
2107 | $xpath = new DOMXPath($document); |
2108 | $fileNodes = $xpath->query("//file"); |
2109 | @@ -731,10 +743,7 @@ |
2110 | // Store the table rows |
2111 | Theme::Set('table_rows', $rows); |
2112 | |
2113 | - // Initialise the theme and capture the output |
2114 | - $output = Theme::RenderReturn('display_form_mediainventory'); |
2115 | - |
2116 | - $response->SetFormRequestResponse($output, __('Media Inventory'), '550px', '350px'); |
2117 | + $response->SetFormRequestResponse(Theme::RenderReturn('table_render'), __('Media Inventory'), '550px', '350px'); |
2118 | $response->AddButton(__('Help'), 'XiboHelpRender("' . HelpManager::Link('Display', 'MediaInventory') . '")'); |
2119 | $response->AddButton(__('Close'), 'XiboDialogClose()'); |
2120 | $response->Respond(); |
2121 | |
2122 | === modified file 'server/lib/pages/layout.class.php' |
2123 | --- server/lib/pages/layout.class.php 2014-11-12 17:20:55 +0000 |
2124 | +++ server/lib/pages/layout.class.php 2015-01-09 11:27:10 +0000 |
2125 | @@ -127,13 +127,18 @@ |
2126 | $formFields = array(); |
2127 | $formFields[] = FormManager::AddText('filter_layout', __('Name'), $layout, NULL, 'l'); |
2128 | $formFields[] = FormManager::AddText('filter_tags', __('Tags'), $tags, NULL, 't'); |
2129 | + |
2130 | + // Users we have permission to see |
2131 | + $users = $this->user->userList(); |
2132 | + array_unshift($users, array('userid' => '', 'username' => 'All')); |
2133 | + |
2134 | $formFields[] = FormManager::AddCombo( |
2135 | 'filter_userid', |
2136 | __('Owner'), |
2137 | $owner, |
2138 | - $db->GetArray("SELECT 0 AS UserID, 'All' AS UserName UNION SELECT DISTINCT user.UserID, user.UserName FROM `layout` INNER JOIN `user` ON layout.UserID = user.UserID "), |
2139 | - 'UserID', |
2140 | - 'UserName', |
2141 | + $users, |
2142 | + 'userid', |
2143 | + 'username', |
2144 | NULL, |
2145 | 'r'); |
2146 | $formFields[] = FormManager::AddCombo( |
2147 | |
2148 | === modified file 'server/lib/pages/log.class.php' |
2149 | --- server/lib/pages/log.class.php 2014-11-03 11:12:50 +0000 |
2150 | +++ server/lib/pages/log.class.php 2015-01-09 11:27:10 +0000 |
2151 | @@ -284,6 +284,8 @@ |
2152 | $output = Theme::RenderReturn('table_render'); |
2153 | |
2154 | $response->initialSortOrder = 2; |
2155 | + $response->dialogClass = 'modal-big'; |
2156 | + $response->dialogTitle = __('Recent Log Messages'); |
2157 | $response->pageSize = 10; |
2158 | $response->SetGridResponse($output); |
2159 | $response->Respond(); |
2160 | |
2161 | === modified file 'server/lib/pages/module.class.php' |
2162 | --- server/lib/pages/module.class.php 2014-11-17 15:15:42 +0000 |
2163 | +++ server/lib/pages/module.class.php 2015-01-09 11:27:10 +0000 |
2164 | @@ -82,36 +82,36 @@ |
2165 | Theme::Set('form_meta', '<input type="hidden" name="p" value="module"><input type="hidden" name="q" value="Grid">'); |
2166 | Theme::Set('pager', ResponseManager::Pager($id)); |
2167 | |
2168 | - // |
2169 | // Do we have any modules to install?! |
2170 | - // |
2171 | - // Get a list of matching files in the modules folder |
2172 | - $files = glob('modules/*.module.php'); |
2173 | - |
2174 | - // Get a list of all currently installed modules |
2175 | - try { |
2176 | - $dbh = PDOConnect::init(); |
2177 | - |
2178 | - $sth = $dbh->prepare("SELECT CONCAT('modules/', LOWER(Module), '.module.php') AS Module FROM `module`"); |
2179 | - $sth->execute(); |
2180 | - |
2181 | - $rows = $sth->fetchAll(); |
2182 | - $installed = array(); |
2183 | - |
2184 | - foreach($rows as $row) |
2185 | - $installed[] = $row['Module']; |
2186 | - } |
2187 | - catch (Exception $e) { |
2188 | - trigger_error(__('Cannot get installed modules'), E_USER_ERROR); |
2189 | - } |
2190 | - |
2191 | - // Compare the two |
2192 | - $to_install = array_diff($files, $installed); |
2193 | - |
2194 | - if (count($to_install) > 0) { |
2195 | - Theme::Set('module_install_url', 'index.php?p=module&q=Install&module='); |
2196 | - Theme::Set('to_install', $to_install); |
2197 | - Theme::Set('prepend', Theme::RenderReturn('module_page_install_modules')); |
2198 | + if (Config::GetSetting('MODULE_CONFIG_LOCKED_CHECKB') != 'Checked') { |
2199 | + // Get a list of matching files in the modules folder |
2200 | + $files = glob('modules/*.module.php'); |
2201 | + |
2202 | + // Get a list of all currently installed modules |
2203 | + try { |
2204 | + $dbh = PDOConnect::init(); |
2205 | + |
2206 | + $sth = $dbh->prepare("SELECT CONCAT('modules/', LOWER(Module), '.module.php') AS Module FROM `module`"); |
2207 | + $sth->execute(); |
2208 | + |
2209 | + $rows = $sth->fetchAll(); |
2210 | + $installed = array(); |
2211 | + |
2212 | + foreach($rows as $row) |
2213 | + $installed[] = $row['Module']; |
2214 | + } |
2215 | + catch (Exception $e) { |
2216 | + trigger_error(__('Cannot get installed modules'), E_USER_ERROR); |
2217 | + } |
2218 | + |
2219 | + // Compare the two |
2220 | + $to_install = array_diff($files, $installed); |
2221 | + |
2222 | + if (count($to_install) > 0) { |
2223 | + Theme::Set('module_install_url', 'index.php?p=module&q=Install&module='); |
2224 | + Theme::Set('to_install', $to_install); |
2225 | + Theme::Set('prepend', Theme::RenderReturn('module_page_install_modules')); |
2226 | + } |
2227 | } |
2228 | |
2229 | // Call to render the template |
2230 | @@ -138,7 +138,8 @@ |
2231 | $SQL .= ' ValidExtensions, '; |
2232 | $SQL .= ' ImageUri, '; |
2233 | $SQL .= ' PreviewEnabled, '; |
2234 | - $SQL .= ' assignable '; |
2235 | + $SQL .= ' assignable, '; |
2236 | + $SQL .= ' settings '; |
2237 | $SQL .= ' FROM `module` '; |
2238 | $SQL .= ' ORDER BY Name '; |
2239 | |
2240 | @@ -174,6 +175,7 @@ |
2241 | $row['enabled'] = Kit::ValidateParam($module['Enabled'], _INT); |
2242 | $row['preview_enabled'] = Kit::ValidateParam($module['PreviewEnabled'], _INT); |
2243 | $row['assignable'] = Kit::ValidateParam($module['assignable'], _INT); |
2244 | + $row['settings'] = json_decode(Kit::ValidateParam($module['settings'], _HTMLSTRING), true); |
2245 | |
2246 | // Initialise array of buttons, because we might not have any |
2247 | $row['buttons'] = array(); |
2248 | @@ -189,6 +191,14 @@ |
2249 | ); |
2250 | } |
2251 | |
2252 | + // Are there any buttons we need to provide as part of the module? |
2253 | + if (isset($row['settings']['buttons'])) { |
2254 | + foreach($row['settings']['buttons'] as $button) { |
2255 | + $button['text'] = __($button['text']); |
2256 | + $row['buttons'][] = $button; |
2257 | + } |
2258 | + } |
2259 | + |
2260 | $rows[] = $row; |
2261 | } |
2262 | |
2263 | |
2264 | === modified file 'server/lib/pages/stats.class.php' |
2265 | --- server/lib/pages/stats.class.php 2014-10-21 14:46:29 +0000 |
2266 | +++ server/lib/pages/stats.class.php 2015-01-09 11:27:10 +0000 |
2267 | @@ -344,6 +344,17 @@ |
2268 | $toDt = strtotime(Kit::GetParam('todt', _POST, _STRING)); |
2269 | $displayId = Kit::GetParam('displayid', _POST, _INT); |
2270 | |
2271 | + // Get an array of display id this user has access to. |
2272 | + $displays = $this->user->DisplayList(); |
2273 | + $displayIds = array(); |
2274 | + |
2275 | + foreach($displays as $display) { |
2276 | + $displayIds[] = $display['displayid']; |
2277 | + } |
2278 | + |
2279 | + if (count($displayIds) <= 0) |
2280 | + trigger_error(__('No displays with View permissions'), E_USER_ERROR); |
2281 | + |
2282 | // Get some data for a bandwidth chart |
2283 | try { |
2284 | $dbh = PDOConnect::init(); |
2285 | @@ -364,7 +375,8 @@ |
2286 | ON display.displayId = stat.displayId |
2287 | WHERE start <= :end |
2288 | AND end >= :start |
2289 | - AND type = :type '; |
2290 | + AND type = :type |
2291 | + AND display.displayId IN (' . implode(',', $displayIds) . ') '; |
2292 | |
2293 | if ($displayId != 0) { |
2294 | $SQL .= ' AND display.displayId = :displayId '; |
2295 | @@ -413,6 +425,17 @@ |
2296 | $fromDt = strtotime(Kit::GetParam('fromdt', _POST, _STRING)); |
2297 | $toDt = strtotime(Kit::GetParam('todt', _POST, _STRING)); |
2298 | |
2299 | + // Get an array of display id this user has access to. |
2300 | + $displays = $this->user->DisplayList(); |
2301 | + $displayIds = array(); |
2302 | + |
2303 | + foreach($displays as $display) { |
2304 | + $displayIds[] = $display['displayid']; |
2305 | + } |
2306 | + |
2307 | + if (count($displayIds) <= 0) |
2308 | + trigger_error(__('No displays with View permissions'), E_USER_ERROR); |
2309 | + |
2310 | // Get some data for a bandwidth chart |
2311 | try { |
2312 | $dbh = PDOConnect::init(); |
2313 | @@ -439,7 +462,8 @@ |
2314 | '; |
2315 | |
2316 | $SQL .= ' WHERE month > :month |
2317 | - AND month < :month2 '; |
2318 | + AND month < :month2 |
2319 | + AND display.displayId IN (' . implode(',', $displayIds) . ') '; |
2320 | |
2321 | if ($displayId != 0) { |
2322 | $SQL .= ' AND display.displayid = :displayid '; |
2323 | @@ -493,7 +517,7 @@ |
2324 | |
2325 | // Set up some suffixes |
2326 | $suffixes = array('bytes', 'k', 'M', 'G', 'T'); |
2327 | - Theme::Set('bandwidthWidgetUnits', $suffixes[$base]); |
2328 | + Theme::Set('bandwidthWidgetUnits', (isset($suffixes[$base]) ? $suffixes[$base] : '')); |
2329 | |
2330 | $output = Theme::RenderReturn('stats_page_bandwidth'); |
2331 | |
2332 | |
2333 | === modified file 'server/lib/pages/timeline.class.php' |
2334 | --- server/lib/pages/timeline.class.php 2014-11-12 17:20:55 +0000 |
2335 | +++ server/lib/pages/timeline.class.php 2015-01-09 11:27:10 +0000 |
2336 | @@ -751,8 +751,15 @@ |
2337 | Debug::LogEntry('audit', sprintf('Permission Granted to View MediaID: %s', $mediaId), 'layout', 'TimeLine'); |
2338 | |
2339 | // Create a media module to handle all the complex stuff |
2340 | - require_once("modules/$mediaType.module.php"); |
2341 | - $tmpModule = new $mediaType($db, $user, $mediaId, $layoutId, $regionId, $lkId); |
2342 | + try { |
2343 | + require_once("modules/$mediaType.module.php"); |
2344 | + $tmpModule = new $mediaType($db, $user, $mediaId, $layoutId, $regionId, $lkId); |
2345 | + } |
2346 | + catch (Exception $e) { |
2347 | + Debug::Audit('Caught exception from Module Create'); |
2348 | + trigger_error($e->getMessage(), E_USER_ERROR); |
2349 | + } |
2350 | + |
2351 | $mediaName = $tmpModule->GetName(); |
2352 | $transitionIn = $tmpModule->GetTransition('in'); |
2353 | $transitionOut = $tmpModule->GetTransition('out'); |
2354 | |
2355 | === modified file 'server/lib/pages/user.class.php' |
2356 | --- server/lib/pages/user.class.php 2014-10-17 16:13:12 +0000 |
2357 | +++ server/lib/pages/user.class.php 2015-01-09 11:27:10 +0000 |
2358 | @@ -122,38 +122,30 @@ |
2359 | // Pinned option? |
2360 | setSession('user_admin', 'Filter', Kit::GetParam('XiboFilterPinned', _REQUEST, _CHECKBOX, 'off')); |
2361 | |
2362 | + // Filter our users? |
2363 | + $filterBy = array(); |
2364 | + |
2365 | // Generate the results |
2366 | $sql = "SELECT user.UserID, user.UserName, user.usertypeid, user.loggedin, user.lastaccessed, user.email, user.homepage, user.retired "; |
2367 | $sql .= " FROM `user` "; |
2368 | $sql .= " WHERE 1 = 1 "; |
2369 | |
2370 | - // Normal users can only see themselves |
2371 | - if ($user->usertypeid == 3) |
2372 | - $sql .= sprintf(" AND userid = %d ", $user->userid); |
2373 | - |
2374 | // Filter on User Type |
2375 | - if($filter_usertypeid != 0) |
2376 | - $sql .= sprintf(" AND usertypeid = %d ", $filter_usertypeid); |
2377 | + if ($filter_usertypeid != 0) |
2378 | + $filterBy['userTypeId'] = $filter_usertypeid; |
2379 | |
2380 | // Filter on User Name |
2381 | if ($filter_username != '') |
2382 | - $sql .= " AND UserName LIKE '%" . sprintf("%s", $db->escape_string($filter_username) . "%' "); |
2383 | - |
2384 | - $sql .= " ORDER by UserName"; |
2385 | - |
2386 | - //Debug::LogEntry('audit', $sql); |
2387 | + $filterBy['userName'] = $filter_username; |
2388 | |
2389 | // Load results into an array |
2390 | - $users = $db->GetArray($sql); |
2391 | + $users = $user->userList(array('userName'), $filterBy); |
2392 | |
2393 | if (!is_array($users)) |
2394 | - { |
2395 | - trigger_error($db->error()); |
2396 | trigger_error(__('Error getting list of users'), E_USER_ERROR); |
2397 | - } |
2398 | - |
2399 | + |
2400 | $cols = array( |
2401 | - array('name' => 'UserName', 'title' => __('Name')), |
2402 | + array('name' => 'username', 'title' => __('Name')), |
2403 | array('name' => 'homepage', 'title' => __('Homepage')), |
2404 | array('name' => 'email', 'title' => __('Email')), |
2405 | array('name' => 'retired', 'title' => __('Retired?'), 'icons' => true) |
2406 | @@ -164,7 +156,7 @@ |
2407 | |
2408 | foreach ($users as $row) { |
2409 | |
2410 | - $row['groupid'] = $user->getGroupFromID($row['UserID'], true); |
2411 | + $row['groupid'] = $user->getGroupFromID($row['userid'], true); |
2412 | |
2413 | // Super admins have some buttons |
2414 | if ($user->usertypeid == 1) { |
2415 | @@ -172,14 +164,14 @@ |
2416 | // Edit |
2417 | $row['buttons'][] = array( |
2418 | 'id' => 'user_button_edit', |
2419 | - 'url' => 'index.php?p=user&q=DisplayForm&userID=' . $row['UserID'], |
2420 | + 'url' => 'index.php?p=user&q=DisplayForm&userID=' . $row['userid'], |
2421 | 'text' => __('Edit') |
2422 | ); |
2423 | |
2424 | // Delete |
2425 | $row['buttons'][] = array( |
2426 | 'id' => 'user_button_delete', |
2427 | - 'url' => 'index.php?p=user&q=DeleteForm&userID=' . $row['UserID'], |
2428 | + 'url' => 'index.php?p=user&q=DeleteForm&userID=' . $row['userid'], |
2429 | 'text' => __('Delete') |
2430 | ); |
2431 | |
2432 | @@ -200,21 +192,21 @@ |
2433 | // Applications |
2434 | $row['buttons'][] = array( |
2435 | 'id' => 'user_button_applications', |
2436 | - 'url' => 'index.php?p=oauth&q=UserTokens&userID=' . $row['UserID'], |
2437 | + 'url' => 'index.php?p=oauth&q=UserTokens&userID=' . $row['userid'], |
2438 | 'text' => __('Applications') |
2439 | ); |
2440 | |
2441 | // Set Home Page |
2442 | $row['buttons'][] = array( |
2443 | 'id' => 'user_button_homepage', |
2444 | - 'url' => 'index.php?p=user&q=SetUserHomePageForm&userid=' . $row['UserID'], |
2445 | + 'url' => 'index.php?p=user&q=SetUserHomePageForm&userid=' . $row['userid'], |
2446 | 'text' => __('Set Homepage') |
2447 | ); |
2448 | |
2449 | // Set Password |
2450 | $row['buttons'][] = array( |
2451 | 'id' => 'user_button_delete', |
2452 | - 'url' => 'index.php?p=user&q=SetPasswordForm&userid=' . $row['UserID'], |
2453 | + 'url' => 'index.php?p=user&q=SetPasswordForm&userid=' . $row['userid'], |
2454 | 'text' => __('Set Password') |
2455 | ); |
2456 | } |
2457 | @@ -252,15 +244,12 @@ |
2458 | $initialGroupId = Kit::GetParam('groupid', _POST, _INT); |
2459 | |
2460 | // Validation |
2461 | - if ($username=="") |
2462 | - { |
2463 | - trigger_error("Please enter a User Name.", E_USER_ERROR); |
2464 | - } |
2465 | + if ($username == '' || strlen($username) > 50) |
2466 | + trigger_error(__('User name must be between 1 and 50 characters.'), E_USER_ERROR); |
2467 | + |
2468 | if ($password=="") |
2469 | - { |
2470 | trigger_error("Please enter a Password.", E_USER_ERROR); |
2471 | - } |
2472 | - |
2473 | + |
2474 | if ($homepage == "") |
2475 | $homepage = "dashboard"; |
2476 | |
2477 | @@ -342,10 +331,8 @@ |
2478 | $retired = Kit::GetParam('retired', _POST, _CHECKBOX); |
2479 | |
2480 | // Validation |
2481 | - if ($username == "") |
2482 | - { |
2483 | - trigger_error(__("Please enter a User Name."), E_USER_ERROR); |
2484 | - } |
2485 | + if ($username == '' || strlen($username) > 50) |
2486 | + trigger_error(__('User name must be between 1 and 50 characters.'), E_USER_ERROR); |
2487 | |
2488 | // Check for duplicate user name |
2489 | $sqlcheck = " "; |
2490 | @@ -563,7 +550,7 @@ |
2491 | // Render the return and output |
2492 | $formFields = array(); |
2493 | $formFields[] = FormManager::AddText('edit_username', __('User Name'), $username, |
2494 | - __('The Login Name of the user.'), 'n', 'required'); |
2495 | + __('The Login Name of the user.'), 'n', 'required maxlength="50"'); |
2496 | |
2497 | $formFields[] = FormManager::AddPassword('edit_password', __('Password'), $password, |
2498 | __('The Password for this user.'), 'p', 'required'); |
2499 | |
2500 | === modified file 'server/lib/service/service_v3.wsdl' |
2501 | --- server/lib/service/service_v3.wsdl 2014-10-31 15:27:56 +0000 |
2502 | +++ server/lib/service/service_v3.wsdl 2015-01-09 11:27:10 +0000 |
2503 | @@ -42,15 +42,6 @@ |
2504 | <message name="ScheduleResponse"> |
2505 | <part name="ScheduleXml" type="xsd:string" /> |
2506 | </message> |
2507 | - <message name="RecieveXmlLogRequest"> |
2508 | - <part name="serverKey" type="xsd:string" /> |
2509 | - <part name="hardwareKey" type="xsd:string" /> |
2510 | - <part name="xml" type="xsd:string" /> |
2511 | - <part name="version" type="xsd:string" /> |
2512 | - </message> |
2513 | - <message name="RecieveXmlLogResponse"> |
2514 | - <part name="success" type="xsd:boolean" /> |
2515 | - </message> |
2516 | <message name="BlackListRequest"> |
2517 | <part name="serverKey" type="xsd:string" /> |
2518 | <part name="hardwareKey" type="xsd:string" /> |
2519 | |
2520 | === modified file 'server/lib/service/xmdssoap3.class.php' |
2521 | --- server/lib/service/xmdssoap3.class.php 2014-11-25 11:09:21 +0000 |
2522 | +++ server/lib/service/xmdssoap3.class.php 2015-01-09 11:27:10 +0000 |
2523 | @@ -32,12 +32,6 @@ |
2524 | private $defaultLayoutId; |
2525 | private $version_instructions; |
2526 | |
2527 | - public function __construct() |
2528 | - { |
2529 | - global $db; |
2530 | - $this->db =& $db; |
2531 | - } |
2532 | - |
2533 | /** |
2534 | * Registers a new display |
2535 | * @param <type> $serverKey |
2536 | @@ -64,7 +58,7 @@ |
2537 | try { |
2538 | $dbh = PDOConnect::init(); |
2539 | $sth = $dbh->prepare(' |
2540 | - SELECT licensed |
2541 | + SELECT licensed, displayid |
2542 | FROM display |
2543 | WHERE license = :hardwareKey'); |
2544 | |
2545 | @@ -97,10 +91,10 @@ |
2546 | |
2547 | // Touch the display record |
2548 | $displayObject = new Display(); |
2549 | - $displayObject->Touch($displayid); |
2550 | + $displayObject->Touch($row['displayid']); |
2551 | |
2552 | // Log Bandwidth |
2553 | - $this->LogBandwidth($displayid, Bandwidth::$REGISTER, strlen($active)); |
2554 | + $this->LogBandwidth($row['displayid'], Bandwidth::$REGISTER, strlen($active)); |
2555 | |
2556 | Debug::LogEntry('audit', $active, get_class(), __FUNCTION__); |
2557 | |
2558 | @@ -114,18 +108,12 @@ |
2559 | */ |
2560 | function RequiredFiles($serverKey, $hardwareKey, $version) |
2561 | { |
2562 | - $db =& $this->db; |
2563 | - |
2564 | // Sanitize |
2565 | - $serverKey = Kit::ValidateParam($serverKey, _STRING); |
2566 | - $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
2567 | - $version = Kit::ValidateParam($version, _STRING); |
2568 | - $rfLookahead = Kit::ValidateParam(Config::GetSetting('REQUIRED_FILES_LOOKAHEAD'), _INT); |
2569 | - |
2570 | - // Make sure we are talking the same language |
2571 | - if (!$this->CheckVersion($version)) |
2572 | - throw new SoapFault('Sender', 'Your client is not of the correct version for communication with this server.'); |
2573 | - |
2574 | + $serverKey = Kit::ValidateParam($serverKey, _STRING); |
2575 | + $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
2576 | + $rfLookahead = Kit::ValidateParam(Config::GetSetting('REQUIRED_FILES_LOOKAHEAD'), _INT); |
2577 | + |
2578 | + // Check the serverKey matches |
2579 | if ($serverKey != Config::GetSetting('SERVER_KEY')) |
2580 | throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); |
2581 | |
2582 | @@ -140,12 +128,15 @@ |
2583 | throw new SoapFault('Sender', 'This display is not licensed.'); |
2584 | |
2585 | if ($this->isAuditing == 1) |
2586 | - Debug::LogEntry("audit", '[IN] with hardware key: ' . $hardwareKey, 'xmds', 'RequiredFiles', '', $this->displayId); |
2587 | - |
2588 | + Debug::LogEntry("audit", '[IN] with hardware key: ' . $hardwareKey, "xmds", "RequiredFiles"); |
2589 | + |
2590 | + // Remove all Nonces for this display |
2591 | + $nonce = new Nonce(); |
2592 | + $nonce->RemoveAllXmdsNonce($this->displayId); |
2593 | + |
2594 | + // Build a new RF |
2595 | $requiredFilesXml = new DOMDocument("1.0"); |
2596 | - $fileElements = $requiredFilesXml->createElement("files"); |
2597 | - $fileElements->setAttribute('version_instructions', $this->version_instructions); |
2598 | - |
2599 | + $fileElements = $requiredFilesXml->createElement("files"); |
2600 | $requiredFilesXml->appendChild($fileElements); |
2601 | |
2602 | // Hour to hour time bands for the query |
2603 | @@ -157,158 +148,158 @@ |
2604 | $fromFilter = $fromFilter - ($fromFilter % 3600); |
2605 | $toFilter = $rfLookahead - ($rfLookahead % 3600); |
2606 | |
2607 | - Debug::LogEntry('audit', sprintf('FromDT = %s. ToDt = %s', date('Y-m-d h:i:s', $fromFilter), date('Y-m-d h:i:s', $toFilter)), 'xmds', 'RequiredFiles', '', $this->displayId); |
2608 | - |
2609 | - // Get a list of all layout ids in the schedule right now. |
2610 | - $SQL = " SELECT DISTINCT layout.layoutID "; |
2611 | - $SQL .= " FROM `campaign` "; |
2612 | - $SQL .= " INNER JOIN schedule_detail ON schedule_detail.CampaignID = campaign.CampaignID "; |
2613 | - $SQL .= " INNER JOIN `lkcampaignlayout` ON lkcampaignlayout.CampaignID = campaign.CampaignID "; |
2614 | - $SQL .= " INNER JOIN `layout` ON lkcampaignlayout.LayoutID = layout.LayoutID "; |
2615 | - $SQL .= " INNER JOIN lkdisplaydg ON lkdisplaydg.DisplayGroupID = schedule_detail.DisplayGroupID "; |
2616 | - $SQL .= sprintf(" WHERE lkdisplaydg.DisplayID = %d ", $this->displayId); |
2617 | - $SQL .= sprintf(" AND schedule_detail.FromDT < %d AND schedule_detail.ToDT > %d ", $toFilter, $fromFilter); |
2618 | - $SQL .= " AND layout.retired = 0 "; |
2619 | - |
2620 | if ($this->isAuditing == 1) |
2621 | - Debug::LogEntry("audit", $SQL, 'xmds', 'RequiredFiles', '', $this->displayId); |
2622 | - |
2623 | - if (!$results = $db->query($SQL)) |
2624 | - { |
2625 | - trigger_error($db->error()); |
2626 | + Debug::LogEntry('audit', sprintf('FromDT = %s. ToDt = %s', date('Y-m-d h:i:s', $fromFilter), date('Y-m-d h:i:s', $toFilter)), 'xmds', 'RequiredFiles', '', $this->displayId); |
2627 | + |
2628 | + try { |
2629 | + $dbh = PDOConnect::init(); |
2630 | + |
2631 | + // Get a list of all layout ids in the schedule right now. |
2632 | + $SQL = " SELECT DISTINCT layout.layoutID "; |
2633 | + $SQL .= " FROM `campaign` "; |
2634 | + $SQL .= " INNER JOIN schedule ON schedule.CampaignID = campaign.CampaignID "; |
2635 | + $SQL .= " INNER JOIN schedule_detail ON schedule_detail.eventID = schedule.eventID "; |
2636 | + $SQL .= " INNER JOIN `lkcampaignlayout` ON lkcampaignlayout.CampaignID = campaign.CampaignID "; |
2637 | + $SQL .= " INNER JOIN `layout` ON lkcampaignlayout.LayoutID = layout.LayoutID "; |
2638 | + $SQL .= " INNER JOIN lkdisplaydg ON lkdisplaydg.DisplayGroupID = schedule_detail.DisplayGroupID "; |
2639 | + $SQL .= " WHERE lkdisplaydg.DisplayID = :displayId "; |
2640 | + $SQL .= " AND schedule_detail.FromDT < :fromdt AND schedule_detail.ToDT > :todt "; |
2641 | + $SQL .= " AND layout.retired = 0 "; |
2642 | + |
2643 | + $sth = $dbh->prepare($SQL); |
2644 | + $sth->execute(array( |
2645 | + 'displayId' => $this->displayId, |
2646 | + 'fromdt' => $toFilter, |
2647 | + 'todt' => $fromFilter |
2648 | + )); |
2649 | + |
2650 | + // Our layout list will always include the default layout |
2651 | + $layouts = array(); |
2652 | + $layouts[] = $this->defaultLayoutId; |
2653 | + |
2654 | + // Build up the other layouts into an array |
2655 | + foreach ($sth->fetchAll() as $row) |
2656 | + $layouts[] = Kit::ValidateParam($row['layoutID'], _INT); |
2657 | + } |
2658 | + catch (Exception $e) { |
2659 | + Debug::LogEntry('error', $e->getMessage(), get_class(), __FUNCTION__); |
2660 | return new SoapFault('Sender', 'Unable to get a list of layouts'); |
2661 | } |
2662 | |
2663 | - // Our layout list will always include the default layout |
2664 | - $layouts = array(); |
2665 | - $layouts[] = $this->defaultLayoutId; |
2666 | - |
2667 | - // Build up the other layouts into an array |
2668 | - while ($row = $db->get_assoc_row($results)) |
2669 | - $layouts[] = Kit::ValidateParam($row['layoutID'], _INT); |
2670 | - |
2671 | // Create a comma separated list to pass into the query which gets file nodes |
2672 | $layoutIdList = implode(',', $layouts); |
2673 | |
2674 | - // Add file nodes to the $fileElements |
2675 | - $SQL = " SELECT 'layout' AS RecordType, layout.layoutID AS path, layout.layoutID AS id, MD5(layout.xml) AS `MD5`, NULL AS FileSize, layout.background, layout.xml AS xml "; |
2676 | - $SQL .= " FROM layout "; |
2677 | - $SQL .= sprintf(" WHERE layout.layoutid IN (%s) ", $layoutIdList); |
2678 | - $SQL .= " UNION "; |
2679 | - $SQL .= " SELECT 'media' AS RecordType, storedAs AS path, media.mediaID AS id, media.`MD5`, media.FileSize, NULL AS background, NULL AS xml "; |
2680 | - $SQL .= " FROM media "; |
2681 | - $SQL .= " INNER JOIN lklayoutmedia "; |
2682 | - $SQL .= " ON lklayoutmedia.MediaID = media.MediaID "; |
2683 | - $SQL .= " INNER JOIN layout "; |
2684 | - $SQL .= " ON layout.LayoutID = lklayoutmedia.LayoutID"; |
2685 | - $SQL .= sprintf(" WHERE layout.layoutid IN (%s) ", $layoutIdList); |
2686 | - $SQL .= " |
2687 | - UNION |
2688 | - SELECT 'media' AS RecordType, storedAs AS path, media.mediaID AS id, media.`MD5`, media.FileSize, NULL AS background, NULL AS xml |
2689 | - FROM `media` |
2690 | - INNER JOIN `lkmediadisplaygroup` |
2691 | - ON lkmediadisplaygroup.mediaid = media.MediaID |
2692 | - INNER JOIN lkdisplaydg |
2693 | - ON lkdisplaydg.DisplayGroupID = lkmediadisplaygroup.DisplayGroupID |
2694 | - "; |
2695 | - $SQL .= sprintf(" WHERE lkdisplaydg.DisplayID = %d ", $this->displayId); |
2696 | - $SQL .= " ORDER BY RecordType DESC"; |
2697 | - |
2698 | - if ($this->isAuditing == 1) |
2699 | - Debug::LogEntry("audit", $SQL, 'xmds', 'RequiredFiles', '', $this->displayId); |
2700 | - |
2701 | - if (!$results = $db->query($SQL)) |
2702 | - { |
2703 | - trigger_error($db->error()); |
2704 | + try { |
2705 | + $dbh = PDOConnect::init(); |
2706 | + |
2707 | + // Add file nodes to the $fileElements |
2708 | + $SQL = " |
2709 | + SELECT 1 AS DownloadOrder, 'media' AS RecordType, storedAs AS path, media.mediaID AS id, media.`MD5`, media.FileSize, NULL AS xml |
2710 | + FROM `media` |
2711 | + WHERE media.type = 'font' |
2712 | + OR (media.type = 'module' AND media.moduleSystemFile = 1) |
2713 | + UNION |
2714 | + "; |
2715 | + $SQL .= " SELECT 4 AS DownloadOrder, 'layout' AS RecordType, layout.layoutID AS path, layout.layoutID AS id, MD5(layout.xml) AS `MD5`, NULL AS FileSize, layout.xml AS xml "; |
2716 | + $SQL .= " FROM layout "; |
2717 | + $SQL .= sprintf(" WHERE layout.layoutid IN (%s) ", $layoutIdList); |
2718 | + $SQL .= " UNION "; |
2719 | + $SQL .= " SELECT 3 AS DownloadOrder, 'media' AS RecordType, storedAs AS path, media.mediaID AS id, media.`MD5`, media.FileSize, NULL AS xml "; |
2720 | + $SQL .= " FROM media "; |
2721 | + $SQL .= " INNER JOIN lklayoutmedia "; |
2722 | + $SQL .= " ON lklayoutmedia.MediaID = media.MediaID "; |
2723 | + $SQL .= " INNER JOIN layout "; |
2724 | + $SQL .= " ON layout.LayoutID = lklayoutmedia.LayoutID"; |
2725 | + $SQL .= sprintf(" WHERE layout.layoutid IN (%s) ", $layoutIdList); |
2726 | + $SQL .= " |
2727 | + UNION |
2728 | + SELECT 2 AS DownloadOrder, 'media' AS RecordType, storedAs AS path, media.mediaID AS id, media.`MD5`, media.FileSize, NULL AS xml |
2729 | + FROM `media` |
2730 | + INNER JOIN `lkmediadisplaygroup` |
2731 | + ON lkmediadisplaygroup.mediaid = media.MediaID |
2732 | + INNER JOIN lkdisplaydg |
2733 | + ON lkdisplaydg.DisplayGroupID = lkmediadisplaygroup.DisplayGroupID |
2734 | + "; |
2735 | + $SQL .= " WHERE lkdisplaydg.DisplayID = :displayId "; |
2736 | + $SQL .= " ORDER BY DownloadOrder, RecordType DESC"; |
2737 | + |
2738 | + $sth = $dbh->prepare($SQL); |
2739 | + $sth->execute(array( |
2740 | + 'displayId' => $this->displayId |
2741 | + )); |
2742 | + |
2743 | + // Prepare a SQL statement in case we need to update the MD5 and FileSize on media nodes. |
2744 | + $mediaSth = $dbh->prepare('UPDATE media SET `MD5` = :md5, FileSize = :size WHERE MediaID = :mediaid'); |
2745 | + |
2746 | + // What is the send file mode? |
2747 | + $sendFileMode = Config::GetSetting('SENDFILE_MODE'); |
2748 | + |
2749 | + foreach ($sth->fetchAll() as $row) { |
2750 | + $recordType = Kit::ValidateParam($row['RecordType'], _WORD); |
2751 | + $path = Kit::ValidateParam($row['path'], _STRING); |
2752 | + $id = Kit::ValidateParam($row['id'], _STRING); |
2753 | + $md5 = Kit::ValidateParam($row['MD5'], _HTMLSTRING); |
2754 | + $fileSize = Kit::ValidateParam($row['FileSize'], _INT); |
2755 | + $xml = Kit::ValidateParam($row['xml'], _HTMLSTRING); |
2756 | + $mediaNonce = ''; |
2757 | + |
2758 | + if ($recordType == 'layout') { |
2759 | + // For layouts the MD5 column is the layout xml |
2760 | + $fileSize = strlen($xml); |
2761 | + |
2762 | + if ($this->isAuditing == 1) |
2763 | + Debug::LogEntry("audit", 'MD5 for layoutid ' . $id . ' is: [' . $md5 . ']', "xmds", "RequiredFiles"); |
2764 | + |
2765 | + // Add nonce |
2766 | + $nonce->AddXmdsNonce('layout', $this->displayId, NULL, $fileSize, NULL, $id); |
2767 | + } |
2768 | + else if ($recordType == 'media') { |
2769 | + // If they are empty calculate them and save them back to the media. |
2770 | + if ($md5 == '' || $fileSize == 0) { |
2771 | + |
2772 | + $md5 = md5_file($libraryLocation.$path); |
2773 | + $fileSize = filesize($libraryLocation.$path); |
2774 | + |
2775 | + // Update the media record with this information |
2776 | + $mediaSth->execute(array('md5' => $md5, 'size' => $fileSize, 'mediaid' => $id)); |
2777 | + } |
2778 | + |
2779 | + // Add nonce |
2780 | + $mediaNonce = $nonce->AddXmdsNonce('file', $this->displayId, $id, $fileSize, $path); |
2781 | + } |
2782 | + else { |
2783 | + continue; |
2784 | + } |
2785 | + |
2786 | + // Add the file node |
2787 | + $file = $requiredFilesXml->createElement("file"); |
2788 | + $file->setAttribute("type", $recordType); |
2789 | + $file->setAttribute("id", $id); |
2790 | + $file->setAttribute("size", $fileSize); |
2791 | + $file->setAttribute("md5", $md5); |
2792 | + $file->setAttribute("download", 'xmds'); |
2793 | + $file->setAttribute("path", $path); |
2794 | + |
2795 | + $fileElements->appendChild($file); |
2796 | + } |
2797 | + } |
2798 | + catch (Exception $e) { |
2799 | + Debug::LogEntry('error', $e->getMessage()); |
2800 | return new SoapFault('Sender', 'Unable to get a list of files'); |
2801 | } |
2802 | |
2803 | - // Added paths |
2804 | - $paths = array(); |
2805 | - |
2806 | - while ($row = $db->get_assoc_row($results)) |
2807 | - { |
2808 | - $recordType = Kit::ValidateParam($row['RecordType'], _WORD); |
2809 | - $path = Kit::ValidateParam($row['path'], _STRING); |
2810 | - $id = Kit::ValidateParam($row['id'], _STRING); |
2811 | - $md5 = Kit::ValidateParam($row['MD5'], _HTMLSTRING); |
2812 | - $fileSize = Kit::ValidateParam($row['FileSize'], _INT); |
2813 | - $background = Kit::ValidateParam($row['background'], _STRING); |
2814 | - $xml = Kit::ValidateParam($row['xml'], _HTMLSTRING); |
2815 | - |
2816 | - if ($recordType == 'layout') |
2817 | - { |
2818 | - // For layouts the MD5 column is the layout xml |
2819 | - $fileSize = strlen($xml); |
2820 | - |
2821 | - if ($this->isAuditing == 1) |
2822 | - Debug::LogEntry("audit", 'MD5 for layoutid ' . $id . ' is: [' . $md5 . ']', 'xmds', 'RequiredFiles', '', $this->displayId); |
2823 | - } |
2824 | - else if ($recordType == 'media') |
2825 | - { |
2826 | - // If they are empty calculate them and save them back to the media. |
2827 | - if ($md5 == '' || $fileSize == 0) |
2828 | - { |
2829 | - $md5 = md5_file($libraryLocation.$path); |
2830 | - $fileSize = filesize($libraryLocation.$path); |
2831 | - |
2832 | - // Update the media record with this information |
2833 | - $SQL = sprintf("UPDATE media SET `MD5` = '%s', FileSize = %d WHERE MediaID = %d", $md5, $fileSize, $id); |
2834 | - |
2835 | - if (!$db->query($SQL)) |
2836 | - trigger_error($db->error()); |
2837 | - } |
2838 | - } |
2839 | - else |
2840 | - { |
2841 | - continue; |
2842 | - } |
2843 | - |
2844 | - // Add the file node |
2845 | - $file = $requiredFilesXml->createElement("file"); |
2846 | - |
2847 | - $file->setAttribute("type", $recordType); |
2848 | - $file->setAttribute("path", $path); |
2849 | - $file->setAttribute("id", $id); |
2850 | - $file->setAttribute("size", $fileSize); |
2851 | - $file->setAttribute("md5", $md5); |
2852 | - |
2853 | - $fileElements->appendChild($file); |
2854 | - |
2855 | - // Add this to the paths array |
2856 | - $paths[] = $path; |
2857 | - |
2858 | - // If this is a layout type and there is a background then add the background node |
2859 | - // TODO: We need to alter the layout table to have a background ID rather than a path |
2860 | - // TODO: We need to alter the background edit method to create a lklayoutmedia link for |
2861 | - // background images (and maintain it when they change) |
2862 | - if ($recordType == 'layout' && $background != '' && !in_array($background, $paths)) |
2863 | - { |
2864 | - // Also append another file node for the background image (if there is one) |
2865 | - $file = $requiredFilesXml->createElement("file"); |
2866 | - $file->setAttribute("type", "media"); |
2867 | - $file->setAttribute("path", $background); |
2868 | - $file->setAttribute("md5", md5_file($libraryLocation.$background)); |
2869 | - $file->setAttribute("size", filesize($libraryLocation.$background)); |
2870 | - $fileElements->appendChild($file); |
2871 | - |
2872 | - // Add this to the paths array |
2873 | - $paths[] = $background; |
2874 | - } |
2875 | - } |
2876 | - |
2877 | Kit::ClassLoader('layout'); |
2878 | |
2879 | // Go through each layout and see if we need to supply any resource nodes. |
2880 | foreach ($layouts as $layoutId) { |
2881 | // Load the layout XML and work out if we have any ticker / text / dataset media items |
2882 | - $layout = new Layout($db); |
2883 | + $layout = new Layout(); |
2884 | |
2885 | $layoutInformation = $layout->LayoutInformation($layoutId); |
2886 | |
2887 | foreach($layoutInformation['regions'] as $region) { |
2888 | foreach($region['media'] as $media) { |
2889 | - if ($media['mediatype'] == 'ticker' || $media['mediatype'] == 'text' || $media['mediatype'] == 'datasetview' || $media['mediatype'] == 'webpage') { |
2890 | + if ($media['render'] == 'html' || $media['mediatype'] == 'ticker' || $media['mediatype'] == 'text' || $media['mediatype'] == 'datasetview' || $media['mediatype'] == 'webpage' || $media['mediatype'] == 'embedded') { |
2891 | // Append this item to required files |
2892 | $file = $requiredFilesXml->createElement("file"); |
2893 | $file->setAttribute('type', 'resource'); |
2894 | @@ -319,6 +310,8 @@ |
2895 | $file->setAttribute('updated', (isset($media['updated']) ? $media['updated'] : 0)); |
2896 | |
2897 | $fileElements->appendChild($file); |
2898 | + |
2899 | + $nonce->AddXmdsNonce('resource', $this->displayId, NULL, NULL, NULL, $layoutId, $region['regionid'], $media['mediaid']); |
2900 | } |
2901 | } |
2902 | } |
2903 | @@ -330,70 +323,65 @@ |
2904 | |
2905 | $fileElements->appendChild($blackList); |
2906 | |
2907 | - // Populate |
2908 | - $SQL = "SELECT MediaID |
2909 | - FROM blacklist |
2910 | - WHERE DisplayID = " . $this->displayId . " |
2911 | - AND isIgnored = 0"; |
2912 | - |
2913 | - if (!$results = $db->query($SQL)) |
2914 | - { |
2915 | - trigger_error($db->error()); |
2916 | + try { |
2917 | + $dbh = PDOConnect::init(); |
2918 | + |
2919 | + $sth = $dbh->prepare('SELECT MediaID FROM blacklist WHERE DisplayID = :displayid AND isIgnored = 0'); |
2920 | + $sth->execute(array( |
2921 | + 'displayid' => $this->displayId |
2922 | + )); |
2923 | + |
2924 | + // Add a black list element for each file |
2925 | + foreach ($sth->fetchAll() as $row) { |
2926 | + $file = $requiredFilesXml->createElement("file"); |
2927 | + $file->setAttribute("id", $row['MediaID']); |
2928 | + |
2929 | + $blackList->appendChild($file); |
2930 | + } |
2931 | + } |
2932 | + catch (Exception $e) { |
2933 | + Debug::LogEntry('error', $e->getMessage()); |
2934 | return new SoapFault('Sender', 'Unable to get a list of blacklisted files'); |
2935 | } |
2936 | |
2937 | - // Add a black list element for each file |
2938 | - while ($row = $db->get_row($results)) |
2939 | - { |
2940 | - $file = $requiredFilesXml->createElement("file"); |
2941 | - $file->setAttribute("id", $row[0]); |
2942 | - |
2943 | - $blackList->appendChild($file); |
2944 | - } |
2945 | - |
2946 | // Phone Home? |
2947 | $this->PhoneHome(); |
2948 | |
2949 | if ($this->isAuditing == 1) |
2950 | - Debug::LogEntry("audit", $requiredFilesXml->saveXML(), 'xmds', 'RequiredFiles', '', $this->displayId); |
2951 | - |
2952 | + Debug::LogEntry("audit", "[OUT]" . $requiredFilesXml->saveXML(), "xmds", "RequiredFiles"); |
2953 | + |
2954 | // Return the results of requiredFiles() |
2955 | $requiredFilesXml->formatOutput = true; |
2956 | $output = $requiredFilesXml->saveXML(); |
2957 | |
2958 | // Log Bandwidth |
2959 | - $this->LogBandwidth($this->displayId, 2, strlen($output)); |
2960 | + $this->LogBandwidth($this->displayId, Bandwidth::$RF, strlen($output)); |
2961 | |
2962 | return $output; |
2963 | } |
2964 | |
2965 | /** |
2966 | - * Gets the specified file |
2967 | - * @return |
2968 | - * @param $hardwareKey Object |
2969 | - * @param $filePath Object |
2970 | - * @param $fileType Object |
2971 | + * Get File |
2972 | + * @param string $serverKey The ServerKey for this CMS |
2973 | + * @param string $hardwareKey The HardwareKey for this Display |
2974 | + * @param int $mediaId The ID |
2975 | + * @param string $fileType The File Type |
2976 | + * @param int $chunkOffset The Offset of the Chunk Requested |
2977 | + * @param string $chunkSize The Size of the Chunk Requested |
2978 | */ |
2979 | function GetFile($serverKey, $hardwareKey, $filePath, $fileType, $chunkOffset, $chunkSize, $version) |
2980 | { |
2981 | - $db =& $this->db; |
2982 | - |
2983 | // Sanitize |
2984 | - $serverKey = Kit::ValidateParam($serverKey, _STRING); |
2985 | - $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
2986 | - $fileType = Kit::ValidateParam($fileType, _WORD); |
2987 | - $chunkOffset = Kit::ValidateParam($chunkOffset, _INT); |
2988 | - $chunkSize = Kit::ValidateParam($chunkSize, _INT); |
2989 | - $version = Kit::ValidateParam($version, _STRING); |
2990 | + $serverKey = Kit::ValidateParam($serverKey, _STRING); |
2991 | + $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
2992 | + $filePath = Kit::ValidateParam($filePath, _STRING); |
2993 | + $fileType = Kit::ValidateParam($fileType, _WORD); |
2994 | + $chunkOffset = Kit::ValidateParam($chunkOffset, _INT); |
2995 | + $chunkSize = Kit::ValidateParam($chunkSize, _INT); |
2996 | |
2997 | $libraryLocation = Config::GetSetting("LIBRARY_LOCATION"); |
2998 | |
2999 | - // Make sure we are talking the same language |
3000 | - if (!$this->CheckVersion($version)) |
3001 | - { |
3002 | - throw new SoapFault('Receiver', "Your client is not of the correct version for communication with this server."); |
3003 | - } |
3004 | - |
3005 | + // Check the serverKey matches |
3006 | if ($serverKey != Config::GetSetting('SERVER_KEY')) |
3007 | throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); |
3008 | |
3009 | @@ -401,60 +389,67 @@ |
3010 | if (!$this->CheckBandwidth()) |
3011 | throw new SoapFault('Receiver', "Bandwidth Limit exceeded"); |
3012 | |
3013 | - //auth this request... |
3014 | + // Authenticate this request... |
3015 | if (!$this->AuthDisplay($hardwareKey)) |
3016 | - { |
3017 | throw new SoapFault('Receiver', "This display client is not licensed"); |
3018 | - } |
3019 | |
3020 | if ($this->isAuditing == 1) |
3021 | - { |
3022 | - Debug::LogEntry("audit", "[IN]", "xmds", "GetFile"); |
3023 | - Debug::LogEntry("audit", "Params: [$hardwareKey] [$filePath] [$fileType] [$chunkOffset] [$chunkSize]", "xmds", "GetFile"); |
3024 | - } |
3025 | - |
3026 | - if ($fileType == "layout") |
3027 | - { |
3028 | - $filePath = Kit::ValidateParam($filePath, _INT); |
3029 | - |
3030 | - $SQL = sprintf("SELECT xml FROM layout WHERE layoutid = %d", $filePath); |
3031 | - if (!$results = $db->query($SQL)) |
3032 | - { |
3033 | - trigger_error($db->error()); |
3034 | + Debug::LogEntry("audit", "[IN] Params: [$hardwareKey] [$filePath] [$fileType] [$chunkOffset] [$chunkSize]", "xmds", "GetFile", '', $this->displayId); |
3035 | + |
3036 | + $nonce = new Nonce(); |
3037 | + |
3038 | + if ($fileType == "layout") { |
3039 | + $fileId = Kit::ValidateParam($filePath, _INT); |
3040 | + |
3041 | + // Validate the nonce |
3042 | + if (!$nonce->AllowedFile('layout', $this->displayId, NULL, $fileId)) |
3043 | + throw new SoapFault('Receiver', 'Requested an invalid file.'); |
3044 | + |
3045 | + try { |
3046 | + $dbh = PDOConnect::init(); |
3047 | + |
3048 | + $sth = $dbh->prepare('SELECT xml FROM layout WHERE layoutid = :layoutid'); |
3049 | + $sth->execute(array('layoutid' => $fileId)); |
3050 | + |
3051 | + if (!$row = $sth->fetch()) |
3052 | + throw new Exception('No file found with that ID'); |
3053 | + |
3054 | + $file = $row['xml']; |
3055 | + |
3056 | + // Store file size for bandwidth log |
3057 | + $chunkSize = strlen($file); |
3058 | + } |
3059 | + catch (Exception $e) { |
3060 | + Debug::LogEntry('error', $e->getMessage()); |
3061 | return new SoapFault('Receiver', 'Unable the find layout.'); |
3062 | } |
3063 | - |
3064 | - $row = $db->get_row($results); |
3065 | - $file = $row[0]; |
3066 | - |
3067 | - // Store file size for bandwidth log |
3068 | - $chunkSize = strlen($file); |
3069 | } |
3070 | - elseif ($fileType == "media") |
3071 | + else if ($fileType == "media") |
3072 | { |
3073 | - $filePath = Kit::ValidateParam($filePath, _STRING); |
3074 | - |
3075 | + // Get the ID |
3076 | if (strstr($filePath, '/') || strstr($filePath, '\\')) |
3077 | - { |
3078 | throw new SoapFault('Receiver', "Invalid file path."); |
3079 | - } |
3080 | |
3081 | + // Validate the nonce |
3082 | + if (!$nonce->AllowedFile('oldfile', $this->displayId, $filePath)) |
3083 | + throw new SoapFault('Receiver', 'Requested an invalid file.'); |
3084 | + |
3085 | // Return the Chunk size specified |
3086 | - $f = fopen($libraryLocation.$filePath,"r"); |
3087 | + $f = fopen($libraryLocation . $filePath, 'r'); |
3088 | |
3089 | fseek($f, $chunkOffset); |
3090 | |
3091 | $file = fread($f, $chunkSize); |
3092 | + |
3093 | + // Store file size for bandwidth log |
3094 | + $chunkSize = strlen($file); |
3095 | } |
3096 | - else |
3097 | - { |
3098 | + else { |
3099 | throw new SoapFault('Receiver', 'Unknown FileType Requested.'); |
3100 | } |
3101 | |
3102 | - if ($this->isAuditing == 1) Debug::LogEntry("audit", "[OUT]", "xmds", "GetFile"); |
3103 | - |
3104 | // Log Bandwidth |
3105 | - $this->LogBandwidth($this->displayId, 4, $chunkSize); |
3106 | + $this->LogBandwidth($this->displayId, Bandwidth::$GETFILE, $chunkSize); |
3107 | |
3108 | return $file; |
3109 | } |
3110 | @@ -466,18 +461,12 @@ |
3111 | */ |
3112 | function Schedule($serverKey, $hardwareKey, $version) |
3113 | { |
3114 | - $db =& $this->db; |
3115 | - |
3116 | // Sanitize |
3117 | - $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3118 | - $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3119 | - $version = Kit::ValidateParam($version, _STRING); |
3120 | + $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3121 | + $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3122 | $rfLookahead = Kit::ValidateParam(Config::GetSetting('REQUIRED_FILES_LOOKAHEAD'), _INT); |
3123 | |
3124 | - // Make sure we are talking the same language |
3125 | - if (!$this->CheckVersion($version)) |
3126 | - throw new SoapFault('Sender', "Your client is not of the correct version for communication with this server."); |
3127 | - |
3128 | + // Check the serverKey matches |
3129 | if ($serverKey != Config::GetSetting('SERVER_KEY')) |
3130 | throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); |
3131 | |
3132 | @@ -489,9 +478,6 @@ |
3133 | if (!$this->AuthDisplay($hardwareKey)) |
3134 | throw new SoapFault('Sender', "This display client is not licensed"); |
3135 | |
3136 | - if ($this->isAuditing == 1) |
3137 | - Debug::LogEntry("audit", "[IN] $hardwareKey", 'xmds', 'Schedule', '', $this->displayId); |
3138 | - |
3139 | $scheduleXml = new DOMDocument("1.0"); |
3140 | $layoutElements = $scheduleXml->createElement("schedule"); |
3141 | |
3142 | @@ -512,57 +498,70 @@ |
3143 | |
3144 | if ($this->isAuditing == 1) |
3145 | Debug::LogEntry('audit', sprintf('FromDT = %s. ToDt = %s', date('Y-m-d h:i:s', $fromFilter), date('Y-m-d h:i:s', $toFilter)), 'xmds', 'Schedule', '', $this->displayId); |
3146 | - |
3147 | - // Add file nodes to the $fileElements |
3148 | - // Firstly get all the scheduled layouts |
3149 | - $SQL = " SELECT layout.layoutID, schedule_detail.FromDT, schedule_detail.ToDT, schedule_detail.eventID, schedule_detail.is_priority, "; |
3150 | - $SQL .= " (SELECT GROUP_CONCAT(StoredAs) FROM media INNER JOIN lklayoutmedia ON lklayoutmedia.MediaID = media.MediaID WHERE lklayoutmedia.LayoutID = layout.LayoutID GROUP BY lklayoutmedia.LayoutID) AS Dependents"; |
3151 | - $SQL .= " FROM `campaign` "; |
3152 | - $SQL .= " INNER JOIN schedule_detail ON schedule_detail.CampaignID = campaign.CampaignID "; |
3153 | - $SQL .= " INNER JOIN `lkcampaignlayout` ON lkcampaignlayout.CampaignID = campaign.CampaignID "; |
3154 | - $SQL .= " INNER JOIN `layout` ON lkcampaignlayout.LayoutID = layout.LayoutID "; |
3155 | - $SQL .= " INNER JOIN lkdisplaydg ON lkdisplaydg.DisplayGroupID = schedule_detail.DisplayGroupID "; |
3156 | - $SQL .= sprintf(" WHERE lkdisplaydg.DisplayID = %d ", $this->displayId); |
3157 | - $SQL .= sprintf(" AND (schedule_detail.FromDT < %d AND schedule_detail.ToDT > %d )", $toFilter, $fromFilter); |
3158 | - $SQL .= " AND layout.retired = 0 "; |
3159 | - $SQL .= " ORDER BY schedule_detail.DisplayOrder, lkcampaignlayout.DisplayOrder, schedule_detail.eventID "; |
3160 | - |
3161 | - if ($this->isAuditing == 1) |
3162 | - Debug::LogEntry("audit", $SQL, 'xmds', 'Schedule', '', $this->displayId); |
3163 | - |
3164 | - // Run the query |
3165 | - if (!$results = $db->query($SQL)) |
3166 | - { |
3167 | - trigger_error($db->error()); |
3168 | + |
3169 | + try { |
3170 | + $dbh = PDOConnect::init(); |
3171 | + |
3172 | + // Get all the module dependants |
3173 | + $sth = $dbh->prepare("SELECT DISTINCT StoredAs FROM `media` WHERE media.type = 'font' OR (media.type = 'module' AND media.moduleSystemFile = 1) "); |
3174 | + $sth->execute(array()); |
3175 | + $rows = $sth->fetchAll(); |
3176 | + $moduleDependents = array(); |
3177 | + |
3178 | + foreach($rows as $dependent) |
3179 | + $moduleDependents[] = $dependent['StoredAs']; |
3180 | + |
3181 | + // Add file nodes to the $fileElements |
3182 | + // Firstly get all the scheduled layouts |
3183 | + $SQL = " SELECT layout.layoutID, schedule_detail.FromDT, schedule_detail.ToDT, schedule.eventID, schedule.is_priority, "; |
3184 | + $SQL .= " (SELECT GROUP_CONCAT(DISTINCT StoredAs) FROM media INNER JOIN lklayoutmedia ON lklayoutmedia.MediaID = media.MediaID WHERE lklayoutmedia.LayoutID = layout.LayoutID AND lklayoutmedia.regionID <> 'module' GROUP BY lklayoutmedia.LayoutID) AS Dependents"; |
3185 | + $SQL .= " FROM `campaign` "; |
3186 | + $SQL .= " INNER JOIN schedule ON schedule.CampaignID = campaign.CampaignID "; |
3187 | + $SQL .= " INNER JOIN schedule_detail ON schedule_detail.eventID = schedule.eventID "; |
3188 | + $SQL .= " INNER JOIN `lkcampaignlayout` ON lkcampaignlayout.CampaignID = campaign.CampaignID "; |
3189 | + $SQL .= " INNER JOIN `layout` ON lkcampaignlayout.LayoutID = layout.LayoutID "; |
3190 | + $SQL .= " INNER JOIN lkdisplaydg ON lkdisplaydg.DisplayGroupID = schedule_detail.DisplayGroupID "; |
3191 | + $SQL .= " WHERE lkdisplaydg.DisplayID = :displayId "; |
3192 | + $SQL .= " AND (schedule_detail.FromDT < :fromdt AND schedule_detail.ToDT > :todt )"; |
3193 | + $SQL .= " AND layout.retired = 0 "; |
3194 | + $SQL .= " ORDER BY schedule.DisplayOrder, lkcampaignlayout.DisplayOrder, schedule_detail.eventID "; |
3195 | + |
3196 | + $sth = $dbh->prepare($SQL); |
3197 | + $sth->execute(array( |
3198 | + 'displayId' => $this->displayId, |
3199 | + 'fromdt' => $toFilter, |
3200 | + 'todt' => $fromFilter |
3201 | + )); |
3202 | + |
3203 | + // We must have some results in here by this point |
3204 | + foreach ($sth->fetchAll() as $row) { |
3205 | + $layoutid = $row[0]; |
3206 | + $fromdt = date('Y-m-d H:i:s', $row[1]); |
3207 | + $todt = date('Y-m-d H:i:s', $row[2]); |
3208 | + $scheduleid = $row[3]; |
3209 | + $is_priority = Kit::ValidateParam($row[4], _INT); |
3210 | + $dependents = implode(',', $moduleDependents) . ',' . Kit::ValidateParam($row[5], _STRING); |
3211 | + |
3212 | + // Add a layout node to the schedule |
3213 | + $layout = $scheduleXml->createElement("layout"); |
3214 | + |
3215 | + $layout->setAttribute("file", $layoutid); |
3216 | + $layout->setAttribute("fromdt", $fromdt); |
3217 | + $layout->setAttribute("todt", $todt); |
3218 | + $layout->setAttribute("scheduleid", $scheduleid); |
3219 | + $layout->setAttribute("priority", $is_priority); |
3220 | + $layout->setAttribute("dependents", $dependents); |
3221 | + |
3222 | + $layoutElements->appendChild($layout); |
3223 | + } |
3224 | + } |
3225 | + catch (Exception $e) { |
3226 | + Debug::LogEntry('error', $e->getMessage()); |
3227 | return new SoapFault('Unable to get A list of layouts for the schedule'); |
3228 | } |
3229 | |
3230 | - // We must have some results in here by this point |
3231 | - while ($row = $db->get_row($results)) |
3232 | - { |
3233 | - $layoutid = $row[0]; |
3234 | - $fromdt = date('Y-m-d H:i:s', $row[1]); |
3235 | - $todt = date('Y-m-d H:i:s', $row[2]); |
3236 | - $scheduleid = $row[3]; |
3237 | - $is_priority = Kit::ValidateParam($row[4], _INT); |
3238 | - $dependents = Kit::ValidateParam($row[5], _STRING); |
3239 | - |
3240 | - // Add a layout node to the schedule |
3241 | - $layout = $scheduleXml->createElement("layout"); |
3242 | - |
3243 | - $layout->setAttribute("file", $layoutid); |
3244 | - $layout->setAttribute("fromdt", $fromdt); |
3245 | - $layout->setAttribute("todt", $todt); |
3246 | - $layout->setAttribute("scheduleid", $scheduleid); |
3247 | - $layout->setAttribute("priority", $is_priority); |
3248 | - $layout->setAttribute("dependents", $dependents); |
3249 | - |
3250 | - $layoutElements->appendChild($layout); |
3251 | - } |
3252 | - |
3253 | // Are we interleaving the default? |
3254 | - if ($this->includeSchedule == 1) |
3255 | - { |
3256 | + if ($this->includeSchedule == 1) { |
3257 | // Add as a node at the end of the schedule. |
3258 | $layout = $scheduleXml->createElement("layout"); |
3259 | |
3260 | @@ -571,6 +570,7 @@ |
3261 | $layout->setAttribute("todt", '2030-01-19 00:00:00'); |
3262 | $layout->setAttribute("scheduleid", 0); |
3263 | $layout->setAttribute("priority", 0); |
3264 | + $layout->setAttribute("dependents", implode(',', $moduleDependents)); |
3265 | |
3266 | $layoutElements->appendChild($layout); |
3267 | } |
3268 | @@ -580,16 +580,25 @@ |
3269 | $default->setAttribute("file", $this->defaultLayoutId); |
3270 | $layoutElements->appendChild($default); |
3271 | |
3272 | + // Add on a list of global dependants |
3273 | + $globalDependents = $scheduleXml->createElement("dependants"); |
3274 | + |
3275 | + foreach ($moduleDependents as $dep) { |
3276 | + $dependent = $scheduleXml->createElement("file", $dep); |
3277 | + $globalDependents->appendChild($dependent); |
3278 | + } |
3279 | + $layoutElements->appendChild($globalDependents); |
3280 | + |
3281 | // Format the output |
3282 | $scheduleXml->formatOutput = true; |
3283 | |
3284 | if ($this->isAuditing == 1) |
3285 | - Debug::LogEntry("audit", $scheduleXml->saveXML(), 'xmds', 'Schedule', '', $this->displayId); |
3286 | + Debug::LogEntry("audit", $scheduleXml->saveXML(), "xmds", "Schedule"); |
3287 | |
3288 | $output = $scheduleXml->saveXML(); |
3289 | |
3290 | // Log Bandwidth |
3291 | - $this->LogBandwidth($this->displayId, 3, strlen($output)); |
3292 | + $this->LogBandwidth($this->displayId, Bandwidth::$SCHEDULE, strlen($output)); |
3293 | |
3294 | return $output; |
3295 | } |
3296 | @@ -603,22 +612,14 @@ |
3297 | */ |
3298 | function BlackList($serverKey, $hardwareKey, $mediaId, $type, $reason, $version) |
3299 | { |
3300 | - $db =& $this->db; |
3301 | - |
3302 | // Sanitize |
3303 | - $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3304 | - $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3305 | - $mediaId = Kit::ValidateParam($mediaId, _STRING); |
3306 | - $type = Kit::ValidateParam($type, _STRING); |
3307 | - $reason = Kit::ValidateParam($reason, _STRING); |
3308 | - $version = Kit::ValidateParam($version, _STRING); |
3309 | - |
3310 | - // Make sure we are talking the same language |
3311 | - if (!$this->CheckVersion($version)) |
3312 | - { |
3313 | - throw new SoapFault('Receiver', "Your client is not of the correct version for communication with this server.", $serverKey); |
3314 | - } |
3315 | - |
3316 | + $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3317 | + $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3318 | + $mediaId = Kit::ValidateParam($mediaId, _STRING); |
3319 | + $type = Kit::ValidateParam($type, _STRING); |
3320 | + $reason = Kit::ValidateParam($reason, _STRING); |
3321 | + |
3322 | + // Check the serverKey matches |
3323 | if ($serverKey != Config::GetSetting('SERVER_KEY')) |
3324 | throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); |
3325 | |
3326 | @@ -626,58 +627,67 @@ |
3327 | if (!$this->CheckBandwidth()) |
3328 | throw new SoapFault('Receiver', "Bandwidth Limit exceeded"); |
3329 | |
3330 | - // Auth this request... |
3331 | + // Authenticate this request... |
3332 | if (!$this->AuthDisplay($hardwareKey)) |
3333 | - { |
3334 | - throw new SoapFault('Receiver', "This display client is not licensed", $hardwareKey); |
3335 | + throw new SoapFault('Receiver', "This display client is not licensed", $hardwareKey); |
3336 | + |
3337 | + if ($this->isAuditing == 1) |
3338 | + Debug::LogEntry( "audit", "[IN] $xml", "xmds", "BlackList", "", $this->displayId); |
3339 | + |
3340 | + try { |
3341 | + $dbh = PDOConnect::init(); |
3342 | + |
3343 | + // Check to see if this media / display is already blacklisted (and not ignored) |
3344 | + $sth = $dbh->prepare('SELECT BlackListID FROM blacklist WHERE MediaID = :mediaid AND isIgnored = 0 AND DisplayID = :displayid'); |
3345 | + $sth->execute(array( |
3346 | + 'mediaid' => $mediaId, |
3347 | + 'displayid' => $this->displayId |
3348 | + )); |
3349 | + |
3350 | + $results = $sth->fetchAll(); |
3351 | + |
3352 | + if (count($results) == 0) { |
3353 | + |
3354 | + $insertSth = $dbh->prepare(' |
3355 | + INSERT INTO blacklist (MediaID, DisplayID, ReportingDisplayID, Reason) |
3356 | + VALUES (:mediaid, :displayid, :reportingdisplayid, :reason) |
3357 | + '); |
3358 | + |
3359 | + // Insert the black list record |
3360 | + if ($type == BLACKLIST_SINGLE) { |
3361 | + $insertSth->execute(array( |
3362 | + 'mediaid' => $mediaId, |
3363 | + 'displayid' => $displayId, |
3364 | + 'reportingdisplayid' => $this->displayId, |
3365 | + 'reason' => $reason |
3366 | + )); |
3367 | + } |
3368 | + else { |
3369 | + $displaySth = $dbh->prepare('SELECT displayID FROM `display`'); |
3370 | + $displaySth->execute(); |
3371 | + |
3372 | + foreach ($displaySth->fetchAll() as $row) { |
3373 | + |
3374 | + $insertSth->execute(array( |
3375 | + 'mediaid' => $mediaId, |
3376 | + 'displayid' => $row['displayID'], |
3377 | + 'reportingdisplayid' => $this->displayId, |
3378 | + 'reason' => $reason |
3379 | + )); |
3380 | + } |
3381 | + } |
3382 | + } |
3383 | + else { |
3384 | + if ($this->isAuditing == 1) |
3385 | + Debug::LogEntry( "audit", "Media Already BlackListed [$mediaId]", "xmds", "BlackList", "", $this->displayId); |
3386 | + } |
3387 | } |
3388 | - |
3389 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "[IN]", "xmds", "BlackList", "", $this->displayId); |
3390 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "$xml", "xmds", "BlackList", "", $this->displayId); |
3391 | - |
3392 | - // Check to see if this media/display is already blacklisted (and not ignored) |
3393 | - $SQL = "SELECT BlackListID FROM blacklist WHERE MediaID = $mediaId AND isIgnored = 0 AND DisplayID = " . $this->displayId; |
3394 | - |
3395 | - if (!$results = $db->query($SQL)) |
3396 | - { |
3397 | - trigger_error($db->error()); |
3398 | + catch (Exception $e) { |
3399 | + Debug::LogEntry('error', $e->getMessage()); |
3400 | return new SoapFault("Unable to query for BlackList records."); |
3401 | } |
3402 | |
3403 | - if ($db->num_rows($results) == 0) |
3404 | - { |
3405 | - // Insert the black list record |
3406 | - $SQL = "SELECT displayID FROM display"; |
3407 | - |
3408 | - if ($type == BLACKLIST_SINGLE) |
3409 | - $SQL .= " WHERE displayID = " . $this->displayId; |
3410 | - |
3411 | - if (!$displays = $db->query($SQL)) |
3412 | - { |
3413 | - trigger_error($db->error()); |
3414 | - return new SoapFault("Unable to query for BlackList Displays."); |
3415 | - } |
3416 | - |
3417 | - while ($row = $db->get_row($displays)) |
3418 | - { |
3419 | - $displayId = $row[0]; |
3420 | - |
3421 | - $SQL = "INSERT INTO blacklist (MediaID, DisplayID, ReportingDisplayID, Reason) |
3422 | - VALUES ($mediaId, $displayId, " . $this->displayId . ", '$reason') "; |
3423 | - |
3424 | - if (!$db->query($SQL)) |
3425 | - { |
3426 | - trigger_error($db->error()); |
3427 | - return new SoapFault("Unable to insert BlackList records."); |
3428 | - } |
3429 | - } |
3430 | - } |
3431 | - else |
3432 | - { |
3433 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "Media Already BlackListed [$mediaId]", "xmds", "BlackList", "", $this->displayId); |
3434 | - } |
3435 | - |
3436 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "[OUT]", "xmds", "BlackList", "", $this->displayId); |
3437 | + $this->LogBandwidth($this->displayId, Bandwidth::$BLACKLIST, strlen($reason)); |
3438 | |
3439 | return true; |
3440 | } |
3441 | @@ -685,111 +695,91 @@ |
3442 | /** |
3443 | * Submit client logging |
3444 | * @return |
3445 | - * @param $version Object |
3446 | * @param $serverKey Object |
3447 | * @param $hardwareKey Object |
3448 | * @param $logXml Object |
3449 | */ |
3450 | function SubmitLog($version, $serverKey, $hardwareKey, $logXml) |
3451 | { |
3452 | - $db =& $this->db; |
3453 | - |
3454 | // Sanitize |
3455 | - $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3456 | - $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3457 | - $version = Kit::ValidateParam($version, _STRING); |
3458 | - $logXml = Kit::ValidateParam($logXml, _HTMLSTRING); |
3459 | - |
3460 | - // Make sure we are talking the same language |
3461 | - if (!$this->CheckVersion($version)) |
3462 | - { |
3463 | - throw new SoapFault('Sender', "Your client is not of the correct version for communication with this server."); |
3464 | - } |
3465 | - |
3466 | + $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3467 | + $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3468 | + $logXml = Kit::ValidateParam($logXml, _HTMLSTRING); |
3469 | + |
3470 | + // Check the serverKey matches |
3471 | if ($serverKey != Config::GetSetting('SERVER_KEY')) |
3472 | - throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); |
3473 | - |
3474 | + throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address. '); |
3475 | + |
3476 | // Make sure we are sticking to our bandwidth limit |
3477 | if (!$this->CheckBandwidth()) |
3478 | throw new SoapFault('Receiver', "Bandwidth Limit exceeded"); |
3479 | |
3480 | // Auth this request... |
3481 | if (!$this->AuthDisplay($hardwareKey)) |
3482 | - { |
3483 | throw new SoapFault('Sender', 'This display client is not licensed.'); |
3484 | - } |
3485 | - |
3486 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "IN", "xmds", "SubmitLog", "", $this->displayId); |
3487 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", 'XML [' . $logXml . ']', "xmds", "SubmitLog", "", $this->displayId); |
3488 | + |
3489 | + if ($this->isAuditing == 1) |
3490 | + Debug::LogEntry( "audit", 'IN. XML [' . $logXml . ']', "xmds", "SubmitLog", "", $this->displayId); |
3491 | |
3492 | // Load the XML into a DOMDocument |
3493 | $document = new DOMDocument("1.0"); |
3494 | |
3495 | if (!$document->loadXML($logXml)) |
3496 | - { |
3497 | throw new SoapFault('Receiver', "XML Cannot be loaded into DOM Document."); |
3498 | - } |
3499 | |
3500 | - foreach ($document->documentElement->childNodes as $node) |
3501 | - { |
3502 | + foreach ($document->documentElement->childNodes as $node) { |
3503 | + |
3504 | // Make sure we dont consider any text nodes |
3505 | - if ($node->nodeType == XML_TEXT_NODE) continue; |
3506 | + if ($node->nodeType == XML_TEXT_NODE) |
3507 | + continue; |
3508 | |
3509 | - //Zero out the common vars |
3510 | - $date = ""; |
3511 | - $message = ""; |
3512 | + // Zero out the common vars |
3513 | + $date = ""; |
3514 | + $message = ""; |
3515 | $scheduleID = ""; |
3516 | - $layoutID = ""; |
3517 | - $mediaID = ""; |
3518 | - $cat = ''; |
3519 | - $method = ''; |
3520 | + $layoutID = ""; |
3521 | + $mediaID = ""; |
3522 | + $cat = ''; |
3523 | + $method = ''; |
3524 | $thread = ''; |
3525 | |
3526 | // This will be a bunch of trace nodes |
3527 | $message = $node->textContent; |
3528 | |
3529 | - if ($this->isAuditing == 1) |
3530 | - Debug::LogEntry( "audit", 'Trace Message: [' . $message . ']', "xmds", "SubmitLog", "", $this->displayId); |
3531 | + // if ($this->isAuditing == 1) |
3532 | + // Debug::LogEntry("audit", 'Trace Message: [' . $message . ']', "xmds", "SubmitLog", "", $this->displayId); |
3533 | |
3534 | // Each element should have a category and a date |
3535 | - $date = $node->getAttribute('date'); |
3536 | - $cat = strtolower($node->getAttribute('category')); |
3537 | + $date = $node->getAttribute('date'); |
3538 | + $cat = strtolower($node->getAttribute('category')); |
3539 | |
3540 | - if ($date == '' || $cat == '') |
3541 | - { |
3542 | + if ($date == '' || $cat == '') { |
3543 | trigger_error('Log submitted without a date or category attribute'); |
3544 | continue; |
3545 | } |
3546 | |
3547 | // Get the date and the message (all log types have these) |
3548 | - foreach ($node->childNodes as $nodeElements) |
3549 | - { |
3550 | - if ($nodeElements->nodeName == "scheduleID") |
3551 | - { |
3552 | + foreach ($node->childNodes as $nodeElements) { |
3553 | + |
3554 | + if ($nodeElements->nodeName == "scheduleID") { |
3555 | $scheduleID = $nodeElements->textContent; |
3556 | } |
3557 | - else if ($nodeElements->nodeName == "layoutID") |
3558 | - { |
3559 | + else if ($nodeElements->nodeName == "layoutID") { |
3560 | $layoutID = $nodeElements->textContent; |
3561 | } |
3562 | - else if ($nodeElements->nodeName == "mediaID") |
3563 | - { |
3564 | + else if ($nodeElements->nodeName == "mediaID") { |
3565 | $mediaID = $nodeElements->textContent; |
3566 | } |
3567 | - else if ($nodeElements->nodeName == "type") |
3568 | - { |
3569 | + else if ($nodeElements->nodeName == "type") { |
3570 | $type = $nodeElements->textContent; |
3571 | } |
3572 | - else if ($nodeElements->nodeName == "method") |
3573 | - { |
3574 | + else if ($nodeElements->nodeName == "method") { |
3575 | $method = $nodeElements->textContent; |
3576 | } |
3577 | - else if ($nodeElements->nodeName == "message") |
3578 | - { |
3579 | + else if ($nodeElements->nodeName == "message") { |
3580 | $message = $nodeElements->textContent; |
3581 | } |
3582 | - else if ($nodeElements->nodeName == "thread") |
3583 | - { |
3584 | + else if ($nodeElements->nodeName == "thread") { |
3585 | if ($nodeElements->textContent != '') |
3586 | $thread = '[' . $nodeElements->textContent . '] '; |
3587 | } |
3588 | @@ -805,7 +795,7 @@ |
3589 | Debug::LogEntry($logType, $message, 'Client', $thread . $method, $date, $this->displayId, $scheduleID, $layoutID, $mediaID); |
3590 | } |
3591 | |
3592 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "OUT", "xmds", "SubmitLog", "", $this->displayId); |
3593 | + $this->LogBandwidth($this->displayId, Bandwidth::$SUBMITLOG, strlen($logXml)); |
3594 | |
3595 | return true; |
3596 | } |
3597 | @@ -813,100 +803,84 @@ |
3598 | /** |
3599 | * Submit display statistics to the server |
3600 | * @return |
3601 | - * @param $version Object |
3602 | * @param $serverKey Object |
3603 | * @param $hardwareKey Object |
3604 | * @param $statXml Object |
3605 | */ |
3606 | function SubmitStats($version, $serverKey, $hardwareKey, $statXml) |
3607 | { |
3608 | - $db =& $this->db; |
3609 | - |
3610 | // Sanitize |
3611 | - $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3612 | - $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3613 | - $version = Kit::ValidateParam($version, _STRING); |
3614 | - $statXml = Kit::ValidateParam($statXml, _HTMLSTRING); |
3615 | - |
3616 | - // Make sure we are talking the same language |
3617 | - if (!$this->CheckVersion($version)) |
3618 | - { |
3619 | - throw new SoapFault('Receiver', "Your client is not of the correct version for communication with this server."); |
3620 | - } |
3621 | - |
3622 | + $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3623 | + $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3624 | + $statXml = Kit::ValidateParam($statXml, _HTMLSTRING); |
3625 | + |
3626 | + // Check the serverKey matches |
3627 | if ($serverKey != Config::GetSetting('SERVER_KEY')) |
3628 | throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); |
3629 | - |
3630 | + |
3631 | // Make sure we are sticking to our bandwidth limit |
3632 | if (!$this->CheckBandwidth()) |
3633 | throw new SoapFault('Receiver', "Bandwidth Limit exceeded"); |
3634 | |
3635 | // Auth this request... |
3636 | if (!$this->AuthDisplay($hardwareKey)) |
3637 | - { |
3638 | throw new SoapFault('Receiver', "This display client is not licensed"); |
3639 | - } |
3640 | - |
3641 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "IN", "xmds", "SubmitStats", "", $this->displayId); |
3642 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "StatXml: [" . $statXml . "]", "xmds", "SubmitStats", "", $this->displayId); |
3643 | + |
3644 | + if ($this->isAuditing == 1) |
3645 | + Debug::LogEntry( "audit", "IN. StatXml: [" . $statXml . "]", "xmds", "SubmitStats", "", $this->displayId); |
3646 | |
3647 | if ($statXml == "") |
3648 | - { |
3649 | throw new SoapFault('Receiver', "Stat XML is empty."); |
3650 | - } |
3651 | - |
3652 | - // Log |
3653 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "About to create Stat Object.", "xmds", "SubmitStats", "", $this->displayId); |
3654 | - |
3655 | - $statObject = new Stat($db); |
3656 | - |
3657 | - // Log |
3658 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "About to Create DOMDocument.", "xmds", "SubmitStats", "", $this->displayId); |
3659 | + |
3660 | + // Log |
3661 | + $statObject = new Stat(); |
3662 | + |
3663 | + // Log |
3664 | + if ($this->isAuditing == 1) |
3665 | + Debug::LogEntry( "audit", "About to Create DOMDocument.", "xmds", "SubmitStats", "", $this->displayId); |
3666 | |
3667 | // Load the XML into a DOMDocument |
3668 | $document = new DOMDocument("1.0"); |
3669 | $document->loadXML($statXml); |
3670 | |
3671 | - foreach ($document->documentElement->childNodes as $node) |
3672 | - { |
3673 | + foreach ($document->documentElement->childNodes as $node) { |
3674 | // Make sure we dont consider any text nodes |
3675 | - if ($node->nodeType == XML_TEXT_NODE) continue; |
3676 | + if ($node->nodeType == XML_TEXT_NODE) |
3677 | + continue; |
3678 | |
3679 | - //Zero out the common vars |
3680 | + // Zero out the common vars |
3681 | $fromdt = ''; |
3682 | - $todt = ''; |
3683 | - $type = ''; |
3684 | + $todt = ''; |
3685 | + $type = ''; |
3686 | |
3687 | $scheduleID = 0; |
3688 | - $layoutID = 0; |
3689 | - $mediaID = ''; |
3690 | - $tag = ''; |
3691 | + $layoutID = 0; |
3692 | + $mediaID = ''; |
3693 | + $tag = ''; |
3694 | |
3695 | // Each element should have these attributes |
3696 | $fromdt = $node->getAttribute('fromdt'); |
3697 | - $todt = $node->getAttribute('todt'); |
3698 | - $type = $node->getAttribute('type'); |
3699 | + $todt = $node->getAttribute('todt'); |
3700 | + $type = $node->getAttribute('type'); |
3701 | |
3702 | - if ($fromdt == '' || $todt == '' || $type == '') |
3703 | - { |
3704 | + if ($fromdt == '' || $todt == '' || $type == '') { |
3705 | trigger_error('Stat submitted without the fromdt, todt or type attributes.'); |
3706 | continue; |
3707 | } |
3708 | |
3709 | $scheduleID = $node->getAttribute('scheduleid'); |
3710 | - $layoutID = $node->getAttribute('layoutid'); |
3711 | - $mediaID = $node->getAttribute('mediaid'); |
3712 | - $tag = $node->getAttribute('tag'); |
3713 | + $layoutID = $node->getAttribute('layoutid'); |
3714 | + $mediaID = $node->getAttribute('mediaid'); |
3715 | + $tag = $node->getAttribute('tag'); |
3716 | |
3717 | // Write the stat record with the information we have available to us. |
3718 | - if (!$statObject->Add($type, $fromdt, $todt, $scheduleID, $this->displayId, $layoutID, $mediaID, $tag)) |
3719 | - { |
3720 | + if (!$statObject->Add($type, $fromdt, $todt, $scheduleID, $this->displayId, $layoutID, $mediaID, $tag)) { |
3721 | trigger_error(sprintf('Stat Add failed with error: %s', $statObject->GetErrorMessage())); |
3722 | continue; |
3723 | } |
3724 | } |
3725 | |
3726 | - if ($this->isAuditing == 1) Debug::LogEntry( "audit", "OUT", "xmds", "SubmitStats", "", $this->displayId); |
3727 | + $this->LogBandwidth($this->displayId, Bandwidth::$SUBMITSTATS, strlen($statXml)); |
3728 | |
3729 | return true; |
3730 | } |
3731 | @@ -918,18 +892,12 @@ |
3732 | */ |
3733 | public function MediaInventory($version, $serverKey, $hardwareKey, $inventory) |
3734 | { |
3735 | - $db =& $this->db; |
3736 | - |
3737 | // Sanitize |
3738 | - $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3739 | - $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3740 | - $version = Kit::ValidateParam($version, _STRING); |
3741 | - $inventory = Kit::ValidateParam($inventory, _HTMLSTRING); |
3742 | - |
3743 | - // Make sure we are talking the same language |
3744 | - if (!$this->CheckVersion($version)) |
3745 | - throw new SoapFault('Receiver', "Your client is not of the correct version for communication with this server."); |
3746 | - |
3747 | + $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3748 | + $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3749 | + $inventory = Kit::ValidateParam($inventory, _HTMLSTRING); |
3750 | + |
3751 | + // Check the serverKey matches |
3752 | if ($serverKey != Config::GetSetting('SERVER_KEY')) |
3753 | throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); |
3754 | |
3755 | @@ -941,7 +909,8 @@ |
3756 | if (!$this->AuthDisplay($hardwareKey)) |
3757 | throw new SoapFault('Receiver', 'This display client is not licensed'); |
3758 | |
3759 | - if ($this->isAuditing == 1) Debug::LogEntry( 'audit', $inventory, 'xmds', 'MediaInventory', '', $this->displayId); |
3760 | + if ($this->isAuditing == 1) |
3761 | + Debug::LogEntry( 'audit', $inventory, 'xmds', 'MediaInventory', '', $this->displayId); |
3762 | |
3763 | // Check that the $inventory contains something |
3764 | if ($inventory == '') |
3765 | @@ -951,20 +920,13 @@ |
3766 | $document = new DOMDocument("1.0"); |
3767 | $document->loadXML($inventory); |
3768 | |
3769 | - // Get some information from the media inventory XML and update the display record with it. |
3770 | - $macAddress = Kit::ValidateParam($document->documentElement->getAttribute('macAddress'), _STRING); |
3771 | - $clientType = Kit::ValidateParam($document->documentElement->getAttribute('clientType'), _STRING); |
3772 | - $clientVersion = Kit::ValidateParam($document->documentElement->getAttribute('clientVersion'), _STRING); |
3773 | - $clientCode = Kit::ValidateParam($document->documentElement->getAttribute('clientCode'), _INT); |
3774 | - |
3775 | // Assume we are complete (but we are getting some) |
3776 | $mediaInventoryComplete = 1; |
3777 | |
3778 | $xpath = new DOMXPath($document); |
3779 | $fileNodes = $xpath->query("//file"); |
3780 | |
3781 | - foreach ($fileNodes as $node) |
3782 | - { |
3783 | + foreach ($fileNodes as $node) { |
3784 | $mediaId = $node->getAttribute('id'); |
3785 | $complete = $node->getAttribute('complete'); |
3786 | $md5 = $node->getAttribute('md5'); |
3787 | @@ -978,8 +940,10 @@ |
3788 | } |
3789 | |
3790 | // Touch the display record |
3791 | - $displayObject = new Display($db); |
3792 | - $displayObject->Touch($hardwareKey, '', $mediaInventoryComplete, $inventory, $macAddress, $clientType, $clientVersion, $clientCode); |
3793 | + $displayObject = new Display(); |
3794 | + $displayObject->Touch($this->displayId, array('mediaInventoryStatus' => $mediaInventoryComplete, 'mediaInventoryXml' => $inventory)); |
3795 | + |
3796 | + $this->LogBandwidth($this->displayId, Bandwidth::$MEDIAINVENTORY, strlen($inventory)); |
3797 | |
3798 | return true; |
3799 | } |
3800 | @@ -991,24 +955,17 @@ |
3801 | * @param <type> $layoutId |
3802 | * @param <type> $regionId |
3803 | * @param <type> $mediaId |
3804 | - * @param <type> $version |
3805 | */ |
3806 | function GetResource($serverKey, $hardwareKey, $layoutId, $regionId, $mediaId, $version) |
3807 | { |
3808 | - $db =& $this->db; |
3809 | - |
3810 | // Sanitize |
3811 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
3812 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
3813 | $layoutId = Kit::ValidateParam($layoutId, _INT); |
3814 | $regionId = Kit::ValidateParam($regionId, _STRING); |
3815 | $mediaId = Kit::ValidateParam($mediaId, _STRING); |
3816 | - $version = Kit::ValidateParam($version, _STRING); |
3817 | - |
3818 | - // Make sure we are talking the same language |
3819 | - if (!$this->CheckVersion($version)) |
3820 | - throw new SoapFault('Receiver', "Your client is not of the correct version for communication with this server."); |
3821 | - |
3822 | + |
3823 | + // Check the serverKey matches |
3824 | if ($serverKey != Config::GetSetting('SERVER_KEY')) |
3825 | throw new SoapFault('Sender', 'The Server key you entered does not match with the server key at this address'); |
3826 | |
3827 | @@ -1020,23 +977,32 @@ |
3828 | if (!$this->AuthDisplay($hardwareKey)) |
3829 | throw new SoapFault('Receiver', "This display client is not licensed"); |
3830 | |
3831 | + // Validate the nonce |
3832 | + $nonce = new Nonce(); |
3833 | + if (!$nonce->AllowedFile('resource', $this->displayId, NULL, $layoutId, $regionId, $mediaId)) |
3834 | + throw new SoapFault('Receiver', 'Requested an invalid file.'); |
3835 | + |
3836 | // What type of module is this? |
3837 | Kit::ClassLoader('region'); |
3838 | - $region = new region($db); |
3839 | + $region = new region(); |
3840 | $type = $region->GetMediaNodeType($layoutId, $regionId, $mediaId); |
3841 | |
3842 | if ($type == '') |
3843 | throw new SoapFault('Receiver', 'Unable to get the media node type'); |
3844 | |
3845 | // Dummy User Object |
3846 | - $user = new User($db); |
3847 | + $user = new User(); |
3848 | $user->userid = 0; |
3849 | $user->usertypeid = 1; |
3850 | |
3851 | + // Initialise the theme (for global styles in GetResource) |
3852 | + new Theme($user); |
3853 | + Theme::SetPagename('module'); |
3854 | + |
3855 | // Get the resource from the module |
3856 | require_once('modules/' . $type . '.module.php'); |
3857 | |
3858 | - if (!$module = new $type($db, $user, $mediaId, $layoutId, $regionId)) |
3859 | + if (!$module = new $type(new Database(), $user, $mediaId, $layoutId, $regionId)) |
3860 | throw new SoapFault('Receiver', 'Cannot create module. Check CMS Log'); |
3861 | |
3862 | $resource = $module->GetResource($this->displayId); |
3863 | @@ -1045,7 +1011,7 @@ |
3864 | throw new SoapFault('Receiver', 'Unable to get the media resource'); |
3865 | |
3866 | // Log Bandwidth |
3867 | - $this->LogBandwidth($this->displayId, 5, strlen($resource)); |
3868 | + $this->LogBandwidth($this->displayId, Bandwidth::$GETRESOURCE, strlen($resource)); |
3869 | |
3870 | return $resource; |
3871 | } |
3872 | @@ -1053,19 +1019,13 @@ |
3873 | /** |
3874 | * PHONE_HOME if required |
3875 | */ |
3876 | - private function PhoneHome() { |
3877 | - |
3878 | - if (Config::GetSetting('PHONE_HOME') == 'On') |
3879 | - { |
3880 | + private function PhoneHome() |
3881 | + { |
3882 | + if (Config::GetSetting('PHONE_HOME') == 'On') { |
3883 | // Find out when we last PHONED_HOME :D |
3884 | // If it's been > 28 days since last PHONE_HOME then |
3885 | - if (Config::GetSetting('PHONE_HOME_DATE') < (time() - (60 * 60 * 24 * 28))) |
3886 | - { |
3887 | - if ($this->isAuditing == 1) |
3888 | - { |
3889 | - Debug::LogEntry("audit", "PHONE_HOME [IN]", "xmds", "RequiredFiles"); |
3890 | - } |
3891 | - |
3892 | + if (Config::GetSetting('PHONE_HOME_DATE') < (time() - (60 * 60 * 24 * 28))) { |
3893 | + |
3894 | try { |
3895 | $dbh = PDOConnect::init(); |
3896 | |
3897 | @@ -1110,90 +1070,94 @@ |
3898 | * @param <type> $hardwareKey |
3899 | * @return <type> |
3900 | */ |
3901 | - private function AuthDisplay($hardwareKey) |
3902 | - { |
3903 | - $db =& $this->db; |
3904 | - |
3905 | - // check in the database for this hardwareKey |
3906 | - $SQL = "SELECT licensed, inc_schedule, isAuditing, displayID, defaultlayoutid, loggedin, email_alert, display, version_instructions FROM display WHERE license = '$hardwareKey'"; |
3907 | - |
3908 | - if (!$result = $db->query($SQL)) |
3909 | - { |
3910 | - trigger_error("License key query failed:" .$db->error()); |
3911 | + private function AuthDisplay($hardwareKey, $status = NULL) |
3912 | + { |
3913 | + try { |
3914 | + $dbh = PDOConnect::init(); |
3915 | + |
3916 | + $sth = $dbh->prepare(' |
3917 | + SELECT licensed, inc_schedule, isAuditing, displayID, defaultlayoutid, loggedin, |
3918 | + email_alert, display, version_instructions, client_type, client_code, client_version |
3919 | + FROM display |
3920 | + WHERE license = :hardwareKey |
3921 | + '); |
3922 | + |
3923 | + $sth->execute(array( |
3924 | + 'hardwareKey' => $hardwareKey |
3925 | + )); |
3926 | + |
3927 | + $result = $sth->fetchAll(); |
3928 | + |
3929 | + // Is it there? |
3930 | + if (count($result) == 0) |
3931 | + return false; |
3932 | + |
3933 | + // We have seen this display before, so check the licensed value |
3934 | + $row = $result[0]; |
3935 | + |
3936 | + if ($row['licensed'] == 0) |
3937 | + return false; |
3938 | + |
3939 | + // See if the client was off-line and if appropriate send an alert |
3940 | + // to say that it has come back on-line |
3941 | + $this->AlertDisplayUp($row['displayID'], $row['display'], $row['loggedin'], $row['email_alert']); |
3942 | + |
3943 | + // It is licensed? |
3944 | + $this->licensed = true; |
3945 | + $this->includeSchedule = $row['inc_schedule']; |
3946 | + $this->isAuditing = $row['isAuditing']; |
3947 | + $this->displayId = $row['displayID']; |
3948 | + $this->defaultLayoutId = $row['defaultlayoutid']; |
3949 | + $this->version_instructions = $row['version_instructions']; |
3950 | + $this->clientType = $row['client_type']; |
3951 | + $this->clientVersion = $row['client_version']; |
3952 | + $this->clientCode = $row['client_code']; |
3953 | + |
3954 | + // Last accessed date on the display |
3955 | + $displayObject = new Display(); |
3956 | + $displayObject->Touch($this->displayId, array('clientAddress' => Kit::GetParam('REMOTE_ADDR', $_SERVER, _STRING))); |
3957 | + |
3958 | + return true; |
3959 | + } |
3960 | + catch (Exception $e) { |
3961 | + Debug::LogEntry('error', $e->getMessage()); |
3962 | return false; |
3963 | + } |
3964 | } |
3965 | |
3966 | - //Is it there? |
3967 | - if ($db->num_rows($result) == 0) |
3968 | - return false; |
3969 | - |
3970 | - //we have seen this display before, so check the licensed value |
3971 | - $row = $db->get_row($result); |
3972 | - |
3973 | - if ($row[0] == 0) |
3974 | - return false; |
3975 | - |
3976 | - // Pull the client IP address |
3977 | - $clientAddress = Kit::GetParam('REMOTE_ADDR', $_SERVER, _STRING); |
3978 | - |
3979 | - // See if the client was offline and if appropriate send an alert |
3980 | - // to say that it has come back online |
3981 | - if ($row[5] == 0 && $row[6] == 1 |
3982 | - && (Config::GetSetting('MAINTENANCE_ENABLED') == 'On' || Config::GetSetting('MAINTENANCE_ENABLED') == 'Protected') |
3983 | - && Config::GetSetting('MAINTENANCE_EMAIL_ALERTS') == 'On') |
3984 | - { |
3985 | - $msgTo = Kit::ValidateParam(Config::GetSetting("mail_to"),_PASSWORD); |
3986 | - $msgFrom = Kit::ValidateParam(Config::GetSetting("mail_from"),_PASSWORD); |
3987 | - |
3988 | - $subject = sprintf(__("Recovery for Display %s"),$row[7]); |
3989 | - $body = sprintf(__("Display %s with ID %d is now back online."), $row[7], $row[3]); |
3990 | - |
3991 | - // Get a list of people that have view access to the display? |
3992 | - if (Config::GetSetting('MAINTENANCE_ALERTS_FOR_VIEW_USERS') == 1) { |
3993 | - foreach (Display::getUsers($row[3]) as $user) { |
3994 | - if ($user['email'] != '') { |
3995 | - Kit::SendEmail($user['email'], $msgFrom, $subject, $body); |
3996 | + private function AlertDisplayUp($displayId, $display, $loggedIn, $emailAlert) |
3997 | + { |
3998 | + $maintenanceEnabled = Config::GetSetting('MAINTENANCE_ENABLED'); |
3999 | + |
4000 | + if ($loggedIn == 0) { |
4001 | + |
4002 | + // Log display up |
4003 | + $statObject = new Stat(); |
4004 | + $statObject->displayUp($displayId); |
4005 | + |
4006 | + // Do we need to email? |
4007 | + if ($emailAlert == 1 && ($maintenanceEnabled == 'On' || $maintenanceEnabled == 'Protected') |
4008 | + && Config::GetSetting('MAINTENANCE_EMAIL_ALERTS') == 'On') { |
4009 | + |
4010 | + $msgTo = Kit::ValidateParam(Config::GetSetting("mail_to") ,_PASSWORD); |
4011 | + $msgFrom = Kit::ValidateParam(Config::GetSetting("mail_from"), _PASSWORD); |
4012 | + |
4013 | + $subject = sprintf(__("Recovery for Display %s"), $display); |
4014 | + $body = sprintf(__("Display %s with ID %d is now back online."), $display, $displayId); |
4015 | + |
4016 | + // Get a list of people that have view access to the display? |
4017 | + if (Config::GetSetting('MAINTENANCE_ALERTS_FOR_VIEW_USERS') == 1) { |
4018 | + foreach (Display::getUsers($displayId) as $user) { |
4019 | + if ($user['email'] != '') { |
4020 | + Kit::SendEmail($user['email'], $msgFrom, $subject, $body); |
4021 | + } |
4022 | } |
4023 | } |
4024 | + |
4025 | + // Send to the original admin contact |
4026 | + Kit::SendEmail($msgTo, $msgFrom, $subject, $body); |
4027 | } |
4028 | - |
4029 | - Kit::SendEmail($msgTo, $msgFrom, $subject, $body); |
4030 | - } |
4031 | - |
4032 | - // Last accessed date on the display |
4033 | - $displayObject = new Display($db); |
4034 | - $displayObject->Touch($hardwareKey, $clientAddress); |
4035 | - |
4036 | - // It is licensed? |
4037 | - $this->licensed = true; |
4038 | - $this->includeSchedule = $row[1]; |
4039 | - $this->isAuditing = $row[2]; |
4040 | - $this->displayId = $row[3]; |
4041 | - $this->defaultLayoutId = $row[4]; |
4042 | - $this->version_instructions = $row[8]; |
4043 | - |
4044 | - return true; |
4045 | - } |
4046 | - |
4047 | - /** |
4048 | - * Checks that the calling service is talking the correct version |
4049 | - * @return |
4050 | - * @param $version Object |
4051 | - */ |
4052 | - private function CheckVersion($version) |
4053 | - { |
4054 | - $db =& $this->db; |
4055 | - |
4056 | - // Look up the Service XMDS version from the Version table |
4057 | - $serverVersion = Config::Version('XmdsVersion'); |
4058 | - |
4059 | - if ($version != $serverVersion) |
4060 | - { |
4061 | - Debug::LogEntry('audit', sprintf('A Client with an incorrect version connected. Client Version: [%s] Server Version [%s]', $version, $serverVersion)); |
4062 | - return false; |
4063 | - } |
4064 | - |
4065 | - return true; |
4066 | + } |
4067 | } |
4068 | |
4069 | /** |
4070 | @@ -1206,13 +1170,23 @@ |
4071 | if ($xmdsLimit <= 0) |
4072 | return true; |
4073 | |
4074 | - // Test bandwidth for the current month |
4075 | - $startOfMonth = strtotime(date('m').'/02/'.date('Y').' 00:00:00'); |
4076 | - |
4077 | - $sql = sprintf('SELECT IFNULL(SUM(Size), 0) AS BandwidthUsage FROM `bandwidth` WHERE Month = %d', $startOfMonth); |
4078 | - $bandwidthUsage = $this->db->GetSingleValue($sql, 'BandwidthUsage', _INT); |
4079 | - |
4080 | - return ($bandwidthUsage >= ($xmdsLimit * 1024)) ? false : true; |
4081 | + try { |
4082 | + $dbh = PDOConnect::init(); |
4083 | + |
4084 | + // Test bandwidth for the current month |
4085 | + $sth = $dbh->prepare('SELECT IFNULL(SUM(Size), 0) AS BandwidthUsage FROM `bandwidth` WHERE Month = :month'); |
4086 | + $sth->execute(array( |
4087 | + 'month' => strtotime(date('m').'/02/'.date('Y').' 00:00:00') |
4088 | + )); |
4089 | + |
4090 | + $bandwidthUsage = $sth->fetchColumn(0); |
4091 | + |
4092 | + return ($bandwidthUsage >= ($xmdsLimit * 1024)) ? false : true; |
4093 | + } |
4094 | + catch (Exception $e) { |
4095 | + Debug::LogEntry('error', $e->getMessage()); |
4096 | + return false; |
4097 | + } |
4098 | } |
4099 | |
4100 | /** |
4101 | @@ -1222,16 +1196,9 @@ |
4102 | * @param <type> $sizeInBytes |
4103 | */ |
4104 | private function LogBandwidth($displayId, $type, $sizeInBytes) |
4105 | - { |
4106 | - $startOfMonth = strtotime(date('m').'/02/'.date('Y').' 00:00:00'); |
4107 | - |
4108 | - $sql = "INSERT INTO `bandwidth` (Month, Type, DisplayID, Size) VALUES (%d, %d, %d, %d) "; |
4109 | - $sql .= "ON DUPLICATE KEY UPDATE Size = Size + %d "; |
4110 | - $sql = sprintf($sql, $startOfMonth, $type, $displayId, $sizeInBytes, $sizeInBytes); |
4111 | - |
4112 | - $this->db->query($sql); |
4113 | - |
4114 | - return true; |
4115 | + { |
4116 | + $bandwidth = new Bandwidth(); |
4117 | + $bandwidth->Log($displayId, $type, $sizeInBytes); |
4118 | } |
4119 | } |
4120 | ?> |
4121 | |
4122 | === modified file 'server/lib/service/xmdssoap4.class.php' |
4123 | --- server/lib/service/xmdssoap4.class.php 2014-11-25 11:09:21 +0000 |
4124 | +++ server/lib/service/xmdssoap4.class.php 2015-01-09 11:27:10 +0000 |
4125 | @@ -21,8 +21,8 @@ |
4126 | define('BLACKLIST_ALL', "All"); |
4127 | define('BLACKLIST_SINGLE', "Single"); |
4128 | |
4129 | -class XMDSSoap4 { |
4130 | - |
4131 | +class XMDSSoap4 |
4132 | +{ |
4133 | private $licensed; |
4134 | private $includeSchedule; |
4135 | private $isAuditing; |
4136 | @@ -40,8 +40,8 @@ |
4137 | * @param <type> $displayName |
4138 | * @return <type> |
4139 | */ |
4140 | - public function RegisterDisplay($serverKey, $hardwareKey, $displayName, $clientType, $clientVersion, $clientCode, $operatingSystem, $macAddress) { |
4141 | - |
4142 | + public function RegisterDisplay($serverKey, $hardwareKey, $displayName, $clientType, $clientVersion, $clientCode, $operatingSystem, $macAddress) |
4143 | + { |
4144 | // Sanitize |
4145 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4146 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4147 | @@ -138,6 +138,9 @@ |
4148 | $displayProfile->displayProfileId = (empty($row['displayprofileid']) ? 0 : Kit::ValidateParam($row['displayprofileid'], _INT)); |
4149 | |
4150 | if ($displayProfile->displayProfileId == 0) { |
4151 | + // We need a theme |
4152 | + new Theme(new User()); |
4153 | + |
4154 | // Load the default profile |
4155 | $displayProfile->type = $clientType; |
4156 | $displayProfile->LoadDefault(); |
4157 | @@ -213,8 +216,8 @@ |
4158 | * @param string $hardwareKey Display Hardware Key |
4159 | * @return string $requiredXml Xml Formatted String |
4160 | */ |
4161 | - function RequiredFiles($serverKey, $hardwareKey) { |
4162 | - |
4163 | + function RequiredFiles($serverKey, $hardwareKey) |
4164 | + { |
4165 | // Sanitize |
4166 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4167 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4168 | @@ -485,8 +488,8 @@ |
4169 | * @param int $chunkOffset The Offset of the Chunk Requested |
4170 | * @param string $chunkSize The Size of the Chunk Requested |
4171 | */ |
4172 | - function GetFile($serverKey, $hardwareKey, $fileId, $fileType, $chunkOffset, $chunkSize) { |
4173 | - |
4174 | + function GetFile($serverKey, $hardwareKey, $fileId, $fileType, $chunkOffset, $chunkSize) |
4175 | + { |
4176 | // Sanitize |
4177 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4178 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4179 | @@ -585,7 +588,8 @@ |
4180 | * @return |
4181 | * @param $hardwareKey Object |
4182 | */ |
4183 | - function Schedule($serverKey, $hardwareKey) { |
4184 | + function Schedule($serverKey, $hardwareKey) |
4185 | + { |
4186 | // Sanitize |
4187 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4188 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4189 | @@ -735,8 +739,8 @@ |
4190 | * @param $mediaId Object |
4191 | * @param $type Object |
4192 | */ |
4193 | - function BlackList($serverKey, $hardwareKey, $mediaId, $type, $reason) { |
4194 | - |
4195 | + function BlackList($serverKey, $hardwareKey, $mediaId, $type, $reason) |
4196 | + { |
4197 | // Sanitize |
4198 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4199 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4200 | @@ -824,8 +828,8 @@ |
4201 | * @param $hardwareKey Object |
4202 | * @param $logXml Object |
4203 | */ |
4204 | - function SubmitLog($serverKey, $hardwareKey, $logXml) { |
4205 | - |
4206 | + function SubmitLog($serverKey, $hardwareKey, $logXml) |
4207 | + { |
4208 | // Sanitize |
4209 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4210 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4211 | @@ -932,8 +936,8 @@ |
4212 | * @param $hardwareKey Object |
4213 | * @param $statXml Object |
4214 | */ |
4215 | - function SubmitStats($serverKey, $hardwareKey, $statXml) { |
4216 | - |
4217 | + function SubmitStats($serverKey, $hardwareKey, $statXml) |
4218 | + { |
4219 | // Sanitize |
4220 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4221 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4222 | @@ -1015,7 +1019,8 @@ |
4223 | * @param <type> $hardwareKey |
4224 | * @param <type> $inventory |
4225 | */ |
4226 | - public function MediaInventory($serverKey, $hardwareKey, $inventory) { |
4227 | + public function MediaInventory($serverKey, $hardwareKey, $inventory) |
4228 | + { |
4229 | // Sanitize |
4230 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4231 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4232 | @@ -1080,8 +1085,8 @@ |
4233 | * @param <type> $regionId |
4234 | * @param <type> $mediaId |
4235 | */ |
4236 | - function GetResource($serverKey, $hardwareKey, $layoutId, $regionId, $mediaId) { |
4237 | - |
4238 | + function GetResource($serverKey, $hardwareKey, $layoutId, $regionId, $mediaId) |
4239 | + { |
4240 | // Sanitize |
4241 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4242 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4243 | @@ -1140,7 +1145,8 @@ |
4244 | return $resource; |
4245 | } |
4246 | |
4247 | - public function NotifyStatus($serverKey, $hardwareKey, $status) { |
4248 | + public function NotifyStatus($serverKey, $hardwareKey, $status) |
4249 | + { |
4250 | // Sanitize |
4251 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4252 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4253 | @@ -1161,16 +1167,17 @@ |
4254 | if ($this->isAuditing == 1) |
4255 | Debug::LogEntry('audit', $status, 'xmds', 'Status', '', $this->displayId); |
4256 | |
4257 | + $this->LogBandwidth($this->displayId, Bandwidth::$NOTIFYSTATUS, strlen($status)); |
4258 | + |
4259 | // Touch the display record |
4260 | $displayObject = new Display(); |
4261 | $displayObject->Touch($this->displayId, json_decode($status, true)); |
4262 | |
4263 | - $this->LogBandwidth($this->displayId, Bandwidth::$NOTIFYSTATUS, strlen($status)); |
4264 | - |
4265 | return true; |
4266 | } |
4267 | |
4268 | - public function SubmitScreenShot($serverKey, $hardwareKey, $screenShot) { |
4269 | + public function SubmitScreenShot($serverKey, $hardwareKey, $screenShot) |
4270 | + { |
4271 | // Sanitize |
4272 | $serverKey = Kit::ValidateParam($serverKey, _STRING); |
4273 | $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING); |
4274 | @@ -1210,8 +1217,8 @@ |
4275 | /** |
4276 | * PHONE_HOME if required |
4277 | */ |
4278 | - private function PhoneHome() { |
4279 | - |
4280 | + private function PhoneHome() |
4281 | + { |
4282 | if (Config::GetSetting('PHONE_HOME') == 'On') { |
4283 | // Find out when we last PHONED_HOME :D |
4284 | // If it's been > 28 days since last PHONE_HOME then |
4285 | @@ -1261,8 +1268,8 @@ |
4286 | * @param <type> $hardwareKey |
4287 | * @return <type> |
4288 | */ |
4289 | - private function AuthDisplay($hardwareKey, $status = NULL) { |
4290 | - |
4291 | + private function AuthDisplay($hardwareKey, $status = NULL) |
4292 | + { |
4293 | try { |
4294 | $dbh = PDOConnect::init(); |
4295 | |
4296 | @@ -1316,8 +1323,8 @@ |
4297 | } |
4298 | } |
4299 | |
4300 | - private function AlertDisplayUp($displayId, $display, $loggedIn, $emailAlert) { |
4301 | - |
4302 | + private function AlertDisplayUp($displayId, $display, $loggedIn, $emailAlert) |
4303 | + { |
4304 | $maintenanceEnabled = Config::GetSetting('MAINTENANCE_ENABLED'); |
4305 | |
4306 | if ($loggedIn == 0) { |
4307 | @@ -1354,7 +1361,8 @@ |
4308 | /** |
4309 | * Check we havent exceeded the bandwidth limits |
4310 | */ |
4311 | - private function CheckBandwidth() { |
4312 | + private function CheckBandwidth() |
4313 | + { |
4314 | $xmdsLimit = Config::GetSetting('MONTHLY_XMDS_TRANSFER_LIMIT_KB'); |
4315 | |
4316 | if ($xmdsLimit <= 0) |
4317 | @@ -1385,8 +1393,8 @@ |
4318 | * @param <type> $type |
4319 | * @param <type> $sizeInBytes |
4320 | */ |
4321 | - private function LogBandwidth($displayId, $type, $sizeInBytes) { |
4322 | - |
4323 | + private function LogBandwidth($displayId, $type, $sizeInBytes) |
4324 | + { |
4325 | $bandwidth = new Bandwidth(); |
4326 | $bandwidth->Log($displayId, $type, $sizeInBytes); |
4327 | } |
4328 | |
4329 | === added directory 'server/modules/3rdparty/twitter-oauth' |
4330 | === added file 'server/modules/3rdparty/twitter-oauth/OAuth.php' |
4331 | --- server/modules/3rdparty/twitter-oauth/OAuth.php 1970-01-01 00:00:00 +0000 |
4332 | +++ server/modules/3rdparty/twitter-oauth/OAuth.php 2015-01-09 11:27:10 +0000 |
4333 | @@ -0,0 +1,872 @@ |
4334 | +<?php |
4335 | +// vim: foldmethod=marker |
4336 | + |
4337 | +/* Generic exception class |
4338 | + */ |
4339 | +if (!class_exists('TwitterOAuthException')) { |
4340 | + class TwitterOAuthException extends Exception { |
4341 | + // pass |
4342 | + } |
4343 | +} |
4344 | + |
4345 | +class TwitterOAuthConsumer { |
4346 | + public $key; |
4347 | + public $secret; |
4348 | + |
4349 | + function __construct($key, $secret, $callback_url=NULL) { |
4350 | + $this->key = $key; |
4351 | + $this->secret = $secret; |
4352 | + $this->callback_url = $callback_url; |
4353 | + } |
4354 | + |
4355 | + function __toString() { |
4356 | + return "OAuthConsumer[key=$this->key,secret=$this->secret]"; |
4357 | + } |
4358 | +} |
4359 | + |
4360 | +class TwitterOAuthToken { |
4361 | + // access tokens and request tokens |
4362 | + public $key; |
4363 | + public $secret; |
4364 | + |
4365 | + /** |
4366 | + * key = the token |
4367 | + * secret = the token secret |
4368 | + */ |
4369 | + function __construct($key, $secret) { |
4370 | + $this->key = $key; |
4371 | + $this->secret = $secret; |
4372 | + } |
4373 | + |
4374 | + /** |
4375 | + * generates the basic string serialization of a token that a server |
4376 | + * would respond to request_token and access_token calls with |
4377 | + */ |
4378 | + function to_string() { |
4379 | + return "oauth_token=" . |
4380 | + TwitterOAuthUtil::urlencode_rfc3986($this->key) . |
4381 | + "&oauth_token_secret=" . |
4382 | + TwitterOAuthUtil::urlencode_rfc3986($this->secret); |
4383 | + } |
4384 | + |
4385 | + function __toString() { |
4386 | + return $this->to_string(); |
4387 | + } |
4388 | +} |
4389 | + |
4390 | +/** |
4391 | + * A class for implementing a Signature Method |
4392 | + * See section 9 ("Signing Requests") in the spec |
4393 | + */ |
4394 | +abstract class TwitterOAuthSignatureMethod { |
4395 | + /** |
4396 | + * Needs to return the name of the Signature Method (ie HMAC-SHA1) |
4397 | + * @return string |
4398 | + */ |
4399 | + abstract public function get_name(); |
4400 | + |
4401 | + /** |
4402 | + * Build up the signature |
4403 | + * NOTE: The output of this function MUST NOT be urlencoded. |
4404 | + * the encoding is handled in TwitterOAuthRequest when the final |
4405 | + * request is serialized |
4406 | + * @param TwitterOAuthRequest $request |
4407 | + * @param OAuthConsumer $consumer |
4408 | + * @param OAuthToken $token |
4409 | + * @return string |
4410 | + */ |
4411 | + abstract public function build_signature($request, $consumer, $token); |
4412 | + |
4413 | + /** |
4414 | + * Verifies that a given signature is correct |
4415 | + * @param TwitterOAuthRequest $request |
4416 | + * @param OAuthConsumer $consumer |
4417 | + * @param OAuthToken $token |
4418 | + * @param string $signature |
4419 | + * @return bool |
4420 | + */ |
4421 | + public function check_signature($request, $consumer, $token, $signature) { |
4422 | + $built = $this->build_signature($request, $consumer, $token); |
4423 | + return $built == $signature; |
4424 | + } |
4425 | +} |
4426 | + |
4427 | +/** |
4428 | + * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] |
4429 | + * where the Signature Base String is the text and the key is the concatenated values (each first |
4430 | + * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&' |
4431 | + * character (ASCII code 38) even if empty. |
4432 | + * - Chapter 9.2 ("HMAC-SHA1") |
4433 | + */ |
4434 | +class TwitterOAuthSignatureMethod_HMAC_SHA1 extends TwitterOAuthSignatureMethod { |
4435 | + function get_name() { |
4436 | + return "HMAC-SHA1"; |
4437 | + } |
4438 | + |
4439 | + public function build_signature($request, $consumer, $token) { |
4440 | + $base_string = $request->get_signature_base_string(); |
4441 | + $request->base_string = $base_string; |
4442 | + |
4443 | + $key_parts = array( |
4444 | + $consumer->secret, |
4445 | + ($token) ? $token->secret : "" |
4446 | + ); |
4447 | + |
4448 | + $key_parts = TwitterOAuthUtil::urlencode_rfc3986($key_parts); |
4449 | + $key = implode('&', $key_parts); |
4450 | + |
4451 | + return base64_encode(hash_hmac('sha1', $base_string, $key, true)); |
4452 | + } |
4453 | +} |
4454 | + |
4455 | +/** |
4456 | + * The PLAINTEXT method does not provide any security protection and SHOULD only be used |
4457 | + * over a secure channel such as HTTPS. It does not use the Signature Base String. |
4458 | + * - Chapter 9.4 ("PLAINTEXT") |
4459 | + */ |
4460 | +class TwitterOAuthSignatureMethod_PLAINTEXT extends TwitterOAuthSignatureMethod { |
4461 | + public function get_name() { |
4462 | + return "PLAINTEXT"; |
4463 | + } |
4464 | + |
4465 | + /** |
4466 | + * oauth_signature is set to the concatenated encoded values of the Consumer Secret and |
4467 | + * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is |
4468 | + * empty. The result MUST be encoded again. |
4469 | + * - Chapter 9.4.1 ("Generating Signatures") |
4470 | + * |
4471 | + * Please note that the second encoding MUST NOT happen in the SignatureMethod, as |
4472 | + * TwitterOAuthRequest handles this! |
4473 | + */ |
4474 | + public function build_signature($request, $consumer, $token) { |
4475 | + $key_parts = array( |
4476 | + $consumer->secret, |
4477 | + ($token) ? $token->secret : "" |
4478 | + ); |
4479 | + |
4480 | + $key_parts = TwitterOAuthUtil::urlencode_rfc3986($key_parts); |
4481 | + $key = implode('&', $key_parts); |
4482 | + $request->base_string = $key; |
4483 | + |
4484 | + return $key; |
4485 | + } |
4486 | +} |
4487 | + |
4488 | +/** |
4489 | + * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in |
4490 | + * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for |
4491 | + * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a |
4492 | + * verified way to the Service Provider, in a manner which is beyond the scope of this |
4493 | + * specification. |
4494 | + * - Chapter 9.3 ("RSA-SHA1") |
4495 | + */ |
4496 | +abstract class TwitterOAuthSignatureMethod_RSA_SHA1 extends TwitterOAuthSignatureMethod { |
4497 | + public function get_name() { |
4498 | + return "RSA-SHA1"; |
4499 | + } |
4500 | + |
4501 | + // Up to the SP to implement this lookup of keys. Possible ideas are: |
4502 | + // (1) do a lookup in a table of trusted certs keyed off of consumer |
4503 | + // (2) fetch via http using a url provided by the requester |
4504 | + // (3) some sort of specific discovery code based on request |
4505 | + // |
4506 | + // Either way should return a string representation of the certificate |
4507 | + protected abstract function fetch_public_cert(&$request); |
4508 | + |
4509 | + // Up to the SP to implement this lookup of keys. Possible ideas are: |
4510 | + // (1) do a lookup in a table of trusted certs keyed off of consumer |
4511 | + // |
4512 | + // Either way should return a string representation of the certificate |
4513 | + protected abstract function fetch_private_cert(&$request); |
4514 | + |
4515 | + public function build_signature($request, $consumer, $token) { |
4516 | + $base_string = $request->get_signature_base_string(); |
4517 | + $request->base_string = $base_string; |
4518 | + |
4519 | + // Fetch the private key cert based on the request |
4520 | + $cert = $this->fetch_private_cert($request); |
4521 | + |
4522 | + // Pull the private key ID from the certificate |
4523 | + $privatekeyid = openssl_get_privatekey($cert); |
4524 | + |
4525 | + // Sign using the key |
4526 | + $ok = openssl_sign($base_string, $signature, $privatekeyid); |
4527 | + |
4528 | + // Release the key resource |
4529 | + openssl_free_key($privatekeyid); |
4530 | + |
4531 | + return base64_encode($signature); |
4532 | + } |
4533 | + |
4534 | + public function check_signature($request, $consumer, $token, $signature) { |
4535 | + $decoded_sig = base64_decode($signature); |
4536 | + |
4537 | + $base_string = $request->get_signature_base_string(); |
4538 | + |
4539 | + // Fetch the public key cert based on the request |
4540 | + $cert = $this->fetch_public_cert($request); |
4541 | + |
4542 | + // Pull the public key ID from the certificate |
4543 | + $publickeyid = openssl_get_publickey($cert); |
4544 | + |
4545 | + // Check the computed signature against the one passed in the query |
4546 | + $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); |
4547 | + |
4548 | + // Release the key resource |
4549 | + openssl_free_key($publickeyid); |
4550 | + |
4551 | + return $ok == 1; |
4552 | + } |
4553 | +} |
4554 | + |
4555 | +class TwitterOAuthRequest { |
4556 | + private $parameters; |
4557 | + private $http_method; |
4558 | + private $http_url; |
4559 | + // for debug purposes |
4560 | + public $base_string; |
4561 | + public static $version = '1.0'; |
4562 | + public static $POST_INPUT = 'php://input'; |
4563 | + |
4564 | + function __construct($http_method, $http_url, $parameters=NULL) { |
4565 | + @$parameters or $parameters = array(); |
4566 | + $parameters = array_merge( TwitterOAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters); |
4567 | + $this->parameters = $parameters; |
4568 | + $this->http_method = $http_method; |
4569 | + $this->http_url = $http_url; |
4570 | + } |
4571 | + |
4572 | + |
4573 | + /** |
4574 | + * attempt to build up a request from what was passed to the server |
4575 | + */ |
4576 | + public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) { |
4577 | + $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") |
4578 | + ? 'http' |
4579 | + : 'https'; |
4580 | + @$http_url or $http_url = $scheme . |
4581 | + '://' . $_SERVER['HTTP_HOST'] . |
4582 | + ':' . |
4583 | + $_SERVER['SERVER_PORT'] . |
4584 | + $_SERVER['REQUEST_URI']; |
4585 | + @$http_method or $http_method = $_SERVER['REQUEST_METHOD']; |
4586 | + |
4587 | + // We weren't handed any parameters, so let's find the ones relevant to |
4588 | + // this request. |
4589 | + // If you run XML-RPC or similar you should use this to provide your own |
4590 | + // parsed parameter-list |
4591 | + if (!$parameters) { |
4592 | + // Find request headers |
4593 | + $request_headers = TwitterOAuthUtil::get_headers(); |
4594 | + |
4595 | + // Parse the query-string to find GET parameters |
4596 | + $parameters = TwitterOAuthUtil::parse_parameters($_SERVER['QUERY_STRING']); |
4597 | + |
4598 | + // It's a POST request of the proper content-type, so parse POST |
4599 | + // parameters and add those overriding any duplicates from GET |
4600 | + if ($http_method == "POST" |
4601 | + && @strstr($request_headers["Content-Type"], |
4602 | + "application/x-www-form-urlencoded") |
4603 | + ) { |
4604 | + $post_data = TwitterOAuthUtil::parse_parameters( |
4605 | + file_get_contents(self::$POST_INPUT) |
4606 | + ); |
4607 | + $parameters = array_merge($parameters, $post_data); |
4608 | + } |
4609 | + |
4610 | + // We have a Authorization-header with OAuth data. Parse the header |
4611 | + // and add those overriding any duplicates from GET or POST |
4612 | + if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") { |
4613 | + $header_parameters = TwitterOAuthUtil::split_header( |
4614 | + $request_headers['Authorization'] |
4615 | + ); |
4616 | + $parameters = array_merge($parameters, $header_parameters); |
4617 | + } |
4618 | + |
4619 | + } |
4620 | + |
4621 | + return new TwitterOAuthRequest($http_method, $http_url, $parameters); |
4622 | + } |
4623 | + |
4624 | + /** |
4625 | + * pretty much a helper function to set up the request |
4626 | + */ |
4627 | + public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) { |
4628 | + @$parameters or $parameters = array(); |
4629 | + $defaults = array("oauth_version" => TwitterOAuthRequest::$version, |
4630 | + "oauth_nonce" => TwitterOAuthRequest::generate_nonce(), |
4631 | + "oauth_timestamp" => TwitterOAuthRequest::generate_timestamp(), |
4632 | + "oauth_consumer_key" => $consumer->key); |
4633 | + if ($token) |
4634 | + $defaults['oauth_token'] = $token->key; |
4635 | + |
4636 | + $parameters = array_merge($defaults, $parameters); |
4637 | + |
4638 | + return new TwitterOAuthRequest($http_method, $http_url, $parameters); |
4639 | + } |
4640 | + |
4641 | + public function set_parameter($name, $value, $allow_duplicates = true) { |
4642 | + if ($allow_duplicates && isset($this->parameters[$name])) { |
4643 | + // We have already added parameter(s) with this name, so add to the list |
4644 | + if (is_scalar($this->parameters[$name])) { |
4645 | + // This is the first duplicate, so transform scalar (string) |
4646 | + // into an array so we can add the duplicates |
4647 | + $this->parameters[$name] = array($this->parameters[$name]); |
4648 | + } |
4649 | + |
4650 | + $this->parameters[$name][] = $value; |
4651 | + } else { |
4652 | + $this->parameters[$name] = $value; |
4653 | + } |
4654 | + } |
4655 | + |
4656 | + public function get_parameter($name) { |
4657 | + return isset($this->parameters[$name]) ? $this->parameters[$name] : null; |
4658 | + } |
4659 | + |
4660 | + public function get_parameters() { |
4661 | + return $this->parameters; |
4662 | + } |
4663 | + |
4664 | + public function unset_parameter($name) { |
4665 | + unset($this->parameters[$name]); |
4666 | + } |
4667 | + |
4668 | + /** |
4669 | + * The request parameters, sorted and concatenated into a normalized string. |
4670 | + * @return string |
4671 | + */ |
4672 | + public function get_signable_parameters() { |
4673 | + // Grab all parameters |
4674 | + $params = $this->parameters; |
4675 | + |
4676 | + // Remove oauth_signature if present |
4677 | + // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") |
4678 | + if (isset($params['oauth_signature'])) { |
4679 | + unset($params['oauth_signature']); |
4680 | + } |
4681 | + |
4682 | + return TwitterOAuthUtil::build_http_query($params); |
4683 | + } |
4684 | + |
4685 | + /** |
4686 | + * Returns the base string of this request |
4687 | + * |
4688 | + * The base string defined as the method, the url |
4689 | + * and the parameters (normalized), each urlencoded |
4690 | + * and the concated with &. |
4691 | + */ |
4692 | + public function get_signature_base_string() { |
4693 | + $parts = array( |
4694 | + $this->get_normalized_http_method(), |
4695 | + $this->get_normalized_http_url(), |
4696 | + $this->get_signable_parameters() |
4697 | + ); |
4698 | + |
4699 | + $parts = TwitterOAuthUtil::urlencode_rfc3986($parts); |
4700 | + |
4701 | + return implode('&', $parts); |
4702 | + } |
4703 | + |
4704 | + /** |
4705 | + * just uppercases the http method |
4706 | + */ |
4707 | + public function get_normalized_http_method() { |
4708 | + return strtoupper($this->http_method); |
4709 | + } |
4710 | + |
4711 | + /** |
4712 | + * parses the url and rebuilds it to be |
4713 | + * scheme://host/path |
4714 | + */ |
4715 | + public function get_normalized_http_url() { |
4716 | + $parts = parse_url($this->http_url); |
4717 | + |
4718 | + $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80'); |
4719 | + $scheme = $parts['scheme']; |
4720 | + $host = $parts['host']; |
4721 | + $path = @$parts['path']; |
4722 | + |
4723 | + if (($scheme == 'https' && $port != '443') |
4724 | + || ($scheme == 'http' && $port != '80')) { |
4725 | + $host = "$host:$port"; |
4726 | + } |
4727 | + return "$scheme://$host$path"; |
4728 | + } |
4729 | + |
4730 | + /** |
4731 | + * builds a url usable for a GET request |
4732 | + */ |
4733 | + public function to_url() { |
4734 | + $post_data = $this->to_postdata(); |
4735 | + $out = $this->get_normalized_http_url(); |
4736 | + if ($post_data) { |
4737 | + $out .= '?'.$post_data; |
4738 | + } |
4739 | + return $out; |
4740 | + } |
4741 | + |
4742 | + /** |
4743 | + * builds the data one would send in a POST request |
4744 | + */ |
4745 | + public function to_postdata() { |
4746 | + return TwitterOAuthUtil::build_http_query($this->parameters); |
4747 | + } |
4748 | + |
4749 | + /** |
4750 | + * builds the Authorization: header |
4751 | + */ |
4752 | + public function to_header($realm=null) { |
4753 | + $first = true; |
4754 | + if($realm) { |
4755 | + $out = 'Authorization: OAuth realm="' . TwitterOAuthUtil::urlencode_rfc3986($realm) . '"'; |
4756 | + $first = false; |
4757 | + } else |
4758 | + $out = 'Authorization: OAuth'; |
4759 | + |
4760 | + $total = array(); |
4761 | + foreach ($this->parameters as $k => $v) { |
4762 | + if (substr($k, 0, 5) != "oauth") continue; |
4763 | + if (is_array($v)) { |
4764 | + throw new OAuthException('Arrays not supported in headers'); |
4765 | + } |
4766 | + $out .= ($first) ? ' ' : ','; |
4767 | + $out .= TwitterOAuthUtil::urlencode_rfc3986($k) . |
4768 | + '="' . |
4769 | + TwitterOAuthUtil::urlencode_rfc3986($v) . |
4770 | + '"'; |
4771 | + $first = false; |
4772 | + } |
4773 | + return $out; |
4774 | + } |
4775 | + |
4776 | + public function __toString() { |
4777 | + return $this->to_url(); |
4778 | + } |
4779 | + |
4780 | + |
4781 | + public function sign_request($signature_method, $consumer, $token) { |
4782 | + $this->set_parameter( |
4783 | + "oauth_signature_method", |
4784 | + $signature_method->get_name(), |
4785 | + false |
4786 | + ); |
4787 | + $signature = $this->build_signature($signature_method, $consumer, $token); |
4788 | + $this->set_parameter("oauth_signature", $signature, false); |
4789 | + } |
4790 | + |
4791 | + public function build_signature($signature_method, $consumer, $token) { |
4792 | + $signature = $signature_method->build_signature($this, $consumer, $token); |
4793 | + return $signature; |
4794 | + } |
4795 | + |
4796 | + /** |
4797 | + * util function: current timestamp |
4798 | + */ |
4799 | + private static function generate_timestamp() { |
4800 | + return time(); |
4801 | + } |
4802 | + |
4803 | + /** |
4804 | + * util function: current nonce |
4805 | + */ |
4806 | + private static function generate_nonce() { |
4807 | + $mt = microtime(); |
4808 | + $rand = mt_rand(); |
4809 | + |
4810 | + return md5($mt . $rand); // md5s look nicer than numbers |
4811 | + } |
4812 | +} |
4813 | + |
4814 | +class TwitterOAuthServer { |
4815 | + protected $timestamp_threshold = 300; // in seconds, five minutes |
4816 | + protected $version = '1.0'; // hi blaine |
4817 | + protected $signature_methods = array(); |
4818 | + |
4819 | + protected $data_store; |
4820 | + |
4821 | + function __construct($data_store) { |
4822 | + $this->data_store = $data_store; |
4823 | + } |
4824 | + |
4825 | + public function add_signature_method($signature_method) { |
4826 | + $this->signature_methods[$signature_method->get_name()] = |
4827 | + $signature_method; |
4828 | + } |
4829 | + |
4830 | + // high level functions |
4831 | + |
4832 | + /** |
4833 | + * process a request_token request |
4834 | + * returns the request token on success |
4835 | + */ |
4836 | + public function fetch_request_token(&$request) { |
4837 | + $this->get_version($request); |
4838 | + |
4839 | + $consumer = $this->get_consumer($request); |
4840 | + |
4841 | + // no token required for the initial token request |
4842 | + $token = NULL; |
4843 | + |
4844 | + $this->check_signature($request, $consumer, $token); |
4845 | + |
4846 | + // Rev A change |
4847 | + $callback = $request->get_parameter('oauth_callback'); |
4848 | + $new_token = $this->data_store->new_request_token($consumer, $callback); |
4849 | + |
4850 | + return $new_token; |
4851 | + } |
4852 | + |
4853 | + /** |
4854 | + * process an access_token request |
4855 | + * returns the access token on success |
4856 | + */ |
4857 | + public function fetch_access_token(&$request) { |
4858 | + $this->get_version($request); |
4859 | + |
4860 | + $consumer = $this->get_consumer($request); |
4861 | + |
4862 | + // requires authorized request token |
4863 | + $token = $this->get_token($request, $consumer, "request"); |
4864 | + |
4865 | + $this->check_signature($request, $consumer, $token); |
4866 | + |
4867 | + // Rev A change |
4868 | + $verifier = $request->get_parameter('oauth_verifier'); |
4869 | + $new_token = $this->data_store->new_access_token($token, $consumer, $verifier); |
4870 | + |
4871 | + return $new_token; |
4872 | + } |
4873 | + |
4874 | + /** |
4875 | + * verify an api call, checks all the parameters |
4876 | + */ |
4877 | + public function verify_request(&$request) { |
4878 | + $this->get_version($request); |
4879 | + $consumer = $this->get_consumer($request); |
4880 | + $token = $this->get_token($request, $consumer, "access"); |
4881 | + $this->check_signature($request, $consumer, $token); |
4882 | + return array($consumer, $token); |
4883 | + } |
4884 | + |
4885 | + // Internals from here |
4886 | + /** |
4887 | + * version 1 |
4888 | + */ |
4889 | + private function get_version(&$request) { |
4890 | + $version = $request->get_parameter("oauth_version"); |
4891 | + if (!$version) { |
4892 | + // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present. |
4893 | + // Chapter 7.0 ("Accessing Protected Ressources") |
4894 | + $version = '1.0'; |
4895 | + } |
4896 | + if ($version !== $this->version) { |
4897 | + throw new OAuthException("OAuth version '$version' not supported"); |
4898 | + } |
4899 | + return $version; |
4900 | + } |
4901 | + |
4902 | + /** |
4903 | + * figure out the signature with some defaults |
4904 | + */ |
4905 | + private function get_signature_method(&$request) { |
4906 | + $signature_method = |
4907 | + @$request->get_parameter("oauth_signature_method"); |
4908 | + |
4909 | + if (!$signature_method) { |
4910 | + // According to chapter 7 ("Accessing Protected Ressources") the signature-method |
4911 | + // parameter is required, and we can't just fallback to PLAINTEXT |
4912 | + throw new OAuthException('No signature method parameter. This parameter is required'); |
4913 | + } |
4914 | + |
4915 | + if (!in_array($signature_method, |
4916 | + array_keys($this->signature_methods))) { |
4917 | + throw new OAuthException( |
4918 | + "Signature method '$signature_method' not supported " . |
4919 | + "try one of the following: " . |
4920 | + implode(", ", array_keys($this->signature_methods)) |
4921 | + ); |
4922 | + } |
4923 | + return $this->signature_methods[$signature_method]; |
4924 | + } |
4925 | + |
4926 | + /** |
4927 | + * try to find the consumer for the provided request's consumer key |
4928 | + */ |
4929 | + private function get_consumer(&$request) { |
4930 | + $consumer_key = @$request->get_parameter("oauth_consumer_key"); |
4931 | + if (!$consumer_key) { |
4932 | + throw new OAuthException("Invalid consumer key"); |
4933 | + } |
4934 | + |
4935 | + $consumer = $this->data_store->lookup_consumer($consumer_key); |
4936 | + if (!$consumer) { |
4937 | + throw new OAuthException("Invalid consumer"); |
4938 | + } |
4939 | + |
4940 | + return $consumer; |
4941 | + } |
4942 | + |
4943 | + /** |
4944 | + * try to find the token for the provided request's token key |
4945 | + */ |
4946 | + private function get_token(&$request, $consumer, $token_type="access") { |
4947 | + $token_field = @$request->get_parameter('oauth_token'); |
4948 | + $token = $this->data_store->lookup_token( |
4949 | + $consumer, $token_type, $token_field |
4950 | + ); |
4951 | + if (!$token) { |
4952 | + throw new OAuthException("Invalid $token_type token: $token_field"); |
4953 | + } |
4954 | + return $token; |
4955 | + } |
4956 | + |
4957 | + /** |
4958 | + * all-in-one function to check the signature on a request |
4959 | + * should guess the signature method appropriately |
4960 | + */ |
4961 | + private function check_signature(&$request, $consumer, $token) { |
4962 | + // this should probably be in a different method |
4963 | + $timestamp = @$request->get_parameter('oauth_timestamp'); |
4964 | + $nonce = @$request->get_parameter('oauth_nonce'); |
4965 | + |
4966 | + $this->check_timestamp($timestamp); |
4967 | + $this->check_nonce($consumer, $token, $nonce, $timestamp); |
4968 | + |
4969 | + $signature_method = $this->get_signature_method($request); |
4970 | + |
4971 | + $signature = $request->get_parameter('oauth_signature'); |
4972 | + $valid_sig = $signature_method->check_signature( |
4973 | + $request, |
4974 | + $consumer, |
4975 | + $token, |
4976 | + $signature |
4977 | + ); |
4978 | + |
4979 | + if (!$valid_sig) { |
4980 | + throw new OAuthException("Invalid signature"); |
4981 | + } |
4982 | + } |
4983 | + |
4984 | + /** |
4985 | + * check that the timestamp is new enough |
4986 | + */ |
4987 | + private function check_timestamp($timestamp) { |
4988 | + if( ! $timestamp ) |
4989 | + throw new OAuthException( |
4990 | + 'Missing timestamp parameter. The parameter is required' |
4991 | + ); |
4992 | + |
4993 | + // verify that timestamp is recentish |
4994 | + $now = time(); |
4995 | + if (abs($now - $timestamp) > $this->timestamp_threshold) { |
4996 | + throw new OAuthException( |
4997 | + "Expired timestamp, yours $timestamp, ours $now" |
4998 | + ); |
4999 | + } |
5000 | + } |
The diff has been truncated for viewing.