]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Irc/extlib/phergie/Phergie/Tools/LogViewer/index.php
Merge branch '0.9.x' into 1.0.x
[quix0rs-gnu-social.git] / plugins / Irc / extlib / phergie / Phergie / Tools / LogViewer / index.php
1 <?php
2 // Phergie Log Viewer ... Currently designed as a single PHP file in order to make it easy to
3 //  'install' this.  Just drop the index.php (or whatever name you wish to rename it to) wherever
4 //  you wish, and it will simply work.  Sure, it would be nice to structure some of this stuff into
5 //  various include files/etc.  But right now this is simple enough of a quick log viewer, that it's
6 //  just one file.
7
8
9 /********** SETUP **********/
10
11 // (Change any of these if/as needed for your setup) 
12 ini_set('default_charset', 'UTF-8');
13 date_default_timezone_set('UTC');
14 $log = "/PATH/AND/FILENAME/TO/YOUR/LOGFILE/PLEASE.db";
15
16
17 /********** PREPARATION **********/
18
19 $db = new PDO('sqlite:' . $log);
20 if (!is_object($db)) {
21     // Failure, can't access Phergie Log.  Bail with an error message, not pretty, but works:
22     echo "ERROR: Cannot access Phergie Log File, please check the configuration & access privileges";
23     exit();
24 }
25
26
27 /********** DETECTION **********/
28
29 // Determine the mode of the application and call the appropriate handler function
30 $mode = empty($_GET['m']) ? '' : $_GET['m'];
31 switch ($mode) {
32     case 'channel':
33         show_days($db);
34         break;
35     case 'day':
36         show_log($db);
37         break;
38     default:
39         show_channels($db);
40 }
41
42 // Exit not really needed here, but reminds us that everything below is support functions:
43 exit();
44
45
46 /********** MODES **********/
47
48 /**
49  * show_channels
50  *
51  * Provide a list of all channel's that we are logging information for:
52  *
53  * @param PDO A PDO object referring to the database 
54  * @return void
55  * @author Eli White <eli@eliw.com>
56  **/
57 function show_channels(PDO $db) {
58     // Begin the HTML page:
59     template_header('Channels');
60     echo "\nChannels:\n<ul>\n";
61
62     // Loop through the database reading in each channel, and echoing out a <li> for it.
63     // only grab actual channels that start with # ... also pre-lowercase everything.
64     // this allows us to 'deal' with variable caps in how the channels were logged.
65     $channels = $db->query("
66         select distinct lower(chan) as c
67         from logs
68         where chan like '#%'
69         ");
70     foreach ($channels as $row) {
71         $html = utf8specialchars($row['c']);
72         $url = urlencode($row['c']);
73         echo "<li><a href=\"?m=channel&w={$url}\">{$html}</a></li>\n";        
74     }
75
76     // Finish off the page:
77     echo "\n</ul>\n";
78     template_footer();
79 }
80
81 /**
82  * show_days
83  *
84  * Create a calendar view of all days available for this particular channel
85  * 
86  * NOTE: May get unwieldy if large log files.  Perhaps consider in the future
87  *  making a paginated version of this?  by year?  Or a separate 'which year' page
88  *  before this?  Not to worry about now.
89  *
90  * @param PDO A PDO object referring to the database 
91  * @return void
92  * @author Eli White <eli@eliw.com>
93  **/
94 function show_days(PDO $db) {
95     $channel = $_GET['w'];
96     $url = urlencode($channel);
97
98     // Begin the HTML page:
99     template_header('Daily Logs for Channel: ' . utf8specialchars($channel));
100     echo "\n<ul>\n";
101
102     // Query the database to discover all days that are available for this channel:
103     $data = array();
104     $prepared = $db->prepare("
105         select distinct date(tstamp) as day
106         from logs
107         where lower(chan) = :chan
108         ");
109     $prepared->execute(array(':chan' => $channel));
110     foreach ($prepared as $row) {
111         list($y, $m, $d) = explode('-', $row['day']);
112         $data[$y][$m][$d] = "{$y}-{$m}-{$d}";
113     }
114
115     // For now, just loop over them all and provide a list:
116     ksort($data);
117     foreach ($data as $year => $months) {
118         ksort($months);
119         foreach ($months as $month => $days) {
120             // Figure out a few facts about this month:
121             $stamp = mktime(0, 0, 0, $month, 1, $year);
122             $first_weekday = idate('w', $stamp);
123             $days_in_month = idate('t', $stamp);
124             $name = date('F', $stamp);
125
126             // We have a month ... start a new table:
127             echo <<<EOTABLE
128 <div class="month">
129   <table>
130     <caption>{$name} {$year}</caption>
131     <tr><th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th></tr>
132 EOTABLE;
133             // Now we need to start looping through the days in this month:
134             echo '<tr>';
135             $rowmod = 0;
136             // Loop through all day entries, no matter how many blanks we need:
137             for ($d = (-$first_weekday + 1); $d < $days_in_month + 1; $d++) {
138                 if (!($rowmod++ % 7)) {
139                     // Stop/start a new row:
140                     echo '</tr><tr>';
141                 }
142                 echo '<td>';
143                 // If this day is pre or post actual month days, make it blank:
144                 if (($d < 1) || ($d > $days_in_month)) {
145                     echo '&nbsp;';
146                 } elseif (isset($days[$d])) {
147                     // Make a link to the day's log:
148                     echo "<a href=\"?m=day&w={$url}&d={$days[$d]}\">{$d}</a>";            
149                 } else {
150                     // Just a dead number:
151                     echo $d;
152                 }
153                 echo '</td>';
154             }
155             // Finish off any blanks needed for a complete table row:
156             while ($rowmod++ % 7) {
157                 echo '<td>&nbsp;</td>';
158             }
159             echo "</tr></table></div>\n";
160         }
161     }
162
163     // Finish off the page:
164     echo "\n</ul>\n";
165     template_footer();    
166 }
167
168 /**
169  * show_log
170  *
171  * Actually show the log for this specific day
172  *
173  * @param PDO A PDO object referring to the database 
174  * @return void
175  * @author Eli White <eli@eliw.com>
176  **/
177 function show_log(PDO $db) {
178     $channel = $_GET['w'];
179     $day = $_GET['d'];
180     $parts = explode('-', $day);
181     $formatted_date = "{$parts[0]}-{$parts[1]}-{$parts[2]}";
182
183     // Begin the HTML page:
184     template_header('Date: ' . utf8specialchars($formatted_date) .
185         ' - Channel: ' . utf8specialchars($channel));
186
187     // Query the database to get all log lines for this date:
188     $prepared = $db->prepare("
189         select time(tstamp) as t, type, nick, message
190         from logs
191         where lower(chan) = :chan and date(tstamp) = :day
192         order by tstamp asc
193         ");
194     $prepared->execute(array(
195         ':chan' => $channel,
196         ':day' => $day,
197         ));
198
199     // Loop through each line,
200     foreach ($prepared as $row) {
201         // Prepare some basic details for output:
202         $color = nick_color($row['nick']);
203         $time = utf8specialchars($row['t']);
204         $msg = utf8specialchars($row['message']);
205         $nick = utf8specialchars($row['nick']);
206         $type = false;
207         
208         // Now change the format of the line based upon the type:
209         switch ($row['type']) {
210             case 4: // PRIVMSG (A Regular Message)
211                 echo "[$time] <span style=\"color:#{$color};\">&lt;{$nick}&gt;</span> {$msg}<br />\n";
212                 break;
213             case 5: // ACTION (emote)
214                 echo "[$time] <span style=\"color:#{$color};\">*{$nick} {$msg}</span><br />\n";
215                 break;
216             case 1: // JOIN
217                 echo "[$time] -> {$nick} joined the room.<br />\n";
218                 break;
219             case 2: // PART (leaves channel)
220                 echo "[$time] -> {$nick} left the room: {$msg}<br />\n";
221                 break;
222             case 3: // QUIT (quits the server)
223                 echo "[$time] -> {$nick} left the server: {$msg}<br />\n";
224                 break;
225             case 6: // NICK (changes their nickname)
226                 echo "[$time] -> {$nick} is now known as: {$msg}<br />\n";
227                 break;
228             case 7: // KICK (booted)
229                 echo "[$time] -> {$nick} boots {$msg} from the room.<br />\n";
230                 break;
231             case 8: // MODE (changed their mode)
232                 $type = 'MODE';
233             case 9: // TOPIC (changed the topic)
234                 $type = $type ? $type : 'TOPIC';
235                 echo "[$time] -> {$nick}: :{$type}: {$msg}<br />\n";
236         }
237     }
238         
239     // Finish up the page:
240     template_footer();
241 }
242
243 /**
244  * nick_color
245  *
246  * Uses a silly little algorithm to pick a consistent but unique(ish) color for
247  *  any given username.  NOTE: Augment this in the future to make it not generate
248  *  'close to white' ones, also maybe to ensure uniqueness?  (Not allow two to have
249  *  colors that are close to each other?)
250  *
251  * @return string A CSS valid hex color string
252  * @author Eli White <eli@eliw.com>
253  **/
254 function nick_color($user) {
255     static $colors = array();
256     
257     if (!isset($colors[$user])) {
258         $colors[$user] = substr(md5($user), 0, 6);
259     }
260
261     return $colors[$user];
262 }
263
264 /**
265  * utf8specialchars
266  *
267  * Just a quick wrapper around htmlspecialchars
268  *
269  * @param string The UTF8 string to escape
270  * @return string An escaped and ready for HTML use string
271  * @author Eli White <eli@eliw.com>
272  **/
273 function utf8specialchars($string) {
274     return htmlspecialchars($string, ENT_COMPAT, 'UTF-8');
275 }
276
277
278 /********** TEMPLATES **********/
279
280 /**
281  * template_header
282  *
283  * Echo out the header for each HTML page
284  *
285  * @param $title string The title to be used for this page.
286  * @return void
287  * @author Eli White <eli@eliw.com>
288  **/
289 function template_header($title) {
290     $css = template_css();
291     echo <<<EOHTML
292 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
293   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
294 <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
295   <head>
296     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
297     <title>Phergie LogViewer - {$title}</title>
298     <style type="text/css" media="all">{$css}</style>
299   </head>
300   <body>
301     <h2>Phergie LogViewer - {$title}</h2>
302 EOHTML;
303 }
304
305 /**
306  * template_footer
307  *
308  * Echo out the bottom of each HTML page
309  *
310  * @return void
311  * @author Eli White <eli@eliw.com>
312  **/
313 function template_footer() {
314     echo <<<EOHTML
315   </body>
316 </html>
317 EOHTML;
318 }
319
320 /**
321  * template_css
322  *
323  * Generate the CSS used by these HTML pages & return it.
324  *
325  * @return string The CSS in question:
326  * @author Eli White <eli@eliw.com>
327  **/
328 function template_css() {
329     return <<<EOCSS
330     div.month {
331         float: left;
332         height: 15em;
333     }
334
335     div.month table {
336         border-collapse: collapse;
337         border: 2px solid black;
338         margin-right: 2em;
339     }
340
341     div.month td, div.month th {
342         text-align: center;
343         vertical-align: bottom;
344         border: 1px solid gray;
345         width: 2em;
346         height: 1.7em;
347         padding: 1px;
348         margin: 0px;
349     }
350
351     div.month th {
352         text-decoration: bold;
353         border: 2px solid black;
354     }
355
356     div.month a {
357         text-decoration: none;
358     }
359
360     a:visited, a:link {
361         color: blue;
362     }
363
364     a:active, a:hover {
365         color: red;
366     }
367 EOCSS;
368 }