| 2150 |
mathias |
1 |
<?php
|
|
|
2 |
// db settings
|
|
|
3 |
$dbserver = 'localhost';
|
|
|
4 |
$dbuser = 'root';
|
|
|
5 |
$dbpassword = 'root';
|
|
|
6 |
|
|
|
7 |
error_reporting(E_ALL);
|
|
|
8 |
|
|
|
9 |
/*
|
|
|
10 |
Simple protocol:
|
|
|
11 |
- Inputs via POST variables.
|
|
|
12 |
- Output is a string that can be evaluated into a JSON
|
|
|
13 |
First element of the array contains return status.
|
|
|
14 |
|
|
|
15 |
This simplified tutorial code should not be deployed without a security review.
|
|
|
16 |
*/
|
|
|
17 |
|
|
|
18 |
@include "json.php";
|
|
|
19 |
|
|
|
20 |
// set up response encoding
|
|
|
21 |
header("Content-Type: text/html; charset=utf-8");
|
|
|
22 |
|
|
|
23 |
// util
|
|
|
24 |
function getPostString($inName) {
|
|
|
25 |
// make sure input strings are 'clean'
|
|
|
26 |
return mysql_real_escape_string(@$_POST[$inName]);
|
|
|
27 |
}
|
|
|
28 |
|
|
|
29 |
// used for json encoding
|
|
|
30 |
$json = new Services_JSON();
|
|
|
31 |
|
|
|
32 |
function echoJson($inData) {
|
|
|
33 |
global $json;
|
|
|
34 |
// delay in ms
|
|
|
35 |
$delay = getPostString('delay');
|
|
|
36 |
if (!empty($delay))
|
|
|
37 |
usleep($delay * 1000);
|
|
|
38 |
echo '/* ' . $json->encode($inData) . ' */';
|
|
|
39 |
}
|
|
|
40 |
|
|
|
41 |
function error($inMessage) {
|
|
|
42 |
$inMessage = str_replace('"', '\\"', $inMessage);
|
|
|
43 |
error_log($inMessage);
|
|
|
44 |
//echo '/* ({error: true, message: "' . $inMessage . '"}) */';
|
|
|
45 |
echoJson(array('error' => true, 'message' => $inMessage));
|
|
|
46 |
exit;
|
|
|
47 |
}
|
|
|
48 |
|
|
|
49 |
|
|
|
50 |
function getArray($inResult, $inArray="true") {
|
|
|
51 |
$o = Array();
|
|
|
52 |
while ($row = ($inArray ? mysql_fetch_row($inResult) : mysql_fetch_object($inResult)))
|
|
|
53 |
$o[] = $row;
|
|
|
54 |
return $o;
|
|
|
55 |
}
|
|
|
56 |
|
|
|
57 |
// connect to DB
|
|
|
58 |
mysql_connect($dbserver, $dbuser, $dbpassword);
|
|
|
59 |
|
|
|
60 |
// select DB
|
|
|
61 |
$database = getPostString("database");
|
|
|
62 |
$database = ($database ? $database : $db);
|
|
|
63 |
if (!mysql_select_db($database))
|
|
|
64 |
error('failed to select db: ' . mysql_error());
|
|
|
65 |
|
|
|
66 |
// select table
|
|
|
67 |
$table = getPostString("table");
|
|
|
68 |
$table = ($table ? $table : $dbtable);
|
|
|
69 |
|
|
|
70 |
// cache
|
|
|
71 |
$colCache = NULL;
|
|
|
72 |
$pkCache = NULL;
|
|
|
73 |
|
|
|
74 |
// set UTF8 output (MySql > 4.0)
|
|
|
75 |
mysql_query("SET NAMES UTF8");
|
|
|
76 |
|
|
|
77 |
// server, database, table meta data
|
|
|
78 |
function getDatabases() {
|
|
|
79 |
$result = mysql_query("SHOW DATABASES");
|
|
|
80 |
$output = Array();
|
|
|
81 |
while ($row = mysql_fetch_row($result)) {
|
|
|
82 |
$r = strtolower($row[0]);
|
|
|
83 |
if ($r != 'mysql' && $r != 'information_schema')
|
|
|
84 |
$output[] = $row[0];
|
|
|
85 |
}
|
|
|
86 |
return $output;
|
|
|
87 |
}
|
|
|
88 |
|
|
|
89 |
function getTables() {
|
|
|
90 |
global $database;
|
|
|
91 |
$result = mysql_query("SHOW TABLES FROM $database");
|
|
|
92 |
$output = Array();
|
|
|
93 |
while ($row = mysql_fetch_row($result))
|
|
|
94 |
$output[] = $row[0];
|
|
|
95 |
return $output;
|
|
|
96 |
}
|
|
|
97 |
|
|
|
98 |
function getColumns() {
|
|
|
99 |
global $table, $colCache;
|
|
|
100 |
if (!$colCache) {
|
|
|
101 |
$result = mysql_query("SHOW COLUMNS FROM `$table`");
|
|
|
102 |
return getArray($result, false);
|
|
|
103 |
$colCache = getArray($result, false);
|
|
|
104 |
}
|
|
|
105 |
return $colCache;
|
|
|
106 |
}
|
|
|
107 |
|
|
|
108 |
// returns object: $this->name, $this->index
|
|
|
109 |
function getPk() {
|
|
|
110 |
global $pkCache;
|
|
|
111 |
if (!$pkCache) {
|
|
|
112 |
$k = '';
|
|
|
113 |
$columns = getColumns();
|
|
|
114 |
for ($i=0; $i < count($columns); $i++) {
|
|
|
115 |
$c = $columns[$i];
|
|
|
116 |
if ($c->Key == 'PRI') {
|
|
|
117 |
$k = $c->Field;
|
|
|
118 |
break;
|
|
|
119 |
}
|
|
|
120 |
}
|
|
|
121 |
$pkCache->index = $i;
|
|
|
122 |
$pkCache->name = $k;
|
|
|
123 |
}
|
|
|
124 |
return $pkCache;
|
|
|
125 |
}
|
|
|
126 |
|
|
|
127 |
function getTableInfo() {
|
|
|
128 |
global $table, $database;
|
|
|
129 |
$c = getColumns();
|
|
|
130 |
$r = rowcount();
|
|
|
131 |
return array("count" => $r, "columns" => $c, "database" => $database, "table" => $table);
|
|
|
132 |
}
|
|
|
133 |
|
|
|
134 |
function getOldPostPkValue() {
|
|
|
135 |
$pk = getPk();
|
|
|
136 |
return getPostString('_o' . $pk->index);
|
|
|
137 |
}
|
|
|
138 |
|
|
|
139 |
function getNewPostPkValue() {
|
|
|
140 |
$pk = getPk();
|
|
|
141 |
return getPostString('_' . $pk->index);
|
|
|
142 |
}
|
|
|
143 |
|
|
|
144 |
function getPostColumns() {
|
|
|
145 |
$columns = getColumns();
|
|
|
146 |
for ($i=0, $a=array(), $p; (($p=getPostString("_".$i)) != ''); $i++) {
|
|
|
147 |
$r = new stdClass();
|
|
|
148 |
$r->name = $columns[$i]->Field;
|
|
|
149 |
$r->value = $p;
|
|
|
150 |
$a[] = $r;
|
|
|
151 |
}
|
|
|
152 |
return $a;
|
|
|
153 |
}
|
|
|
154 |
|
|
|
155 |
function getOrderBy() {
|
|
|
156 |
$ob = getPostString("orderby");
|
|
|
157 |
if (is_numeric($ob)) {
|
|
|
158 |
$columns = getColumns();
|
|
|
159 |
$ob = $columns[intval($ob)-1]->Field;
|
|
|
160 |
}
|
|
|
161 |
return $ob;
|
|
|
162 |
}
|
|
|
163 |
|
|
|
164 |
function getWhere() {
|
|
|
165 |
$w = getPostString("where");
|
|
|
166 |
return ($w ? " WHERE $w" : "");
|
|
|
167 |
}
|
|
|
168 |
|
|
|
169 |
// basic operations
|
|
|
170 |
function rowcount() {
|
|
|
171 |
global $table;
|
|
|
172 |
$query = "SELECT COUNT(*) FROM `$table`" . getWhere();
|
|
|
173 |
$result = mysql_query($query);
|
|
|
174 |
if (!$result)
|
|
|
175 |
error("failed to perform query: $query. " . mysql_error());
|
|
|
176 |
if ($row = mysql_fetch_row($result))
|
|
|
177 |
return $row[0];
|
|
|
178 |
else
|
|
|
179 |
return 0;
|
|
|
180 |
}
|
|
|
181 |
|
|
|
182 |
function select($inQuery = '') {
|
|
|
183 |
global $table;
|
|
|
184 |
// built limit clause
|
|
|
185 |
$lim = (int)getPostString("limit");
|
|
|
186 |
$off = (int)getPostString("offset");
|
|
|
187 |
$limit = ($lim || $off ? " LIMIT $off, $lim" : "");
|
|
|
188 |
// build order by clause
|
|
|
189 |
$desc = (boolean)getPostString("desc");
|
|
|
190 |
$ob = getOrderBy();
|
|
|
191 |
$orderby = ($ob ? " ORDER BY `" . $ob . "`" . ($desc ? " DESC" : "") : "");
|
|
|
192 |
// build query
|
|
|
193 |
$query = ($inQuery ? $inQuery : "SELECT * FROM `$table`" . getWhere() . $orderby . $limit);
|
|
|
194 |
// execute query
|
|
|
195 |
if (!$result = mysql_query($query))
|
|
|
196 |
error("failed to perform query: $query. " . mysql_error());
|
|
|
197 |
// fetch each result row
|
|
|
198 |
return getArray($result);
|
|
|
199 |
}
|
|
|
200 |
|
|
|
201 |
function reflectRow() {
|
|
|
202 |
global $table;
|
|
|
203 |
$pk = getPk();
|
|
|
204 |
$key = getNewPostPkValue();
|
|
|
205 |
$where = "`$pk->name`=\"$key\"";
|
|
|
206 |
return select("SELECT * FROM `$table` WHERE $where LIMIT 1");
|
|
|
207 |
}
|
|
|
208 |
|
|
|
209 |
function update() {
|
|
|
210 |
// build set clause
|
|
|
211 |
for ($i=0, $set = array(), $cols = getPostColumns(), $v; ($v=$cols[$i]); $i++)
|
|
|
212 |
$set[] = "`$v->name` = '$v->value'";
|
|
|
213 |
$set = implode(', ', $set);
|
|
|
214 |
// our table
|
|
|
215 |
global $table;
|
|
|
216 |
// build query
|
|
|
217 |
$pk = getPk();
|
|
|
218 |
$pkValue = getOldPostPkValue();
|
|
|
219 |
$query = "UPDATE `$table` SET $set WHERE `$pk->name` = '$pkValue' LIMIT 1";
|
|
|
220 |
// execute query
|
|
|
221 |
if (!mysql_query($query))
|
|
|
222 |
error("failed to perform query: [$query]. " .
|
|
|
223 |
"MySql says: [" . mysql_error() ."]");
|
|
|
224 |
else {
|
|
|
225 |
return reflectRow();
|
|
|
226 |
}
|
|
|
227 |
}
|
|
|
228 |
|
|
|
229 |
function insert() {
|
|
|
230 |
global $table;
|
|
|
231 |
// build values clause
|
|
|
232 |
for ($i=0, $values = array(), $cols = getPostColumns(), $v; ($v=$cols[$i]); $i++)
|
|
|
233 |
$values[] = $v->value;
|
|
|
234 |
$values = '"' . implode('", "', $values) . '"';
|
|
|
235 |
// build query
|
|
|
236 |
$query = "INSERT INTO `$table` VALUES($values)";
|
|
|
237 |
// execute query
|
|
|
238 |
if (!mysql_query($query))
|
|
|
239 |
error("failed to perform query: [$query]. " .
|
|
|
240 |
"MySql says: [" . mysql_error() ."]");
|
|
|
241 |
else {
|
|
|
242 |
return reflectRow();
|
|
|
243 |
}
|
|
|
244 |
}
|
|
|
245 |
|
|
|
246 |
function delete() {
|
|
|
247 |
global $table;
|
|
|
248 |
// build query
|
|
|
249 |
$n = getPostString("count");
|
|
|
250 |
$pk = getPk();
|
|
|
251 |
for ($i = 0, $deleted=array(); $i < $n; $i++) {
|
|
|
252 |
$key = getPostString("_$i");
|
|
|
253 |
array_push($deleted, $key);
|
|
|
254 |
$query = "DELETE FROM `$table` WHERE `$pk->name`=\"$key\" LIMIT 1";
|
|
|
255 |
// execute query
|
|
|
256 |
if (!mysql_query($query) || mysql_affected_rows() != 1)
|
|
|
257 |
error("failed to perform query: [$query]. " .
|
|
|
258 |
"Affected rows: " . mysql_affected_rows() .". " .
|
|
|
259 |
"MySql says: [" . mysql_error() ."]");
|
|
|
260 |
}
|
|
|
261 |
return $deleted;
|
|
|
262 |
}
|
|
|
263 |
|
|
|
264 |
// find (full text search)
|
|
|
265 |
function findData($inFindCol, $inFind, $inOrderBy, $inFullText) {
|
|
|
266 |
global $table;
|
|
|
267 |
$where = ($inFullText ? "WHERE MATCH(`$inFindCol`) AGAINST ('$inFind')" : "WHERE $inFindCol LIKE '$inFind'");
|
|
|
268 |
$query = "SELECT * FROM $table $where $inOrderBy";
|
|
|
269 |
$result = mysql_query($query);
|
|
|
270 |
// return rows
|
|
|
271 |
return getArray($result);
|
|
|
272 |
}
|
|
|
273 |
|
|
|
274 |
// binary search through sorted data, supports start point ($inFindFrom) and direction ($inFindForward)
|
|
|
275 |
function findRow($inData, $inFindFrom=-1, $inFindForward) {
|
|
|
276 |
$b = -1;
|
|
|
277 |
$l = count($inData);
|
|
|
278 |
if (!$inData)
|
|
|
279 |
return $b;
|
|
|
280 |
if (!$inFindFrom==-1 || $l < 2)
|
|
|
281 |
$b = 0;
|
|
|
282 |
else {
|
|
|
283 |
// binary search
|
|
|
284 |
$t = $l-1;
|
|
|
285 |
$b = 0;
|
|
|
286 |
while ($b <= $t) {
|
|
|
287 |
$p = floor(($b+$t)/2);
|
|
|
288 |
$d = $inData[$p][0];
|
|
|
289 |
if ($d < $inFindFrom)
|
|
|
290 |
$b = $p + 1;
|
|
|
291 |
else if ($d > $inFindFrom)
|
|
|
292 |
$t = $p - 1;
|
|
|
293 |
else {
|
|
|
294 |
$b = $p;
|
|
|
295 |
break;
|
|
|
296 |
}
|
|
|
297 |
}
|
|
|
298 |
if ($inFindFrom == $inData[$b][0]) {
|
|
|
299 |
// add or subtract 1
|
|
|
300 |
$b = ($inFindForward ? ($b+1 > $l-1 ? 0 : $b+1) : ($b-1 < 0 ? $l-1 : $b-1) );
|
|
|
301 |
}
|
|
|
302 |
else if (!$inFindForward)
|
|
|
303 |
// subtract 1
|
|
|
304 |
$b = ($b-1 < 0 ? $l-1 : $b-1);
|
|
|
305 |
}
|
|
|
306 |
return $inData[$b][0];
|
|
|
307 |
}
|
|
|
308 |
|
|
|
309 |
function buildFindWhere($inFindData, $inKey, $inCol) {
|
|
|
310 |
$o = Array();
|
|
|
311 |
foreach($inFindData as $row)
|
|
|
312 |
$o[] = $inCol . "='" . $row[$inKey] . "'";
|
|
|
313 |
return (count($o) ? ' WHERE ' . implode(' OR ', $o) : '');
|
|
|
314 |
}
|
|
|
315 |
|
|
|
316 |
function find($inFindCol, $inFind='', $inOb='', $inFindFrom=0, $inFindForward=true, $inFullText=true) {
|
|
|
317 |
global $table;
|
|
|
318 |
// build order by clause
|
|
|
319 |
$desc = (boolean)getPostString("desc");
|
|
|
320 |
if (!$inOb)
|
|
|
321 |
$inOb = getOrderBy();
|
|
|
322 |
if ($inOb)
|
|
|
323 |
$inOb = "`" . $inOb . "`" ;
|
|
|
324 |
$orderby = ($inOb ? " ORDER BY $inOb " . ($desc ? " DESC" : "") : "");
|
|
|
325 |
// update inputs from post
|
|
|
326 |
if (!$inFind)
|
|
|
327 |
$inFind = getPostString('findText');
|
|
|
328 |
if (!$inFindCol)
|
|
|
329 |
$inFindCol = getPostString('findCol');
|
|
|
330 |
if (empty($inFindFrom))
|
|
|
331 |
$inFindFrom = getPostString('findFrom');
|
|
|
332 |
$ff = getPostString('findForward');
|
|
|
333 |
if ($ff)
|
|
|
334 |
$inFindForward = (strtolower($ff) == 'true' ? true : false);
|
|
|
335 |
$ft = getPostString('findFullText');
|
|
|
336 |
if ($ft)
|
|
|
337 |
$inFullText = (strtolower($ft) == 'true' ? true : false);
|
|
|
338 |
|
|
|
339 |
// get find data
|
|
|
340 |
$f = findData($inFindCol, $inFind, $orderby, $inFullText);
|
|
|
341 |
$pk = getPk();
|
|
|
342 |
|
|
|
343 |
// execute query
|
|
|
344 |
$where = buildFindWhere($f, $pk->index, 'f');
|
|
|
345 |
$query = "SELECT Row, f FROM (SELECT @row := @row + 1 AS Row, $pk->name as f FROM `$table` $orderby) AS tempTable $where";
|
|
|
346 |
mysql_query('SET @row = -1;');
|
|
|
347 |
if (!$result = mysql_query($query))
|
|
|
348 |
error("failed to perform query: $query. " . mysql_error());
|
|
|
349 |
|
|
|
350 |
// return row number
|
|
|
351 |
return findRow(getArray($result), $inFindFrom, $inFindForward);
|
|
|
352 |
}
|
|
|
353 |
|
|
|
354 |
// our command list
|
|
|
355 |
$cmds = array(
|
|
|
356 |
"count" => "rowcount",
|
|
|
357 |
"select" => "select",
|
|
|
358 |
"update" => "update",
|
|
|
359 |
"insert" => "insert",
|
|
|
360 |
"delete" => "delete",
|
|
|
361 |
"find" => "find",
|
|
|
362 |
"databases" => "getDatabases",
|
|
|
363 |
"tables" => "getTables",
|
|
|
364 |
"columns" => "getColumns",
|
|
|
365 |
"info" => "getTableInfo"
|
|
|
366 |
);
|
|
|
367 |
|
|
|
368 |
// process input params
|
|
|
369 |
$cmd = @$_POST["command"];
|
|
|
370 |
|
|
|
371 |
//$cmd="select";
|
|
|
372 |
|
|
|
373 |
// dispatch command
|
|
|
374 |
$func = @$cmds[$cmd];
|
|
|
375 |
if (function_exists($func))
|
|
|
376 |
echoJson(call_user_func($func));
|
|
|
377 |
else
|
|
|
378 |
error("bad command");
|
|
|
379 |
?>
|