ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/BBClone/trunk/lib/marker.php
Revision: 381
Committed: Sat Dec 9 08:46:24 2017 UTC (6 years, 11 months ago) by joku
File size: 13476 byte(s)
Log Message:
 update Copyright

File Contents

# User Rev Content
1 joku 63 <?php
2     /* This file is part of BBClone (A PHP based Web Counter on Steroids)
3     *
4     * SVN FILE $Id$
5     *
6 joku 381 * Copyright (C) 2001-2018, the BBClone Team (see doc/authors.txt for details)
7 joku 63 *
8     * This program is free software: you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation, either version 3 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * See doc/copying.txt for details
19     */
20    
21     ////////////
22     // Marker //
23     ////////////
24    
25     // Main Class Counter
26     class bbc_marker {
27     var $sep, $filename, $ignored, $string;
28    
29     // randomly choose a counter file to write to
30     function bbc_counter_file($cache_path, $counter_pre, $counter_suf) {
31     global $BBC_COUNTER_FILES;
32    
33     mt_srand((double) microtime() * 1000000);
34     return ($cache_path.$counter_pre.mt_rand(0, ($BBC_COUNTER_FILES - 1)).$counter_suf);
35     }
36    
37     function bbc_known_range($addr, $class_a) {
38     // look up whether an address is registerred
39     global $BBC_IP2EXT_PATH;
40    
41     $long = sprintf("%u", ip2long($addr));
42     $file = $BBC_IP2EXT_PATH.$class_a.".inc";
43     $is_valid = false;
44    
45     if (!is_readable($file)) return false;
46    
47     $fp = fopen($file, "rb");
48    
49     while (($range = fgetcsv($fp, 32, "|")) !== false) {
50     if (($long >= $range[1]) && ($long < ($range[1] + $range[2]))) {
51     $is_valid = true;
52     break;
53     }
54     }
55     fclose($fp);
56     return ($is_valid ? true : false);
57     }
58    
59     // validates a hostname or ip address
60     function bbc_valid_ip($addr, $prx = 0) {
61     $iptest = explode(".", $addr);
62     $iptest = defined("_rev") ? array_reverse($iptest) : $iptest;
63     $oct = count($iptest);
64    
65     if ($oct != 4) return false;
66    
67     for ($i = 0; $i < $oct; $i++) {
68     $iptest[$i] = trim($iptest[$i]);
69    
70     if ((!preg_match(":^[0-9]{1,3}$:", $iptest[$i])) || ($iptest[$i] > 255)) return false;
71     }
72    
73     if (($iptest[0] < 1) || ($iptest[0] > 223) || ($iptest[3] < 1) || ($iptest[3] > 254) ||
74     (($prx) && ($this->bbc_known_range($addr, $iptest[0]) === false))) return false;
75    
76     return (defined("_rev") ? implode(".", $iptest) : $addr);
77     }
78    
79     // converts a hexadecimal ip address to the dotted format if applicable
80     function bbc_hex2ip($str) {
81     if (!preg_match(":[a-fA-F0-9]{8}:", $str)) return $str;
82    
83     $arr = explode(".", wordwrap($str, 2, ".", 2));
84    
85     for ($i = 0, $k = count($arr); $i < $k; $i++) $arr[$i] = trim(hexdec($arr[$i]));
86     return ($arr[0].".".$arr[1].".".$arr[2].".".$arr[3]);
87     }
88    
89     // returns the first valid host
90     function bbc_select_host($array) {
91     arsort($array, SORT_NUMERIC);
92    
93     foreach ($array as $key => $val) {
94     $key = $this->bbc_hex2ip(trim($key));
95    
96     if (($prx = $this->bbc_valid_ip($key, 1)) !== false) return $prx;
97     }
98     return false;
99     }
100    
101     // extract the first valid address from a chain
102     function bbc_unchain_addr($val) {
103     if (strpos($val, ",") === false) return $val;
104    
105     $array = explode(",", $val);
106    
107     for ($i = 0, $max = count($array); $i < $max; $i++) $array[$i] = trim($array[$i]);
108     return $this->bbc_select_host(array_flip($array));
109     }
110    
111     // return the correct remote address
112     function bbc_get_remote_addr($addr, $reverse) {
113     $addr = $this->bbc_unchain_addr($addr);
114     $reverse = $this->bbc_unchain_addr($reverse);
115    
116     if ((!empty($reverse)) && ($this->bbc_valid_ip($addr, 1) === false)) return $reverse;
117     elseif (empty($addr)) return "127.0.0.1";
118     else return ((substr($addr, 0, strpos($addr, ".")) == 127) ? "127.0.0.1" : $addr);
119     }
120    
121     // check for client in proxy headers
122     function bbc_parse_headers() {
123     if (_BBC_PHP < 410) global $HTTP_SERVER_VARS;
124    
125     foreach (((_BBC_PHP < 410) ? $HTTP_SERVER_VARS : $_SERVER) as $key => $val) {
126     if (!(substr($key, 0, strpos($key, "_")) == "HTTP")) continue;
127    
128     if ((stristr($val, " for ") !== false)) {
129     $tmp = explode(" for ", strtolower($val));
130     $tmpval = trim($tmp[count($tmp) - 1]);
131     $tmpval = $this->bbc_unchain_addr($tmpval);
132     $chk[$tmpval] = isset($chk[$tmpval]) ? ++$chk[$tmpval] : 1;
133     }
134     if ((strpos($key, "_CLIENT") !== false) || (substr($key, -4) == "_FOR")) {
135     $val = $this->bbc_unchain_addr($val);
136     $chk[$val] = isset($chk[$val]) ? ++$chk[$val] : 1;
137     }
138     // If we find this, the client's ip address needs to be reversed
139     if (($key == "HTTP_VIA") && (preg_match("|Traffic[ \-]?Server/5\.2\.0|i", $val))) {
140     !defined("_rev") ? define("_rev", 1) : "";
141     }
142     }
143     return (!empty($chk) ? $this->bbc_select_host($chk) : false);
144     }
145    
146     // Check if an ip address is matching up against the blacklist
147     function bbc_is_ignored($blacklist, $client) {
148     $ipmatch = (empty($blacklist) ? "" : explode(",", $blacklist));
149    
150     if (empty($ipmatch)) return false;
151    
152     for($i = count($ipmatch) - 1; $i >= 0; $i--) {
153     $test = trim($ipmatch[$i]);
154    
155     if (substr($client, 0, strlen($test)) === $test) return true;
156     }
157     return false;
158     }
159    
160     // checking for matching hosts which we have to ignore. We assume that a
161     // keyword with leading slash implies an uri and everything else a hostname
162     function bbc_ignore_ref($array) {
163     global $BBC_IGNORE_REFER;
164    
165     if (!empty($BBC_IGNORE_REFER)) {
166     foreach(explode(",", $BBC_IGNORE_REFER) as $test) {
167     $test = trim($test);
168     $is_path = ($test[0] == "/") ? true : false;
169    
170     if (stristr(($is_path ? $array[2] : $array[1]), $test) !== false) return true;
171     }
172     }
173     return false;
174     }
175    
176     // checks for a valid url format
177     function bbc_valid_ref($ref) {
178     $tmp = explode(":", $ref);
179    
180     for ($i = 0, $k = count($tmp); $i < $k; $i++) $tmp[$i] = trim($tmp[$i]);
181     return (((($tmp[0] == "http") || ($tmp[0] == "https")) && (substr($tmp[1], 0, 2) == "//")) ? true : false);
182     }
183    
184     //converts a referrer to an array with the hostname, ip address and the full referrer
185     function bbc_parse_ref($ref) {
186     if (!$this->bbc_valid_ref($ref)) return false;
187    
188     // getting rid of stupid user input
189     $ref = str_replace(":/", "://", preg_replace(":/+:", "/", $ref));
190     $ref = preg_replace(":\.+(/|$):", "\\1", $ref);
191     $ref = substr(strstr($ref, "://"), 3);
192    
193     $uri = (($slash = strpos($ref, "/")) !== false) ? substr($ref, $slash) : "/";
194     $host_raw = strtolower((($slash !== false) ? substr($ref, 0, $slash) : $ref));
195     $host = (($port = strpos($host_raw, ":")) !== false) ? substr($host_raw, 0, $port) : $host_raw;
196    
197     return (preg_match("|^[a-zA-Z0-9._\-]{2,64}$|", $host) ? array("http://".$host_raw.$uri, $host, $uri) : false);
198     }
199    
200     // determine and filter stuff which came from the local server
201     function bbc_filter_ref($srvhost, $ref, $srvname, $srvaddr) {
202     $ref_array = $this->bbc_parse_ref($ref);
203    
204     if (is_array($ref_array) && ($this->bbc_ignore_ref($ref_array) !== false)) return "ignored";
205    
206     if (!$ref_array || ($ref_array[1] == $srvaddr) || ($ref_array[1] == $srvname) ||
207     ((substr($ref_array[1], 0, 4) == "127.") || (substr($ref_array[1], 0, 2) == "0.")) ||
208     ((substr($srvname, 0, 4) == "www.") && (substr($srvname, 4) == $ref_array[1])) ||
209     ((substr($ref_array[1], 0, 4) == "www.") && (substr($ref_array[1], 4) == $srvname)) ||
210     (!empty($srvhost) && (($srvhost == $ref_array[1]) ||
211     ((substr($srvhost, 0, 4) == "www.") && (substr($srvhost, 4) == $ref_array[1])) ||
212     ((substr($ref_array[1], 0, 4) == "www.") && (substr($ref_array[1], 4) == $srvhost))))) {
213     return "unknown";
214     }
215     else return $ref_array[0];
216     }
217    
218     // avoid trails of query strings which aren't relevant for page counting
219     function bbc_filter_uri($script, $pinfo, $uri) {
220 matthys 264 global $BBC_USE_ORIGINAL_URI;
221    
222     // check if we should use original uri, else we filter uri by default
223     if ((!empty($BBC_USE_ORIGINAL_URI))) {
224     return $uri;
225     }
226     // filter -> getting rid of stupid user input
227 joku 63 foreach (array("pinfo", "uri") as $path) {
228     ${$path} = str_replace(":/", "://", preg_replace(":/+:", "/", ${$path}));
229     ${$path} = preg_replace(":\.+(/|$):", "\\1", ${$path});
230     }
231    
232     // On some systems path info is just an alias for the script uri
233     $pinfo = ($uri == $pinfo) ? 0 : $pinfo;
234    
235     $uri = !empty($pinfo) ? substr($uri, 0, (strlen($uri) - strlen($pinfo))) : $uri;
236     $uri = (basename($uri) !== $script) ? (((($dir = dirname($uri)) == ".") || (empty($dir))) ? "/" : $dir."/")
237     .$script : $uri;
238    
239     $test = explode(".", $script);
240     $tmp = strtolower(trim($test[0]));
241     $tmp = ((count($test) == 2) && (($tmp == "index") || ($tmp == "default"))) ? true : false;
242    
243     return (($tmp !== false) ? substr($uri, 0, (strrpos($uri, "/") + 1)) : (empty($uri) ? "/" : $uri));
244     }
245    
246     // automatic page name generation in case of not being specified
247     function bbc_auto_page_name($uri) {
248     if (!is_string($uri) || empty($uri) || ($uri == "/")) return "index";
249    
250     $uri = (substr($uri, -1) == "/") ? substr($uri, 1, -1) : ((($dot = strrpos($uri, ".")) !== false) ?
251     substr($uri, 1, --$dot) : substr($uri, 1));
252     $uri = strtr($uri, array("/" => " -&gt; ", "_" => " "));
253    
254     return ucwords($uri);
255     }
256    
257     // write the entry
258     function bbc_write_entry() {
259     global $BBC_CACHE_PATH;
260    
261     $file = $this->filename;
262     $base = basename($file);
263    
264     if (!is_readable($file)) return array($base, "r");
265     if (!is_writable($file)) return array($base, "w");
266    
267     $fp = defined("_BBC_DIO") ? dio_open($file, O_RDWR | O_APPEND) : fopen($file, "ab+");
268    
269     if (defined("_BBC_DIO") && (dio_fcntl($fp, F_SETLK, 1) !== -1)) {
270     dio_write($fp, $this->string);
271     dio_fcntl($fp, F_SETLK, 0);
272    
273     $ok = 1;
274     }
275     else {
276     if (defined("_BBC_SEM") ? ($id = bbc_semlock($file)) : flock($fp, LOCK_EX)) {
277     fputs($fp, $this->string);
278     fflush($fp);
279     defined("_BBC_SEM") ? sem_release($id) : flock($fp, LOCK_UN);
280    
281     $ok = 1;
282     }
283     }
284     defined("_BBC_DIO") ? dio_close($fp) : fclose($fp);
285    
286     return (isset($ok) ? array($base, "o") : array($base, "l"));
287     }
288    
289     // constructor
290     function bbc_marker() {
291     if (_BBC_PHP < 410) global $HTTP_SERVER_VARS;
292    
293     global $BBC_CACHE_PATH, $BBC_COUNTER_PREFIX, $BBC_COUNTER_SUFFIX, $BBC_IGNORE_IP, $BBC_SEP, $BBC_TIMESTAMP,
294     $BBC_TIME_OFFSET, $DOCUMENT_ROOT, $HTTP_HOST, $HTTP_X_REMOTECLIENT_IP, $LOCAL_ADDR, $PATH_INFO,
295     $PHP_SELF, $SCRIPT_FILENAME, $SERVER_NAME;
296    
297     $this->sep = $BBC_SEP;
298     $this->ignored = false;
299     $this->filename = $this->bbc_counter_file($BBC_CACHE_PATH, $BBC_COUNTER_PREFIX, $BBC_COUNTER_SUFFIX);
300    
301     $time = $BBC_TIMESTAMP + ($BBC_TIME_OFFSET * 60);
302    
303     // loads of initialisations
304     $hdr = array("DOCUMENT_ROOT", "HTTP_USER_AGENT", "LOCAL_ADDR", "REMOTE_HOST", "REMOTE_ADDR", "HTTP_HOST",
305     "HTTP_REFERER", "HTTP_X_REMOTECLIENT_IP", "ORIG_PATH_INFO", "ORIG_PATH_TRANSLATED",
306     "ORIG_SCRIPT_FILENAME", "PATH_INFO", "PATH_TRANSLATED", "HTTP_PC_REMOTE_ADDR", "PHP_SELF",
307     "SCRIPT_FILENAME", "SERVER_NAME", "SERVER_ADDR");
308    
309     foreach ($hdr as $str) {
310     $$str = ((_BBC_PHP < 410) ? !empty($HTTP_SERVER_VARS[$str]) : !empty($_SERVER[$str])) ?
311     bbc_clean(((_BBC_PHP < 410) ? $HTTP_SERVER_VARS[$str] : $_SERVER[$str]), $BBC_SEP) : false;
312     }
313    
314     // determine whether we got the "ORIG_" prefix
315     foreach (array("PATH_INFO", "PATH_TRANSLATED", "SCRIPT_FILENAME") as $env) {
316     $$env = !empty(${"ORIG_".$env}) ? ${"ORIG_".$env} : $$env;
317     }
318    
319     $filename = (empty($PATH_TRANSLATED) || ($PATH_TRANSLATED == $DOCUMENT_ROOT)) ? basename($SCRIPT_FILENAME) :
320     basename($PATH_TRANSLATED);
321     $REMOTE_ADDR = ((stristr(PHP_OS, "darwin") !== false) && !empty($HTTP_PC_REMOTE_ADDR)) ? $HTTP_PC_REMOTE_ADDR :
322     $REMOTE_ADDR;
323     $REQUEST_URI = $this->bbc_filter_uri($filename, $PATH_INFO , $PHP_SELF);
324     $SERVER_ADDR = empty($SERVER_ADDR) ? $LOCAL_ADDR : $SERVER_ADDR;
325     $SERVER_ADDR = $this->bbc_valid_ip($SERVER_ADDR) ? $SERVER_ADDR : "127.0.0.1";
326     $HTTP_USER_AGENT = empty($HTTP_USER_AGENT) ? "unknown" : $HTTP_USER_AGENT;
327     $HTTP_REFERER = empty($HTTP_REFERER) ? "unknown" :
328     $this->bbc_filter_ref($HTTP_HOST, $HTTP_REFERER, $SERVER_NAME, $SERVER_ADDR);
329     // Use a page name even if the user didn't specify it
330     $page = defined("_BBC_PAGE_NAME") ? bbc_clean(_BBC_PAGE_NAME, $BBC_SEP) : $this->bbc_auto_page_name($REQUEST_URI);
331     $prx = $this->bbc_parse_headers();
332    
333     if (!empty($prx)) {
334     $prx_addr = $this->bbc_get_remote_addr($REMOTE_ADDR, $HTTP_X_REMOTECLIENT_IP);
335    
336     if (($this->ignored = $this->bbc_is_ignored($BBC_IGNORE_IP, $prx_addr)) !== false) return;
337     else $REMOTE_ADDR = bbc_clean($prx, $BBC_SEP);
338     }
339     else {
340     $prx_addr = "unknown";
341     $REMOTE_ADDR = $this->bbc_get_remote_addr($REMOTE_ADDR, $HTTP_X_REMOTECLIENT_IP);
342     }
343    
344     if (($this->ignored = $this->bbc_is_ignored($BBC_IGNORE_IP, $REMOTE_ADDR)) !== false) return;
345    
346     // "unknown" is meant as a placeholder for the hostname, which will be processed at a different location
347     $this->string = $time.$this->sep.$prx_addr.$this->sep.$REMOTE_ADDR.$this->sep."unknown".$this->sep
348     .$HTTP_USER_AGENT.$this->sep.$HTTP_REFERER.$this->sep.$REQUEST_URI.$this->sep.$page."\n";
349     }
350     }
351 matthys 15 ?>

Properties

Name Value
svn:keywords Id