phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / includes / acp / acp_database.php

History | View | Annotate | Download (58.8 kB)

1
<?php
2
/**
3
*
4
* @package acp
5
* @version $Id: acp_database.php 11561 2011-11-20 03:00:09Z git-gate $
6
* @copyright (c) 2005 phpBB Group
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8
*
9
*/
10
11
/**
12
* @ignore
13
*/
14
if (!defined('IN_PHPBB'))
15
{
16
        exit;
17
}
18
19
/**
20
* @package acp
21
*/
22
class acp_database
23
{
24
        var $u_action;
25
26
        function main($id, $mode)
27
        {
28
                global $cache, $db, $user, $auth, $template, $table_prefix;
29
                global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
30
31
                $user->add_lang('acp/database');
32
33
                $this->tpl_name = 'acp_database';
34
                $this->page_title = 'ACP_DATABASE';
35
36
                $action        = request_var('action', '');
37
                $submit = (isset($_POST['submit'])) ? true : false;
38
39
                $template->assign_vars(array(
40
                        'MODE'        => $mode
41
                ));
42
43
                switch ($mode)
44
                {
45
                        case 'backup':
46
47
                                $this->page_title = 'ACP_BACKUP';
48
49
                                switch ($action)
50
                                {
51
                                        case 'download':
52
                                                $type        = request_var('type', '');
53
                                                $table        = request_var('table', array(''));
54
                                                $format        = request_var('method', '');
55
                                                $where        = request_var('where', '');
56
57
                                                if (!sizeof($table))
58
                                                {
59
                                                        trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING);
60
                                                }
61
62
                                                $store = $download = $structure = $schema_data = false;
63
64
                                                if ($where == 'store_and_download' || $where == 'store')
65
                                                {
66
                                                        $store = true;
67
                                                }
68
69
                                                if ($where == 'store_and_download' || $where == 'download')
70
                                                {
71
                                                        $download = true;
72
                                                }
73
74
                                                if ($type == 'full' || $type == 'structure')
75
                                                {
76
                                                        $structure = true;
77
                                                }
78
79
                                                if ($type == 'full' || $type == 'data')
80
                                                {
81
                                                        $schema_data = true;
82
                                                }
83
84
                                                @set_time_limit(1200);
85
                                                @set_time_limit(0);
86
87
                                                $time = time();
88
89
                                                $filename = 'backup_' . $time . '_' . unique_id();
90
                                                switch ($db->sql_layer)
91
                                                {
92
                                                        case 'mysqli':
93
                                                        case 'mysql4':
94
                                                        case 'mysql':
95
                                                                $extractor = new mysql_extractor($download, $store, $format, $filename, $time);
96
                                                        break;
97
98
                                                        case 'sqlite':
99
                                                                $extractor = new sqlite_extractor($download, $store, $format, $filename, $time);
100
                                                        break;
101
102
                                                        case 'postgres':
103
                                                                $extractor = new postgres_extractor($download, $store, $format, $filename, $time);
104
                                                        break;
105
106
                                                        case 'oracle':
107
                                                                $extractor = new oracle_extractor($download, $store, $format, $filename, $time);
108
                                                        break;
109
110
                                                        case 'mssql':
111
                                                        case 'mssql_odbc':
112
                                                        case 'mssqlnative':
113
                                                                $extractor = new mssql_extractor($download, $store, $format, $filename, $time);
114
                                                        break;
115
116
                                                        case 'firebird':
117
                                                                $extractor = new firebird_extractor($download, $store, $format, $filename, $time);
118
                                                        break;
119
                                                }
120
121
                                                $extractor->write_start($table_prefix);
122
123
                                                foreach ($table as $table_name)
124
                                                {
125
                                                        // Get the table structure
126
                                                        if ($structure)
127
                                                        {
128
                                                                $extractor->write_table($table_name);
129
                                                        }
130
                                                        else
131
                                                        {
132
                                                                // We might wanna empty out all that junk :D
133
                                                                switch ($db->sql_layer)
134
                                                                {
135
                                                                        case 'sqlite':
136
                                                                        case 'firebird':
137
                                                                                $extractor->flush('DELETE FROM ' . $table_name . ";\n");
138
                                                                        break;
139
140
                                                                        case 'mssql':
141
                                                                        case 'mssql_odbc':
142
                                                                        case 'mssqlnative':
143
                                                                                $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n");
144
                                                                        break;
145
146
                                                                        case 'oracle':
147
                                                                                $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n");
148
                                                                        break;
149
150
                                                                        default:
151
                                                                                $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n");
152
                                                                        break;
153
                                                                }
154
                                                        }
155
156
                                                        // Data
157
                                                        if ($schema_data)
158
                                                        {
159
                                                                $extractor->write_data($table_name);
160
                                                        }
161
                                                }
162
163
                                                $extractor->write_end();
164
165
                                                add_log('admin', 'LOG_DB_BACKUP');
166
167
                                                if ($download == true)
168
                                                {
169
                                                        exit;
170
                                                }
171
172
                                                trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action));
173
                                        break;
174
175
                                        default:
176
                                                include($phpbb_root_path . 'includes/functions_install.' . $phpEx);
177
                                                $tables = get_tables($db);
178
                                                asort($tables);
179
                                                foreach ($tables as $table_name)
180
                                                {
181
                                                        if (strlen($table_prefix) === 0 || stripos($table_name, $table_prefix) === 0)
182
                                                        {
183
                                                                $template->assign_block_vars('tables', array(
184
                                                                        'TABLE'        => $table_name
185
                                                                ));
186
                                                        }
187
                                                }
188
                                                unset($tables);
189
190
                                                $template->assign_vars(array(
191
                                                        'U_ACTION'        => $this->u_action . '&amp;action=download'
192
                                                ));
193
194
                                                $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2');
195
196
                                                foreach ($available_methods as $type => $module)
197
                                                {
198
                                                        if (!@extension_loaded($module))
199
                                                        {
200
                                                                continue;
201
                                                        }
202
203
                                                        $template->assign_block_vars('methods', array(
204
                                                                'TYPE'        => $type
205
                                                        ));
206
                                                }
207
208
                                                $template->assign_block_vars('methods', array(
209
                                                        'TYPE'        => 'text'
210
                                                ));
211
                                        break;
212
                                }
213
                        break;
214
215
                        case 'restore':
216
217
                                $this->page_title = 'ACP_RESTORE';
218
219
                                switch ($action)
220
                                {
221
                                        case 'submit':
222
                                                $delete = request_var('delete', '');
223
                                                $file = request_var('file', '');
224
                                                $download = request_var('download', '');
225
226
                                                if (!preg_match('#^backup_\d{10,}_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches))
227
                                                {
228
                                                        trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
229
                                                }
230
231
                                                $file_name = $phpbb_root_path . 'store/' . $matches[0];
232
233
                                                if (!file_exists($file_name) || !is_readable($file_name))
234
                                                {
235
                                                        trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
236
                                                }
237
238
                                                if ($delete)
239
                                                {
240
                                                        if (confirm_box(true))
241
                                                        {
242
                                                                unlink($file_name);
243
                                                                add_log('admin', 'LOG_DB_DELETE');
244
                                                                trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action));
245
                                                        }
246
                                                        else
247
                                                        {
248
                                                                confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file)));
249
                                                        }
250
                                                }
251
                                                else if ($download || confirm_box(true))
252
                                                {
253
                                                        if ($download)
254
                                                        {
255
                                                                $name = $matches[0];
256
257
                                                                switch ($matches[1])
258
                                                                {
259
                                                                        case 'sql':
260
                                                                                $mimetype = 'text/x-sql';
261
                                                                        break;
262
                                                                        case 'sql.bz2':
263
                                                                                $mimetype = 'application/x-bzip2';
264
                                                                        break;
265
                                                                        case 'sql.gz':
266
                                                                                $mimetype = 'application/x-gzip';
267
                                                                        break;
268
                                                                }
269
270
                                                                header('Pragma: no-cache');
271
                                                                header("Content-Type: $mimetype; name=\"$name\"");
272
                                                                header("Content-disposition: attachment; filename=$name");
273
274
                                                                @set_time_limit(0);
275
276
                                                                $fp = @fopen($file_name, 'rb');
277
278
                                                                if ($fp !== false)
279
                                                                {
280
                                                                        while (!feof($fp))
281
                                                                        {
282
                                                                                echo fread($fp, 8192);
283
                                                                        }
284
                                                                        fclose($fp);
285
                                                                }
286
287
                                                                flush();
288
                                                                exit;
289
                                                        }
290
291
                                                        switch ($matches[1])
292
                                                        {
293
                                                                case 'sql':
294
                                                                        $fp = fopen($file_name, 'rb');
295
                                                                        $read = 'fread';
296
                                                                        $seek = 'fseek';
297
                                                                        $eof = 'feof';
298
                                                                        $close = 'fclose';
299
                                                                        $fgetd = 'fgetd';
300
                                                                break;
301
302
                                                                case 'sql.bz2':
303
                                                                        $fp = bzopen($file_name, 'r');
304
                                                                        $read = 'bzread';
305
                                                                        $seek = '';
306
                                                                        $eof = 'feof';
307
                                                                        $close = 'bzclose';
308
                                                                        $fgetd = 'fgetd_seekless';
309
                                                                break;
310
311
                                                                case 'sql.gz':
312
                                                                        $fp = gzopen($file_name, 'rb');
313
                                                                        $read = 'gzread';
314
                                                                        $seek = 'gzseek';
315
                                                                        $eof = 'gzeof';
316
                                                                        $close = 'gzclose';
317
                                                                        $fgetd = 'fgetd';
318
                                                                break;
319
                                                        }
320
321
                                                        switch ($db->sql_layer)
322
                                                        {
323
                                                                case 'mysql':
324
                                                                case 'mysql4':
325
                                                                case 'mysqli':
326
                                                                case 'sqlite':
327
                                                                        while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false)
328
                                                                        {
329
                                                                                $db->sql_query($sql);
330
                                                                        }
331
                                                                break;
332
333
                                                                case 'firebird':
334
                                                                        $delim = ";\n";
335
                                                                        while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false)
336
                                                                        {
337
                                                                                $query = trim($sql);
338
                                                                                if (substr($query, 0, 8) === 'SET TERM')
339
                                                                                {
340
                                                                                        $delim = $query[9] . "\n";
341
                                                                                        continue;
342
                                                                                }
343
                                                                                $db->sql_query($query);
344
                                                                        }
345
                                                                break;
346
347
                                                                case 'postgres':
348
                                                                        $delim = ";\n";
349
                                                                        while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false)
350
                                                                        {
351
                                                                                $query = trim($sql);
352
353
                                                                                if (substr($query, 0, 13) == 'CREATE DOMAIN')
354
                                                                                {
355
                                                                                        list(, , $domain) = explode(' ', $query);
356
                                                                                        $sql = "SELECT domain_name
357
                                                                                                FROM information_schema.domains
358
                                                                                                WHERE domain_name = '$domain';";
359
                                                                                        $result = $db->sql_query($sql);
360
                                                                                        if (!$db->sql_fetchrow($result))
361
                                                                                        {
362
                                                                                                $db->sql_query($query);
363
                                                                                        }
364
                                                                                        $db->sql_freeresult($result);
365
                                                                                }
366
                                                                                else
367
                                                                                {
368
                                                                                        $db->sql_query($query);
369
                                                                                }
370
371
                                                                                if (substr($query, 0, 4) == 'COPY')
372
                                                                                {
373
                                                                                        while (($sub = $fgetd($fp, "\n", $read, $seek, $eof)) !== '\.')
374
                                                                                        {
375
                                                                                                if ($sub === false)
376
                                                                                                {
377
                                                                                                        trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING);
378
                                                                                                }
379
                                                                                                pg_put_line($db->db_connect_id, $sub . "\n");
380
                                                                                        }
381
                                                                                        pg_put_line($db->db_connect_id, "\\.\n");
382
                                                                                        pg_end_copy($db->db_connect_id);
383
                                                                                }
384
                                                                        }
385
                                                                break;
386
387
                                                                case 'oracle':
388
                                                                        while (($sql = $fgetd($fp, "/\n", $read, $seek, $eof)) !== false)
389
                                                                        {
390
                                                                                $db->sql_query($sql);
391
                                                                        }
392
                                                                break;
393
394
                                                                case 'mssql':
395
                                                                case 'mssql_odbc':
396
                                                                case 'mssqlnative':
397
                                                                        while (($sql = $fgetd($fp, "GO\n", $read, $seek, $eof)) !== false)
398
                                                                        {
399
                                                                                $db->sql_query($sql);
400
                                                                        }
401
                                                                break;
402
                                                        }
403
404
                                                        $close($fp);
405
406
                                                        // Purge the cache due to updated data
407
                                                        $cache->purge();
408
409
                                                        add_log('admin', 'LOG_DB_RESTORE');
410
                                                        trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action));
411
                                                        break;
412
                                                }
413
                                                else if (!$download)
414
                                                {
415
                                                        confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file)));
416
                                                }
417
418
                                        default:
419
                                                $methods = array('sql');
420
                                                $available_methods = array('sql.gz' => 'zlib', 'sql.bz2' => 'bz2');
421
422
                                                foreach ($available_methods as $type => $module)
423
                                                {
424
                                                        if (!@extension_loaded($module))
425
                                                        {
426
                                                                continue;
427
                                                        }
428
                                                        $methods[] = $type;
429
                                                }
430
431
                                                $dir = $phpbb_root_path . 'store/';
432
                                                $dh = @opendir($dir);
433
434
                                                $backup_files = array();
435
436
                                                if ($dh)
437
                                                {
438
                                                        while (($file = readdir($dh)) !== false)
439
                                                        {
440
                                                                if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches))
441
                                                                {
442
                                                                        if (in_array($matches[2], $methods))
443
                                                                        {
444
                                                                                $backup_files[(int) $matches[1]] = $file;
445
                                                                        }
446
                                                                }
447
                                                        }
448
                                                        closedir($dh);
449
                                                }
450
451
                                                if (!empty($backup_files))
452
                                                {
453
                                                        krsort($backup_files);
454
455
                                                        foreach ($backup_files as $name => $file)
456
                                                        {
457
                                                                $template->assign_block_vars('files', array(
458
                                                                        'FILE'                => $file,
459
                                                                        'NAME'                => $user->format_date($name, 'd-m-Y H:i:s', true),
460
                                                                        'SUPPORTED'        => true,
461
                                                                ));
462
                                                        }
463
                                                }
464
465
                                                $template->assign_vars(array(
466
                                                        'U_ACTION'        => $this->u_action . '&amp;action=submit'
467
                                                ));
468
                                        break;
469
                                }
470
                        break;
471
                }
472
        }
473
}
474
475
/**
476
* @package acp
477
*/
478
class base_extractor
479
{
480
        var $fh;
481
        var $fp;
482
        var $write;
483
        var $close;
484
        var $store;
485
        var $download;
486
        var $time;
487
        var $format;
488
        var $run_comp = false;
489
490
        function base_extractor($download = false, $store = false, $format, $filename, $time)
491
        {
492
                $this->download = $download;
493
                $this->store = $store;
494
                $this->time = $time;
495
                $this->format = $format;
496
497
                switch ($format)
498
                {
499
                        case 'text':
500
                                $ext = '.sql';
501
                                $open = 'fopen';
502
                                $this->write = 'fwrite';
503
                                $this->close = 'fclose';
504
                                $mimetype = 'text/x-sql';
505
                        break;
506
                        case 'bzip2':
507
                                $ext = '.sql.bz2';
508
                                $open = 'bzopen';
509
                                $this->write = 'bzwrite';
510
                                $this->close = 'bzclose';
511
                                $mimetype = 'application/x-bzip2';
512
                        break;
513
                        case 'gzip':
514
                                $ext = '.sql.gz';
515
                                $open = 'gzopen';
516
                                $this->write = 'gzwrite';
517
                                $this->close = 'gzclose';
518
                                $mimetype = 'application/x-gzip';
519
                        break;
520
                }
521
522
                if ($download == true)
523
                {
524
                        $name = $filename . $ext;
525
                        header('Pragma: no-cache');
526
                        header("Content-Type: $mimetype; name=\"$name\"");
527
                        header("Content-disposition: attachment; filename=$name");
528
529
                        switch ($format)
530
                        {
531
                                case 'bzip2':
532
                                        ob_start();
533
                                break;
534
535
                                case 'gzip':
536
                                        if ((isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'msie') === false)
537
                                        {
538
                                                ob_start('ob_gzhandler');
539
                                        }
540
                                        else
541
                                        {
542
                                                $this->run_comp = true;
543
                                        }
544
                                break;
545
                        }
546
                }
547
548
                if ($store == true)
549
                {
550
                        global $phpbb_root_path;
551
                        $file = $phpbb_root_path . 'store/' . $filename . $ext;
552
553
                        $this->fp = $open($file, 'w');
554
555
                        if (!$this->fp)
556
                        {
557
                                trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
558
                        }
559
                }
560
        }
561
562
        function write_end()
563
        {
564
                static $close;
565
566
                if ($this->store)
567
                {
568
                        if ($close === null)
569
                        {
570
                                $close = $this->close;
571
                        }
572
                        $close($this->fp);
573
                }
574
575
                // bzip2 must be written all the way at the end
576
                if ($this->download && $this->format === 'bzip2')
577
                {
578
                        $c = ob_get_clean();
579
                        echo bzcompress($c);
580
                }
581
        }
582
583
        function flush($data)
584
        {
585
                static $write;
586
                if ($this->store === true)
587
                {
588
                        if ($write === null)
589
                        {
590
                                $write = $this->write;
591
                        }
592
                        $write($this->fp, $data);
593
                }
594
595
                if ($this->download === true)
596
                {
597
                        if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp))
598
                        {
599
                                echo $data;
600
                        }
601
602
                        // we can write the gzip data as soon as we get it
603
                        if ($this->format === 'gzip')
604
                        {
605
                                if ($this->run_comp)
606
                                {
607
                                        echo gzencode($data);
608
                                }
609
                                else
610
                                {
611
                                        ob_flush();
612
                                        flush();
613
                                }
614
                        }
615
                }
616
        }
617
}
618
619
/**
620
* @package acp
621
*/
622
class mysql_extractor extends base_extractor
623
{
624
        function write_start($table_prefix)
625
        {
626
                $sql_data = "#\n";
627
                $sql_data .= "# phpBB Backup Script\n";
628
                $sql_data .= "# Dump of tables for $table_prefix\n";
629
                $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
630
                $sql_data .= "#\n";
631
                $this->flush($sql_data);
632
        }
633
634
        function write_table($table_name)
635
        {
636
                global $db;
637
                static $new_extract;
638
639
                if ($new_extract === null)
640
                {
641
                        if ($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>='))
642
                        {
643
                                $new_extract = true;
644
                        }
645
                        else
646
                        {
647
                                $new_extract = false;
648
                        }
649
                }
650
651
                if ($new_extract)
652
                {
653
                        $this->new_write_table($table_name);
654
                }
655
                else
656
                {
657
                        $this->old_write_table($table_name);
658
                }
659
        }
660
661
        function write_data($table_name)
662
        {
663
                global $db;
664
                if ($db->sql_layer === 'mysqli')
665
                {
666
                        $this->write_data_mysqli($table_name);
667
                }
668
                else
669
                {
670
                        $this->write_data_mysql($table_name);
671
                }
672
        }
673
674
        function write_data_mysqli($table_name)
675
        {
676
                global $db;
677
                $sql = "SELECT *
678
                        FROM $table_name";
679
                $result = mysqli_query($db->db_connect_id, $sql, MYSQLI_USE_RESULT);
680
                if ($result != false)
681
                {
682
                        $fields_cnt = mysqli_num_fields($result);
683
684
                        // Get field information
685
                        $field = mysqli_fetch_fields($result);
686
                        $field_set = array();
687
688
                        for ($j = 0; $j < $fields_cnt; $j++)
689
                        {
690
                                $field_set[] = $field[$j]->name;
691
                        }
692
693
                        $search                        = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
694
                        $replace                = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
695
                        $fields                        = implode(', ', $field_set);
696
                        $sql_data                = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
697
                        $first_set                = true;
698
                        $query_len                = 0;
699
                        $max_len                = get_usable_memory();
700
701
                        while ($row = mysqli_fetch_row($result))
702
                        {
703
                                $values        = array();
704
                                if ($first_set)
705
                                {
706
                                        $query = $sql_data . '(';
707
                                }
708
                                else
709
                                {
710
                                        $query  .= ',(';
711
                                }
712
713
                                for ($j = 0; $j < $fields_cnt; $j++)
714
                                {
715
                                        if (!isset($row[$j]) || is_null($row[$j]))
716
                                        {
717
                                                $values[$j] = 'NULL';
718
                                        }
719
                                        else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024))
720
                                        {
721
                                                $values[$j] = $row[$j];
722
                                        }
723
                                        else
724
                                        {
725
                                                $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
726
                                        }
727
                                }
728
                                $query .= implode(', ', $values) . ')';
729
730
                                $query_len += strlen($query);
731
                                if ($query_len > $max_len)
732
                                {
733
                                        $this->flush($query . ";\n\n");
734
                                        $query = '';
735
                                        $query_len = 0;
736
                                        $first_set = true;
737
                                }
738
                                else
739
                                {
740
                                        $first_set = false;
741
                                }
742
                        }
743
                        mysqli_free_result($result);
744
745
                        // check to make sure we have nothing left to flush
746
                        if (!$first_set && $query)
747
                        {
748
                                $this->flush($query . ";\n\n");
749
                        }
750
                }
751
        }
752
753
        function write_data_mysql($table_name)
754
        {
755
                global $db;
756
                $sql = "SELECT *
757
                        FROM $table_name";
758
                $result = mysql_unbuffered_query($sql, $db->db_connect_id);
759
760
                if ($result != false)
761
                {
762
                        $fields_cnt = mysql_num_fields($result);
763
764
                        // Get field information
765
                        $field = array();
766
                        for ($i = 0; $i < $fields_cnt; $i++)
767
                        {
768
                                $field[] = mysql_fetch_field($result, $i);
769
                        }
770
                        $field_set = array();
771
772
                        for ($j = 0; $j < $fields_cnt; $j++)
773
                        {
774
                                $field_set[] = $field[$j]->name;
775
                        }
776
777
                        $search                        = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
778
                        $replace                = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
779
                        $fields                        = implode(', ', $field_set);
780
                        $sql_data                = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
781
                        $first_set                = true;
782
                        $query_len                = 0;
783
                        $max_len                = get_usable_memory();
784
785
                        while ($row = mysql_fetch_row($result))
786
                        {
787
                                $values = array();
788
                                if ($first_set)
789
                                {
790
                                        $query = $sql_data . '(';
791
                                }
792
                                else
793
                                {
794
                                        $query  .= ',(';
795
                                }
796
797
                                for ($j = 0; $j < $fields_cnt; $j++)
798
                                {
799
                                        if (!isset($row[$j]) || is_null($row[$j]))
800
                                        {
801
                                                $values[$j] = 'NULL';
802
                                        }
803
                                        else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp'))
804
                                        {
805
                                                $values[$j] = $row[$j];
806
                                        }
807
                                        else
808
                                        {
809
                                                $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
810
                                        }
811
                                }
812
                                $query .= implode(', ', $values) . ')';
813
814
                                $query_len += strlen($query);
815
                                if ($query_len > $max_len)
816
                                {
817
                                        $this->flush($query . ";\n\n");
818
                                        $query = '';
819
                                        $query_len = 0;
820
                                        $first_set = true;
821
                                }
822
                                else
823
                                {
824
                                        $first_set = false;
825
                                }
826
                        }
827
                        mysql_free_result($result);
828
829
                        // check to make sure we have nothing left to flush
830
                        if (!$first_set && $query)
831
                        {
832
                                $this->flush($query . ";\n\n");
833
                        }
834
                }
835
        }
836
837
        function new_write_table($table_name)
838
        {
839
                global $db;
840
841
                $sql = 'SHOW CREATE TABLE ' . $table_name;
842
                $result = $db->sql_query($sql);
843
                $row = $db->sql_fetchrow($result);
844
845
                $sql_data = '# Table: ' . $table_name . "\n";
846
                $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
847
                $this->flush($sql_data . $row['Create Table'] . ";\n\n");
848
849
                $db->sql_freeresult($result);
850
        }
851
852
        function old_write_table($table_name)
853
        {
854
                global $db;
855
856
                $sql_data = '# Table: ' . $table_name . "\n";
857
                $sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
858
                $sql_data .= "CREATE TABLE $table_name(\n";
859
                $rows = array();
860
861
                $sql = "SHOW FIELDS
862
                        FROM $table_name";
863
                $result = $db->sql_query($sql);
864
865
                while ($row = $db->sql_fetchrow($result))
866
                {
867
                        $line = '   ' . $row['Field'] . ' ' . $row['Type'];
868
869
                        if (!is_null($row['Default']))
870
                        {
871
                                $line .= " DEFAULT '{$row['Default']}'";
872
                        }
873
874
                        if ($row['Null'] != 'YES')
875
                        {
876
                                $line .= ' NOT NULL';
877
                        }
878
879
                        if ($row['Extra'] != '')
880
                        {
881
                                $line .= ' ' . $row['Extra'];
882
                        }
883
884
                        $rows[] = $line;
885
                }
886
                $db->sql_freeresult($result);
887
888
                $sql = "SHOW KEYS
889
                        FROM $table_name";
890
891
                $result = $db->sql_query($sql);
892
893
                $index = array();
894
                while ($row = $db->sql_fetchrow($result))
895
                {
896
                        $kname = $row['Key_name'];
897
898
                        if ($kname != 'PRIMARY')
899
                        {
900
                                if ($row['Non_unique'] == 0)
901
                                {
902
                                        $kname = "UNIQUE|$kname";
903
                                }
904
                        }
905
906
                        if ($row['Sub_part'])
907
                        {
908
                                $row['Column_name'] .= '(' . $row['Sub_part'] . ')';
909
                        }
910
                        $index[$kname][] = $row['Column_name'];
911
                }
912
                $db->sql_freeresult($result);
913
914
                foreach ($index as $key => $columns)
915
                {
916
                        $line = '   ';
917
918
                        if ($key == 'PRIMARY')
919
                        {
920
                                $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')';
921
                        }
922
                        else if (strpos($key, 'UNIQUE') === 0)
923
                        {
924
                                $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')';
925
                        }
926
                        else if (strpos($key, 'FULLTEXT') === 0)
927
                        {
928
                                $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')';
929
                        }
930
                        else
931
                        {
932
                                $line .= "KEY $key (" . implode(', ', $columns) . ')';
933
                        }
934
935
                        $rows[] = $line;
936
                }
937
938
                $sql_data .= implode(",\n", $rows);
939
                $sql_data .= "\n);\n\n";
940
941
                $this->flush($sql_data);
942
        }
943
}
944
945
/**
946
* @package acp
947
*/
948
class sqlite_extractor extends base_extractor
949
{
950
        function write_start($prefix)
951
        {
952
                $sql_data = "--\n";
953
                $sql_data .= "-- phpBB Backup Script\n";
954
                $sql_data .= "-- Dump of tables for $prefix\n";
955
                $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
956
                $sql_data .= "--\n";
957
                $sql_data .= "BEGIN TRANSACTION;\n";
958
                $this->flush($sql_data);
959
        }
960
961
        function write_table($table_name)
962
        {
963
                global $db;
964
                $sql_data = '-- Table: ' . $table_name . "\n";
965
                $sql_data .= "DROP TABLE $table_name;\n";
966
967
                $sql = "SELECT sql
968
                        FROM sqlite_master
969
                        WHERE type = 'table'
970
                                AND name = '" . $db->sql_escape($table_name) . "'
971
                        ORDER BY type DESC, name;";
972
                $result = $db->sql_query($sql);
973
                $row = $db->sql_fetchrow($result);
974
                $db->sql_freeresult($result);
975
976
                // Create Table
977
                $sql_data .= $row['sql'] . ";\n";
978
979
                $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');");
980
981
                $ar = array();
982
                while ($row = $db->sql_fetchrow($result))
983
                {
984
                        $ar[] = $row;
985
                }
986
                $db->sql_freeresult($result);
987
988
                foreach ($ar as $value)
989
                {
990
                        if (strpos($value['name'], 'autoindex') !== false)
991
                        {
992
                                continue;
993
                        }
994
995
                        $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');");
996
997
                        $fields = array();
998
                        while ($row = $db->sql_fetchrow($result))
999
                        {
1000
                                $fields[] = $row['name'];
1001
                        }
1002
                        $db->sql_freeresult($result);
1003
1004
                        $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
1005
                }
1006
1007
                $this->flush($sql_data . "\n");
1008
        }
1009
1010
        function write_data($table_name)
1011
        {
1012
                global $db;
1013
                static $proper;
1014
1015
                if (is_null($proper))
1016
                {
1017
                        $proper = version_compare(PHP_VERSION, '5.1.3', '>=');
1018
                }
1019
1020
                if ($proper)
1021
                {
1022
                        $col_types = sqlite_fetch_column_types($db->db_connect_id, $table_name);
1023
                }
1024
                else
1025
                {
1026
                        $sql = "SELECT sql
1027
                                FROM sqlite_master
1028
                                WHERE type = 'table'
1029
                                        AND name = '" . $table_name . "'";
1030
                        $table_data = sqlite_single_query($db->db_connect_id, $sql);
1031
                        $table_data = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', '', $table_data);
1032
                        $table_data = trim($table_data);
1033
1034
                        preg_match('#\((.*)\)#s', $table_data, $matches);
1035
1036
                        $table_cols = explode(',', trim($matches[1]));
1037
                        foreach ($table_cols as $declaration)
1038
                        {
1039
                                $entities = preg_split('#\s+#', trim($declaration));
1040
                                $column_name = preg_replace('/"?([^"]+)"?/', '\1', $entities[0]);
1041
1042
                                // Hit a primary key, those are not what we need :D
1043
                                if (empty($entities[1]) || (strtolower($entities[0]) === 'primary' && strtolower($entities[1]) === 'key'))
1044
                                {
1045
                                        continue;
1046
                                }
1047
                                $col_types[$column_name] = $entities[1];
1048
                        }
1049
                }
1050
1051
                $sql = "SELECT *
1052
                        FROM $table_name";
1053
                $result = sqlite_unbuffered_query($db->db_connect_id, $sql);
1054
                $rows = sqlite_fetch_all($result, SQLITE_ASSOC);
1055
                $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
1056
                foreach ($rows as $row)
1057
                {
1058
                        foreach ($row as $column_name => $column_data)
1059
                        {
1060
                                if (is_null($column_data))
1061
                                {
1062
                                        $row[$column_name] = 'NULL';
1063
                                }
1064
                                else if ($column_data == '')
1065
                                {
1066
                                        $row[$column_name] = "''";
1067
                                }
1068
                                else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false)
1069
                                {
1070
                                        $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
1071
                                }
1072
                        }
1073
                        $this->flush($sql_insert . implode(', ', $row) . ");\n");
1074
                }
1075
        }
1076
1077
        function write_end()
1078
        {
1079
                $this->flush("COMMIT;\n");
1080
                parent::write_end();
1081
        }
1082
}
1083
1084
/**
1085
* @package acp
1086
*/
1087
class postgres_extractor extends base_extractor
1088
{
1089
        function write_start($prefix)
1090
        {
1091
                $sql_data = "--\n";
1092
                $sql_data .= "-- phpBB Backup Script\n";
1093
                $sql_data .= "-- Dump of tables for $prefix\n";
1094
                $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
1095
                $sql_data .= "--\n";
1096
                $sql_data .= "BEGIN TRANSACTION;\n";
1097
                $this->flush($sql_data);
1098
        }
1099
1100
        function write_table($table_name)
1101
        {
1102
                global $db;
1103
                static $domains_created = array();
1104
1105
                $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default
1106
                        FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b
1107
                        WHERE a.domain_name = b.domain_name
1108
                                AND b.table_name = '{$table_name}'";
1109
                $result = $db->sql_query($sql);
1110
                while ($row = $db->sql_fetchrow($result))
1111
                {
1112
                        if (empty($domains_created[$row['domain_name']]))
1113
                        {
1114
                                $domains_created[$row['domain_name']] = true;
1115
                                //$sql_data = "DROP DOMAIN {$row['domain_name']};\n";
1116
                                $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}";
1117
                                if (!empty($row['character_maximum_length']))
1118
                                {
1119
                                        $sql_data .= '(' . $row['character_maximum_length'] . ')';
1120
                                }
1121
                                $sql_data .= ' NOT NULL';
1122
                                if (!empty($row['domain_default']))
1123
                                {
1124
                                        $sql_data .= ' DEFAULT ' . $row['domain_default'];
1125
                                }
1126
                                $this->flush($sql_data . ";\n");
1127
                        }
1128
                }
1129
1130
                $sql_data = '-- Table: ' . $table_name . "\n";
1131
                $sql_data .= "DROP TABLE $table_name;\n";
1132
                // PGSQL does not "tightly" bind sequences and tables, we must guess...
1133
                $sql = "SELECT relname
1134
                        FROM pg_class
1135
                        WHERE relkind = 'S'
1136
                                AND relname = '{$table_name}_seq'";
1137
                $result = $db->sql_query($sql);
1138
                // We don't even care about storing the results. We already know the answer if we get rows back.
1139
                if ($db->sql_fetchrow($result))
1140
                {
1141
                        $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n";
1142
                        $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n";
1143
                }
1144
                $db->sql_freeresult($result);
1145
1146
                $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull
1147
                        FROM pg_class c, pg_attribute a, pg_type t
1148
                        WHERE c.relname = '" . $db->sql_escape($table_name) . "'
1149
                                AND a.attnum > 0
1150
                                AND a.attrelid = c.oid
1151
                                AND a.atttypid = t.oid
1152
                        ORDER BY a.attnum";
1153
                $result = $db->sql_query($field_query);
1154
1155
                $sql_data .= "CREATE TABLE $table_name(\n";
1156
                $lines = array();
1157
                while ($row = $db->sql_fetchrow($result))
1158
                {
1159
                        // Get the data from the table
1160
                        $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
1161
                                FROM pg_attrdef d, pg_class c
1162
                                WHERE (c.relname = '" . $db->sql_escape($table_name) . "')
1163
                                        AND (c.oid = d.adrelid)
1164
                                        AND d.adnum = " . $row['attnum'];
1165
                        $def_res = $db->sql_query($sql_get_default);
1166
                        $def_row = $db->sql_fetchrow($def_res);
1167
                        $db->sql_freeresult($def_res);
1168
1169
                        if (empty($def_row))
1170
                        {
1171
                                unset($row['rowdefault']);
1172
                        }
1173
                        else
1174
                        {
1175
                                $row['rowdefault'] = $def_row['rowdefault'];
1176
                        }
1177
1178
                        if ($row['type'] == 'bpchar')
1179
                        {
1180
                                // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement.
1181
                                $row['type'] = 'char';
1182
                        }
1183
1184
                        $line = '  ' . $row['field'] . ' ' . $row['type'];
1185
1186
                        if (strpos($row['type'], 'char') !== false)
1187
                        {
1188
                                if ($row['lengthvar'] > 0)
1189
                                {
1190
                                        $line .= '(' . ($row['lengthvar'] - 4) . ')';
1191
                                }
1192
                        }
1193
1194
                        if (strpos($row['type'], 'numeric') !== false)
1195
                        {
1196
                                $line .= '(';
1197
                                $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff));
1198
                                $line .= ')';
1199
                        }
1200
1201
                        if (isset($row['rowdefault']))
1202
                        {
1203
                                $line .= ' DEFAULT ' . $row['rowdefault'];
1204
                        }
1205
1206
                        if ($row['notnull'] == 't')
1207
                        {
1208
                                $line .= ' NOT NULL';
1209
                        }
1210
1211
                        $lines[] = $line;
1212
                }
1213
                $db->sql_freeresult($result);
1214
1215
1216
                // Get the listing of primary keys.
1217
                $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key
1218
                        FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia
1219
                        WHERE (bc.oid = i.indrelid)
1220
                                AND (ic.oid = i.indexrelid)
1221
                                AND (ia.attrelid = i.indexrelid)
1222
                                AND        (ta.attrelid = bc.oid)
1223
                                AND (bc.relname = '" . $db->sql_escape($table_name) . "')
1224
                                AND (ta.attrelid = i.indrelid)
1225
                                AND (ta.attnum = i.indkey[ia.attnum-1])
1226
                        ORDER BY index_name, tab_name, column_name";
1227
1228
                $result = $db->sql_query($sql_pri_keys);
1229
1230
                $index_create = $index_rows = $primary_key = array();
1231
1232
                // We do this in two steps. It makes placing the comma easier
1233
                while ($row = $db->sql_fetchrow($result))
1234
                {
1235
                        if ($row['primary_key'] == 't')
1236
                        {
1237
                                $primary_key[] = $row['column_name'];
1238
                                $primary_key_name = $row['index_name'];
1239
                        }
1240
                        else
1241
                        {
1242
                                // We have to store this all this info because it is possible to have a multi-column key...
1243
                                // we can loop through it again and build the statement
1244
                                $index_rows[$row['index_name']]['table'] = $table_name;
1245
                                $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false;
1246
                                $index_rows[$row['index_name']]['column_names'][] = $row['column_name'];
1247
                        }
1248
                }
1249
                $db->sql_freeresult($result);
1250
1251
                if (!empty($index_rows))
1252
                {
1253
                        foreach ($index_rows as $idx_name => $props)
1254
                        {
1255
                                $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");";
1256
                        }
1257
                }
1258
1259
                if (!empty($primary_key))
1260
                {
1261
                        $lines[] = "  CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")";
1262
                }
1263
1264
                // Generate constraint clauses for CHECK constraints
1265
                $sql_checks = "SELECT conname as index_name, consrc
1266
                        FROM pg_constraint, pg_class bc
1267
                        WHERE conrelid = bc.oid
1268
                                AND bc.relname = '" . $db->sql_escape($table_name) . "'
1269
                                AND NOT EXISTS (
1270
                                        SELECT *
1271
                                                FROM pg_constraint as c, pg_inherits as i
1272
                                                WHERE i.inhrelid = pg_constraint.conrelid
1273
                                                        AND c.conname = pg_constraint.conname
1274
                                                        AND c.consrc = pg_constraint.consrc
1275
                                                        AND c.conrelid = i.inhparent
1276
                                )";
1277
                $result = $db->sql_query($sql_checks);
1278
1279
                // Add the constraints to the sql file.
1280
                while ($row = $db->sql_fetchrow($result))
1281
                {
1282
                        if (!is_null($row['consrc']))
1283
                        {
1284
                                $lines[] = '  CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc'];
1285
                        }
1286
                }
1287
                $db->sql_freeresult($result);
1288
1289
                $sql_data .= implode(", \n", $lines);
1290
                $sql_data .= "\n);\n";
1291
1292
                if (!empty($index_create))
1293
                {
1294
                        $sql_data .= implode("\n", $index_create) . "\n\n";
1295
                }
1296
                $this->flush($sql_data);
1297
        }
1298
1299
        function write_data($table_name)
1300
        {
1301
                global $db;
1302
                // Grab all of the data from current table.
1303
                $sql = "SELECT *
1304
                        FROM $table_name";
1305
                $result = $db->sql_query($sql);
1306
1307
                $i_num_fields = pg_num_fields($result);
1308
                $seq = '';
1309
1310
                for ($i = 0; $i < $i_num_fields; $i++)
1311
                {
1312
                        $ary_type[] = pg_field_type($result, $i);
1313
                        $ary_name[] = pg_field_name($result, $i);
1314
1315
1316
                        $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
1317
                                FROM pg_attrdef d, pg_class c
1318
                                WHERE (c.relname = '{$table_name}')
1319
                                        AND (c.oid = d.adrelid)
1320
                                        AND d.adnum = " . strval($i + 1);
1321
                        $result2 = $db->sql_query($sql);
1322
                        if ($row = $db->sql_fetchrow($result2))
1323
                        {
1324
                                // Determine if we must reset the sequences
1325
                                if (strpos($row['rowdefault'], "nextval('") === 0)
1326
                                {
1327
                                        $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n";
1328
                                }
1329
                        }
1330
                }
1331
1332
                $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n");
1333
                while ($row = $db->sql_fetchrow($result))
1334
                {
1335
                        $schema_vals = array();
1336
1337
                        // Build the SQL statement to recreate the data.
1338
                        for ($i = 0; $i < $i_num_fields; $i++)
1339
                        {
1340
                                $str_val = $row[$ary_name[$i]];
1341
1342
                                if (preg_match('#char|text|bool|bytea#i', $ary_type[$i]))
1343
                                {
1344
                                        $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val));
1345
                                        $str_empty = '';
1346
                                }
1347
                                else
1348
                                {
1349
                                        $str_empty = '\N';
1350
                                }
1351
1352
                                if (empty($str_val) && $str_val !== '0')
1353
                                {
1354
                                        $str_val = $str_empty;
1355
                                }
1356
1357
                                $schema_vals[] = $str_val;
1358
                        }
1359
1360
                        // Take the ordered fields and their associated data and build it
1361
                        // into a valid sql statement to recreate that field in the data.
1362
                        $this->flush(implode("\t", $schema_vals) . "\n");
1363
                }
1364
                $db->sql_freeresult($result);
1365
                $this->flush("\\.\n");
1366
1367
                // Write out the sequence statements
1368
                $this->flush($seq);
1369
        }
1370
1371
        function write_end()
1372
        {
1373
                $this->flush("COMMIT;\n");
1374
                parent::write_end();
1375
        }
1376
}
1377
1378
/**
1379
* @package acp
1380
*/
1381
class mssql_extractor extends base_extractor
1382
{
1383
        function write_end()
1384
        {
1385
                $this->flush("COMMIT\nGO\n");
1386
                parent::write_end();
1387
        }
1388
1389
        function write_start($prefix)
1390
        {
1391
                $sql_data = "--\n";
1392
                $sql_data .= "-- phpBB Backup Script\n";
1393
                $sql_data .= "-- Dump of tables for $prefix\n";
1394
                $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
1395
                $sql_data .= "--\n";
1396
                $sql_data .= "BEGIN TRANSACTION\n";
1397
                $sql_data .= "GO\n";
1398
                $this->flush($sql_data);
1399
        }
1400
1401
        function write_table($table_name)
1402
        {
1403
                global $db;
1404
                $sql_data = '-- Table: ' . $table_name . "\n";
1405
                $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n";
1406
                $sql_data .= "DROP TABLE $table_name;\n";
1407
                $sql_data .= "GO\n";
1408
                $sql_data .= "\nCREATE TABLE [$table_name] (\n";
1409
                $rows = array();
1410
1411
                $text_flag = false;
1412
1413
                $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY
1414
                        FROM INFORMATION_SCHEMA.COLUMNS
1415
                        WHERE TABLE_NAME = '$table_name'";
1416
                $result = $db->sql_query($sql);
1417
1418
                while ($row = $db->sql_fetchrow($result))
1419
                {
1420
                        $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]";
1421
1422
                        if ($row['DATA_TYPE'] == 'text')
1423
                        {
1424
                                $text_flag = true;
1425
                        }
1426
1427
                        if ($row['IS_IDENTITY'])
1428
                        {
1429
                                $line .= ' IDENTITY (1 , 1)';
1430
                        }
1431
1432
                        if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text')
1433
                        {
1434
                                $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')';
1435
                        }
1436
1437
                        if ($row['IS_NULLABLE'] == 'YES')
1438
                        {
1439
                                $line .= ' NULL';
1440
                        }
1441
                        else
1442
                        {
1443
                                $line .= ' NOT NULL';
1444
                        }
1445
1446
                        if ($row['COLUMN_DEFAULT'])
1447
                        {
1448
                                $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT'];
1449
                        }
1450
1451
                        $rows[] = $line;
1452
                }
1453
                $db->sql_freeresult($result);
1454
1455
                $sql_data .= implode(",\n", $rows);
1456
                $sql_data .= "\n) ON [PRIMARY]";
1457
1458
                if ($text_flag)
1459
                {
1460
                        $sql_data .= " TEXTIMAGE_ON [PRIMARY]";
1461
                }
1462
1463
                $sql_data .= "\nGO\n\n";
1464
                $rows = array();
1465
1466
                $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME
1467
                        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
1468
                        WHERE TABLE_NAME = '$table_name'";
1469
                $result = $db->sql_query($sql);
1470
                while ($row = $db->sql_fetchrow($result))
1471
                {
1472
                        if (!sizeof($rows))
1473
                        {
1474
                                $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n";
1475
                                $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY  CLUSTERED \n\t(\n";
1476
                        }
1477
                        $rows[] = "\t\t[{$row['COLUMN_NAME']}]";
1478
                }
1479
                if (sizeof($rows))
1480
                {
1481
                        $sql_data .= implode(",\n", $rows);
1482
                        $sql_data .= "\n\t)  ON [PRIMARY] \nGO\n";
1483
                }
1484
                $db->sql_freeresult($result);
1485
1486
                $index = array();
1487
                $sql = "EXEC sp_statistics '$table_name'";
1488
                $result = $db->sql_query($sql);
1489
                while ($row = $db->sql_fetchrow($result))
1490
                {
1491
                        if ($row['TYPE'] == 3)
1492
                        {
1493
                                $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']';
1494
                        }
1495
                }
1496
                $db->sql_freeresult($result);
1497
1498
                foreach ($index as $index_name => $column_name)
1499
                {
1500
                        $index[$index_name] = implode(', ', $column_name);
1501
                }
1502
1503
                foreach ($index as $index_name => $columns)
1504
                {
1505
                        $sql_data .= "\nCREATE  INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n";
1506
                }
1507
                $this->flush($sql_data);
1508
        }
1509
1510
        function write_data($table_name)
1511
        {
1512
                global $db;
1513
1514
                if ($db->sql_layer === 'mssql')
1515
                {
1516
                        $this->write_data_mssql($table_name);
1517
                }
1518
                else if($db->sql_layer === 'mssqlnative')
1519
                {
1520
                        $this->write_data_mssqlnative($table_name);
1521
                }
1522
                else
1523
                {
1524
                        $this->write_data_odbc($table_name);
1525
                }
1526
        }
1527
1528
        function write_data_mssql($table_name)
1529
        {
1530
                global $db;
1531
                $ary_type = $ary_name = array();
1532
                $ident_set = false;
1533
                $sql_data = '';
1534
1535
                // Grab all of the data from current table.
1536
                $sql = "SELECT *
1537
                        FROM $table_name";
1538
                $result = $db->sql_query($sql);
1539
1540
                $retrieved_data = mssql_num_rows($result);
1541
1542
                $i_num_fields = mssql_num_fields($result);
1543
1544
                for ($i = 0; $i < $i_num_fields; $i++)
1545
                {
1546
                        $ary_type[$i] = mssql_field_type($result, $i);
1547
                        $ary_name[$i] = mssql_field_name($result, $i);
1548
                }
1549
1550
                if ($retrieved_data)
1551
                {
1552
                        $sql = "SELECT 1 as has_identity
1553
                                FROM INFORMATION_SCHEMA.COLUMNS
1554
                                WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1555
                        $result2 = $db->sql_query($sql);
1556
                        $row2 = $db->sql_fetchrow($result2);
1557
                        if (!empty($row2['has_identity']))
1558
                        {
1559
                                $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1560
                                $ident_set = true;
1561
                        }
1562
                        $db->sql_freeresult($result2);
1563
                }
1564
1565
                while ($row = $db->sql_fetchrow($result))
1566
                {
1567
                        $schema_vals = $schema_fields = array();
1568
1569
                        // Build the SQL statement to recreate the data.
1570
                        for ($i = 0; $i < $i_num_fields; $i++)
1571
                        {
1572
                                $str_val = $row[$ary_name[$i]];
1573
1574
                                if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1575
                                {
1576
                                        $str_quote = '';
1577
                                        $str_empty = "''";
1578
                                        $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1579
                                }
1580
                                else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1581
                                {
1582
                                        if (empty($str_val))
1583
                                        {
1584
                                                $str_quote = '';
1585
                                        }
1586
                                        else
1587
                                        {
1588
                                                $str_quote = "'";
1589
                                        }
1590
                                }
1591
                                else
1592
                                {
1593
                                        $str_quote = '';
1594
                                        $str_empty = 'NULL';
1595
                                }
1596
1597
                                if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1598
                                {
1599
                                        $str_val = $str_empty;
1600
                                }
1601
1602
                                $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1603
                                $schema_fields[$i] = $ary_name[$i];
1604
                        }
1605
1606
                        // Take the ordered fields and their associated data and build it
1607
                        // into a valid sql statement to recreate that field in the data.
1608
                        $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1609
1610
                        $this->flush($sql_data);
1611
                        $sql_data = '';
1612
                }
1613
                $db->sql_freeresult($result);
1614
1615
                if ($retrieved_data && $ident_set)
1616
                {
1617
                        $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1618
                }
1619
                $this->flush($sql_data);
1620
        }
1621
        
1622
        function write_data_mssqlnative($table_name)
1623
        {
1624
                global $db;
1625
                $ary_type = $ary_name = array();
1626
                $ident_set = false;
1627
                $sql_data = '';
1628
1629
                // Grab all of the data from current table.
1630
                $sql = "SELECT * FROM $table_name";
1631
                $db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC));
1632
                $result = $db->sql_query($sql);
1633
1634
                $retrieved_data = $db->mssqlnative_num_rows($result);
1635
1636
                if (!$retrieved_data)
1637
                {
1638
                        $db->sql_freeresult($result);
1639
                        return;
1640
                }
1641
1642
                $sql = "SELECT * FROM $table_name";
1643
                $result_fields = $db->sql_query_limit($sql, 1);
1644
1645
                $row = new result_mssqlnative($result_fields);
1646
                $i_num_fields = $row->num_fields();
1647
                
1648
                for ($i = 0; $i < $i_num_fields; $i++)
1649
                {
1650
                        $ary_type[$i] = $row->field_type($i);
1651
                        $ary_name[$i] = $row->field_name($i);
1652
                }
1653
                $db->sql_freeresult($result_fields);
1654
1655
                $sql = "SELECT 1 as has_identity
1656
                        FROM INFORMATION_SCHEMA.COLUMNS
1657
                        WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1658
                $result2 = $db->sql_query($sql);
1659
                $row2 = $db->sql_fetchrow($result2);
1660
                
1661
                if (!empty($row2['has_identity']))
1662
                {
1663
                        $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1664
                        $ident_set = true;
1665
                }
1666
                $db->sql_freeresult($result2);
1667
1668
                while ($row = $db->sql_fetchrow($result))
1669
                {
1670
                        $schema_vals = $schema_fields = array();
1671
1672
                        // Build the SQL statement to recreate the data.
1673
                        for ($i = 0; $i < $i_num_fields; $i++)
1674
                        {
1675
                                $str_val = $row[$ary_name[$i]];
1676
1677
                                // defaults to type number - better quote just to be safe, so check for is_int too
1678
                                if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1679
                                {
1680
                                        $str_quote = '';
1681
                                        $str_empty = "''";
1682
                                        $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1683
                                }
1684
                                else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1685
                                {
1686
                                        if (empty($str_val))
1687
                                        {
1688
                                                $str_quote = '';
1689
                                        }
1690
                                        else
1691
                                        {
1692
                                                $str_quote = "'";
1693
                                        }
1694
                                }
1695
                                else
1696
                                {
1697
                                        $str_quote = '';
1698
                                        $str_empty = 'NULL';
1699
                                }
1700
1701
                                if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1702
                                {
1703
                                        $str_val = $str_empty;
1704
                                }
1705
1706
                                $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1707
                                $schema_fields[$i] = $ary_name[$i];
1708
                        }
1709
1710
                        // Take the ordered fields and their associated data and build it
1711
                        // into a valid sql statement to recreate that field in the data.
1712
                        $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1713
1714
                        $this->flush($sql_data);
1715
                        $sql_data = '';
1716
                }
1717
                $db->sql_freeresult($result);
1718
1719
                if ($ident_set)
1720
                {
1721
                        $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1722
                }
1723
                $this->flush($sql_data);
1724
        }        
1725
        
1726
        function write_data_odbc($table_name)
1727
        {
1728
                global $db;
1729
                $ary_type = $ary_name = array();
1730
                $ident_set = false;
1731
                $sql_data = '';
1732
1733
                // Grab all of the data from current table.
1734
                $sql = "SELECT *
1735
                        FROM $table_name";
1736
                $result = $db->sql_query($sql);
1737
1738
                $retrieved_data = odbc_num_rows($result);
1739
1740
                if ($retrieved_data)
1741
                {
1742
                        $sql = "SELECT 1 as has_identity
1743
                                FROM INFORMATION_SCHEMA.COLUMNS
1744
                                WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
1745
                        $result2 = $db->sql_query($sql);
1746
                        $row2 = $db->sql_fetchrow($result2);
1747
                        if (!empty($row2['has_identity']))
1748
                        {
1749
                                $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
1750
                                $ident_set = true;
1751
                        }
1752
                        $db->sql_freeresult($result2);
1753
                }
1754
1755
                $i_num_fields = odbc_num_fields($result);
1756
1757
                for ($i = 0; $i < $i_num_fields; $i++)
1758
                {
1759
                        $ary_type[$i] = odbc_field_type($result, $i + 1);
1760
                        $ary_name[$i] = odbc_field_name($result, $i + 1);
1761
                }
1762
1763
                while ($row = $db->sql_fetchrow($result))
1764
                {
1765
                        $schema_vals = $schema_fields = array();
1766
1767
                        // Build the SQL statement to recreate the data.
1768
                        for ($i = 0; $i < $i_num_fields; $i++)
1769
                        {
1770
                                $str_val = $row[$ary_name[$i]];
1771
1772
                                if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
1773
                                {
1774
                                        $str_quote = '';
1775
                                        $str_empty = "''";
1776
                                        $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
1777
                                }
1778
                                else if (preg_match('#date|timestamp#i', $ary_type[$i]))
1779
                                {
1780
                                        if (empty($str_val))
1781
                                        {
1782
                                                $str_quote = '';
1783
                                        }
1784
                                        else
1785
                                        {
1786
                                                $str_quote = "'";
1787
                                        }
1788
                                }
1789
                                else
1790
                                {
1791
                                        $str_quote = '';
1792
                                        $str_empty = 'NULL';
1793
                                }
1794
1795
                                if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
1796
                                {
1797
                                        $str_val = $str_empty;
1798
                                }
1799
1800
                                $schema_vals[$i] = $str_quote . $str_val . $str_quote;
1801
                                $schema_fields[$i] = $ary_name[$i];
1802
                        }
1803
1804
                        // Take the ordered fields and their associated data and build it
1805
                        // into a valid sql statement to recreate that field in the data.
1806
                        $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
1807
1808
                        $this->flush($sql_data);
1809
1810
                        $sql_data = '';
1811
1812
                }
1813
                $db->sql_freeresult($result);
1814
1815
                if ($retrieved_data && $ident_set)
1816
                {
1817
                        $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
1818
                }
1819
                $this->flush($sql_data);
1820
        }
1821
1822
}
1823
1824
/**
1825
* @package acp
1826
*/
1827
class oracle_extractor extends base_extractor
1828
{
1829
        function write_table($table_name)
1830
        {
1831
                global $db;
1832
                $sql_data = '-- Table: ' . $table_name . "\n";
1833
                $sql_data .= "DROP TABLE $table_name\n/\n";
1834
                $sql_data .= "\nCREATE TABLE $table_name (\n";
1835
1836
                $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT
1837
                        FROM ALL_TAB_COLS
1838
                        WHERE table_name = '{$table_name}'";
1839
                $result = $db->sql_query($sql);
1840
1841
                $rows = array();
1842
                while ($row = $db->sql_fetchrow($result))
1843
                {
1844
                        $line = '  "' . $row['column_name'] . '" ' . $row['data_type'];
1845
1846
                        if ($row['data_type'] !== 'CLOB')
1847
                        {
1848
                                if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR')
1849
                                {
1850
                                        $line .= '(' . $row['data_precision'] . ')';
1851
                                }
1852
                                else
1853
                                {
1854
                                        $line .= '(' . $row['data_length'] . ')';
1855
                                }
1856
                        }
1857
1858
                        if (!empty($row['data_default']))
1859
                        {
1860
                                $line .= ' DEFAULT ' . $row['data_default'];
1861
                        }
1862
1863
                        if ($row['nullable'] == 'N')
1864
                        {
1865
                                $line .= ' NOT NULL';
1866
                        }
1867
                        $rows[] = $line;
1868
                }
1869
                $db->sql_freeresult($result);
1870
1871
                $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
1872
                        FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
1873
                        WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
1874
                                AND B.CONSTRAINT_TYPE = 'P'
1875
                                AND A.TABLE_NAME = '{$table_name}'";
1876
                $result = $db->sql_query($sql);
1877
1878
                $primary_key = array();
1879
                $contraint_name = '';
1880
                while ($row = $db->sql_fetchrow($result))
1881
                {
1882
                        $constraint_name = '"' . $row['constraint_name'] . '"';
1883
                        $primary_key[] = '"' . $row['column_name'] . '"';
1884
                }
1885
                $db->sql_freeresult($result);
1886
1887
                if (sizeof($primary_key))
1888
                {
1889
                        $rows[] = "  CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')';
1890
                }
1891
1892
                $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
1893
                        FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
1894
                        WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
1895
                                AND B.CONSTRAINT_TYPE = 'U'
1896
                                AND A.TABLE_NAME = '{$table_name}'";
1897
                $result = $db->sql_query($sql);
1898
1899
                $unique = array();
1900
                $contraint_name = '';
1901
                while ($row = $db->sql_fetchrow($result))
1902
                {
1903
                        $constraint_name = '"' . $row['constraint_name'] . '"';
1904
                        $unique[] = '"' . $row['column_name'] . '"';
1905
                }
1906
                $db->sql_freeresult($result);
1907
1908
                if (sizeof($unique))
1909
                {
1910
                        $rows[] = "  CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')';
1911
                }
1912
1913
                $sql_data .= implode(",\n", $rows);
1914
                $sql_data .= "\n)\n/\n";
1915
1916
                $sql = "SELECT A.REFERENCED_NAME, C.*
1917
                        FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C
1918
                        WHERE A.REFERENCED_TYPE = 'SEQUENCE'
1919
                                AND A.NAME = B.TRIGGER_NAME
1920
                                AND B.TABLE_NAME = '{$table_name}'
1921
                                AND C.SEQUENCE_NAME = A.REFERENCED_NAME";
1922
                $result = $db->sql_query($sql);
1923
1924
                $type = request_var('type', '');
1925
1926
                while ($row = $db->sql_fetchrow($result))
1927
                {
1928
                        $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n";
1929
                        $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\"";
1930
1931
                        if ($type == 'full')
1932
                        {
1933
                                $sql_data .= ' START WITH ' . $row['last_number'];
1934
                        }
1935
1936
                        $sql_data .= "\n/\n";
1937
                }
1938
                $db->sql_freeresult($result);
1939
1940
                $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY
1941
                        FROM USER_TRIGGERS
1942
                        WHERE TABLE_NAME = '{$table_name}'";
1943
                $result = $db->sql_query($sql);
1944
                while ($row = $db->sql_fetchrow($result))
1945
                {
1946
                        $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n";
1947
                }
1948
                $db->sql_freeresult($result);
1949
1950
                $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME
1951
                        FROM USER_INDEXES A, USER_IND_COLUMNS B
1952
                        WHERE A.UNIQUENESS = 'NONUNIQUE'
1953
                                AND A.INDEX_NAME = B.INDEX_NAME
1954
                                AND B.TABLE_NAME = '{$table_name}'";
1955
                $result = $db->sql_query($sql);
1956
1957
                $index = array();
1958
1959
                while ($row = $db->sql_fetchrow($result))
1960
                {
1961
                        $index[$row['index_name']][] = $row['column_name'];
1962
                }
1963
1964
                foreach ($index as $index_name => $column_names)
1965
                {
1966
                        $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n";
1967
                }
1968
                $db->sql_freeresult($result);
1969
                $this->flush($sql_data);
1970
        }
1971
1972
        function write_data($table_name)
1973
        {
1974
                global $db;
1975
                $ary_type = $ary_name = array();
1976
1977
                // Grab all of the data from current table.
1978
                $sql = "SELECT *
1979
                        FROM $table_name";
1980
                $result = $db->sql_query($sql);
1981
1982
                $i_num_fields = ocinumcols($result);
1983
1984
                for ($i = 0; $i < $i_num_fields; $i++)
1985
                {
1986
                        $ary_type[$i] = ocicolumntype($result, $i + 1);
1987
                        $ary_name[$i] = ocicolumnname($result, $i + 1);
1988
                }
1989
1990
                $sql_data = '';
1991
1992
                while ($row = $db->sql_fetchrow($result))
1993
                {
1994
                        $schema_vals = $schema_fields = array();
1995
1996
                        // Build the SQL statement to recreate the data.
1997
                        for ($i = 0; $i < $i_num_fields; $i++)
1998
                        {
1999
                                // Oracle uses uppercase - we use lowercase
2000
                                $str_val = $row[strtolower($ary_name[$i])];
2001
2002
                                if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i]))
2003
                                {
2004
                                        $str_quote = '';
2005
                                        $str_empty = "''";
2006
                                        $str_val = sanitize_data_oracle($str_val);
2007
                                }
2008
                                else if (preg_match('#date|timestamp#i', $ary_type[$i]))
2009
                                {
2010
                                        if (empty($str_val))
2011
                                        {
2012
                                                $str_quote = '';
2013
                                        }
2014
                                        else
2015
                                        {
2016
                                                $str_quote = "'";
2017
                                        }
2018
                                }
2019
                                else
2020
                                {
2021
                                        $str_quote = '';
2022
                                        $str_empty = 'NULL';
2023
                                }
2024
2025
                                if (empty($str_val) && $str_val !== '0')
2026
                                {
2027
                                        $str_val = $str_empty;
2028
                                }
2029
2030
                                $schema_vals[$i] = $str_quote . $str_val . $str_quote;
2031
                                $schema_fields[$i] = '"' . $ary_name[$i] . '"';
2032
                        }
2033
2034
                        // Take the ordered fields and their associated data and build it
2035
                        // into a valid sql statement to recreate that field in the data.
2036
                        $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n";
2037
2038
                        $this->flush($sql_data);
2039
                }
2040
                $db->sql_freeresult($result);
2041
        }
2042
2043
        function write_start($prefix)
2044
        {
2045
                $sql_data = "--\n";
2046
                $sql_data .= "-- phpBB Backup Script\n";
2047
                $sql_data .= "-- Dump of tables for $prefix\n";
2048
                $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
2049
                $sql_data .= "--\n";
2050
                $this->flush($sql_data);
2051
        }
2052
}
2053
2054
/**
2055
* @package acp
2056
*/
2057
class firebird_extractor extends base_extractor
2058
{
2059
        function write_start($prefix)
2060
        {
2061
                $sql_data = "--\n";
2062
                $sql_data .= "-- phpBB Backup Script\n";
2063
                $sql_data .= "-- Dump of tables for $prefix\n";
2064
                $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
2065
                $sql_data .= "--\n";
2066
                $this->flush($sql_data);
2067
        }
2068
2069
        function write_data($table_name)
2070
        {
2071
                global $db;
2072
                $ary_type = $ary_name = array();
2073
2074
                // Grab all of the data from current table.
2075
                $sql = "SELECT *
2076
                        FROM $table_name";
2077
                $result = $db->sql_query($sql);
2078
2079
                $i_num_fields = ibase_num_fields($result);
2080
2081
                for ($i = 0; $i < $i_num_fields; $i++)
2082
                {
2083
                        $info = ibase_field_info($result, $i);
2084
                        $ary_type[$i] = $info['type'];
2085
                        $ary_name[$i] = $info['name'];
2086
                }
2087
2088
                while ($row = $db->sql_fetchrow($result))
2089
                {
2090
                        $schema_vals = $schema_fields = array();
2091
2092
                        // Build the SQL statement to recreate the data.
2093
                        for ($i = 0; $i < $i_num_fields; $i++)
2094
                        {
2095
                                $str_val = $row[strtolower($ary_name[$i])];
2096
2097
                                if (preg_match('#char|text|bool|varbinary|blob#i', $ary_type[$i]))
2098
                                {
2099
                                        $str_quote = '';
2100
                                        $str_empty = "''";
2101
                                        $str_val = sanitize_data_generic(str_replace("'", "''", $str_val));
2102
                                }
2103
                                else if (preg_match('#date|timestamp#i', $ary_type[$i]))
2104
                                {
2105
                                        if (empty($str_val))
2106
                                        {
2107
                                                $str_quote = '';
2108
                                        }
2109
                                        else
2110
                                        {
2111
                                                $str_quote = "'";
2112
                                        }
2113
                                }
2114
                                else
2115
                                {
2116
                                        $str_quote = '';
2117
                                        $str_empty = 'NULL';
2118
                                }
2119
2120
                                if (empty($str_val) && $str_val !== '0')
2121
                                {
2122
                                        $str_val = $str_empty;
2123
                                }
2124
2125
                                $schema_vals[$i] = $str_quote . $str_val . $str_quote;
2126
                                $schema_fields[$i] = '"' . $ary_name[$i] . '"';
2127
                        }
2128
2129
                        // Take the ordered fields and their associated data and build it
2130
                        // into a valid sql statement to recreate that field in the data.
2131
                        $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n";
2132
2133
                        $this->flush($sql_data);
2134
                }
2135
                $db->sql_freeresult($result);
2136
        }
2137
2138
        function write_table($table_name)
2139
        {
2140
                global $db;
2141
2142
                $sql_data = '-- Table: ' . $table_name . "\n";
2143
                $sql_data .= "DROP TABLE $table_name;\n";
2144
2145
                $data_types = array(7 => 'SMALLINT', 8 => 'INTEGER', 10 => 'FLOAT', 12 => 'DATE', 13 => 'TIME', 14 => 'CHARACTER', 27 => 'DOUBLE PRECISION', 35 => 'TIMESTAMP', 37 => 'VARCHAR', 40 => 'CSTRING', 261 => 'BLOB', 701 => 'DECIMAL', 702 => 'NUMERIC');
2146
2147
                $sql_data .= "\nCREATE TABLE $table_name (\n";
2148
2149
                $sql = 'SELECT DISTINCT R.RDB$FIELD_NAME as FNAME, R.RDB$NULL_FLAG as NFLAG, R.RDB$DEFAULT_SOURCE as DSOURCE, F.RDB$FIELD_TYPE as FTYPE, F.RDB$FIELD_SUB_TYPE as STYPE, F.RDB$FIELD_LENGTH as FLEN
2150
                        FROM RDB$RELATION_FIELDS R
2151
                        JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME
2152
                        LEFT JOIN RDB$FIELD_DIMENSIONS D ON R.RDB$FIELD_SOURCE = D.RDB$FIELD_NAME
2153
                        WHERE F.RDB$SYSTEM_FLAG = 0
2154
                                AND R.RDB$RELATION_NAME = \''. $table_name . '\'
2155
                        ORDER BY R.RDB$FIELD_POSITION';
2156
                $result = $db->sql_query($sql);
2157
2158
                $rows = array();
2159
                while ($row = $db->sql_fetchrow($result))
2160
                {
2161
                        $line = "\t" . '"' . $row['fname'] . '" ' . $data_types[$row['ftype']];
2162
2163
                        if ($row['ftype'] == 261 && $row['stype'] == 1)
2164
                        {
2165
                                $line .= ' SUB_TYPE TEXT';
2166
                        }
2167
2168
                        if ($row['ftype'] == 37 || $row['ftype'] == 14)
2169
                        {
2170
                                $line .= ' (' . $row['flen'] . ')';
2171
                        }
2172
2173
                        if (!empty($row['dsource']))
2174
                        {
2175
                                $line .= ' ' . $row['dsource'];
2176
                        }
2177
2178
                        if (!empty($row['nflag']))
2179
                        {
2180
                                $line .= ' NOT NULL';
2181
                        }
2182
                        $rows[] = $line;
2183
                }
2184
                $db->sql_freeresult($result);
2185
2186
                $sql_data .= implode(",\n", $rows);
2187
                $sql_data .= "\n);\n";
2188
                $keys = array();
2189
2190
                $sql = 'SELECT I.RDB$FIELD_NAME as NAME
2191
                        FROM RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS I, RDB$INDICES IDX
2192
                        WHERE (I.RDB$INDEX_NAME = RC.RDB$INDEX_NAME)
2193
                                AND (IDX.RDB$INDEX_NAME = RC.RDB$INDEX_NAME)
2194
                                AND (RC.RDB$RELATION_NAME = \''. $table_name . '\')
2195
                        ORDER BY I.RDB$FIELD_POSITION';
2196
                $result = $db->sql_query($sql);
2197
2198
                while ($row = $db->sql_fetchrow($result))
2199
                {
2200
                        $keys[] = $row['name'];
2201
                }
2202
2203
                if (sizeof($keys))
2204
                {
2205
                        $sql_data .= "\nALTER TABLE $table_name ADD PRIMARY KEY (" . implode(', ', $keys) . ');';
2206
                }
2207
2208
                $db->sql_freeresult($result);
2209
2210
                $sql = 'SELECT I.RDB$INDEX_NAME as INAME, I.RDB$UNIQUE_FLAG as UFLAG, S.RDB$FIELD_NAME as FNAME
2211
                        FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME=I.RDB$INDEX_NAME
2212
                        WHERE (I.RDB$SYSTEM_FLAG IS NULL  OR  I.RDB$SYSTEM_FLAG=0)
2213
                                AND I.RDB$FOREIGN_KEY IS NULL
2214
                                AND I.RDB$RELATION_NAME = \''. $table_name . '\'
2215
                                AND I.RDB$INDEX_NAME NOT STARTING WITH \'RDB$\'
2216
                        ORDER BY S.RDB$FIELD_POSITION';
2217
                $result = $db->sql_query($sql);
2218
2219
                $index = array();
2220
                while ($row = $db->sql_fetchrow($result))
2221
                {
2222
                        $index[$row['iname']]['unique'] = !empty($row['uflag']);
2223
                        $index[$row['iname']]['values'][] = $row['fname'];
2224
                }
2225
2226
                foreach ($index as $index_name => $data)
2227
                {
2228
                        $sql_data .= "\nCREATE ";
2229
                        if ($data['unique'])
2230
                        {
2231
                                $sql_data .= 'UNIQUE ';
2232
                        }
2233
                        $sql_data .= "INDEX $index_name ON $table_name(" . implode(', ', $data['values']) . ");";
2234
                }
2235
                $sql_data .= "\n";
2236
2237
                $db->sql_freeresult($result);
2238
2239
                $sql = 'SELECT D1.RDB$DEPENDENT_NAME as DNAME, D1.RDB$FIELD_NAME as FNAME, D1.RDB$DEPENDENT_TYPE, R1.RDB$RELATION_NAME
2240
                        FROM RDB$DEPENDENCIES D1
2241
                        LEFT JOIN RDB$RELATIONS R1 ON ((D1.RDB$DEPENDENT_NAME = R1.RDB$RELATION_NAME) AND (NOT (R1.RDB$VIEW_BLR IS NULL)))
2242
                        WHERE (D1.RDB$DEPENDED_ON_TYPE = 0)
2243
                                AND (D1.RDB$DEPENDENT_TYPE <> 3)
2244
                                AND (D1.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\')
2245
                        UNION SELECT DISTINCT F2.RDB$RELATION_NAME, D2.RDB$FIELD_NAME, D2.RDB$DEPENDENT_TYPE, R2.RDB$RELATION_NAME FROM RDB$DEPENDENCIES D2, RDB$RELATION_FIELDS F2
2246
                        LEFT JOIN RDB$RELATIONS R2 ON ((F2.RDB$RELATION_NAME = R2.RDB$RELATION_NAME) AND (NOT (R2.RDB$VIEW_BLR IS NULL)))
2247
                        WHERE (D2.RDB$DEPENDENT_TYPE = 3)
2248
                                AND (D2.RDB$DEPENDENT_NAME = F2.RDB$FIELD_SOURCE)
2249
                                AND (D2.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\')
2250
                        ORDER BY 1, 2';
2251
                $result = $db->sql_query($sql);
2252
                while ($row = $db->sql_fetchrow($result))
2253
                {
2254
                        $sql = 'SELECT T1.RDB$DEPENDED_ON_NAME as GEN, T1.RDB$FIELD_NAME, T1.RDB$DEPENDED_ON_TYPE
2255
                                FROM RDB$DEPENDENCIES T1
2256
                                WHERE (T1.RDB$DEPENDENT_NAME = \'' . $row['dname'] . '\')
2257
                                        AND (T1.RDB$DEPENDENT_TYPE = 2 AND T1.RDB$DEPENDED_ON_TYPE = 14)
2258
                                UNION ALL SELECT DISTINCT D.RDB$DEPENDED_ON_NAME, D.RDB$FIELD_NAME, D.RDB$DEPENDED_ON_TYPE
2259
                                FROM RDB$DEPENDENCIES D, RDB$RELATION_FIELDS F
2260
                                WHERE (D.RDB$DEPENDENT_TYPE = 3)
2261
                                        AND (D.RDB$DEPENDENT_NAME = F.RDB$FIELD_SOURCE)
2262
                                        AND (F.RDB$RELATION_NAME = \'' . $row['dname'] . '\')
2263
                                ORDER BY 1,2';
2264
                        $result2 = $db->sql_query($sql);
2265
                        $row2 = $db->sql_fetchrow($result2);
2266
                        $db->sql_freeresult($result2);
2267
                        $gen_name = $row2['gen'];
2268
2269
                        $sql_data .= "\nDROP GENERATOR " . $gen_name . ";";
2270
                        $sql_data .= "\nSET TERM ^ ;";
2271
                        $sql_data .= "\nCREATE GENERATOR " . $gen_name . "^";
2272
                        $sql_data .= "\nSET GENERATOR  " . $gen_name . " TO 0^\n";
2273
                        $sql_data .= "\nCREATE TRIGGER {$row['dname']} FOR $table_name";
2274
                        $sql_data .= "\nBEFORE INSERT\nAS\nBEGIN";
2275
                        $sql_data .= "\n  NEW.{$row['fname']} = GEN_ID(" . $gen_name . ", 1);";
2276
                        $sql_data .= "\nEND^\n";
2277
                        $sql_data .= "\nSET TERM ; ^\n";
2278
                }
2279
2280
                $this->flush($sql_data);
2281
2282
                $db->sql_freeresult($result);
2283
        }
2284
}
2285
2286
// get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P)
2287
function get_usable_memory()
2288
{
2289
        $val = trim(@ini_get('memory_limit'));
2290
2291
        if (preg_match('/(\\d+)([mkg]?)/i', $val, $regs))
2292
        {
2293
                $memory_limit = (int) $regs[1];
2294
                switch ($regs[2])
2295
                {
2296
2297
                        case 'k':
2298
                        case 'K':
2299
                                $memory_limit *= 1024;
2300
                        break;
2301
2302
                        case 'm':
2303
                        case 'M':
2304
                                $memory_limit *= 1048576;
2305
                        break;
2306
2307
                        case 'g':
2308
                        case 'G':
2309
                                $memory_limit *= 1073741824;
2310
                        break;
2311
                }
2312
2313
                // how much memory PHP requires at the start of export (it is really a little less)
2314
                if ($memory_limit > 6100000)
2315
                {
2316
                        $memory_limit -= 6100000;
2317
                }
2318
2319
                // allow us to consume half of the total memory available
2320
                $memory_limit /= 2;
2321
        }
2322
        else
2323
        {
2324
                // set the buffer to 1M if we have no clue how much memory PHP will give us :P
2325
                $memory_limit = 1048576;
2326
        }
2327
2328
        return $memory_limit;
2329
}
2330
2331
function sanitize_data_mssql($text)
2332
{
2333
        $data = preg_split('/[\n\t\r\b\f]/', $text);
2334
        preg_match_all('/[\n\t\r\b\f]/', $text, $matches);
2335
2336
        $val = array();
2337
2338
        foreach ($data as $value)
2339
        {
2340
                if (strlen($value))
2341
                {
2342
                        $val[] = "'" . $value . "'";
2343
                }
2344
                if (sizeof($matches[0]))
2345
                {
2346
                        $val[] = 'char(' . ord(array_shift($matches[0])) . ')';
2347
                }
2348
        }
2349
2350
        return implode('+', $val);
2351
}
2352
2353
function sanitize_data_oracle($text)
2354
{
2355
//        $data = preg_split('/[\0\n\t\r\b\f\'"\/\\\]/', $text);
2356
//        preg_match_all('/[\0\n\t\r\b\f\'"\/\\\]/', $text, $matches);
2357
        $data = preg_split('/[\0\b\f\'\/]/', $text);
2358
        preg_match_all('/[\0\r\b\f\'\/]/', $text, $matches);
2359
2360
        $val = array();
2361
2362
        foreach ($data as $value)
2363
        {
2364
                if (strlen($value))
2365
                {
2366
                        $val[] = "'" . $value . "'";
2367
                }
2368
                if (sizeof($matches[0]))
2369
                {
2370
                        $val[] = 'chr(' . ord(array_shift($matches[0])) . ')';
2371
                }
2372
        }
2373
2374
        return implode('||', $val);
2375
}
2376
2377
function sanitize_data_generic($text)
2378
{
2379
        $data = preg_split('/[\n\t\r\b\f]/', $text);
2380
        preg_match_all('/[\n\t\r\b\f]/', $text, $matches);
2381
2382
        $val = array();
2383
2384
        foreach ($data as $value)
2385
        {
2386
                if (strlen($value))
2387
                {
2388
                        $val[] = "'" . $value . "'";
2389
                }
2390
                if (sizeof($matches[0]))
2391
                {
2392
                        $val[] = "'" . array_shift($matches[0]) . "'";
2393
                }
2394
        }
2395
2396
        return implode('||', $val);
2397
}
2398
2399
// modified from PHP.net
2400
function fgetd(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)
2401
{
2402
        $record = '';
2403
        $delim_len = strlen($delim);
2404
2405
        while (!$eof($fp))
2406
        {
2407
                $pos = strpos($record, $delim);
2408
                if ($pos === false)
2409
                {
2410
                        $record .= $read($fp, $buffer);
2411
                        if ($eof($fp) && ($pos = strpos($record, $delim)) !== false)
2412
                        {
2413
                                $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR);
2414
                                return substr($record, 0, $pos);
2415
                        }
2416
                }
2417
                else
2418
                {
2419
                        $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR);
2420
                        return substr($record, 0, $pos);
2421
                }
2422
        }
2423
2424
        return false;
2425
}
2426
2427
function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)
2428
{
2429
        static $array = array();
2430
        static $record = '';
2431
2432
        if (!sizeof($array))
2433
        {
2434
                while (!$eof($fp))
2435
                {
2436
                        if (strpos($record, $delim) !== false)
2437
                        {
2438
                                $array = explode($delim, $record);
2439
                                $record = array_pop($array);
2440
                                break;
2441
                        }
2442
                        else
2443
                        {
2444
                                $record .= $read($fp, $buffer);
2445
                        }
2446
                }
2447
                if ($eof($fp) && strpos($record, $delim) !== false)
2448
                {
2449
                        $array = explode($delim, $record);
2450
                        $record = array_pop($array);
2451
                }
2452
        }
2453
2454
        if (sizeof($array))
2455
        {
2456
                return array_shift($array);
2457
        }
2458
2459
        return false;
2460
}
2461
2462
?>