1<?php 2/** 3 * directions plug-in - Nuno Flores 4 * based on logstats plug-in by J.-F. Lalande (jf@lalande.nom.fr) 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Nuno Flores (nuno.flores@gmail.com) 8 */ 9 10if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 12require_once(DOKU_PLUGIN.'action.php'); 13 14/** 15 * All DokuWiki plugins to extend the parser/rendering mechanism 16 * need to inherit from this class 17 */ 18class action_plugin_directions extends DokuWiki_Action_Plugin { 19 20 /** 21 * return some info 22 */ 23 function getInfo(){ 24 return array( 25 'author' => 'Nuno Flores', 26 'email' => 'nuno.flores@gmail.com', 27 'date' => '2011-03-01', 28 'name' => 'directions plugin (logger component)', 29 'desc' => 'Logs when a user navigates from one wikipage to another.', 30 'url' => 'http://www.dokuwiki.org/plugin:directions', 31 ); 32 } 33 34 35 /* 36 * Log. 37 * 38 * @author J.-F. Lalande (jf@lalande.nom.fr) 39 */ 40 function dir_tpl_logfile(){ 41 global $ID; 42 $this->dir_logPageAccess(cleanID($ID)); 43 } 44 45 /** 46 * Checks the existance of the log file. 47 * 48 * @author J.-F. Lalande (jf@lalande.nom.fr) 49 * adapted by Nuno Flores (nuno.flores@gmail.com) 50 */ 51 function dir_init_log_file($file){ 52 global $conf; 53 54 if(!@file_exists($file)){ 55 $fh = @fopen($file,'a'); 56 if($fh){ 57 fclose($fh); 58 if($conf['fperm']) 59 chmod($file, $conf['fperm']); 60 }else{ 61 nice_die("directions plugin error: Unable to create 62 $file ; The directory where access.log will be 63 created must be writtable by the apache daemon. 64 if you think that it's possibly a bug, 65 please report it !"); 66 } 67 } 68 return $file; 69 } 70 71 /* 72 * Init the paths for hits.log 73 * 74 * @author J.-F. Lalande (jf@lalande.nom.fr) 75 * adapted by Nuno Flores (nuno.flores@gmail.com) 76 */ 77 function dir_init_log_path(){ 78 global $conf; 79 $logstats_accessconf = $this->getConf('hitslog'); 80 81 82 if($logstats_accessconf == "") 83 { 84 nice_die('Error in directions plugin (logger component): the configuration 85 variable $conf[\'plugin\'][\'directions\'][\'hitslog\'] is 86 not set or the default value cannot be read.'); 87 } 88 $tmp_accesslogname = DOKU_INC . $logstats_accessconf; 89 $tmp_accesslogname = init_path($tmp_accesslogname); 90 if($tmp_accesslogname == "") 91 { 92 $this->dir_init_log_file(DOKU_INC . $logstats_accessconf); 93 94 } 95 } 96 97 98 /* 99 * Register its handlers with the dokuwiki's event controller 100 * 101 * @author J.-F. Lalande (jf@lalande.nom.fr) 102 * adapted by Nuno Flores (nuno.flores@gmail.com) 103 */ 104 function register(&$controller) { 105 $controller->register_hook('ACTION_HEADERS_SEND', 'BEFORE', $this, 'dir_tpl_logfile'); 106 $this->dir_init_log_path(); 107 } 108 109/** 110 * beautify a wiki page id for the log 111 * 112 * The wiki page id will be transformed to a filename like string 113 * utf8 codes will be encoded. 114 * 115 * @param $id wiki page id 116 * 117 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 118 */ 119function dir_prepareID($path){ 120 $path = cleanID($path); 121 $path = str_replace(':','/',$path); 122 $path = utf8_encodeFN($path); 123 return $path; 124} 125 126/** 127 * checks if a file exists and returns an appropriate web 128 * server status 129 * 130 * @param $file complete filepath to check 131 * 132 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 133 */ 134function dir_getStatus($file){ 135 if(@file_exists($file)){ 136 $size = @filesize($file); 137 return "200 $size"; 138 }else 139 return "404 0"; 140} 141 142/** 143 * logs access to a wiki page 144 * 145 * @param $id page id of the wiki page including namespace 146 * 147 * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 148 */ 149function dir_logPageAccess($id){ 150 global $ACT; 151 152 if ($ACT == 'show'){ 153 $page = $this->dir_prepareID($id); 154 155 $crumbs = breadcrumbs(); // get last visited pages 156 $crumbs = array_keys($crumbs); // get raw page IDs 157 array_pop($crumbs); // skip current page 158 $referer = array_pop($crumbs); // get current page's predecessor 159 $referer = ($referer) ? $this->dir_prepareID($referer) : ''; 160 161 $this->dir_logAccess($page,$this->dir_getStatus(wikiFN($id)),$referer); 162 } 163} 164 165/** 166 * creates a log file entry and writes it to the log 167 * 168 * This function writes access information of the current page to a log 169 * file. It uses the combined log file format that is also used by the 170 * apache web server. A whole bunch of available log analysers could be 171 * used to visualize the log. 172 * 173 * @param $page page name that was called 174 * @param $status HTTP status code followed by the file size 175 * @param $referer predecessor of $page (which page link to $page) 176 * Is this field empty, the functions tries to get 177 * the referer from the web server (HTTP_REFERER) 178 * 179 * @author Matthias Grimm <matthias.grimm@users.sourceforge.net> 180 * 181 * combined log file format: 182 * <host> <rfc931> <user> [<timestamp>] "<request>" <error> <filesize> 183 * "<referer>" "<agent>"\n 184 * 185 * <host> IP of the client host (we don't do reverse host lookups) 186 * <rfc931> remote user identification or '-' if not available 187 * <user> user id or '-' if not available 188 * <timestamp> time in format [01/Dec/2005:22:19:12 +0200] 189 * <request> Requested protocol, for eg. GET or POST, requested page 190 * and protocol 191 * <error> error code from server, for eg. 200 (OK) or 404 (file 192 * not found) 193 * <filesize> size of the wiki page (only the bare text) 194 * <referer> page that called this one. We don't have this information 195 * and filled the dokuwiki script name in. 196 * <agent> identifying information that the client browser reports 197 * about itself 198 */ 199function dir_logAccess($page,$status,$referer=''){ 200 global $conf; 201 202 if ($this->getConf('hitslog') != ""){ 203 $host = $_SERVER['REMOTE_ADDR']; 204 $user = isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : "-"; 205 $timestamp = date("[d/M/Y:H:i:s O]"); 206 $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : ""; 207 $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : ""; 208 $agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; 209 210 // We have to check if this agent is not banned 211 if ($this->getConf('banned_agents') != "") 212 { 213 $tmp_array_agents_banned = explode(',', $this->getConf('banned_agents')); 214 foreach ($tmp_array_agents_banned as $agents_banned) 215 { 216 if (stristr($agent, $agents_banned) !== false) 217 { 218 return 0; // exit the function, nothing have to be written 219 } 220 } 221 } 222 223 // We have to check if this IP is not banned 224 if ($this->getConf('banned_ip') != "") 225 { 226 $tmp_array_ip_banned = explode(',', $this->getConf('banned_ip')); 227 foreach ($tmp_array_ip_banned as $ip_banned) 228 { 229 //echo $ip_banned . "=" . $host; 230 if (strcmp($host, $ip_banned) == 0) 231 { 232 //echo "Banned: " . $host . "!!!"; 233 return 0; // exit the function, nothing have to be written 234 } 235 } 236 } 237 238 // Banned some users 239 if ($this->getConf('banned_users') != "") 240 { 241 $tmp_array_users_banned = explode(',', $this->getConf('banned_users')); 242 foreach ($tmp_array_users_banned as $users_banned) 243 { 244 //echo $users_banned . "=" . $host; 245 if (strcmp($user, $users_banned) == 0) 246 { 247 //echo "Banned: " . $host . "!!!"; 248 return 0; // exit the function, nothing have to be written 249 } 250 } 251 } 252 253 // Analyzing referer 254 //echo "referrer:" . $referer . "/"; 255 if ($referer == ""){ 256 //echo "referrer: " . $_SERVER['HTTP_REFERER']; 257 if(isset($_SERVER['HTTP_REFERER'])){ 258 $cnt = preg_match('/\?id=((\w+\:*)+)/i',$_SERVER['HTTP_REFERER'], $match); 259 if($cnt == 1) 260 { 261 $referer = $this->dir_prepareID($match[1]); 262 } 263 else 264 { 265 $referer = $_SERVER['HTTP_REFERER']; 266 } 267 } 268 } 269 // NUNO FLORES: Taken out... 270 //$logline = "$host - $user $timestamp \"$method $page $protocol\" $status \"$referer\" \"$agent\"\n"; 271 //io_saveFile(DOKU_INC . $this->getConf('accesslog'), $logline, true); 272 273 // NUNO FLORES: Put in... 274 $hit = "$user>$referer>$page\n"; 275 io_saveFile(DOKU_INC . $this->getConf('hitslog'), $hit, true); 276 277 } 278} 279 280 281} // End of class 282 283