Version Description
Download this release
Release Info
Developer | error |
Plugin | Bad Behavior |
Version | 1.1.3 |
Comparing to | |
See all releases |
Code changes from version 1.1 to 1.1.3
- README.txt +3 -3
- bad-behavior-core.php +8 -8
- bad-behavior-database.php +8 -10
- bad-behavior-generic.php +4 -0
- bad-behavior-http-headers.php +6 -4
- bad-behavior-mediawiki.php +5 -1
- bad-behavior-msnbot.php +5 -1
- bad-behavior-user-agent.php +4 -1
- bad-behavior-wordpress.php +5 -1
README.txt
CHANGED
@@ -17,11 +17,11 @@ As the operator of a Web site, this can cause you several problems. First, the s
|
|
17 |
Bad Behavior intends to target any malicious software directed at a Web site, whether it be a spambot, ill-designed search engine bot, or system crackers. In that spirit, it is not limited to WordPress users; a generic interface has been provided whereby it can be integrated into virtually any PHP-based software.
|
18 |
|
19 |
== Installation ==
|
20 |
-
SeeAlso: http://www.ioerror.us/software/bad-behavior/installing-and-using-bad-behavior/
|
21 |
|
22 |
1. Bad Behavior installs like any other multi-file WordPress plugin. Unzip the bad-behavior.zip file, and you will have a bad-behavior folder containing all the Bad Behavior files.
|
23 |
|
24 |
-
2. Before uploading, edit the bad-behavior/bad-behavior-wordpress
|
25 |
|
26 |
3. Upload the folder and its contents to your wp-content/plugins directory, taking care to use ASCII mode. Once on the server, activate the plugin from your admin page.
|
27 |
|
@@ -38,4 +38,4 @@ If you continue to have trouble, contact me and provide a copy of the logs which
|
|
38 |
|
39 |
= How can I view Bad Behavior's log files? =
|
40 |
|
41 |
-
To view the Bad Behavior log, you will need a copy of phpMyAdmin installed, or some other way to view the database. Bad Behavior stores its log in the
|
17 |
Bad Behavior intends to target any malicious software directed at a Web site, whether it be a spambot, ill-designed search engine bot, or system crackers. In that spirit, it is not limited to WordPress users; a generic interface has been provided whereby it can be integrated into virtually any PHP-based software.
|
18 |
|
19 |
== Installation ==
|
20 |
+
SeeAlso: http://www.ioerror.us/software/bad-behavior/installing-and-using-bad-behavior/on-wordpress/
|
21 |
|
22 |
1. Bad Behavior installs like any other multi-file WordPress plugin. Unzip the bad-behavior.zip file, and you will have a bad-behavior folder containing all the Bad Behavior files.
|
23 |
|
24 |
+
2. Before uploading, edit the bad-behavior/bad-behavior-wordpress.php file and customize the configuration variables there. When logging is on, all blocked requests will be logged. When verbose logging is on, all requests - successful or not - will be logged. And the logging duration specifies how many days worth of logs will be stored in the database. I recommend not using verbose logging without a really good reason, as your database will fill up fast.
|
25 |
|
26 |
3. Upload the folder and its contents to your wp-content/plugins directory, taking care to use ASCII mode. Once on the server, activate the plugin from your admin page.
|
27 |
|
38 |
|
39 |
= How can I view Bad Behavior's log files? =
|
40 |
|
41 |
+
To view the Bad Behavior log, you will need a copy of phpMyAdmin installed, or some other way to view the database. Bad Behavior stores its log in the wp_bad_behavior_log table in your WordPress database. Browse or search through it with phpMyAdmin, the MySQL command line, or another tool. At this time Bad Behavior does not come with a built-in log viewer, though this feature is planned.
|
bad-behavior-core.php
CHANGED
@@ -27,15 +27,9 @@ if (version_compare(phpversion(), "5.0.0") < 0) {
|
|
27 |
require_once(WP_BB_CWD . "/bad-behavior-php4.php");
|
28 |
}
|
29 |
|
30 |
-
// Load up database stuff only if requested
|
31 |
-
if ($wp_bb_verbose_logging || $wp_bb_logging) {
|
32 |
-
require_once(WP_BB_CWD . "/bad-behavior-database.php");
|
33 |
-
}
|
34 |
-
|
35 |
// Set up some initial variables.
|
36 |
$wp_bb_approved = 2;
|
37 |
$wp_bb_db_failure = FALSE;
|
38 |
-
$wp_bb_log = 'bad_behavior_log';
|
39 |
$wp_bb_remote_addr = $_SERVER['REMOTE_ADDR'];
|
40 |
$wp_bb_request_method = $_SERVER['REQUEST_METHOD'];
|
41 |
$wp_bb_http_host = $_SERVER['HTTP_HOST'];
|
@@ -48,6 +42,11 @@ else
|
|
48 |
$wp_bb_http_user_agent = $_SERVER['HTTP_USER_AGENT'];
|
49 |
$wp_bb_server_signature = $_SERVER['SERVER_SIGNATURE'];
|
50 |
|
|
|
|
|
|
|
|
|
|
|
51 |
// Reconstruct the entire HTTP headers as received.
|
52 |
$wp_bb_headers = "$wp_bb_request_method $wp_bb_request_uri $wp_bb_server_protocol\n";
|
53 |
$wp_bb_http_headers = getheaders();
|
@@ -83,7 +82,7 @@ elseif (stripos($wp_bb_http_user_agent, "msnbot") !== FALSE) {
|
|
83 |
}
|
84 |
elseif (stripos($wp_bb_http_user_agent, "Googlebot") !== FALSE ||
|
85 |
stripos($wp_bb_http_user_agent, "Mediapartners-Google") !== FALSE) {
|
86 |
-
require_once(WP_BB_CWD . "/bad-behavior-
|
87 |
}
|
88 |
// Now analyze requests coming from "Konqueror"
|
89 |
elseif (stripos($wp_bb_http_user_agent, "Konqueror") !== FALSE) {
|
@@ -101,7 +100,8 @@ elseif (stripos($wp_bb_http_user_agent, "Lynx") !== FALSE) {
|
|
101 |
elseif (stripos($wp_bb_http_user_agent, "MovableType") !== FALSE) {
|
102 |
require_once(WP_BB_CWD . "/bad-behavior-movabletype.php");
|
103 |
}
|
104 |
-
elseif (stripos($wp_bb_http_user_agent, "Mozilla") !== FALSE
|
|
|
105 |
require_once(WP_BB_CWD . "/bad-behavior-mozilla.php");
|
106 |
}
|
107 |
|
27 |
require_once(WP_BB_CWD . "/bad-behavior-php4.php");
|
28 |
}
|
29 |
|
|
|
|
|
|
|
|
|
|
|
30 |
// Set up some initial variables.
|
31 |
$wp_bb_approved = 2;
|
32 |
$wp_bb_db_failure = FALSE;
|
|
|
33 |
$wp_bb_remote_addr = $_SERVER['REMOTE_ADDR'];
|
34 |
$wp_bb_request_method = $_SERVER['REQUEST_METHOD'];
|
35 |
$wp_bb_http_host = $_SERVER['HTTP_HOST'];
|
42 |
$wp_bb_http_user_agent = $_SERVER['HTTP_USER_AGENT'];
|
43 |
$wp_bb_server_signature = $_SERVER['SERVER_SIGNATURE'];
|
44 |
|
45 |
+
// Load up database stuff only if requested
|
46 |
+
if ($wp_bb_verbose_logging || $wp_bb_logging) {
|
47 |
+
require_once(WP_BB_CWD . "/bad-behavior-database.php");
|
48 |
+
}
|
49 |
+
|
50 |
// Reconstruct the entire HTTP headers as received.
|
51 |
$wp_bb_headers = "$wp_bb_request_method $wp_bb_request_uri $wp_bb_server_protocol\n";
|
52 |
$wp_bb_http_headers = getheaders();
|
82 |
}
|
83 |
elseif (stripos($wp_bb_http_user_agent, "Googlebot") !== FALSE ||
|
84 |
stripos($wp_bb_http_user_agent, "Mediapartners-Google") !== FALSE) {
|
85 |
+
require_once(WP_BB_CWD . "/bad-behavior-google.php");
|
86 |
}
|
87 |
// Now analyze requests coming from "Konqueror"
|
88 |
elseif (stripos($wp_bb_http_user_agent, "Konqueror") !== FALSE) {
|
100 |
elseif (stripos($wp_bb_http_user_agent, "MovableType") !== FALSE) {
|
101 |
require_once(WP_BB_CWD . "/bad-behavior-movabletype.php");
|
102 |
}
|
103 |
+
elseif (stripos($wp_bb_http_user_agent, "Mozilla") !== FALSE &&
|
104 |
+
stripos($wp_bb_http_user_agent, "Mozilla") == 0) {
|
105 |
require_once(WP_BB_CWD . "/bad-behavior-mozilla.php");
|
106 |
}
|
107 |
|
bad-behavior-database.php
CHANGED
@@ -6,15 +6,13 @@
|
|
6 |
if (!defined('WP_BB_CWD'))
|
7 |
die('');
|
8 |
|
9 |
-
$wp_bb_log = "bad_behavior_log";
|
10 |
-
|
11 |
function wp_bb_db_create_tables() {
|
12 |
-
global $
|
13 |
|
14 |
if (defined("WP_BB_NO_CREATE"))
|
15 |
return;
|
16 |
|
17 |
-
$query = "CREATE TABLE IF NOT EXISTS
|
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',
|
@@ -31,9 +29,9 @@ function wp_bb_db_create_tables() {
|
|
31 |
$wp_bb_db_failure = TRUE;
|
32 |
}
|
33 |
// Upgrades from 1.0
|
34 |
-
$query = "DESCRIBE `
|
35 |
if (wp_bb_db_query($query) == 0) {
|
36 |
-
$query = "ALTER TABLE `
|
37 |
if (wp_bb_db_query($query) === FALSE) {
|
38 |
$wp_bb_db_failure = TRUE;
|
39 |
}
|
@@ -41,9 +39,9 @@ function wp_bb_db_create_tables() {
|
|
41 |
}
|
42 |
|
43 |
function wp_bb_db_clear_old_entries() {
|
44 |
-
global $
|
45 |
|
46 |
-
$query = "DELETE FROM
|
47 |
`date` < DATE_SUB('" . gmstrftime("%Y-%m-%d %H:%M:%S") .
|
48 |
"', INTERVAL $wp_bb_logging_duration DAY)";
|
49 |
if (wp_bb_db_query($query) === FALSE) {
|
@@ -59,7 +57,7 @@ function wp_bb_db_sanitize($untrusted_input) {
|
|
59 |
function wp_bb_db_log($response) {
|
60 |
global $wp_bb_remote_addr, $wp_bb_request_method, $wp_bb_http_host;
|
61 |
global $wp_bb_request_uri, $wp_bb_server_protocol, $wp_bb_http_referer;
|
62 |
-
global $wp_bb_http_user_agent, $wp_bb_headers
|
63 |
global $wp_bb_request_entity;
|
64 |
|
65 |
// Sanitize input
|
@@ -75,7 +73,7 @@ function wp_bb_db_log($response) {
|
|
75 |
$response = intval($response);
|
76 |
|
77 |
$date = wp_bb_date();
|
78 |
-
$query = "INSERT INTO
|
79 |
(`ip`, `date`, `request_method`, `http_host`, `request_uri`, `server_protocol`, `http_referer`, `http_user_agent`, `http_headers`, `request_entity`, `http_response`) VALUES
|
80 |
('$remote_addr', '$date', '$request_method', '$host', '$request_uri', '$server_protocol', '$referer', '$user_agent', '$headers', '$request_entity', '$response')";
|
81 |
if (wp_bb_db_query($query) === FALSE) {
|
6 |
if (!defined('WP_BB_CWD'))
|
7 |
die('');
|
8 |
|
|
|
|
|
9 |
function wp_bb_db_create_tables() {
|
10 |
+
global $wp_bb_db_failure;
|
11 |
|
12 |
if (defined("WP_BB_NO_CREATE"))
|
13 |
return;
|
14 |
|
15 |
+
$query = "CREATE TABLE IF NOT EXISTS `" . WP_BB_LOG . "` (
|
16 |
`id` int(11) NOT NULL auto_increment,
|
17 |
`ip` text NOT NULL,
|
18 |
`date` datetime NOT NULL default '0000-00-00 00:00:00',
|
29 |
$wp_bb_db_failure = TRUE;
|
30 |
}
|
31 |
// Upgrades from 1.0
|
32 |
+
$query = "DESCRIBE `" . WP_BB_LOG . "` `request_entity`;";
|
33 |
if (wp_bb_db_query($query) == 0) {
|
34 |
+
$query = "ALTER TABLE `" . WP_BB_LOG . "` ADD `request_entity` TEXT AFTER `http_headers`;";
|
35 |
if (wp_bb_db_query($query) === FALSE) {
|
36 |
$wp_bb_db_failure = TRUE;
|
37 |
}
|
39 |
}
|
40 |
|
41 |
function wp_bb_db_clear_old_entries() {
|
42 |
+
global $wp_bb_logging_duration;
|
43 |
|
44 |
+
$query = "DELETE FROM `" . WP_BB_LOG . "` WHERE
|
45 |
`date` < DATE_SUB('" . gmstrftime("%Y-%m-%d %H:%M:%S") .
|
46 |
"', INTERVAL $wp_bb_logging_duration DAY)";
|
47 |
if (wp_bb_db_query($query) === FALSE) {
|
57 |
function wp_bb_db_log($response) {
|
58 |
global $wp_bb_remote_addr, $wp_bb_request_method, $wp_bb_http_host;
|
59 |
global $wp_bb_request_uri, $wp_bb_server_protocol, $wp_bb_http_referer;
|
60 |
+
global $wp_bb_http_user_agent, $wp_bb_headers;
|
61 |
global $wp_bb_request_entity;
|
62 |
|
63 |
// Sanitize input
|
73 |
$response = intval($response);
|
74 |
|
75 |
$date = wp_bb_date();
|
76 |
+
$query = "INSERT INTO `" . WP_BB_LOG . "`
|
77 |
(`ip`, `date`, `request_method`, `http_host`, `request_uri`, `server_protocol`, `http_referer`, `http_user_agent`, `http_headers`, `request_entity`, `http_response`) VALUES
|
78 |
('$remote_addr', '$date', '$request_method', '$host', '$request_uri', '$server_protocol', '$referer', '$user_agent', '$headers', '$request_entity', '$response')";
|
79 |
if (wp_bb_db_query($query) === FALSE) {
|
bad-behavior-generic.php
CHANGED
@@ -47,6 +47,10 @@ $wp_bb_logging_duration = 7;
|
|
47 |
// should NOT munge it here!
|
48 |
$wp_bb_email = "badbots@ioerror.us";
|
49 |
|
|
|
|
|
|
|
|
|
50 |
###############################################################################
|
51 |
|
52 |
# DO NOT EDIT BELOW THIS LINE
|
47 |
// should NOT munge it here!
|
48 |
$wp_bb_email = "badbots@ioerror.us";
|
49 |
|
50 |
+
// The database table name to use.
|
51 |
+
// You can customize the table name if necessary.
|
52 |
+
define('WP_BB_LOG', /* $software_specific_prefix . */ 'bad_behavior_log');
|
53 |
+
|
54 |
###############################################################################
|
55 |
|
56 |
# DO NOT EDIT BELOW THIS LINE
|
bad-behavior-http-headers.php
CHANGED
@@ -12,7 +12,7 @@ if (!defined('WP_BB_CWD'))
|
|
12 |
// FIXME: whitelist whois.sc netblocks when rwhoisd.ccom.net becomes available
|
13 |
if (array_key_exists('Range', $wp_bb_http_headers_mixed) &&
|
14 |
strpos($wp_bb_http_headers_mixed['Range'], "=0-") !== FALSE) {
|
15 |
-
if (strncmp($wp_bb_http_user_agent, "MovableType"))
|
16 |
wp_bb_spammer();
|
17 |
}
|
18 |
|
@@ -21,9 +21,11 @@ if (array_key_exists('via', $wp_bb_http_headers)) {
|
|
21 |
wp_bb_spammer();
|
22 |
}
|
23 |
// pinappleproxy is used by referrer spammers
|
24 |
-
if (array_key_exists('Via', $wp_bb_http_headers_mixed)
|
25 |
-
|
26 |
-
|
|
|
|
|
27 |
}
|
28 |
|
29 |
// Headers which are not seen from normal user agents; only malicious bots
|
12 |
// FIXME: whitelist whois.sc netblocks when rwhoisd.ccom.net becomes available
|
13 |
if (array_key_exists('Range', $wp_bb_http_headers_mixed) &&
|
14 |
strpos($wp_bb_http_headers_mixed['Range'], "=0-") !== FALSE) {
|
15 |
+
if (strncmp($wp_bb_http_user_agent, "MovableType", 11))
|
16 |
wp_bb_spammer();
|
17 |
}
|
18 |
|
21 |
wp_bb_spammer();
|
22 |
}
|
23 |
// pinappleproxy is used by referrer spammers
|
24 |
+
if (array_key_exists('Via', $wp_bb_http_headers_mixed)) {
|
25 |
+
if (stripos($wp_bb_http_headers_mixed['Via'], "pinappleproxy") !== FALSE ||
|
26 |
+
stripos($wp_bb_http_headers_mixed['Via'], "PCNETSERVER") !== FALSE) {
|
27 |
+
wp_bb_spammer();
|
28 |
+
}
|
29 |
}
|
30 |
|
31 |
// Headers which are not seen from normal user agents; only malicious bots
|
bad-behavior-mediawiki.php
CHANGED
@@ -57,6 +57,10 @@ $wp_bb_logging_duration = 7;
|
|
57 |
// should NOT munge it here!
|
58 |
$wp_bb_email = $wgEmergencyContact;
|
59 |
|
|
|
|
|
|
|
|
|
60 |
###############################################################################
|
61 |
|
62 |
# DO NOT EDIT BELOW THIS LINE
|
@@ -87,7 +91,7 @@ function wp_bb_mediawiki_run() {
|
|
87 |
global $wp_bb_logging, $wp_bb_verbose_logging, $wp_bb_logging_duration, $wp_bb_email;
|
88 |
|
89 |
// globals defined in core
|
90 |
-
global $wp_bb_approved, $wp_bb_db_failure
|
91 |
global $wp_bb_remote_addr, $wp_bb_request_method, $wp_bb_http_host;
|
92 |
global $wp_bb_request_uri, $wp_bb_server_protocol, $wp_bb_http_referer;
|
93 |
global $wp_bb_http_user_agent, $wp_bb_server_signature;
|
57 |
// should NOT munge it here!
|
58 |
$wp_bb_email = $wgEmergencyContact;
|
59 |
|
60 |
+
// The database table name to use.
|
61 |
+
// You can customize the table name if necessary.
|
62 |
+
define('WP_BB_LOG', $wgDBprefix . 'bad_behavior_log');
|
63 |
+
|
64 |
###############################################################################
|
65 |
|
66 |
# DO NOT EDIT BELOW THIS LINE
|
91 |
global $wp_bb_logging, $wp_bb_verbose_logging, $wp_bb_logging_duration, $wp_bb_email;
|
92 |
|
93 |
// globals defined in core
|
94 |
+
global $wp_bb_approved, $wp_bb_db_failure;
|
95 |
global $wp_bb_remote_addr, $wp_bb_request_method, $wp_bb_http_host;
|
96 |
global $wp_bb_request_uri, $wp_bb_server_protocol, $wp_bb_http_referer;
|
97 |
global $wp_bb_http_user_agent, $wp_bb_server_signature;
|
bad-behavior-msnbot.php
CHANGED
@@ -7,7 +7,11 @@ if (!defined('WP_BB_CWD'))
|
|
7 |
|
8 |
// require_once(WP_BB_CWD . "/bad-behavior-accept.php");
|
9 |
|
10 |
-
if (matchCIDR($wp_bb_remote_addr, "207.46.0.0/16") === FALSE
|
|
|
|
|
|
|
|
|
11 |
wp_bb_spammer();
|
12 |
}
|
13 |
|
7 |
|
8 |
// require_once(WP_BB_CWD . "/bad-behavior-accept.php");
|
9 |
|
10 |
+
if (matchCIDR($wp_bb_remote_addr, "207.46.0.0/16") === FALSE &&
|
11 |
+
matchCIDR($wp_bb_remote_addr, "65.52.0.0/14") === FALSE &&
|
12 |
+
matchCIDR($wp_bb_remote_addr, "207.68.128.0/18") === FALSE &&
|
13 |
+
matchCIDR($wp_bb_remote_addr, "207.68.192.0/20") === FALSE &&
|
14 |
+
matchCIDR($wp_bb_remote_addr, "64.4.0.0/18") === FALSE) {
|
15 |
wp_bb_spammer();
|
16 |
}
|
17 |
|
bad-behavior-user-agent.php
CHANGED
@@ -15,11 +15,12 @@ $wp_bb_spambots_str0 = array(
|
|
15 |
"Email Siphon", // spam harvester
|
16 |
"grub crawler", // misc comment/email spam
|
17 |
// "Java 1.", // Some doubt about this one
|
18 |
-
"libwww-perl", // exploited boxes
|
19 |
"LWP", // exploited boxes
|
20 |
"Microsoft URL", // spam harvester
|
21 |
"Missigua", // spam harvester
|
22 |
"Mozilla ", // forum exploits
|
|
|
|
|
23 |
"www.weblogs.com", // referrer spam (not the real www.weblogs.com)
|
24 |
);
|
25 |
// Occurs anywhere in the string
|
@@ -28,6 +29,8 @@ $wp_bb_spambots_str = array(
|
|
28 |
"DTS Agent", // misc comment/email spam
|
29 |
"grub-client", // search engine ignores robots.txt
|
30 |
"Indy Library", // misc comment/email spam
|
|
|
|
|
31 |
"POE-Component-Client", // free poker, etc.
|
32 |
"WISEbot", // spam harvester
|
33 |
"WISEnutbot", // spam harvester
|
15 |
"Email Siphon", // spam harvester
|
16 |
"grub crawler", // misc comment/email spam
|
17 |
// "Java 1.", // Some doubt about this one
|
|
|
18 |
"LWP", // exploited boxes
|
19 |
"Microsoft URL", // spam harvester
|
20 |
"Missigua", // spam harvester
|
21 |
"Mozilla ", // forum exploits
|
22 |
+
"Shockwave Flash", // spam harvester
|
23 |
+
"Wordpress Hash Grabber",// malicious software
|
24 |
"www.weblogs.com", // referrer spam (not the real www.weblogs.com)
|
25 |
);
|
26 |
// Occurs anywhere in the string
|
29 |
"DTS Agent", // misc comment/email spam
|
30 |
"grub-client", // search engine ignores robots.txt
|
31 |
"Indy Library", // misc comment/email spam
|
32 |
+
"libwww-perl", // exploited boxes
|
33 |
+
".NET CLR 1)", // free poker, etc.
|
34 |
"POE-Component-Client", // free poker, etc.
|
35 |
"WISEbot", // spam harvester
|
36 |
"WISEnutbot", // spam harvester
|
bad-behavior-wordpress.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Bad Behavior
|
4 |
-
Version: 1.
|
5 |
Plugin URI: http://www.ioerror.us/software/bad-behavior/
|
6 |
Description: Stop comment spam before it starts by trapping and blocking spambots before they have a chance to post comments.
|
7 |
Author: Michael Hampton
|
@@ -51,6 +51,10 @@ $wp_bb_logging_duration = 7;
|
|
51 |
$wp_bb_email = get_bloginfo('admin_email');
|
52 |
//$wp_bb_email = "badbots@ioerror.us";
|
53 |
|
|
|
|
|
|
|
|
|
54 |
###############################################################################
|
55 |
|
56 |
# DO NOT EDIT BELOW THIS LINE
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Bad Behavior
|
4 |
+
Version: 1.1.3
|
5 |
Plugin URI: http://www.ioerror.us/software/bad-behavior/
|
6 |
Description: Stop comment spam before it starts by trapping and blocking spambots before they have a chance to post comments.
|
7 |
Author: Michael Hampton
|
51 |
$wp_bb_email = get_bloginfo('admin_email');
|
52 |
//$wp_bb_email = "badbots@ioerror.us";
|
53 |
|
54 |
+
// The database table name to use.
|
55 |
+
// You can customize the table name if necessary.
|
56 |
+
define('WP_BB_LOG', $table_prefix . 'bad_behavior_log');
|
57 |
+
|
58 |
###############################################################################
|
59 |
|
60 |
# DO NOT EDIT BELOW THIS LINE
|