Merge lp:~alexharrington/xibo/upgrade-db-backup-switch into lp:~xibo-maintainers/xibo/encke

Proposed by Alex Harrington
Status: Merged
Merged at revision: not available
Proposed branch: lp:~alexharrington/xibo/upgrade-db-backup-switch
Merge into: lp:~xibo-maintainers/xibo/encke
Diff against target: None lines
To merge this branch: bzr merge lp:~alexharrington/xibo/upgrade-db-backup-switch
Reviewer Review Type Date Requested Status
Dan Garner Needs Information
Review via email: mp+12199@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Dan Garner (dangarner) wrote :

Generates a Text Conflict in Upgrade.php - I am not sure how to resolve.

review: Needs Information

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'client/dotNET/FileCollector.cs'
2--- client/dotNET/FileCollector.cs 2009-03-13 09:21:56 +0000
3+++ client/dotNET/FileCollector.cs 2009-07-26 11:40:59 +0000
4@@ -236,6 +236,9 @@
5 }
6 else
7 {
8+ // Set the flag to indicate we have a connection to XMDS
9+ Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
10+
11 // What file type were we getting
12 if (currentFileList.type == "layout")
13 {
14
15=== modified file 'client/dotNET/HardwareKey.cs'
16--- client/dotNET/HardwareKey.cs 2009-03-02 23:21:22 +0000
17+++ client/dotNET/HardwareKey.cs 2009-07-26 11:40:59 +0000
18@@ -31,7 +31,18 @@
19 {
20 System.Diagnostics.Debug.WriteLine("[IN]", "HardwareKey");
21
22- hardwareKey = Hashes.MD5(GetCPUId() + GetVolumeSerial("C"));
23+ // Get the key from the Settings
24+ hardwareKey = Properties.Settings.Default.hardwareKey;
25+
26+ // Is the key empty?
27+ if (hardwareKey == "")
28+ {
29+ // Calculate the Hardware key from the CPUID and Volume Serial
30+ hardwareKey = Hashes.MD5(GetCPUId() + GetVolumeSerial("C"));
31+
32+ // Store the key
33+ Properties.Settings.Default.hardwareKey = hardwareKey;
34+ }
35
36 System.Diagnostics.Debug.WriteLine("[OUT]", "HardwareKey");
37 }
38@@ -48,6 +59,19 @@
39 }
40
41 /// <summary>
42+ /// Regenerates the hardware key
43+ /// </summary>
44+ public void Regenerate()
45+ {
46+ // Calculate the Hardware key from the CPUID and Volume Serial
47+ hardwareKey = Hashes.MD5(GetCPUId() + GetVolumeSerial("C"));
48+
49+ // Store the key
50+ Properties.Settings.Default.hardwareKey = hardwareKey;
51+ Properties.Settings.Default.Save();
52+ }
53+
54+ /// <summary>
55 /// return Volume Serial Number from hard drive
56 /// </summary>
57 /// <param name="strDriveLetter">[optional] Drive letter</param>
58
59=== modified file 'client/dotNET/Image.cs'
60--- client/dotNET/Image.cs 2009-02-25 22:57:05 +0000
61+++ client/dotNET/Image.cs 2009-08-03 14:09:45 +0000
62@@ -27,30 +27,37 @@
63 {
64 class ImagePosition : Media
65 {
66+ private string _filePath;
67+ PictureBox _pictureBox;
68+
69 public ImagePosition(RegionOptions options)
70 : base(options.width, options.height, options.top, options.left)
71 {
72- this.filePath = options.uri;
73+ _filePath = options.uri;
74
75- if (!System.IO.File.Exists(this.filePath))
76+ if (!System.IO.File.Exists(_filePath))
77 {
78 // Exit
79- this.loaded = false;
80+ System.Diagnostics.Trace.WriteLine(new LogMessage("Image - Dispose", "Cannot Create image object. Invalid Filepath."), LogType.Error.ToString());
81 return;
82 }
83
84- Bitmap img = new Bitmap(this.filePath);
85-
86- this.pictureBox = new PictureBox();
87- this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
88- this.pictureBox.Image = img;
89- this.pictureBox.Size = new Size(width, height);
90- this.pictureBox.Location = new Point(0, 0);
91- this.pictureBox.BorderStyle = BorderStyle.None;
92- this.pictureBox.BackColor = Color.Transparent;
93- this.loaded = true;
94-
95- this.Controls.Add(this.pictureBox);
96+ try
97+ {
98+ _pictureBox = new PictureBox();
99+ _pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
100+ _pictureBox.Image = new Bitmap(_filePath);
101+ _pictureBox.Size = new Size(width, height);
102+ _pictureBox.Location = new Point(0, 0);
103+ _pictureBox.BorderStyle = BorderStyle.None;
104+ _pictureBox.BackColor = Color.Transparent;
105+
106+ this.Controls.Add(this._pictureBox);
107+ }
108+ catch (Exception ex)
109+ {
110+ System.Diagnostics.Trace.WriteLine(new LogMessage("ImagePosition", String.Format("Cannot create Image Object with exception: {0}", ex.Message)), LogType.Error.ToString());
111+ }
112 }
113
114 public override void RenderMedia()
115@@ -60,16 +67,22 @@
116
117 protected override void Dispose(bool disposing)
118 {
119- if (disposing && loaded)
120+ if (disposing)
121 {
122- this.pictureBox.Dispose();
123+ try
124+ {
125+ Controls.Remove(_pictureBox);
126+
127+ _pictureBox.Image.Dispose();
128+ _pictureBox.Dispose();
129+ }
130+ catch (Exception ex)
131+ {
132+ System.Diagnostics.Trace.WriteLine(new LogMessage("Image - Dispose", String.Format("Cannot dispose Image Object with exception: {0}", ex.Message)), LogType.Error.ToString());
133+ }
134 }
135
136 base.Dispose(disposing);
137 }
138-
139- private string filePath;
140- private bool loaded;
141- PictureBox pictureBox;
142 }
143 }
144
145=== added file 'client/dotNET/LogMessage.cs'
146--- client/dotNET/LogMessage.cs 1970-01-01 00:00:00 +0000
147+++ client/dotNET/LogMessage.cs 2009-07-26 11:40:59 +0000
148@@ -0,0 +1,75 @@
149+/*
150+ * Xibo - Digitial Signage - http://www.xibo.org.uk
151+ * Copyright (C) 2009 Daniel Garner
152+ *
153+ * This file is part of Xibo.
154+ *
155+ * Xibo is free software: you can redistribute it and/or modify
156+ * it under the terms of the GNU Affero General Public License as published by
157+ * the Free Software Foundation, either version 3 of the License, or
158+ * any later version.
159+ *
160+ * Xibo is distributed in the hope that it will be useful,
161+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
162+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163+ * GNU Affero General Public License for more details.
164+ *
165+ * You should have received a copy of the GNU Affero General Public License
166+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
167+ */
168+using System;
169+using System.Collections.Generic;
170+using System.Text;
171+
172+namespace XiboClient
173+{
174+ class LogMessage
175+ {
176+ String _method;
177+ String _message;
178+ int _scheduleId;
179+ int _layoutId;
180+ int _mediaId;
181+
182+ public LogMessage(String method, String message)
183+ {
184+ _method = method;
185+ _message = message;
186+ }
187+
188+ public LogMessage(String method, String message, int scheduleId, int layoutId)
189+ {
190+ _method = method;
191+ _message = message;
192+ _scheduleId = scheduleId;
193+ _layoutId = layoutId;
194+ }
195+
196+ public LogMessage(String method, String message, int scheduleId, int layoutId, int mediaId)
197+ {
198+ _method = method;
199+ _message = message;
200+ _scheduleId = scheduleId;
201+ _layoutId = layoutId;
202+ _mediaId = mediaId;
203+ }
204+
205+ public override string ToString()
206+ {
207+ // Format the message into the expected XML sub nodes.
208+ // Just do this with a string builder rather than an XML builder.
209+ String theMessage;
210+
211+ theMessage = String.Format("<message>{0}</message>", _message);
212+ theMessage += String.Format("<method>{0}</method>", _method);
213+
214+ if (_scheduleId != 0) theMessage += String.Format("<scheduleid>{0}</scheduleid>", _scheduleId.ToString());
215+ if (_layoutId != 0) theMessage += String.Format("<layoutid>{0}</layoutid>", _scheduleId.ToString());
216+ if (_mediaId != 0) theMessage += String.Format("<mediaid>{0}</mediaid>", _scheduleId.ToString());
217+
218+ return theMessage;
219+ }
220+ }
221+
222+ public enum LogType { Info, Audit, Error }
223+}
224
225=== modified file 'client/dotNET/MainForm.cs'
226--- client/dotNET/MainForm.cs 2009-03-08 11:40:17 +0000
227+++ client/dotNET/MainForm.cs 2009-07-30 23:01:31 +0000
228@@ -34,9 +34,24 @@
229 {
230 public partial class MainForm : Form
231 {
232+ private Schedule schedule;
233+ private Collection<Region> regions;
234+ private bool isExpired = false;
235+ private int scheduleId;
236+ private int layoutId;
237+
238+ double layoutWidth;
239+ double layoutHeight;
240+ double scaleFactor;
241+
242+ private StatLog _statLog;
243+ private Stat _stat;
244+
245 public MainForm()
246 {
247 InitializeComponent();
248+
249+ _statLog = new StatLog();
250 }
251
252 private void MainForm_Load(object sender, EventArgs e)
253@@ -50,7 +65,7 @@
254 Directory.CreateDirectory(Properties.Settings.Default.LibraryPath + @"\backgrounds");
255 }
256 catch (Exception ex)
257- { System.Diagnostics.Debug.WriteLine(ex.Message); }
258+ { System.Diagnostics.Trace.WriteLine(ex.Message); }
259 }
260
261 // Hide the cursor
262@@ -71,7 +86,7 @@
263 }
264 catch (Exception ex)
265 {
266- System.Diagnostics.Debug.WriteLine(ex.Message);
267+ System.Diagnostics.Debug.WriteLine(ex.Message, LogType.Error.ToString());
268 MessageBox.Show("Fatal Error initialising the application", "Fatal Error");
269 this.Close();
270 this.Dispose();
271@@ -89,6 +104,15 @@
272 this.scheduleId = scheduleId;
273 this.layoutId = layoutId;
274
275+ if (_stat != null)
276+ {
277+ // Log the end of the currently running layout.
278+ _stat.toDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
279+
280+ // Record this stat event in the statLog object
281+ _statLog.RecordStat(_stat);
282+ }
283+
284 try
285 {
286 this.DestroyLayout();
287@@ -102,9 +126,6 @@
288 System.Diagnostics.Debug.WriteLine(ex.Message);
289 isExpired = true;
290 }
291-
292- // Flush the TraceListener
293- System.Diagnostics.Trace.Flush();
294 }
295
296
297@@ -113,7 +134,12 @@
298 /// </summary>
299 private void PrepareLayout(string layoutPath)
300 {
301- XmlLog.AppendStat("Layout Started", StatType.LayoutStart, scheduleId, layoutId, "0");
302+ // Create a start record for this layout
303+ _stat = new Stat();
304+ _stat.type = StatType.Layout;
305+ _stat.scheduleID = scheduleId;
306+ _stat.layoutID = layoutId;
307+ _stat.fromDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
308
309 // Get this layouts XML
310 XmlDocument layoutXml = new XmlDocument();
311@@ -213,20 +239,6 @@
312 leftOverY = 0;
313 }
314
315- // Are we licensed?
316- if (Properties.Settings.Default.licensed == 0)
317- {
318- // Show a label indicating this fact
319- notLic = new Label();
320- notLic.Location = new Point(0, 0);
321- notLic.Size = new System.Drawing.Size(500, 200);
322- notLic.Text = "This Display is not Licensed.";
323- notLic.BackColor = Color.WhiteSmoke;
324- this.Controls.Add(notLic);
325- notLic.BringToFront();
326- notLic.Show();
327- }
328-
329 // New region and region options objects
330 regions = new Collection<Region>();
331 RegionOptions options = new RegionOptions();
332@@ -305,7 +317,7 @@
333 // All the media nodes for this region / layout combination
334 options.mediaNodes = region.ChildNodes;
335
336- Region temp = new Region();
337+ Region temp = new Region(ref _statLog);
338 temp.DurationElapsedEvent += new Region.DurationElapsedDelegate(temp_DurationElapsedEvent);
339
340 System.Diagnostics.Debug.WriteLine("Created new region", "MainForm - Prepare Layout");
341@@ -368,6 +380,8 @@
342
343 foreach (Region region in regions)
344 {
345+ region.Clear();
346+
347 this.Controls.Remove(region);
348
349 try
350@@ -384,27 +398,21 @@
351
352 regions.Clear();
353 regions = null;
354-
355- this.Controls.Remove(notLic);
356-
357- // Want a check for powerpoint instances left open by this user
358- /*foreach (System.Diagnostics.Process proc in System.Diagnostics.Process.GetProcessesByName("POWERPNT"))
359- {
360- System.Diagnostics.Debug.WriteLine("Killing leftover Powerpoint process.", "MainForm - DestoryLayout");
361- // Close them (End Process)
362- proc.Kill();
363- }*/
364- }
365-
366- private Schedule schedule;
367- private Collection<Region> regions;
368- private bool isExpired = false;
369- private Label notLic;
370- private int scheduleId;
371- private int layoutId;
372-
373- double layoutWidth;
374- double layoutHeight;
375- double scaleFactor;
376+ }
377+
378+ /// <summary>
379+ /// Force a flush of the stats log
380+ /// </summary>
381+ public void FlushStats()
382+ {
383+ try
384+ {
385+ _statLog.Flush();
386+ }
387+ catch
388+ {
389+ System.Diagnostics.Trace.WriteLine(new LogMessage("MainForm - FlushStats", "Unable to Flush Stats"), LogType.Error.ToString());
390+ }
391+ }
392 }
393 }
394\ No newline at end of file
395
396=== modified file 'client/dotNET/Media.cs'
397--- client/dotNET/Media.cs 2008-12-19 23:34:13 +0000
398+++ client/dotNET/Media.cs 2009-08-03 21:56:06 +0000
399@@ -28,6 +28,8 @@
400 {
401 public Media(int width, int height, int top, int left)
402 {
403+ Hide();
404+
405 this.width = width;
406 this.height = height;
407 this.top = top;
408@@ -45,9 +47,12 @@
409 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
410 this.BackColor = System.Drawing.Color.Transparent;
411 this.TransparencyKey = System.Drawing.Color.White;
412+
413+ SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
414+ SetStyle(ControlStyles.AllPaintingInWmPaint, true);
415 }
416
417- public virtual void RenderMedia()
418+ protected void StartTimer()
419 {
420 //start the timer
421 if (!timerStarted && duration != 0)
422@@ -60,9 +65,15 @@
423
424 timerStarted = true;
425 }
426+ }
427+
428+ public virtual void RenderMedia()
429+ {
430+ // Start the timer for this media
431+ StartTimer();
432
433 // Show the form
434- this.Show();
435+ Show();
436 }
437
438 protected virtual void timer_Tick(object sender, EventArgs e)
439
440=== modified file 'client/dotNET/OptionForm.cs'
441--- client/dotNET/OptionForm.cs 2009-03-08 11:40:17 +0000
442+++ client/dotNET/OptionForm.cs 2009-07-26 11:40:59 +0000
443@@ -58,6 +58,9 @@
444 System.Diagnostics.Debug.WriteLine("Getting the Hardware Key", "OptionForm");
445 hardwareKey = new HardwareKey();
446
447+ // Regenerate the key
448+ hardwareKey.Regenerate();
449+
450 System.Diagnostics.Debug.WriteLine("Getting the Library Path", "OptionForm");
451 if (Properties.Settings.Default.LibraryPath == "DEFAULT")
452 {
453@@ -114,6 +117,8 @@
454 {
455 textBoxResults.Text = "Sending Request";
456
457+ this.xmds1.Url = Properties.Settings.Default.XiboClient_xmds_xmds;
458+
459 Properties.Settings.Default.displayName = textBoxDisplayName.Text;
460 Properties.Settings.Default.Save();
461
462
463=== modified file 'client/dotNET/Program.cs'
464--- client/dotNET/Program.cs 2009-03-08 12:51:18 +0000
465+++ client/dotNET/Program.cs 2009-07-26 11:40:59 +0000
466@@ -35,25 +35,25 @@
467 Application.SetCompatibleTextRenderingDefault(false);
468
469 System.Diagnostics.Trace.Listeners.Add(new XiboTraceListener());
470- System.Diagnostics.Trace.AutoFlush = true;
471+ System.Diagnostics.Trace.AutoFlush = false;
472
473 Form formMain;
474
475 if (arg.GetLength(0) > 0)
476 {
477- System.Diagnostics.Trace.WriteLine("Options Started", "Main");
478+ System.Diagnostics.Trace.WriteLine(new LogMessage("Main", "Options Started"), LogType.Info.ToString());
479 formMain = new OptionForm();
480 }
481 else
482 {
483- System.Diagnostics.Trace.WriteLine("Client Started", "Main");
484+ System.Diagnostics.Trace.WriteLine(new LogMessage("Main", "Client Started"), LogType.Info.ToString());
485 formMain = new MainForm();
486 }
487
488 Application.Run(formMain);
489
490 // Always flush at the end
491- System.Diagnostics.Trace.WriteLine("Application Finished", "Main");
492+ System.Diagnostics.Trace.WriteLine(new LogMessage("Main", "Application Finished"), LogType.Info.ToString());
493 System.Diagnostics.Trace.Flush();
494 }
495 }
496
497=== modified file 'client/dotNET/Properties/Settings.Designer.cs'
498--- client/dotNET/Properties/Settings.Designer.cs 2009-03-08 11:40:17 +0000
499+++ client/dotNET/Properties/Settings.Designer.cs 2009-07-30 23:01:31 +0000
500@@ -47,7 +47,7 @@
501 [global::System.Configuration.UserScopedSettingAttribute()]
502 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
503 [global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.WebServiceUrl)]
504- [global::System.Configuration.DefaultSettingValueAttribute("http://localhost/Xibo/server/xmds.php")]
505+ [global::System.Configuration.DefaultSettingValueAttribute("http://localhost/1.0.0/server/xmds.php")]
506 public string XiboClient_xmds_xmds {
507 get {
508 return ((string)(this["XiboClient_xmds_xmds"]));
509@@ -93,18 +93,6 @@
510 }
511 }
512
513- [global::System.Configuration.UserScopedSettingAttribute()]
514- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
515- [global::System.Configuration.DefaultSettingValueAttribute("900")]
516- public decimal collectInterval {
517- get {
518- return ((decimal)(this["collectInterval"]));
519- }
520- set {
521- this["collectInterval"] = value;
522- }
523- }
524-
525 [global::System.Configuration.ApplicationScopedSettingAttribute()]
526 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
527 [global::System.Configuration.DefaultSettingValueAttribute("log.xml")]
528@@ -215,5 +203,61 @@
529 return ((string)(this["Version"]));
530 }
531 }
532+
533+ [global::System.Configuration.UserScopedSettingAttribute()]
534+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
535+ [global::System.Configuration.DefaultSettingValueAttribute("")]
536+ public string hardwareKey {
537+ get {
538+ return ((string)(this["hardwareKey"]));
539+ }
540+ set {
541+ this["hardwareKey"] = value;
542+ }
543+ }
544+
545+ [global::System.Configuration.UserScopedSettingAttribute()]
546+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
547+ [global::System.Configuration.DefaultSettingValueAttribute("50")]
548+ public int StatsFlushCount {
549+ get {
550+ return ((int)(this["StatsFlushCount"]));
551+ }
552+ set {
553+ this["StatsFlushCount"] = value;
554+ }
555+ }
556+
557+ [global::System.Configuration.ApplicationScopedSettingAttribute()]
558+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
559+ [global::System.Configuration.DefaultSettingValueAttribute("stats.xml")]
560+ public string StatsLogFile {
561+ get {
562+ return ((string)(this["StatsLogFile"]));
563+ }
564+ }
565+
566+ [global::System.Configuration.UserScopedSettingAttribute()]
567+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
568+ public global::System.DateTime XmdsLastConnection {
569+ get {
570+ return ((global::System.DateTime)(this["XmdsLastConnection"]));
571+ }
572+ set {
573+ this["XmdsLastConnection"] = value;
574+ }
575+ }
576+
577+ [global::System.Configuration.UserScopedSettingAttribute()]
578+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
579+ [global::System.Configuration.DefaultSettingValueAttribute("900")]
580+ public decimal collectInterval {
581+ get {
582+ return ((decimal)(this["collectInterval"]));
583+ }
584+ set {
585+ this["collectInterval"] = value;
586+ }
587+ }
588 }
589 }
590
591=== modified file 'client/dotNET/Properties/Settings.settings'
592--- client/dotNET/Properties/Settings.settings 2009-03-08 11:40:17 +0000
593+++ client/dotNET/Properties/Settings.settings 2009-07-30 23:01:31 +0000
594@@ -9,7 +9,7 @@
595 <Value Profile="(Default)">schedule.xml</Value>
596 </Setting>
597 <Setting Name="XiboClient_xmds_xmds" Type="(Web Service URL)" Scope="User">
598- <Value Profile="(Default)">http://localhost/Xibo/server/xmds.php</Value>
599+ <Value Profile="(Default)">http://localhost/1.0.0/server/xmds.php</Value>
600 </Setting>
601 <Setting Name="ServerKey" Type="System.String" Scope="User">
602 <Value Profile="(Default)">changetocustomerkey</Value>
603@@ -20,9 +20,6 @@
604 <Setting Name="licensed" Type="System.Int32" Scope="User">
605 <Value Profile="(Default)">0</Value>
606 </Setting>
607- <Setting Name="collectInterval" Type="System.Decimal" Scope="User">
608- <Value Profile="(Default)">900</Value>
609- </Setting>
610 <Setting Name="logLocation" Type="System.String" Scope="Application">
611 <Value Profile="(Default)">log.xml</Value>
612 </Setting>
613@@ -53,5 +50,20 @@
614 <Setting Name="Version" Type="System.String" Scope="Application">
615 <Value Profile="(Default)">1</Value>
616 </Setting>
617+ <Setting Name="hardwareKey" Type="System.String" Scope="User">
618+ <Value Profile="(Default)" />
619+ </Setting>
620+ <Setting Name="StatsFlushCount" Type="System.Int32" Scope="User">
621+ <Value Profile="(Default)">50</Value>
622+ </Setting>
623+ <Setting Name="StatsLogFile" Type="System.String" Scope="Application">
624+ <Value Profile="(Default)">stats.xml</Value>
625+ </Setting>
626+ <Setting Name="XmdsLastConnection" Type="System.DateTime" Scope="User">
627+ <Value Profile="(Default)" />
628+ </Setting>
629+ <Setting Name="collectInterval" Type="System.Decimal" Scope="User">
630+ <Value Profile="(Default)">900</Value>
631+ </Setting>
632 </Settings>
633 </SettingsFile>
634\ No newline at end of file
635
636=== modified file 'client/dotNET/Region.cs'
637--- client/dotNET/Region.cs 2009-06-20 10:05:53 +0000
638+++ client/dotNET/Region.cs 2009-08-03 21:56:06 +0000
639@@ -31,9 +31,24 @@
640 class Region : Panel
641 {
642 private BlackList blackList;
643-
644- public Region()
645+ public delegate void DurationElapsedDelegate();
646+ public event DurationElapsedDelegate DurationElapsedEvent;
647+
648+ private Media media;
649+ private RegionOptions options;
650+ public bool hasExpired = false;
651+ public bool layoutExpired = false;
652+ private int currentSequence = -1;
653+
654+ // Stat objects
655+ private StatLog _statLog;
656+ private Stat _stat;
657+
658+ public Region(ref StatLog statLog)
659 {
660+ // Store the statLog
661+ _statLog = statLog;
662+
663 //default options
664 options.width = 1024;
665 options.height = 768;
666@@ -45,6 +60,9 @@
667 this.Size = new System.Drawing.Size(options.width, options.height);
668 this.BackColor = System.Drawing.Color.Transparent;
669
670+ SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
671+ SetStyle(ControlStyles.AllPaintingInWmPaint, true);
672+
673 // Create a new BlackList for us to use
674 blackList = new BlackList();
675 }
676@@ -139,19 +157,21 @@
677
678 //add event handler
679 media.DurationElapsedEvent += new Media.DurationElapsedDelegate(media_DurationElapsedEvent);
680-
681+
682 //any additional media specific render options (and starts the timer)
683 media.RenderMedia();
684
685+ Controls.Add(media);
686+
687 // This media has started and is being replaced
688- XmlLog.AppendStat("Media Start", StatType.MediaStart, options.scheduleId, options.layoutId, options.mediaid);
689-
690- //media.Opacity = 0F; // Completely Opaque
691-
692- this.Controls.Add(media);
693+ _stat = new Stat();
694+ _stat.type = StatType.Media;
695+ _stat.fromDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
696+ _stat.scheduleID = options.scheduleId;
697+ _stat.layoutID = options.layoutId;
698+ _stat.mediaID = options.mediaid;
699
700 System.Diagnostics.Debug.WriteLine("Showing new media", "Region - Eval Options");
701-
702 }
703
704 /// <summary>
705@@ -180,7 +200,7 @@
706 return;
707 }
708
709-
710+ // Move the sequence on
711 currentSequence++;
712
713 if (currentSequence >= options.mediaNodes.Count)
714@@ -201,10 +221,11 @@
715 options.text = "";
716 options.documentTemplate = "";
717 options.copyrightNotice = "";
718- options.scrollSpeed = 1;
719+ options.scrollSpeed = 30;
720 options.updateInterval = 6;
721 options.uri = "";
722 options.direction = "none";
723+ options.javaScript = "";
724
725 // Get a media node
726 bool validNode = false;
727@@ -284,7 +305,7 @@
728 System.Diagnostics.Trace.WriteLine("Non integer scrollSpeed in XLF", "Region - SetNextMediaNode");
729 }
730 }
731- else if (option.Name == "updateInverval")
732+ else if (option.Name == "updateInterval")
733 {
734 try
735 {
736@@ -314,6 +335,10 @@
737 {
738 options.text = raw.InnerText;
739 }
740+ else if (raw.Name == "embedScript")
741+ {
742+ options.javaScript = raw.InnerText;
743+ }
744 }
745
746 // That should cover all the new options
747@@ -350,8 +375,18 @@
748 System.Diagnostics.Debug.WriteLine(ex.Message);
749 }
750
751- // This media has expired and is being replaced
752- XmlLog.AppendStat("Media Expired", StatType.MediaEnd, options.scheduleId, options.layoutId, options.mediaid);
753+ try
754+ {
755+ // Here we say that this media is expired
756+ _stat.toDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
757+
758+ // Record this stat event in the statLog object
759+ _statLog.RecordStat(_stat);
760+ }
761+ catch
762+ {
763+ System.Diagnostics.Trace.WriteLine("No Stat record when one was expected", LogType.Error.ToString());
764+ }
765 }
766 }
767
768@@ -367,6 +402,29 @@
769 }
770
771 /// <summary>
772+ /// Clears the Region of anything that it shouldnt still have...
773+ /// </summary>
774+ public void Clear()
775+ {
776+ try
777+ {
778+ // What happens if we are disposing this region but we have not yet completed the stat event?
779+ if (String.IsNullOrEmpty(_stat.toDate))
780+ {
781+ // Say that this media has ended
782+ _stat.toDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
783+
784+ // Record this stat event in the statLog object
785+ _statLog.RecordStat(_stat);
786+ }
787+ }
788+ catch
789+ {
790+ System.Diagnostics.Trace.WriteLine(new LogMessage("Region - Clear", "Error closing off stat record"), LogType.Error.ToString());
791+ }
792+ }
793+
794+ /// <summary>
795 /// Performs the disposal.
796 /// </summary>
797 protected override void Dispose(bool disposing)
798@@ -393,16 +451,6 @@
799
800 base.Dispose(disposing);
801 }
802-
803- public delegate void DurationElapsedDelegate();
804- public event DurationElapsedDelegate DurationElapsedEvent;
805-
806- private Media media;
807- private RegionOptions options;
808- public bool hasExpired = false;
809- public bool layoutExpired = false;
810- private int currentSequence = -1;
811-
812 }
813
814 /// <summary>
815@@ -431,6 +479,7 @@
816 public string text;
817 public string documentTemplate;
818 public string copyrightNotice;
819+ public string javaScript;
820 public int updateInterval;
821 public int scrollSpeed;
822
823
824=== removed file 'client/dotNET/Resources/Thumbs.db'
825Binary files client/dotNET/Resources/Thumbs.db 2008-12-19 23:34:13 +0000 and client/dotNET/Resources/Thumbs.db 1970-01-01 00:00:00 +0000 differ
826=== modified file 'client/dotNET/Rss.cs'
827--- client/dotNET/Rss.cs 2009-06-20 10:39:40 +0000
828+++ client/dotNET/Rss.cs 2009-08-03 21:56:06 +0000
829@@ -81,9 +81,25 @@
830 this.documentText = options.text;
831 this.documentTemplate = options.documentTemplate;
832
833+ // What do we want the background to look like
834+ String bodyStyle;
835+ String document;
836+
837+ if (backgroundImage == null || backgroundImage == "")
838+ {
839+ bodyStyle = "background-color:" + backgroundColor + " ;";
840+ }
841+ else
842+ {
843+ bodyStyle = "background-image: url('" + backgroundImage + "'); background-attachment:fixed; background-color:" + backgroundColor + " background-repeat: no-repeat; background-position: " + backgroundLeft + " " + backgroundTop + ";";
844+ }
845+
846+ // Build the document string
847+ document = String.Format("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /><script type='text/javascript'>{0}</script><style type='text/css'>body {{{2}}}, p, h1, h2, h3, h4, h5 {{ margin:2px; font-size:{1}em; }}</style></head><body></body></html>", Properties.Resources.textRender, options.scaleFactor.ToString(), bodyStyle);
848+
849 try
850 {
851- webBrowser.DocumentText = String.Format("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /><script type='text/javascript'>{0}</script><style type='text/css'>p, h1, h2, h3, h4, h5 {{ margin:2px; font-size:{1}em; }}</style></head><body></body></html>", Properties.Resources.textRender, options.scaleFactor.ToString());
852+ webBrowser.DocumentText = document;
853 }
854 catch (Exception e)
855 {
856@@ -102,9 +118,10 @@
857 try
858 {
859 wc = new System.Net.WebClient();
860- wc.Encoding = System.Text.Encoding.UTF8;
861+
862+ //wc.Encoding = System.Text.Encoding.UTF8;
863
864- System.Diagnostics.Debug.WriteLine("Created at WebClient and set the Encoding to UTF8", "RSS - Refresh local RSS");
865+ System.Diagnostics.Debug.WriteLine("Created at WebClient", "RSS - Refresh local RSS");
866
867 wc.OpenReadCompleted += new System.Net.OpenReadCompletedEventHandler(wc_OpenReadCompleted);
868
869@@ -119,6 +136,7 @@
870 void wc_OpenReadCompleted(object sender, System.Net.OpenReadCompletedEventArgs e)
871 {
872 String rssContents;
873+ System.Net.WebClient wc = (System.Net.WebClient) sender;
874
875 if (e.Error != null)
876 {
877@@ -133,10 +151,10 @@
878
879 try
880 {
881- System.IO.StreamReader sr = new System.IO.StreamReader(data, Encoding.UTF8);
882+ System.IO.StreamReader sr = new System.IO.StreamReader(data, wc.Encoding);
883 rssContents = sr.ReadToEnd();
884
885- StreamWriter sw = new StreamWriter(File.Open(rssFilePath, FileMode.Create, FileAccess.Write, FileShare.Read));
886+ StreamWriter sw = new StreamWriter(File.Open(rssFilePath, FileMode.Create, FileAccess.Write, FileShare.Read), wc.Encoding);
887
888 System.Diagnostics.Debug.WriteLine("Retrieved RSS - about to write it", "RSS - wc_OpenReadCompleted");
889
890@@ -218,21 +236,14 @@
891
892 //Add the control
893 this.Controls.Add(webBrowser);
894+
895+ Show();
896 }
897
898 private void loadLoading()
899 {
900 HtmlDocument htmlDoc = webBrowser.Document;
901
902- if (backgroundImage == null || backgroundImage == "")
903- {
904- htmlDoc.Body.Style = "background-color:" + backgroundColor + " ;";
905- }
906- else
907- {
908- htmlDoc.Body.Style = "background-image: url('" + backgroundImage + "'); background-attachment:fixed; background-color:" + backgroundColor + " background-repeat: no-repeat; background-position: " + backgroundLeft + " " + backgroundTop + ";";
909- }
910-
911 htmlDoc.Body.InnerHtml = "<h1>Loading...</h1>";
912 }
913
914@@ -243,15 +254,6 @@
915
916 htmlDoc.Body.InnerHtml = "";
917
918- if (backgroundImage == null || backgroundImage == "")
919- {
920- htmlDoc.Body.Style = "background-color:" + backgroundColor + " ;";
921- }
922- else
923- {
924- htmlDoc.Body.Style = "background-image: url('" + backgroundImage + "'); background-attachment:fixed; background-color:" + backgroundColor + " background-repeat: no-repeat; background-position: " + backgroundLeft + " " + backgroundTop + ";";
925- }
926-
927 //Get the RSS
928 rssReader = new RssReader();
929 rssReader.Url = rssFilePath;
930@@ -343,7 +345,7 @@
931 textWrap = String.Format("width: {0}px;", this.width - 50);
932 }
933
934- textRender += string.Format("<div id='text' style='position:relative;overflow:hidden;width:{0}px; height:{1}px;'>", this.width, this.height);
935+ textRender += string.Format("<div id='text' style='position:relative;overflow:hidden;width:{0}px; height:{1}px;'>", this.width - 10, this.height);
936 textRender += string.Format("<div id='innerText' style='position:absolute; left: 0px; top: 0px; {0}'>{1}</div></div>", textWrap, documentText);
937
938 htmlDoc.Body.InnerHtml = textRender;
939@@ -423,7 +425,7 @@
940 /// </summary>
941 public override void RenderMedia()
942 {
943- base.RenderMedia();
944+ base.StartTimer();
945 }
946
947 protected override void Dispose(bool disposing)
948
949=== modified file 'client/dotNET/RssReader.cs'
950--- client/dotNET/RssReader.cs 2008-12-19 23:34:13 +0000
951+++ client/dotNET/RssReader.cs 2009-07-07 06:05:50 +0000
952@@ -85,11 +85,8 @@
953 throw new ArgumentException("You must provide a feed URL");
954 }
955
956- //start the parsing process
957- XmlReader reader = XmlReader.Create(Url);
958-
959 XmlDocument xmlDoc = new XmlDocument();
960- xmlDoc.Load(reader);
961+ xmlDoc.Load(Url);
962
963 //parse the items of the feed
964 ParseDocElements(xmlDoc.SelectSingleNode("//channel"), "title", ref feedTitle);
965@@ -97,8 +94,6 @@
966
967 ParseRssItems(xmlDoc);
968
969- reader.Close();
970-
971 //return the feed items
972 return feedItems;
973 }
974
975=== modified file 'client/dotNET/Schedule.cs'
976--- client/dotNET/Schedule.cs 2009-06-18 18:36:21 +0000
977+++ client/dotNET/Schedule.cs 2009-08-03 21:56:06 +0000
978@@ -95,24 +95,25 @@
979 if (e.Error != null)
980 {
981 //There was an error - what do we do?
982- System.Diagnostics.Debug.WriteLine(e.Error.Message);
983+ System.Diagnostics.Trace.WriteLine(e.Error.Message);
984
985 // Is it a "not licensed" error
986 if (e.Error.Message == "This display client is not licensed")
987 {
988 Properties.Settings.Default.licensed = 0;
989- Properties.Settings.Default.Save();
990 }
991
992 xmdsProcessing = false;
993 }
994 else
995 {
996+ // Set the flag to indicate we have a connection to XMDS
997+ Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
998+
999 // Firstly we know we are licensed if we get this far
1000 if (Properties.Settings.Default.licensed == 0)
1001 {
1002 Properties.Settings.Default.licensed = 1;
1003- Properties.Settings.Default.Save();
1004 }
1005
1006 try
1007@@ -156,11 +157,6 @@
1008 {
1009 System.Diagnostics.Debug.WriteLine("Schedule Retrival Complete.");
1010
1011- // Send the XML log here if necessary
1012- XmlLog log = new XmlLog();
1013-
1014- log.PrepareAndSend();
1015-
1016 // Set XMDS to no longer be processing
1017 xmdsProcessing = false;
1018
1019@@ -168,13 +164,16 @@
1020 if (e.Error != null)
1021 {
1022 //There was an error - what do we do?
1023- System.Diagnostics.Debug.WriteLine(e.Error.Message);
1024+ System.Diagnostics.Trace.WriteLine(e.Error.Message);
1025 }
1026 else
1027 {
1028 // Only update the schedule if its changed.
1029 String md5CurrentSchedule = "";
1030
1031+ // Set the flag to indicate we have a connection to XMDS
1032+ Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
1033+
1034 try
1035 {
1036 StreamReader sr = new StreamReader(File.Open(this.scheduleLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite));
1037@@ -217,10 +216,17 @@
1038 System.Diagnostics.Debug.WriteLine("Layout file changed");
1039
1040 // If the layout that got changed is the current layout, move on
1041- if (layoutSchedule[currentLayout].layoutFile == Properties.Settings.Default.LibraryPath + @"\" + layoutPath)
1042- {
1043- forceChange = true;
1044- NextLayout();
1045+ try
1046+ {
1047+ if (layoutSchedule[currentLayout].layoutFile == Properties.Settings.Default.LibraryPath + @"\" + layoutPath)
1048+ {
1049+ forceChange = true;
1050+ NextLayout();
1051+ }
1052+ }
1053+ catch (Exception ex)
1054+ {
1055+ System.Diagnostics.Trace.WriteLine(new LogMessage("fileCollector_LayoutFileChanged", String.Format("Unable to determine current layout with exception {0}", ex.Message)), LogType.Error.ToString());
1056 }
1057 }
1058
1059@@ -235,7 +241,7 @@
1060 }
1061 else
1062 {
1063- Application.DoEvents(); // Make sure everything that is cued to render does
1064+ Application.DoEvents(); // Make sure everything that is queued to render does
1065
1066 xmdsProcessing = true;
1067
1068@@ -244,6 +250,9 @@
1069 // Fire off a get required files event - async
1070 xmds2.RequiredFilesAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, Properties.Settings.Default.Version);
1071 }
1072+
1073+ // Flush the log
1074+ System.Diagnostics.Trace.Flush();
1075 }
1076
1077 /// <summary>
1078@@ -270,8 +279,6 @@
1079
1080 System.Diagnostics.Debug.WriteLine(String.Format("Next layout: {0}", layoutSchedule[currentLayout].layoutFile), "Schedule - Next Layout");
1081
1082- XmlLog.AppendStat("Layout Finished", StatType.LayoutEnd, layoutSchedule[previousLayout].scheduleid, layoutSchedule[previousLayout].id, "0");
1083-
1084 forceChange = false;
1085
1086 //Raise the event
1087
1088=== added file 'client/dotNET/StatLog.cs'
1089--- client/dotNET/StatLog.cs 1970-01-01 00:00:00 +0000
1090+++ client/dotNET/StatLog.cs 2009-08-02 15:54:18 +0000
1091@@ -0,0 +1,330 @@
1092+/*
1093+ * Xibo - Digitial Signage - http://www.xibo.org.uk
1094+ * Copyright (C) 2009 Daniel Garner
1095+ *
1096+ * This file is part of Xibo.
1097+ *
1098+ * Xibo is free software: you can redistribute it and/or modify
1099+ * it under the terms of the GNU Affero General Public License as published by
1100+ * the Free Software Foundation, either version 3 of the License, or
1101+ * any later version.
1102+ *
1103+ * Xibo is distributed in the hope that it will be useful,
1104+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1105+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1106+ * GNU Affero General Public License for more details.
1107+ *
1108+ * You should have received a copy of the GNU Affero General Public License
1109+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
1110+ */
1111+using System;
1112+using System.Collections.Generic;
1113+using System.Collections.ObjectModel;
1114+using System.Text;
1115+using System.IO;
1116+using System.Windows.Forms;
1117+using System.Xml;
1118+
1119+namespace XiboClient
1120+{
1121+ class StatLog
1122+ {
1123+ private Collection<Stat> _stats;
1124+ private xmds.xmds _xmds;
1125+ private String _lastSubmit;
1126+ private HardwareKey _hardwareKey;
1127+ private Boolean _xmdsProcessing;
1128+
1129+ public StatLog()
1130+ {
1131+ _stats = new Collection<Stat>();
1132+ _xmds = new xmds.xmds();
1133+
1134+ // Register a listener for the XMDS stats
1135+ _xmds.SubmitStatsCompleted += new XiboClient.xmds.SubmitStatsCompletedEventHandler(_xmds_SubmitStatsCompleted);
1136+
1137+ // Get the key for this display
1138+ _hardwareKey = new HardwareKey();
1139+
1140+ _xmdsProcessing = false;
1141+ }
1142+
1143+ /// <summary>
1144+ /// Record a complete Layout Event
1145+ /// </summary>
1146+ /// <param name="fromDT"></param>
1147+ /// <param name="toDT"></param>
1148+ /// <param name="scheduleID"></param>
1149+ /// <param name="layoutID"></param>
1150+ public void RecordLayout(String fromDT, String toDT, int scheduleID, int layoutID)
1151+ {
1152+ if (!Properties.Settings.Default.statsEnabled) return;
1153+
1154+ Stat stat = new Stat();
1155+
1156+ stat.type = StatType.Layout;
1157+ stat.fromDate = fromDT;
1158+ stat.toDate = toDT;
1159+ stat.scheduleID = scheduleID;
1160+ stat.layoutID = layoutID;
1161+
1162+ _stats.Add(stat);
1163+
1164+ return;
1165+ }
1166+
1167+ /// <summary>
1168+ /// Record a complete Media Event
1169+ /// </summary>
1170+ /// <param name="fromDT"></param>
1171+ /// <param name="toDT"></param>
1172+ /// <param name="layoutID"></param>
1173+ /// <param name="mediaID"></param>
1174+ public void RecordMedia(String fromDT, String toDT, int layoutID, String mediaID)
1175+ {
1176+ if (!Properties.Settings.Default.statsEnabled) return;
1177+
1178+ Stat stat = new Stat();
1179+
1180+ stat.type = StatType.Media;
1181+ stat.fromDate = fromDT;
1182+ stat.toDate = toDT;
1183+ stat.layoutID = layoutID;
1184+ stat.mediaID = mediaID;
1185+
1186+ _stats.Add(stat);
1187+
1188+ return;
1189+ }
1190+
1191+ /// <summary>
1192+ /// Record a complete Event
1193+ /// </summary>
1194+ /// <param name="fromDT"></param>
1195+ /// <param name="toDT"></param>
1196+ /// <param name="tag"></param>
1197+ public void RecordEvent(String fromDT, String toDT, String tag)
1198+ {
1199+ if (!Properties.Settings.Default.statsEnabled) return;
1200+
1201+ Stat stat = new Stat();
1202+
1203+ stat.type = StatType.Event;
1204+ stat.fromDate = fromDT;
1205+ stat.toDate = toDT;
1206+ stat.tag = tag;
1207+
1208+ _stats.Add(stat);
1209+
1210+ return;
1211+ }
1212+
1213+ /// <summary>
1214+ /// RecordStat
1215+ /// </summary>
1216+ /// <param name="stat"></param>
1217+ public void RecordStat(Stat stat)
1218+ {
1219+ System.Diagnostics.Debug.WriteLine(String.Format("Recording a Stat Record. Current Count = {0}", _stats.Count.ToString()), LogType.Audit.ToString());
1220+
1221+ _stats.Add(stat);
1222+
1223+ // At some point we will need to flush the stats
1224+ if (_stats.Count >= Properties.Settings.Default.StatsFlushCount)
1225+ {
1226+ Flush();
1227+ }
1228+
1229+ return;
1230+ }
1231+
1232+ /// <summary>
1233+ /// Flush the stats
1234+ /// </summary>
1235+ public void Flush()
1236+ {
1237+ System.Diagnostics.Debug.WriteLine(new LogMessage("Flush", String.Format("IN")), LogType.Audit.ToString());
1238+
1239+ // Determine if there is anything to flush
1240+ if (_stats.Count < 1 || _xmdsProcessing) return;
1241+
1242+ int threshold = ((int)Properties.Settings.Default.collectInterval * 5);
1243+
1244+ // Determine where we want to log.
1245+ if (Properties.Settings.Default.XmdsLastConnection.AddSeconds(threshold) < DateTime.Now)
1246+ {
1247+ FlushToFile();
1248+ }
1249+ else
1250+ {
1251+ FlushToXmds();
1252+ }
1253+
1254+ System.Diagnostics.Debug.WriteLine(new LogMessage("Flush", String.Format("OUT")), LogType.Audit.ToString());
1255+ }
1256+
1257+ /// <summary>
1258+ /// Send the Stat to a File
1259+ /// </summary>
1260+ private void FlushToFile()
1261+ {
1262+ System.Diagnostics.Debug.WriteLine(new LogMessage("FlushToFile", String.Format("IN")), LogType.Audit.ToString());
1263+
1264+ // There is something to flush - we want to parse the collection adding to the TextWriter each time.
1265+ try
1266+ {
1267+ // Open the Text Writer
1268+ StreamWriter tw = new StreamWriter(File.Open(Application.UserAppDataPath + "//" + Properties.Settings.Default.StatsLogFile, FileMode.Append, FileAccess.Write, FileShare.Read), Encoding.UTF8);
1269+
1270+ try
1271+ {
1272+ foreach (Stat stat in _stats)
1273+ {
1274+ tw.WriteLine(stat.ToString());
1275+ }
1276+ }
1277+ catch (Exception ex)
1278+ {
1279+ System.Diagnostics.Trace.WriteLine(new LogMessage("FlushToFile", String.Format("Error writing stats line to file with exception {0}", ex.Message)), LogType.Error.ToString());
1280+ }
1281+ finally
1282+ {
1283+ // Close the tw.
1284+ tw.Close();
1285+ tw.Dispose();
1286+ }
1287+ }
1288+ catch (Exception ex)
1289+ {
1290+ // Log this exception
1291+ System.Diagnostics.Trace.WriteLine(new LogMessage("FlushToFile", String.Format("Error writing stats to file with exception {0}", ex.Message)), LogType.Error.ToString());
1292+ }
1293+ finally
1294+ {
1295+ // Always clear the stats. If the file open failed for some reason then we dont want to try again
1296+ _stats.Clear();
1297+ }
1298+
1299+ System.Diagnostics.Debug.WriteLine(new LogMessage("FlushToFile", String.Format("OUT")), LogType.Audit.ToString());
1300+ }
1301+
1302+ /// <summary>
1303+ /// Send the Stats to XMDS
1304+ /// </summary>
1305+ private void FlushToXmds()
1306+ {
1307+ System.Diagnostics.Debug.WriteLine(new LogMessage("FlushToXmds", String.Format("IN")), LogType.Audit.ToString());
1308+
1309+ String stats;
1310+
1311+ stats = "<log>";
1312+
1313+ // Load the Stats collection into a string
1314+ try
1315+ {
1316+ foreach (Stat stat in _stats)
1317+ {
1318+ stats += stat.ToString();
1319+ }
1320+ }
1321+ catch (Exception ex)
1322+ {
1323+ System.Diagnostics.Trace.WriteLine(new LogMessage("FlushToXmds", String.Format("Error converting stat to a string {0}", ex.Message)), LogType.Error.ToString());
1324+ }
1325+
1326+ stats += "</log>";
1327+
1328+ // Store the stats as the last sent (so we have a record if it fails)
1329+ _lastSubmit = stats;
1330+
1331+ // Clear the stats collection
1332+ _stats.Clear();
1333+
1334+ // Submit the string to XMDS
1335+ _xmdsProcessing = true;
1336+
1337+ _xmds.SubmitStatsAsync(Properties.Settings.Default.Version, Properties.Settings.Default.ServerKey, _hardwareKey.Key, stats);
1338+
1339+ // Log out
1340+ System.Diagnostics.Debug.WriteLine(new LogMessage("FlushToXmds", String.Format("OUT")), LogType.Audit.ToString());
1341+ }
1342+
1343+ /// <summary>
1344+ /// Capture the XMDS call and see if it went well
1345+ /// </summary>
1346+ /// <param name="sender"></param>
1347+ /// <param name="e"></param>
1348+ void _xmds_SubmitStatsCompleted(object sender, XiboClient.xmds.SubmitStatsCompletedEventArgs e)
1349+ {
1350+ System.Diagnostics.Debug.WriteLine(new LogMessage("_xmds_SubmitStatsCompleted", String.Format("IN")), LogType.Audit.ToString());
1351+
1352+ _xmdsProcessing = false;
1353+
1354+ // Test if we succeeded or not
1355+ if (e.Error != null)
1356+ {
1357+ // We had an error, log it.
1358+ System.Diagnostics.Trace.WriteLine(new LogMessage("_xmds_SubmitStatsCompleted", String.Format("Error during Submit to XMDS {0}", e.Error.Message)), LogType.Error.ToString());
1359+
1360+ // Dump the stats to a file instead
1361+ if (_lastSubmit != "")
1362+ {
1363+ try
1364+ {
1365+ // Open the Text Writer
1366+ StreamWriter tw = new StreamWriter(File.Open(Application.UserAppDataPath + "//" + Properties.Settings.Default.StatsLogFile, FileMode.Append, FileAccess.Write, FileShare.Read), Encoding.UTF8);
1367+
1368+ try
1369+ {
1370+ tw.Write(_lastSubmit);
1371+ }
1372+ catch (Exception ex)
1373+ {
1374+ // Log this exception
1375+ System.Diagnostics.Trace.WriteLine(new LogMessage("_xmds_SubmitStatsCompleted", String.Format("Error writing stats to file with exception {0}", ex.Message)), LogType.Error.ToString());
1376+ }
1377+ finally
1378+ {
1379+ tw.Close();
1380+ tw.Dispose();
1381+ }
1382+ }
1383+ catch (Exception ex)
1384+ {
1385+ // Log this exception
1386+ System.Diagnostics.Trace.WriteLine(new LogMessage("_xmds_SubmitStatsCompleted", String.Format("Could not open the file with exception {0}", ex.Message)), LogType.Error.ToString());
1387+ }
1388+ }
1389+ }
1390+
1391+ // Clear the last sumbit
1392+ _lastSubmit = "";
1393+
1394+ System.Diagnostics.Debug.WriteLine(new LogMessage("_xmds_SubmitStatsCompleted", String.Format("OUT")), LogType.Audit.ToString());
1395+ }
1396+ }
1397+
1398+ class Stat
1399+ {
1400+ public StatType type;
1401+ public String fromDate;
1402+ public String toDate;
1403+ public int layoutID;
1404+ public int scheduleID;
1405+ public String mediaID;
1406+ public String tag;
1407+
1408+ public override string ToString()
1409+ {
1410+ // Format the message into the expected XML sub nodes.
1411+ // Just do this with a string builder rather than an XML builder.
1412+ String theMessage;
1413+
1414+ theMessage = String.Format("<stat type=\"{0}\" fromdt=\"{1}\" todt=\"{2}\" layoutid=\"{3}\" scheduleid=\"{4}\" mediaid=\"{5}\"></stat>", type, fromDate, toDate, layoutID.ToString(), scheduleID.ToString(), mediaID);
1415+
1416+ return theMessage;
1417+ }
1418+ }
1419+
1420+ public enum StatType { Layout, Media, Event };
1421+}
1422
1423=== modified file 'client/dotNET/Text.cs'
1424--- client/dotNET/Text.cs 2009-06-20 10:39:40 +0000
1425+++ client/dotNET/Text.cs 2009-08-03 21:56:06 +0000
1426@@ -27,7 +27,17 @@
1427 {
1428 class Text : Media
1429 {
1430- private double scaleFactor;
1431+ private string filePath;
1432+ private string direction;
1433+ private string backgroundImage;
1434+ private string backgroundColor;
1435+ private WebBrowser webBrowser;
1436+ private string _documentText;
1437+
1438+ private string backgroundTop;
1439+ private string backgroundLeft;
1440+ private double _scaleFactor;
1441+ private int _scrollSpeed;
1442
1443 //<summary>
1444 //Creates a Text display control
1445@@ -41,7 +51,7 @@
1446 this.backgroundImage = options.backgroundImage;
1447 this.backgroundColor = options.backgroundColor;
1448
1449- scaleFactor = options.scaleFactor;
1450+ _scaleFactor = options.scaleFactor;
1451
1452 backgroundTop = options.backgroundTop + "px";
1453 backgroundLeft = options.backgroundLeft + "px";
1454@@ -50,12 +60,28 @@
1455 webBrowser.Size = this.Size;
1456 webBrowser.ScrollBarsEnabled = false;
1457
1458- //set the text
1459- documentText = options.text;
1460+ // set the text
1461+ _documentText = options.text;
1462+ _scrollSpeed = options.scrollSpeed;
1463+
1464+ // What do we want the background to look like
1465+ String bodyStyle;
1466+ String document;
1467+
1468+ if (backgroundImage == null || backgroundImage == "")
1469+ {
1470+ bodyStyle = "background-color:" + backgroundColor + " ;";
1471+ }
1472+ else
1473+ {
1474+ bodyStyle = "background-image: url('" + backgroundImage + "'); background-attachment:fixed; background-color:" + backgroundColor + " background-repeat: no-repeat; background-position: " + backgroundLeft + " " + backgroundTop + ";";
1475+ }
1476+
1477+ document = String.Format("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /><script type='text/javascript'>{0}</script>{2}<style type='text/css'>body {{{3}}}, p, h1, h2, h3, h4, h5 {{ margin:2px; font-size:{1}em; }}</style></head><body></body></html>", Properties.Resources.textRender, options.scaleFactor.ToString(), options.javaScript, bodyStyle);
1478
1479 try
1480 {
1481- webBrowser.DocumentText = String.Format("<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /><script type='text/javascript'>{0}</script><style type='text/css'>p, h1, h2, h3, h4, h5 {{ margin:2px; font-size:{1}em; }}</style></head><body></body></html>", Properties.Resources.textRender, options.scaleFactor.ToString());
1482+ webBrowser.DocumentText = document;
1483 }
1484 catch (Exception e)
1485 {
1486@@ -68,24 +94,14 @@
1487
1488 void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
1489 {
1490-
1491 HtmlDocument htmlDoc = webBrowser.Document;
1492-
1493- if (backgroundImage == null || backgroundImage == "")
1494- {
1495- htmlDoc.Body.Style = "background-color:" + backgroundColor + " ;";
1496- }
1497- else
1498- {
1499- htmlDoc.Body.Style = "background-image: url('" + backgroundImage + "'); background-attachment:fixed; background-color:" + backgroundColor + " background-repeat: no-repeat; background-position: " + backgroundLeft + " " + backgroundTop + ";";
1500- }
1501
1502 //decide whether we need a marquee or not
1503 if (direction == "none")
1504 {
1505 //we dont
1506- //set the body of the webBrowser to the document text (altered by the RSS feed)
1507- htmlDoc.Body.InnerHtml = documentText;
1508+ //set the body of the webBrowser to the document text
1509+ htmlDoc.Body.InnerHtml = _documentText;
1510 }
1511 else
1512 {
1513@@ -93,24 +109,36 @@
1514 String textWrap = "";
1515 if (direction == "left" || direction == "right") textWrap = "white-space: nowrap";
1516
1517- textRender += string.Format("<div id='text' style='position:relative;overflow:hidden;width:{0}; height:{1};'>", this.width, this.height);
1518- textRender += string.Format("<div id='innerText' style='position:absolute; left: 0px; top: 0px; {0}'>{1}</div></div>", textWrap, documentText);
1519+ textRender += string.Format("<div id='text' style='position:relative;overflow:hidden;width:{0}; height:{1};'>", this.width - 10, this.height);
1520+ textRender += string.Format("<div id='innerText' style='position:absolute; left: 0px; top: 0px; {0}'>{1}</div></div>", textWrap, _documentText);
1521
1522 htmlDoc.Body.InnerHtml = textRender;
1523
1524 Object[] objArray = new Object[2];
1525 objArray[0] = direction;
1526- objArray[1] = 30;
1527+ objArray[1] = _scrollSpeed;
1528
1529 htmlDoc.InvokeScript("init", objArray);
1530 }
1531
1532+ System.Diagnostics.Debug.WriteLine(htmlDoc.Body.InnerHtml, LogType.Audit.ToString());
1533+
1534+ // Try to call the EmbedInit Function
1535+ try
1536+ {
1537+ htmlDoc.InvokeScript("EmbedInit");
1538+ }
1539+ catch { }
1540+
1541+ // Add the control
1542 this.Controls.Add(webBrowser);
1543+
1544+ Show();
1545 }
1546
1547 public override void RenderMedia()
1548 {
1549- base.RenderMedia();
1550+ base.StartTimer();
1551 }
1552
1553 protected override void Dispose(bool disposing)
1554@@ -123,15 +151,5 @@
1555
1556 base.Dispose(disposing);
1557 }
1558-
1559- private string filePath;
1560- private string direction;
1561- private string backgroundImage;
1562- private string backgroundColor;
1563- private WebBrowser webBrowser;
1564- private string documentText;
1565-
1566- private string backgroundTop;
1567- private string backgroundLeft;
1568 }
1569 }
1570
1571=== modified file 'client/dotNET/Web References/xmds/Reference.cs'
1572--- client/dotNET/Web References/xmds/Reference.cs 2008-12-19 23:34:13 +0000
1573+++ client/dotNET/Web References/xmds/Reference.cs 2009-07-26 11:40:59 +0000
1574@@ -41,6 +41,10 @@
1575
1576 private System.Threading.SendOrPostCallback BlackListOperationCompleted;
1577
1578+ private System.Threading.SendOrPostCallback SubmitLogOperationCompleted;
1579+
1580+ private System.Threading.SendOrPostCallback SubmitStatsOperationCompleted;
1581+
1582 private bool useDefaultCredentialsSetExplicitly;
1583
1584 /// <remarks/>
1585@@ -98,6 +102,12 @@
1586 public event BlackListCompletedEventHandler BlackListCompleted;
1587
1588 /// <remarks/>
1589+ public event SubmitLogCompletedEventHandler SubmitLogCompleted;
1590+
1591+ /// <remarks/>
1592+ public event SubmitStatsCompletedEventHandler SubmitStatsCompleted;
1593+
1594+ /// <remarks/>
1595 [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#RegisterDisplay", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
1596 [return: System.Xml.Serialization.SoapElementAttribute("ActivationMessage")]
1597 public string RegisterDisplay(string serverKey, string hardwareKey, string displayName, string version) {
1598@@ -320,6 +330,78 @@
1599 }
1600
1601 /// <remarks/>
1602+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#SubmitLog", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
1603+ [return: System.Xml.Serialization.SoapElementAttribute("success")]
1604+ public bool SubmitLog(string version, string serverKey, string hardwareKey, string logXml) {
1605+ object[] results = this.Invoke("SubmitLog", new object[] {
1606+ version,
1607+ serverKey,
1608+ hardwareKey,
1609+ logXml});
1610+ return ((bool)(results[0]));
1611+ }
1612+
1613+ /// <remarks/>
1614+ public void SubmitLogAsync(string version, string serverKey, string hardwareKey, string logXml) {
1615+ this.SubmitLogAsync(version, serverKey, hardwareKey, logXml, null);
1616+ }
1617+
1618+ /// <remarks/>
1619+ public void SubmitLogAsync(string version, string serverKey, string hardwareKey, string logXml, object userState) {
1620+ if ((this.SubmitLogOperationCompleted == null)) {
1621+ this.SubmitLogOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSubmitLogOperationCompleted);
1622+ }
1623+ this.InvokeAsync("SubmitLog", new object[] {
1624+ version,
1625+ serverKey,
1626+ hardwareKey,
1627+ logXml}, this.SubmitLogOperationCompleted, userState);
1628+ }
1629+
1630+ private void OnSubmitLogOperationCompleted(object arg) {
1631+ if ((this.SubmitLogCompleted != null)) {
1632+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
1633+ this.SubmitLogCompleted(this, new SubmitLogCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
1634+ }
1635+ }
1636+
1637+ /// <remarks/>
1638+ [System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#SubmitLog", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
1639+ [return: System.Xml.Serialization.SoapElementAttribute("success")]
1640+ public bool SubmitStats(string version, string serverKey, string hardwareKey, string statXml) {
1641+ object[] results = this.Invoke("SubmitStats", new object[] {
1642+ version,
1643+ serverKey,
1644+ hardwareKey,
1645+ statXml});
1646+ return ((bool)(results[0]));
1647+ }
1648+
1649+ /// <remarks/>
1650+ public void SubmitStatsAsync(string version, string serverKey, string hardwareKey, string statXml) {
1651+ this.SubmitStatsAsync(version, serverKey, hardwareKey, statXml, null);
1652+ }
1653+
1654+ /// <remarks/>
1655+ public void SubmitStatsAsync(string version, string serverKey, string hardwareKey, string statXml, object userState) {
1656+ if ((this.SubmitStatsOperationCompleted == null)) {
1657+ this.SubmitStatsOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSubmitStatsOperationCompleted);
1658+ }
1659+ this.InvokeAsync("SubmitStats", new object[] {
1660+ version,
1661+ serverKey,
1662+ hardwareKey,
1663+ statXml}, this.SubmitStatsOperationCompleted, userState);
1664+ }
1665+
1666+ private void OnSubmitStatsOperationCompleted(object arg) {
1667+ if ((this.SubmitStatsCompleted != null)) {
1668+ System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
1669+ this.SubmitStatsCompleted(this, new SubmitStatsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
1670+ }
1671+ }
1672+
1673+ /// <remarks/>
1674 public new void CancelAsync(object userState) {
1675 base.CancelAsync(userState);
1676 }
1677@@ -493,6 +575,58 @@
1678 }
1679 }
1680 }
1681+
1682+ /// <remarks/>
1683+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.1433")]
1684+ public delegate void SubmitLogCompletedEventHandler(object sender, SubmitLogCompletedEventArgs e);
1685+
1686+ /// <remarks/>
1687+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.1433")]
1688+ [System.Diagnostics.DebuggerStepThroughAttribute()]
1689+ [System.ComponentModel.DesignerCategoryAttribute("code")]
1690+ public partial class SubmitLogCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1691+
1692+ private object[] results;
1693+
1694+ internal SubmitLogCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
1695+ base(exception, cancelled, userState) {
1696+ this.results = results;
1697+ }
1698+
1699+ /// <remarks/>
1700+ public bool Result {
1701+ get {
1702+ this.RaiseExceptionIfNecessary();
1703+ return ((bool)(this.results[0]));
1704+ }
1705+ }
1706+ }
1707+
1708+ /// <remarks/>
1709+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.1433")]
1710+ public delegate void SubmitStatsCompletedEventHandler(object sender, SubmitStatsCompletedEventArgs e);
1711+
1712+ /// <remarks/>
1713+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "2.0.50727.1433")]
1714+ [System.Diagnostics.DebuggerStepThroughAttribute()]
1715+ [System.ComponentModel.DesignerCategoryAttribute("code")]
1716+ public partial class SubmitStatsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
1717+
1718+ private object[] results;
1719+
1720+ internal SubmitStatsCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
1721+ base(exception, cancelled, userState) {
1722+ this.results = results;
1723+ }
1724+
1725+ /// <remarks/>
1726+ public bool Result {
1727+ get {
1728+ this.RaiseExceptionIfNecessary();
1729+ return ((bool)(this.results[0]));
1730+ }
1731+ }
1732+ }
1733 }
1734
1735 #pragma warning restore 1591
1736\ No newline at end of file
1737
1738=== modified file 'client/dotNET/Web References/xmds/Reference.map'
1739--- client/dotNET/Web References/xmds/Reference.map 2009-01-23 20:51:50 +0000
1740+++ client/dotNET/Web References/xmds/Reference.map 2009-07-26 11:40:59 +0000
1741@@ -1,6 +1,6 @@
1742 <?xml version="1.0" encoding="utf-8"?>
1743 <DiscoveryClientResultsFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
1744 <Results>
1745- <DiscoveryClientResult referenceType="System.Web.Services.Discovery.ContractReference" url="http://localhost/Xibo/server/xmds.php?wsdl" filename="xmds.wsdl" />
1746+ <DiscoveryClientResult referenceType="System.Web.Services.Discovery.ContractReference" url="http://localhost/1.0.0/server/xmds.php?wsdl" filename="xmds.wsdl" />
1747 </Results>
1748 </DiscoveryClientResultsFile>
1749\ No newline at end of file
1750
1751=== modified file 'client/dotNET/Web References/xmds/xmds.wsdl'
1752--- client/dotNET/Web References/xmds/xmds.wsdl 2009-01-23 20:51:50 +0000
1753+++ client/dotNET/Web References/xmds/xmds.wsdl 2009-07-26 11:40:59 +0000
1754@@ -63,6 +63,24 @@
1755 <wsdl:message name="BlackListResponse">
1756 <wsdl:part name="success" type="xsd:boolean" />
1757 </wsdl:message>
1758+ <wsdl:message name="SubmitLogRequest">
1759+ <wsdl:part name="version" type="xsd:string" />
1760+ <wsdl:part name="serverKey" type="xsd:string" />
1761+ <wsdl:part name="hardwareKey" type="xsd:string" />
1762+ <wsdl:part name="logXml" type="xsd:string" />
1763+ </wsdl:message>
1764+ <wsdl:message name="SubmitLogResponse">
1765+ <wsdl:part name="success" type="xsd:boolean" />
1766+ </wsdl:message>
1767+ <wsdl:message name="SubmitStatsRequest">
1768+ <wsdl:part name="version" type="xsd:string" />
1769+ <wsdl:part name="serverKey" type="xsd:string" />
1770+ <wsdl:part name="hardwareKey" type="xsd:string" />
1771+ <wsdl:part name="statXml" type="xsd:string" />
1772+ </wsdl:message>
1773+ <wsdl:message name="SubmitStatsResponse">
1774+ <wsdl:part name="success" type="xsd:boolean" />
1775+ </wsdl:message>
1776 <wsdl:portType name="xmdsPortType">
1777 <wsdl:operation name="RegisterDisplay">
1778 <documentation>Registered the Display on the Xibo Network</documentation>
1779@@ -94,6 +112,16 @@
1780 <wsdl:input message="tns:BlackListRequest" />
1781 <wsdl:output message="tns:BlackListResponse" />
1782 </wsdl:operation>
1783+ <wsdl:operation name="SubmitLog">
1784+ <documentation>Submit Logging from the Client</documentation>
1785+ <wsdl:input message="tns:SubmitLogRequest" />
1786+ <wsdl:output message="tns:SubmitLogResponse" />
1787+ </wsdl:operation>
1788+ <wsdl:operation name="SubmitStats">
1789+ <documentation>Submit Display statistics from the Client</documentation>
1790+ <wsdl:input message="tns:SubmitStatsRequest" />
1791+ <wsdl:output message="tns:SubmitStatsResponse" />
1792+ </wsdl:operation>
1793 </wsdl:portType>
1794 <wsdl:binding name="xmdsBinding" type="tns:xmdsPortType">
1795 <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />
1796@@ -151,10 +179,28 @@
1797 <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
1798 </wsdl:output>
1799 </wsdl:operation>
1800+ <wsdl:operation name="SubmitLog">
1801+ <soap:operation soapAction="urn:xmds#SubmitLog" style="rpc" />
1802+ <wsdl:input>
1803+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
1804+ </wsdl:input>
1805+ <wsdl:output>
1806+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
1807+ </wsdl:output>
1808+ </wsdl:operation>
1809+ <wsdl:operation name="SubmitStats">
1810+ <soap:operation soapAction="urn:xmds#SubmitLog" style="rpc" />
1811+ <wsdl:input>
1812+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
1813+ </wsdl:input>
1814+ <wsdl:output>
1815+ <soap:body use="encoded" namespace="urn:xmds" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
1816+ </wsdl:output>
1817+ </wsdl:operation>
1818 </wsdl:binding>
1819 <wsdl:service name="xmds">
1820 <wsdl:port name="xmdsPort" binding="tns:xmdsBinding">
1821- <soap:address location="http://localhost/Xibo/server/xmds.php" />
1822+ <soap:address location="http://localhost/1.0.0/server/xmds.php" />
1823 </wsdl:port>
1824 </wsdl:service>
1825 </wsdl:definitions>
1826\ No newline at end of file
1827
1828=== modified file 'client/dotNET/XiboClient.csproj'
1829--- client/dotNET/XiboClient.csproj 2009-03-28 19:13:50 +0000
1830+++ client/dotNET/XiboClient.csproj 2009-07-26 11:40:59 +0000
1831@@ -141,9 +141,11 @@
1832 <Compile Include="RssReader.cs" />
1833 <Compile Include="Schedule.cs" />
1834 <Compile Include="Settings.cs" />
1835+ <Compile Include="StatLog.cs" />
1836 <Compile Include="Text.cs">
1837 <SubType>Form</SubType>
1838 </Compile>
1839+ <Compile Include="LogMessage.cs" />
1840 <Compile Include="Video.cs">
1841 <SubType>Form</SubType>
1842 </Compile>
1843@@ -163,7 +165,6 @@
1844 </Compile>
1845 <Compile Include="WindowAnimator.cs" />
1846 <Compile Include="XiboTraceListener.cs" />
1847- <Compile Include="XmlLog.cs" />
1848 </ItemGroup>
1849 <ItemGroup>
1850 <COMReference Include="AxShockwaveFlashObjects">
1851@@ -226,10 +227,10 @@
1852 <WebReferences Include="Web References\" />
1853 </ItemGroup>
1854 <ItemGroup>
1855- <WebReferenceUrl Include="http://localhost/Xibo/server/xmds.php%3fwsdl">
1856+ <WebReferenceUrl Include="http://localhost/1.0.0/server/xmds.php%3fwsdl">
1857 <UrlBehavior>Dynamic</UrlBehavior>
1858 <RelPath>Web References\xmds\</RelPath>
1859- <UpdateFromURL>http://localhost/Xibo/server/xmds.php%3fwsdl</UpdateFromURL>
1860+ <UpdateFromURL>http://localhost/1.0.0/server/xmds.php%3fwsdl</UpdateFromURL>
1861 <ServiceLocationURL>
1862 </ServiceLocationURL>
1863 <CachedDynamicPropName>
1864
1865=== modified file 'client/dotNET/XiboTraceListener.cs'
1866--- client/dotNET/XiboTraceListener.cs 2009-03-08 12:41:17 +0000
1867+++ client/dotNET/XiboTraceListener.cs 2009-08-02 15:54:18 +0000
1868@@ -30,6 +30,13 @@
1869 {
1870 class XiboTraceListener : TraceListener
1871 {
1872+ private Collection<TraceMessage> _traceMessages;
1873+ private String _logPath;
1874+ private Boolean _xmdsProcessing;
1875+ private xmds.xmds _xmds;
1876+ private String _lastSubmit;
1877+ private HardwareKey _hardwareKey;
1878+
1879 public XiboTraceListener()
1880 {
1881 InitializeListener();
1882@@ -44,8 +51,17 @@
1883 private void InitializeListener()
1884 {
1885 // Make a new collection of TraceMessages
1886- traceMessages = new Collection<TraceMessage>();
1887- logPath = Application.UserAppDataPath + @"/" + Properties.Settings.Default.logLocation;
1888+ _traceMessages = new Collection<TraceMessage>();
1889+ _logPath = Application.UserAppDataPath + @"/" + Properties.Settings.Default.logLocation;
1890+
1891+ _xmdsProcessing = false;
1892+ _xmds = new xmds.xmds();
1893+
1894+ // Register a listener for the XMDS stats
1895+ _xmds.SubmitLogCompleted += new XiboClient.xmds.SubmitLogCompletedEventHandler(_xmds_SubmitLogCompleted);
1896+
1897+ // Get the key for this display
1898+ _hardwareKey = new HardwareKey();
1899 }
1900
1901 private void AddToCollection(string message, string category)
1902@@ -56,62 +72,133 @@
1903 traceMessage.dateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
1904 traceMessage.message = message;
1905
1906- traceMessages.Add(traceMessage);
1907+ _traceMessages.Add(traceMessage);
1908 }
1909
1910 private void FlushToFile()
1911 {
1912+ if (_traceMessages.Count < 1) return;
1913+
1914 try
1915 {
1916- XmlTextWriter xw = new XmlTextWriter(File.Open(logPath, FileMode.Append, FileAccess.Write, FileShare.Read), Encoding.UTF8);
1917-
1918- foreach (TraceMessage message in traceMessages)
1919+ // Open the Text Writer
1920+ StreamWriter tw = new StreamWriter(File.Open(_logPath, FileMode.Append, FileAccess.Write, FileShare.Read), Encoding.UTF8);
1921+
1922+ String theMessage;
1923+
1924+ foreach (TraceMessage message in _traceMessages)
1925 {
1926- xw.WriteStartElement("trace");
1927- xw.WriteElementString("category", message.category);
1928- xw.WriteElementString("date", message.dateTime);
1929- xw.WriteElementString("message", message.message);
1930- xw.WriteEndElement();
1931+ String traceMsg = message.message.ToString();
1932+
1933+ theMessage = String.Format("<trace date=\"{0}\" category=\"{1}\">{2}</trace>", message.dateTime, message.category, traceMsg);
1934+ tw.WriteLine(theMessage);
1935 }
1936
1937- xw.Close();
1938+ // Close the tw.
1939+ tw.Close();
1940+ tw.Dispose();
1941
1942 // Remove the messages we have just added
1943- traceMessages.Clear();
1944+ _traceMessages.Clear();
1945 }
1946- catch (Exception e)
1947+ catch
1948 {
1949 // What can we do?
1950 }
1951-
1952- // Test the size of the XML file
1953- FileInfo fileInfo = new FileInfo(logPath);
1954-
1955- // If its greater than a certain size - send it to the WebService
1956- if (fileInfo.Length > 6000)
1957- {
1958- // Move the current log file to a ready file
1959- try
1960- {
1961- String logPathTemp = Application.UserAppDataPath + @"/" + String.Format("{0}.ready", DateTime.Now.ToFileTime().ToString());
1962-
1963- File.Move(logPath, logPathTemp);
1964- }
1965- catch (Exception ex)
1966- {
1967-
1968- }
1969- }
1970+ finally
1971+ {
1972+ _traceMessages.Clear();
1973+ }
1974+ }
1975+
1976+ /// <summary>
1977+ /// Flush the log to XMDS
1978+ /// </summary>
1979+ private void FlushToXmds()
1980+ {
1981+ String log;
1982+
1983+ log = "<log>";
1984+
1985+ // Load the Stats collection into a string
1986+ try
1987+ {
1988+ foreach (TraceMessage traceMessage in _traceMessages)
1989+ {
1990+ String traceMsg = traceMessage.message.ToString();
1991+
1992+ log += String.Format("<trace date=\"{0}\" category=\"{1}\">{2}</trace>", traceMessage.dateTime, traceMessage.category, traceMsg);
1993+ }
1994+ }
1995+ catch (Exception ex)
1996+ {
1997+ System.Diagnostics.Trace.WriteLine(new LogMessage("FlushToXmds", String.Format("Error converting stat to a string {0}", ex.Message)), LogType.Error.ToString());
1998+ }
1999+
2000+ log += "</log>";
2001+
2002+ // Store the stats as the last sent (so we have a record if it fails)
2003+ _lastSubmit = log;
2004+
2005+ // Clear the stats collection
2006+ _traceMessages.Clear();
2007+
2008+ // Submit the string to XMDS
2009+ _xmdsProcessing = true;
2010+
2011+ _xmds.SubmitLogAsync(Properties.Settings.Default.Version, Properties.Settings.Default.ServerKey, _hardwareKey.Key, log);
2012+ }
2013+
2014+ /// <summary>
2015+ /// Capture the XMDS call and see if it went well
2016+ /// </summary>
2017+ /// <param name="sender"></param>
2018+ /// <param name="e"></param>
2019+ void _xmds_SubmitLogCompleted(object sender, XiboClient.xmds.SubmitLogCompletedEventArgs e)
2020+ {
2021+ _xmdsProcessing = false;
2022+
2023+ // Test if we succeeded or not
2024+ if (e.Error != null)
2025+ {
2026+ // We had an error, log it.
2027+ System.Diagnostics.Trace.WriteLine(new LogMessage("_xmds_SubmitLogCompleted", String.Format("Error during Submit to XMDS {0}", e.Error.Message)), LogType.Error.ToString());
2028+
2029+ // Dump the stats to a file instead
2030+ if (_lastSubmit != "")
2031+ {
2032+ try
2033+ {
2034+ // Open the Text Writer
2035+ StreamWriter tw = new StreamWriter(File.Open(_logPath, FileMode.Append, FileAccess.Write, FileShare.Read), Encoding.UTF8);
2036+
2037+ try
2038+ {
2039+ tw.Write(_lastSubmit);
2040+ }
2041+ catch {}
2042+ finally
2043+ {
2044+ tw.Close();
2045+ tw.Dispose();
2046+ }
2047+ }
2048+ catch {}
2049+ }
2050+ }
2051+
2052+ // Clear the last sumbit
2053+ _lastSubmit = "";
2054 }
2055
2056 public override void Write(string message)
2057 {
2058- AddToCollection(message, "");
2059+ AddToCollection(message, "Audit");
2060 }
2061
2062 public override void Write(object o)
2063 {
2064- AddToCollection(o.ToString(), "");
2065+ AddToCollection(o.ToString(), "Audit");
2066 }
2067
2068 public override void Write(string message, string category)
2069@@ -162,16 +249,47 @@
2070
2071 public override void Close()
2072 {
2073- FlushToFile();
2074+ // Determine if there is anything to flush
2075+ if (_traceMessages.Count < 1) return;
2076+
2077+ // As we are closing if XMDS is already busy just log to file.
2078+ if (_xmdsProcessing)
2079+ {
2080+ FlushToFile();
2081+ }
2082+ else
2083+ {
2084+ int threshold = ((int)Properties.Settings.Default.collectInterval * 5);
2085+
2086+ // Determine where we want to log.
2087+ if (Properties.Settings.Default.XmdsLastConnection.AddSeconds(threshold) < DateTime.Now)
2088+ {
2089+ FlushToFile();
2090+ }
2091+ else
2092+ {
2093+ FlushToXmds();
2094+ }
2095+ }
2096 }
2097
2098 public override void Flush()
2099 {
2100- FlushToFile();
2101+ // Determine if there is anything to flush
2102+ if (_traceMessages.Count < 1 || _xmdsProcessing) return;
2103+
2104+ int threshold = ((int)Properties.Settings.Default.collectInterval * 5);
2105+
2106+ // Determine where we want to log.
2107+ if (Properties.Settings.Default.XmdsLastConnection.AddSeconds(threshold) < DateTime.Now)
2108+ {
2109+ FlushToFile();
2110+ }
2111+ else
2112+ {
2113+ FlushToXmds();
2114+ }
2115 }
2116-
2117- private Collection<TraceMessage> traceMessages;
2118- private String logPath;
2119 }
2120
2121 [Serializable]
2122
2123=== removed file 'client/dotNET/XmlLog.cs'
2124--- client/dotNET/XmlLog.cs 2009-03-08 12:51:18 +0000
2125+++ client/dotNET/XmlLog.cs 1970-01-01 00:00:00 +0000
2126@@ -1,172 +0,0 @@
2127-/*
2128- * Xibo - Digitial Signage - http://www.xibo.org.uk
2129- * Copyright (C) 2006,2007,2008 Daniel Garner and James Packer
2130- *
2131- * This file is part of Xibo.
2132- *
2133- * Xibo is free software: you can redistribute it and/or modify
2134- * it under the terms of the GNU Affero General Public License as published by
2135- * the Free Software Foundation, either version 3 of the License, or
2136- * any later version.
2137- *
2138- * Xibo is distributed in the hope that it will be useful,
2139- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2140- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2141- * GNU Affero General Public License for more details.
2142- *
2143- * You should have received a copy of the GNU Affero General Public License
2144- * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
2145- */
2146-using System;
2147-using System.Collections.Generic;
2148-using System.IO;
2149-using System.Text;
2150-using System.Windows.Forms;
2151-using System.Xml;
2152-
2153-namespace XiboClient
2154-{
2155- class XmlLog
2156- {
2157- /// <summary>
2158- /// Creates a new XmlLog Class used for sending the log
2159- /// </summary>
2160- /// <param name="logPath"></param>
2161- public XmlLog()
2162- {
2163- logPath = Application.UserAppDataPath + @"/" + Properties.Settings.Default.logLocation;
2164-
2165- // Get the key for this display
2166- hardwareKey = new HardwareKey();
2167-
2168- // Setup the WebService call
2169- xmds1 = new XiboClient.xmds.xmds();
2170- xmds1.RecieveXmlLogCompleted += new XiboClient.xmds.RecieveXmlLogCompletedEventHandler(xmds1_RecieveXmlLogCompleted);
2171-
2172- return;
2173- }
2174-
2175- /// <summary>
2176- /// Prepares the log for sending
2177- /// </summary>
2178- public void PrepareAndSend()
2179- {
2180- currentFile = 0;
2181-
2182- // Get a list of all the log files avaiable to process
2183- DirectoryInfo di = new DirectoryInfo(Application.UserAppDataPath);
2184-
2185- files = di.GetFiles("*.ready");
2186-
2187- // There thought never be no files
2188- if (files.Length == 0) return;
2189-
2190- // Send them (one by one)
2191- SendLog(files[currentFile].FullName);
2192-
2193- return;
2194- }
2195-
2196- /// <summary>
2197- /// Sends and XmlLog files that are ready to send
2198- /// Binds a xmds1.RecieveXmlLogCompleted event
2199- /// </summary>
2200- public void SendLog(string filePath)
2201- {
2202- // Read the Xml
2203- try
2204- {
2205- StreamReader tr = new StreamReader(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
2206- xmds1.RecieveXmlLogAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, tr.ReadToEnd(), Properties.Settings.Default.Version);
2207- tr.Close();
2208- }
2209- catch (Exception ex)
2210- {
2211- System.Diagnostics.Debug.WriteLine(ex.Message);
2212- }
2213- }
2214-
2215- /// <summary>
2216- /// Completed sending the XML Log
2217- /// </summary>
2218- /// <param name="sender"></param>
2219- /// <param name="e"></param>
2220- void xmds1_RecieveXmlLogCompleted(object sender, XiboClient.xmds.RecieveXmlLogCompletedEventArgs e)
2221- {
2222- // Delete the Log File if success
2223- if (e.Error != null)
2224- {
2225- System.Diagnostics.Debug.WriteLine(e.Error.Message);
2226- }
2227- else
2228- {
2229- if (e.Result)
2230- {
2231- try
2232- {
2233- // Do the delete
2234- File.Delete(files[currentFile].FullName);
2235- }
2236- catch (Exception ex)
2237- {
2238- System.Diagnostics.Debug.WriteLine(ex.Message);
2239- }
2240- }
2241- }
2242-
2243- // Process the next file in the que
2244- currentFile++;
2245-
2246- if (currentFile < files.Length)
2247- {
2248- SendLog(files[currentFile].FullName);
2249- }
2250-
2251- return;
2252- }
2253-
2254- /// <summary>
2255- /// Appends a Stats XML message to the current Log
2256- /// </summary>
2257- /// <param name="message"></param>
2258- /// <param name="cat"></param>
2259- /// <param name="type"></param>
2260- /// <param name="scheduleID"></param>
2261- /// <param name="layoutID"></param>
2262- /// <param name="mediaID"></param>
2263- public static void AppendStat(String message, StatType type, int scheduleID, int layoutID, string mediaID)
2264- {
2265- if (!Properties.Settings.Default.statsEnabled) return;
2266-
2267- try
2268- {
2269- XmlTextWriter xw = new XmlTextWriter(File.Open(Application.UserAppDataPath + "//" + Properties.Settings.Default.logLocation, FileMode.Append, FileAccess.Write, FileShare.Read), Encoding.UTF8);
2270-
2271- xw.WriteStartElement("stat");
2272-
2273- xw.WriteElementString("date", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
2274- xw.WriteElementString("message", message);
2275- xw.WriteElementString("type", type.ToString());
2276- xw.WriteElementString("scheduleID", scheduleID.ToString());
2277- xw.WriteElementString("layoutID", layoutID.ToString());
2278- if (mediaID != "0") xw.WriteElementString("mediaID", mediaID.ToString());
2279-
2280- xw.WriteEndElement();
2281-
2282- xw.Close();
2283- }
2284- catch (Exception ex)
2285- {
2286- }
2287- }
2288-
2289- private XiboClient.xmds.xmds xmds1;
2290- private HardwareKey hardwareKey;
2291- string logPath;
2292-
2293- FileInfo[] files;
2294- int currentFile;
2295- }
2296-
2297- public enum StatType { LayoutStart, LayoutEnd, MediaStart, MediaEnd };
2298-}
2299
2300=== modified file 'client/dotNET/app.config'
2301--- client/dotNET/app.config 2009-03-08 11:40:17 +0000
2302+++ client/dotNET/app.config 2009-07-30 23:01:31 +0000
2303@@ -14,7 +14,7 @@
2304 <value>DEFAULT</value>
2305 </setting>
2306 <setting name="XiboClient_xmds_xmds" serializeAs="String">
2307- <value>http://localhost/Xibo/server/xmds.php</value>
2308+ <value>http://localhost/1.0.0/server/xmds.php</value>
2309 </setting>
2310 <setting name="ServerKey" serializeAs="String">
2311 <value>changetocustomerkey</value>
2312@@ -25,9 +25,6 @@
2313 <setting name="licensed" serializeAs="String">
2314 <value>0</value>
2315 </setting>
2316- <setting name="collectInterval" serializeAs="String">
2317- <value>900</value>
2318- </setting>
2319 <setting name="powerpointEnabled" serializeAs="String">
2320 <value>False</value>
2321 </setting>
2322@@ -49,6 +46,18 @@
2323 <setting name="ProxyPort" serializeAs="String">
2324 <value />
2325 </setting>
2326+ <setting name="hardwareKey" serializeAs="String">
2327+ <value />
2328+ </setting>
2329+ <setting name="StatsFlushCount" serializeAs="String">
2330+ <value>50</value>
2331+ </setting>
2332+ <setting name="XmdsLastConnection" serializeAs="String">
2333+ <value />
2334+ </setting>
2335+ <setting name="collectInterval" serializeAs="String">
2336+ <value>900</value>
2337+ </setting>
2338 </XiboClient.Properties.Settings>
2339 </userSettings>
2340 <applicationSettings>
2341@@ -65,6 +74,9 @@
2342 <setting name="Version" serializeAs="String">
2343 <value>1</value>
2344 </setting>
2345+ <setting name="StatsLogFile" serializeAs="String">
2346+ <value>stats.xml</value>
2347+ </setting>
2348 </XiboClient.Properties.Settings>
2349 </applicationSettings>
2350 </configuration>
2351\ No newline at end of file
2352
2353=== removed file 'client/dotNET/bin/Release/XiboClient.XmlSerializers.dll'
2354Binary files client/dotNET/bin/Release/XiboClient.XmlSerializers.dll 2009-06-20 10:39:40 +0000 and client/dotNET/bin/Release/XiboClient.XmlSerializers.dll 1970-01-01 00:00:00 +0000 differ
2355=== removed file 'client/dotNET/bin/Release/XiboClient.exe'
2356Binary files client/dotNET/bin/Release/XiboClient.exe 2009-06-20 10:39:40 +0000 and client/dotNET/bin/Release/XiboClient.exe 1970-01-01 00:00:00 +0000 differ
2357=== modified file 'client/dotNET/bin/Release/XiboClient.exe.config'
2358--- client/dotNET/bin/Release/XiboClient.exe.config 2009-03-08 12:41:17 +0000
2359+++ client/dotNET/bin/Release/XiboClient.exe.config 2009-07-30 23:01:31 +0000
2360@@ -14,7 +14,7 @@
2361 <value>DEFAULT</value>
2362 </setting>
2363 <setting name="XiboClient_xmds_xmds" serializeAs="String">
2364- <value>http://localhost/Xibo/server/xmds.php</value>
2365+ <value>http://localhost/1.0.0/server/xmds.php</value>
2366 </setting>
2367 <setting name="ServerKey" serializeAs="String">
2368 <value>changetocustomerkey</value>
2369@@ -25,9 +25,6 @@
2370 <setting name="licensed" serializeAs="String">
2371 <value>0</value>
2372 </setting>
2373- <setting name="collectInterval" serializeAs="String">
2374- <value>900</value>
2375- </setting>
2376 <setting name="powerpointEnabled" serializeAs="String">
2377 <value>False</value>
2378 </setting>
2379@@ -49,6 +46,18 @@
2380 <setting name="ProxyPort" serializeAs="String">
2381 <value />
2382 </setting>
2383+ <setting name="hardwareKey" serializeAs="String">
2384+ <value />
2385+ </setting>
2386+ <setting name="StatsFlushCount" serializeAs="String">
2387+ <value>50</value>
2388+ </setting>
2389+ <setting name="XmdsLastConnection" serializeAs="String">
2390+ <value />
2391+ </setting>
2392+ <setting name="collectInterval" serializeAs="String">
2393+ <value>900</value>
2394+ </setting>
2395 </XiboClient.Properties.Settings>
2396 </userSettings>
2397 <applicationSettings>
2398@@ -65,6 +74,9 @@
2399 <setting name="Version" serializeAs="String">
2400 <value>1</value>
2401 </setting>
2402+ <setting name="StatsLogFile" serializeAs="String">
2403+ <value>stats.xml</value>
2404+ </setting>
2405 </XiboClient.Properties.Settings>
2406 </applicationSettings>
2407 </configuration>
2408\ No newline at end of file
2409
2410=== removed file 'client/dotNET/bin/Release/XiboClient.pdb'
2411Binary files client/dotNET/bin/Release/XiboClient.pdb 2009-06-20 10:39:40 +0000 and client/dotNET/bin/Release/XiboClient.pdb 1970-01-01 00:00:00 +0000 differ
2412=== modified file 'client/dotNET/bin/Release/XiboClient.vshost.exe.config'
2413--- client/dotNET/bin/Release/XiboClient.vshost.exe.config 2009-03-08 12:41:17 +0000
2414+++ client/dotNET/bin/Release/XiboClient.vshost.exe.config 2009-07-30 23:01:31 +0000
2415@@ -14,7 +14,7 @@
2416 <value>DEFAULT</value>
2417 </setting>
2418 <setting name="XiboClient_xmds_xmds" serializeAs="String">
2419- <value>http://localhost/Xibo/server/xmds.php</value>
2420+ <value>http://localhost/1.0.0/server/xmds.php</value>
2421 </setting>
2422 <setting name="ServerKey" serializeAs="String">
2423 <value>changetocustomerkey</value>
2424@@ -25,9 +25,6 @@
2425 <setting name="licensed" serializeAs="String">
2426 <value>0</value>
2427 </setting>
2428- <setting name="collectInterval" serializeAs="String">
2429- <value>900</value>
2430- </setting>
2431 <setting name="powerpointEnabled" serializeAs="String">
2432 <value>False</value>
2433 </setting>
2434@@ -49,6 +46,18 @@
2435 <setting name="ProxyPort" serializeAs="String">
2436 <value />
2437 </setting>
2438+ <setting name="hardwareKey" serializeAs="String">
2439+ <value />
2440+ </setting>
2441+ <setting name="StatsFlushCount" serializeAs="String">
2442+ <value>50</value>
2443+ </setting>
2444+ <setting name="XmdsLastConnection" serializeAs="String">
2445+ <value />
2446+ </setting>
2447+ <setting name="collectInterval" serializeAs="String">
2448+ <value>900</value>
2449+ </setting>
2450 </XiboClient.Properties.Settings>
2451 </userSettings>
2452 <applicationSettings>
2453@@ -65,6 +74,9 @@
2454 <setting name="Version" serializeAs="String">
2455 <value>1</value>
2456 </setting>
2457+ <setting name="StatsLogFile" serializeAs="String">
2458+ <value>stats.xml</value>
2459+ </setting>
2460 </XiboClient.Properties.Settings>
2461 </applicationSettings>
2462 </configuration>
2463\ No newline at end of file
2464
2465=== modified file 'server/3rdparty/fckeditor/editor/css/fck_editorarea.css'
2466--- server/3rdparty/fckeditor/editor/css/fck_editorarea.css 2008-12-14 14:41:09 +0000
2467+++ server/3rdparty/fckeditor/editor/css/fck_editorarea.css 2009-08-03 12:54:45 +0000
2468@@ -40,7 +40,7 @@
2469
2470 body, td
2471 {
2472- font-family: Arial, Verdana, sans-serif;
2473+ font-family: "Times New Roman", Times, serif;
2474 font-size: 12px;
2475 }
2476
2477
2478=== modified file 'server/3rdparty/jQuery/jquery.tablesorter.pack.js'
2479--- server/3rdparty/jQuery/jquery.tablesorter.pack.js 2008-12-14 14:42:52 +0000
2480+++ server/3rdparty/jQuery/jquery.tablesorter.pack.js 2009-06-27 10:56:12 +0000
2481@@ -1,8 +1,7 @@
2482 /*
2483 *
2484 * TableSorter 2.0 - Client-side table sorting with ease!
2485- * Version 2.0
2486- * @requires jQuery v1.1.3
2487+ * Version 2.0.3
2488 *
2489 * Copyright (c) 2007 Christian Bach
2490 * Examples and docs at: http://tablesorter.com
2491@@ -11,4 +10,4 @@
2492 * http://www.gnu.org/licenses/gpl.html
2493 *
2494 */
2495-eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(6($){$.1z({w:y 6(){7 k=[],12=[];u.2r={2g:"3c",2s:"2V",1P:"3L",2G:"3E",2x:"3w",1y:14,1l:"3b",1q:{},12:[],19:{16:["1X","1U"]},K:{},1Q:F,2I:W,H:[],1t:[],1g:"2u",L:F};6 1f(a,b){18(a+","+(y T().15()-b.15())+"3h")}6 18(s){q(1o 1O!="26"&&1o 1O.L!="26"){1O.18(s)}M{30(s)}}6 23(a,b){q(a.8.L){7 c=""}7 d=[],V=a.13[0].N[0].V,l=V.x;B(7 i=0;i<l;i++){7 p=F;q($.1w&&($(b[i]).Y()&&$(b[i]).Y().17)){p=1L($(b[i]).Y().17)}M q((a.8.K[i]&&a.8.K[i].17)){p=1L(a.8.K[i].17)}q(!p){p=2E(a.8,V[i])}q(a.8.L){c+="1u:"+i+" 3C:"+p.C+"\\n"}d.O(p)}q(a.8.L){18(c)}m d};6 2E(a,b){7 l=k.x;B(7 i=1;i<l;i++){q(k[i].I($.1G(1F(a,b)))){m k[i]}}m k[0]}6 1L(a){7 l=k.x;B(7 i=0;i<l;i++){q(k[i].C.Z()==a.Z()){m k[i]}}m F}6 1K(a){q(a.8.L){7 b=y T()}7 d=(a.13[0]&&a.13[0].N.x)||0,2m=a.13[0].N[0].V.x,k=a.8.1q,R={1x:[],1k:[]};B(7 i=0;i<d;++i){7 c=a.13[0].N[i],1d=[];R.1x.O($(c));B(7 j=0;j<2m;++j){1d.O(k[j].D(1F(a.8,c.V[j]),a,c.V[j]))}1d.O(i);R.1k.O(1d);1d=14};q(a.8.L){1f("3i R B "+d+" N:",b)}m R};6 1F(a,b){q(!b)m"";7 t="";q(1o(a.1l)=="6"){t=a.1l(b)}M q(a.1l=="3e"){t=$(b).1b()}M{q(b.1A[0]&&b.1A[0].3a()){t=b.1A[0].2a}M{t=b.2a}}m t}6 1n(a,b){q(a.8.L){7 d=y T()}7 c=b,r=c.1x,n=c.1k,29=n.x,1B=(n[0].x-1),2d=$("1p:1c",a).32();N=[];B(7 i=0;i<29;i++){N.O(r[n[i][1B]]);q(a.8.1D==14){2d.2k(r[n[i][1B]])}}q(a.8.1D!=14){a.8.1D(a,N)}N=14;1E(a);q(a.8.L){1f("2X 1h:",d)}};6 20(b){q(b.8.L){7 c=y T()}7 d=($.1w)?W:F,1H=[];B(7 i=0;i<b.1e.N.x;i++){1H[i]=0};$1s=$(1J(b,1H,0,b.1e.N[0].V.x));$1s.1r(6(a){u.11=0;u.1u=a;u.1j=1T(b.8.2G);q(1S(u)||1R(b,a))u.1i=W;q(!u.1i){$(u).1m(b.8.2g)}b.8.1t[a]=u});q(b.8.L){1f("2O K:",c);18($1s)}m $1s};6 1J(a,b,d){7 e=[],r=a.1e.N,c=r[d].V;B(7 i=b[d];i<c.x;i++){7 f=c[i];q(f.2N>1){e=e.3K(1J(a,b,d+f.2K))}M{q(a.1e.x==1||(f.2K>1||!r[d+1])){e.O(f)}b[d]=(i+d)}}m e};6 1S(a){q(($.1w)&&($(a).Y().17===F)){m W};m F}6 1R(a,i){q((a.8.K[i])&&(a.8.K[i].17===F)){m W};m F}6 1E(a){7 c=a.8.12;7 l=c.x;B(7 i=0;i<l;i++){2J(c[i]).D(a)}}6 2J(a){7 l=12.x;B(7 i=0;i<l;i++){q(12[i].C.Z()==a.Z()){m 12[i]}}};6 1T(v){q(1o(v)!="3J"){i=(v.Z()=="3I")?1:0}M{i=(v==(0||1))?v:0}m i}6 2H(v,a){7 l=a.x;B(7 i=0;i<l;i++){q(a[i][0]==v){m W}}m F}6 1N(b,c,d,e){c.1v(e[0]).1v(e[1]);7 h=[];c.1r(6(a){q(!u.1i){h[u.1u]=$(u)}});7 l=d.x;B(7 i=0;i<l;i++){h[d[i][0]].1m(e[d[i][1]])}}6 2F(a,b){7 c=a.8;q(c.1Q){7 d=$(\'<3H>\');$("1p:1c 1M:1c 3G",a).1r(6(){d.2k($(\'<3F>\').16(\'2D\',$(u).2D()))});$(a).3D(d)}}6 2B(a,b){7 c=a.8,l=b.x;B(7 i=0;i<l;i++){7 s=b[i],o=c.1t[s[0]];o.11=s[1];o.11++}}6 1I(a,b,d){q(a.8.L){7 f=y T()}7 g="7 2A = 6(a,b) {",l=b.x;B(7 i=0;i<l;i++){7 c=b[i][0];7 h=b[i][1];7 s=(2z(a.8.1q,c)=="1b")?((h==0)?"2y":"2w"):((h==0)?"2v":"2t");7 e="e"+i;g+="7 "+e+" = "+s+"(a["+c+"],b["+c+"]); ";g+="q("+e+") { m "+e+"; } ";g+="M { "}B(7 i=0;i<l;i++){g+="}; "}g+="m 0; ";g+="}; ";3B(g);d.1k.3A(2A);q(a.8.L){1f("3z 3y "+b.3x()+" 3v 3u "+h+" 2q:",f)}m d};6 2y(a,b){m((a<b)?-1:((a>b)?1:0))};6 2w(a,b){m((b<a)?-1:((b>a)?1:0))};6 2v(a,b){m a-b};6 2t(a,b){m b-a};6 2z(a,i){m a[i].J};u.2o=6(f){m u.1r(6(){7 c,$3t,$K,R,8,3s=0,3r;u.8={};8=$.1z(u.8,$.w.2r,f);q(!u.1e||!u.13)m W;c=$(u);$K=20(u);u.8.1q=23(u,$K);R=1K(u);7 d=[8.1P,8.2s];2F(u);$K.3p(6(e){q(!u.1i){7 b=$(u);7 i=u.1u;u.1j=u.11++%2;q(!e[8.2x]){8.H=[];q(8.1y!=14){7 a=8.1y;B(7 j=0;j<a.x;j++){8.H.O(a[j])}}8.H.O([i,u.1j])}M{q(2H(i,8.H)){B(7 j=0;j<8.H.x;j++){7 s=8.H[j],o=8.1t[s[0]];q(s[0]==i){o.11=s[1];o.11++;s[1]=o.11%2}}}M{8.H.O([i,u.1j])}};1N(c[0],$K,8.H,d);1n(c[0],1I(c[0],8.H,R));m F}}).3o(6(){q(8.2I){u.3n=6(){m F};m F}});c.1C("3m",6(){R=1K(u)}).1C("2j",6(e,a){7 b=8.H=a;2B(u,b);1N(u,$K,b,d);1n(u,1I(u,b,R))}).1C("3l",6(){1n(u,R)});q($.1w&&($(u).Y()&&$(u).Y().2i)){8.H=$(u).Y().2i}q(8.H.x>0){c.3k("2j",[8.H])}1E(u)})};u.G=6(b){7 l=k.x,a=W;B(7 i=0;i<l;i++){q(k[i].C.Z()==b.C.Z()){a=F}}q(a){k.O(b)}};u.2h=6(a){12.O(a)};u.S=6(s){7 i=3j(s);m(2f(i))?0:i};u.24=6(s){7 i=3g(s);m(2f(i))?0:i}}});$.3f.1z({w:$.w.2o});$.w.G({C:"1b",I:6(s){m W},D:6(s){m $.1G(s.Z())},J:"1b"});$.w.G({C:"2c",I:6(s){m s.25(y Q(/^\\d+$/))},D:6(s){m $.w.24(s)},J:"P"});$.w.G({C:"3d",I:6(s){m/^[£$€?.]/.U(s)},D:6(s){m $.w.S(s.X(y Q(/[^0-9.]/g),""))},J:"P"});$.w.G({C:"2c",I:6(s){m/^\\d+$/.U(s)},D:6(s){m $.w.S(s)},J:"P"});$.w.G({C:"39",I:6(s){m s.25(y Q(/^(\\+|-)?[0-9]+\\.[0-9]+((E|e)(\\+|-)?[0-9]+)?$/))},D:6(s){m $.w.S(s.X(y Q(/,/),""))},J:"P"});$.w.G({C:"38",I:6(s){m/^\\d{2,3}[\\.]\\d{2,3}[\\.]\\d{2,3}[\\.]\\d{2,3}$/.U(s)},D:6(s){7 a=s.37(".");7 r="";B(7 i=0,1a;1a=a[i];i++){q(1a.x==2){r+="0"+1a}M{r+=1a}}m $.w.S(s)},J:"P"});$.w.G({C:"36",I:6(s){m/^(28?|27|2e):\\/\\/$/.U(s)},D:6(s){m 2b.1G(s.X(y Q(/(28?|27|2e):\\/\\//),\'\'))},J:"1b"});$.w.G({C:"35",I:6(s){m/^\\d{4}[\\/-]\\d{1,2}[\\/-]\\d{1,2}$/.U(s)},D:6(s){m $.w.S((s!="")?y T(s.X(y Q(/-/g),"/")).15():"0")},J:"P"});$.w.G({C:"34",I:6(s){m/^\\d{1,3}%$/.U(s)},D:6(s){m $.w.S(s.X(y Q(/%/g),""))},J:"P"});$.w.G({C:"33",I:6(s){m/^[A-31-z]{3,10}\\.?[0-9]{1,2},([0-9]{4}|\\\'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\\s(2Z|3q)))$/.U(s);\n },\n D: 6(s) {\n m $.w.S(y T(s).15());\n },\n J: "P"\n });\n \n $.w.G({\n C: "2Y",\n I: 6(s) {\n m /\\d{1,2}[\\/-]\\d{1,2}[\\/-]\\d{2,4}/.U(s);\n },\n D: 6(s,1h) {\n 7 c = 1h.8;\n s = s.X(y Q(/-/g),"/");\n q(c.1g == "2u") {\n /** 2l 22 2p 21 2n D */\n s = s.X(y Q(/(\\d{1,2})[\\/-](\\d{1,2})[\\/-](\\d{4})/), "$3/$1/$2");\n } M q(c.1g == "2W") {\n /** 2l 22 2p 21 2n D */\n s = s.X(y Q(/(\\d{1,2})[\\/-](\\d{1,2})[\\/-](\\d{4})/), "$3/$2/$1");\n } M q(c.1g == "2C/1Z/1Y" || c.1g == "2C-1Z-1Y") {\n s = s.X(y Q(/(\\d{1,2})[\\/-](\\d{1,2})[\\/-](\\d{2})/), "$1/$2/$3"); \n }\n m $.w.S(y T(s).15());\n },\n J: "P"\n });\n \n $.w.G({\n C: "2q",\n I: 6(s) {\n m /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\\s(2U|2T)))$/.U(s);\n },\n D: 6(s) {\n m $.w.S(y T("2S/1W/1W " + s).15());\n },\n J: "P"\n });\n \n \n $.w.G({\n C: "2R",\n I: 6(s) {\n m F;\n },\n D: 6(s,1h,2M) {\n 7 c = 1h.8, p = (!c.1V) ? \'2Q\':c.1V;m $(2M).Y()[p]},J:"P"});$.w.2h({C:"2P",D:6(a){$("> 1p:1c/1M:2L:1X",a).1v(a.8.19.16[1]).1m(a.8.19.16[0]);$("> 1p:1c/1M:2L:1U",a).1v(a.8.19.16[0]).1m(a.8.19.16[1])}})})(2b);',62,234,'||||||function|var|config||||||||||||||return||||if||||this||tablesorter|length|new|||for|id|format||false|addParser|sortList|is|type|headers|debug|else|rows|push|numeric|RegExp|cache|formatFloat|Date|test|cells|true|replace|data|toLowerCase||count|widgets|tBodies|null|getTime|css|sorter|log|widgetZebra|item|text|first|cols|tHead|benchmark|dateFormat|table|sortDisabled|order|normalized|textExtraction|addClass|appendToTable|typeof|tbody|parsers|each|tableHeaders|headerList|column|removeClass|meta|row|sortForce|extend|childNodes|checkCell|bind|appender|applyWidget|getElementText|trim|tableHeadersRows|multisort|checkCellColSpan|buildCache|getParserById|tr|setHeadersCss|console|cssDesc|widthFixed|checkHeaderOptions|checkHeaderMetadata|formatSortingOrder|odd|parserMetadataName|01|even|yy|mm|buildHeaders|in|the|buildParserCache|formatInt|match|undefined|ftp|https|totalRows|innerHTML|jQuery|integer|tableBody|file|isNaN|cssHeader|addWidget|sortlist|sorton|append|reformat|totalCells|ISO|construct|string|time|defaults|cssAsc|sortNumericDesc|us|sortNumeric|sortTextDesc|sortMultiSortKey|sortText|getCachedSortType|sortWrapper|updateHeaderSortCount|dd|width|detectParserForColumn|fixColumnWidth|sortInitialOrder|isValueInArray|cancelSelection|getWidgetById|rowSpan|visible|cell|colSpan|Built|zebra|sortValue|metadata|2000|pm|am|headerSortUp|uk|Rebuilt|shortDate|AM|alert|Za|empty|usLongDate|percent|isoDate|url|split|ipAddress|floating|hasChildNodes|simple|header|currency|complex|fn|parseInt|ms|Building|parseFloat|trigger|appendCache|update|onselectstart|mousedown|click|PM|sortOrder|shiftDown|document|dir|and|shiftKey|toString|on|Sorting|sort|eval|parser|prepend|asc|col|td|colgroup|desc|Number|concat|headerSortDown'.split('|'),0,{}))
2496\ No newline at end of file
2497+(function($){$.extend({tablesorter:new function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'.',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}var rows=table.tBodies[0].rows;if(table.tBodies[0].rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,cells[i]);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,node){var l=parsers.length;for(var i=1;i<l;i++){if(parsers[i].is($.trim(getElementText(table.config,node)),table,node)){return parsers[i];}}return parsers[0];}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=table.tBodies[0].rows[i],cols=[];cache.row.push($(c));for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j]));}cols.push(i);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){if(!node)return"";var t="";if(config.textExtraction=="simple"){if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){t=node.childNodes[0].innerHTML;}else{t=node.innerHTML;}}else{if(typeof(config.textExtraction)=="function"){t=config.textExtraction(node);}else{t=$(node).text();}}return t;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){rows.push(r[n[i][checkCell]]);if(!table.config.appender){var o=r[n[i][checkCell]];var l=o.length;for(var j=0;j<l;j++){tableBody[0].appendChild(o[j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false,tableHeadersRows=[];for(var i=0;i<table.tHead.rows.length;i++){tableHeadersRows[i]=0;};$tableHeaders=$("thead th",table);$tableHeaders.each(function(index){this.count=0;this.column=index;this.order=formatSortingOrder(table.config.sortInitialOrder);if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(!this.sortDisabled){$(this).addClass(table.config.cssHeader);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){i=(v.toLowerCase()=="desc")?1:0;}else{i=(v==(0||1))?v:0;}return i;}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(getCachedSortType(table.config.parsers,c)=="text")?((order==0)?"sortText":"sortTextDesc"):((order==0)?"sortNumeric":"sortNumericDesc");var e="e"+i;dynamicExp+="var "+e+" = "+s+"(a["+c+"],b["+c+"]); ";dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function sortText(a,b){return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){var DECIMAL='\\'+config.decimal;var exp='/(^[+]?0('+DECIMAL+'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)'+DECIMAL+'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*'+DECIMAL+'0+$)/';return RegExp(exp).test($.trim(s));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}$("tr:visible",table.tBodies[0]).filter(':even').removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]).end().filter(':odd').removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);
2498\ No newline at end of file
2499
2500=== removed file 'server/img/Thumbs.db'
2501Binary files server/img/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2502=== removed file 'server/img/bodys/Thumbs.db'
2503Binary files server/img/bodys/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/bodys/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2504=== removed file 'server/img/dashboard/Thumbs.db'
2505Binary files server/img/dashboard/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/dashboard/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2506=== removed file 'server/img/dialogs/Thumbs.db'
2507Binary files server/img/dialogs/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/dialogs/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2508=== removed file 'server/img/fades/Thumbs.db'
2509Binary files server/img/fades/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/fades/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2510=== removed file 'server/img/filterform/Thumbs.db'
2511Binary files server/img/filterform/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/filterform/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2512=== removed file 'server/img/forms/Thumbs.db'
2513Binary files server/img/forms/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/forms/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2514=== removed file 'server/img/login/Thumbs.db'
2515Binary files server/img/login/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/login/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2516=== removed file 'server/img/logos/Thumbs.db'
2517Binary files server/img/logos/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/logos/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2518=== removed file 'server/img/tables/Thumbs.db'
2519Binary files server/img/tables/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/tables/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2520=== removed file 'server/img/tabs/Thumbs.db'
2521Binary files server/img/tabs/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/tabs/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2522=== removed file 'server/img/titles/Thumbs.db'
2523Binary files server/img/titles/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/titles/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2524=== removed file 'server/img/weather_rss/Thumbs.db'
2525Binary files server/img/weather_rss/Thumbs.db 2009-06-20 12:00:21 +0000 and server/img/weather_rss/Thumbs.db 1970-01-01 00:00:00 +0000 differ
2526=== added file 'server/install/database/7.sql'
2527--- server/install/database/7.sql 1970-01-01 00:00:00 +0000
2528+++ server/install/database/7.sql 2009-08-08 13:39:17 +0000
2529@@ -0,0 +1,24 @@
2530+
2531+INSERT INTO `pages` (
2532+`pageID` ,
2533+`name` ,
2534+`pagegroupID`
2535+)
2536+VALUES (
2537+NULL , 'stats', '9'
2538+);
2539+
2540+INSERT INTO `menuitem` (`MenuID`, `PageID`, `Args`, `Text`, `Class`, `Img`, `Sequence`)
2541+SELECT '4', pageID, NULL, 'Statistics', NULL, NULL, '9' FROM pages WHERE name = 'stats';
2542+
2543+ALTER TABLE `stat` ADD `Tag` VARCHAR( 254 ) NULL ;
2544+
2545+ALTER TABLE `stat` ADD `Type` VARCHAR( 20 ) NOT NULL DEFAULT 'Media' AFTER `statID` ;
2546+
2547+ALTER TABLE `stat` CHANGE `Type` `Type` VARCHAR( 20 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
2548+
2549+ALTER TABLE `stat` CHANGE `mediaID` `mediaID` VARCHAR( 50 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL;
2550+
2551+UPDATE `version` SET `app_ver` = '1.0.3';
2552+UPDATE `setting` SET `value` = 0 WHERE `setting` = 'PHONE_HOME_DATE';
2553+UPDATE `version` SET `DBVersion` = '7';
2554
2555=== modified file 'server/lib/app/app_functions.php'
2556--- server/lib/app/app_functions.php 2009-02-21 17:52:52 +0000
2557+++ server/lib/app/app_functions.php 2009-07-28 21:08:19 +0000
2558@@ -325,105 +325,6 @@
2559 return $hms;
2560 }
2561
2562-define('STAT_LAYOUT_START', 'LayoutStart');
2563-define('STAT_LAYOUT_END', 'LayoutEnd');
2564-define('STAT_MEDIA_START', 'MediaStart');
2565-define('STAT_MEDIA_END', 'MediaEnd');
2566-
2567-/**
2568- * Records a Stat Record
2569- * @return
2570- * @param $statType Object
2571- * @param $statDate Object
2572- * @param $scheduleID Object
2573- * @param $displayID Object
2574- * @param $layoutID Object
2575- * @param $mediaID Object
2576- * @param $start Object
2577- * @param $end Object
2578- */
2579-function StatRecord($statType, $statDate, $scheduleID, $displayID, $layoutID, $mediaID, $start, $end)
2580-{
2581- global $db;
2582-
2583- $infinityDate = "2050-12-31 00:00:00";
2584-
2585- // Look up the stat type
2586- switch ($statType)
2587- {
2588- case STAT_LAYOUT_START:
2589- // If its a layout start
2590- // Check for an open Layout which has this schedule & close it
2591- $SQL = "";
2592- $SQL .= " UPDATE stat SET end = '$end' WHERE scheduleID = '$scheduleID' AND layoutID = '$layoutID' AND end = '$infinityDate' ";
2593-
2594- if (!$db->query($SQL))
2595- {
2596- trigger_error($db->error());
2597- return false;
2598- }
2599-
2600- // Insert a new stat record for this layout
2601- $SQL = "";
2602- $SQL .= " INSERT INTO stat (statDate, scheduleID, displayID, layoutID, start, end)";
2603- $SQL .= " VALUES ('$statDate', '$scheduleID', '$displayID', '$layoutID', '$start', '$infinityDate')";
2604-
2605- if (!$db->query($SQL))
2606- {
2607- trigger_error($db->error());
2608- return false;
2609- }
2610-
2611- break;
2612-
2613- case STAT_LAYOUT_END:
2614- // If its a layout end
2615- // Close the layout stat record for this schedule (by updating the end time)
2616- // Also close any open media records (they should all be shut anyway)
2617- $SQL = "";
2618- $SQL .= " UPDATE stat SET end = '$end' WHERE scheduleID = '$scheduleID' AND layoutID = '$layoutID' AND end = '$infinityDate' ";
2619-
2620- if (!$db->query($SQL))
2621- {
2622- trigger_error($db->error());
2623- return false;
2624- }
2625- break;
2626-
2627- case STAT_MEDIA_START:
2628- // If its a media start
2629- // Create a new media stat record for this layout
2630- $SQL = "";
2631- $SQL .= " INSERT INTO stat (statDate, scheduleID, displayID, layoutID, mediaID, start, end)";
2632- $SQL .= " VALUES ('$statDate', '$scheduleID', '$displayID', '$layoutID', '$mediaID', '$start', '$infinityDate')";
2633-
2634- if (!$db->query($SQL))
2635- {
2636- trigger_error($db->error());
2637- return false;
2638- }
2639- break;
2640-
2641- case STAT_MEDIA_END:
2642- // If its a media end
2643- // Close the stat record
2644- $SQL = "";
2645- $SQL .= " UPDATE stat SET end = '$end' WHERE scheduleID = '$scheduleID' AND layoutID = '$layoutID' AND mediaID = '$mediaID' AND end = '$infinityDate' ";
2646-
2647- if (!$db->query($SQL))
2648- {
2649- trigger_error($db->error());
2650- return false;
2651- }
2652- break;
2653-
2654- default:
2655- return false;
2656- }
2657-
2658- return true;
2659-}
2660-
2661 /**
2662 * Gets web safe colors
2663 * @return
2664
2665=== modified file 'server/lib/app/session.class.php'
2666--- server/lib/app/session.class.php 2008-12-19 22:10:39 +0000
2667+++ server/lib/app/session.class.php 2009-07-07 20:01:49 +0000
2668@@ -29,7 +29,8 @@
2669
2670 public $isExpired = 1;
2671
2672- function __construct(database $db) {
2673+ function __construct(database $db)
2674+ {
2675 $this->db =& $db;
2676
2677 session_set_save_handler(array(&$this, 'open'),
2678@@ -64,38 +65,27 @@
2679 {
2680 $db =& $this->db;
2681
2682- $userAgent = $_SERVER['HTTP_USER_AGENT'];
2683- $remoteAddr = $_SERVER['REMOTE_ADDR'];
2684+ $userAgent = Kit::GetParam('HTTP_USER_AGENT', $_SERVER, _STRING, 'No user agent');
2685+ $remoteAddr = Kit::GetParam('REMOTE_ADDR', $_SERVER, _STRING);
2686+ $securityToken = Kit::GetParam('SecurityToken', _POST, _STRING, null);
2687
2688 $this->key = $key;
2689 $newExp = time() + $this->max_lifetime;
2690
2691 $this->gc($this->max_lifetime);
2692
2693- if(isset($_POST['SecurityToken']))
2694- {
2695- $securityToken = validate($_POST['SecurityToken']);
2696-
2697- if (!$securityToken)
2698- {
2699- log_entry($db, "error", "Invalid Security Token");
2700- $securityToken = null;
2701- }
2702- }
2703- else
2704- {
2705- $securityToken = null;
2706- }
2707-
2708+ // Get this session
2709 $SQL = " SELECT session_data, IsExpired, SecurityToken FROM session ";
2710- $SQL .= " WHERE session_id = '$key' ";
2711- $SQL .= " AND RemoteAddr = '$remoteAddr' ";
2712-
2713- if (!$result = $db->query($SQL));
2714+ $SQL .= " WHERE session_id = '%s' ";
2715+ $SQL .= " AND UserAgent = '%s' ";
2716+
2717+ $SQL = sprintf($SQL, $db->escape_string($key), $db->escape_string($userAgent));
2718+
2719+ $result = $db->query($SQL);
2720
2721 if ($db->num_rows($result) != 0)
2722 {
2723-
2724+ // Get the row
2725 $row = $db->get_row($result);
2726
2727 // We have the Key and the Remote Address.
2728@@ -109,10 +99,10 @@
2729 // We have a security token, so dont require a login
2730 $this->isExpired = 0;
2731
2732- if (!$db->query("UPDATE session SET session_expiration = $newExp, isExpired = 0 WHERE session_id = '$key' "))
2733+ if (!$db->query(sprintf("UPDATE session SET session_expiration = $newExp, isExpired = 0 WHERE session_id = '%s' ", $db->escape_string($key))))
2734 {
2735 log_entry($db, "error", $db->error());
2736- }
2737+ }
2738 }
2739 else
2740 {
2741@@ -123,49 +113,55 @@
2742 }
2743
2744 // Either way - update this SESSION so that the security token is NULL
2745- $db->query("UPDATE session SET SecurityToken = NULL WHERE session_id = '$key' ");
2746+ $db->query(sprintf("UPDATE session SET SecurityToken = NULL WHERE session_id = '%s' ", $db->escape_string($key)));
2747
2748 return($row[0]);
2749 }
2750- else {
2751+ else
2752+ {
2753 $empty = '';
2754 return settype($empty, "string");
2755 }
2756 }
2757
2758- function write($key, $val) {
2759-
2760- $db =& $this->db;
2761-
2762- $val = addslashes($val);
2763+ function write($key, $val)
2764+ {
2765+ $db =& $this->db;
2766
2767 $newExp = time() + $this->max_lifetime;
2768 $lastaccessed = date("Y-m-d H:i:s");
2769- $userAgent = $_SERVER['HTTP_USER_AGENT'];
2770- $remoteAddr = $_SERVER['REMOTE_ADDR'];
2771+ $userAgent = Kit::GetParam('HTTP_USER_AGENT', $_SERVER, _STRING, 'No user agent');
2772+ $remoteAddr = Kit::GetParam('REMOTE_ADDR', $_SERVER, _STRING);
2773
2774- $result = $db->query("SELECT session_id FROM session WHERE session_id = '$key'");
2775+ $result = $db->query(sprintf("SELECT session_id FROM session WHERE session_id = '%s'", $db->escape_string($key)));
2776
2777 if ($db->num_rows($result) == 0)
2778 {
2779 //INSERT
2780 $SQL = "INSERT INTO session (session_id, session_data, session_expiration, LastAccessed, LastPage, userID, IsExpired, UserAgent, RemoteAddr)
2781- VALUES ('$key','$val',$newExp,'$lastaccessed','login', NULL, 0, '$userAgent', '$remoteAddr')";
2782+ VALUES ('%s', '%s', %d, '%s', 'login', NULL, 0, '%s', '%s')";
2783+
2784+ $SQL = sprintf($SQL, $db->escape_string($key), $db->escape_string($val), $newExp, $db->escape_string($lastaccessed), $db->escape_string($userAgent), $db->escape_string($remoteAddr));
2785 }
2786 else
2787 {
2788 //UPDATE
2789 $SQL = "UPDATE session SET ";
2790- $SQL .= " session_data = '$val', ";
2791- $SQL .= " session_expiration = '$newExp', ";
2792- $SQL .= " lastaccessed = '$lastaccessed' ";
2793- $SQL .= " WHERE session_id = '$key' ";
2794+ $SQL .= " session_data = '%s', ";
2795+ $SQL .= " session_expiration = %d, ";
2796+ $SQL .= " lastaccessed = '%s', ";
2797+ $SQL .= " RemoteAddr = '%s' ";
2798+ $SQL .= " WHERE session_id = '%s' ";
2799+
2800+ $SQL = sprintf($SQL, $db->escape_string($val), $newExp, $db->escape_string($lastaccessed), $db->escape_string($remoteAddr), $db->escape_string($key));
2801 }
2802
2803- if(!$db->query($SQL)) {
2804+ if(!$db->query($SQL))
2805+ {
2806 log_entry($db, "error", $db->error());
2807 return(false);
2808 }
2809+
2810 return true;
2811 }
2812
2813@@ -173,7 +169,7 @@
2814 {
2815 $db =& $this->db;
2816
2817- $SQL = "UPDATE session SET IsExpired = 1 WHERE session_id = '$key'";
2818+ $SQL = sprintf("UPDATE session SET IsExpired = 1 WHERE session_id = '%s'", $db->escape_string($key));
2819
2820 $result = $db->query("$SQL");
2821
2822@@ -193,26 +189,32 @@
2823 {
2824 $db =& $this->db;
2825
2826- $SQL = "UPDATE session SET userID = $userid WHERE session_id = '$key' ";
2827+ $SQL = sprintf("UPDATE session SET userID = %d WHERE session_id = '%s' ",$userid, $db->escape_string($key));
2828
2829- if(!$db->query($SQL)) {
2830+ if(!$db->query($SQL))
2831+ {
2832 trigger_error($db->error(), E_USER_NOTICE);
2833 return(false);
2834 }
2835 return true;
2836 }
2837
2838- // Update the session (after login)
2839- static function RegenerateSessionID()
2840+ /**
2841+ * Updates the session ID with a new one
2842+ * @return
2843+ */
2844+ public function RegenerateSessionID($oldSessionID)
2845 {
2846- $old_sess_id = session_id();
2847+ $db =& $this->db;
2848
2849 session_regenerate_id(false);
2850
2851 $new_sess_id = session_id();
2852+
2853+ $this->key = $new_sess_id;
2854
2855- $query = "UPDATE `session` SET `session_id` = '$new_sess_id' WHERE session_id = '$old_sess_id'";
2856- mysql_query($query);
2857+ $query = sprintf("UPDATE session SET session_id = '%s' WHERE session_id = '%s'", $db->escape_string($new_sess_id), $db->escape_string($oldSessionID));
2858+ $db->query($query);
2859 }
2860
2861 function set_page($key, $lastpage)
2862@@ -221,9 +223,10 @@
2863
2864 $_SESSION['pagename'] = $lastpage;
2865
2866- $SQL = "UPDATE session SET LastPage = '$lastpage' WHERE session_id = '$key' ";
2867+ $SQL = sprintf("UPDATE session SET LastPage = '%s' WHERE session_id = '%s' ", $db->escape_string($lastpage), $db->escape_string($key));
2868
2869- if(!$db->query($SQL)) {
2870+ if(!$db->query($SQL))
2871+ {
2872 trigger_error($db->error(), E_USER_NOTICE);
2873 return(false);
2874 }
2875@@ -236,7 +239,7 @@
2876
2877 $this->isExpired = $isExpired;
2878
2879- $SQL = "UPDATE session SET IsExpired = $this->isExpired WHERE session_id = '$this->key'";
2880+ $SQL = sprintf("UPDATE session SET IsExpired = $this->isExpired WHERE session_id = '%s'", $db->escape_string($this->key));
2881
2882 if (!$db->query($SQL))
2883 {
2884@@ -248,7 +251,7 @@
2885 {
2886 $db =& $this->db;
2887
2888- $SQL = "UPDATE session SET securityToken = '$token' WHERE session_id = '$this->key'";
2889+ $SQL = sprintf("UPDATE session SET securityToken = '%s' WHERE session_id = '%s'", $db->escape_string($token), $db->escape_string($this->key));
2890
2891 if (!$db->query($SQL))
2892 {
2893
2894=== added file 'server/lib/data/layout.data.class.php'
2895--- server/lib/data/layout.data.class.php 1970-01-01 00:00:00 +0000
2896+++ server/lib/data/layout.data.class.php 2009-07-30 23:01:31 +0000
2897@@ -0,0 +1,185 @@
2898+<?php
2899+/*
2900+ * Xibo - Digitial Signage - http://www.xibo.org.uk
2901+ * Copyright (C) 2009 Daniel Garner
2902+ *
2903+ * This file is part of Xibo.
2904+ *
2905+ * Xibo is free software: you can redistribute it and/or modify
2906+ * it under the terms of the GNU Affero General Public License as published by
2907+ * the Free Software Foundation, either version 3 of the License, or
2908+ * any later version.
2909+ *
2910+ * Xibo is distributed in the hope that it will be useful,
2911+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2912+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2913+ * GNU Affero General Public License for more details.
2914+ *
2915+ * You should have received a copy of the GNU Affero General Public License
2916+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
2917+ */
2918+defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
2919+
2920+class Layout extends Data
2921+{
2922+ private $xml;
2923+
2924+ public function EditTags($layoutID, $tags)
2925+ {
2926+ $db =& $this->db;
2927+
2928+ Debug::LogEntry($db, 'audit', 'IN', 'Layout', 'EditTags');
2929+
2930+ // Make sure we get an array
2931+ if(!is_array($tags))
2932+ {
2933+ $this->SetError(25000, 'Must pass EditTags an array');
2934+ return false;
2935+ }
2936+
2937+ // Set the XML
2938+ if (!$this->SetXml($layoutID))
2939+ {
2940+ Debug::LogEntry($db, 'audit', 'Failed to Set the layout Xml.', 'Layout', 'EditTags');
2941+ return false;
2942+ }
2943+
2944+ Debug::LogEntry($db, 'audit', 'Got the XML from the DB. Now creating the tags.', 'Layout', 'EditTags');
2945+
2946+ // Create the tags XML
2947+ $tagsXml = '<tags>';
2948+
2949+ foreach($tags as $tag)
2950+ {
2951+ $tagsXml .= sprintf('<tag>%s</tag>', $tag);
2952+ }
2953+
2954+ $tagsXml .= '</tags>';
2955+
2956+ Debug::LogEntry($db, 'audit', 'Tags XML is:' . $tagsXml, 'Layout', 'EditTags');
2957+
2958+ // Load the tags XML into a document
2959+ $tagsXmlDoc = new DOMDocument('1.0');
2960+ $tagsXmlDoc->loadXML($tagsXml);
2961+
2962+
2963+ // Load the XML for this layout
2964+ $xml = new DOMDocument("1.0");
2965+ $xml->loadXML($this->xml);
2966+
2967+ // Import the new node into this document
2968+ $newTagsNode = $xml->importNode($tagsXmlDoc->documentElement, true);
2969+
2970+ // Xpath for an existing tags node
2971+ $xpath = new DOMXPath($xml);
2972+ $tagsNode = $xpath->query("//tags");
2973+
2974+ // Does the tags node exist?
2975+ if ($tagsNode->length < 1)
2976+ {
2977+ // We need to append our new node to the layout node
2978+ $layoutXpath = new DOMXPath($xml);
2979+ $layoutNode = $xpath->query("//layout");
2980+ $layoutNode = $layoutNode->item(0);
2981+
2982+ $layoutNode->appendChild($newTagsNode);
2983+ }
2984+ else
2985+ {
2986+ // We need to swap our new node with the existing one
2987+ $tagsNode = $tagsNode->item(0);
2988+
2989+ // Replace the node
2990+ $tagsNode->parentNode->replaceChild($newTagsNode, $tagsNode);
2991+ }
2992+
2993+ // Format the output a bit nicer for Alex
2994+ $xml->formatOutput = true;
2995+
2996+ // Convert back to XML
2997+ $xml = $xml->saveXML();
2998+
2999+ Debug::LogEntry($db, 'audit', $xml, 'layout', 'EditTags');
3000+
3001+ // Save it
3002+ if (!$this->SetLayoutXml($layoutID, $xml)) return false;
3003+
3004+ Debug::LogEntry($db, 'audit', 'OUT', 'Layout', 'EditTags');
3005+
3006+ return true;
3007+ }
3008+
3009+ /**
3010+ * Sets the Layout XML for this layoutid
3011+ * @return
3012+ * @param $layoutID Object
3013+ */
3014+ private function SetXml($layoutID)
3015+ {
3016+ if(!$this->xml = $this->GetLayoutXml($layoutID))
3017+ {
3018+ return false;
3019+ }
3020+
3021+ return true;
3022+ }
3023+
3024+ /**
3025+ * Gets the Xml for the specified layout
3026+ * @return
3027+ * @param $layoutid Object
3028+ */
3029+ private function GetLayoutXml($layoutid)
3030+ {
3031+ $db =& $this->db;
3032+
3033+ Debug::LogEntry($db, 'audit', 'IN', 'Layout', 'GetLayoutXml');
3034+
3035+ //Get the Xml for this Layout from the DB
3036+ $SQL = sprintf("SELECT xml FROM layout WHERE layoutID = %d ", $layoutid);
3037+
3038+ if (!$results = $db->query($SQL))
3039+ {
3040+ trigger_error($db->error());
3041+ $this->SetError(25000, 'Layout does not exist.');
3042+ return false;
3043+ }
3044+
3045+ $row = $db->get_row($results) ;
3046+
3047+ Debug::LogEntry($db, 'audit', 'OUT', 'Layout', 'GetLayoutXml');
3048+
3049+ return $row[0];
3050+ }
3051+
3052+ /**
3053+ * Sets the Layout Xml and writes it back to the database
3054+ * @return
3055+ * @param $layoutid Object
3056+ * @param $xml Object
3057+ */
3058+ private function SetLayoutXml($layoutid, $xml)
3059+ {
3060+ $db =& $this->db;
3061+
3062+ Debug::LogEntry($db, 'audit', 'IN', 'Layout', 'SetLayoutXml');
3063+
3064+ $xml = addslashes($xml);
3065+
3066+ // Write it back to the database
3067+ $SQL = sprintf("UPDATE layout SET xml = '%s' WHERE layoutID = %d ", $xml, $layoutid);
3068+
3069+
3070+ if (!$db->query($SQL))
3071+ {
3072+ trigger_error($db->error());
3073+ $this->SetError(25000, 'Unable to Update Layout.');
3074+ return false;
3075+ }
3076+
3077+ Debug::LogEntry($db, 'audit', 'OUT', 'Layout', 'SetLayoutXml');
3078+
3079+ return true;
3080+ }
3081+}
3082+?>
3083\ No newline at end of file
3084
3085=== added file 'server/lib/data/stat.data.class.php'
3086--- server/lib/data/stat.data.class.php 1970-01-01 00:00:00 +0000
3087+++ server/lib/data/stat.data.class.php 2009-08-08 11:04:39 +0000
3088@@ -0,0 +1,74 @@
3089+<?php
3090+/*
3091+ * Xibo - Digitial Signage - http://www.xibo.org.uk
3092+ * Copyright (C) 2009 Daniel Garner
3093+ *
3094+ * This file is part of Xibo.
3095+ *
3096+ * Xibo is free software: you can redistribute it and/or modify
3097+ * it under the terms of the GNU Affero General Public License as published by
3098+ * the Free Software Foundation, either version 3 of the License, or
3099+ * any later version.
3100+ *
3101+ * Xibo is distributed in the hope that it will be useful,
3102+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3103+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3104+ * GNU Affero General Public License for more details.
3105+ *
3106+ * You should have received a copy of the GNU Affero General Public License
3107+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
3108+ */
3109+defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
3110+
3111+class Stat extends data
3112+{
3113+ public function Add($type, $fromDT, $toDT, $scheduleID, $displayID, $layoutID, $mediaID, $tag)
3114+ {
3115+ $db =& $this->db;
3116+ $statDate = date("Y-m-d H:i:s");
3117+ $SQL = '';
3118+
3119+ $type = $db->escape_string($type);
3120+
3121+ // We should run different SQL depending on what Type we are
3122+ switch ($type)
3123+ {
3124+ case 'Media':
3125+ case 'media':
3126+ $SQL .= " INSERT INTO stat (Type, statDate, scheduleID, displayID, layoutID, mediaID, start, end)";
3127+ $SQL .= sprintf(" VALUES ('%s', '%s', %d, %d, %d, '%s', '%s', '%s')", $type, $statDate, $scheduleID, $displayID, $layoutID, $db->escape_string($mediaID), $fromDT, $toDT);
3128+
3129+ break;
3130+
3131+ case 'Layout':
3132+ case 'layout':
3133+ $SQL .= " INSERT INTO stat (Type, statDate, scheduleID, displayID, layoutID, start, end)";
3134+ $SQL .= sprintf(" VALUES ('%s', '%s', %d, %d, %d, '%s', '%s')", $type, $statDate, $scheduleID, $displayID, $layoutID, $fromDT, $toDT);
3135+
3136+ break;
3137+
3138+ case 'Event':
3139+ case 'event':
3140+
3141+ $SQL .= " INSERT INTO stat (Type, statDate, scheduleID, displayID, layoutID, start, end, Tag)";
3142+ $SQL .= sprintf(" VALUES ('%s', '%s', %d, %d, %d, '%s', '%s', '%s')", $type, $statDate, $scheduleID, $displayID, 0, $fromDT, $toDT, $db->escape_string($tag));
3143+
3144+ break;
3145+
3146+ default:
3147+ // Nothing to do, just exit
3148+ return true;
3149+ }
3150+
3151+ // We only get here if we have some SQL to run
3152+ if (!$db->query($SQL))
3153+ {
3154+ trigger_error($db->error());
3155+ $this->SetError(25000, 'Stat Insert Failed.');
3156+ return false;
3157+ }
3158+
3159+ return true;
3160+ }
3161+}
3162+?>
3163\ No newline at end of file
3164
3165=== modified file 'server/lib/modules/module.class.php'
3166--- server/lib/modules/module.class.php 2009-04-27 19:28:08 +0000
3167+++ server/lib/modules/module.class.php 2009-08-03 10:54:29 +0000
3168@@ -61,7 +61,7 @@
3169 $this->user =& $user;
3170
3171 $this->mediaid = $mediaid;
3172- $this->name = "";
3173+ $this->name = '';
3174 $this->layoutid = $layoutid;
3175 $this->regionid = $regionid;
3176
3177@@ -175,7 +175,7 @@
3178 }
3179 else
3180 {
3181- if ($this->mediaid != '')
3182+ if ($this->mediaid != '' && $this->regionSpecific == 0)
3183 {
3184 // We do not have a region or a layout
3185 // But this is some existing media
3186@@ -183,7 +183,9 @@
3187 $this->existingMedia = true;
3188
3189 // Load what we know about this media into the object
3190- $SQL = "SELECT duration,name FROM media WHERE mediaID = '$mediaid'";
3191+ $SQL = "SELECT duration, name FROM media WHERE mediaID = '$mediaid'";
3192+
3193+ Debug::LogEntry($db, 'audit', $SQL, 'Module', 'SetMediaInformation');
3194
3195 if (!$result = $db->query($SQL))
3196 {
3197@@ -194,7 +196,7 @@
3198 {
3199 $row = $db->get_row($result);
3200 $this->duration = $row[0];
3201- $this->name = $row[1];
3202+ $this->name = $row[1];
3203 }
3204 }
3205
3206@@ -262,7 +264,10 @@
3207 */
3208 final protected function SetOption($name, $value)
3209 {
3210- if ($name == '' || $value == '') return;
3211+ $db =& $this->db;
3212+ if ($name == '') return;
3213+
3214+ Debug::LogEntry($db, 'audit', sprintf('IN with Name=%s and value=%s', $name, $value), 'module', 'Set Option');
3215
3216 // Get the options node from this document
3217 $optionNodes = $this->xml->getElementsByTagName('options');
3218@@ -272,6 +277,7 @@
3219 // Create a new option node
3220 $newNode = $this->xml->createElement($name, $value);
3221
3222+ Debug::LogEntry($db, 'audit', sprintf('Created a new Option Node with Name=%s and value=%s', $name, $value), 'module', 'Set Option');
3223
3224 // Check to see if we already have this option or not
3225 $xpath = new DOMXPath($this->xml);
3226@@ -535,8 +541,11 @@
3227 */
3228 public function GetName()
3229 {
3230+ $db =& $this->db;
3231+
3232+ Debug::LogEntry($db, 'audit', sprintf('Module name returned for MediaID: %s is %s', $this->mediaid, $this->name), 'Module', 'GetName');
3233+
3234 return $this->name;
3235 }
3236-
3237 }
3238 ?>
3239
3240=== modified file 'server/lib/pages/layout.class.php'
3241--- server/lib/pages/layout.class.php 2009-06-20 12:00:21 +0000
3242+++ server/lib/pages/layout.class.php 2009-08-03 10:54:29 +0000
3243@@ -57,6 +57,9 @@
3244 $ajax = Kit::GetParam('ajax', _GET, _WORD, 'false');
3245
3246 $this->layoutid = Kit::GetParam('layoutid', _REQUEST, _INT);
3247+
3248+ // Include the layout data class
3249+ include_once("lib/data/layout.data.class.php");
3250
3251 //set the information that we know
3252 if ($usertype == 1) $this->isadmin = true;
3253@@ -289,6 +292,18 @@
3254 $response->SetError("Unknown error adding layout.");
3255 $response->Respond();
3256 }
3257+
3258+ // Create an array out of the tags
3259+ $tagsArray = split(' ', $tags);
3260+
3261+ // Add the tags XML to the layout
3262+ $layoutObject = new Layout($db);
3263+
3264+ if (!$layoutObject->EditTags($id, $tagsArray))
3265+ {
3266+ //there was an ERROR
3267+ trigger_error($layoutObject->GetErrorMessage(), E_USER_ERROR);
3268+ }
3269
3270 $response->SetFormSubmitResponse('Layout Details Changed.', true, sprintf("index.php?p=layout&layoutid=%d&modify=true", $id));
3271 $response->Respond();
3272@@ -399,6 +414,18 @@
3273 $response->SetError(sprintf("Unknown error editing %s", $layout));
3274 $response->Respond();
3275 }
3276+
3277+ // Create an array out of the tags
3278+ $tagsArray = split(' ', $tags);
3279+
3280+ // Add the tags XML to the layout
3281+ $layoutObject = new Layout($db);
3282+
3283+ if (!$layoutObject->EditTags($this->layoutid, $tagsArray))
3284+ {
3285+ //there was an ERROR
3286+ trigger_error($layoutObject->GetErrorMessage(), E_USER_ERROR);
3287+ }
3288
3289 $response->SetFormSubmitResponse('Layout Details Changed.');
3290 $response->Respond();
3291@@ -1320,18 +1347,22 @@
3292 $count++;
3293
3294 //Build up a button with position information
3295+ $mediaName = '';
3296+ $mediaType = '';
3297 $mediaid = $mediaNode->getAttribute('id');
3298 $lkid = $mediaNode->getAttribute('lkid');
3299 $mediaType = $mediaNode->getAttribute('type');
3300 $mediaFileName = $mediaNode->getAttribute('filename');
3301 $mediaDuration = $mediaNode->getAttribute('duration');
3302
3303- //Get media name
3304+ // Get media name
3305 require_once("modules/$mediaType.module.php");
3306
3307 // Create the media object without any region and layout information
3308- $tmpModule = new $mediaType($db, $user, $mediaid);
3309- $mediaName = $tmpModule->GetName();
3310+ $tmpModule = new $mediaType($db, $user, $mediaid);
3311+ $mediaName = $tmpModule->GetName();
3312+
3313+ Debug::LogEntry($db, 'audit', sprintf('Module name returned for MediaID: %s is %s', $mediaid, $mediaName), 'layout', 'RegionOptions');
3314
3315 //Do we have a thumbnail for this media?
3316 if ($mediaType == "image" && file_exists($libraryLocation."tn_$mediaFileName"))
3317
3318=== modified file 'server/lib/pages/region.class.php'
3319--- server/lib/pages/region.class.php 2009-01-23 19:29:48 +0000
3320+++ server/lib/pages/region.class.php 2009-07-30 23:01:31 +0000
3321@@ -404,7 +404,7 @@
3322 $mediaNodeList = $xpath->query("//region[@id='$regionid']/media[@lkid='$lkid']");
3323 }
3324
3325- //Get the old media node (the one we are to replace)
3326+ // Get the old media node (the one we are to replace)
3327 $oldMediaNode = $mediaNodeList->item(0);
3328
3329 //Get the LkId of the current record... if its not blank we want to update this link with the new id
3330
3331=== modified file 'server/lib/pages/report.class.php'
3332--- server/lib/pages/report.class.php 2009-03-13 10:10:07 +0000
3333+++ server/lib/pages/report.class.php 2009-08-03 10:54:29 +0000
3334@@ -210,9 +210,7 @@
3335 <td>$ip</td>
3336 <td>$browser</td>
3337 <td>
3338- <div class="buttons">
3339- <a class="neutral" href="index.php?p=report&q=ConfirmLogout&userid=$userID" onclick="return init_button(this,'Logout User', exec_filter_callback, set_form_size(450,150))"><span>Logout</span></a>
3340- </div>
3341+ <button class="XiboFormButton" href="index.php?p=report&q=ConfirmLogout&userid=$userID"><span>Logout</span></a>
3342 </td>
3343 </tr>
3344 END;
3345@@ -234,14 +232,15 @@
3346 $userID = Kit::GetParam('userid', _GET, _INT);
3347
3348 $form = <<<END
3349- <form class="dialog_form" method="post" action="index.php?p=report&q=LogoutUser">
3350+ <form class="XiboForm" method="post" action="index.php?p=report&q=LogoutUser">
3351 <input type="hidden" name="userid" value="userid" />
3352 <p>Are you sure you want to logout this user?</p>
3353 <input type="submit" value="Yes">
3354 <input type="submit" value="No" onclick="$('#div_dialog').dialog('close');return false; ">
3355 </form>
3356 END;
3357- $arh->SetFormSubmitResponse($form);
3358+
3359+ $arh->SetFormRequestResponse($form, 'Logout User', '450px', '300px');
3360 $arh->Respond();
3361 }
3362
3363@@ -424,6 +423,7 @@
3364 $output .= '</tbody></table></div>';
3365
3366 $response->SetGridResponse($output);
3367+ $response->sortable = false;
3368 $response->Respond();
3369 }
3370
3371
3372=== added file 'server/lib/pages/stats.class.php'
3373--- server/lib/pages/stats.class.php 1970-01-01 00:00:00 +0000
3374+++ server/lib/pages/stats.class.php 2009-08-08 11:04:39 +0000
3375@@ -0,0 +1,152 @@
3376+<?php
3377+/*
3378+ * Xibo - Digitial Signage - http://www.xibo.org.uk
3379+ * Copyright (C) 2009 Daniel Garner
3380+ *
3381+ * This file is part of Xibo.
3382+ *
3383+ * Xibo is free software: you can redistribute it and/or modify
3384+ * it under the terms of the GNU Affero General Public License as published by
3385+ * the Free Software Foundation, either version 3 of the License, or
3386+ * any later version.
3387+ *
3388+ * Xibo is distributed in the hope that it will be useful,
3389+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3390+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3391+ * GNU Affero General Public License for more details.
3392+ *
3393+ * You should have received a copy of the GNU Affero General Public License
3394+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
3395+ */
3396+defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
3397+
3398+class statsDAO
3399+{
3400+ private $db;
3401+ private $user;
3402+
3403+ function __construct(database $db, user $user)
3404+ {
3405+ $this->db =& $db;
3406+ $this->user =& $user;
3407+ }
3408+
3409+ function displayPage()
3410+ {
3411+
3412+ include("template/pages/stats_view.php");
3413+
3414+ return false;
3415+ }
3416+
3417+ function on_page_load()
3418+ {
3419+ return '';
3420+ }
3421+
3422+ function echo_page_heading()
3423+ {
3424+ echo 'Display Statistics';
3425+ return true;
3426+ }
3427+
3428+ public function StatsForm()
3429+ {
3430+ $db =& $this->db;
3431+ $user =& $this->user;
3432+ $output = '';
3433+
3434+ $fromdt = date("Y-m-d H:i:s", time() - 86400);
3435+ $todt = date("Y-m-d H:i:s");
3436+ $display_list = dropdownlist("SELECT 'All', 'All' UNION SELECT displayID, display FROM display WHERE licensed = 1 ORDER BY 2", "displayid");
3437+
3438+ // We want to build a form which will sit on the page and allow a button press to generate a CSV file.
3439+ $output .= '<script type="text/javascript">$(document).onload(function(){$(".date-pick").datepicker({dateFormat: "dd/mm/yy"})});</script>';
3440+ $output .= '<form action="index.php?p=stats&q=OutputCSV" method="post">';
3441+ $output .= ' <table>';
3442+ $output .= ' <tr>';
3443+ $output .= ' <td>From Date</td>';
3444+ $output .= ' <td><input type="text" class="date-pick" name="fromdt" value="' . $fromdt . '"/></td>';
3445+ $output .= ' <td>To Date</td>';
3446+ $output .= ' <td><input type="text" class="date-pick" name="todt" value="' . $todt . '" /></td>';
3447+ $output .= ' </tr>';
3448+ $output .= ' <tr>';
3449+ $output .= ' <td>Display</td>';
3450+ $output .= ' <td>' . $display_list . '</td>';
3451+ $output .= ' </tr>';
3452+
3453+ $output .= ' <tr>';
3454+ $output .= ' <td><input type="submit" value="Export" /></td>';
3455+ $output .= ' </tr>';
3456+ $output .= ' </table>';
3457+ $output .= '</form>';
3458+
3459+ echo $output;
3460+ }
3461+
3462+ /**
3463+ * Outputs a CSV of stats
3464+ * @return
3465+ */
3466+ public function OutputCSV()
3467+ {
3468+ $db =& $this->db;
3469+ $output = '';
3470+
3471+ // We are expecting some parameters
3472+ $fromdt = Kit::GetParam('fromdt', _POST, _STRING);
3473+ $todt = Kit::GetParam('todt', _POST, _STRING);
3474+ $displayID = Kit::GetParam('displayid', _POST, _INT);
3475+
3476+ // We want to output a load of stuff to the browser as a text file.
3477+ header('Content-Type: text/csv');
3478+ header('Content-Disposition: attachment; filename="stats.csv"');
3479+ header("Content-Transfer-Encoding: binary");
3480+ header('Accept-Ranges: bytes');
3481+
3482+ $SQL = 'SELECT stat.*, display.Display, layout.Layout, media.Name AS MediaName ';
3483+ $SQL .= ' FROM stat ';
3484+ $SQL .= ' INNER JOIN display ON stat.DisplayID = display.DisplayID ';
3485+ $SQL .= ' INNER JOIN layout ON layout.LayoutID = stat.LayoutID ';
3486+ $SQL .= ' LEFT OUTER JOIN media ON media.mediaID = stat.mediaID ';
3487+ $SQL .= ' WHERE 1=1 ';
3488+ $SQL .= sprintf(" AND stat.end > '%s' ", $fromdt);
3489+ $SQL .= sprintf(" AND stat.start <= '%s' ", $todt);
3490+
3491+ if ($displayID != 0)
3492+ {
3493+ $SQL .= sprintf(" AND stat.displayID = %d ", $displayID);
3494+ }
3495+
3496+ Debug::LogEntry($db, 'audit', $SQL, 'Stats', 'OutputCSV');
3497+
3498+ if (!$result = $db->query($SQL))
3499+ {
3500+ trigger_error($db->error());
3501+ trigger_error('Failed to query for Stats.', E_USER_ERROR);
3502+ }
3503+
3504+ // Header row
3505+ $output .= "Type, FromDT, ToDT, Layout, Display, Media, Tag\n";
3506+
3507+ while($row = $db->get_assoc_row($result))
3508+ {
3509+ // Read the columns
3510+ $type = Kit::ValidateParam($row['type'], _STRING);
3511+ $fromdt = Kit::ValidateParam($row['start'], _STRING);
3512+ $todt = Kit::ValidateParam($row['end'], _STRING);
3513+ $layout = Kit::ValidateParam($row['Layout'], _STRING);
3514+ $display = Kit::ValidateParam($row['Display'], _STRING);
3515+ $media = Kit::ValidateParam($row['MediaName'], _STRING);
3516+ $tag = Kit::ValidateParam($row['Tag'], _STRING);
3517+
3518+ $output .= "$type, $fromdt, $todt, $layout, $display, $media, $tag\n";
3519+ }
3520+
3521+ //Debug::LogEntry($db, 'audit', 'Output: ' . $output, 'Stats', 'OutputCSV');
3522+
3523+ echo $output;
3524+ exit;
3525+ }
3526+}
3527+?>
3528\ No newline at end of file
3529
3530=== modified file 'server/lib/xmds.inc.php'
3531--- server/lib/xmds.inc.php 2009-03-22 12:06:30 +0000
3532+++ server/lib/xmds.inc.php 2009-07-28 21:08:19 +0000
3533@@ -27,9 +27,9 @@
3534 require_once("lib/app/app_functions.php");
3535 require_once("lib/app/debug.class.php");
3536 require_once("lib/app/kit.class.php");
3537-
3538+require_once("lib/data/data.class.php");
3539 require_once("config/db_config.php");
3540-require_once("config/config.class.php");
3541
3542+require_once("config/config.class.php");
3543include_once('lib/data/stat.data.class.php');
3544
3545 // Sort out magic quotes
3546 if (get_magic_quotes_gpc())
3547
3548=== modified file 'server/modules/embedded.module.php'
3549--- server/modules/embedded.module.php 2009-06-20 10:05:53 +0000
3550+++ server/modules/embedded.module.php 2009-08-03 12:10:12 +0000
3551@@ -52,12 +52,29 @@
3552 <table>
3553 <tr>
3554 <td><label for="duration" title="The duration in seconds this webpage should be displayed">Duration<span class="required">*</span></label></td>
3555- <td><input id="duration" name="duration" type="text"></td>
3556+ <td><input id="duration" name="duration" type="text"></td>
3557 </tr>
3558 <tr>
3559 <td colspan="2">
3560 <label for="embedHtml" title="The HTML you want to Embed in this Layout.">Embed HTML<span class="required">*</span></label><br />
3561- <textarea id="embedHtml" name="embedHtml"></textarea>
3562+<textarea id="embedHtml" name="embedHtml">
3563+
3564+</textarea>
3565+ </td>
3566+ </tr>
3567+ <tr>
3568+ <td colspan="2">
3569+ <label for="embedScript" title="The JavaScript you want to Embed in this Layout.">Embed Script<span class="required">*</span></label><br />
3570+<textarea id="embedScript" name="embedScript">
3571+<script type="text/javascript">
3572+function EmbedInit()
3573+{
3574+ // Init will be called when this page is loaded in the client.
3575+
3576+ return;
3577+}
3578+</script>
3579+</textarea>
3580 </td>
3581 </tr>
3582 <tr>
3583@@ -103,6 +120,10 @@
3584 $textNode = $textNodes->item(0);
3585 $embedHtml = $textNode->nodeValue;
3586
3587+ $textNodes = $rawXml->getElementsByTagName('embedScript');
3588+ $textNode = $textNodes->item(0);
3589+ $embedScript= $textNode->nodeValue;
3590+
3591 //Output the form
3592 $form = <<<FORM
3593 <form class="XiboForm" method="post" action="index.php?p=module&mod=$this->type&q=Exec&method=EditMedia">
3594@@ -121,6 +142,12 @@
3595 </td>
3596 </tr>
3597 <tr>
3598+ <td colspan="2">
3599+ <label for="embedScript" title="The JavaScript you want to Embed in this Layout.">Embed Script<span class="required">*</span></label><br />
3600+ <textarea id="embedScript" name="embedScript">$embedScript</textarea>
3601+ </td>
3602+ </tr>
3603+ <tr>
3604 <td></td>
3605 <td>
3606 <input id="btnSave" type="submit" value="Save" />
3607@@ -154,6 +181,7 @@
3608
3609 //Other properties
3610 $embedHtml = Kit::GetParam('embedHtml', _POST, _HTMLSTRING);
3611+ $embedScript = Kit::GetParam('embedScript', _POST, _HTMLSTRING);
3612 $duration = Kit::GetParam('duration', _POST, _INT, 0);
3613
3614 $url = "index.php?p=layout&layoutid=$layoutid&regionid=$regionid&q=RegionOptions";
3615@@ -178,7 +206,7 @@
3616 $this->duration = $duration;
3617
3618 // Any Options
3619- $this->SetRaw('<embedHtml><![CDATA[' . $embedHtml . ']]></embedHtml>');
3620+ $this->SetRaw('<embedHtml><![CDATA[' . $embedHtml . ']]></embedHtml><embedScript><![CDATA[' . $embedScript . ']]></embedScript>');
3621
3622 // Should have built the media object entirely by this time
3623 // This saves the Media Object to the Region
3624@@ -208,11 +236,12 @@
3625
3626 //Other properties
3627 $embedHtml = Kit::GetParam('embedHtml', _POST, _HTMLSTRING);
3628+ $embedScript = Kit::GetParam('embedScript', _POST, _HTMLSTRING);
3629 $duration = Kit::GetParam('duration', _POST, _INT, 0);
3630
3631 $url = "index.php?p=layout&layoutid=$layoutid&regionid=$regionid&q=RegionOptions";
3632
3633- //Validate the URL?
3634+ // Validate the URL?
3635 if ($embedHtml == "")
3636 {
3637 $this->response->SetError('Please enter some HTML to embed.');
3638@@ -231,7 +260,7 @@
3639 $this->duration = $duration;
3640
3641 // Any Options
3642- $this->SetRaw('<embedHtml><![CDATA[' . $embedHtml . ']]></embedHtml>');
3643+ $this->SetRaw('<embedHtml><![CDATA[' . $embedHtml . ']]></embedHtml><embedScript><![CDATA[' . $embedScript . ']]></embedScript>');
3644
3645 // Should have built the media object entirely by this time
3646 // This saves the Media Object to the Region
3647
3648=== modified file 'server/modules/flash.module.php'
3649--- server/modules/flash.module.php 2009-05-24 09:59:49 +0000
3650+++ server/modules/flash.module.php 2009-06-28 10:47:06 +0000
3651@@ -784,8 +784,11 @@
3652 // Editing the existing record
3653 $new_mediaid = $mediaid;
3654
3655- $SQL = "UPDATE media SET name = '$name', duration = '$duration', permissionID = $permissionid";
3656- $SQL .= " WHERE mediaID = $mediaid ";
3657+ $SQL = "UPDATE media SET name = '%s', duration = %d, permissionID = %d";
3658+ $SQL .= " WHERE mediaID = %d ";
3659+ $SQL = sprintf($SQL, $db->escape_string($name), $duration, $permissionid, $mediaid);
3660+
3661+ Debug::LogEntry($db, 'audit', $SQL);
3662
3663 if (!$db->query($SQL))
3664 {
3665
3666=== modified file 'server/modules/image.module.php'
3667--- server/modules/image.module.php 2009-05-24 09:59:49 +0000
3668+++ server/modules/image.module.php 2009-06-28 10:47:06 +0000
3669@@ -794,8 +794,11 @@
3670 // Editing the existing record
3671 $new_mediaid = $mediaid;
3672
3673- $SQL = "UPDATE media SET name = '$name', duration = '$duration', permissionID = $permissionid";
3674- $SQL .= " WHERE mediaID = $mediaid ";
3675+ $SQL = "UPDATE media SET name = '%s', duration = %d, permissionID = %d";
3676+ $SQL .= " WHERE mediaID = %d ";
3677+ $SQL = sprintf($SQL, $db->escape_string($name), $duration, $permissionid, $mediaid);
3678+
3679+ Debug::LogEntry($db, 'audit', $SQL);
3680
3681 if (!$db->query($SQL))
3682 {
3683
3684=== modified file 'server/modules/module_user_general.php'
3685--- server/modules/module_user_general.php 2009-03-25 19:36:36 +0000
3686+++ server/modules/module_user_general.php 2009-07-07 20:01:49 +0000
3687@@ -89,8 +89,6 @@
3688
3689 $sql = sprintf("SELECT UserID, UserName, UserPassword, usertypeid, groupID FROM user WHERE UserName = '%s' AND UserPassword = '%s'", $db->escape_string($username), $db->escape_string($password));
3690
3691- Debug::LogEntry($db, 'audit', $sql);
3692-
3693 if(!$result = $db->query($sql)) trigger_error('A database error occurred while checking your login details.', E_USER_ERROR);
3694
3695 if ($db->num_rows($result)==0)
3696@@ -122,6 +120,7 @@
3697 $db->query($SQL) or trigger_error("Can not write last accessed info.", E_USER_ERROR);
3698
3699 $session->setIsExpired(0);
3700+ $session->RegenerateSessionID(session_id());
3701
3702 return true;
3703 }
3704
3705=== modified file 'server/modules/powerpoint.module.php'
3706--- server/modules/powerpoint.module.php 2009-05-24 09:59:49 +0000
3707+++ server/modules/powerpoint.module.php 2009-06-28 10:47:06 +0000
3708@@ -784,8 +784,11 @@
3709 // Editing the existing record
3710 $new_mediaid = $mediaid;
3711
3712- $SQL = "UPDATE media SET name = '$name', duration = '$duration', permissionID = $permissionid";
3713- $SQL .= " WHERE mediaID = $mediaid ";
3714+ $SQL = "UPDATE media SET name = '%s', duration = %d, permissionID = %d";
3715+ $SQL .= " WHERE mediaID = %d ";
3716+ $SQL = sprintf($SQL, $db->escape_string($name), $duration, $permissionid, $mediaid);
3717+
3718+ Debug::LogEntry($db, 'audit', $SQL);
3719
3720 if (!$db->query($SQL))
3721 {
3722
3723=== modified file 'server/modules/text.module.php'
3724--- server/modules/text.module.php 2009-02-27 19:30:45 +0000
3725+++ server/modules/text.module.php 2009-08-03 12:10:12 +0000
3726@@ -62,6 +62,10 @@
3727 <td><input id="duration" name="duration" type="text"></td>
3728 </tr>
3729 <tr>
3730+ <td><label for="scrollSpeed" title="The scroll speed of the ticker.">Scroll Speed<span class="required">*</span> (lower is faster)</label></td>
3731+ <td><input id="scrollSpeed" name="scrollSpeed" type="text" value="30"></td>
3732+ </tr>
3733+ <tr>
3734 <td colspan="4">
3735 <textarea id="ta_text" name="ta_text"></textarea>
3736 </td>
3737@@ -95,11 +99,12 @@
3738 {
3739 $db =& $this->db;
3740
3741- $layoutid = $this->layoutid;
3742- $regionid = $this->regionid;
3743- $mediaid = $this->mediaid;
3744+ $layoutid = $this->layoutid;
3745+ $regionid = $this->regionid;
3746+ $mediaid = $this->mediaid;
3747
3748- $direction = $this->GetOption('direction');
3749+ $direction = $this->GetOption('direction');
3750+ $scrollSpeed = $this->GetOption('scrollSpeed');
3751
3752 // Get the text out of RAW
3753 $rawXml = new DOMDocument();
3754@@ -128,6 +133,10 @@
3755 <td><input id="duration" name="duration" value="$this->duration" type="text"></td>
3756 </tr>
3757 <tr>
3758+ <td><label for="scrollSpeed" title="The scroll speed of the ticker.">Scroll Speed<span class="required">*</span> (lower is faster)</label></td>
3759+ <td><input id="scrollSpeed" name="scrollSpeed" type="text" value="$scrollSpeed"></td>
3760+ </tr>
3761+ <tr>
3762 <td colspan="4">
3763 <textarea id="ta_text" name="ta_text">$text</textarea>
3764 </td>
3765@@ -169,6 +178,7 @@
3766 $direction = Kit::GetParam('direction', _POST, _WORD, 'none');
3767 $duration = Kit::GetParam('duration', _POST, _INT, 0);
3768 $text = Kit::GetParam('ta_text', _POST, _HTMLSTRING);
3769+ $scrollSpeed = Kit::GetParam('scrollSpeed', _POST, _INT, 30);
3770
3771 $url = "index.php?p=layout&layoutid=$layoutid&regionid=$regionid&q=RegionOptions";
3772
3773@@ -193,6 +203,7 @@
3774
3775 // Any Options
3776 $this->SetOption('direction', $direction);
3777+ $this->SetOption('scrollSpeed', $scrollSpeed);
3778 $this->SetRaw('<text><![CDATA[' . $text . ']]></text>');
3779
3780 // Should have built the media object entirely by this time
3781@@ -225,6 +236,7 @@
3782 $direction = Kit::GetParam('direction', _POST, _WORD, 'none');
3783 $duration = Kit::GetParam('duration', _POST, _INT, 0);
3784 $text = Kit::GetParam('ta_text', _POST, _HTMLSTRING);
3785+ $scrollSpeed = Kit::GetParam('scrollSpeed', _POST, _INT, 30);
3786
3787 $url = "index.php?p=layout&layoutid=$layoutid&regionid=$regionid&q=RegionOptions";
3788
3789@@ -248,6 +260,7 @@
3790
3791 // Any Options
3792 $this->SetOption('direction', $direction);
3793+ $this->SetOption('scrollSpeed', $scrollSpeed);
3794 $this->SetRaw('<text><![CDATA[' . $text . ']]></text>');
3795
3796 // Should have built the media object entirely by this time
3797
3798=== modified file 'server/modules/ticker.module.php'
3799--- server/modules/ticker.module.php 2009-06-18 18:36:21 +0000
3800+++ server/modules/ticker.module.php 2009-07-05 20:56:48 +0000
3801@@ -272,7 +272,7 @@
3802 $copyright = Kit::GetParam('copyright', _POST, _STRING);
3803
3804 $url = "index.php?p=layout&layoutid=$layoutid&regionid=$regionid&q=RegionOptions";
3805-
3806+
3807 //validation
3808 if ($text == '')
3809 {
3810
3811=== modified file 'server/modules/video.module.php'
3812--- server/modules/video.module.php 2009-05-24 09:59:49 +0000
3813+++ server/modules/video.module.php 2009-06-28 10:47:06 +0000
3814@@ -771,8 +771,11 @@
3815 // Editing the existing record
3816 $new_mediaid = $mediaid;
3817
3818- $SQL = "UPDATE media SET name = '$name', duration = '$duration', permissionID = $permissionid";
3819- $SQL .= " WHERE mediaID = $mediaid ";
3820+ $SQL = "UPDATE media SET name = '%s', duration = %d, permissionID = %d";
3821+ $SQL .= " WHERE mediaID = %d ";
3822+ $SQL = sprintf($SQL, $db->escape_string($name), $duration, $permissionid, $mediaid);
3823+
3824+ Debug::LogEntry($db, 'audit', $SQL);
3825
3826 if (!$db->query($SQL))
3827 {
3828
3829=== modified file 'server/template/css/xibo.css'
3830--- server/template/css/xibo.css 2009-06-20 12:00:21 +0000
3831+++ server/template/css/xibo.css 2009-08-03 12:10:12 +0000
3832@@ -48,7 +48,12 @@
3833
3834 #embedHtml {
3835 width: 500px;
3836- height: 310px;
3837+ height: 140px;
3838+}
3839+
3840+#embedScript {
3841+ width: 500px;
3842+ height: 140px;
3843 }
3844
3845 .regionTransparency {
3846
3847=== added file 'server/template/pages/stats_view.php'
3848--- server/template/pages/stats_view.php 1970-01-01 00:00:00 +0000
3849+++ server/template/pages/stats_view.php 2009-08-03 16:42:20 +0000
3850@@ -0,0 +1,42 @@
3851+<?php
3852+/*
3853+ * Xibo - Digitial Signage - http://www.xibo.org.uk
3854+ * Copyright (C) 2009 Daniel Garner
3855+ *
3856+ * This file is part of Xibo.
3857+ *
3858+ * Xibo is free software: you can redistribute it and/or modify
3859+ * it under the terms of the GNU Affero General Public License as published by
3860+ * the Free Software Foundation, either version 3 of the License, or
3861+ * any later version.
3862+ *
3863+ * Xibo is distributed in the hope that it will be useful,
3864+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3865+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3866+ * GNU Affero General Public License for more details.
3867+ *
3868+ * You should have received a copy of the GNU Affero General Public License
3869+ * along with Xibo. If not, see <http://www.gnu.org/licenses/>.
3870+ */
3871+ defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
3872+?>
3873+<div id="form_container">
3874+ <div id="form_header">
3875+ <div id="form_header_left"></div>
3876+ <div id="form_header_right"></div>
3877+ </div>
3878+
3879+ <div id="form_body">
3880+ <div class="SecondNav">
3881+
3882+ </div>
3883+ <?php $this->StatsForm(); ?>
3884+ </div>
3885+
3886+ <div id="form_footer">
3887+ <div id="form_footer_left">
3888+ </div>
3889+ <div id="form_footer_right">
3890+ </div>
3891+ </div>
3892+</div>
3893\ No newline at end of file
3894
3895=== modified file 'server/upgrade.php'
3896--- server/upgrade.php 2009-06-15 08:16:19 +0000
3897+++ server/upgrade.php 2009-09-21 22:58:45 +0000
3898@@ -205,6 +205,12 @@
3899 }
3900 }
3901
3902+ echo '<div class="info"><p>';
3903+ echo "Perform automatic database upgrade?";
3904+ echo '</p></div><div class="install-table">';
3905+ echo '<input type="checkbox" name="doBackup" checked />';
3906+ echo '</div><hr width="25%" />';
3907+
3908 $_SESSION['step'] = 3;
3909 echo '<input type="hidden" name="includes" value="true" />';
3910 echo '<p><input type="submit" value="Next >" /></p>';
3911@@ -242,11 +248,18 @@
3912 echo "FAIL: " . $fault_string;
3913 }
3914 else {
3915+ $doBackup = Kit::GetParam("doBackup", $_POST, _BOOL);
3916+
3917 set_time_limit(0);
3918 // Backup the database
3919- echo '<div class="info">';
3920- echo '<p>Backing up your database';
3921- backup_tables($db, '*');
3922+ echo '<div class="info"><p>';
3923+ if ($doBackup) {
3924+ echo 'Backing up your database';
3925+ backup_tables($db, '*');
3926+ }
3927+ else {
3928+ echo 'Skipping database backup';
3929+ }
3930 echo '</p>';
3931
3932 $sqlStatementCount = 0;
3933
3934=== modified file 'server/xmds.php'
3935--- server/xmds.php 2009-06-03 11:55:05 +0000
3936+++ server/xmds.php 2009-08-08 11:04:39 +0000
3937@@ -30,8 +30,6 @@
3938 {
3939 global $db;
3940
3941- if (eregi('[^A-Za-z0-9]', $hardwareKey)) return false;
3942-
3943 //check in the database for this hardwareKey
3944 $SQL = "SELECT licensed, inc_schedule, isAuditing, displayID FROM display WHERE license = '$hardwareKey'";
3945 if (!$result = $db->query($SQL))
3946@@ -554,6 +552,7 @@
3947 $SQL .= " INNER JOIN schedule_detail ON schedule_detail.layoutID = layout.layoutID ";
3948 $SQL .= " INNER JOIN display ON schedule_detail.displayID = display.displayID ";
3949 $SQL .= " WHERE display.license = '$hardwareKey' ";
3950+ $SQL .= " AND layout.retired = 0 ";
3951
3952 // Store the Base SQL for this display
3953 $SQLBase = $SQL;
3954@@ -648,105 +647,7 @@
3955 {
3956 global $db;
3957
3958- // Sanitize
3959- $serverKey = Kit::ValidateParam($serverKey, _STRING);
3960- $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING);
3961- $version = Kit::ValidateParam($version, _STRING);
3962-
3963- // Make sure we are talking the same language
3964- if (!CheckVersion($version))
3965- {
3966- return new soap_fault("SOAP-ENV:Client", "", "Your client is not of the correct version for communication with this server. You can get the latest from http://www.xibo.org.uk", $serverKey);
3967- }
3968-
3969- //auth this request...
3970- if (!$displayInfo = Auth($hardwareKey))
3971- {
3972- return new soap_fault("SOAP-ENV:Client", "", "This display client is not licensed", $hardwareKey);
3973- }
3974-
3975- if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "[IN]", "xmds", "RecieveXmlLog", "", $displayInfo['displayid']);
3976- if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "$xml", "xmds", "RecieveXmlLog", "", $displayInfo['displayid']);
3977-
3978- $document = new DOMDocument("1.0");
3979- $document->loadXML("<log>".$xml."</log>");
3980-
3981- foreach ($document->documentElement->childNodes as $node)
3982- {
3983- //Zero out the common vars
3984- $date = "";
3985- $message = "";
3986- $scheduleID = "";
3987- $layoutID = "";
3988- $mediaID = "";
3989- $type = "";
3990- $cat = '';
3991-
3992- // Get the date and the message (all log types have these)
3993- foreach ($node->childNodes as $nodeElements)
3994- {
3995- if ($nodeElements->nodeName == "date")
3996- {
3997- $date = $nodeElements->textContent;
3998- }
3999- else if ($nodeElements->nodeName == "message")
4000- {
4001- $message = $nodeElements->textContent;
4002- }
4003- else if ($nodeElements->nodeName == "scheduleID")
4004- {
4005- $scheduleID = $nodeElements->textContent;
4006- }
4007- else if ($nodeElements->nodeName == "layoutID")
4008- {
4009- $layoutID = $nodeElements->textContent;
4010- }
4011- else if ($nodeElements->nodeName == "mediaID")
4012- {
4013- $mediaID = $nodeElements->textContent;
4014- }
4015- else if ($nodeElements->nodeName == "type")
4016- {
4017- $type = $nodeElements->textContent;
4018- }
4019- else if ($nodeElements->nodeName == "category")
4020- {
4021- $cat = $nodeElements->textContent;
4022- }
4023- }
4024-
4025- switch ($node->nodeName)
4026- {
4027- case "stat":
4028- if ($mediaID == '') $mediaID = 0;
4029-
4030- StatRecord($type, $date, $scheduleID, $displayInfo['displayid'], $layoutID, $mediaID, $date, $date);
4031- break;
4032-
4033- case "trace":
4034-
4035- // We have a trace message
4036- // Either Audit or Error (if *)
4037- if (substr($message, 0, 3) == '[*]')
4038- {
4039- Debug::LogEntry($db, "error", $message, ".NET Client", $cat, $date, $displayInfo['displayid'], $scheduleID, $layoutID, $mediaID);
4040- }
4041- else
4042- {
4043- Debug::LogEntry($db, "audit", $message, ".NET Client", $cat, $date, $displayInfo['displayid'], $scheduleID, $layoutID, $mediaID);
4044- }
4045-
4046- break;
4047-
4048- default:
4049- Debug::LogEntry($db, "audit", "Unknown entry in client log " . $node->nodeName, "xmds", "RecieveXmlLog", $date, $displayInfo['displayid'], $scheduleID, $layoutID, $mediaID);
4050- break;
4051- }
4052- }
4053-
4054- if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "[OUT]", "xmds", "RecieveXmlLog", "", $displayInfo['displayid']);
4055-
4056- return true;
4057+ return new soap_fault("SOAP-ENV:Client", "", "This is a depricated service call. You should instead call either SubmitLog or SubmitStats", $serverKey);
4058 }
4059
4060 define('BLACKLIST_ALL', "All");
4061@@ -835,6 +736,203 @@
4062 return true;
4063 }
4064
4065+/**
4066+ * Submit client logging
4067+ * @return
4068+ * @param $version Object
4069+ * @param $serverKey Object
4070+ * @param $hardwareKey Object
4071+ * @param $logXml Object
4072+ */
4073+function SubmitLog($version, $serverKey, $hardwareKey, $logXml)
4074+{
4075+ global $db;
4076+
4077+ // Sanitize
4078+ $serverKey = Kit::ValidateParam($serverKey, _STRING);
4079+ $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING);
4080+ $version = Kit::ValidateParam($version, _STRING);
4081+ $logXml = Kit::ValidateParam($logXml, _HTMLSTRING);
4082+
4083+ // Make sure we are talking the same language
4084+ if (!CheckVersion($version))
4085+ {
4086+ return new soap_fault("SOAP-ENV:Client", "", "Your client is not of the correct version for communication with this server. You can get the latest from http://www.xibo.org.uk", $serverKey);
4087+ }
4088+
4089+ // Auth this request...
4090+ if (!$displayInfo = Auth($hardwareKey))
4091+ {
4092+ return new soap_fault("SOAP-ENV:Client", "", "This display client is not licensed", $hardwareKey);
4093+ }
4094+
4095+ if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "IN", "xmds", "SubmitLog", "", $displayInfo['displayid']);
4096+ if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", 'XML [' . $logXml . ']', "xmds", "SubmitLog", "", $displayInfo['displayid']);
4097+
4098+ // Load the XML into a DOMDocument
4099+ $document = new DOMDocument("1.0");
4100+
4101+ if (!$document->loadXML($logXml))
4102+ {
4103+ return new soap_fault("SOAP-ENV:Client", "", "XML Cannot be loaded into DOM Document.", $hardwareKey);
4104+ }
4105+
4106+ foreach ($document->documentElement->childNodes as $node)
4107+ {
4108+ //Zero out the common vars
4109+ $date = "";
4110+ $message = "";
4111+ $scheduleID = "";
4112+ $layoutID = "";
4113+ $mediaID = "";
4114+ $cat = '';
4115+ $method = '';
4116+
4117+ // This will be a bunch of trace nodes
4118+ $message = $node->textContent;
4119+
4120+ // Each element should have a category and a date
4121+ $date = $node->getAttribute('date');
4122+ $cat = $node->getAttribute('category');
4123+
4124+ if ($date == '' || $cat == '')
4125+ {
4126+ trigger_error('Log submitted without a date or category attribute');
4127+ continue;
4128+ }
4129+
4130+ // Get the date and the message (all log types have these)
4131+ foreach ($node->childNodes as $nodeElements)
4132+ {
4133+ if ($nodeElements->nodeName == "scheduleID")
4134+ {
4135+ $scheduleID = $nodeElements->textContent;
4136+ }
4137+ else if ($nodeElements->nodeName == "layoutID")
4138+ {
4139+ $layoutID = $nodeElements->textContent;
4140+ }
4141+ else if ($nodeElements->nodeName == "mediaID")
4142+ {
4143+ $mediaID = $nodeElements->textContent;
4144+ }
4145+ else if ($nodeElements->nodeName == "type")
4146+ {
4147+ $type = $nodeElements->textContent;
4148+ }
4149+ else if ($nodeElements->nodeName == "method")
4150+ {
4151+ $method = $nodeElements->textContent;
4152+ }
4153+ }
4154+
4155+ // We should have enough information to log this now.
4156+ if ($cat == 'error' || $cat == 'Error')
4157+ {
4158+ Debug::LogEntry($db, $cat, $message, 'Client', $method, $date, $displayInfo['displayid'], $scheduleID, $layoutID, $mediaID);
4159+ }
4160+ else
4161+ {
4162+ Debug::LogEntry($db, 'audit', $message, 'Client', $method, $date, $displayInfo['displayid'], $scheduleID, $layoutID, $mediaID);
4163+ }
4164+ }
4165+
4166+ if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "OUT", "xmds", "SubmitLog", "", $displayInfo['displayid']);
4167+
4168+ return true;
4169+}
4170+
4171+/**
4172+ * Submit display statistics to the server
4173+ * @return
4174+ * @param $version Object
4175+ * @param $serverKey Object
4176+ * @param $hardwareKey Object
4177+ * @param $statXml Object
4178+ */
4179+function SubmitStats($version, $serverKey, $hardwareKey, $statXml)
4180+{
4181+ global $db;
4182+
4183+ // Sanitize
4184+ $serverKey = Kit::ValidateParam($serverKey, _STRING);
4185+ $hardwareKey = Kit::ValidateParam($hardwareKey, _STRING);
4186+ $version = Kit::ValidateParam($version, _STRING);
4187+ $statXml = Kit::ValidateParam($statXml, _HTMLSTRING);
4188+
4189+ // Make sure we are talking the same language
4190+ if (!CheckVersion($version))
4191+ {
4192+ return new soap_fault("SOAP-ENV:Client", "", "Your client is not of the correct version for communication with this server. You can get the latest from http://www.xibo.org.uk", $serverKey);
4193+ }
4194+
4195+ // Auth this request...
4196+ if (!$displayInfo = Auth($hardwareKey))
4197+ {
4198+ return new soap_fault("SOAP-ENV:Client", "", "This display client is not licensed", $hardwareKey);
4199+ }
4200+
4201+ if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "IN", "xmds", "SubmitStats", "", $displayInfo['displayid']);
4202+ if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "StatXml: [" . $statXml . "]", "xmds", "SubmitStats", "", $displayInfo['displayid']);
4203+
4204+ if ($statXml == "")
4205+ {
4206+ return new soap_fault("SOAP-ENV:Client", "", "Stat XML is empty.", $hardwareKey);
4207+ }
4208+
4209+ // Log
4210+ if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "About to create Stat Object.", "xmds", "SubmitStats", "", $displayInfo['displayid']);
4211+
4212+ $statObject = new Stat($db);
4213+
4214+ // Log
4215+ if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "About to Create DOMDocument.", "xmds", "SubmitStats", "", $displayInfo['displayid']);
4216+
4217+ // Load the XML into a DOMDocument
4218+ $document = new DOMDocument("1.0");
4219+ $document->loadXML($statXml);
4220+
4221+ foreach ($document->documentElement->childNodes as $node)
4222+ {
4223+ //Zero out the common vars
4224+ $fromdt = '';
4225+ $todt = '';
4226+ $type = '';
4227+
4228+ $scheduleID = 0;
4229+ $layoutID = 0;
4230+ $mediaID = '';
4231+ $tag = '';
4232+
4233+ // Each element should have these attributes
4234+ $fromdt = $node->getAttribute('fromdt');
4235+ $todt = $node->getAttribute('todt');
4236+ $type = $node->getAttribute('type');
4237+
4238+ if ($fromdt == '' || $todt == '' || $type == '')
4239+ {
4240+ trigger_error('Stat submitted without the fromdt, todt or type attributes.');
4241+ continue;
4242+ }
4243+
4244+ $scheduleID = $node->getAttribute('scheduleid');
4245+ $layoutID = $node->getAttribute('layoutid');
4246+ $mediaID = $node->getAttribute('mediaid');
4247+ $tag = $node->getAttribute('tag');
4248+
4249+ // Write the stat record with the information we have available to us.
4250+ if (!$statObject->Add($type, $fromdt, $todt, $scheduleID, $displayInfo['displayid'], $layoutID, $mediaID, $tag))
4251+ {
4252+ trigger_error(sprintf('Stat Add failed with error: %s', $statObject->GetErrorMessage()));
4253+ continue;
4254+ }
4255+ }
4256+
4257+ if ($displayInfo['isAuditing'] == 1) Debug::LogEntry ($db, "audit", "OUT", "xmds", "SubmitStats", "", $displayInfo['displayid']);
4258+
4259+ return true;
4260+}
4261+
4262 //$debug = 1;
4263 $service = new soap_server();
4264
4265@@ -899,10 +997,32 @@
4266 'encoded',
4267 'Set media to be blacklisted'
4268 );
4269+
4270+$service->register("SubmitLog",
4271+ array('version' => 'xsd:string', 'serverKey' => 'xsd:string', 'hardwareKey' => 'xsd:string', 'logXml' => 'xsd:string'),
4272+ array('success' => 'xsd:boolean'),
4273+ 'urn:xmds',
4274+ 'urn:xmds#SubmitLog',
4275+ 'rpc',
4276+ 'encoded',
4277+ 'Submit Logging from the Client'
4278+ );
4279+
4280+$service->register("SubmitStats",
4281+ array('version' => 'xsd:string', 'serverKey' => 'xsd:string', 'hardwareKey' => 'xsd:string', 'statXml' => 'xsd:string'),
4282+ array('success' => 'xsd:boolean'),
4283+ 'urn:xmds',
4284+ 'urn:xmds#SubmitLog',
4285+ 'rpc',
4286+ 'encoded',
4287+ 'Submit Display statistics from the Client'
4288+ );
4289+
4290+
4291
4292 $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
4293 $service->service($HTTP_RAW_POST_DATA);
4294
4295-Debug::LogEntry($db, 'audit',$service->debug_str);
4296+//Debug::LogEntry($db, 'audit', $service->debug_str, "xmds", "NuSOAP");
4297
4298 ?>
4299\ No newline at end of file

Subscribers

People subscribed via source and target branches