TightURL

TightURL Git Source Tree

Root/tighturl.lib.inc.php

1<?php
2define("TLVERSION", "0.1.4");
3define("TLREQUIRED_PHP_VERSION", "4.3.0");
4error_reporting (E_ALL);
5
6// You REALLY don't want to edit below here unless you know what you're doing.
7
8// *************************************************************************
9
10  if (version_compare(phpversion(), REQUIRED_PHP_VERSION)<0) {
11    die("$svcname Error: TightURL ".VERSION." needs PHP >= ".REQUIRED_PHP_VERSION." (you are using ".phpversion().")");
12  }
13
14
15$validipv4pattern = "/^(http|https|ftp|sftp):\/\/(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.";
16$validipv4pattern .= "(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
17$validipv4pattern .= "\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\/*/";
18
19// ****** !All overridable configuration variables must go above this line! ******
20
21function TightURL_version_check() {
22  global $VUCycle;
23  
24  // check http://tighturl.com/version.php and/or http://tighturl.sf.net/version.php
25  // parse out if there's a security release
26  // notify admin of this tighturl installation once if there's a new version,
27  // once a week, if there's a security fix.
28  // Possibly display "newer version available" on templates.
29  // Possibly disable vulnerable versions after a certain amount of time.
30  // ie, only show "Site down for emergency maintenance. If you are the administrator, click here."
31  // validate against mysql database password, show vulnerability screen.
32
33  if ($VUCycle < 24) $VUCycle = 24; // someone's trying to get banned.
34}
35
36/**
37 * Checks accepted URLs against URI blacklists and marks listed URLs as abused.
38 */
39function TightURL_KillBot($query='') {
40
41  global $dbtable;
42
43  if ($query == "") $query="SELECT * FROM $dbtable;";
44
45  // Query records with status normal, and added within last 2 weeks or records with status normal and more than 7 hits and hit within the last 2 weeks
46  // "SELECT * FROM $dbtable where status=0 && (DATE_SUB(CURDATE(), INTERVAL 14 DAY) <= adddate || (hits > 7 && DATE_SUB(CURDATE(), INTERVAL 14 DAY) <= lasthit)) ORDER BY id;"
47  $set = mysql_query($query);
48  $rows = @mysql_num_rows($set) or $rows = 0;
49
50  for ($i = 0; $i <$rows; $i++) {
51
52    $row = mysql_fetch_array($set);
53    $id = $row["id"];
54    $url = $row["url"];
55    $status = $row["status"];
56    $hits = $row["hits"];
57
58    $hit = URI_on_URIBL($url);
59    if ($hit) {
60      // Change this to disable instead of delete, delete at some future point.
61      $req ="update $dbtable set status=3 where id='$id';";
62      $res = mysql_query($req);
63    }
64// elseif ($hits > 4000) {
65// // Change this to disable instead of delete, delete at some future point.
66// $req ="update $dbtable set status=5 where id='$id';";
67// $res = mysql_query($req);
68// }
69    else {
70      $req = "update $dbtable set lastcheck=NOW(), checkcount=checkcount+1 where id='$id';";
71      $res = mysql_query($req);
72    }
73  }
74}
75
76function TightURL_NewReport($query='') {
77
78  global $dbtable;
79
80  if ($query == "") $query="SELECT * FROM $dbtable;";
81
82  $set = mysql_query($query);
83  $rows = @mysql_num_rows($set) or $rows = 0;
84
85  if ($rows > 0) {
86    $MP = "/usr/sbin/sendmail -t ron@vnetworx.net";
87    $fd = popen($MP, "w");
88    fputs($fd, "To: ron@vnetworx.net\n");
89    fputs($fd, "From: killbot@tighturl.com <killbot@tighturl.com>\n");
90    fputs($fd, "Subject: TightURL additions report\n");
91    fputs($fd, "\n");
92
93    for ($i = 0; $i <$rows; $i++) {
94      $row = mysql_fetch_array($set);
95      $id = $row["id"];
96      $url = $row["url"];
97      fputs($fd, "Block: http://tighturl.com/?p=" . base_convert($id, 10, 36) . " URL: $url\n\n");
98    }
99    pclose($fd);
100  }
101}
102
103/**
104 * Checks to see if a given URI is on a URI blacklist.
105 * Currently this means SURBL (http://www.surbl.org) and URIBL (http://www.uribl.com)
106 *
107 * Returns TRUE if the domain is listed on any configured URIBLs.
108 *
109 * A companion URI extractor must be written for the below issues
110 * Must be changed to do full resolution of redirections on URI, simulating a browser
111 * Must be changed to do IPv6 lookups
112 * Must be changed to check multiple URIs
113 * Must be changed to optionally check HTML entity encoded versions of URIs
114 * Must be changed to handle URIBL's inclusion of some third-level domains.
115 *
116 */
117function URI_on_URIBL($uri) {
118
119// This code does not yet properly implement a correct and efficient querying
120// of URI BL data.
121
122  global $uribl, $uribluri, $validurlpattern, $validipv4pattern, $tltlds, $validschemes;
123
124  $uribls = "";
125
126  if ($uri) {
127    // Test for IPv4 address, reverse the quads if found
128    if (preg_match($validipv4pattern,$uri,$matches)) {
129      $domain=$matches[5] . "." . $matches[4] . "." . $matches[3] . "." . $matches[2];
130    }
131    else {
132      // strip out second-level domain name, *unless* on exception list,
133      // in which case, strip out third level also and test that instead.
134      preg_match("/^".$validschemes.$validurlpattern."$/", $uri, $matches);
135      //preg_match($validurlpattern, $uri, $matches);
136      $domain = $matches[4];
137      if (preg_match("/".$tltlds."$/", $domain, $matches)) {$levels = 2;} else {$levels = 1;}
138      //if (preg_match($tltlds, $domain, $matches)) {$levels = 2;} else {$levels = 1;}
139
140      // klugey stripping routine to reduce domain to base domain name
141      // expect regex wojuld be better
142// (.*\..*){2} matches vnetworx.co.uk but not vnetworx.com
143// .*(\.co\.uk) matches[1] .co.uk
144
145      $ss = countSubstrs($domain, ".");
146      while ($ss > $levels) {
147        $chop = strpos($domain, ".");
148        $domain = substr($domain, $chop + 1);
149        $ss = countSubstrs($domain, ".");
150      }
151    }
152
153    // Query URI blacklists to see if domain/IP appears as target in known spam
154    // or something involved in a malware/phishing attack.
155    for ($i=0; $i<count($uribl); $i++) {
156      $fqdn = $domain . "." . $uribl[$i];
157      $recexists = gethostbyname($fqdn); // ghbn weirdly returns the name on failure
158      if ($recexists != $fqdn) {
159        if ($i > 0) $uribls .= ", ";
160        $uribls .= $uribl[$i];
161      }
162    }
163    if ($uribls) return $uribls; else return FALSE; // change to return an array of indexes into the URIBL array
164  }
165}
166
167/**
168 * Checks to see if a given URL is a Reserved URL.
169 *
170 * Returns TRUE if the ID is listed as a Reserved URL.
171 */
172function on_Reserve($decimal) {
173  global $ReservedURL;
174
175  $res=FALSE;
176
177  if ($decimal) {
178    $sexatrigesimal = base_convert($decimal, 10, 36);
179    for ($i=0; $i<count($ReservedURL); $i++) {
180      if ($sexatrigesimal == strtolower($ReservedURL[$i])) return TRUE;
181    }
182    return FALSE;
183  }
184}
185
186function http_headers ($uri) {
187  array ($headers);
188  // Split URI into host and resource parts
189  $parsed = parse_url($uri);
190
191  if ($parsed[port] == 0) $parsed[port] = 80;
192
193  $connection = fsockopen ($parsed[host], $parsed[port]);
194  if ($connection) {
195    stream_set_timeout($connection, 2);
196    fwrite($connection, "HEAD $parsed[path] HTTP/1.1\r\nHOST: $parsed[host]\r\n\r\n");
197    while (!feof($connection)) {
198      $line_read=fgets($connection);
199      if ($line_read == "") break;
200      $headers[] = $line_read;
201    }
202    fclose ($connection);
203  }
204  return $headers;
205}
206
207// ***************** Non-TightURL-specific functions *********************
208
209/**
210 * sanitize a string for MySQL input
211 */
212if (! function_exists('sanitize_sql_string')) {
213  function sanitize_sql_string($string) {
214    if (get_magic_quotes_gpc()) $string = stripslashes($string);
215    return mysql_escape_string($string);
216  }
217}
218
219/**
220 * Counts the number of times a substring is contained in a given string.
221 */
222if (! function_exists('countSubstrs')) {
223  function countSubstrs($haystack, $needle) {
224    return (($p = strpos($haystack, $needle)) === false) ? 0 : (1 + countSubstrs(substr($haystack, $p+1), $needle));
225  }
226}
227
228// ***************** PHP compatibility functions *********************
229
230/**
231 * Add back get_magic_quotes_gpc() if this is PHP6 or later
232 */
233if (! function_exists('get_magic_quotes_gpc')) {
234    function get_magic_quotes_gpc()
235    {
236        return 0;
237    }
238}
239
240/**
241 * Add in version_compare for PHP < 4.0.7
242 */
243if (! function_exists('version_compare')) {
244  function version_compare($version1, $version2)
245  {
246    $v1 = explode('.', $version1);
247    $v2 = explode('.', $version2);
248   
249    if ($v1[0] > $v2[0]) $ret = 1;
250    elseif ($v1[0] < $v2[0]) $ret = -1;
251    else {
252      // Major version numbers are equal
253      if ($v1[1] > $v2[1]) $ret = 1;
254      elseif ($v1[1] < $v2[1]) $ret = -1;
255      else {
256        // Minor version numbers are equal
257        if ($v1[2] > $v2[2]) $ret = 1;
258        elseif ($v1[2] < $v2[2]) $ret = -1;
259        else $ret = 0;
260      }
261    }
262    return $ret;
263  }
264}
265
266/**
267 * Add in file_get_contents for PHP < 4.3.0
268 */
269if (! function_exists('file_get_contents')) {
270  function file_get_contents($filename, $incpath = false, $resource_context = null)
271  {
272    if (false === $fh = fopen($filename, 'rb', $incpath)) {
273      trigger_error('file_get_contents() failed to open stream: No such file or directory', E_USER_WARNING);
274      return false;
275    }
276    clearstatcache();
277    if ($fsize = @filesize($filename)) $data = fread($fh, $fsize);
278    else {
279      $data = '';
280      while (!feof($fh)) $data .= fread($fh, 8192);
281    }
282    fclose($fh);
283    return $data;
284  }
285}
286
287?>
288

Archive Download this file

Branches