diff options
Diffstat (limited to 'plugins/Irc/extlib/phergie/Phergie/Tools/LogViewer/index.php')
-rwxr-xr-x | plugins/Irc/extlib/phergie/Phergie/Tools/LogViewer/index.php | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/plugins/Irc/extlib/phergie/Phergie/Tools/LogViewer/index.php b/plugins/Irc/extlib/phergie/Phergie/Tools/LogViewer/index.php new file mode 100755 index 000000000..fc27fa294 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Tools/LogViewer/index.php @@ -0,0 +1,368 @@ +<?php +// Phergie Log Viewer ... Currently designed as a single PHP file in order to make it easy to +// 'install' this. Just drop the index.php (or whatever name you wish to rename it to) wherever +// you wish, and it will simply work. Sure, it would be nice to structure some of this stuff into +// various include files/etc. But right now this is simple enough of a quick log viewer, that it's +// just one file. + + +/********** SETUP **********/ + +// (Change any of these if/as needed for your setup) +ini_set('default_charset', 'UTF-8'); +date_default_timezone_set('UTC'); +$log = "/PATH/AND/FILENAME/TO/YOUR/LOGFILE/PLEASE.db"; + + +/********** PREPARATION **********/ + +$db = new PDO('sqlite:' . $log); +if (!is_object($db)) { + // Failure, can't access Phergie Log. Bail with an error message, not pretty, but works: + echo "ERROR: Cannot access Phergie Log File, please check the configuration & access privileges"; + exit(); +} + + +/********** DETECTION **********/ + +// Determine the mode of the application and call the appropriate handler function +$mode = empty($_GET['m']) ? '' : $_GET['m']; +switch ($mode) { + case 'channel': + show_days($db); + break; + case 'day': + show_log($db); + break; + default: + show_channels($db); +} + +// Exit not really needed here, but reminds us that everything below is support functions: +exit(); + + +/********** MODES **********/ + +/** + * show_channels + * + * Provide a list of all channel's that we are logging information for: + * + * @param PDO A PDO object referring to the database + * @return void + * @author Eli White <eli@eliw.com> + **/ +function show_channels(PDO $db) { + // Begin the HTML page: + template_header('Channels'); + echo "\nChannels:\n<ul>\n"; + + // Loop through the database reading in each channel, and echoing out a <li> for it. + // only grab actual channels that start with # ... also pre-lowercase everything. + // this allows us to 'deal' with variable caps in how the channels were logged. + $channels = $db->query(" + select distinct lower(chan) as c + from logs + where chan like '#%' + "); + foreach ($channels as $row) { + $html = utf8specialchars($row['c']); + $url = urlencode($row['c']); + echo "<li><a href=\"?m=channel&w={$url}\">{$html}</a></li>\n"; + } + + // Finish off the page: + echo "\n</ul>\n"; + template_footer(); +} + +/** + * show_days + * + * Create a calendar view of all days available for this particular channel + * + * NOTE: May get unwieldy if large log files. Perhaps consider in the future + * making a paginated version of this? by year? Or a separate 'which year' page + * before this? Not to worry about now. + * + * @param PDO A PDO object referring to the database + * @return void + * @author Eli White <eli@eliw.com> + **/ +function show_days(PDO $db) { + $channel = $_GET['w']; + $url = urlencode($channel); + + // Begin the HTML page: + template_header('Daily Logs for Channel: ' . utf8specialchars($channel)); + echo "\n<ul>\n"; + + // Query the database to discover all days that are available for this channel: + $data = array(); + $prepared = $db->prepare(" + select distinct date(tstamp) as day + from logs + where lower(chan) = :chan + "); + $prepared->execute(array(':chan' => $channel)); + foreach ($prepared as $row) { + list($y, $m, $d) = explode('-', $row['day']); + $data[$y][$m][$d] = "{$y}-{$m}-{$d}"; + } + + // For now, just loop over them all and provide a list: + ksort($data); + foreach ($data as $year => $months) { + ksort($months); + foreach ($months as $month => $days) { + // Figure out a few facts about this month: + $stamp = mktime(0, 0, 0, $month, 1, $year); + $first_weekday = idate('w', $stamp); + $days_in_month = idate('t', $stamp); + $name = date('F', $stamp); + + // We have a month ... start a new table: + echo <<<EOTABLE +<div class="month"> + <table> + <caption>{$name} {$year}</caption> + <tr><th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th></tr> +EOTABLE; + // Now we need to start looping through the days in this month: + echo '<tr>'; + $rowmod = 0; + // Loop through all day entries, no matter how many blanks we need: + for ($d = (-$first_weekday + 1); $d < $days_in_month + 1; $d++) { + if (!($rowmod++ % 7)) { + // Stop/start a new row: + echo '</tr><tr>'; + } + echo '<td>'; + // If this day is pre or post actual month days, make it blank: + if (($d < 1) || ($d > $days_in_month)) { + echo ' '; + } elseif (isset($days[$d])) { + // Make a link to the day's log: + echo "<a href=\"?m=day&w={$url}&d={$days[$d]}\">{$d}</a>"; + } else { + // Just a dead number: + echo $d; + } + echo '</td>'; + } + // Finish off any blanks needed for a complete table row: + while ($rowmod++ % 7) { + echo '<td> </td>'; + } + echo "</tr></table></div>\n"; + } + } + + // Finish off the page: + echo "\n</ul>\n"; + template_footer(); +} + +/** + * show_log + * + * Actually show the log for this specific day + * + * @param PDO A PDO object referring to the database + * @return void + * @author Eli White <eli@eliw.com> + **/ +function show_log(PDO $db) { + $channel = $_GET['w']; + $day = $_GET['d']; + $parts = explode('-', $day); + $formatted_date = "{$parts[0]}-{$parts[1]}-{$parts[2]}"; + + // Begin the HTML page: + template_header('Date: ' . utf8specialchars($formatted_date) . + ' - Channel: ' . utf8specialchars($channel)); + + // Query the database to get all log lines for this date: + $prepared = $db->prepare(" + select time(tstamp) as t, type, nick, message + from logs + where lower(chan) = :chan and date(tstamp) = :day + order by tstamp asc + "); + $prepared->execute(array( + ':chan' => $channel, + ':day' => $day, + )); + + // Loop through each line, + foreach ($prepared as $row) { + // Prepare some basic details for output: + $color = nick_color($row['nick']); + $time = utf8specialchars($row['t']); + $msg = utf8specialchars($row['message']); + $nick = utf8specialchars($row['nick']); + $type = false; + + // Now change the format of the line based upon the type: + switch ($row['type']) { + case 4: // PRIVMSG (A Regular Message) + echo "[$time] <span style=\"color:#{$color};\"><{$nick}></span> {$msg}<br />\n"; + break; + case 5: // ACTION (emote) + echo "[$time] <span style=\"color:#{$color};\">*{$nick} {$msg}</span><br />\n"; + break; + case 1: // JOIN + echo "[$time] -> {$nick} joined the room.<br />\n"; + break; + case 2: // PART (leaves channel) + echo "[$time] -> {$nick} left the room: {$msg}<br />\n"; + break; + case 3: // QUIT (quits the server) + echo "[$time] -> {$nick} left the server: {$msg}<br />\n"; + break; + case 6: // NICK (changes their nickname) + echo "[$time] -> {$nick} is now known as: {$msg}<br />\n"; + break; + case 7: // KICK (booted) + echo "[$time] -> {$nick} boots {$msg} from the room.<br />\n"; + break; + case 8: // MODE (changed their mode) + $type = 'MODE'; + case 9: // TOPIC (changed the topic) + $type = $type ? $type : 'TOPIC'; + echo "[$time] -> {$nick}: :{$type}: {$msg}<br />\n"; + } + } + + // Finish up the page: + template_footer(); +} + +/** + * nick_color + * + * Uses a silly little algorithm to pick a consistent but unique(ish) color for + * any given username. NOTE: Augment this in the future to make it not generate + * 'close to white' ones, also maybe to ensure uniqueness? (Not allow two to have + * colors that are close to each other?) + * + * @return string A CSS valid hex color string + * @author Eli White <eli@eliw.com> + **/ +function nick_color($user) { + static $colors = array(); + + if (!isset($colors[$user])) { + $colors[$user] = substr(md5($user), 0, 6); + } + + return $colors[$user]; +} + +/** + * utf8specialchars + * + * Just a quick wrapper around htmlspecialchars + * + * @param string The UTF8 string to escape + * @return string An escaped and ready for HTML use string + * @author Eli White <eli@eliw.com> + **/ +function utf8specialchars($string) { + return htmlspecialchars($string, ENT_COMPAT, 'UTF-8'); +} + + +/********** TEMPLATES **********/ + +/** + * template_header + * + * Echo out the header for each HTML page + * + * @param $title string The title to be used for this page. + * @return void + * @author Eli White <eli@eliw.com> + **/ +function template_header($title) { + $css = template_css(); + echo <<<EOHTML +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html lang="en" xmlns="http://www.w3.org/1999/xhtml"> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Phergie LogViewer - {$title}</title> + <style type="text/css" media="all">{$css}</style> + </head> + <body> + <h2>Phergie LogViewer - {$title}</h2> +EOHTML; +} + +/** + * template_footer + * + * Echo out the bottom of each HTML page + * + * @return void + * @author Eli White <eli@eliw.com> + **/ +function template_footer() { + echo <<<EOHTML + </body> +</html> +EOHTML; +} + +/** + * template_css + * + * Generate the CSS used by these HTML pages & return it. + * + * @return string The CSS in question: + * @author Eli White <eli@eliw.com> + **/ +function template_css() { + return <<<EOCSS + div.month { + float: left; + height: 15em; + } + + div.month table { + border-collapse: collapse; + border: 2px solid black; + margin-right: 2em; + } + + div.month td, div.month th { + text-align: center; + vertical-align: bottom; + border: 1px solid gray; + width: 2em; + height: 1.7em; + padding: 1px; + margin: 0px; + } + + div.month th { + text-decoration: bold; + border: 2px solid black; + } + + div.month a { + text-decoration: none; + } + + a:visited, a:link { + color: blue; + } + + a:active, a:hover { + color: red; + } +EOCSS; +} |