TightURL

TightURL Commit Details

Date:2009-12-12 03:28:28 (2 years 1 month ago)
Author:Ron Guerin
Branch:master
Commit:d05777481498312b2b148f188006f152a6f44e76
Parents:
Message:Initial Check-in of TightURL 0.1.4 code

Changes:
AABUSE (full)
ACHANGELOG (full)
ADOCUMENTATION (full)
AINSTALL (full)
ALICENSE (full)
ANEWS (full)
AREADME (full)
ATODO (full)
AUPGRADING (full)
Abad-behavior/COPYING (full)
Abad-behavior/README.txt (full)
Abad-behavior/bad-behavior-generic.php (full)
Abad-behavior/bad-behavior-lifetype.php (full)
Abad-behavior/bad-behavior-mediawiki.php (full)
Abad-behavior/bad-behavior-tighturl.php (full)
Abad-behavior/bad-behavior-wordpress-admin.php (full)
Abad-behavior/bad-behavior-wordpress.php (full)
Abad-behavior/bad-behavior/banned.inc.php (full)
Abad-behavior/bad-behavior/blackhole.inc.php (full)
Abad-behavior/bad-behavior/blackhole.inc.php~ (full)
Abad-behavior/bad-behavior/blacklist.inc.php (full)
Abad-behavior/bad-behavior/common_tests.inc.php (full)
Abad-behavior/bad-behavior/core.inc.php (full)
Abad-behavior/bad-behavior/functions.inc.php (full)
Abad-behavior/bad-behavior/google.inc.php (full)
Abad-behavior/bad-behavior/housekeeping.inc.php (full)
Abad-behavior/bad-behavior/index.html
Abad-behavior/bad-behavior/konqueror.inc.php (full)
Abad-behavior/bad-behavior/lynx.inc.php (full)
Abad-behavior/bad-behavior/movabletype.inc.php (full)
Abad-behavior/bad-behavior/mozilla.inc.php (full)
Abad-behavior/bad-behavior/msie.inc.php (full)
Abad-behavior/bad-behavior/msnbot.inc.php (full)
Abad-behavior/bad-behavior/opera.inc.php (full)
Abad-behavior/bad-behavior/post.inc.php (full)
Abad-behavior/bad-behavior/responses.inc.php (full)
Abad-behavior/bad-behavior/safari.inc.php (full)
Abad-behavior/bad-behavior/screener.inc.php (full)
Abad-behavior/bad-behavior/trackback.inc.php (full)
Abad-behavior/bad-behavior/version.inc.php (full)
Abad-behavior/bad-behavior/whitelist.inc.php (full)
Abad-behavior/index.html
Agettext.php (full)
Alocal/tighturl.api.tmpl (full)
Alocal/tighturl.config.inc.php (full)
Alocal/tighturl.faq.tmpl (full)
Alocal/tighturl.main.tmpl (full)
Alocal/tighturl.save.tmpl (full)
Alocal/tighturl.setup.tmpl (full)
Alocal/tighturl.tmpl (full)
Astreams.php (full)
Atighturl-base10 (full)
Atighturl-base10.php (full)
Atighturl-base36 (full)
Atighturl-base36.php (full)
Atighturl-install.php (full)
Atighturl-killbot.php (full)
Atighturl.blacklist.tmpl (full)
Atighturl.blippattern.inc.php (full)
Atighturl.blpattern.inc.php (full)
Atighturl.complaints.tmpl (full)
Atighturl.lib.inc.php (full)
Atighturl.php (full)
Atighturl.policy.tmpl (full)
Atighturl.ptcpattern.inc.php (full)
Atighturl.redirpattern.inc.php (full)
Atighturl.tltpattern.inc.php (full)
Atighturl.urlpattern.inc.php (full)

File differences

ABUSE
1The following attempts to document and explain the anti-abuse system in
2TightURL. Ideally abuse is kept out of the database to begin with, but in
3many cases it must be dealt with afterward.
4
5 1. Rejection of bad bots thanks to Bad Behavior.
6
7 2. Rejection of invalid URLs. Since garbage in the database is abusive
8    to the operator of the TightURL service, we attempt to keep junk out.
9
10 3. Rejection of blacklisted file extensions. Much abuse involves getting
11    someone to run a Windows executable. A set of abused extensions is
12    provided, and can be updated by the site administrator.
13
14 4. Rejection of locally blacklisted sites.
15
16 5. Rejection of URI blacklisted sites.
17
18 6. Rejection of links to known redirector sites.
19
20 7. Re-checking accepted URLs for those who run the "killbot".
CHANGELOG
1v 0.1.3.3a
2October 17, 2008
3----------------
4 Bugfix: TightURL was failing to screen out forbidden extensions such as .exe
5         All users should upgrade to restore this important functionality.
6
7Feature: It is possible, if not necessarily advisable, to activate Policy Ban
8         URLs. ex: http://example.com/?ban=abc
9         This will mark the TightURL http://example.com/abc as banned for
10         violating your site's policy/Terms of Service. This feature is
11         activated by setting $pbi in tighturl.config.inc.php and is intended
12         only to allow administrators a fast and easy way to disable URLs in
13         the database. This feature will be secured in a following release
14         against misuse.
15
16v 0.1.3.3
17September 13, 2008
18------------------
19 Change: A modification has been made to the URL resolver routine to increase
20         PHP version compatibility.
21 Change: Having discovered a new class of Internet abuse, a Pay-To-Click (PTC)
22         blacklist has been added.
23 Change: Missing blacklist handling is more robust in case any are compltely
24         removed.
25 Change: Upgraded to Bad Behavior 2.0.23, which still generates one warning
26         corrected in the version distributed with TightURL.
27
28v 0.1.3.2
29July 26, 2008
30---------------
31 Bugfix: Some incorrect information in UPGRADING that referred to some work
32         in progress on the upcoming major release has been removed and
33         replaced with the correct information.
34 Change: A modification has been made to the URI blacklist lookups to try and
35         work around DNS setups that deliberately falsify returned information
36         when the true response is NXDOMAIN.
37
38v 0.1.3.1
39July 24, 2008
40---------------
41 Bugfix: Some late night last minute packaging errors resulted in an error
42         in the default local blacklist file. This has been corrected.
43 Bugfix: Another slip-up due to the late hour, the installer script creates
44         a database which begins issuing redirection URLs in the ten-thousands
45         instead of zero. This has been corrected.
46
47v 0.1.3
48July 24, 2008
49---------------
50Feature: Optional full Bad Behavior integration into TightURL front-end!
51         http://www.bad-behavior.ioerror.us/
52Feature: Option to require submitted URLs to exist.
53Feature: Resolves all submitted HTTP URLs to the end up to 10 redirects.
54 Bugfix: Strip tags embedded within <title> tags in tighturl.tmpl .
55Feature: New templates for blacklisted URLs, URLs that violate site policy,
56         URLs disabled due to complaints, Greylisted URLs, and previews.
57Feature: tighturl-install.php preliminary web-based installer and
58         upgrade script. Presently allows for either the initial creation of
59         the tables TightURL uses, or upgrades an existing 0.1.2 or earlier
60         database to the current schema.
61Feature: tighturl-killbot shell script partly developed to cut off service to
62         abused URLs. An attempt will be made to piggyback maintenance tasks
63         on top of service requests.
64Feature: TightURL now updates the fields status, lasthit, hits, adddate, addip.
65         These fields were added as necessary for the anti-abuse
66         system. There is no intent to add an ability to view this data
67         for its own sake, however it may later be displayed as part the
68         anti-abuse information in previews.
69Feature: Updatable urlpatterns, two-level domains pattern, redirector patterns.
70         rejecting URIs of other known redirectors.
71Feature: Blacklist domains to refuse to create TightURLs for.
72Feature: TightURL does not accept links to itself; TightURL allows an domain
73         alias to be configured for this purpose. Both the main site and the
74         alias will be recognized with or without a preceeding "www." .
75Feature: Attempt to stop use of TightURL as an obfuscation service by
76         linking to other redirectors.
77Feature: TightURL no longer accepts URLs it can't shorten.
78 Change: TightURL now returns 301 redirects instead of 302
79Feature: Blacklist Windows executables and other file extensions.
80 Change: TightURL no longer contains any OS-specific code, thus Windows
81         support should be transparent now. Reports about TightURL working or
82         not under Windows, BSD, or OS X would be appreciated.
83 Change: Replaced chkdnsrr with gethostbyname, which should work on
84         non-Unix operating systems without a replacement function.
85 Bugfix: URIBL check was slow and worse did not work. Now works and not slow.
86 BugFix: TightURL now accepts the nasty URLs Yahoo uses.
87 Bugfix: Was truncating URLs longer than 256 characters.
88         New limit on URLs is 2083 characters
89 Bugfix: Inconsistency between config.inc.php and tighturl.sql
90         (closes SF bug 1161870)
91 Bugfix: Fix PHP warnings for defined constants. (closes SF bug 1161874)
92
93v 0.1.2
94December 3, 2004
95----------------
96 Bugfix: @ was not considered valid in URLs and should be.
97 Bugfix: Local text about running an experimental service removed from main template.
98 Bugfix: Main template link to TightURL changed from /sourcecode to /project.
99Feature: Reserved IDs, and Regexes moved into tighturl.config.inc.php
100Feature: sample config file and sample templates moved to ./local directory
101Feature: Supports validation of IPv6 URLs. (not supported for URIBL lookups)
102
103v 0.1.1
104December 2, 2004
105----------------
106 Bugfix: Bad tighturl.sql file fixed
107 Bugfix: Empty database issue fixed.
108
109v 0.1
110December 2, 2004
111----------------
112Initial Alpha release.
DOCUMENTATION
1Submitted URLs that are accepted are assigned a sequential Base-36 ID code.
2
3 http://example.com/aa (aa is the Base-36 ID)
4
5This allows for assigning the shortest ID possible.
6
7Duplicate accepted URLs will have the existing ID returned, in preference
8to always assigning the shortest URL possible.
9
10
INSTALL
1                              TightURL
2                            Installation
3                          version 0.1.3.2
4
5  Installing TightURL
6  -------------------
7
8  1. Untar the file: tar zxvf tighturl-0.1.3.2.tar.gz or
9     unzip the file: unzip tighturl-0.1.3.2.zip
10
11  2. Move the files in the directory to where you want to run
12     your installation of TightURL.
13
14  3. Rename tighturl.php to index.php if desired. (highly desirable!)
15
16  4. A. New installations should move the contents of the ./local directory
17        into the main TightURL directory.
18     B. Upgrades should review the contents of ./local and adjust existing
19        config file and templates as seen fit. Things probably won't work
20        correctly unless you modify the tighturl.config.inc in ./local with
21        your desired settings and use that.
22
23  5. New installations should create a MySQL database and user if
24     necessary. If you don't know how, (we were all beginners once) it
25     goes something like this:
26       mysql -u root -p
27       Enter password: **********
28       mysql> create database tighturl;
29       mysql> quit
30
31     If you also need to add a MySQL user (you should never use "root"),
32     then before you quit MySQL, you should enter a command like this:
33
34       mysql> grant all on dbname.* to dbuser@localhost identified by 'pass';
35
36     substituting the name of your database for "dbname", the name of the
37     MySQL user you want to create for "dbuser", and the desired password
38     in place of "pass".
39
40  6. Edit the config settings in tighturl.config.inc.php as needed.
41     New installs will need to change at least the MySQL database settings.
42     See 'Configuration Settings' below.
43
44  7. Run the script: tighturl-install.php
45     When this is done, you will need to remove or rename this script
46     before your TightURL installation will work.
47
48  8. If you can set a custom 404 page for your Web site/directory, you
49     can set it to tighturl/index.php and get shorter URLs. To take
50     advantage of this, set $FOFMethod=TRUE in tighturl.config.inc.php.
51
52  9. Change the $svcname in tighturl.config.inc.php if desired.
53
54 10. Edit the master site HTML template tighturl.tmpl if desired.
55     See 'TightURL Templates' below.
56
57 11. Edit the HTML sub-templates if desired. These are:
58     A. tighturl.main.tmpl : HTML shown for your TightURL homepage
59     B. tighturl.save.tmpl : HTML shown when a URL is saved
60     C. tighturl.help.tmpl : HTML shown for Help info (may not exist yet)
61     D. tighturl.faq.tmpl : HTML shown for FAQ (may not exist yet)
62     D. tighturl.blacklist.tmpl : HTML shown for blacklisted URL submissions
63     D. tighturl.policy.tmpl : HTML shown for URL submissions that violate
64                                   your local policy.
65
66     See 'TightURL Templates' below for more information.
67
68  Configuration Settings
69  ----------------------
70
71  These are the configuration (variables) settings that can and should
72  be changed in tighturl.config.inc.php :
73
74  MySQL:
75    $dbhost : DNS name of your MySQL server
76    $dbuser : MySQL user name
77    $dbpass : password for MySQL user name
78    $dbname : database containing TightURL's table
79    $dbtable : name of TightURL's table
80
81  Operating modes:
82    $FOFMethod : Use 404-Method or mod_rewrite to compress TightURLs
83      0 (FALSE) = full URL path (not compressed) TightURLs
84      1 = 404-Method compressed TightURLs
85      2 = mod_rewrite compressed TightURLs
86
87    URIBL variables:
88      $uribl : Array of URIBLs to check
89      $uriblurl : Array of Web sites corresponding to URIBLs checked
90
91  Text strings and style variables:
92    $svcname : One-word name for your TightURL service
93    $verbtext : One-word name for the act of tightening URLs
94    $pasttext : Past-tense name for a tightended URL
95    $tagline : "tag line" for your TightURL service
96    $headcolor : Color for the TightURL <H1> HTML header
97    $tablecolor : Color for the table the URL input field appears in
98    $copystart : 4-digit year of start of your copyright on your content.
99                  defaults to current year if not given.
100
101  NEVER CHANGE SETTINGS IN tighturl.php OR YOU WILL LOSE YOUR CHANGES
102  any time you upgrade to a newer version of TightURL. Always put your
103  configuration settings in tighturl.config.inc.php where they will
104  survive upgrades. Values in tighturl.config.inc.php override the
105  defaults (garbage) in tinyurl.php .
106
107  Reserved URLs
108  -------------
109
110  Because we use Base-36 numbers as TightURL IDs, as time goes on,
111  certain desirable URLs will be issued that we might want to keep
112  for ourselves.
113
114  For instance, the letters 'faq' are well-understood around the Internet
115  to mean "Frequently Answered Questions". We might want to use the URL
116  http://example.com/faq to point to our FAQ page, rather than issue it
117  as a regular TightURL to a random visitor. Reserved URLs allow you to
118  specify Base-36 IDs that should never be issued as TightURLs.
119
120  There are two kinds of Reserved URLs. External (implicit) and Internal
121  (explicit) Reserved URLs.
122
123    External Reserved URLs:
124
125       Any URL which exists in your Web space will be served up by
126       your Web server, and not TightURL. For this reason, any URL
127       reasonably within your TightURL ID space that you want to use
128       with your TightURL site itself should be reserved so that you
129       don't issue a TightURL to anyone that won't actually work.
130
131       For example, if you have a directory named: /www/example.com/faq
132       your Web server will attempt to serve index.html from within
133       that directory, and TightURL will never even see the request.
134       This kind of reservation is implicit, and TightURL must be
135       made aware of it.
136
137    Internal Reserved URLs:
138
139      Any URL which does not exist in your Web space but is Reserved
140      within TightURL will cause TightURL to look for a correspondingly
141      named TightURL Template, and serve that. If the template does
142      not exist, a 404 error is generated.
143
144      For example, if you have reserved the ID 'faq', and TightURL
145      sees a request for this reserved ID, it will attempt to open a
146      template named tighturl.faq.tmpl and return that to the browser.
147
148  It is VERY IMPORTANT that you decide what your Reserved URLs will be
149  before your TightURL service is put into operation, or else you run
150  the risk of wanting to reserve a URL that's already been issued as
151  a TightURL to someone. For example, by the time you've issued your
152  19826th TightURL, you will have lost the opportunity to use 'faq' as
153  a Reserved URL, because decimal (Base-10) number '19826' is number
154  'faq' in sexigesimal (Base-36).
155
156    Reserving URLs:
157
158      To reserve a URL, add it to the configuration array $ReservedURL .
159      The following URLs are reserved by default:
160
161        faq, help, code, source, docs, cvs, arch, url,
162        about, admin, setup, svn
163
164  There is little point in reserving URLs larger than 5 charcters long.
165  The first 6 character ID is '100000' sexigesimal, which would be far
166  past your 60 millionth TightURL issued. Since each additional Reserved
167  URL adds a little more processing time, you don't want to add URLs
168  that will never be issued anyway.
169
170  TightURL presently uses the ID "api" with the template that describes
171  how to use the TightURL API. It would be the 13878th TightURL in the
172  system, which can easily be achieved on a moderately-used corporate-
173  wide TightURL installation.
174
175  TightURL Templates
176  ------------------
177  TightURL supports a simple variable-substitution templating system with
178  one level of template nesting.
179
180  The outer template is *always* the main site template, tighturl.tmpl .
181  This template controls your site design and is *always* used to generate
182  output pages to the browser.
183
184  The inner template is *always* one of the following sub-templates
185  (or no sub-template):
186    tighturl.main.tmpl : HTML shown for your TightURL homepage
187    tighturl.save.tmpl : HTML shown when a URL is saved
188    tighturl.help.tmpl : HTML shown for Help info (may not exist yet)
189    (none) : No inner template.
190
191  Please note that many screens are generated using only the main site
192  (outer) template. All error screens are generated this way.
193
194  The variables supported by TightURL Templates are:
195
196    $HTML : In the innermost or only template, replaced by a HTML
197                   message from TightURL. In an outer template, it is
198                   replaced by contents of the inner (sub-)template.
199                   You should never remove this variable from a template.
200    $PARM : Parameter when 404-Method not used.
201    $URL : Replaced by browser submitted URL.
202    $URLLEN : Replaced by lenghth of the submitted URL.
203    $TIGHTURL : Replaced by TightURL generated by the submission.
204    $TIGHTURLLEN : Replaced by length of the generated TightURL.
205    $DIFF : Replaced by difference in length between URLs.
206    $INPUT : Replaced by submitted URL for use when there has
207                   been an error detected in the input.
208    $SVCNAME : Replaced by name chosen for your TightURL service.
209    $HEADCOLOR : Replaced by color value chosen for <H1> HTML tags.
210    $TABLECOLOR : Replaced by color value chosen for the table.
211    $TAGLINE : Replaced by "tag line" for your TightURL service.
212    $CPASTTEXT : Replaced by capitalized past tense description of
213                   tightened URLs.
214    $PASTTEXT : Same as $CPASTTEXT, but first letter not capitalized.
215    $CVERBTEXT : Replaced by capitalized verb description of your
216                   TightURL service.
217    $VERBTEXT : Same as $CVERBTEXT, but first letter not capitalized.
218    $COPYRIGHT : Replaced by generated copyright string created from
219                   $copystart config value and current year.
220    $URIBLS : Replaced by HTML showing URIBLs being checked.
221    $HOST : Replaced by hostname of Web site.
222    $SELF : Replaced by the URL path to the TightURL script.
223    $BBSTATS : Replaced by Bad Behavior stats when BB2 is enabled.
224    $TIGHTURLVER : Replaced by the TightURL running version number.
225
226  TightURL Operating Modes
227  ------------------------
228
229  TightURL supports three distinct "operating modes". These are known as
230  "basic", "mod_rewrite", and "404 Method". You want to avoid changing your
231  operating mode later, as changes to or from basic mode will cause all your
232  URLs to change. Changes between mod_rewrite and the 404 Method do not
233  result in changes to your URLs, but your operating mode is something you
234  should choose carefully and then stick with.
235
236    Using basic mode
237    ----------------
238
239    This operating mode produces URLs that follow this pattern:
240    http://example.com/?i=id or http://example.com/yoursite/?i=id
241
242    No changes to httpd.conf or .htaccess are required for basic mode, but
243    this produces slightly longer and more inconvenient to type URLs. If you
244    can use mod_rewrite or the 404 Method, it is highly recommended that you
245    do so.
246
247
248    Using mod_rewrite with Apache
249    -----------------------------
250
251    PLEASE NOTE: There was a longstanding bug in Apache mod_rewrite that
252    probably makes TightURL or anything like it unable to work except with
253    what are still very recent versions of Apache.
254    https://issues.apache.org/bugzilla/show_bug.cgi?id=34602
255
256    Users are encouraged to use "404 Mode", and especially in the event
257    their Apache version has the bug shown above.
258
259
260    This operating mode produces URLs that follow this pattern:
261    http://example.com/id or http://example.com/yoursite/id
262
263    TightURL can be used with mod_rewrite by adding the following lines to
264    httpd.conf or if you can't modify httpd.conf, you can use .htaccess :
265
266    <IfModule mod_rewrite.c>
267      RewriteEngine On
268      RewriteRule ^view/([a-z0-9-]+)/?$ index.php?v=$1 [NC,L]
269      RewriteRule ^([a-z0-9-]+)/?$ index.php?i=$1 [NC,L]
270    </IfModule>
271
272    If you change the parameters (form variables) from "i" for the TightURL ID
273    to look up, and "v" for the TightURL ID to preview, then you'll need to
274    adjust these lines accordingly.
275
276    Be aware that http.conf is read once when the Web server is started or
277    reloaded, but .htaccess must be read and parsed for *every request*, so
278    you always want to use http.conf over .htaccess whenever possible.
279
280
281    Using "The 404-Method" with Apache
282    ----------------------------------
283
284    This operating mode produces URLs that follow this pattern:
285    http://example.com/id or http://example.com/yoursite/id
286
287    The "404-Method" refers to instructing your Web server to direct all
288    requests that generate a "Not found" error (which is an HTTP error code
289    404) to the TightURL script. By doing this, TightURL will run for URLs in
290    your TightURL site that don't exist, such as would be the case for
291    http://example.com/tighturl.php/xxyy
292
293    The xxyy is a TightURL ID number, not an actual Web page in your site. By
294    sending non-existent page requests to the TightURL script, you can look up
295    those IDs and issue an HTTP Redirect without the need for mod_rewrite.
296
297    To use the 404-Method, set $FOFMethod=1 in tighturl.config.inc.php.
298
299      Using .htaccess
300      ---------------
301
302      Then put this in your .htaccess file:
303
304        ErrorDocument 404 /index.php
305
306      This change should take effect immediately after saving .htaccess .
307      If it doesn't work, make sure you have AllowOverride FileInfo on in the
308      directory you're running TightURL from.
309
310      Using httpd.conf
311      ----------------
312
313      Alternatively to using .htaccess (and for improved performance), put the
314      following line in your httpd.conf in the appropriate Directory section
315      (and VirtualHost if applicable):
316
317        ErrorDocument 404 /index.php
318
319      You will need to reload your Apache configuration for this change to take
320      effect.
321
322  See the Apache documentation for more information.
323  http://httpd.apache.org/docs/mod/core.html#errordocument
324  http://httpd.apache.org/docs/mod/core.html#allowoverride
325
326
327  AntiAbuse: Generally if your web site is connected to the Internet and
328  and the TightURL library can make outbound network connections, you should
329  run with the antiabuse system turned on. When the antiabuse system is
330  turned off, virtually everything will be accepted into your database that
331  can be shortened.
332
333  NetChecks: Generally if your web site is connected to the Internet and
334  and the TightURL library can make outbound network connections, you should
335  run with the netchecks system turned on. If your site has no connectivity
336  or ability to make outbound network connections, you should turn the
337  netchecks off. When netchecks are off, TightURL will not be able to resolve
338  URLs through redirections to their final destination, check for new versions
339  of TightURL, or check submitted URLs against URI blacklists.
340
341
342  Adding more URIBLs
343  ------------------
344
345  In the event other URIBLs beside SURBL become available, and you wish
346  to check those also, edit $uribl and $uriblurl in
347  tighturl.config.inc.php .
348
349  To add a new URIBL named uribl.example.com whose Web site is located
350  at http://www.example.com
351
352  Change this:
353
354      $uribl = array("multi.surbl.org");
355      $uriblurl = array("www.surbl.org");
356
357  To this:
358
359      $uribl = array("multi.surbl.org","uribl.example.com");
360      $uriblurl = array("www.surbl.org","www.example.com");
361
362  You can add as many URIBLs as you want this way.
363
364  Squeezing Your Base URL Down to the Smallest Possible Size
365  ----------------------------------------------------------
366  The "base URL" is the fixed portion of your TightURL URLs. This
367  would be everything up to the TightURL ID at the end of the URL.
368  The length of the TightURL ID will start out at 1 character and may
369  get up to 6 characters after tens of millions of TightURLs have been
370  created in your system. (Most TightURL installations are not
371  expected to get into the tens of thousands, let alone tens of
372  millions) Because the ID is at most 6 characters, the most
373  important thing you can do to get the shortest URL possible is to
374  "squeeze" as many characters out of the base portion of the URL
375  as possible.
376
377  The following URL is "unfortunately long", but should still allow
378  you to create tens of millions of TightURLs that can be used without
379  wrapping in most e-mail programs. It is 72 characters long:
380
381  http://www.a-really-quite-long-name.com/~example01/tighturl.php?i=abcdef
382
383  This URL is not only unfortunately long, it is unnecessarily long
384  as well. The following optimizations can be attempted:
385
386  1. Drop the "www."
387  2. Rename tighturl.php to something shorter.
388  3. Rename tighturl.php to index.php and put it in a 1-character subdir.
389
390  If optimizations 1 and 3 are successfully applied, we get a 58
391  character URL (14 characters shorter):
392
393  http://a-really-quite-long-name.com/~example01/t/?i=abcdef
394
395  A more optimistic domain name (39 characters):
396
397  http://example.com/~example/t/?i=abcdef
398
399  Ideal scenario with own domain (29 characters):
400
401  http://tighturl.com/?i=abcdef
402
403  If you are able to use Mod_Rewrite or the 404-Method as shown
404  above, you can also drop the "?i=" portion of the URL, saving
405  another 3 characters.
406
407  Mod_Rewrite or 404-Method scenario (26 characters):
408
409  http://tighturl.com/abcdef
410
411  This also works with the "unfortunately long" URL, bringing
412  it down to 56 characters:
413
414  http://a-really-quite-long-name.com/~example01/t/abcdef
415
416********************************************************************************
LICENSE
1            GNU GENERAL PUBLIC LICENSE
2               Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9                Preamble
10
11  The licenses for most software are designed to take away your
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Library General Public License instead.) You can apply it to
19your programs, too.
20
21  When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in new free programs; and that you know you can do these things.
27
28  To protect your rights, we need to make restrictions that forbid
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33  For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
38
39  We protect your rights with two steps: (1) copyright the software, and
40(2) offer you this license which gives you legal permission to copy,
41distribute and/or modify the software.
42
43  Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50  Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56  The precise terms and conditions for copying, distribution and
57modification follow.
58
59            GNU GENERAL PUBLIC LICENSE
60   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62  0. This License applies to any program or other work which contains
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79  1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you may at your option offer warranty protection in exchange for a fee.
89
90  2. You may modify your copy or copies of the Program or any portion
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, provided that you also meet all of these conditions:
94
95    a) You must cause the modified files to carry prominent notices
96    stating that you changed the files and the date of any change.
97
98    b) You must cause any work that you distribute or publish, that in
99    whole or in part contains or is derived from the Program or any
100    part thereof, to be licensed as a whole at no charge to all third
101    parties under the terms of this License.
102
103    c) If the modified program normally reads commands interactively
104    when run, you must cause it, when started running for such
105    interactive use in the most ordinary way, to print or display an
106    announcement including an appropriate copyright notice and a
107    notice that there is no warranty (or else, saying that you provide
108    a warranty) and that users may redistribute the program under
109    these conditions, and telling the user how to view a copy of this
110    License. (Exception: if the Program itself is interactive but
111    does not normally print such an announcement, your work based on
112    the Program is not required to print an announcement.)
113
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134  3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 1 and 2 above provided that you also do one of the following:
137
138    a) Accompany it with the complete corresponding machine-readable
139    source code, which must be distributed under the terms of Sections
140    1 and 2 above on a medium customarily used for software interchange; or,
141
142    b) Accompany it with a written offer, valid for at least three
143    years, to give any third party, for a charge no more than your
144    cost of physically performing source distribution, a complete
145    machine-readable copy of the corresponding source code, to be
146    distributed under the terms of Sections 1 and 2 above on a medium
147    customarily used for software interchange; or,
148
149    c) Accompany it with the information you received as to the offer
150    to distribute corresponding source code. (This alternative is
151    allowed only for noncommercial distribution and only if you
152    received the program in object code or executable form with such
153    an offer, in accord with Subsection b above.)
154
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172  4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180  5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189  6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197  7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229  8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237  9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250  10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of promoting the sharing and reuse of software generally.
257
258                NO WARRANTY
259
260  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY OF SUCH DAMAGES.
279
280             END OF TERMS AND CONDITIONS
281
282        How to Apply These Terms to Your New Programs
283
284  If you develop a new program, and you want it to be of the greatest
285possible use to the public, the best way to achieve this is to make it
286free software which everyone can redistribute and change under these terms.
287
288  To do so, attach the following notices to the program. It is safest
289to attach them to the start of each source file to most effectively
290convey the exclusion of warranty; and each file should have at least
291the "copyright" line and a pointer to where the full notice is found.
292
293    <one line to give the program's name and a brief idea of what it does.>
294    Copyright (C) <year> <name of author>
295
296    This program is free software; you can redistribute it and/or modify
297    it under the terms of the GNU General Public License as published by
298    the Free Software Foundation; either version 2 of the License, or
299    (at your option) any later version.
300
301    This program is distributed in the hope that it will be useful,
302    but WITHOUT ANY WARRANTY; without even the implied warranty of
303    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304    GNU General Public License for more details.
305
306    You should have received a copy of the GNU General Public License
307    along with this program; if not, write to the Free Software
308    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
309
310
311Also add information on how to contact you by electronic and paper mail.
312
313If the program is interactive, make it output a short notice like this
314when it starts in an interactive mode:
315
316    Gnomovision version 69, Copyright (C) year name of author
317    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318    This is free software, and you are welcome to redistribute it
319    under certain conditions; type `show c' for details.
320
321The hypothetical commands `show w' and `show c' should show the appropriate
322parts of the General Public License. Of course, the commands you use may
323be called something other than `show w' and `show c'; they could even be
324mouse-clicks or menu items--whatever suits your program.
325
326You should also get your employer (if you work as a programmer) or your
327school, if any, to sign a "copyright disclaimer" for the program, if
328necessary. Here is a sample; alter the names:
329
330  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331  `Gnomovision' (which makes passes at compilers) written by James Hacker.
332
333  <signature of Ty Coon>, 1 April 1989
334  Ty Coon, President of Vice
335
336This General Public License does not permit incorporating your program into
337proprietary programs. If your program is a subroutine library, you may
338consider it more useful to permit linking proprietary applications with the
339library. If this is what you want to do, use the GNU Library General
340Public License instead of this License.
NEWS
1NEWS
2====
3
4This is a quick release of the version in use at http://tighturl.com
5due to some user requests and the need to spend more time working on
6the next major release. It contains an all new installer, bugfixes,
7and some important new functionality backported from the development
8version.
9
10There's likely to be some unused templates.
11
12**** First time TightURL users who installed 0.1.3 should delete and
13then recreate their database, then install this version and re-run
14the installer script to avoid generating needlessly large URLs.
15Everyone else should follow the normal instructions.
README
1
2                                TightURL
3                            Version 0.1.3.2
4
5  What is it?
6  -----------
7
8  TightURL is a LAMP-based (Linux Apache MySQL PHP) blind redirection
9  service similar to TinyURL, designed for personal or company use by
10  those who prefer not to use external services, or cannot use them for
11  legal or logistical reasons. It may run correctly on a WAMP server
12  (Windows Apache MySQL PHP), but it is unknown if it does or not.
13
14  The major consideration in the design was the ability to customize
15  the application without altering program code. All browser output
16  except fatal error messages is produced by HTML-based templates.
17
18  A fair amount of customization is possible simply by setting a few
19  configuration variables in the configuration file or editing the
20  included HTML template files. Under no circumstances does the program
21  script file ever have to be edited, unless you're a developer.
22
23  The primary reason for a blind redirection service is to avoid
24  e-mailing URLs to people that are broken when received, because the
25  recipient's e-mail program is unable to pick up the rest of the URL
26  after a line-wrap. It is called a blind redirection service because
27  you can't tell where you'll end up just by looking at the link.
28
29  For the purposes of TightURL, we want to generate the shortest
30  redirection URL possible, thus we use a blind redirection URL, and
31  encourage the use of mod_rewrite or the "404-page Method" to achieve
32  the shortest possible URL.
33
34  Can I use it without getting a special domain for it?
35  -----------------------------------------------------
36  Yes. The requirement for TightURL to be considered useful is the
37  ability is to create a URL that won't wrap in a plain text e-mail
38  message. That means the upper limit is about 72 characters of URL.
39  A worst case scenario looks like this:
40
41  http://www.a-really-quite-long-name.com/~example01/tighturl.php?i=abcdef
42
43  Even this example can actually be made 10 characters shorter in most
44  cases without needing to ask the webmaster for special settings:
45
46  http://www.a-really-quite-long-name.com/~example01/t/?i=abcdef
47
48  See INSTALL for more details on how to "squeeze" your base URL down
49  to the smallest possible size.
50
51  Why was it written?
52  -------------------
53
54  This software was written for the oldest reason in the Free Software
55  book; to scratch an itch. The author had been looking for some
56  Free Software to run his own URL shortening service. Finding no Free
57  Software that fit the bill, and wanting a first PHP project to work
58  on, TightURL was born. Issuing an HTTP Redirect is not exactly
59  rocket science, what the URL shortening service is really providing
60  is convenience and processing resources.
61
62  The software itself can be boiled down to a very few lines if it is
63  hard-wired to its configuration values and output screens. But
64  since the author had been looking for some cookie-cutter software and
65  couldn't find any, he decided to write this so that hopefully no one
66  else will have to. It can be cosmetically tweaked from the config
67  file very easily, and in more depth by editing the HTML templates.
68
69
70  Additional Disclaimer
71  ---------------------
72
73  Original author's code sucks. He is a rank amateur, evertything a
74  professional developer despises. (I wouldn't run code written by me
75  if I were you.)
76
77  Contributing (code) to TightURL
78  -------------------------------
79
80  Patches welcome. Critical advice welcomed if gently given.
81  Access to CVS or Arch possible, please contact maintainer.
82  ron-a-t-vnetworx.net
83
84  The Latest Version
85  ------------------
86
87  Details about the latest stable and development versions are
88  available at the TightURL Web site at http://tighturl.com/ .
89
90  Documentation
91  -------------
92
93  The documentation available as of the date of this release is the
94  contents of this README file. Additional documentation is available
95  at runtime in the browser for using TightURL.
96
97  Requirements
98  ------------
99
100  PHP - Should work with any version >= 4.3.0
101  MySQL - Should work with versions greater than >= 3.x
102
103  Features
104  --------
105
106  * Can create very short URLs using mod_rewrite or the "404 Method"
107  * ID size kept very short by using Base-36 IDs
108  * The same URL entered more than once always returns the same ID
109  * All output is generated by templates.
110  * Site design is controlled by a single template.
111
112  Known Limitations
113  -----------------
114
115  TightURL probably works under Windows with Apache and MySQL, but we
116  have no way of knowing for sure until someone reports they've tested it
117  and it works. One possible problem would be if TightURL can't find
118  nslookup on the PATH. The Windows version uses nslookup as a kluge for
119  missing functionality in PHP for Windows.
120
121  Coming Features
122  ---------------
123
124  Please see the file called TODO.
125
126  Installation
127  ------------
128
129  Please see the file called INSTALL for detailed installation
130  instructions.
131
132  Anti-spam Features
133  ------------------
134
135  A problem with blind redirection services is they can be abused by
136  spammers to conceal the domains their spam is trying to get people to visit.
137  The TightURL Library attempts to screen out other known redirection
138  services, Windows executables, and matches against your local blacklist.
139
140  To keep spammers and phishers from abusing TightURL, it checks the URI
141  blacklists at multi.surbl.org and black.uribl.com . TightURL will refuse to
142  add URLs that appear on these URI BLs. You can add additional URI BLs.
143
144  Licensing
145  ---------
146
147  Please see the file called LICENSE.
148
149  Acknowledgments
150  ----------------
151
152  The TightURL developer(s) acknowledge the following copyrighted works
153  that make up portions of the TightURL software:
154
155  Bad Behavior
TODO
1Bugs:
2=====
3All known bugs in the released versions have been fixed.
4
5API:
6====
7The API has not been implemented, and may not be as it seems to be little
8more than an abuse vector.
UPGRADING
1Upgrading TightURL
2==================
3
4Please note that those using nightly builds of TightURL may end up with cruft
5in their databases. Upgrades are designed to work with released versions.
6
7There have been many additions to the configuration file. You may wish to
8review the sample tighturl.config. You should also compare your templates
9against the ones in this version of TightURL if you've customized your
10templates.
11
12Current users of versions 0.1.3.1
13---------------------------------
14Your database is current. No need to run tighturl-install.php .
15
16Current users of version 0.1.3
17------------------------------
18Users upgrading from the (broken) 0.1.3 release should delete their empty
19database, recreate it, and run tighturl-install.php again.
20
21Current users of versions prior to 0.1.3
22----------------------------------------
23Users upgrading from versions prior to 0.1.3 should run the installer
24script, tighturl-install.php in order to upgrade their database to the latest
25version.
bad-behavior/COPYING
1            GNU GENERAL PUBLIC LICENSE
2               Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9                Preamble
10
11  The licenses for most software are designed to take away your
12freedom to share and change it. By contrast, the GNU General Public
13License is intended to guarantee your freedom to share and change free
14software--to make sure the software is free for all its users. This
15General Public License applies to most of the Free Software
16Foundation's software and to any other program whose authors commit to
17using it. (Some other Free Software Foundation software is covered by
18the GNU Lesser General Public License instead.) You can apply it to
19your programs, too.
20
21  When we speak of free software, we are referring to freedom, not
22price. Our General Public Licenses are designed to make sure that you
23have the freedom to distribute copies of free software (and charge for
24this service if you wish), that you receive source code or can get it
25if you want it, that you can change the software or use pieces of it
26in new free programs; and that you know you can do these things.
27
28  To protect your rights, we need to make restrictions that forbid
29anyone to deny you these rights or to ask you to surrender the rights.
30These restrictions translate to certain responsibilities for you if you
31distribute copies of the software, or if you modify it.
32
33  For example, if you distribute copies of such a program, whether
34gratis or for a fee, you must give the recipients all the rights that
35you have. You must make sure that they, too, receive or can get the
36source code. And you must show them these terms so they know their
37rights.
38
39  We protect your rights with two steps: (1) copyright the software, and
40(2) offer you this license which gives you legal permission to copy,
41distribute and/or modify the software.
42
43  Also, for each author's protection and ours, we want to make certain
44that everyone understands that there is no warranty for this free
45software. If the software is modified by someone else and passed on, we
46want its recipients to know that what they have is not the original, so
47that any problems introduced by others will not reflect on the original
48authors' reputations.
49
50  Finally, any free program is threatened constantly by software
51patents. We wish to avoid the danger that redistributors of a free
52program will individually obtain patent licenses, in effect making the
53program proprietary. To prevent this, we have made it clear that any
54patent must be licensed for everyone's free use or not licensed at all.
55
56  The precise terms and conditions for copying, distribution and
57modification follow.
58
59            GNU GENERAL PUBLIC LICENSE
60   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62  0. This License applies to any program or other work which contains
63a notice placed by the copyright holder saying it may be distributed
64under the terms of this General Public License. The "Program", below,
65refers to any such program or work, and a "work based on the Program"
66means either the Program or any derivative work under copyright law:
67that is to say, a work containing the Program or a portion of it,
68either verbatim or with modifications and/or translated into another
69language. (Hereinafter, translation is included without limitation in
70the term "modification".) Each licensee is addressed as "you".
71
72Activities other than copying, distribution and modification are not
73covered by this License; they are outside its scope. The act of
74running the Program is not restricted, and the output from the Program
75is covered only if its contents constitute a work based on the
76Program (independent of having been made by running the Program).
77Whether that is true depends on what the Program does.
78
79  1. You may copy and distribute verbatim copies of the Program's
80source code as you receive it, in any medium, provided that you
81conspicuously and appropriately publish on each copy an appropriate
82copyright notice and disclaimer of warranty; keep intact all the
83notices that refer to this License and to the absence of any warranty;
84and give any other recipients of the Program a copy of this License
85along with the Program.
86
87You may charge a fee for the physical act of transferring a copy, and
88you may at your option offer warranty protection in exchange for a fee.
89
90  2. You may modify your copy or copies of the Program or any portion
91of it, thus forming a work based on the Program, and copy and
92distribute such modifications or work under the terms of Section 1
93above, provided that you also meet all of these conditions:
94
95    a) You must cause the modified files to carry prominent notices
96    stating that you changed the files and the date of any change.
97
98    b) You must cause any work that you distribute or publish, that in
99    whole or in part contains or is derived from the Program or any
100    part thereof, to be licensed as a whole at no charge to all third
101    parties under the terms of this License.
102
103    c) If the modified program normally reads commands interactively
104    when run, you must cause it, when started running for such
105    interactive use in the most ordinary way, to print or display an
106    announcement including an appropriate copyright notice and a
107    notice that there is no warranty (or else, saying that you provide
108    a warranty) and that users may redistribute the program under
109    these conditions, and telling the user how to view a copy of this
110    License. (Exception: if the Program itself is interactive but
111    does not normally print such an announcement, your work based on
112    the Program is not required to print an announcement.)
113
114These requirements apply to the modified work as a whole. If
115identifiable sections of that work are not derived from the Program,
116and can be reasonably considered independent and separate works in
117themselves, then this License, and its terms, do not apply to those
118sections when you distribute them as separate works. But when you
119distribute the same sections as part of a whole which is a work based
120on the Program, the distribution of the whole must be on the terms of
121this License, whose permissions for other licensees extend to the
122entire whole, and thus to each and every part regardless of who wrote it.
123
124Thus, it is not the intent of this section to claim rights or contest
125your rights to work written entirely by you; rather, the intent is to
126exercise the right to control the distribution of derivative or
127collective works based on the Program.
128
129In addition, mere aggregation of another work not based on the Program
130with the Program (or with a work based on the Program) on a volume of
131a storage or distribution medium does not bring the other work under
132the scope of this License.
133
134  3. You may copy and distribute the Program (or a work based on it,
135under Section 2) in object code or executable form under the terms of
136Sections 1 and 2 above provided that you also do one of the following:
137
138    a) Accompany it with the complete corresponding machine-readable
139    source code, which must be distributed under the terms of Sections
140    1 and 2 above on a medium customarily used for software interchange; or,
141
142    b) Accompany it with a written offer, valid for at least three
143    years, to give any third party, for a charge no more than your
144    cost of physically performing source distribution, a complete
145    machine-readable copy of the corresponding source code, to be
146    distributed under the terms of Sections 1 and 2 above on a medium
147    customarily used for software interchange; or,
148
149    c) Accompany it with the information you received as to the offer
150    to distribute corresponding source code. (This alternative is
151    allowed only for noncommercial distribution and only if you
152    received the program in object code or executable form with such
153    an offer, in accord with Subsection b above.)
154
155The source code for a work means the preferred form of the work for
156making modifications to it. For an executable work, complete source
157code means all the source code for all modules it contains, plus any
158associated interface definition files, plus the scripts used to
159control compilation and installation of the executable. However, as a
160special exception, the source code distributed need not include
161anything that is normally distributed (in either source or binary
162form) with the major components (compiler, kernel, and so on) of the
163operating system on which the executable runs, unless that component
164itself accompanies the executable.
165
166If distribution of executable or object code is made by offering
167access to copy from a designated place, then offering equivalent
168access to copy the source code from the same place counts as
169distribution of the source code, even though third parties are not
170compelled to copy the source along with the object code.
171
172  4. You may not copy, modify, sublicense, or distribute the Program
173except as expressly provided under this License. Any attempt
174otherwise to copy, modify, sublicense or distribute the Program is
175void, and will automatically terminate your rights under this License.
176However, parties who have received copies, or rights, from you under
177this License will not have their licenses terminated so long as such
178parties remain in full compliance.
179
180  5. You are not required to accept this License, since you have not
181signed it. However, nothing else grants you permission to modify or
182distribute the Program or its derivative works. These actions are
183prohibited by law if you do not accept this License. Therefore, by
184modifying or distributing the Program (or any work based on the
185Program), you indicate your acceptance of this License to do so, and
186all its terms and conditions for copying, distributing or modifying
187the Program or works based on it.
188
189  6. Each time you redistribute the Program (or any work based on the
190Program), the recipient automatically receives a license from the
191original licensor to copy, distribute or modify the Program subject to
192these terms and conditions. You may not impose any further
193restrictions on the recipients' exercise of the rights granted herein.
194You are not responsible for enforcing compliance by third parties to
195this License.
196
197  7. If, as a consequence of a court judgment or allegation of patent
198infringement or for any other reason (not limited to patent issues),
199conditions are imposed on you (whether by court order, agreement or
200otherwise) that contradict the conditions of this License, they do not
201excuse you from the conditions of this License. If you cannot
202distribute so as to satisfy simultaneously your obligations under this
203License and any other pertinent obligations, then as a consequence you
204may not distribute the Program at all. For example, if a patent
205license would not permit royalty-free redistribution of the Program by
206all those who receive copies directly or indirectly through you, then
207the only way you could satisfy both it and this License would be to
208refrain entirely from distribution of the Program.
209
210If any portion of this section is held invalid or unenforceable under
211any particular circumstance, the balance of the section is intended to
212apply and the section as a whole is intended to apply in other
213circumstances.
214
215It is not the purpose of this section to induce you to infringe any
216patents or other property right claims or to contest validity of any
217such claims; this section has the sole purpose of protecting the
218integrity of the free software distribution system, which is
219implemented by public license practices. Many people have made
220generous contributions to the wide range of software distributed
221through that system in reliance on consistent application of that
222system; it is up to the author/donor to decide if he or she is willing
223to distribute software through any other system and a licensee cannot
224impose that choice.
225
226This section is intended to make thoroughly clear what is believed to
227be a consequence of the rest of this License.
228
229  8. If the distribution and/or use of the Program is restricted in
230certain countries either by patents or by copyrighted interfaces, the
231original copyright holder who places the Program under this License
232may add an explicit geographical distribution limitation excluding
233those countries, so that distribution is permitted only in or among
234countries not thus excluded. In such case, this License incorporates
235the limitation as if written in the body of this License.
236
237  9. The Free Software Foundation may publish revised and/or new versions
238of the General Public License from time to time. Such new versions will
239be similar in spirit to the present version, but may differ in detail to
240address new problems or concerns.
241
242Each version is given a distinguishing version number. If the Program
243specifies a version number of this License which applies to it and "any
244later version", you have the option of following the terms and conditions
245either of that version or of any later version published by the Free
246Software Foundation. If the Program does not specify a version number of
247this License, you may choose any version ever published by the Free Software
248Foundation.
249
250  10. If you wish to incorporate parts of the Program into other free
251programs whose distribution conditions are different, write to the author
252to ask for permission. For software which is copyrighted by the Free
253Software Foundation, write to the Free Software Foundation; we sometimes
254make exceptions for this. Our decision will be guided by the two goals
255of preserving the free status of all derivatives of our free software and
256of promoting the sharing and reuse of software generally.
257
258                NO WARRANTY
259
260  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268REPAIR OR CORRECTION.
269
270  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278POSSIBILITY OF SUCH DAMAGES.
279
280             END OF TERMS AND CONDITIONS
281
282        How to Apply These Terms to Your New Programs
283
284  If you develop a new program, and you want it to be of the greatest
285possible use to the public, the best way to achieve this is to make it
286free software which everyone can redistribute and change under these terms.
287
288  To do so, attach the following notices to the program. It is safest
289to attach them to the start of each source file to most effectively
290convey the exclusion of warranty; and each file should have at least
291the "copyright" line and a pointer to where the full notice is found.
292
293    <one line to give the program's name and a brief idea of what it does.>
294    Copyright (C) <year> <name of author>
295
296    This program is free software; you can redistribute it and/or modify
297    it under the terms of the GNU General Public License as published by
298    the Free Software Foundation; either version 2 of the License, or
299    (at your option) any later version.
300
301    This program is distributed in the hope that it will be useful,
302    but WITHOUT ANY WARRANTY; without even the implied warranty of
303    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304    GNU General Public License for more details.
305
306    You should have received a copy of the GNU General Public License along
307    with this program; if not, write to the Free Software Foundation, Inc.,
308    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
310Also add information on how to contact you by electronic and paper mail.
311
312If the program is interactive, make it output a short notice like this
313when it starts in an interactive mode:
314
315    Gnomovision version 69, Copyright (C) year name of author
316    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317    This is free software, and you are welcome to redistribute it
318    under certain conditions; type `show c' for details.
319
320The hypothetical commands `show w' and `show c' should show the appropriate
321parts of the General Public License. Of course, the commands you use may
322be called something other than `show w' and `show c'; they could even be
323mouse-clicks or menu items--whatever suits your program.
324
325You should also get your employer (if you work as a programmer) or your
326school, if any, to sign a "copyright disclaimer" for the program, if
327necessary. Here is a sample; alter the names:
328
329  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330  `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332  <signature of Ty Coon>, 1 April 1989
333  Ty Coon, President of Vice
334
335This General Public License does not permit incorporating your program into
336proprietary programs. If your program is a subroutine library, you may
337consider it more useful to permit linking proprietary applications with the
338library. If this is what you want to do, use the GNU Lesser General
339Public License instead of this License.
bad-behavior/README.txt
1=== Bad Behavior ===
2Tags: comment,trackback,referrer,spam,robot,antispam
3Contributors: error, MarkJaquith, Firas, skeltoac
4Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=error%40ioerror%2eus&item_name=Bad%20Behavior%20%28From%20WordPress%20Page%29&no_shipping=1&cn=Comments%20about%20Bad%20Behavior&tax=0&currency_code=USD&bn=PP%2dDonationsBF&charset=UTF%2d8
5Requires at least: 1.2
6Tested up to: 2.7
7Stable tag: 2.0.23
8
9Welcome to a whole new way of keeping your blog, forum, guestbook, wiki or
10content management system free of link spam. Bad Behavior is a PHP-based
11solution for blocking link spam and the robots which deliver it.
12
13Bad Behavior complements other link spam solutions by acting as a gatekeeper,
14preventing spammers from ever delivering their junk, and in many cases, from
15ever reading your site in the first place. This keeps your site's load down,
16makes your site logs cleaner, and can help prevent denial of service
17conditions caused by spammers.
18
19Bad Behavior also transcends other link spam solutions by working in a
20completely different, unique way. Instead of merely looking at the content of
21potential spam, Bad Behavior analyzes the delivery method as well as the
22software the spammer is using. In this way, Bad Behavior can stop spam attacks
23even when nobody has ever seen the particular spam before.
24
25Bad Behavior is designed to work alongside existing spam prevention services
26to increase their effectiveness and efficiency. Whenever possible, you should
27run it in combination with a more traditional spam prevention service.
28
29Bad Behavior works on, or can be adapted to, virtually any PHP-based Web
30software package. Bad Behavior is available natively for WordPress, MediaWiki,
31Drupal, ExpressionEngine, and LifeType, and people have successfully made it
32work with Movable Type, phpBB, and many other packages.
33
34Installing and configuring Bad Behavior on most platforms is simple and takes
35only a few minutes. In most cases, no configuration at all is needed. Simply
36turn it on and stop worrying about spam!
37
38The core of Bad Behavior is free software released under the GNU General
39Public License. (On some non-free platforms, special license terms exist for
40Bad Behavior's platform connector.)
41
42== Installation ==
43
44*Warning*: If you are upgrading from a 1.x.x version of Bad Behavior,
45you must remove it from your system entirely, and delete all of its
46database tables, before installing Bad Behavior 2.0.x. You do not need
47to remove a 2.0.x version of Bad Behavior before upgrading to this
48release.
49
50Bad Behavior has been designed to install on each host software in the
51manner most appropriate to each platform. It's usually sufficient to
52follow the generic instructions for installing any plugin or extension
53for your host software.
54
55On MediaWiki, it is necessary to add a second line to LocalSettings.php
56when installing the extension. Your LocalSettings.php should include
57the following:
58
59` include_once( 'includes/DatabaseFunctions.php' );
60    include( './extensions/Bad-Behavior/bad-behavior-mediawiki.php' );
61
62For complete documentation and installation instructions, please visit
63http://www.bad-behavior.ioerror.us/
64
65== Release Notes ==
66
67= Bad Behavior 2.0 Known Issues =
68
69* Bad Behavior may be unable to protect cached pages on MediaWiki.
70
71* When upgrading from version 2.0.19 or prior on MediaWiki and WordPress,
72you must remove the old version of Bad Behavior from your system manually
73before manually installing the new version. Other platforms are not
74affected by this issue.
75
76* The basic functionality of Bad Behavior on WordPress requires version 1.2
77or later. The management page for WordPress, which allows browsing Bad
78Behavior's logs, requires version 2.1 or later. Users of older versions should
79use phpMyAdmin to browse Bad Behavior's logs, or upgrade WordPress.
80
81* On WordPress when using WordPress Advanced Cache (WP-Cache) or WP-Super
82Cache, Bad Behavior requires a patch to WP-Cache or WP-Super Cache in order to
83protect Cached pages. Bad Behavior cannot protect Super Cached pages.
84
85  Edit the wp-content/plugins/wp-cache/wp-cache-phase1.php or
86wp-content/plugins/wp-super-cache/wp-cache-phase1.php file and find the
87following two lines at around line 34 (line 56 in WP-Super Cache):
88
89` if (! ($meta = unserialize(@file_get_contents($meta_pathname))) )
90        return;`
91
92  Immediately after this, insert the following line:
93
94` require_once( ABSPATH . 'wp-content/plugins/Bad-Behavior/bad-behavior-generic.php');`
95
96  Then visit your site. Everything should work normally, but spammers will
97not be able to access your cached pages either.
98
99* When using Bad Behavior in conjunction with Spam Karma 2, you may see PHP
100warnings when Spam Karma 2 displays its internally generated CAPTCHA. This
101is a design problem in Spam Karma 2. Contact the author of Spam Karma 2 for
102a fix.
bad-behavior/bad-behavior-generic.php
1<?php
2/*
3Bad Behavior - detects and blocks unwanted Web accesses
4Copyright (C) 2005-2006 Michael Hampton
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11As a special exemption, you may link this program with any of the
12programs listed below, regardless of the license terms of those
13programs, and distribute the resulting program, without including the
14source code for such programs: ExpressionEngine
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25Please report any problems to badbots AT ioerror DOT us
26*/
27
28###############################################################################
29###############################################################################
30
31define('BB2_CWD', dirname(__FILE__));
32
33// Settings you can adjust for Bad Behavior.
34// Most of these are unused in non-database mode.
35$bb2_settings_defaults = array(
36    'log_table' => 'bad_behavior',
37    'display_stats' => true,
38    'strict' => false,
39    'verbose' => false,
40    'logging' => true,
41    'httpbl_key' => '',
42    'httpbl_threat' => '25',
43    'httpbl_maxage' => '30',
44);
45
46// Bad Behavior callback functions.
47
48// Return current time in the format preferred by your database.
49function bb2_db_date() {
50    return gmdate('Y-m-d H:i:s'); // Example is MySQL format
51}
52
53// Return affected rows from most recent query.
54function bb2_db_affected_rows() {
55    return false;
56}
57
58// Escape a string for database usage
59function bb2_db_escape($string) {
60    // return mysql_real_escape_string($string);
61    return $string; // No-op when database not in use.
62}
63
64// Return the number of rows in a particular query.
65function bb2_db_num_rows($result) {
66    if ($result !== FALSE)
67        return count($result);
68    return 0;
69}
70
71// Run a query and return the results, if any.
72// Should return FALSE if an error occurred.
73// Bad Behavior will use the return value here in other callbacks.
74function bb2_db_query($query) {
75    return FALSE;
76}
77
78// Return all rows in a particular query.
79// Should contain an array of all rows generated by calling mysql_fetch_assoc()
80// or equivalent and appending the result of each call to an array.
81function bb2_db_rows($result) {
82    return $result;
83}
84
85// Return emergency contact email address.
86function bb2_email() {
87    // return "example@example.com"; // You need to change this.
88    return "badbots@ioerror.us"; // You need to change this.
89}
90
91// retrieve settings from database
92// Settings are hard-coded for non-database use
93function bb2_read_settings() {
94    global $bb2_settings_defaults;
95    return $bb2_settings_defaults;
96}
97
98// write settings to database
99function bb2_write_settings($settings) {
100    return false;
101}
102
103// installation
104function bb2_install() {
105    return false;
106}
107
108// Screener
109// Insert this into the <head> section of your HTML through a template call
110// or whatever is appropriate. This is optional we'll fall back to cookies
111// if you don't use it.
112function bb2_insert_head() {
113    global $bb2_javascript;
114    echo $bb2_javascript;
115}
116
117// Display stats? This is optional.
118function bb2_insert_stats($force = false) {
119    $settings = bb2_read_settings();
120
121    if ($force || $settings['display_stats']) {
122        $blocked = bb2_db_query("SELECT COUNT(*) FROM " . $settings['log_table'] . " WHERE `key` NOT LIKE '00000000'");
123        if ($blocked !== FALSE) {
124            echo sprintf('<p><a href="http://www.bad-behavior.ioerror.us/">%1$s</a> %2$s <strong>%3$s</strong> %4$s</p>', __('Bad Behavior'), __('has blocked'), $blocked[0]["COUNT(*)"], __('access attempts in the last 7 days.'));
125        }
126    }
127}
128
129// Return the top-level relative path of wherever we are (for cookies)
130// You should provide in $url the top-level URL for your site.
131function bb2_relative_path() {
132    //$url = parse_url(get_bloginfo('url'));
133    //return $url['path'] . '/';
134    return '/';
135}
136
137// Calls inward to Bad Behavor itself.
138require_once(BB2_CWD . "/bad-behavior/version.inc.php");
139require_once(BB2_CWD . "/bad-behavior/core.inc.php");
140bb2_install(); // FIXME: see above
141
142bb2_start(bb2_read_settings());
143
144?>
bad-behavior/bad-behavior-lifetype.php
1<?php
2    /*
3    http://blog.markplace.net
4
5    Bad Behavior - LifeType Plugin
6    Copyright (C) 2006 Mark Wu http://blog.markplace.net
7
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 2 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    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21    */
22
23    // This file is the entry point for Bad Behavior in LifeType.
24
25    if (!defined('PLOG_CLASS_PATH')) die('No cheating!');
26
27    // Timer start
28    $bb2_mtime = explode(" ", microtime());
29    $bb2_timer_start = $bb2_mtime[1] + $bb2_mtime[0];
30
31    define('BB2_CWD', PLOG_CLASS_PATH . "plugins/badbehavior/" );
32    define('BB2_EMERGENCY_EMAIL', "admin@yourblog.com" );
33    define('BB2_DEFAULT_LOG_TABLE', "bad_behavior" );
34
35    // Bad Behavior callback functions.
36
37    // Return current time in the format preferred by your database.
38    function bb2_db_date() {
39        return gmdate('Y-m-d H:i:s');
40    }
41
42    // Return affected rows from most recent query.
43    function bb2_db_affected_rows() {
44        lt_include( PLOG_CLASS_PATH."class/database/db.class.php" );
45        $db =& Db::getDb();
46
47        return $db->Affected_Rows();
48    }
49
50    // Escape a string for database usage
51    function bb2_db_escape($string) {
52        lt_include( PLOG_CLASS_PATH."class/database/db.class.php" );
53
54        return Db::qstr($string);
55    }
56
57    // Return the number of rows in a particular query.
58    function bb2_db_num_rows($result) {
59        return $result->RecordCount();
60    }
61
62    // Run a query and return the results, if any.
63    // Should return FALSE if an error occurred.
64    function bb2_db_query($query) {
65        lt_include( PLOG_CLASS_PATH."class/database/db.class.php" );
66        $db =& Db::getDb();
67
68        $result = $db->Execute( $query );
69
70        if (!$result)
71            return FALSE;
72
73        return $result;
74    }
75
76    // Return all rows in a particular query.
77    // Should contain an array of all rows generated by calling mysql_fetch_assoc()
78    // or equivalent and appending the result of each call to an array.
79    function bb2_db_rows($result) {
80        $rows = array();
81        while( $row = $result->FetchRow()) {
82            $rows[] = $row;
83        }
84
85        return $rows;
86    }
87
88    // Return emergency contact email address.
89    function bb2_email() {
90        return BB2_EMERGENCY_EMAIL;
91    }
92
93    // retrieve settings from lifetype config
94    function bb2_read_settings() {
95        lt_include( PLOG_CLASS_PATH."class/database/db.class.php" );
96        lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
97        $config =& Config::getConfig();
98        $prefix = Db::getPrefix();
99        $logTable = $config->getValue( 'bb2_log_table', BB2_DEFAULT_LOG_TABLE );
100        $displayStats = $config->getValue( 'bb2_display_stats', true );
101        $strict = $config->getValue( 'bb2_strict', false );
102        $verbose = $config->getValue( 'bb2_verbose', false );
103        $isInstalled = $config->getValue( 'bb2_installed', false );
104        $logging = $config->getValue( 'bb2_logging', true );
105        $httpbl_key = $config->getValue( 'bb2_httpbl_key', '' );
106        $httpbl_threat = $config->getValue( 'bb2_httpbl_threat', '25' );
107        $httpbl_maxage = $config->getValue( 'bb2_httpbl_maxage', '30' );
108
109        return array('log_table' => $prefix . $logTable,
110                     'display_stats' => $displayStats,
111                     'strict' => $strict,
112                     'verbose' => $verbose,
113                     'logging' => $logging,
114                     'httpbl_key' => $httpbl_key,
115                     'httpbl_threat' => $httpbl_threat,
116                     'httpbl_maxage' => $httpbl_maxage,
117                     'is_installed' => $isInstalled );
118    }
119
120    // write settings to lifetype config
121    function bb2_write_settings($settings) {
122        lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
123        $config =& Config::getConfig();
124        $config->setValue( 'bb2_log_table', BB2_DEFAULT_LOG_TABLE );
125        $config->setValue( 'bb2_display_stats', $settings['display_stats'] );
126        $config->setValue( 'bb2_strict', $settings['strict'] );
127        $config->setValue( 'bb2_verbose', $settings['verbose'] );
128        $config->setValue( 'bb2_httpbl_key', $settings['httpbl_key'] );
129        $config->setValue( 'bb2_httpbl_threat', $settings['httpbl_threat'] );
130        $config->setValue( 'bb2_httpbl_maxage', $settings['httpbl_maxage'] );
131        $config->setValue( 'bb2_installed', $settings['is_installed'] );
132        $config->save();
133    }
134
135    // installation
136    function bb2_install() {
137        $settings = bb2_read_settings();
138        if( $settings['is_installed'] == false && $settings['logging'] )
139        {
140            bb2_db_query(bb2_table_structure($settings['log_table']));
141            $settings['is_installed'] = true;
142            bb2_write_settings( $settings );
143        }
144    }
145
146    // Return the top-level relative path of wherever we are (for cookies)
147    function bb2_relative_path() {
148        lt_include( PLOG_CLASS_PATH."class/config/config.class.php" );
149        $config =& Config::getConfig();
150
151        $url = parse_url( $config->getValue( 'base_url' ) );
152        if( empty($url['path']) )
153            return '/';
154        else {
155            if( substr( $url['path'], -1, 1 ) == '/' )
156                return $url['path'];
157            else
158                return $url['path'] . '/';
159        }
160    }
161
162    // Load Bad Behavior Core
163    lt_include(BB2_CWD . "bad-behavior/core.inc.php");
164    bb2_install();
165    $settings = bb2_read_settings();
166    bb2_start($settings);
167
168    // Time Stop
169    $bb2_mtime = explode(" ", microtime());
170    $bb2_timer_stop = $bb2_mtime[1] + $bb2_mtime[0];
171    $bb2_timer_total = $bb2_timer_stop - $bb2_timer_start;
172?>
bad-behavior/bad-behavior-mediawiki.php
1<?php
2/*
3http://www.bad-behavior.ioerror.us/
4
5Bad Behavior - detects and blocks unwanted Web accesses
6Copyright (C) 2005 Michael Hampton
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 2 of the License, or
11(at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23// This file is the entry point for Bad Behavior.
24
25if (!defined('MEDIAWIKI')) die();
26
27// Settings you can adjust for Bad Behavior.
28$bb2_settings_defaults = array(
29    'log_table' => $wgDBprefix . 'bad_behavior',
30    'display_stats' => true,
31    'strict' => false,
32    'verbose' => false,
33    'logging' => true,
34    'httpbl_key' => '',
35    'httpbl_threat' => '25',
36    'httpbl_maxage' => '30',
37);
38
39define('BB2_CWD', dirname(__FILE__));
40
41// Bad Behavior callback functions.
42
43// Return current time in the format preferred by your database.
44function bb2_db_date() {
45    return gmdate('Y-m-d H:i:s');
46}
47
48// Return affected rows from most recent query.
49function bb2_db_affected_rows($result) {
50    return wfAffectedRows($result);
51}
52
53// Escape a string for database usage
54function bb2_db_escape($string) {
55    // FIXME SECURITY: Get a straight answer from somebody on how MW escapes stuff
56    return addslashes($string);
57}
58
59// Return the number of rows in a particular query.
60function bb2_db_num_rows($result) {
61    return wfNumRows($result);
62}
63
64// Run a query and return the results, if any.
65// Should return FALSE if an error occurred.
66function bb2_db_query($query) {
67    $bb2_last_query = wfQuery($query, DB_WRITE);
68    return $bb2_last_query;
69}
70
71// Return all rows in a particular query.
72// Should contain an array of all rows generated by calling mysql_fetch_assoc()
73// or equivalent and appending the result of each call to an array.
74function bb2_db_rows($result) {
75    $rows = array();
76    while ($row = wfFetchRow($result)) {
77        $rows[] = $row;
78    }
79    return $rows;
80}
81
82// Return emergency contact email address.
83function bb2_email() {
84    global $wgEmergencyContact;
85    return $wgEmergencyContact;
86}
87
88// This Bad Behavior-related function is a stub. You can help MediaWiki by expanding it.
89// retrieve settings from database
90function bb2_read_settings() {
91    global $bb2_settings_defaults;
92    return $bb2_settings_defaults;
93}
94
95// This Bad Behavior-related function is a stub. You can help MediaWiki by expanding it.
96// write settings to database
97function bb2_write_settings($settings) {
98    return;
99}
100
101// In some configurations automatic table creation may fail with the message
102// You must update your load-balancing configuration.
103// You can create the table manually (see query in
104// bad-behavior/database.inc.php) and add this line to your LocalSettings.php:
105//
106// define('BB2_NO_CREATE', true);
107
108// installation
109function bb2_install() {
110    $settings = bb2_read_settings();
111    if (defined('BB2_NO_CREATE')) return;
112    if (!$settings['logging']) return;
113    bb2_db_query(bb2_table_structure($settings['log_table']));
114}
115
116// Return the top-level relative path of wherever we are (for cookies)
117function bb2_relative_path() {
118    // TODO: This might not be the best way, but it seems to work
119    global $wgScript;
120    return dirname($wgScript) . "/";
121}
122
123// Cute timer display
124function bb2_mediawiki_timer(&$parser, &$text) {
125    global $bb2_timer_total;
126    $text = "<!-- Bad Behavior " . BB2_VERSION . " run time: " . number_format(1000 * $bb2_timer_total, 3) . " ms -->" . $text;
127    return true;
128}
129
130function bb2_mediawiki_entry() {
131    global $bb2_timer_total;
132
133    $bb2_mtime = explode(" ", microtime());
134    $bb2_timer_start = $bb2_mtime[1] + $bb2_mtime[0];
135
136    if (php_sapi_name() != 'cli') {
137        require_once(BB2_CWD . "/bad-behavior/core.inc.php");
138        bb2_install(); // FIXME: see above
139        $settings = bb2_read_settings();
140        bb2_start($settings);
141    }
142
143    $bb2_mtime = explode(" ", microtime());
144    $bb2_timer_stop = $bb2_mtime[1] + $bb2_mtime[0];
145    $bb2_timer_total = $bb2_timer_stop - $bb2_timer_start;
146}
147
148require_once(BB2_CWD . "/bad-behavior/version.inc.php");
149$wgExtensionCredits['other'][] = array(
150    'name' => 'Bad Behavior',
151    'version' => BB2_VERSION,
152    'author' => 'Michael Hampton',
153    'description' => 'Detects and blocks unwanted Web accesses',
154    'url' => 'http://www.bad-behavior.ioerror.us/'
155);
156
157#$wgHooks['ParserAfterTidy'][] = 'bb2_mediawiki_timer';
158$wgExtensionFunctions[] = 'bb2_mediawiki_entry';
159
160?>
bad-behavior/bad-behavior-tighturl.php
1<?php
2/*
3Bad Behavior for TightURL - detects and blocks unwanted Web accesses
4Ron Guerin <ron@vnetworx.net>
5
6I wrote almost none of this, but if you're using this file, you should contact
7me (Ron Guerin) and not Michael Hampton, the author of Bad Behavior if you
8have questions about this file or the installation of Bad Behavior that you
9got with TightURL (which has been modified so as to not throw some unneeded
10warnings).
11
12Based on bad-behavior-generic.php
13Copyright (C) 2005-2006 Michael Hampton badbots AT ioerror DOT us
14
15This program is free software; you can redistribute it and/or modify
16it under the terms of the GNU General Public License as published by
17the Free Software Foundation; either version 2 of the License, or
18(at your option) any later version.
19
20This program is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23GNU General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with this program; if not, write to the Free Software
27Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28
29*/
30
31###############################################################################
32###############################################################################
33
34define('BB2_CWD', dirname(__FILE__));
35
36// Settings you can adjust for Bad Behavior.
37// Change these by changing the corresponding TightURL settings in
38// tighturl.config.inc.php instead of editing this file.
39
40$bb2_settings_defaults = array( 'log_table' => $dbtable . '_bb2',
41                                'display_stats' => $BBstats,
42                                'strict' => $BBstrict,
43                                'verbose' => $BBverbose,
44                                'logging' => $BBLogging
45);
46
47// Bad Behavior callback functions.
48
49// Return current time in the format preferred by your database.
50function bb2_db_date() {
51    return gmdate('Y-m-d H:i:s'); // Example is MySQL format
52}
53
54// Return affected rows from most recent query.
55function bb2_db_affected_rows() {
56    return mysql_affected_rows();
57}
58
59// Escape a string for database usage
60function bb2_db_escape($string) {
61    return mysql_real_escape_string($string);
62}
63
64// Return the number of rows in a particular query.
65function bb2_db_num_rows($result) {
66    if ($result !== FALSE) return mysql_num_rows($result);
67    return 0;
68}
69
70// Run a query and return the results, if any.
71// Should return FALSE if an error occurred.
72// Bad Behavior will use the return value here in other callbacks.
73function bb2_db_query($query) {
74    return mysql_query($query);
75}
76
77// Return all rows of a particular query in an array.
78
79function bb2_db_rows($result) {
80    $rows = array();
81    while ($row = mysql_fetch_assoc($result)) {
82        $rows[] = $row;
83    }
84    return $rows;
85}
86
87// Return emergency contact email address.
88function bb2_email() {
89    return $SiteAdminEmail;
90}
91
92// read settings from TightURL
93function bb2_read_settings() {
94    global $bb2_settings_defaults;
95        $settings = $bb2_settings_defaults;
96    return $settings;
97}
98
99// write settings to TightURL
100function bb2_write_settings($settings) {
101    return false;
102}
103
104// installation
105function bb2_install() {
106  return bb2_db_query("CREATE TABLE IF NOT EXISTS `".$settings['log_table']."` (
107        `id` INT(11) NOT NULL auto_increment,
108        `ip` TEXT NOT NULL,
109        `date` DATETIME NOT NULL default '0000-00-00 00:00:00',
110        `request_method` TEXT NOT NULL,
111        `request_uri` TEXT NOT NULL,
112        `server_protocol` TEXT NOT NULL,
113        `http_headers` TEXT NOT NULL,
114        `user_agent` TEXT NOT NULL,
115        `request_entity` TEXT NOT NULL,
116        `key` TEXT NOT NULL,
117        INDEX (`ip`(15)),
118        INDEX (`user_agent`(10)),
119        PRIMARY KEY (`id`))");
120}
121
122// Screener
123// Insert this into the <head> section of your HTML through a template call
124// or whatever is appropriate. This is optional we'll fall back to cookies
125// if you don't use it.
126function bb2_insert_head() {
127    global $bb2_javascript;
128    return $bb2_javascript;
129}
130
131// Display stats
132function bb2_insert_stats($force = false) {
133    $settings = bb2_read_settings();
134
135    if ($force || $settings['display_stats']) {
136        $blocked = bb2_db_query("SELECT COUNT(*) FROM " . $settings['log_table'] . " WHERE `key` NOT LIKE '00000000'");
137        if ($blocked !== FALSE) {
138                    if (! isset($blocked[0]["COUNT(*)"])) {
139                $count = 0;
140            }
141            else {
142                $count = $blocked[0]["COUNT(*)"];
143            }
144            $ret = '<br /><a href="http://www.bad-behavior.ioerror.us/">Bad Behavior</a> has blocked ' . $count . ' access attempt(s) in the last 7 days.';
145        }
146        else {
147            $ret = "";
148        }
149    }
150    return($ret);
151}
152
153// Return the top-level relative path of wherever we are (for cookies)
154// You should provide in $url the top-level URL for your site.
155function bb2_relative_path() {
156        global $self;
157    return $self;
158}
159
160// Calls inward to Bad Behavior itself.
161require_once(BB2_CWD . "/bad-behavior/version.inc.php");
162require_once(BB2_CWD . "/bad-behavior/core.inc.php");
163
164bb2_start(bb2_read_settings());
165
166?>
bad-behavior/bad-behavior-wordpress-admin.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3require_once("bad-behavior/responses.inc.php");
4
5function bb2_admin_pages() {
6    global $wp_db_version;
7
8    if (function_exists('current_user_can')) {
9        // The new 2.x way
10        if (current_user_can('manage_options')) {
11            $bb2_is_admin = true;
12        }
13    } else {
14        // The old 1.x way
15        global $user_ID;
16        if (user_can_edit_user($user_ID, 0)) {
17            $bb2_is_admin = true;
18        }
19    }
20
21    if ($bb2_is_admin) {
22        add_options_page(__("Bad Behavior"), __("Bad Behavior"), 8, 'bb2_options', 'bb2_options');
23        if ($wp_db_version >= 4772) { // Version 2.1 or later
24            add_management_page(__("Bad Behavior"), __("Bad Behavior"), 8, 'bb2_manage', 'bb2_manage');
25        }
26        @session_start();
27    }
28}
29
30function bb2_clean_log_link($uri) {
31    foreach (array("paged", "ip", "key", "blocked", "request_method", "user_agent") as $arg) {
32        $uri = remove_query_arg($arg, $uri);
33    }
34    return $uri;
35}
36
37function bb2_httpbl_lookup($ip) {
38    $engines = array(
39        2 => "Bloglines",
40        5 => "Googlebot",
41        8 => "msnbot",
42        9 => "Yahoo! Slurp",
43    );
44    $settings = bb2_read_settings();
45    $httpbl_key = $settings['httpbl_key'];
46    if (!$httpbl_key) return false;
47
48    $r = $_SESSION['httpbl'][$ip];
49    $d = "";
50    if (!$r) { // Lookup
51        $find = implode('.', array_reverse(explode('.', $ip)));
52        $result = gethostbynamel("${httpbl_key}.${find}.dnsbl.httpbl.org.");
53        if (!empty($result)) {
54            $r = $result[0];
55            $_SESSION['httpbl'][$ip] = $r;
56        }
57    }
58    if ($r) { // Interpret
59        $ip = explode('.', $r);
60        if ($ip[0] == 127) {
61            if ($ip[3] == 0) {
62                if ($engines[$ip[2]]) {
63                    $d .= $engines[$ip[2]];
64                } else {
65                    $d .= "Search engine ${ip[2]}<br/>\n";
66                }
67            }
68            if ($ip[3] & 1) {
69                $d .= "Suspicious<br/>\n";
70            }
71            if ($ip[3] & 2) {
72                $d .= "Harvester<br/>\n";
73            }
74            if ($ip[3] & 4) {
75                $d .= "Comment Spammer<br/>\n";
76            }
77            if ($ip[3] & 7) {
78                $d .= "Threat level ${ip[2]}<br/>\n";
79            }
80            if ($ip[3] > 0) {
81                $d .= "Age ${ip[1]} days<br/>\n";
82            }
83        }
84    }
85    return $d;
86}
87
88function bb2_manage() {
89    global $wpdb;
90
91    $request_uri = $_SERVER["REQUEST_URI"];
92    $settings = bb2_read_settings();
93    $rows_per_page = 100;
94    $where = "";
95
96    // Get query variables desired by the user with input validation
97    $paged = 0 + $_GET['paged']; if (!$paged) $paged = 1;
98    if ($_GET['key']) $where .= "AND `key` = '" . $wpdb->escape($_GET['key']) . "' ";
99    if ($_GET['blocked']) $where .= "AND `key` != '00000000' ";
100    if ($_GET['ip']) $where .= "AND `ip` = '" . $wpdb->escape($_GET['ip']) . "' ";
101    if ($_GET['user_agent']) $where .= "AND `user_agent` = '" . $wpdb->escape($_GET['user_agent']) . "' ";
102    if ($_GET['request_method']) $where .= "AND `request_method` = '" . $wpdb->escape($_GET['request_method']) . "' ";
103
104    // Query the DB based on variables selected
105    $r = bb2_db_query("SELECT COUNT(*) FROM `" . $settings['log_table']);
106    $results = bb2_db_rows($r);
107    $totalcount = $results[0]["COUNT(*)"];
108    $r = bb2_db_query("SELECT COUNT(*) FROM `" . $settings['log_table'] . "` WHERE 1=1 " . $where);
109    $results = bb2_db_rows($r);
110    $count = $results[0]["COUNT(*)"];
111    $pages = ceil($count / 100);
112    $r = bb2_db_query("SELECT * FROM `" . $settings['log_table'] . "` WHERE 1=1 " . $where . "ORDER BY `date` DESC LIMIT " . ($paged - 1) * $rows_per_page . "," . $rows_per_page);
113    $results = bb2_db_rows($r);
114
115    // Display rows to the user
116?>
117<div class="wrap">
118<h2><?php _e("Bad Behavior"); ?></h2>
119<form method="post" action="<?php echo $request_uri; ?>">
120    <p>For more information please visit the <a href="http://www.bad-behavior.ioerror.us/">Bad Behavior</a> homepage.</p>
121    <p>If you find Bad Behavior valuable, please consider making a <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=error%40ioerror%2eus&item_name=Bad%20Behavior%20<?php echo BB2_VERSION; ?>%20%28From%20Admin%29&no_shipping=1&cn=Comments%20about%20Bad%20Behavior&tax=0&currency_code=USD&bn=PP%2dDonationsBF&charset=UTF%2d8">financial contribution</a> to further development of Bad Behavior.</p>
122
123<div class="tablenav">
124<?php
125    $page_links = paginate_links(array('base' => add_query_arg("paged", "%#%"), 'format' => '', 'total' => $pages, 'current' => $paged));
126    if ($page_links) echo "<div class=\"tablenav-pages\">$page_links</div>\n";
127?>
128<div class="alignleft">
129<?php if ($count < $totalcount): ?>
130Displaying <strong><?php echo $count; ?></strong> of <strong><?php echo $totalcount; ?></strong> records filtered by:<br/>
131<?php if ($_GET['key']) echo "Status [<a href=\"" . remove_query_arg(array("paged", "key"), $request_uri) . "\">X</a>] "; ?>
132<?php if ($_GET['blocked']) echo "Blocked [<a href=\"" . remove_query_arg(array("paged", "blocked"), $request_uri) . "\">X</a>] "; ?>
133<?php if ($_GET['ip']) echo "IP [<a href=\"" . remove_query_arg(array("paged", "ip"), $request_uri) . "\">X</a>] "; ?>
134<?php if ($_GET['user_agent']) echo "User Agent [<a href=\"" . remove_query_arg(array("paged", "user_agent"), $request_uri) . "\">X</a>] "; ?>
135<?php if ($_GET['request_method']) echo "GET/POST [<a href=\"" . remove_query_arg(array("paged", "request_method"), $request_uri) . "\">X</a>] "; ?>
136<?php else: ?>
137Displaying all <strong><?php echo $totalcount; ?></strong> records<br/>
138<?php endif; ?>
139<?php if (!$_GET['key'] && !$_GET['blocked']) { ?><a href="<?php echo add_query_arg(array("blocked" => "true", "paged" => false), $request_uri); ?>">Show Blocked</a><?php } ?>
140</div>
141</div>
142
143<table class="widefat">
144    <thead>
145    <tr>
146    <th scope="col" class="check-column"><input type="checkbox" onclick="checkAll(document.getElementById('request-filter'));" /></th>
147    <th scope="col"><?php _e("IP/Date/Status"); ?></th>
148    <th scope="col"><?php _e("Headers"); ?></th>
149    <th scope="col"><?php _e("Entity"); ?></th>
150    </tr>
151    </thead>
152    <tbody>
153<?php
154    $alternate = 0;
155    if ($results) foreach ($results as $result) {
156        $key = bb2_get_response($result["key"]);
157        $alternate++;
158        if ($alternate % 2) {
159            echo "<tr id=\"request-" . $result["id"] . "\" valign=\"top\">\n";
160        } else {
161            echo "<tr id=\"request-" . $result["id"] . "\" class=\"alternate\" valign=\"top\">\n";
162        }
163        echo "<th scope=\"row\" class=\"check-column\"><input type=\"checkbox\" name=\"submit[]\" value=\"" . $result["id"] . "\" /></th>\n";
164        $httpbl = bb2_httpbl_lookup($result["ip"]);
165        echo "<td><a href=\"" . add_query_arg("ip", $result["ip"], remove_query_arg("paged", $request_uri)) . "\">" . $result["ip"] . "</a><br/><br/>\n" . $result["date"] . "<br/><br/><a href=\"" . add_query_arg("key", $result["key"], remove_query_arg(array("paged", "blocked"), $request_uri)) . "\">" . $key["log"] . "</a>\n";
166        if ($httpbl) echo "<br/><br/>http:BL:<br/>$httpbl\n";
167        echo "</td>\n";
168        $headers = str_replace("\n", "<br/>\n", htmlspecialchars($result['http_headers']));
169        if (@strpos($headers, $result['user_agent']) !== FALSE) $headers = substr_replace($headers, "<a href=\"" . add_query_arg("user_agent", rawurlencode($result["user_agent"]), remove_query_arg("paged", $request_uri)) . "\">" . $result['user_agent'] . "</a>", strpos($headers, $result['user_agent']), strlen($result['user_agent']));
170        if (strpos($headers, $result['request_method']) !== FALSE) $headers = substr_replace($headers, "<a href=\"" . add_query_arg("request_method", rawurlencode($result["request_method"]), remove_query_arg("paged", $request_uri)) . "\">" . $result['request_method'] . "</a>", strpos($headers, $result['request_method']), strlen($result['request_method']));
171        echo "<td>$headers</td>\n";
172        echo "<td>" . str_replace("\n", "<br/>\n", htmlspecialchars($result["request_entity"])) . "</td>\n";
173        echo "</tr>\n";
174    }
175?>
176    </tbody>
177</table>
178<div class="tablenav">
179<?php
180    $page_links = paginate_links(array('base' => add_query_arg("paged", "%#%"), 'format' => '', 'total' => $pages, 'current' => $paged));
181    if ($page_links) echo "<div class=\"tablenav-pages\">$page_links</div>\n";
182?>
183<div class="alignleft">
184</div>
185</div>
186</form>
187</div>
188<?php
189}
190
191function bb2_options()
192{
193    $settings = bb2_read_settings();
194
195    if ($_POST) {
196        if ($_POST['display_stats']) {
197            $settings['display_stats'] = true;
198        } else {
199            $settings['display_stats'] = false;
200        }
201        if ($_POST['strict']) {
202            $settings['strict'] = true;
203        } else {
204            $settings['strict'] = false;
205        }
206        if ($_POST['verbose']) {
207            $settings['verbose'] = true;
208        } else {
209            $settings['verbose'] = false;
210        }
211        if ($_POST['logging']) {
212            if ($_POST['logging'] == 'verbose') {
213                $settings['verbose'] = true;
214                $settings['logging'] = true;
215            } else if ($_POST['logging'] == 'normal') {
216                $settings['verbose'] = false;
217                $settings['logging'] = true;
218            } else {
219                $settings['verbose'] = false;
220                $settings['logging'] = false;
221            }
222        } else {
223            $settings['verbose'] = false;
224            $settings['logging'] = false;
225        }
226        if ($_POST['httpbl_key']) {
227            $settings['httpbl_key'] = $_POST['httpbl_key'];
228        } else {
229            $settings['httpbl_key'] = '';
230        }
231        if ($_POST['httpbl_threat']) {
232            $settings['httpbl_threat'] = $_POST['httpbl_threat'];
233        } else {
234            $settings['httpbl_threat'] = '25';
235        }
236        if ($_POST['httpbl_maxage']) {
237            $settings['httpbl_maxage'] = $_POST['httpbl_maxage'];
238        } else {
239            $settings['httpbl_maxage'] = '30';
240        }
241        bb2_write_settings($settings);
242?>
243    <div id="message" class="updated fade"><p><strong><?php _e('Options saved.') ?></strong></p></div>
244<?php
245    }
246?>
247    <div class="wrap">
248    <h2><?php _e("Bad Behavior"); ?></h2>
249    <form method="post" action="<?php echo $_SERVER['REQUEST_URI']; ?>">
250    <p>For more information please visit the <a href="http://www.bad-behavior.ioerror.us/">Bad Behavior</a> homepage.</p>
251    <p>If you find Bad Behavior valuable, please consider making a <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=error%40ioerror%2eus&item_name=Bad%20Behavior%20<?php echo BB2_VERSION; ?>%20%28From%20Admin%29&no_shipping=1&cn=Comments%20about%20Bad%20Behavior&tax=0&currency_code=USD&bn=PP%2dDonationsBF&charset=UTF%2d8">financial contribution</a> to further development of Bad Behavior.</p>
252
253    <h3><?php _e('Statistics'); ?></h3>
254    <?php bb2_insert_stats(true); ?>
255    <table class="form-table">
256    <tr><td><label><input type="checkbox" name="display_stats" value="true" <?php if ($settings['display_stats']) { ?>checked="checked" <?php } ?>/> <?php _e('Display statistics in blog footer'); ?></label></td></tr>
257    </table>
258
259    <h3><?php _e('Logging'); ?></h3>
260    <table class="form-table">
261    <tr><td><label><input type="radio" name="logging" value="verbose" <?php if ($settings['verbose'] && $settings['logging']) { ?>checked="checked" <?php } ?>/> <?php _e('Verbose HTTP request logging'); ?></label></td></tr>
262    <tr><td><label><input type="radio" name="logging" value="normal" <?php if ($settings['logging'] && !$settings['verbose']) { ?>checked="checked" <?php } ?>/> <?php _e('Normal HTTP request logging (recommended)'); ?></label></td></tr>
263    <tr><td><label><input type="radio" name="logging" value="false" <?php if (!$settings['logging']) { ?>checked="checked" <?php } ?>/> <?php _e('Do not log HTTP requests (not recommended)'); ?></label></td></tr>
264    </table>
265
266    <h3><?php _e('Strict Mode'); ?></h3>
267    <table class="form-table">
268    <tr><td><label><input type="checkbox" name="strict" value="true" <?php if ($settings['strict']) { ?>checked="checked" <?php } ?>/> <?php _e('Strict checking (blocks more spam but may block some people)'); ?></label></td></tr>
269    </table>
270
271    <h3><?php _e('http:BL'); ?></h3>
272    <p>To use Bad Behavior's http:BL features you must have an <a href="http://www.projecthoneypot.org/httpbl_configure.php?rf=24694">http:BL Access Key</a>.</p>
273    <table class="form-table">
274    <tr><td><label><input type="text" size="12" maxlength="12" name="httpbl_key" value="<?php echo $settings['httpbl_key']; ?>" /> http:BL Access Key</label></td></tr>
275    <tr><td><label><input type="text" size="3" maxlength="3" name="httpbl_threat" value="<?php echo $settings['httpbl_threat']; ?>" /> Minimum Threat Level (25 is recommended)</label></td></tr>
276    <tr><td><label><input type="text" size="3" maxlength="3" name="httpbl_maxage" value="<?php echo $settings['httpbl_maxage']; ?>" /> Maximum Age of Data (30 is recommended)</label></td></tr>
277    </table>
278
279    <p class="submit"><input class="button" type="submit" name="submit" value="<?php _e('Update &raquo;'); ?>" /></p>
280    </form>
281    </div>
282<?php
283}
284
285add_action('admin_menu', 'bb2_admin_pages');
286
287?>
bad-behavior/bad-behavior-wordpress.php
1<?php
2/*
3Plugin Name: Bad Behavior
4Version: 2.0.23
5Description: Deny automated spambots access to your PHP-based Web site.
6Plugin URI: http://www.bad-behavior.ioerror.us/
7Author: Michael Hampton
8Author URI: http://www.homelandstupidity.us/
9License: GPL
10
11Bad Behavior - detects and blocks unwanted Web accesses
12Copyright (C) 2005 Michael Hampton
13
14This program is free software; you can redistribute it and/or modify
15it under the terms of the GNU General Public License as published by
16the Free Software Foundation; either version 2 of the License, or
17(at your option) any later version.
18
19As a special exemption, you may link this program with any of the
20programs listed below, regardless of the license terms of those
21programs, and distribute the resulting program, without including the
22source code for such programs: ExpressionEngine
23
24This program is distributed in the hope that it will be useful,
25but WITHOUT ANY WARRANTY; without even the implied warranty of
26MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27GNU General Public License for more details.
28
29You should have received a copy of the GNU General Public License
30along with this program; if not, write to the Free Software
31Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32
33Please report any problems to badbots AT ioerror DOT us
34*/
35
36###############################################################################
37###############################################################################
38
39if (!defined('ABSPATH')) die("No cheating!");
40
41$bb2_mtime = explode(" ", microtime());
42$bb2_timer_start = $bb2_mtime[1] + $bb2_mtime[0];
43
44define('BB2_CWD', dirname(__FILE__));
45
46// Bad Behavior callback functions.
47
48// Return current time in the format preferred by your database.
49function bb2_db_date() {
50    return get_gmt_from_date(current_time('mysql'));
51}
52
53// Return affected rows from most recent query.
54function bb2_db_affected_rows() {
55    global $wpdb;
56
57    return $wpdb->rows_affected;
58}
59
60// Escape a string for database usage
61function bb2_db_escape($string) {
62    global $wpdb;
63
64    return $wpdb->escape($string);
65}
66
67// Return the number of rows in a particular query.
68function bb2_db_num_rows($result) {
69    if ($result !== FALSE)
70        return count($result);
71    return 0;
72}
73
74// Run a query and return the results, if any.
75// Should return FALSE if an error occurred.
76// Bad Behavior will use the return value here in other callbacks.
77function bb2_db_query($query) {
78    global $wpdb;
79
80    $wpdb->hide_errors();
81    $result = $wpdb->get_results($query, ARRAY_A);
82    $wpdb->show_errors();
83    if (mysql_error()) {
84        return FALSE;
85    }
86    return $result;
87}
88
89// Return all rows in a particular query.
90// Should contain an array of all rows generated by calling mysql_fetch_assoc()
91// or equivalent and appending the result of each call to an array.
92// For WP this is pretty much a no-op.
93function bb2_db_rows($result) {
94    return $result;
95}
96
97// Return emergency contact email address.
98function bb2_email() {
99    return get_bloginfo('admin_email');
100}
101
102// retrieve settings from database
103function bb2_read_settings() {
104    global $wpdb;
105
106    // Add in default settings when they aren't yet present in WP
107    $settings = get_settings('bad_behavior_settings');
108    if (!$settings) $settings = array();
109    return array_merge(array('log_table' => $wpdb->prefix . 'bad_behavior', 'display_stats' => true, 'strict' => false, 'verbose' => false, 'logging' => true, 'httpbl_key' => '', 'httpbl_threat' => '25', 'httpbl_maxage' => '30',), $settings);
110}
111
112// write settings to database
113function bb2_write_settings($settings) {
114    update_option('bad_behavior_settings', $settings);
115}
116
117// installation
118function bb2_install() {
119    $settings = bb2_read_settings();
120    if (!$settings['logging']) return;
121    bb2_db_query(bb2_table_structure($settings['log_table']));
122}
123
124// Cute timer display; screener
125function bb2_insert_head() {
126    global $bb2_timer_total;
127    global $bb2_javascript;
128    echo "\n<!-- Bad Behavior " . BB2_VERSION . " run time: " . number_format(1000 * $bb2_timer_total, 3) . " ms -->\n";
129    echo $bb2_javascript;
130}
131
132// Display stats?
133function bb2_insert_stats($force = false) {
134    $settings = bb2_read_settings();
135
136    if ($force || $settings['display_stats']) {
137        $blocked = bb2_db_query("SELECT COUNT(*) FROM " . $settings['log_table'] . " WHERE `key` NOT LIKE '00000000'");
138        if ($blocked !== FALSE) {
139            echo sprintf('<p><a href="http://www.bad-behavior.ioerror.us/">%1$s</a> %2$s <strong>%3$s</strong> %4$s</p>', __('Bad Behavior'), __('has blocked'), $blocked[0]["COUNT(*)"], __('access attempts in the last 7 days.'));
140        }
141    }
142}
143
144// Return the top-level relative path of wherever we are (for cookies)
145function bb2_relative_path() {
146    $url = parse_url(get_bloginfo('url'));
147    return $url['path'] . '/';
148}
149
150// FIXME: some sort of hack to run install on 1.5 (and older?) blogs
151// FIXME: figure out what's wrong on 2.0 that this doesn't work
152// register_activation_hook(__FILE__, 'bb2_install');
153//add_action('activate_bb2/bad-behavior-wordpress.php', 'bb2_install');
154add_action('wp_head', 'bb2_insert_head');
155add_action('wp_footer', 'bb2_insert_stats');
156
157// Calls inward to Bad Behavor itself.
158require_once(BB2_CWD . "/bad-behavior/version.inc.php");
159require_once(BB2_CWD . "/bad-behavior/core.inc.php");
160bb2_install(); // FIXME: see above
161
162if (is_admin() || strstr($_SERVER['PHP_SELF'], 'wp-admin/')) { // 1.5 kludge
163    #wp_enqueue_script("admin-forms");
164    require_once(BB2_CWD . "/bad-behavior-wordpress-admin.php");
165}
166
167bb2_start(bb2_read_settings());
168
169$bb2_mtime = explode(" ", microtime());
170$bb2_timer_stop = $bb2_mtime[1] + $bb2_mtime[0];
171$bb2_timer_total = $bb2_timer_stop - $bb2_timer_start;
172
173?>
bad-behavior/bad-behavior/banned.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Functions called when a request has been denied
4// This part can be gawd-awful slow, doesn't matter :)
5
6require_once(BB2_CORE . "/responses.inc.php");
7
8function bb2_display_denial($settings, $key, $previous_key = false)
9{
10    if (!$previous_key) $previous_key = $key;
11    if ($key == "e87553e1") {
12        // FIXME: lookup the real key
13    }
14    // Create support key
15    $ip = explode(".", $_SERVER['REMOTE_ADDR']);
16    $ip_hex = "";
17    foreach ($ip as $octet) {
18        $ip_hex .= str_pad(dechex($octet), 2, 0, STR_PAD_LEFT);
19    }
20    $support_key = implode("-", str_split("$ip_hex$key", 4));
21
22    // Get response data
23    $response = bb2_get_response($previous_key);
24    header("HTTP/1.1 " . $response['response'] . " Bad Behavior");
25    header("Status: " . $response['response'] . " Bad Behavior");
26?>
27<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
28<html xmlns="http://www.w3.org/1999/xhtml">
29<head>
30<title>HTTP Error <?php echo $response['response']; ?></title>
31</head>
32<body>
33<h1>Error <?php echo $response['response']; ?></h1>
34<p>We're sorry, but we could not fulfill your request for
35<?php echo htmlspecialchars($_SERVER['REQUEST_URI']) ?> on this server.</p>
36<p><?php echo $response['explanation']; ?></p>
37<p>Your technical support key is: <strong><?php echo $support_key; ?></strong></p>
38<p>You can use this key to <a href="http://www.ioerror.us/bb2-support-key?key=<?php echo $support_key; ?>">fix this problem yourself</a>.</p>
39<p>If you are unable to fix the problem yourself, please contact <a href="mailto:<?php echo htmlspecialchars(str_replace("@", "+nospam@nospam.", bb2_email())); ?>"><?php echo htmlspecialchars(str_replace("@", " at ", bb2_email())); ?></a> and be sure to provide the technical support key shown above.</p>
40<?php
41}
42
43function bb2_log_denial($settings, $package, $key, $previous_key=false)
44{
45    if (!$settings['logging']) return;
46    bb2_db_query(bb2_insert($settings, $package, $key));
47}
48
49?>
bad-behavior/bad-behavior/blackhole.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Look up address on various blackhole lists.
4// These cannot be used for GET requests under any circumstances!
5function bb2_blackhole($package) {
6    // Only conservative lists
7    $bb2_blackhole_lists = array(
8        "sbl-xbl.spamhaus.org", // All around nasties
9// "dnsbl.sorbs.net", // Old useless data.
10// "list.dsbl.org", // Old useless data.
11// "dnsbl.ioerror.us", // Bad Behavior Blackhole
12    );
13
14    // Things that shouldn't be blocked, from aggregate lists
15    $bb2_blackhole_exceptions = array(
16        "sbl-xbl.spamhaus.org" => array("127.0.0.4"), // CBL is problematic
17        "dnsbl.sorbs.net" => array("127.0.0.10",), // Dynamic IPs only
18        "list.dsbl.org" => array(),
19        "dnsbl.ioerror.us" => array(),
20    );
21
22    // Check the blackhole lists
23    $ip = $package['ip'];
24    $find = implode('.', array_reverse(explode('.', $ip)));
25    foreach ($bb2_blackhole_lists as $dnsbl) {
26        $result = gethostbynamel($find . "." . $dnsbl . ".");
27        if (!empty($result)) {
28            // Got a match and it isn't on the exception list
29            $result = @array_diff($result, $bb2_blackhole_exceptions[$dnsbl]);
30            if (!empty($result)) {
31                return '136673cd';
32            }
33        }
34    }
35    return false;
36}
37
38function bb2_httpbl($settings, $package) {
39    if (!@$settings['httpbl_key']) return false;
40
41    $find = implode('.', array_reverse(explode('.', $package['ip'])));
42    $result = gethostbynamel($settings['httpbl_key'].".${find}.dnsbl.httpbl.org.");
43    if (!empty($result)) {
44        $ip = explode('.', $result[0]);
45        if ($ip[0] == 127 && ($ip[3] & 7) && $ip[2] >= $settings['httpbl_threat'] && $ip[1] >= $settings['httpbl_maxage']) {
46            return '2b021b1f';
47        }
48    }
49    return false;
50}
51?>
bad-behavior/bad-behavior/blackhole.inc.php~
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Look up address on various blackhole lists.
4// These cannot be used for GET requests under any circumstances!
5function bb2_blackhole($package) {
6    // Only conservative lists
7    $bb2_blackhole_lists = array(
8        "sbl-xbl.spamhaus.org", // All around nasties
9// "dnsbl.sorbs.net", // Old useless data.
10// "list.dsbl.org", // Old useless data.
11// "dnsbl.ioerror.us", // Bad Behavior Blackhole
12    );
13
14    // Things that shouldn't be blocked, from aggregate lists
15    $bb2_blackhole_exceptions = array(
16        "sbl-xbl.spamhaus.org" => array("127.0.0.4"), // CBL is problematic
17        "dnsbl.sorbs.net" => array("127.0.0.10",), // Dynamic IPs only
18        "list.dsbl.org" => array(),
19        "dnsbl.ioerror.us" => array(),
20    );
21
22    // Check the blackhole lists
23    $ip = $package['ip'];
24    $find = implode('.', array_reverse(explode('.', $ip)));
25    foreach ($bb2_blackhole_lists as $dnsbl) {
26        $result = gethostbynamel($find . "." . $dnsbl . ".");
27        if (!empty($result)) {
28            // Got a match and it isn't on the exception list
29            $result = @array_diff($result, $bb2_blackhole_exceptions[$dnsbl]);
30            if (!empty($result)) {
31                return '136673cd';
32            }
33        }
34    }
35    return false;
36}
37
38function bb2_httpbl($settings, $package) {
39    if (!$settings['httpbl_key']) return false;
40
41    $find = implode('.', array_reverse(explode('.', $package['ip'])));
42    $result = gethostbynamel($settings['httpbl_key'].".${find}.dnsbl.httpbl.org.");
43    if (!empty($result)) {
44        $ip = explode('.', $result[0]);
45        if ($ip[0] == 127 && ($ip[3] & 7) && $ip[2] >= $settings['httpbl_threat'] && $ip[1] >= $settings['httpbl_maxage']) {
46            return '2b021b1f';
47        }
48    }
49    return false;
50}
51?>
bad-behavior/bad-behavior/blacklist.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3function bb2_blacklist($package) {
4
5    // Blacklisted user agents
6    // These user agent strings occur at the beginning of the line.
7    $bb2_spambots_0 = array(
8        "<sc", // XSS exploit attempts
9        "8484 Boston Project", // video poker/porn spam
10        "adwords", // referrer spam
11        "autoemailspider", // spam harvester
12        "blogsearchbot-martin", // from honeypot
13        "CherryPicker", // spam harvester
14        "core-project/", // FrontPage extension exploits
15        "Diamond", // delivers spyware/adware
16        "Digger", // spam harvester
17        "ecollector", // spam harvester
18        "EmailCollector", // spam harvester
19        "Email Siphon", // spam harvester
20        "EmailSiphon", // spam harvester
21        "grub crawler", // misc comment/email spam
22        "HttpProxy", // misc comment/email spam
23        "Internet Explorer", // XMLRPC exploits seen
24        "ISC Systems iRc", // spam harvester
25        "Jakarta Commons", // custommised spambots
26        "Java 1.", // definitely a spammer
27        "Java/1.", // definitely a spammer
28        "libwww-perl", // spambot scripts
29        "LWP", // spambot scripts
30        "Microsoft URL", // spam harvester
31        "Missigua", // spam harvester
32        "MJ12bot/v1.0.8", // malicious botnet
33        "Movable Type", // customised spambots
34        "Mozilla ", // malicious software
35        "Mozilla/4.0(", // from honeypot
36        "Mozilla/4.0+(", // suspicious harvester
37        "MSIE", // malicious software
38        "NutchCVS", // unidentified robots
39        "Nutscrape/", // misc comment spam
40        "OmniExplorer", // spam harvester
41        "psycheclone", // spam harvester
42        "PussyCat ", // misc comment spam
43        "PycURL", // misc comment spam
44// "Shockwave Flash", // spam harvester
45// WP 2.5 now has Flash; FIXME
46        "Super Happy Fun ", // spam harvester
47        "TrackBack/", // trackback spam
48        "user", // suspicious harvester
49        "User Agent: ", // spam harvester
50        "User-Agent: ", // spam harvester
51        "Winnie Poh", // Automated Coppermine hacks
52        "Wordpress", // malicious software
53        "\"", // malicious software
54    );
55
56    // These user agent strings occur anywhere within the line.
57    $bb2_spambots = array(
58        "\r", // A really dumb bot
59        "; Widows ", // misc comment/email spam
60        "a href=", // referrer spam
61        "Bad Behavior Test", // Add this to your user-agent to test BB
62        "compatible ; MSIE", // misc comment/email spam
63        "compatible-", // misc comment/email spam
64        "DTS Agent", // misc comment/email spam
65        "Email Extractor", // spam harvester
66        "Gecko/25", // revisit this in 500 years
67        "grub-client", // search engine ignores robots.txt
68        "hanzoweb", // very badly behaved crawler
69        "Indy Library", // misc comment/email spam
70        "larbin@unspecified", // stealth harvesters
71        "Murzillo compatible", // comment spam bot
72        ".NET CLR 1)", // free poker, etc.
73        "POE-Component-Client", // free poker, etc.
74        "Turing Machine", // www.anonymizer.com abuse
75        "WebaltBot", // spam harvester
76        "WISEbot", // spam harvester
77        "WISEnutbot", // spam harvester
78        "Windows NT 4.0;)", // wikispam bot
79        "Windows NT 5.0;)", // wikispam bot
80        "Windows NT 5.1;)", // wikispam bot
81        "Windows XP 5", // spam harvester
82        "WordPress/4.01", // pingback spam
83        "\\\\)", // spam harvester
84    );
85
86    // These are regular expression matches.
87    $bb2_spambots_regex = array(
88        "/^[A-Z]{10}$/", // misc email spam
89        "/^Mozilla...[05]$/i", // fake user agent/email spam
90        "/[bcdfghjklmnpqrstvwxz ]{8,}/",
91// "/(;\){1,2}$/", // misc spammers/harvesters
92// "/MSIE.*Windows XP/", // misc comment spam
93    );
94
95    // Do not edit below this line.
96
97    @$ua = $package['headers_mixed']['User-Agent'];
98
99    foreach ($bb2_spambots_0 as $spambot) {
100        $pos = strpos($ua, $spambot);
101        if ($pos !== FALSE && $pos == 0) {
102            return "17f4e8c8";
103        }
104    }
105
106    foreach ($bb2_spambots as $spambot) {
107        if (strpos($ua, $spambot) !== FALSE) {
108            return "17f4e8c8";
109        }
110    }
111
112    foreach ($bb2_spambots_regex as $spambot) {
113        if (preg_match($spambot, $ua)) {
114            return "17f4e8c8";
115        }
116    }
117
118    return FALSE;
119}
120
121?>
bad-behavior/bad-behavior/common_tests.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Enforce adherence to protocol version claimed by user-agent.
4
5function bb2_protocol($settings, $package)
6{
7    // Is it claiming to be HTTP/1.0? Then it shouldn't do HTTP/1.1 things
8    // Always run this test; we should never see Expect:
9    if (array_key_exists('Expect', $package['headers_mixed']) && stripos($package['headers_mixed']['Expect'], "100-continue") !== FALSE) {
10        return "a0105122";
11    }
12
13    // Is it claiming to be HTTP/1.1? Then it shouldn't do HTTP/1.0 things
14    // Blocks some common corporate proxy servers in strict mode
15    if ($settings['strict'] && !strcmp($package['server_protocol'], "HTTP/1.1")) {
16        if (array_key_exists('Pragma', $package['headers_mixed']) && strpos($package['headers_mixed']['Pragma'], "no-cache") !== FALSE && !array_key_exists('Cache-Control', $package['headers_mixed'])) {
17            return "41feed15";
18        }
19    }
20    return false;
21}
22
23function bb2_cookies($settings, $package)
24{
25    // Enforce RFC 2965 sec 3.3.5 and 9.1
26    // Bots wanting new-style cookies should send Cookie2
27    if (strpos($package['headers_mixed']['Cookie'], '$Version=0') !== FALSE && !array_key_exists('Cookie2', $package['headers_mixed'])) {
28        return '6c502ff1';
29    }
30    return false;
31}
32
33function bb2_misc_headers($settings, $package)
34{
35    @$ua = $package['headers_mixed']['User-Agent'];
36
37    if (!strcmp($package['request_method'], "POST") && empty($ua)) {
38        return "f9f2b8b9";
39    }
40
41    // Broken spambots send URLs with various invalid characters
42    // Some broken browsers send the #vector in the referer field :(
43    // if (strpos($package['request_uri'], "#") !== FALSE || strpos($package['headers_mixed']['Referer'], "#") !== FALSE) {
44    if (strpos($package['request_uri'], "#") !== FALSE) {
45        return "dfd9b1ad";
46    }
47
48    // Range: field exists and begins with 0
49    // Real user-agents do not start ranges at 0
50    // NOTE: this blocks the whois.sc bot. No big loss.
51    // Exceptions: MT (not fixable); LJ (refuses to fix; may be
52    // blocked again in the future)
53    if (array_key_exists('Range', $package['headers_mixed']) && strpos($package['headers_mixed']['Range'], "=0-") !== FALSE) {
54        if (strncmp($ua, "MovableType", 11) && strncmp($ua, "URI::Fetch", 10) && strncmp($ua, "php-openid/", 11)) {
55            return "7ad04a8a";
56        }
57    }
58
59    // Content-Range is a response header, not a request header
60    if (array_key_exists('Content-Range', $package['headers_mixed'])) {
61        return '7d12528e';
62    }
63
64    // Lowercase via is used by open proxies/referrer spammers
65    // Exceptions: Clearswift uses lowercase via (refuses to fix;
66    // may be blocked again in the future)
67    if (array_key_exists('via', $package['headers']) &&
68        strpos($package['headers']['via'],'Clearswift') === FALSE) {
69        return "9c9e4979";
70    }
71
72    // pinappleproxy is used by referrer spammers
73    if (array_key_exists('Via', $package['headers_mixed'])) {
74        if (stripos($package['headers_mixed']['Via'], "pinappleproxy") !== FALSE || stripos($package['headers_mixed']['Via'], "PCNETSERVER") !== FALSE || stripos($package['headers_mixed']['Via'], "Invisiware") !== FALSE) {
75            return "939a6fbb";
76        }
77    }
78
79    // TE: if present must have Connection: TE
80    // RFC 2616 14.39
81    // Blocks Microsoft ISA Server 2004 in strict mode. Contact Microsoft
82    // to obtain a hotfix.
83    if ($settings['strict'] && array_key_exists('Te', $package['headers_mixed'])) {
84        if (!preg_match('/\bTE\b/', $package['headers_mixed']['Connection'])) {
85            return "582ec5e4";
86        }
87    }
88
89    if (array_key_exists('Connection', $package['headers_mixed'])) {
90        // Connection: keep-alive and close are mutually exclusive
91        if (preg_match('/\bKeep-Alive\b/i', $package['headers_mixed']['Connection']) && preg_match('/\bClose\b/i', $package['headers_mixed']['Connection'])) {
92            return "a52f0448";
93        }
94        // Close shouldn't appear twice
95        if (preg_match('/\bclose,\s?close\b/i', $package['headers_mixed']['Connection'])) {
96            return "a52f0448";
97        }
98        // Keey-Alive shouldn't appear twice either
99        if (preg_match('/\bkeep-alive,\s?keep-alive\b/i', $package['headers_mixed']['Connection'])) {
100            return "a52f0448";
101        }
102    }
103
104
105    // Headers which are not seen from normal user agents; only malicious bots
106    if (array_key_exists('X-Aaaaaaaaaaaa', $package['headers_mixed']) || array_key_exists('X-Aaaaaaaaaa', $package['headers_mixed'])) {
107        return "b9cc1d86";
108    }
109    // Proxy-Connection does not exist and should never be seen in the wild
110    if (array_key_exists('Proxy-Connection', $package['headers_mixed'])) {
111        return "b7830251";
112    }
113
114    if (array_key_exists('Referer', $package['headers_mixed'])) {
115        // Referer, if it exists, must not be blank
116        if (empty($package['headers_mixed'])) {
117            return "69920ee5";
118        }
119
120        // Referer, if it exists, must contain a :
121        // While a relative URL is technically valid in Referer, all known
122        // legit user-agents send an absolute URL
123        if (strpos($package['headers_mixed']['Referer'], ":") === FALSE) {
124            return "45b35e30";
125        }
126    }
127
128    // "uk" is not a language (ISO 639) nor a country (ISO 3166)
129    // oops, yes it is :( Please shoot any Ukrainian spammers you see.
130# if (preg_match('/\buk\b/', $package['headers_mixed']['Accept-Language'])) {
131# return "35ea7ffa";
132# }
133
134    return false;
135}
136
137?>
bad-behavior/bad-behavior/core.inc.php
1<?php if (!defined('BB2_CWD')) die("I said no cheating!");
2
3// Bad Behavior entry point is start_bad_behavior().
4// If you're reading this, you are probably lost.
5// Go read the bad-behavior-generic.php file.
6
7define('BB2_CORE', dirname(__FILE__));
8define('BB2_COOKIE', 'bb2_screener_');
9
10require_once(BB2_CORE . "/functions.inc.php");
11
12// Our log table structure
13function bb2_table_structure($name)
14{
15    // It's not paranoia if they really are out to get you.
16    $name_escaped = bb2_db_escape($name);
17    return "CREATE TABLE IF NOT EXISTS `$name_escaped` (
18        `id` INT(11) NOT NULL auto_increment,
19        `ip` TEXT NOT NULL,
20        `date` DATETIME NOT NULL default '0000-00-00 00:00:00',
21        `request_method` TEXT NOT NULL,
22        `request_uri` TEXT NOT NULL,
23        `server_protocol` TEXT NOT NULL,
24        `http_headers` TEXT NOT NULL,
25        `user_agent` TEXT NOT NULL,
26        `request_entity` TEXT NOT NULL,
27        `key` TEXT NOT NULL,
28        INDEX (`ip`(15)),
29        INDEX (`user_agent`(10)),
30        PRIMARY KEY (`id`) );"; // TODO: INDEX might need tuning
31}
32
33// Insert a new record
34function bb2_insert($settings, $package, $key)
35{
36    $ip = bb2_db_escape($package['ip']);
37    $date = bb2_db_date();
38    $request_method = bb2_db_escape($package['request_method']);
39    $request_uri = bb2_db_escape($package['request_uri']);
40    $server_protocol = bb2_db_escape($package['server_protocol']);
41    $user_agent = bb2_db_escape($package['user_agent']);
42    $headers = "$request_method $request_uri $server_protocol\n";
43    foreach ($package['headers'] as $h => $v) {
44        $headers .= bb2_db_escape("$h: $v\n");
45    }
46    $request_entity = "";
47    if (!strcasecmp($request_method, "POST")) {
48        foreach ($package['request_entity'] as $h => $v) {
49            $request_entity .= bb2_db_escape("$h: $v\n");
50        }
51    }
52    return "INSERT INTO `" . bb2_db_escape($settings['log_table']) . "`
53        (`ip`, `date`, `request_method`, `request_uri`, `server_protocol`, `http_headers`, `user_agent`, `request_entity`, `key`) VALUES
54        ('$ip', '$date', '$request_method', '$request_uri', '$server_protocol', '$headers', '$user_agent', '$request_entity', '$key')";
55}
56
57// Kill 'em all!
58function bb2_banned($settings, $package, $key, $previous_key=false)
59{
60    // Some spambots hit too hard. Slow them down a bit.
61    sleep(2);
62
63    require_once(BB2_CORE . "/banned.inc.php");
64    bb2_display_denial($settings, $key, $previous_key);
65    bb2_log_denial($settings, $package, $key, $previous_key);
66    if (is_callable('bb2_banned_callback')) {
67        bb2_banned_callback($settings, $package, $key);
68    }
69    // Penalize the spammers some more
70    require_once(BB2_CORE . "/housekeeping.inc.php");
71    bb2_housekeeping($settings, $package);
72    die();
73}
74
75function bb2_approved($settings, $package)
76{
77    // Dirk wanted this
78    if (is_callable('bb2_approved_callback')) {
79        bb2_approved_callback($settings, $package);
80    }
81
82    // Decide what to log on approved requests.
83    if (($settings['verbose'] && $settings['logging']) || empty($package['user_agent'])) {
84        bb2_db_query(bb2_insert($settings, $package, "00000000"));
85    }
86}
87
88// Check the results of a particular test; see below for usage
89// Returns FALSE if test passed (yes this is backwards)
90function bb2_test($settings, $package, $result)
91{
92    if ($result !== FALSE)
93    {
94        bb2_banned($settings, $package, $result);
95        return TRUE;
96    }
97    return FALSE;
98}
99
100
101// Let God sort 'em out!
102function bb2_start($settings)
103{
104    // Gather up all the information we need, first of all.
105    $headers = bb2_load_headers();
106    // Postprocess the headers to mixed-case
107    // FIXME: get the world to stop using PHP as CGI
108    $headers_mixed = array();
109    foreach ($headers as $h => $v) {
110        $headers_mixed[uc_all($h)] = $v;
111    }
112
113    // We use these frequently. Keep a copy close at hand.
114    $ip = $_SERVER['REMOTE_ADDR'];
115    $request_method = $_SERVER['REQUEST_METHOD'];
116    $request_uri = $_SERVER['REQUEST_URI'];
117    $server_protocol = $_SERVER['SERVER_PROTOCOL'];
118    @$user_agent = $_SERVER['HTTP_USER_AGENT'];
119
120    // Reconstruct the HTTP entity, if present.
121    $request_entity = array();
122    if (!strcasecmp($request_method, "POST") || !strcasecmp($request_method, "PUT")) {
123        foreach ($_POST as $h => $v) {
124            $request_entity[$h] = $v;
125        }
126    }
127
128    $package = array('ip' => $ip, 'headers' => $headers, 'headers_mixed' => $headers_mixed, 'request_method' => $request_method, 'request_uri' => $request_uri, 'server_protocol' => $server_protocol, 'request_entity' => $request_entity, 'user_agent' => $user_agent, 'is_browser' => false);
129
130    // Please proceed to the security checkpoint and have your
131    // identification and boarding pass ready.
132
133    // First check the whitelist
134    require_once(BB2_CORE . "/whitelist.inc.php");
135    if (!bb2_whitelist($package)) {
136        // Now check the blacklist
137        require_once(BB2_CORE . "/blacklist.inc.php");
138        bb2_test($settings, $package, bb2_blacklist($package));
139
140        // Check the http:BL
141        require_once(BB2_CORE . "/blackhole.inc.php");
142        bb2_test($settings, $package, bb2_httpbl($settings, $package));
143
144        // Check for common stuff
145        require_once(BB2_CORE . "/common_tests.inc.php");
146        bb2_test($settings, $package, bb2_protocol($settings, $package));
147        bb2_test($settings, $package, bb2_cookies($settings, $package));
148        bb2_test($settings, $package, bb2_misc_headers($settings, $package));
149
150        // Specific checks
151        @$ua = $headers_mixed['User-Agent'];
152        // MSIE checks
153        if (stripos($ua, "MSIE") !== FALSE) {
154            $package['is_browser'] = true;
155            if (stripos($ua, "Opera") !== FALSE) {
156                require_once(BB2_CORE . "/opera.inc.php");
157                bb2_test($settings, $package, bb2_opera($package));
158            } else {
159                require_once(BB2_CORE . "/msie.inc.php");
160                bb2_test($settings, $package, bb2_msie($package));
161            }
162        } elseif (stripos($ua, "Konqueror") !== FALSE) {
163            $package['is_browser'] = true;
164            require_once(BB2_CORE . "/konqueror.inc.php");
165            bb2_test($settings, $package, bb2_konqueror($package));
166        } elseif (stripos($ua, "Opera") !== FALSE) {
167            $package['is_browser'] = true;
168            require_once(BB2_CORE . "/opera.inc.php");
169            bb2_test($settings, $package, bb2_opera($package));
170        } elseif (stripos($ua, "Safari") !== FALSE) {
171            $package['is_browser'] = true;
172            require_once(BB2_CORE . "/safari.inc.php");
173            bb2_test($settings, $package, bb2_safari($package));
174        } elseif (stripos($ua, "Lynx") !== FALSE) {
175            $package['is_browser'] = true;
176            require_once(BB2_CORE . "/lynx.inc.php");
177            bb2_test($settings, $package, bb2_lynx($package));
178        } elseif (stripos($ua, "MovableType") !== FALSE) {
179            require_once(BB2_CORE . "/movabletype.inc.php");
180            bb2_test($settings, $package, bb2_movabletype($package));
181        } elseif (stripos($ua, "msnbot") !== FALSE || stripos($ua, "MS Search") !== FALSE) {
182            require_once(BB2_CORE . "/msnbot.inc.php");
183            bb2_test($settings, $package, bb2_msnbot($package));
184        } elseif (stripos($ua, "Googlebot") !== FALSE || stripos($ua, "Mediapartners-Google") !== FALSE) {
185            require_once(BB2_CORE . "/google.inc.php");
186            bb2_test($settings, $package, bb2_google($package));
187        } elseif (stripos($ua, "Mozilla") !== FALSE && stripos($ua, "Mozilla") == 0) {
188            $package['is_browser'] = true;
189            require_once(BB2_CORE . "/mozilla.inc.php");
190            bb2_test($settings, $package, bb2_mozilla($package));
191        }
192
193        // More intensive screening applies to POST requests
194        if (!strcasecmp('POST', $package['request_method'])) {
195            require_once(BB2_CORE . "/post.inc.php");
196            bb2_test($settings, $package, bb2_post($settings, $package));
197        }
198    }
199
200    // Last chance screening.
201    require_once(BB2_CORE . "/screener.inc.php");
202    bb2_screener($settings, $package);
203
204    // And that's about it.
205    bb2_approved($settings, $package);
206    return true;
207}
208?>
bad-behavior/bad-behavior/functions.inc.php
1<?php if (!defined('BB2_CORE')) die("I said no cheating!");
2
3// Miscellaneous helper functions.
4
5// stripos() needed because stripos is only present on PHP 5
6if (!function_exists('stripos')) {
7    function stripos($haystack,$needle,$offset = 0) {
8        return(strpos(strtolower($haystack),strtolower($needle),$offset));
9    }
10}
11
12// str_split() needed because str_split is only present on PHP 5
13if (!function_exists('str_split')) {
14    function str_split($string, $split_length=1)
15    {
16        if ($split_length < 1) {
17            return false;
18        }
19
20        for ($pos=0, $chunks = array(); $pos < strlen($string); $pos+=$split_length) {
21            $chunks[] = substr($string, $pos, $split_length);
22        }
23        return $chunks;
24    }
25}
26
27// Convert a string to mixed-case on word boundaries.
28function uc_all($string) {
29    $temp = preg_split('/(\W)/', str_replace("_", "-", $string), -1, PREG_SPLIT_DELIM_CAPTURE);
30    foreach ($temp as $key=>$word) {
31        $temp[$key] = ucfirst(strtolower($word));
32    }
33    return join ('', $temp);
34}
35
36// Determine if an IP address resides in a CIDR netblock or netblocks.
37function match_cidr($addr, $cidr) {
38    $output = false;
39
40    if (is_array($cidr)) {
41        foreach ($cidr as $cidrlet) {
42            if (match_cidr($addr, $cidrlet)) {
43                $output = true;
44            }
45        }
46    } else {
47        @list($ip, $mask) = explode('/', $cidr);
48        if (!$mask) $mask = 32;
49        $mask = pow(2,32) - pow(2, (32 - $mask));
50        $output = ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
51    }
52    return $output;
53}
54
55// Obtain all the HTTP headers.
56// NB: on PHP-CGI we have to fake it out a bit, since we can't get the REAL
57// headers. Run PHP as Apache 2.0 module if possible for best results.
58function bb2_load_headers() {
59    if (!is_callable('getallheaders')) {
60        $headers = array();
61        foreach ($_SERVER as $h => $v)
62            if (ereg('HTTP_(.+)', $h, $hp))
63                $headers[str_replace("_", "-", uc_all($hp[1]))] = $v;
64    } else {
65        $headers = getallheaders();
66    }
67    return $headers;
68}
69
70?>
bad-behavior/bad-behavior/google.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Analyze user agents claiming to be Googlebot
4
5function bb2_google($package)
6{
7    if (match_cidr($package['ip'], "66.249.64.0/19") === FALSE && match_cidr($package['ip'], "64.233.160.0/19") === FALSE && match_cidr($package['ip'], "72.14.192.0/18") === FALSE) {
8        return "f1182195";
9    }
10    return false;
11}
12
13?>
bad-behavior/bad-behavior/housekeeping.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3function bb2_housekeeping($settings, $package)
4{
5    // FIXME Yes, the interval's hard coded (again) for now.
6    $query = "DELETE FROM `" . $settings['log_table'] . "` WHERE `date` < DATE_SUB('" . bb2_db_date() . "', INTERVAL 7 DAY)";
7    bb2_db_query($query);
8
9    // Waste a bunch more of the spammer's time, sometimes.
10    if (rand(1,1000) == 1) {
11        $query = "OPTIMIZE TABLE `" . $settings['log_table'] . "`";
12        bb2_db_query($query);
13    }
14}
15
16?>
bad-behavior/bad-behavior/konqueror.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Analyze user agents claiming to be Konqueror
4
5function bb2_konqueror($package)
6{
7    // CafeKelsa is a dev project at Yahoo which indexes job listings for
8    // Yahoo! HotJobs. It identifies as Konqueror so we skip these checks.
9    if (stripos($package['headers_mixed']['User-Agent'], "YahooSeeker/CafeKelsa") === FALSE || match_cidr($package['ip'], "209.73.160.0/19") === FALSE) {
10        if (!array_key_exists('Accept', $package['headers_mixed'])) {
11            return "17566707";
12        }
13    }
14    return false;
15}
16
17?>
bad-behavior/bad-behavior/lynx.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Analyze user agents claiming to be Lynx
4
5function bb2_lynx($package)
6{
7    if (!array_key_exists('Accept', $package['headers_mixed'])) {
8        return "17566707";
9    }
10    return false;
11}
12
13?>
bad-behavior/bad-behavior/movabletype.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3function bb2_movabletype($package)
4{
5    // Is it a trackback?
6    if (strcasecmp($package['request_method'], "POST")) {
7        if (strcmp($package['headers_mixed']['Range'], "bytes=0-99999")) {
8            return "7d12528e";
9        }
10    }
11    return false;
12}
13
14?>
bad-behavior/bad-behavior/mozilla.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Analyze user agents claiming to be Mozilla
4
5function bb2_mozilla($package)
6{
7    // First off, workaround for Google Desktop, until they fix it FIXME
8    // Google Desktop fixed it, but apparently some old versions are
9    // still out there. :(
10    // Always check accept header for Mozilla user agents
11    if (strpos($package['headers_mixed']['User-Agent'], "Google Desktop") === FALSE && strpos($package['headers_mixed']['User-Agent'], "PLAYSTATION 3") === FALSE) {
12        if (!array_key_exists('Accept', $package['headers_mixed'])) {
13            return "17566707";
14        }
15    }
16    return false;
17}
18
19?>
bad-behavior/bad-behavior/msie.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Analyze user agents claiming to be MSIE
4
5function bb2_msie($package)
6{
7    if (!array_key_exists('Accept', $package['headers_mixed'])) {
8        return "17566707";
9    }
10
11    // MSIE does NOT send "Windows ME" or "Windows XP" in the user agent
12    if (strpos($package['headers_mixed']['User-Agent'], "Windows ME") !== FALSE || strpos($package['headers_mixed']['User-Agent'], "Windows XP") !== FALSE || strpos($package['headers_mixed']['User-Agent'], "Windows 2000") !== FALSE || strpos($package['headers_mixed']['User-Agent'], "Win32") !== FALSE) {
13        return "a1084bad";
14    }
15
16    // MSIE does NOT send Connection: TE but Akamai does
17    // Bypass this test when Akamai detected
18    if (!array_key_exists('Akamai-Origin-Hop', $package['headers_mixed']) && @preg_match('/\bTE\b/i', $package['headers_mixed']['Connection'])) {
19        return "2b90f772";
20    }
21
22    return false;
23}
24
25?>
bad-behavior/bad-behavior/msnbot.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Analyze user agents claiming to be msnbot
4
5function bb2_msnbot($package)
6{
7    if (match_cidr($package['ip'], "207.46.0.0/16") === FALSE && match_cidr($package['ip'], "65.52.0.0/14") === FALSE && match_cidr($package['ip'], "207.68.128.0/18") === FALSE && match_cidr($package['ip'], "207.68.192.0/20") === FALSE && match_cidr($package['ip'], "64.4.0.0/18") === FALSE) {
8        return "e4de0453";
9    }
10    return false;
11}
12
13?>
bad-behavior/bad-behavior/opera.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Analyze user agents claiming to be Opera
4
5function bb2_opera($package)
6{
7    if (!array_key_exists('Accept', $package['headers_mixed'])) {
8        return "17566707";
9    }
10    return false;
11}
12
13?>
bad-behavior/bad-behavior/post.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// All tests which apply specifically to POST requests
4function bb2_post($settings, $package)
5{
6    // Check blackhole lists for known spam/malicious activity
7    require_once(BB2_CORE . "/blackhole.inc.php");
8    bb2_test($settings, $package, bb2_blackhole($package));
9
10    // MovableType needs specialized screening
11    if (stripos($package['headers_mixed']['User-Agent'], "MovableType") !== FALSE) {
12        if (strcmp($package['headers_mixed']['Range'], "bytes=0-99999")) {
13            return "7d12528e";
14        }
15    }
16
17    // Trackbacks need special screening
18    $request_entity = $package['request_entity'];
19    if (isset($request_entity['title']) && isset($request_entity['url']) && isset($request_entity['blog_name'])) {
20        require_once(BB2_CORE . "/trackback.inc.php");
21        return bb2_trackback($package);
22    }
23
24    // Catch a few completely broken spambots
25    foreach ($request_entity as $key => $value) {
26        $pos = strpos($key, " document.write");
27        if ($pos !== FALSE) {
28            return "dfd9b1ad";
29        }
30    }
31
32    // If Referer exists, it should refer to a page on our site
33    if (array_key_exists('Referer', $package['headers_mixed']) && stripos($package['headers_mixed']['Referer'], $package['headers_mixed']['Host']) === FALSE) {
34        return "cd361abb";
35    }
36
37    // Screen by cookie/JavaScript form add
38    if (isset($_COOKIE[BB2_COOKIE])) {
39        $screener1 = explode(" ", $_COOKIE[BB2_COOKIE]);
40    } else {
41        $screener1 = array(0);
42    }
43    if (isset($_POST[BB2_COOKIE])) {
44        $screener2 = explode(" ", $_POST[BB2_COOKIE]);
45    } else {
46        $screener2 = array(0);
47    }
48    $screener = max($screener1[0], $screener2[0]);
49
50    if ($screener > 0) {
51        // Posting too fast? 5 sec
52        // FIXME: even 5 sec is too intrusive
53        // if ($screener + 5 > time())
54        // return "408d7e72";
55        // Posting too slow? 48 hr
56        if ($screener + 172800 < time())
57            return "b40c8ddc";
58
59        // Screen by IP address
60        $ip = ip2long($package['ip']);
61        $ip_screener = ip2long($screener[1]);
62// FIXME: This is b0rked, but why?
63// if ($ip && $ip_screener && abs($ip_screener - $ip) > 256)
64// return "c1fa729b";
65
66        if (!empty($package['headers_mixed']['X-Forwarded-For'])) {
67            $ip = $package['headers_mixed']['X-Forwarded-For'];
68        }
69        // Screen for user agent changes
70        // User connected previously with blank user agent
71// $q = bb2_db_query("SELECT `ip` FROM " . $settings['log_table'] . " WHERE (`ip` = '" . $package['ip'] . "' OR `ip` = '" . $screener[1] . "') AND `user_agent` != '" . $package['user_agent'] . "' AND `date` > DATE_SUB('" . bb2_db_date() . "', INTERVAL 5 MINUTE)");
72        // Damnit, too many ways for this to fail :(
73// if ($q !== FALSE && $q != NULL && bb2_db_num_rows($q) > 0)
74// return "799165c2";
75    }
76
77    return false;
78}
79
80?>
bad-behavior/bad-behavior/responses.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Defines the responses which Bad Behavior might return.
4
5function bb2_get_response($key) {
6    $bb2_responses = array(
7        '00000000' => array('response' => 200, 'explanation' => '', 'log' => 'Permitted'),
8        '136673cd' => array('response' => 403, 'explanation' => 'Your Internet Protocol address is listed on a blacklist of addresses involved in malicious or illegal activity. See the listing below for more details on specific blacklists and removal procedures.', 'log' => 'IP address found on external blacklist'),
9        '17566707' => array('response' => 403, 'explanation' => 'An invalid request was received from your browser. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'Required header \'Accept\' missing'),
10        '17f4e8c8' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'User-Agent was found on blacklist'),
11        '21f11d3f' => array('response' => 403, 'explanation' => 'An invalid request was received. You claimed to be a mobile Web device, but you do not actually appear to be a mobile Web device.', 'log' => 'User-Agent claimed to be AvantGo, claim appears false'),
12        '2b021b1f' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'IP address found on http:BL blacklist'),
13        '2b90f772' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. If you are using the Opera browser, then Opera must appear in your user agent.', 'log' => 'Connection: TE present, not supported by MSIE'),
14        '35ea7ffa' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Check your browser\'s language and locale settings.', 'log' => 'Invalid language specified'),
15        '408d7e72' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'POST comes too quickly after GET'),
16        '41feed15' => array('response' => 400, 'explanation' => 'An invalid request was received. This may be caused by a malfunctioning proxy server. Bypass the proxy server and connect directly, or contact your proxy server administrator.', 'log' => 'Header \'Pragma\' without \'Cache-Control\' prohibited for HTTP/1.1 requests'),
17        '45b35e30' => array('response' => 403, 'explanation' => 'An invalid request was received from your browser. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'Header \'Referer\' is corrupt'),
18        '57796684' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'Prohibited header \'X-Aaaaaaaaaa\' or \'X-Aaaaaaaaaaaa\' present'),
19        '582ec5e4' => array('response' => 400, 'explanation' => 'An invalid request was received. If you are using a proxy server, bypass the proxy server or contact your proxy server administrator. This may also be caused by a bug in the Opera web browser.', 'log' => '"Header \'TE\' present but TE not specified in \'Connection\' header'),
20        '69920ee5' => array('response' => 403, 'explanation' => 'An invalid request was received from your browser. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'Header \'Referer\' present but blank'),
21        '6c502ff1' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'Bot not fully compliant with RFC 2965'),
22        '799165c2' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'Rotating user-agents detected'),
23        '7a06532b' => array('response' => 400, 'explanation' => 'An invalid request was received from your browser. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'Required header \'Accept-Encoding\' missing'),
24        '7ad04a8a' => array('response' => 400, 'explanation' => 'The automated program you are using is not permitted to access this server. Please use a different program or a standard Web browser.', 'log' => 'Prohibited header \'Range\' present'),
25        '7d12528e' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'Prohibited header \'Range\' or \'Content-Range\' in POST request'),
26        '939a6fbb' => array('response' => 403, 'explanation' => 'The proxy server you are using is not permitted to access this server. Please bypass the proxy server, or contact your proxy server administrator.', 'log' => 'Banned proxy server in use'),
27        '9c9e4979' => array('response' => 403, 'explanation' => 'The proxy server you are using is not permitted to access this server. Please bypass the proxy server, or contact your proxy server administrator.', 'log' => 'Prohibited header \'via\' present'),
28        'a0105122' => array('response' => 417, 'explanation' => 'Expectation failed. Please retry your request.', 'log' => 'Header \'Expect\' prohibited; resend without Expect'),
29        'a1084bad' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'User-Agent claimed to be MSIE, with invalid Windows version'),
30        'a52f0448' => array('response' => 400, 'explanation' => 'An invalid request was received. This may be caused by a malfunctioning proxy server or browser privacy software. If you are using a proxy server, bypass the proxy server or contact your proxy server administrator.', 'log' => 'Header \'Connection\' contains invalid values'),
31        'b40c8ddc' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, close your browser, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'POST more than two days after GET'),
32        'b7830251' => array('response' => 400, 'explanation' => 'Your proxy server sent an invalid request. Please contact the proxy server administrator to have this problem fixed.', 'log' => 'Prohibited header \'Proxy-Connection\' present'),
33        'b9cc1d86' => array('response' => 403, 'explanation' => 'The proxy server you are using is not permitted to access this server. Please bypass the proxy server, or contact your proxy server administrator.', 'log' => 'Prohibited header \'X-Aaaaaaaaaa\' or \'X-Aaaaaaaaaaaa\' present'),
34        'c1fa729b' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'Use of rotating proxy servers detected'),
35        'cd361abb' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Data may not be posted from offsite forms.', 'log' => 'Referer did not point to a form on this site'),
36        'd60b87c7' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, please remove any viruses or spyware from your computer.', 'log' => 'Trackback received via proxy server'),
37        'dfd9b1ad' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'Request contained a malicious JavaScript or SQL injection attack'),
38        'e4de0453' => array('response' => 403, 'explanation' => 'An invalid request was received. You claimed to be a major search engine, but you do not appear to actually be a major search engine.', 'log' => 'User-Agent claimed to be msnbot, claim appears to be false'),
39        'e87553e1' => array('response' => 403, 'explanation' => 'You do not have permission to access this server.', 'log' => 'I know you and I don\'t like you, dirty spammer.'),
40        'f0dcb3fd' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. Before trying again, run anti-virus and anti-spyware software and remove any viruses and spyware from your computer.', 'log' => 'Web browser attempted to send a trackback'),
41        'f1182195' => array('response' => 403, 'explanation' => 'An invalid request was received. You claimed to be a major search engine, but you do not appear to actually be a major search engine.', 'log' => 'User-Agent claimed to be Googlebot, claim appears to be false.'),
42        'f9f2b8b9' => array('response' => 403, 'explanation' => 'You do not have permission to access this server. This may be caused by a malfunctioning proxy server or browser privacy software.', 'log' => 'A User-Agent is required but none was provided.'),
43    );
44
45    if (array_key_exists($key, $bb2_responses)) return $bb2_responses[$key];
46    return array('00000000');
47}
48?>
bad-behavior/bad-behavior/safari.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Analyze user agents claiming to be Safari
4
5function bb2_safari($package)
6{
7    if (!array_key_exists('Accept', $package['headers_mixed'])) {
8        return "17566707";
9    }
10    return false;
11}
12
13?>
bad-behavior/bad-behavior/screener.inc.php
1<?php if (!defined('BB2_CWD')) die("I said no cheating!");
2
3// Bad Behavior browser screener
4
5function bb2_screener_cookie($settings, $package, $cookie_name, $cookie_value)
6{
7    // FIXME: Set the real cookie
8    setcookie($cookie_name, $cookie_value, 0, bb2_relative_path());
9}
10
11function bb2_screener_javascript($settings, $package, $cookie_name, $cookie_value)
12{
13    global $bb2_javascript;
14
15    // FIXME: do something
16    $bb2_javascript = "<script type=\"text/javascript\">
17<!--
18function bb2_addLoadEvent(func) {
19    var oldonload = window.onload;
20    if (typeof window.onload != 'function') {
21        window.onload = func;
22    } else {
23        window.onload = function() {
24            oldonload();
25            func();
26        }
27    }
28}
29
30bb2_addLoadEvent(function() {
31    for ( i=0; i < document.forms.length; i++ ) {
32        if (document.forms[i].method == 'post') {
33            var myElement = document.createElement('input');
34            myElement.setAttribute('type', 'hidden');
35            myElement.name = '$cookie_name';
36            myElement.value = '$cookie_value';
37            document.forms[i].appendChild(myElement);
38        }
39    }
40});
41// --></script>
42        ";
43}
44
45function bb2_screener($settings, $package)
46{
47    $cookie_name = BB2_COOKIE;
48
49    // Set up a simple cookie
50    $screener = array(time(), $package['ip']);
51    if (isset($package['headers_mixed']['X-Forwarded-For'])) {
52        array_push($screener, $package['headers_mixed']['X-Forwarded-For']);
53    }
54    if (isset($package['headers_mixed']['Client-Ip'])) {
55        array_push($screener, $package['headers_mixed']['Client-Ip']);
56    }
57
58    $cookie_value = implode(" ", $screener);
59
60    bb2_screener_cookie($settings, $package, BB2_COOKIE, $cookie_value);
61    bb2_screener_javascript($settings, $package, BB2_COOKIE, $cookie_value);
62}
63?>
bad-behavior/bad-behavior/trackback.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3// Specialized screening for trackbacks
4function bb2_trackback($package)
5{
6    // Web browsers don't send trackbacks
7    if ($package['is_browser']) {
8        return 'f0dcb3fd';
9    }
10
11    // Proxy servers don't send trackbacks either
12    if (array_key_exists('Via', $package['headers_mixed']) || array_key_exists('Max-Forwards', $package['headers_mixed']) || array_key_exists('X-Forwarded-For', $package['headers_mixed']) || array_key_exists('Client-Ip', $package['headers_mixed'])) {
13        return 'd60b87c7';
14    }
15    return false;
16}
17
18?>
bad-behavior/bad-behavior/version.inc.php
1<?php if (!defined('BB2_CWD')) die("I said no cheating!");
2define('BB2_VERSION', "2.0.23");
3?>
bad-behavior/bad-behavior/whitelist.inc.php
1<?php if (!defined('BB2_CORE')) die('I said no cheating!');
2
3function bb2_whitelist($package)
4{
5    // DANGER! DANGER! DANGER! DANGER! DANGER! DANGER! DANGER! DANGER!
6
7    // Inappropriate whitelisting WILL expose you to spam, or cause Bad
8    // Behavior to stop functioning entirely! DO NOT WHITELIST unless you
9    // are 100% CERTAIN that you should.
10
11    // IP address ranges use the CIDR format.
12
13    // Includes four examples of whitelisting by IP address and netblock.
14    $bb2_whitelist_ip_ranges = array(
15        "64.191.203.34", // Digg whitelisted as of 2.0.12
16        "208.67.217.130", // Digg whitelisted as of 2.0.12
17        "10.0.0.0/8",
18        "172.16.0.0/12",
19        "192.168.0.0/16",
20// "127.0.0.1",
21    );
22
23    // DANGER! DANGER! DANGER! DANGER! DANGER! DANGER! DANGER! DANGER!
24
25    // Inappropriate whitelisting WILL expose you to spam, or cause Bad
26    // Behavior to stop functioning entirely! DO NOT WHITELIST unless you
27    // are 100% CERTAIN that you should.
28
29    // You should not whitelist search engines by user agent. Use the IP
30    // netblock for the search engine instead. See http://whois.arin.net/
31    // to locate the netblocks for an IP.
32
33    // User agents are matched by exact match only.
34
35    // Includes one example of whitelisting by user agent.
36    // All are commented out.
37    $bb2_whitelist_user_agents = array(
38    // "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) It's me, let me in",
39    );
40
41    // DANGER! DANGER! DANGER! DANGER! DANGER! DANGER! DANGER! DANGER!
42
43    // Do not edit below this line
44
45    if (!empty($bb2_whitelist_ip_ranges)) {
46        foreach ($bb2_whitelist_ip_ranges as $range) {
47            if (match_cidr($package['ip'], $range)) return true;
48        }
49    }
50    if (!empty($bb2_whitelist_user_agents)) {
51        foreach ($bb2_whitelist_user_agents as $user_agent) {
52            if (!strcmp($package['headers_mixed']['User-Agent'], $user_agent)) return true;
53        }
54    }
55    return false;
56}
57
58?>
gettext.php
1<?php
2/**
3 * PHP-Gettext External Library: gettext_reader class
4 *
5 * @package External
6 * @subpackage PHP-gettext
7 * @version 1.0.7-WordPress.2.8.5
8 *
9 * @internal
10     Copyright (c) 2003 Danilo Segan <danilo@kvota.net>.
11     Copyright (c) 2005 Nico Kaiser <nico@siriux.net>
12
13     This file is part of PHP-gettext.
14
15     PHP-gettext is free software; you can redistribute it and/or modify
16     it under the terms of the GNU General Public License as published by
17     the Free Software Foundation; either version 2 of the License, or
18     (at your option) any later version.
19
20     PHP-gettext is distributed in the hope that it will be useful,
21     but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23     GNU General Public License for more details.
24
25     You should have received a copy of the GNU General Public License
26     along with PHP-gettext; if not, write to the Free Software
27     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
29*/
30
31/**
32 * Provides a simple gettext replacement that works independently from
33 * the system's gettext abilities.
34 * It can read MO files and use them for translating strings.
35 * The files are passed to gettext_reader as a Stream (see streams.php)
36 *
37 * This version has the ability to cache all strings and translations to
38 * speed up the string lookup.
39 * While the cache is enabled by default, it can be switched off with the
40 * second parameter in the constructor (e.g. whenusing very large MO files
41 * that you don't want to keep in memory)
42 */
43class gettext_reader {
44    //public:
45     var $error = 0; // public variable that holds error code (0 if no error)
46
47     //private:
48    var $BYTEORDER = 0; // 0: low endian, 1: big endian
49    var $STREAM = NULL;
50    var $short_circuit = false;
51    var $enable_cache = false;
52    var $originals = NULL; // offset of original table
53    var $translations = NULL; // offset of translation table
54    var $pluralheader = NULL; // cache header field for plural forms
55    var $select_string_function = NULL; // cache function, which chooses plural forms
56    var $total = 0; // total string count
57    var $table_originals = NULL; // table for original strings (offsets)
58    var $table_translations = NULL; // table for translated strings (offsets)
59    var $cache_translations = NULL; // original -> translation mapping
60
61
62    /* Methods */
63
64
65    /**
66     * Reads a 32bit Integer from the Stream
67     *
68     * @access private
69     * @return Integer from the Stream
70     */
71    function readint() {
72        if ($this->BYTEORDER == 0) {
73            // low endian
74            $low_end = unpack('V', $this->STREAM->read(4));
75            return array_shift($low_end);
76        } else {
77            // big endian
78            $big_end = unpack('N', $this->STREAM->read(4));
79            return array_shift($big_end);
80        }
81    }
82
83    /**
84     * Reads an array of Integers from the Stream
85     *
86     * @param int count How many elements should be read
87     * @return Array of Integers
88     */
89    function readintarray($count) {
90    if ($this->BYTEORDER == 0) {
91            // low endian
92            return unpack('V'.$count, $this->STREAM->read(4 * $count));
93        } else {
94            // big endian
95            return unpack('N'.$count, $this->STREAM->read(4 * $count));
96        }
97    }
98
99    /**
100     * Constructor
101     *
102     * @param object Reader the StreamReader object
103     * @param boolean enable_cache Enable or disable caching of strings (default on)
104     */
105    function gettext_reader($Reader, $enable_cache = true) {
106        // If there isn't a StreamReader, turn on short circuit mode.
107        if (! $Reader || isset($Reader->error) ) {
108            $this->short_circuit = true;
109            return;
110        }
111
112        // Caching can be turned off
113        $this->enable_cache = $enable_cache;
114
115        // $MAGIC1 = (int)0x950412de; //bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565
116        $MAGIC1 = (int) - 1794895138;
117        // $MAGIC2 = (int)0xde120495; //bug
118        $MAGIC2 = (int) - 569244523;
119        // 64-bit fix
120        $MAGIC3 = (int) 2500072158;
121
122        $this->STREAM = $Reader;
123        $magic = $this->readint();
124        if ($magic == $MAGIC1 || $magic == $MAGIC3) { // to make sure it works for 64-bit platforms
125            $this->BYTEORDER = 0;
126        } elseif ($magic == ($MAGIC2 & 0xFFFFFFFF)) {
127            $this->BYTEORDER = 1;
128        } else {
129            $this->error = 1; // not MO file
130            return false;
131        }
132
133        // FIXME: Do we care about revision? We should.
134        $revision = $this->readint();
135
136        $this->total = $this->readint();
137        $this->originals = $this->readint();
138        $this->translations = $this->readint();
139    }
140
141    /**
142     * Loads the translation tables from the MO file into the cache
143     * If caching is enabled, also loads all strings into a cache
144     * to speed up translation lookups
145     *
146     * @access private
147     */
148    function load_tables() {
149        if (is_array($this->cache_translations) &&
150            is_array($this->table_originals) &&
151            is_array($this->table_translations))
152            return;
153
154        /* get original and translations tables */
155        $this->STREAM->seekto($this->originals);
156        $this->table_originals = $this->readintarray($this->total * 2);
157        $this->STREAM->seekto($this->translations);
158        $this->table_translations = $this->readintarray($this->total * 2);
159
160        if ($this->enable_cache) {
161            $this->cache_translations = array ();
162            /* read all strings in the cache */
163            for ($i = 0; $i < $this->total; $i++) {
164                $this->STREAM->seekto($this->table_originals[$i * 2 + 2]);
165                $original = $this->STREAM->read($this->table_originals[$i * 2 + 1]);
166                $this->STREAM->seekto($this->table_translations[$i * 2 + 2]);
167                $translation = $this->STREAM->read($this->table_translations[$i * 2 + 1]);
168                $this->cache_translations[$original] = $translation;
169            }
170        }
171    }
172
173    /**
174     * Returns a string from the "originals" table
175     *
176     * @access private
177     * @param int num Offset number of original string
178     * @return string Requested string if found, otherwise ''
179     */
180    function get_original_string($num) {
181        $length = $this->table_originals[$num * 2 + 1];
182        $offset = $this->table_originals[$num * 2 + 2];
183        if (! $length)
184            return '';
185        $this->STREAM->seekto($offset);
186        $data = $this->STREAM->read($length);
187        return (string)$data;
188    }
189
190    /**
191     * Returns a string from the "translations" table
192     *
193     * @access private
194     * @param int num Offset number of original string
195     * @return string Requested string if found, otherwise ''
196     */
197    function get_translation_string($num) {
198        $length = $this->table_translations[$num * 2 + 1];
199        $offset = $this->table_translations[$num * 2 + 2];
200        if (! $length)
201            return '';
202        $this->STREAM->seekto($offset);
203        $data = $this->STREAM->read($length);
204        return (string)$data;
205    }
206
207    /**
208     * Binary search for string
209     *
210     * @access private
211     * @param string string
212     * @param int start (internally used in recursive function)
213     * @param int end (internally used in recursive function)
214     * @return int string number (offset in originals table)
215     */
216    function find_string($string, $start = -1, $end = -1) {
217        if (($start == -1) or ($end == -1)) {
218            // find_string is called with only one parameter, set start end end
219            $start = 0;
220            $end = $this->total;
221        }
222        if (abs($start - $end) <= 1) {
223            // We're done, now we either found the string, or it doesn't exist
224            $txt = $this->get_original_string($start);
225            if ($string == $txt)
226                return $start;
227            else
228                return -1;
229        } else if ($start > $end) {
230            // start > end -> turn around and start over
231            return $this->find_string($string, $end, $start);
232        } else {
233            // Divide table in two parts
234            $half = (int)(($start + $end) / 2);
235            $cmp = strcmp($string, $this->get_original_string($half));
236            if ($cmp == 0)
237                // string is exactly in the middle => return it
238                return $half;
239            else if ($cmp < 0)
240                // The string is in the upper half
241                return $this->find_string($string, $start, $half);
242            else
243                // The string is in the lower half
244                return $this->find_string($string, $half, $end);
245        }
246    }
247
248    /**
249     * Translates a string
250     *
251     * @access public
252     * @param string string to be translated
253     * @return string translated string (or original, if not found)
254     */
255    function translate($string) {
256        if ($this->short_circuit)
257            return $string;
258        $this->load_tables();
259
260        if ($this->enable_cache) {
261            // Caching enabled, get translated string from cache
262            if (array_key_exists($string, $this->cache_translations))
263                return $this->cache_translations[$string];
264            else
265                return $string;
266        } else {
267            // Caching not enabled, try to find string
268            $num = $this->find_string($string);
269            if ($num == -1)
270                return $string;
271            else
272                return $this->get_translation_string($num);
273        }
274    }
275
276    /**
277     * Get possible plural forms from MO header
278     *
279     * @access private
280     * @return string plural form header
281     */
282    function get_plural_forms() {
283        // lets assume message number 0 is header
284        // this is true, right?
285        $this->load_tables();
286
287        // cache header field for plural forms
288        if (! is_string($this->pluralheader)) {
289            if ($this->enable_cache) {
290                $header = $this->cache_translations[""];
291            } else {
292                $header = $this->get_translation_string(0);
293            }
294            $header .= "\n"; //make sure our regex matches
295            if (eregi("plural-forms: ([^\n]*)\n", $header, $regs))
296                $expr = $regs[1];
297            else
298                $expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
299
300            // add parentheses
301             // important since PHP's ternary evaluates from left to right
302             $expr.= ';';
303             $res= '';
304             $p= 0;
305             for ($i= 0; $i < strlen($expr); $i++) {
306                $ch= $expr[$i];
307                switch ($ch) {
308                    case '?':
309                        $res.= ' ? (';
310                        $p++;
311                        break;
312                    case ':':
313                        $res.= ') : (';
314                        break;
315                    case ';':
316                        $res.= str_repeat( ')', $p) . ';';
317                        $p= 0;
318                        break;
319                    default:
320                        $res.= $ch;
321                }
322            }
323            $this->pluralheader = $res;
324        }
325
326        return $this->pluralheader;
327    }
328
329    /**
330     * Detects which plural form to take
331     *
332     * @access private
333     * @param n count
334     * @return int array index of the right plural form
335     */
336    function select_string($n) {
337        if (is_null($this->select_string_function)) {
338            $string = $this->get_plural_forms();
339            if (preg_match("/nplurals\s*=\s*(\d+)\s*\;\s*plural\s*=\s*(.*?)\;+/", $string, $matches)) {
340                $nplurals = $matches[1];
341                $expression = $matches[2];
342                $expression = str_replace("n", '$n', $expression);
343            } else {
344                $nplurals = 2;
345                $expression = ' $n == 1 ? 0 : 1 ';
346            }
347            $func_body = "
348                \$plural = ($expression);
349                return (\$plural <= $nplurals)? \$plural : \$plural - 1;";
350            $this->select_string_function = create_function('$n', $func_body);
351        }
352        return call_user_func($this->select_string_function, $n);
353    }
354
355    /**
356     * Plural version of gettext
357     *
358     * @access public
359     * @param string single
360     * @param string plural
361     * @param string number
362     * @return translated plural form
363     */
364    function ngettext($single, $plural, $number) {
365        if ($this->short_circuit) {
366            if ($number != 1)
367                return $plural;
368            else
369                return $single;
370        }
371
372        // find out the appropriate form
373        $select = $this->select_string($number);
374
375        // this should contains all strings separated by NULLs
376        $key = $single.chr(0).$plural;
377
378
379        if ($this->enable_cache) {
380            if (! array_key_exists($key, $this->cache_translations)) {
381                return ($number != 1) ? $plural : $single;
382            } else {
383                $result = $this->cache_translations[$key];
384                $list = explode(chr(0), $result);
385                return $list[$select];
386            }
387        } else {
388            $num = $this->find_string($key);
389            if ($num == -1) {
390                return ($number != 1) ? $plural : $single;
391            } else {
392                $result = $this->get_translation_string($num);
393                $list = explode(chr(0), $result);
394                return $list[$select];
395            }
396        }
397    }
398
399}
400
401?>
local/tighturl.api.tmpl
1<p>This is the TightURL API documentation. Please stand by.</p>
local/tighturl.config.inc.php
1<?php
2/**
3 * TightURL Local Configuration File
4 * Make all changes here, *not* in the TightURL script file.
5 *
6 * @package TightURL
7 * @author Ron Guerin <ron@vnetworx.net>
8 */
9
10/**
11 * MySQL variables
12 */
13$dbhost = "localhost";
14$dbuser = "dbuser";
15$dbpass = "dbpass";
16$dbname = "tighturl";
17$dbtable = "tighturl";
18
19/**
20 * Site
21 */
22$sitenames = array("example.com","www.example.com");
23
24/**
25 * Operating modes
26 */
27$FOFMethod = FALSE; //FALSE=Use full URL path or mod_rewrite, TRUE=Use 404 Method to compress URLs
28$antiabuse = TRUE; //0=do not run network checks or other anti-abuse measures on submitted URIs, 1=run tests
29                    //Must be set to something other than true to deactivate
30$netchecks = TRUE; //0=do not run network checks, 1=run network tests as part of anti-abuse system
31$mustexist = TRUE; //0=do not check URLs to see if they exist, 1=check URLs if netchecks are on.
32$BB2=TRUE; //0=do not use Bad Behavior, 1=Protect your site with Bad Behavior
33
34/**
35 * URIBL variables
36 */
37$uribl = array("multi.surbl.org", "black.uribl.com");
38$uriblurl = array("www.surbl.org", "www.uribl.com");
39
40/** Text strings and style variables
41 *
42 */
43$svcname = "URLSquisher";
44$verbtext = "Squish";
45$pasttext = "Squished";
46$tagline = "Squish long URLs to make short ones";
47$headcolor = "#006600";
48$tablecolor = "#00CC99";
49$copystart = date("Y");
50$copyrightholder = "SquishURL Enterprises";
51$complain = true;
52$validschemes = "(http|https|ftp|sftp)";
53$forbid = "\.(cmd|bat|exe|scr|pif|vbs|js|pif|msi|cdr)";
54
55// Validate IP addresses
56
57$validipv4pattern = ":\/\/(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\."
58 . "(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])"
59 . "\.(\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])\/*";
60
61// Reserved URLs
62$ReservedURL = array("x", "rest", "xmlrpc", "soap", "xml", "atom", "rss", "blog",
63                     "faq", "help", "about", "api", "code", "source", "docs",
64                     "cvs", "arch", "url", "admin", "setup", "svn", "project", "abuse", "exploited");
65?>
local/tighturl.faq.tmpl
1<p>This is the TightURL FAQ. Please stand by.</p>
local/tighturl.main.tmpl
1  Long URLs that don't fit on one line often aren't clickable after you
2  e-mail them. They can also be tedious to type out on
3  Web-enabled cellphones. $SVCNAME squeezes very long URLs
4  like this:<br />
5  <br />
6  &nbsp;&nbsp;&nbsp; http://www.cspan.org/watch/index.asp?Cat=TV&amp;Code=CS&amp;ShowVidDays=30&amp;ShowVidDesc=&amp;ArchiveDays=30<br />
7  <br />
8  Down to a <span style='font-style: italic;'>$PASTTEXT</span>, compact URL
9  like this:<br />
10  <br />
11  &nbsp;&nbsp;&nbsp; http://$HOST$SELF$PARMda42<br>
12  <br />
local/tighturl.save.tmpl
1  Your $PASTTEXT URL is: <code><a href='$TIGHTURL' target='_blank'>$TIGHTURL</a></code> (opens in new window)<br />
2  <br />
3  That's $TIGHTURLLEN characters, which is $DIFF shorter than the $URLLEN characters of: <code>$URL</code>.
4  <form>
5    <input type="hidden" name="tighturl" value="$TIGHTURL">
6  </form>
7
8  <script language="javascript">
9    // copy URL to clipboard for IE
10    url=document.all("tighturl").createTextRange();
11    url.select();
12    url.execCommand("copy");
13    // copy URL to clipboard for Mozilla
14    var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);
15    clipboard.copyString(href);
16  </script>
local/tighturl.setup.tmpl
1$__HTML : <br />
2$__PARM : <br />
3$__URLLEN : <br />
4$__URL : <br />
5$__INPUT : <br />
6$__TIGHTURLVER : <br />
7$__TIGHTURLLEN : <br />
8$__TIGHTURL : <br />
9$__DIFF : <br />
10$__SVCNAME : <br />
11$__HEADCOLOR : <br />
12$__TABLECOLOR : <br />
13$__TAGLINE : <br />
14$__CPASTTEXT : <br />
15$__PASTTEXT : <br />
16$__VERBTEXT : <br />
17$__CVERBTEXT : <br />
18$__COPYRIGHTHOLDER : <br />
19$__COPYRIGHT : <br />
20$__URIBLS : <br />
21$__HOST : <br />
22$__SELF : <br />
23$__BBSTATS : <br />
24$____VARIABLENAME : Allows you to print $VARIABLENAME literally. : <br />
25
local/tighturl.tmpl
1<html>
2  <head>
3    <title>$SVCNAME</title>
4  </head>
5  <body>
6    <span style='font-weight: bold; color: $HEADCOLOR;'>$SVCNAME :: $TAGLINE</span>
7    <p>
8      $HTML
9    </p>
10    <p>
11      <form action='$SELF' method='GPOST'>
12        <input type='hidden' name='save' value='y'>
13        <table style='background-color: $TABLECOLOR; text-align: left;' border='1' cellpadding='2' cellspacing='2'>
14          <tbody>
15            <tr>
16              <td align='undefined' 'valign='undefined'>Enter a URL to $VERBTEXT (it must exist):<br>
17                <input type='text' name='url' size='80' value='$INPUT'> <input type='submit' name='tighturlaction' value='$CVERBTEXT URL'>
18              </td>
19            </tr>
20          </tbody>
21        </table>
22      </form>
23      <br />
24      $SVCNAME Bookmarklet:&nbsp; Drag the link
25      <a href="javascript:void(location.href='http://$HOST$SELF?save=y&url='+location.href)"
26      onmouseover="window.status='';return true" onclick="return false">$SVCNAME</a> into your browser
27      toolbar.&nbsp; Then you can create a $SVCNAME URL for any page open in your browser window
28      simply by clicking on the bookmarklet.</p>
29      <center>
30        <p><small><small>
31        &copy;$COPYRIGHT $COPYRIGHTHOLDER.<br />$SVCNAME uses $URIBLS to
32        protect against redirector abuse by spammers.<br /><br />
33        $SVCNAME is powered by <a href="http://tighturl.com/project/">TightURL $TIGHTURLVER</a>,
34        which is <a href="http://www.fsf.org/licenses/gpl.html">Free Software</a>.$BBSTATS</small></small></p>
35      </center>
36    </p>
37  </body>
38</html>
streams.php
1<?php
2/**
3 * PHP-Gettext External Library: StreamReader classes
4 *
5 * @package External
6 * @subpackage PHP-gettext
7 * @version 1.0.7-WordPress.2.8.5
8 *
9 * @internal
10   Copyright (c) 2003, 2005 Danilo Segan <danilo@kvota.net>.
11
12   This file is part of PHP-gettext.
13
14   PHP-gettext is free software; you can redistribute it and/or modify
15   it under the terms of the GNU General Public License as published by
16   the Free Software Foundation; either version 2 of the License, or
17   (at your option) any later version.
18
19   PHP-gettext is distributed in the hope that it will be useful,
20   but WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22   GNU General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with PHP-gettext; if not, write to the Free Software
26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
28 */
29
30
31// Simple class to wrap file streams, string streams, etc.
32// seek is essential, and it should be byte stream
33class StreamReader {
34  // should return a string [FIXME: perhaps return array of bytes?]
35  function read($bytes) {
36    return false;
37  }
38
39  // should return new position
40  function seekto($position) {
41    return false;
42  }
43
44  // returns current position
45  function currentpos() {
46    return false;
47  }
48
49  // returns length of entire stream (limit for seekto()s)
50  function length() {
51    return false;
52  }
53}
54
55class StringReader {
56  var $_pos;
57  var $_str;
58
59  function StringReader($str='') {
60    $this->_str = $str;
61    $this->_pos = 0;
62    // If string functions are overloaded, we need to use the mb versions
63    $this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr');
64  }
65
66  function _substr($string, $start, $length) {
67    if ($this->is_overloaded) {
68        return mb_substr($string,$start,$length,'ascii');
69    } else {
70        return substr($string,$start,$length);
71    }
72  }
73
74  function _strlen($string) {
75    if ($this->is_overloaded) {
76        return mb_strlen($string,'ascii');
77    } else {
78        return strlen($string);
79    }
80  }
81
82  function read($bytes) {
83      $data = $this->_substr($this->_str, $this->_pos, $bytes);
84    $this->_pos += $bytes;
85    if ($this->_strlen($this->_str)<$this->_pos)
86      $this->_pos = $this->_strlen($this->_str);
87
88    return $data;
89  }
90
91  function seekto($pos) {
92    $this->_pos = $pos;
93    if ($this->_strlen($this->_str)<$this->_pos)
94      $this->_pos = $this->_strlen($this->_str);
95    return $this->_pos;
96  }
97
98  function currentpos() {
99    return $this->_pos;
100  }
101
102  function length() {
103    return $this->_strlen($this->_str);
104  }
105}
106
107
108class FileReader {
109  var $_pos;
110  var $_fd;
111  var $_length;
112
113  function FileReader($filename) {
114    if (file_exists($filename)) {
115
116      $this->_length=filesize($filename);
117      $this->_pos = 0;
118      $this->_fd = fopen($filename,'rb');
119      if (!$this->_fd) {
120    $this->error = 3; // Cannot read file, probably permissions
121    return false;
122      }
123    } else {
124      $this->error = 2; // File doesn't exist
125      return false;
126    }
127  }
128
129  function read($bytes) {
130    if ($bytes) {
131      fseek($this->_fd, $this->_pos);
132
133      // PHP 5.1.1 does not read more than 8192 bytes in one fread()
134      // the discussions at PHP Bugs suggest it's the intended behaviour
135      while ($bytes > 0) {
136        $chunk = fread($this->_fd, $bytes);
137        $data .= $chunk;
138        $bytes -= strlen($chunk);
139      }
140      $this->_pos = ftell($this->_fd);
141
142      return $data;
143    } else return '';
144  }
145
146  function seekto($pos) {
147    fseek($this->_fd, $pos);
148    $this->_pos = ftell($this->_fd);
149    return $this->_pos;
150  }
151
152  function currentpos() {
153    return $this->_pos;
154  }
155
156  function length() {
157    return $this->_length;
158  }
159
160  function close() {
161    fclose($this->_fd);
162  }
163
164}
165
166// Preloads entire file in memory first, then creates a StringReader
167// over it (it assumes knowledge of StringReader internals)
168class CachedFileReader extends StringReader {
169  function CachedFileReader($filename) {
170    parent::StringReader();
171
172    if (file_exists($filename)) {
173
174      $length=filesize($filename);
175      $fd = fopen($filename,'rb');
176
177      if (!$fd) {
178        $this->error = 3; // Cannot read file, probably permissions
179        return false;
180      }
181      $this->_str = fread($fd, $length);
182      fclose($fd);
183
184    } else {
185      $this->error = 2; // File doesn't exist
186      return false;
187    }
188  }
189}
190
191
192?>
tighturl-base10
1#!/usr/bin/php
2<?php
3  echo "TightURLID: ".$argv[1]." DBID: ".base_convert($argv[1], 36, 10)."\n";
4  exit;
5?>
tighturl-base10.php
1<html>
2<head>
3<title>TightURL ID converter</title>
4</head>
5<body>
6<?php
7if (isset($_POST[id]))
8{
9  echo "<p>TightURLID(Base-36): ".$_POST[id]."<br />DBID(decimal): ".base_convert($_POST[id], 36, 10)."</p>\n";
10}
11else
12{
13?>
14  <form method="POST" action="<?php echo $PHP_SELF; ?>">
15  id:<input type="text" name="id">
16  <input type=submit name="submit" value="Convert ID to decimal">
17  </form>
18<?php
19}
20?>
21</body>
22</html>
tighturl-base36
1#!/usr/bin/php
2<?php
3  echo "DBID: ".$argv[1]." TightURLID: ".base_convert($argv[1], 10, 36)."\n";
4  exit;
5?>
tighturl-base36.php
1<html>
2<head>
3<title>Convert base 10 to TightURL ID</title>
4</head>
5<body>
6<?php
7if (isset($_POST[decimal]))
8{
9  echo "<p>Base-10(decimal): ".$_POST[decimal]."<br />TightURL ID(base-36): ".base_convert($_POST[decimal], 10, 36)."</p>\n";
10}
11else
12{
13?>
14  <form method="POST" action="<?php echo $PHP_SELF; ?>">
15  id:<input type="text" name="decimal">
16  <input type=submit name="submit" value="Convert decimal to sexatrigesimal">
17  </form>
18<?php
19}
20?>
21</body>
22</html>
tighturl-install.php
1<?php
2// Very crude installer thrown together so there can be a
3// new TightURL 0.1.4 release. It is ugly but will do the job.
4
5if (isset($_REQUEST['Action']) && $_REQUEST['Action'])
6{
7
8// Install TightURL by setting up the database. This will create tables if needed.
9// It will also upgrade previous versions of the database to be 0.1.4 compliant
10
11  (require_once("tighturl.config.inc.php")) or die_HTML("Error: Cannot locate tighturl.config.inc.php.");
12
13  // Connect to MySQL, open database.
14  $conn = @mysql_connect($dbhost, $dbuser, $dbpass) or die_HTML("Error: Cannot connect to database.");
15  $db = mysql_select_db($dbname, $conn) or die_HTML("Error: Cannot select database. ". mysql_error());
16
17  $new = mysql_query("CREATE TABLE `".$dbtable."` ( `id` int(11) unsigned NOT NULL auto_increment, `status` tinyint(3) unsigned NOT NULL, `hits` int(11) NOT NULL default '0', `lasthit` datetime NOT NULL default '0000-00-00 00:00:00', `url` text NOT NULL, `adddate` datetime NOT NULL default '0000-00-00 00:00:00', `addip` text NOT NULL, `lastcheck` datetime NOT NULL default '0000-00-00 00:00:00', `checkcount` int(10) unsigned NOT NULL, `complaints` int(10) unsigned NOT NULL, `lastcomplaint` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1;");
18  mysql_query("CREATE TABLE IF NOT EXISTS `".$dbtable."_bb2` ( `id` int(11) NOT NULL auto_increment, `ip` text NOT NULL, `date` datetime NOT NULL default '0000-00-00 00:00:00', `request_method` text NOT NULL, `request_uri` text NOT NULL, `server_protocol` text NOT NULL, `http_headers` text NOT NULL, `user_agent` text NOT NULL, `request_entity` text NOT NULL, `key` text NOT NULL, PRIMARY KEY (`id`), KEY `ip` (`ip`(15)), KEY `user_agent` (`user_agent`(10))) ENGINE=MyISAM DEFAULT CHARSET=latin1;");
19
20  if (! $new) {
21    $fields = mysql_list_fields('$dbname', '$dbtable');
22    $result = mysql_query("SHOW COLUMNS FROM $dbtable");
23
24    $columnnames = array();
25    while ($row = mysql_fetch_array($result)) {
26      $columnnames[]=$row[0];
27    }
28
29    $hits = FALSE; $lasthit = FALSE;
30    if (in_array('hits', $columnnames)) $hits = TRUE;
31    if (in_array('lasthit', $columnnames)) $lasthit = TRUE;
32    if (in_array('status', $columnnames)) $status = TRUE;
33
34    if (! $status) { // If there's a status field, then this DB has already been upgraded, do nothing.
35      $maker = "ALTER TABLE `tighturl` DROP PRIMARY KEY, CHANGE `id` `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT FIRST, ADD `status` tinyint(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `id`";
36      if ($hits) {
37        $maker .= ", CHANGE `hits` `hits` int(11) NOT NULL DEFAULT '0' AFTER `status`";
38      }
39      else {
40        $maker .= ", ADD `hits` int(11) NOT NULL DEFAULT '0' AFTER `status`";
41      }
42      if ($lasthit) {
43        $maker .= ", CHANGE `lasthit` `lasthit` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `hits`";
44      }
45      else {
46        $maker .= ", ADD `lasthit` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `hits`";
47      }
48      $maker .= ", CHANGE `url` `url` text NOT NULL AFTER `lasthit`"
49       . ", ADD `adddate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `url`"
50       . ", ADD `addip` text NOT NULL AFTER `adddate`"
51       . ", ADD `checkcount` int(10) NOT NULL DEFAULT '0' AFTER `addip`"
52       . ", ADD `lastcheck` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `checkcount`"
53       . ", ADD `complaints` int(10) NOT NULL DEFAULT '0' AFTER `lastcheck`"
54       . ", ADD `lastcomplaint` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `complaints`"
55       . ", ADD PRIMARY KEY (`id`), TYPE=MyISAM;";
56
57      mysql_query($maker) or die_HTML("Error: Database error. ". mysql_error());
58    }
59  }
60
61?>
62<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
63<html>
64<head>
65   <title>TightURL Installer</title>
66</head>
67<body>
68
69<h1>Finished.</h1>
70
71<p>Your TightURL database has been installed or upgraded as appropriate.</p>
72
73<p><font color="red">You must delete (or at least rename) tighturl-install.php in order to run TightURL.</font></p>
74
75</body>
76</html>
77
78<?php
79exit;
80
81} else {
82// start else clause
83
84?>
85<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
86<html>
87<head>
88   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
89   <TITLE>TightURL Install/Upgrade</TITLE>
90</head>
91<body>
92<h1>Welcome to the TightURL Installer and Upgrader</h1>
93
94<P>This script will either set up a newly created TightURL database, or upgrade an existing TightURL database
95to work with the version of TightURL you just installed. This process will happen automatically once you click
96the "install/upgrade now!" button below.</P>
97
98<P>Before starting, please make sure you've completed the following steps below:<br />
99<ol>
100  <li>BACK UP your TightURL database!!!!</li>
101  <li>Make sure <FONT FACE="FIXED"><CODE>tighturl.config.inc.php</CODE></FONT> has the proper settings for
102      <FONT FACE="FIXED"><CODE>$dbhost</CODE></FONT>, <FONT FACE="FIXED"><CODE>$dbname</CODE></FONT>, <FONT FACE="FIXED"><CODE>$dbtable</CODE></FONT>,
103      <FONT FACE="FIXED"><CODE>$dbuser</CODE></FONT>, and <FONT FACE="FIXED"><CODE>$dbpass</CODE></FONT>.</li>
104</ol>
105
106<form action="tighturl-install.php" method="post">
107  <table border="0">
108    <tr>
109      <td width="100%">
110        <p align="center">
111          <input type="submit" name="Action" value="Install/Upgrade Now!">
112        </p>
113      </td>
114    </tr>
115  </table>
116</form>
117</P>
118
119<P><HR NOSHADE></P>
120</BODY>
121</HTML>
122<?php
123} // end else clause
124
125function die_HTML($errmsg) {
126
127  echo "<html>\n <head>\n <title>TightURL Installer/Upgrader</title>\n </head>\n <body>\n";
128  echo " " . $errmsg . "<br />\n";
129  echo " </body>\n</html>";
130  die;
131}
132
133?>
tighturl-killbot.php
1#!/usr/bin/php
2<?php
3define("VERSION", "0.1.4");
4define("REQUIRED_PHP_VERSION", "4.3.0");
5error_reporting (E_ALL);
6
7  if (version_compare(phpversion(), REQUIRED_PHP_VERSION)<0) {
8    die("Error: TightURL ".VERSION." needs PHP >= ".REQUIRED_PHP_VERSION." (you are using ".phpversion().")");
9  }
10
11  if (file_exists("tighturl.tltpattern.inc.php")) include("tighturl.tltpattern.inc.php");
12  if (file_exists("tighturl.urlpattern.inc.php")) include("tighturl.urlpattern.inc.php");
13  if (file_exists("tighturl.ptcpattern.inc.php")) include("tighturl.ptcpattern.inc.php");
14  if (file_exists("tighturl.blippattern.inc.php")) include("tighturl.blippattern.inc.php");
15  (include("tighturl.lib.inc.php")) or die("Error: cannot load tighturl.lib.inc.php");
16  if (file_exists("tighturl.config.inc.php")) include("tighturl.config.inc.php");
17
18  // Connect to MySQL, open database.
19  $conn = @mysql_connect($dbhost, $dbuser, $dbpass) or die("Error: Cannot connect to database.");
20  $db = mysql_select_db($dbname, $conn) or die("Error: Cannot select database. ". mysql_error());
21
22  // Query records with status normal, and added within last 10 days or records with status normal and more than 7 hits and hit within the last 7 days
23  TightURL_KillBot("SELECT * FROM $dbtable where status=0 && (DATE_SUB(CURDATE(), INTERVAL 10 DAY) <= adddate || (hits > 7 && DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= lasthit)) ORDER BY id;");
24  TightURL_NewReport("SELECT * FROM $dbtable where (status=0) && (checkcount < 2) ORDER BY id;");
25  exit;
26
27?>
tighturl.blacklist.tmpl
1  <font color="red"><b>The $SVCNAME redirection URL you have requested has been disabled due to
2  its appearance on one or more of the URI blacklists this site has used to
3  detect abuse, including spamming and phishing abuse.</b></font><br /><br />
4
5  Most likely it was listed on one of the following URI Blacklists: $URIBLS .
tighturl.blippattern.inc.php
1<?php
2  define("TLBLIPPVERSION", "0.2.0.0");
3  $bl = "(219\.79\.171\.149|218\.102\.114\.245|81\.84\.75\.62|68\.112\.119\.213)";
4?>
tighturl.blpattern.inc.php
1<?php
2  define("TLBLPVERSION", "0.2.0.0");
3  $bl = "(boymeet|kit\.net|kinkystud|eharmony|payaff\.com|220\.228\.154\.249|adultfriendfinder|"
4   . "bux\.to|plimus\.com|IDiscoveredTheSecret\.com|nowmakemoneyonline\.com|\.slide\.com|"
5   . "\.t35\.com|clickbank\.net|successwithbobjay\.com|indianfriendfinder\.com|sexnos\.ru|"
6   . "linksynergy\.com|creditsolutions\.com|viralebookexplosion\.com|greatcityrealestate\.com|"
7   . "myworldpower\.com|shmyl\.com|\.googlepages\.com\/home|abcw3b\.com|freewebtown\.com|"
8   . "h1\.ripway\.com|tccinvest\.com|accesstrade\.net|forpinkpussy\.com|freewebs\.com|"
9   . "webcams\.com|teenlovelive\.com|epicwealthsystems\.com|socialmarker\.com|dqry\.com|"
10   . "actionpooses\.com|badeweek\.com|workfor3dollars\.com|verymite\.com|dutypand\.comx|"
11   . "emegacenterpharma\.com|jeeran\.com|e-researchcenter\.us\.com|wsrv\.net|"
12   . "thebiggestlaunches\.com|picturesetc\.net|linkbucks\.com|supertraff\.info|"
13   . "110mb\.com|molotilka\.com|pilo4ka\.com|meet-safe\.org|100freeinfo\.com|extasy\.3x\.ro|"
14   . "coldcashpartners\.com|therealestatepal\.com|32mail\.com|milehighair\.com|"
15   . "passionatechicks\.com|sharecash\.org|bearmarketingsystem\.com|findadultflings\.com|"
16   . "agilityhoster\.com|cash2009\.cn|nicetest\.ru|vsetut\.uz|americasbestinternetbusiness.com|"
17   . "my2dollars\.info|80profits\.com|drinkqi\.com|yourcashads\.com|abprofitsponder\.com|"
18   . "xr\.com|gay-stay\.co\.uk|byupor\.biz|124\.237\.121\.60)";
19?>
tighturl.complaints.tmpl
1  <font color="red"><b>The $SVCNAME redirection URL you have requested has been disabled due to
2  excessive abuse complaints.</b></font>
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?>
tighturl.php
1<?php
2/**
3 * TightURL :: A blind redirection service
4 *
5 * Copyright (c) 2004-2008, Ron Guerin <ron@vnetworx.net>
6 * portions Copyright (c) 2002,2003 Free Software Foundation
7 *
8 * This file implements a blind redirection service named TightURL.
9 * TightURL is Free Software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * TightURL is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 * See the GNU General Public License for more details.
18 *
19 * If you are not able to view the LICENSE, which should
20 * always be possible within a valid and working TightURL release,
21 * please write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * to get a copy of the GNU General Public License or to report a
24 * possible license violation.
25 *
26 * @package TightURL
27 * @author Ron Guerin <ron@vnetworx.net>
28 * @license http://www.fsf.org/licenses/gpl.html GNU Public License
29 * @copyright Copyright &copy; 2004-2009 Ron Guerin
30 * @filesource
31 * @link http://tighturl.com TightURL
32 * @version 0.1.4
33 *
34 */
35
36define("VERSION", "0.1.4");
37define("REQUIRED_PHP_VERSION", "4.3.0");
38
39// System defaults, DO NOT EDIT THIS FILE
40// Edit tighturl.config.inc.php instead!
41
42global $copyright, $conn, $db, $os, $svcname;
43
44$dbhost = "localhost";
45$dbuser = "dbuser";
46$dbpass = "dbpass";
47$dbname = "tighturl";
48$dbtable = "urls";
49$FOFMethod=FALSE; //0=Full URL path or mod_rewrite, 1=404-Method compressed URLs
50$os="";
51
52// URIBL variables
53$uribl = array("multi.surbl.org", "black.uribl.com");
54$uriblurl = array("www.surbl.org", "www.uribl.com");
55
56// Bad Behavior variables
57$BB2 = true;
58$BBstats = true;
59$BBstrict = false;
60$BBverbose = true;
61$BBLogging = true;
62$bb2_settings_defaults = "";
63
64// Require submitted URLs to exist?
65$mustexist = true;
66
67// Text strings and style variables
68$svcname = "URLSquisher";
69$verbtext = "Squish";
70$pasttext = "Squished";
71$tagline = "Squish long URLs to make short ones";
72$headcolor = "#006600";
73$tablecolor = "#00CC99";
74$copystart = date("Y");
75$copyrightholder = "SquishURL Enterprises";
76
77// Reserved URLs
78$ReservedURL = array("x", "rest", "xmlrpc", "soap", "xml", "atom", "rss", "blog",
79                     "faq", "help", "about", "api", "code", "source", "docs",
80                     "git", "cvs", "arch", "url", "admin", "setup", "svn", "project",
81                     "abuse", "cgi-sys", "exploited");
82
83// You REALLY don't want to edit below here unless you know what you're doing.
84
85// *************************************************************************
86
87  if (version_compare(phpversion(), REQUIRED_PHP_VERSION)<0) {
88    die_HTML($svcname, "Error: TightURL ".VERSION." needs PHP >= ".REQUIRED_PHP_VERSION." (you are using ".phpversion().")");
89  }
90
91  if (file_exists("tighturl-install.php")) die_HTML($svcname, "Error: You must remove tighturl-install.php before using $svcname.");
92
93  $os=strpos(strtolower(PHP_OS), "win")===false?"nix":"win";
94
95  $validurlpattern = "\:\/\/([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)"
96   . "*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])"
97   . "\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)"
98   . "\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)"
99   . "\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])"
100   . "|((([0-9A-F]{1,4}(((:[0-9A-F]{1,4}){5}::[0-9A-F]{1,4})|((:[0-9A-F]{1,4}){4}"
101   . "::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,1})|((:[0-9A-F]{1,4}){3}::[0-9A-F]{1,4}"
102   . "(:[0-9A-F]{1,4}){0,2})|((:[0-9A-F]{1,4}){2}::[0-9A-F]{1,4}(:[0-9A-F]{1,4})"
103   . "{0,3})|(:[0-9A-F]{1,4}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,4})|(::[0-9A-F]{1,4}"
104   . "(:[0-9A-F]{1,4}){0,5})|(:[0-9A-F]{1,4}){7}))|(::[0-9A-F]{1,4}(:[0-9A-F]{1,4}"
105   . "){0,6}))|::)|((([0-9A-F]{1,4}(((:[0-9A-F]{1,4}){3}::([0-9A-F]{1,4}){1})"
106   . "|((:[0-9A-F]{1,4}){2}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,1})|((:[0-9A-F]{1,4})"
107   . "{1}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,2})|(::[0-9A-F]{1,4}(:[0-9A-F]{1,4}"
108   . "){0,3})|((:[0-9A-F]{1,4}){0,5})))|([:]{2}[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,4}))"
109   . ":|::)((25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{0,2})\.){3}(25[0-5]|2[0-4][0-9]|"
110   . "[0-1]?[0-9]{0,2})"
111   . "|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org"
112   . "|mobi|biz|arpa|info|name|pro|aero|coop|museum"
113   . "|[a-zA-Z]{2}))(\:[0-9]+)*(\/.($|[a-zA-Z0-9\.\:\,\?\'\(\)\\\*\+&%\$;|#\=~_\-\s@]*))*\/*";
114
115  $validipv4pattern = ":\/\/(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\."
116   . "(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])"
117   . "\.(\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])\/*";
118
119  $forbid = "\.(cmd|bat|exe|scr|pif|vbs|js|pif|msi|cdr)";
120
121// ****** !All overridable configuration variables must go above this line! ******
122
123  if (! isset($antiabuse)) $antiabuse = true;
124  if (! isset($netchecks)) $netchecks = true;
125  if (! isset($mustexist)) $mustexist = true;
126
127  // Status: 0=Ok, 1=Warn, 2=Black, 3=Policy, 4=Complaints
128
129  if (file_exists("tighturl.urlpattern.inc.php")) include("tighturl.urlpattern.inc.php");
130  if (file_exists("tighturl.tltpattern.inc.php")) include("tighturl.tltpattern.inc.php");
131  if (file_exists("tighturl.redirpattern.inc.php")) include("tighturl.redirpattern.inc.php");
132  if (file_exists("tighturl.ptcpattern.inc.php")) include("tighturl.ptcpattern.inc.php");
133  if (file_exists("tighturl.blpattern.inc.php")) include("tighturl.blpattern.inc.php");
134  if (file_exists("tighturl.config.inc.php")) include("tighturl.config.inc.php");
135
136  // Figure out our copyright string
137  $thisyear = date("Y");
138  $copyright = $copystart;
139  if ($copystart != $thisyear) $copyright .= "-" . $thisyear;
140  $uribls = "";
141  for ($i=0; $i<count($uribl); $i++) {
142    if ($i > 0) $uribls .= ", ";
143    $uribls .= "<a href='http://" . $uriblurl[$i] . "'>" . $uribl[$i] . "</a>";
144  }
145
146 if (! $FOFMethod) $parm = "?i="; // We need the parameter tag
147
148 // Figure out correct self
149  if (strncmp($_SERVER['PHP_SELF'], $_SERVER['REQUEST_URI'], strlen($_SERVER['PHP_SELF'])) != 0) {
150    if (preg_match("|(.*)/.*$|",$_SERVER['PHP_SELF'],$matches)) $self = $matches[1];
151    if (! preg_match("|.*/$|", $self)) $self .= "/";
152  }
153  else {
154    $self = $_SERVER['PHP_SELF']; // We need the script name
155    if (! preg_match("|.*/$|", $self)) $self .= "/";
156  }
157
158  // Connect to MySQL, open database.
159  $conn = @mysql_connect($dbhost, $dbuser, $dbpass) or die_HTML($svcname, "Error: Cannot connect to database.");
160  $db = mysql_select_db($dbname, $conn) or die_HTML($svcname, "Error: Cannot select database. ". mysql_error());
161
162  // When in doubt, turn Bad Behavior on, set it to FALSE in the config to turn it off.
163  if (! isset($BB2)) $BB2 = true;
164
165  // If user has not turned off Bad Behavior in the config, use BB2 (highly recommended) TODO: warn user if $BB2 but not BB2
166  if ($BB2 && file_exists("bad-behavior/bad-behavior-tighturl.php")) require_once("bad-behavior/bad-behavior-tighturl.php");
167    else $BB2 = FALSE;
168
169  // Figure out what kind of request this is and service it.
170
171  // This is klugey. Clean up later.
172  // also I think data should be sanitized immediately
173  if ((isset($_REQUEST['save']) && $_REQUEST['save'] == 'y')
174   && (isset($_REQUEST['url']) && ! empty($_REQUEST['url']) && trim($_REQUEST['url']) != ""
175   && (preg_match("/^.*url=(.*)$/", $_SERVER['QUERY_STRING'], $matches) != 0))) {
176    $url = trim($matches[1]);
177    if (preg_match("/^(.*)&tighturlaction.*$/", $matches[1], $matches)) $url = $matches[1];
178    save_URL(urldecode($url));
179  }
180  elseif (isset($_REQUEST['i']) && !empty($_REQUEST['i'])) {
181    lookup_ID($_REQUEST['i']);
182  }
183  elseif (isset($pbi) && !empty($pbi) && isset($_REQUEST[$pbi]) && !empty($_REQUEST[$pbi])) {
184    PolicyBan_ID($_REQUEST[$pbi]);
185  }
186  elseif ($FOFMethod && preg_match("/^\/+([a-zA-Z0-9]+)\/*(.*)\/*$/", $_SERVER['REQUEST_URI'], $matches)) {
187    lookup_ID($matches[1]);
188  }
189  elseif ($FOFMethod && $_SERVER['REQUEST_URI'] != "/") {
190    display_HTML("", "", "Error: Couldn't find a valid " . $svcname . " URI.");
191  }
192  else {
193    display_HTML("", "main");
194  }
195  exit;
196
197// *************************************************************************
198
199
200/**
201 * sanitize a string for SQL input
202 */
203function sanitize_sql_string($string) {
204  return(mysql_real_escape_string($string));
205}
206
207/**
208 * Counts the number of times a substring is contained in a given string.
209 */
210function countSubstrs($haystack, $needle) {
211  return (($p = strpos($haystack, $needle)) === false) ? 0 : (1 + countSubstrs(substr($haystack, $p+1), $needle));
212}
213
214/**
215 * Checks to see if a given URI is on a URI blacklist.
216 * Currently this means SURBL (http://www.surbl.org) and URIBL (http://www.uribl.com)
217 *
218 * Returns TRUE if the domain is listed on any configured URIBLs, returns FALSE if
219 * anything goes wrong or the anti-abuse system is turned off.
220 *
221 * A companion URI extractor must be written for the below issues
222 * Must be changed to do full resolution of redirections on URI, simulating a browser
223 * Must be changed to do IPv6 lookups
224 * Must be changed to check multiple URIs (maybe a wrapper instead)
225 * Must be changed to optionally check HTML entity encoded versions of URIs
226 * Must be changed to handle URIBL's inclusion of some third-level domains.
227 *
228 */
229function URI_on_URIBL($uri) {
230
231// This code does not yet properly implement a correct and efficient querying
232// of URI BL data.
233
234  global $uribl, $uribluri, $validschemes, $validurlpattern, $validipv4pattern,
235         $antiabuse, $netchecks, $tltlds;
236
237  // Everything gets a pass if antiabuse or network tests are off.
238  if ((! $antiabuse) || (! $netchecks)) return(false);
239
240  $uribls = "";
241
242  if ($uri) {
243    // Test for IPv4 address, reverse the quads if found
244    if (preg_match("/^".$validschemes.$validipv4pattern."/", $uri, $matches)) {
245      $domain=$matches[5] . "." . $matches[4] . "." . $matches[3] . "." . $matches[2];
246    }
247    else {
248      // strip out second-level domain name, *unless* on exception list,
249      // in which case, strip out third level also and test that instead.
250      // FIX: when testing uribl.com lists, also test additional level. First hit wins.
251
252      preg_match("/^".$validschemes.$validurlpattern."$/", $uri, $matches);
253      $domain = $matches[4];
254      if (preg_match("/".$tltlds."$/", $domain, $matches)) {$levels = 2;} else {$levels = 1;}
255
256      // klugey stripping routine to reduce domain to base domain name
257      // expect regex wojuld be better
258
259      $ss = countSubstrs($domain, ".");
260      while ($ss > $levels) {
261        $chop = strpos($domain, ".");
262        $domain = substr($domain, $chop + 1);
263        $ss = countSubstrs($domain, ".");
264      }
265    }
266
267    // Query URI blacklists to see if domain/IP appears as target in known spam
268    // or something involved in a malware/phishing attack.
269    for ($i=0; $i<count($uribl); $i++) {
270      $fqdn = $domain . "." . $uribl[$i];
271      $recexists = gethostbyname($fqdn); // ghbn weirdly returns the name on failure
272      if (($recexists != $fqdn) && preg_match("<^127\.>", $recexists)) {
273        if ($i > 0) $uribls .= ", ";
274        $uribls .= $uribl[$i];
275      }
276    }
277    return ($uribls); // change to return an array of indexes into the URIBL array
278  }
279}
280
281/**
282 * Checks to see if a given URL is a Reserved URL.
283 *
284 * Returns TRUE if the ID is listed as a Reserved URL.
285 */
286function on_Reserve($decimal) {
287  global $ReservedURL;
288
289  $res=FALSE;
290
291  if ($decimal) {
292    $sexatrigesimal = base_convert($decimal, 10, 36);
293    for ($i=0; $i<count($ReservedURL); $i++) {
294      if ($sexatrigesimal == strtolower($ReservedURL[$i])) return TRUE;
295    }
296    return FALSE;
297  }
298}
299
300/**
301 * Save the given URL in the database if unique and return the ID or return an existing ID for given URL.
302 * The ID returned will be a sexatrigesimal (Base-36) number.
303 *
304 * Saves the URL in the database, converts the decimal ID value returned by the database to
305 * a sexatrigesimal value, and displays the generated TightURL.
306 */
307function save_URL($url) {
308  global $dbtable, $svcname, $FOFMethod, $validschemes, $validurlpattern, $pasttext, $self, $redir, $bl,
309         $antiabuse, $netchecks, $ptc, $forbid, $mustexist;
310
311  if ($_SERVER['HTTP_USER_AGENT'] == "Python-urllib/2.5") {
312    display_HTML("", "save", "", $url, "http://tighturl.com/haibot");
313    exit;
314  }
315
316  $selfref = "|^(http://" . $_SERVER['HTTP_HOST'] . $self . ")|i";
317  $aliasref = "|^(http://www." . $_SERVER['HTTP_HOST'] . $self . ")|i";
318  $remote = $_SERVER['REMOTE_ADDR'];
319
320  if (preg_match($selfref, $url) || preg_match($aliasref, $url)) {
321    display_HTML("", "", "Error: A " . $svcname . " URL cannot point to another URL within " . $_SERVER['HTTP_HOST'] . $self . " .", $url, "", $url);
322  }
323  elseif (! preg_match("/^".$validschemes.$validurlpattern."$/", $url)) {
324    display_HTML("", "", "Error: That URL (".htmlspecialchars(strip_tags($url)).") is not valid.", $url, "", $url);
325  }
326  elseif (($forbid != "") && (preg_match("!.*".$forbid."$!i", $url))) {
327    display_HTML("", "", "Error: Executable URIs are not accepted here due to phishing/malware abuse.", $url, "", $url);
328  }
329// This code was never meant to be in a release. oops
330// elseif (preg_match("!.*\.gif$!", $url)) { // replace this with image comparison
331// display_HTML("", "", "Error: URL rejected for service abuse.", $url, "", $url);
332// }
333//RR elseif (isset($mustexist) && $mustexist && isset($netchecks) && $netchecks && (! Resolve_URL($url, $chain))) {
334//RR display_HTML("", "", "Error: Submitted URL does not exist on the public Internet.", $url, "", $url);
335//RR }
336  elseif (isset($bl) && preg_match("/.*".$bl.".*/i", $url)) { // delete this crap
337// echo "url: $url bl: $bl\n";
338    display_HTML("", "", "Error: URL rejected for violating our terms of use.", $url, "", $url);
339  }
340  elseif (preg_match("<.*".$redir.".*>i", $url)) {
341    display_HTML("", "", "Error: ".$svcname." is not a URL obfuscation service, and does not accept redirection links.", $url, "", $url);
342  }
343  elseif (isset($ptc) && preg_match("/.*".$ptc.".*/i", $url)) {
344    display_HTML("", "", "Error: ".$svcname." does not accept PTC (Pay To Click) links due to spamming abuse.", $url, "", $url);
345  }
346  else {
347    $safeurl = sanitize_sql_string($url);
348    $result = mysql_query("SELECT MAX(id) FROM $dbtable") or display_HTML("", "", "Error: $svcname system error.", $url, "", $url);
349    $lastid = mysql_result($result, 0) + 1;
350    $guesssexatrigesimal = base_convert($lastid, 10, 36);
351    $guessurl = "http://" . $_SERVER['HTTP_HOST'] . $self;
352    if (! $FOFMethod) $guessurl .= "?i="; // We need the parameter tag
353    $guessurl .= $guesssexatrigesimal; // Append the Base-36 ID to the URL
354    if ( strlen($guessurl) >= strlen($url) ) {
355      display_HTML("", "", "Fail: That URL cannot be shortened by $svcname. Sorry!", $url, "", $url);
356    }
357    else {
358      if ($antiabuse && $netchecks) {$lists = URI_on_URIBL($url);} else {$lists = false;}
359      if (! $lists) {
360        $rows=0; $srows=0; $testurl=$safeurl;
361        if (preg_match("/\/$/", $testurl)) $testurl = rtrim($testurl,"/");
362        $req = "SELECT * FROM $dbtable WHERE url = '$testurl/';";
363        $res = mysql_query($req);
364        $srows = @mysql_num_rows($res) or $srows = 0;
365        if ($srows == 0) {
366          $req = "SELECT * FROM $dbtable WHERE url = '$testurl';";
367          $res = mysql_query($req);
368          $rows = @mysql_num_rows($res) or $rows = 0;
369        }
370        if ($rows == 0 && $srows == 0) {
371          do {
372            $req ="INSERT INTO $dbtable (id, url, adddate, addip) ";
373            $req .= "VALUES ('', '$safeurl', NOW(), '$remote');";
374            if (mysql_query($req)) {
375              $decimal = mysql_insert_id();
376            }
377            else {
378              die_HTML($svcname, "Error: Database failure.");
379            }
380            $reserved_id = on_Reserve($decimal);
381            if ($reserved_id) {
382              // Delete this record so it doesn't override the reserved ID. (?)
383              $req = "DELETE FROM $dbtable WHERE id = '$decimal';";
384              $res = mysql_query($req) or die_HTML($svcname, "Error: Database failure.");
385            }
386          } while ($reserved_id);
387        }
388        else {
389          // Return existing ID for this duplicate request
390          $decimal = mysql_result($res, 0, "id");
391        }
392        $sexatrigesimal = base_convert($decimal, 10, 36);
393        $address = "http://" . $_SERVER['HTTP_HOST'] . $self;
394        if (! $FOFMethod) $address .= "?i="; // We need the parameter tag
395        $address .= $sexatrigesimal; // Append the Base-36 ID to the URL
396        display_HTML("", "save", "", $url, $address);
397      }
398      else {
399        display_HTML("HTTP/1.0 403 Forbidden", "", "Error: Submitted URL (" . $url . ") is listed in " . $lists . ". You may not create a " . $svcname . " link for it.");
400      }
401    }
402  }
403}
404
405/**
406 *
407 */
408function PolicyBan_ID($sexatrigesimal) {
409  global $dbtable, $svcname;
410
411  // First, convert unsafe user input sexatrigesimal to decimal, which will be safe.
412  $decimal = base_convert ($sexatrigesimal, 36, 10);
413
414  $req = "SELECT * FROM $dbtable WHERE id = '$decimal';";
415  $res = mysql_query($req) or die_HTML($svcname, "Error: Query failed");
416
417  $rows = mysql_num_rows($res);
418  if (($rows != 0) && (mysql_result($res, 0, "url") != "")) {
419    $req ="update $dbtable set status='4' where id='$decimal';";
420    $res = mysql_query($req);
421    die_HTML($svcname, "ID: " . $sexatrigesimal . " banned for policy violation.", $code="HTTP/1.0 200 OK");
422  }
423}
424
425/**
426 * Looks up given ID in the database and redirects, displays template, or
427 * displays error page. Expects the ID to be a sexatrigesimal (Base-36) number,
428 * which is the format used by TightURLs.
429 *
430 * We convert the ID to decimal before looking it up in the database, as the
431 * ID field is a MySQL autoincrement decimal value.
432 */
433function lookup_ID($sexatrigesimal) {
434  global $dbtable, $svcname;
435
436  // First, convert unsafe user input sexatrigesimal to decimal, which will be safe.
437  $decimal = base_convert ($sexatrigesimal, 36, 10);
438
439  $req = "SELECT * FROM $dbtable WHERE id = '$decimal';";
440  $res = mysql_query($req) or die_HTML($svcname, "Error: Query failed");
441
442  $rows = mysql_num_rows($res);
443  if (($rows != 0) && (mysql_result($res, 0, "url") != "")) {
444    // Change this logic to display a templated page instead?
445    switch (mysql_result($res, 0, "status")) {
446    case 5:
447      display_HTML("HTTP/1.0 403 Forbidden", "complaints");
448      return;
449      break;
450    case 4:
451      display_HTML("HTTP/1.0 403 Forbidden", "policy");
452      return;
453      break;
454    case 3:
455      display_HTML("HTTP/1.0 403 Forbidden", "blacklist");
456      return;
457      break;
458    default:
459      $url = stripslashes(mysql_result($res, 0, "url"));
460      break;
461    }
462    $req ="update $dbtable set lasthit=NOW(), hits=hits+1 where id='$decimal';";
463    $res = mysql_query($req);
464    header("HTTP/1.0 301 Moved Permanently");
465    header("Location: $url");
466  }
467  elseif (! on_Reserve($decimal)) { // Not found, Not on reserve
468    display_HTML("HTTP/1.0 404 Not Found", "", "Error: That " . $svcname . " ID is not in our database.");
469  }
470  else { // It's a(n implied) Reserved URL
471    // Is this a template or an API?
472    $sexatrigesimal = strtolower($sexatrigesimal);
473    switch ($sexatrigesimal) {
474    case "rest":
475      api_REST();
476      break;
477    case "xmlrpc":
478      api_XMLRPC();
479      break;
480    case "soap":
481      api_SOAP();
482      break;
483    default:
484      display_HTML("", $sexatrigesimal);
485    }
486  }
487}
488
489function api_REST() {
490  die_HTML($svcname, "Error: REST API not implemented yet.", "HTTP/1.0 501 Not Implemented");
491}
492
493function api_XMLRPC() {
494  die_HTML($svcname, "Error: XML-RPC API not implemented yet.", "HTTP/1.0 501 Not Implemented");
495}
496
497function api_SOAP() {
498  die_HTML($svcname, "Error: SOAP API not implemented yet.", "HTTP/1.0 501 Not Implemented");
499}
500
501/**
502 * Display HTML page using template and template variables.
503 *
504 * Reads in the main system template file (tighturl.tmpl) into $html .
505 *
506 * $code
507 * HTTP 1.0 status code and message.
508 *
509 * $template
510 * Checks for the existence of a subtemplate named tighturl.$template.tmpl
511 * and replaces template variable $HTML in the main template tighturl.tmpl
512 * with the contents of tighturl.$template.tmpl if any.
513 *
514 * Then any remaining $HTML from the only or inner template is replaced by $content,
515 * along with $url, $tighturl, and $input. A variety of other replacements are
516 * made using various global variables.
517 *
518 * $content
519 * HTML content to be replace template variable $HTML
520 *
521 * $url
522 * URL submitted to TightURL
523 *
524 * $tighturl
525 * TightURL generated for $url
526 *
527 * $input
528 * When submitted URL does not validate it is passed back as $input
529 *
530 * Template variables are words in all capital letters that start with a
531 * $ symbol, such as $TEMPLATEVARIABLE. TightURL now supports at least
532 * 20 template variables. At runtime, these template variables are replaced
533 * by program variables.
534 * - $HTML : HTML passed into the function as $input by the program or an inner template
535 * - $PARM : Parameter tag when not using 404-Method
536 * - $URL : URL submitted to TightURL
537 * - $URLLEN : Length of the submitted URL
538 * - $TIGHTURL : TightURL generated for the submitted URL
539 * - $TIGHTURLLEN : Length of generated TightURL
540 * - $DIFF : Difference in length between submitted and TightURLs
541 * - $INPUT : Bad input URL being passed back to output form
542 * - $SVCNAME : Name of the TightURL service
543 * - $HEADCOLOR : Color of the H1 Header tag
544 * - $TABLECOLOR : Color of the table containing URL input field
545 * - $TAGLINE : Tagline of the TightURL service
546 * - $CPASTTEXT : Capitalized past-tense word for tightening URLs
547 * - $PASTTEXT : Non-Capitalized past-tense word for tightening URLs
548 * - $CVERBTEXT : Capitalized action word for tightening URLs
549 * - $VERBTEXT : Non-Capitalized action word for tightening URLs
550 * - $COPYRIGHT : Copyright duration string generated from $copystart global variable,
551 * will be current 4-digit year if $copystart not defined.
552 * - $COPYRIGHTHOLDER : Name of copyright holder
553 * - $URLBLS : HTML string of URIBLs TightURL is checking
554 * - $HOST : Hostname TightURL is running on
555 * - $SELF : Name TightURL is invoked as
556 */
557function display_HTML ($code, $template, $content="", $url="", $tighturl="", $input="") {
558  global $svcname, $verbtext, $pasttext, $tagline, $uribls, $parm,
559       $headcolor, $tablecolor, $copyright, $copyrightholder, $self, $BB2;
560
561// $url = htmlspecialchars($url);
562  if ($code="") $code = "HTTP/1.0 200 OK";
563  if (preg_match("/\/$/", $template)) $template = rtrim($template,"/");
564  if (file_exists("tighturl.tmpl")) {
565    $html = file_get_contents("tighturl.tmpl");
566    if (($template != "") && file_exists("tighturl." . $template . ".tmpl")) {
567      $template = file_get_contents("tighturl." . $template . ".tmpl");
568      $html = preg_replace("/\\\$HTML/", $template, $html);
569    }
570    elseif ($template != "") {
571      die_HTML($svcname, "Error: Template file tighturl." . $template . ".tmpl cannot be found.");
572    }
573    if (substr($content, 0, 6) == "Error:") {
574      $content = preg_replace("/Error:/", "<big><font color='red'>Error:", $content)."</font></big>";
575    }
576    if ($content) $content .= "<br />\n";
577    // Always replace longer similar tokens before shorter ones. Things won't work the
578    // way you expect if you replace $URL first, and then replace $URLMORELETTERS.
579    $html = preg_replace("/\\\$HTML/", $content, $html);
580    $html = preg_replace("/\\\$PARM/", $parm, $html);
581    $html = preg_replace("/\\\$URLLEN/", strlen($url), $html);
582    $html = preg_replace("/\\\$URL/", htmlspecialchars(strip_tags($url), ENT_QUOTES), $html);
583    $html = preg_replace("/\\\$INPUT/", $input, $html);
584    $html = preg_replace("/\\\$TIGHTURLVER/", VERSION, $html);
585    $html = preg_replace("/\\\$TIGHTURLLEN/", strlen($tighturl), $html);
586    $html = preg_replace("/\\\$TIGHTURL/", $tighturl, $html);
587    $html = preg_replace("/\\\$DIFF/", strlen($url)-strlen($tighturl), $html);
588    $html = preg_replace("/\\\$SVCNAME/", $svcname, $html);
589    $html = preg_replace("/\\\$HEADCOLOR/", $headcolor, $html);
590    $html = preg_replace("/\\\$TABLECOLOR/", $tablecolor, $html);
591    $html = preg_replace("/\\\$TAGLINE/", $tagline, $html);
592    $html = preg_replace("/\\\$CPASTTEXT/", $pasttext, $html);
593    $html = preg_replace("/\\\$PASTTEXT/", strtolower($pasttext), $html);
594    $html = preg_replace("/\\\$VERBTEXT/", strtolower($verbtext), $html);
595    $html = preg_replace("/\\\$CVERBTEXT/", $verbtext, $html);
596    $html = preg_replace("/\\\$COPYRIGHTHOLDER/", $copyrightholder, $html);
597    $html = preg_replace("/\\\$COPYRIGHT/", $copyright, $html);
598    $html = preg_replace("/\\\$URIBLS/", $uribls, $html);
599    $html = preg_replace("/\\\$HOST/", $_SERVER['HTTP_HOST'], $html);
600    $html = preg_replace("/\\\$SELF/", $self, $html);
601    $html = preg_replace("/\\\$__/", "$", $html); // Template Variables shown as text instead of substituted
602    if (preg_match("|<title>(.*)</title>|is", $html, $matches))
603      $html = preg_replace("|<title>(.*)</title>|is", "<title>" . strip_tags($matches[1]) . "</title>", $html);
604    if ($BB2) {
605      $html = preg_replace("/\\\$BBSTATS/", bb2_insert_stats(), $html);
606      $bb2code = bb2_insert_head();
607      if (preg_match("|<head>(.*)</head>|is", $html, $matches))
608        $html = preg_replace("|<head>(.*)</head>|is", "<head>\n" . $bb2code . $matches[1] . "</head>", $html);
609    }
610    else {
611      $html = preg_replace("/\\\$BBSTATS/", "", $html);
612    }
613    header($code);
614    echo $html;
615  }
616  else {
617    die_HTML($svcname, "Error: <big><font color='red'>Error: TightURL Redirection service (" . $svcname . ") site template not found.</font></big>");
618  }
619}
620
621/**
622 * Die in an HTML-friendly way, without the benefit of a template.
623 * Use display_HTML to "die" using the TightURL site template.
624 */
625function die_HTML($svcname, $errmsg, $code="HTTP/1.0 500 Internal Server Error") {
626
627  header($code);
628  echo "<html>\n <head>\n <title>" . $svcname . "</title>\n </head>\n <body>\n";
629  echo " " . $errmsg . "<br />\n";
630  echo " </body>\n</html>";
631  die;
632}
633
634/**
635 * Verifies the existence and accessibility of a resource in a given URL.
636 *
637 * Returns FALSE if the resource does not exist or cannot be accessed using
638 * supplied authentication information, else returns the resolved and verified
639 * URL. Given URL is returned as resolved to itself if $netchecks are off.
640 *
641 * Will recurse through redirection chains up to 12 times by default. This
642 * value is preferably selectable by the user in a configuration screen
643 * somewhere, but probably should not be lower than 12, as attempts are made
644 * to detect HTML and JavaScript redirects in addition to HTTP redirects, and
645 * a dozen redirects to find the end is quite possible.
646 *
647 * Unfortunately Google's GFE server erroneously returns 404 errors when
648 * they should be returning something like a 405, making it impossible to
649 * use HTTP HEAD to verify the existence of resources front-ended by GFE.
650 * Additionally Amazon throws a 405 attempting to HEAD some of their resources
651 * so this function does not attempt to use HEAD at all.
652 *
653 * BUG: Presently only does HTTP
654 *
655 */
656//function Resolve_URL ($url, &$resolvedchain=array(""), $chainlen=12) {
657function Resolve_URL ($url, &$resolvedchain, $chainlen=12) {
658// $resolvedchain = array($url);
659
660  if (! isset($resolvedchain)) $resolvedchain=array("");
661
662  global $netchecks;
663
664  if (! $netchecks) {
665    // If network checks off, accept submitted URL as resolved.
666    return($url);
667  }
668
669  $parsed = parse_url($url);
670
671  $pre = isset($parsed['scheme']) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '' : '//') : '';
672  $pre .= isset($parsed['user']) ? $parsed['user'].(isset($parsed['pass']) ? ':'.$parsed['pass'] : '').'@' : '';
673  $pre .= isset($parsed['host']) ? $parsed['host'] : '';
674  $pre .= isset($parsed['port']) ? ':'.$parsed['port'] : '';
675  if(isset($parsed['path']))
676    $post = (substr($parsed['path'], 0, 1) == '/') ? $parsed['path'] : ('/'.$parsed['path']);
677  else
678    $post = "/";
679  $post .= isset($parsed['query']) ? '?'.$parsed['query'] : '';
680  $post .= isset($parsed['fragment']) ? '#'.$parsed['fragment'] : '';
681
682  $resolved = false;
683
684  // Change this to support all protocols TightURL supports, not just HTTP
685  if (! isset($parsed['port']) || $parsed['port'] == 0) $parsed['port'] = 80;
686//if($connection = @fsockopen ($parsed['host'], $parsed['port'], $errno, $errstr, 5)) {
687  $ip = gethostbyname($parsed['host']); // This is supposed to avoid unnecessary DNS lookups
688  if($connection = @fsockopen ($ip, $parsed['port'], $errno, $errstr, 5)) {
689    stream_set_timeout($connection, 5);
690    // HTTP send Connection: Close so we don't have to wait
691    // Google's GFE handling of HEAD is broken, and Amazon returns 405 on HEAD so had to use GET
692    fwrite($connection, "GET ".$post." HTTP/1.0\r\nHost: ".$parsed['host']."\r\nConnection: Close\r\n\r\n");
693    while (!feof($connection)) {
694      $line_read=fgets($connection);
695      if ($line_read == "") break; //blank line is header delimiter, if you see it you're done here
696                                   //Fix: change this and start parsing the body for HTML-based redirections.
697
698      if (preg_match("/HTTP\/\S* +(\S*) /", $line_read, $matches)) { // Look for certain HTTP status codes
699        switch ($matches[1]) {
700        case 200: // Ok, we have a final destination (as far as HTTP is concerned)
701        case 201: // Created, we have a final destination
702        case 202: // Accepted, we have a final destination
703        case 203: // Non-authoritative reply, we have a final destination
704        case 204: // No content, we have a final destination
705        case 205: // Reset content, we have a final destination
706        case 206: // Partial content, we have a final destination
707        case 207: // Multi-status, we have a final destination
708        case 304: // Not Modified (this is ok)
709        case 401: // Authorization required (this is ok)
710        case 402: // Payment required (this is ok)
711        case 403: // Forbidden (but also ok)
712        case 405: // Method not allowed (but also ok)
713        case 406: // Not acceptable (acceptable here unless someone tells us otherwise)
714        case 409: // Conflict (acceptable unless someone tells us otherwise)
715        case 421: // Too many connections (fail ok)
716        case 426: // Use TLS (fail ok)
717        case 500: // Internal server error (fail ok)
718        case 502: // Bad gateway (fail ok)
719        case 503: // Service unavailable (fail ok)
720        case 504: // Gateway timeout (fail ok)
721        case 505: // HTTP version not supported (fail ok)
722        case 509: // Bandwidth exceeded pseudo code (fail ok)
723          $resolved = $url;
724          $resolvedchain[] = $url;
725          break 2;
726        case 300:
727        case 301:
728        case 302:
729        case 307:
730          break;
731        case 404: // Not found
732        case 408: // Request timeout (this URL will never work again)
733        case 410: // Gone (and not coming back)
734          break 2;
735        default:
736          $resolved = $url;
737          $resolvedchain[] = $url;
738          break 2;
739        }
740      }
741
742      // If this is a redirect (300, 301, 302, 307), follow it if the chain isn't too long
743      if (preg_match("/Location: (.*)\r\n/", $line_read, $matches)) {
744        fclose($connection);
745        $connection = false;
746        $resolvedchain[] = $url;
747        if ($chainlen > 0 ) $resolved = Resolve_URL($matches[1], $resolvedchain, $chainlen - 1);
748        break;
749      }
750
751    }
752    // Parse body here?
753    if ($connection) fclose($connection);
754  }
755  return($resolved);
756}
757?>
tighturl.policy.tmpl
1  <font face="red"><b>The $SVCNAME redirection URL you have requested has been disabled due to
2  violations of $SVCNAME policy/Terms of Service.</b></font>
tighturl.ptcpattern.inc.php
1<?php
2  define("TLPTCBLVERSION", "0.1.4");
3  $ptc = "(1-800-mail\.com|1000clicksptr\.com|100cents-1000dollars\.com|"
4  . "100-dollars-mail\.com|100dollarsbonus\.info|100dollarsmails\.com|"
5  . "100euromails\.com|100usd\.com|10bux\.net|10dollar-mail\.com|"
6  . "10euromails.com|168paid\.com|1-dollar-mail\.com|1stprofit\.com|"
7  . "2-dollar-mail\.com|2-opt\.com|2008mails\.com|200dollars-email\.com|"
8  . "200dollarsmail\.com|200eurocent-200euro\.com|200euromails\.com|"
9  . "200euromails\.net|20dollarsmail\.com|247payouts\.com|25dollarsmail\.com|"
10  . "25-dollars-mail\.com|2dollaremails\.com|3-dollar-mail\.com|"
11  . "300dollarsmail\.com|30dollarsmail\.com|37-21mail\.com|400dollarsmail\.com|"
12  . "4bux\.info|5-dollar-mail\.com|500cents-500dollars\.net|"
13  . "500cents-500dollars\.org|500pounds-and-500pence\.com|50centptr\.com|"
14  . "50dollarsmail\.com|520searcher\.com|5dollarmails\.com|60euromail\.com|"
15  . "60de\.com|7878clicks\.com|7centsolos\.com|7thheavenptr\.net|"
16  . "8cent-emails\.com|80euromail\.com|a-n-cash\.com|an-cash\.com|"
17  . "aaa-mails\.com|activeptr\.net|ad5\.biz|ad-fortune\.com|adsbux\.org|"
18  . "adsmaker\.net|adsneed\.com|advercash\.net|aglocomails\.com|ahacash\.com|"
19  . "allcashmail\.com|allyousubmitters\.com|almiyachts\.com|alwayspay\.com|"
20  . "american-mails\.com|amigoemail\.com|amity-cash\.com|ans-advertising\.com|"
21  . "anycallmails\.com|apachemails\.com|applemails\.com|appolomails\.com|"
22  . "arab-gpt\.com|arabbux\.com|arcane-mails\.com|arcsurvey\.com|"
23  . "arcticmails\.com|asonewishes\.com|at-mails\.com|atom-mails\.com|"
24  . "atomsmails\.com|auction-emails\.com|awsurveys\.com|b-u-x\.net|"
25  . "babyloncash\.com|ban-mail\.com|banboocash\.com|bank-mails\.com|"
26  . "bank-mails\.net|bearshare-mails\.com|beautymails\.com|beeptr\.com|"
27  . "beetrmails\.com|best-mails\.com|best-hyip\.be|bestflymails\.com|"
28  . "beta-cash\.com|bettybucks\.com|beyondemails\.com|bez-minimum\.info|"
29  . "bigdollar-mails\.com|biggestdollars\.com|bigluck-mails\.com|"
30  . "bigpaymail\.com|billiondollarmails\.com|bluemaniacs\.com|"
31  . "bluerwebmail\.com|boa-mails\.com|bobomails\.com|bobmail\.com|"
32  . "boffopaidmail\.com|bonniemails\.com|boratmails\.com|businessptr\.com|"
33  . "boss-mails\.com|bournemouthbreeze\.com|bravevolitation\.com|bugcash\.com|"
34  . "bux\.to|bux-cash\.com|buxer\.org|buxeuro\.com|buxgalore\.com|buxone\.com|"
35  . "buxforever\.com|buxp\.info|buxbank\.com|camel-mails\.com|"
36  . "can-discount\.com|candy-mail\.com|cannabismails\.com|capitalmails\.net|"
37  . "cashbux\.com|cashbux\.org|casheden\.com|cash-kitty\.com|cashfiesta\.com|"
38  . "cash-harvest\.com|cash4grabs\.info|cashnclicks\.com|cashorigin\.com|"
39  . "cashpointclicks\.com|cashread\.com|cashsea\.com|casino-mails\.com|"
40  . "cat-mail\.com|cat-mails\.com|cat-ptr\.com|catch-cash\.com|"
41  . "class-act-clicks\.com|classical-mail\.com|cgcash\.info|charm-mail\.com|"
42  . "chicago-ptr\.com|chick-mails\.com|chobit-mails\.com|chobitmails\.com|"
43  . "chobitsmails\.net|click2earnmoney\.com|click-mails\.com|click-wizard\.net|"
44  . "clickandbux\.com|clickbux\.org|clickbuxx\.com|clickcent\.net|"
45  . "clickearnmoney\.com|clickingmoney4u\.com|click-monkey\.biz|clickoly\.com|"
46  . "clicks-4-cash\.com|clicksensation\.info|clicktopsites\.com|clixsense\.com|"
47  . "clixy\.net|clonebux\.com|cloudmails\.com|closet-clickers\.com|"
48  . "cloverclicks\.net|coast-mail\.com|coastmail\.com|coinclicks\.info|"
49  . "comeongain\.com|compactmails\.com|cookie-mails\.com|cooperativemail\.com|"
50  . "copymails\.com|cosplaymails\.com|coverclicks\.com|cowboy-mail\.com|"
51  . "crabmails\.com|crazy-4-cash\.com|cream-mails\.com|dallas-ptr\.com|"
52  . "danger-mails\.com|davemails\.com|darkangelmailsdaydayupemails\.com|"
53  . "dayscash\.com|dayseeking\.net|deepseacash\.com|deliriouspaidemails\.com|"
54  . "delta-cash\.com|devclix\.com|diamondbux\.com|digital-ptr\.com|"
55  . "dj-mails\.com|dog-mails\.com|dollar-factory\.com|dollarsmaker\.net|"
56  . "dollarslove\.com|dollarsmaker\.com|dolphincents\.com|domainmail\.com|"
57  . "donkeycash\.info|donut-m\.biz|duno\.com|dragone-search\.com|"
58  . "dragonhole\.com|dreamstarmail\.com|drumcash\.com|dynasty-mails\.com|"
59  . "dungeonanddragonemails\.com|d-biz\.com|e-mailptr\.com|eagleclicknet\.com|"
60  . "earn-emails\.com|earn4read\.com|earnptr\.com|earnup\.com|easy-gain\.com|"
61  . "easyhits\.org|egoldclicks\.net|electric-mails\.com|"
62  . "elephantadvertising\.com|elephant-mails\.com|e-mailptr\.com|"
63  . "email2rewards\.com|e-mailpaysu\.com|emailpremium\.com|emailprofit.us"
64  . "emails-empire\.com|emailspayu\.net|emails-empire\.com|"
65  . "emeraldcoastptc\.info|energy-mails\.com|englandbux\.com|englandbux\.org|"
66  . "enjoyfunds\.com|eqmails\.com|eurocentsmail\.com|eurobux\.org|"
67  . "euro-mails\.com|europtr.\net|everylooking\.com|eceryrich\.com|"
68  . "expert-mails\.com|extra10\.com|eyemails\.com|fairydollars\.com|"
69  . "fairytaleptr\.com|farland-cash\.com|fastbux\.com|fastbux\.org|"
70  . "fastcashemaills\.com|fastpaidptr\.com|fellowequality\.com|"
71  . "fillmyaccount\.com|filmyinbox\.com|fire-mails\.com|flashrich\.com|"
72  . "flaviomails\.be|fly-field\.com|freeclickcash\.net|free-kingdom\.com|"
73  . "freemoneymails\.net|feer-mial\.com|feermial\.com|fortuneemail\.com|"
74  . "fourleafclovermail\.com|foxcash\.com|ft-mails\.com|funkycashmail\.com|futureptr\.com|"
75  . "fx-mails\.com|gamma-cash\.com|gem-mails\.com|getpaid4clicks\.com|"
76  . "getpaidbyemail\.com|getpaideasy\.com|getpaidlinks\.net|getpaidwatch\.com|"
77  . "getor-mails\.com|giga-cash\.com|giga-mails\.com|goaio\.com|godmail\.info|"
78  . "godmails\.com|gogoplease\.cn|goldencatch\.com|goldenemail\.com|"
79  . "goldptr\.net|golfmails\.com|goodluck-email\.com|google-mails\.com|"
80  . "gothic-mail\.com|gowellup\.com|gp2profits\.com|graspaftertime\.com|"
81  . "grassmails\.com|green-cash\.com|greetgold\.com|halfmillionmails\.com|"
82  . "halomoney\.com|happyearning\.com|happyptr\.com|healthyptc\.com|"
83  . "heroptr\.com|highbidppc\.com|\happybizs\.com|hkbux\.com|"
84  . "holiday-mails\.com|hollywood-mail\.com|honestmails\.com|honestptr\.com|"
85  . "horse-mails\.com|huge-mails\.com|husky-mails\.com|icashout\.com|"
86  . "ice-mails\.net|ilikeemails\.com|insaneptr\.net|inspiremarrow\.com|"
87  . "instant-dollars\.com|instantads\.org|intgold\.com|invest-mail\.com|"
88  . "iphonemails\.com|ippomails\.com|ippomails\.net|jackpot-ads\.biz|"
89  . "jays-paidmail\.com|job-readmail\.com|junglecash\.com|jungleclicks\.com|"
90  . "justcashinc\.com|kiddays\.com|kitcatcash\.com|klikini\.net|kukmail\.com|"
91  . "libertycash\.biz|lifeisabeachclicks\.net|lightstarmail\.com|linkread\.com|"
92  . "lion-mails\.com|littleengineptr\.com|loading-mails\.com|logans-legacy\.com|"
93  . "lolclicks\.com|lookingemail\.com|lovebird-mails\.com|loveburd-mails\.com|"
94  . "loving-mail\.com|magicalmails\.com|magicash\.com|magic-mails\.com|"
95  . "magnetismail\.com|mailbling\.com|mails2earn\.net|mainbux\.com|"
96  . "make-free-money-online\.info|malisanko-emails\.com|mangoemails\.com|"
97  . "many-mails\.com|mapleptr\.com|maystromails\.com|maystromails\.net|"
98  . "mdbux\.com|medal-mails\.com|mega-ptr\.com|megaptr\.com|"
99  . "meggarichemails\.com|mellow-mails\.com|metal-emails\.com|"
100  . "metalpaidread\.com|meteor-mails\.com|michellesrandomizer\.com|"
101  . "milion-mail\.com|million-mails\.com|millionaire-mail\.com|mimimcash\.com|"
102  . "minbux\.com|mincashbux\.com|mintysmails\.com|minibux\.com|"
103  . "moneybagsmail\.com|moneybux\.com|moneybux\.org|moneyclicks\.biz|"
104  . "moneyems\.com|moneydogptc\.com|moneymouser\.com|moneysbank\.com|"
105  . "moonbux\.com|mushroomsmail\.com|mybux\.info|mygpt\.com|myspacetoearn\.net|"
106  . "mysweetheartmail\.com|nature-mails\.com|neobux\.com|netgold4u\.com|"
107  . "newsptr\.com|niceptr\.com|nickelsbyemail\.com|nickoftime-email\.com|"
108  . "njgirl\.biz|no2allmails\.com|nocs.usnokiamails\.com|number-emails\.com|"
109  . "numenmail\.com|oceansoflife\.com|ohomails\.com|onedollarmail\.com|"
110  . "one-mails\.com|oneperson-mail\.com|onlygravy\.com|onlythebestptr\.com|"
111  . "ok-mails\.com|ok-ptr\.com|ok-usd\.com|okayemail\.com|onlygravy\.com|"
112  . "on-sunday\.com|orangemails\.com|oursharedsuccess\.com|ourpaidmail\.com|"
113  . "paidbux\.com|paidclicks\.ws|paidemail\.com|paidmail\.ru|"
114  . "paidmailagency\.com|paidmailengine\.com|paidstation\.com|paidworld\.com|"
115  . "paidmail\.ru|papajuan\.info|pay-to-mail\.info|payingcoins\.com|paytc\.net|"
116  . "payyou123\.com|payyoudollar\.com|perfect-emails\.com|pekingcash\.com|"
117  . "petromails\.com|pcash\.info|phoenixcash\.info|pig-mails\.com|"
118  . "pizzamails\.com|platinum-investment\.com|platinum-mails\.com|"
119  . "pleasant-mails\.com|polarbearmails\.com|pomoterprosemail\.com|"
120  . "popomails\.com|post4cash\.com|powerbux\.org|power-mails\.net|"
121  . "powersmails\.net|premiermails\.com|pretti.mail\.com|prettyptr\.com|"
122  . "pretty-mail\.com|probux\.net|professionalmails\.com|profers\.com|"
123  . "profitfrommails\.com|profitptr\.net|propaidemail\.com|ptcad\.net|"
124  . "ptindex\.com|ptp8\.com|ptr-enterprise\.com|ptr-enterprises\.com|"
125  . "ptrforce\.com|ptr-hun\.info|ptrland\.com|ptr-trading\.com|puma-mails\.com|"
126  . "pumpkin-mails\.com|puppypaid2clicks\.com|quality-profits\.com|"
127  . "quickbux\.org|rabbit-mails\.com|racingemails\.com|rainbow-mails\.com|"
128  . "rainbow-mail\.net|ranoscash\.com|rat-mails\.com|readformoney.us"
129  . "realmails\.com|readrevenue\.com|reliableclix\.com|richmails\.com|"
130  . "rivermails\.com|road-mails\.com|rock-mails\.com|rolex-mails\.com|"
131  . "rosenet-emails\.com|royalcash-mails\.com|royalinvest\.biz|"
132  . "rushnsuccess\.com|saytheirmail\.com|scarlettmails\.com|secret-mails\.net|"
133  . "sea-mails\.com|seekbizs\.com|seekmails\.com|sepooq\.com|seriousbucks\.com|"
134  . "seven-bux\.com|sharedmails\.com|sheepmails\.com|shirecash\.com|"
135  . "silvanamails\.com|silvanamails\.net|siteclubemail\.com|sky-mails\.net|"
136  . "sky-wolf\.net|smile-email\.com|smoothlinks\.com|snapdollars\.com|"
137  . "snowman-mails\.com|solarclick\.com|\southmails\.com|space-mails\.com|"
138  . "spaz-emails\.com|spedia\.com|speed-mails\.com|spicemails\.com|"
139  . "spiderchess\.com|spidermanemails\.com|sprint-cash\.com|startmails\.com|"
140  . "strongptr\.com|studio-mail\.com|summer-mails.ussunday-mails\.com|"
141  . "sunflowersptr\.com|sun-cash\.com|suns-cash\.com|sunsetclix\.com|"
142  . "super-mails\.com|super-program\.com|superstarmail\.com|surfjunky\.com|"
143  . "surfjunky\.com|surfanearn\.net|surforhits\.com|surprisemails\.com|"
144  . "surveyking\.com|sweet-mails\.com|symantec-mail\.com|systemmails\.com|"
145  . "tarbux\.com|tata-cash\.com|tendollarsmail\.com|teneuromail\.com|"
146  . "tomails\.com|thebux\.com|thebux\.helloweb\.eu|theclickers\.net|"
147  . "thegoldclick\.com|thegoldmail\.com|therichcash\.com|thinkbux\.com|"
148  . "timelessearn\.com|tnt-e-mail\.com|tombmailer\.com|tomoonmail\.com|"
149  . "tons-referrals\.com|tradingptr\.com|trafficcool\.com|trafficinvader\.com|"
150  . "travelmails\.com|treasureclicks\.info|trustfulmail\.com|trustmails\.com|"
151  . "trusturbux\.com|turtle-mails\.com|twistedclickers\.com|twodollarsmail\.com|"
152  . "tycoonmails\.com|unionptr\.com|united-empire\.com|unitmails\.com|"
153  . "universalclix\.com\.br|usa-canada-email\.com|usa-clicks\.us|"
154  . "usd-ad\.com|vegas-mails\.com|velocityclicks\.com|verdiencredits\.nl|"
155  . "vice-ptr\.com|viennamails\.com|viper-clicks\.com|virtualcardzone\.com|"
156  . "visionptr\.com|warm-mails\.com|wc-mails\.com|weapon-earnings\.info|"
157  . "webbercash\.com|well-email\.com|welovepay\.com|western-clicks\.com|"
158  . "western-mails\.com|wet-clicks\.com|wingmails\.com|womail\.com|"
159  . "woderemails\.com|wonderful-mails\.com|woo-mails\.com|worldbux\.info|"
160  . "worldwidemails\.com|workmails\.com|wowearnings\.com|wow-mails\.com|"
161  . "xsc-mail\.com|xtremeptc\.com|y2e\.info|yippeemails\.com|"
162  . "yourspiderweb\.com|zero-investments\.com|zy-mails\.com)";
163?>
tighturl.redirpattern.inc.php
1<?php
2  define("TLRDPVERSION", "0.1.4");
3  $redir = "(0rz\.tw|leenk\.org|dwarfurl\.com|\.1tiny\.com|\.301url\.com|"
4   . "\.all\.at|andmuchmore\.com|ataja\.es|babyurl\.com|\.back\.to|"
5   . "\.beam\.at|\.been\.at|biglnk\.com|\.bite\.to|\.board\.to|"
6   . "\.bounce\.to|\.bowl\.to|\.break\.at|\.browse\.to|browser\.to|"
7   . "\.change\.to|\.chip\.ms|compactURL\.com|\.connect\.to|"
8   . "\.crash\.to|\.cut\.by|digbig\.com|\.direct\.at|\.dive\.to|"
9   . "\.doiop\.com|\.drink\.to|\.drive\.to|\.drop\.to|\.easy\.to|"
10   . "\.eb\.cx|\.elfurl\.com|escape\.to|\.everything\.at|\.fade\.to|"
11   . "\.fanclub\.ms|\.firstpage\.de|\.flingk\.com|\.fly\.to|"
12   . "\.flying\.to|fornovices\.com|\.forward\.to|\.fullspeed\.to|"
13   . "fun\.to|\.fun\.ms|\.gameday\.de|gentleurl\.net|\.germany\.ms|"
14   . "\.get\.to|\.getit\.at|glinki\.com|got\.to|\.hard-ware\.de|"
15   . "\.hello\.to|\.hey\.to|\.hop\.to|hottestpix\.com|\.how\.to|"
16   . "\.hp\.ms|imegastores\.com|jeeee\.net\.jump\.to|\.kiss\.to|"
17   . "latest-info\.com|learn\.to|\.lin\.kz|link\.toolbot\.com|"
18   . "linkezy\.com|linktrim\.com|ln-s\.net|\.lnk\.in|lznk\.com|"
19   . "makeashorterlink\.com|\.mediasite\.de|\.megapage\.de|"
20   . "\.metamark\.net|\.messages\.to|\.mine\.at|\.minilien\.com|"
21   . "\.more\.at|\.more\.by|\.move\.to|moviefever\.com|mp3-archives\.com|"
22   . "\.musicpage\.de|\.mypage\.org|myprivateidaho\.com|\.mysite\.de|"
23   . "myurl\.com\.tw|\.nav\.to|nlug\.org\/url|\.notlong\.com|"
24   . "\.notrix\.at|\.notrix\.ch|\.notrix\.de|\.notrix\.net|"
25   . "now\.to|\.on\.to|\.page\.to|\.pagina\.de|\.paulding\.net|"
26   . "\.played\.by|\.playsite\.de|\.privat\.ms|\.quickly\.to|\.qrl\.be|"
27   . "qurl\.com|\.qurl\.net|radpages\.com|\.redirect\.to|remember\.to|"
28   . "resourcez\.com|return\.to|rubyurl\.com|\.rulestheweb\.com|"
29   . "\.run\.to|\.runurl\.com|sail\.to|\.scroll\.to|\.seite\.ms|"
30   . "\.shorl\.com|\.shortcut\.to|\.shortlinks\.co\.uk|shurl\.net|"
31   . "shurl\.org|\.simurl\.com|\.skip\.to|skocz\.pl|\.smcurl\.com|"
32   . "\.snap\.to|snipurl\.com|\.soft-ware\.de|sports-reports\.com|"
33   . "\.start\.at|\.stick\.by|stop\.to|\.surf\.to|s-url\.net|"
34   . "\.switch\.to|\.talk\.to|thrill\.to|\.tighturl\.com|tiny\.cc|"
35   . "tinyclick\.com|tinylink\.com|\.tinyr\.us|tinyurl\.co\.uk|"
36   . "tinyurl\.com|tiny\.vj\.e\.pl|\.tip\.nu|\.tny\.se|\.top\.ms|"
37   . "tophonors\.com|\.transfer\.to|\.travel\.to|turl\.jp|\.turn\.to|"
38   . "uncutuncensored.com|\.url123\.com|url\.fibiger\.org|\.url\.fm|"
39   . "urlcut\.com|urlcut\.net|urlfreeze\.com|urlic\.com|urlin\.it|"
40   . "urlmask\.com|\.urlx\.org|urlser\.com|vacations\.to|veryweird\.com|"
41   . "videopage\.de|virtualpage\.de|\.w3\.to|\.w3t\.org|\.walk\.to|"
42   . "\.warp9\.to|web-freebies\.com|webalias\.com|webdare\.com|"
43   . "\.window\.to|xrl\.us|xxx-posed\.com|\.yatuc\.com|\.yep\.it|"
44   . "\.yours\.at|\.zap\.to|\.zip\.to|zuso\.tw|hugeurl\.com|elfurl\.com|"
45   . "doiop\.com|301url\.com|kuso\.cc|urlx\.org|urlsnip\.com|sx\.am|"
46   . "trimurl\.com|urlbee\.com|urllogs\.com|tiniuri\.com|xn6\.net|"
47   . "9ax\.ne|shorturl\.com|not2long\.net|iceglow\.com|irotator\.com|"
48   . "igoto\.co\.uk|dl\.am|zwap\.to|explode\.to|unonic\.com|net\.tf|"
49   . "us\.tf|int\.tf|ca\.tf|ch\.tf|edu\.tf|ru\.tf|pl\.tf|cz\.tf|bg\.tf|"
50   . "sg\.tf|kickme\.to|lovez\.it|needz\.it|craves\.it|means\.it|"
51   . "digs\.it|adores\.it|chills\.it|is-groovin\.it|is-chillin\.it|"
52   . "drives\.it|reads\.it|surfs\.it|swims\.it|playz\.it|singz\.it|"
53   . "dances\.it|has\.it|does\.it|shows\.it|rules\.it|rocks\.it|"
54   . "makes\.it|says\.it|owns\.it|zor\.org|1024bit\.at|128bit\.at|"
55   . "16bit\.at|256bit\.at|32bit\.at|512bit\.at|64bit\.at|8bit\.at|"
56   . "again\.at|allday\.at|alone\.at|altair\.at|american\.at|"
57   . "amiga500\.at|ammo\.at|amplifier\.at|amstrad\.at|anglican\.at|"
58   . "angry\.at|around\.at|arrange\.at|australian\.at|baptist\.at|"
59   . "basque\.at|battle\.at|bazooka\.at|berber\.at|blackhole\.at|"
60   . "booze\.at|bosnian\.at|brainiac\.at|brazilian\.at|bummer\.at|"
61   . "burn\.at|c-64\.at|catholic\.at|catalonian\.at|chapel\.at|"
62   . "christiandemocrats\.at|cname\.at|colors\.at|commodore\.at|"
63   . "commodore64\.at|communists\.at|conservatives\.at|conspiracy\.at|"
64   . "cooldude\.at|croatian\.at|cuteboy\.at|dancemix\.at|danceparty\.at|"
65   . "danish\.at|dealing\.at|deep\.at|democrats\.at|divxlinks\.at|"
66   . "divxmovies\.at|divxstuff\.at|dizzy\.at|dork\.at|dutch\.at|"
67   . "dvdlinks\.at|dvdmovies\.at|dvdstuff\.at|emulaaaaars\.at|end\.at|"
68   . "english\.at|eniac\.at|error403\.at|error404\.at|evangelism\.at|"
69   . "exhibitionist\.at|faith\.at|fight\.at|finish\.at|finnish\.at|"
70   . "forward\.at|freebie\.at|freemp3\.at|french\.at|graduatejobs\.at|"
71   . "greenparty\.at|grunge\.at|hacked\.at|hang\.at|hangup\.at|hide\.at|"
72   . "hindu\.at|htmlpage\.at|hungarian\.at|icelandic\.at|independents\.at|"
73   . "invisible\.at|japanese\.at|jive\.at|kickass\.at|kindergarden\.at|"
74   . "kurd\.at|labour\.at|leech\.at|liberals\.at|linuxserver\.at|"
75   . "liqour\.at|maxed\.at|meltdown\.at|methodist\.at|microcomputers\.at|"
76   . "mingle\.at|mirror\.at|moan\.at|mormons\.at|musicmix\.at|"
77   . "nationalists\.at|nerds\.at|neuromancer\.at|newbie\.at|nicepage\.at|"
78   . "ninja\.at|norwegian\.at|ntserver\.at|paint\.at|palestinian\.at|"
79   . "phoneme\.at|phreaking\.at|polish\.at|popmusic\.at|portuguese\.at|"
80   . "powermac\.at|processor\.at|prospects\.at|protestant\.at|rapmusic\.at|"
81   . "raveparty\.at|reachme\.at|reboot\.at|relaxed\.at|republicans\.at|"
82   . "researcher\.at|reset\.at|resolve\.at|retrocomputers\.at|rockparty\.at|"
83   . "rollover\.at|rough\.at|rumble\.at|russian\.at|scared\.at|seikh\.at|"
84   . "serbian\.at|short\.as|silence\.at|simpler\.at|sinclair\.at|"
85   . "slowdown\.at|socialists\.at|spanish\.at|split\.at|stand\.at|"
86   . "saaaaned\.at|stumble\.at|supercomputer\.at|swedish\.at|synagogue\.at|"
87   . "syntax\.at|syntaxerror\.at|techie\.at|temple\.at|thinkbig\.at|"
88   . "thirsty\.at|throw\.at|aaaaplist\.at|trekkie\.at|trouble\.at|"
89   . "turkish\.at|unexplained\.at|unixserver\.at|vegetarian\.at|venture\.at|"
90   . "verycool\.at|vic-20\.at|viewing\.at|vintagecomputers\.at|"
91   . "virii\.at|vodka\.at|wannabe\.at|webpagedesign\.at|wheels\.at|"
92   . "whisper\.at|whiz\.at|wonderful\.at|zx80\.at|zx81\.at|zxspectrum\.at|"
93   . "15h\.com|1dr\.biz|2url\.org|7ref|8rf\.com|active\.ws|bydl\.com|"
94   . "bittyurl\.com|bizz\.cc\|briefurl\.com|c-o\.in|chopurl\.com|"
95   . "ko168\.com|cool158\.com|cool168\.com|ontheinter\.net|cutalink\.com|"
96   . "dephine\.org|fx\.to|drlinky\.com|fireme\.to|ontheway\.to|"
97   . "nextdoor\.to|fancyurl\.com|get2\.us|spotted\.us|went2\.us|"
98   . "hasballs\.com|globalredirect\.com|go\.cc|gonow\.to|gowwwgo\.com|"
99   . "hotshorturl\.com|here\.is|hothere\.com|coolhere\.com|homepagehere\.com|"
100   . "mustbehere\.com|onlyhere\.net|pagehere\.com|surfhere\.net|"
101   . "zonehere\.com|iscool\.net|l8t\.com|5ux\.xom|9irl\.com|9uy\.com|"
102   . "just\.as|linkfrog\.net|lispurl\.com|linkzip\.net|midgeturl\.com|"
103   . "r8\.org|nanoref\.com|ozonez\.com|ppcredirect\.com|pulsar\.net|"
104   . "quickurl\.net|qwer\.org|red\.tc|sky\.tc|tnx\.be|lol\.la|the\.vg|"
105   . "redirectfree\.com|surl\.ws|sg5\.co\.uk|freegaming\.org|"
106   . "freebiefinders\.net|op7\.net|2cd\.net|0kn\.com|v9z\.com|"
107   . "shortenurl\.com|simurl\.com|passingg\.as|redirect\.hm|rr\.nu|"
108   . "kwik\.to|fw\.nu|ontheweb\.nu|isthebe\.st|byinter\.net|findhere\.org|"
109   . "onthenet\.as|ugly\.as|assexy\.as|pass\.as|athissite\.com|"
110   . "athersite\.com|isgre\.at|lookin\.at|beastdeals\.at|lowestprices\.at|"
111   . "spydar\.com|tz4\.com|cemper\.com|urlproxy\.com|i\.am|listen\.to|"
112   . "xaddr\.com|urlot\.com|nbjmp\.com|alink2\.uic\.to|shmyl\.com|"
113   . "get-shorty\.com|linkfreeze\.net|wapurl\.co\.uk|mb01\.com|"
114   . "twurl\.cc|moourl\.com|eroticagateway\.com|hido\.net|lix\.in|"
115   . "urlbrief\.com|ws-linker\.info|anrdoezrs\.net|blackapplehost\.com/.*files\.php|"
116   . "ai\.waiwaito\.com|miniurl\.pl|shortlinks\.co\.uk|tinyurlscript\.com|"
117   . "tinurl\.mobi|is\.gd|bit\.ly|go-link\.ru|shorterlink\.org)";
118?>
tighturl.tltpattern.inc.php
1<?php
2define("TLTLTPVERSION", "0.1.4.4");
3$tltlds = ".*\.(2000\.hu|ab\.ca|ab\.se|abo\.pa|ac\.ae|ac\.am|ac\.at|ac\.bd|"
4 . "ac\.be|ac\.cn|ac\.com|ac\.cr|ac\.cy|ac\.fj|ac\.fk|ac\.gg|ac\.gn|"
5 . "ac\.hu|ac\.id|ac\.il|ac\.im|ac\.in|ac\.ir|ac\.je|ac\.jp|ac\.ke|"
6 . "ac\.kr|ac\.lk|ac\.ma|ac\.mw|ac\.ng|ac\.nz|ac\.om|ac\.pa|ac\.pg|"
7 . "ac\.rs|ac\.ru|ac\.rw|ac\.se|ac\.th|ac\.tj|ac\.tz|ac\.ug|ac\.uk|"
8 . "ac\.vn|ac\.yu|ac\.za|ac\.zm|ac\.zw|act\.au|ad\.jp|adm\.br|"
9 . "adult\.ht|adv\.br|adygeya\.ru|aero\.mv|aero\.tt|aeroport\.fr|"
10 . "agr\.br|agrar\.hu|agro\.pl|ah\.cn|aichi\.jp|aid\.pl|ak\.us|"
11 . "akita\.jp|al\.us|aland\.fi|alderney\.gg|alt\.na|alt\.za|"
12 . "altai\.ru|am\.br|amur\.ru|amursk\.ru|aomori\.jp|ar\.us|"
13 . "arkhangelsk\.ru|army\.mil|arq\.br|art\.br|art\.do|art\.dz|"
14 . "art\.ht|art\.pl|arts\.co|arts\.ro|arts\.ve|asn\.au|asn\.lv|"
15 . "ass\.dz|assedic\.fr|assn\.lk|asso\.dz|asso\.fr|asso\.gp|asso\.ht|"
16 . "asso\.mc|asso\.re|astrakhan\.ru|at\.tf|at\.tt|atm\.pl|ato\.br|"
17 . "au\.com|au\.tt|auto\.pl|av\.tr|avocat\.fr|avoues\.fr|az\.us|"
18 . "baikal\.ru|barreau\.fr|bashkiria\.ru|bbs\.tr|bc\.ca|bd\.se|be\.tt|"
19 . "bel\.tr|belgie\.be|belgorod\.ru|bg\.tf|bialystok\.pl|bib\.ve|"
20 . "bio\.br|bir\.ru|biz\.az|biz\.bh|biz\.cy|biz\.et|biz\.fj|biz\.ly|"
21 . "biz\.mv|biz\.nr|biz\.om|biz\.pk|biz\.pl|biz\.pr|biz\.tj|biz\.tr|"
22 . "biz\.tt|biz\.vn|bj\.cn|bl\.uk|bmd\.br|bolt\.hu|bourse\.za|br\.com|"
23 . "brand\.se|british-library\.uk|bryansk\.ru|buryatia\.ru|busan\.kr|"
24 . "c\.se|ca\.tf|ca\.tt|ca\.us|casino\.hu|cbg\.ru|cc\.bh|cci\.fr|"
25 . "ch\.tf|ch\.vu|chambagri\.fr|chel\.ru|chelyabinsk\.ru|"
26 . "cherkassy\.ua|chernigov\.ua|chernovtsy\.ua|chiba\.jp|"
27 . "chirurgiens-dentistes\.fr|chita\.ru|chukotka\.ru|chungbuk\.kr|"
28 . "chungnam\.kr|chuvashia\.ru|cim\.br|city\.hu|city\.za|ck\.ua|"
29 . "club\.tw|cmw\.ru|cn\.com|cn\.ua|cng\.br|cnt\.br|co\.ae|co\.ag|"
30 . "co\.am|co\.ao|co\.at|co\.ba|co\.bw|co\.ck|co\.cr|co\.dk|co\.ee|"
31 . "co\.fk|co\.gg|co\.hu|co\.id|co\.il|co\.im|co\.in|co\.ir|co\.je|"
32 . "co\.jp|co\.ke|co\.kr|co\.ls|co\.ma|co\.mu|co\.mw|co\.mz|co\.nz|"
33 . "co\.om|co\.rs|co\.rw|co\.st|co\.th|co\.tj|co\.tt|co\.tv|co\.tz|"
34 . "co\.ua|co\.ug|co\.uk|co\.us|co\.uz|co\.ve|co\.vi|co\.yu|co\.za|"
35 . "co\.zm|co\.zw|com\.ac|com\.ae|com\.af|com\.ag|com\.ai|com\.al|"
36 . "com\.am|com\.an|com\.ar|com\.au|com\.aw|com\.az|com\.ba|com\.bb|"
37 . "com\.bd|com\.bh|com\.bm|com\.bn|com\.bo|com\.br|com\.bs|com\.bt|"
38 . "com\.bz|com\.cd|com\.ch|com\.cn|com\.co|com\.cu|com\.cy|com\.dm|"
39 . "com\.do|com\.dz|com\.ec|com\.ee|com\.eg|com\.er|com\.es|com\.et|"
40 . "com\.fj|com\.fk|com\.fr|com\.ge|com\.gh|com\.gi|com\.gn|com\.gp|"
41 . "com\.gr|com\.gt|com\.gu|com\.hk|com\.hn|com\.hr|com\.ht|com\.io|"
42 . "com\.jm|com\.jo|com\.kg|com\.kh|com\.ki|com\.kw|com\.ky|com\.kz|"
43 . "com\.la|com\.lb|com\.lc|com\.li|com\.lk|com\.lr|com\.lv|com\.ly|"
44 . "com\.mg|com\.mk|com\.mm|com\.mn|com\.mo|com\.mt|com\.mu|com\.mv|"
45 . "com\.mw|com\.mx|com\.my|com\.na|com\.nc|com\.nf|com\.ng|com\.ni|"
46 . "com\.np|com\.nr|com\.om|com\.pa|com\.pe|com\.pf|com\.pg|com\.ph|"
47 . "com\.pk|com\.pl|com\.pr|com\.ps|com\.pt|com\.py|com\.qa|com\.re|"
48 . "com\.ro|com\.ru|com\.rw|com\.sa|com\.sb|com\.sc|com\.sd|com\.sg|"
49 . "com\.sh|com\.st|com\.sv|com\.sy|com\.tj|com\.tn|com\.tr|com\.tt|"
50 . "com\.tw|com\.ua|com\.uy|com\.uz|com\.vc|com\.ve|com\.vi|com\.vn|"
51 . "com\.vu|com\.ws|com\.ye|conf\.au|conf\.lv|consulado\.st|coop\.br|"
52 . "coop\.ht|coop\.mv|coop\.mw|coop\.tt|cpa\.pro|cq\.cn|cri\.nz|"
53 . "crimea\.ua|csiro\.au|ct\.us|cul\.na|cv\.ua|cz\.tf|d\.se|"
54 . "daejeon\.kr|dagestan\.ru|dc\.us|de\.com|de\.net|de\.tf|de\.tt|"
55 . "de\.us|de\.vu|dk\.org|dk\.tt|dn\.ua|dnepropetrovsk\.ua|dni\.us|"
56 . "dns\.be|donetsk\.ua|dp\.ua|dpn\.br|dr\.tr|dudinka\.ru|"
57 . "e-burg\.ru|e\.se|e164\.arpa|ebiz\.tw|ecn\.br|ed\.ao|ed\.cr|ed\.jp|"
58 . "edu\.ac|edu\.af|edu\.ai|edu\.al|edu\.am|edu\.an|edu\.ar|edu\.au|"
59 . "edu\.az|edu\.ba|edu\.bb|edu\.bd|edu\.bh|edu\.bm|edu\.bn|edu\.bo|"
60 . "edu\.br|edu\.bt|edu\.ck|edu\.cn|edu\.co|edu\.cu|edu\.dm|edu\.do|"
61 . "edu\.dz|edu\.ec|edu\.ee|edu\.eg|edu\.er|edu\.es|edu\.et|edu\.ge|"
62 . "edu\.gh|edu\.gi|edu\.gp|edu\.gr|edu\.gt|edu\.gu|edu\.hk|edu\.hn|"
63 . "edu\.ht|edu\.hu|edu\.in|edu\.it|edu\.jm|edu\.jo|edu\.kg|edu\.kh|"
64 . "edu\.kw|edu\.ky|edu\.kz|edu\.lb|edu\.lc|edu\.lk|edu\.lr|edu\.lv|"
65 . "edu\.ly|edu\.mg|edu\.mm|edu\.mn|edu\.mo|edu\.mt|edu\.mv|edu\.mw|"
66 . "edu\.mx|edu\.my|edu\.na|edu\.ng|edu\.ni|edu\.np|edu\.nr|edu\.om|"
67 . "edu\.pa|edu\.pe|edu\.pf|edu\.ph|edu\.pk|edu\.pl|edu\.pr|edu\.ps|"
68 . "edu\.pt|edu\.py|edu\.qa|edu\.rs|edu\.ru|edu\.rw|edu\.sa|edu\.sb|"
69 . "edu\.sc|edu\.sd|edu\.sg|edu\.sh|edu\.sk|edu\.st|edu\.sv|edu\.tf|"
70 . "edu\.tj|edu\.tr|edu\.tt|edu\.tw|edu\.ua|edu\.uk|edu\.uy|edu\.ve|"
71 . "edu\.vi|edu\.vn|edu\.vu|edu\.ws|edu\.ye|edu\.yu|edu\.za|"
72 . "edunet\.tn|ehime\.jp|ekloges\.cy|embaixada\.st|eng\.br|ens\.tn|"
73 . "ernet\.in|erotica\.hu|erotika\.hu|es\.kr|es\.tt|esp\.br|etc\.br|"
74 . "eti\.br|eu\.com|eu\.org|eu\.tf|eu\.tt|eun\.eg|"
75 . "experts-comptables\.fr|f\.se|fam\.pk|far\.br|fareast\.ru|fax\.nr|"
76 . "fed\.us|fgov\.be|fh\.se|fhs\.no|fhsk\.se|fhv\.se|fi\.cr|fie\.ee|"
77 . "film\.hu|fin\.ec|fin\.tn|firm\.co|firm\.ht|firm\.in|firm\.ro|"
78 . "firm\.ve|fj\.cn|fl\.us|fm\.br|fnd\.br|folkebibl\.no|forum\.hu|"
79 . "fot\.br|fr\.tt|fr\.vu|from\.hr|fst\.br|fukui\.jp|fukuoka\.jp|"
80 . "fukushima\.jp|fylkesbibl\.no|g\.se|g12\.br|ga\.us|game\.tw|"
81 . "games\.hu|gangwon\.kr|gb\.com|gb\.net|gc\.ca|gd\.cn|gda\.pl|"
82 . "gdansk\.pl|geek\.nz|gen\.in|gen\.nz|gen\.tr|geometre-expert\.fr|"
83 . "ggf\.br|gifu\.jp|mina\.pl|go\.cr|go\.id|go\.jp|go\.ke|go\.kr|"
84 . "go\.th|go\.tj|go\.tz|go\.ug|gob\.bo|gob\.do|gob\.es|gob\.gt|"
85 . "gob\.hn|gob\.mx|gob\.ni|gob\.pa|gob\.pe|gob\.pk|gob\.sv|gok\.pk|"
86 . "gon\.pk|gop\.pk|gos\.pk|gouv\.fr|gouv\.ht|gouv\.rw|gov\.ac|"
87 . "gov\.ae|gov\.af|gov\.ai|gov\.al|gov\.am|gov\.ar|gov\.au|gov\.az|"
88 . "gov\.ba|gov\.bb|gov\.bd|gov\.bf|gov\.bh|gov\.bm|gov\.bo|gov\.br|"
89 . "gov\.bt|gov\.by|gov\.ch|gov\.ck|gov\.cn|gov\.co|gov\.cu|gov\.cx|"
90 . "gov\.cy|gov\.dm|gov\.do|gov\.dz|gov\.ec|gov\.eg|gov\.er|gov\.et|"
91 . "gov\.fj|gov\.fk|gov\.ge|gov\.gg|gov\.gh|gov\.gi|gov\.gn|gov\.gr|"
92 . "gov\.gu|gov\.hu|gov\.hu|gov\.ie|gov\.il|gov\.im|gov\.in|gov\.io|"
93 . "gov\.ir|gov\.it|gov\.je|gov\.jm|gov\.jo|gov\.jp|gov\.kg|gov\.kh|"
94 . "gov\.kw|gov\.ky|gov\.kz|gov\.lb|gov\.lc|gov\.li|gov\.lk|gov\.lr|"
95 . "gov\.lt|gov\.lu|gov\.lv|gov\.ly|gov\.ma|gov\.mg|gov\.mm|gov\.mn|"
96 . "gov\.mo|gov\.mt|gov\.mv|gov\.mw|gov\.my|gov\.ng|gov\.np|gov\.nr|"
97 . "gov\.om|gov\.ph|gov\.pk|gov\.pl|gov\.pr|gov\.ps|gov\.pt|gov\.py|"
98 . "gov\.qa|gov\.rs|gov\.ru|gov\.rw|gov\.sa|gov\.sb|gov\.sc|gov\.sd|"
99 . "gov\.sg|gov\.sh|gov\.sk|gov\.st|gov\.sy|gov\.tj|gov\.tn|gov\.to|"
100 . "gov\.tp|gov\.tr|gov\.tt|gov\.tv|gov\.tw|gov\.ua|gov\.uk|gov\.ve|"
101 . "gov\.vi|gov\.vn|gov\.ws|gov\.ye|gov\.za|gov\.zm|gov\.zw|govt\.nz|"
102 . "gr\.jp|greta\.fr|grozny\.ru|grp\.lk|gs\.cn|gsm\.pl|gub\.uy|"
103 . "guernsey\.gg|gunma\.jp|gv\.ao|gv\.at|gwangju\.kr|gx\.cn|"
104 . "gyeongbuk\.kr|gyeonggi\.kr|gyeongnam\.kr|gz\.cn|h\.se|ha\.cn|"
105 . "hb\.cn|he\.cn|health\.vn|herad\.no|hi\.cn|hi\.us|hiroshima\.jp|"
106 . "hk\.cn|hl\.cn|hn\.cn|hokkaido\.jp|hotel\.hu|hotel\.lk|hs\.kr|"
107 . "hu\.com|huissier-justice\.fr|hyogo\.jp|i\.se|ia\.us|ibaraki\.jp|"
108 . "icnet\.uk|id\.au|id\.fj|id\.ir|id\.lv|id\.ly|id\.us|idf\.il|"
109 . "idn\.sg|idrett\.no|idv\.hk|idv\.tw|if\.ua|il\.us|imb\.br|"
110 . "in-addr\.arpa|in\.rs|in\.th|in\.ua|in\.us|incheon\.kr|ind\.br|"
111 . "ind\.er|ind\.gg|ind\.gt|ind\.in|ind\.je|ind\.tn|inf\.br|inf\.cu|"
112 . "info\.au|info\.az|info\.bh|info\.co|info\.cu|info\.cy|info\.ec|"
113 . "info\.et|info\.fj|info\.ht|info\.hu|info\.mv|info\.nr|info\.pl|"
114 . "info\.pr|info\.ro|info\.sd|info\.tn|info\.tr|info\.tt|info\.ve|"
115 . "info\.vn|ing\.pa|ingatlan\.hu|inima\.al|int\.am|int\.ar|int\.az|"
116 . "int\.bo|int\.co|int\.lk|int\.mv|int\.mw|int\.pt|int\.ru|int\.rw|"
117 . "int\.tf|int\.tj|int\.tt|int\.ve|int\.vn|intl\.tn|ip6\.arpa|"
118 . "iris\.arpa|irkutsk\.ru|isa\.us|ishikawa\.jp|isla\.pr|it\.ao|"
119 . "it\.tt|ivano-frankivsk\.ua|ivanovo\.ru|iwate\.jp|iwi\.nz|iz\.hr|"
120 . "izhevsk\.ru|jamal\.ru|jar\.ru|jeju\.kr|jeonbuk\.kr|jeonnam\.kr|"
121 . "jersey\.je|jet\.uk|jl\.cn|jobs\.tt|jogasz\.hu|jor\.br|"
122 . "joshkar-ola\.ru|js\.cn|jx\.cn|k-uralsk\.ru|k\.se|k12\.ec|k12\.il|"
123 . "k12\.tr|kagawa\.jp|kagoshima\.jp|kalmykia\.ru|kaluga\.ru|"
124 . "kamchatka\.ru|kanagawa\.jp|kanazawa\.jp|karelia\.ru|katowice\.pl|"
125 . "kawasaki\.jp|kazan\.ru|kchr\.ru|kemerovo\.ru|kg\.kr|kh\.ua|"
126 . "khabarovsk\.ru|khakassia\.ru|kharkov\.ua|kherson\.ua|"
127 . "khmelnitskiy\.ua|khv\.ru|kids\.us|kiev\.ua|kirov\.ru|"
128 . "kirovograd\.ua|kitakyushu\.jp|km\.ua|kms\.ru|kobe\.jp|kochi\.jp|"
129 . "koenig\.ru|komforb\.se|komi\.ru|kommunalforbund\.se|kommune\.no|"
130 . "komvux\.se|konyvelo\.hu|kostroma\.ru|kr\.ua|krakow\.pl|"
131 . "krasnoyarsk\.ru|ks\.ua|ks\.us|kuban\.ru|kumamoto\.jp|kurgan\.ru|"
132 . "kursk\.ru|kustanai\.ru|kuzbass\.ru|kv\.ua|ky\.us|kyonggi\.kr|"
133 . "kyoto\.jp|la\.us|lakas\.hu|lanarb\.se|lanbib\.se|law\.pro|"
134 . "law\.za|lel\.br|lg\.jp|lg\.ua|lipetsk\.ru|lkd\.co\.im|ln\.cn|"
135 . "lodz\.pl|ltd\.co\.im|ltd\.cy|ltd\.gg|ltd\.gi|ltd\.je|ltd\.lk|"
136 . "ltd\.uk|lublin\.pl|lugansk\.ua|lutsk\.ua|lviv\.ua|m\.se|ma\.us|"
137 . "magadan\.ru|magnitka\.ru|mail\.pl|maori\.nz|mari-el\.ru|mari\.ru|"
138 . "marine\.ru|mat\.br|matsuyama\.jp|mb\.ca|md\.us|me\.uk|me\.us|"
139 . "med\.br|med\.ec|med\.ee|med\.ht|med\.ly|med\.om|med\.pa|med\.pro|"
140 . "med\.sa|med\.sd|medecin\.fr|media\.hu|media\.pl|mi\.th|mi\.us|"
141 . "miasta\.pl|mie\.jp|mil\.ac|mil\.ae|mil\.am|mil\.ar|mil\.az|"
142 . "mil\.ba|mil\.bd|mil\.bo|mil\.br|mil\.by|mil\.co|mil\.do|mil\.ec|"
143 . "mil\.eg|mil\.er|mil\.fj|mil\.ge|mil\.gh|mil\.gt|mil\.gu|mil\.hn|"
144 . "mil\.id|mil\.in|mil\.io|mil\.jo|mil\.kg|mil\.kh|mil\.kr|mil\.kw|"
145 . "mil\.kz|mil\.lb|mil\.lt|mil\.lu|mil\.lv|mil\.mg|mil\.mv|mil\.my"
146 . "mil\.no|mil\.np|mil\.nz|mil\.om|mil\.pe|mil\.ph|mil\.pl|mil\.ru|"
147 . "mil\.rw|mil\.se|mil\.sh|mil\.sk|mil\.st|mil\.tj|mil\.tr|mil\.tw|"
148 . "mil\.uk|mil\.uy|mil\.ve|mil\.ye|mil\.za|miyagi\.jp|miyazaki\.jp|"
149 . "mk\.ua|mn\.us|mo\.cn|mo\.us|mob\.nr|mobi\.tt|mobil\.nr|mobile\.nr|"
150 . "mod\.gi|mod\.om|mod\.uk|mordovia\.ru|mosreg\.ru|ms\.kr|ms\.us|"
151 . "msk\.ru|mt\.us|muni\.il|murmansk\.ru|mus\.br|museum\.mn|"
152 . "museum\.mv|museum\.mw|museum\.no|museum\.om|museum\.tt|"
153 . "music\.mobi|mytis\.ru|n\.se|nagano\.jp|nagasaki\.jp|nagoya\.jp|"
154 . "nakhodka\.ru|nalchik\.ru|name\.ae|name\.az|name\.cy|name\.et|"
155 . "name\.fj|name\.hr|name\.mv|name\.my|name\.pr|name\.tj|name\.tr|"
156 . "name\.tt|name\.vn|nara\.jp|nat\.tn|national-library-scotland\.uk|"
157 . "naturbruksgymn\.se|navy\.mil|nb\.ca|nc\.us|nd\.us|ne\.jp|ne\.ke|"
158 . "ne\.kr|ne\.tz|ne\.ug|ne\.us|nel\.uk|net\.ac|net\.ae|net\.af|"
159 . "net\.ag|net\.ai|net\.al|net\.am|net\.an|net\.ar|net\.au|net\.az|"
160 . "net\.ba|net\.bb|net\.bd|net\.bh|net\.bm|net\.bn|net\.bo|net\.br|"
161 . "net\.bs|net\.bt|net\.bz|net\.cd|net\.ch|net\.ck|net\.cn|net\.co|"
162 . "net\.cu|net\.cy|net\.dm|net\.do|net\.dz|net\.ec|net\.eg|net\.er|"
163 . "net\.et|net\.fj|net\.fk|net\.ge|net\.gg|net\.gn|net\.gp|net\.gr|"
164 . "net\.gt|net\.gu|net\.hk|net\.hn|net\.ht|net\.id|net\.il|net\.im|"
165 . "net\.in|net\.io|net\.ir|net\.je|net\.jm|net\.jo|net\.jp|net\.kg|"
166 . "net\.kh|net\.ki|net\.kw|net\.ky|net\.kz|net\.la|net\.lb|net\.lc|"
167 . "net\.li|net\.lk|net\.lr|net\.lu|net\.lv|net\.ly|net\.ma|net\.mm|"
168 . "net\.mo|net\.mt|net\.mu|net\.mv|net\.mw|net\.mx|net\.my|net\.na|"
169 . "net\.nc|net\.nf|net\.ng|net\.ni|net\.np|net\.nr|net\.nz|net\.om|"
170 . "net\.pa|net\.pe|net\.pg|net\.ph|net\.pk|net\.pl|net\.pr|net\.ps|"
171 . "net\.pt|net\.py|net\.qa|net\.ru|net\.rw|net\.sa|net\.sb|net\.sc|"
172 . "net\.sd|net\.sg|net\.sh|net\.st|net\.sy|net\.tf|net\.th|net\.tj|"
173 . "net\.tn|net\.tr|net\.tt|net\.tw|net\.ua|net\.uk|net\.uy|net\.uz|"
174 . "net\.vc|net\.ve|net\.vi|net\.vn|net\.vu|net\.ws|net\.ye|net\.za|"
175 . "new\.ke|news\.hu|nf\.ca|ngo\.lk|ngo\.ph|ngo\.pl|ngo\.za|nh\.us|"
176 . "nhs\.uk|nic\.im|nic\.in|nic\.tt|nic\.uk|nieruchomosci\.pl|"
177 . "niigata\.jp|nikolaev\.ua|nj\.us|nkz\.ru|nl\.ca|nls\.uk|nm\.cn|"
178 . "nm\.us|nnov\.ru|no\.com|nom\.ad|nom\.ag|nom\.br|nom\.co|nom\.es|"
179 . "nom\.fk|nom\.fr|nom\.mg|nom\.ni|nom\.pa|nom\.pe|nom\.pl|nom\.re|"
180 . "nom\.ro|nom\.ve|nom\.za|nome\.pt|norilsk\.ru|not\.br|notaires\.fr|"
181 . "nov\.ru|novosibirsk\.ru|ns\.ca|nsk\.ru|nsn\.us|nsw\.au|nt\.au|"
182 . "nt\.ca|nt\.ro|ntr\.br|nu\.ca|nui\.hu|nv\.us|nx\.cn|ny\.us|o\.se|"
183 . "od\.ua|odessa\.ua|odo\.br|off\.ai|odessa\.ua|odo\.br|off\.ai|"
184 . "og\.ao|oh\.us|oita\.jp|ok\.us|okayama\.jp|okinawa\.jp|olsztyn\.pl|"
185 . "omsk\.ru|on\.ca|opole\.pl|or\.at|or\.cr|or\.id|or\.jp|or\.ke|"
186 . "or\.kr|or\.th|or\.tz|or\.ug|or\.us|orenburg\.ru|org\.ac|org\.ae|"
187 . "org\.ag|org\.ai|org\.al|org\.am|org\.an|org\.ar|org\.au|org\.az|"
188 . "org\.ba|org\.bb|org\.bd|org\.bh|org\.bm|org\.bn|org\.bo|org\.br|"
189 . "org\.bs|org\.bt|org\.bw|org\.bz|org\.cd|org\.ch|org\.ck|org\.cn|"
190 . "org\.co|org\.cu|org\.cy|org\.dm|org\.do|org\.dz|org\.ec|org\.ee|"
191 . "org\.eg|org\.er|org\.es|org\.et|org\.fj|org\.fk|org\.ge|org\.gg|"
192 . "org\.gh|org\.gi|org\.gn|org\.gp|org\.gr|org\.gt|org\.gu|org\.hk|"
193 . "org\.hn|org\.ht|org\.hu|org\.il|org\.im|org\.in|org\.io|org\.ir|"
194 . "org\.je|org\.jm|org\.jo|org\.jp|org\.kg|org\.kh|org\.ki|org\.kw|"
195 . "org\.ky|org\.kz|org\.la|org\.lb|org\.lc|org\.li|org\.lk|org\.lr|"
196 . "org\.ls|org\.lu|org\.lv|org\.ly|org\.ma|org\.mg|org\.mk|org\.mm|"
197 . "org\.mn|org\.mo|org\.mt|org\.mu|org\.mv|org\.mw|org\.mx|org\.my|"
198 . "org\.na|org\.nc|org\.ng|org\.ni|org\.np|org\.nr|org\.nz|org\.om|"
199 . "org\.pa|org\.pe|org\.pf|org\.ph|org\.pk|org\.pl|org\.pr|org\.ps|"
200 . "org\.pt|org\.py|org\.qa|org\.ro|org\.rs|org\.ru|org\.sa|org\.sb|"
201 . "org\.sc|org\.sd|org\.se|org\.sg|org\.sh|org\.st|org\.sv|org\.sy|"
202 . "org\.tj|org\.tn|org\.tr|org\.tt|org\.tw|org\.ua|org\.uk|org\.uy|"
203 . "org\.uz|org\.vc|org\.ve|org\.vi|org\.vn|org\.vu|org\.ws|org\.ye|"
204 . "org\.yu|org\.za|org\.zm|org\.zw|oryol\.ru|osaka\.jp|oskol\.ru|"
205 . "otc\.au|oz\.au|pa\.us|palana\.ru|parliament\.cy|parliament\.uk|"
206 . "parti\.se|pb\.ao|pc\.pl|pe\.ca|pe\.kr|penza\.ru|per\.kh|per\.sg|"
207 . "perm\.ru|perso\.ht|pharmacien\.fr|pl\.tf|pl\.ua|plc\.co\.im|"
208 . "plc\.ly|plc\.uk|plo\.ps|pol\.dz|pol\.ht|pol\.tr|police\.uk|"
209 . "poltava\.ua|port\.fr|powiat\.pl|poznan\.pl|pp\.az|pp\.ru|pp\.se|"
210 . "ppg\.br|prd\.fr|prd\.mg|press\.cy|press\.ma|press\.se|presse\.fr|"
211 . "pri\.ee|principe\.st|priv\.at|priv\.hu|priv\.no|priv\.pl|pro\.ae|"
212 . "pro\.br|pro\.cy|pro\.ec|pro\.fj|pro\.ht|pro\.mv|pro\.om|pro\.pr|"
213 . "pro\.tt|pro\.vn|psc\.br|psi\.br|pskov\.ru|ptz\.ru|pub\.sa|"
214 . "publ\.pt|pvt\.ge|pyatigorsk\.ru|qc\.ca|qc\.com|qh\.cn|qld\.au|"
215 . "qsl\.br|re\.kr|realestate\.pl|rec\.br|rec\.co|rec\.ro|rec\.ve|"
216 . "red\.sv|reklam\.hu|rel\.ht|rel\.pl|res\.in|ri\.us|rnd\.ru|"
217 . "rnrt\.tn|rns\.tn|rnu\.tn|rovno\.ua|rs\.ba|ru\.com|ru\.tf|"
218 . "rubtsovsk\.ru|rv\.ua|ryazan\.ru|s\.se|sa\.au|sa\.com|sa\.cr|"
219 . "saga\.jp|saitama\.jp|sakhalin\.ru|samara\.ru|saotome\.st|"
220 . "sapporo\.jp|saratov\.ru|sark\.gg|sc\.cn|sc\.ke|sc\.kr|sc\.ug|"
221 . "sc\.us|sch\.ae|sch\.gg|sch\.id|sch\.ir|sch\.je|sch\.lk|sch\.ly|"
222 . "sch\.ng|sch\.om|sch\.sa|sch\.sd|sch\.uk|sch\.zm|school\.fj|"
223 . "school\.nz|school\.za|sci\.eg|sd\.cn|sd\.us|se\.com|se\.tt|"
224 . "sebastopol\.ua|sec\.ps|sendai\.jp|seoul\.kr|sex\.hu|sex\.pl|"
225 . "sg\.tf|sh\.cn|shiga\.jp|shimane\.jp|shizuoka\.jp|shop\.ht|"
226 . "shop\.hu|shop\.pl|simbirsk\.ru|sk\.ca|sklep\.pl|sld\.do|sld\.pa|"
227 . "slg\.br|slupsk\.pl|smolensk\.ru|sn\.cn|snz\.ru|soc\.lk|"
228 . "soros\.al|sos\.pl|spb\.ru|sport\.hu|srv\.br|sshn\.se|stat\.no|"
229 . "stavropol\.ru|store\.co|store\.ro|store\.st|store\.ve|stv\.ru|"
230 . "suli\.hu|sumy\.ua|surgut\.ru|sx\.cn|syzran\.ru|szczecin\.pl|"
231 . "szex\.hu|szkola\.pl|t\.se|takamatsu\.jp|tambov\.ru|targi\.pl|"
232 . "tas\.au|tatarstan\.ru|te\.ua|tec\.ve|tel\.no|tel\.nr|tel\.tr|"
233 . "telecom\.na|telememo\.au|ternopil\.ua|test\.ru|tirana\.al|tj\.cn|"
234 . "tld\.am|tlf\.nr|tm\.cy|tm\.fr|tm\.hu|tm\.mc|tm\.mg|tm\.mt|"
235 . "tm\.pl|tm\.ro|tm\.se|tm\.za|tmp\.br|tn\.us|tochigi\.jp|"
236 . "tokushima\.jp|tokyo\.jp|tom\.ru|tomsk\.ru|torun\.pl|tottori\.jp|"
237 . "tourism\.pl|tourism\.tn|toyama\.jp|tozsde\.hu|travel\.pl|"
238 . "travel\.tt|trd\.br|tsaritsyn\.ru|tsk\.ru|tula\.ru|tur\.br|"
239 . "turystyka\.pl|tuva\.ru|tv\.bo|tv\.br|tv\.sd|tver\.ru|tw\.cn|"
240 . "tx\.us|tyumen\.ru|u\.se|udm\.ru|udmurtia\.ru|uk\.com|uk\.net|"
241 . "uk\.tt|ulan-ude\.ru|ulsan\.kr|unam\.na|unbi\.ba|uniti\.al|"
242 . "unsa\.ba|upt\.al|uri\.arpa|urn\.arpa|us\.com|us\.tf|us\.tt|"
243 . "ut\.us|utazas\.hu|utsunomiya\.jp|uu\.mt|uy\.com|uzhgorod\.ua|"
244 . "va\.us|vatican\.va|vdonsk\.ru|vet\.br|veterinaire\.fr|vgs\.no|"
245 . "vic\.au|video\.hu|vinnica\.ua|vladikavkaz\.ru|vladimir\.ru|"
246 . "vladivostok\.ru|vn\.ua|volgograd\.ru||vologda\.ru|voronezh\.ru|"
247 . "vrn\.ru|vt\.us|vyatka\.ru|w\.se|wa\.au|wa\.us|wakayama\.jp|"
248 . "warszawa\.pl|waw\.pl|weather\.mobi|web\.co|web\.do|web\.id|"
249 . "web\.lk|web\.pk|web\.tj|web\.tr|web\.ve|web\.za|wi\.us|wroc\.pl|"
250 . "wroclaw\.pl|wv\.us|www\.ro|wy\.us|x\.se|xj\.cn|xz\.cn|y\.se|"
251 . "yakutia\.ru|yamagata\.jp|yamaguchi\.jp|yamal\.ru|yamanashi\.jp|"
252 . "yaroslavl\.ru|yekaterinburg\.ru|yk\.ca|yn\.cn|yokohama\.jp|"
253 . "yuzhno-sakhalinsk\.ru|z\.se|za\.com|za\.pl|zaporizhzhe\.ua|"
254 . "zgora\.pl|zgrad\.ru|zhitomir\.ua|zj\.cn|zlg\.br|zp\.ua|zt\.ua)";
255?>
tighturl.urlpattern.inc.php
1<?php
2
3  $validschemes = "(http|https|ftp|sftp)";
4
5  $validurlpattern = "\:\/\/([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)"
6   . "*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])"
7   . "\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)"
8   . "\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)"
9   . "\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])"
10   . "|((([0-9A-F]{1,4}(((:[0-9A-F]{1,4}){5}::[0-9A-F]{1,4})|((:[0-9A-F]{1,4}){4}"
11   . "::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,1})|((:[0-9A-F]{1,4}){3}::[0-9A-F]{1,4}"
12   . "(:[0-9A-F]{1,4}){0,2})|((:[0-9A-F]{1,4}){2}::[0-9A-F]{1,4}(:[0-9A-F]{1,4})"
13   . "{0,3})|(:[0-9A-F]{1,4}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,4})|(::[0-9A-F]{1,4}"
14   . "(:[0-9A-F]{1,4}){0,5})|(:[0-9A-F]{1,4}){7}))|(::[0-9A-F]{1,4}(:[0-9A-F]{1,4}"
15   . "){0,6}))|::)|((([0-9A-F]{1,4}(((:[0-9A-F]{1,4}){3}::([0-9A-F]{1,4}){1})"
16   . "|((:[0-9A-F]{1,4}){2}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,1})|((:[0-9A-F]{1,4})"
17   . "{1}::[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,2})|(::[0-9A-F]{1,4}(:[0-9A-F]{1,4}"
18   . "){0,3})|((:[0-9A-F]{1,4}){0,5})))|([:]{2}[0-9A-F]{1,4}(:[0-9A-F]{1,4}){0,4}))"
19   . ":|::)((25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{0,2})\.){3}(25[0-5]|2[0-4][0-9]|"
20   . "[0-1]?[0-9]{0,2})"
21   . "|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org"
22   . "|mobi|biz|arpa|info|name|pro|aero|coop|museum|asia|cat|jobs|tel|travel"
23   . "|[a-zA-Z]{2}))(\:[0-9]+)*(\/.($|[a-zA-Z0-9\.\:\,\?\'\(\)\\\*\+&%\$;|#\=~_\-\s@]*))*\/*";
24?>

Archive Download the corresponding diff file

Branches