This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * @package fwolflib |
||
4 | * @copyright Copyright 2006, Fwolf |
||
5 | * @author Fwolf <[email protected]> |
||
6 | */ |
||
7 | |||
8 | |||
9 | require_once(dirname(__FILE__) . '/fwolflib.php'); |
||
10 | require_once('adodb/adodb.inc.php'); |
||
11 | |||
12 | |||
13 | /** |
||
14 | * Data backup tool, result is sql format. |
||
15 | * Test under sybase 11.92 ok. |
||
16 | * |
||
17 | * @deprecated Use Fwlib\Db\DbDataExport |
||
18 | * @package fwolflib |
||
19 | * @copyright Copyright 2006, Fwolf |
||
20 | * @author Fwolf <[email protected]> |
||
21 | * @since 2006-11-14 |
||
22 | * @access public |
||
23 | * @version $Id$ |
||
24 | */ |
||
25 | class DbBak2Sql extends Fwolflib { |
||
26 | /** |
||
27 | * Charset of database |
||
28 | * If charset of db diff from os, do convert when execute sql. |
||
29 | * @var string |
||
30 | * @access public |
||
31 | */ |
||
32 | var $mCharsetDb = ''; |
||
33 | |||
34 | /** |
||
35 | * Charset of operation system |
||
36 | * @var string |
||
37 | * @access public |
||
38 | * @see $mCharsetDb |
||
39 | */ |
||
40 | var $mCharsetOs = ''; |
||
41 | |||
42 | /** |
||
43 | * Db connection object |
||
44 | * @var object |
||
45 | * @access private |
||
46 | */ |
||
47 | var $mDb; |
||
48 | |||
49 | /** |
||
50 | * Ignore columns |
||
51 | * These columns will not be trans to sql when processed. |
||
52 | * @var array |
||
53 | * @access public |
||
54 | */ |
||
55 | var $mIgnoreColumn = array('lasttime'); |
||
56 | |||
57 | /** |
||
58 | * Log file |
||
59 | * Log file to write, this is only filename, path is $this->mTargetPath |
||
60 | * @var string |
||
61 | * @access public |
||
62 | * @see $mTargetPath |
||
63 | */ |
||
64 | var $mLogFile = 'dbbak2sql.log'; |
||
65 | |||
66 | /** |
||
67 | * Db server information array |
||
68 | * Array item: host, user, pass, name, type. |
||
69 | * @var array |
||
70 | * @access private |
||
71 | */ |
||
72 | var $mServer = array(); |
||
73 | |||
74 | /** |
||
75 | * Summary text |
||
76 | * @var string |
||
77 | * @access public |
||
78 | */ |
||
79 | var $mSummary = ''; |
||
80 | |||
81 | /** |
||
82 | * Tables will be backup |
||
83 | * Include needed, exclude no needed, this is result. |
||
84 | * @var array |
||
85 | * @access private |
||
86 | */ |
||
87 | var $mTable = array(); |
||
88 | |||
89 | /** |
||
90 | * Tables to be exclude from backup task |
||
91 | * @var array |
||
92 | * @access private |
||
93 | */ |
||
94 | var $mTableExclude = array(); |
||
95 | |||
96 | /** |
||
97 | * Table need to be group by some cols when backup |
||
98 | * Usually used when table contains too much rows |
||
99 | * @var array |
||
100 | * @access private |
||
101 | */ |
||
102 | var $mTableGroupby = array(); |
||
103 | |||
104 | /** |
||
105 | * Tables to be include in backup task |
||
106 | * If not empty, will only backup tables in this list. |
||
107 | * @var array |
||
108 | * @access private |
||
109 | */ |
||
110 | var $mTableInclude = array(); |
||
111 | |||
112 | /** |
||
113 | * Where to save exported sql files. |
||
114 | * @var string |
||
115 | * @access private |
||
116 | */ |
||
117 | var $mTargetPath = '/tmp/dbbak2sql'; |
||
118 | |||
119 | |||
120 | /** |
||
121 | * Construct function |
||
122 | * @access public |
||
123 | * @param array $server Db server information |
||
124 | */ |
||
125 | function __construct($server=array()) |
||
126 | { |
||
127 | if (!empty($server)) |
||
128 | $this->SetDatabase($server); |
||
129 | } // end of func __construct |
||
130 | |||
131 | |||
132 | /** |
||
133 | * Do backup to database |
||
134 | * @access public |
||
135 | */ |
||
136 | public function Bak() |
||
137 | { |
||
138 | file_put_contents($this->mTargetPath . '/' . $this->mLogFile, ''); |
||
139 | $this->GetTableList(); |
||
140 | foreach ($this->mTable as $tbl) |
||
141 | $this->BakTable($tbl); |
||
142 | $this->Summary(); |
||
143 | } // end of func Bak |
||
144 | |||
145 | |||
146 | /** |
||
147 | * Do backup to a single table |
||
148 | * @access private |
||
149 | * @param string $tbl Table name |
||
150 | */ |
||
151 | private function BakTable($tbl) |
||
152 | { |
||
153 | // Clear sql file(sql is save to seperated file, not need clear anymore |
||
154 | //file_put_contents($this->mTargetPath . "/$tbl.sql", ''); |
||
155 | $this->Log("Begin to backup $tbl, "); |
||
156 | |||
157 | $cols = $this->GetTblFields($tbl); |
||
158 | |||
159 | // Split sql to 10000 rows per step |
||
160 | $sql_step = 10000; |
||
161 | $sql_offset = 0; |
||
162 | // Rows and Byte count |
||
163 | $done_rows = 0; |
||
164 | $done_bytes = 0; |
||
165 | |||
166 | // Get total rows |
||
167 | $sql = "select count(1) as c from $tbl"; |
||
168 | $rs = $this->mDb->Execute($sql); |
||
169 | $rowcount = $rs->fields['c']; |
||
170 | $this->Log("Got $rowcount rows: "); |
||
171 | |||
172 | // Write rs to sql |
||
173 | // GetInsertSQL failed for unknown reason, manual generate sql |
||
174 | //$sql = $this->mDb->GetInsertSQL($rs, $cols, false, false); |
||
175 | $bakfile = $this->mTargetPath . "/$tbl.sql"; |
||
176 | $sql = "truncate table $tbl;\n"; |
||
177 | if (true == $this->NeedIdentityInsert()) |
||
0 ignored issues
–
show
|
|||
178 | $sql .= "set identity_insert $tbl on;\n"; |
||
179 | |||
180 | // Backup by groupby will cause two situation: |
||
181 | // 1. one sql file will contain rows diffs with sql_step. |
||
182 | // 2. sql file saved's number sometimes is not continued. |
||
183 | |||
184 | // Groupby rules is converted to where clauses |
||
185 | $ar_where = $this->GroupbyRule2WhereSql($tbl); |
||
186 | while ($sql_offset < $rowcount) |
||
187 | { |
||
188 | $this->Log("."); |
||
189 | // Execute sql |
||
190 | // When ar_where is empty, the loop should be end. |
||
191 | // Or groupby is not used. |
||
192 | if (!empty($ar_where)) |
||
193 | { |
||
194 | $s_where = array_shift($ar_where); |
||
195 | $sql_select = "select * from $tbl $s_where"; |
||
196 | $rs = $this->mDb->Execute($sql_select); |
||
197 | } |
||
198 | else |
||
199 | { |
||
200 | $sql_select = "select * from $tbl"; |
||
201 | // This select sql does not need iconv |
||
202 | //if ($this->mCharsetDb != $this->mCharsetOs) |
||
203 | // $sql = mb_convert_encoding($sql, $this->mCharsetDb, $this->mCharsetOs); |
||
204 | $rs = $this->mDb->SelectLimit($sql_select, $sql_step, $sql_offset); |
||
205 | } |
||
206 | $rs_rows = $rs->RecordCount(); |
||
207 | if (0 != $this->mDb->ErrorNo()) |
||
208 | $this->Log("\n" . $db->ErrorMsg() . "\n"); |
||
209 | else |
||
210 | { |
||
211 | $sql .= $this->Rs2Sql($rs, $tbl, $cols); |
||
212 | $done_rows += $rs_rows; |
||
213 | } |
||
214 | |||
215 | // Save this step to file |
||
216 | if ($this->mCharsetDb != $this->mCharsetOs) |
||
217 | $sql = mb_convert_encoding($sql, $this->mCharsetOs, $this->mCharsetDb); |
||
218 | // Save to seperated file, first check about how many files will be used. |
||
219 | if ($rowcount > $sql_step) |
||
220 | { |
||
221 | $i = strlen(strval(ceil($rowcount / $sql_step))); |
||
222 | $s = substr(str_repeat('0', $i) . strval(floor($sql_offset / $sql_step)), $i * -1) . '.'; |
||
223 | } |
||
224 | else |
||
225 | $s = ''; |
||
226 | $bakfile = $this->mTargetPath . "/$tbl.${s}sql"; |
||
227 | file_put_contents($bakfile, $sql, FILE_APPEND); |
||
228 | // Prepare for loop |
||
229 | $done_bytes += strlen($sql); |
||
230 | unset($sql); |
||
231 | $sql = ''; |
||
232 | //$sql_offset += $sql_step; |
||
233 | $sql_offset += $rs_rows; |
||
234 | unset($rs); |
||
235 | } |
||
236 | |||
237 | // End sql, the last one. |
||
238 | if (true == $this->NeedIdentityInsert()) |
||
0 ignored issues
–
show
|
|||
239 | $sql .= "set identity_insert $tbl off;\n"; |
||
240 | file_put_contents($bakfile, $sql, FILE_APPEND); |
||
241 | |||
242 | $this->Log("Saved $done_rows rows, Total size: $done_bytes bytes.\n"); |
||
243 | |||
244 | } // end of func BakTable |
||
245 | |||
246 | |||
247 | /** |
||
248 | * 获得数据库连接 |
||
249 | * @access private |
||
250 | * @param array $server |
||
251 | * @return object |
||
252 | */ |
||
253 | private function &DbConn($server) |
||
254 | { |
||
255 | global $ADODB_FETCH_MODE; |
||
256 | |||
257 | //ADODB设定 |
||
258 | $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC; |
||
259 | |||
260 | try |
||
261 | { |
||
262 | $conn = &ADONewConnection($server['type']); |
||
263 | //$conn->debug = true; |
||
264 | $conn->Connect($server['host'], |
||
265 | $server['user'], |
||
266 | $server['pass'], |
||
267 | $server['name']); |
||
268 | //针对mysql 4.1以上,UTF8编码的数据库,需要在连接后指定编码 |
||
269 | //$conn->Execute('set names "utf8"'); |
||
270 | if ('mysql' == $server['type']) $conn->Execute('set names "utf8"'); |
||
271 | } |
||
272 | catch (Exception $e) |
||
273 | { |
||
274 | //var_dump($e); |
||
275 | adodb_backtrace($e->getTrace()); |
||
276 | //echo $e; |
||
277 | exit(); |
||
278 | } |
||
279 | return $conn; |
||
280 | } // end of func DbConn |
||
281 | |||
282 | |||
283 | /** |
||
284 | * Retrieve table list from db |
||
285 | * @access private |
||
286 | */ |
||
287 | private function GetTableList() |
||
288 | { |
||
289 | if (!empty($this->mTableInclude)) |
||
290 | $this->mTable = $this->mTableInclude; |
||
291 | else |
||
292 | // Adodb 4.65 can't read sysbase table list currect, |
||
293 | // Replaced it with 4.93a, it's fine. |
||
294 | $this->mTable = $this->mDb->MetaTables('TABLES'); |
||
295 | |||
296 | // Compute exclude |
||
297 | foreach ($this->mTableExclude as $tbl) |
||
298 | { |
||
299 | $idx = array_search($tbl, $this->mTable); |
||
300 | if (!(false === $idx)) |
||
301 | unset($this->mTable[$idx]); |
||
302 | } |
||
303 | |||
304 | // Write Log |
||
305 | $this->Log("Ready for backup " . count($this->mTable) . " tables.\n"); |
||
306 | } // end of func GetTableList |
||
307 | |||
308 | |||
309 | /** |
||
310 | * Get fields of a table, ignore prefered fields |
||
311 | * @access private |
||
312 | * @param string $tbl |
||
313 | * @return array |
||
314 | */ |
||
315 | private function GetTblFields($tbl) |
||
316 | { |
||
317 | $rs_cols = $this->mDb->MetaColumns($tbl, false); |
||
318 | //print_r($rs_cols); |
||
319 | $cols = array(); |
||
320 | if (!empty($rs_cols)) |
||
321 | foreach ($rs_cols as $c) |
||
322 | { |
||
323 | // Ignore some columns ?(timestamp) |
||
324 | if (false == in_array($c->name, $this->mIgnoreColumn)) |
||
0 ignored issues
–
show
|
|||
325 | array_push($cols, $c->name); |
||
326 | } |
||
327 | return $cols; |
||
328 | } // end of func GetTblFields |
||
329 | |||
330 | |||
331 | /** |
||
332 | * Convert groupby rules to where sql clauses |
||
333 | * Retrieve data from db by groupby rules, and convert to where sql. |
||
334 | * Used when backup, where clauses can used directly in select sql |
||
335 | * @access private |
||
336 | * @param string $tbl |
||
337 | * @return array |
||
338 | */ |
||
339 | private function GroupbyRule2WhereSql($tbl) |
||
340 | { |
||
341 | $ar_where = array(); |
||
342 | if (!empty($this->mTableGroupby[$tbl])) |
||
343 | { |
||
344 | $groupby = $this->mTableGroupby[$tbl]; |
||
345 | $sql = "select distinct $groupby from $tbl"; |
||
346 | $rs = $this->mDb->Execute($sql); |
||
347 | |||
348 | // Convert every rows to where sql |
||
349 | $cols = explode(',', $groupby); |
||
350 | $rs_cols = $this->mDb->MetaColumns($tbl, false); |
||
351 | while (!empty($rs) && !$rs->EOF && !empty($cols)) |
||
352 | { |
||
353 | $sql = ' WHERE 1=1 '; |
||
354 | View Code Duplication | foreach ($cols as $c) |
|
355 | { |
||
356 | $val = $this->ParseSqlData($rs->fields[$c], $rs_cols[strtoupper($c)]->type); |
||
357 | $sql .= " and $c=$val "; |
||
358 | } |
||
359 | array_push($ar_where, $sql); |
||
360 | $rs->MoveNext(); |
||
361 | } |
||
362 | } |
||
363 | return $ar_where; |
||
364 | } // end of function GroupbyRule2WhereSql |
||
365 | |||
366 | |||
367 | /** |
||
368 | * Save log |
||
369 | * Both log file and summary text is saved to. |
||
370 | * @access private |
||
371 | * @param string $log |
||
372 | */ |
||
373 | public function Log ($log) { |
||
374 | $logfile = $this->mTargetPath . '/' . $this->mLogFile; |
||
375 | file_put_contents($logfile, $log, FILE_APPEND); |
||
376 | echo $log; |
||
377 | $this->mSummary .= $log; |
||
378 | } // end of func Log |
||
379 | |||
380 | |||
381 | /** |
||
382 | * Determin if current db driver need set identity_insert tbl on/off |
||
383 | * @access private |
||
384 | * @return boolean |
||
385 | */ |
||
386 | private function NeedIdentityInsert() |
||
387 | { |
||
388 | $ar_need = array('mssql', 'sybase', 'sybase_ase'); |
||
389 | if (true == in_array($this->mServer['type'], $ar_need)) |
||
0 ignored issues
–
show
|
|||
390 | return true; |
||
391 | else |
||
392 | return false; |
||
393 | } // end of func NeedIdentityInsert |
||
394 | |||
395 | |||
396 | /** |
||
397 | * Parse sql text used in sql value field |
||
398 | * @access private |
||
399 | * @param string $val |
||
400 | * @param string $type |
||
401 | * @return string |
||
402 | */ |
||
403 | private function ParseSqlData($val, $type) |
||
404 | { |
||
405 | // First, ' -> '' in sybase |
||
406 | //if (true == in_array($this->mServer['type'], array('sybase', 'sybase_ase'))) |
||
407 | // $val = str_replace("'", "''", $val); |
||
408 | // Quote fields of char |
||
409 | $varchar = array('char', 'charn', 'text', 'varchar', 'varchar2', 'varcharn'); |
||
410 | if (true == in_array($type, $varchar)) |
||
0 ignored issues
–
show
|
|||
411 | $val = '"' . addslashes($val) . '"'; |
||
412 | |||
413 | // Datetime field |
||
414 | $datestyle = array('date', 'daten', 'datetime', 'datetimn'); |
||
415 | if (in_array($type, $datestyle)) |
||
416 | if (empty($val)) |
||
417 | $val = 'null'; |
||
418 | else |
||
419 | $val = '"' . $val . '"'; |
||
420 | |||
421 | // If a numeric field is null |
||
422 | if (!in_array($type, $varchar) && !in_array($type, $datestyle) && is_null($val)) |
||
423 | $val = 'null'; |
||
424 | |||
425 | return $val; |
||
426 | } // end of func ParseSqlData |
||
427 | |||
428 | |||
429 | /** |
||
430 | * Convert ADOdb recordset to sql text |
||
431 | * @access private |
||
432 | * @param object $rs |
||
433 | * @param string $tbl |
||
434 | * @param array $cols |
||
435 | * @return string |
||
436 | */ |
||
437 | private function Rs2Sql(&$rs, $tbl, $cols=array()) |
||
438 | { |
||
439 | if (empty($rs) || $rs->EOF) |
||
440 | return ''; |
||
441 | else |
||
442 | { |
||
443 | $sql = ''; |
||
444 | if (empty($cols)) |
||
445 | $cols = $this->GetTblFields($tbl); |
||
446 | $rs_cols = $this->mDb->MetaColumns($tbl, false); |
||
447 | |||
448 | while (!$rs->EOF) |
||
449 | { |
||
450 | // Insert sql begin |
||
451 | $sql_i = "INSERT INTO $tbl (" . implode(',', $cols) . " ) VALUES ( \n"; |
||
452 | // Fields data |
||
453 | $ar = array(); |
||
454 | View Code Duplication | foreach ($cols as $c) |
|
455 | { |
||
456 | $val = $rs->fields[$c]; |
||
457 | $type = $rs_cols[strtoupper($c)]->type; |
||
458 | array_push($ar, $this->ParseSqlData($val, $type)); |
||
459 | } |
||
460 | $sql_i .= implode(',', $ar) . "\n"; |
||
461 | // Insert sql end |
||
462 | $sql_i .= ");\n"; |
||
463 | $sql .= $sql_i; |
||
464 | // Move cursor |
||
465 | $rs->MoveNext(); |
||
466 | } |
||
467 | } |
||
468 | return $sql; |
||
469 | } // end of func Rs2Sql |
||
470 | |||
471 | |||
472 | /** |
||
473 | * Accept database information from outside class |
||
474 | * Didnot validate data send in. |
||
475 | * And connect to db after store infomation. |
||
476 | * @access public |
||
477 | * @var array $server array items: host, user, pass, name, type |
||
478 | */ |
||
479 | View Code Duplication | public function SetDatabase($server) |
|
480 | { |
||
481 | if (!empty($server) && is_array($server)) |
||
482 | { |
||
483 | $this->mServer = $server; |
||
484 | $this->mDb = $this->DbConn($this->mServer); |
||
485 | } |
||
486 | } // end of func SetDatabase |
||
487 | |||
488 | |||
489 | /** |
||
490 | * Set tables will not be backup |
||
491 | * @access public |
||
492 | * @var array $ar |
||
493 | */ |
||
494 | public function SetTableExclude($ar) |
||
495 | { |
||
496 | if (!empty($ar) and is_array($ar)) |
||
497 | { |
||
498 | $this->mTableExclude = $ar; |
||
499 | } |
||
500 | } // end of func SetTableExclude |
||
501 | |||
502 | |||
503 | /** |
||
504 | * Set table group by rules when backup-select |
||
505 | * If given cols is empty, it will remove tbl from list need-to-be groupby. |
||
506 | * Multi cols can be assigned split by ','. |
||
507 | * @access public |
||
508 | * @var string $tbl |
||
509 | * @var string $cols |
||
510 | */ |
||
511 | public function SetTableGroupby($tbl, $cols) |
||
512 | { |
||
513 | if (empty($cols)) |
||
514 | unset($this->mTableGroupby[$tbl]); |
||
515 | else |
||
516 | $this->mTableGroupby[$tbl] = $cols; |
||
517 | } // end of func SetTableGroupby |
||
518 | |||
519 | |||
520 | /** |
||
521 | * Set tables will only be backup |
||
522 | * @access public |
||
523 | * @var array $ar |
||
524 | */ |
||
525 | public function SetTableInclude($ar) |
||
526 | { |
||
527 | if (!empty($ar) and is_array($ar)) |
||
528 | { |
||
529 | $this->mTableInclude = $ar; |
||
530 | } |
||
531 | } // end of func SetTableInclude |
||
532 | |||
533 | |||
534 | /** |
||
535 | * Set where to save sql files exported. |
||
536 | * If directory doesn't exists, create it. |
||
537 | * @access public |
||
538 | * @var string $path |
||
539 | */ |
||
540 | public function SetTargetPath($path) |
||
541 | { |
||
542 | $this->mTargetPath = $path; |
||
543 | // Check and create |
||
544 | if (file_exists($path) && !is_dir($path)) |
||
545 | die("Target path is a file."); |
||
546 | elseif (!file_exists($path)) |
||
547 | mkdir($path, 0700, true); // Do path end with '/' needed ? |
||
548 | } // end of func SetTargetPath |
||
549 | |||
550 | /** |
||
551 | * Print or write summary text of the whole backup process |
||
552 | * @access private |
||
553 | */ |
||
554 | private function Summary() |
||
555 | { |
||
556 | echo $this->mSummary . "\n"; |
||
557 | } // end of func Summary |
||
558 | |||
559 | |||
560 | } // end of class DbBak2Sql |
||
561 | /* |
||
562 | $db = DbConn(); |
||
563 | |||
564 | //打印各市地区编码 |
||
565 | $sql[2] = 'select substring(bm, 1, 4), mc from dqk where bm like "%00"'; |
||
566 | |||
567 | $sql = $sql[4]; |
||
568 | $sql = mb_convert_encoding($sql, 'gbk', 'utf8'); |
||
569 | $rs = $db->Execute($sql); |
||
570 | if (0 != $db->ErrorNo()) |
||
571 | echo $db->ErrorMsg(); |
||
572 | $s = ''; |
||
573 | $ar = $rs->GetArray(); |
||
574 | |||
575 | //输出方式一,直接print |
||
576 | //$s = print_r($ar, true); |
||
577 | //输出方式二,tab间隔,便于导入 |
||
578 | foreach ($ar as $key=>$row) |
||
579 | { |
||
580 | foreach ($row as $var) |
||
581 | $s .= "$var\t"; |
||
582 | $s .= "\n"; |
||
583 | } |
||
584 | |||
585 | $s = mb_convert_encoding($s, 'utf8', 'gbk'); |
||
586 | echo $s; |
||
587 | */ |
||
588 | ?> |
||
589 |
When comparing two booleans, it is generally considered safer to use the strict comparison operator.