-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmysqlw.php
More file actions
152 lines (130 loc) · 5.28 KB
/
mysqlw.php
File metadata and controls
152 lines (130 loc) · 5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<?php
require_once "dbinfo.php";
?>
<?php
/** @author Volodymyr Sereda
* This class is designed to be the only entry point into the database.
* It offers better error handling, and only allows a parameter interface.
* The w in mysqlw stands for wrapper :)
* It never needs to be instantiated explicitly. Just use the static instance() method. Singleton pattern is used!
* BEWARE. Sqli is tricky, so this class may have BUGS. I found all that I noticed, but remain vigilant!
*
* The name of the query function has been changed from query() to wquery() for easy searching of legacy code.
* wqueryE accepts an extra argument, which is the error message upon failure (E=exception). It throws an exception
* upon failure and offers much better error reporting.
* wquery should be considered legacy, and was only created for existing code. Prefer to use wqueryE where possible.
*
* Do NOT put SQL parameters straight into the search string! That leads to SQL injection issues. Instead, all parameters
* must be bound programmatically. Insert ? markers into the query, and provide the parameters in the array (second parameter).
* For example, the old query->("SELECT * from stuff WHERE a=$one and b=$two and c=$three") is equivalent to the new
* wquery->("SELECT * from stuff WHERE a=? and b=? and c=?", array($one, $two, $three)).
*
* Example usage:
* Original mysqli:
* --------------------------------------------------------------------------
* con = new mysqli(HOST, USER, PASSWORD, DATABASE);
* if (con->connect_errno)
* die("merp");
* $injection = "'hi";
* $result = $con->query("SELECT * FROM somewhere WHERE entry=$injection");
* if(!$result)
* die("derp");
* $entry = $result->fetch_object()->entry;
* --------------------------------------------------------------------------
* New mysqlw:
* --------------------------------------------------------------------------
* $nonInjection = "'hi";
* $entry = Mysqlw::instance()->wqueryE("SELECT * FROM somewhere WHERE entry=?",
array($nonInjection), "herp")->fetch_object()->entry;
* --------------------------------------------------------------------------
*/
class Mysqlw
{
public $con;
public $affected_rows=0;
public $error="";
private static $instance=null;
public static function instance()
{
if(Mysqlw::$instance==null)
return Mysqlw::$instance=new Mysqlw();
else
return Mysqlw::$instance;
}
private function __construct()
{
global $dbUsername, $dbPassword, $dbHost, $dbDatabase;
$this->con = new mysqli($dbHost, $dbUsername, $dbPassword, $dbDatabase);
if ($this->con->connect_errno)
throw new Exception("Connect failed: " . $this->con->connect_error);
Mysqlw::$instance=null;
}
public function __destruct()
{
if($this->con)
$this->con->close();
}
public function wquery($query, $parameters=array())
{
$answer=null;
$prepared = $this->con->prepare($query);
if($prepared)
{
if($this->bindParams($prepared, $parameters) && $prepared->execute())
{
$answer=$prepared->get_result(); //returns false for non select statements
}
}
$this->affected_rows = $this->con->affected_rows;
$this->error=$this->con->error;
if($prepared)
$prepared->close();
if($answer!==null)
return ($answer===FALSE) ? TRUE:$answer; //If it is false, then this was not a select statement. Still passed.
else
return false;
}
public function wqueryE($query, $parameters=array(), $msg="")
{
$ex=null;
$answer = null;
$prepared = $this->con->prepare($query);
try
{
if(!$prepared)
throw new Exception($msg . " (failed preparing statement: " . $this->con->error . ")");
if(!$this->bindParams($prepared, $parameters))
throw new Exception($msg . " (unable to bind parameters: " . $this->con->error . ")");
//Parameters should be bound. Execute!
if($prepared->execute())
$answer=$prepared->get_result(); //returns false for non select statements
else
throw new Exception($msg . " (failed executing: " . $this->con->error . ")");
}
catch(Exception $e)
{
$ex=$e;
}
$this->affected_rows = $this->con->affected_rows;
$this->error=$this->con->error;
if($prepared)
$prepared->close();
if($ex!=null)
throw $ex;
return $answer===FALSE ? TRUE:$answer; //If it is false, then this was not a select statement. Still passed.
}
private function bindParams($prepared, $params)
{
if(count($params)==0)
return true;
$typestr = str_repeat("s", count($params));
$refarray = array();
for($i = 0; $i < count($params); ++$i)
$refarray[] = &$params[$i];
if(!call_user_func_array(array($prepared, "bind_param"), array_merge(array($typestr), $refarray)))
return false;
else
return true;
}
}
?>