Version Description
- Reduced the number of database connections that Wordfence makes to one.
- Modified the memory efficient unbuffered queries we use to only use a single DB connection.
- Removed status updates during post and comment scans which prevents interference with unbuffered queries and makes the scans even faster.
Download this release
Release Info
Developer | mmaunder |
Plugin | Wordfence Security – Firewall & Malware Scan |
Version | 1.3.2 |
Comparing to | |
See all releases |
Code changes from version 1.3.1 to 1.3.2
- lib/wfDB.php +21 -16
- lib/wfScanEngine.php +2 -3
- lib/wfSchema.php +1 -1
- readme.txt +6 -1
- wordfence.php +1 -1
lib/wfDB.php
CHANGED
@@ -1,11 +1,12 @@
|
|
1 |
<?php
|
2 |
class wfDB {
|
3 |
private $dbh = false;
|
|
|
4 |
private $dbhost = false;
|
5 |
private $dbpassword = false;
|
6 |
private $dbname = false;
|
7 |
private $dbuser = false;
|
8 |
-
public function __construct($dbhost = false, $dbuser = false, $dbpassword = false, $dbname = false){
|
9 |
if($dbhost && $dbuser && $dbpassword && $dbname){
|
10 |
$this->dbhost = $dbhost;
|
11 |
$this->dbuser = $dbuser;
|
@@ -19,7 +20,20 @@ class wfDB {
|
|
19 |
$this->dbpassword = $wpdb->dbpassword;
|
20 |
$this->dbname = $wpdb->dbname;
|
21 |
}
|
22 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
}
|
24 |
public function querySingleRec(){
|
25 |
$args = func_get_args();
|
@@ -30,7 +44,7 @@ class wfDB {
|
|
30 |
} else {
|
31 |
wfdie("No arguments passed to querySingle()");
|
32 |
}
|
33 |
-
$res = mysql_query($query, $this->
|
34 |
$err = mysql_error();
|
35 |
if($err){
|
36 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
@@ -49,7 +63,7 @@ class wfDB {
|
|
49 |
} else {
|
50 |
wfdie("No arguments passed to querySingle()");
|
51 |
}
|
52 |
-
$res = mysql_query($query, $this->
|
53 |
$err = mysql_error();
|
54 |
if($err){
|
55 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
@@ -73,14 +87,14 @@ class wfDB {
|
|
73 |
} else {
|
74 |
wfdie("No arguments passed to query()");
|
75 |
}
|
76 |
-
$res = mysql_query($query, $this->
|
77 |
$err = mysql_error();
|
78 |
if($err){
|
79 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
80 |
}
|
81 |
return $res;
|
82 |
}
|
83 |
-
public function uQuery(){ //sprintfString, arguments
|
84 |
$args = func_get_args();
|
85 |
if(sizeof($args) == 1){
|
86 |
$query = $args[0];
|
@@ -92,22 +106,13 @@ class wfDB {
|
|
92 |
} else {
|
93 |
wfdie("No arguments passed to query()");
|
94 |
}
|
95 |
-
$res = mysql_unbuffered_query($query, $this->
|
96 |
$err = mysql_error();
|
97 |
if($err){
|
98 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
99 |
}
|
100 |
return $res;
|
101 |
}
|
102 |
-
private function getDBH(){
|
103 |
-
if($this->dbh){
|
104 |
-
return $this->dbh;
|
105 |
-
}
|
106 |
-
$dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, true );
|
107 |
-
mysql_select_db($this->dbname, $dbh);
|
108 |
-
$this->dbh = $dbh;
|
109 |
-
return $dbh;
|
110 |
-
}
|
111 |
private function wfdie($msg){
|
112 |
error_log($msg);
|
113 |
exit(1);
|
1 |
<?php
|
2 |
class wfDB {
|
3 |
private $dbh = false;
|
4 |
+
private static $dbhCache = false;
|
5 |
private $dbhost = false;
|
6 |
private $dbpassword = false;
|
7 |
private $dbname = false;
|
8 |
private $dbuser = false;
|
9 |
+
public function __construct($createNewHandle = false, $dbhost = false, $dbuser = false, $dbpassword = false, $dbname = false){
|
10 |
if($dbhost && $dbuser && $dbpassword && $dbname){
|
11 |
$this->dbhost = $dbhost;
|
12 |
$this->dbuser = $dbuser;
|
20 |
$this->dbpassword = $wpdb->dbpassword;
|
21 |
$this->dbname = $wpdb->dbname;
|
22 |
}
|
23 |
+
if($createNewHandle){
|
24 |
+
$dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, true );
|
25 |
+
mysql_select_db($this->dbname, $dbh);
|
26 |
+
$this->dbh = $dbh;
|
27 |
+
} else {
|
28 |
+
if(self::$dbhCache){
|
29 |
+
$this->dbh = self::$dbhCache;
|
30 |
+
} else {
|
31 |
+
$dbh = mysql_connect( $this->dbhost, $this->dbuser, $this->dbpassword, true );
|
32 |
+
mysql_select_db($this->dbname, $dbh);
|
33 |
+
self::$dbhCache = $dbh;
|
34 |
+
$this->dbh = self::$dbhCache;
|
35 |
+
}
|
36 |
+
}
|
37 |
}
|
38 |
public function querySingleRec(){
|
39 |
$args = func_get_args();
|
44 |
} else {
|
45 |
wfdie("No arguments passed to querySingle()");
|
46 |
}
|
47 |
+
$res = mysql_query($query, $this->dbh);
|
48 |
$err = mysql_error();
|
49 |
if($err){
|
50 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
63 |
} else {
|
64 |
wfdie("No arguments passed to querySingle()");
|
65 |
}
|
66 |
+
$res = mysql_query($query, $this->dbh);
|
67 |
$err = mysql_error();
|
68 |
if($err){
|
69 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
87 |
} else {
|
88 |
wfdie("No arguments passed to query()");
|
89 |
}
|
90 |
+
$res = mysql_query($query, $this->dbh);
|
91 |
$err = mysql_error();
|
92 |
if($err){
|
93 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
94 |
}
|
95 |
return $res;
|
96 |
}
|
97 |
+
public function uQuery(){ //sprintfString, arguments NOTE: Very important that there is no other DB activity between uQuery and when you call mysql_free_result on the return value of uQuery.
|
98 |
$args = func_get_args();
|
99 |
if(sizeof($args) == 1){
|
100 |
$query = $args[0];
|
106 |
} else {
|
107 |
wfdie("No arguments passed to query()");
|
108 |
}
|
109 |
+
$res = mysql_unbuffered_query($query, $this->dbh);
|
110 |
$err = mysql_error();
|
111 |
if($err){
|
112 |
$trace=debug_backtrace(); $caller=array_shift($trace); error_log("Wordfence DB error in " . $caller['file'] . " line " . $caller['line'] . ": $err");
|
113 |
}
|
114 |
return $res;
|
115 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
private function wfdie($msg){
|
117 |
error_log($msg);
|
118 |
exit(1);
|
lib/wfScanEngine.php
CHANGED
@@ -282,13 +282,12 @@ class wfScanEngine {
|
|
282 |
$this->status(1, 'info', "Starting posts scan");
|
283 |
global $wpdb;
|
284 |
$wfdb = new wfDB();
|
|
|
285 |
$q1 = $wfdb->uQuery("select ID, post_title, post_type, post_date, post_content from $wpdb->posts where post_type IN ('page', 'post') and post_status = 'publish'");
|
286 |
$h = new wordfenceURLHoover($this->apiKey, $this->wp_version);
|
287 |
$postDat = array();
|
288 |
while($row = mysql_fetch_assoc($q1)){
|
289 |
-
$this->status(2, 'info', "Scanning " . $row['post_type'] . ": \"" . $row['post_title'] . "\"");
|
290 |
$h->hoover($row['ID'], $row['post_title'] . ' ' . $row['post_content']);
|
291 |
-
|
292 |
$postDat[$row['ID']] = array(
|
293 |
'contentMD5' => md5($row['post_content']),
|
294 |
'title' => $row['post_title'],
|
@@ -372,6 +371,7 @@ class wfScanEngine {
|
|
372 |
private function scanComments(){
|
373 |
global $wpdb;
|
374 |
$wfdb = new wfDB();
|
|
|
375 |
$q1 = $wfdb->uQuery("select comment_ID, comment_date, comment_type, comment_author, comment_author_url, comment_content from $wpdb->comments where comment_approved=1");
|
376 |
if( ! $q1){
|
377 |
return;
|
@@ -381,7 +381,6 @@ class wfScanEngine {
|
|
381 |
$gotRow = false;
|
382 |
while($row = mysql_fetch_assoc($q1)){
|
383 |
$gotRow = true; //because we can't use mysql_num_rows on unbuffered queries
|
384 |
-
$this->status(2, 'info', "Scanning comment ID " . $row['comment_ID'] . " with author " . $row['comment_author']);
|
385 |
$h->hoover($row['comment_ID'], $row['comment_author_url'] . ' ' . $row['comment_author'] . ' ' . $row['comment_content']);
|
386 |
$commentDat[$row['comment_ID']] = array(
|
387 |
'contentMD5' => md5($row['comment_content'] . $row['comment_author'] . $row['comment_author_url']),
|
282 |
$this->status(1, 'info', "Starting posts scan");
|
283 |
global $wpdb;
|
284 |
$wfdb = new wfDB();
|
285 |
+
//NOTE: There must be no other DB activity by wfDB between here and free_result below because we're doing an unbuffered query. THAT INCLUDES calls to status() which updates the DB
|
286 |
$q1 = $wfdb->uQuery("select ID, post_title, post_type, post_date, post_content from $wpdb->posts where post_type IN ('page', 'post') and post_status = 'publish'");
|
287 |
$h = new wordfenceURLHoover($this->apiKey, $this->wp_version);
|
288 |
$postDat = array();
|
289 |
while($row = mysql_fetch_assoc($q1)){
|
|
|
290 |
$h->hoover($row['ID'], $row['post_title'] . ' ' . $row['post_content']);
|
|
|
291 |
$postDat[$row['ID']] = array(
|
292 |
'contentMD5' => md5($row['post_content']),
|
293 |
'title' => $row['post_title'],
|
371 |
private function scanComments(){
|
372 |
global $wpdb;
|
373 |
$wfdb = new wfDB();
|
374 |
+
//NOTE: There must be no other DB activity by wfDB between here and free_result below because we're doing an unbuffered query. THAT INCLUDES calls to status() which updates the DB
|
375 |
$q1 = $wfdb->uQuery("select comment_ID, comment_date, comment_type, comment_author, comment_author_url, comment_content from $wpdb->comments where comment_approved=1");
|
376 |
if( ! $q1){
|
377 |
return;
|
381 |
$gotRow = false;
|
382 |
while($row = mysql_fetch_assoc($q1)){
|
383 |
$gotRow = true; //because we can't use mysql_num_rows on unbuffered queries
|
|
|
384 |
$h->hoover($row['comment_ID'], $row['comment_author_url'] . ' ' . $row['comment_author'] . ' ' . $row['comment_content']);
|
385 |
$commentDat[$row['comment_ID']] = array(
|
386 |
'contentMD5' => md5($row['comment_content'] . $row['comment_author'] . $row['comment_author_url']),
|
lib/wfSchema.php
CHANGED
@@ -139,7 +139,7 @@ class wfSchema {
|
|
139 |
private $prefix = 'wp_';
|
140 |
public function __construct($dbhost = false, $dbuser = false, $dbpassword = false, $dbname = false){
|
141 |
if($dbhost){ //for testing
|
142 |
-
$this->db = new wfDB($dbhost, $dbuser, $dbpassword, $dbname);
|
143 |
$this->prefix = 'wp_';
|
144 |
} else {
|
145 |
global $wpdb;
|
139 |
private $prefix = 'wp_';
|
140 |
public function __construct($dbhost = false, $dbuser = false, $dbpassword = false, $dbname = false){
|
141 |
if($dbhost){ //for testing
|
142 |
+
$this->db = new wfDB(false, $dbhost, $dbuser, $dbpassword, $dbname);
|
143 |
$this->prefix = 'wp_';
|
144 |
} else {
|
145 |
global $wpdb;
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: mmaunder
|
|
3 |
Tags: anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence
|
4 |
Requires at least: 3.3.1
|
5 |
Tested up to: 3.3.2
|
6 |
-
Stable tag: 1.3.
|
7 |
|
8 |
Wordfence is an enterprise firewall and anti-virus plugin for WordPress.
|
9 |
|
@@ -89,6 +89,11 @@ Yes! Simply visit the Options page, click on advanced options and enable or disa
|
|
89 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
90 |
|
91 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
92 |
= 1.3.1 =
|
93 |
* Fixed a bug where if you have the plugin "secure-wordpress" installed, you can't do a Wordfence scan because it says you have the wrong version. This is because secure-wordpress trashes the $wp_version global variable to hide your version rather than using the filters provided by WordPress. So coded a workaround so that your Wordfence scans will work with that plugin installed.
|
94 |
|
3 |
Tags: anti-virus, malware, firewall, antivirus, virus, google safe browsing, phishing, scrapers, hacking, wordfence
|
4 |
Requires at least: 3.3.1
|
5 |
Tested up to: 3.3.2
|
6 |
+
Stable tag: 1.3.2
|
7 |
|
8 |
Wordfence is an enterprise firewall and anti-virus plugin for WordPress.
|
9 |
|
89 |
5. If you're technically minded, this is the under-the-hood view of Wordfence options where you can fine-tune your security settings.
|
90 |
|
91 |
== Changelog ==
|
92 |
+
= 1.3.2 =
|
93 |
+
* Reduced the number of database connections that Wordfence makes to one.
|
94 |
+
* Modified the memory efficient unbuffered queries we use to only use a single DB connection.
|
95 |
+
* Removed status updates during post and comment scans which prevents interference with unbuffered queries and makes the scans even faster.
|
96 |
+
|
97 |
= 1.3.1 =
|
98 |
* Fixed a bug where if you have the plugin "secure-wordpress" installed, you can't do a Wordfence scan because it says you have the wrong version. This is because secure-wordpress trashes the $wp_version global variable to hide your version rather than using the filters provided by WordPress. So coded a workaround so that your Wordfence scans will work with that plugin installed.
|
99 |
|
wordfence.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Wordfence
|
|
4 |
Plugin URI: http://wordfence.com/
|
5 |
Description: Anti-virus and Firewall for WordPress
|
6 |
Author: Mark Maunder
|
7 |
-
Version: 1.3.
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
require_once('lib/wordfenceConstants.php');
|
4 |
Plugin URI: http://wordfence.com/
|
5 |
Description: Anti-virus and Firewall for WordPress
|
6 |
Author: Mark Maunder
|
7 |
+
Version: 1.3.2
|
8 |
Author URI: http://wordfence.com/
|
9 |
*/
|
10 |
require_once('lib/wordfenceConstants.php');
|