*/ if(!defined('DOKU_INC')) die(); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'action.php'); class action_plugin_dlcount extends DokuWiki_Action_Plugin { const DATADIR = '_media'; // below $conf['metadir'], no trailing slash const SUFFIX = '.meta'; /** * return some info */ function getInfo(){ return confToHash(dirname(__FILE__).'/INFO.txt'); } /* * plugin should use this method to register its handlers with the dokuwiki's event controller */ function register(&$controller) { $controller->register_hook('MEDIA_SENDFILE', 'BEFORE', $this, '_countdl'); $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, '_showcount'); $controller->register_hook('MEDIA_DELETE_FILE', 'AFTER', $this, '_delcounter'); $controller->register_hook('MEDIA_UPLOAD_FINISH', 'BEFORE', $this, '_delcounter2'); } function _delcounter(&$event, $param) { $metafn = $this->metaFnFromFullPath($event->data['path']); if (file_exists($metafn)) @unlink($metafn); } function _delcounter2(&$event, $param) { $metafn = $this->metaFnFromFullPath($event->data[1]); // TODO: Maybe keep counter if updating file ($event->data[4] == 1, i.e. overwrite) if (file_exists($metafn)) @unlink($metafn); } function _showcount(&$event, $param) { global $conf; if (!$this->getConf('show_dlcount') && !$this->getConf('show_filesize')) return; // return if there's nothing to do $html = &$event->data; $matchct = preg_match_all('/\]*>[^\<]*\<\/a\>/', $html, $matches, PREG_OFFSET_CAPTURE|PREG_PATTERN_ORDER); if ($matchct == 0) return; // do nothing $newhtml = ''; $lastoffset = 0; //print_r($matches); die(); foreach ($matches[0] as $i=>$match) { $href = $matches[1][$i][0]; $fn = false; if (strpos($href, 'fetch.php?') !== false) { // no rewrite (http://wiki.birth-online.de/lib/exe/fetch.php?media=software:php:dlcount.tar.gz) $fn = '/' . substr($href, strpos($href, '?media=')+strlen('?media=')); $fn = str_replace(':', '/', $fn); } elseif (strpos($href, 'fetch.php/') !== false) { // no rewrite with useslash (http://wiki.birth-online.de/lib/exe/fetch.php/software/php/dlcount.tar.gz) // THANKS TO: TMH 2009-02-22 via dokuwiki.org $fn = '/' . substr($href, strpos($href, 'fetch.php/')+strlen('fetch.php/')); $fn = str_replace(':', '/', $fn); } else { // rewrite (http://wiki.birth-online.de/_media/software/php/dlcount.tar.gz) $fn = substr($href, strpos($href, '/_media/')+strlen('/_media/')-1); } $metafn = $conf['metadir'] . '/' . self::DATADIR . $fn . self::SUFFIX; $meta = array('dlcount' => 0); $txt = array(); if (file_exists($metafn)) $meta = unserialize(io_readFile($metafn, false)); if ($this->getConf('show_filesize')) $txt['filesize'] = $this->size_translate(filesize($conf['mediadir'] . '/' . $fn)); if ($this->getConf('show_lastmod')) { $fmod = filemtime($conf['mediadir'] . '/' . $fn); $txt['lastmod'] = '' . reset(explode(' ', $this->time_translate(time()-$fmod))) . ' ago'; } if ($this->getConf('show_dlcount')) { if ($meta['dlcount'] != 1) $s = 's'; else $s = ''; $txt['dlcount'] = $meta['dlcount'] . ' download' . $s; if (isset($meta['lastdl'])) $txt['dlcount'] = '' . $txt['dlcount'] . ''; } $txt = ' (' . implode(', ', $txt) . ')'; $afteroffset = $match[1] + strlen($match[0]); $newhtml .= substr($html, $lastoffset, $afteroffset-$lastoffset) . $txt; $lastoffset = $afteroffset; } $newhtml .= substr($html, $lastoffset); $html = $newhtml; } function _countdl(&$event, $param) { if ($event->data['download'] != 1) return; // skip embedded images (we don't want to count these) $metafn = $this->metaFnFromFullPath($event->data['file']); // read metafile $ctr = 0; $meta = array(); if (file_exists($metafn)) { $metastring = io_readFile($metafn, false); $meta = unserialize($metastring); if (isset($meta['dlcount'])) { $ctr = $meta['dlcount']; } } // advance counter $ctr++; // more statistics $meta['lastdl'] = time(); $meta['dlusers'][] = array( 'Time' => time(), 'IP' => $this->getClientIP(), 'Referer' => $_SERVER['HTTP_REFERER'], 'UserAgent' => $_SERVER['HTTP_USER_AGENT'], ); $meta['dlusers'] = array_slice($meta['dlusers'], -50); // only keep last 50 downloaders // output to metafile io_makeFileDir($metafn); $meta['dlcount'] = $ctr; io_saveFile($metafn, serialize($meta)); } /** * Returns the filename of the META file for specified MEDIA file * @global array $conf Global Configuration * @param string $fullpath Path to MEDIA file * @return string Path to META file */ function metaFnFromFullPath($fullpath) { global $conf; $mediadir = realpath($conf['mediadir']); $fn = str_replace($mediadir, '', $fullpath); return $conf['metadir'] . '/' . self::DATADIR . $fn . self::SUFFIX; } /** * Checks for a valid non-127-IP * @param string $ip IP-Address * @return bool TRUE if IP is valid and not localnet, FALSE if invalid or local */ function isValidIP($ip) { $ip = trim($ip); $isvalid = true; $i = split('\.', $ip, 4); $iv = array(); foreach ($i as $key=>$val) { $iv[$key] = intval($val); if (strlen($val)>3 || strlen($val)<=0 || $iv[$key]<0 || $iv[$key]>255) { $isvalid = false; } } if ($iv[0]==0) { $isvalid = false; } if ($iv[0]==127 && $iv[1]==0 && $iv[2]==0 && $iv[3]==1) { $isvalid = false; } return $isvalid; } /** * Returns the IP of the accessing client PC, if possible * @return string|bool The client IP or FALSE on error. */ function getClientIP() { $addr = $_SERVER['HTTP_X_FORWARDED_FOR']; if (!empty($addr) && $this->isValidIP($addr)) return $addr; $addr = $_SERVER['HTTP_CLIENT_IP']; if (!empty($addr) && $this->isValidIP($addr)) return $addr; $addr = $_SERVER['REMOTE_ADDR']; if (!empty($addr) && $this->isValidIP($addr)) return $addr; return false; } // BEGIN: borrowed and modified from http://de3.php.net/manual/en/function.filesize.php function size_translate($filesize) { $array = array( 'TiB' => 1024 * 1024 * 1024 * 1024, 'GiB' => 1024 * 1024 * 1024, 'MiB' => 1024 * 1024, 'KiB' => 1024, ); if($filesize <= 1024) { return $filesize . ' B'; } foreach ($array as $name=>$size) { if($filesize >= $size) { return round((round($filesize / $size * 100) / 100), 2) . ' ' . $name; } } return $filesize; } // END: borrowed and modified from http://de3.php.net/manual/en/function.filesize.php // BEGIN: borrowed and modified from http://de3.php.net/manual/en/function.filesize.php function time_translate($seconds) { $array = array( 'y' => 60 * 60 * 24 * 365.25, 'M' => 60 * 60 * 24 * 30.5, 'w' => 60 * 60 * 24 * 7, 'd' => 60 * 60 * 24, 'h' => 60 * 60, 'm' => 60, 's' => 1, ); foreach ($array as $name=>$secs) { if ($seconds < $secs && $secs != end($array)) continue; $resv = floor($seconds / $secs); $res .= ' ' . $resv . $name; $seconds -= $resv*$secs; } return trim($res); } // END: borrowed and modified from http://de3.php.net/manual/en/function.filesize.php }